Home | History | Annotate | Download | only in gc
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package gc
      6 
      7 import (
      8 	"cmd/compile/internal/types"
      9 	"fmt"
     10 	"sort"
     11 )
     12 
     13 const (
     14 	// expression switch
     15 	switchKindExpr  = iota // switch a {...} or switch 5 {...}
     16 	switchKindTrue         // switch true {...} or switch {...}
     17 	switchKindFalse        // switch false {...}
     18 )
     19 
     20 const (
     21 	binarySearchMin = 4 // minimum number of cases for binary search
     22 	integerRangeMin = 2 // minimum size of integer ranges
     23 )
     24 
     25 // An exprSwitch walks an expression switch.
     26 type exprSwitch struct {
     27 	exprname *Node // node for the expression being switched on
     28 	kind     int   // kind of switch statement (switchKind*)
     29 }
     30 
     31 // A typeSwitch walks a type switch.
     32 type typeSwitch struct {
     33 	hashname *Node // node for the hash of the type of the variable being switched on
     34 	facename *Node // node for the concrete type of the variable being switched on
     35 	okname   *Node // boolean node used for comma-ok type assertions
     36 }
     37 
     38 // A caseClause is a single case clause in a switch statement.
     39 type caseClause struct {
     40 	node    *Node  // points at case statement
     41 	ordinal int    // position in switch
     42 	hash    uint32 // hash of a type switch
     43 	// isconst indicates whether this case clause is a constant,
     44 	// for the purposes of the switch code generation.
     45 	// For expression switches, that's generally literals (case 5:, not case x:).
     46 	// For type switches, that's concrete types (case time.Time:), not interfaces (case io.Reader:).
     47 	isconst bool
     48 }
     49 
     50 // caseClauses are all the case clauses in a switch statement.
     51 type caseClauses struct {
     52 	list   []caseClause // general cases
     53 	defjmp *Node        // OGOTO for default case or OBREAK if no default case present
     54 	niljmp *Node        // OGOTO for nil type case in a type switch
     55 }
     56 
     57 // typecheckswitch typechecks a switch statement.
     58 func typecheckswitch(n *Node) {
     59 	typecheckslice(n.Ninit.Slice(), Etop)
     60 
     61 	var nilonly string
     62 	var top int
     63 	var t *types.Type
     64 
     65 	if n.Left != nil && n.Left.Op == OTYPESW {
     66 		// type switch
     67 		top = Etype
     68 		n.Left.Right = typecheck(n.Left.Right, Erv)
     69 		t = n.Left.Right.Type
     70 		if t != nil && !t.IsInterface() {
     71 			yyerrorl(n.Pos, "cannot type switch on non-interface value %L", n.Left.Right)
     72 		}
     73 	} else {
     74 		// expression switch
     75 		top = Erv
     76 		if n.Left != nil {
     77 			n.Left = typecheck(n.Left, Erv)
     78 			n.Left = defaultlit(n.Left, nil)
     79 			t = n.Left.Type
     80 		} else {
     81 			t = types.Types[TBOOL]
     82 		}
     83 		if t != nil {
     84 			switch {
     85 			case !okforeq[t.Etype]:
     86 				yyerrorl(n.Pos, "cannot switch on %L", n.Left)
     87 			case t.IsSlice():
     88 				nilonly = "slice"
     89 			case t.IsArray() && !IsComparable(t):
     90 				yyerrorl(n.Pos, "cannot switch on %L", n.Left)
     91 			case t.IsStruct():
     92 				if f := IncomparableField(t); f != nil {
     93 					yyerrorl(n.Pos, "cannot switch on %L (struct containing %v cannot be compared)", n.Left, f.Type)
     94 				}
     95 			case t.Etype == TFUNC:
     96 				nilonly = "func"
     97 			case t.IsMap():
     98 				nilonly = "map"
     99 			}
    100 		}
    101 	}
    102 
    103 	n.Type = t
    104 
    105 	var def, niltype *Node
    106 	for _, ncase := range n.List.Slice() {
    107 		if ncase.List.Len() == 0 {
    108 			// default
    109 			if def != nil {
    110 				setlineno(ncase)
    111 				yyerrorl(ncase.Pos, "multiple defaults in switch (first at %v)", def.Line())
    112 			} else {
    113 				def = ncase
    114 			}
    115 		} else {
    116 			ls := ncase.List.Slice()
    117 			for i1, n1 := range ls {
    118 				setlineno(n1)
    119 				ls[i1] = typecheck(ls[i1], Erv|Etype)
    120 				n1 = ls[i1]
    121 				if n1.Type == nil || t == nil {
    122 					continue
    123 				}
    124 
    125 				setlineno(ncase)
    126 				switch top {
    127 				// expression switch
    128 				case Erv:
    129 					ls[i1] = defaultlit(ls[i1], t)
    130 					n1 = ls[i1]
    131 					switch {
    132 					case n1.Op == OTYPE:
    133 						yyerrorl(ncase.Pos, "type %v is not an expression", n1.Type)
    134 					case n1.Type != nil && assignop(n1.Type, t, nil) == 0 && assignop(t, n1.Type, nil) == 0:
    135 						if n.Left != nil {
    136 							yyerrorl(ncase.Pos, "invalid case %v in switch on %v (mismatched types %v and %v)", n1, n.Left, n1.Type, t)
    137 						} else {
    138 							yyerrorl(ncase.Pos, "invalid case %v in switch (mismatched types %v and bool)", n1, n1.Type)
    139 						}
    140 					case nilonly != "" && !isnil(n1):
    141 						yyerrorl(ncase.Pos, "invalid case %v in switch (can only compare %s %v to nil)", n1, nilonly, n.Left)
    142 					case t.IsInterface() && !n1.Type.IsInterface() && !IsComparable(n1.Type):
    143 						yyerrorl(ncase.Pos, "invalid case %L in switch (incomparable type)", n1)
    144 					}
    145 
    146 				// type switch
    147 				case Etype:
    148 					var missing, have *types.Field
    149 					var ptr int
    150 					switch {
    151 					case n1.Op == OLITERAL && n1.Type.IsKind(TNIL):
    152 						// case nil:
    153 						if niltype != nil {
    154 							yyerrorl(ncase.Pos, "multiple nil cases in type switch (first at %v)", niltype.Line())
    155 						} else {
    156 							niltype = ncase
    157 						}
    158 					case n1.Op != OTYPE && n1.Type != nil: // should this be ||?
    159 						yyerrorl(ncase.Pos, "%L is not a type", n1)
    160 						// reset to original type
    161 						n1 = n.Left.Right
    162 						ls[i1] = n1
    163 					case !n1.Type.IsInterface() && t.IsInterface() && !implements(n1.Type, t, &missing, &have, &ptr):
    164 						if have != nil && !missing.Broke() && !have.Broke() {
    165 							yyerrorl(ncase.Pos, "impossible type switch case: %L cannot have dynamic type %v"+
    166 								" (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)
    167 						} else if !missing.Broke() {
    168 							if ptr != 0 {
    169 								yyerrorl(ncase.Pos, "impossible type switch case: %L cannot have dynamic type %v"+
    170 									" (%v method has pointer receiver)", n.Left.Right, n1.Type, missing.Sym)
    171 							} else {
    172 								yyerrorl(ncase.Pos, "impossible type switch case: %L cannot have dynamic type %v"+
    173 									" (missing %v method)", n.Left.Right, n1.Type, missing.Sym)
    174 							}
    175 						}
    176 					}
    177 				}
    178 			}
    179 		}
    180 
    181 		if n.Type == nil || n.Type.IsUntyped() {
    182 			// if the value we're switching on has no type or is untyped,
    183 			// we've already printed an error and don't need to continue
    184 			// typechecking the body
    185 			return
    186 		}
    187 
    188 		if top == Etype {
    189 			ll := ncase.List
    190 			if ncase.Rlist.Len() != 0 {
    191 				nvar := ncase.Rlist.First()
    192 				if ll.Len() == 1 && ll.First().Type != nil && !ll.First().Type.IsKind(TNIL) {
    193 					// single entry type switch
    194 					nvar.Type = ll.First().Type
    195 				} else {
    196 					// multiple entry type switch or default
    197 					nvar.Type = n.Type
    198 				}
    199 
    200 				nvar = typecheck(nvar, Erv|Easgn)
    201 				ncase.Rlist.SetFirst(nvar)
    202 			}
    203 		}
    204 
    205 		typecheckslice(ncase.Nbody.Slice(), Etop)
    206 	}
    207 	switch top {
    208 	// expression switch
    209 	case Erv:
    210 		checkDupExprCases(n.Left, n.List.Slice())
    211 	}
    212 }
    213 
    214 // walkswitch walks a switch statement.
    215 func walkswitch(sw *Node) {
    216 	// convert switch {...} to switch true {...}
    217 	if sw.Left == nil {
    218 		sw.Left = nodbool(true)
    219 		sw.Left = typecheck(sw.Left, Erv)
    220 	}
    221 
    222 	if sw.Left.Op == OTYPESW {
    223 		var s typeSwitch
    224 		s.walk(sw)
    225 	} else {
    226 		var s exprSwitch
    227 		s.walk(sw)
    228 	}
    229 }
    230 
    231 // walk generates an AST implementing sw.
    232 // sw is an expression switch.
    233 // The AST is generally of the form of a linear
    234 // search using if..goto, although binary search
    235 // is used with long runs of constants.
    236 func (s *exprSwitch) walk(sw *Node) {
    237 	casebody(sw, nil)
    238 
    239 	cond := sw.Left
    240 	sw.Left = nil
    241 
    242 	s.kind = switchKindExpr
    243 	if Isconst(cond, CTBOOL) {
    244 		s.kind = switchKindTrue
    245 		if !cond.Val().U.(bool) {
    246 			s.kind = switchKindFalse
    247 		}
    248 	}
    249 
    250 	cond = walkexpr(cond, &sw.Ninit)
    251 	t := sw.Type
    252 	if t == nil {
    253 		return
    254 	}
    255 
    256 	// convert the switch into OIF statements
    257 	var cas []*Node
    258 	if s.kind == switchKindTrue || s.kind == switchKindFalse {
    259 		s.exprname = nodbool(s.kind == switchKindTrue)
    260 	} else if consttype(cond) > 0 {
    261 		// leave constants to enable dead code elimination (issue 9608)
    262 		s.exprname = cond
    263 	} else {
    264 		s.exprname = temp(cond.Type)
    265 		cas = []*Node{nod(OAS, s.exprname, cond)}
    266 		typecheckslice(cas, Etop)
    267 	}
    268 
    269 	// Enumerate the cases and prepare the default case.
    270 	clauses := s.genCaseClauses(sw.List.Slice())
    271 	sw.List.Set(nil)
    272 	cc := clauses.list
    273 
    274 	// handle the cases in order
    275 	for len(cc) > 0 {
    276 		run := 1
    277 		if okforcmp[t.Etype] && cc[0].isconst {
    278 			// do binary search on runs of constants
    279 			for ; run < len(cc) && cc[run].isconst; run++ {
    280 			}
    281 			// sort and compile constants
    282 			sort.Sort(caseClauseByConstVal(cc[:run]))
    283 		}
    284 
    285 		a := s.walkCases(cc[:run])
    286 		cas = append(cas, a)
    287 		cc = cc[run:]
    288 	}
    289 
    290 	// handle default case
    291 	if nerrors == 0 {
    292 		cas = append(cas, clauses.defjmp)
    293 		sw.Nbody.Prepend(cas...)
    294 		walkstmtlist(sw.Nbody.Slice())
    295 	}
    296 }
    297 
    298 // walkCases generates an AST implementing the cases in cc.
    299 func (s *exprSwitch) walkCases(cc []caseClause) *Node {
    300 	if len(cc) < binarySearchMin {
    301 		// linear search
    302 		var cas []*Node
    303 		for _, c := range cc {
    304 			n := c.node
    305 			lno := setlineno(n)
    306 
    307 			a := nod(OIF, nil, nil)
    308 			if rng := n.List.Slice(); rng != nil {
    309 				// Integer range.
    310 				// exprname is a temp or a constant,
    311 				// so it is safe to evaluate twice.
    312 				// In most cases, this conjunction will be
    313 				// rewritten by walkinrange into a single comparison.
    314 				low := nod(OGE, s.exprname, rng[0])
    315 				high := nod(OLE, s.exprname, rng[1])
    316 				a.Left = nod(OANDAND, low, high)
    317 				a.Left = typecheck(a.Left, Erv)
    318 				a.Left = walkexpr(a.Left, nil) // give walk the opportunity to optimize the range check
    319 			} 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 {
    320 				a.Left = nod(OEQ, s.exprname, n.Left) // if name == val
    321 				a.Left = typecheck(a.Left, Erv)
    322 			} else if s.kind == switchKindTrue {
    323 				a.Left = n.Left // if val
    324 			} else {
    325 				// s.kind == switchKindFalse
    326 				a.Left = nod(ONOT, n.Left, nil) // if !val
    327 				a.Left = typecheck(a.Left, Erv)
    328 			}
    329 			a.Nbody.Set1(n.Right) // goto l
    330 
    331 			cas = append(cas, a)
    332 			lineno = lno
    333 		}
    334 		return liststmt(cas)
    335 	}
    336 
    337 	// find the middle and recur
    338 	half := len(cc) / 2
    339 	a := nod(OIF, nil, nil)
    340 	n := cc[half-1].node
    341 	var mid *Node
    342 	if rng := n.List.Slice(); rng != nil {
    343 		mid = rng[1] // high end of range
    344 	} else {
    345 		mid = n.Left
    346 	}
    347 	le := nod(OLE, s.exprname, mid)
    348 	if Isconst(mid, CTSTR) {
    349 		// Search by length and then by value; see caseClauseByConstVal.
    350 		lenlt := nod(OLT, nod(OLEN, s.exprname, nil), nod(OLEN, mid, nil))
    351 		leneq := nod(OEQ, nod(OLEN, s.exprname, nil), nod(OLEN, mid, nil))
    352 		a.Left = nod(OOROR, lenlt, nod(OANDAND, leneq, le))
    353 	} else {
    354 		a.Left = le
    355 	}
    356 	a.Left = typecheck(a.Left, Erv)
    357 	a.Nbody.Set1(s.walkCases(cc[:half]))
    358 	a.Rlist.Set1(s.walkCases(cc[half:]))
    359 	return a
    360 }
    361 
    362 // casebody builds separate lists of statements and cases.
    363 // It makes labels between cases and statements
    364 // and deals with fallthrough, break, and unreachable statements.
    365 func casebody(sw *Node, typeswvar *Node) {
    366 	if sw.List.Len() == 0 {
    367 		return
    368 	}
    369 
    370 	lno := setlineno(sw)
    371 
    372 	var cas []*Node  // cases
    373 	var stat []*Node // statements
    374 	var def *Node    // defaults
    375 	br := nod(OBREAK, nil, nil)
    376 
    377 	for _, n := range sw.List.Slice() {
    378 		setlineno(n)
    379 		if n.Op != OXCASE {
    380 			Fatalf("casebody %v", n.Op)
    381 		}
    382 		n.Op = OCASE
    383 		needvar := n.List.Len() != 1 || n.List.First().Op == OLITERAL
    384 
    385 		jmp := nod(OGOTO, autolabel(".s"), nil)
    386 		switch n.List.Len() {
    387 		case 0:
    388 			// default
    389 			if def != nil {
    390 				yyerrorl(n.Pos, "more than one default case")
    391 			}
    392 			// reuse original default case
    393 			n.Right = jmp
    394 			def = n
    395 		case 1:
    396 			// one case -- reuse OCASE node
    397 			n.Left = n.List.First()
    398 			n.Right = jmp
    399 			n.List.Set(nil)
    400 			cas = append(cas, n)
    401 		default:
    402 			// Expand multi-valued cases and detect ranges of integer cases.
    403 			if typeswvar != nil || sw.Left.Type.IsInterface() || !n.List.First().Type.IsInteger() || n.List.Len() < integerRangeMin {
    404 				// Can't use integer ranges. Expand each case into a separate node.
    405 				for _, n1 := range n.List.Slice() {
    406 					cas = append(cas, nod(OCASE, n1, jmp))
    407 				}
    408 				break
    409 			}
    410 			// Find integer ranges within runs of constants.
    411 			s := n.List.Slice()
    412 			j := 0
    413 			for j < len(s) {
    414 				// Find a run of constants.
    415 				var run int
    416 				for run = j; run < len(s) && Isconst(s[run], CTINT); run++ {
    417 				}
    418 				if run-j >= integerRangeMin {
    419 					// Search for integer ranges in s[j:run].
    420 					// Typechecking is done, so all values are already in an appropriate range.
    421 					search := s[j:run]
    422 					sort.Sort(constIntNodesByVal(search))
    423 					for beg, end := 0, 1; end <= len(search); end++ {
    424 						if end < len(search) && search[end].Int64() == search[end-1].Int64()+1 {
    425 							continue
    426 						}
    427 						if end-beg >= integerRangeMin {
    428 							// Record range in List.
    429 							c := nod(OCASE, nil, jmp)
    430 							c.List.Set2(search[beg], search[end-1])
    431 							cas = append(cas, c)
    432 						} else {
    433 							// Not large enough for range; record separately.
    434 							for _, n := range search[beg:end] {
    435 								cas = append(cas, nod(OCASE, n, jmp))
    436 							}
    437 						}
    438 						beg = end
    439 					}
    440 					j = run
    441 				}
    442 				// Advance to next constant, adding individual non-constant
    443 				// or as-yet-unhandled constant cases as we go.
    444 				for ; j < len(s) && (j < run || !Isconst(s[j], CTINT)); j++ {
    445 					cas = append(cas, nod(OCASE, s[j], jmp))
    446 				}
    447 			}
    448 		}
    449 
    450 		stat = append(stat, nod(OLABEL, jmp.Left, nil))
    451 		if typeswvar != nil && needvar && n.Rlist.Len() != 0 {
    452 			l := []*Node{
    453 				nod(ODCL, n.Rlist.First(), nil),
    454 				nod(OAS, n.Rlist.First(), typeswvar),
    455 			}
    456 			typecheckslice(l, Etop)
    457 			stat = append(stat, l...)
    458 		}
    459 		stat = append(stat, n.Nbody.Slice()...)
    460 
    461 		// Search backwards for the index of the fallthrough
    462 		// statement. Do not assume it'll be in the last
    463 		// position, since in some cases (e.g. when the statement
    464 		// list contains autotmp_ variables), one or more OVARKILL
    465 		// nodes will be at the end of the list.
    466 		fallIndex := len(stat) - 1
    467 		for stat[fallIndex].Op == OVARKILL {
    468 			fallIndex--
    469 		}
    470 		last := stat[fallIndex]
    471 		if last.Op != OFALL {
    472 			stat = append(stat, br)
    473 		}
    474 	}
    475 
    476 	stat = append(stat, br)
    477 	if def != nil {
    478 		cas = append(cas, def)
    479 	}
    480 
    481 	sw.List.Set(cas)
    482 	sw.Nbody.Set(stat)
    483 	lineno = lno
    484 }
    485 
    486 // genCaseClauses generates the caseClauses value for clauses.
    487 func (s *exprSwitch) genCaseClauses(clauses []*Node) caseClauses {
    488 	var cc caseClauses
    489 	for _, n := range clauses {
    490 		if n.Left == nil && n.List.Len() == 0 {
    491 			// default case
    492 			if cc.defjmp != nil {
    493 				Fatalf("duplicate default case not detected during typechecking")
    494 			}
    495 			cc.defjmp = n.Right
    496 			continue
    497 		}
    498 		c := caseClause{node: n, ordinal: len(cc.list)}
    499 		if n.List.Len() > 0 {
    500 			c.isconst = true
    501 		}
    502 		switch consttype(n.Left) {
    503 		case CTFLT, CTINT, CTRUNE, CTSTR:
    504 			c.isconst = true
    505 		}
    506 		cc.list = append(cc.list, c)
    507 	}
    508 
    509 	if cc.defjmp == nil {
    510 		cc.defjmp = nod(OBREAK, nil, nil)
    511 	}
    512 	return cc
    513 }
    514 
    515 // genCaseClauses generates the caseClauses value for clauses.
    516 func (s *typeSwitch) genCaseClauses(clauses []*Node) caseClauses {
    517 	var cc caseClauses
    518 	for _, n := range clauses {
    519 		switch {
    520 		case n.Left == nil:
    521 			// default case
    522 			if cc.defjmp != nil {
    523 				Fatalf("duplicate default case not detected during typechecking")
    524 			}
    525 			cc.defjmp = n.Right
    526 			continue
    527 		case n.Left.Op == OLITERAL:
    528 			// nil case in type switch
    529 			if cc.niljmp != nil {
    530 				Fatalf("duplicate nil case not detected during typechecking")
    531 			}
    532 			cc.niljmp = n.Right
    533 			continue
    534 		}
    535 
    536 		// general case
    537 		c := caseClause{
    538 			node:    n,
    539 			ordinal: len(cc.list),
    540 			isconst: !n.Left.Type.IsInterface(),
    541 			hash:    typehash(n.Left.Type),
    542 		}
    543 		cc.list = append(cc.list, c)
    544 	}
    545 
    546 	if cc.defjmp == nil {
    547 		cc.defjmp = nod(OBREAK, nil, nil)
    548 	}
    549 
    550 	// diagnose duplicate cases
    551 	s.checkDupCases(cc.list)
    552 	return cc
    553 }
    554 
    555 func (s *typeSwitch) checkDupCases(cc []caseClause) {
    556 	if len(cc) < 2 {
    557 		return
    558 	}
    559 	// We store seen types in a map keyed by type hash.
    560 	// It is possible, but very unlikely, for multiple distinct types to have the same hash.
    561 	seen := make(map[uint32][]*Node)
    562 	// To avoid many small allocations of length 1 slices,
    563 	// also set up a single large slice to slice into.
    564 	nn := make([]*Node, 0, len(cc))
    565 Outer:
    566 	for _, c := range cc {
    567 		prev, ok := seen[c.hash]
    568 		if !ok {
    569 			// First entry for this hash.
    570 			nn = append(nn, c.node)
    571 			seen[c.hash] = nn[len(nn)-1 : len(nn) : len(nn)]
    572 			continue
    573 		}
    574 		for _, n := range prev {
    575 			if eqtype(n.Left.Type, c.node.Left.Type) {
    576 				yyerrorl(c.node.Pos, "duplicate case %v in type switch\n\tprevious case at %v", c.node.Left.Type, n.Line())
    577 				// avoid double-reporting errors
    578 				continue Outer
    579 			}
    580 		}
    581 		seen[c.hash] = append(seen[c.hash], c.node)
    582 	}
    583 }
    584 
    585 func checkDupExprCases(exprname *Node, clauses []*Node) {
    586 	// boolean (naked) switch, nothing to do.
    587 	if exprname == nil {
    588 		return
    589 	}
    590 	// The common case is that s's expression is not an interface.
    591 	// In that case, all constant clauses have the same type,
    592 	// so checking for duplicates can be done solely by value.
    593 	if !exprname.Type.IsInterface() {
    594 		seen := make(map[interface{}]*Node)
    595 		for _, ncase := range clauses {
    596 			for _, n := range ncase.List.Slice() {
    597 				// Can't check for duplicates that aren't constants, per the spec. Issue 15896.
    598 				// Don't check for duplicate bools. Although the spec allows it,
    599 				// (1) the compiler hasn't checked it in the past, so compatibility mandates it, and
    600 				// (2) it would disallow useful things like
    601 				//       case GOARCH == "arm" && GOARM == "5":
    602 				//       case GOARCH == "arm":
    603 				//     which would both evaluate to false for non-ARM compiles.
    604 				if ct := consttype(n); ct == 0 || ct == CTBOOL {
    605 					continue
    606 				}
    607 
    608 				val := n.Val().Interface()
    609 				prev, dup := seen[val]
    610 				if !dup {
    611 					seen[val] = n
    612 					continue
    613 				}
    614 				yyerrorl(ncase.Pos, "duplicate case %s in switch\n\tprevious case at %v",
    615 					nodeAndVal(n), prev.Line())
    616 			}
    617 		}
    618 		return
    619 	}
    620 	// s's expression is an interface. This is fairly rare, so keep this simple.
    621 	// Duplicates are only duplicates if they have the same type and the same value.
    622 	type typeVal struct {
    623 		typ string
    624 		val interface{}
    625 	}
    626 	seen := make(map[typeVal]*Node)
    627 	for _, ncase := range clauses {
    628 		for _, n := range ncase.List.Slice() {
    629 			if ct := consttype(n); ct == 0 || ct == CTBOOL {
    630 				continue
    631 			}
    632 			tv := typeVal{
    633 				typ: n.Type.LongString(),
    634 				val: n.Val().Interface(),
    635 			}
    636 			prev, dup := seen[tv]
    637 			if !dup {
    638 				seen[tv] = n
    639 				continue
    640 			}
    641 			yyerrorl(ncase.Pos, "duplicate case %s in switch\n\tprevious case at %v",
    642 				nodeAndVal(n), prev.Line())
    643 		}
    644 	}
    645 }
    646 
    647 func nodeAndVal(n *Node) string {
    648 	show := n.String()
    649 	val := n.Val().Interface()
    650 	if s := fmt.Sprintf("%#v", val); show != s {
    651 		show += " (value " + s + ")"
    652 	}
    653 	return show
    654 }
    655 
    656 // walk generates an AST that implements sw,
    657 // where sw is a type switch.
    658 // The AST is generally of the form of a linear
    659 // search using if..goto, although binary search
    660 // is used with long runs of concrete types.
    661 func (s *typeSwitch) walk(sw *Node) {
    662 	cond := sw.Left
    663 	sw.Left = nil
    664 
    665 	if cond == nil {
    666 		sw.List.Set(nil)
    667 		return
    668 	}
    669 	if cond.Right == nil {
    670 		yyerrorl(sw.Pos, "type switch must have an assignment")
    671 		return
    672 	}
    673 
    674 	cond.Right = walkexpr(cond.Right, &sw.Ninit)
    675 	if !cond.Right.Type.IsInterface() {
    676 		yyerrorl(sw.Pos, "type switch must be on an interface")
    677 		return
    678 	}
    679 
    680 	var cas []*Node
    681 
    682 	// predeclare temporary variables and the boolean var
    683 	s.facename = temp(cond.Right.Type)
    684 
    685 	a := nod(OAS, s.facename, cond.Right)
    686 	a = typecheck(a, Etop)
    687 	cas = append(cas, a)
    688 
    689 	s.okname = temp(types.Types[TBOOL])
    690 	s.okname = typecheck(s.okname, Erv)
    691 
    692 	s.hashname = temp(types.Types[TUINT32])
    693 	s.hashname = typecheck(s.hashname, Erv)
    694 
    695 	// set up labels and jumps
    696 	casebody(sw, s.facename)
    697 
    698 	clauses := s.genCaseClauses(sw.List.Slice())
    699 	sw.List.Set(nil)
    700 	def := clauses.defjmp
    701 
    702 	// For empty interfaces, do:
    703 	//     if e._type == nil {
    704 	//         do nil case if it exists, otherwise default
    705 	//     }
    706 	//     h := e._type.hash
    707 	// Use a similar strategy for non-empty interfaces.
    708 
    709 	// Get interface descriptor word.
    710 	// For empty interfaces this will be the type.
    711 	// For non-empty interfaces this will be the itab.
    712 	itab := nod(OITAB, s.facename, nil)
    713 
    714 	// Check for nil first.
    715 	i := nod(OIF, nil, nil)
    716 	i.Left = nod(OEQ, itab, nodnil())
    717 	if clauses.niljmp != nil {
    718 		// Do explicit nil case right here.
    719 		i.Nbody.Set1(clauses.niljmp)
    720 	} else {
    721 		// Jump to default case.
    722 		lbl := autolabel(".s")
    723 		i.Nbody.Set1(nod(OGOTO, lbl, nil))
    724 		// Wrap default case with label.
    725 		blk := nod(OBLOCK, nil, nil)
    726 		blk.List.Set2(nod(OLABEL, lbl, nil), def)
    727 		def = blk
    728 	}
    729 	i.Left = typecheck(i.Left, Erv)
    730 	cas = append(cas, i)
    731 
    732 	// Load hash from type or itab.
    733 	h := nodSym(ODOTPTR, itab, nil)
    734 	h.Type = types.Types[TUINT32]
    735 	h.SetTypecheck(1)
    736 	if cond.Right.Type.IsEmptyInterface() {
    737 		h.Xoffset = int64(2 * Widthptr) // offset of hash in runtime._type
    738 	} else {
    739 		h.Xoffset = int64(2 * Widthptr) // offset of hash in runtime.itab
    740 	}
    741 	h.SetBounded(true) // guaranteed not to fault
    742 	a = nod(OAS, s.hashname, h)
    743 	a = typecheck(a, Etop)
    744 	cas = append(cas, a)
    745 
    746 	cc := clauses.list
    747 
    748 	// insert type equality check into each case block
    749 	for _, c := range cc {
    750 		c.node.Right = s.typeone(c.node)
    751 	}
    752 
    753 	// generate list of if statements, binary search for constant sequences
    754 	for len(cc) > 0 {
    755 		if !cc[0].isconst {
    756 			n := cc[0].node
    757 			cas = append(cas, n.Right)
    758 			cc = cc[1:]
    759 			continue
    760 		}
    761 
    762 		// identify run of constants
    763 		var run int
    764 		for run = 1; run < len(cc) && cc[run].isconst; run++ {
    765 		}
    766 
    767 		// sort by hash
    768 		sort.Sort(caseClauseByType(cc[:run]))
    769 
    770 		// for debugging: linear search
    771 		if false {
    772 			for i := 0; i < run; i++ {
    773 				n := cc[i].node
    774 				cas = append(cas, n.Right)
    775 			}
    776 			continue
    777 		}
    778 
    779 		// combine adjacent cases with the same hash
    780 		ncase := 0
    781 		for i := 0; i < run; i++ {
    782 			ncase++
    783 			hash := []*Node{cc[i].node.Right}
    784 			for j := i + 1; j < run && cc[i].hash == cc[j].hash; j++ {
    785 				hash = append(hash, cc[j].node.Right)
    786 			}
    787 			cc[i].node.Right = liststmt(hash)
    788 		}
    789 
    790 		// binary search among cases to narrow by hash
    791 		cas = append(cas, s.walkCases(cc[:ncase]))
    792 		cc = cc[ncase:]
    793 	}
    794 
    795 	// handle default case
    796 	if nerrors == 0 {
    797 		cas = append(cas, def)
    798 		sw.Nbody.Prepend(cas...)
    799 		sw.List.Set(nil)
    800 		walkstmtlist(sw.Nbody.Slice())
    801 	}
    802 }
    803 
    804 // typeone generates an AST that jumps to the
    805 // case body if the variable is of type t.
    806 func (s *typeSwitch) typeone(t *Node) *Node {
    807 	var name *Node
    808 	var init Nodes
    809 	if t.Rlist.Len() == 0 {
    810 		name = nblank
    811 		nblank = typecheck(nblank, Erv|Easgn)
    812 	} else {
    813 		name = t.Rlist.First()
    814 		init.Append(nod(ODCL, name, nil))
    815 		a := nod(OAS, name, nil)
    816 		a = typecheck(a, Etop)
    817 		init.Append(a)
    818 	}
    819 
    820 	a := nod(OAS2, nil, nil)
    821 	a.List.Set2(name, s.okname) // name, ok =
    822 	b := nod(ODOTTYPE, s.facename, nil)
    823 	b.Type = t.Left.Type // interface.(type)
    824 	a.Rlist.Set1(b)
    825 	a = typecheck(a, Etop)
    826 	a = walkexpr(a, &init)
    827 	init.Append(a)
    828 
    829 	c := nod(OIF, nil, nil)
    830 	c.Left = s.okname
    831 	c.Nbody.Set1(t.Right) // if ok { goto l }
    832 
    833 	init.Append(c)
    834 	return init.asblock()
    835 }
    836 
    837 // walkCases generates an AST implementing the cases in cc.
    838 func (s *typeSwitch) walkCases(cc []caseClause) *Node {
    839 	if len(cc) < binarySearchMin {
    840 		var cas []*Node
    841 		for _, c := range cc {
    842 			n := c.node
    843 			if !c.isconst {
    844 				Fatalf("typeSwitch walkCases")
    845 			}
    846 			a := nod(OIF, nil, nil)
    847 			a.Left = nod(OEQ, s.hashname, nodintconst(int64(c.hash)))
    848 			a.Left = typecheck(a.Left, Erv)
    849 			a.Nbody.Set1(n.Right)
    850 			cas = append(cas, a)
    851 		}
    852 		return liststmt(cas)
    853 	}
    854 
    855 	// find the middle and recur
    856 	half := len(cc) / 2
    857 	a := nod(OIF, nil, nil)
    858 	a.Left = nod(OLE, s.hashname, nodintconst(int64(cc[half-1].hash)))
    859 	a.Left = typecheck(a.Left, Erv)
    860 	a.Nbody.Set1(s.walkCases(cc[:half]))
    861 	a.Rlist.Set1(s.walkCases(cc[half:]))
    862 	return a
    863 }
    864 
    865 // caseClauseByConstVal sorts clauses by constant value to enable binary search.
    866 type caseClauseByConstVal []caseClause
    867 
    868 func (x caseClauseByConstVal) Len() int      { return len(x) }
    869 func (x caseClauseByConstVal) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
    870 func (x caseClauseByConstVal) Less(i, j int) bool {
    871 	// n1 and n2 might be individual constants or integer ranges.
    872 	// We have checked for duplicates already,
    873 	// so ranges can be safely represented by any value in the range.
    874 	n1 := x[i].node
    875 	var v1 interface{}
    876 	if s := n1.List.Slice(); s != nil {
    877 		v1 = s[0].Val().U
    878 	} else {
    879 		v1 = n1.Left.Val().U
    880 	}
    881 
    882 	n2 := x[j].node
    883 	var v2 interface{}
    884 	if s := n2.List.Slice(); s != nil {
    885 		v2 = s[0].Val().U
    886 	} else {
    887 		v2 = n2.Left.Val().U
    888 	}
    889 
    890 	switch v1 := v1.(type) {
    891 	case *Mpflt:
    892 		return v1.Cmp(v2.(*Mpflt)) < 0
    893 	case *Mpint:
    894 		return v1.Cmp(v2.(*Mpint)) < 0
    895 	case string:
    896 		// Sort strings by length and then by value.
    897 		// It is much cheaper to compare lengths than values,
    898 		// and all we need here is consistency.
    899 		// We respect this sorting in exprSwitch.walkCases.
    900 		a := v1
    901 		b := v2.(string)
    902 		if len(a) != len(b) {
    903 			return len(a) < len(b)
    904 		}
    905 		return a < b
    906 	}
    907 
    908 	Fatalf("caseClauseByConstVal passed bad clauses %v < %v", x[i].node.Left, x[j].node.Left)
    909 	return false
    910 }
    911 
    912 type caseClauseByType []caseClause
    913 
    914 func (x caseClauseByType) Len() int      { return len(x) }
    915 func (x caseClauseByType) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
    916 func (x caseClauseByType) Less(i, j int) bool {
    917 	c1, c2 := x[i], x[j]
    918 	// sort by hash code, then ordinal (for the rare case of hash collisions)
    919 	if c1.hash != c2.hash {
    920 		return c1.hash < c2.hash
    921 	}
    922 	return c1.ordinal < c2.ordinal
    923 }
    924 
    925 type constIntNodesByVal []*Node
    926 
    927 func (x constIntNodesByVal) Len() int      { return len(x) }
    928 func (x constIntNodesByVal) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
    929 func (x constIntNodesByVal) Less(i, j int) bool {
    930 	return x[i].Val().U.(*Mpint).Cmp(x[j].Val().U.(*Mpint)) < 0
    931 }
    932