github.com/FenixAra/go@v0.0.0-20170127160404-96ea0918e670/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 "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  }