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 "go.h"
6
7 static Node* walkprint(Node*, NodeList**, int);
8 static Node* conv(Node*, Type*);
9 static Node* mapfn(char*, Type*);
10 static Node* makenewvar(Type*, NodeList**, Node**);
11 static Node* ascompatee1(int, Node*, Node*, NodeList**);
12 static NodeList* ascompatee(int, NodeList*, NodeList*, NodeList**);
13 static NodeList* ascompatet(int, NodeList*, Type**, int, NodeList**);
14 static NodeList* ascompatte(int, int, Type**, NodeList*, int, NodeList**);
15 static Node* convas(Node*, NodeList**);
16 static void heapmoves(void);
17 static NodeList* paramstoheap(Type **argin, int out);
18 static NodeList* reorder1(NodeList*);
19 static NodeList* reorder3(NodeList*);
20 static Node* addstr(Node*, NodeList**);
21 static Node* appendslice(Node*, NodeList**);
22 static Node* append(Node*, NodeList**);
23
24 // can this code branch reach the end
25 // without an unconditional RETURN
26 // this is hard, so it is conservative
27 static int
28 walkret(NodeList *l)
29 {
30 Node *n;
31
32 loop:
33 while(l && l->next)
34 l = l->next;
35 if(l == nil)
36 return 1;
37
38 // at this point, we have the last
39 // statement of the function
40 n = l->n;
41 switch(n->op) {
42 case OBLOCK:
43 l = n->list;
44 goto loop;
45
46 case OGOTO:
47 case ORETURN:
48 case OPANIC:
49 return 0;
50 break;
51 }
52
53 // all other statements
54 // will flow to the end
55 return 1;
56 }
57
58 void
59 walk(Node *fn)
60 {
61 char s[50];
62 NodeList *l;
63 Node *n;
64 int lno;
65
66 curfn = fn;
67
68 if(debug['W']) {
69 snprint(s, sizeof(s), "\nbefore %S", curfn->nname->sym);
70 dumplist(s, curfn->nbody);
71 }
72 if(curfn->type->outtuple)
73 if(walkret(curfn->nbody))
74 yyerror("function ends without a return statement");
75
76 lno = lineno;
77 for(l=fn->dcl; l; l=l->next) {
78 n = l->n;
79 if(n->op != ONAME || n->class != PAUTO)
80 continue;
81 lineno = n->lineno;
82 typecheck(&n, Erv | Easgn); // only needed for unused variables
83 if(!n->used && n->sym->name[0] != '&' && !nsyntaxerrors)
84 yyerror("%S declared and not used", n->sym);
85 }
86 lineno = lno;
87 if(nerrors != 0)
88 return;
89 walkstmtlist(curfn->nbody);
90 if(debug['W']) {
91 snprint(s, sizeof(s), "after walk %S", curfn->nname->sym);
92 dumplist(s, curfn->nbody);
93 }
94 heapmoves();
95 if(debug['W'] && curfn->enter != nil) {
96 snprint(s, sizeof(s), "enter %S", curfn->nname->sym);
97 dumplist(s, curfn->enter);
98 }
99 }
100
101
102 void
103 walkstmtlist(NodeList *l)
104 {
105 for(; l; l=l->next)
106 walkstmt(&l->n);
107 }
108
109 static int
110 samelist(NodeList *a, NodeList *b)
111 {
112 for(; a && b; a=a->next, b=b->next)
113 if(a->n != b->n)
114 return 0;
115 return a == b;
116 }
117
118 static int
119 paramoutheap(Node *fn)
120 {
121 NodeList *l;
122
123 for(l=fn->dcl; l; l=l->next) {
124 switch(l->n->class) {
125 case PPARAMOUT|PHEAP:
126 return 1;
127 case PAUTO:
128 case PAUTO|PHEAP:
129 // stop early - parameters are over
130 return 0;
131 }
132 }
133 return 0;
134 }
135
136 void
137 walkstmt(Node **np)
138 {
139 NodeList *init;
140 NodeList *ll, *rl;
141 int cl;
142 Node *n, *f;
143
144 n = *np;
145 if(n == N)
146 return;
147
148 setlineno(n);
149
150 switch(n->op) {
151 default:
152 if(n->op == ONAME)
153 yyerror("%S is not a top level statement", n->sym);
154 else
155 yyerror("%O is not a top level statement", n->op);
156 dump("nottop", n);
157 break;
158
159 case OASOP:
160 case OAS:
161 case OAS2:
162 case OAS2DOTTYPE:
163 case OAS2RECV:
164 case OAS2FUNC:
165 case OAS2MAPW:
166 case OAS2MAPR:
167 case OCLOSE:
168 case OCOPY:
169 case OCALLMETH:
170 case OCALLINTER:
171 case OCALL:
172 case OCALLFUNC:
173 case OSEND:
174 case ORECV:
175 case OPRINT:
176 case OPRINTN:
177 case OPANIC:
178 case OEMPTY:
179 case ORECOVER:
180 if(n->typecheck == 0) {
181 dump("missing typecheck:", n);
182 fatal("missing typecheck");
183 }
184 init = n->ninit;
185 n->ninit = nil;
186 walkexpr(&n, &init);
187 n->ninit = concat(init, n->ninit);
188 break;
189
190 case OBREAK:
191 case ODCL:
192 case OCONTINUE:
193 case OFALL:
194 case OGOTO:
195 case OLABEL:
196 case ODCLCONST:
197 case ODCLTYPE:
198 break;
199
200 case OBLOCK:
201 walkstmtlist(n->list);
202 break;
203
204 case OXCASE:
205 yyerror("case statement out of place");
206 n->op = OCASE;
207 case OCASE:
208 walkstmt(&n->right);
209 break;
210
211 case ODEFER:
212 hasdefer = 1;
213 switch(n->left->op) {
214 case OPRINT:
215 case OPRINTN:
216 walkexprlist(n->left->list, &n->ninit);
217 n->left = walkprint(n->left, &n->ninit, 1);
218 break;
219 default:
220 walkexpr(&n->left, &n->ninit);
221 break;
222 }
223 break;
224
225 case OFOR:
226 walkstmtlist(n->ninit);
227 if(n->ntest != N) {
228 walkstmtlist(n->ntest->ninit);
229 init = n->ntest->ninit;
230 n->ntest->ninit = nil;
231 walkexpr(&n->ntest, &init);
232 n->ntest->ninit = concat(init, n->ntest->ninit);
233 }
234 walkstmt(&n->nincr);
235 walkstmtlist(n->nbody);
236 break;
237
238 case OIF:
239 walkstmtlist(n->ninit);
240 walkexpr(&n->ntest, &n->ninit);
241 walkstmtlist(n->nbody);
242 walkstmtlist(n->nelse);
243 break;
244
245 case OPROC:
246 switch(n->left->op) {
247 case OPRINT:
248 case OPRINTN:
249 walkexprlist(n->left->list, &n->ninit);
250 n->left = walkprint(n->left, &n->ninit, 1);
251 break;
252 default:
253 walkexpr(&n->left, &n->ninit);
254 break;
255 }
256 break;
257
258 case ORETURN:
259 walkexprlist(n->list, &n->ninit);
260 if(n->list == nil)
261 break;
262 if((curfn->type->outnamed && count(n->list) > 1) || paramoutheap(curfn)) {
263 // assign to the function out parameters,
264 // so that reorder3 can fix up conflicts
265 rl = nil;
266 for(ll=curfn->dcl; ll != nil; ll=ll->next) {
267 cl = ll->n->class & ~PHEAP;
268 if(cl == PAUTO)
269 break;
270 if(cl == PPARAMOUT)
271 rl = list(rl, ll->n);
272 }
273 if(samelist(rl, n->list)) {
274 // special return in disguise
275 n->list = nil;
276 break;
277 }
278 if(count(n->list) == 1 && count(rl) > 1) {
279 // OAS2FUNC in disguise
280 f = n->list->n;
281 if(f->op != OCALLFUNC && f->op != OCALLMETH && f->op != OCALLINTER)
282 fatal("expected return of call, have %#N", f);
283 n->list = concat(list1(f), ascompatet(n->op, rl, &f->type, 0, &n->ninit));
284 break;
285 }
286 ll = ascompatee(n->op, rl, n->list, &n->ninit);
287 n->list = reorder3(ll);
288 break;
289 }
290 ll = ascompatte(n->op, 0, getoutarg(curfn->type), n->list, 1, &n->ninit);
291 n->list = ll;
292 break;
293
294 case OSELECT:
295 walkselect(n);
296 break;
297
298 case OSWITCH:
299 walkswitch(n);
300 break;
301
302 case ORANGE:
303 walkrange(n);
304 break;
305
306 case OXFALL:
307 yyerror("fallthrough statement out of place");
308 n->op = OFALL;
309 break;
310 }
311
312 *np = n;
313 }
314
315
316 /*
317 * walk the whole tree of the body of an
318 * expression or simple statement.
319 * the types expressions are calculated.
320 * compile-time constants are evaluated.
321 * complex side effects like statements are appended to init
322 */
323
324 void
325 walkexprlist(NodeList *l, NodeList **init)
326 {
327 for(; l; l=l->next)
328 walkexpr(&l->n, init);
329 }
330
331 void
332 walkexprlistsafe(NodeList *l, NodeList **init)
333 {
334 for(; l; l=l->next) {
335 l->n = safeexpr(l->n, init);
336 walkexpr(&l->n, init);
337 }
338 }
339
340 void
341 walkexpr(Node **np, NodeList **init)
342 {
343 Node *r, *l, *var, *a;
344 NodeList *ll, *lr, *lpost;
345 Type *t;
346 int et;
347 int64 v, v1, v2, len;
348 int32 lno;
349 Node *n, *fn;
350 char buf[100], *p;
351
352 n = *np;
353
354 if(n == N)
355 return;
356
357 if(init == &n->ninit) {
358 // not okay to use n->ninit when walking n,
359 // because we might replace n with some other node
360 // and would lose the init list.
361 fatal("walkexpr init == &n->ninit");
362 }
363
364 // annoying case - not typechecked
365 if(n->op == OKEY) {
366 walkexpr(&n->left, init);
367 walkexpr(&n->right, init);
368 return;
369 }
370
371 lno = setlineno(n);
372
373 if(debug['w'] > 1)
374 dump("walk-before", n);
375
376 if(n->typecheck != 1) {
377 dump("missed typecheck", n);
378 fatal("missed typecheck");
379 }
380
381 t = T;
382 et = Txxx;
383
384 switch(n->op) {
385 default:
386 dump("walk", n);
387 fatal("walkexpr: switch 1 unknown op %N", n);
388 goto ret;
389
390 case OTYPE:
391 case ONONAME:
392 case OINDREG:
393 case OEMPTY:
394 goto ret;
395
396 case ONOT:
397 case OMINUS:
398 case OPLUS:
399 case OCOM:
400 case OREAL:
401 case OIMAG:
402 case ODOT:
403 case ODOTPTR:
404 case ODOTMETH:
405 case ODOTINTER:
406 case OIND:
407 walkexpr(&n->left, init);
408 goto ret;
409
410 case OLEN:
411 case OCAP:
412 walkexpr(&n->left, init);
413
414 // replace len(*[10]int) with 10.
415 // delayed until now to preserve side effects.
416 t = n->left->type;
417 if(isptr[t->etype])
418 t = t->type;
419 if(isfixedarray(t)) {
420 safeexpr(n->left, init);
421 nodconst(n, n->type, t->bound);
422 n->typecheck = 1;
423 }
424 goto ret;
425
426 case OLSH:
427 case ORSH:
428 case OAND:
429 case OOR:
430 case OXOR:
431 case OSUB:
432 case OMUL:
433 case OEQ:
434 case ONE:
435 case OLT:
436 case OLE:
437 case OGE:
438 case OGT:
439 case OADD:
440 case OCOMPLEX:
441 walkexpr(&n->left, init);
442 walkexpr(&n->right, init);
443 goto ret;
444
445 case OANDAND:
446 case OOROR:
447 walkexpr(&n->left, init);
448 // cannot put side effects from n->right on init,
449 // because they cannot run before n->left is checked.
450 // save elsewhere and store on the eventual n->right.
451 ll = nil;
452 walkexpr(&n->right, &ll);
453 n->right->ninit = concat(n->right->ninit, ll);
454 goto ret;
455
456 case OPRINT:
457 case OPRINTN:
458 walkexprlist(n->list, init);
459 n = walkprint(n, init, 0);
460 goto ret;
461
462 case OPANIC:
463 n = mkcall("panic", T, init, n->left);
464 goto ret;
465
466 case ORECOVER:
467 n = mkcall("recover", n->type, init, nod(OADDR, nodfp, N));
468 goto ret;
469
470 case OLITERAL:
471 n->addable = 1;
472 goto ret;
473
474 case ONAME:
475 if(!(n->class & PHEAP) && n->class != PPARAMREF)
476 n->addable = 1;
477 goto ret;
478
479 case OCALLINTER:
480 t = n->left->type;
481 if(n->list && n->list->n->op == OAS)
482 goto ret;
483 walkexpr(&n->left, init);
484 walkexprlist(n->list, init);
485 ll = ascompatte(n->op, n->isddd, getinarg(t), n->list, 0, init);
486 n->list = reorder1(ll);
487 goto ret;
488
489 case OCALLFUNC:
490 t = n->left->type;
491 if(n->list && n->list->n->op == OAS)
492 goto ret;
493
494 if(n->left->op == OCLOSURE) {
495 walkcallclosure(n, init);
496 t = n->left->type;
497 }
498
499 walkexpr(&n->left, init);
500 walkexprlist(n->list, init);
501
502 ll = ascompatte(n->op, n->isddd, getinarg(t), n->list, 0, init);
503 n->list = reorder1(ll);
504 goto ret;
505
506 case OCALLMETH:
507 t = n->left->type;
508 if(n->list && n->list->n->op == OAS)
509 goto ret;
510 walkexpr(&n->left, init);
511 walkexprlist(n->list, init);
512 ll = ascompatte(n->op, 0, getthis(t), list1(n->left->left), 0, init);
513 lr = ascompatte(n->op, n->isddd, getinarg(t), n->list, 0, init);
514 ll = concat(ll, lr);
515 n->left->left = N;
516 ullmancalc(n->left);
517 n->list = reorder1(ll);
518 goto ret;
519
520 case OAS:
521 *init = concat(*init, n->ninit);
522 n->ninit = nil;
523 walkexpr(&n->left, init);
524 n->left = safeexpr(n->left, init);
525
526 if(oaslit(n, init))
527 goto ret;
528
529 walkexpr(&n->right, init);
530 if(n->left != N && n->right != N) {
531 r = convas(nod(OAS, n->left, n->right), init);
532 r->dodata = n->dodata;
533 n = r;
534 }
535
536 goto ret;
537
538 case OAS2:
539 *init = concat(*init, n->ninit);
540 n->ninit = nil;
541 walkexprlistsafe(n->list, init);
542 walkexprlistsafe(n->rlist, init);
543 ll = ascompatee(OAS, n->list, n->rlist, init);
544 ll = reorder3(ll);
545 n = liststmt(ll);
546 goto ret;
547
548 case OAS2FUNC:
549 as2func:
550 // a,b,... = fn()
551 *init = concat(*init, n->ninit);
552 n->ninit = nil;
553 r = n->rlist->n;
554 walkexprlistsafe(n->list, init);
555 walkexpr(&r, init);
556 l = n->list->n;
557
558 // all the really hard stuff - explicit function calls and so on -
559 // is gone, but map assignments remain.
560 // if there are map assignments here, assign via
561 // temporaries, because ascompatet assumes
562 // the targets can be addressed without function calls
563 // and map index has an implicit one.
564 lpost = nil;
565 if(l->op == OINDEXMAP) {
566 var = nod(OXXX, N, N);
567 tempname(var, l->type);
568 n->list->n = var;
569 a = nod(OAS, l, var);
570 typecheck(&a, Etop);
571 lpost = list(lpost, a);
572 }
573 l = n->list->next->n;
574 if(l->op == OINDEXMAP) {
575 var = nod(OXXX, N, N);
576 tempname(var, l->type);
577 n->list->next->n = var;
578 a = nod(OAS, l, var);
579 typecheck(&a, Etop);
580 lpost = list(lpost, a);
581 }
582 ll = ascompatet(n->op, n->list, &r->type, 0, init);
583 walkexprlist(lpost, init);
584 n = liststmt(concat(concat(list1(r), ll), lpost));
585 goto ret;
586
587 case OAS2RECV:
588 *init = concat(*init, n->ninit);
589 n->ninit = nil;
590 r = n->rlist->n;
591 walkexprlistsafe(n->list, init);
592 walkexpr(&r->left, init);
593 fn = chanfn("chanrecv2", 2, r->left->type);
594 r = mkcall1(fn, getoutargx(fn->type), init, typename(r->left->type), r->left);
595 n->rlist->n = r;
596 n->op = OAS2FUNC;
597 goto as2func;
598
599 case OAS2MAPR:
600 // a,b = m[i];
601 *init = concat(*init, n->ninit);
602 n->ninit = nil;
603 r = n->rlist->n;
604 walkexprlistsafe(n->list, init);
605 walkexpr(&r->left, init);
606 fn = mapfn("mapaccess2", r->left->type);
607 r = mkcall1(fn, getoutargx(fn->type), init, typename(r->left->type), r->left, r->right);
608 n->rlist = list1(r);
609 n->op = OAS2FUNC;
610 goto as2func;
611
612 case OAS2MAPW:
613 // map[] = a,b - mapassign2
614 // a,b = m[i];
615 *init = concat(*init, n->ninit);
616 n->ninit = nil;
617 walkexprlistsafe(n->list, init);
618 l = n->list->n;
619 t = l->left->type;
620 n = mkcall1(mapfn("mapassign2", t), T, init, typename(t), l->left, l->right, n->rlist->n, n->rlist->next->n);
621 goto ret;
622
623 case OAS2DOTTYPE:
624 // a,b = i.(T)
625 *init = concat(*init, n->ninit);
626 n->ninit = nil;
627 r = n->rlist->n;
628 walkexprlistsafe(n->list, init);
629 r->op = ODOTTYPE2;
630 walkexpr(&r, init);
631 ll = ascompatet(n->op, n->list, &r->type, 0, init);
632 n = liststmt(concat(list1(r), ll));
633 goto ret;
634
635 case ODOTTYPE:
636 case ODOTTYPE2:
637 // Build name of function: assertI2E2 etc.
638 strcpy(buf, "assert");
639 p = buf+strlen(buf);
640 if(isnilinter(n->left->type))
641 *p++ = 'E';
642 else
643 *p++ = 'I';
644 *p++ = '2';
645 if(isnilinter(n->type))
646 *p++ = 'E';
647 else if(isinter(n->type))
648 *p++ = 'I';
649 else
650 *p++ = 'T';
651 if(n->op == ODOTTYPE2)
652 *p++ = '2';
653 *p = '\0';
654
655 fn = syslook(buf, 1);
656 ll = list1(typename(n->type));
657 ll = list(ll, n->left);
658 argtype(fn, n->left->type);
659 argtype(fn, n->type);
660 n = nod(OCALL, fn, N);
661 n->list = ll;
662 typecheck(&n, Erv | Efnstruct);
663 walkexpr(&n, init);
664 goto ret;
665
666 case OCONVIFACE:
667 // Build name of function: convI2E etc.
668 // Not all names are possible
669 // (e.g., we'll never generate convE2E or convE2I).
670 walkexpr(&n->left, init);
671 strcpy(buf, "conv");
672 p = buf+strlen(buf);
673 if(isnilinter(n->left->type))
674 *p++ = 'E';
675 else if(isinter(n->left->type))
676 *p++ = 'I';
677 else
678 *p++ = 'T';
679 *p++ = '2';
680 if(isnilinter(n->type))
681 *p++ = 'E';
682 else
683 *p++ = 'I';
684 *p = '\0';
685
686 fn = syslook(buf, 1);
687 ll = nil;
688 if(!isinter(n->left->type))
689 ll = list(ll, typename(n->left->type));
690 if(!isnilinter(n->type))
691 ll = list(ll, typename(n->type));
692 ll = list(ll, n->left);
693 argtype(fn, n->left->type);
694 argtype(fn, n->type);
695 dowidth(fn->type);
696 n = nod(OCALL, fn, N);
697 n->list = ll;
698 typecheck(&n, Erv);
699 walkexpr(&n, init);
700 goto ret;
701
702 case OCONV:
703 case OCONVNOP:
704 if(thechar == '5') {
705 if(isfloat[n->left->type->etype]) {
706 if(n->type->etype == TINT64) {
707 n = mkcall("float64toint64", n->type, init, conv(n->left, types[TFLOAT64]));
708 goto ret;
709 }
710 if(n->type->etype == TUINT64) {
711 n = mkcall("float64touint64", n->type, init, conv(n->left, types[TFLOAT64]));
712 goto ret;
713 }
714 }
715 if(isfloat[n->type->etype]) {
716 if(n->left->type->etype == TINT64) {
717 n = mkcall("int64tofloat64", n->type, init, conv(n->left, types[TINT64]));
718 goto ret;
719 }
720 if(n->left->type->etype == TUINT64) {
721 n = mkcall("uint64tofloat64", n->type, init, conv(n->left, types[TUINT64]));
722 goto ret;
723 }
724 }
725 }
726 walkexpr(&n->left, init);
727 goto ret;
728
729 case OASOP:
730 if(n->etype == OANDNOT) {
731 n->etype = OAND;
732 n->right = nod(OCOM, n->right, N);
733 typecheck(&n->right, Erv);
734 }
735 n->left = safeexpr(n->left, init);
736 walkexpr(&n->left, init);
737 l = n->left;
738 walkexpr(&n->right, init);
739
740 /*
741 * on 32-bit arch, rewrite 64-bit ops into l = l op r.
742 * on 386, rewrite float ops into l = l op r.
743 * everywhere, rewrite map ops into l = l op r.
744 * everywhere, rewrite string += into l = l op r.
745 * everywhere, rewrite complex /= into l = l op r.
746 * TODO(rsc): Maybe this rewrite should be done always?
747 */
748 et = n->left->type->etype;
749 if((widthptr == 4 && (et == TUINT64 || et == TINT64)) ||
750 (thechar == '8' && isfloat[et]) ||
751 l->op == OINDEXMAP ||
752 et == TSTRING ||
753 (iscomplex[et] && n->etype == ODIV)) {
754 l = safeexpr(n->left, init);
755 a = l;
756 if(a->op == OINDEXMAP) {
757 // map index has "lhs" bit set in a->etype.
758 // make a copy so we can clear it on the rhs.
759 a = nod(OXXX, N, N);
760 *a = *l;
761 a->etype = 0;
762 }
763 r = nod(OAS, l, nod(n->etype, a, n->right));
764 typecheck(&r, Etop);
765 walkexpr(&r, init);
766 n = r;
767 }
768 goto ret;
769
770 case OANDNOT:
771 walkexpr(&n->left, init);
772 walkexpr(&n->right, init);
773 n->op = OAND;
774 n->right = nod(OCOM, n->right, N);
775 typecheck(&n->right, Erv);
776 goto ret;
777
778 case ODIV:
779 case OMOD:
780 walkexpr(&n->left, init);
781 walkexpr(&n->right, init);
782 /*
783 * rewrite complex div into function call.
784 */
785 et = n->left->type->etype;
786 if(iscomplex[et] && n->op == ODIV) {
787 t = n->type;
788 n = mkcall("complex128div", types[TCOMPLEX128], init,
789 conv(n->left, types[TCOMPLEX128]),
790 conv(n->right, types[TCOMPLEX128]));
791 n = conv(n, t);
792 goto ret;
793 }
794 /*
795 * rewrite div and mod into function calls
796 * on 32-bit architectures.
797 */
798 if(widthptr > 4 || (et != TUINT64 && et != TINT64))
799 goto ret;
800 if(et == TINT64)
801 strcpy(namebuf, "int64");
802 else
803 strcpy(namebuf, "uint64");
804 if(n->op == ODIV)
805 strcat(namebuf, "div");
806 else
807 strcat(namebuf, "mod");
808 n = mkcall(namebuf, n->type, init,
809 conv(n->left, types[et]), conv(n->right, types[et]));
810 goto ret;
811
812 case OINDEX:
813 walkexpr(&n->left, init);
814 walkexpr(&n->right, init);
815
816 // if range of type cannot exceed static array bound,
817 // disable bounds check
818 if(isfixedarray(n->left->type))
819 if(n->right->type->width < 4)
820 if((1<<(8*n->right->type->width)) <= n->left->type->bound)
821 n->etype = 1;
822
823 if(isconst(n->left, CTSTR))
824 if(n->right->type->width < 4)
825 if((1<<(8*n->right->type->width)) <= n->left->val.u.sval->len)
826 n->etype = 1;
827
828 // check for static out of bounds
829 if(isconst(n->right, CTINT) && !n->etype) {
830 v = mpgetfix(n->right->val.u.xval);
831 len = 1LL<<60;
832 t = n->left->type;
833 if(isconst(n->left, CTSTR))
834 len = n->left->val.u.sval->len;
835 if(t != T && isptr[t->etype])
836 t = t->type;
837 if(isfixedarray(t))
838 len = t->bound;
839 if(v < 0 || v >= (1LL<<31) || v >= len)
840 yyerror("index out of bounds");
841 else if(isconst(n->left, CTSTR)) {
842 // replace "abc"[2] with 'b'.
843 // delayed until now because "abc"[2] is not
844 // an ideal constant.
845 nodconst(n, n->type, n->left->val.u.sval->s[v]);
846 }
847 }
848 goto ret;
849
850 case OINDEXMAP:
851 if(n->etype == 1)
852 goto ret;
853
854 t = n->left->type;
855 n = mkcall1(mapfn("mapaccess1", t), t->type, init, typename(t), n->left, n->right);
856 goto ret;
857
858 case ORECV:
859 walkexpr(&n->left, init);
860 walkexpr(&n->right, init);
861 n = mkcall1(chanfn("chanrecv1", 2, n->left->type), n->type, init, typename(n->left->type), n->left);
862 goto ret;
863
864 case OSLICE:
865 case OSLICEARR:
866 walkexpr(&n->left, init);
867 n->left = safeexpr(n->left, init);
868 walkexpr(&n->right->left, init);
869 n->right->left = safeexpr(n->right->left, init);
870 walkexpr(&n->right->right, init);
871 n->right->right = safeexpr(n->right->right, init);
872
873 len = 1LL<<60;
874 t = n->left->type;
875 if(t != T && isptr[t->etype])
876 t = t->type;
877 if(isfixedarray(t))
878 len = t->bound;
879
880 // check for static out of bounds
881 // NOTE: v > len not v >= len.
882 v1 = -1;
883 v2 = -1;
884 if(isconst(n->right->left, CTINT)) {
885 v1 = mpgetfix(n->right->left->val.u.xval);
886 if(v1 < 0 || v1 >= (1LL<<31) || v1 > len) {
887 yyerror("slice index out of bounds");
888 v1 = -1;
889 }
890 }
891 if(isconst(n->right->right, CTINT)) {
892 v2 = mpgetfix(n->right->right->val.u.xval);
893 if(v2 < 0 || v2 >= (1LL<<31) || v2 > len) {
894 yyerror("slice index out of bounds");
895 v2 = -1;
896 }
897 }
898 if(v1 >= 0 && v2 >= 0 && v1 > v2)
899 yyerror("inverted slice range");
900
901 if(n->op == OSLICEARR)
902 goto slicearray;
903
904 // dynamic slice
905 // sliceslice(old []any, lb uint64, hb uint64, width uint64) (ary []any)
906 // sliceslice1(old []any, lb uint64, width uint64) (ary []any)
907 t = n->type;
908 et = n->etype;
909 if(n->right->left == N)
910 l = nodintconst(0);
911 else
912 l = conv(n->right->left, types[TUINT64]);
913 if(n->right->right != N) {
914 fn = syslook("sliceslice", 1);
915 argtype(fn, t->type); // any-1
916 argtype(fn, t->type); // any-2
917 n = mkcall1(fn, t, init,
918 n->left,
919 l,
920 conv(n->right->right, types[TUINT64]),
921 nodintconst(t->type->width));
922 } else {
923 fn = syslook("sliceslice1", 1);
924 argtype(fn, t->type); // any-1
925 argtype(fn, t->type); // any-2
926 n = mkcall1(fn, t, init,
927 n->left,
928 l,
929 nodintconst(t->type->width));
930 }
931 n->etype = et; // preserve no-typecheck flag from OSLICE to the slice* call.
932 goto ret;
933
934 slicearray:
935 // static slice
936 // slicearray(old *any, uint64 nel, lb uint64, hb uint64, width uint64) (ary []any)
937 t = n->type;
938 fn = syslook("slicearray", 1);
939 argtype(fn, n->left->type->type); // any-1
940 argtype(fn, t->type); // any-2
941 if(n->right->left == N)
942 l = nodintconst(0);
943 else
944 l = conv(n->right->left, types[TUINT64]);
945 if(n->right->right == N)
946 r = nodintconst(n->left->type->type->bound);
947 else
948 r = conv(n->right->right, types[TUINT64]);
949 n = mkcall1(fn, t, init,
950 n->left, nodintconst(n->left->type->type->bound),
951 l,
952 r,
953 nodintconst(t->type->width));
954 goto ret;
955
956 case OADDR:;
957 Node *nvar, *nstar;
958
959 // turn &Point(1, 2) or &[]int(1, 2) or &[...]int(1, 2) into allocation.
960 // initialize with
961 // nvar := new(*Point);
962 // *nvar = Point(1, 2);
963 // and replace expression with nvar
964 switch(n->left->op) {
965 case OARRAYLIT:
966 case OMAPLIT:
967 case OSTRUCTLIT:
968 nvar = makenewvar(n->type, init, &nstar);
969 anylit(0, n->left, nstar, init);
970 n = nvar;
971 goto ret;
972 }
973
974 walkexpr(&n->left, init);
975 goto ret;
976
977 case ONEW:
978 n = callnew(n->type->type);
979 goto ret;
980
981 case OCMPSTR:
982 // If one argument to the comparison is an empty string,
983 // comparing the lengths instead will yield the same result
984 // without the function call.
985 if((isconst(n->left, CTSTR) && n->left->val.u.sval->len == 0) ||
986 (isconst(n->right, CTSTR) && n->right->val.u.sval->len == 0)) {
987 r = nod(n->etype, nod(OLEN, n->left, N), nod(OLEN, n->right, N));
988 typecheck(&r, Erv);
989 walkexpr(&r, init);
990 n = r;
991 goto ret;
992 }
993
994 // s + "badgerbadgerbadger" == "badgerbadgerbadger"
995 if((n->etype == OEQ || n->etype == ONE) &&
996 isconst(n->right, CTSTR) &&
997 n->left->op == OADDSTR && isconst(n->left->right, CTSTR) &&
998 cmpslit(n->right, n->left->right) == 0) {
999 r = nod(n->etype, nod(OLEN, n->left->left, N), nodintconst(0));
1000 typecheck(&r, Erv);
1001 walkexpr(&r, init);
1002 n = r;
1003 goto ret;
1004 }
1005
1006 // prepare for rewrite below
1007 if(n->etype == OEQ || n->etype == ONE) {
1008 n->left = cheapexpr(n->left, init);
1009 n->right = cheapexpr(n->right, init);
1010 }
1011
1012 // sys_cmpstring(s1, s2) :: 0
1013 r = mkcall("cmpstring", types[TINT], init,
1014 conv(n->left, types[TSTRING]),
1015 conv(n->right, types[TSTRING]));
1016 r = nod(n->etype, r, nodintconst(0));
1017
1018 // quick check of len before full compare for == or !=
1019 if(n->etype == OEQ || n->etype == ONE) {
1020 if(n->etype == OEQ)
1021 r = nod(OANDAND, nod(OEQ, nod(OLEN, n->left, N), nod(OLEN, n->right, N)), r);
1022 else
1023 r = nod(OOROR, nod(ONE, nod(OLEN, n->left, N), nod(OLEN, n->right, N)), r);
1024 typecheck(&r, Erv);
1025 walkexpr(&r, nil);
1026 }
1027 typecheck(&r, Erv);
1028 n = r;
1029 goto ret;
1030
1031 case OADDSTR:
1032 n = addstr(n, init);
1033 goto ret;
1034
1035 case OSLICESTR:
1036 // sys_slicestring(s, lb, hb)
1037 if(n->right->left == N)
1038 l = nodintconst(0);
1039 else
1040 l = conv(n->right->left, types[TINT]);
1041 if(n->right->right) {
1042 n = mkcall("slicestring", n->type, init,
1043 conv(n->left, types[TSTRING]),
1044 l,
1045 conv(n->right->right, types[TINT]));
1046 } else {
1047 n = mkcall("slicestring1", n->type, init,
1048 conv(n->left, types[TSTRING]),
1049 l);
1050 }
1051 goto ret;
1052
1053 case OAPPEND:
1054 if(n->isddd)
1055 n = appendslice(n, init);
1056 else
1057 n = append(n, init);
1058 goto ret;
1059
1060 case OCOPY:
1061 if(n->right->type->etype == TSTRING)
1062 fn = syslook("slicestringcopy", 1);
1063 else
1064 fn = syslook("slicecopy", 1);
1065 argtype(fn, n->left->type);
1066 argtype(fn, n->right->type);
1067 n = mkcall1(fn, n->type, init,
1068 n->left, n->right,
1069 nodintconst(n->left->type->type->width));
1070 goto ret;
1071
1072 case OCLOSE:
1073 // cannot use chanfn - closechan takes any, not chan any
1074 fn = syslook("closechan", 1);
1075 argtype(fn, n->left->type);
1076 n = mkcall1(fn, T, init, n->left);
1077 goto ret;
1078
1079 case OMAKECHAN:
1080 n = mkcall1(chanfn("makechan", 1, n->type), n->type, init,
1081 typename(n->type),
1082 conv(n->left, types[TINT64]));
1083 goto ret;
1084
1085 case OMAKEMAP:
1086 t = n->type;
1087
1088 fn = syslook("makemap", 1);
1089 argtype(fn, t->down); // any-1
1090 argtype(fn, t->type); // any-2
1091
1092 n = mkcall1(fn, n->type, init,
1093 typename(n->type),
1094 conv(n->left, types[TINT64]));
1095 goto ret;
1096
1097 case OMAKESLICE:
1098 // makeslice(t *Type, nel int64, max int64) (ary []any)
1099 l = n->left;
1100 r = n->right;
1101 if(r == nil)
1102 l = r = safeexpr(l, init);
1103 t = n->type;
1104 fn = syslook("makeslice", 1);
1105 argtype(fn, t->type); // any-1
1106 n = mkcall1(fn, n->type, init,
1107 typename(n->type),
1108 conv(l, types[TINT64]),
1109 conv(r, types[TINT64]));
1110 goto ret;
1111
1112 case ORUNESTR:
1113 // sys_intstring(v)
1114 n = mkcall("intstring", n->type, init,
1115 conv(n->left, types[TINT64]));
1116 goto ret;
1117
1118 case OARRAYBYTESTR:
1119 // slicebytetostring([]byte) string;
1120 n = mkcall("slicebytetostring", n->type, init, n->left);
1121 goto ret;
1122
1123 case OARRAYRUNESTR:
1124 // sliceinttostring([]int) string;
1125 n = mkcall("sliceinttostring", n->type, init, n->left);
1126 goto ret;
1127
1128 case OSTRARRAYBYTE:
1129 // stringtoslicebyte(string) []byte;
1130 n = mkcall("stringtoslicebyte", n->type, init, conv(n->left, types[TSTRING]));
1131 goto ret;
1132
1133 case OSTRARRAYRUNE:
1134 // stringtosliceint(string) []int
1135 n = mkcall("stringtosliceint", n->type, init, n->left);
1136 goto ret;
1137
1138 case OCMPIFACE:
1139 // ifaceeq(i1 any-1, i2 any-2) (ret bool);
1140 if(!eqtype(n->left->type, n->right->type))
1141 fatal("ifaceeq %O %T %T", n->op, n->left->type, n->right->type);
1142 if(isnilinter(n->left->type))
1143 fn = syslook("efaceeq", 1);
1144 else
1145 fn = syslook("ifaceeq", 1);
1146 argtype(fn, n->right->type);
1147 argtype(fn, n->left->type);
1148 r = mkcall1(fn, n->type, init, n->left, n->right);
1149 if(n->etype == ONE) {
1150 r = nod(ONOT, r, N);
1151 typecheck(&r, Erv);
1152 }
1153 n = r;
1154 goto ret;
1155
1156 case OARRAYLIT:
1157 case OMAPLIT:
1158 case OSTRUCTLIT:
1159 nvar = nod(OXXX, N, N);
1160 tempname(nvar, n->type);
1161 anylit(0, n, nvar, init);
1162 n = nvar;
1163 goto ret;
1164
1165 case OSEND:
1166 n = mkcall1(chanfn("chansend1", 2, n->left->type), T, init, typename(n->left->type), n->left, n->right);
1167 goto ret;
1168
1169 case OCLOSURE:
1170 n = walkclosure(n, init);
1171 goto ret;
1172 }
1173 fatal("missing switch %O", n->op);
1174
1175 ret:
1176 if(debug['w'] && n != N)
1177 dump("walk", n);
1178
1179 ullmancalc(n);
1180 lineno = lno;
1181 *np = n;
1182 }
1183
1184 static Node*
1185 makenewvar(Type *t, NodeList **init, Node **nstar)
1186 {
1187 Node *nvar, *nas;
1188
1189 nvar = nod(OXXX, N, N);
1190 tempname(nvar, t);
1191 nas = nod(OAS, nvar, callnew(t->type));
1192 typecheck(&nas, Etop);
1193 walkexpr(&nas, init);
1194 *init = list(*init, nas);
1195
1196 *nstar = nod(OIND, nvar, N);
1197 typecheck(nstar, Erv);
1198 return nvar;
1199 }
1200
1201 static Node*
1202 ascompatee1(int op, Node *l, Node *r, NodeList **init)
1203 {
1204 return convas(nod(OAS, l, r), init);
1205 }
1206
1207 static NodeList*
1208 ascompatee(int op, NodeList *nl, NodeList *nr, NodeList **init)
1209 {
1210 NodeList *ll, *lr, *nn;
1211
1212 /*
1213 * check assign expression list to
1214 * a expression list. called in
1215 * expr-list = expr-list
1216 */
1217
1218 // ensure order of evaluation for function calls
1219 for(ll=nl; ll; ll=ll->next)
1220 ll->n = safeexpr(ll->n, init);
1221 for(lr=nr; lr; lr=lr->next)
1222 lr->n = safeexpr(lr->n, init);
1223
1224 nn = nil;
1225 for(ll=nl, lr=nr; ll && lr; ll=ll->next, lr=lr->next)
1226 nn = list(nn, ascompatee1(op, ll->n, lr->n, init));
1227
1228 // cannot happen: caller checked that lists had same length
1229 if(ll || lr)
1230 yyerror("error in shape across %O", op);
1231 return nn;
1232 }
1233
1234 /*
1235 * l is an lv and rt is the type of an rv
1236 * return 1 if this implies a function call
1237 * evaluating the lv or a function call
1238 * in the conversion of the types
1239 */
1240 static int
1241 fncall(Node *l, Type *rt)
1242 {
1243 if(l->ullman >= UINF || l->op == OINDEXMAP)
1244 return 1;
1245 if(eqtype(l->type, rt))
1246 return 0;
1247 return 1;
1248 }
1249
1250 static NodeList*
1251 ascompatet(int op, NodeList *nl, Type **nr, int fp, NodeList **init)
1252 {
1253 Node *l, *tmp, *a;
1254 NodeList *ll;
1255 Type *r;
1256 Iter saver;
1257 int ucount;
1258 NodeList *nn, *mm;
1259
1260 /*
1261 * check assign type list to
1262 * a expression list. called in
1263 * expr-list = func()
1264 */
1265 r = structfirst(&saver, nr);
1266 nn = nil;
1267 mm = nil;
1268 ucount = 0;
1269 for(ll=nl; ll; ll=ll->next) {
1270 if(r == T)
1271 break;
1272 l = ll->n;
1273 if(isblank(l)) {
1274 r = structnext(&saver);
1275 continue;
1276 }
1277
1278 // any lv that causes a fn call must be
1279 // deferred until all the return arguments
1280 // have been pulled from the output arguments
1281 if(fncall(l, r->type)) {
1282 tmp = nod(OXXX, N, N);
1283 tempname(tmp, r->type);
1284 typecheck(&tmp, Erv);
1285 a = nod(OAS, l, tmp);
1286 a = convas(a, init);
1287 mm = list(mm, a);
1288 l = tmp;
1289 }
1290
1291 a = nod(OAS, l, nodarg(r, fp));
1292 a = convas(a, init);
1293 ullmancalc(a);
1294 if(a->ullman >= UINF)
1295 ucount++;
1296 nn = list(nn, a);
1297 r = structnext(&saver);
1298 }
1299
1300 if(ll != nil || r != T)
1301 yyerror("assignment count mismatch: %d = %d",
1302 count(nl), structcount(*nr));
1303 if(ucount)
1304 fatal("reorder2: too many function calls evaluating parameters");
1305 return concat(nn, mm);
1306 }
1307
1308 /*
1309 * package all the arguments that match a ... T parameter into a []T.
1310 */
1311 static NodeList*
1312 mkdotargslice(NodeList *lr0, NodeList *nn, Type *l, int fp, NodeList **init)
1313 {
1314 Node *a, *n;
1315 Type *tslice;
1316
1317 tslice = typ(TARRAY);
1318 tslice->type = l->type->type;
1319 tslice->bound = -1;
1320
1321 n = nod(OCOMPLIT, N, typenod(tslice));
1322 n->list = lr0;
1323 typecheck(&n, Erv);
1324 if(n->type == T)
1325 fatal("mkdotargslice: typecheck failed");
1326 walkexpr(&n, init);
1327
1328 a = nod(OAS, nodarg(l, fp), n);
1329 nn = list(nn, convas(a, init));
1330 return nn;
1331 }
1332
1333 /*
1334 * helpers for shape errors
1335 */
1336 static char*
1337 dumptypes(Type **nl, char *what)
1338 {
1339 int first;
1340 Type *l;
1341 Iter savel;
1342 Fmt fmt;
1343
1344 fmtstrinit(&fmt);
1345 fmtprint(&fmt, "\t");
1346 l = structfirst(&savel, nl);
1347 first = 1;
1348 for(l = structfirst(&savel, nl); l != T; l = structnext(&savel)) {
1349 if(first)
1350 first = 0;
1351 else
1352 fmtprint(&fmt, ", ");
1353 fmtprint(&fmt, "%T", l);
1354 }
1355 if(first)
1356 fmtprint(&fmt, "[no arguments %s]", what);
1357 return fmtstrflush(&fmt);
1358 }
1359
1360 static char*
1361 dumpnodetypes(NodeList *l, char *what)
1362 {
1363 int first;
1364 Node *r;
1365 Fmt fmt;
1366
1367 fmtstrinit(&fmt);
1368 fmtprint(&fmt, "\t");
1369 first = 1;
1370 for(; l; l=l->next) {
1371 r = l->n;
1372 if(first)
1373 first = 0;
1374 else
1375 fmtprint(&fmt, ", ");
1376 fmtprint(&fmt, "%T", r->type);
1377 }
1378 if(first)
1379 fmtprint(&fmt, "[no arguments %s]", what);
1380 return fmtstrflush(&fmt);
1381 }
1382
1383 /*
1384 * check assign expression list to
1385 * a type list. called in
1386 * return expr-list
1387 * func(expr-list)
1388 */
1389 static NodeList*
1390 ascompatte(int op, int isddd, Type **nl, NodeList *lr, int fp, NodeList **init)
1391 {
1392 Type *l, *ll;
1393 Node *r, *a;
1394 NodeList *nn, *lr0, *alist;
1395 Iter savel;
1396 char *l1, *l2;
1397
1398 lr0 = lr;
1399 l = structfirst(&savel, nl);
1400 r = N;
1401 if(lr)
1402 r = lr->n;
1403 nn = nil;
1404
1405 // f(g()) where g has multiple return values
1406 if(r != N && lr->next == nil && r->type->etype == TSTRUCT && r->type->funarg) {
1407 // optimization - can do block copy
1408 if(eqtypenoname(r->type, *nl)) {
1409 a = nodarg(*nl, fp);
1410 a->type = r->type;
1411 nn = list1(convas(nod(OAS, a, r), init));
1412 goto ret;
1413 }
1414
1415 // conversions involved.
1416 // copy into temporaries.
1417 alist = nil;
1418 for(l=structfirst(&savel, &r->type); l; l=structnext(&savel)) {
1419 a = nod(OXXX, N, N);
1420 tempname(a, l->type);
1421 alist = list(alist, a);
1422 }
1423 a = nod(OAS2, N, N);
1424 a->list = alist;
1425 a->rlist = lr;
1426 typecheck(&a, Etop);
1427 walkstmt(&a);
1428 *init = list(*init, a);
1429 lr = alist;
1430 r = lr->n;
1431 l = structfirst(&savel, nl);
1432 }
1433
1434 loop:
1435 if(l != T && l->isddd) {
1436 // the ddd parameter must be last
1437 ll = structnext(&savel);
1438 if(ll != T)
1439 yyerror("... must be last argument");
1440
1441 // special case --
1442 // only if we are assigning a single ddd
1443 // argument to a ddd parameter then it is
1444 // passed thru unencapsulated
1445 if(r != N && lr->next == nil && isddd && eqtype(l->type, r->type)) {
1446 a = nod(OAS, nodarg(l, fp), r);
1447 a = convas(a, init);
1448 nn = list(nn, a);
1449 goto ret;
1450 }
1451
1452 // normal case -- make a slice of all
1453 // remaining arguments and pass it to
1454 // the ddd parameter.
1455 nn = mkdotargslice(lr, nn, l, fp, init);
1456 goto ret;
1457 }
1458
1459 if(l == T || r == N) {
1460 if(l != T || r != N) {
1461 l1 = dumptypes(nl, "expected");
1462 l2 = dumpnodetypes(lr0, "given");
1463 if(l != T)
1464 yyerror("not enough arguments to %O\n%s\n%s", op, l1, l2);
1465 else
1466 yyerror("too many arguments to %O\n%s\n%s", op, l1, l2);
1467 }
1468 goto ret;
1469 }
1470
1471 a = nod(OAS, nodarg(l, fp), r);
1472 a = convas(a, init);
1473 nn = list(nn, a);
1474
1475 l = structnext(&savel);
1476 r = N;
1477 lr = lr->next;
1478 if(lr != nil)
1479 r = lr->n;
1480 goto loop;
1481
1482 ret:
1483 for(lr=nn; lr; lr=lr->next)
1484 lr->n->typecheck = 1;
1485 return nn;
1486 }
1487
1488 // generate code for print
1489 static Node*
1490 walkprint(Node *nn, NodeList **init, int defer)
1491 {
1492 Node *r;
1493 Node *n;
1494 NodeList *l, *all;
1495 Node *on;
1496 Type *t;
1497 int notfirst, et, op;
1498 NodeList *calls, *intypes, *args;
1499 Fmt fmt;
1500
1501 on = nil;
1502 op = nn->op;
1503 all = nn->list;
1504 calls = nil;
1505 notfirst = 0;
1506 intypes = nil;
1507 args = nil;
1508
1509 memset(&fmt, 0, sizeof fmt);
1510 if(defer) {
1511 // defer print turns into defer printf with format string
1512 fmtstrinit(&fmt);
1513 intypes = list(intypes, nod(ODCLFIELD, N, typenod(types[TSTRING])));
1514 args = list1(nod(OXXX, N, N));
1515 }
1516
1517 for(l=all; l; l=l->next) {
1518 if(notfirst) {
1519 if(defer)
1520 fmtprint(&fmt, " ");
1521 else
1522 calls = list(calls, mkcall("printsp", T, init));
1523 }
1524 notfirst = op == OPRINTN;
1525
1526 n = l->n;
1527 if(n->op == OLITERAL) {
1528 switch(n->val.ctype) {
1529 case CTINT:
1530 defaultlit(&n, types[TINT64]);
1531 break;
1532 case CTFLT:
1533 defaultlit(&n, types[TFLOAT64]);
1534 break;
1535 }
1536 }
1537 if(n->op != OLITERAL && n->type && n->type->etype == TIDEAL)
1538 defaultlit(&n, types[TINT64]);
1539 defaultlit(&n, nil);
1540 l->n = n;
1541 if(n->type == T || n->type->etype == TFORW)
1542 continue;
1543
1544 t = n->type;
1545 et = n->type->etype;
1546 if(isinter(n->type)) {
1547 if(defer) {
1548 if(isnilinter(n->type))
1549 fmtprint(&fmt, "%%e");
1550 else
1551 fmtprint(&fmt, "%%i");
1552 } else {
1553 if(isnilinter(n->type))
1554 on = syslook("printeface", 1);
1555 else
1556 on = syslook("printiface", 1);
1557 argtype(on, n->type); // any-1
1558 }
1559 } else if(isptr[et] || et == TCHAN || et == TMAP || et == TFUNC || et == TUNSAFEPTR) {
1560 if(defer) {
1561 fmtprint(&fmt, "%%p");
1562 } else {
1563 on = syslook("printpointer", 1);
1564 argtype(on, n->type); // any-1
1565 }
1566 } else if(isslice(n->type)) {
1567 if(defer) {
1568 fmtprint(&fmt, "%%a");
1569 } else {
1570 on = syslook("printslice", 1);
1571 argtype(on, n->type); // any-1
1572 }
1573 } else if(isint[et]) {
1574 if(defer) {
1575 if(et == TUINT64)
1576 fmtprint(&fmt, "%%U");
1577 else {
1578 fmtprint(&fmt, "%%D");
1579 t = types[TINT64];
1580 }
1581 } else {
1582 if(et == TUINT64)
1583 on = syslook("printuint", 0);
1584 else
1585 on = syslook("printint", 0);
1586 }
1587 } else if(isfloat[et]) {
1588 if(defer) {
1589 fmtprint(&fmt, "%%f");
1590 t = types[TFLOAT64];
1591 } else
1592 on = syslook("printfloat", 0);
1593 } else if(iscomplex[et]) {
1594 if(defer) {
1595 fmtprint(&fmt, "%%C");
1596 t = types[TCOMPLEX128];
1597 } else
1598 on = syslook("printcomplex", 0);
1599 } else if(et == TBOOL) {
1600 if(defer)
1601 fmtprint(&fmt, "%%t");
1602 else
1603 on = syslook("printbool", 0);
1604 } else if(et == TSTRING) {
1605 if(defer)
1606 fmtprint(&fmt, "%%S");
1607 else
1608 on = syslook("printstring", 0);
1609 } else {
1610 badtype(OPRINT, n->type, T);
1611 continue;
1612 }
1613
1614 if(!defer) {
1615 t = *getinarg(on->type);
1616 if(t != nil)
1617 t = t->type;
1618 if(t != nil)
1619 t = t->type;
1620 }
1621
1622 if(!eqtype(t, n->type)) {
1623 n = nod(OCONV, n, N);
1624 n->type = t;
1625 }
1626
1627 if(defer) {
1628 intypes = list(intypes, nod(ODCLFIELD, N, typenod(t)));
1629 args = list(args, n);
1630 } else {
1631 r = nod(OCALL, on, N);
1632 r->list = list1(n);
1633 calls = list(calls, r);
1634 }
1635 }
1636
1637 if(defer) {
1638 if(op == OPRINTN)
1639 fmtprint(&fmt, "\n");
1640 on = syslook("goprintf", 1);
1641 on->type = functype(nil, intypes, nil);
1642 args->n = nod(OLITERAL, N, N);
1643 args->n->val.ctype = CTSTR;
1644 args->n->val.u.sval = strlit(fmtstrflush(&fmt));
1645 r = nod(OCALL, on, N);
1646 r->list = args;
1647 typecheck(&r, Etop);
1648 walkexpr(&r, init);
1649 } else {
1650 if(op == OPRINTN)
1651 calls = list(calls, mkcall("printnl", T, nil));
1652 typechecklist(calls, Etop);
1653 walkexprlist(calls, init);
1654
1655 r = nod(OEMPTY, N, N);
1656 typecheck(&r, Etop);
1657 walkexpr(&r, init);
1658 r->ninit = calls;
1659 }
1660 return r;
1661 }
1662
1663 Node*
1664 callnew(Type *t)
1665 {
1666 Node *fn;
1667
1668 dowidth(t);
1669 fn = syslook("new", 1);
1670 argtype(fn, t);
1671 return mkcall1(fn, ptrto(t), nil, nodintconst(t->width));
1672 }
1673
1674 static Node*
1675 convas(Node *n, NodeList **init)
1676 {
1677 Type *lt, *rt;
1678
1679 if(n->op != OAS)
1680 fatal("convas: not OAS %O", n->op);
1681
1682 n->typecheck = 1;
1683
1684 if(n->left == N || n->right == N)
1685 goto out;
1686
1687 lt = n->left->type;
1688 rt = n->right->type;
1689 if(lt == T || rt == T)
1690 goto out;
1691
1692 if(isblank(n->left)) {
1693 defaultlit(&n->right, T);
1694 goto out;
1695 }
1696
1697 if(n->left->op == OINDEXMAP) {
1698 n = mkcall1(mapfn("mapassign1", n->left->left->type), T, init,
1699 typename(n->left->left->type),
1700 n->left->left, n->left->right, n->right);
1701 goto out;
1702 }
1703
1704 if(eqtype(lt, rt))
1705 goto out;
1706
1707 n->right = assignconv(n->right, lt, "assignment");
1708 walkexpr(&n->right, init);
1709
1710 out:
1711 ullmancalc(n);
1712 return n;
1713 }
1714
1715 /*
1716 * from ascompat[te]
1717 * evaluating actual function arguments.
1718 * f(a,b)
1719 * if there is exactly one function expr,
1720 * then it is done first. otherwise must
1721 * make temp variables
1722 */
1723 NodeList*
1724 reorder1(NodeList *all)
1725 {
1726 Node *f, *a, *n;
1727 NodeList *l, *r, *g;
1728 int c, d, t;
1729
1730 c = 0; // function calls
1731 t = 0; // total parameters
1732
1733 for(l=all; l; l=l->next) {
1734 n = l->n;
1735 t++;
1736 ullmancalc(n);
1737 if(n->ullman >= UINF)
1738 c++;
1739 }
1740 if(c == 0 || t == 1)
1741 return all;
1742
1743 g = nil; // fncalls assigned to tempnames
1744 f = N; // last fncall assigned to stack
1745 r = nil; // non fncalls and tempnames assigned to stack
1746 d = 0;
1747 for(l=all; l; l=l->next) {
1748 n = l->n;
1749 if(n->ullman < UINF) {
1750 r = list(r, n);
1751 continue;
1752 }
1753 d++;
1754 if(d == c) {
1755 f = n;
1756 continue;
1757 }
1758
1759 // make assignment of fncall to tempname
1760 a = nod(OXXX, N, N);
1761 tempname(a, n->right->type);
1762 a = nod(OAS, a, n->right);
1763 g = list(g, a);
1764
1765 // put normal arg assignment on list
1766 // with fncall replaced by tempname
1767 n->right = a->left;
1768 r = list(r, n);
1769 }
1770
1771 if(f != N)
1772 g = list(g, f);
1773 return concat(g, r);
1774 }
1775
1776 /*
1777 * from ascompat[ee]
1778 * a,b = c,d
1779 * simultaneous assignment. there cannot
1780 * be later use of an earlier lvalue.
1781 */
1782
1783 static int
1784 vmatch2(Node *l, Node *r)
1785 {
1786 NodeList *ll;
1787
1788 /*
1789 * isolate all right sides
1790 */
1791 if(r == N)
1792 return 0;
1793 switch(r->op) {
1794 case ONAME:
1795 // match each right given left
1796 if(l == r)
1797 return 1;
1798 case OLITERAL:
1799 return 0;
1800 }
1801 if(vmatch2(l, r->left))
1802 return 1;
1803 if(vmatch2(l, r->right))
1804 return 1;
1805 for(ll=r->list; ll; ll=ll->next)
1806 if(vmatch2(l, ll->n))
1807 return 1;
1808 return 0;
1809 }
1810
1811 int
1812 vmatch1(Node *l, Node *r)
1813 {
1814 NodeList *ll;
1815
1816 /*
1817 * isolate all left sides
1818 */
1819 if(l == N || r == N)
1820 return 0;
1821 switch(l->op) {
1822 case ONAME:
1823 switch(l->class) {
1824 case PPARAM:
1825 case PPARAMREF:
1826 case PAUTO:
1827 break;
1828 default:
1829 // assignment to non-stack variable
1830 // must be delayed if right has function calls.
1831 if(r->ullman >= UINF)
1832 return 1;
1833 break;
1834 }
1835 return vmatch2(l, r);
1836 case OLITERAL:
1837 return 0;
1838 }
1839 if(vmatch1(l->left, r))
1840 return 1;
1841 if(vmatch1(l->right, r))
1842 return 1;
1843 for(ll=l->list; ll; ll=ll->next)
1844 if(vmatch1(ll->n, r))
1845 return 1;
1846 return 0;
1847 }
1848
1849 NodeList*
1850 reorder3(NodeList *all)
1851 {
1852 Node *n1, *n2, *q;
1853 int c1, c2;
1854 NodeList *l1, *l2, *r;
1855
1856 r = nil;
1857 for(l1=all, c1=0; l1; l1=l1->next, c1++) {
1858 n1 = l1->n;
1859 for(l2=all, c2=0; l2; l2=l2->next, c2++) {
1860 n2 = l2->n;
1861 if(c2 > c1) {
1862 if(vmatch1(n1->left, n2->right)) {
1863 // delay assignment to n1->left
1864 q = nod(OXXX, N, N);
1865 tempname(q, n1->right->type);
1866 q = nod(OAS, n1->left, q);
1867 n1->left = q->right;
1868 r = list(r, q);
1869 break;
1870 }
1871 }
1872 }
1873 }
1874 return concat(all, r);
1875 }
1876
1877 /*
1878 * walk through argin parameters.
1879 * generate and return code to allocate
1880 * copies of escaped parameters to the heap.
1881 */
1882 static NodeList*
1883 paramstoheap(Type **argin, int out)
1884 {
1885 Type *t;
1886 Iter savet;
1887 Node *v;
1888 NodeList *nn;
1889
1890 nn = nil;
1891 for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) {
1892 v = t->nname;
1893 if(v == N && out && hasdefer) {
1894 // Defer might stop a panic and show the
1895 // return values as they exist at the time of panic.
1896 // Make sure to zero them on entry to the function.
1897 nn = list(nn, nod(OAS, nodarg(t, 1), N));
1898 }
1899 if(v == N || !(v->class & PHEAP))
1900 continue;
1901
1902 // generate allocation & copying code
1903 if(v->alloc == nil)
1904 v->alloc = callnew(v->type);
1905 nn = list(nn, nod(OAS, v->heapaddr, v->alloc));
1906 if((v->class & ~PHEAP) != PPARAMOUT)
1907 nn = list(nn, nod(OAS, v, v->stackparam));
1908 }
1909 return nn;
1910 }
1911
1912 /*
1913 * walk through argout parameters copying back to stack
1914 */
1915 static NodeList*
1916 returnsfromheap(Type **argin)
1917 {
1918 Type *t;
1919 Iter savet;
1920 Node *v;
1921 NodeList *nn;
1922
1923 nn = nil;
1924 for(t = structfirst(&savet, argin); t != T; t = structnext(&savet)) {
1925 v = t->nname;
1926 if(v == N || v->class != (PHEAP|PPARAMOUT))
1927 continue;
1928 nn = list(nn, nod(OAS, v->stackparam, v));
1929 }
1930 return nn;
1931 }
1932
1933 /*
1934 * take care of migrating any function in/out args
1935 * between the stack and the heap. adds code to
1936 * curfn's before and after lists.
1937 */
1938 static void
1939 heapmoves(void)
1940 {
1941 NodeList *nn;
1942 int32 lno;
1943
1944 lno = lineno;
1945 lineno = curfn->lineno;
1946 nn = paramstoheap(getthis(curfn->type), 0);
1947 nn = concat(nn, paramstoheap(getinarg(curfn->type), 0));
1948 nn = concat(nn, paramstoheap(getoutarg(curfn->type), 1));
1949 curfn->enter = concat(curfn->enter, nn);
1950 lineno = curfn->endlineno;
1951 curfn->exit = returnsfromheap(getoutarg(curfn->type));
1952 lineno = lno;
1953 }
1954
1955 static Node*
1956 vmkcall(Node *fn, Type *t, NodeList **init, va_list va)
1957 {
1958 int i, n;
1959 Node *r;
1960 NodeList *args;
1961
1962 if(fn->type == T || fn->type->etype != TFUNC)
1963 fatal("mkcall %#N %T", fn, fn->type);
1964
1965 args = nil;
1966 n = fn->type->intuple;
1967 for(i=0; i<n; i++)
1968 args = list(args, va_arg(va, Node*));
1969
1970 r = nod(OCALL, fn, N);
1971 r->list = args;
1972 if(fn->type->outtuple > 0)
1973 typecheck(&r, Erv | Efnstruct);
1974 else
1975 typecheck(&r, Etop);
1976 walkexpr(&r, init);
1977 r->type = t;
1978 return r;
1979 }
1980
1981 Node*
1982 mkcall(char *name, Type *t, NodeList **init, ...)
1983 {
1984 Node *r;
1985 va_list va;
1986
1987 va_start(va, init);
1988 r = vmkcall(syslook(name, 0), t, init, va);
1989 va_end(va);
1990 return r;
1991 }
1992
1993 Node*
1994 mkcall1(Node *fn, Type *t, NodeList **init, ...)
1995 {
1996 Node *r;
1997 va_list va;
1998
1999 va_start(va, init);
2000 r = vmkcall(fn, t, init, va);
2001 va_end(va);
2002 return r;
2003 }
2004
2005 static Node*
2006 conv(Node *n, Type *t)
2007 {
2008 if(eqtype(n->type, t))
2009 return n;
2010 n = nod(OCONV, n, N);
2011 n->type = t;
2012 typecheck(&n, Erv);
2013 return n;
2014 }
2015
2016 Node*
2017 chanfn(char *name, int n, Type *t)
2018 {
2019 Node *fn;
2020 int i;
2021
2022 if(t->etype != TCHAN)
2023 fatal("chanfn %T", t);
2024 fn = syslook(name, 1);
2025 for(i=0; i<n; i++)
2026 argtype(fn, t->type);
2027 return fn;
2028 }
2029
2030 static Node*
2031 mapfn(char *name, Type *t)
2032 {
2033 Node *fn;
2034
2035 if(t->etype != TMAP)
2036 fatal("mapfn %T", t);
2037 fn = syslook(name, 1);
2038 argtype(fn, t->down);
2039 argtype(fn, t->type);
2040 argtype(fn, t->down);
2041 argtype(fn, t->type);
2042 return fn;
2043 }
2044
2045 static Node*
2046 addstr(Node *n, NodeList **init)
2047 {
2048 Node *r, *cat, *typstr;
2049 NodeList *in, *args;
2050 int i, count;
2051
2052 count = 0;
2053 for(r=n; r->op == OADDSTR; r=r->left)
2054 count++; // r->right
2055 count++; // r
2056
2057 // prepare call of runtime.catstring of type int, string, string, string
2058 // with as many strings as we have.
2059 cat = syslook("concatstring", 1);
2060 cat->type = T;
2061 cat->ntype = nod(OTFUNC, N, N);
2062 in = list1(nod(ODCLFIELD, N, typenod(types[TINT]))); // count
2063 typstr = typenod(types[TSTRING]);
2064 for(i=0; i<count; i++)
2065 in = list(in, nod(ODCLFIELD, N, typstr));
2066 cat->ntype->list = in;
2067 cat->ntype->rlist = list1(nod(ODCLFIELD, N, typstr));
2068
2069 args = nil;
2070 for(r=n; r->op == OADDSTR; r=r->left)
2071 args = concat(list1(conv(r->right, types[TSTRING])), args);
2072 args = concat(list1(conv(r, types[TSTRING])), args);
2073 args = concat(list1(nodintconst(count)), args);
2074
2075 r = nod(OCALL, cat, N);
2076 r->list = args;
2077 typecheck(&r, Erv);
2078 walkexpr(&r, init);
2079 r->type = n->type;
2080
2081 return r;
2082 }
2083
2084 static Node*
2085 appendslice(Node *n, NodeList **init)
2086 {
2087 Node *f;
2088
2089 f = syslook("appendslice", 1);
2090 argtype(f, n->type);
2091 argtype(f, n->type->type);
2092 argtype(f, n->type);
2093 return mkcall1(f, n->type, init, typename(n->type), n->list->n, n->list->next->n);
2094 }
2095
2096 // expand append(src, a [, b]* ) to
2097 //
2098 // init {
2099 // s := src
2100 // const argc = len(args) - 1
2101 // if cap(s) - len(s) < argc {
2102 // s = growslice(s, argc)
2103 // }
2104 // n := len(s)
2105 // s = s[:n+argc]
2106 // s[n] = a
2107 // s[n+1] = b
2108 // ...
2109 // }
2110 // s
2111 static Node*
2112 append(Node *n, NodeList **init)
2113 {
2114 NodeList *l, *a;
2115 Node *nsrc, *ns, *nn, *na, *nx, *fn;
2116 int argc;
2117
2118 walkexprlistsafe(n->list, init);
2119
2120 nsrc = n->list->n;
2121 argc = count(n->list) - 1;
2122 if (argc < 1) {
2123 return nsrc;
2124 }
2125
2126 l = nil;
2127
2128 ns = nod(OXXX, N, N); // var s
2129 tempname(ns, nsrc->type);
2130 l = list(l, nod(OAS, ns, nsrc)); // s = src
2131
2132 na = nodintconst(argc); // const argc
2133 nx = nod(OIF, N, N); // if cap(s) - len(s) < argc
2134 nx->ntest = nod(OLT, nod(OSUB, nod(OCAP, ns, N), nod(OLEN, ns, N)), na);
2135
2136 fn = syslook("growslice", 1); // growslice(<type>, old []T, n int64) (ret []T)
2137 argtype(fn, ns->type->type); // 1 old []any
2138 argtype(fn, ns->type->type); // 2 ret []any
2139
2140 nx->nbody = list1(nod(OAS, ns, mkcall1(fn, ns->type, &nx->ninit,
2141 typename(ns->type),
2142 ns,
2143 conv(na, types[TINT64]))));
2144 l = list(l, nx);
2145
2146 nn = nod(OXXX, N, N); // var n
2147 tempname(nn, types[TINT]);
2148 l = list(l, nod(OAS, nn, nod(OLEN, ns, N))); // n = len(s)
2149
2150 nx = nod(OSLICE, ns, nod(OKEY, N, nod(OADD, nn, na))); // ...s[:n+argc]
2151 nx->etype = 1; // disable bounds check
2152 l = list(l, nod(OAS, ns, nx)); // s = s[:n+argc]
2153
2154 for (a = n->list->next; a != nil; a = a->next) {
2155 nx = nod(OINDEX, ns, nn); // s[n] ...
2156 nx->etype = 1; // disable bounds check
2157 l = list(l, nod(OAS, nx, a->n)); // s[n] = arg
2158 if (a->next != nil)
2159 l = list(l, nod(OAS, nn, nod(OADD, nn, nodintconst(1)))); // n = n + 1
2160 }
2161
2162 typechecklist(l, Etop);
2163 walkstmtlist(l);
2164 *init = concat(*init, l);
2165 return ns;
2166 }