]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/gc/walk.c
[dev.garbage] all: merge dev.cc (493ad916c3b1) into dev.garbage
[gostls13.git] / src / cmd / gc / walk.c
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 #include        "../ld/textflag.h"
9 #include        "../../runtime/mgc0.h"
10
11 static  Node*   walkprint(Node*, NodeList**);
12 static  Node*   writebarrierfn(char*, Type*, Type*);
13 static  Node*   applywritebarrier(Node*, NodeList**);
14 static  Node*   mapfn(char*, Type*);
15 static  Node*   mapfndel(char*, Type*);
16 static  Node*   ascompatee1(int, Node*, Node*, NodeList**);
17 static  NodeList*       ascompatee(int, NodeList*, NodeList*, NodeList**);
18 static  NodeList*       ascompatet(int, NodeList*, Type**, int, NodeList**);
19 static  NodeList*       ascompatte(int, Node*, int, Type**, NodeList*, int, NodeList**);
20 static  Node*   convas(Node*, NodeList**);
21 static  void    heapmoves(void);
22 static  NodeList*       paramstoheap(Type **argin, int out);
23 static  NodeList*       reorder1(NodeList*);
24 static  NodeList*       reorder3(NodeList*);
25 static  Node*   addstr(Node*, NodeList**);
26 static  Node*   appendslice(Node*, NodeList**);
27 static  Node*   append(Node*, NodeList**);
28 static  Node*   copyany(Node*, NodeList**, int);
29 static  Node*   sliceany(Node*, NodeList**);
30 static  void    walkcompare(Node**, NodeList**);
31 static  void    walkrotate(Node**);
32 static  void    walkmul(Node**, NodeList**);
33 static  void    walkdiv(Node**, NodeList**);
34 static  int     bounded(Node*, int64);
35 static  Mpint   mpzero;
36 static  void    walkprintfunc(Node**, NodeList**);
37
38 void
39 walk(Node *fn)
40 {
41         char s[50];
42         NodeList *l;
43         int lno;
44
45         curfn = fn;
46
47         if(debug['W']) {
48                 snprint(s, sizeof(s), "\nbefore %S", curfn->nname->sym);
49                 dumplist(s, curfn->nbody);
50         }
51
52         lno = lineno;
53
54         // Final typecheck for any unused variables.
55         // It's hard to be on the heap when not-used, but best to be consistent about &~PHEAP here and below.
56         for(l=fn->dcl; l; l=l->next)
57                 if(l->n->op == ONAME && (l->n->class&~PHEAP) == PAUTO)
58                         typecheck(&l->n, Erv | Easgn);
59
60         // Propagate the used flag for typeswitch variables up to the NONAME in it's definition.
61         for(l=fn->dcl; l; l=l->next)
62                 if(l->n->op == ONAME && (l->n->class&~PHEAP) == PAUTO && l->n->defn && l->n->defn->op == OTYPESW && l->n->used)
63                         l->n->defn->left->used++;
64         
65         for(l=fn->dcl; l; l=l->next) {
66                 if(l->n->op != ONAME || (l->n->class&~PHEAP) != PAUTO || l->n->sym->name[0] == '&' || l->n->used)
67                         continue;
68                 if(l->n->defn && l->n->defn->op == OTYPESW) {
69                         if(l->n->defn->left->used)
70                                 continue;
71                         lineno = l->n->defn->left->lineno;
72                         yyerror("%S declared and not used", l->n->sym);
73                         l->n->defn->left->used = 1; // suppress repeats
74                 } else {
75                         lineno = l->n->lineno;
76                         yyerror("%S declared and not used", l->n->sym);
77                 }
78         }       
79
80         lineno = lno;
81         if(nerrors != 0)
82                 return;
83         walkstmtlist(curfn->nbody);
84         if(debug['W']) {
85                 snprint(s, sizeof(s), "after walk %S", curfn->nname->sym);
86                 dumplist(s, curfn->nbody);
87         }
88         heapmoves();
89         if(debug['W'] && curfn->enter != nil) {
90                 snprint(s, sizeof(s), "enter %S", curfn->nname->sym);
91                 dumplist(s, curfn->enter);
92         }
93 }
94
95
96 void
97 walkstmtlist(NodeList *l)
98 {
99         for(; l; l=l->next)
100                 walkstmt(&l->n);
101 }
102
103 static int
104 samelist(NodeList *a, NodeList *b)
105 {
106         for(; a && b; a=a->next, b=b->next)
107                 if(a->n != b->n)
108                         return 0;
109         return a == b;
110 }
111
112 static int
113 paramoutheap(Node *fn)
114 {
115         NodeList *l;
116
117         for(l=fn->dcl; l; l=l->next) {
118                 switch(l->n->class) {
119                 case PPARAMOUT:
120                 case PPARAMOUT|PHEAP:
121                         return l->n->addrtaken;
122                 case PAUTO:
123                 case PAUTO|PHEAP:
124                         // stop early - parameters are over
125                         return 0;
126                 }
127         }
128         return 0;
129 }
130
131 void
132 walkstmt(Node **np)
133 {
134         NodeList *init;
135         NodeList *ll, *rl;
136         int cl;
137         Node *n, *f;
138
139         n = *np;
140         if(n == N)
141                 return;
142         if(n->dodata == 2) // don't walk, generated by anylit.
143                 return;
144
145         setlineno(n);
146
147         walkstmtlist(n->ninit);
148
149         switch(n->op) {
150         default:
151                 if(n->op == ONAME)
152                         yyerror("%S is not a top level statement", n->sym);
153                 else
154                         yyerror("%O is not a top level statement", n->op);
155                 dump("nottop", n);
156                 break;
157
158         case OAS:
159         case OASOP:
160         case OAS2:
161         case OAS2DOTTYPE:
162         case OAS2RECV:
163         case OAS2FUNC:
164         case OAS2MAPR:
165         case OCLOSE:
166         case OCOPY:
167         case OCALLMETH:
168         case OCALLINTER:
169         case OCALL:
170         case OCALLFUNC:
171         case ODELETE:
172         case OSEND:
173         case OPRINT:
174         case OPRINTN:
175         case OPANIC:
176         case OEMPTY:
177         case ORECOVER:
178                 if(n->typecheck == 0)
179                         fatal("missing typecheck: %+N", n);
180                 init = n->ninit;
181                 n->ninit = nil;
182                 walkexpr(&n, &init);
183                 addinit(&n, init);
184                 if((*np)->op == OCOPY && n->op == OCONVNOP)
185                         n->op = OEMPTY; // don't leave plain values as statements.
186                 break;
187
188         case ORECV:
189                 // special case for a receive where we throw away
190                 // the value received.
191                 if(n->typecheck == 0)
192                         fatal("missing typecheck: %+N", n);
193                 init = n->ninit;
194                 n->ninit = nil;
195
196                 walkexpr(&n->left, &init);
197                 n = mkcall1(chanfn("chanrecv1", 2, n->left->type), T, &init, typename(n->left->type), n->left, nodnil());
198                 walkexpr(&n, &init);
199
200                 addinit(&n, init);
201                 break;
202
203         case OBREAK:
204         case ODCL:
205         case OCONTINUE:
206         case OFALL:
207         case OGOTO:
208         case OLABEL:
209         case ODCLCONST:
210         case ODCLTYPE:
211         case OCHECKNIL:
212         case OVARKILL:
213                 break;
214
215         case OBLOCK:
216                 walkstmtlist(n->list);
217                 break;
218
219         case OXCASE:
220                 yyerror("case statement out of place");
221                 n->op = OCASE;
222         case OCASE:
223                 walkstmt(&n->right);
224                 break;
225
226         case ODEFER:
227                 hasdefer = 1;
228                 switch(n->left->op) {
229                 case OPRINT:
230                 case OPRINTN:
231                         walkprintfunc(&n->left, &n->ninit);
232                         break;
233                 case OCOPY:
234                         n->left = copyany(n->left, &n->ninit, 1);
235                         break;
236                 default:
237                         walkexpr(&n->left, &n->ninit);
238                         break;
239                 }
240                 break;
241
242         case OFOR:
243                 if(n->ntest != N) {
244                         walkstmtlist(n->ntest->ninit);
245                         init = n->ntest->ninit;
246                         n->ntest->ninit = nil;
247                         walkexpr(&n->ntest, &init);
248                         addinit(&n->ntest, init);
249                 }
250                 walkstmt(&n->nincr);
251                 walkstmtlist(n->nbody);
252                 break;
253
254         case OIF:
255                 walkexpr(&n->ntest, &n->ninit);
256                 walkstmtlist(n->nbody);
257                 walkstmtlist(n->nelse);
258                 break;
259
260         case OPROC:
261                 switch(n->left->op) {
262                 case OPRINT:
263                 case OPRINTN:
264                         walkprintfunc(&n->left, &n->ninit);
265                         break;
266                 case OCOPY:
267                         n->left = copyany(n->left, &n->ninit, 1);
268                         break;
269                 default:
270                         walkexpr(&n->left, &n->ninit);
271                         break;
272                 }
273                 break;
274
275         case ORETURN:
276                 walkexprlist(n->list, &n->ninit);
277                 if(n->list == nil)
278                         break;
279                 if((curfn->type->outnamed && count(n->list) > 1) || paramoutheap(curfn)) {
280                         // assign to the function out parameters,
281                         // so that reorder3 can fix up conflicts
282                         rl = nil;
283                         for(ll=curfn->dcl; ll != nil; ll=ll->next) {
284                                 cl = ll->n->class & ~PHEAP;
285                                 if(cl == PAUTO)
286                                         break;
287                                 if(cl == PPARAMOUT)
288                                         rl = list(rl, ll->n);
289                         }
290                         if(samelist(rl, n->list)) {
291                                 // special return in disguise
292                                 n->list = nil;
293                                 break;
294                         }
295                         if(count(n->list) == 1 && count(rl) > 1) {
296                                 // OAS2FUNC in disguise
297                                 f = n->list->n;
298                                 if(f->op != OCALLFUNC && f->op != OCALLMETH && f->op != OCALLINTER)
299                                         fatal("expected return of call, have %N", f);
300                                 n->list = concat(list1(f), ascompatet(n->op, rl, &f->type, 0, &n->ninit));
301                                 break;
302                         }
303
304                         // move function calls out, to make reorder3's job easier.
305                         walkexprlistsafe(n->list, &n->ninit);
306                         ll = ascompatee(n->op, rl, n->list, &n->ninit);
307                         n->list = reorder3(ll);
308                         break;
309                 }
310                 ll = ascompatte(n->op, nil, 0, getoutarg(curfn->type), n->list, 1, &n->ninit);
311                 n->list = ll;
312                 break;
313
314         case ORETJMP:
315                 break;
316
317         case OSELECT:
318                 walkselect(n);
319                 break;
320
321         case OSWITCH:
322                 walkswitch(n);
323                 break;
324
325         case ORANGE:
326                 walkrange(n);
327                 break;
328
329         case OXFALL:
330                 yyerror("fallthrough statement out of place");
331                 n->op = OFALL;
332                 break;
333         }
334
335         if(n->op == ONAME)
336                 fatal("walkstmt ended up with name: %+N", n);
337         
338         *np = n;
339 }
340
341
342 /*
343  * walk the whole tree of the body of an
344  * expression or simple statement.
345  * the types expressions are calculated.
346  * compile-time constants are evaluated.
347  * complex side effects like statements are appended to init
348  */
349
350 void
351 walkexprlist(NodeList *l, NodeList **init)
352 {
353         for(; l; l=l->next)
354                 walkexpr(&l->n, init);
355 }
356
357 void
358 walkexprlistsafe(NodeList *l, NodeList **init)
359 {
360         for(; l; l=l->next) {
361                 l->n = safeexpr(l->n, init);
362                 walkexpr(&l->n, init);
363         }
364 }
365
366 void
367 walkexprlistcheap(NodeList *l, NodeList **init)
368 {
369         for(; l; l=l->next) {
370                 l->n = cheapexpr(l->n, init);
371                 walkexpr(&l->n, init);
372         }
373 }
374
375 void
376 walkexpr(Node **np, NodeList **init)
377 {
378         Node *r, *l, *var, *a;
379         Node *map, *key;
380         NodeList *ll, *lr;
381         Type *t;
382         int et, old_safemode;
383         int64 v;
384         int32 lno;
385         Node *n, *fn, *n1, *n2;
386         Sym *sym;
387         char buf[100], *p;
388
389         n = *np;
390
391         if(n == N)
392                 return;
393
394         if(init == &n->ninit) {
395                 // not okay to use n->ninit when walking n,
396                 // because we might replace n with some other node
397                 // and would lose the init list.
398                 fatal("walkexpr init == &n->ninit");
399         }
400
401         if(n->ninit != nil) {
402                 walkstmtlist(n->ninit);
403                 *init = concat(*init, n->ninit);
404                 n->ninit = nil;
405         }
406
407         // annoying case - not typechecked
408         if(n->op == OKEY) {
409                 walkexpr(&n->left, init);
410                 walkexpr(&n->right, init);
411                 return;
412         }
413
414         lno = setlineno(n);
415
416         if(debug['w'] > 1)
417                 dump("walk-before", n);
418
419         if(n->typecheck != 1)
420                 fatal("missed typecheck: %+N\n", n);
421
422         switch(n->op) {
423         default:
424                 dump("walk", n);
425                 fatal("walkexpr: switch 1 unknown op %+hN", n);
426                 break;
427
428         case OTYPE:
429         case ONONAME:
430         case OINDREG:
431         case OEMPTY:
432                 goto ret;
433
434         case ONOT:
435         case OMINUS:
436         case OPLUS:
437         case OCOM:
438         case OREAL:
439         case OIMAG:
440         case ODOTMETH:
441         case ODOTINTER:
442                 walkexpr(&n->left, init);
443                 goto ret;
444
445         case OIND:
446                 walkexpr(&n->left, init);
447                 goto ret;
448
449         case ODOT:
450                 usefield(n);
451                 walkexpr(&n->left, init);
452                 goto ret;
453
454         case ODOTPTR:
455                 usefield(n);
456                 if(n->op == ODOTPTR && n->left->type->type->width == 0) {
457                         // No actual copy will be generated, so emit an explicit nil check.
458                         n->left = cheapexpr(n->left, init);
459                         checknil(n->left, init);
460                 }
461                 walkexpr(&n->left, init);
462                 goto ret;
463
464         case OEFACE:
465                 walkexpr(&n->left, init);
466                 walkexpr(&n->right, init);
467                 goto ret;
468
469         case OSPTR:
470         case OITAB:
471                 walkexpr(&n->left, init);
472                 goto ret;
473
474         case OLEN:
475         case OCAP:
476                 walkexpr(&n->left, init);
477
478                 // replace len(*[10]int) with 10.
479                 // delayed until now to preserve side effects.
480                 t = n->left->type;
481                 if(isptr[t->etype])
482                         t = t->type;
483                 if(isfixedarray(t)) {
484                         safeexpr(n->left, init);
485                         nodconst(n, n->type, t->bound);
486                         n->typecheck = 1;
487                 }
488                 goto ret;
489
490         case OLSH:
491         case ORSH:
492                 walkexpr(&n->left, init);
493                 walkexpr(&n->right, init);
494                 t = n->left->type;
495                 n->bounded = bounded(n->right, 8*t->width);
496                 if(debug['m'] && n->etype && !isconst(n->right, CTINT))
497                         warn("shift bounds check elided");
498                 goto ret;
499
500         case OAND:
501         case OSUB:
502         case OHMUL:
503         case OLT:
504         case OLE:
505         case OGE:
506         case OGT:
507         case OADD:
508         case OCOMPLEX:
509         case OLROT:
510                 // Use results from call expression as arguments for complex.
511                 if(n->op == OCOMPLEX && n->left == N && n->right == N) {
512                         n->left = n->list->n;
513                         n->right = n->list->next->n;
514                 }
515                 walkexpr(&n->left, init);
516                 walkexpr(&n->right, init);
517                 goto ret;
518
519         case OOR:
520         case OXOR:
521                 walkexpr(&n->left, init);
522                 walkexpr(&n->right, init);
523                 walkrotate(&n);
524                 goto ret;
525
526         case OEQ:
527         case ONE:
528                 walkexpr(&n->left, init);
529                 walkexpr(&n->right, init);
530                 // Disable safemode while compiling this code: the code we
531                 // generate internally can refer to unsafe.Pointer.
532                 // In this case it can happen if we need to generate an ==
533                 // for a struct containing a reflect.Value, which itself has
534                 // an unexported field of type unsafe.Pointer.
535                 old_safemode = safemode;
536                 safemode = 0;
537                 walkcompare(&n, init);
538                 safemode = old_safemode;
539                 goto ret;
540
541         case OANDAND:
542         case OOROR:
543                 walkexpr(&n->left, init);
544                 // cannot put side effects from n->right on init,
545                 // because they cannot run before n->left is checked.
546                 // save elsewhere and store on the eventual n->right.
547                 ll = nil;
548                 walkexpr(&n->right, &ll);
549                 addinit(&n->right, ll);
550                 goto ret;
551
552         case OPRINT:
553         case OPRINTN:
554                 walkexprlist(n->list, init);
555                 n = walkprint(n, init);
556                 goto ret;
557
558         case OPANIC:
559                 n = mkcall("gopanic", T, init, n->left);
560                 goto ret;
561
562         case ORECOVER:
563                 n = mkcall("gorecover", n->type, init, nod(OADDR, nodfp, N));
564                 goto ret;
565
566         case OLITERAL:
567                 n->addable = 1;
568                 goto ret;
569
570         case OCLOSUREVAR:
571         case OCFUNC:
572                 n->addable = 1;
573                 goto ret;
574
575         case ONAME:
576                 if(!(n->class & PHEAP) && n->class != PPARAMREF)
577                         n->addable = 1;
578                 goto ret;
579
580         case OCALLINTER:
581                 t = n->left->type;
582                 if(n->list && n->list->n->op == OAS)
583                         goto ret;
584                 walkexpr(&n->left, init);
585                 walkexprlist(n->list, init);
586                 ll = ascompatte(n->op, n, n->isddd, getinarg(t), n->list, 0, init);
587                 n->list = reorder1(ll);
588                 goto ret;
589
590         case OCALLFUNC:
591                 t = n->left->type;
592                 if(n->list && n->list->n->op == OAS)
593                         goto ret;
594
595                 walkexpr(&n->left, init);
596                 walkexprlist(n->list, init);
597
598                 ll = ascompatte(n->op, n, n->isddd, getinarg(t), n->list, 0, init);
599                 n->list = reorder1(ll);
600                 goto ret;
601
602         case OCALLMETH:
603                 t = n->left->type;
604                 if(n->list && n->list->n->op == OAS)
605                         goto ret;
606                 walkexpr(&n->left, init);
607                 walkexprlist(n->list, init);
608                 ll = ascompatte(n->op, n, 0, getthis(t), list1(n->left->left), 0, init);
609                 lr = ascompatte(n->op, n, n->isddd, getinarg(t), n->list, 0, init);
610                 ll = concat(ll, lr);
611                 n->left->left = N;
612                 ullmancalc(n->left);
613                 n->list = reorder1(ll);
614                 goto ret;
615
616         case OAS:
617                 *init = concat(*init, n->ninit);
618                 n->ninit = nil;
619
620                 walkexpr(&n->left, init);
621                 n->left = safeexpr(n->left, init);
622
623                 if(oaslit(n, init))
624                         goto ret;
625
626                 if(n->right == N || iszero(n->right) && !flag_race)
627                         goto ret;
628
629                 switch(n->right->op) {
630                 default:
631                         walkexpr(&n->right, init);
632                         break;
633                 
634                 case ORECV:
635                         // x = <-c; n->left is x, n->right->left is c.
636                         // orderstmt made sure x is addressable.
637                         walkexpr(&n->right->left, init);
638                         n1 = nod(OADDR, n->left, N);
639                         r = n->right->left; // the channel
640                         n = mkcall1(chanfn("chanrecv1", 2, r->type), T, init, typename(r->type), r, n1);
641                         walkexpr(&n, init);
642                         goto ret;
643                 }
644
645                 if(n->left != N && n->right != N) {
646                         r = convas(nod(OAS, n->left, n->right), init);
647                         r->dodata = n->dodata;
648                         n = r;
649                         n = applywritebarrier(n, init);
650                 }
651
652                 goto ret;
653
654         case OAS2:
655                 *init = concat(*init, n->ninit);
656                 n->ninit = nil;
657                 walkexprlistsafe(n->list, init);
658                 walkexprlistsafe(n->rlist, init);
659                 ll = ascompatee(OAS, n->list, n->rlist, init);
660                 ll = reorder3(ll);
661                 for(lr = ll; lr != nil; lr = lr->next)
662                         lr->n = applywritebarrier(lr->n, init);
663                 n = liststmt(ll);
664                 goto ret;
665
666         case OAS2FUNC:
667                 // a,b,... = fn()
668                 *init = concat(*init, n->ninit);
669                 n->ninit = nil;
670                 r = n->rlist->n;
671                 walkexprlistsafe(n->list, init);
672                 walkexpr(&r, init);
673
674                 ll = ascompatet(n->op, n->list, &r->type, 0, init);
675                 for(lr = ll; lr != nil; lr = lr->next)
676                         lr->n = applywritebarrier(lr->n, init);
677                 n = liststmt(concat(list1(r), ll));
678                 goto ret;
679
680         case OAS2RECV:
681                 // x, y = <-c
682                 // orderstmt made sure x is addressable.
683                 *init = concat(*init, n->ninit);
684                 n->ninit = nil;
685                 r = n->rlist->n;
686                 walkexprlistsafe(n->list, init);
687                 walkexpr(&r->left, init);
688                 if(isblank(n->list->n))
689                         n1 = nodnil();
690                 else
691                         n1 = nod(OADDR, n->list->n, N);
692                 n1->etype = 1; // addr does not escape
693                 fn = chanfn("chanrecv2", 2, r->left->type);
694                 r = mkcall1(fn, n->list->next->n->type, init, typename(r->left->type), r->left, n1);
695                 n = nod(OAS, n->list->next->n, r);
696                 typecheck(&n, Etop);
697                 goto ret;
698
699         case OAS2MAPR:
700                 // a,b = m[i];
701                 *init = concat(*init, n->ninit);
702                 n->ninit = nil;
703                 r = n->rlist->n;
704                 walkexprlistsafe(n->list, init);
705                 walkexpr(&r->left, init);
706                 walkexpr(&r->right, init);
707                 t = r->left->type;
708                 p = nil;
709                 if(t->type->width <= 128) { // Check ../../runtime/hashmap.c:MAXVALUESIZE before changing.
710                         switch(simsimtype(t->down)) {
711                         case TINT32:
712                         case TUINT32:
713                                 p = "mapaccess2_fast32";
714                                 break;
715                         case TINT64:
716                         case TUINT64:
717                                 p = "mapaccess2_fast64";
718                                 break;
719                         case TSTRING:
720                                 p = "mapaccess2_faststr";
721                                 break;
722                         }
723                 }
724                 if(p != nil) {
725                         // fast versions take key by value
726                         key = r->right;
727                 } else {
728                         // standard version takes key by reference
729                         // orderexpr made sure key is addressable.
730                         key = nod(OADDR, r->right, N);
731                         p = "mapaccess2";
732                 }
733
734                 // from:
735                 //   a,b = m[i]
736                 // to:
737                 //   var,b = mapaccess2*(t, m, i)
738                 //   a = *var
739                 a = n->list->n;
740                 var = temp(ptrto(t->type));
741                 var->typecheck = 1;
742                 fn = mapfn(p, t);
743                 r = mkcall1(fn, getoutargx(fn->type), init, typename(t), r->left, key);
744
745                 // mapaccess2* returns a typed bool, but due to spec changes,
746                 // the boolean result of i.(T) is now untyped so we make it the
747                 // same type as the variable on the lhs.
748                 if(!isblank(n->list->next->n))
749                         r->type->type->down->type = n->list->next->n->type;
750                 n->rlist = list1(r);
751                 n->op = OAS2FUNC;
752                 n->list->n = var;
753                 walkexpr(&n, init);
754                 *init = list(*init, n);
755                 n = nod(OAS, a, nod(OIND, var, N));
756                 typecheck(&n, Etop);
757                 walkexpr(&n, init);
758                 // mapaccess needs a zero value to be at least this big.
759                 if(zerosize < t->type->width)
760                         zerosize = t->type->width;
761                 // TODO: ptr is always non-nil, so disable nil check for this OIND op.
762                 goto ret;
763
764         case ODELETE:
765                 *init = concat(*init, n->ninit);
766                 n->ninit = nil;
767                 map = n->list->n;
768                 key = n->list->next->n;
769                 walkexpr(&map, init);
770                 walkexpr(&key, init);
771                 // orderstmt made sure key is addressable.
772                 key = nod(OADDR, key, N);
773                 t = map->type;
774                 n = mkcall1(mapfndel("mapdelete", t), T, init, typename(t), map, key);
775                 goto ret;
776
777         case OAS2DOTTYPE:
778                 // a,b = i.(T)
779                 *init = concat(*init, n->ninit);
780                 n->ninit = nil;
781                 r = n->rlist->n;
782                 walkexprlistsafe(n->list, init);
783                 if(isblank(n->list->n) && !isinter(r->type)) {
784                         strcpy(buf, "assert");
785                         p = buf+strlen(buf);
786                         if(isnilinter(r->left->type))
787                                 *p++ = 'E';
788                         else
789                                 *p++ = 'I';
790                         *p++ = '2';
791                         *p++ = 'T';
792                         *p++ = 'O';
793                         *p++ = 'K';
794                         *p = '\0';
795                         
796                         fn = syslook(buf, 1);
797
798                         // runtime.assert(E|I)2TOK returns a typed bool, but due
799                         // to spec changes, the boolean result of i.(T) is now untyped
800                         // so we make it the same type as the variable on the lhs.
801                         if(!isblank(n->list->next->n))
802                                 fn->type->type->down->type->type = n->list->next->n->type;
803                         ll = list1(typename(r->type));
804                         ll = list(ll, r->left);
805                         argtype(fn, r->left->type);
806                         n1 = nod(OCALL, fn, N);
807                         n1->list = ll;
808                         n = nod(OAS, n->list->next->n, n1);
809                         typecheck(&n, Etop);
810                         walkexpr(&n, init);
811                         goto ret;
812                 }
813
814                 r->op = ODOTTYPE2;
815                 walkexpr(&r, init);
816                 ll = ascompatet(n->op, n->list, &r->type, 0, init);
817                 n = liststmt(concat(list1(r), ll));
818                 goto ret;
819
820         case ODOTTYPE:
821         case ODOTTYPE2:
822                 // Build name of function: assertI2E2 etc.
823                 strcpy(buf, "assert");
824                 p = buf+strlen(buf);
825                 if(isnilinter(n->left->type))
826                         *p++ = 'E';
827                 else
828                         *p++ = 'I';
829                 *p++ = '2';
830                 if(isnilinter(n->type))
831                         *p++ = 'E';
832                 else if(isinter(n->type))
833                         *p++ = 'I';
834                 else
835                         *p++ = 'T';
836                 if(n->op == ODOTTYPE2)
837                         *p++ = '2';
838                 *p = '\0';
839
840                 fn = syslook(buf, 1);
841                 ll = list1(typename(n->type));
842                 ll = list(ll, n->left);
843                 argtype(fn, n->left->type);
844                 argtype(fn, n->type);
845                 n = nod(OCALL, fn, N);
846                 n->list = ll;
847                 typecheck(&n, Erv | Efnstruct);
848                 walkexpr(&n, init);
849                 goto ret;
850
851         case OCONVIFACE:
852                 walkexpr(&n->left, init);
853
854                 // Optimize convT2E as a two-word copy when T is uintptr-shaped.
855                 if(isnilinter(n->type) && isdirectiface(n->left->type) && n->left->type->width == widthptr && isint[simsimtype(n->left->type)]) {
856                         l = nod(OEFACE, typename(n->left->type), n->left);
857                         l->type = n->type;
858                         l->typecheck = n->typecheck;
859                         n = l;
860                         goto ret;
861                 }
862
863                 // Build name of function: convI2E etc.
864                 // Not all names are possible
865                 // (e.g., we'll never generate convE2E or convE2I).
866                 strcpy(buf, "conv");
867                 p = buf+strlen(buf);
868                 if(isnilinter(n->left->type))
869                         *p++ = 'E';
870                 else if(isinter(n->left->type))
871                         *p++ = 'I';
872                 else
873                         *p++ = 'T';
874                 *p++ = '2';
875                 if(isnilinter(n->type))
876                         *p++ = 'E';
877                 else
878                         *p++ = 'I';
879                 *p = '\0';
880
881                 fn = syslook(buf, 1);
882                 ll = nil;
883                 if(!isinter(n->left->type))
884                         ll = list(ll, typename(n->left->type));
885                 if(!isnilinter(n->type))
886                         ll = list(ll, typename(n->type));
887                 if(!isinter(n->left->type) && !isnilinter(n->type)){
888                         sym = pkglookup(smprint("%-T.%-T", n->left->type, n->type), itabpkg);
889                         if(sym->def == N) {
890                                 l = nod(ONAME, N, N);
891                                 l->sym = sym;
892                                 l->type = ptrto(types[TUINT8]);
893                                 l->addable = 1;
894                                 l->class = PEXTERN;
895                                 l->xoffset = 0;
896                                 sym->def = l;
897                                 ggloblsym(sym, widthptr, DUPOK|NOPTR);
898                         }
899                         l = nod(OADDR, sym->def, N);
900                         l->addable = 1;
901                         ll = list(ll, l);
902
903                         if(isdirectiface(n->left->type) && n->left->type->width == widthptr && isint[simsimtype(n->left->type)]) {
904                                 /* For pointer types, we can make a special form of optimization
905                                  *
906                                  * These statements are put onto the expression init list:
907                                  *      Itab *tab = atomicloadtype(&cache);
908                                  *      if(tab == nil)
909                                  *              tab = typ2Itab(type, itype, &cache);
910                                  *
911                                  * The CONVIFACE expression is replaced with this:
912                                  *      OEFACE{tab, ptr};
913                                  */
914                                 l = temp(ptrto(types[TUINT8]));
915
916                                 n1 = nod(OAS, l, sym->def);
917                                 typecheck(&n1, Etop);
918                                 *init = list(*init, n1);
919
920                                 fn = syslook("typ2Itab", 1);
921                                 n1 = nod(OCALL, fn, N);
922                                 n1->list = ll;
923                                 typecheck(&n1, Erv);
924                                 walkexpr(&n1, init);
925
926                                 n2 = nod(OIF, N, N);
927                                 n2->ntest = nod(OEQ, l, nodnil());
928                                 n2->nbody = list1(nod(OAS, l, n1));
929                                 n2->likely = -1;
930                                 typecheck(&n2, Etop);
931                                 *init = list(*init, n2);
932
933                                 l = nod(OEFACE, l, n->left);
934                                 l->typecheck = n->typecheck; 
935                                 l->type = n->type;
936                                 n = l;
937                                 goto ret;
938                         }
939                 }
940                 if(isinter(n->left->type)) {
941                         ll = list(ll, n->left);
942                 } else {
943                         // regular types are passed by reference to avoid C vararg calls
944                         // orderexpr arranged for n->left to be a temporary for all
945                         // the conversions it could see. comparison of an interface
946                         // with a non-interface, especially in a switch on interface value
947                         // with non-interface cases, is not visible to orderstmt, so we
948                         // have to fall back on allocating a temp here.
949                         if(islvalue(n->left))
950                                 ll = list(ll, nod(OADDR, n->left, N));
951                         else
952                                 ll = list(ll, nod(OADDR, copyexpr(n->left, n->left->type, init), N));
953                 }
954                 argtype(fn, n->left->type);
955                 argtype(fn, n->type);
956                 dowidth(fn->type);
957                 n = nod(OCALL, fn, N);
958                 n->list = ll;
959                 typecheck(&n, Erv);
960                 walkexpr(&n, init);
961                 goto ret;
962
963         case OCONV:
964         case OCONVNOP:
965                 if(thechar == '5') {
966                         if(isfloat[n->left->type->etype]) {
967                                 if(n->type->etype == TINT64) {
968                                         n = mkcall("float64toint64", n->type, init, conv(n->left, types[TFLOAT64]));
969                                         goto ret;
970                                 }
971                                 if(n->type->etype == TUINT64) {
972                                         n = mkcall("float64touint64", n->type, init, conv(n->left, types[TFLOAT64]));
973                                         goto ret;
974                                 }
975                         }
976                         if(isfloat[n->type->etype]) {
977                                 if(n->left->type->etype == TINT64) {
978                                         n = mkcall("int64tofloat64", n->type, init, conv(n->left, types[TINT64]));
979                                         goto ret;
980                                 }
981                                 if(n->left->type->etype == TUINT64) {
982                                         n = mkcall("uint64tofloat64", n->type, init, conv(n->left, types[TUINT64]));
983                                         goto ret;
984                                 }
985                         }
986                 }
987                 walkexpr(&n->left, init);
988                 goto ret;
989
990         case OANDNOT:
991                 walkexpr(&n->left, init);
992                 n->op = OAND;
993                 n->right = nod(OCOM, n->right, N);
994                 typecheck(&n->right, Erv);
995                 walkexpr(&n->right, init);
996                 goto ret;
997
998         case OMUL:
999                 walkexpr(&n->left, init);
1000                 walkexpr(&n->right, init);
1001                 walkmul(&n, init);
1002                 goto ret;
1003
1004         case ODIV:
1005         case OMOD:
1006                 walkexpr(&n->left, init);
1007                 walkexpr(&n->right, init);
1008                 /*
1009                  * rewrite complex div into function call.
1010                  */
1011                 et = n->left->type->etype;
1012                 if(iscomplex[et] && n->op == ODIV) {
1013                         t = n->type;
1014                         n = mkcall("complex128div", types[TCOMPLEX128], init,
1015                                 conv(n->left, types[TCOMPLEX128]),
1016                                 conv(n->right, types[TCOMPLEX128]));
1017                         n = conv(n, t);
1018                         goto ret;
1019                 }
1020                 // Nothing to do for float divisions.
1021                 if(isfloat[et])
1022                         goto ret;
1023
1024                 // Try rewriting as shifts or magic multiplies.
1025                 walkdiv(&n, init);
1026
1027                 /*
1028                  * rewrite 64-bit div and mod into function calls
1029                  * on 32-bit architectures.
1030                  */
1031                 switch(n->op) {
1032                 case OMOD:
1033                 case ODIV:
1034                         if(widthreg >= 8 || (et != TUINT64 && et != TINT64))
1035                                 goto ret;
1036                         if(et == TINT64)
1037                                 strcpy(namebuf, "int64");
1038                         else
1039                                 strcpy(namebuf, "uint64");
1040                         if(n->op == ODIV)
1041                                 strcat(namebuf, "div");
1042                         else
1043                                 strcat(namebuf, "mod");
1044                         n = mkcall(namebuf, n->type, init,
1045                                 conv(n->left, types[et]), conv(n->right, types[et]));
1046                         break;
1047                 default:
1048                         break;
1049                 }
1050                 goto ret;
1051
1052         case OINDEX:
1053                 walkexpr(&n->left, init);
1054                 // save the original node for bounds checking elision.
1055                 // If it was a ODIV/OMOD walk might rewrite it.
1056                 r = n->right;
1057                 walkexpr(&n->right, init);
1058
1059                 // if range of type cannot exceed static array bound,
1060                 // disable bounds check.
1061                 if(n->bounded)
1062                         goto ret;
1063                 t = n->left->type;
1064                 if(t != T && isptr[t->etype])
1065                         t = t->type;
1066                 if(isfixedarray(t)) {
1067                         n->bounded = bounded(r, t->bound);
1068                         if(debug['m'] && n->bounded && !isconst(n->right, CTINT))
1069                                 warn("index bounds check elided");
1070                         if(smallintconst(n->right) && !n->bounded)
1071                                 yyerror("index out of bounds");
1072                 } else if(isconst(n->left, CTSTR)) {
1073                         n->bounded = bounded(r, n->left->val.u.sval->len);
1074                         if(debug['m'] && n->bounded && !isconst(n->right, CTINT))
1075                                 warn("index bounds check elided");
1076                         if(smallintconst(n->right)) {
1077                                 if(!n->bounded)
1078                                         yyerror("index out of bounds");
1079                                 else {
1080                                         // replace "abc"[1] with 'b'.
1081                                         // delayed until now because "abc"[1] is not
1082                                         // an ideal constant.
1083                                         v = mpgetfix(n->right->val.u.xval);
1084                                         nodconst(n, n->type, n->left->val.u.sval->s[v]);
1085                                         n->typecheck = 1;
1086                                 }
1087                         }
1088                 }
1089
1090                 if(isconst(n->right, CTINT))
1091                 if(mpcmpfixfix(n->right->val.u.xval, &mpzero) < 0 ||
1092                    mpcmpfixfix(n->right->val.u.xval, maxintval[TINT]) > 0)
1093                         yyerror("index out of bounds");
1094                 goto ret;
1095
1096         case OINDEXMAP:
1097                 if(n->etype == 1)
1098                         goto ret;
1099                 walkexpr(&n->left, init);
1100                 walkexpr(&n->right, init);
1101
1102                 t = n->left->type;
1103                 p = nil;
1104                 if(t->type->width <= 128) {  // Check ../../runtime/hashmap.c:MAXVALUESIZE before changing.
1105                         switch(simsimtype(t->down)) {
1106                         case TINT32:
1107                         case TUINT32:
1108                                 p = "mapaccess1_fast32";
1109                                 break;
1110                         case TINT64:
1111                         case TUINT64:
1112                                 p = "mapaccess1_fast64";
1113                                 break;
1114                         case TSTRING:
1115                                 p = "mapaccess1_faststr";
1116                                 break;
1117                         }
1118                 }
1119                 if(p != nil) {
1120                         // fast versions take key by value
1121                         key = n->right;
1122                 } else {
1123                         // standard version takes key by reference.
1124                         // orderexpr made sure key is addressable.
1125                         key = nod(OADDR, n->right, N);
1126                         p = "mapaccess1";
1127                 }
1128                 n = mkcall1(mapfn(p, t), ptrto(t->type), init, typename(t), n->left, key);
1129                 n = nod(OIND, n, N);
1130                 n->type = t->type;
1131                 n->typecheck = 1;
1132                 // mapaccess needs a zero value to be at least this big.
1133                 if(zerosize < t->type->width)
1134                         zerosize = t->type->width;
1135                 goto ret;
1136
1137         case ORECV:
1138                 fatal("walkexpr ORECV"); // should see inside OAS only
1139
1140         case OSLICE:
1141                 if(n->right != N && n->right->left == N && n->right->right == N) { // noop
1142                         walkexpr(&n->left, init);
1143                         n = n->left;
1144                         goto ret;
1145                 }
1146                 // fallthrough
1147         case OSLICEARR:
1148         case OSLICESTR:
1149                 if(n->right == N) // already processed
1150                         goto ret;
1151
1152                 walkexpr(&n->left, init);
1153                 // cgen_slice can't handle string literals as source
1154                 // TODO the OINDEX case is a bug elsewhere that needs to be traced.  it causes a crash on ([2][]int{ ... })[1][lo:hi]
1155                 if((n->op == OSLICESTR && n->left->op == OLITERAL) || (n->left->op == OINDEX))
1156                         n->left = copyexpr(n->left, n->left->type, init);
1157                 else
1158                         n->left = safeexpr(n->left, init);
1159                 walkexpr(&n->right->left, init);
1160                 n->right->left = safeexpr(n->right->left, init);
1161                 walkexpr(&n->right->right, init);
1162                 n->right->right = safeexpr(n->right->right, init);
1163                 n = sliceany(n, init);  // chops n->right, sets n->list
1164                 goto ret;
1165         
1166         case OSLICE3:
1167         case OSLICE3ARR:
1168                 if(n->right == N) // already processed
1169                         goto ret;
1170
1171                 walkexpr(&n->left, init);
1172                 // TODO the OINDEX case is a bug elsewhere that needs to be traced.  it causes a crash on ([2][]int{ ... })[1][lo:hi]
1173                 // TODO the comment on the previous line was copied from case OSLICE. it might not even be true.
1174                 if(n->left->op == OINDEX)
1175                         n->left = copyexpr(n->left, n->left->type, init);
1176                 else
1177                         n->left = safeexpr(n->left, init);
1178                 walkexpr(&n->right->left, init);
1179                 n->right->left = safeexpr(n->right->left, init);
1180                 walkexpr(&n->right->right->left, init);
1181                 n->right->right->left = safeexpr(n->right->right->left, init);
1182                 walkexpr(&n->right->right->right, init);
1183                 n->right->right->right = safeexpr(n->right->right->right, init);
1184                 n = sliceany(n, init);  // chops n->right, sets n->list
1185                 goto ret;
1186
1187         case OADDR:
1188                 walkexpr(&n->left, init);
1189                 goto ret;
1190
1191         case ONEW:
1192                 if(n->esc == EscNone && n->type->type->width < (1<<16)) {
1193                         r = temp(n->type->type);
1194                         r = nod(OAS, r, N);  // zero temp
1195                         typecheck(&r, Etop);
1196                         *init = list(*init, r);
1197                         r = nod(OADDR, r->left, N);
1198                         typecheck(&r, Erv);
1199                         n = r;
1200                 } else {
1201                         n = callnew(n->type->type);
1202                 }
1203                 goto ret;
1204
1205         case OCMPSTR:
1206                 // If one argument to the comparison is an empty string,
1207                 // comparing the lengths instead will yield the same result
1208                 // without the function call.
1209                 if((isconst(n->left, CTSTR) && n->left->val.u.sval->len == 0) ||
1210                    (isconst(n->right, CTSTR) && n->right->val.u.sval->len == 0)) {
1211                         r = nod(n->etype, nod(OLEN, n->left, N), nod(OLEN, n->right, N));
1212                         typecheck(&r, Erv);
1213                         walkexpr(&r, init);
1214                         r->type = n->type;
1215                         n = r;
1216                         goto ret;
1217                 }
1218
1219                 // s + "badgerbadgerbadger" == "badgerbadgerbadger"
1220                 if((n->etype == OEQ || n->etype == ONE) &&
1221                    isconst(n->right, CTSTR) &&
1222                    n->left->op == OADDSTR && count(n->left->list) == 2 &&
1223                    isconst(n->left->list->next->n, CTSTR) &&
1224                    cmpslit(n->right, n->left->list->next->n) == 0) {
1225                         r = nod(n->etype, nod(OLEN, n->left->list->n, N), nodintconst(0));
1226                         typecheck(&r, Erv);
1227                         walkexpr(&r, init);
1228                         r->type = n->type;
1229                         n = r;
1230                         goto ret;
1231                 }
1232
1233                 if(n->etype == OEQ || n->etype == ONE) {
1234                         // prepare for rewrite below
1235                         n->left = cheapexpr(n->left, init);
1236                         n->right = cheapexpr(n->right, init);
1237
1238                         r = mkcall("eqstring", types[TBOOL], init,
1239                                 conv(n->left, types[TSTRING]),
1240                                 conv(n->right, types[TSTRING]));
1241
1242                         // quick check of len before full compare for == or !=
1243                         if(n->etype == OEQ) {
1244                                 // len(left) == len(right) && eqstring(left, right)
1245                                 r = nod(OANDAND, nod(OEQ, nod(OLEN, n->left, N), nod(OLEN, n->right, N)), r);
1246                         } else {
1247                                 // len(left) != len(right) || !eqstring(left, right)
1248                                 r = nod(ONOT, r, N);
1249                                 r = nod(OOROR, nod(ONE, nod(OLEN, n->left, N), nod(OLEN, n->right, N)), r);
1250                         }
1251                         typecheck(&r, Erv);
1252                         walkexpr(&r, nil);
1253                 } else {
1254                         // sys_cmpstring(s1, s2) :: 0
1255                         r = mkcall("cmpstring", types[TINT], init,
1256                                 conv(n->left, types[TSTRING]),
1257                                 conv(n->right, types[TSTRING]));
1258                         r = nod(n->etype, r, nodintconst(0));
1259                 }
1260
1261                 typecheck(&r, Erv);
1262                 if(n->type->etype != TBOOL) fatal("cmp %T", n->type);
1263                 r->type = n->type;
1264                 n = r;
1265                 goto ret;
1266
1267         case OADDSTR:
1268                 n = addstr(n, init);
1269                 goto ret;
1270         
1271         case OAPPEND:
1272                 if(n->isddd)
1273                         n = appendslice(n, init); // also works for append(slice, string).
1274                 else
1275                         n = append(n, init);
1276                 goto ret;
1277
1278         case OCOPY:
1279                 n = copyany(n, init, flag_race);
1280                 goto ret;
1281
1282         case OCLOSE:
1283                 // cannot use chanfn - closechan takes any, not chan any
1284                 fn = syslook("closechan", 1);
1285                 argtype(fn, n->left->type);
1286                 n = mkcall1(fn, T, init, n->left);
1287                 goto ret;
1288
1289         case OMAKECHAN:
1290                 n = mkcall1(chanfn("makechan", 1, n->type), n->type, init,
1291                         typename(n->type),
1292                         conv(n->left, types[TINT64]));
1293                 goto ret;
1294
1295         case OMAKEMAP:
1296                 t = n->type;
1297
1298                 fn = syslook("makemap", 1);
1299                 argtype(fn, t->down);   // any-1
1300                 argtype(fn, t->type);   // any-2
1301
1302                 n = mkcall1(fn, n->type, init,
1303                         typename(n->type),
1304                         conv(n->left, types[TINT64]));
1305                 goto ret;
1306
1307         case OMAKESLICE:
1308                 l = n->left;
1309                 r = n->right;
1310                 if(r == nil)
1311                         l = r = safeexpr(l, init);
1312                 t = n->type;
1313                 if(n->esc == EscNone
1314                         && smallintconst(l) && smallintconst(r)
1315                         && (t->type->width == 0 || mpgetfix(r->val.u.xval) < (1ULL<<16) / t->type->width)) {
1316                         // var arr [r]T
1317                         // n = arr[:l]
1318                         t = aindex(r, t->type); // [r]T
1319                         var = temp(t);
1320                         a = nod(OAS, var, N); // zero temp
1321                         typecheck(&a, Etop);
1322                         *init = list(*init, a);
1323                         r = nod(OSLICE, var, nod(OKEY, N, l)); // arr[:l]
1324                         r = conv(r, n->type); // in case n->type is named.
1325                         typecheck(&r, Erv);
1326                         walkexpr(&r, init);
1327                         n = r;
1328                 } else {
1329                         // makeslice(t *Type, nel int64, max int64) (ary []any)
1330                         fn = syslook("makeslice", 1);
1331                         argtype(fn, t->type);                   // any-1
1332                         n = mkcall1(fn, n->type, init,
1333                                 typename(n->type),
1334                                 conv(l, types[TINT64]),
1335                                 conv(r, types[TINT64]));
1336                 }
1337                 goto ret;
1338
1339         case ORUNESTR:
1340                 // sys_intstring(v)
1341                 n = mkcall("intstring", n->type, init,
1342                         conv(n->left, types[TINT64]));
1343                 goto ret;
1344
1345         case OARRAYBYTESTR:
1346                 // slicebytetostring([]byte) string;
1347                 n = mkcall("slicebytetostring", n->type, init, n->left);
1348                 goto ret;
1349
1350         case OARRAYBYTESTRTMP:
1351                 // slicebytetostringtmp([]byte) string;
1352                 n = mkcall("slicebytetostringtmp", n->type, init, n->left);
1353                 goto ret;
1354
1355         case OARRAYRUNESTR:
1356                 // slicerunetostring([]rune) string;
1357                 n = mkcall("slicerunetostring", n->type, init, n->left);
1358                 goto ret;
1359
1360         case OSTRARRAYBYTE:
1361                 // stringtoslicebyte(string) []byte;
1362                 n = mkcall("stringtoslicebyte", n->type, init, conv(n->left, types[TSTRING]));
1363                 goto ret;
1364
1365         case OSTRARRAYRUNE:
1366                 // stringtoslicerune(string) []rune
1367                 n = mkcall("stringtoslicerune", n->type, init, n->left);
1368                 goto ret;
1369
1370         case OCMPIFACE:
1371                 // ifaceeq(i1 any-1, i2 any-2) (ret bool);
1372                 if(!eqtype(n->left->type, n->right->type))
1373                         fatal("ifaceeq %O %T %T", n->op, n->left->type, n->right->type);
1374                 if(isnilinter(n->left->type))
1375                         fn = syslook("efaceeq", 1);
1376                 else
1377                         fn = syslook("ifaceeq", 1);
1378
1379                 n->right = cheapexpr(n->right, init);
1380                 n->left = cheapexpr(n->left, init);
1381                 argtype(fn, n->right->type);
1382                 argtype(fn, n->left->type);
1383                 r = mkcall1(fn, n->type, init, n->left, n->right);
1384                 if(n->etype == ONE)
1385                         r = nod(ONOT, r, N);
1386                 
1387                 // check itable/type before full compare.
1388                 if(n->etype == OEQ)
1389                         r = nod(OANDAND, nod(OEQ, nod(OITAB, n->left, N), nod(OITAB, n->right, N)), r);
1390                 else
1391                         r = nod(OOROR, nod(ONE, nod(OITAB, n->left, N), nod(OITAB, n->right, N)), r);
1392                 typecheck(&r, Erv);
1393                 walkexpr(&r, init);
1394                 r->type = n->type;
1395                 n = r;
1396                 goto ret;
1397
1398         case OARRAYLIT:
1399         case OMAPLIT:
1400         case OSTRUCTLIT:
1401         case OPTRLIT:
1402                 var = temp(n->type);
1403                 anylit(0, n, var, init);
1404                 n = var;
1405                 goto ret;
1406
1407         case OSEND:
1408                 n1 = n->right;
1409                 n1 = assignconv(n1, n->left->type->type, "chan send");
1410                 walkexpr(&n1, init);
1411                 n1 = nod(OADDR, n1, N);
1412                 n = mkcall1(chanfn("chansend1", 2, n->left->type), T, init, typename(n->left->type), n->left, n1);
1413                 goto ret;
1414
1415         case OCLOSURE:
1416                 n = walkclosure(n, init);
1417                 goto ret;
1418         
1419         case OCALLPART:
1420                 n = walkpartialcall(n, init);
1421                 goto ret;
1422         }
1423         fatal("missing switch %O", n->op);
1424
1425 ret:
1426         // Expressions that are constant at run time but not
1427         // considered const by the language spec are not turned into
1428         // constants until walk. For example, if n is y%1 == 0, the
1429         // walk of y%1 may have replaced it by 0.
1430         // Check whether n with its updated args is itself now a constant.
1431         t = n->type;
1432         evconst(n);
1433         n->type = t;
1434         if(n->op == OLITERAL)
1435                 typecheck(&n, Erv);
1436
1437         ullmancalc(n);
1438
1439         if(debug['w'] && n != N)
1440                 dump("walk", n);
1441
1442         lineno = lno;
1443         *np = n;
1444 }
1445
1446 static Node*
1447 ascompatee1(int op, Node *l, Node *r, NodeList **init)
1448 {
1449         Node *n;
1450         USED(op);
1451         
1452         // convas will turn map assigns into function calls,
1453         // making it impossible for reorder3 to work.
1454         n = nod(OAS, l, r);
1455         if(l->op == OINDEXMAP)
1456                 return n;
1457
1458         return convas(n, init);
1459 }
1460
1461 static NodeList*
1462 ascompatee(int op, NodeList *nl, NodeList *nr, NodeList **init)
1463 {
1464         NodeList *ll, *lr, *nn;
1465
1466         /*
1467          * check assign expression list to
1468          * a expression list. called in
1469          *      expr-list = expr-list
1470          */
1471
1472         // ensure order of evaluation for function calls
1473         for(ll=nl; ll; ll=ll->next)
1474                 ll->n = safeexpr(ll->n, init);
1475         for(lr=nr; lr; lr=lr->next)
1476                 lr->n = safeexpr(lr->n, init);
1477
1478         nn = nil;
1479         for(ll=nl, lr=nr; ll && lr; ll=ll->next, lr=lr->next) {
1480                 // Do not generate 'x = x' during return. See issue 4014.
1481                 if(op == ORETURN && ll->n == lr->n)
1482                         continue;
1483                 nn = list(nn, ascompatee1(op, ll->n, lr->n, init));
1484         }
1485
1486         // cannot happen: caller checked that lists had same length
1487         if(ll || lr)
1488                 yyerror("error in shape across %+H %O %+H / %d %d [%s]", nl, op, nr, count(nl), count(nr), curfn->nname->sym->name);
1489         return nn;
1490 }
1491
1492 /*
1493  * l is an lv and rt is the type of an rv
1494  * return 1 if this implies a function call
1495  * evaluating the lv or a function call
1496  * in the conversion of the types
1497  */
1498 static int
1499 fncall(Node *l, Type *rt)
1500 {
1501         Node r;
1502
1503         if(l->ullman >= UINF || l->op == OINDEXMAP)
1504                 return 1;
1505         memset(&r, 0, sizeof r);
1506         if(needwritebarrier(l, &r))
1507                 return 1;
1508         if(eqtype(l->type, rt))
1509                 return 0;
1510         return 1;
1511 }
1512
1513 static NodeList*
1514 ascompatet(int op, NodeList *nl, Type **nr, int fp, NodeList **init)
1515 {
1516         Node *l, *tmp, *a;
1517         NodeList *ll;
1518         Type *r;
1519         Iter saver;
1520         int ucount;
1521         NodeList *nn, *mm;
1522
1523         USED(op);
1524
1525         /*
1526          * check assign type list to
1527          * a expression list. called in
1528          *      expr-list = func()
1529          */
1530         r = structfirst(&saver, nr);
1531         nn = nil;
1532         mm = nil;
1533         ucount = 0;
1534         for(ll=nl; ll; ll=ll->next) {
1535                 if(r == T)
1536                         break;
1537                 l = ll->n;
1538                 if(isblank(l)) {
1539                         r = structnext(&saver);
1540                         continue;
1541                 }
1542
1543                 // any lv that causes a fn call must be
1544                 // deferred until all the return arguments
1545                 // have been pulled from the output arguments
1546                 if(fncall(l, r->type)) {
1547                         tmp = temp(r->type);
1548                         typecheck(&tmp, Erv);
1549                         a = nod(OAS, l, tmp);
1550                         a = convas(a, init);
1551                         mm = list(mm, a);
1552                         l = tmp;
1553                 }
1554
1555                 a = nod(OAS, l, nodarg(r, fp));
1556                 a = convas(a, init);
1557                 ullmancalc(a);
1558                 if(a->ullman >= UINF) {
1559                         dump("ascompatet ucount", a);
1560                         ucount++;
1561                 }
1562                 nn = list(nn, a);
1563                 r = structnext(&saver);
1564         }
1565
1566         if(ll != nil || r != T)
1567                 yyerror("ascompatet: assignment count mismatch: %d = %d",
1568                         count(nl), structcount(*nr));
1569
1570         if(ucount)
1571                 fatal("ascompatet: too many function calls evaluating parameters");
1572         return concat(nn, mm);
1573 }
1574
1575  /*
1576  * package all the arguments that match a ... T parameter into a []T.
1577  */
1578 static NodeList*
1579 mkdotargslice(NodeList *lr0, NodeList *nn, Type *l, int fp, NodeList **init, Node *ddd)
1580 {
1581         Node *a, *n;
1582         Type *tslice;
1583         int esc;
1584         
1585         esc = EscUnknown;
1586         if(ddd != nil)
1587                 esc = ddd->esc;
1588         
1589         tslice = typ(TARRAY);
1590         tslice->type = l->type->type;
1591         tslice->bound = -1;
1592
1593         if(count(lr0) == 0) {
1594                 n = nodnil();
1595                 n->type = tslice;
1596         } else {
1597                 n = nod(OCOMPLIT, N, typenod(tslice));
1598                 if(ddd != nil)
1599                         n->alloc = ddd->alloc; // temporary to use
1600                 n->list = lr0;
1601                 n->esc = esc;
1602                 typecheck(&n, Erv);
1603                 if(n->type == T)
1604                         fatal("mkdotargslice: typecheck failed");
1605                 walkexpr(&n, init);
1606         }
1607
1608         a = nod(OAS, nodarg(l, fp), n);
1609         nn = list(nn, convas(a, init));
1610         return nn;
1611 }
1612
1613 /*
1614  * helpers for shape errors
1615  */
1616 static char*
1617 dumptypes(Type **nl, char *what)
1618 {
1619         int first;
1620         Type *l;
1621         Iter savel;
1622         Fmt fmt;
1623
1624         fmtstrinit(&fmt);
1625         fmtprint(&fmt, "\t");
1626         first = 1;
1627         for(l = structfirst(&savel, nl); l != T; l = structnext(&savel)) {
1628                 if(first)
1629                         first = 0;
1630                 else
1631                         fmtprint(&fmt, ", ");
1632                 fmtprint(&fmt, "%T", l);
1633         }
1634         if(first)
1635                 fmtprint(&fmt, "[no arguments %s]", what);
1636         return fmtstrflush(&fmt);
1637 }
1638
1639 static char*
1640 dumpnodetypes(NodeList *l, char *what)
1641 {
1642         int first;
1643         Node *r;
1644         Fmt fmt;
1645
1646         fmtstrinit(&fmt);
1647         fmtprint(&fmt, "\t");
1648         first = 1;
1649         for(; l; l=l->next) {
1650                 r = l->n;
1651                 if(first)
1652                         first = 0;
1653                 else
1654                         fmtprint(&fmt, ", ");
1655                 fmtprint(&fmt, "%T", r->type);
1656         }
1657         if(first)
1658                 fmtprint(&fmt, "[no arguments %s]", what);
1659         return fmtstrflush(&fmt);
1660 }
1661
1662 /*
1663  * check assign expression list to
1664  * a type list. called in
1665  *      return expr-list
1666  *      func(expr-list)
1667  */
1668 static NodeList*
1669 ascompatte(int op, Node *call, int isddd, Type **nl, NodeList *lr, int fp, NodeList **init)
1670 {
1671         Type *l, *ll;
1672         Node *r, *a;
1673         NodeList *nn, *lr0, *alist;
1674         Iter savel;
1675         char *l1, *l2;
1676
1677         lr0 = lr;
1678         l = structfirst(&savel, nl);
1679         r = N;
1680         if(lr)
1681                 r = lr->n;
1682         nn = nil;
1683
1684         // f(g()) where g has multiple return values
1685         if(r != N && lr->next == nil && r->type->etype == TSTRUCT && r->type->funarg) {
1686                 // optimization - can do block copy
1687                 if(eqtypenoname(r->type, *nl)) {
1688                         a = nodarg(*nl, fp);
1689                         r = nod(OCONVNOP, r, N);
1690                         r->type = a->type;
1691                         nn = list1(convas(nod(OAS, a, r), init));
1692                         goto ret;
1693                 }
1694
1695                 // conversions involved.
1696                 // copy into temporaries.
1697                 alist = nil;
1698                 for(l=structfirst(&savel, &r->type); l; l=structnext(&savel)) {
1699                         a = temp(l->type);
1700                         alist = list(alist, a);
1701                 }
1702                 a = nod(OAS2, N, N);
1703                 a->list = alist;
1704                 a->rlist = lr;
1705                 typecheck(&a, Etop);
1706                 walkstmt(&a);
1707                 *init = list(*init, a);
1708                 lr = alist;
1709                 r = lr->n;
1710                 l = structfirst(&savel, nl);
1711         }
1712
1713 loop:
1714         if(l != T && l->isddd) {
1715                 // the ddd parameter must be last
1716                 ll = structnext(&savel);
1717                 if(ll != T)
1718                         yyerror("... must be last argument");
1719
1720                 // special case --
1721                 // only if we are assigning a single ddd
1722                 // argument to a ddd parameter then it is
1723                 // passed thru unencapsulated
1724                 if(r != N && lr->next == nil && isddd && eqtype(l->type, r->type)) {
1725                         a = nod(OAS, nodarg(l, fp), r);
1726                         a = convas(a, init);
1727                         nn = list(nn, a);
1728                         goto ret;
1729                 }
1730
1731                 // normal case -- make a slice of all
1732                 // remaining arguments and pass it to
1733                 // the ddd parameter.
1734                 nn = mkdotargslice(lr, nn, l, fp, init, call->right);
1735                 goto ret;
1736         }
1737
1738         if(l == T || r == N) {
1739                 if(l != T || r != N) {
1740                         l1 = dumptypes(nl, "expected");
1741                         l2 = dumpnodetypes(lr0, "given");
1742                         if(l != T)
1743                                 yyerror("not enough arguments to %O\n%s\n%s", op, l1, l2);
1744                         else
1745                                 yyerror("too many arguments to %O\n%s\n%s", op, l1, l2);
1746                 }
1747                 goto ret;
1748         }
1749
1750         a = nod(OAS, nodarg(l, fp), r);
1751         a = convas(a, init);
1752         nn = list(nn, a);
1753
1754         l = structnext(&savel);
1755         r = N;
1756         lr = lr->next;
1757         if(lr != nil)
1758                 r = lr->n;
1759         goto loop;
1760
1761 ret:
1762         for(lr=nn; lr; lr=lr->next)
1763                 lr->n->typecheck = 1;
1764         return nn;
1765 }
1766
1767 // generate code for print
1768 static Node*
1769 walkprint(Node *nn, NodeList **init)
1770 {
1771         Node *r;
1772         Node *n;
1773         NodeList *l, *all;
1774         Node *on;
1775         Type *t;
1776         int notfirst, et, op;
1777         NodeList *calls;
1778
1779         op = nn->op;
1780         all = nn->list;
1781         calls = nil;
1782         notfirst = 0;
1783
1784         // Hoist all the argument evaluation up before the lock.
1785         walkexprlistcheap(all, init);
1786
1787         calls = list(calls, mkcall("printlock", T, init));
1788
1789         for(l=all; l; l=l->next) {
1790                 if(notfirst) {
1791                         calls = list(calls, mkcall("printsp", T, init));
1792                 }
1793                 notfirst = op == OPRINTN;
1794
1795                 n = l->n;
1796                 if(n->op == OLITERAL) {
1797                         switch(n->val.ctype) {
1798                         case CTRUNE:
1799                                 defaultlit(&n, runetype);
1800                                 break;
1801                         case CTINT:
1802                                 defaultlit(&n, types[TINT64]);
1803                                 break;
1804                         case CTFLT:
1805                                 defaultlit(&n, types[TFLOAT64]);
1806                                 break;
1807                         }
1808                 }
1809                 if(n->op != OLITERAL && n->type && n->type->etype == TIDEAL)
1810                         defaultlit(&n, types[TINT64]);
1811                 defaultlit(&n, nil);
1812                 l->n = n;
1813                 if(n->type == T || n->type->etype == TFORW)
1814                         continue;
1815
1816                 t = n->type;
1817                 et = n->type->etype;
1818                 if(isinter(n->type)) {
1819                         if(isnilinter(n->type))
1820                                 on = syslook("printeface", 1);
1821                         else
1822                                 on = syslook("printiface", 1);
1823                         argtype(on, n->type);           // any-1
1824                 } else if(isptr[et] || et == TCHAN || et == TMAP || et == TFUNC || et == TUNSAFEPTR) {
1825                         on = syslook("printpointer", 1);
1826                         argtype(on, n->type);   // any-1
1827                 } else if(isslice(n->type)) {
1828                         on = syslook("printslice", 1);
1829                         argtype(on, n->type);   // any-1
1830                 } else if(isint[et]) {
1831                         if(et == TUINT64) {
1832                                 if((t->sym->pkg == runtimepkg || compiling_runtime) && strcmp(t->sym->name, "hex") == 0)
1833                                         on = syslook("printhex", 0);
1834                                 else
1835                                         on = syslook("printuint", 0);
1836                         } else
1837                                 on = syslook("printint", 0);
1838                 } else if(isfloat[et]) {
1839                         on = syslook("printfloat", 0);
1840                 } else if(iscomplex[et]) {
1841                         on = syslook("printcomplex", 0);
1842                 } else if(et == TBOOL) {
1843                         on = syslook("printbool", 0);
1844                 } else if(et == TSTRING) {
1845                         on = syslook("printstring", 0);
1846                 } else {
1847                         badtype(OPRINT, n->type, T);
1848                         continue;
1849                 }
1850
1851                 t = *getinarg(on->type);
1852                 if(t != nil)
1853                         t = t->type;
1854                 if(t != nil)
1855                         t = t->type;
1856
1857                 if(!eqtype(t, n->type)) {
1858                         n = nod(OCONV, n, N);
1859                         n->type = t;
1860                 }
1861
1862                 r = nod(OCALL, on, N);
1863                 r->list = list1(n);
1864                 calls = list(calls, r);
1865         }
1866
1867         if(op == OPRINTN)
1868                 calls = list(calls, mkcall("printnl", T, nil));
1869
1870         calls = list(calls, mkcall("printunlock", T, init));
1871
1872         typechecklist(calls, Etop);
1873         walkexprlist(calls, init);
1874
1875         r = nod(OEMPTY, N, N);
1876         typecheck(&r, Etop);
1877         walkexpr(&r, init);
1878         r->ninit = calls;
1879         return r;
1880 }
1881
1882 Node*
1883 callnew(Type *t)
1884 {
1885         Node *fn;
1886
1887         dowidth(t);
1888         fn = syslook("newobject", 1);
1889         argtype(fn, t);
1890         return mkcall1(fn, ptrto(t), nil, typename(t));
1891 }
1892
1893 static int
1894 isstack(Node *n)
1895 {
1896         while(n->op == ODOT || n->op == OPAREN || n->op == OCONVNOP || n->op == OINDEX && isfixedarray(n->left->type))
1897                 n = n->left;
1898         
1899         switch(n->op) {
1900         case OINDREG:
1901                 // OINDREG only ends up in walk if it's indirect of SP.
1902                 return 1;
1903
1904         case ONAME:
1905                 switch(n->class) {
1906                 case PAUTO:
1907                 case PPARAM:
1908                 case PPARAMOUT:
1909                         return 1;
1910                 }
1911                 break;
1912         }
1913         
1914         return 0;
1915 }
1916
1917 static int
1918 isglobal(Node *n)
1919 {
1920         while(n->op == ODOT || n->op == OPAREN || n->op == OCONVNOP || n->op == OINDEX && isfixedarray(n->left->type))
1921                 n = n->left;
1922         
1923         switch(n->op) {
1924         case ONAME:
1925                 switch(n->class) {
1926                 case PEXTERN:
1927                         return 1;
1928                 }
1929                 break;
1930         }
1931         
1932         return 0;
1933 }
1934
1935 // Do we need a write barrier for the assignment l = r?
1936 int
1937 needwritebarrier(Node *l, Node *r)
1938 {
1939         if(!use_writebarrier)
1940                 return 0;
1941
1942         if(l == N || isblank(l))
1943                 return 0;
1944
1945         // No write barrier for write of non-pointers.
1946         dowidth(l->type);
1947         if(!haspointers(l->type))
1948                 return 0;
1949
1950         // No write barrier for write to stack.
1951         if(isstack(l))
1952                 return 0;
1953
1954         // No write barrier for implicit or explicit zeroing.
1955         if(r == N || iszero(r))
1956                 return 0;
1957
1958         // No write barrier for initialization to constant.
1959         if(r->op == OLITERAL)
1960                 return 0;
1961
1962         // No write barrier for storing static (read-only) data.
1963         if(r->op == ONAME && strncmp(r->sym->name, "statictmp_", 10) == 0)
1964                 return 0;
1965
1966         // No write barrier for storing address of stack values,
1967         // which are guaranteed only to be written to the stack.
1968         if(r->op == OADDR && isstack(r->left))
1969                 return 0;
1970
1971         // No write barrier for storing address of global, which
1972         // is live no matter what.
1973         if(r->op == OADDR && isglobal(r->left))
1974                 return 0;
1975
1976         // No write barrier for reslice: x = x[0:y] or x = append(x, ...).
1977         // Both are compiled to modify x directly.
1978         // In the case of append, a write barrier may still be needed
1979         // if the underlying array grows, but the append code can
1980         // generate the write barrier directly in that case.
1981         // (It does not yet, but the cost of the write barrier will be
1982         // small compared to the cost of the allocation.)
1983         if(r->reslice) {
1984                 switch(r->op) {
1985                 case OSLICE:
1986                 case OSLICE3:
1987                 case OSLICESTR:
1988                 case OAPPEND:
1989                         break;
1990                 default:
1991                         dump("bad reslice-l", l);
1992                         dump("bad reslice-r", r);
1993                         break;
1994                 }
1995                 return 0;
1996         }
1997
1998         // Otherwise, be conservative and use write barrier.
1999         return 1;
2000 }
2001
2002 // TODO(rsc): Perhaps componentgen should run before this.
2003 static Node*
2004 applywritebarrier(Node *n, NodeList **init)
2005 {
2006         Node *l, *r;
2007         Type *t;
2008         vlong x;
2009         static Bvec *bv;
2010         char name[32];
2011
2012         if(n->left && n->right && needwritebarrier(n->left, n->right)) {
2013                 t = n->left->type;
2014                 l = nod(OADDR, n->left, N);
2015                 l->etype = 1; // addr does not escape
2016                 if(t->width == widthptr) {
2017                         n = mkcall1(writebarrierfn("writebarrierptr", t, n->right->type), T, init,
2018                                 l, n->right);
2019                 } else if(t->etype == TSTRING) {
2020                         n = mkcall1(writebarrierfn("writebarrierstring", t, n->right->type), T, init,
2021                                 l, n->right);
2022                 } else if(isslice(t)) {
2023                         n = mkcall1(writebarrierfn("writebarrierslice", t, n->right->type), T, init,
2024                                 l, n->right);
2025                 } else if(isinter(t)) {
2026                         n = mkcall1(writebarrierfn("writebarrieriface", t, n->right->type), T, init,
2027                                 l, n->right);
2028                 } else if(t->width <= 4*widthptr) {
2029                         x = 0;
2030                         if(bv == nil)
2031                                 bv = bvalloc(BitsPerPointer*4);
2032                         bvresetall(bv);
2033                         twobitwalktype1(t, &x, bv);
2034                         // The bvgets are looking for BitsPointer in successive slots.
2035                         enum {
2036                                 PtrBit = 1,
2037                         };
2038                         if(BitsPointer != (1<<PtrBit))
2039                                 fatal("wrong PtrBit");
2040                         switch(t->width/widthptr) {
2041                         default:
2042                                 fatal("found writebarrierfat for %d-byte object of type %T", (int)t->width, t);
2043                         case 2:
2044                                 snprint(name, sizeof name, "writebarrierfat%d%d",
2045                                         bvget(bv, PtrBit), bvget(bv, BitsPerPointer+PtrBit));
2046                                 break;
2047                         case 3:
2048                                 snprint(name, sizeof name, "writebarrierfat%d%d%d",
2049                                         bvget(bv, PtrBit), bvget(bv, BitsPerPointer+PtrBit), bvget(bv, 2*BitsPerPointer+PtrBit));
2050                                 break;
2051                         case 4:
2052                                 snprint(name, sizeof name, "writebarrierfat%d%d%d%d",
2053                                         bvget(bv, PtrBit), bvget(bv, BitsPerPointer+PtrBit), bvget(bv, 2*BitsPerPointer+PtrBit), bvget(bv, 3*BitsPerPointer+PtrBit));
2054                                 break;
2055                         }
2056                         n = mkcall1(writebarrierfn(name, t, n->right->type), T, init,
2057                                 l, nodnil(), n->right);
2058                 } else {
2059                         r = n->right;
2060                         while(r->op == OCONVNOP)
2061                                 r = r->left;
2062                         r = nod(OADDR, r, N);
2063                         r->etype = 1; // addr does not escape
2064                         //warnl(n->lineno, "writebarrierfat %T %N", t, r);
2065                         n = mkcall1(writebarrierfn("writebarrierfat", t, r->left->type), T, init,
2066                                 typename(t), l, r);
2067                 }
2068         }
2069         return n;
2070 }
2071
2072 static Node*
2073 convas(Node *n, NodeList **init)
2074 {
2075         Type *lt, *rt;
2076         Node *map, *key, *val;
2077
2078         if(n->op != OAS)
2079                 fatal("convas: not OAS %O", n->op);
2080
2081         n->typecheck = 1;
2082
2083         if(n->left == N || n->right == N)
2084                 goto out;
2085
2086         lt = n->left->type;
2087         rt = n->right->type;
2088         if(lt == T || rt == T)
2089                 goto out;
2090
2091         if(isblank(n->left)) {
2092                 defaultlit(&n->right, T);
2093                 goto out;
2094         }
2095
2096         if(n->left->op == OINDEXMAP) {
2097                 map = n->left->left;
2098                 key = n->left->right;
2099                 val = n->right;
2100                 walkexpr(&map, init);
2101                 walkexpr(&key, init);
2102                 walkexpr(&val, init);
2103                 // orderexpr made sure key and val are addressable.
2104                 key = nod(OADDR, key, N);
2105                 val = nod(OADDR, val, N);
2106                 n = mkcall1(mapfn("mapassign1", map->type), T, init,
2107                         typename(map->type), map, key, val);
2108                 goto out;
2109         }
2110
2111         if(!eqtype(lt, rt)) {
2112                 n->right = assignconv(n->right, lt, "assignment");
2113                 walkexpr(&n->right, init);
2114         }
2115
2116 out:
2117         ullmancalc(n);
2118         return n;
2119 }
2120
2121 /*
2122  * from ascompat[te]
2123  * evaluating actual function arguments.
2124  *      f(a,b)
2125  * if there is exactly one function expr,
2126  * then it is done first. otherwise must
2127  * make temp variables
2128  */
2129 static NodeList*
2130 reorder1(NodeList *all)
2131 {
2132         Node *f, *a, *n;
2133         NodeList *l, *r, *g;
2134         int c, d, t;
2135
2136         c = 0;  // function calls
2137         t = 0;  // total parameters
2138
2139         for(l=all; l; l=l->next) {
2140                 n = l->n;
2141                 t++;
2142                 ullmancalc(n);
2143                 if(n->ullman >= UINF)
2144                         c++;
2145         }
2146         if(c == 0 || t == 1)
2147                 return all;
2148
2149         g = nil;        // fncalls assigned to tempnames
2150         f = N;  // last fncall assigned to stack
2151         r = nil;        // non fncalls and tempnames assigned to stack
2152         d = 0;
2153         for(l=all; l; l=l->next) {
2154                 n = l->n;
2155                 if(n->ullman < UINF) {
2156                         r = list(r, n);
2157                         continue;
2158                 }
2159                 d++;
2160                 if(d == c) {
2161                         f = n;
2162                         continue;
2163                 }
2164
2165                 // make assignment of fncall to tempname
2166                 a = temp(n->right->type);
2167                 a = nod(OAS, a, n->right);
2168                 g = list(g, a);
2169
2170                 // put normal arg assignment on list
2171                 // with fncall replaced by tempname
2172                 n->right = a->left;
2173                 r = list(r, n);
2174         }
2175
2176         if(f != N)
2177                 g = list(g, f);
2178         return concat(g, r);
2179 }
2180
2181 static void reorder3save(Node**, NodeList*, NodeList*, NodeList**);
2182 static int aliased(Node*, NodeList*, NodeList*);
2183
2184 /*
2185  * from ascompat[ee]
2186  *      a,b = c,d
2187  * simultaneous assignment. there cannot
2188  * be later use of an earlier lvalue.
2189  *
2190  * function calls have been removed.
2191  */
2192 static NodeList*
2193 reorder3(NodeList *all)
2194 {
2195         NodeList *list, *early, *mapinit;
2196         Node *l;
2197
2198         // If a needed expression may be affected by an
2199         // earlier assignment, make an early copy of that
2200         // expression and use the copy instead.
2201         early = nil;
2202         mapinit = nil;
2203         for(list=all; list; list=list->next) {
2204                 l = list->n->left;
2205
2206                 // Save subexpressions needed on left side.
2207                 // Drill through non-dereferences.
2208                 for(;;) {
2209                         if(l->op == ODOT || l->op == OPAREN) {
2210                                 l = l->left;
2211                                 continue;
2212                         }
2213                         if(l->op == OINDEX && isfixedarray(l->left->type)) {
2214                                 reorder3save(&l->right, all, list, &early);
2215                                 l = l->left;
2216                                 continue;
2217                         }
2218                         break;
2219                 }
2220                 switch(l->op) {
2221                 default:
2222                         fatal("reorder3 unexpected lvalue %#O", l->op);
2223                 case ONAME:
2224                         break;
2225                 case OINDEX:
2226                 case OINDEXMAP:
2227                         reorder3save(&l->left, all, list, &early);
2228                         reorder3save(&l->right, all, list, &early);
2229                         if(l->op == OINDEXMAP)
2230                                 list->n = convas(list->n, &mapinit);
2231                         break;
2232                 case OIND:
2233                 case ODOTPTR:
2234                         reorder3save(&l->left, all, list, &early);
2235                 }
2236
2237                 // Save expression on right side.
2238                 reorder3save(&list->n->right, all, list, &early);
2239         }
2240
2241         early = concat(mapinit, early);
2242         return concat(early, all);
2243 }
2244
2245 static int vmatch2(Node*, Node*);
2246 static int varexpr(Node*);
2247
2248 /*
2249  * if the evaluation of *np would be affected by the 
2250  * assignments in all up to but not including stop,
2251  * copy into a temporary during *early and
2252  * replace *np with that temp.
2253  */
2254 static void
2255 reorder3save(Node **np, NodeList *all, NodeList *stop, NodeList **early)
2256 {
2257         Node *n, *q;
2258
2259         n = *np;
2260         if(!aliased(n, all, stop))
2261                 return;
2262         
2263         q = temp(n->type);
2264         q = nod(OAS, q, n);
2265         typecheck(&q, Etop);
2266         *early = list(*early, q);
2267         *np = q->left;
2268 }
2269
2270 /*
2271  * what's the outer value that a write to n affects?
2272  * outer value means containing struct or array.
2273  */
2274 Node*
2275 outervalue(Node *n)
2276 {       
2277         for(;;) {
2278                 if(n->op == ODOT || n->op == OPAREN) {
2279                         n = n->left;
2280                         continue;
2281                 }
2282                 if(n->op == OINDEX && isfixedarray(n->left->type)) {
2283                         n = n->left;
2284                         continue;
2285                 }
2286                 break;
2287         }
2288         return n;
2289 }
2290
2291 /*
2292  * Is it possible that the computation of n might be
2293  * affected by writes in as up to but not including stop?
2294  */
2295 static int
2296 aliased(Node *n, NodeList *all, NodeList *stop)
2297 {
2298         int memwrite, varwrite;
2299         Node *a;
2300         NodeList *l;
2301
2302         if(n == N)
2303                 return 0;
2304
2305         // Look for obvious aliasing: a variable being assigned
2306         // during the all list and appearing in n.
2307         // Also record whether there are any writes to main memory.
2308         // Also record whether there are any writes to variables
2309         // whose addresses have been taken.
2310         memwrite = 0;
2311         varwrite = 0;
2312         for(l=all; l!=stop; l=l->next) {
2313                 a = outervalue(l->n->left);
2314                 if(a->op != ONAME) {
2315                         memwrite = 1;
2316                         continue;
2317                 }
2318                 switch(n->class) {
2319                 default:
2320                         varwrite = 1;
2321                         continue;
2322                 case PAUTO:
2323                 case PPARAM:
2324                 case PPARAMOUT:
2325                         if(n->addrtaken) {
2326                                 varwrite = 1;
2327                                 continue;
2328                         }
2329                         if(vmatch2(a, n)) {
2330                                 // Direct hit.
2331                                 return 1;
2332                         }
2333                 }
2334         }
2335
2336         // The variables being written do not appear in n.
2337         // However, n might refer to computed addresses
2338         // that are being written.
2339         
2340         // If no computed addresses are affected by the writes, no aliasing.
2341         if(!memwrite && !varwrite)
2342                 return 0;
2343
2344         // If n does not refer to computed addresses
2345         // (that is, if n only refers to variables whose addresses
2346         // have not been taken), no aliasing.
2347         if(varexpr(n))
2348                 return 0;
2349
2350         // Otherwise, both the writes and n refer to computed memory addresses.
2351         // Assume that they might conflict.
2352         return 1;
2353 }
2354
2355 /*
2356  * does the evaluation of n only refer to variables
2357  * whose addresses have not been taken?
2358  * (and no other memory)
2359  */
2360 static int
2361 varexpr(Node *n)
2362 {
2363         if(n == N)
2364                 return 1;
2365
2366         switch(n->op) {
2367         case OLITERAL:  
2368                 return 1;
2369         case ONAME:
2370                 switch(n->class) {
2371                 case PAUTO:
2372                 case PPARAM:
2373                 case PPARAMOUT:
2374                         if(!n->addrtaken)
2375                                 return 1;
2376                 }
2377                 return 0;
2378
2379         case OADD:
2380         case OSUB:
2381         case OOR:
2382         case OXOR:
2383         case OMUL:
2384         case ODIV:
2385         case OMOD:
2386         case OLSH:
2387         case ORSH:
2388         case OAND:
2389         case OANDNOT:
2390         case OPLUS:
2391         case OMINUS:
2392         case OCOM:
2393         case OPAREN:
2394         case OANDAND:
2395         case OOROR:
2396         case ODOT:  // but not ODOTPTR
2397         case OCONV:
2398         case OCONVNOP:
2399         case OCONVIFACE:
2400         case ODOTTYPE:
2401                 return varexpr(n->left) && varexpr(n->right);
2402         }
2403
2404         // Be conservative.
2405         return 0;
2406 }
2407
2408 /*
2409  * is the name l mentioned in r?
2410  */
2411 static int
2412 vmatch2(Node *l, Node *r)
2413 {
2414         NodeList *ll;
2415
2416         if(r == N)
2417                 return 0;
2418         switch(r->op) {
2419         case ONAME:
2420                 // match each right given left
2421                 return l == r;
2422         case OLITERAL:
2423                 return 0;
2424         }
2425         if(vmatch2(l, r->left))
2426                 return 1;
2427         if(vmatch2(l, r->right))
2428                 return 1;
2429         for(ll=r->list; ll; ll=ll->next)
2430                 if(vmatch2(l, ll->n))
2431                         return 1;
2432         return 0;
2433 }
2434
2435 /*
2436  * is any name mentioned in l also mentioned in r?
2437  * called by sinit.c
2438  */
2439 int
2440 vmatch1(Node *l, Node *r)
2441 {
2442         NodeList *ll;
2443
2444         /*
2445          * isolate all left sides
2446          */
2447         if(l == N || r == N)
2448                 return 0;
2449         switch(l->op) {
2450         case ONAME:
2451                 switch(l->class) {
2452                 case PPARAM:
2453                 case PPARAMREF:
2454                 case PAUTO:
2455                         break;
2456                 default:
2457                         // assignment to non-stack variable
2458                         // must be delayed if right has function calls.
2459                         if(r->ullman >= UINF)
2460                                 return 1;
2461                         break;
2462                 }
2463                 return vmatch2(l, r);
2464         case OLITERAL:
2465                 return 0;
2466         }
2467         if(vmatch1(l->left, r))
2468                 return 1;
2469         if(vmatch1(l->right, r))
2470                 return 1;
2471         for(ll=l->list; ll; ll=ll->next)
2472                 if(vmatch1(ll->n, r))
2473                         return 1;
2474         return 0;
2475 }
2476
2477 /*
2478  * walk through argin parameters.
2479  * generate and return code to allocate
2480  * copies of escaped parameters to the heap.
2481  */
2482 static NodeList*
2483 paramstoheap(Type **argin, int out)
2484 {
2485         Type *t;
2486         Iter savet;
2487         Node *v;
2488         NodeList *nn;
2489
2490         nn = nil;
2491         for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) {
2492                 v = t->nname;
2493                 if(v && v->sym && v->sym->name[0] == '~' && v->sym->name[1] == 'r') // unnamed result
2494                         v = N;
2495                 // In precisestack mode, the garbage collector assumes results
2496                 // are always live, so zero them always.
2497                 if(out && (precisestack_enabled || (v == N && hasdefer))) {
2498                         // Defer might stop a panic and show the
2499                         // return values as they exist at the time of panic.
2500                         // Make sure to zero them on entry to the function.
2501                         nn = list(nn, nod(OAS, nodarg(t, 1), N));
2502                 }
2503                 if(v == N || !(v->class & PHEAP))
2504                         continue;
2505
2506                 // generate allocation & copying code
2507                 if(compiling_runtime)
2508                         yyerror("%N escapes to heap, not allowed in runtime.", v);
2509                 if(v->alloc == nil)
2510                         v->alloc = callnew(v->type);
2511                 nn = list(nn, nod(OAS, v->heapaddr, v->alloc));
2512                 if((v->class & ~PHEAP) != PPARAMOUT)
2513                         nn = list(nn, nod(OAS, v, v->stackparam));
2514         }
2515         return nn;
2516 }
2517
2518 /*
2519  * walk through argout parameters copying back to stack
2520  */
2521 static NodeList*
2522 returnsfromheap(Type **argin)
2523 {
2524         Type *t;
2525         Iter savet;
2526         Node *v;
2527         NodeList *nn;
2528
2529         nn = nil;
2530         for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) {
2531                 v = t->nname;
2532                 if(v == N || v->class != (PHEAP|PPARAMOUT))
2533                         continue;
2534                 nn = list(nn, nod(OAS, v->stackparam, v));
2535         }
2536         return nn;
2537 }
2538
2539 /*
2540  * take care of migrating any function in/out args
2541  * between the stack and the heap.  adds code to
2542  * curfn's before and after lists.
2543  */
2544 static void
2545 heapmoves(void)
2546 {
2547         NodeList *nn;
2548         int32 lno;
2549
2550         lno = lineno;
2551         lineno = curfn->lineno;
2552         nn = paramstoheap(getthis(curfn->type), 0);
2553         nn = concat(nn, paramstoheap(getinarg(curfn->type), 0));
2554         nn = concat(nn, paramstoheap(getoutarg(curfn->type), 1));
2555         curfn->enter = concat(curfn->enter, nn);
2556         lineno = curfn->endlineno;
2557         curfn->exit = returnsfromheap(getoutarg(curfn->type));
2558         lineno = lno;
2559 }
2560
2561 static Node*
2562 vmkcall(Node *fn, Type *t, NodeList **init, va_list va)
2563 {
2564         int i, n;
2565         Node *r;
2566         NodeList *args;
2567
2568         if(fn->type == T || fn->type->etype != TFUNC)
2569                 fatal("mkcall %N %T", fn, fn->type);
2570
2571         args = nil;
2572         n = fn->type->intuple;
2573         for(i=0; i<n; i++)
2574                 args = list(args, va_arg(va, Node*));
2575
2576         r = nod(OCALL, fn, N);
2577         r->list = args;
2578         if(fn->type->outtuple > 0)
2579                 typecheck(&r, Erv | Efnstruct);
2580         else
2581                 typecheck(&r, Etop);
2582         walkexpr(&r, init);
2583         r->type = t;
2584         return r;
2585 }
2586
2587 Node*
2588 mkcall(char *name, Type *t, NodeList **init, ...)
2589 {
2590         Node *r;
2591         va_list va;
2592
2593         va_start(va, init);
2594         r = vmkcall(syslook(name, 0), t, init, va);
2595         va_end(va);
2596         return r;
2597 }
2598
2599 Node*
2600 mkcall1(Node *fn, Type *t, NodeList **init, ...)
2601 {
2602         Node *r;
2603         va_list va;
2604
2605         va_start(va, init);
2606         r = vmkcall(fn, t, init, va);
2607         va_end(va);
2608         return r;
2609 }
2610
2611 Node*
2612 conv(Node *n, Type *t)
2613 {
2614         if(eqtype(n->type, t))
2615                 return n;
2616         n = nod(OCONV, n, N);
2617         n->type = t;
2618         typecheck(&n, Erv);
2619         return n;
2620 }
2621
2622 Node*
2623 chanfn(char *name, int n, Type *t)
2624 {
2625         Node *fn;
2626         int i;
2627
2628         if(t->etype != TCHAN)
2629                 fatal("chanfn %T", t);
2630         fn = syslook(name, 1);
2631         for(i=0; i<n; i++)
2632                 argtype(fn, t->type);
2633         return fn;
2634 }
2635
2636 static Node*
2637 mapfn(char *name, Type *t)
2638 {
2639         Node *fn;
2640
2641         if(t->etype != TMAP)
2642                 fatal("mapfn %T", t);
2643         fn = syslook(name, 1);
2644         argtype(fn, t->down);
2645         argtype(fn, t->type);
2646         argtype(fn, t->down);
2647         argtype(fn, t->type);
2648         return fn;
2649 }
2650
2651 static Node*
2652 mapfndel(char *name, Type *t)
2653 {
2654         Node *fn;
2655
2656         if(t->etype != TMAP)
2657                 fatal("mapfn %T", t);
2658         fn = syslook(name, 1);
2659         argtype(fn, t->down);
2660         argtype(fn, t->type);
2661         argtype(fn, t->down);
2662         return fn;
2663 }
2664
2665 static Node*
2666 writebarrierfn(char *name, Type *l, Type *r)
2667 {
2668         Node *fn;
2669
2670         fn = syslook(name, 1);
2671         argtype(fn, l);
2672         argtype(fn, r);
2673         return fn;
2674 }
2675
2676 static Node*
2677 addstr(Node *n, NodeList **init)
2678 {
2679         Node *r, *cat, *slice;
2680         NodeList *args, *l;
2681         int c;
2682         Type *t;
2683
2684         // orderexpr rewrote OADDSTR to have a list of strings.
2685         c = count(n->list);
2686         if(c < 2)
2687                 yyerror("addstr count %d too small", c);
2688
2689         // build list of string arguments
2690         args = nil;
2691         for(l=n->list; l != nil; l=l->next)
2692                 args = list(args, conv(l->n, types[TSTRING]));
2693
2694         if(c <= 5) {
2695                 // small numbers of strings use direct runtime helpers.
2696                 // note: orderexpr knows this cutoff too.
2697                 snprint(namebuf, sizeof(namebuf), "concatstring%d", c);
2698         } else {
2699                 // large numbers of strings are passed to the runtime as a slice.
2700                 strcpy(namebuf, "concatstrings");
2701                 t = typ(TARRAY);
2702                 t->type = types[TSTRING];
2703                 t->bound = -1;
2704                 slice = nod(OCOMPLIT, N, typenod(t));
2705                 slice->alloc = n->alloc;
2706                 slice->list = args;
2707                 slice->esc = EscNone;
2708                 args = list1(slice);
2709         }
2710         cat = syslook(namebuf, 1);
2711         r = nod(OCALL, cat, N);
2712         r->list = args;
2713         typecheck(&r, Erv);
2714         walkexpr(&r, init);
2715         r->type = n->type;
2716
2717         return r;
2718 }
2719
2720 // expand append(l1, l2...) to
2721 //   init {
2722 //     s := l1
2723 //     if n := len(l1) + len(l2) - cap(s); n > 0 {
2724 //       s = growslice(s, n)
2725 //     }
2726 //     s = s[:len(l1)+len(l2)]
2727 //     memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T))
2728 //   }
2729 //   s
2730 //
2731 // l2 is allowed to be a string.
2732 static Node*
2733 appendslice(Node *n, NodeList **init)
2734 {
2735         NodeList *l;
2736         Node *l1, *l2, *nt, *nif, *fn;
2737         Node *nptr1, *nptr2, *nwid;
2738         Node *s;
2739
2740         walkexprlistsafe(n->list, init);
2741
2742         // walkexprlistsafe will leave OINDEX (s[n]) alone if both s
2743         // and n are name or literal, but those may index the slice we're
2744         // modifying here.  Fix explicitly.
2745         for(l=n->list; l; l=l->next)
2746                 l->n = cheapexpr(l->n, init);
2747
2748         l1 = n->list->n;
2749         l2 = n->list->next->n;
2750
2751         s = temp(l1->type); // var s []T
2752         l = nil;
2753         l = list(l, nod(OAS, s, l1)); // s = l1
2754
2755         nt = temp(types[TINT]);
2756         nif = nod(OIF, N, N);
2757         // n := len(s) + len(l2) - cap(s)
2758         nif->ninit = list1(nod(OAS, nt,
2759                 nod(OSUB, nod(OADD, nod(OLEN, s, N), nod(OLEN, l2, N)), nod(OCAP, s, N))));
2760         nif->ntest = nod(OGT, nt, nodintconst(0));
2761         // instantiate growslice(Type*, []any, int64) []any
2762         fn = syslook("growslice", 1);
2763         argtype(fn, s->type->type);
2764         argtype(fn, s->type->type);
2765
2766         // s = growslice(T, s, n)
2767         nif->nbody = list1(nod(OAS, s, mkcall1(fn, s->type, &nif->ninit,
2768                                                typename(s->type),
2769                                                s,
2770                                                conv(nt, types[TINT64]))));
2771
2772         l = list(l, nif);
2773
2774         if(flag_race) {
2775                 // rely on runtime to instrument copy.
2776                 // copy(s[len(l1):len(l1)+len(l2)], l2)
2777                 nptr1 = nod(OSLICE, s, nod(OKEY,
2778                         nod(OLEN, l1, N),
2779                         nod(OADD, nod(OLEN, l1, N), nod(OLEN, l2, N))));
2780                 nptr1->etype = 1;
2781                 nptr2 = l2;
2782                 if(l2->type->etype == TSTRING)
2783                         fn = syslook("slicestringcopy", 1);
2784                 else
2785                         fn = syslook("slicecopy", 1);
2786                 argtype(fn, l1->type);
2787                 argtype(fn, l2->type);
2788                 nt = mkcall1(fn, types[TINT], &l,
2789                                 nptr1, nptr2,
2790                                 nodintconst(s->type->type->width));
2791                 l = list(l, nt);
2792         } else {
2793                 // memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T))
2794                 nptr1 = nod(OINDEX, s, nod(OLEN, l1, N));
2795                 nptr1->bounded = 1;
2796                 nptr1 = nod(OADDR, nptr1, N);
2797
2798                 nptr2 = nod(OSPTR, l2, N);
2799
2800                 fn = syslook("memmove", 1);
2801                 argtype(fn, s->type->type);     // 1 old []any
2802                 argtype(fn, s->type->type);     // 2 ret []any
2803
2804                 nwid = cheapexpr(conv(nod(OLEN, l2, N), types[TUINTPTR]), &l);
2805                 nwid = nod(OMUL, nwid, nodintconst(s->type->type->width));
2806                 nt = mkcall1(fn, T, &l, nptr1, nptr2, nwid);
2807                 l = list(l, nt);
2808         }
2809
2810         // s = s[:len(l1)+len(l2)]
2811         nt = nod(OADD, nod(OLEN, l1, N), nod(OLEN, l2, N));
2812         nt = nod(OSLICE, s, nod(OKEY, N, nt));
2813         nt->etype = 1;
2814         l = list(l, nod(OAS, s, nt));
2815
2816         typechecklist(l, Etop);
2817         walkstmtlist(l);
2818         *init = concat(*init, l);
2819         return s;
2820 }
2821
2822 // expand append(src, a [, b]* ) to
2823 //
2824 //   init {
2825 //     s := src
2826 //     const argc = len(args) - 1
2827 //     if cap(s) - len(s) < argc {
2828 //          s = growslice(s, argc)
2829 //     }
2830 //     n := len(s)
2831 //     s = s[:n+argc]
2832 //     s[n] = a
2833 //     s[n+1] = b
2834 //     ...
2835 //   }
2836 //   s
2837 static Node*
2838 append(Node *n, NodeList **init)
2839 {
2840         NodeList *l, *a;
2841         Node *nsrc, *ns, *nn, *na, *nx, *fn;
2842         int argc;
2843
2844         walkexprlistsafe(n->list, init);
2845
2846         // walkexprlistsafe will leave OINDEX (s[n]) alone if both s
2847         // and n are name or literal, but those may index the slice we're
2848         // modifying here.  Fix explicitly.
2849         for(l=n->list; l; l=l->next)
2850                 l->n = cheapexpr(l->n, init);
2851
2852         nsrc = n->list->n;
2853
2854         // Resolve slice type of multi-valued return.
2855         if(istype(nsrc->type, TSTRUCT))
2856                 nsrc->type = nsrc->type->type->type;
2857         argc = count(n->list) - 1;
2858         if (argc < 1) {
2859                 return nsrc;
2860         }
2861
2862         l = nil;
2863
2864         ns = temp(nsrc->type);
2865         l = list(l, nod(OAS, ns, nsrc));  // s = src
2866
2867         na = nodintconst(argc);         // const argc
2868         nx = nod(OIF, N, N);            // if cap(s) - len(s) < argc
2869         nx->ntest = nod(OLT, nod(OSUB, nod(OCAP, ns, N), nod(OLEN, ns, N)), na);
2870
2871         fn = syslook("growslice", 1);   //   growslice(<type>, old []T, n int64) (ret []T)
2872         argtype(fn, ns->type->type);    // 1 old []any
2873         argtype(fn, ns->type->type);    // 2 ret []any
2874
2875         nx->nbody = list1(nod(OAS, ns, mkcall1(fn,  ns->type, &nx->ninit,
2876                                                typename(ns->type),
2877                                                ns,
2878                                                conv(na, types[TINT64]))));
2879         l = list(l, nx);
2880
2881         nn = temp(types[TINT]);
2882         l = list(l, nod(OAS, nn, nod(OLEN, ns, N)));     // n = len(s)
2883
2884         nx = nod(OSLICE, ns, nod(OKEY, N, nod(OADD, nn, na)));   // ...s[:n+argc]
2885         nx->etype = 1;
2886         l = list(l, nod(OAS, ns, nx));                  // s = s[:n+argc]
2887
2888         for (a = n->list->next;  a != nil; a = a->next) {
2889                 nx = nod(OINDEX, ns, nn);               // s[n] ...
2890                 nx->bounded = 1;
2891                 l = list(l, nod(OAS, nx, a->n));        // s[n] = arg
2892                 if (a->next != nil)
2893                         l = list(l, nod(OAS, nn, nod(OADD, nn, nodintconst(1))));  // n = n + 1
2894         }
2895
2896         typechecklist(l, Etop);
2897         walkstmtlist(l);
2898         *init = concat(*init, l);
2899         return ns;
2900 }
2901
2902 // Lower copy(a, b) to a memmove call or a runtime call.
2903 //
2904 // init {
2905 //   n := len(a)
2906 //   if n > len(b) { n = len(b) }
2907 //   memmove(a.ptr, b.ptr, n*sizeof(elem(a)))
2908 // }
2909 // n;
2910 //
2911 // Also works if b is a string.
2912 //
2913 static Node*
2914 copyany(Node *n, NodeList **init, int runtimecall)
2915 {
2916         Node *nl, *nr, *nfrm, *nto, *nif, *nlen, *nwid, *fn;
2917         NodeList *l;
2918         
2919         if(haspointers(n->left->type->type)) {
2920                 fn = writebarrierfn("writebarriercopy", n->left->type, n->right->type);
2921                 return mkcall1(fn, n->type, init, typename(n->left->type->type), n->left, n->right);
2922         }
2923
2924         if(runtimecall) {
2925                 if(n->right->type->etype == TSTRING)
2926                         fn = syslook("slicestringcopy", 1);
2927                 else
2928                         fn = syslook("slicecopy", 1);
2929                 argtype(fn, n->left->type);
2930                 argtype(fn, n->right->type);
2931                 return mkcall1(fn, n->type, init,
2932                                 n->left, n->right,
2933                                 nodintconst(n->left->type->type->width));
2934         }
2935         walkexpr(&n->left, init);
2936         walkexpr(&n->right, init);
2937         nl = temp(n->left->type);
2938         nr = temp(n->right->type);
2939         l = nil;
2940         l = list(l, nod(OAS, nl, n->left));
2941         l = list(l, nod(OAS, nr, n->right));
2942
2943         nfrm = nod(OSPTR, nr, N);
2944         nto = nod(OSPTR, nl, N);
2945
2946         nlen = temp(types[TINT]);
2947         // n = len(to)
2948         l = list(l, nod(OAS, nlen, nod(OLEN, nl, N)));
2949         // if n > len(frm) { n = len(frm) }
2950         nif = nod(OIF, N, N);
2951         nif->ntest = nod(OGT, nlen, nod(OLEN, nr, N));
2952         nif->nbody = list(nif->nbody,
2953                 nod(OAS, nlen, nod(OLEN, nr, N)));
2954         l = list(l, nif);
2955
2956         // Call memmove.
2957         fn = syslook("memmove", 1);
2958         argtype(fn, nl->type->type);
2959         argtype(fn, nl->type->type);
2960         nwid = temp(types[TUINTPTR]);
2961         l = list(l, nod(OAS, nwid, conv(nlen, types[TUINTPTR])));
2962         nwid = nod(OMUL, nwid, nodintconst(nl->type->type->width));
2963         l = list(l, mkcall1(fn, T, init, nto, nfrm, nwid));
2964
2965         typechecklist(l, Etop);
2966         walkstmtlist(l);
2967         *init = concat(*init, l);
2968         return nlen;
2969 }
2970
2971 // Generate frontend part for OSLICE[3][ARR|STR]
2972 // 
2973 static  Node*
2974 sliceany(Node* n, NodeList **init)
2975 {
2976         int bounded, slice3;
2977         Node *src, *lb, *hb, *cb, *bound, *chk, *chk0, *chk1, *chk2;
2978         int64 lbv, hbv, cbv, bv, w;
2979         Type *bt;
2980
2981 //      print("before sliceany: %+N\n", n);
2982
2983         src = n->left;
2984         lb = n->right->left;
2985         slice3 = n->op == OSLICE3 || n->op == OSLICE3ARR;
2986         if(slice3) {
2987                 hb = n->right->right->left;
2988                 cb = n->right->right->right;
2989         } else {
2990                 hb = n->right->right;
2991                 cb = N;
2992         }
2993
2994         bounded = n->etype;
2995         
2996         if(n->op == OSLICESTR)
2997                 bound = nod(OLEN, src, N);
2998         else
2999                 bound = nod(OCAP, src, N);
3000
3001         typecheck(&bound, Erv);
3002         walkexpr(&bound, init);  // if src is an array, bound will be a const now.
3003
3004         // static checks if possible
3005         bv = 1LL<<50;
3006         if(isconst(bound, CTINT)) {
3007                 if(!smallintconst(bound))
3008                         yyerror("array len too large");
3009                 else
3010                         bv = mpgetfix(bound->val.u.xval);
3011         }
3012
3013         if(isconst(cb, CTINT)) {
3014                 cbv = mpgetfix(cb->val.u.xval);
3015                 if(cbv < 0 || cbv > bv)
3016                         yyerror("slice index out of bounds");
3017         }
3018         if(isconst(hb, CTINT)) {
3019                 hbv = mpgetfix(hb->val.u.xval);
3020                 if(hbv < 0 || hbv > bv)
3021                         yyerror("slice index out of bounds");
3022         }
3023         if(isconst(lb, CTINT)) {
3024                 lbv = mpgetfix(lb->val.u.xval);
3025                 if(lbv < 0 || lbv > bv) {
3026                         yyerror("slice index out of bounds");
3027                         lbv = -1;
3028                 }
3029                 if(lbv == 0)
3030                         lb = N;
3031         }
3032
3033         // Checking src[lb:hb:cb] or src[lb:hb].
3034         // if chk0 || chk1 || chk2 { panicslice() }
3035         chk = N;
3036         chk0 = N; // cap(src) < cb
3037         chk1 = N; // cb < hb for src[lb:hb:cb]; cap(src) < hb for src[lb:hb]
3038         chk2 = N; // hb < lb
3039
3040         // All comparisons are unsigned to avoid testing < 0.
3041         bt = types[simtype[TUINT]];
3042         if(cb != N && cb->type->width > 4)
3043                 bt = types[TUINT64];
3044         if(hb != N && hb->type->width > 4)
3045                 bt = types[TUINT64];
3046         if(lb != N && lb->type->width > 4)
3047                 bt = types[TUINT64];
3048
3049         bound = cheapexpr(conv(bound, bt), init);
3050
3051         if(cb != N) {
3052                 cb = cheapexpr(conv(cb, bt), init);
3053                 if(!bounded)
3054                         chk0 = nod(OLT, bound, cb);
3055         } else if(slice3) {
3056                 // When we figure out what this means, implement it.
3057                 fatal("slice3 with cb == N"); // rejected by parser
3058         }
3059                 
3060         if(hb != N) {
3061                 hb = cheapexpr(conv(hb, bt), init);
3062                 if(!bounded) {
3063                         if(cb != N)
3064                                 chk1 = nod(OLT, cb, hb);
3065                         else
3066                                 chk1 = nod(OLT, bound, hb);
3067                 }
3068         } else if(slice3) {
3069                 // When we figure out what this means, implement it.
3070                 fatal("slice3 with hb == N"); // rejected by parser
3071         } else if(n->op == OSLICEARR) {
3072                 hb = bound;
3073         } else {
3074                 hb = nod(OLEN, src, N);
3075                 typecheck(&hb, Erv);
3076                 walkexpr(&hb, init);
3077                 hb = cheapexpr(conv(hb, bt), init);
3078         }
3079
3080         if(lb != N) {
3081                 lb = cheapexpr(conv(lb, bt), init);
3082                 if(!bounded)
3083                         chk2 = nod(OLT, hb, lb);  
3084         }
3085
3086         if(chk0 != N || chk1 != N || chk2 != N) {
3087                 chk = nod(OIF, N, N);
3088                 chk->nbody = list1(mkcall("panicslice", T, init));
3089                 chk->likely = -1;
3090                 if(chk0 != N)
3091                         chk->ntest = chk0;
3092                 if(chk1 != N) {
3093                         if(chk->ntest == N)
3094                                 chk->ntest = chk1;
3095                         else
3096                                 chk->ntest = nod(OOROR, chk->ntest, chk1);
3097                 }
3098                 if(chk2 != N) {
3099                         if(chk->ntest == N)
3100                                 chk->ntest = chk2;
3101                         else
3102                                 chk->ntest = nod(OOROR, chk->ntest, chk2);
3103                 }
3104                 typecheck(&chk, Etop);
3105                 walkstmt(&chk);
3106                 *init = concat(*init, chk->ninit);
3107                 chk->ninit = nil;
3108                 *init = list(*init, chk);
3109         }
3110         
3111         // prepare new cap, len and offs for backend cgen_slice
3112         // cap = bound [ - lo ]
3113         n->right = N;
3114         n->list = nil;
3115         if(!slice3)
3116                 cb = bound;
3117         if(lb == N)
3118                 bound = conv(cb, types[simtype[TUINT]]);
3119         else
3120                 bound = nod(OSUB, conv(cb, types[simtype[TUINT]]), conv(lb, types[simtype[TUINT]]));
3121         typecheck(&bound, Erv);
3122         walkexpr(&bound, init);
3123         n->list = list(n->list, bound);
3124
3125         // len = hi [ - lo]
3126         if(lb == N)
3127                 hb = conv(hb, types[simtype[TUINT]]);
3128         else
3129                 hb = nod(OSUB, conv(hb, types[simtype[TUINT]]), conv(lb, types[simtype[TUINT]]));
3130         typecheck(&hb, Erv);
3131         walkexpr(&hb, init);
3132         n->list = list(n->list, hb);
3133
3134         // offs = [width *] lo, but omit if zero
3135         if(lb != N) {
3136                 if(n->op == OSLICESTR)
3137                         w = 1;
3138                 else
3139                         w = n->type->type->width;
3140                 lb = conv(lb, types[TUINTPTR]);
3141                 if(w > 1)
3142                         lb = nod(OMUL, nodintconst(w), lb);
3143                 typecheck(&lb, Erv);
3144                 walkexpr(&lb, init);
3145                 n->list = list(n->list, lb);
3146         }
3147
3148 //      print("after sliceany: %+N\n", n);
3149
3150         return n;
3151 }
3152
3153 static Node*
3154 eqfor(Type *t)
3155 {
3156         int a;
3157         Node *n;
3158         Node *ntype;
3159         Sym *sym;
3160
3161         // Should only arrive here with large memory or
3162         // a struct/array containing a non-memory field/element.
3163         // Small memory is handled inline, and single non-memory
3164         // is handled during type check (OCMPSTR etc).
3165         a = algtype1(t, nil);
3166         if(a != AMEM && a != -1)
3167                 fatal("eqfor %T", t);
3168
3169         if(a == AMEM) {
3170                 n = syslook("memequal", 1);
3171                 argtype(n, t);
3172                 argtype(n, t);
3173                 return n;
3174         }
3175
3176         sym = typesymprefix(".eq", t);
3177         n = newname(sym);
3178         n->class = PFUNC;
3179         ntype = nod(OTFUNC, N, N);
3180         ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(ptrto(t))));
3181         ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(ptrto(t))));
3182         ntype->list = list(ntype->list, nod(ODCLFIELD, N, typenod(types[TUINTPTR])));
3183         ntype->rlist = list(ntype->rlist, nod(ODCLFIELD, N, typenod(types[TBOOL])));
3184         typecheck(&ntype, Etype);
3185         n->type = ntype->type;
3186         return n;
3187 }
3188
3189 static int
3190 countfield(Type *t)
3191 {
3192         Type *t1;
3193         int n;
3194         
3195         n = 0;
3196         for(t1=t->type; t1!=T; t1=t1->down)
3197                 n++;
3198         return n;
3199 }
3200
3201 static void
3202 walkcompare(Node **np, NodeList **init)
3203 {
3204         Node *n, *l, *r, *call, *a, *li, *ri, *expr, *cmpl, *cmpr;
3205         int andor, i;
3206         Type *t, *t1;
3207         
3208         n = *np;
3209         
3210         // Must be comparison of array or struct.
3211         // Otherwise back end handles it.
3212         t = n->left->type;
3213         switch(t->etype) {
3214         default:
3215                 return;
3216         case TARRAY:
3217                 if(isslice(t))
3218                         return;
3219                 break;
3220         case TSTRUCT:
3221                 break;
3222         }
3223         
3224         cmpl = n->left;
3225         while(cmpl != N && cmpl->op == OCONVNOP)
3226                 cmpl = cmpl->left;
3227         cmpr = n->right;
3228         while(cmpr != N && cmpr->op == OCONVNOP)
3229                 cmpr = cmpr->left;
3230         
3231         if(!islvalue(cmpl) || !islvalue(cmpr)) {
3232                 fatal("arguments of comparison must be lvalues - %N %N", cmpl, cmpr);
3233         }
3234
3235         l = temp(ptrto(t));
3236         a = nod(OAS, l, nod(OADDR, cmpl, N));
3237         a->right->etype = 1;  // addr does not escape
3238         typecheck(&a, Etop);
3239         *init = list(*init, a);
3240
3241         r = temp(ptrto(t));
3242         a = nod(OAS, r, nod(OADDR, cmpr, N));
3243         a->right->etype = 1;  // addr does not escape
3244         typecheck(&a, Etop);
3245         *init = list(*init, a);
3246
3247         expr = N;
3248         andor = OANDAND;
3249         if(n->op == ONE)
3250                 andor = OOROR;
3251
3252         if(t->etype == TARRAY &&
3253                 t->bound <= 4 &&
3254                 issimple[t->type->etype]) {
3255                 // Four or fewer elements of a basic type.
3256                 // Unroll comparisons.
3257                 for(i=0; i<t->bound; i++) {
3258                         li = nod(OINDEX, l, nodintconst(i));
3259                         ri = nod(OINDEX, r, nodintconst(i));
3260                         a = nod(n->op, li, ri);
3261                         if(expr == N)
3262                                 expr = a;
3263                         else
3264                                 expr = nod(andor, expr, a);
3265                 }
3266                 if(expr == N)
3267                         expr = nodbool(n->op == OEQ);
3268                 r = expr;
3269                 goto ret;
3270         }
3271
3272         if(t->etype == TSTRUCT && countfield(t) <= 4) {
3273                 // Struct of four or fewer fields.
3274                 // Inline comparisons.
3275                 for(t1=t->type; t1; t1=t1->down) {
3276                         if(isblanksym(t1->sym))
3277                                 continue;
3278                         li = nod(OXDOT, l, newname(t1->sym));
3279                         ri = nod(OXDOT, r, newname(t1->sym));
3280                         a = nod(n->op, li, ri);
3281                         if(expr == N)
3282                                 expr = a;
3283                         else
3284                                 expr = nod(andor, expr, a);
3285                 }
3286                 if(expr == N)
3287                         expr = nodbool(n->op == OEQ);
3288                 r = expr;
3289                 goto ret;
3290         }
3291
3292         // Chose not to inline.  Call equality function directly.
3293         call = nod(OCALL, eqfor(t), N);
3294         call->list = list(call->list, l);
3295         call->list = list(call->list, r);
3296         call->list = list(call->list, nodintconst(t->width));
3297         r = call;
3298         if(n->op != OEQ)
3299                 r = nod(ONOT, r, N);
3300         goto ret;
3301
3302 ret:
3303         typecheck(&r, Erv);
3304         walkexpr(&r, init);
3305         if(r->type != n->type) {
3306                 r = nod(OCONVNOP, r, N);
3307                 r->type = n->type;
3308                 r->typecheck = 1;
3309         }
3310         *np = r;
3311         return;
3312 }
3313
3314 static int
3315 samecheap(Node *a, Node *b)
3316 {
3317         Node *ar, *br;
3318         while(a != N && b != N && a->op == b->op) {
3319                 switch(a->op) {
3320                 default:
3321                         return 0;
3322                 case ONAME:
3323                         return a == b;
3324                 case ODOT:
3325                 case ODOTPTR:
3326                         ar = a->right;
3327                         br = b->right;
3328                         if(ar->op != ONAME || br->op != ONAME || ar->sym != br->sym)
3329                                 return 0;
3330                         break;
3331                 case OINDEX:
3332                         ar = a->right;
3333                         br = b->right;
3334                         if(!isconst(ar, CTINT) || !isconst(br, CTINT) || mpcmpfixfix(ar->val.u.xval, br->val.u.xval) != 0)
3335                                 return 0;
3336                         break;
3337                 }
3338                 a = a->left;
3339                 b = b->left;
3340         }
3341         return 0;
3342 }
3343
3344 static void
3345 walkrotate(Node **np)
3346 {
3347         int w, sl, sr, s;
3348         Node *l, *r;
3349         Node *n;
3350
3351         if(thechar == '9')
3352                 return;
3353         
3354         n = *np;
3355
3356         // Want << | >> or >> | << or << ^ >> or >> ^ << on unsigned value.
3357         l = n->left;
3358         r = n->right;
3359         if((n->op != OOR && n->op != OXOR) ||
3360            (l->op != OLSH && l->op != ORSH) ||
3361            (r->op != OLSH && r->op != ORSH) ||
3362            n->type == T || issigned[n->type->etype] ||
3363            l->op == r->op) {
3364                 return;
3365         }
3366
3367         // Want same, side effect-free expression on lhs of both shifts.
3368         if(!samecheap(l->left, r->left))
3369                 return;
3370         
3371         // Constants adding to width?
3372         w = l->type->width * 8;
3373         if(smallintconst(l->right) && smallintconst(r->right)) {
3374                 if((sl=mpgetfix(l->right->val.u.xval)) >= 0 && (sr=mpgetfix(r->right->val.u.xval)) >= 0 && sl+sr == w)
3375                         goto yes;
3376                 return;
3377         }
3378         
3379         // TODO: Could allow s and 32-s if s is bounded (maybe s&31 and 32-s&31).
3380         return;
3381         
3382 yes:
3383         // Rewrite left shift half to left rotate.
3384         if(l->op == OLSH)
3385                 n = l;
3386         else
3387                 n = r;
3388         n->op = OLROT;
3389         
3390         // Remove rotate 0 and rotate w.
3391         s = mpgetfix(n->right->val.u.xval);
3392         if(s == 0 || s == w)
3393                 n = n->left;
3394
3395         *np = n;
3396         return;
3397 }
3398
3399 /*
3400  * walkmul rewrites integer multiplication by powers of two as shifts.
3401  */
3402 static void
3403 walkmul(Node **np, NodeList **init)
3404 {
3405         Node *n, *nl, *nr;
3406         int pow, neg, w;
3407         
3408         n = *np;
3409         if(!isint[n->type->etype])
3410                 return;
3411
3412         if(n->right->op == OLITERAL) {
3413                 nl = n->left;
3414                 nr = n->right;
3415         } else if(n->left->op == OLITERAL) {
3416                 nl = n->right;
3417                 nr = n->left;
3418         } else
3419                 return;
3420
3421         neg = 0;
3422
3423         // x*0 is 0 (and side effects of x).
3424         if(mpgetfix(nr->val.u.xval) == 0) {
3425                 cheapexpr(nl, init);
3426                 nodconst(n, n->type, 0);
3427                 goto ret;
3428         }
3429
3430         // nr is a constant.
3431         pow = powtwo(nr);
3432         if(pow < 0)
3433                 return;
3434         if(pow >= 1000) {
3435                 // negative power of 2, like -16
3436                 neg = 1;
3437                 pow -= 1000;
3438         }
3439
3440         w = nl->type->width*8;
3441         if(pow+1 >= w)// too big, shouldn't happen
3442                 return;
3443
3444         nl = cheapexpr(nl, init);
3445
3446         if(pow == 0) {
3447                 // x*1 is x
3448                 n = nl;
3449                 goto ret;
3450         }
3451         
3452         n = nod(OLSH, nl, nodintconst(pow));
3453
3454 ret:
3455         if(neg)
3456                 n = nod(OMINUS, n, N);
3457
3458         typecheck(&n, Erv);
3459         walkexpr(&n, init);
3460         *np = n;
3461 }
3462
3463 /*
3464  * walkdiv rewrites division by a constant as less expensive
3465  * operations.
3466  */
3467 static void
3468 walkdiv(Node **np, NodeList **init)
3469 {
3470         Node *n, *nl, *nr, *nc;
3471         Node *n1, *n2, *n3, *n4;
3472         int pow; // if >= 0, nr is 1<<pow
3473         int s; // 1 if nr is negative.
3474         int w;
3475         Type *twide;
3476         Magic m;
3477
3478         // TODO(minux)
3479         if(thechar == '9')
3480                 return;
3481
3482         n = *np;
3483         if(n->right->op != OLITERAL)
3484                 return;
3485         // nr is a constant.
3486         nl = cheapexpr(n->left, init);
3487         nr = n->right;
3488
3489         // special cases of mod/div
3490         // by a constant
3491         w = nl->type->width*8;
3492         s = 0;
3493         pow = powtwo(nr);
3494         if(pow >= 1000) {
3495                 // negative power of 2
3496                 s = 1;
3497                 pow -= 1000;
3498         }
3499
3500         if(pow+1 >= w) {
3501                 // divisor too large.
3502                 return;
3503         }
3504         if(pow < 0) {
3505                 goto divbymul;
3506         }
3507
3508         switch(pow) {
3509         case 0:
3510                 if(n->op == OMOD) {
3511                         // nl % 1 is zero.
3512                         nodconst(n, n->type, 0);
3513                 } else if(s) {
3514                         // divide by -1
3515                         n->op = OMINUS;
3516                         n->right = N;
3517                 } else {
3518                         // divide by 1
3519                         n = nl;
3520                 }
3521                 break;
3522         default:
3523                 if(issigned[n->type->etype]) {
3524                         if(n->op == OMOD) {
3525                                 // signed modulo 2^pow is like ANDing
3526                                 // with the last pow bits, but if nl < 0,
3527                                 // nl & (2^pow-1) is (nl+1)%2^pow - 1.
3528                                 nc = nod(OXXX, N, N);
3529                                 nodconst(nc, types[simtype[TUINT]], w-1);
3530                                 n1 = nod(ORSH, nl, nc); // n1 = -1 iff nl < 0.
3531                                 if(pow == 1) {
3532                                         typecheck(&n1, Erv);
3533                                         n1 = cheapexpr(n1, init);
3534                                         // n = (nl+ε)&1 -ε where Îµ=1 iff nl<0.
3535                                         n2 = nod(OSUB, nl, n1);
3536                                         nc = nod(OXXX, N, N);
3537                                         nodconst(nc, nl->type, 1);
3538                                         n3 = nod(OAND, n2, nc);
3539                                         n = nod(OADD, n3, n1);
3540                                 } else {
3541                                         // n = (nl+ε)&(nr-1) - Îµ where Îµ=2^pow-1 iff nl<0.
3542                                         nc = nod(OXXX, N, N);
3543                                         nodconst(nc, nl->type, (1LL<<pow)-1);
3544                                         n2 = nod(OAND, n1, nc); // n2 = 2^pow-1 iff nl<0.
3545                                         typecheck(&n2, Erv);
3546                                         n2 = cheapexpr(n2, init);
3547
3548                                         n3 = nod(OADD, nl, n2);
3549                                         n4 = nod(OAND, n3, nc);
3550                                         n = nod(OSUB, n4, n2);
3551                                 }
3552                                 break;
3553                         } else {
3554                                 // arithmetic right shift does not give the correct rounding.
3555                                 // if nl >= 0, nl >> n == nl / nr
3556                                 // if nl < 0, we want to add 2^n-1 first.
3557                                 nc = nod(OXXX, N, N);
3558                                 nodconst(nc, types[simtype[TUINT]], w-1);
3559                                 n1 = nod(ORSH, nl, nc); // n1 = -1 iff nl < 0.
3560                                 if(pow == 1) {
3561                                         // nl+1 is nl-(-1)
3562                                         n->left = nod(OSUB, nl, n1);
3563                                 } else {
3564                                         // Do a logical right right on -1 to keep pow bits.
3565                                         nc = nod(OXXX, N, N);
3566                                         nodconst(nc, types[simtype[TUINT]], w-pow);
3567                                         n2 = nod(ORSH, conv(n1, tounsigned(nl->type)), nc);
3568                                         n->left = nod(OADD, nl, conv(n2, nl->type));
3569                                 }
3570                                 // n = (nl + 2^pow-1) >> pow
3571                                 n->op = ORSH;
3572                                 nc = nod(OXXX, N, N);
3573                                 nodconst(nc, types[simtype[TUINT]], pow);
3574                                 n->right = nc;
3575                                 n->typecheck = 0;
3576                         }
3577                         if(s)
3578                                 n = nod(OMINUS, n, N);
3579                         break;
3580                 }
3581                 nc = nod(OXXX, N, N);
3582                 if(n->op == OMOD) {
3583                         // n = nl & (nr-1)
3584                         n->op = OAND;
3585                         nodconst(nc, nl->type, mpgetfix(nr->val.u.xval)-1);
3586                 } else {
3587                         // n = nl >> pow
3588                         n->op = ORSH;
3589                         nodconst(nc, types[simtype[TUINT]], pow);
3590                 }
3591                 n->typecheck = 0;
3592                 n->right = nc;
3593                 break;
3594         }
3595         goto ret;
3596
3597 divbymul:
3598         // try to do division by multiply by (2^w)/d
3599         // see hacker's delight chapter 10
3600         // TODO: support 64-bit magic multiply here.
3601         m.w = w;
3602         if(issigned[nl->type->etype]) {
3603                 m.sd = mpgetfix(nr->val.u.xval);
3604                 smagic(&m);
3605         } else {
3606                 m.ud = mpgetfix(nr->val.u.xval);
3607                 umagic(&m);
3608         }
3609         if(m.bad)
3610                 return;
3611
3612         // We have a quick division method so use it
3613         // for modulo too.
3614         if(n->op == OMOD)
3615                 goto longmod;
3616
3617         switch(simtype[nl->type->etype]) {
3618         default:
3619                 return;
3620
3621         case TUINT8:
3622         case TUINT16:
3623         case TUINT32:
3624                 // n1 = nl * magic >> w (HMUL)
3625                 nc = nod(OXXX, N, N);
3626                 nodconst(nc, nl->type, m.um);
3627                 n1 = nod(OMUL, nl, nc);
3628                 typecheck(&n1, Erv);
3629                 n1->op = OHMUL;
3630                 if(m.ua) {
3631                         // Select a Go type with (at least) twice the width.
3632                         switch(simtype[nl->type->etype]) {
3633                         default:
3634                                 return;
3635                         case TUINT8:
3636                         case TUINT16:
3637                                 twide = types[TUINT32];
3638                                 break;
3639                         case TUINT32:
3640                                 twide = types[TUINT64];
3641                                 break;
3642                         case TINT8:
3643                         case TINT16:
3644                                 twide = types[TINT32];
3645                                 break;
3646                         case TINT32:
3647                                 twide = types[TINT64];
3648                                 break;
3649                         }
3650
3651                         // add numerator (might overflow).
3652                         // n2 = (n1 + nl)
3653                         n2 = nod(OADD, conv(n1, twide), conv(nl, twide));
3654
3655                         // shift by m.s
3656                         nc = nod(OXXX, N, N);
3657                         nodconst(nc, types[TUINT], m.s);
3658                         n = conv(nod(ORSH, n2, nc), nl->type);
3659                 } else {
3660                         // n = n1 >> m.s
3661                         nc = nod(OXXX, N, N);
3662                         nodconst(nc, types[TUINT], m.s);
3663                         n = nod(ORSH, n1, nc);
3664                 }
3665                 break;
3666
3667         case TINT8:
3668         case TINT16:
3669         case TINT32:
3670                 // n1 = nl * magic >> w
3671                 nc = nod(OXXX, N, N);
3672                 nodconst(nc, nl->type, m.sm);
3673                 n1 = nod(OMUL, nl, nc);
3674                 typecheck(&n1, Erv);
3675                 n1->op = OHMUL;
3676                 if(m.sm < 0) {
3677                         // add the numerator.
3678                         n1 = nod(OADD, n1, nl);
3679                 }
3680                 // shift by m.s
3681                 nc = nod(OXXX, N, N);
3682                 nodconst(nc, types[TUINT], m.s);
3683                 n2 = conv(nod(ORSH, n1, nc), nl->type);
3684                 // add 1 iff n1 is negative.
3685                 nc = nod(OXXX, N, N);
3686                 nodconst(nc, types[TUINT], w-1);
3687                 n3 = nod(ORSH, nl, nc); // n4 = -1 iff n1 is negative.
3688                 n = nod(OSUB, n2, n3);
3689                 // apply sign.
3690                 if(m.sd < 0)
3691                         n = nod(OMINUS, n, N);
3692                 break;
3693         }
3694         goto ret;
3695
3696 longmod:
3697         // rewrite as A%B = A - (A/B*B).
3698         n1 = nod(ODIV, nl, nr);
3699         n2 = nod(OMUL, n1, nr);
3700         n = nod(OSUB, nl, n2);
3701         goto ret;
3702
3703 ret:
3704         typecheck(&n, Erv);
3705         walkexpr(&n, init);
3706         *np = n;
3707 }
3708
3709 // return 1 if integer n must be in range [0, max), 0 otherwise
3710 static int
3711 bounded(Node *n, int64 max)
3712 {
3713         int64 v;
3714         int32 bits;
3715         int sign;
3716
3717         if(n->type == T || !isint[n->type->etype])
3718                 return 0;
3719
3720         sign = issigned[n->type->etype];
3721         bits = 8*n->type->width;
3722
3723         if(smallintconst(n)) {
3724                 v = mpgetfix(n->val.u.xval);
3725                 return 0 <= v && v < max;
3726         }
3727
3728         switch(n->op) {
3729         case OAND:
3730                 v = -1;
3731                 if(smallintconst(n->left)) {
3732                         v = mpgetfix(n->left->val.u.xval);
3733                 } else if(smallintconst(n->right)) {
3734                         v = mpgetfix(n->right->val.u.xval);
3735                 }
3736                 if(0 <= v && v < max)
3737                         return 1;
3738                 break;
3739
3740         case OMOD:
3741                 if(!sign && smallintconst(n->right)) {
3742                         v = mpgetfix(n->right->val.u.xval);
3743                         if(0 <= v && v <= max)
3744                                 return 1;
3745                 }
3746                 break;
3747         
3748         case ODIV:
3749                 if(!sign && smallintconst(n->right)) {
3750                         v = mpgetfix(n->right->val.u.xval);
3751                         while(bits > 0 && v >= 2) {
3752                                 bits--;
3753                                 v >>= 1;
3754                         }
3755                 }
3756                 break;
3757         
3758         case ORSH:
3759                 if(!sign && smallintconst(n->right)) {
3760                         v = mpgetfix(n->right->val.u.xval);
3761                         if(v > bits)
3762                                 return 1;
3763                         bits -= v;
3764                 }
3765                 break;
3766         }
3767         
3768         if(!sign && bits <= 62 && (1LL<<bits) <= max)
3769                 return 1;
3770         
3771         return 0;
3772 }
3773
3774 void
3775 usefield(Node *n)
3776 {
3777         Type *field, *l;
3778
3779         if(!fieldtrack_enabled)
3780                 return;
3781
3782         switch(n->op) {
3783         default:
3784                 fatal("usefield %O", n->op);
3785         case ODOT:
3786         case ODOTPTR:
3787                 break;
3788         }
3789         
3790         field = n->paramfld;
3791         if(field == T)
3792                 fatal("usefield %T %S without paramfld", n->left->type, n->right->sym);
3793         if(field->note == nil || strstr(field->note->s, "go:\"track\"") == nil)
3794                 return;
3795
3796         // dedup on list
3797         if(field->lastfn == curfn)
3798                 return;
3799         field->lastfn = curfn;
3800         field->outer = n->left->type;
3801         if(isptr[field->outer->etype])
3802                 field->outer = field->outer->type;
3803         if(field->outer->sym == S)
3804                 yyerror("tracked field must be in named struct type");
3805         if(!exportname(field->sym->name))
3806                 yyerror("tracked field must be exported (upper case)");
3807
3808         l = typ(0);
3809         l->type = field;
3810         l->down = curfn->paramfld;
3811         curfn->paramfld = l;
3812 }
3813
3814 static int
3815 candiscardlist(NodeList *l)
3816 {
3817         for(; l; l=l->next)
3818                 if(!candiscard(l->n))
3819                         return 0;
3820         return 1;
3821 }
3822
3823 int
3824 candiscard(Node *n)
3825 {
3826         if(n == N)
3827                 return 1;
3828         
3829         switch(n->op) {
3830         default:
3831                 return 0;
3832
3833         case ONAME:
3834         case ONONAME:
3835         case OTYPE:
3836         case OPACK:
3837         case OLITERAL:
3838         case OADD:
3839         case OSUB:
3840         case OOR:
3841         case OXOR:
3842         case OADDSTR:
3843         case OADDR:
3844         case OANDAND:
3845         case OARRAYBYTESTR:
3846         case OARRAYRUNESTR:
3847         case OSTRARRAYBYTE:
3848         case OSTRARRAYRUNE:
3849         case OCAP:
3850         case OCMPIFACE:
3851         case OCMPSTR:
3852         case OCOMPLIT:
3853         case OMAPLIT:
3854         case OSTRUCTLIT:
3855         case OARRAYLIT:
3856         case OPTRLIT:
3857         case OCONV:
3858         case OCONVIFACE:
3859         case OCONVNOP:
3860         case ODOT:
3861         case OEQ:
3862         case ONE:
3863         case OLT:
3864         case OLE:
3865         case OGT:
3866         case OGE:
3867         case OKEY:
3868         case OLEN:
3869         case OMUL:
3870         case OLSH:
3871         case ORSH:
3872         case OAND:
3873         case OANDNOT:
3874         case ONEW:
3875         case ONOT:
3876         case OCOM:
3877         case OPLUS:
3878         case OMINUS:
3879         case OOROR:
3880         case OPAREN:
3881         case ORUNESTR:
3882         case OREAL:
3883         case OIMAG:
3884         case OCOMPLEX:
3885                 // Discardable as long as the subpieces are.
3886                 break;
3887
3888         case ODIV:
3889         case OMOD:
3890                 // Discardable as long as we know it's not division by zero.
3891                 if(isconst(n->right, CTINT) && mpcmpfixc(n->right->val.u.xval, 0) != 0)
3892                         break;
3893                 if(isconst(n->right, CTFLT) && mpcmpfltc(n->right->val.u.fval, 0) != 0)
3894                         break;
3895                 return 0;
3896
3897         case OMAKECHAN:
3898         case OMAKEMAP:
3899                 // Discardable as long as we know it won't fail because of a bad size.
3900                 if(isconst(n->left, CTINT) && mpcmpfixc(n->left->val.u.xval, 0) == 0)
3901                         break;
3902                 return 0;
3903         
3904         case OMAKESLICE:
3905                 // Difficult to tell what sizes are okay.
3906                 return 0;               
3907         }
3908         
3909         if(!candiscard(n->left) ||
3910            !candiscard(n->right) ||
3911            !candiscard(n->ntest) ||
3912            !candiscard(n->nincr) ||
3913            !candiscardlist(n->ninit) ||
3914            !candiscardlist(n->nbody) ||
3915            !candiscardlist(n->nelse) ||
3916            !candiscardlist(n->list) ||
3917            !candiscardlist(n->rlist)) {
3918                 return 0;
3919         }
3920         
3921         return 1;
3922 }
3923
3924 // rewrite
3925 //      print(x, y, z)
3926 // into
3927 //      func(a1, a2, a3) {
3928 //              print(a1, a2, a3)
3929 //      }(x, y, z)
3930 // and same for println.
3931 static void
3932 walkprintfunc(Node **np, NodeList **init)
3933 {
3934         Node *n;
3935         Node *a, *fn, *t, *oldfn;
3936         NodeList *l, *printargs;
3937         int num;
3938         char buf[100];
3939         static int prgen;
3940         
3941         n = *np;
3942
3943         if(n->ninit != nil) {
3944                 walkstmtlist(n->ninit);
3945                 *init = concat(*init, n->ninit);
3946                 n->ninit = nil;
3947         }
3948
3949         t = nod(OTFUNC, N, N);
3950         num = 0;
3951         printargs = nil;
3952         for(l=n->list; l != nil; l=l->next) {
3953                 snprint(buf, sizeof buf, "a%d", num++);
3954                 a = nod(ODCLFIELD, newname(lookup(buf)), typenod(l->n->type));
3955                 t->list = list(t->list, a);
3956                 printargs = list(printargs, a->left);
3957         }
3958
3959         fn = nod(ODCLFUNC, N, N);
3960         snprint(buf, sizeof buf, "print·%d", ++prgen);
3961         fn->nname = newname(lookup(buf));
3962         fn->nname->defn = fn;
3963         fn->nname->ntype = t;
3964         declare(fn->nname, PFUNC);
3965
3966         oldfn = curfn;
3967         curfn = nil;
3968         funchdr(fn);
3969         
3970         a = nod(n->op, N, N);
3971         a->list = printargs;
3972         typecheck(&a, Etop);
3973         walkstmt(&a);
3974         
3975         fn->nbody = list1(a);
3976
3977         funcbody(fn);
3978         
3979         typecheck(&fn, Etop);
3980         typechecklist(fn->nbody, Etop);
3981         xtop = list(xtop, fn);
3982         curfn = oldfn;
3983
3984         a = nod(OCALL, N, N);
3985         a->left = fn->nname;
3986         a->list = n->list;
3987         typecheck(&a, Etop);
3988         walkexpr(&a, init);
3989         *np = a;
3990 }