|
|
1.1 root 1: # include "mfile2"
2:
3: /* some storage declarations */
4:
5: # ifndef ONEPASS
6: NODE node[TREESZ];
7: char filename[100] = ""; /* the name of the file */
8: int ftnno; /* number of current function */
9: int lineno;
10: # else
11: # define NOMAIN
12: #endif
13:
14: int nrecur;
15: int lflag;
16: extern int Wflag;
17: int edebug = 0;
18: int xdebug = 0;
19: int udebug = 0;
20:
21: OFFSZ tmpoff; /* offset for first temporary, in bits for current block */
22: OFFSZ maxoff; /* maximum temporary offset over all blocks in current ftn, in bits */
23: int maxtreg;
24:
25: NODE *stotree;
26: int stocook;
27:
28: OFFSZ baseoff = 0;
29: OFFSZ maxtemp = 0;
30:
31: p2init( argc, argv ) char *argv[];{
32: /* set the values of the pass 2 arguments */
33:
34: register int c;
35: register char *cp;
36: register files;
37:
38: allo0(); /* free all regs */
39: files = 0;
40:
41: for( c=1; c<argc; ++c ){
42: if( *(cp=argv[c]) == '-' ){
43: while( *++cp ){
44: switch( *cp ){
45:
46: case 'X': /* pass1 flags */
47: while( *++cp ) { /* VOID */ }
48: --cp;
49: break;
50:
51: case 'l': /* linenos */
52: ++lflag;
53: break;
54:
55: case 'W': /*Shut up warning: etc. */
56: ++Wflag;
57: break;
58:
59: case 'e': /* expressions */
60: ++edebug;
61: break;
62:
63: case 'o': /* orders */
64: ++odebug;
65: break;
66:
67: case 'r': /* register allocation */
68: ++rdebug;
69: break;
70:
71: case 'a': /* rallo */
72: ++radebug;
73: break;
74:
75: case 't': /* ttype calls */
76: ++tdebug;
77: break;
78:
79: case 's': /* shapes */
80: ++sdebug;
81: break;
82:
83: case 'u': /* Sethi-Ullman testing (machine dependent) */
84: ++udebug;
85: break;
86:
87: case 'x': /* general machine-dependent debugging flag */
88: ++xdebug;
89: break;
90:
91: default:
92: cerror( "bad option: %c", *cp );
93: }
94: }
95: }
96: else files = 1; /* assumed to be a filename */
97: }
98:
99: mkdope();
100: setrew();
101: return( files );
102:
103: }
104:
105: # ifndef NOMAIN
106:
107: mainp2( argc, argv ) char *argv[]; {
108: register files;
109: register temp;
110: register c;
111: register char *cp;
112: register NODE *p;
113:
114: files = p2init( argc, argv );
115: tinit();
116:
117: reread:
118:
119: if( files ){
120: while( files < argc && argv[files][0] == '-' ) {
121: ++files;
122: }
123: if( files > argc ) return( nerrors );
124: freopen( argv[files], "r", stdin );
125: }
126: while( (c=getchar()) > 0 ) switch( c ){
127: case ')':
128: /* copy line unchanged */
129: while( (c=getchar()) > 0 ){
130: PUTCHAR(c);
131: if( c == '\n' ) break;
132: }
133: continue;
134:
135: case '[':
136: /* beginning of a block */
137: temp = rdin(10); /* ftnno */
138: tmpoff = baseoff = rdin(10); /* autooff for block gives max offset of autos in block */
139: maxtreg = rdin(10);
140: if( getchar() != '\n' ) cerror( "intermediate file format error");
141:
142: if( temp != ftnno ){ /* beginning of function */
143: maxoff = baseoff;
144: ftnno = temp;
145: maxtemp = 0;
146: }
147: else {
148: if( baseoff > maxoff ) maxoff = baseoff;
149: /* maxoff at end of ftn is max of autos and temps
150: over all blocks in the function */
151: }
152: setregs();
153: continue;
154:
155: case ']': /* end of block */
156: SETOFF( maxoff, ALSTACK );
157: eobl2();
158: while( (c=getchar()) != '\n' ){
159: if( c <= 0 ) cerror( "intermediate file format eof" );
160: }
161: continue;
162:
163: case '.':
164: /* compile code for an expression */
165: lineno = rdin( 10 );
166: for( cp=filename; (*cp=getchar()) != '\n'; ++cp ) ; /* VOID, reads filename */
167: *cp = '\0';
168: if( lflag ) lineid( lineno, filename );
169:
170: tmpoff = baseoff; /* expression at top level reuses temps */
171: p = eread();
172:
173: if( edebug ) fwalk( p, eprint, 0 );
174:
175: # ifdef MYREADER
176: MYREADER(p); /* do your own laundering of the input */
177: # endif
178:
179: nrecur = 0;
180: delay( p ); /* expression statement throws out results */
181: reclaim( p, RNULL, 0 );
182:
183: allchk();
184: tcheck();
185: continue;
186:
187: default:
188: cerror( "intermediate file format error" );
189:
190: }
191:
192: /* EOF */
193: if( files ) goto reread;
194: return(nerrors);
195:
196: }
197:
198: # endif
199:
200: # ifdef ONEPASS
201:
202: p2compile( p ) NODE *p; {
203:
204: if( lflag ) lineid( lineno, filename );
205: tmpoff = baseoff; /* expression at top level reuses temps */
206: /* generate code for the tree p */
207: if( edebug ) fwalk( p, eprint, 0 );
208:
209: # ifdef MYREADER
210: MYREADER(p); /* do your own laundering of the input */
211: # endif
212: nrecur = 0;
213: delay( p ); /* do the code generation */
214: reclaim( p, RNULL, 0 );
215: allchk();
216: /* can't do tcheck here; some stuff (e.g., attributes) may be around from first pass */
217: /* first pass will do it... */
218: }
219:
220: p2bbeg( aoff, myreg ) {
221: static int myftn = -1;
222: tmpoff = baseoff = aoff;
223: maxtreg = myreg;
224: if( myftn != ftnno ){ /* beginning of function */
225: maxoff = baseoff;
226: myftn = ftnno;
227: maxtemp = 0;
228: }
229: else {
230: if( baseoff > maxoff ) maxoff = baseoff;
231: /* maxoff at end of ftn is max of autos and temps over all blocks */
232: }
233: setregs();
234: }
235:
236: p2bend(){
237: SETOFF( maxoff, ALSTACK );
238: eobl2();
239: }
240:
241: # endif
242:
243: NODE *deltrees[DELAYS];
244: int deli;
245:
246: delay( p ) register NODE *p; {
247: /* look in all legal places for COMOP's and ++ and -- ops to delay */
248: /* note; don't delay ++ and -- within calls or things like
249: /* getchar (in their macro forms) will start behaving strangely */
250: register i;
251:
252: /* look for visible COMOPS, and rewrite repeatedly */
253:
254: while( delay1( p ) ) { /* VOID */ }
255:
256: /* look for visible, delayable ++ and -- */
257:
258: deli = 0;
259: delay2( p );
260: codgen( p, FOREFF ); /* do what is left */
261: for( i = 0; i<deli; ++i ) codgen( deltrees[i], FOREFF ); /* do the rest */
262: }
263:
264: delay1( p ) register NODE *p; { /* look for COMOPS */
265: register o, ty;
266:
267: o = p->op;
268: ty = optype( o );
269: if( ty == LTYPE ) return( 0 );
270: else if( ty == UTYPE ) return( delay1( p->left ) );
271:
272: switch( o ){
273:
274: case QUEST:
275: case ANDAND:
276: case OROR:
277: /* don't look on RHS */
278: return( delay1(p->left ) );
279:
280: case COMOP: /* the meat of the routine */
281: delay( p->left ); /* completely evaluate the LHS */
282: /* rewrite the COMOP */
283: { register NODE *q;
284: q = p->right;
285: ncopy( p, p->right );
286: q->op = FREE;
287: }
288: return( 1 );
289: }
290:
291: return( delay1(p->left) || delay1(p->right ) );
292: }
293:
294: delay2( p ) register NODE *p; {
295:
296: /* look for delayable ++ and -- operators */
297:
298: register o, ty;
299: o = p->op;
300: ty = optype( o );
301:
302: switch( o ){
303:
304: case NOT:
305: case QUEST:
306: case ANDAND:
307: case OROR:
308: case CALL:
309: case UNARY CALL:
310: case STCALL:
311: case UNARY STCALL:
312: case FORTCALL:
313: case UNARY FORTCALL:
314: case COMOP:
315: case CBRANCH:
316: /* for the moment, don7t delay past a conditional context, or
317: /* inside of a call */
318: return;
319:
320: case UNARY MUL:
321: /* if *p++, do not rewrite */
322: if( autoincr( p ) ) return;
323: break;
324:
325: case INCR:
326: case DECR:
327: if( deltest( p ) ){
328: if( deli < DELAYS ){
329: register NODE *q;
330: deltrees[deli++] = tcopy(p);
331: q = p->left;
332: p->right->op = FREE; /* zap constant */
333: ncopy( p, q );
334: q->op = FREE;
335: return;
336: }
337: }
338:
339: }
340:
341: if( ty == BITYPE ) delay2( p->right );
342: if( ty != LTYPE ) delay2( p->left );
343: }
344:
345: codgen( p, cookie ) NODE *p; {
346:
347: /* generate the code for p;
348: order may call codgen recursively */
349: /* cookie is used to describe the context */
350:
351: for(;;){
352: canon(p); /* creats OREG from * if possible and does sucomp */
353: stotree = NIL;
354: if( edebug ){
355: printf( "store called on:\n" );
356: fwalk( p, eprint, 0 );
357: }
358: store(p);
359: if( stotree==NIL ) break;
360:
361: /* because it's minimal, can do w.o. stores */
362:
363: order( stotree, stocook );
364: }
365:
366: order( p, cookie );
367:
368: }
369:
370: char *cnames[] = {
371: "SANY",
372: "SAREG",
373: "STAREG",
374: "SBREG",
375: "STBREG",
376: "SCC",
377: "SNAME",
378: "SCON",
379: "SFLD",
380: "SOREG",
381: "STARNM",
382: "STARREG",
383: "INTEMP",
384: "FORARG",
385: "SWADD",
386: 0,
387: };
388:
389: prcook( cookie ){
390:
391: /* print a nice-looking description of cookie */
392:
393: int i, flag;
394:
395: if( cookie & SPECIAL ){
396: if( cookie == SZERO ) printf( "SZERO" );
397: else if( cookie == SONE ) printf( "SONE" );
398: else if( cookie == SMONE ) printf( "SMONE" );
399: else printf( "SPECIAL+%d", cookie & ~SPECIAL );
400: return;
401: }
402:
403: flag = 0;
404: for( i=0; cnames[i]; ++i ){
405: if( cookie & (1<<i) ){
406: if( flag ) printf( "|" );
407: ++flag;
408: printf( cnames[i] );
409: }
410: }
411:
412: }
413:
414: int odebug = 0;
415:
416: order(p,cook) NODE *p; {
417:
418: register o, ty, m;
419: int m1;
420: int cookie;
421: NODE *p1, *p2;
422:
423: /* by this time, p should be able to be generated without stores;
424: the only question is how */
425:
426: again:
427:
428: cookie = cook;
429: rcount();
430: canon(p);
431: rallo( p, p->rall );
432:
433: if( odebug ){
434: printf( "order( %o, ", p );
435: prcook( cookie );
436: printf( " )\n" );
437: fwalk( p, eprint, 0 );
438: }
439:
440: o = p->op;
441: ty = optype(o);
442:
443: /* first of all, for most ops, see if it is in the table */
444:
445: /* look for ops */
446:
447: switch( m = p->op ){
448:
449: default:
450: /* look for op in table */
451: for(;;){
452: if( (m = match( p, cookie ) ) == MDONE ) goto cleanup;
453: else if( m == MNOPE ){
454: if( !(cookie = nextcook( p, cookie ) ) ) goto nomat;
455: continue;
456: }
457: else break;
458: }
459: break;
460:
461: case COMOP:
462: case FORCE:
463: case CBRANCH:
464: case QUEST:
465: case ANDAND:
466: case OROR:
467: case NOT:
468: case UNARY CALL:
469: case CALL:
470: case UNARY STCALL:
471: case STCALL:
472: case UNARY FORTCALL:
473: case FORTCALL:
474: /* don't even go near the table... */
475: ;
476:
477: }
478: /* get here to do rewriting if no match or
479: fall through from above for hard ops */
480:
481: p1 = p->left;
482: if( ty == BITYPE ) p2 = p->right;
483: else p2 = NIL;
484:
485: if( odebug ){
486: printf( "order( %o, ", p );
487: prcook( cook );
488: printf( " ), cookie " );
489: prcook( cookie );
490: printf( ", rewrite %s\n", opst[m] );
491: }
492: switch( m ){
493: default:
494: nomat:
495: cerror( "no table entry for op %s", opst[p->op] );
496:
497: case COMOP:
498: codgen( p1, FOREFF );
499: p2->rall = p->rall;
500: codgen( p2, cookie );
501: ncopy( p, p2 );
502: p2->op = FREE;
503: goto cleanup;
504:
505: case FORCE:
506: /* recurse, letting the work be done by rallo */
507: p = p->left;
508: cook = INTAREG|INTBREG;
509: goto again;
510:
511: case CBRANCH:
512: o = p2->lval;
513: cbranch( p1, -1, o );
514: p2->op = FREE;
515: p->op = FREE;
516: return;
517:
518: case QUEST:
519: cbranch( p1, -1, m=getlab() );
520: p2->left->rall = p->rall;
521: codgen( p2->left, INTAREG|INTBREG );
522: /* force right to compute result into same reg used by left */
523: p2->right->rall = p2->left->rval|MUSTDO;
524: reclaim( p2->left, RNULL, 0 );
525: cbgen( 0, m1 = getlab(), 'I' );
526: deflab( m );
527: codgen( p2->right, INTAREG|INTBREG );
528: deflab( m1 );
529: p->op = REG; /* set up node describing result */
530: p->lval = 0;
531: p->rval = p2->right->rval;
532: p->type = p2->right->type;
533: tfree( p2->right );
534: p2->op = FREE;
535: goto cleanup;
536:
537: case ANDAND:
538: case OROR:
539: case NOT: /* logical operators */
540: /* if here, must be a logical operator for 0-1 value */
541: cbranch( p, -1, m=getlab() );
542: p->op = CCODES;
543: p->label = m;
544: order( p, INTAREG );
545: goto cleanup;
546:
547: case FLD: /* fields of funny type */
548: if ( p1->op == UNARY MUL ){
549: offstar( p1->left );
550: goto again;
551: }
552:
553: case UNARY MINUS:
554: order( p1, INBREG|INAREG );
555: goto again;
556:
557: case NAME:
558: /* all leaves end up here ... */
559: if( o == REG ) goto nomat;
560: order( p, INTAREG|INTBREG );
561: goto again;
562:
563: case INIT:
564: uerror( "illegal initialization" );
565: return;
566:
567: case UNARY FORTCALL:
568: p->right = NIL;
569: case FORTCALL:
570: o = p->op = UNARY FORTCALL;
571: if( genfcall( p, cookie ) ) goto nomat;
572: goto cleanup;
573:
574: case UNARY CALL:
575: p->right = NIL;
576: case CALL:
577: o = p->op = UNARY CALL;
578: if( gencall( p, cookie ) ) goto nomat;
579: goto cleanup;
580:
581: case UNARY STCALL:
582: p->right = NIL;
583: case STCALL:
584: o = p->op = UNARY STCALL;
585: if( genscall( p, cookie ) ) goto nomat;
586: goto cleanup;
587:
588: /* if arguments are passed in register, care must be taken that reclaim
589: /* not throw away the register which now has the result... */
590:
591: case UNARY MUL:
592: if( cook == FOREFF ){
593: /* do nothing */
594: order( p->left, FOREFF );
595: p->op = FREE;
596: return;
597: }
598: offstar( p->left );
599: canon(p);
600: if( canaddr(p) && cook != INTEMP ) goto cleanup;
601: goto again;
602:
603: case INCR: /* INCR and DECR */
604: if( setincr(p) ) goto again;
605:
606: /* x++ becomes (x += 1) -1; */
607:
608: if( cook & FOREFF ){ /* result not needed so inc or dec and be done with it */
609: /* x++ => x += 1 */
610: p->op = (p->op==INCR)?ASG PLUS:ASG MINUS;
611: goto again;
612: }
613:
614: p1 = tcopy(p);
615: reclaim( p->left, RNULL, 0 );
616: p->left = p1;
617: p1->op = (p->op==INCR)?ASG PLUS:ASG MINUS;
618: p->op = (p->op==INCR)?MINUS:PLUS;
619: goto again;
620:
621: case STASG:
622: if( setstr( p ) ) goto again;
623: goto nomat;
624:
625: case ASG PLUS: /* and other assignment ops */
626: if( setasop(p) ) goto again;
627:
628: /* there are assumed to be no side effects in LHS */
629:
630: p2 = tcopy(p);
631: p->op = ASSIGN;
632: reclaim( p->right, RNULL, 0 );
633: p->right = p2;
634: canon(p);
635: rallo( p, p->rall );
636:
637: if( odebug ) fwalk( p, eprint, 0 );
638:
639: order( p2->left, INTBREG|INTAREG );
640: order( p2, INTBREG|INTAREG );
641: goto again;
642:
643: case ASSIGN:
644: if( setasg( p ) ) goto again;
645: goto nomat;
646:
647:
648: case BITYPE:
649: if( setbin( p ) ) goto again;
650: /* try to replace binary ops by =ops */
651: switch(o){
652:
653: case PLUS:
654: case MINUS:
655: case MUL:
656: case DIV:
657: case MOD:
658: case AND:
659: case OR:
660: case ER:
661: case LS:
662: case RS:
663: p->op = ASG o;
664: goto again;
665: }
666: goto nomat;
667:
668: }
669:
670: cleanup:
671:
672: /* if it is not yet in the right state, put it there */
673:
674: if( cook & FOREFF ){
675: reclaim( p, RNULL, 0 );
676: return;
677: }
678:
679: if( p->op==FREE ) return;
680:
681: if( tshape( p, cook ) ) return;
682:
683: if( (m=match(p,cook) ) == MDONE ) return;
684:
685: /* we are in bad shape, try one last chance */
686: if( lastchance( p, cook ) ) goto again;
687:
688: goto nomat;
689: }
690:
691: int callflag;
692: int fregs;
693:
694: store( p ) register NODE *p; {
695:
696: /* find a subtree of p which should be stored */
697:
698: register o, ty;
699:
700: o = p->op;
701: ty = optype(o);
702:
703: if( ty == LTYPE ) return;
704:
705: switch( o ){
706:
707: case UNARY CALL:
708: case UNARY FORTCALL:
709: case UNARY STCALL:
710: ++callflag;
711: break;
712:
713: case UNARY MUL:
714: if( asgop(p->left->op) ) stoasg( p->left, UNARY MUL );
715: break;
716:
717: case CALL:
718: case FORTCALL:
719: case STCALL:
720: store( p->left );
721: stoarg( p->right, o );
722: ++callflag;
723: return;
724:
725: case COMOP:
726: markcall( p->right );
727: if( p->right->su > fregs ) SETSTO( p, INTEMP );
728: store( p->left );
729: return;
730:
731: case ANDAND:
732: case OROR:
733: case QUEST:
734: markcall( p->right );
735: if( p->right->su > fregs ) SETSTO( p, INTEMP );
736: case CBRANCH: /* to prevent complicated expressions on the LHS from being stored */
737: case NOT:
738: constore( p->left );
739: return;
740:
741: }
742:
743: if( ty == UTYPE ){
744: store( p->left );
745: return;
746: }
747:
748: if( asgop( p->right->op ) ) stoasg( p->right, o );
749:
750: if( p->su>fregs ){ /* must store */
751: mkadrs( p ); /* set up stotree and stocook to subtree
752: that must be stored */
753: }
754:
755: store( p->right );
756: store( p->left );
757: }
758:
759: constore( p ) register NODE *p; {
760:
761: /* store conditional expressions */
762: /* the point is, avoid storing expressions in conditional
763: conditional context, since the evaluation order is predetermined */
764:
765: switch( p->op ) {
766:
767: case ANDAND:
768: case OROR:
769: case QUEST:
770: markcall( p->right );
771: case NOT:
772: constore( p->left );
773: return;
774:
775: }
776:
777: store( p );
778: }
779:
780: markcall( p ) register NODE *p; { /* mark off calls below the current node */
781:
782: again:
783: switch( p->op ){
784:
785: case UNARY CALL:
786: case UNARY STCALL:
787: case UNARY FORTCALL:
788: case CALL:
789: case STCALL:
790: case FORTCALL:
791: ++callflag;
792: return;
793:
794: }
795:
796: switch( optype( p->op ) ){
797:
798: case BITYPE:
799: markcall( p->right );
800: case UTYPE:
801: p = p->left;
802: /* eliminate recursion (aren't I clever...) */
803: goto again;
804: case LTYPE:
805: return;
806: }
807:
808: }
809:
810: stoarg( p, calltype ) register NODE *p; {
811: /* arrange to store the args */
812:
813: if( p->op == CM ){
814: stoarg( p->left, calltype );
815: p = p->right ;
816: }
817: if( calltype == CALL ){
818: STOARG(p);
819: }
820: else if( calltype == STCALL ){
821: STOSTARG(p);
822: }
823: else {
824: STOFARG(p);
825: }
826: callflag = 0;
827: store(p);
828: # ifndef NESTCALLS
829: if( callflag ){ /* prevent two calls from being active at once */
830: SETSTO(p,INTEMP);
831: store(p); /* do again to preserve bottom up nature.... */
832: }
833: #endif
834: }
835:
836: int negrel[] = { NE, EQ, GT, GE, LT, LE, UGT, UGE, ULT, ULE } ; /* negatives of relationals */
837:
838: cbranch( p, true, false ) NODE *p; {
839: /* evaluate p for truth value, and branch to true or false
840: /* accordingly: label <0 means fall through */
841:
842: register o, lab, flab, tlab;
843:
844: lab = -1;
845:
846: switch( o=p->op ){
847:
848: case ULE:
849: case ULT:
850: case UGE:
851: case UGT:
852: case EQ:
853: case NE:
854: case LE:
855: case LT:
856: case GE:
857: case GT:
858: if( true < 0 ){
859: o = p->op = negrel[ o-EQ ];
860: true = false;
861: false = -1;
862: }
863: #ifndef NOOPT
864: if( p->right->op == ICON && p->right->lval == 0 && p->right->name[0] == '\0' ){
865: switch( o ){
866:
867: case UGT:
868: case ULE:
869: o = p->op = (o==UGT)?NE:EQ;
870: case EQ:
871: case NE:
872: case LE:
873: case LT:
874: case GE:
875: case GT:
876: if( logop(p->left->op) ){
877: /* strange situation: e.g., (a!=0) == 0 */
878: /* must prevent reference to p->left->lable, so get 0/1 */
879: /* we could optimize, but why bother */
880: codgen( p->left, INAREG|INBREG );
881: }
882: codgen( p->left, FORCC );
883: cbgen( o, true, 'I' );
884: break;
885:
886: case UGE:
887: cbgen( 0, true, 'I' ); /* unconditional branch */
888: case ULT:
889: ; /* do nothing for LT */
890: }
891: }
892: else
893: #endif
894: {
895: p->label = true;
896: codgen( p, FORCC );
897: }
898: if( false>=0 ) cbgen( 0, false, 'I' );
899: reclaim( p, RNULL, 0 );
900: return;
901:
902: case ANDAND:
903: lab = false<0 ? getlab() : false ;
904: cbranch( p->left, -1, lab );
905: cbranch( p->right, true, false );
906: if( false < 0 ) deflab( lab );
907: p->op = FREE;
908: return;
909:
910: case OROR:
911: lab = true<0 ? getlab() : true;
912: cbranch( p->left, lab, -1 );
913: cbranch( p->right, true, false );
914: if( true < 0 ) deflab( lab );
915: p->op = FREE;
916: return;
917:
918: case NOT:
919: cbranch( p->left, false, true );
920: p->op = FREE;
921: break;
922:
923: case COMOP:
924: codgen( p->left, FOREFF );
925: p->op = FREE;
926: cbranch( p->right, true, false );
927: return;
928:
929: case QUEST:
930: flab = false<0 ? getlab() : false;
931: tlab = true<0 ? getlab() : true;
932: cbranch( p->left, -1, lab = getlab() );
933: cbranch( p->right->left, tlab, flab );
934: deflab( lab );
935: cbranch( p->right->right, true, false );
936: if( true < 0 ) deflab( tlab);
937: if( false < 0 ) deflab( flab );
938: p->right->op = FREE;
939: p->op = FREE;
940: return;
941:
942: case ICON:
943: if( p->type != FLOAT && p->type != DOUBLE ){
944:
945: if( p->lval || p->name[0] ){
946: /* addresses of C objects are never 0 */
947: if( true>=0 ) cbgen( 0, true, 'I' );
948: }
949: else if( false>=0 ) cbgen( 0, false, 'I' );
950: p->op = FREE;
951: return;
952: }
953: /* fall through to default with other strange constants */
954:
955: default:
956: /* get condition codes */
957: codgen( p, FORCC );
958: if( true >= 0 ) cbgen( NE, true, 'I' );
959: if( false >= 0 ) cbgen( true >= 0 ? 0 : EQ, false, 'I' );
960: reclaim( p, RNULL, 0 );
961: return;
962:
963: }
964:
965: }
966:
967: rcount(){ /* count recursions */
968: if( ++nrecur > NRECUR ){
969: cerror( "expression causes compiler loop: try simplifying" );
970: }
971:
972: }
973:
974: eprint( p, down, a, b ) NODE *p; int *a, *b; {
975:
976: *a = *b = down+1;
977: while( down >= 2 ){
978: printf( "\t" );
979: down -= 2;
980: }
981: if( down-- ) printf( " " );
982:
983:
984: printf( "%o) %s", p, opst[p->op] );
985: switch( p->op ) { /* special cases */
986:
987: case REG:
988: printf( " %s", rnames[p->rval] );
989: break;
990:
991: case ICON:
992: case NAME:
993: case OREG:
994: printf( " " );
995: adrput( p );
996: break;
997:
998: case STCALL:
999: case UNARY STCALL:
1000: case STARG:
1001: case STASG:
1002: printf( " size=%d", p->stsize );
1003: printf( " align=%d", p->stalign );
1004: break;
1005: }
1006:
1007: printf( ", " );
1008: tprint( p->type );
1009: printf( ", " );
1010: if( p->rall == NOPREF ) printf( "NOPREF" );
1011: else {
1012: if( p->rall & MUSTDO ) printf( "MUSTDO " );
1013: else printf( "PREF " );
1014: printf( "%s", rnames[p->rall&~MUSTDO]);
1015: }
1016: printf( ", SU= %d\n", p->su );
1017:
1018: }
1019:
1020: # ifndef NOMAIN
1021: NODE *
1022: eread(){
1023:
1024: /* call eread recursively to get subtrees, if any */
1025:
1026: register NODE *p;
1027: register i, c;
1028: register char *pc;
1029: register j;
1030:
1031: i = rdin( 10 );
1032:
1033: p = talloc();
1034:
1035: p->op = i;
1036:
1037: i = optype(i);
1038:
1039: if( i == LTYPE ) p->lval = rdin( 10 );
1040: if( i != BITYPE ) p->rval = rdin( 10 );
1041:
1042: p->type = rdin(8 );
1043: p->rall = NOPREF; /* register allocation information */
1044:
1045: if( p->op == STASG || p->op == STARG || p->op == STCALL || p->op == UNARY STCALL ){
1046: p->stsize = (rdin( 10 ) + (SZCHAR-1) )/SZCHAR;
1047: p->stalign = rdin(10) / SZCHAR;
1048: if( getchar() != '\n' ) cerror( "illegal \n" );
1049: }
1050: else { /* usual case */
1051: if( p->op == REG ) rbusy( p->rval, p->type ); /* non usually, but sometimes justified */
1052: for( pc=p->name,j=0; ( c = getchar() ) != '\n'; ++j ){
1053: if( j < NCHNAM ) *pc++ = c;
1054: }
1055: if( j < NCHNAM ) *pc = '\0';
1056: }
1057:
1058: /* now, recursively read descendents, if any */
1059:
1060: if( i != LTYPE ) p->left = eread();
1061: if( i == BITYPE ) p->right = eread();
1062:
1063: return( p );
1064:
1065: }
1066:
1067: CONSZ
1068: rdin( base ){
1069: register sign, c;
1070: CONSZ val;
1071:
1072: sign = 1;
1073: val = 0;
1074:
1075: while( (c=getchar()) > 0 ) {
1076: if( c == '-' ){
1077: if( val != 0 ) cerror( "illegal -");
1078: sign = -sign;
1079: continue;
1080: }
1081: if( c == '\t' ) break;
1082: if( c>='0' && c<='9' ) {
1083: val *= base;
1084: if( sign > 0 )
1085: val += c-'0';
1086: else
1087: val -= c-'0';
1088: continue;
1089: }
1090: cerror( "illegal character `%c' on intermediate file", c );
1091: break;
1092: }
1093:
1094: if( c <= 0 ) {
1095: cerror( "unexpected EOF");
1096: }
1097: return( val );
1098: }
1099: # endif
1100:
1101: #ifndef FIELDOPS
1102: /* do this if there is no special hardware support for fields */
1103:
1104: ffld( p, down, down1, down2 ) NODE *p; int *down1, *down2; {
1105: /* look for fields that are not in an lvalue context, and rewrite them... */
1106: register NODE *shp;
1107: register s, o, v, ty;
1108:
1109: *down1 = asgop( p->op );
1110: *down2 = 0;
1111:
1112: if( !down && p->op == FLD ){ /* rewrite the node */
1113:
1114: if( !rewfld(p) ) return;
1115:
1116: ty = (szty(p->type) == 2)? LONG: INT;
1117: v = p->rval;
1118: s = UPKFSZ(v);
1119: # ifdef RTOLBYTES
1120: o = UPKFOFF(v); /* amount to shift */
1121: # else
1122: o = szty(p->type)*SZINT - s - UPKFOFF(v); /* amount to shift */
1123: #endif
1124:
1125: /* make & mask part */
1126:
1127: p->left->type = ty;
1128:
1129: p->op = AND;
1130: p->right = talloc();
1131: p->right->op = ICON;
1132: p->right->rall = NOPREF;
1133: p->right->type = ty;
1134: p->right->lval = 1;
1135: p->right->rval = 0;
1136: p->right->name[0] = '\0';
1137: p->right->lval <<= s;
1138: p->right->lval--;
1139:
1140: /* now, if a shift is needed, do it */
1141:
1142: if( o != 0 ){
1143: shp = talloc();
1144: shp->op = RS;
1145: shp->rall = NOPREF;
1146: shp->type = ty;
1147: shp->left = p->left;
1148: shp->right = talloc();
1149: shp->right->op = ICON;
1150: shp->right->rall = NOPREF;
1151: shp->right->type = ty;
1152: shp->right->rval = 0;
1153: shp->right->lval = o; /* amount to shift */
1154: shp->right->name[0] = '\0';
1155: p->left = shp;
1156: /* whew! */
1157: }
1158: }
1159: }
1160: #endif
1161:
1162: oreg2( p ) register NODE *p; {
1163:
1164: /* look for situations where we can turn * into OREG */
1165:
1166: NODE *q;
1167: register i;
1168: register r;
1169: register char *cp;
1170: register NODE *ql, *qr;
1171: CONSZ temp;
1172:
1173: if( p->op == UNARY MUL ){
1174: q = p->left;
1175: if( q->op == REG ){
1176: temp = q->lval;
1177: r = q->rval;
1178: cp = q->name;
1179: goto ormake;
1180: }
1181:
1182: if( q->op != PLUS && q->op != MINUS ) return;
1183: ql = q->left;
1184: qr = q->right;
1185:
1186: #ifdef R2REGS
1187:
1188: /* look for doubly indexed expressions */
1189:
1190: if( q->op == PLUS) {
1191: if( (r=base(ql))>=0 && (i=offset(qr, tlen(p)))>=0) {
1192: makeor2(p, ql, r, i);
1193: return;
1194: } else if( (r=base(qr))>=0 && (i=offset(ql, tlen(p)))>=0) {
1195: makeor2(p, qr, r, i);
1196: return;
1197: }
1198: }
1199:
1200:
1201: #endif
1202:
1203: if( (q->op==PLUS || q->op==MINUS) && qr->op == ICON &&
1204: ql->op==REG && szty(qr->type)==1) {
1205: temp = qr->lval;
1206: if( q->op == MINUS ) temp = -temp;
1207: r = ql->rval;
1208: temp += ql->lval;
1209: cp = qr->name;
1210: if( *cp && ( q->op == MINUS || *ql->name ) ) return;
1211: if( !*cp ) cp = ql->name;
1212:
1213: ormake:
1214: if( notoff( p->type, r, temp, cp ) ) return;
1215: p->op = OREG;
1216: p->rval = r;
1217: p->lval = temp;
1218: for( i=0; i<NCHNAM; ++i )
1219: p->name[i] = *cp++;
1220: tfree(q);
1221: return;
1222: }
1223: }
1224:
1225: }
1226:
1227: canon(p) NODE *p; {
1228: /* put p in canonical form */
1229: int oreg2(), sucomp();
1230:
1231: #ifndef FIELDOPS
1232: int ffld();
1233: fwalk( p, ffld, 0 ); /* look for field operators */
1234: # endif
1235: walkf( p, oreg2 ); /* look for and create OREG nodes */
1236: #ifdef MYCANON
1237: MYCANON(p); /* your own canonicalization routine(s) */
1238: #endif
1239: walkf( p, sucomp ); /* do the Sethi-Ullman computation */
1240:
1241: }
1242:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.