// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package gc

import (
	"cmd/compile/internal/types"
	"fmt"
	"sort"
)

const (
	// expression switch
	switchKindExpr  = iota // switch a {...} or switch 5 {...}
	switchKindTrue         // switch true {...} or switch {...}
	switchKindFalse        // switch false {...}
)

const (
	binarySearchMin = 4 // minimum number of cases for binary search
	integerRangeMin = 2 // minimum size of integer ranges
)

// An exprSwitch walks an expression switch.
type exprSwitch struct {
	exprname *Node // node for the expression being switched on
	kind     int   // kind of switch statement (switchKind*)
}

// A typeSwitch walks a type switch.
type typeSwitch struct {
	hashname *Node // node for the hash of the type of the variable being switched on
	facename *Node // node for the concrete type of the variable being switched on
	okname   *Node // boolean node used for comma-ok type assertions
}

// A caseClause is a single case clause in a switch statement.
type caseClause struct {
	node    *Node  // points at case statement
	ordinal int    // position in switch
	hash    uint32 // hash of a type switch
	// isconst indicates whether this case clause is a constant,
	// for the purposes of the switch code generation.
	// For expression switches, that's generally literals (case 5:, not case x:).
	// For type switches, that's concrete types (case time.Time:), not interfaces (case io.Reader:).
	isconst bool
}

// caseClauses are all the case clauses in a switch statement.
type caseClauses struct {
	list   []caseClause // general cases
	defjmp *Node        // OGOTO for default case or OBREAK if no default case present
	niljmp *Node        // OGOTO for nil type case in a type switch
}

