|
|
1.1 root 1: #include <u.h>
2: #include <libc.h>
3: #include <bio.h>
4: #include <ctype.h>
5: #define Extern extern
6: #include "parl.h"
7: #include "globl.h"
8:
9: void
10: gendata(Node *n)
11: {
12: Type *t;
13: Inst *i;
14: ulong s;
15:
16: if(n == ZeroN)
17: return;
18:
19: switch(n->type) {
20: default:
21: gendata(n->left);
22: gendata(n->right);
23: break;
24:
25: case OAGDECL:
26: case OUNDECL:
27: case OADTDECL:
28: case OSETDECL:
29: case OFUNC:
30: break;
31:
32: case ONAME:
33: switch(n->t->class) {
34: case Internal:
35: case Global:
36: iline = n->srcline;
37: t = n->t;
38: if(n->init)
39: doinit(n, t, n->init, 0);
40:
41: s = t->size;
42: if(s == 0)
43: break;
44: if(s & (Align_data-1))
45: s += Align_data-(s&(Align_data-1));
46:
47: i = ai();
48: i->op = AGLOBL;
49: mkaddr(con(s), &i->dst, 0);
50: mkaddr(n, &i->src1, 0);
51: ilink(i);
52: break;
53: }
54: break;
55: }
56: }
57:
58: /* Load/store instructions by type
59:
60: TXXX TINT TUINT TSINT TSUINT TCHAR TFLOAT TIND
61: TCHAN TARY TAGG TUNI TFUNC TVOID
62: */
63: int ostore[] ={ AGOK, AMOVW, AMOVW, AMOVH, AMOVH, AMOVB, AFMOVD, AMOVW,
64: AMOVW, AGOK, AGOK, AGOK, AGOK, AGOK };
65:
66: int oload[] = { AGOK, AMOVW, AMOVW, AMOVH, AMOVHU,AMOVBU,AFMOVD, AMOVW,
67: AMOVW,AGOK, AGOK, AGOK, AGOK, AGOK };
68:
69: void
70: load(Node *from, Node *to)
71: {
72: Node n1;
73: int op;
74:
75: op = oload[from->t->type];
76: reg(&n1, from->t, to);
77: instruction(op, from, ZeroN, &n1);
78: assign(&n1, to);
79: regfree(&n1);
80: }
81:
82: void
83: store(Node *from, Node *to)
84: {
85: Node n1;
86: int op, t;
87:
88: op = ostore[to->t->type];
89:
90: t = from->t->type;
91:
92: if(t != TFLOAT)
93: if(vconst(from) == 0) {
94: instruction(op, from, ZeroN, to);
95: return;
96: }
97:
98: if(t == to->t->type)
99: reg(&n1, to->t, from);
100: else
101: reg(&n1, to->t, ZeroN);
102:
103: assign(from, &n1);
104: instruction(op, &n1, ZeroN, to);
105: regfree(&n1);
106: }
107:
108: void
109: inttoflt(Node *s, Node *d)
110: {
111: Inst *nofix;
112: Node n, *tmp;
113:
114: reg(&n, d->t, d);
115: tmp = stknode(d->t);
116: instruction(AMOVW, s, ZeroN, tmp);
117: instruction(AFMOVD, tmp, ZeroN, &n);
118: instruction(AFMOVWD, &n, ZeroN, d);
119: regfree(&n);
120: if(s->t->type == TUINT) {
121: instruction(ACMP, s, ZeroN, con(0));
122: instruction(ABGE, ZeroN, ZeroN, ZeroN);
123: nofix = ipc;
124: reg(&n, builtype[TFLOAT], ZeroN);
125: instruction(AFMOVD, conf(4294967296.), ZeroN, &n);
126: instruction(AFADDD, &n, ZeroN, d);
127: regfree(&n);
128: label(nofix, ipc->pc+1);
129: }
130: }
131:
132: /*
133: * Compile code for moves
134: */
135: void
136: assign(Node *src, Node *dst)
137: {
138: Node n1, *tmp;
139: int op, dt;
140:
141: if(opt('a'))
142: print("assign: %N = %N\n", dst, src);
143:
144: if(dst == ZeroN)
145: return;
146:
147: switch(src->type) {
148: case ONAME:
149: case OINDREG:
150: case OIND:
151: load(src, dst);
152: return;
153: }
154:
155: switch(dst->type) {
156: case ONAME:
157: case OINDREG:
158: case OIND:
159: store(src, dst);
160: return;
161: }
162:
163: /* delete register/register nop moves */
164: if(src->type == OREGISTER)
165: if(dst->type == OREGISTER)
166: if(dst->reg == src->reg)
167: if(dst->type == src->type)
168: return;
169:
170: op = AGOK;
171: dt = dst->t->type;
172: switch(src->t->type) {
173: case TINT:
174: case TUINT:
175: case TIND:
176: case TCHANNEL:
177: switch(dt) {
178: case TINT:
179: case TUINT:
180: case TCHAR:
181: case TSUINT:
182: case TSINT:
183: case TIND:
184: case TCHANNEL:
185: op = AMOVW;
186: break;
187:
188: case TFLOAT:
189: inttoflt(src, dst);
190: return;
191: }
192: break;
193:
194: case TSUINT:
195: switch(dt) {
196: case TINT:
197: case TUINT:
198: case TIND:
199: op = AMOVHU;
200: break;
201:
202: case TSUINT:
203: case TCHAR:
204: case TSINT:
205: op = AMOVW;
206: break;
207:
208: case TFLOAT:
209: inttoflt(src, dst);
210: return;
211: }
212: break;
213:
214: case TSINT:
215: switch(dt) {
216: case TINT:
217: case TUINT:
218: case TIND:
219: op = AMOVH;
220: break;
221:
222: case TSUINT:
223: case TCHAR:
224: case TSINT:
225: op = AMOVW;
226: break;
227:
228: case TFLOAT:
229: inttoflt(src, dst);
230: return;
231: }
232: break;
233:
234: case TFLOAT:
235: switch(dt) {
236: case TINT:
237: case TUINT:
238: case TIND:
239: case TCHAR:
240: case TSINT:
241: case TSUINT:
242: reg(&n1, builtype[TFLOAT], ZeroN);
243: tmp = stknode(builtype[TINT]);
244: instruction(AFMOVDW, src, ZeroN, &n1);
245: instruction(AFMOVD, &n1, ZeroN, tmp);
246: regfree(&n1);
247: instruction(AMOVW, tmp, ZeroN, dst);
248: assign(dst, dst);
249: return;
250:
251: case TFLOAT:
252: op = AFMOVD;
253: break;
254: }
255: break;
256: case TCHAR:
257: switch(dt) {
258: case TINT:
259: case TUINT:
260: case TIND:
261: op = AMOVBU;
262: break;
263:
264: case TSUINT:
265: case TSINT:
266: case TCHAR:
267: op = AMOVW;
268: break;
269:
270: case TFLOAT:
271: inttoflt(src, dst);
272: return;
273: }
274: break;
275: }
276: instruction(op, src, ZeroN, dst);
277: }
278:
279: /*
280: * Generate the address of an expression
281: */
282: void
283: genaddr(Node *expr, Node *dst)
284: {
285: Node n, *tmp;
286:
287: if(opt('g'))
288: print("genaddr: %N\n", expr);
289:
290: if(expr->type == OIND) {
291: genexp(expr->left, dst);
292: return;
293: }
294: if(isaddr(expr) == 0) {
295: tmp = stknode(expr->t);
296: n.type = OASGN;
297: n.t = tmp->t;
298: n.left = tmp;
299: n.right = expr;
300: n.islval = 0;
301: genexp(&n, ZeroN);
302: expr = tmp;
303: }
304: n = *expr;
305: reg(&n, builtype[TIND], dst);
306: n.type = OADDR;
307: n.left = expr;
308: n.right = ZeroN;
309: n.t = builtype[TIND];
310: assign(&n, dst);
311: regfree(&n);
312: }
313:
314: /*
315: * generate an l-value into a register
316: */
317: void
318: rgenaddr(Node *t, Node *rval, Node *lval)
319: {
320: Node *r;
321: ulong v;
322:
323: *t = *rval;
324: t->t = builtype[TIND];
325: reg(t, t->t, lval);
326: if(rval->type == OIND) {
327: r = rval->left;
328: while(r->type == OADD)
329: r = r->right;
330: if(immed(r)) {
331: v = r->ival;
332: r->ival = 0;
333: genaddr(rval, t);
334: t->ival += v;
335: r->ival = v;
336: t->type = OINDREG;
337: t->t = rval->t;
338: return;
339: }
340: }
341: genaddr(rval, t);
342: t->type = OINDREG;
343: t->t = rval->t;
344: }
345:
346: /*
347: * pre and post increment generation
348: */
349: void
350: postop(Node *rval, Node *lval)
351: {
352: Node *l, *nconst;
353: Node n1, n2, n3, n4;
354:
355: l = rval->left;
356: nconst = con(1);
357: if(l->t->type == TIND)
358: nconst->ival = l->t->next->size;
359:
360: if(rval->type == OPDEC)
361: nconst->ival = -nconst->ival;
362:
363: if(l->islval < Sucompute)
364: rgenaddr(&n2, l, ZeroN);
365: else
366: n2 = *l;
367:
368: n3.type = OADD;
369: n3.t = builtype[TINT];
370:
371: /* Easy if we dont need the value after the inc */
372: if(lval == ZeroN) {
373: reg(&n1, l->t, lval);
374: assign(&n2, &n1);
375:
376: codmop(&n3, nconst, &n1, &n1);
377:
378: assign(&n1, &n2);
379: goto out;
380: }
381:
382: reg(&n4, l->t, lval);
383: assign(&n2, &n4);
384: reg(&n1, l->t, ZeroN);
385: /* Thank RISC for three address ! */
386: codmop(&n3, nconst, &n4, &n1);
387: assign(&n1, &n2);
388:
389: regfree(&n4);
390: out:
391: regfree(&n1);
392: if(l->islval < Sucompute)
393: regfree(&n2);
394: }
395:
396: void
397: preop(Node *rval, Node *lval)
398: {
399: Node n1, n2, n3;
400: Node *l, *nconst;
401:
402: l = rval->left;
403: nconst = con(1);
404: if(l->t->type == TIND)
405: nconst->ival = l->t->next->size;
406:
407: if(rval->type == OEDEC)
408: nconst->ival = -nconst->ival;
409:
410: if(l->islval < Sucompute)
411: rgenaddr(&n2, l, ZeroN);
412: else
413: n2 = *l;
414:
415: reg(&n1, l->t, lval);
416: assign(&n2, &n1);
417:
418: n3.type = OADD;
419: n3.t = builtype[TINT];
420: codmop(&n3, nconst, &n1, &n1);
421:
422: assign(&n1, &n2);
423:
424: regfree(&n1);
425: if(l->islval < Sucompute)
426: regfree(&n2);
427: }
428:
429: void
430: docall(Node *n)
431: {
432: Node *rsp;
433:
434: if(atv == ZeroN) {
435: instruction(AJMPL, ZeroN, ZeroN, n);
436: return;
437: }
438:
439: /*
440: * if calling through an activation, link
441: * to the new stack
442: */
443: ratv.ival = atv->atvsafe;
444: rsp = regn(RegSP);
445: instruction(AMOVW, rsp, ZeroN, &ratv);
446: ratv.type = OREGISTER;
447: assign(&ratv, rsp);
448: instruction(AJMPL, ZeroN, ZeroN, n);
449: rsp->type = OINDREG;
450: rsp->ival = atv->atvsafe;
451: instruction(AMOVW, rsp, ZeroN, regn(RegSP));
452: regfree(&ratv);
453: }
454:
455: void
456: become(Node *rval)
457: {
458: Node nl;
459: Node *l, *r, *ns, *tmp;
460:
461: tmp = rval->left;
462: r = tmp->right;
463: l = tmp->left;
464:
465: if(opt('b')) {
466: print("BECOME:\n");
467: ptree(rval, 0);
468: }
469:
470: tmp = ZeroN;
471: if(!isaddr(l)) {
472: tmp = stknode(builtype[TIND]);
473: genaddr(l, tmp);
474: }
475:
476: /* Generate the alias saves */
477: genelist(rval->right);
478:
479: evalarg(r, 0);
480:
481: /*
482: * Write out tail recursion
483: */
484: if(l->type == ONAME && curfunc->sym == l->sym) {
485: tip = block[Scope];
486: evalarg(r, 4);
487: instruction(AJMP, ZeroN, ZeroN, ZeroN);
488: label(ipc, becomentry->pc+1);
489: return;
490: }
491:
492: ns = an(ONAME, ZeroN, ZeroN);
493: ns->sym = malloc(sizeof(Sym));
494: ns->sym->name = ".xframe";
495: ns->ti = ati(builtype[TADT], Parameter);
496: ns->ti->offset = 0;
497: ns->t = builtype[TINT];
498: ns = an(OADDR, ns, nil);
499: sucalc(ns);
500:
501: reg(&ratv, builtype[TIND], ZeroN);
502: ratv.ival = Parambase;
503: genexp(ns, &ratv);
504: evalarg(r, 3);
505: regfree(&ratv);
506:
507: /* Restore the complex pointer */
508: switch(curfunc->t->next->type) {
509: case TADT:
510: case TUNION:
511: case TAGGREGATE:
512: assign(rnode, regn(Regspass));
513: break;
514: }
515:
516: if(tmp) {
517: reg(&nl, builtype[TIND], ZeroN);
518: assign(tmp, &nl);
519: nl.type = OINDREG;
520: nl.ival = 0;
521: instruction(ARETURN, con(ratv.ival), ZeroN, &nl);
522: regfree(&nl);
523: }
524: else
525: instruction(ARETURN, con(ratv.ival), ZeroN, l);
526: }
527:
528: /*
529: * Compile code expressions
530: */
531: void
532: genexp(Node *rval, Node *lval)
533: {
534: Node nl, nr, nspare;
535: Node *l, *r, *nstack;
536:
537: l = rval->left;
538: r = rval->right;
539:
540: if(opt('v'))
541: print("%L R %N L %N\n", rval->srcline, rval, lval);
542:
543: if(rval->t)
544: switch(rval->t->type) {
545: case TADT:
546: case TUNION:
547: case TAGGREGATE:
548: gencomplex(rval, lval);
549: return;
550: }
551:
552: /* addressable */
553: if(isaddr(rval)) {
554: assign(rval, lval);
555: return;
556: }
557:
558: /* Follow function call evaluations into stack temporary */
559: if(rval->sun >= Sucall)
560: if(l->sun >= Sucall)
561: if(r && r->sun >= Sucall)
562: switch(rval->type) {
563: case OFUNC:
564: case OLAND:
565: case OLOR:
566: break;
567:
568: default:
569: regret(&nspare, r->t);
570: genexp(r, &nspare);
571: nstack = stknode(r->t);
572: assign(&nspare, nstack);
573: regfree(&nspare);
574: nspare = *rval;
575: nspare.right = nstack;
576: genexp(&nspare, lval);
577: return;
578: }
579:
580: switch(rval->type) {
581: default:
582: fatal("genexp: %N", rval);
583: break;
584:
585: case OBLOCK:
586: bstmnt(l);
587: genexp(r, lval);
588: break;
589:
590: case OBECOME:
591: become(rval);
592: break;
593:
594: case ODOT:
595: nstack = stknode(l->t);
596: genexp(l, nstack);
597: if(rval == ZeroN)
598: break;
599:
600: rgenaddr(&nspare, nstack, ZeroN);
601: nspare.ival = r->ival;
602: nspare.t = rval->t;
603: genexp(&nspare, lval);
604: regfree(&nspare);
605: break;
606:
607: case OCONV:
608: if(lval == ZeroN) {
609: warn(rval, "result ignored");
610: break;
611: }
612:
613: if(convisnop(l->t, rval->t) && convisnop(rval->t, lval->t)) {
614: genexp(l, lval);
615: break;
616: }
617: reg(&nl, l->t, lval);
618: genexp(l, &nl);
619: reg(&nr, rval->t, &nl);
620: assign(&nl, &nr);
621: assign(&nr, lval);
622: regfree(&nr);
623: regfree(&nl);
624: break;
625:
626: case OASGN:
627: oasgn(rval, lval);
628: break;
629:
630: case OADDR:
631: if(lval == ZeroN) {
632: warn(rval, "result ignored");
633: break;
634: }
635:
636: genaddr(l, lval);
637: break;
638:
639: case OIND:
640: if(lval == ZeroN) {
641: warn(rval, "result ignored");
642: break;
643: }
644: reg(&nr, builtype[TIND], lval);
645: if(l->type == OADD && l->right->type == OCONST) {
646: nr.ival = l->right->ival;
647: genexp(l->left, &nr);
648: }
649: else {
650: genexp(l, &nr);
651: nr.ival = 0;
652: }
653: nr.type = OINDREG;
654: nr.t = rval->t;
655: assign(&nr, lval);
656: regfree(&nr);
657: break;
658:
659: case OCAND:
660: case OCOR:
661: case OEQ:
662: case OLEQ:
663: case ONEQ:
664: case OLT:
665: case OGEQ:
666: case OGT:
667: case OHI:
668: case OLO:
669: case OLOS:
670: case OHIS:
671: if(lval == ZeroN)
672: break;
673:
674: gencond(rval, lval, True);
675: break;
676:
677: case ONOT:
678: gencond(l, lval, False);
679: break;
680:
681: case OADDEQ:
682: case OSUBEQ:
683: case ORSHEQ:
684: case OLSHEQ:
685: case OANDEQ:
686: case OOREQ:
687: case OXOREQ:
688: while(l->type == OCONV)
689: l = l->left;
690:
691: /* Peel off the instructions with immediate operands */
692: if(r->t->type != TFLOAT)
693: if(r->type == OCONST) {
694: if(l->islval < Sucompute)
695: rgenaddr(&nspare, l, ZeroN);
696: else
697: nspare = *l;
698: reg(&nl, r->t, lval);
699: assign(&nspare, &nl);
700: codmop(rval, r, &nl, &nl);
701: assign(&nl, &nspare);
702:
703: regfree(&nl);
704: if(l->islval < Sucompute)
705: regfree(&nspare);
706: break;
707: }
708:
709: /* Fall through */
710: case OMULEQ:
711: case ODIVEQ:
712: case OMODEQ:
713: while(l->type == OCONV)
714: l = l->left;
715:
716: if(l->sun >= r->sun) {
717: if(l->islval < Sucompute)
718: rgenaddr(&nspare, l, ZeroN);
719: else
720: nspare = *l;
721: reg(&nr, r->t, ZeroN);
722: genexp(r, &nr);
723: } else {
724: reg(&nr, r->t, ZeroN);
725: genexp(r, &nr);
726: if(l->islval < Sucompute)
727: rgenaddr(&nspare, l, ZeroN);
728: else
729: nspare = *l;
730: }
731:
732: reg(&nl, rval->t, lval);
733: assign(&nspare, &nl);
734: codmop(rval, &nr, ZeroN, &nl);
735: assign(&nl, &nspare);
736: assign(&nl, lval);
737: regfree(&nl);
738: regfree(&nr);
739: if(l->islval < Sucompute)
740: regfree(&nspare);
741: break;
742:
743: case OADD:
744: case OSUB:
745: case OLAND:
746: case OLOR:
747: case OXOR:
748: case OLSH:
749: case ORSH:
750: case OALSH:
751: case OARSH:
752: if(lval == ZeroN)
753: break;
754:
755: /* Peel off the instructions with immediate operands */
756: if(r->t->type != TFLOAT)
757: if(r->type == OCONST) {
758: genexp(l, lval);
759: if(r->ival == 0)
760: if(rval->type != OLAND)
761: break;
762: codmop(rval, r, lval, lval);
763: break;
764: }
765:
766: /* Fall through */
767: case OMUL:
768: case ODIV:
769: case OMOD:
770: if(lval == ZeroN) {
771: warn(rval, "result ignored");
772: break;
773: }
774:
775: if(rval->type == OMUL && mulcon(rval, lval))
776: break;
777:
778: if(l->sun >= r->sun) {
779: reg(&nl, l->t, lval);
780: genexp(l, &nl);
781: reg(&nr, r->t, ZeroN);
782: genexp(r, &nr);
783: codmop(rval, &nr, &nl, &nl);
784: }
785: else {
786: reg(&nr, r->t, ZeroN);
787: genexp(r, &nr);
788: reg(&nl, l->t, lval);
789: genexp(l, &nl);
790: codmop(rval, &nr, &nl, &nl);
791: }
792: regfree(&nr);
793: assign(&nl, lval);
794: regfree(&nl);
795: break;
796:
797: case OPINC:
798: case OPDEC:
799: postop(rval, lval);
800: break;
801:
802: case OEINC:
803: case OEDEC:
804: preop(rval, lval);
805: break;
806:
807: case OSEND:
808: genexp(l, lval);
809: break;
810:
811: case ORECV:
812: case OCALL:
813: if(l->sun >= Sucall) {
814: reg(&nr, builtype[TIND], ZeroN);
815: genaddr(l, &nr);
816: if(nr.type != OREGISTER)
817: fatal("genexp: call %N", &nr);
818:
819: nstack = stknode(builtype[TIND]);
820: assign(&nr, nstack);
821: regfree(&nr);
822:
823: genarg(r);
824:
825: reg(&nr, builtype[TIND], ZeroN);
826: assign(nstack, &nr);
827: nr.type = OINDREG;
828: nr.ival = 0;
829: docall(&nr);
830: regfree(&nr);
831: break;
832: }
833:
834: genarg(r);
835:
836: if(!isaddr(l)) {
837: reg(&nr, builtype[TIND], ZeroN);
838: genaddr(l, &nr);
839: if(nr.type != OREGISTER)
840: fatal("genexp: call %N", &nr);
841: nr.type = OINDREG;
842: nr.ival = 0;
843: docall(&nr);
844: regfree(&nr);
845: }
846: else
847: docall(l);
848:
849: /* Return value */
850: if(lval) {
851: regret(&nr, rval->t);
852: assign(&nr, lval);
853: regfree(&nr);
854: }
855: break;
856:
857: }
858: }
859:
860: /*
861: * Compile assignment operator
862: */
863: void
864: oasgn(Node *rval, Node *lval)
865: {
866: Node n1, n2;
867: Node *l, *r;
868:
869: r = rval->right;
870: l = rval->left;
871:
872: if(opt('q')) {
873: print("OASGN r");
874: ptree(rval, 0);
875: print("OASGN l");
876: ptree(lval,0);
877: print("*\n");
878: }
879:
880: if(l->islval >= Sucompute)
881: if(l->sun < Sucall) {
882: if(lval != ZeroN || r->islval < Sucompute) {
883: reg(&n1, r->t, lval);
884: genexp(r, &n1);
885: assign(&n1, l);
886: regfree(&n1);
887: } else
888: assign(r, l);
889: return;
890: }
891:
892: if(l->sun >= r->sun) {
893: rgenaddr(&n2, l, ZeroN);
894: if(r->islval >= Sucompute) {
895: assign(r, &n2);
896: assign(r, lval);
897: regfree(&n2);
898: return;
899: }
900: reg(&n1, r->t, lval);
901: genexp(r, &n1);
902: } else {
903: reg(&n1, r->t, lval);
904: genexp(r, &n1);
905: rgenaddr(&n2, l, ZeroN);
906: }
907: assign(&n1, &n2);
908: regfree(&n1);
909: regfree(&n2);
910: }
911:
912: void
913: evalarg(Node *n, int pass)
914: {
915: Node *tmp, n1;
916:
917: if(n == ZeroN)
918: return;
919:
920: switch(n->type) {
921: case OLIST:
922: evalarg(n->left, pass);
923: evalarg(n->right, pass);
924: break;
925:
926: default:
927: switch(pass) {
928: case 0:
929: if(n->type == OBLOCK) {
930: stmnt(n->left);
931: *n = *n->right;
932: break;
933: }
934: if(n->sun < Sucall)
935: break;
936:
937: tmp = stknode(n->t);
938: n1.type = OASGN;
939: n1.left = tmp;
940: n1.right = n;
941: n1.t = n->t;
942: sucalc(&n1);
943: genexp(&n1, ZeroN);
944: *n = *tmp;
945: break;
946:
947: case 1:
948: if(atv)
949: tmp = atvnode(n->t);
950: else
951: tmp = argnode(n->t);
952: compute:
953: switch(n->t->type) {
954: default:
955: fatal("evalarg %T", n->t);
956: case TADT:
957: case TUNION:
958: case TAGGREGATE:
959: gencomplex(n, tmp);
960: break;
961:
962: case TSINT:
963: case TSUINT:
964: case TCHAR:
965: case TINT:
966: case TUINT:
967: case TIND:
968: case TFLOAT:
969: case TCHANNEL:
970: n1.type = OASGN;
971: n1.left = tmp;
972: n1.right = n;
973: n1.t = n->t;
974: sucalc(&n1);
975: genexp(&n1, ZeroN);
976: break;
977: }
978: break;
979: case 3:
980: /*
981: * Second pass becoming somebody else
982: */
983: tmp = atvnode(n->t);
984: if(n->type == ONAME)
985: if(n->ti->class == Parameter)
986: if(n->ti->offset == tmp->left->right->ival)
987: break;
988: goto compute;
989: case 4:
990: /*
991: * Second pass becoming myself
992: */
993: tmp = paramnode(n->t);
994: if(tmp->type == ONAME)
995: if(tmp->sym == n->sym)
996: if(tmp->ti->class == n->ti->class)
997: break;
998: goto compute;
999: }
1000: }
1001: }
1002:
1003: /*
1004: * genarg - Push function arguments onto the stack
1005: */
1006: void
1007: genarg(Node *n)
1008: {
1009: evalarg(n, 0);
1010:
1011: args = Argbase;
1012: if(atv) {
1013: reg(&ratv, builtype[TIND], 0);
1014: assign(atv, &ratv);
1015: ratv.type = OINDREG;
1016: ratv.ival = Argbase;
1017: evalarg(n, 1);
1018: return;
1019: }
1020:
1021: evalarg(n, 1);
1022: if(args > maxframe)
1023: maxframe = args;
1024: }
1025:
1026: /*
1027: * Compute the frame size of function arguments
1028: */
1029: void
1030: framesize(Node *n)
1031: {
1032: if(n == ZeroN)
1033: return;
1034:
1035: switch(n->type) {
1036: case OLIST:
1037: framesize(n->left);
1038: framesize(n->right);
1039: break;
1040:
1041: default:
1042: frsize = align(frsize, builtype[TINT]);
1043: frsize += n->t->size;
1044: }
1045: }
1046:
1047: void
1048: setcond(Node *lval)
1049: {
1050: Inst *true, *false;
1051:
1052: if(lval == ZeroN)
1053: return;
1054:
1055: true = ipc;
1056: assign(con(1), lval);
1057: instruction(AJMP, ZeroN, ZeroN, ZeroN);
1058: false = ipc;
1059: label(true, ipc->pc+1);
1060: assign(con(0), lval);
1061: label(false, ipc->pc+1);
1062: }
1063:
1064: void
1065: andand(Node *l, Node *r, int bool)
1066: {
1067: Inst *true, *false;
1068:
1069: if(l->t == ZeroT)
1070: instruction(AJMP, ZeroN, ZeroN, ZeroN);
1071: else
1072: gencond(l, ZeroN, bool);
1073:
1074: false = ipc;
1075:
1076: if(r->t == ZeroT)
1077: instruction(AJMP, ZeroN, ZeroN, ZeroN);
1078: else
1079: gencond(r, ZeroN, !bool);
1080:
1081: true = ipc;
1082:
1083: label(false, ipc->pc+1);
1084: instruction(AJMP, ZeroN, ZeroN, ZeroN);
1085: label(true, ipc->pc+1);
1086:
1087: }
1088:
1089: void
1090: oror(Node *l, Node *r, int bool)
1091: {
1092: Inst *false1, *false2;
1093:
1094: if(l->t == ZeroT)
1095: instruction(AJMP, ZeroN, ZeroN, ZeroN);
1096: else
1097: gencond(l, ZeroN, !bool);
1098:
1099: false1 = ipc;
1100:
1101: if(r->t == ZeroT)
1102: instruction(AJMP, ZeroN, ZeroN, ZeroN);
1103: else
1104: gencond(r, ZeroN, !bool);
1105:
1106: false2 = ipc;
1107:
1108: instruction(AJMP, ZeroN, ZeroN, ZeroN);
1109: label(false1, ipc->pc+1);
1110: label(false2, ipc->pc+1);
1111: }
1112:
1113: /*
1114: * Generate for boolean conditionals
1115: */
1116: void
1117: gencond(Node *rval, Node *lval, int bool)
1118: {
1119: int op;
1120: Node n1, n2;
1121: Node *l, *r, *nstack;
1122:
1123: l = rval->left;
1124: r = rval->right;
1125:
1126: op = rval->type;
1127: switch(op) {
1128: default:
1129: reg(&n1, rval->t, lval);
1130: genexp(rval, &n1);
1131: if(bool)
1132: op = OEQ;
1133: else
1134: op = ONEQ;
1135: codcond(op, &n1, con(0));
1136: setcond(lval);
1137: regfree(&n1);
1138: return;
1139:
1140: case OCAND:
1141: if(bool == False)
1142: oror(l, r, bool);
1143: else
1144: andand(l, r, bool);
1145: break;
1146:
1147: case OCOR:
1148: if(bool == False)
1149: andand(l, r, bool);
1150: else
1151: oror(l, r, bool);
1152: break;
1153:
1154: case ONOT:
1155: gencond(rval->left, lval, !bool);
1156: break;
1157:
1158: case OHI:
1159: case OLO:
1160: case OLOS:
1161: case OHIS:
1162: case OEQ:
1163: case OLEQ:
1164: case ONEQ:
1165: case OLT:
1166: case OGEQ:
1167: case OGT:
1168: if(r->sun >= Sucall && l->sun >= Sucall) {
1169: nstack = stknode(l->t);
1170: genexp(l, nstack);
1171: rval->left = nstack;
1172: gencond(rval, lval, bool);
1173: return;
1174: }
1175:
1176: if(bool)
1177: op = not[op];
1178:
1179: if(immed(r)) {
1180: reg(&n1, l->t, lval);
1181: genexp(l, &n1);
1182: codcond(op, &n1, r);
1183: regfree(&n1);
1184: setcond(lval);
1185: return;
1186: }
1187: if(l->sun >= r->sun) {
1188: reg(&n1, l->t, lval);
1189: genexp(l, &n1);
1190: reg(&n2, r->t, ZeroN);
1191: genexp(r, &n2);
1192: }
1193: else {
1194: reg(&n2, r->t, lval);
1195: genexp(r, &n2);
1196: reg(&n1, l->t, ZeroN);
1197: genexp(l, &n1);
1198: }
1199: codcond(op, &n1, &n2);
1200: regfree(&n1);
1201: regfree(&n2);
1202: }
1203: setcond(lval);
1204: }
1205:
1206: void
1207: genelist(Node *n)
1208: {
1209: if(n == ZeroN)
1210: return;
1211:
1212: switch(n->type) {
1213: case OLIST:
1214: genelist(n->left);
1215: genelist(n->right);
1216: break;
1217: default:
1218: genexp(n, ZeroN);
1219: break;
1220: }
1221: }
1222:
1223: void
1224: gensubreg(Node *n, Node *reg)
1225: {
1226: if(n == ZeroN)
1227: return;
1228:
1229: switch(n->type) {
1230: default:
1231: gensubreg(n->left, reg);
1232: gensubreg(n->right, reg);
1233: break;
1234: case OREGISTER:
1235: *n = *reg;
1236: break;
1237: }
1238: }
1239:
1240: void
1241: genmove(Node *rval, Type *rt, Node *lval, int o)
1242: {
1243: Type *t;
1244: Node *l, *r;
1245:
1246: for(t = rt->next; t; t = t->member) {
1247: switch(t->type) {
1248: case TFUNC:
1249: break;
1250: case TADT:
1251: case TAGGREGATE:
1252: genmove(rval, t, lval, t->offset);
1253: break;
1254: default:
1255: r = an(OADDR, rval, ZeroN);
1256: r->t = at(TIND, t);
1257: r = an(OADD, r, con(o+t->offset));
1258: r->t = r->left->t;
1259: r = an(OIND, r, ZeroN);
1260: r->t = t;
1261: l = an(OADDR, lval, ZeroN);
1262: l->t = at(TIND, t);
1263: l = an(OADD, l, con(o+t->offset));
1264: l->t = l->left->t;
1265: l = an(OIND, l, ZeroN);
1266: l->t = t;
1267: sucalc(r);
1268: sucalc(l);
1269: genexp(r, l);
1270: }
1271: }
1272: }
1273:
1274: int
1275: bitmove(Node *rval, Node *lval)
1276: {
1277: if(!isaddr(rval))
1278: return 0;
1279:
1280: if(!isaddr(lval))
1281: return 0;
1282:
1283: genmove(rval, rval->t, lval, 0);
1284: return 1;
1285: }
1286:
1287: /*
1288: * generate moves for complex types
1289: */
1290: void
1291: gencomplex(Node *rval, Node *lval)
1292: {
1293: Type *t;
1294: Inst *back;
1295: int size, w, i, o;
1296: Node *l, *r, *tmp, *ptr;
1297: Node n1, n2, treg, loop;
1298:
1299: if(opt('x')) {
1300: print("GENCOM r\n");
1301: ptree(rval, 0);
1302: print("*\nGENCOM l\n");
1303: ptree(lval, 0);
1304: }
1305:
1306: r = rval->right;
1307: l = rval->left;
1308:
1309: switch(rval->type) {
1310: case OBLOCK:
1311: bstmnt(l);
1312: gencomplex(r, lval);
1313: break;
1314:
1315: case ODOT:
1316: tmp = stknode(l->t);
1317: genexp(l, tmp);
1318: if(rval == ZeroN)
1319: break;
1320:
1321: tmp->ival = r->ival;
1322: tmp->t = rval->t;
1323: genexp(tmp, lval);
1324: break;
1325:
1326: case OASGN:
1327: if(l->type == OILIST) {
1328: if(!isaddr(r) || lval != 0) {
1329: tmp = stknode(r->t);
1330: gencomplex(r, tmp);
1331: }
1332: else
1333: tmp = r;
1334:
1335: reg(&treg, builtype[TIND], ZeroN);
1336: genaddr(tmp, &treg);
1337: ptr = stknode(builtype[TIND]);
1338: assign(&treg, ptr);
1339: regfree(&treg);
1340:
1341: gensubreg(l->left, ptr);
1342: genelist(l->left);
1343: if(lval)
1344: gencomplex(tmp, lval);
1345: break;
1346: }
1347: if(lval == ZeroN) {
1348: if(rval->islval < Sucompute)
1349: gencomplex(r, l);
1350: break;
1351: }
1352: tmp = stknode(rval->t);
1353: gencomplex(r, tmp);
1354: gencomplex(tmp, l);
1355: gencomplex(tmp, lval);
1356: break;
1357:
1358: case ORECV:
1359: case OCALL:
1360: if(lval == ZeroN) {
1361: tmp = stknode(rval->t);
1362: gencomplex(rval, tmp);
1363: break;
1364: }
1365:
1366: if(l->sun >= Sucall) {
1367: reg(&treg, builtype[TIND], ZeroN);
1368: genaddr(l, &treg);
1369: if(treg.type != OREGISTER)
1370: fatal("gencomplex: call %N", &treg);
1371:
1372: l = stknode(builtype[TIND]);
1373: l = an(OIND, l, ZeroN);
1374: l->t = builtype[TIND];
1375: assign(&treg, l);
1376: regfree(&treg);
1377: }
1378: genarg(r);
1379:
1380: t = at(TIND, lval->t);
1381: regret(&n1, t);
1382: if(isaddr(lval)) {
1383: lval = an(OADDR, lval, ZeroN);
1384: lval->t = t;
1385: genexp(lval, &n1);
1386: tmp = ZeroN;
1387: }
1388: else {
1389: tmp = stknode(lval->t);
1390: n2.type = OADDR;
1391: n2.ival = 0;
1392: n2.t = t;
1393: n2.left = tmp;
1394: n2.right = ZeroN;
1395: genexp(&n2, &n1);
1396: }
1397:
1398: if(!isaddr(l)) {
1399: reg(&treg, builtype[TIND], ZeroN);
1400: genaddr(l, &treg);
1401: if(treg.type != OREGISTER)
1402: fatal("gencomplex: call %N", &treg);
1403:
1404: treg.type = OINDREG;
1405: treg.ival = 0;
1406: docall(&treg);
1407: regfree(&treg);
1408: }
1409: else
1410: docall(l);
1411:
1412: regfree(&n1);
1413:
1414: if(tmp)
1415: gencomplex(tmp, lval);
1416:
1417: break;
1418:
1419: case OILIST:
1420: if(lval == ZeroN) {
1421: warn(rval, "result ignored");
1422: break;
1423: }
1424:
1425: t = lval->t;
1426: lval->t = builtype[TINT];
1427: rgenaddr(&n2, lval, ZeroN);
1428: if(t->type == TPOLY)
1429: lval->t = polyshape;
1430: else
1431: lval->t = t;
1432: o = n2.ival;
1433: n2.ival = 0;
1434: cominit(&n2, lval->t, rval, o);
1435: regfree(&n2);
1436: break;
1437:
1438: default:
1439: if(lval == ZeroN) {
1440: warn(rval, "result ignored");
1441: break;
1442: }
1443:
1444: size = rval->t->size;
1445: w = builtype[TINT]->size;
1446: size /= w;
1447: if(size < 6 && notunion(rval->t) && bitmove(rval, lval))
1448: break;
1449:
1450: if(rval->sun > lval->sun) {
1451: t = rval->t;
1452: rval->t = builtype[TINT];
1453: rgenaddr(&n1, rval, ZeroN);
1454: rval->t = t;
1455:
1456: t = lval->t;
1457: lval->t = builtype[TINT];
1458: rgenaddr(&n2, lval, ZeroN);
1459: lval->t = t;
1460: }
1461: else {
1462: t = lval->t;
1463: lval->t = builtype[TINT];
1464: rgenaddr(&n2, lval, ZeroN);
1465: lval->t = t;
1466:
1467: t = rval->t;
1468: rval->t = builtype[TINT];
1469: rgenaddr(&n1, rval, ZeroN);
1470: rval->t = t;
1471: }
1472:
1473: reg(&treg, builtype[TINT], ZeroN);
1474: if(size < 6) {
1475: for(i = 0; i < size; i++) {
1476: instruction(AMOVW, &n1, ZeroN, &treg);
1477: instruction(AMOVW, &treg, ZeroN, &n2);
1478: n1.ival += w;
1479: n2.ival += w;
1480: }
1481: }
1482: else {
1483: reg(&loop, builtype[TINT], ZeroN);
1484:
1485: instruction(AMOVW, con(size), ZeroN, &loop);
1486: instruction(AMOVW, &n1, ZeroN, &treg);
1487: back = ipc;
1488: instruction(AMOVW, &treg, ZeroN, &n2);
1489: n1.type = OREGISTER;
1490: n2.type = OREGISTER;
1491: instruction(AADD, con(w), ZeroN, &n1);
1492: instruction(AADD, con(w), ZeroN, &n2);
1493: instruction(ASUBCC, con(1), ZeroN, &loop);
1494: instruction(ABNE, ZeroN, ZeroN, ZeroN);
1495: label(ipc, back->pc);
1496: regfree(&loop);
1497: }
1498: regfree(&treg);
1499: regfree(&n1);
1500: regfree(&n2);
1501: }
1502: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.