github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/src/cmd/gc/swt.c (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  #include	<u.h>
     6  #include	<libc.h>
     7  #include	"go.h"
     8  
     9  enum
    10  {
    11  	Snorm		= 0,
    12  	Strue,
    13  	Sfalse,
    14  	Stype,
    15  
    16  	Tdefault,	// default case
    17  	Texprconst,	// normal constant case
    18  	Texprvar,	// normal variable case
    19  	Ttypenil,	// case nil
    20  	Ttypeconst,	// type hashes
    21  	Ttypevar,	// interface type
    22  
    23  	Ncase	= 4,	// count needed to split
    24  };
    25  
    26  typedef	struct	Case	Case;
    27  struct	Case
    28  {
    29  	Node*	node;		// points at case statement
    30  	uint32	hash;		// hash of a type switch
    31  	uint8	type;		// type of case
    32  	uint8	diag;		// suppress multiple diagnostics
    33  	uint16	ordinal;	// position in switch
    34  	Case*	link;		// linked list to link
    35  };
    36  #define	C	((Case*)nil)
    37  /*c2go Case *C; */
    38  
    39  void
    40  dumpcase(Case *c0)
    41  {
    42  	Case *c;
    43  
    44  	for(c=c0; c!=C; c=c->link) {
    45  		switch(c->type) {
    46  		case Tdefault:
    47  			print("case-default\n");
    48  			print("	ord=%d\n", c->ordinal);
    49  			break;
    50  		case Texprconst:
    51  			print("case-exprconst\n");
    52  			print("	ord=%d\n", c->ordinal);
    53  			break;
    54  		case Texprvar:
    55  			print("case-exprvar\n");
    56  			print("	ord=%d\n", c->ordinal);
    57  			print("	op=%O\n", c->node->left->op);
    58  			break;
    59  		case Ttypenil:
    60  			print("case-typenil\n");
    61  			print("	ord=%d\n", c->ordinal);
    62  			break;
    63  		case Ttypeconst:
    64  			print("case-typeconst\n");
    65  			print("	ord=%d\n", c->ordinal);
    66  			print("	hash=%ux\n", c->hash);
    67  			break;
    68  		case Ttypevar:
    69  			print("case-typevar\n");
    70  			print("	ord=%d\n", c->ordinal);
    71  			break;
    72  		default:
    73  			print("case-???\n");
    74  			print("	ord=%d\n", c->ordinal);
    75  			print("	op=%O\n", c->node->left->op);
    76  			print("	hash=%ux\n", c->hash);
    77  			break;
    78  		}
    79  	}
    80  	print("\n");
    81  }
    82  
    83  static int
    84  ordlcmp(Case *c1, Case *c2)
    85  {
    86  	// sort default first
    87  	if(c1->type == Tdefault)
    88  		return -1;
    89  	if(c2->type == Tdefault)
    90  		return +1;
    91  
    92  	// sort nil second
    93  	if(c1->type == Ttypenil)
    94  		return -1;
    95  	if(c2->type == Ttypenil)
    96  		return +1;
    97  
    98  	// sort by ordinal
    99  	if(c1->ordinal > c2->ordinal)
   100  		return +1;
   101  	if(c1->ordinal < c2->ordinal)
   102  		return -1;
   103  	return 0;
   104  }
   105  
   106  static int
   107  exprcmp(Case *c1, Case *c2)
   108  {
   109  	int ct, n;
   110  	Node *n1, *n2;
   111  
   112  	// sort non-constants last
   113  	if(c1->type != Texprconst)
   114  		return +1;
   115  	if(c2->type != Texprconst)
   116  		return -1;
   117  
   118  	n1 = c1->node->left;
   119  	n2 = c2->node->left;
   120  
   121  	// sort by type (for switches on interface)
   122  	ct = n1->val.ctype;
   123  	if(ct != n2->val.ctype)
   124  		return ct - n2->val.ctype;
   125  	if(!eqtype(n1->type, n2->type)) {
   126  		if(n1->type->vargen > n2->type->vargen)
   127  			return +1;
   128  		else
   129  			return -1;
   130  	}
   131  
   132  	// sort by constant value
   133  	n = 0;
   134  	switch(ct) {
   135  	case CTFLT:
   136  		n = mpcmpfltflt(n1->val.u.fval, n2->val.u.fval);
   137  		break;
   138  	case CTINT:
   139  	case CTRUNE:
   140  		n = mpcmpfixfix(n1->val.u.xval, n2->val.u.xval);
   141  		break;
   142  	case CTSTR:
   143  		n = cmpslit(n1, n2);
   144  		break;
   145  	}
   146  
   147  	return n;
   148  }
   149  
   150  static int
   151  typecmp(Case *c1, Case *c2)
   152  {
   153  
   154  	// sort non-constants last
   155  	if(c1->type != Ttypeconst)
   156  		return +1;
   157  	if(c2->type != Ttypeconst)
   158  		return -1;
   159  
   160  	// sort by hash code
   161  	if(c1->hash > c2->hash)
   162  		return +1;
   163  	if(c1->hash < c2->hash)
   164  		return -1;
   165  
   166  	// sort by ordinal so duplicate error
   167  	// happens on later case.
   168  	if(c1->ordinal > c2->ordinal)
   169  		return +1;
   170  	if(c1->ordinal < c2->ordinal)
   171  		return -1;
   172  	return 0;
   173  }
   174  
   175  static Case*
   176  csort(Case *l, int(*f)(Case*, Case*))
   177  {
   178  	Case *l1, *l2, *le;
   179  
   180  	if(l == C || l->link == C)
   181  		return l;
   182  
   183  	l1 = l;
   184  	l2 = l;
   185  	for(;;) {
   186  		l2 = l2->link;
   187  		if(l2 == C)
   188  			break;
   189  		l2 = l2->link;
   190  		if(l2 == C)
   191  			break;
   192  		l1 = l1->link;
   193  	}
   194  
   195  	l2 = l1->link;
   196  	l1->link = C;
   197  	l1 = csort(l, f);
   198  	l2 = csort(l2, f);
   199  
   200  	/* set up lead element */
   201  	if((*f)(l1, l2) < 0) {
   202  		l = l1;
   203  		l1 = l1->link;
   204  	} else {
   205  		l = l2;
   206  		l2 = l2->link;
   207  	}
   208  	le = l;
   209  
   210  	for(;;) {
   211  		if(l1 == C) {
   212  			while(l2) {
   213  				le->link = l2;
   214  				le = l2;
   215  				l2 = l2->link;
   216  			}
   217  			le->link = C;
   218  			break;
   219  		}
   220  		if(l2 == C) {
   221  			while(l1) {
   222  				le->link = l1;
   223  				le = l1;
   224  				l1 = l1->link;
   225  			}
   226  			break;
   227  		}
   228  		if((*f)(l1, l2) < 0) {
   229  			le->link = l1;
   230  			le = l1;
   231  			l1 = l1->link;
   232  		} else {
   233  			le->link = l2;
   234  			le = l2;
   235  			l2 = l2->link;
   236  		}
   237  	}
   238  	le->link = C;
   239  	return l;
   240  }
   241  
   242  static Node*
   243  newlabel(void)
   244  {
   245  	static int label;
   246  
   247  	label++;
   248  	snprint(namebuf, sizeof(namebuf), "%.6d", label);
   249  	return newname(lookup(namebuf));
   250  }
   251  
   252  /*
   253   * build separate list of statements and cases
   254   * make labels between cases and statements
   255   * deal with fallthrough, break, unreachable statements
   256   */
   257  static void
   258  casebody(Node *sw, Node *typeswvar)
   259  {
   260  	Node *n, *c, *last;
   261  	Node *def;
   262  	NodeList *cas, *stat, *l, *lc;
   263  	Node *go, *br;
   264  	int32 lno, needvar;
   265  
   266  	if(sw->list == nil)
   267  		return;
   268  
   269  	lno = setlineno(sw);
   270  
   271  	cas = nil;	// cases
   272  	stat = nil;	// statements
   273  	def = N;	// defaults
   274  	br = nod(OBREAK, N, N);
   275  
   276  	for(l=sw->list; l; l=l->next) {
   277  		n = l->n;
   278  		setlineno(n);
   279  		if(n->op != OXCASE)
   280  			fatal("casebody %O", n->op);
   281  		n->op = OCASE;
   282  		needvar = count(n->list) != 1 || n->list->n->op == OLITERAL;
   283  
   284  		go = nod(OGOTO, newlabel(), N);
   285  		if(n->list == nil) {
   286  			if(def != N)
   287  				yyerror("more than one default case");
   288  			// reuse original default case
   289  			n->right = go;
   290  			def = n;
   291  		}
   292  
   293  		if(n->list != nil && n->list->next == nil) {
   294  			// one case - reuse OCASE node.
   295  			c = n->list->n;
   296  			n->left = c;
   297  			n->right = go;
   298  			n->list = nil;
   299  			cas = list(cas, n);
   300  		} else {
   301  			// expand multi-valued cases
   302  			for(lc=n->list; lc; lc=lc->next) {
   303  				c = lc->n;
   304  				cas = list(cas, nod(OCASE, c, go));
   305  			}
   306  		}
   307  
   308  		stat = list(stat, nod(OLABEL, go->left, N));
   309  		if(typeswvar && needvar && n->nname != N) {
   310  			NodeList *l;
   311  
   312  			l = list1(nod(ODCL, n->nname, N));
   313  			l = list(l, nod(OAS, n->nname, typeswvar));
   314  			typechecklist(l, Etop);
   315  			stat = concat(stat, l);
   316  		}
   317  		stat = concat(stat, n->nbody);
   318  
   319  		// botch - shouldn't fall thru declaration
   320  		last = stat->end->n;
   321  		if(last->xoffset == n->xoffset && last->op == OXFALL) {
   322  			if(typeswvar) {
   323  				setlineno(last);
   324  				yyerror("cannot fallthrough in type switch");
   325  			}
   326  			if(l->next == nil) {
   327  				setlineno(last);
   328  				yyerror("cannot fallthrough final case in switch");
   329  			}
   330  			last->op = OFALL;
   331  		} else
   332  			stat = list(stat, br);
   333  	}
   334  
   335  	stat = list(stat, br);
   336  	if(def)
   337  		cas = list(cas, def);
   338  
   339  	sw->list = cas;
   340  	sw->nbody = stat;
   341  	lineno = lno;
   342  }
   343  
   344  static Case*
   345  mkcaselist(Node *sw, int arg)
   346  {
   347  	Node *n;
   348  	Case *c, *c1, *c2;
   349  	NodeList *l;
   350  	int ord;
   351  
   352  	c = C;
   353  	ord = 0;
   354  
   355  	for(l=sw->list; l; l=l->next) {
   356  		n = l->n;
   357  		c1 = mal(sizeof(*c1));
   358  		c1->link = c;
   359  		c = c1;
   360  
   361  		ord++;
   362  		if((uint16)ord != ord)
   363  			fatal("too many cases in switch");
   364  		c->ordinal = ord;
   365  		c->node = n;
   366  
   367  		if(n->left == N) {
   368  			c->type = Tdefault;
   369  			continue;
   370  		}
   371  
   372  		switch(arg) {
   373  		case Stype:
   374  			c->hash = 0;
   375  			if(n->left->op == OLITERAL) {
   376  				c->type = Ttypenil;
   377  				continue;
   378  			}
   379  			if(istype(n->left->type, TINTER)) {
   380  				c->type = Ttypevar;
   381  				continue;
   382  			}
   383  
   384  			c->hash = typehash(n->left->type);
   385  			c->type = Ttypeconst;
   386  			continue;
   387  
   388  		case Snorm:
   389  		case Strue:
   390  		case Sfalse:
   391  			c->type = Texprvar;
   392  			c->hash = typehash(n->left->type);
   393  			switch(consttype(n->left)) {
   394  			case CTFLT:
   395  			case CTINT:
   396  			case CTRUNE:
   397  			case CTSTR:
   398  				c->type = Texprconst;
   399  			}
   400  			continue;
   401  		}
   402  	}
   403  
   404  	if(c == C)
   405  		return C;
   406  
   407  	// sort by value and diagnose duplicate cases
   408  	switch(arg) {
   409  	case Stype:
   410  		c = csort(c, typecmp);
   411  		for(c1=c; c1!=C; c1=c1->link) {
   412  			for(c2=c1->link; c2!=C && c2->hash==c1->hash; c2=c2->link) {
   413  				if(c1->type == Ttypenil || c1->type == Tdefault)
   414  					break;
   415  				if(c2->type == Ttypenil || c2->type == Tdefault)
   416  					break;
   417  				if(!eqtype(c1->node->left->type, c2->node->left->type))
   418  					continue;
   419  				yyerrorl(c2->node->lineno, "duplicate case %T in type switch\n\tprevious case at %L", c2->node->left->type, c1->node->lineno);
   420  			}
   421  		}
   422  		break;
   423  	case Snorm:
   424  	case Strue:
   425  	case Sfalse:
   426  		c = csort(c, exprcmp);
   427  		for(c1=c; c1->link!=C; c1=c1->link) {
   428  			if(exprcmp(c1, c1->link) != 0)
   429  				continue;
   430  			setlineno(c1->link->node);
   431  			yyerror("duplicate case %N in switch\n\tprevious case at %L", c1->node->left, c1->node->lineno);
   432  		}
   433  		break;
   434  	}
   435  
   436  	// put list back in processing order
   437  	c = csort(c, ordlcmp);
   438  	return c;
   439  }
   440  
   441  static	Node*	exprname;
   442  
   443  static Node*
   444  exprbsw(Case *c0, int ncase, int arg)
   445  {
   446  	NodeList *cas;
   447  	Node *a, *n;
   448  	Case *c;
   449  	int i, half, lno;
   450  
   451  	cas = nil;
   452  	if(ncase < Ncase) {
   453  		for(i=0; i<ncase; i++) {
   454  			n = c0->node;
   455  			lno = setlineno(n);
   456  
   457  			if(assignop(n->left->type, exprname->type, nil) == OCONVIFACE ||
   458  			   assignop(exprname->type, n->left->type, nil) == OCONVIFACE)
   459  				goto snorm;
   460  
   461  			switch(arg) {
   462  			case Strue:
   463  				a = nod(OIF, N, N);
   464  				a->ntest = n->left;			// if val
   465  				a->nbody = list1(n->right);			// then goto l
   466  				break;
   467  
   468  			case Sfalse:
   469  				a = nod(OIF, N, N);
   470  				a->ntest = nod(ONOT, n->left, N);	// if !val
   471  				typecheck(&a->ntest, Erv);
   472  				a->nbody = list1(n->right);			// then goto l
   473  				break;
   474  
   475  			default:
   476  			snorm:
   477  				a = nod(OIF, N, N);
   478  				a->ntest = nod(OEQ, exprname, n->left);	// if name == val
   479  				typecheck(&a->ntest, Erv);
   480  				a->nbody = list1(n->right);			// then goto l
   481  				break;
   482  			}
   483  
   484  			cas = list(cas, a);
   485  			c0 = c0->link;
   486  			lineno = lno;
   487  		}
   488  		return liststmt(cas);
   489  	}
   490  
   491  	// find the middle and recur
   492  	c = c0;
   493  	half = ncase>>1;
   494  	for(i=1; i<half; i++)
   495  		c = c->link;
   496  	a = nod(OIF, N, N);
   497  	a->ntest = nod(OLE, exprname, c->node->left);
   498  	typecheck(&a->ntest, Erv);
   499  	a->nbody = list1(exprbsw(c0, half, arg));
   500  	a->nelse = list1(exprbsw(c->link, ncase-half, arg));
   501  	return a;
   502  }
   503  
   504  /*
   505   * normal (expression) switch.
   506   * rebulid case statements into if .. goto
   507   */
   508  static void
   509  exprswitch(Node *sw)
   510  {
   511  	Node *def;
   512  	NodeList *cas;
   513  	Node *a;
   514  	Case *c0, *c, *c1;
   515  	Type *t;
   516  	int arg, ncase;
   517  
   518  	casebody(sw, N);
   519  
   520  	arg = Snorm;
   521  	if(isconst(sw->ntest, CTBOOL)) {
   522  		arg = Strue;
   523  		if(sw->ntest->val.u.bval == 0)
   524  			arg = Sfalse;
   525  	}
   526  	walkexpr(&sw->ntest, &sw->ninit);
   527  	t = sw->type;
   528  	if(t == T)
   529  		return;
   530  
   531  	/*
   532  	 * convert the switch into OIF statements
   533  	 */
   534  	exprname = N;
   535  	cas = nil;
   536  	if(arg != Strue && arg != Sfalse) {
   537  		exprname = temp(sw->ntest->type);
   538  		cas = list1(nod(OAS, exprname, sw->ntest));
   539  		typechecklist(cas, Etop);
   540  	} else {
   541  		exprname = nodbool(arg == Strue);
   542  	}
   543  
   544  	c0 = mkcaselist(sw, arg);
   545  	if(c0 != C && c0->type == Tdefault) {
   546  		def = c0->node->right;
   547  		c0 = c0->link;
   548  	} else {
   549  		def = nod(OBREAK, N, N);
   550  	}
   551  
   552  loop:
   553  	if(c0 == C) {
   554  		cas = list(cas, def);
   555  		sw->nbody = concat(cas, sw->nbody);
   556  		sw->list = nil;
   557  		walkstmtlist(sw->nbody);
   558  		return;
   559  	}
   560  
   561  	// deal with the variables one-at-a-time
   562  	if(!okforcmp[t->etype] || c0->type != Texprconst) {
   563  		a = exprbsw(c0, 1, arg);
   564  		cas = list(cas, a);
   565  		c0 = c0->link;
   566  		goto loop;
   567  	}
   568  
   569  	// do binary search on run of constants
   570  	ncase = 1;
   571  	for(c=c0; c->link!=C; c=c->link) {
   572  		if(c->link->type != Texprconst)
   573  			break;
   574  		ncase++;
   575  	}
   576  
   577  	// break the chain at the count
   578  	c1 = c->link;
   579  	c->link = C;
   580  
   581  	// sort and compile constants
   582  	c0 = csort(c0, exprcmp);
   583  	a = exprbsw(c0, ncase, arg);
   584  	cas = list(cas, a);
   585  
   586  	c0 = c1;
   587  	goto loop;
   588  
   589  }
   590  
   591  static	Node*	hashname;
   592  static	Node*	facename;
   593  static	Node*	boolname;
   594  
   595  static Node*
   596  typeone(Node *t)
   597  {
   598  	NodeList *init;
   599  	Node *a, *b, *var;
   600  
   601  	var = t->nname;
   602  	init = nil;
   603  	if(var == N) {
   604  		typecheck(&nblank, Erv | Easgn);
   605  		var = nblank;
   606  	} else
   607  		init = list1(nod(ODCL, var, N));
   608  
   609  	a = nod(OAS2, N, N);
   610  	a->list = list(list1(var), boolname);	// var,bool =
   611  	b = nod(ODOTTYPE, facename, N);
   612  	b->type = t->left->type;		// interface.(type)
   613  	a->rlist = list1(b);
   614  	typecheck(&a, Etop);
   615  	init = list(init, a);
   616  
   617  	b = nod(OIF, N, N);
   618  	b->ntest = boolname;
   619  	b->nbody = list1(t->right);		// if bool { goto l }
   620  	a = liststmt(list(init, b));
   621  	return a;
   622  }
   623  
   624  static Node*
   625  typebsw(Case *c0, int ncase)
   626  {
   627  	NodeList *cas;
   628  	Node *a, *n;
   629  	Case *c;
   630  	int i, half;
   631  
   632  	cas = nil;
   633  
   634  	if(ncase < Ncase) {
   635  		for(i=0; i<ncase; i++) {
   636  			n = c0->node;
   637  			if(c0->type != Ttypeconst)
   638  				fatal("typebsw");
   639  			a = nod(OIF, N, N);
   640  			a->ntest = nod(OEQ, hashname, nodintconst(c0->hash));
   641  			typecheck(&a->ntest, Erv);
   642  			a->nbody = list1(n->right);
   643  			cas = list(cas, a);
   644  			c0 = c0->link;
   645  		}
   646  		return liststmt(cas);
   647  	}
   648  
   649  	// find the middle and recur
   650  	c = c0;
   651  	half = ncase>>1;
   652  	for(i=1; i<half; i++)
   653  		c = c->link;
   654  	a = nod(OIF, N, N);
   655  	a->ntest = nod(OLE, hashname, nodintconst(c->hash));
   656  	typecheck(&a->ntest, Erv);
   657  	a->nbody = list1(typebsw(c0, half));
   658  	a->nelse = list1(typebsw(c->link, ncase-half));
   659  	return a;
   660  }
   661  
   662  /*
   663   * convert switch of the form
   664   *	switch v := i.(type) { case t1: ..; case t2: ..; }
   665   * into if statements
   666   */
   667  static void
   668  typeswitch(Node *sw)
   669  {
   670  	Node *def;
   671  	NodeList *cas, *hash;
   672  	Node *a, *n;
   673  	Case *c, *c0, *c1;
   674  	int ncase;
   675  	Type *t;
   676  	Val v;
   677  
   678  	if(sw->ntest == nil)
   679  		return;
   680  	if(sw->ntest->right == nil) {
   681  		setlineno(sw);
   682  		yyerror("type switch must have an assignment");
   683  		return;
   684  	}
   685  	walkexpr(&sw->ntest->right, &sw->ninit);
   686  	if(!istype(sw->ntest->right->type, TINTER)) {
   687  		yyerror("type switch must be on an interface");
   688  		return;
   689  	}
   690  	cas = nil;
   691  
   692  	/*
   693  	 * predeclare temporary variables
   694  	 * and the boolean var
   695  	 */
   696  	facename = temp(sw->ntest->right->type);
   697  	a = nod(OAS, facename, sw->ntest->right);
   698  	typecheck(&a, Etop);
   699  	cas = list(cas, a);
   700  
   701  	casebody(sw, facename);
   702  
   703  	boolname = temp(types[TBOOL]);
   704  	typecheck(&boolname, Erv);
   705  
   706  	hashname = temp(types[TUINT32]);
   707  	typecheck(&hashname, Erv);
   708  
   709  	t = sw->ntest->right->type;
   710  	if(isnilinter(t))
   711  		a = syslook("efacethash", 1);
   712  	else
   713  		a = syslook("ifacethash", 1);
   714  	argtype(a, t);
   715  	a = nod(OCALL, a, N);
   716  	a->list = list1(facename);
   717  	a = nod(OAS, hashname, a);
   718  	typecheck(&a, Etop);
   719  	cas = list(cas, a);
   720  
   721  	c0 = mkcaselist(sw, Stype);
   722  	if(c0 != C && c0->type == Tdefault) {
   723  		def = c0->node->right;
   724  		c0 = c0->link;
   725  	} else {
   726  		def = nod(OBREAK, N, N);
   727  	}
   728  	
   729  	/*
   730  	 * insert if statement into each case block
   731  	 */
   732  	for(c=c0; c!=C; c=c->link) {
   733  		n = c->node;
   734  		switch(c->type) {
   735  
   736  		case Ttypenil:
   737  			v.ctype = CTNIL;
   738  			a = nod(OIF, N, N);
   739  			a->ntest = nod(OEQ, facename, nodlit(v));
   740  			typecheck(&a->ntest, Erv);
   741  			a->nbody = list1(n->right);		// if i==nil { goto l }
   742  			n->right = a;
   743  			break;
   744  		
   745  		case Ttypevar:
   746  		case Ttypeconst:
   747  			n->right = typeone(n);
   748  			break;
   749  		}
   750  	}
   751  
   752  	/*
   753  	 * generate list of if statements, binary search for constant sequences
   754  	 */
   755  	while(c0 != C) {
   756  		if(c0->type != Ttypeconst) {
   757  			n = c0->node;
   758  			cas = list(cas, n->right);
   759  			c0=c0->link;
   760  			continue;
   761  		}
   762  		
   763  		// identify run of constants
   764  		c1 = c = c0;
   765  		while(c->link!=C && c->link->type==Ttypeconst)
   766  			c = c->link;
   767  		c0 = c->link;
   768  		c->link = nil;
   769  
   770  		// sort by hash
   771  		c1 = csort(c1, typecmp);
   772  		
   773  		// for debugging: linear search
   774  		if(0) {
   775  			for(c=c1; c!=C; c=c->link) {
   776  				n = c->node;
   777  				cas = list(cas, n->right);
   778  			}
   779  			continue;
   780  		}
   781  
   782  		// combine adjacent cases with the same hash
   783  		ncase = 0;
   784  		for(c=c1; c!=C; c=c->link) {
   785  			ncase++;
   786  			hash = list1(c->node->right);
   787  			while(c->link != C && c->link->hash == c->hash) {
   788  				hash = list(hash, c->link->node->right);
   789  				c->link = c->link->link;
   790  			}
   791  			c->node->right = liststmt(hash);
   792  		}
   793  		
   794  		// binary search among cases to narrow by hash
   795  		cas = list(cas, typebsw(c1, ncase));
   796  	}
   797  	if(nerrors == 0) {
   798  		cas = list(cas, def);
   799  		sw->nbody = concat(cas, sw->nbody);
   800  		sw->list = nil;
   801  		walkstmtlist(sw->nbody);
   802  	}
   803  }
   804  
   805  void
   806  walkswitch(Node *sw)
   807  {
   808  	/*
   809  	 * reorder the body into (OLIST, cases, statements)
   810  	 * cases have OGOTO into statements.
   811  	 * both have inserted OBREAK statements
   812  	 */
   813  	if(sw->ntest == N) {
   814  		sw->ntest = nodbool(1);
   815  		typecheck(&sw->ntest, Erv);
   816  	}
   817  
   818  	if(sw->ntest->op == OTYPESW) {
   819  		typeswitch(sw);
   820  //dump("sw", sw);
   821  		return;
   822  	}
   823  	exprswitch(sw);
   824  	// Discard old AST elements after a walk. They can confuse racewealk.
   825  	sw->ntest = nil;
   826  	sw->list = nil;
   827  }
   828  
   829  /*
   830   * type check switch statement
   831   */
   832  void
   833  typecheckswitch(Node *n)
   834  {
   835  	int top, lno, ptr;
   836  	char *nilonly;
   837  	Type *t, *badtype, *missing, *have;
   838  	NodeList *l, *ll;
   839  	Node *ncase, *nvar;
   840  	Node *def;
   841  
   842  	lno = lineno;
   843  	typechecklist(n->ninit, Etop);
   844  	nilonly = nil;
   845  
   846  	if(n->ntest != N && n->ntest->op == OTYPESW) {
   847  		// type switch
   848  		top = Etype;
   849  		typecheck(&n->ntest->right, Erv);
   850  		t = n->ntest->right->type;
   851  		if(t != T && t->etype != TINTER)
   852  			yyerror("cannot type switch on non-interface value %lN", n->ntest->right);
   853  	} else {
   854  		// value switch
   855  		top = Erv;
   856  		if(n->ntest) {
   857  			typecheck(&n->ntest, Erv);
   858  			defaultlit(&n->ntest, T);
   859  			t = n->ntest->type;
   860  		} else
   861  			t = types[TBOOL];
   862  		if(t) {
   863  			if(!okforeq[t->etype])
   864  				yyerror("cannot switch on %lN", n->ntest);
   865  			else if(t->etype == TARRAY && !isfixedarray(t))
   866  				nilonly = "slice";
   867  			else if(t->etype == TARRAY && isfixedarray(t) && algtype1(t, nil) == ANOEQ)
   868  				yyerror("cannot switch on %lN", n->ntest);
   869  			else if(t->etype == TSTRUCT && algtype1(t, &badtype) == ANOEQ)
   870  				yyerror("cannot switch on %lN (struct containing %T cannot be compared)", n->ntest, badtype);
   871  			else if(t->etype == TFUNC)
   872  				nilonly = "func";
   873  			else if(t->etype == TMAP)
   874  				nilonly = "map";
   875  		}
   876  	}
   877  	n->type = t;
   878  
   879  	def = N;
   880  	for(l=n->list; l; l=l->next) {
   881  		ncase = l->n;
   882  		setlineno(n);
   883  		if(ncase->list == nil) {
   884  			// default
   885  			if(def != N)
   886  				yyerror("multiple defaults in switch (first at %L)", def->lineno);
   887  			else
   888  				def = ncase;
   889  		} else {
   890  			for(ll=ncase->list; ll; ll=ll->next) {
   891  				setlineno(ll->n);
   892  				typecheck(&ll->n, Erv | Etype);
   893  				if(ll->n->type == T || t == T)
   894  					continue;
   895  				setlineno(ncase);
   896  				switch(top) {
   897  				case Erv:	// expression switch
   898  					defaultlit(&ll->n, t);
   899  					if(ll->n->op == OTYPE)
   900  						yyerror("type %T is not an expression", ll->n->type);
   901  					else if(ll->n->type != T && !assignop(ll->n->type, t, nil) && !assignop(t, ll->n->type, nil)) {
   902  						if(n->ntest)
   903  							yyerror("invalid case %N in switch on %N (mismatched types %T and %T)", ll->n, n->ntest, ll->n->type, t);
   904  						else
   905  							yyerror("invalid case %N in switch (mismatched types %T and bool)", ll->n, ll->n->type);
   906  					} else if(nilonly && !isconst(ll->n, CTNIL)) {
   907  						yyerror("invalid case %N in switch (can only compare %s %N to nil)", ll->n, nilonly, n->ntest);
   908  					}
   909  					break;
   910  				case Etype:	// type switch
   911  					if(ll->n->op == OLITERAL && istype(ll->n->type, TNIL)) {
   912  						;
   913  					} else if(ll->n->op != OTYPE && ll->n->type != T) {  // should this be ||?
   914  						yyerror("%lN is not a type", ll->n);
   915  						// reset to original type
   916  						ll->n = n->ntest->right;
   917  					} else if(ll->n->type->etype != TINTER && t->etype == TINTER && !implements(ll->n->type, t, &missing, &have, &ptr)) {
   918  						if(have && !missing->broke && !have->broke)
   919  							yyerror("impossible type switch case: %lN cannot have dynamic type %T"
   920  								" (wrong type for %S method)\n\thave %S%hT\n\twant %S%hT",
   921  								n->ntest->right, ll->n->type, missing->sym, have->sym, have->type,
   922  								missing->sym, missing->type);
   923  						else if(!missing->broke)
   924  							yyerror("impossible type switch case: %lN cannot have dynamic type %T"
   925  								" (missing %S method)", n->ntest->right, ll->n->type, missing->sym);
   926  					}
   927  					break;
   928  				}
   929  			}
   930  		}
   931  		if(top == Etype && n->type != T) {
   932  			ll = ncase->list;
   933  			nvar = ncase->nname;
   934  			if(nvar != N) {
   935  				if(ll && ll->next == nil && ll->n->type != T && !istype(ll->n->type, TNIL)) {
   936  					// single entry type switch
   937  					nvar->ntype = typenod(ll->n->type);
   938  				} else {
   939  					// multiple entry type switch or default
   940  					nvar->ntype = typenod(n->type);
   941  				}
   942  			}
   943  		}
   944  		typechecklist(ncase->nbody, Etop);
   945  	}
   946  
   947  	lineno = lno;
   948  }