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/internal/obj"
      9 	"fmt"
     10 	"sort"
     11 	"strconv"
     12 )
     13 
     14 const (
     15 	// expression switch
     16 	switchKindExpr  = iota // switch a {...} or switch 5 {...}
     17 	switchKindTrue         // switch true {...} or switch {...}
     18 	switchKindFalse        // switch false {...}
     19 
     20 	// type switch
     21 	switchKindType // switch a.(type) {...}
     22 )
     23 
     24 const (
     25 	caseKindDefault = iota // default:
     26 
     27 	// expression switch
     28 	caseKindExprConst // case 5:
     29 	caseKindExprVar   // case x:
     30 
     31 	// type switch
     32 	caseKindTypeNil   // case nil:
     33 	caseKindTypeConst // case time.Time: (concrete type, has type hash)
     34 	caseKindTypeVar   // case io.Reader: (interface type)
     35 )
     36 
     37 const binarySearchMin = 4 // minimum number of cases for binary search
     38 
     39 // An exprSwitch walks an expression switch.
     40 type exprSwitch struct {
     41 	exprname *Node // node for the expression being switched on
     42 	kind     int   // kind of switch statement (switchKind*)
     43 }
     44 
     45 // A typeSwitch walks a type switch.
     46 type typeSwitch struct {
     47 	hashname *Node // node for the hash of the type of the variable being switched on
     48 	facename *Node // node for the concrete type of the variable being switched on
     49 	okname   *Node // boolean node used for comma-ok type assertions
     50 }
     51 
     52 // A caseClause is a single case clause in a switch statement.
     53 type caseClause struct {
     54 	node    *Node  // points at case statement
     55 	ordinal int    // position in switch
     56 	hash    uint32 // hash of a type switch
     57 	typ     uint8  // type of case
     58 }
     59 
     60 // typecheckswitch typechecks a switch statement.
     61 func typecheckswitch(n *Node) {
     62 	lno := int(lineno)
     63 	typechecklist(n.Ninit, Etop)
     64 
     65 	var nilonly string
     66 	var top int
     67 	var t *Type
     68 
     69 	if n.Left != nil && n.Left.Op == OTYPESW {
     70 		// type switch
     71 		top = Etype
     72 		typecheck(&n.Left.Right, Erv)
     73 		t = n.Left.Right.Type
     74 		if t != nil && t.Etype != TINTER {
     75 			Yyerror("cannot type switch on non-interface value %v", Nconv(n.Left.Right, obj.FmtLong))
     76 		}
     77 	} else {
     78 		// expression switch
     79 		top = Erv
     80 		if n.Left != nil {
     81 			typecheck(&n.Left, Erv)
     82 			defaultlit(&n.Left, nil)
     83 			t = n.Left.Type
     84 		} else {
     85 			t = Types[TBOOL]
     86 		}
     87 		if t != nil {
     88 			var badtype *Type
     89 			switch {
     90 			case !okforeq[t.Etype]:
     91 				Yyerror("cannot switch on %v", Nconv(n.Left, obj.FmtLong))
     92 			case t.Etype == TARRAY && !Isfixedarray(t):
     93 				nilonly = "slice"
     94 			case t.Etype == TARRAY && Isfixedarray(t) && algtype1(t, nil) == ANOEQ:
     95 				Yyerror("cannot switch on %v", Nconv(n.Left, obj.FmtLong))
     96 			case t.Etype == TSTRUCT && algtype1(t, &badtype) == ANOEQ:
     97 				Yyerror("cannot switch on %v (struct containing %v cannot be compared)", Nconv(n.Left, obj.FmtLong), badtype)
     98 			case t.Etype == TFUNC:
     99 				nilonly = "func"
    100 			case t.Etype == TMAP:
    101 				nilonly = "map"
    102 			}
    103 		}
    104 	}
    105 
    106 	n.Type = t
    107 
    108 	var def *Node
    109 	var ll *NodeList
    110 	for l := n.List; l != nil; l = l.Next {
    111 		ncase := l.N
    112 		setlineno(n)
    113 		if ncase.List == nil {
    114 			// default
    115 			if def != nil {
    116 				Yyerror("multiple defaults in switch (first at %v)", def.Line())
    117 			} else {
    118 				def = ncase
    119 			}
    120 		} else {
    121 			for ll = ncase.List; ll != nil; ll = ll.Next {
    122 				setlineno(ll.N)
    123 				typecheck(&ll.N, Erv|Etype)
    124 				if ll.N.Type == nil || t == nil {
    125 					continue
    126 				}
    127 				setlineno(ncase)
    128 				switch top {
    129 				// expression switch
    130 				case Erv:
    131 					defaultlit(&ll.N, t)
    132 					switch {
    133 					case ll.N.Op == OTYPE:
    134 						Yyerror("type %v is not an expression", ll.N.Type)
    135 					case ll.N.Type != nil && assignop(ll.N.Type, t, nil) == 0 && assignop(t, ll.N.Type, nil) == 0:
    136 						if n.Left != nil {
    137 							Yyerror("invalid case %v in switch on %v (mismatched types %v and %v)", ll.N, n.Left, ll.N.Type, t)
    138 						} else {
    139 							Yyerror("invalid case %v in switch (mismatched types %v and bool)", ll.N, ll.N.Type)
    140 						}
    141 					case nilonly != "" && !Isconst(ll.N, CTNIL):
    142 						Yyerror("invalid case %v in switch (can only compare %s %v to nil)", ll.N, nilonly, n.Left)
    143 					}
    144 
    145 				// type switch
    146 				case Etype:
    147 					var missing, have *Type
    148 					var ptr int
    149 					switch {
    150 					case ll.N.Op == OLITERAL && Istype(ll.N.Type, TNIL):
    151 					case ll.N.Op != OTYPE && ll.N.Type != nil: // should this be ||?
    152 						Yyerror("%v is not a type", Nconv(ll.N, obj.FmtLong))
    153 						// reset to original type
    154 						ll.N = n.Left.Right
    155 					case ll.N.Type.Etype != TINTER && t.Etype == TINTER && !implements(ll.N.Type, t, &missing, &have, &ptr):
    156 						if have != nil && missing.Broke == 0 && have.Broke == 0 {
    157 							Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (wrong type for %v method)\n\thave %v%v\n\twant %v%v", Nconv(n.Left.Right, obj.FmtLong), ll.N.Type, missing.Sym, have.Sym, Tconv(have.Type, obj.FmtShort), missing.Sym, Tconv(missing.Type, obj.FmtShort))
    158 						} else if missing.Broke == 0 {
    159 							Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (missing %v method)", Nconv(n.Left.Right, obj.FmtLong), ll.N.Type, missing.Sym)
    160 						}
    161 					}
    162 				}
    163 			}
    164 		}
    165 
    166 		if top == Etype && n.Type != nil {
    167 			ll = ncase.List
    168 			if ncase.Rlist != nil {
    169 				nvar := ncase.Rlist.N
    170 				if ll != nil && ll.Next == nil && ll.N.Type != nil && !Istype(ll.N.Type, TNIL) {
    171 					// single entry type switch
    172 					nvar.Name.Param.Ntype = typenod(ll.N.Type)
    173 				} else {
    174 					// multiple entry type switch or default
    175 					nvar.Name.Param.Ntype = typenod(n.Type)
    176 				}
    177 
    178 				typecheck(&nvar, Erv|Easgn)
    179 				ncase.Rlist.N = nvar
    180 			}
    181 		}
    182 
    183 		typechecklist(ncase.Nbody, Etop)
    184 	}
    185 
    186 	lineno = int32(lno)
    187 }
    188 
    189 // walkswitch walks a switch statement.
    190 func walkswitch(sw *Node) {
    191 	// convert switch {...} to switch true {...}
    192 	if sw.Left == nil {
    193 		sw.Left = Nodbool(true)
    194 		typecheck(&sw.Left, Erv)
    195 	}
    196 
    197 	if sw.Left.Op == OTYPESW {
    198 		var s typeSwitch
    199 		s.walk(sw)
    200 	} else {
    201 		var s exprSwitch
    202 		s.walk(sw)
    203 	}
    204 }
    205 
    206 // walk generates an AST implementing sw.
    207 // sw is an expression switch.
    208 // The AST is generally of the form of a linear
    209 // search using if..goto, although binary search
    210 // is used with long runs of constants.
    211 func (s *exprSwitch) walk(sw *Node) {
    212 	casebody(sw, nil)
    213 
    214 	cond := sw.Left
    215 	sw.Left = nil
    216 
    217 	s.kind = switchKindExpr
    218 	if Isconst(cond, CTBOOL) {
    219 		s.kind = switchKindTrue
    220 		if !cond.Val().U.(bool) {
    221 			s.kind = switchKindFalse
    222 		}
    223 	}
    224 
    225 	walkexpr(&cond, &sw.Ninit)
    226 	t := sw.Type
    227 	if t == nil {
    228 		return
    229 	}
    230 
    231 	// convert the switch into OIF statements
    232 	var cas *NodeList
    233 	if s.kind == switchKindTrue || s.kind == switchKindFalse {
    234 		s.exprname = Nodbool(s.kind == switchKindTrue)
    235 	} else if consttype(cond) >= 0 {
    236 		// leave constants to enable dead code elimination (issue 9608)
    237 		s.exprname = cond
    238 	} else {
    239 		s.exprname = temp(cond.Type)
    240 		cas = list1(Nod(OAS, s.exprname, cond))
    241 		typechecklist(cas, Etop)
    242 	}
    243 
    244 	// enumerate the cases, and lop off the default case
    245 	cc := caseClauses(sw, s.kind)
    246 	sw.List = nil
    247 	var def *Node
    248 	if len(cc) > 0 && cc[0].typ == caseKindDefault {
    249 		def = cc[0].node.Right
    250 		cc = cc[1:]
    251 	} else {
    252 		def = Nod(OBREAK, nil, nil)
    253 	}
    254 
    255 	// handle the cases in order
    256 	for len(cc) > 0 {
    257 		// deal with expressions one at a time
    258 		if !okforcmp[t.Etype] || cc[0].typ != caseKindExprConst {
    259 			a := s.walkCases(cc[:1])
    260 			cas = list(cas, a)
    261 			cc = cc[1:]
    262 			continue
    263 		}
    264 
    265 		// do binary search on runs of constants
    266 		var run int
    267 		for run = 1; run < len(cc) && cc[run].typ == caseKindExprConst; run++ {
    268 		}
    269 
    270 		// sort and compile constants
    271 		sort.Sort(caseClauseByExpr(cc[:run]))
    272 		a := s.walkCases(cc[:run])
    273 		cas = list(cas, a)
    274 		cc = cc[run:]
    275 	}
    276 
    277 	// handle default case
    278 	if nerrors == 0 {
    279 		cas = list(cas, def)
    280 		sw.Nbody = concat(cas, sw.Nbody)
    281 		walkstmtlist(sw.Nbody)
    282 	}
    283 }
    284 
    285 // walkCases generates an AST implementing the cases in cc.
    286 func (s *exprSwitch) walkCases(cc []*caseClause) *Node {
    287 	if len(cc) < binarySearchMin {
    288 		// linear search
    289 		var cas *NodeList
    290 		for _, c := range cc {
    291 			n := c.node
    292 			lno := int(setlineno(n))
    293 
    294 			a := Nod(OIF, nil, nil)
    295 			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 {
    296 				a.Left = Nod(OEQ, s.exprname, n.Left) // if name == val
    297 				typecheck(&a.Left, Erv)
    298 			} else if s.kind == switchKindTrue {
    299 				a.Left = n.Left // if val
    300 			} else {
    301 				// s.kind == switchKindFalse
    302 				a.Left = Nod(ONOT, n.Left, nil) // if !val
    303 				typecheck(&a.Left, Erv)
    304 			}
    305 			a.Nbody = list1(n.Right) // goto l
    306 
    307 			cas = list(cas, a)
    308 			lineno = int32(lno)
    309 		}
    310 		return liststmt(cas)
    311 	}
    312 
    313 	// find the middle and recur
    314 	half := len(cc) / 2
    315 	a := Nod(OIF, nil, nil)
    316 	mid := cc[half-1].node.Left
    317 	le := Nod(OLE, s.exprname, mid)
    318 	if Isconst(mid, CTSTR) {
    319 		// Search by length and then by value; see exprcmp.
    320 		lenlt := Nod(OLT, Nod(OLEN, s.exprname, nil), Nod(OLEN, mid, nil))
    321 		leneq := Nod(OEQ, Nod(OLEN, s.exprname, nil), Nod(OLEN, mid, nil))
    322 		a.Left = Nod(OOROR, lenlt, Nod(OANDAND, leneq, le))
    323 	} else {
    324 		a.Left = le
    325 	}
    326 	typecheck(&a.Left, Erv)
    327 	a.Nbody = list1(s.walkCases(cc[:half]))
    328 	a.Rlist = list1(s.walkCases(cc[half:]))
    329 	return a
    330 }
    331 
    332 // casebody builds separate lists of statements and cases.
    333 // It makes labels between cases and statements
    334 // and deals with fallthrough, break, and unreachable statements.
    335 func casebody(sw *Node, typeswvar *Node) {
    336 	if sw.List == nil {
    337 		return
    338 	}
    339 
    340 	lno := setlineno(sw)
    341 
    342 	var cas *NodeList  // cases
    343 	var stat *NodeList // statements
    344 	var def *Node      // defaults
    345 	br := Nod(OBREAK, nil, nil)
    346 
    347 	for l := sw.List; l != nil; l = l.Next {
    348 		n := l.N
    349 		setlineno(n)
    350 		if n.Op != OXCASE {
    351 			Fatal("casebody %v", Oconv(int(n.Op), 0))
    352 		}
    353 		n.Op = OCASE
    354 		needvar := count(n.List) != 1 || n.List.N.Op == OLITERAL
    355 
    356 		jmp := Nod(OGOTO, newCaseLabel(), nil)
    357 		if n.List == nil {
    358 			if def != nil {
    359 				Yyerror("more than one default case")
    360 			}
    361 			// reuse original default case
    362 			n.Right = jmp
    363 			def = n
    364 		}
    365 
    366 		if n.List != nil && n.List.Next == nil {
    367 			// one case -- reuse OCASE node
    368 			n.Left = n.List.N
    369 			n.Right = jmp
    370 			n.List = nil
    371 			cas = list(cas, n)
    372 		} else {
    373 			// expand multi-valued cases
    374 			for lc := n.List; lc != nil; lc = lc.Next {
    375 				cas = list(cas, Nod(OCASE, lc.N, jmp))
    376 			}
    377 		}
    378 
    379 		stat = list(stat, Nod(OLABEL, jmp.Left, nil))
    380 		if typeswvar != nil && needvar && n.Rlist != nil {
    381 			l := list1(Nod(ODCL, n.Rlist.N, nil))
    382 			l = list(l, Nod(OAS, n.Rlist.N, typeswvar))
    383 			typechecklist(l, Etop)
    384 			stat = concat(stat, l)
    385 		}
    386 		stat = concat(stat, n.Nbody)
    387 
    388 		// botch - shouldn't fall thru declaration
    389 		last := stat.End.N
    390 		if last.Xoffset == n.Xoffset && last.Op == OXFALL {
    391 			if typeswvar != nil {
    392 				setlineno(last)
    393 				Yyerror("cannot fallthrough in type switch")
    394 			}
    395 
    396 			if l.Next == nil {
    397 				setlineno(last)
    398 				Yyerror("cannot fallthrough final case in switch")
    399 			}
    400 
    401 			last.Op = OFALL
    402 		} else {
    403 			stat = list(stat, br)
    404 		}
    405 	}
    406 
    407 	stat = list(stat, br)
    408 	if def != nil {
    409 		cas = list(cas, def)
    410 	}
    411 
    412 	sw.List = cas
    413 	sw.Nbody = stat
    414 	lineno = lno
    415 }
    416 
    417 // nSwitchLabel is the number of switch labels generated.
    418 // This should be per-function, but it is a global counter for now.
    419 var nSwitchLabel int
    420 
    421 func newCaseLabel() *Node {
    422 	label := strconv.Itoa(nSwitchLabel)
    423 	nSwitchLabel++
    424 	return newname(Lookup(label))
    425 }
    426 
    427 // caseClauses generates a slice of caseClauses
    428 // corresponding to the clauses in the switch statement sw.
    429 // Kind is the kind of switch statement.
    430 func caseClauses(sw *Node, kind int) []*caseClause {
    431 	var cc []*caseClause
    432 	for l := sw.List; l != nil; l = l.Next {
    433 		n := l.N
    434 		c := new(caseClause)
    435 		cc = append(cc, c)
    436 		c.ordinal = len(cc)
    437 		c.node = n
    438 
    439 		if n.Left == nil {
    440 			c.typ = caseKindDefault
    441 			continue
    442 		}
    443 
    444 		if kind == switchKindType {
    445 			// type switch
    446 			switch {
    447 			case n.Left.Op == OLITERAL:
    448 				c.typ = caseKindTypeNil
    449 			case Istype(n.Left.Type, TINTER):
    450 				c.typ = caseKindTypeVar
    451 			default:
    452 				c.typ = caseKindTypeConst
    453 				c.hash = typehash(n.Left.Type)
    454 			}
    455 		} else {
    456 			// expression switch
    457 			switch consttype(n.Left) {
    458 			case CTFLT, CTINT, CTRUNE, CTSTR:
    459 				c.typ = caseKindExprConst
    460 			default:
    461 				c.typ = caseKindExprVar
    462 			}
    463 		}
    464 	}
    465 
    466 	if cc == nil {
    467 		return nil
    468 	}
    469 
    470 	// sort by value and diagnose duplicate cases
    471 	if kind == switchKindType {
    472 		// type switch
    473 		sort.Sort(caseClauseByType(cc))
    474 		for i, c1 := range cc {
    475 			if c1.typ == caseKindTypeNil || c1.typ == caseKindDefault {
    476 				break
    477 			}
    478 			for _, c2 := range cc[i+1:] {
    479 				if c2.typ == caseKindTypeNil || c2.typ == caseKindDefault || c1.hash != c2.hash {
    480 					break
    481 				}
    482 				if Eqtype(c1.node.Left.Type, c2.node.Left.Type) {
    483 					yyerrorl(int(c2.node.Lineno), "duplicate case %v in type switch\n\tprevious case at %v", c2.node.Left.Type, c1.node.Line())
    484 				}
    485 			}
    486 		}
    487 	} else {
    488 		// expression switch
    489 		sort.Sort(caseClauseByExpr(cc))
    490 		for i, c1 := range cc {
    491 			if i+1 == len(cc) {
    492 				break
    493 			}
    494 			c2 := cc[i+1]
    495 			if exprcmp(c1, c2) != 0 {
    496 				continue
    497 			}
    498 			setlineno(c2.node)
    499 			Yyerror("duplicate case %v in switch\n\tprevious case at %v", c1.node.Left, c1.node.Line())
    500 		}
    501 	}
    502 
    503 	// put list back in processing order
    504 	sort.Sort(caseClauseByOrd(cc))
    505 	return cc
    506 }
    507 
    508 // walk generates an AST that implements sw,
    509 // where sw is a type switch.
    510 // The AST is generally of the form of a linear
    511 // search using if..goto, although binary search
    512 // is used with long runs of concrete types.
    513 func (s *typeSwitch) walk(sw *Node) {
    514 	cond := sw.Left
    515 	sw.Left = nil
    516 
    517 	if cond == nil {
    518 		sw.List = nil
    519 		return
    520 	}
    521 	if cond.Right == nil {
    522 		setlineno(sw)
    523 		Yyerror("type switch must have an assignment")
    524 		return
    525 	}
    526 
    527 	walkexpr(&cond.Right, &sw.Ninit)
    528 	if !Istype(cond.Right.Type, TINTER) {
    529 		Yyerror("type switch must be on an interface")
    530 		return
    531 	}
    532 
    533 	var cas *NodeList
    534 
    535 	// predeclare temporary variables and the boolean var
    536 	s.facename = temp(cond.Right.Type)
    537 
    538 	a := Nod(OAS, s.facename, cond.Right)
    539 	typecheck(&a, Etop)
    540 	cas = list(cas, a)
    541 
    542 	s.okname = temp(Types[TBOOL])
    543 	typecheck(&s.okname, Erv)
    544 
    545 	s.hashname = temp(Types[TUINT32])
    546 	typecheck(&s.hashname, Erv)
    547 
    548 	// set up labels and jumps
    549 	casebody(sw, s.facename)
    550 
    551 	// calculate type hash
    552 	t := cond.Right.Type
    553 	if isnilinter(t) {
    554 		a = syslook("efacethash", 1)
    555 	} else {
    556 		a = syslook("ifacethash", 1)
    557 	}
    558 	substArgTypes(a, t)
    559 	a = Nod(OCALL, a, nil)
    560 	a.List = list1(s.facename)
    561 	a = Nod(OAS, s.hashname, a)
    562 	typecheck(&a, Etop)
    563 	cas = list(cas, a)
    564 
    565 	cc := caseClauses(sw, switchKindType)
    566 	sw.List = nil
    567 	var def *Node
    568 	if len(cc) > 0 && cc[0].typ == caseKindDefault {
    569 		def = cc[0].node.Right
    570 		cc = cc[1:]
    571 	} else {
    572 		def = Nod(OBREAK, nil, nil)
    573 	}
    574 
    575 	// insert type equality check into each case block
    576 	for _, c := range cc {
    577 		n := c.node
    578 		switch c.typ {
    579 		case caseKindTypeNil:
    580 			var v Val
    581 			v.U = new(NilVal)
    582 			a = Nod(OIF, nil, nil)
    583 			a.Left = Nod(OEQ, s.facename, nodlit(v))
    584 			typecheck(&a.Left, Erv)
    585 			a.Nbody = list1(n.Right) // if i==nil { goto l }
    586 			n.Right = a
    587 
    588 		case caseKindTypeVar, caseKindTypeConst:
    589 			n.Right = s.typeone(n)
    590 		}
    591 	}
    592 
    593 	// generate list of if statements, binary search for constant sequences
    594 	for len(cc) > 0 {
    595 		if cc[0].typ != caseKindTypeConst {
    596 			n := cc[0].node
    597 			cas = list(cas, n.Right)
    598 			cc = cc[1:]
    599 			continue
    600 		}
    601 
    602 		// identify run of constants
    603 		var run int
    604 		for run = 1; run < len(cc) && cc[run].typ == caseKindTypeConst; run++ {
    605 		}
    606 
    607 		// sort by hash
    608 		sort.Sort(caseClauseByType(cc[:run]))
    609 
    610 		// for debugging: linear search
    611 		if false {
    612 			for i := 0; i < run; i++ {
    613 				n := cc[i].node
    614 				cas = list(cas, n.Right)
    615 			}
    616 			continue
    617 		}
    618 
    619 		// combine adjacent cases with the same hash
    620 		ncase := 0
    621 		for i := 0; i < run; i++ {
    622 			ncase++
    623 			hash := list1(cc[i].node.Right)
    624 			for j := i + 1; j < run && cc[i].hash == cc[j].hash; j++ {
    625 				hash = list(hash, cc[j].node.Right)
    626 			}
    627 			cc[i].node.Right = liststmt(hash)
    628 		}
    629 
    630 		// binary search among cases to narrow by hash
    631 		cas = list(cas, s.walkCases(cc[:ncase]))
    632 		cc = cc[ncase:]
    633 	}
    634 
    635 	// handle default case
    636 	if nerrors == 0 {
    637 		cas = list(cas, def)
    638 		sw.Nbody = concat(cas, sw.Nbody)
    639 		sw.List = nil
    640 		walkstmtlist(sw.Nbody)
    641 	}
    642 }
    643 
    644 // typeone generates an AST that jumps to the
    645 // case body if the variable is of type t.
    646 func (s *typeSwitch) typeone(t *Node) *Node {
    647 	var name *Node
    648 	var init *NodeList
    649 	if t.Rlist == nil {
    650 		name = nblank
    651 		typecheck(&nblank, Erv|Easgn)
    652 	} else {
    653 		name = t.Rlist.N
    654 		init = list1(Nod(ODCL, name, nil))
    655 		a := Nod(OAS, name, nil)
    656 		typecheck(&a, Etop)
    657 		init = list(init, a)
    658 	}
    659 
    660 	a := Nod(OAS2, nil, nil)
    661 	a.List = list(list1(name), s.okname) // name, ok =
    662 	b := Nod(ODOTTYPE, s.facename, nil)
    663 	b.Type = t.Left.Type // interface.(type)
    664 	a.Rlist = list1(b)
    665 	typecheck(&a, Etop)
    666 	init = list(init, a)
    667 
    668 	c := Nod(OIF, nil, nil)
    669 	c.Left = s.okname
    670 	c.Nbody = list1(t.Right) // if ok { goto l }
    671 
    672 	return liststmt(list(init, c))
    673 }
    674 
    675 // walkCases generates an AST implementing the cases in cc.
    676 func (s *typeSwitch) walkCases(cc []*caseClause) *Node {
    677 	if len(cc) < binarySearchMin {
    678 		var cas *NodeList
    679 		for _, c := range cc {
    680 			n := c.node
    681 			if c.typ != caseKindTypeConst {
    682 				Fatal("typeSwitch walkCases")
    683 			}
    684 			a := Nod(OIF, nil, nil)
    685 			a.Left = Nod(OEQ, s.hashname, Nodintconst(int64(c.hash)))
    686 			typecheck(&a.Left, Erv)
    687 			a.Nbody = list1(n.Right)
    688 			cas = list(cas, a)
    689 		}
    690 		return liststmt(cas)
    691 	}
    692 
    693 	// find the middle and recur
    694 	half := len(cc) / 2
    695 	a := Nod(OIF, nil, nil)
    696 	a.Left = Nod(OLE, s.hashname, Nodintconst(int64(cc[half-1].hash)))
    697 	typecheck(&a.Left, Erv)
    698 	a.Nbody = list1(s.walkCases(cc[:half]))
    699 	a.Rlist = list1(s.walkCases(cc[half:]))
    700 	return a
    701 }
    702 
    703 type caseClauseByOrd []*caseClause
    704 
    705 func (x caseClauseByOrd) Len() int      { return len(x) }
    706 func (x caseClauseByOrd) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
    707 func (x caseClauseByOrd) Less(i, j int) bool {
    708 	c1, c2 := x[i], x[j]
    709 	switch {
    710 	// sort default first
    711 	case c1.typ == caseKindDefault:
    712 		return true
    713 	case c2.typ == caseKindDefault:
    714 		return false
    715 
    716 	// sort nil second
    717 	case c1.typ == caseKindTypeNil:
    718 		return true
    719 	case c2.typ == caseKindTypeNil:
    720 		return false
    721 	}
    722 
    723 	// sort by ordinal
    724 	return c1.ordinal < c2.ordinal
    725 }
    726 
    727 type caseClauseByExpr []*caseClause
    728 
    729 func (x caseClauseByExpr) Len() int      { return len(x) }
    730 func (x caseClauseByExpr) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
    731 func (x caseClauseByExpr) Less(i, j int) bool {
    732 	return exprcmp(x[i], x[j]) < 0
    733 }
    734 
    735 func exprcmp(c1, c2 *caseClause) int {
    736 	// sort non-constants last
    737 	if c1.typ != caseKindExprConst {
    738 		return +1
    739 	}
    740 	if c2.typ != caseKindExprConst {
    741 		return -1
    742 	}
    743 
    744 	n1 := c1.node.Left
    745 	n2 := c2.node.Left
    746 
    747 	// sort by type (for switches on interface)
    748 	ct := int(n1.Val().Ctype())
    749 	if ct > int(n2.Val().Ctype()) {
    750 		return +1
    751 	}
    752 	if ct < int(n2.Val().Ctype()) {
    753 		return -1
    754 	}
    755 	if !Eqtype(n1.Type, n2.Type) {
    756 		if n1.Type.Vargen > n2.Type.Vargen {
    757 			return +1
    758 		} else {
    759 			return -1
    760 		}
    761 	}
    762 
    763 	// sort by constant value to enable binary search
    764 	switch ct {
    765 	case CTFLT:
    766 		return mpcmpfltflt(n1.Val().U.(*Mpflt), n2.Val().U.(*Mpflt))
    767 	case CTINT, CTRUNE:
    768 		return Mpcmpfixfix(n1.Val().U.(*Mpint), n2.Val().U.(*Mpint))
    769 	case CTSTR:
    770 		// Sort strings by length and then by value.
    771 		// It is much cheaper to compare lengths than values,
    772 		// and all we need here is consistency.
    773 		// We respect this sorting in exprSwitch.walkCases.
    774 		a := n1.Val().U.(string)
    775 		b := n2.Val().U.(string)
    776 		if len(a) < len(b) {
    777 			return -1
    778 		}
    779 		if len(a) > len(b) {
    780 			return +1
    781 		}
    782 		return stringsCompare(a, b)
    783 	}
    784 
    785 	return 0
    786 }
    787 
    788 type caseClauseByType []*caseClause
    789 
    790 func (x caseClauseByType) Len() int      { return len(x) }
    791 func (x caseClauseByType) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
    792 func (x caseClauseByType) Less(i, j int) bool {
    793 	c1, c2 := x[i], x[j]
    794 	switch {
    795 	// sort non-constants last
    796 	case c1.typ != caseKindTypeConst:
    797 		return false
    798 	case c2.typ != caseKindTypeConst:
    799 		return true
    800 
    801 	// sort by hash code
    802 	case c1.hash != c2.hash:
    803 		return c1.hash < c2.hash
    804 	}
    805 
    806 	// sort by ordinal
    807 	return c1.ordinal < c2.ordinal
    808 }
    809 
    810 func dumpcase(cc []*caseClause) {
    811 	for _, c := range cc {
    812 		switch c.typ {
    813 		case caseKindDefault:
    814 			fmt.Printf("case-default\n")
    815 			fmt.Printf("\tord=%d\n", c.ordinal)
    816 
    817 		case caseKindExprConst:
    818 			fmt.Printf("case-exprconst\n")
    819 			fmt.Printf("\tord=%d\n", c.ordinal)
    820 
    821 		case caseKindExprVar:
    822 			fmt.Printf("case-exprvar\n")
    823 			fmt.Printf("\tord=%d\n", c.ordinal)
    824 			fmt.Printf("\top=%v\n", Oconv(int(c.node.Left.Op), 0))
    825 
    826 		case caseKindTypeNil:
    827 			fmt.Printf("case-typenil\n")
    828 			fmt.Printf("\tord=%d\n", c.ordinal)
    829 
    830 		case caseKindTypeConst:
    831 			fmt.Printf("case-typeconst\n")
    832 			fmt.Printf("\tord=%d\n", c.ordinal)
    833 			fmt.Printf("\thash=%x\n", c.hash)
    834 
    835 		case caseKindTypeVar:
    836 			fmt.Printf("case-typevar\n")
    837 			fmt.Printf("\tord=%d\n", c.ordinal)
    838 
    839 		default:
    840 			fmt.Printf("case-???\n")
    841 			fmt.Printf("\tord=%d\n", c.ordinal)
    842 			fmt.Printf("\top=%v\n", Oconv(int(c.node.Left.Op), 0))
    843 			fmt.Printf("\thash=%x\n", c.hash)
    844 		}
    845 	}
    846 
    847 	fmt.Printf("\n")
    848 }
    849