1 #include "limbo.h"
2
3 static Node* putinline(Node*);
4 static void fpcall(Src*, int, Node*, Node*);
5
6 void
optabinit(void)7 optabinit(void)
8 {
9 int i;
10
11 for(i = 0; setisbyteinst[i] >= 0; i++)
12 isbyteinst[setisbyteinst[i]] = 1;
13
14 for(i = 0; setisused[i] >= 0; i++)
15 isused[setisused[i]] = 1;
16
17 for(i = 0; setsideeffect[i] >= 0; i++)
18 sideeffect[setsideeffect[i]] = 1;
19
20 opind[Tbyte] = 1;
21 opind[Tint] = 2;
22 opind[Tbig] = 3;
23 opind[Treal] = 4;
24 opind[Tstring] = 5;
25 opind[Tfix] = 6;
26
27 opcommute[Oeq] = Oeq;
28 opcommute[Oneq] = Oneq;
29 opcommute[Olt] = Ogt;
30 opcommute[Ogt] = Olt;
31 opcommute[Ogeq] = Oleq;
32 opcommute[Oleq] = Ogeq;
33 opcommute[Oadd] = Oadd;
34 opcommute[Omul] = Omul;
35 opcommute[Oxor] = Oxor;
36 opcommute[Oor] = Oor;
37 opcommute[Oand] = Oand;
38
39 oprelinvert[Oeq] = Oneq;
40 oprelinvert[Oneq] = Oeq;
41 oprelinvert[Olt] = Ogeq;
42 oprelinvert[Ogt] = Oleq;
43 oprelinvert[Ogeq] = Olt;
44 oprelinvert[Oleq] = Ogt;
45
46 isrelop[Oeq] = 1;
47 isrelop[Oneq] = 1;
48 isrelop[Olt] = 1;
49 isrelop[Oleq] = 1;
50 isrelop[Ogt] = 1;
51 isrelop[Ogeq] = 1;
52 isrelop[Oandand] = 1;
53 isrelop[Ooror] = 1;
54 isrelop[Onot] = 1;
55
56 precasttab[Tstring][Tbyte] = tint;
57 precasttab[Tbyte][Tstring] = tint;
58 precasttab[Treal][Tbyte] = tint;
59 precasttab[Tbyte][Treal] = tint;
60 precasttab[Tbig][Tbyte] = tint;
61 precasttab[Tbyte][Tbig] = tint;
62 precasttab[Tfix][Tbyte] = tint;
63 precasttab[Tbyte][Tfix] = tint;
64 precasttab[Tbig][Tfix] = treal;
65 precasttab[Tfix][Tbig] = treal;
66 precasttab[Tstring][Tfix] = treal;
67 precasttab[Tfix][Tstring] = treal;
68
69 casttab[Tint][Tint] = IMOVW;
70 casttab[Tbig][Tbig] = IMOVL;
71 casttab[Treal][Treal] = IMOVF;
72 casttab[Tbyte][Tbyte] = IMOVB;
73 casttab[Tstring][Tstring] = IMOVP;
74 casttab[Tfix][Tfix] = ICVTXX; /* never same type */
75
76 casttab[Tint][Tbyte] = ICVTWB;
77 casttab[Tint][Treal] = ICVTWF;
78 casttab[Tint][Tstring] = ICVTWC;
79 casttab[Tint][Tfix] = ICVTXX;
80 casttab[Tbyte][Tint] = ICVTBW;
81 casttab[Treal][Tint] = ICVTFW;
82 casttab[Tstring][Tint] = ICVTCW;
83 casttab[Tfix][Tint] = ICVTXX;
84
85 casttab[Tint][Tbig] = ICVTWL;
86 casttab[Treal][Tbig] = ICVTFL;
87 casttab[Tstring][Tbig] = ICVTCL;
88 casttab[Tbig][Tint] = ICVTLW;
89 casttab[Tbig][Treal] = ICVTLF;
90 casttab[Tbig][Tstring] = ICVTLC;
91
92 casttab[Treal][Tstring] = ICVTFC;
93 casttab[Tstring][Treal] = ICVTCF;
94
95 casttab[Treal][Tfix] = ICVTFX;
96 casttab[Tfix][Treal] = ICVTXF;
97
98 casttab[Tstring][Tarray] = ICVTCA;
99 casttab[Tarray][Tstring] = ICVTAC;
100
101 /*
102 * placeholders; fixed in precasttab
103 */
104 casttab[Tbyte][Tstring] = 0xff;
105 casttab[Tstring][Tbyte] = 0xff;
106 casttab[Tbyte][Treal] = 0xff;
107 casttab[Treal][Tbyte] = 0xff;
108 casttab[Tbyte][Tbig] = 0xff;
109 casttab[Tbig][Tbyte] = 0xff;
110 casttab[Tfix][Tbyte] = 0xff;
111 casttab[Tbyte][Tfix] = 0xff;
112 casttab[Tfix][Tbig] = 0xff;
113 casttab[Tbig][Tfix] = 0xff;
114 casttab[Tfix][Tstring] = 0xff;
115 casttab[Tstring][Tfix] = 0xff;
116 }
117
118 /*
119 * global variable and constant initialization checking
120 */
121 int
vcom(Decl * ids)122 vcom(Decl *ids)
123 {
124 Decl *v;
125 int ok;
126
127 ok = 1;
128 for(v = ids; v != nil; v = v->next)
129 ok &= varcom(v);
130 for(v = ids; v != nil; v = v->next)
131 v->init = simplify(v->init);
132 return ok;
133 }
134
135 Node*
simplify(Node * n)136 simplify(Node *n)
137 {
138 if(n == nil)
139 return nil;
140 if(debug['F'])
141 print("simplify %n\n", n);
142 n = efold(rewrite(n));
143 if(debug['F'])
144 print("simplified %n\n", n);
145 return n;
146 }
147
148 static int
isfix(Node * n)149 isfix(Node *n)
150 {
151 if(n->ty->kind == Tint || n->ty->kind == Tfix){
152 if(n->op == Ocast)
153 return n->left->ty->kind == Tint || n->left->ty->kind == Tfix;
154 return 1;
155 }
156 return 0;
157 }
158
159 /*
160 * rewrite an expression to make it easiser to compile,
161 * or give the correct results
162 */
163 Node*
rewrite(Node * n)164 rewrite(Node *n)
165 {
166 Long v;
167 Type *t;
168 Decl *d;
169 Node *nn, *left, *right;
170
171 if(n == nil)
172 return nil;
173
174 left = n->left;
175 right = n->right;
176
177 /*
178 * rewrites
179 */
180 switch(n->op){
181 case Oname:
182 d = n->decl;
183 if(d->importid != nil){
184 left = mkbin(Omdot, dupn(1, &n->src, d->eimport), mkdeclname(&n->src, d->importid));
185 left->ty = n->ty;
186 return rewrite(left);
187 }
188 if((t = n->ty)->kind == Texception){
189 if(t->cons)
190 fatal("cons in rewrite Oname");
191 n = mkbin(Oadd, n, mkconst(&n->src, 2*IBY2WD));
192 n = mkunary(Oind, n);
193 n->ty = t;
194 n->left->ty = n->left->left->ty = tint;
195 return rewrite(n);
196 }
197 break;
198 case Odas:
199 n->op = Oas;
200 return rewrite(n);
201 case Oneg:
202 n->left = rewrite(left);
203 if(n->ty == treal)
204 break;
205 left = n->left;
206 n->right = left;
207 n->left = mkconst(&n->src, 0);
208 n->left->ty = n->ty;
209 n->op = Osub;
210 break;
211 case Ocomp:
212 v = 0;
213 v = ~v;
214 n->right = mkconst(&n->src, v);
215 n->right->ty = n->ty;
216 n->left = rewrite(left);
217 n->op = Oxor;
218 break;
219 case Oinc:
220 case Odec:
221 case Opreinc:
222 case Opredec:
223 n->left = rewrite(left);
224 switch(n->ty->kind){
225 case Treal:
226 n->right = mkrconst(&n->src, 1.0);
227 break;
228 case Tint:
229 case Tbig:
230 case Tbyte:
231 case Tfix:
232 n->right = mkconst(&n->src, 1);
233 n->right->ty = n->ty;
234 break;
235 default:
236 fatal("can't rewrite inc/dec %n", n);
237 break;
238 }
239 if(n->op == Opreinc)
240 n->op = Oaddas;
241 else if(n->op == Opredec)
242 n->op = Osubas;
243 break;
244 case Oslice:
245 if(right->left->op == Onothing)
246 right->left = mkconst(&right->left->src, 0);
247 n->left = rewrite(left);
248 n->right = rewrite(right);
249 break;
250 case Oindex:
251 n->op = Oindx;
252 n->left = rewrite(left);
253 n->right = rewrite(right);
254 n = mkunary(Oind, n);
255 n->ty = n->left->ty;
256 n->left->ty = tint;
257 break;
258 case Oload:
259 n->right = mkn(Oname, nil, nil);
260 n->right->src = n->left->src;
261 n->right->decl = n->ty->tof->decl;
262 n->right->ty = n->ty;
263 n->left = rewrite(left);
264 break;
265 case Ocast:
266 if(left->ty->kind == Texception){
267 n = rewrite(left);
268 break;
269 }
270 n->op = Ocast;
271 t = precasttab[left->ty->kind][n->ty->kind];
272 if(t != nil){
273 n->left = mkunary(Ocast, left);
274 n->left->ty = t;
275 return rewrite(n);
276 }
277 n->left = rewrite(left);
278 break;
279 case Oraise:
280 if(left->ty == tstring)
281 {}
282 else if(!left->ty->cons)
283 break;
284 else if(left->op != Ocall || left->left->ty->kind == Tfn){
285 left = mkunary(Ocall, left);
286 left->ty = left->left->ty;
287 }
288 n->left = rewrite(left);
289 break;
290 case Ocall:
291 t = left->ty;
292 if(t->kind == Tref)
293 t = t->tof;
294 if(t->kind == Tfn){
295 if(debug['U']) print("call %n\n", left);
296 if(left->ty->kind == Tref){ /* call by function reference */
297 n->left = mkunary(Oind, left);
298 n->left->ty = t;
299 return rewrite(n);
300 }
301 d = nil;
302 if(left->op == Oname)
303 d = left->decl;
304 else if(left->op == Omdot && left->right->op == Odot)
305 d = left->right->right->decl;
306 else if(left->op == Omdot || left->op == Odot)
307 d = left->right->decl;
308 else if(left->op != Oind)
309 fatal("cannot deal with call %n in rewrite", n);
310 if(ispoly(d))
311 addfnptrs(d, 0);
312 n->left = rewrite(left);
313 if(right != nil)
314 n->right = rewrite(right);
315 if(d != nil && d->caninline == 1)
316 n = simplify(putinline(n));
317 break;
318 }
319 switch(n->ty->kind){
320 case Tref:
321 n = mkunary(Oref, n);
322 n->ty = n->left->ty;
323 n->left->ty = n->left->ty->tof;
324 n->left->left->ty = n->left->ty;
325 return rewrite(n);
326 case Tadt:
327 n->op = Otuple;
328 n->right = nil;
329 if(n->ty->tags != nil){
330 n->left = nn = mkunary(Oseq, mkconst(&n->src, left->right->decl->tag));
331 if(right != nil){
332 nn->right = right;
333 nn->src.stop = right->src.stop;
334 }
335 n->ty = left->right->decl->ty->tof;
336 }else
337 n->left = right;
338 return rewrite(n);
339 case Tadtpick:
340 n->op = Otuple;
341 n->right = nil;
342 n->left = nn = mkunary(Oseq, mkconst(&n->src, left->right->decl->tag));
343 if(right != nil){
344 nn->right = right;
345 nn->src.stop = right->src.stop;
346 }
347 n->ty = left->right->decl->ty->tof;
348 return rewrite(n);
349 case Texception:
350 if(!n->ty->cons)
351 return n->left;
352 if(left->op == Omdot){
353 left->right->ty = left->ty;
354 left = left->right;
355 }
356 n->op = Otuple;
357 n->right = nil;
358 n->left = nn = mkunary(Oseq, left->decl->init);
359 nn->right = mkunary(Oseq, mkconst(&n->src, 0));
360 nn->right->right = right;
361 n->ty = mkexbasetype(n->ty);
362 n = mkunary(Oref, n);
363 n->ty = internaltype(mktype(&n->src.start, &n->src.stop, Tref, t, nil));
364 return rewrite(n);
365 default:
366 fatal("can't deal with %n in rewrite/Ocall", n);
367 break;
368 }
369 break;
370 case Omdot:
371 /*
372 * what about side effects from left?
373 */
374 d = right->decl;
375 switch(d->store){
376 case Dfn:
377 n->left = rewrite(left);
378 if(right->op == Odot){
379 n->right = dupn(1, &left->src, right->right);
380 n->right->ty = d->ty;
381 }
382 break;
383 case Dconst:
384 case Dtag:
385 case Dtype:
386 /* handled by fold */
387 return n;
388 case Dglobal:
389 right->op = Oconst;
390 right->val = d->offset;
391 right->ty = tint;
392
393 n->left = left = mkunary(Oind, left);
394 left->ty = tint;
395 n->op = Oadd;
396 n = mkunary(Oind, n);
397 n->ty = n->left->ty;
398 n->left->ty = tint;
399 n->left = rewrite(n->left);
400 return n;
401 case Darg:
402 return n;
403 default:
404 fatal("can't deal with %n in rewrite/Omdot", n);
405 break;
406 }
407 break;
408 case Odot:
409 /*
410 * what about side effects from left?
411 */
412 d = right->decl;
413 switch(d->store){
414 case Dfn:
415 if(right->left != nil){
416 n = mkbin(Omdot, dupn(1, &left->src, right->left), right);
417 right->left = nil;
418 n->ty = d->ty;
419 return rewrite(n);
420 }
421 if(left->ty->kind == Tpoly){
422 n = mkbin(Omdot, mkdeclname(&left->src, d->link), mkdeclname(&left->src, d->link->next));
423 n->ty = d->ty;
424 return rewrite(n);
425 }
426 n->op = Oname;
427 n->decl = d;
428 n->right = nil;
429 n->left = nil;
430 return n;
431 case Dconst:
432 case Dtag:
433 case Dtype:
434 /* handled by fold */
435 return n;
436 }
437 if(istuple(left))
438 return n; /* handled by fold */
439 right->op = Oconst;
440 right->val = d->offset;
441 right->ty = tint;
442
443 if(left->ty->kind != Tref){
444 n->left = mkunary(Oadr, left);
445 n->left->ty = tint;
446 }
447 n->op = Oadd;
448 n = mkunary(Oind, n);
449 n->ty = n->left->ty;
450 n->left->ty = tint;
451 n->left = rewrite(n->left);
452 return n;
453 case Oadr:
454 left = rewrite(left);
455 n->left = left;
456 if(left->op == Oind)
457 return left->left;
458 break;
459 case Otagof:
460 if(n->decl == nil){
461 n->op = Oind;
462 return rewrite(n);
463 }
464 return n;
465 case Omul:
466 case Odiv:
467 left = n->left = rewrite(left);
468 right = n->right = rewrite(right);
469 if(n->ty->kind == Tfix && isfix(left) && isfix(right)){
470 if(left->op == Ocast && tequal(left->ty, n->ty))
471 n->left = left->left;
472 if(right->op == Ocast && tequal(right->ty, n->ty))
473 n->right = right->left;
474 }
475 break;
476 case Oself:
477 if(newfnptr)
478 return n;
479 if(selfdecl == nil){
480 d = selfdecl = mkids(&n->src, enter(strdup(".self"), 5), tany, nil);
481 installids(Dglobal, d);
482 d->refs++;
483 }
484 nn = mkn(Oload, nil, nil);
485 nn->src = n->src;
486 nn->left = mksconst(&n->src, enterstring(strdup("$self"), 5));
487 nn->ty = impdecl->ty;
488 usetype(nn->ty);
489 usetype(nn->ty->tof);
490 nn = rewrite(nn);
491 nn->op = Oself;
492 return nn;
493 case Ofnptr:
494 if(n->flags == 0){
495 /* module */
496 if(left == nil)
497 left = mkn(Oself, nil, nil);
498 return rewrite(left);
499 }
500 right->flags = n->flags;
501 n = right;
502 d = n->decl;
503 if(n->flags == FNPTR2){
504 if(left != nil && left->op != Oname)
505 fatal("not Oname for addiface");
506 if(left == nil){
507 addiface(nil, d);
508 if(newfnptr)
509 n->flags |= FNPTRN;
510 }
511 else
512 addiface(left->decl, d); /* is this necessary ? */
513 n->ty = tint;
514 return n;
515 }
516 if(n->flags == FNPTRA){
517 n = mkdeclname(&n->src, d->link);
518 n->ty = tany;
519 return n;
520 }
521 if(n->flags == (FNPTRA|FNPTR2)){
522 n = mkdeclname(&n->src, d->link->next);
523 n->ty = tint;
524 return n;
525 }
526 break;
527 case Ochan:
528 if(left == nil)
529 left = n->left = mkconst(&n->src, 0);
530 n->left = rewrite(left);
531 break;
532 default:
533 n->left = rewrite(left);
534 n->right = rewrite(right);
535 break;
536 }
537
538 return n;
539 }
540
541 /*
542 * label a node with sethi-ullman numbers and addressablity
543 * genaddr interprets addable to generate operands,
544 * so a change here mandates a change there.
545 *
546 * addressable:
547 * const Rconst $value may also be Roff or Rdesc or Rnoff
548 * Asmall(local) Rreg value(FP)
549 * Asmall(global) Rmreg value(MP)
550 * ind(Rareg) Rreg value(FP)
551 * ind(Ramreg) Rmreg value(MP)
552 * ind(Rreg) Radr *value(FP)
553 * ind(Rmreg) Rmadr *value(MP)
554 * ind(Raadr) Radr value(value(FP))
555 * ind(Ramadr) Rmadr value(value(MP))
556 *
557 * almost addressable:
558 * adr(Rreg) Rareg
559 * adr(Rmreg) Ramreg
560 * add(const, Rareg) Rareg
561 * add(const, Ramreg) Ramreg
562 * add(const, Rreg) Raadr
563 * add(const, Rmreg) Ramadr
564 * add(const, Raadr) Raadr
565 * add(const, Ramadr) Ramadr
566 * adr(Radr) Raadr
567 * adr(Rmadr) Ramadr
568 *
569 * strangely addressable:
570 * fn Rpc
571 * mdot(module,exp) Rmpc
572 */
573 Node*
sumark(Node * n)574 sumark(Node *n)
575 {
576 Node *left, *right;
577 long v;
578
579 if(n == nil)
580 return nil;
581
582 n->temps = 0;
583 n->addable = Rcant;
584
585 left = n->left;
586 right = n->right;
587 if(left != nil){
588 sumark(left);
589 n->temps = left->temps;
590 }
591 if(right != nil){
592 sumark(right);
593 if(right->temps == n->temps)
594 n->temps++;
595 else if(right->temps > n->temps)
596 n->temps = right->temps;
597 }
598
599 switch(n->op){
600 case Oadr:
601 switch(left->addable){
602 case Rreg:
603 n->addable = Rareg;
604 break;
605 case Rmreg:
606 n->addable = Ramreg;
607 break;
608 case Radr:
609 n->addable = Raadr;
610 break;
611 case Rmadr:
612 n->addable = Ramadr;
613 break;
614 }
615 break;
616 case Oind:
617 switch(left->addable){
618 case Rreg:
619 n->addable = Radr;
620 break;
621 case Rmreg:
622 n->addable = Rmadr;
623 break;
624 case Rareg:
625 n->addable = Rreg;
626 break;
627 case Ramreg:
628 n->addable = Rmreg;
629 break;
630 case Raadr:
631 n->addable = Radr;
632 break;
633 case Ramadr:
634 n->addable = Rmadr;
635 break;
636 }
637 break;
638 case Oname:
639 switch(n->decl->store){
640 case Darg:
641 case Dlocal:
642 n->addable = Rreg;
643 break;
644 case Dglobal:
645 n->addable = Rmreg;
646 if(LDT && n->decl->ty->kind == Tiface)
647 n->addable = Rldt;
648 break;
649 case Dtype:
650 /*
651 * check for inferface to load
652 */
653 if(n->decl->ty->kind == Tmodule)
654 n->addable = Rmreg;
655 break;
656 case Dfn:
657 if(n->flags & FNPTR){
658 if(n->flags == FNPTR2)
659 n->addable = Roff;
660 else if(n->flags == (FNPTR2|FNPTRN))
661 n->addable = Rnoff;
662 }
663 else
664 n->addable = Rpc;
665 break;
666 default:
667 fatal("cannot deal with %K in Oname in %n", n->decl, n);
668 break;
669 }
670 break;
671 case Omdot:
672 n->addable = Rmpc;
673 break;
674 case Oconst:
675 switch(n->ty->kind){
676 case Tint:
677 case Tfix:
678 v = n->val;
679 if(v < 0 && ((v >> 29) & 0x7) != 7
680 || v > 0 && (v >> 29) != 0){
681 n->decl = globalconst(n);
682 n->addable = Rmreg;
683 }else
684 n->addable = Rconst;
685 break;
686 case Tbig:
687 n->decl = globalBconst(n);
688 n->addable = Rmreg;
689 break;
690 case Tbyte:
691 n->decl = globalbconst(n);
692 n->addable = Rmreg;
693 break;
694 case Treal:
695 n->decl = globalfconst(n);
696 n->addable = Rmreg;
697 break;
698 case Tstring:
699 n->decl = globalsconst(n);
700 n->addable = Rmreg;
701 break;
702 default:
703 fatal("cannot %T const in sumark", n->ty);
704 break;
705 }
706 break;
707 case Oadd:
708 if(right->addable == Rconst){
709 switch(left->addable){
710 case Rareg:
711 n->addable = Rareg;
712 break;
713 case Ramreg:
714 n->addable = Ramreg;
715 break;
716 case Rreg:
717 case Raadr:
718 n->addable = Raadr;
719 break;
720 case Rmreg:
721 case Ramadr:
722 n->addable = Ramadr;
723 break;
724 }
725 }
726 break;
727 }
728 if(n->addable < Rcant)
729 n->temps = 0;
730 else if(n->temps == 0)
731 n->temps = 1;
732 return n;
733 }
734
735 Node*
mktn(Type * t)736 mktn(Type *t)
737 {
738 Node *n;
739
740 n = mkn(Oname, nil, nil);
741 usedesc(mktdesc(t));
742 n->ty = t;
743 n->decl = t->decl;
744 if(n->decl == nil)
745 fatal("mktn t %T nil decl", t);
746 n->addable = Rdesc;
747 return n;
748 }
749
750 /* does a tuple of the form (a, b, ...) form a contiguous block
751 * of memory on the stack when offsets are assigned later
752 * - only when (a, b, ...) := rhs and none of the names nil
753 * can we guarantee this
754 */
755 static int
tupblk0(Node * n,Decl ** dd)756 tupblk0(Node *n, Decl **dd)
757 {
758 Decl *d;
759 int nid;
760
761 switch(n->op){
762 case Otuple:
763 for(n = n->left; n != nil; n = n->right)
764 if(!tupblk0(n->left, dd))
765 return 0;
766 return 1;
767 case Oname:
768 if(n->decl == nildecl)
769 return 0;
770 d = *dd;
771 if(d != nil && d->next != n->decl)
772 return 0;
773 nid = n->decl->nid;
774 if(d == nil && nid == 1)
775 return 0;
776 if(d != nil && nid != 0)
777 return 0;
778 *dd = n->decl;
779 return 1;
780 }
781 return 0;
782 }
783
784 /* could force locals to be next to each other
785 * - need to shuffle locals list
786 * - later
787 */
788 static Node*
tupblk(Node * n)789 tupblk(Node *n)
790 {
791 Decl *d;
792
793 if(n->op != Otuple)
794 return nil;
795 d = nil;
796 if(!tupblk0(n, &d))
797 return nil;
798 while(n->op == Otuple)
799 n = n->left->left;
800 if(n->op != Oname || n->decl->nid == 1)
801 fatal("bad tupblk");
802 return n;
803 }
804
805 /* for cprof */
806 #define esrc(src, osrc, nto) (src != nil && nto != nil ? src : osrc)
807
808 /*
809 * compile an expression with an implicit assignment
810 * note: you are not allowed to use to->src
811 *
812 * need to think carefully about the types used in moves
813 * it particular, it would be nice to gen movp rather than movc sometimes.
814 */
815 Node*
ecom(Src * src,Node * nto,Node * n)816 ecom(Src *src, Node *nto, Node *n)
817 {
818 Node *left, *right, *tn;
819 Node tl, tr, tto, ttn;
820 Type *t, *tt;
821 Inst *p, *pp;
822 int op;
823
824 if(debug['e']){
825 print("ecom: %n\n", n);
826 if(nto != nil)
827 print("ecom to: %n\n", nto);
828 }
829
830 if(n->addable < Rcant){
831 /*
832 * think carefully about the type used here
833 */
834 if(nto != nil)
835 genmove(src, Mas, n->ty, n, nto);
836 return nto;
837 }
838
839 tl.decl = nil;
840 tr.decl = nil;
841 tto.decl = nil;
842 ttn.decl = nil;
843
844 left = n->left;
845 right = n->right;
846 op = n->op;
847 switch(op){
848 default:
849 case Oadr:
850 fatal("can't %n in ecom", n);
851 return nto;
852 case Oif:
853 p = bcom(left, 1, nil);
854 ecom(&right->left->src, nto, right->left);
855 if(right->right != nil){
856 pp = p;
857 p = genrawop(&right->left->src, IJMP, nil, nil, nil);
858 patch(pp, nextinst());
859 ecom(&right->right->src, nto, right->right);
860 }
861 patch(p, nextinst());
862 break;
863 case Ocomma:
864 tn = left->left;
865 ecom(&left->src, nil, left);
866 ecom(&right->src, nto, right);
867 tfree(tn);
868 break;
869 case Oname:
870 if(n->addable == Rpc){
871 if(nto != nil)
872 genmove(src, Mas, n->ty, n, nto);
873 return nto;
874 }
875 fatal("can't %n in ecom", n);
876 break;
877 case Onothing:
878 break;
879 case Oused:
880 if(nto != nil)
881 fatal("superfluous used %n to %n", left, nto);
882 talloc(&tto, left->ty, nil);
883 ecom(&left->src, &tto, left);
884 tfree(&tto);
885 break;
886 case Oas:
887 if(right->ty == tany)
888 right->ty = n->ty;
889 if(left->op == Oname && left->decl->ty == tany){
890 if(nto == nil)
891 nto = talloc(&tto, right->ty, nil);
892 left = nto;
893 nto = nil;
894 }
895 if(left->op == Oinds){
896 indsascom(src, nto, n);
897 tfree(&tto);
898 break;
899 }
900 if(left->op == Oslice){
901 slicelcom(src, nto, n);
902 tfree(&tto);
903 break;
904 }
905
906 if(left->op == Otuple){
907 if(!tupsaliased(right, left)){
908 if((tn = tupblk(left)) != nil){
909 tn->ty = n->ty;
910 ecom(&n->right->src, tn, right);
911 if(nto != nil)
912 genmove(src, Mas, n->ty, tn, nto);
913 tfree(&tto);
914 break;
915 }
916 if((tn = tupblk(right)) != nil){
917 tn->ty = n->ty;
918 tuplcom(tn, left);
919 if(nto != nil)
920 genmove(src, Mas, n->ty, tn, nto);
921 tfree(&tto);
922 break;
923 }
924 if(nto == nil && right->op == Otuple && left->ty->kind != Tadtpick){
925 tuplrcom(right, left);
926 tfree(&tto);
927 break;
928 }
929 }
930 if(right->addable >= Ralways
931 || right->op != Oname
932 || tupaliased(right, left)){
933 talloc(&tr, n->ty, nil);
934 ecom(&n->right->src, &tr, right);
935 right = &tr;
936 }
937 tuplcom(right, n->left);
938 if(nto != nil)
939 genmove(src, Mas, n->ty, right, nto);
940 tfree(&tr);
941 tfree(&tto);
942 break;
943 }
944
945 /*
946 * check for left/right aliasing and build right into temporary
947 */
948 if(right->op == Otuple){
949 if(!tupsaliased(left, right) && (tn = tupblk(right)) != nil){
950 tn->ty = n->ty;
951 right = tn;
952 }
953 else if(left->op != Oname || tupaliased(left, right))
954 right = ecom(&right->src, talloc(&tr, right->ty, nil), right);
955 }
956
957 /*
958 * think carefully about types here
959 */
960 if(left->addable >= Rcant)
961 left = eacom(left, &tl, nto);
962 ecom(&n->src, left, right);
963 if(nto != nil)
964 genmove(src, Mas, nto->ty, left, nto);
965 tfree(&tl);
966 tfree(&tr);
967 tfree(&tto);
968 break;
969 case Ochan:
970 if(left && left->addable >= Rcant)
971 left = eacom(left, &tl, nto);
972 genchan(src, left, n->ty->tof, nto);
973 tfree(&tl);
974 break;
975 case Oinds:
976 if(right->addable < Ralways){
977 if(left->addable >= Rcant)
978 left = eacom(left, &tl, nil);
979 }else if(left->temps <= right->temps){
980 right = ecom(&right->src, talloc(&tr, right->ty, nil), right);
981 if(left->addable >= Rcant)
982 left = eacom(left, &tl, nil);
983 }else{
984 left = eacom(left, &tl, nil);
985 right = ecom(&right->src, talloc(&tr, right->ty, nil), right);
986 }
987 genop(&n->src, op, left, right, nto);
988 tfree(&tl);
989 tfree(&tr);
990 break;
991 case Osnd:
992 if(right->addable < Rcant){
993 if(left->addable >= Rcant)
994 left = eacom(left, &tl, nto);
995 }else if(left->temps < right->temps){
996 right = eacom(right, &tr, nto);
997 if(left->addable >= Rcant)
998 left = eacom(left, &tl, nil);
999 }else{
1000 left = eacom(left, &tl, nto);
1001 right = eacom(right, &tr, nil);
1002 }
1003 p = genrawop(&n->src, ISEND, right, nil, left);
1004 p->m.offset = n->ty->size; /* for optimizer */
1005 if(nto != nil)
1006 genmove(src, Mas, right->ty, right, nto);
1007 tfree(&tl);
1008 tfree(&tr);
1009 break;
1010 case Orcv:
1011 if(nto == nil){
1012 ecom(&n->src, talloc(&tto, n->ty, nil), n);
1013 tfree(&tto);
1014 return nil;
1015 }
1016 if(left->addable >= Rcant)
1017 left = eacom(left, &tl, nto);
1018 if(left->ty->kind == Tchan){
1019 p = genrawop(src, IRECV, left, nil, nto);
1020 p->m.offset = n->ty->size; /* for optimizer */
1021 }else{
1022 recvacom(src, nto, n);
1023 }
1024 tfree(&tl);
1025 break;
1026 case Ocons:
1027 /*
1028 * another temp which can go with analysis
1029 */
1030 if(left->addable >= Rcant)
1031 left = eacom(left, &tl, nil);
1032 if(!sameaddr(right, nto)){
1033 ecom(&right->src, talloc(&tto, n->ty, nto), right);
1034 genmove(src, Mcons, left->ty, left, &tto);
1035 if(!sameaddr(&tto, nto))
1036 genmove(src, Mas, nto->ty, &tto, nto);
1037 }else
1038 genmove(src, Mcons, left->ty, left, nto);
1039 tfree(&tl);
1040 tfree(&tto);
1041 break;
1042 case Ohd:
1043 if(left->addable >= Rcant)
1044 left = eacom(left, &tl, nto);
1045 genmove(src, Mhd, nto->ty, left, nto);
1046 tfree(&tl);
1047 break;
1048 case Otl:
1049 if(left->addable >= Rcant)
1050 left = eacom(left, &tl, nto);
1051 genmove(src, Mtl, left->ty, left, nto);
1052 tfree(&tl);
1053 break;
1054 case Otuple:
1055 if((tn = tupblk(n)) != nil){
1056 tn->ty = n->ty;
1057 genmove(src, Mas, n->ty, tn, nto);
1058 break;
1059 }
1060 tupcom(nto, n);
1061 break;
1062 case Oadd:
1063 case Osub:
1064 case Omul:
1065 case Odiv:
1066 case Omod:
1067 case Oand:
1068 case Oor:
1069 case Oxor:
1070 case Olsh:
1071 case Orsh:
1072 case Oexp:
1073 /*
1074 * check for 2 operand forms
1075 */
1076 if(sameaddr(nto, left)){
1077 if(right->addable >= Rcant)
1078 right = eacom(right, &tr, nto);
1079 genop(src, op, right, nil, nto);
1080 tfree(&tr);
1081 break;
1082 }
1083
1084 if(opcommute[op] && sameaddr(nto, right) && n->ty != tstring){
1085 if(left->addable >= Rcant)
1086 left = eacom(left, &tl, nto);
1087 genop(src, opcommute[op], left, nil, nto);
1088 tfree(&tl);
1089 break;
1090 }
1091
1092 if(right->addable < left->addable
1093 && opcommute[op]
1094 && n->ty != tstring){
1095 op = opcommute[op];
1096 left = right;
1097 right = n->left;
1098 }
1099 if(left->addable < Ralways){
1100 if(right->addable >= Rcant)
1101 right = eacom(right, &tr, nto);
1102 }else if(right->temps <= left->temps){
1103 left = ecom(&left->src, talloc(&tl, left->ty, nto), left);
1104 if(right->addable >= Rcant)
1105 right = eacom(right, &tr, nil);
1106 }else{
1107 right = eacom(right, &tr, nto);
1108 left = ecom(&left->src, talloc(&tl, left->ty, nil), left);
1109 }
1110
1111 /*
1112 * check for 2 operand forms
1113 */
1114 if(sameaddr(nto, left))
1115 genop(src, op, right, nil, nto);
1116 else if(opcommute[op] && sameaddr(nto, right) && n->ty != tstring)
1117 genop(src, opcommute[op], left, nil, nto);
1118 else
1119 genop(src, op, right, left, nto);
1120 tfree(&tl);
1121 tfree(&tr);
1122 break;
1123 case Oaddas:
1124 case Osubas:
1125 case Omulas:
1126 case Odivas:
1127 case Omodas:
1128 case Oexpas:
1129 case Oandas:
1130 case Ooras:
1131 case Oxoras:
1132 case Olshas:
1133 case Orshas:
1134 if(left->op == Oinds){
1135 indsascom(src, nto, n);
1136 break;
1137 }
1138 if(right->addable < Rcant){
1139 if(left->addable >= Rcant)
1140 left = eacom(left, &tl, nto);
1141 }else if(left->temps < right->temps){
1142 right = eacom(right, &tr, nto);
1143 if(left->addable >= Rcant)
1144 left = eacom(left, &tl, nil);
1145 }else{
1146 left = eacom(left, &tl, nto);
1147 right = eacom(right, &tr, nil);
1148 }
1149 genop(&n->src, op, right, nil, left);
1150 if(nto != nil)
1151 genmove(src, Mas, left->ty, left, nto);
1152 tfree(&tl);
1153 tfree(&tr);
1154 break;
1155 case Olen:
1156 if(left->addable >= Rcant)
1157 left = eacom(left, &tl, nto);
1158 op = -1;
1159 t = left->ty;
1160 if(t == tstring)
1161 op = ILENC;
1162 else if(t->kind == Tarray)
1163 op = ILENA;
1164 else if(t->kind == Tlist)
1165 op = ILENL;
1166 else
1167 fatal("can't len %n", n);
1168 genrawop(src, op, left, nil, nto);
1169 tfree(&tl);
1170 break;
1171 case Oneg:
1172 if(left->addable >= Rcant)
1173 left = eacom(left, &tl, nto);
1174 genop(&n->src, op, left, nil, nto);
1175 tfree(&tl);
1176 break;
1177 case Oinc:
1178 case Odec:
1179 if(left->op == Oinds){
1180 indsascom(src, nto, n);
1181 break;
1182 }
1183 if(left->addable >= Rcant)
1184 left = eacom(left, &tl, nil);
1185 if(nto != nil)
1186 genmove(src, Mas, left->ty, left, nto);
1187 if(right->addable >= Rcant)
1188 fatal("inc/dec amount not addressable: %n", n);
1189 genop(&n->src, op, right, nil, left);
1190 tfree(&tl);
1191 break;
1192 case Ospawn:
1193 if(left->left->op == Oind)
1194 fpcall(&n->src, op, left, nto);
1195 else
1196 callcom(&n->src, op, left, nto);
1197 break;
1198 case Oraise:
1199 if(left->addable >= Rcant)
1200 left = eacom(left, &tl, nil);
1201 genrawop(&n->src, IRAISE, left, nil, nil);
1202 tfree(&tl);
1203 break;
1204 case Ocall:
1205 if(left->op == Oind)
1206 fpcall(esrc(src, &n->src, nto), op, n, nto);
1207 else
1208 callcom(esrc(src, &n->src, nto), op, n, nto);
1209 break;
1210 case Oref:
1211 t = left->ty;
1212 if(left->op == Oname && left->decl->store == Dfn || left->op == Omdot && left->right->op == Oname && left->right->decl->store == Dfn){ /* create a function reference */
1213 Decl *d;
1214 Node *mod, *ind;
1215
1216 d = left->decl;
1217 if(left->op == Omdot){
1218 d = left->right->decl;
1219 mod = left->left;
1220 }
1221 else if(d->eimport != nil)
1222 mod = d->eimport;
1223 else{
1224 mod = rewrite(mkn(Oself, nil, nil));
1225 addiface(nil, d);
1226 }
1227 sumark(mod);
1228 talloc(&tto, n->ty, nto);
1229 genrawop(src, INEW, mktn(usetype(tfnptr)), nil, &tto);
1230 tr.src = *src;
1231 tr.op = Oind;
1232 tr.left = &tto;
1233 tr.right = nil;
1234 tr.ty = tany;
1235 sumark(&tr);
1236 ecom(src, &tr, mod);
1237 ind = mkunary(Oind, mkbin(Oadd, dupn(0, src, &tto), mkconst(src, IBY2WD)));
1238 ind->ty = ind->left->ty = ind->left->right->ty = tint;
1239 tr.op = Oas;
1240 tr.left = ind;
1241 tr.right = mkdeclname(src, d);
1242 tr.ty = tr.right->ty = tint;
1243 sumark(&tr);
1244 tr.right->addable = mod->op == Oself && newfnptr ? Rnoff : Roff;
1245 ecom(src, nil, &tr);
1246 if(!sameaddr(&tto, nto))
1247 genmove(src, Mas, n->ty, &tto, nto);
1248 tfree(&tto);
1249 break;
1250 }
1251 if(left->op == Oname && left->decl->store == Dtype){
1252 genrawop(src, INEW, mktn(t), nil, nto);
1253 break;
1254 }
1255 if(t->kind == Tadt && t->tags != nil){
1256 pickdupcom(src, nto, left);
1257 break;
1258 }
1259
1260 tt = t;
1261 if(left->op == Oconst && left->decl->store == Dtag)
1262 t = left->decl->ty->tof;
1263 /*
1264 * could eliminate temp if to does not occur
1265 * in tuple initializer
1266 */
1267 talloc(&tto, n->ty, nto);
1268 genrawop(src, INEW, mktn(t), nil, &tto);
1269 tr.op = Oind;
1270 tr.left = &tto;
1271 tr.right = nil;
1272 tr.ty = tt;
1273 sumark(&tr);
1274 ecom(src, &tr, left);
1275 if(!sameaddr(&tto, nto))
1276 genmove(src, Mas, n->ty, &tto, nto);
1277 tfree(&tto);
1278 break;
1279 case Oload:
1280 if(left->addable >= Rcant)
1281 left = eacom(left, &tl, nto);
1282 talloc(&tr, tint, nil);
1283 if(LDT)
1284 genrawop(src, ILOAD, left, right, nto);
1285 else{
1286 genrawop(src, ILEA, right, nil, &tr);
1287 genrawop(src, ILOAD, left, &tr, nto);
1288 }
1289 tfree(&tl);
1290 tfree(&tr);
1291 break;
1292 case Ocast:
1293 if(left->addable >= Rcant)
1294 left = eacom(left, &tl, nto);
1295 t = left->ty;
1296 if(t->kind == Tfix || n->ty->kind == Tfix){
1297 op = casttab[t->kind][n->ty->kind];
1298 if(op == ICVTXX)
1299 genfixcastop(src, op, left, nto);
1300 else{
1301 tn = sumark(mkrconst(src, scale2(t, n->ty)));
1302 genrawop(src, op, left, tn, nto);
1303 }
1304 }
1305 else
1306 genrawop(src, casttab[t->kind][n->ty->kind], left, nil, nto);
1307 tfree(&tl);
1308 break;
1309 case Oarray:
1310 if(left->addable >= Rcant)
1311 left = eacom(left, &tl, nto);
1312 genrawop(esrc(src, &left->src, nto), arrayz ? INEWAZ : INEWA, left, mktn(n->ty->tof), nto);
1313 if(right != nil)
1314 arraycom(nto, right);
1315 tfree(&tl);
1316 break;
1317 case Oslice:
1318 tn = right->right;
1319 right = right->left;
1320
1321 /*
1322 * make the left node of the slice directly addressable
1323 * therefore, if it's len is taken (via tn),
1324 * left's tree won't be rewritten
1325 */
1326 if(left->addable >= Rcant)
1327 left = eacom(left, &tl, nil);
1328
1329 if(tn->op == Onothing){
1330 tn = mkn(Olen, left, nil);
1331 tn->src = *src;
1332 tn->ty = tint;
1333 sumark(tn);
1334 }
1335 if(tn->addable < Ralways){
1336 if(right->addable >= Rcant)
1337 right = eacom(right, &tr, nil);
1338 }else if(right->temps <= tn->temps){
1339 tn = ecom(&tn->src, talloc(&ttn, tn->ty, nil), tn);
1340 if(right->addable >= Rcant)
1341 right = eacom(right, &tr, nil);
1342 }else{
1343 right = eacom(right, &tr, nil);
1344 tn = ecom(&tn->src, talloc(&ttn, tn->ty, nil), tn);
1345 }
1346 op = ISLICEA;
1347 if(nto->ty == tstring)
1348 op = ISLICEC;
1349
1350 /*
1351 * overwrite the destination last,
1352 * since it might be used in computing the slice bounds
1353 */
1354 if(!sameaddr(left, nto))
1355 ecom(&left->src, nto, left);
1356
1357 genrawop(src, op, right, tn, nto);
1358 tfree(&tl);
1359 tfree(&tr);
1360 tfree(&ttn);
1361 break;
1362 case Oindx:
1363 if(right->addable < Rcant){
1364 if(left->addable >= Rcant)
1365 left = eacom(left, &tl, nto);
1366 }else if(left->temps < right->temps){
1367 right = eacom(right, &tr, nto);
1368 if(left->addable >= Rcant)
1369 left = eacom(left, &tl, nil);
1370 }else{
1371 left = eacom(left, &tl, nto);
1372 right = eacom(right, &tr, nil);
1373 }
1374 if(nto->addable >= Ralways)
1375 nto = ecom(src, talloc(&tto, nto->ty, nil), nto);
1376 op = IINDX;
1377 switch(left->ty->tof->size){
1378 case IBY2LG:
1379 op = IINDL;
1380 if(left->ty->tof == treal)
1381 op = IINDF;
1382 break;
1383 case IBY2WD:
1384 op = IINDW;
1385 break;
1386 case 1:
1387 op = IINDB;
1388 break;
1389 }
1390 genrawop(src, op, left, nto, right);
1391 // array[] of {....} [index] frees array too early (before index value used)
1392 // function(...) [index] frees array too early (before index value used)
1393 if(tl.decl != nil)
1394 tfreelater(&tl);
1395 else
1396 tfree(&tl);
1397 tfree(&tr);
1398 tfree(&tto);
1399 break;
1400 case Oind:
1401 n = eacom(n, &tl, nto);
1402 genmove(src, Mas, n->ty, n, nto);
1403 tfree(&tl);
1404 break;
1405 case Onot:
1406 case Oandand:
1407 case Ooror:
1408 case Oeq:
1409 case Oneq:
1410 case Olt:
1411 case Oleq:
1412 case Ogt:
1413 case Ogeq:
1414 p = bcom(n, 1, nil);
1415 genmove(src, Mas, tint, sumark(mkconst(src, 1)), nto);
1416 pp = genrawop(src, IJMP, nil, nil, nil);
1417 patch(p, nextinst());
1418 genmove(src, Mas, tint, sumark(mkconst(src, 0)), nto);
1419 patch(pp, nextinst());
1420 break;
1421 case Oself:
1422 if(newfnptr){
1423 if(nto != nil)
1424 genrawop(src, ISELF, nil, nil, nto);
1425 break;
1426 }
1427 tn = sumark(mkdeclname(src, selfdecl));
1428 p = genbra(src, Oneq, tn, sumark(mkdeclname(src, nildecl)));
1429 n->op = Oload;
1430 ecom(src, tn, n);
1431 patch(p, nextinst());
1432 genmove(src, Mas, n->ty, tn, nto);
1433 break;
1434 }
1435 return nto;
1436 }
1437
1438 /*
1439 * compile exp n to yield an addressable expression
1440 * use reg to build a temporary; if t is a temp, it is usable
1441 * if dangle leaves the address dangling, generate into a temporary
1442 * this should only happen with arrays
1443 *
1444 * note that 0adr's are strange as they are only used
1445 * for calculating the addresses of fields within adt's.
1446 * therefore an Oind is the parent or grandparent of the Oadr,
1447 * and we pick off all of the cases where Oadr's argument is not
1448 * addressable by looking from the Oind.
1449 */
1450 Node*
eacom(Node * n,Node * reg,Node * t)1451 eacom(Node *n, Node *reg, Node *t)
1452 {
1453 Node *left, *tn;
1454
1455 if(n->op == Ocomma){
1456 tn = n->left->left;
1457 ecom(&n->left->src, nil, n->left);
1458 n = eacom(n->right, reg, t);
1459 tfree(tn);
1460 return n;
1461 }
1462
1463 if(debug['e'] || debug['E'])
1464 print("eacom: %n\n", n);
1465
1466 left = n->left;
1467 if(n->op != Oind){
1468 ecom(&n->src, talloc(reg, n->ty, t), n);
1469 reg->src = n->src;
1470 return reg;
1471 }
1472
1473 if(left->op == Oadd && left->right->op == Oconst){
1474 if(left->left->op == Oadr){
1475 left->left->left = eacom(left->left->left, reg, t);
1476 sumark(n);
1477 if(n->addable >= Rcant)
1478 fatal("eacom can't make node addressable: %n", n);
1479 return n;
1480 }
1481 talloc(reg, left->left->ty, t);
1482 ecom(&left->left->src, reg, left->left);
1483 left->left->decl = reg->decl;
1484 left->left->addable = Rreg;
1485 left->left = reg;
1486 left->addable = Raadr;
1487 n->addable = Radr;
1488 }else if(left->op == Oadr){
1489 talloc(reg, left->left->ty, t);
1490 ecom(&left->left->src, reg, left->left);
1491
1492 /*
1493 * sleaze: treat the temp as the type of the field, not the enclosing structure
1494 */
1495 reg->ty = n->ty;
1496 reg->src = n->src;
1497 return reg;
1498 }else{
1499 talloc(reg, left->ty, t);
1500 ecom(&left->src, reg, left);
1501 n->left = reg;
1502 n->addable = Radr;
1503 }
1504 return n;
1505 }
1506
1507 /*
1508 * compile an assignment to an array slice
1509 */
1510 Node*
slicelcom(Src * src,Node * nto,Node * n)1511 slicelcom(Src *src, Node *nto, Node *n)
1512 {
1513 Node *left, *right, *v;
1514 Node tl, tr, tv, tu;
1515
1516 tl.decl = nil;
1517 tr.decl = nil;
1518 tv.decl = nil;
1519 tu.decl = nil;
1520
1521 left = n->left->left;
1522 right = n->left->right->left;
1523 v = n->right;
1524 if(right->addable < Ralways){
1525 if(left->addable >= Rcant)
1526 left = eacom(left, &tl, nto);
1527 }else if(left->temps <= right->temps){
1528 right = ecom(&right->src, talloc(&tr, right->ty, nto), right);
1529 if(left->addable >= Rcant)
1530 left = eacom(left, &tl, nil);
1531 }else{
1532 left = eacom(left, &tl, nil); /* dangle on right and v */
1533 right = ecom(&right->src, talloc(&tr, right->ty, nil), right);
1534 }
1535
1536 switch(n->op){
1537 case Oas:
1538 if(v->addable >= Rcant)
1539 v = eacom(v, &tv, nil);
1540 break;
1541 }
1542
1543 genrawop(&n->src, ISLICELA, v, right, left);
1544 if(nto != nil)
1545 genmove(src, Mas, n->ty, left, nto);
1546 tfree(&tl);
1547 tfree(&tv);
1548 tfree(&tr);
1549 tfree(&tu);
1550 return nto;
1551 }
1552
1553 /*
1554 * compile an assignment to a string location
1555 */
1556 Node*
indsascom(Src * src,Node * nto,Node * n)1557 indsascom(Src *src, Node *nto, Node *n)
1558 {
1559 Node *left, *right, *u, *v;
1560 Node tl, tr, tv, tu;
1561
1562 tl.decl = nil;
1563 tr.decl = nil;
1564 tv.decl = nil;
1565 tu.decl = nil;
1566
1567 left = n->left->left;
1568 right = n->left->right;
1569 v = n->right;
1570 if(right->addable < Ralways){
1571 if(left->addable >= Rcant)
1572 left = eacom(left, &tl, nto);
1573 }else if(left->temps <= right->temps){
1574 right = ecom(&right->src, talloc(&tr, right->ty, nto), right);
1575 if(left->addable >= Rcant)
1576 left = eacom(left, &tl, nil);
1577 }else{
1578 left = eacom(left, &tl, nil); /* dangle on right and v */
1579 right = ecom(&right->src, talloc(&tr, right->ty, nil), right);
1580 }
1581
1582 switch(n->op){
1583 case Oas:
1584 if(v->addable >= Rcant)
1585 v = eacom(v, &tv, nil);
1586 break;
1587 case Oinc:
1588 case Odec:
1589 if(v->addable >= Rcant)
1590 fatal("inc/dec amount not addable");
1591 u = talloc(&tu, tint, nil);
1592 genop(&n->left->src, Oinds, left, right, u);
1593 if(nto != nil)
1594 genmove(src, Mas, n->ty, u, nto);
1595 nto = nil;
1596 genop(&n->src, n->op, v, nil, u);
1597 v = u;
1598 break;
1599 case Oaddas:
1600 case Osubas:
1601 case Omulas:
1602 case Odivas:
1603 case Omodas:
1604 case Oexpas:
1605 case Oandas:
1606 case Ooras:
1607 case Oxoras:
1608 case Olshas:
1609 case Orshas:
1610 if(v->addable >= Rcant)
1611 v = eacom(v, &tv, nil);
1612 u = talloc(&tu, tint, nil);
1613 genop(&n->left->src, Oinds, left, right, u);
1614 genop(&n->src, n->op, v, nil, u);
1615 v = u;
1616 break;
1617 }
1618
1619 genrawop(&n->src, IINSC, v, right, left);
1620 tfree(&tl);
1621 tfree(&tv);
1622 tfree(&tr);
1623 tfree(&tu);
1624 if(nto != nil)
1625 genmove(src, Mas, n->ty, v, nto);
1626 return nto;
1627 }
1628
1629 void
callcom(Src * src,int op,Node * n,Node * ret)1630 callcom(Src *src, int op, Node *n, Node *ret)
1631 {
1632 Node frame, tadd, toff, pass, *a, *mod, *ind, *nfn, *args, tmod, tind, *tn;
1633 Inst *in,*p;
1634 Decl *d, *callee;
1635 long off;
1636 int iop;
1637
1638 args = n->right;
1639 nfn = n->left;
1640 switch(nfn->op){
1641 case Odot:
1642 callee = nfn->right->decl;
1643 nfn->addable = Rpc;
1644 break;
1645 case Omdot:
1646 callee = nfn->right->decl;
1647 break;
1648 case Oname:
1649 callee = nfn->decl;
1650 break;
1651 default:
1652 callee = nil;
1653 fatal("bad call op in callcom");
1654 }
1655 if(nfn->addable != Rpc && nfn->addable != Rmpc)
1656 fatal("can't gen call addresses");
1657 if(nfn->ty->tof != tnone && ret == nil){
1658 ecom(src, talloc(&tmod, nfn->ty->tof, nil), n);
1659 tfree(&tmod);
1660 return;
1661 }
1662 if(ispoly(callee))
1663 addfnptrs(callee, 0);
1664 if(nfn->ty->varargs){
1665 nfn->decl = dupdecl(nfn->right->decl);
1666 nfn->decl->desc = gendesc(nfn->right->decl, idoffsets(nfn->ty->ids, MaxTemp, MaxAlign), nfn->ty->ids);
1667 }
1668
1669 talloc(&frame, tint, nil);
1670
1671 mod = nfn->left;
1672 ind = nfn->right;
1673 tmod.decl = tind.decl = nil;
1674 if(nfn->addable == Rmpc){
1675 if(mod->addable >= Rcant)
1676 mod = eacom(mod, &tmod, nil); /* dangle always */
1677 if(ind->op != Oname && ind->addable >= Ralways){
1678 talloc(&tind, ind->ty, nil);
1679 ecom(&ind->src, &tind, ind);
1680 ind = &tind;
1681 }
1682 else if(ind->decl != nil && ind->decl->store != Darg)
1683 ind->addable = Roff;
1684 }
1685
1686 /*
1687 * stop nested uncalled frames
1688 * otherwise exception handling very complicated
1689 */
1690 for(a = args; a != nil; a = a->right){
1691 if(hascall(a->left)){
1692 tn = mkn(0, nil, nil);
1693 talloc(tn, a->left->ty, nil);
1694 ecom(&a->left->src, tn, a->left);
1695 a->left = tn;
1696 tn->flags |= TEMP;
1697 }
1698 }
1699
1700 /*
1701 * allocate the frame
1702 */
1703 if(nfn->addable == Rmpc && !nfn->ty->varargs){
1704 genrawop(src, IMFRAME, mod, ind, &frame);
1705 }else if(nfn->op == Odot){
1706 genrawop(src, IFRAME, nfn->left, nil, &frame);
1707 }else{
1708 in = genrawop(src, IFRAME, nil, nil, &frame);
1709 in->sm = Adesc;
1710 in->s.decl = nfn->decl;
1711 }
1712
1713 /*
1714 * build a fake node for the argument area
1715 */
1716 toff = znode;
1717 tadd = znode;
1718 pass = znode;
1719 toff.op = Oconst;
1720 toff.addable = Rconst;
1721 toff.ty = tint;
1722 tadd.op = Oadd;
1723 tadd.addable = Raadr;
1724 tadd.left = &frame;
1725 tadd.right = &toff;
1726 tadd.ty = tint;
1727 pass.op = Oind;
1728 pass.addable = Radr;
1729 pass.left = &tadd;
1730
1731 /*
1732 * compile all the args
1733 */
1734 d = nfn->ty->ids;
1735 off = 0;
1736 for(a = args; a != nil; a = a->right){
1737 off = d->offset;
1738 toff.val = off;
1739 if(d->ty->kind == Tpoly)
1740 pass.ty = a->left->ty;
1741 else
1742 pass.ty = d->ty;
1743 ecom(&a->left->src, &pass, a->left);
1744 d = d->next;
1745 if(a->left->flags & TEMP)
1746 tfree(a->left);
1747 }
1748 if(off > maxstack)
1749 maxstack = off;
1750
1751 /*
1752 * pass return value
1753 */
1754 if(ret != nil){
1755 toff.val = REGRET*IBY2WD;
1756 pass.ty = nfn->ty->tof;
1757 p = genrawop(src, ILEA, ret, nil, &pass);
1758 p->m.offset = ret->ty->size; /* for optimizer */
1759 }
1760
1761 /*
1762 * call it
1763 */
1764 if(nfn->addable == Rmpc){
1765 iop = IMCALL;
1766 if(op == Ospawn)
1767 iop = IMSPAWN;
1768 genrawop(src, iop, &frame, ind, mod);
1769 tfree(&tmod);
1770 tfree(&tind);
1771 }else if(nfn->op == Odot){
1772 iop = ICALL;
1773 if(op == Ospawn)
1774 iop = ISPAWN;
1775 genrawop(src, iop, &frame, nil, nfn->right);
1776 }else{
1777 iop = ICALL;
1778 if(op == Ospawn)
1779 iop = ISPAWN;
1780 in = genrawop(src, iop, &frame, nil, nil);
1781 in->d.decl = nfn->decl;
1782 in->dm = Apc;
1783 }
1784 tfree(&frame);
1785 }
1786
1787 /*
1788 * initialization code for arrays
1789 * a must be addressable (< Rcant)
1790 */
1791 void
arraycom(Node * a,Node * elems)1792 arraycom(Node *a, Node *elems)
1793 {
1794 Node tindex, fake, tmp, ri, *e, *n, *q, *body, *wild;
1795 Inst *top, *out;
1796 /* Case *c; */
1797
1798 if(debug['A'])
1799 print("arraycom: %n %n\n", a, elems);
1800
1801 /* c = elems->ty->cse; */
1802 /* don't use c->wild in case we've been inlined */
1803 wild = nil;
1804 for(e = elems; e != nil; e = e->right)
1805 for(q = e->left->left; q != nil; q = q->right)
1806 if(q->left->op == Owild)
1807 wild = e->left;
1808 if(wild != nil)
1809 arraydefault(a, wild->right);
1810
1811 tindex = znode;
1812 fake = znode;
1813 talloc(&tmp, tint, nil);
1814 tindex.op = Oindx;
1815 tindex.addable = Rcant;
1816 tindex.left = a;
1817 tindex.right = nil;
1818 tindex.ty = tint;
1819 fake.op = Oind;
1820 fake.addable = Radr;
1821 fake.left = &tmp;
1822 fake.ty = a->ty->tof;
1823
1824 for(e = elems; e != nil; e = e->right){
1825 /*
1826 * just duplicate the initializer for Oor
1827 */
1828 for(q = e->left->left; q != nil; q = q->right){
1829 if(q->left->op == Owild)
1830 continue;
1831
1832 body = e->left->right;
1833 if(q->right != nil)
1834 body = dupn(0, &nosrc, body);
1835 top = nil;
1836 out = nil;
1837 ri.decl = nil;
1838 if(q->left->op == Orange){
1839 /*
1840 * for(i := q.left.left; i <= q.left.right; i++)
1841 */
1842 talloc(&ri, tint, nil);
1843 ri.src = q->left->src;
1844 ecom(&q->left->src, &ri, q->left->left);
1845
1846 /* i <= q.left.right; */
1847 n = mkn(Oleq, &ri, q->left->right);
1848 n->src = q->left->src;
1849 n->ty = tint;
1850 top = nextinst();
1851 out = bcom(n, 1, nil);
1852
1853 tindex.right = &ri;
1854 }else{
1855 tindex.right = q->left;
1856 }
1857
1858 tindex.addable = Rcant;
1859 tindex.src = q->left->src;
1860 ecom(&tindex.src, &tmp, &tindex);
1861
1862 ecom(&body->src, &fake, body);
1863
1864 if(q->left->op == Orange){
1865 /* i++ */
1866 n = mkbin(Oinc, &ri, sumark(mkconst(&ri.src, 1)));
1867 n->ty = tint;
1868 n->addable = Rcant;
1869 ecom(&n->src, nil, n);
1870
1871 /* jump to test */
1872 patch(genrawop(&q->left->src, IJMP, nil, nil, nil), top);
1873 patch(out, nextinst());
1874 tfree(&ri);
1875 }
1876 }
1877 }
1878 tfree(&tmp);
1879 }
1880
1881 /*
1882 * default initialization code for arrays.
1883 * compiles to
1884 * n = len a;
1885 * while(n){
1886 * n--;
1887 * a[n] = elem;
1888 * }
1889 */
1890 void
arraydefault(Node * a,Node * elem)1891 arraydefault(Node *a, Node *elem)
1892 {
1893 Inst *out, *top;
1894 Node n, e, *t;
1895
1896 if(debug['A'])
1897 print("arraydefault: %n %n\n", a, elem);
1898
1899 t = mkn(Olen, a, nil);
1900 t->src = elem->src;
1901 t->ty = tint;
1902 t->addable = Rcant;
1903 talloc(&n, tint, nil);
1904 n.src = elem->src;
1905 ecom(&t->src, &n, t);
1906
1907 top = nextinst();
1908 out = bcom(&n, 1, nil);
1909
1910 t = mkbin(Odec, &n, sumark(mkconst(&elem->src, 1)));
1911 t->ty = tint;
1912 t->addable = Rcant;
1913 ecom(&t->src, nil, t);
1914
1915 e.decl = nil;
1916 if(elem->addable >= Rcant)
1917 elem = eacom(elem, &e, nil);
1918
1919 t = mkn(Oindx, a, &n);
1920 t->src = elem->src;
1921 t = mkbin(Oas, mkunary(Oind, t), elem);
1922 t->ty = elem->ty;
1923 t->left->ty = elem->ty;
1924 t->left->left->ty = tint;
1925 sumark(t);
1926 ecom(&t->src, nil, t);
1927
1928 patch(genrawop(&t->src, IJMP, nil, nil, nil), top);
1929
1930 tfree(&n);
1931 tfree(&e);
1932 patch(out, nextinst());
1933 }
1934
1935 void
tupcom(Node * nto,Node * n)1936 tupcom(Node *nto, Node *n)
1937 {
1938 Node tadr, tadd, toff, fake, *e;
1939 Decl *d;
1940
1941 if(debug['Y'])
1942 print("tupcom %n\nto %n\n", n, nto);
1943
1944 /*
1945 * build a fake node for the tuple
1946 */
1947 toff = znode;
1948 tadd = znode;
1949 fake = znode;
1950 tadr = znode;
1951 toff.op = Oconst;
1952 toff.ty = tint;
1953 tadr.op = Oadr;
1954 tadr.left = nto;
1955 tadr.ty = tint;
1956 tadd.op = Oadd;
1957 tadd.left = &tadr;
1958 tadd.right = &toff;
1959 tadd.ty = tint;
1960 fake.op = Oind;
1961 fake.left = &tadd;
1962 sumark(&fake);
1963 if(fake.addable >= Rcant)
1964 fatal("tupcom: bad value exp %n", &fake);
1965
1966 /*
1967 * compile all the exps
1968 */
1969 d = n->ty->ids;
1970 for(e = n->left; e != nil; e = e->right){
1971 toff.val = d->offset;
1972 fake.ty = d->ty;
1973 ecom(&e->left->src, &fake, e->left);
1974 d = d->next;
1975 }
1976 }
1977
1978 void
tuplcom(Node * n,Node * nto)1979 tuplcom(Node *n, Node *nto)
1980 {
1981 Node tadr, tadd, toff, fake, tas, *e, *as;
1982 Decl *d;
1983
1984 if(debug['Y'])
1985 print("tuplcom %n\nto %n\n", n, nto);
1986
1987 /*
1988 * build a fake node for the tuple
1989 */
1990 toff = znode;
1991 tadd = znode;
1992 fake = znode;
1993 tadr = znode;
1994 toff.op = Oconst;
1995 toff.ty = tint;
1996 tadr.op = Oadr;
1997 tadr.left = n;
1998 tadr.ty = tint;
1999 tadd.op = Oadd;
2000 tadd.left = &tadr;
2001 tadd.right = &toff;
2002 tadd.ty = tint;
2003 fake.op = Oind;
2004 fake.left = &tadd;
2005 sumark(&fake);
2006 if(fake.addable >= Rcant)
2007 fatal("tuplcom: bad value exp for %n", &fake);
2008
2009 /*
2010 * compile all the exps
2011 */
2012 d = nto->ty->ids;
2013 if(nto->ty->kind == Tadtpick)
2014 d = nto->ty->tof->ids->next;
2015 for(e = nto->left; e != nil; e = e->right){
2016 as = e->left;
2017 if(as->op != Oname || as->decl != nildecl){
2018 toff.val = d->offset;
2019 fake.ty = d->ty;
2020 fake.src = as->src;
2021 if(as->addable < Rcant)
2022 genmove(&as->src, Mas, d->ty, &fake, as);
2023 else{
2024 tas.op = Oas;
2025 tas.ty = d->ty;
2026 tas.src = as->src;
2027 tas.left = as;
2028 tas.right = &fake;
2029 tas.addable = Rcant;
2030 ecom(&tas.src, nil, &tas);
2031 }
2032 }
2033 d = d->next;
2034 }
2035 }
2036
2037 void
tuplrcom(Node * n,Node * nto)2038 tuplrcom(Node *n, Node *nto)
2039 {
2040 Node *s, *d, tas;
2041 Decl *de;
2042
2043 de = nto->ty->ids;
2044 for(s = n->left, d = nto->left; s != nil && d != nil; s = s->right, d = d->right){
2045 if(d->left->op != Oname || d->left->decl != nildecl){
2046 tas.op = Oas;
2047 tas.ty = de->ty;
2048 tas.src = s->left->src;
2049 tas.left = d->left;
2050 tas.right = s->left;
2051 sumark(&tas);
2052 ecom(&tas.src, nil, &tas);
2053 }
2054 de = de->next;
2055 }
2056 if(s != nil || d != nil)
2057 fatal("tuplrcom");
2058 }
2059
2060 /*
2061 * boolean compiler
2062 * fall through when condition == true
2063 */
2064 Inst*
bcom(Node * n,int iftrue,Inst * b)2065 bcom(Node *n, int iftrue, Inst *b)
2066 {
2067 Inst *bb;
2068 Node tl, tr, *t, *left, *right, *tn;
2069 int op;
2070
2071 if(n->op == Ocomma){
2072 tn = n->left->left;
2073 ecom(&n->left->src, nil, n->left);
2074 bb = bcom(n->right, iftrue, b);
2075 tfree(tn);
2076 return bb;
2077 }
2078
2079 if(debug['b'])
2080 print("bcom %n %d\n", n, iftrue);
2081
2082 left = n->left;
2083 right = n->right;
2084 op = n->op;
2085
2086 switch(op){
2087 case Onothing:
2088 return b;
2089 case Onot:
2090 return bcom(n->left, !iftrue, b);
2091 case Oandand:
2092 if(!iftrue)
2093 return oror(n, iftrue, b);
2094 return andand(n, iftrue, b);
2095 case Ooror:
2096 if(!iftrue)
2097 return andand(n, iftrue, b);
2098 return oror(n, iftrue, b);
2099 case Ogt:
2100 case Ogeq:
2101 case Oneq:
2102 case Oeq:
2103 case Olt:
2104 case Oleq:
2105 break;
2106 default:
2107 if(n->ty->kind == Tint){
2108 right = mkconst(&n->src, 0);
2109 right->addable = Rconst;
2110 left = n;
2111 op = Oneq;
2112 break;
2113 }
2114 fatal("can't bcom %n", n);
2115 return b;
2116 }
2117
2118 if(iftrue)
2119 op = oprelinvert[op];
2120
2121 if(left->addable < right->addable){
2122 t = left;
2123 left = right;
2124 right = t;
2125 op = opcommute[op];
2126 }
2127
2128 tl.decl = nil;
2129 tr.decl = nil;
2130 if(right->addable < Ralways){
2131 if(left->addable >= Rcant)
2132 left = eacom(left, &tl, nil);
2133 }else if(left->temps <= right->temps){
2134 right = ecom(&right->src, talloc(&tr, right->ty, nil), right);
2135 if(left->addable >= Rcant)
2136 left = eacom(left, &tl, nil);
2137 }else{
2138 left = eacom(left, &tl, nil);
2139 right = ecom(&right->src, talloc(&tr, right->ty, nil), right);
2140 }
2141 bb = genbra(&n->src, op, left, right);
2142 bb->branch = b;
2143 tfree(&tl);
2144 tfree(&tr);
2145 return bb;
2146 }
2147
2148 Inst*
andand(Node * n,int iftrue,Inst * b)2149 andand(Node *n, int iftrue, Inst *b)
2150 {
2151 if(debug['b'])
2152 print("andand %n\n", n);
2153 b = bcom(n->left, iftrue, b);
2154 b = bcom(n->right, iftrue, b);
2155 return b;
2156 }
2157
2158 Inst*
oror(Node * n,int iftrue,Inst * b)2159 oror(Node *n, int iftrue, Inst *b)
2160 {
2161 Inst *bb;
2162
2163 if(debug['b'])
2164 print("oror %n\n", n);
2165 bb = bcom(n->left, !iftrue, nil);
2166 b = bcom(n->right, iftrue, b);
2167 patch(bb, nextinst());
2168 return b;
2169 }
2170
2171 /*
2172 * generate code for a recva expression
2173 * this is just a hacked up small alt
2174 */
2175 void
recvacom(Src * src,Node * nto,Node * n)2176 recvacom(Src *src, Node *nto, Node *n)
2177 {
2178 Label *labs;
2179 Case *c;
2180 Node which, tab, off, add, adr, slot, *left;
2181 Type *talt;
2182 Inst *p;
2183
2184 left = n->left;
2185
2186 labs = allocmem(1 * sizeof *labs);
2187 labs[0].isptr = left->addable >= Rcant;
2188 c = allocmem(sizeof *c);
2189 c->nlab = 1;
2190 c->labs = labs;
2191 talt = mktalt(c);
2192
2193 talloc(&which, tint, nil);
2194 talloc(&tab, talt, nil);
2195
2196 /*
2197 * build the node for the address of each channel,
2198 * the values to send, and the storage fro values received
2199 */
2200 off = znode;
2201 off.op = Oconst;
2202 off.ty = tint;
2203 off.addable = Rconst;
2204 adr = znode;
2205 adr.op = Oadr;
2206 adr.left = &tab;
2207 adr.ty = tint;
2208 add = znode;
2209 add.op = Oadd;
2210 add.left = &adr;
2211 add.right = &off;
2212 add.ty = tint;
2213 slot = znode;
2214 slot.op = Oind;
2215 slot.left = &add;
2216 sumark(&slot);
2217
2218 /*
2219 * gen the channel
2220 * this sleaze is lying to the garbage collector
2221 */
2222 off.val = 2*IBY2WD;
2223 if(left->addable < Rcant)
2224 genmove(src, Mas, tint, left, &slot);
2225 else{
2226 slot.ty = left->ty;
2227 ecom(src, &slot, left);
2228 slot.ty = nil;
2229 }
2230
2231 /*
2232 * gen the value
2233 */
2234 off.val += IBY2WD;
2235 p = genrawop(&left->src, ILEA, nto, nil, &slot);
2236 p->m.offset = nto->ty->size; /* for optimizer */
2237
2238 /*
2239 * number of senders and receivers
2240 */
2241 off.val = 0;
2242 genmove(src, Mas, tint, sumark(mkconst(src, 0)), &slot);
2243 off.val += IBY2WD;
2244 genmove(src, Mas, tint, sumark(mkconst(src, 1)), &slot);
2245 off.val += IBY2WD;
2246
2247 p = genrawop(src, IALT, &tab, nil, &which);
2248 p->m.offset = talt->size; /* for optimizer */
2249 tfree(&which);
2250 tfree(&tab);
2251 }
2252
2253 /*
2254 * generate code to duplicate an adt with pick fields
2255 * this is just a hacked up small pick
2256 * n is Oind(exp)
2257 */
2258 void
pickdupcom(Src * src,Node * nto,Node * n)2259 pickdupcom(Src *src, Node *nto, Node *n)
2260 {
2261 Node *start, *stop, *node, *orig, *dest, tmp, clab;
2262 Case *c;
2263 Inst *j, *jmps, *wild;
2264 Label *labs;
2265 Decl *d, *tg, *stg;
2266 Type *t;
2267 int i, nlab;
2268 char buf[32];
2269
2270 if(n->op != Oind)
2271 fatal("pickdupcom not Oind: %n" ,n);
2272
2273 t = n->ty;
2274 nlab = t->decl->tag;
2275
2276 /*
2277 * generate global which has case labels
2278 */
2279 seprint(buf, buf+sizeof(buf), ".c%d", nlabel++);
2280 d = mkids(src, enter(buf, 0), mktype(&src->start, &src->stop, Tcase, nil, nil), nil);
2281 d->init = mkdeclname(src, d);
2282
2283 clab.addable = Rmreg;
2284 clab.left = nil;
2285 clab.right = nil;
2286 clab.op = Oname;
2287 clab.ty = d->ty;
2288 clab.decl = d;
2289
2290 /*
2291 * generate a temp to hold the real value
2292 * then generate a case on the tag
2293 */
2294 orig = n->left;
2295 talloc(&tmp, orig->ty, nil);
2296 ecom(src, &tmp, orig);
2297 orig = mkunary(Oind, &tmp);
2298 orig->ty = tint;
2299 sumark(orig);
2300
2301 dest = mkunary(Oind, nto);
2302 dest->ty = nto->ty->tof;
2303 sumark(dest);
2304
2305 genrawop(src, ICASE, orig, nil, &clab);
2306
2307 labs = allocmem(nlab * sizeof *labs);
2308
2309 i = 0;
2310 jmps = nil;
2311 for(tg = t->tags; tg != nil; tg = tg->next){
2312 stg = tg;
2313 for(; tg->next != nil; tg = tg->next)
2314 if(stg->ty != tg->next->ty)
2315 break;
2316 start = sumark(simplify(mkdeclname(src, stg)));
2317 stop = start;
2318 node = start;
2319 if(stg != tg){
2320 stop = sumark(simplify(mkdeclname(src, tg)));
2321 node = mkbin(Orange, start, stop);
2322 }
2323
2324 labs[i].start = start;
2325 labs[i].stop = stop;
2326 labs[i].node = node;
2327 labs[i++].inst = nextinst();
2328
2329 genrawop(src, INEW, mktn(tg->ty->tof), nil, nto);
2330 genmove(src, Mas, tg->ty->tof, orig, dest);
2331
2332 j = genrawop(src, IJMP, nil, nil, nil);
2333 j->branch = jmps;
2334 jmps = j;
2335 }
2336
2337 /*
2338 * this should really be a runtime error
2339 */
2340 wild = genrawop(src, IJMP, nil, nil, nil);
2341 patch(wild, wild);
2342
2343 patch(jmps, nextinst());
2344 tfree(&tmp);
2345
2346 if(i > nlab)
2347 fatal("overflowed label tab for pickdupcom");
2348
2349 c = allocmem(sizeof *c);
2350 c->nlab = i;
2351 c->nsnd = 0;
2352 c->labs = labs;
2353 c->iwild = wild;
2354
2355 d->ty->cse = c;
2356 usetype(d->ty);
2357 installids(Dglobal, d);
2358 }
2359
2360 /*
2361 * see if name n occurs anywhere in e
2362 */
2363 int
tupaliased(Node * n,Node * e)2364 tupaliased(Node *n, Node *e)
2365 {
2366 for(;;){
2367 if(e == nil)
2368 return 0;
2369 if(e->op == Oname && e->decl == n->decl)
2370 return 1;
2371 if(tupaliased(n, e->left))
2372 return 1;
2373 e = e->right;
2374 }
2375 }
2376
2377 /*
2378 * see if any name in n occurs anywere in e
2379 */
2380 int
tupsaliased(Node * n,Node * e)2381 tupsaliased(Node *n, Node *e)
2382 {
2383 for(;;){
2384 if(n == nil)
2385 return 0;
2386 if(n->op == Oname && tupaliased(n, e))
2387 return 1;
2388 if(tupsaliased(n->left, e))
2389 return 1;
2390 n = n->right;
2391 }
2392 }
2393
2394 /*
2395 * put unaddressable constants in the global data area
2396 */
2397 Decl*
globalconst(Node * n)2398 globalconst(Node *n)
2399 {
2400 Decl *d;
2401 Sym *s;
2402 char buf[32];
2403
2404 seprint(buf, buf+sizeof(buf), ".i.%.8lux", (long)n->val);
2405 s = enter(buf, 0);
2406 d = s->decl;
2407 if(d == nil){
2408 d = mkids(&n->src, s, tint, nil);
2409 installids(Dglobal, d);
2410 d->init = n;
2411 d->refs++;
2412 }
2413 return d;
2414 }
2415
2416 Decl*
globalBconst(Node * n)2417 globalBconst(Node *n)
2418 {
2419 Decl *d;
2420 Sym *s;
2421 char buf[32];
2422
2423 seprint(buf, buf+sizeof(buf), ".B.%.8lux.%8lux", (long)(n->val>>32), (long)n->val);
2424
2425 s = enter(buf, 0);
2426 d = s->decl;
2427 if(d == nil){
2428 d = mkids(&n->src, s, tbig, nil);
2429 installids(Dglobal, d);
2430 d->init = n;
2431 d->refs++;
2432 }
2433 return d;
2434 }
2435
2436 Decl*
globalbconst(Node * n)2437 globalbconst(Node *n)
2438 {
2439 Decl *d;
2440 Sym *s;
2441 char buf[32];
2442
2443 seprint(buf, buf+sizeof(buf), ".b.%.2lux", (long)n->val & 0xff);
2444 s = enter(buf, 0);
2445 d = s->decl;
2446 if(d == nil){
2447 d = mkids(&n->src, s, tbyte, nil);
2448 installids(Dglobal, d);
2449 d->init = n;
2450 d->refs++;
2451 }
2452 return d;
2453 }
2454
2455 Decl*
globalfconst(Node * n)2456 globalfconst(Node *n)
2457 {
2458 Decl *d;
2459 Sym *s;
2460 char buf[32];
2461 ulong dv[2];
2462
2463 dtocanon(n->rval, dv);
2464 seprint(buf, buf+sizeof(buf), ".f.%.8lux.%8lux", dv[0], dv[1]);
2465 s = enter(buf, 0);
2466 d = s->decl;
2467 if(d == nil){
2468 d = mkids(&n->src, s, treal, nil);
2469 installids(Dglobal, d);
2470 d->init = n;
2471 d->refs++;
2472 }
2473 return d;
2474 }
2475
2476 Decl*
globalsconst(Node * n)2477 globalsconst(Node *n)
2478 {
2479 Decl *d;
2480 Sym *s;
2481
2482 s = n->decl->sym;
2483 d = s->decl;
2484 if(d == nil){
2485 d = mkids(&n->src, s, tstring, nil);
2486 installids(Dglobal, d);
2487 d->init = n;
2488 }
2489 d->refs++;
2490 return d;
2491 }
2492
2493 static Node*
subst(Decl * d,Node * e,Node * n)2494 subst(Decl *d, Node *e, Node *n)
2495 {
2496 if(n == nil)
2497 return nil;
2498 if(n->op == Oname){
2499 if(d == n->decl){
2500 n = dupn(0, nil, e);
2501 n->ty = d->ty;
2502 }
2503 return n;
2504 }
2505 n->left = subst(d, e, n->left);
2506 n->right = subst(d, e, n->right);
2507 return n;
2508 }
2509
2510 static Node*
putinline(Node * n)2511 putinline(Node *n)
2512 {
2513 Node *e, *tn;
2514 Type *t;
2515 Decl *d;
2516
2517 if(debug['z']) print("inline1: %n\n", n);
2518 if(n->left->op == Oname)
2519 d = n->left->decl;
2520 else
2521 d = n->left->right->decl;
2522 e = d->init;
2523 t = e->ty;
2524 e = dupn(1, &n->src, e->right->left->left);
2525 for(d = t->ids, n = n->right; d != nil && n != nil; d = d->next, n = n->right){
2526 if(hasside(n->left, 0) && occurs(d, e) != 1){
2527 tn = talloc(mkn(0, nil, nil), d->ty, nil);
2528 e = mkbin(Ocomma, mkbin(Oas, tn, n->left), subst(d, tn, e));
2529 e->ty = e->right->ty;
2530 e->left->ty = d->ty;
2531 }
2532 else
2533 e = subst(d, n->left, e);
2534 }
2535 if(d != nil || n != nil)
2536 fatal("bad arg match in putinline()");
2537 if(debug['z']) print("inline2: %n\n", e);
2538 return e;
2539 }
2540
2541 static void
fpcall(Src * src,int op,Node * n,Node * ret)2542 fpcall(Src *src, int op, Node *n, Node *ret)
2543 {
2544 Node tp, *e, *mod, *ind;
2545
2546 tp.decl = nil;
2547 e = n->left->left;
2548 if(e->addable >= Rcant)
2549 e = eacom(e, &tp, nil);
2550 mod = mkunary(Oind, e);
2551 ind = mkunary(Oind, mkbin(Oadd, dupn(0, src, e), mkconst(src, IBY2WD)));
2552 n->left = mkbin(Omdot, mod, ind);
2553 n->left->ty = e->ty->tof;
2554 mod->ty = ind->ty = ind->left->ty = ind->left->right->ty = tint;
2555 sumark(n);
2556 callcom(src, op, n, ret);
2557 tfree(&tp);
2558 }
2559