github.com/slayercat/go@v0.0.0-20170428012452-c51559813f61/src/cmd/compile/internal/gc/swt.go (about)

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