|
|
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: static Glab *gotos;
10: static Glab *labels;
11: static Jmps *contstack;
12: static Jmps *brkstack;
13: static Jmps *retstack;
14: static Jmps *rescues;
15: static Node *lstmnt;
16:
17: /* Compile a function */
18: void
19: fungen(Node *code, Node *args)
20: {
21: int l;
22: Type *t;
23: Node n1;
24: ulong rpc;
25: Inst *fcode;
26:
27: l = line;
28: fcode = ipc;
29:
30: iter(code, 1);
31: typechk(code, 0);
32: rewrite(code);
33:
34: args->left->right = code;
35:
36: if(code)
37: sucalc(code);
38:
39: if(opt('t')) {
40: print("\nTree:\n");
41: ptree(code, 0);
42: }
43:
44: /* Clear the label stack */
45: labels = 0;
46: gotos = 0;
47: rescues = 0;
48:
49: if(opt('q') == 0 && nerr == 0) {
50: t = curfunc->t->next;
51: switch(t->type) {
52: case TPOLY:
53: curfunc = dupn(curfunc);
54: curfunc->t = at(TFUNC, polyshape);
55: /* No Break */
56: case TADT:
57: case TUNION:
58: case TAGGREGATE:
59: t = at(TIND, t);
60: regret(&n1, t);
61: rnode = stknode(n1.t);
62: assign(&n1, rnode);
63: regfree(&n1);
64: becomentry = ipc;
65: }
66:
67: lstmnt = nil;
68: if(code)
69: stmnt(code);
70:
71: if(t->type != TVOID)
72: if(lstmnt == 0 ||
73: (lstmnt->type != ORET && lstmnt->type != OBECOME))
74: diag(lstmnt, "typed function has no return");
75:
76: rpc = ipc->pc+1;
77: /* Improve optimiser by using non return register */
78: switch(t->type) {
79: case TVOID:
80: instruction(ANOP, ZeroN, ZeroN, regn(Freg));
81: instruction(ANOP, ZeroN, ZeroN, regn(Retireg));
82: break;
83: case TFLOAT:
84: instruction(ANOP, ZeroN, ZeroN, regn(Retireg));
85: break;
86: default:
87: instruction(ANOP, ZeroN, ZeroN, regn(Freg));
88: break;
89: }
90:
91: instruction(ARETURN, ZeroN, ZeroN, ZeroN);
92:
93: /* Patch in all the returns */
94: while(retstack) {
95: label(retstack->i, rpc);
96: popjmp(&retstack);
97: }
98:
99: /* Back patch the entry */
100: resolvegoto();
101:
102: /* Patch in the frame size */
103: funentry->dst.ival = maxframe + frame;
104: }
105:
106: leaveblock();
107:
108: regcheck();
109:
110: if(opt('N') || opt('R') || opt('P'))
111: regopt(fcode);
112:
113: line = l;
114: }
115:
116: void
117: bstmnt(Node *n)
118: {
119: Node *tmp;
120:
121: tmp = lstmnt;
122: stmnt(n);
123: lstmnt = tmp;
124: }
125:
126: /* Compile code for a statement */
127: void
128: stmnt(Node *n)
129: {
130: Jmps *p;
131: Node *l, *r, n1, com;
132: Inst *false, *truedone, *loop, *enter;
133:
134: if(n == ZeroN)
135: return;
136:
137: l = n->left;
138: r = n->right;
139: iline = n->srcline;
140: lstmnt = n;
141:
142: switch(n->type) {
143: default:
144: genexp(n, ZeroN);
145: break;
146:
147: case OLIST:
148: stmnt(l);
149: stmnt(r);
150: break;
151:
152: case OBLOCK:
153: stmnt(l);
154: break;
155:
156: case OLBLOCK:
157: if(l == ZeroN) {
158: warn(n, "empty guarded block");
159: break;
160: }
161: lblock(l);
162: break;
163:
164: case OPAR:
165: parcode(l->left);
166: break;
167:
168: case OSWITCH:
169: switchcode(n);
170: break;
171:
172: case OSELECT:
173: selcode(n);
174: break;
175:
176: case OGOTO:
177: instruction(AJMP, ZeroN, ZeroN, ZeroN);
178: setgoto(n, ipc);
179: break;
180:
181: case OLABEL:
182: setlabel(n, ipc->pc+1);
183: break;
184:
185: case OCASE:
186: case ODEFAULT:
187: n->pc = ipc->pc+1;
188:
189: if(l && l->type != OCONST)
190: stmnt(l);
191:
192: if(r)
193: stmnt(r);
194: break;
195:
196: case OIF:
197: gencond(l, ZeroN, True);
198: false = ipc;
199: if(r && r->type == OELSE) {
200: stmnt(r->left);
201: truedone = instruction(AJMP, ZeroN, ZeroN, ZeroN);
202: label(false, ipc->pc+1);
203: stmnt(r->right);
204: label(truedone, ipc->pc+1);
205: break;
206: }
207:
208: if(r)
209: stmnt(r);
210:
211: label(false, ipc->pc+1);
212: break;
213:
214: case ORET:
215: if(l) {
216: switch(l->t->type) {
217: default:
218: regret(&n1, l->t);
219: genexp(l, &n1);
220: regfree(&n1);
221: break;
222:
223: case TADT:
224: case TUNION:
225: case TAGGREGATE:
226: com.type = OASGN;
227: com.t = l->t;
228: com.left = an(OIND, rnode, ZeroN);
229: com.left->t = rnode->t->next;
230: com.right = l;
231: sucalc(&com);
232: genexp(&com, ZeroN);
233: break;
234: }
235: }
236:
237: instruction(AJMP, ZeroN, ZeroN, ZeroN);
238: pushjmp(&retstack);
239: break;
240:
241: case ODWHILE:
242: instruction(AJMP, ZeroN, ZeroN, ZeroN);
243: enter = ipc;
244: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Continue */
245: pushjmp(&contstack);
246: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Break */
247: pushjmp(&brkstack);
248:
249: label(enter, ipc->pc+1);
250: loop = ipc;
251: if(r)
252: stmnt(r);
253:
254: label(contstack->i, ipc->pc+1);
255: if(l) {
256: gencond(l, ZeroN, True);
257: label(ipc, brkstack->i->pc);
258: }
259: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Loop */
260: label(ipc, loop->pc+1);
261:
262: label(brkstack->i, ipc->pc+1);
263: popjmp(&contstack);
264: popjmp(&brkstack);
265: break;
266:
267: case OWHILE:
268: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Continue */
269: pushjmp(&contstack);
270: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Break */
271: pushjmp(&brkstack);
272:
273: label(contstack->i, ipc->pc+1);
274: loop = ipc;
275: if(l) { /* Cond */
276: gencond(l, ZeroN, True);
277: label(ipc, brkstack->i->pc);
278: }
279:
280: if(r)
281: stmnt(r);
282:
283: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Loop */
284: label(ipc, loop->pc+1);
285:
286: label(brkstack->i, ipc->pc+1);
287: popjmp(&contstack);
288: popjmp(&brkstack);
289: break;
290:
291: case OFOR:
292: if(l->left) /* Assign */
293: genexp(l->left, ZeroN);
294:
295: l = l->right;
296:
297: instruction(AJMP, ZeroN, ZeroN, ZeroN);
298: enter = ipc;
299: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Continue */
300: pushjmp(&contstack);
301: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Break */
302: pushjmp(&brkstack);
303: label(enter, ipc->pc+1);
304:
305: if(l->left) { /* Cond */
306: gencond(l->left, ZeroN, True);
307: label(ipc, brkstack->i->pc);
308: }
309: if(r)
310: stmnt(r);
311: label(contstack->i, ipc->pc+1);
312: if(l->right) /* Action */
313: genexp(l->right, ZeroN);
314:
315: instruction(AJMP, ZeroN, ZeroN, ZeroN);
316: label(ipc, enter->pc);
317:
318: label(brkstack->i, ipc->pc+1);
319: popjmp(&contstack);
320: popjmp(&brkstack);
321: break;
322:
323: case ORAISE:
324: if(l) {
325: instruction(AJMP, ZeroN, ZeroN, ZeroN);
326: setgoto(l, ipc);
327: break;
328: }
329: if(rescues == 0) {
330: diag(n, "raise without rescue");
331: break;
332: }
333: instruction(AJMP, ZeroN, ZeroN, ZeroN);
334: label(ipc, rescues->i->pc+1);
335: if(rescues->par != inpar)
336: diag(n, "raise breaks join in par");
337: if(rescues->crit != incrit)
338: diag(n, "raise breaks critical section");
339: break;
340:
341: case ORESCUE:
342: instruction(AJMP, ZeroN, ZeroN, ZeroN);
343: enter = ipc;
344: if(l->type == OLABEL) {
345: setlabel(l, ipc->pc+1);
346: l = l->left;
347: }
348: stmnt(l);
349: label(enter, ipc->pc+1);
350: pushlab(&rescues, enter);
351: break;
352:
353: case OBREAK:
354: p = brkstack;
355: while(p) {
356: n->ival--;
357: if(n->ival == 0)
358: break;
359: p = p->next;
360: }
361: if(p) {
362: if(p->par != inpar)
363: diag(n, "break breaks join in par");
364: if(p->crit != incrit)
365: diag(n, "break breaks critical section");
366: instruction(AJMP, ZeroN, ZeroN, ZeroN);
367: label(ipc, p->i->pc);
368: break;
369: }
370: diag(n, "break not in loop/switch/select");
371: break;
372:
373: case OCONT:
374: p = contstack;
375: while(p) {
376: n->ival--;
377: if(n->ival == 0)
378: break;
379: p = p->next;
380: }
381: if(p) {
382: if(p->par != inpar)
383: diag(n, "continue breaks join in par");
384: if(p->crit != incrit)
385: diag(n, "continue breaks critical section");
386: instruction(AJMP, ZeroN, ZeroN, ZeroN);
387: label(ipc, p->i->pc);
388: break;
389: }
390: diag(n, "continue not in loop");
391: break;
392: }
393: }
394:
395: int
396: cascmp(Node **a, Node **b)
397: {
398: int av, bv;
399:
400: av = (*a)->left->ival;
401: bv = (*b)->left->ival;
402: if(av < bv)
403: return -1;
404: return av > bv;
405: }
406:
407: void
408: casecount(Node *n, Node **vec)
409: {
410: if(n == ZeroN)
411: return;
412:
413: switch(n->type) {
414: case ODEFAULT:
415: case OCASE:
416: if(vec)
417: vec[veccnt] = n;
418: veccnt++;
419: break;
420:
421: default:
422: casecount(n->left, vec);
423: casecount(n->right, vec);
424: break;
425: }
426: }
427:
428: void
429: switchcode(Node *n)
430: {
431: Node val;
432: long defpc;
433: Inst *enter;
434: int i, r, safe;
435: Node **cases, *defl, *c, *il, com;
436:
437: c = n->right;
438: if(c == ZeroN) {
439: warn(n, "empty switch statement");
440: return;
441: }
442:
443: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Entry */
444: enter = ipc;
445: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Break */
446: pushjmp(&brkstack);
447:
448: safe = 0;
449: if(c->type == OLBLOCK) {
450: incrit++;
451: safe = 1;
452: c = c->left;
453: }
454: /* Generate the code */
455: stmnt(c);
456:
457: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Done break */
458: label(ipc, brkstack->i->pc);
459:
460: /* Count */
461: veccnt = 0;
462: casecount(c, 0);
463:
464: /* Save */
465: cases = malloc(sizeof(Node*)*veccnt);
466: veccnt = 0;
467: casecount(c, cases);
468:
469: defl = 0;
470: for(i = 0; i < veccnt; i++) {
471: c = cases[i];
472: switch(c->type) {
473: case OCASE:
474: if(c->left->type != OCONST) {
475: diag(c, "case must be constant");
476: cases[i] = ZeroN;
477: }
478: break;
479:
480: case ODEFAULT:
481: if(defl)
482: diag(c, "switch already has default");
483: defl = c;
484: cases[i] = ZeroN;
485: break;
486: }
487: }
488:
489: /* Close up the table */
490: for(i = 0; i < veccnt; i++) {
491: if(cases[i] == ZeroN) {
492: veccnt--;
493: memmove(cases+i, cases+i+1, (veccnt-i)*sizeof(Node*));
494: }
495: }
496:
497: qsort(cases, veccnt, sizeof(Node*), cascmp);
498:
499: for(i = 0; i < veccnt-1; i++) {
500: r = cases[i]->left->ival;
501: if(r == cases[i+1]->left->ival)
502: diag(cases[i+1], "duplicate case %d in switch", r);
503: }
504:
505: label(enter, ipc->pc+1);
506: SET(il);
507: if(safe) {
508: il = internnode(builtype[TIND]);
509: il = an(OADDR, il, ZeroN);
510: il->t = builtype[TIND];
511:
512: com.type = OCALL;
513: com.t = builtype[TVOID];
514: com.left = ginode;
515: com.right = il;
516:
517: sucalc(&com);
518: stmnt(&com);
519: }
520:
521: reg(&val, builtype[TINT], ZeroN);
522: genexp(n->left, &val);
523:
524: defpc = brkstack->i->pc;
525: if(defl)
526: defpc = defl->pc;
527:
528: gencmps(cases, veccnt, defpc, &val);
529:
530: regfree(&val);
531: label(brkstack->i, ipc->pc+1);
532:
533: if(safe) {
534: com.type = OCALL;
535: com.t = builtype[TVOID];
536: com.left = gonode;
537: com.right = il;
538:
539: sucalc(&com);
540: stmnt(&com);
541: incrit--;
542: }
543: popjmp(&brkstack);
544: }
545:
546: Node*
547: gcom(Node *n)
548: {
549: Node *l;
550:
551: if(n == 0)
552: return ZeroN;
553:
554: switch(n->type) {
555: case ORECV:
556: return n;
557: case OCALL:
558: if(issend(n->left))
559: return n;
560: /* Fall through */
561: default:
562: l = gcom(n->left);
563: if(l == 0)
564: l = gcom(n->right);
565: return l;
566: }
567: }
568:
569: int
570: regcode(Node **cases, int cnt)
571: {
572: int i, var;
573: Node *l, *c;
574:
575: var = 0;
576: for(i = 0; i < cnt; i++) {
577: c = cases[i];
578: switch(c->type) {
579: case OCASE:
580: l = gcom(c->left);
581: if(l == 0) {
582: diag(c, "case expr needs send/receive");
583: cases[i] = ZeroN;
584: break;
585: }
586: if(l->t->variant)
587: var++;
588: switch(l->type) {
589: default: /* Catch the send rewrites */
590: l->left = selsend;
591: c->t = l->t;
592: l->t = builtype[TVOID];
593: break;
594: case ORECV:
595: case OCRCV:
596: c->left = l;
597: l->type = OCALL;
598: c->t = l->t;
599: l->t = builtype[TVOID];
600: l->left = selrecv;
601: break;
602: }
603: /* Only the channel argument */
604: while(l->right->type == OLIST)
605: l->right = l->right->left;
606: break;
607: case ODEFAULT:
608: diag(c, "alt already has default");
609: cases[i] = ZeroN;
610: break;
611: }
612: }
613: return var;
614: }
615:
616: void
617: selcode(Node *n)
618: {
619: Inst *enter;
620: Node val, com;
621: int i, x, safe, var;
622: Node **cases, *c, *il;
623:
624: safe = 0;
625:
626: val.srcline = n->srcline;
627: com.srcline = n->srcline;
628:
629: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Entry */
630: enter = ipc;
631: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Break */
632: pushjmp(&brkstack);
633:
634: c = n->left;
635: if(c == nil)
636: return;
637: if(c->type == OLBLOCK) {
638: incrit++;
639: safe = 1;
640: c = c->left;
641: }
642: stmnt(c);
643:
644: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Done break */
645: label(ipc, brkstack->i->pc);
646:
647: veccnt = 0;
648: casecount(n->left, 0);
649: cases = malloc(sizeof(Node*)*veccnt);
650: veccnt = 0;
651: casecount(n->left, cases);
652:
653: /* Convert expression to register channels for select */
654: var = regcode(cases, veccnt);
655:
656: for(i = 0; i < veccnt; i++) {
657: if(cases[i] == ZeroN) {
658: veccnt--;
659: memmove(cases+i, cases+i+1, (veccnt-i)*sizeof(Node*));
660: }
661: }
662: if(veccnt == 0)
663: return;
664:
665: label(enter, ipc->pc+1);
666: SET(il);
667: if(safe) {
668: il = internnode(builtype[TIND]);
669: il = an(OADDR, il, ZeroN);
670: il->t = builtype[TIND];
671:
672: com.type = OCALL;
673: com.t = builtype[TVOID];
674: com.left = ginode;
675: com.right = il;
676:
677: sucalc(&com);
678: stmnt(&com);
679: }
680:
681: /* Assign values */
682: for(i = 0; i < veccnt; i++) {
683: c = cases[i];
684: x = i;
685: if(var)
686: x = typesig(c->t);
687: c->left->ival = x;
688: }
689:
690: /* Sort if type match */
691: if(var)
692: qsort(cases, veccnt, sizeof(Node*), cascmp);
693:
694: /* Detect type clashes */
695: for(i = 0; i < veccnt-1; i++) {
696: c = cases[i];
697: if(c->left->ival == cases[i+1]->left->ival)
698: diag(c, "duplicate variant type %V", c->t);
699: }
700:
701: /* Code the selsend/selrecv expressions */
702: for(i = 0; i < veccnt; i++)
703: genexp(cases[i]->left, ZeroN);
704:
705: com.type = OCALL;
706: com.t = builtype[TVOID];
707: com.left = doselect;
708: if(var)
709: com.left = varselect;
710: com.right = ZeroN;
711: sucalc(&com);
712: stmnt(&com);
713:
714: regret(&val, builtype[TINT]);
715: gencmps(cases, veccnt, -1, &val);
716: regfree(&val);
717:
718: label(brkstack->i, ipc->pc+1);
719: if(safe) {
720: com.type = OCALL;
721: com.t = builtype[TVOID];
722: com.left = gonode;
723: com.right = il;
724: sucalc(&com);
725: stmnt(&com);
726: incrit--;
727: }
728: popjmp(&brkstack);
729: }
730:
731: void
732: gencmps(Node **c, int cnt, long defpc, Node *val)
733: {
734: Node n, con, **r;
735: int i;
736: Inst *patch;
737:
738: con.type = OCONST;
739: con.t = builtype[TINT];
740:
741: if(cnt < 4) {
742: for(i = 0; i < cnt; i++) {
743: con.ival = (*c)->left->ival;
744: reg(&n, builtype[TINT], ZeroN);
745: assign(&con, &n);
746: codcond(OEQ, &n, val);
747: label(ipc, (*c)->pc);
748: regfree(&n);
749: c++;
750: }
751: if(defpc != -1) {
752: instruction(AJMP, ZeroN, ZeroN, ZeroN);
753: label(ipc, defpc);
754: }
755: return;
756: }
757: i = cnt/2;
758: r = c+i;
759:
760: con.ival = (*r)->left->ival;
761: reg(&n, builtype[TINT], ZeroN);
762: assign(&con, &n);
763: codcond(OLT, &n, val);
764: patch = ipc;
765: codcond(OEQ, &n, val);
766: label(ipc, (*r)->pc);
767: regfree(&n);
768: gencmps(c, i, defpc, val);
769:
770: label(patch, ipc->pc+1);
771: gencmps(r+1, cnt-i-1, defpc, val);
772: }
773:
774: ulong
775: framefind(Node *n)
776: {
777: ulong l, r;
778:
779: if(n == ZeroN)
780: return 0;
781:
782: switch(n->type) {
783: default:
784: l = framefind(n->left);
785: r = framefind(n->right);
786: if(r > l)
787: l = r;
788: break;
789: case OCALL:
790: frsize = 0;
791: framesize(n->right);
792: l = frsize;
793: }
794: return l;
795: }
796:
797: void
798: parcode(Node *n)
799: {
800: Type *t;
801: ulong frs;
802: int i, cnt;
803: Inst *loop;
804: Node *barrier, **slist, com, retr;
805: Node *stv, *stvp, *oatv, *p;
806:
807: veccnt = 0;
808: listcount(n, 0);
809: slist = malloc(sizeof(Node*)*veccnt);
810: veccnt = 0;
811: listcount(n, slist);
812:
813: if(opt('O')) {
814: for(i = 0; i < veccnt; i++) {
815: ptree(slist[i], 0);
816: print("*\n");
817: }
818: }
819:
820: if(veccnt < 2) {
821: warn(n, "only one statement in par");
822: stmnt(slist[0]);
823: return;
824: }
825:
826: inpar++;
827: oatv = atv;
828: cnt = veccnt;
829:
830: /*
831: * This slime is Parrend in the runtime
832: */
833: t = at(TAGGREGATE, 0);
834: t->size = SZPAREND*builtype[TINT]->size;
835: barrier = an(OADDR, stknode(t), ZeroN);
836: barrier->t = at(TIND, t);
837:
838: /*
839: * Build activation vector
840: */
841: t = at(TIND, builtype[TIND]);
842: t->size = t->next->size * cnt;
843: stv = stknode(t);
844: stv->ti->t = at(TARRAY, 0);
845:
846: /*
847: * craft: pid = pfork(cnt, stv)
848: */
849: com.type = OCALL;
850: com.t = builtype[TINT];
851: com.left = pforknode;
852: stvp = an(OADDR, stv, ZeroN);
853: stvp->t = builtype[TIND];
854: com.right = an(OLIST, con(veccnt-1), an(OLIST, stvp, barrier));
855:
856: sucalc(&com);
857: genexp(&com, ZeroN);
858:
859: for(i = 0; i < cnt-1; i++) {
860: regret(&retr, builtype[TINT]);
861: instruction(ACMP, con(i), ZeroN, &retr);
862: instruction(ABNE, ZeroN, ZeroN, ZeroN);
863: loop = ipc;
864: regfree(&retr);
865:
866: /*
867: * find the largest frame in this activation
868: */
869: frs = framefind(slist[i]);
870: /* ensure enough space for ALEF_pexit args */
871: if(frs < 2*builtype[TIND]->size) {
872: frs = 2*builtype[TIND]->size;
873: frs = align(frs, builtype[TIND]);
874: }
875: if(opt('O'))
876: print("%d: frame %d\n", i, frs);
877:
878: /*
879: * Compute my activation from stack vector: atv = stv[pid]
880: */
881: t = builtype[TIND];
882: atv = stknode(t);
883: p = an(OADD, stvp, con(i*builtype[TIND]->size));
884: p->t = t;
885: p = an(OIND, p, ZeroN);
886: p->t = t;
887: /*
888: * 2*sizeof(*) is enough for save SP at activation top plus hole
889: * for the saved activation pc
890: */
891: p = an(OSUB, p, con(frs+2*builtype[TIND]->size));
892: p->t = t;
893: /*
894: * word used for activation link
895: */
896: atv->atvsafe = frs+builtype[TIND]->size;
897: p = an(OASGN, atv, p);
898: p->t = t;
899:
900: sucalc(p);
901: genexp(p, ZeroN);
902:
903: stmnt(slist[i]);
904:
905: com.type = OCALL;
906: com.t = builtype[TVOID];
907: com.left = pexitnode;
908: com.right = barrier;
909:
910: sucalc(&com);
911: stmnt(&com);
912:
913: label(loop, ipc->pc+1);
914: }
915: atv = oatv;
916:
917: stmnt(slist[i]);
918:
919: /*
920: * craft terminator: ALEF_pdone(&barrier, stv);
921: */
922: com.type = OCALL;
923: com.t = builtype[TINT];
924: com.left = pdonenode;
925: stvp = an(OADDR, stv, ZeroN);
926: stvp->t = builtype[TIND];
927: com.right = an(OLIST, barrier, stvp);
928:
929: sucalc(&com);
930: stmnt(&com);
931:
932: inpar--;
933: }
934:
935: void
936: lblock(Node *n)
937: {
938: Node com, *i;
939:
940: i = internnode(builtype[TIND]);
941: i = an(OADDR, i, ZeroN);
942: i->t = builtype[TIND];
943:
944: com.type = OCALL;
945: com.t = builtype[TVOID];
946: com.left = ginode;
947: com.right = i;
948: sucalc(&com);
949: stmnt(&com);
950:
951: incrit++;
952: stmnt(n);
953: incrit--;
954:
955: com.type = OCALL;
956: com.t = builtype[TVOID];
957: com.left = gonode;
958: com.right = i;
959: sucalc(&com);
960: stmnt(&com);
961: }
962:
963: /* determine addressablility and number of registers */
964: void
965: sucalc(Node *n)
966: {
967: Node *l, *r;
968:
969: if(n == 0)
970: return;
971:
972: l = n->left;
973: r = n->right;
974: n->sun = 0;
975: n->islval = 0;
976:
977: /* Addressability */
978: switch(n->type) {
979: case OBECOME:
980: sucalc(l);
981: if(l->type == OCALL)
982: n->right = paramdep(l->right);
983: return;
984:
985: case OCONST:
986: n->islval = 20;
987: return;
988:
989: case OREGISTER:
990: n->islval = 11;
991: return;
992:
993: case OINDREG:
994: n->islval = 12;
995: return;
996:
997: case ONAME:
998: n->islval = 10;
999: return;
1000:
1001: case OADDR:
1002: sucalc(l);
1003: if(l->islval == 10)
1004: n->islval = 2;
1005: if(l->islval == 12)
1006: n->islval = 3;
1007: break;
1008:
1009: case OIND:
1010: sucalc(l);
1011: if(l->islval == 11)
1012: n->islval = 12;
1013: if(l->islval == 3)
1014: n->islval = 12;
1015: if(l->islval == 2)
1016: n->islval = 10;
1017: break;
1018:
1019: case OADD:
1020: sucalc(l);
1021: sucalc(r);
1022: if(l->islval == 20) {
1023: if(r->islval == 2)
1024: n->islval = 2;
1025: if(r->islval == 3)
1026: n->islval = 3;
1027: }
1028: if(r->islval == 20) {
1029: if(l->islval == 2)
1030: n->islval = 2;
1031: if(l->islval == 3)
1032: n->islval = 3;
1033: }
1034: break;
1035:
1036: default:
1037: sucalc(l);
1038: sucalc(r);
1039: break;
1040: }
1041:
1042: /* Number of registers */
1043: switch(n->type) {
1044: default:
1045: if(l != ZeroN)
1046: n->sun = l->sun;
1047: if(r != ZeroN) {
1048: if(n->sun == r->sun)
1049: n->sun = n->sun + 1;
1050: else if(r->sun > n->sun)
1051: n->sun = r->sun;
1052: }
1053: if(n->sun == 0)
1054: n->sun = 1;
1055: break;
1056:
1057: case OCALL:
1058: case OSEND:
1059: case ORECV:
1060: n->sun = Sucall;
1061: break;
1062: }
1063: }
1064:
1065: void
1066: setlabel(Node *n, ulong pc)
1067: {
1068: Glab *i;
1069:
1070: for(i = labels; i; i = i->next) {
1071: if(i->n->sym == n->sym) {
1072: diag(n, "label %s used twice", n->sym->name);
1073: return;
1074: }
1075: }
1076: i = malloc(sizeof(Glab));
1077: i->n = n;
1078: i->par = inpar;
1079: i->crit = incrit;
1080: i->pc = pc;
1081: i->next = labels;
1082: labels = i;
1083: }
1084:
1085: void
1086: setgoto(Node *n, Inst *i)
1087: {
1088: Glab *g;
1089:
1090: g = malloc(sizeof(Glab));
1091: g->n = n;
1092: g->i = i;
1093: g->par = inpar;
1094: g->crit = incrit;
1095: g->next = gotos;
1096: gotos = g;
1097: }
1098:
1099: Glab*
1100: findlab(Node *n)
1101: {
1102: Glab *i;
1103:
1104: for(i = labels; i; i = i->next)
1105: if(i->n->sym == n->sym)
1106: return i;
1107:
1108: return 0;
1109: }
1110:
1111: void
1112: resolvegoto(void)
1113: {
1114: Glab *g, *l;
1115:
1116: for(g = gotos; g; g = g->next) {
1117: l = findlab(g->n);
1118: if(l == 0) {
1119: diag(g->n, "no label called %s", g->n->sym->name);
1120: continue;
1121: }
1122:
1123: if(g->par != l->par)
1124: diag(g->n, "raise/goto breaks join from par");
1125: if(g->crit != l->crit)
1126: diag(g->n, "raise/goto breaks critical section");
1127:
1128: label(g->i, l->pc);
1129: }
1130: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.