// typecheckswitch typechecks a switch statement.
func typecheckswitch(n *Node) {
	typecheckslice(n.Ninit.Slice(), ctxStmt)

	var nilonly string
	var top int
	var t *types.Type

	if n.Left != nil && n.Left.Op == OTYPESW {
		// type switch
		top = Etype
		n.Left.Right = typecheck(n.Left.Right, ctxExpr)
		t = n.Left.Right.Type
		if t != nil && !t.IsInterface() {
			yyerrorl(n.Pos, "cannot type switch on non-interface value %L", n.Left.Right)
		}
		if v := n.Left.Left; v != nil && !v.isBlank() && n.List.Len() == 0 {
			// We don't actually declare the type switch's guarded
			// declaration itself. So if there are no cases, we
			// won't notice that it went unused.
			yyerrorl(v.Pos, "%v declared and not used", v.Sym)
		}
	} else {
		// expression switch
		top = ctxExpr
		if n.Left != nil {
			n.Left = typecheck(n.Left, ctxExpr)
			n.Left = defaultlit(n.Left, nil)
			t = n.Left.Type
		} else {
			t = types.Types[TBOOL]
		}
		if t != nil {
			switch {
			case !okforeq[t.Etype]:
				yyerrorl(n.Pos, "cannot switch on %L", n.Left)
			case t.IsSlice():
				nilonly = "slice"
			case t.IsArray() && !IsComparable(t):
				yyerrorl(n.Pos, "cannot switch on %L", n.Left)
			case t.IsStruct():
				if f := IncomparableField(t); f != nil {
					yyerrorl(n.Pos, "cannot switch on %L (struct containing %v cannot be compared)", n.Left, f.Type)
				}
			case t.Etype == TFUNC:
				nilonly = "func"
			case t.IsMap():
				nilonly = "map"
			}
		}
	}

	n.Type = t

	var def, niltype *Node
	for _, ncase := range n.List.Slice() {
		if ncase.List.Len() == 0 {
			// default
			if def != nil {
				setlineno(ncase)
				yyerrorl(ncase.Pos, "multiple defaults in switch (first at %v)", def.Line())
			} else {
				def = ncase
			}
		} else {
			ls := ncase.List.Slice()
			for i1, n1 := range ls {
				setlineno(n1)
				ls[i1] = typecheck(ls[i1], ctxExpr|Etype)
				n1 = ls[i1]
				if n1.Type == nil || t == nil {
					continue
				}

				setlineno(ncase)
				switch top {
				// expression switch
				case ctxExpr:
					ls[i1] = defaultlit(ls[i1], t)
					n1 = ls[i1]
					switch {
					case n1.Op == OTYPE:
						yyerrorl(ncase.Pos, "type %v is not an expression", n1.Type)
					case n1.Type != nil && assignop(n1.Type, t, nil) == 0 && assignop(t, n1.Type, nil) == 0:
						if n.Left != nil {
							yyerrorl(ncase.Pos, "invalid case %v in switch on %v (mismatched types %v and %v)", n1, n.Left, n1.Type, t)
						} else {
							yyerrorl(ncase.Pos, "invalid case %v in switch (mismatched types %v and bool)", n1, n1.Type)
						}
					case nilonly != "" && !n1.isNil():
						yyerrorl(ncase.Pos, "invalid case %v in switch (can only compare %s %v to nil)", n1, nilonly, n.Left)
					case t.IsInterface() && !n1.Type.IsInterface() && !IsComparable(n1.Type):
						yyerrorl(ncase.Pos, "invalid case %L in switch (incomparable type)", n1)
					}

				// type switch
				case Etype:
					var missing, have *types.Field
					var ptr int
					switch {
					case n1.Op == OLITERAL && n1.Type.IsKind(TNIL):
						// case nil:
						if niltype != nil {
							yyerrorl(ncase.Pos, "multiple nil cases in type switch (first at %v)", niltype.Line())
						} else {
							niltype = ncase
						}
					case n1.Op != OTYPE && n1.Type != nil: // should this be ||?
						yyerrorl(ncase.Pos, "%L is not a type", n1)
						// reset to original type
						n1 = n.Left.Right
						ls[i1] = n1
					case !n1.Type.IsInterface() && t.IsInterface() && !implements(n1.Type, t, &missing, &have, &ptr):
						if have != nil && !missing.Broke() && !have.Broke() {
							yyerrorl(ncase.Pos, "impossible type switch case: %L cannot have dynamic type %v"+
								" (wrong type for %v method)\n\thave %v%S\n\twant %v%S", n.Left.Right, n1.Type, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
						} else if !missing.Broke() {
							if ptr != 0 {
								yyerrorl(ncase.Pos, "impossible type switch case: %L cannot have dynamic type %v"+
									" (%v method has pointer receiver)", n.Left.Right, n1.Type, missing.Sym)
							} else {
								yyerrorl(ncase.Pos, "impossible type switch case: %L cannot have dynamic type %v"+
									" (missing %v method)", n.Left.Right, n1.Type, missing.Sym)
							}
						}
					}
				}
			}
		}

		if n.Type == nil || n.Type.IsUntyped() {
			// if the value we're switching on has no type or is untyped,
			// we've already printed an error and don't need to continue
			// typechecking the body
			return
		}

		if top == Etype {
			ll := ncase.List
			if ncase.Rlist.Len() != 0 {
				nvar := ncase.Rlist.First()
				if ll.Len() == 1 && ll.First().Type != nil && !ll.First().Type.IsKind(TNIL) {
					// single entry type switch
					nvar.Type = ll.First().Type
				} else {
					// multiple entry type switch or default
					nvar.Type = n.Type
				}

				nvar = typecheck(nvar, ctxExpr|ctxAssign)
				ncase.Rlist.SetFirst(nvar)
			}
		}

		typecheckslice(ncase.Nbody.Slice(), ctxStmt)
	}
	switch top {
	// expression switch
	case ctxExpr:
		checkDupExprCases(n.Left, n.List.Slice())
	}
}

// walkswitch walks a switch statement.
func walkswitch(sw *Node) {
	// convert switch {...} to switch true {...}
	if sw.Left == nil {
		sw.Left = nodbool(true)
		sw.Left = typecheck(sw.Left, ctxExpr)
		sw.Left = defaultlit(sw.Left, nil)
	}

	if sw.Left.Op == OTYPESW {
		var s typeSwitch
		s.walk(sw)
	} else {
		var s exprSwitch
		s.walk(sw)
	}
}

// walk generates an AST implementing sw.
// sw is an expression switch.
// The AST is generally of the form of a linear
// search using if..goto, although binary search
// is used with long runs of constants.
func (s *exprSwitch) walk(sw *Node) {
	// Guard against double walk, see #25776.
	if sw.List.Len() == 0 && sw.Nbody.Len() > 0 {
		return // Was fatal, but eliminating every possible source of double-walking is hard
	}

	casebody(sw, nil)

	cond := sw.Left
	sw.Left = nil

	s.kind = switchKindExpr
	if Isconst(cond, CTBOOL) {
		s.kind = switchKindTrue
		if !cond.Val().U.(bool) {
			s.kind = switchKindFalse
		}
	}

	// Given "switch string(byteslice)",
	// with all cases being constants (or the default case),
	// use a zero-cost alias of the byte slice.
	// In theory, we could be more aggressive,
	// allowing any side-effect-free expressions in cases,
	// but it's a bit tricky because some of that information
	// is unavailable due to the introduction of temporaries during order.
	// Restricting to constants is simple and probably powerful enough.
	// Do this before calling walkexpr on cond,
	// because walkexpr will lower the string
	// conversion into a runtime call.
	// See issue 24937 for more discussion.
	if cond.Op == OBYTES2STR {
		ok := true
		for _, cas := range sw.List.Slice() {
			if cas.Op != OCASE {
				Fatalf("switch string(byteslice) bad op: %v", cas.Op)
			}
			if cas.Left != nil && !Isconst(cas.Left, CTSTR) {
				ok = false
				break
			}
		}
		if ok {
			cond.Op = OBYTES2STRTMP
		}
	}

	cond = walkexpr(cond, &sw.Ninit)
	t := sw.Type
	if t == nil {
		return
	}

	// convert the switch into OIF statements
	var cas []*Node
	if s.kind == switchKindTrue || s.kind == switchKindFalse {
		s.exprname = nodbool(s.kind == switchKindTrue)
	} else if consttype(cond) > 0 {
		// leave constants to enable dead code elimination (issue 9608)
		s.exprname = cond
	} else {
		s.exprname = temp(cond.Type)
		cas = []*Node{nod(OAS, s.exprname, cond)} // This gets walk()ed again in walkstmtlist just before end of this function.  See #29562.
		typecheckslice(cas, ctxStmt)
	}

	// Enumerate the cases and prepare the default case.
	clauses := s.genCaseClauses(sw.List.Slice())
	sw.List.Set(nil)
	cc := clauses.list

	// handle the cases in order
	for len(cc) > 0 {
		run := 1
		if okforcmp[t.Etype] && cc[0].isconst {
			// do binary search on runs of constants
			for ; run < len(cc) && cc[run].isconst; run++ {
			}
			// sort and compile constants
			sort.Sort(caseClauseByConstVal(cc[:run]))
		}

		a := s.walkCases(cc[:run])
		cas = append(cas, a)
		cc = cc[run:]
	}

	// handle default case
	if nerrors == 0 {
		cas = append(cas, clauses.defjmp)
		sw.Nbody.Prepend(cas...)
		walkstmtlist(sw.Nbody.Slice())
	}
}

// walkCases generates an AST implementing the cases in cc.
func (s *exprSwitch) walkCases(cc []caseClause) *Node {
	if len(cc) < binarySearchMin {
		// linear search
		var cas []*Node
		for _, c := range cc {
			n := c.node
			lno := setlineno(n)

			a := nod(OIF, nil, nil)
			if rng := n.List.Slice(); rng != nil {
				// Integer range.
				// exprname is a temp or a constant,
				// so it is safe to evaluate twice.
				// In most cases, this conjunction will be
				// rewritten by walkinrange into a single comparison.
				low := nod(OGE, s.exprname, rng[0])
				high := nod(OLE, s.exprname, rng[1])
				a.Left = nod(OANDAND, low, high)
			} else if (s.kind != switchKindTrue && s.kind != switchKindFalse) || assignop(n.Left.Type, s.exprname.Type, nil) == OCONVIFACE || assignop(s.exprname.Type, n.Left.Type, nil) == OCONVIFACE {
				a.Left = nod(OEQ, s.exprname, n.Left) // if name == val
			} else if s.kind == switchKindTrue {
				a.Left = n.Left // if val
			} else {
				// s.kind == switchKindFalse
				a.Left = nod(ONOT, n.Left, nil) // if !val
			}
			a.Left = typecheck(a.Left, ctxExpr)
			a.Left = defaultlit(a.Left, nil)
			a.Nbody.Set1(n.Right) // goto l

			cas = append(cas, a)
			lineno = lno
		}
		return liststmt(cas)
	}

	// find the middle and recur
	half := len(cc) / 2
	a := nod(OIF, nil, nil)
	n := cc[half-1].node
	var mid *Node
	if rng := n.List.Slice(); rng != nil {
		mid = rng[1] // high end of range
	} else {
		mid = n.Left
	}
	le := nod(OLE, s.exprname, mid)
	if Isconst(mid, CTSTR) {
		// Search by length and then by value; see caseClauseByConstVal.
		lenlt := nod(OLT, nod(OLEN, s.exprname, nil), nod(OLEN, mid, nil))
		leneq := nod(OEQ, nod(OLEN, s.exprname, nil), nod(OLEN, mid, nil))
		a.Left = nod(OOROR, lenlt, nod(OANDAND, leneq, le))
	} else {
		a.Left = le
	}
	a.Left = typecheck(a.Left, ctxExpr)
	a.Left = defaultlit(a.Left, nil)
	a.Nbody.Set1(s.walkCases(cc[:half]))
	a.Rlist.Set1(s.walkCases(cc[half:]))
	return a
}

// casebody builds separate lists of statements and cases.
// It makes labels between cases and statements
// and deals with fallthrough, break, and unreachable statements.
func casebody(sw *Node, typeswvar *Node) {
	if sw.List.Len() == 0 {
		return
	}

	lno := setlineno(sw)

	var cas []*Node  // cases
	var stat []*Node // statements
	var def *Node    // defaults
	br := nod(OBREAK, nil, nil)

	for _, n := range sw.List.Slice() {
		setlineno(n)
		if n.Op != OXCASE {
			Fatalf("casebody %v", n.Op)
		}
		n.Op = OCASE
		needvar := n.List.Len() != 1 || n.List.First().Op == OLITERAL

		lbl := autolabel(".s")
		jmp := nodSym(OGOTO, nil, lbl)
		switch n.List.Len() {
		case 0:
			// default
			if def != nil {
				yyerrorl(n.Pos, "more than one default case")
			}
			// reuse original default case
			n.Right = jmp
			def = n
		case 1:
			// one case -- reuse OCASE node
			n.Left = n.List.First()
			n.Right = jmp
			n.List.Set(nil)
			cas = append(cas, n)
		default:
			// Expand multi-valued cases and detect ranges of integer cases.
			if typeswvar != nil || sw.Left.Type.IsInterface() || !n.List.First().Type.IsInteger() || n.List.Len() < integerRangeMin {
				// Can't use integer ranges. Expand each case into a separate node.
				for _, n1 := range n.List.Slice() {
					cas = append(cas, nod(OCASE, n1, jmp))
				}
				break
			}
			// Find integer ranges within runs of constants.
			s := n.List.Slice()
			j := 0
			for j < len(s) {
				// Find a run of constants.
				var run int
				for run = j; run < len(s) && Isconst(s[run], CTINT); run++ {
				}
				if run-j >= integerRangeMin {
					// Search for integer ranges in s[j:run].
					// Typechecking is done, so all values are already in an appropriate range.
					search := s[j:run]
					sort.Sort(constIntNodesByVal(search))
					for beg, end := 0, 1; end <= len(search); end++ {
						if end < len(search) && search[end].Int64() == search[end-1].Int64()+1 {
							continue
						}
						if end-beg >= integerRangeMin {
							// Record range in List.
							c := nod(OCASE, nil, jmp)
							c.List.Set2(search[beg], search[end-1])
							cas = append(cas, c)
						} else {
							// Not large enough for range; record separately.
							for _, n := range search[beg:end] {
								cas = append(cas, nod(OCASE, n, jmp))
							}
						}
						beg = end
					}
					j = run
				}
				// Advance to next constant, adding individual non-constant
				// or as-yet-unhandled constant cases as we go.
				for ; j < len(s) && (j < run || !Isconst(s[j], CTINT)); j++ {
					cas = append(cas, nod(OCASE, s[j], jmp))
				}
			}
		}

		stat = append(stat, nodSym(OLABEL, nil, lbl))
		if typeswvar != nil && needvar && n.Rlist.Len() != 0 {
			l := []*Node{
				nod(ODCL, n.Rlist.First(), nil),
				nod(OAS, n.Rlist.First(), typeswvar),
			}
			typecheckslice(l, ctxStmt)
			stat = append(stat, l...)
		}
		stat = append(stat, n.Nbody.Slice()...)

		// Search backwards for the index of the fallthrough
		// statement. Do not assume it'll be in the last
		// position, since in some cases (e.g. when the statement
		// list contains autotmp_ variables), one or more OVARKILL
		// nodes will be at the end of the list.
		fallIndex := len(stat) - 1
		for stat[fallIndex].Op == OVARKILL {
			fallIndex--
		}
		last := stat[fallIndex]
		if last.Op != OFALL {
			stat = append(stat, br)
		}
	}

	stat = append(stat, br)
	if def != nil {
		cas = append(cas, def)
	}

	sw.List.Set(cas)
	sw.Nbody.Set(stat)
	lineno = lno
}

// genCaseClauses generates the caseClauses value for clauses.
func (s *exprSwitch) genCaseClauses(clauses []*Node) caseClauses {
	var cc caseClauses
	for _, n := range clauses {
		if n.Left == nil && n.List.Len() == 0 {
			// default case
			if cc.defjmp != nil {
				Fatalf("duplicate default case not detected during typechecking")
			}
			cc.defjmp = n.Right
			continue
		}
		c := caseClause{node: n, ordinal: len(cc.list)}
		if n.List.Len() > 0 {
			c.isconst = true
		}
		switch consttype(n.Left) {
		case CTFLT, CTINT, CTRUNE, CTSTR:
			c.isconst = true
		}
		cc.list = append(cc.list, c)
	}

	if cc.defjmp == nil {
		cc.defjmp = nod(OBREAK, nil, nil)
	}
	return cc
}

// genCaseClauses generates the caseClauses value for clauses.
func (s *typeSwitch) genCaseClauses(clauses []*Node) caseClauses {
	var cc caseClauses
	for _, n := range clauses {
		switch {
		case n.Left == nil:
			// default case
			if cc.defjmp != nil {
				Fatalf("duplicate default case not detected during typechecking")
			}
			cc.defjmp = n.Right
			continue
		case n.Left.Op == OLITERAL:
			// nil case in type switch
			if cc.niljmp != nil {
				Fatalf("duplicate nil case not detected during typechecking")
			}
			cc.niljmp = n.Right
			continue
		}

		// general case
		c := caseClause{
			node:    n,
			ordinal: len(cc.list),
			isconst: !n.Left.Type.IsInterface(),
			hash:    typehash(n.Left.Type),
		}
		cc.list = append(cc.list, c)
	}

	if cc.defjmp == nil {
		cc.defjmp = nod(OBREAK, nil, nil)
	}

	// diagnose duplicate cases
	s.checkDupCases(cc.list)
	return cc
}

func (s *typeSwitch) checkDupCases(cc []caseClause) {
	if len(cc) < 2 {
		return
	}
	// We store seen types in a map keyed by type hash.
	// It is possible, but very unlikely, for multiple distinct types to have the same hash.
	seen := make(map[uint32][]*Node)
	// To avoid many small allocations of length 1 slices,
	// also set up a single large slice to slice into.
	nn := make([]*Node, 0, len(cc))
Outer:
	for _, c := range cc {
		prev, ok := seen[c.hash]
		if !ok {
			// First entry for this hash.
			nn = append(nn, c.node)
			seen[c.hash] = nn[len(nn)-1 : len(nn) : len(nn)]
			continue
		}
		for _, n := range prev {
			if types.Identical(n.Left.Type, c.node.Left.Type) {
				yyerrorl(c.node.Pos, "duplicate case %v in type switch\n\tprevious case at %v", c.node.Left.Type, n.Line())
				// avoid double-reporting errors
				continue Outer
			}
		}
		seen[c.hash] = append(seen[c.hash], c.node)
	}
}

func checkDupExprCases(exprname *Node, clauses []*Node) {
	// boolean (naked) switch, nothing to do.
	if exprname == nil {
		return
	}
	// The common case is that s's expression is not an interface.
	// In that case, all constant clauses have the same type,
	// so checking for duplicates can be done solely by value.
	if !exprname.Type.IsInterface() {
		seen := make(map[interface{}]*Node)
		for _, ncase := range clauses {
			for _, n := range ncase.List.Slice() {
				// Can't check for duplicates that aren't constants, per the spec. Issue 15896.
				// Don't check for duplicate bools. Although the spec allows it,
				// (1) the compiler hasn't checked it in the past, so compatibility mandates it, and
				// (2) it would disallow useful things like
				//       case GOARCH == "arm" && GOARM == "5":
				//       case GOARCH == "arm":
				//     which would both evaluate to false for non-ARM compiles.
				if ct := consttype(n); ct == 0 || ct == CTBOOL {
					continue
				}

				val := n.Val().Interface()
				prev, dup := seen[val]
				if !dup {
					seen[val] = n
					continue
				}
				yyerrorl(ncase.Pos, "duplicate case %s in switch\n\tprevious case at %v",
					nodeAndVal(n), prev.Line())
			}
		}
		return
	}

	// s's expression is an interface. This is fairly rare, so
	// keep this simple. Case expressions are only duplicates if
	// they have the same value and identical types.
	//
	// In general, we have to use eqtype to test type identity,
	// because == gives false negatives for anonymous types and
	// the byte/uint8 and rune/int32 builtin type aliases.
	// However, this is not a problem here, because constant
	// expressions are always untyped or have a named type, and we
	// explicitly handle the builtin type aliases below.
	//
	// This approach may need to be revisited though if we fix
	// #21866 by treating all type aliases like byte/uint8 and
	// rune/int32.
	type typeVal struct {
		typ *types.Type
		val interface{}
	}
	seen := make(map[typeVal]*Node)
	for _, ncase := range clauses {
		for _, n := range ncase.List.Slice() {
			if ct := consttype(n); ct == 0 || ct == CTBOOL || ct == CTNIL {
				continue
			}
			tv := typeVal{
				typ: n.Type,
				val: n.Val().Interface(),
			}
			switch tv.typ {
			case types.Bytetype:
				tv.typ = types.Types[TUINT8]
			case types.Runetype:
				tv.typ = types.Types[TINT32]
			}
			prev, dup := seen[tv]
			if !dup {
				seen[tv] = n
				continue
			}
			yyerrorl(ncase.Pos, "duplicate case %s in switch\n\tprevious case at %v",
				nodeAndVal(n), prev.Line())
		}
	}
}

func nodeAndVal(n *Node) string {
	show := n.String()
	val := n.Val().Interface()
	if s := fmt.Sprintf("%#v", val); show != s {
		show += " (value " + s + ")"
	}
	return show
}

// walk generates an AST that implements sw,
// where sw is a type switch.
// The AST is generally of the form of a linear
// search using if..goto, although binary search
// is used with long runs of concrete types.
func (s *typeSwitch) walk(sw *Node) {
	cond := sw.Left
	sw.Left = nil

	if cond == nil {
		sw.List.Set(nil)
		return
	}
	if cond.Right == nil {
		yyerrorl(sw.Pos, "type switch must have an assignment")
		return
	}

	cond.Right = walkexpr(cond.Right, &sw.Ninit)
	if !cond.Right.Type.IsInterface() {
		yyerrorl(sw.Pos, "type switch must be on an interface")
		return
	}

	var cas []*Node

	// predeclare temporary variables and the boolean var
	s.facename = temp(cond.Right.Type)

	a := nod(OAS, s.facename, cond.Right)
	a = typecheck(a, ctxStmt)
	cas = append(cas, a)

	s.okname = temp(types.Types[TBOOL])
	s.okname = typecheck(s.okname, ctxExpr)

	s.hashname = temp(types.Types[TUINT32])
	s.hashname = typecheck(s.hashname, ctxExpr)

	// set up labels and jumps
	casebody(sw, s.facename)

	clauses := s.genCaseClauses(sw.List.Slice())
	sw.List.Set(nil)
	def := clauses.defjmp

	// For empty interfaces, do:
	//     if e._type == nil {
	//         do nil case if it exists, otherwise default
	//     }
	//     h := e._type.hash
	// Use a similar strategy for non-empty interfaces.

	// Get interface descriptor word.
	// For empty interfaces this will be the type.
	// For non-empty interfaces this will be the itab.
	itab := nod(OITAB, s.facename, nil)

	// Check for nil first.
	i := nod(OIF, nil, nil)
	i.Left = nod(OEQ, itab, nodnil())
	if clauses.niljmp != nil {
		// Do explicit nil case right here.
		i.Nbody.Set1(clauses.niljmp)
	} else {
		// Jump to default case.
		lbl := autolabel(".s")
		i.Nbody.Set1(nodSym(OGOTO, nil, lbl))
		// Wrap default case with label.
		blk := nod(OBLOCK, nil, nil)
		blk.List.Set2(nodSym(OLABEL, nil, lbl), def)
		def = blk
	}
	i.Left = typecheck(i.Left, ctxExpr)
	i.Left = defaultlit(i.Left, nil)
	cas = append(cas, i)

	// Load hash from type or itab.
	h := nodSym(ODOTPTR, itab, nil)
	h.Type = types.Types[TUINT32]
	h.SetTypecheck(1)
	if cond.Right.Type.IsEmptyInterface() {
		h.Xoffset = int64(2 * Widthptr) // offset of hash in runtime._type
	} else {
		h.Xoffset = int64(2 * Widthptr) // offset of hash in runtime.itab
	}
	h.SetBounded(true) // guaranteed not to fault
	a = nod(OAS, s.hashname, h)
	a = typecheck(a, ctxStmt)
	cas = append(cas, a)

	cc := clauses.list

	// insert type equality check into each case block
	for _, c := range cc {
		c.node.Right = s.typeone(c.node)
	}

	// generate list of if statements, binary search for constant sequences
	for len(cc) > 0 {
		if !cc[0].isconst {
			n := cc[0].node
			cas = append(cas, n.Right)
			cc = cc[1:]
			continue
		}

		// identify run of constants
		var run int
		for run = 1; run < len(cc) && cc[run].isconst; run++ {
		}

		// sort by hash
		sort.Sort(caseClauseByType(cc[:run]))

		// for debugging: linear search
		if false {
			for i := 0; i < run; i++ {
				n := cc[i].node
				cas = append(cas, n.Right)
			}
			continue
		}

		// combine adjacent cases with the same hash
		var batch []caseClause
		for i, j := 0, 0; i < run; i = j {
			hash := []*Node{cc[i].node.Right}
			for j = i + 1; j < run && cc[i].hash == cc[j].hash; j++ {
				hash = append(hash, cc[j].node.Right)
			}
			cc[i].node.Right = liststmt(hash)
			batch = append(batch, cc[i])
		}

		// binary search among cases to narrow by hash
		cas = append(cas, s.walkCases(batch))
		cc = cc[run:]
	}

	// handle default case
	if nerrors == 0 {
		cas = append(cas, def)
		sw.Nbody.Prepend(cas...)
		sw.List.Set(nil)
		walkstmtlist(sw.Nbody.Slice())
	}
}

// typeone generates an AST that jumps to the
// case body if the variable is of type t.
func (s *typeSwitch) typeone(t *Node) *Node {
	var name *Node
	var init Nodes
	if t.Rlist.Len() == 0 {
		name = nblank
		nblank = typecheck(nblank, ctxExpr|ctxAssign)
	} else {
		name = t.Rlist.First()
		init.Append(nod(ODCL, name, nil))
		a := nod(OAS, name, nil)
		a = typecheck(a, ctxStmt)
		init.Append(a)
	}

	a := nod(OAS2, nil, nil)
	a.List.Set2(name, s.okname) // name, ok =
	b := nod(ODOTTYPE, s.facename, nil)
	b.Type = t.Left.Type // interface.(type)
	a.Rlist.Set1(b)
	a = typecheck(a, ctxStmt)
	a = walkexpr(a, &init)
	init.Append(a)

	c := nod(OIF, nil, nil)
	c.Left = s.okname
	c.Nbody.Set1(t.Right) // if ok { goto l }

	init.Append(c)
	return init.asblock()
}

// walkCases generates an AST implementing the cases in cc.
func (s *typeSwitch) walkCases(cc []caseClause) *Node {
	if len(cc) < binarySearchMin {
		var cas []*Node
		for _, c := range cc {
			n := c.node
			if !c.isconst {
				Fatalf("typeSwitch walkCases")
			}
			a := nod(OIF, nil, nil)
			a.Left = nod(OEQ, s.hashname, nodintconst(int64(c.hash)))
			a.Left = typecheck(a.Left, ctxExpr)
			a.Left = defaultlit(a.Left, nil)
			a.Nbody.Set1(n.Right)
			cas = append(cas, a)
		}
		return liststmt(cas)
	}

	// find the middle and recur
	half := len(cc) / 2
	a := nod(OIF, nil, nil)
	a.Left = nod(OLE, s.hashname, nodintconst(int64(cc[half-1].hash)))
	a.Left = typecheck(a.Left, ctxExpr)
	a.Left = defaultlit(a.Left, nil)
	a.Nbody.Set1(s.walkCases(cc[:half]))
	a.Rlist.Set1(s.walkCases(cc[half:]))
	return a
}

// caseClauseByConstVal sorts clauses by constant value to enable binary search.
type caseClauseByConstVal []caseClause

func (x caseClauseByConstVal) Len() int      { return len(x) }
func (x caseClauseByConstVal) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x caseClauseByConstVal) Less(i, j int) bool {
	// n1 and n2 might be individual constants or integer ranges.
	// We have checked for duplicates already,
	// so ranges can be safely represented by any value in the range.
	n1 := x[i].node
	var v1 interface{}
	if s := n1.List.Slice(); s != nil {
		v1 = s[0].Val().U
	} else {
		v1 = n1.Left.Val().U
	}

	n2 := x[j].node
	var v2 interface{}
	if s := n2.List.Slice(); s != nil {
		v2 = s[0].Val().U
	} else {
		v2 = n2.Left.Val().U
	}

	switch v1 := v1.(type) {
	case *Mpflt:
		return v1.Cmp(v2.(*Mpflt)) < 0
	case *Mpint:
		return v1.Cmp(v2.(*Mpint)) < 0
	case string:
		// Sort strings by length and then by value.
		// It is much cheaper to compare lengths than values,
		// and all we need here is consistency.
		// We respect this sorting in exprSwitch.walkCases.
		a := v1
		b := v2.(string)
		if len(a) != len(b) {
			return len(a) < len(b)
		}
		return a < b
	}

	Fatalf("caseClauseByConstVal passed bad clauses %v < %v", x[i].node.Left, x[j].node.Left)
	return false
}

type caseClauseByType []caseClause

func (x caseClauseByType) Len() int      { return len(x) }
func (x caseClauseByType) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x caseClauseByType) Less(i, j int) bool {
	c1, c2 := x[i], x[j]
	// sort by hash code, then ordinal (for the rare case of hash collisions)
	if c1.hash != c2.hash {
		return c1.hash < c2.hash
	}
	return c1.ordinal < c2.ordinal
}

type constIntNodesByVal []*Node

func (x constIntNodesByVal) Len() int      { return len(x) }
func (x constIntNodesByVal) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x constIntNodesByVal) Less(i, j int) bool {
	return x[i].Val().U.(*Mpint).Cmp(x[j].Val().U.(*Mpint)) < 0
}
