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