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