blob: c4d5665d8358be8d12cfa07985d07ef1498e45ff [file] [log] [blame]
Russ Cox4dee7472009-01-06 09:41:38 -08001// Inferno utils/8c/sgen.c
2// http://code.google.com/p/inferno-os/source/browse/utils/8c/sgen.c
3//
4// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
5// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
6// Portions Copyright © 1997-1999 Vita Nuova Limited
7// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
8// Portions Copyright © 2004,2006 Bruce Ellis
9// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
10// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
11// Portions Copyright © 2009 The Go Authors. All rights reserved.
12//
13// Permission is hereby granted, free of charge, to any person obtaining a copy
14// of this software and associated documentation files (the "Software"), to deal
15// in the Software without restriction, including without limitation the rights
16// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17// copies of the Software, and to permit persons to whom the Software is
18// furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included in
21// all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29// THE SOFTWARE.
30
31#include "gc.h"
32
Russ Cox2bd101c42009-03-20 16:40:00 -070033int32
34argsize(void)
35{
36 Type *t;
37 int32 s;
38
39//print("t=%T\n", thisfn);
40 s = 0;
41 for(t=thisfn->down; t!=T; t=t->down) {
42 switch(t->etype) {
43 case TVOID:
44 break;
45 case TDOT:
46 s += 64;
47 break;
48 default:
49 s = align(s, t, Aarg1);
50 s = align(s, t, Aarg2);
51 break;
52 }
53//print(" %d %T\n", s, t);
54 }
55 return (s+7) & ~7;
56}
57
Russ Cox4dee7472009-01-06 09:41:38 -080058void
59codgen(Node *n, Node *nn)
60{
61 Prog *sp;
62 Node *n1, nod, nod1;
63
64 cursafe = 0;
65 curarg = 0;
66 maxargsafe = 0;
67
68 /*
69 * isolate name
70 */
71 for(n1 = nn;; n1 = n1->left) {
72 if(n1 == Z) {
73 diag(nn, "cant find function name");
74 return;
75 }
76 if(n1->op == ONAME)
77 break;
78 }
79 nearln = nn->lineno;
Russ Cox2bd101c42009-03-20 16:40:00 -070080
Russ Cox4dee7472009-01-06 09:41:38 -080081 gpseudo(ATEXT, n1->sym, nodconst(stkoff));
Russ Cox2bd101c42009-03-20 16:40:00 -070082 p->to.type = D_CONST2;
83 p->to.offset2 = argsize();
Russ Cox4dee7472009-01-06 09:41:38 -080084
85 /*
86 * isolate first argument
87 */
88 if(REGARG) {
89 if(typesuv[thisfn->link->etype]) {
90 nod1 = *nodret->left;
91 nodreg(&nod, &nod1, REGARG);
92 gmove(&nod, &nod1);
93 } else
94 if(firstarg && typechlp[firstargtype->etype]) {
95 nod1 = *nodret->left;
96 nod1.sym = firstarg;
97 nod1.type = firstargtype;
98 nod1.xoffset = align(0, firstargtype, Aarg1);
99 nod1.etype = firstargtype->etype;
100 nodreg(&nod, &nod1, REGARG);
101 gmove(&nod, &nod1);
102 }
103 }
104
105 sp = p;
106 retok = 0;
107 gen(n);
108 if(!retok)
109 if(thisfn->link->etype != TVOID)
110 warn(Z, "no return at end of function: %s", n1->sym->name);
111 noretval(3);
112 if(thisfn && thisfn->link && typefd[thisfn->link->etype])
113 gins(AFLDZ, Z, Z);
114 gbranch(ORETURN);
115
116 if(!debug['N'] || debug['R'] || debug['P'])
117 regopt(sp);
118 sp->to.offset += maxargsafe;
119}
120
121void
122supgen(Node *n)
123{
Russ Coxaf0143c2009-01-06 11:34:02 -0800124 int32 spc;
Russ Cox4dee7472009-01-06 09:41:38 -0800125 Prog *sp;
126
127 if(n == Z)
128 return;
129 suppress++;
130 spc = pc;
131 sp = lastp;
132 gen(n);
133 lastp = sp;
134 pc = spc;
135 sp->link = nil;
136 suppress--;
137}
138
139void
140gen(Node *n)
141{
142 Node *l, nod;
143 Prog *sp, *spc, *spb;
144 Case *cn;
Russ Coxaf0143c2009-01-06 11:34:02 -0800145 int32 sbc, scc;
Russ Cox4dee7472009-01-06 09:41:38 -0800146 int f, o;
147
148loop:
149 if(n == Z)
150 return;
151 nearln = n->lineno;
152 o = n->op;
153 if(debug['G'])
154 if(o != OLIST)
155 print("%L %O\n", nearln, o);
156
157 retok = 0;
158 switch(o) {
159
160 default:
161 complex(n);
162 cgen(n, Z);
163 break;
164
165 case OLIST:
166 gen(n->left);
167
168 rloop:
169 n = n->right;
170 goto loop;
171
172 case ORETURN:
173 retok = 1;
174 complex(n);
175 if(n->type == T)
176 break;
177 l = n->left;
178 if(l == Z) {
179 noretval(3);
180 if(typefd[n->type->etype])
181 gins(AFLDZ, Z, Z);
182 gbranch(ORETURN);
183 break;
184 }
185 if(typesuv[n->type->etype]) {
186 sugen(l, nodret, n->type->width);
187 noretval(3);
188 gbranch(ORETURN);
189 break;
190 }
191 regret(&nod, n);
192 cgen(l, &nod);
193 regfree(&nod);
194 if(typefd[n->type->etype])
195 noretval(1);
196 else
197 noretval(2);
198 gbranch(ORETURN);
199 break;
200
201 case OLABEL:
202 l = n->left;
203 if(l) {
204 l->xoffset = pc;
205 if(l->label)
206 patch(l->label, pc);
207 }
208 gbranch(OGOTO); /* prevent self reference in reg */
209 patch(p, pc);
210 goto rloop;
211
212 case OGOTO:
213 retok = 1;
214 n = n->left;
215 if(n == Z)
216 return;
217 if(n->complex == 0) {
218 diag(Z, "label undefined: %s", n->sym->name);
219 return;
220 }
221 if(suppress)
222 return;
223 gbranch(OGOTO);
224 if(n->xoffset) {
225 patch(p, n->xoffset);
226 return;
227 }
228 if(n->label)
229 patch(n->label, pc-1);
230 n->label = p;
231 return;
232
233 case OCASE:
234 l = n->left;
235 if(cases == C)
236 diag(n, "case/default outside a switch");
237 if(l == Z) {
238 cas();
239 cases->val = 0;
240 cases->def = 1;
241 cases->label = pc;
242 goto rloop;
243 }
244 complex(l);
245 if(l->type == T)
246 goto rloop;
247 if(l->op == OCONST)
248 if(typechl[l->type->etype]) {
249 cas();
250 cases->val = l->vconst;
251 cases->def = 0;
252 cases->label = pc;
253 goto rloop;
254 }
255 diag(n, "case expression must be integer constant");
256 goto rloop;
257
258 case OSWITCH:
259 l = n->left;
260 complex(l);
261 if(l->type == T)
262 break;
263 if(!typechl[l->type->etype]) {
264 diag(n, "switch expression must be integer");
265 break;
266 }
267
268 gbranch(OGOTO); /* entry */
269 sp = p;
270
271 cn = cases;
272 cases = C;
273 cas();
274
275 sbc = breakpc;
276 breakpc = pc;
277 gbranch(OGOTO);
278 spb = p;
279
280 gen(n->right);
281 gbranch(OGOTO);
282 patch(p, breakpc);
283
284 patch(sp, pc);
285 regalloc(&nod, l, Z);
286 nod.type = types[TLONG];
287 cgen(l, &nod);
288 doswit(&nod);
289 regfree(&nod);
290 patch(spb, pc);
291
292 cases = cn;
293 breakpc = sbc;
294 break;
295
296 case OWHILE:
297 case ODWHILE:
298 l = n->left;
299 gbranch(OGOTO); /* entry */
300 sp = p;
301
302 scc = continpc;
303 continpc = pc;
304 gbranch(OGOTO);
305 spc = p;
306
307 sbc = breakpc;
308 breakpc = pc;
309 gbranch(OGOTO);
310 spb = p;
311
312 patch(spc, pc);
313 if(n->op == OWHILE)
314 patch(sp, pc);
315 bcomplex(l, Z); /* test */
316 patch(p, breakpc);
317
318 if(n->op == ODWHILE)
319 patch(sp, pc);
320 gen(n->right); /* body */
321 gbranch(OGOTO);
322 patch(p, continpc);
323
324 patch(spb, pc);
325 continpc = scc;
326 breakpc = sbc;
327 break;
328
329 case OFOR:
330 l = n->left;
331 gen(l->right->left); /* init */
332 gbranch(OGOTO); /* entry */
333 sp = p;
334
335 scc = continpc;
336 continpc = pc;
337 gbranch(OGOTO);
338 spc = p;
339
340 sbc = breakpc;
341 breakpc = pc;
342 gbranch(OGOTO);
343 spb = p;
344
345 patch(spc, pc);
346 gen(l->right->right); /* inc */
347 patch(sp, pc);
348 if(l->left != Z) { /* test */
349 bcomplex(l->left, Z);
350 patch(p, breakpc);
351 }
352 gen(n->right); /* body */
353 gbranch(OGOTO);
354 patch(p, continpc);
355
356 patch(spb, pc);
357 continpc = scc;
358 breakpc = sbc;
359 break;
360
361 case OCONTINUE:
362 if(continpc < 0) {
363 diag(n, "continue not in a loop");
364 break;
365 }
366 gbranch(OGOTO);
367 patch(p, continpc);
368 break;
369
370 case OBREAK:
371 if(breakpc < 0) {
372 diag(n, "break not in a loop");
373 break;
374 }
375 gbranch(OGOTO);
376 patch(p, breakpc);
377 break;
378
379 case OIF:
380 l = n->left;
381 if(bcomplex(l, n->right)) {
382 if(typefd[l->type->etype])
383 f = !l->fconst;
384 else
385 f = !l->vconst;
386 if(debug['c'])
387 print("%L const if %s\n", nearln, f ? "false" : "true");
388 if(f) {
389 supgen(n->right->left);
390 gen(n->right->right);
391 }
392 else {
393 gen(n->right->left);
394 supgen(n->right->right);
395 }
396 }
397 else {
398 sp = p;
399 if(n->right->left != Z)
400 gen(n->right->left);
401 if(n->right->right != Z) {
402 gbranch(OGOTO);
403 patch(sp, pc);
404 sp = p;
405 gen(n->right->right);
406 }
407 patch(sp, pc);
408 }
409 break;
410
411 case OSET:
412 case OUSED:
413 usedset(n->left, o);
414 break;
415 }
416}
417
418void
419usedset(Node *n, int o)
420{
421 if(n->op == OLIST) {
422 usedset(n->left, o);
423 usedset(n->right, o);
424 return;
425 }
426 complex(n);
427 switch(n->op) {
428 case OADDR: /* volatile */
429 gins(ANOP, n, Z);
430 break;
431 case ONAME:
432 if(o == OSET)
433 gins(ANOP, Z, n);
434 else
435 gins(ANOP, n, Z);
436 break;
437 }
438}
439
440void
441noretval(int n)
442{
443
444 if(n & 1) {
445 gins(ANOP, Z, Z);
446 p->to.type = REGRET;
447 }
448 if(n & 2) {
449 gins(ANOP, Z, Z);
450 p->to.type = FREGRET;
451 }
452}
453
454/* welcome to commute */
455static void
456commute(Node *n)
457{
458 Node *l, *r;
459
460 l = n->left;
461 r = n->right;
462 if(r->complex > l->complex) {
463 n->left = r;
464 n->right = l;
465 }
466}
467
468void
469indexshift(Node *n)
470{
471 int g;
472
473 if(!typechlp[n->type->etype])
474 return;
475 simplifyshift(n);
476 if(n->op == OASHL && n->right->op == OCONST){
477 g = vconst(n->right);
478 if(g >= 0 && g < 4)
479 n->addable = 7;
480 }
481}
482
483/*
484 * calculate addressability as follows
485 * NAME ==> 10/11 name+value(SB/SP)
486 * REGISTER ==> 12 register
487 * CONST ==> 20 $value
488 * *(20) ==> 21 value
489 * &(10) ==> 13 $name+value(SB)
490 * &(11) ==> 1 $name+value(SP)
491 * (13) + (20) ==> 13 fold constants
492 * (1) + (20) ==> 1 fold constants
493 * *(13) ==> 10 back to name
494 * *(1) ==> 11 back to name
495 *
496 * (20) * (X) ==> 7 multiplier in indexing
497 * (X,7) + (13,1) ==> 8 adder in indexing (addresses)
498 * (8) ==> &9(OINDEX) index, almost addressable
499 *
500 * calculate complexity (number of registers)
501 */
502void
503xcom(Node *n)
504{
505 Node *l, *r;
506 int g;
507
508 if(n == Z)
509 return;
510 l = n->left;
511 r = n->right;
512 n->complex = 0;
513 n->addable = 0;
514 switch(n->op) {
515 case OCONST:
516 n->addable = 20;
517 break;
518
519 case ONAME:
520 n->addable = 10;
521 if(n->class == CPARAM || n->class == CAUTO)
522 n->addable = 11;
523 break;
524
Russ Cox2bd101c42009-03-20 16:40:00 -0700525 case OEXREG:
526 n->addable = 10;
527 break;
528
Russ Cox4dee7472009-01-06 09:41:38 -0800529 case OREGISTER:
530 n->addable = 12;
531 break;
532
533 case OINDREG:
534 n->addable = 12;
535 break;
536
537 case OADDR:
538 xcom(l);
539 if(l->addable == 10)
540 n->addable = 13;
541 else
542 if(l->addable == 11)
543 n->addable = 1;
544 break;
545
546 case OADD:
547 xcom(l);
548 xcom(r);
549 if(n->type->etype != TIND)
550 break;
551
552 switch(r->addable) {
553 case 20:
554 switch(l->addable) {
555 case 1:
556 case 13:
557 commadd:
558 l->type = n->type;
559 *n = *l;
560 l = new(0, Z, Z);
561 *l = *(n->left);
562 l->xoffset += r->vconst;
563 n->left = l;
564 r = n->right;
565 goto brk;
566 }
567 break;
568
569 case 1:
570 case 13:
571 case 10:
572 case 11:
573 /* l is the base, r is the index */
574 if(l->addable != 20)
575 n->addable = 8;
576 break;
577 }
578 switch(l->addable) {
579 case 20:
580 switch(r->addable) {
581 case 13:
582 case 1:
583 r = n->left;
584 l = n->right;
585 n->left = l;
586 n->right = r;
587 goto commadd;
588 }
589 break;
590
591 case 13:
592 case 1:
593 case 10:
594 case 11:
595 /* r is the base, l is the index */
596 if(r->addable != 20)
597 n->addable = 8;
598 break;
599 }
600 if(n->addable == 8 && !side(n)) {
601 indx(n);
602 l = new1(OINDEX, idx.basetree, idx.regtree);
603 l->scale = idx.scale;
604 l->addable = 9;
605 l->complex = l->right->complex;
606 l->type = l->left->type;
607 n->op = OADDR;
608 n->left = l;
609 n->right = Z;
610 n->addable = 8;
611 break;
612 }
613 break;
614
615 case OINDEX:
616 xcom(l);
617 xcom(r);
618 n->addable = 9;
619 break;
620
621 case OIND:
622 xcom(l);
623 if(l->op == OADDR) {
624 l = l->left;
625 l->type = n->type;
626 *n = *l;
627 return;
628 }
629 switch(l->addable) {
630 case 20:
631 n->addable = 21;
632 break;
633 case 1:
634 n->addable = 11;
635 break;
636 case 13:
637 n->addable = 10;
638 break;
639 }
640 break;
641
642 case OASHL:
643 xcom(l);
644 xcom(r);
645 indexshift(n);
646 break;
647
648 case OMUL:
649 case OLMUL:
650 xcom(l);
651 xcom(r);
652 g = vlog(l);
653 if(g >= 0) {
654 n->left = r;
655 n->right = l;
656 l = r;
657 r = n->right;
658 }
659 g = vlog(r);
660 if(g >= 0) {
661 n->op = OASHL;
662 r->vconst = g;
663 r->type = types[TINT];
664 indexshift(n);
665 break;
666 }
667commute(n);
668 break;
669
670 case OASLDIV:
671 xcom(l);
672 xcom(r);
673 g = vlog(r);
674 if(g >= 0) {
675 n->op = OASLSHR;
676 r->vconst = g;
677 r->type = types[TINT];
678 }
679 break;
680
681 case OLDIV:
682 xcom(l);
683 xcom(r);
684 g = vlog(r);
685 if(g >= 0) {
686 n->op = OLSHR;
687 r->vconst = g;
688 r->type = types[TINT];
689 indexshift(n);
690 break;
691 }
692 break;
693
694 case OASLMOD:
695 xcom(l);
696 xcom(r);
697 g = vlog(r);
698 if(g >= 0) {
699 n->op = OASAND;
700 r->vconst--;
701 }
702 break;
703
704 case OLMOD:
705 xcom(l);
706 xcom(r);
707 g = vlog(r);
708 if(g >= 0) {
709 n->op = OAND;
710 r->vconst--;
711 }
712 break;
713
714 case OASMUL:
715 case OASLMUL:
716 xcom(l);
717 xcom(r);
718 g = vlog(r);
719 if(g >= 0) {
720 n->op = OASASHL;
721 r->vconst = g;
722 }
723 break;
724
725 case OLSHR:
726 case OASHR:
727 xcom(l);
728 xcom(r);
729 indexshift(n);
730 break;
731
732 default:
733 if(l != Z)
734 xcom(l);
735 if(r != Z)
736 xcom(r);
737 break;
738 }
739brk:
740 if(n->addable >= 10)
741 return;
742 if(l != Z)
743 n->complex = l->complex;
744 if(r != Z) {
745 if(r->complex == n->complex)
746 n->complex = r->complex+1;
747 else
748 if(r->complex > n->complex)
749 n->complex = r->complex;
750 }
751 if(n->complex == 0)
752 n->complex++;
753
754 if(com64(n))
755 return;
756
757 switch(n->op) {
758
759 case OFUNC:
760 n->complex = FNX;
761 break;
762
763 case OLMOD:
764 case OMOD:
765 case OLMUL:
766 case OLDIV:
767 case OMUL:
768 case ODIV:
769 case OASLMUL:
770 case OASLDIV:
771 case OASLMOD:
772 case OASMUL:
773 case OASDIV:
774 case OASMOD:
775 if(r->complex >= l->complex) {
776 n->complex = l->complex + 3;
777 if(r->complex > n->complex)
778 n->complex = r->complex;
779 } else {
780 n->complex = r->complex + 3;
781 if(l->complex > n->complex)
782 n->complex = l->complex;
783 }
784 break;
785
786 case OLSHR:
787 case OASHL:
788 case OASHR:
789 case OASLSHR:
790 case OASASHL:
791 case OASASHR:
792 if(r->complex >= l->complex) {
793 n->complex = l->complex + 2;
794 if(r->complex > n->complex)
795 n->complex = r->complex;
796 } else {
797 n->complex = r->complex + 2;
798 if(l->complex > n->complex)
799 n->complex = l->complex;
800 }
801 break;
802
803 case OADD:
804 case OXOR:
805 case OAND:
806 case OOR:
807 /*
808 * immediate operators, make const on right
809 */
810 if(l->op == OCONST) {
811 n->left = r;
812 n->right = l;
813 }
814 break;
815
816 case OEQ:
817 case ONE:
818 case OLE:
819 case OLT:
820 case OGE:
821 case OGT:
822 case OHI:
823 case OHS:
824 case OLO:
825 case OLS:
826 /*
827 * compare operators, make const on left
828 */
829 if(r->op == OCONST) {
830 n->left = r;
831 n->right = l;
832 n->op = invrel[relindex(n->op)];
833 }
834 break;
835 }
836}
837
838void
839indx(Node *n)
840{
841 Node *l, *r;
842
843 if(debug['x'])
844 prtree(n, "indx");
845
846 l = n->left;
847 r = n->right;
848 if(l->addable == 1 || l->addable == 13 || r->complex > l->complex) {
849 n->right = l;
850 n->left = r;
851 l = r;
852 r = n->right;
853 }
854 if(l->addable != 7) {
855 idx.regtree = l;
856 idx.scale = 1;
857 } else
858 if(l->right->addable == 20) {
859 idx.regtree = l->left;
860 idx.scale = 1 << l->right->vconst;
861 } else
862 if(l->left->addable == 20) {
863 idx.regtree = l->right;
864 idx.scale = 1 << l->left->vconst;
865 } else
866 diag(n, "bad index");
867
868 idx.basetree = r;
869 if(debug['x']) {
870 print("scale = %d\n", idx.scale);
871 prtree(idx.regtree, "index");
872 prtree(idx.basetree, "base");
873 }
874}
875
876int
877bcomplex(Node *n, Node *c)
878{
879 Node *b, nod;
880
881 complex(n);
882 if(n->type != T)
883 if(tcompat(n, T, n->type, tnot))
884 n->type = T;
885 if(n->type != T) {
886 if(c != Z && n->op == OCONST && deadheads(c))
887 return 1;
888 if(typev[n->type->etype] && machcap(Z)) {
889 b = &nod;
890 b->op = ONE;
891 b->left = n;
892 b->right = new(0, Z, Z);
893 *b->right = *nodconst(0);
894 b->right->type = n->type;
895 b->type = types[TLONG];
896 cgen64(b, Z);
897 return 0;
898 }
899 bool64(n);
900 boolgen(n, 1, Z);
901 } else
902 gbranch(OGOTO);
903 return 0;
904}