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