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