|
|
1.1 root 1: #ifndef lint
2: static char *sccsid ="@(#)reader.c 4.4 (Berkeley) 8/22/85";
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: order( p1, INBREG|INAREG );
621: goto again;
622:
623: case NAME:
624: /* all leaves end up here ... */
625: if( o == REG ) goto nomat;
626: order( p, INTAREG|INTBREG );
627: goto again;
628:
629: case INIT:
630: uerror( "illegal initialization" );
631: return;
632:
633: case UNARY FORTCALL:
634: p->in.right = NIL;
635: case FORTCALL:
636: o = p->in.op = UNARY FORTCALL;
637: if( genfcall( p, cookie ) ) goto nomat;
638: goto cleanup;
639:
640: case UNARY CALL:
641: p->in.right = NIL;
642: case CALL:
643: o = p->in.op = UNARY CALL;
644: if( gencall( p, cookie ) ) goto nomat;
645: goto cleanup;
646:
647: case UNARY STCALL:
648: p->in.right = NIL;
649: case STCALL:
650: o = p->in.op = UNARY STCALL;
651: if( genscall( p, cookie ) ) goto nomat;
652: goto cleanup;
653:
654: /* if arguments are passed in register, care must be taken that reclaim
655: /* not throw away the register which now has the result... */
656:
657: case UNARY MUL:
658: if( cook == FOREFF ){
659: /* do nothing */
660: order( p->in.left, FOREFF );
661: p->in.op = FREE;
662: return;
663: }
664: offstar( p->in.left );
665: goto again;
666:
667: case INCR: /* INCR and DECR */
668: if( setincr(p) ) goto again;
669:
670: /* x++ becomes (x += 1) -1; */
671:
672: if( cook & FOREFF ){ /* result not needed so inc or dec and be done with it */
673: /* x++ => x += 1 */
674: p->in.op = (p->in.op==INCR)?ASG PLUS:ASG MINUS;
675: goto again;
676: }
677:
678: p1 = tcopy(p);
679: reclaim( p->in.left, RNULL, 0 );
680: p->in.left = p1;
681: p1->in.op = (p->in.op==INCR)?ASG PLUS:ASG MINUS;
682: p->in.op = (p->in.op==INCR)?MINUS:PLUS;
683: goto again;
684:
685: case STASG:
686: if( setstr( p ) ) goto again;
687: goto nomat;
688:
689: case ASG PLUS: /* and other assignment ops */
690: if( setasop(p) ) goto again;
691:
692: /* there are assumed to be no side effects in LHS */
693:
694: p2 = tcopy(p);
695: p->in.op = ASSIGN;
696: reclaim( p->in.right, RNULL, 0 );
697: p->in.right = p2;
698: canon(p);
699: rallo( p, p->in.rall );
700:
701: # ifndef BUG4
702: if( odebug ) fwalk( p, eprint, 0 );
703: # endif
704:
705: order( p2->in.left, INTBREG|INTAREG );
706: order( p2, INTBREG|INTAREG );
707: goto again;
708:
709: case ASSIGN:
710: if( setasg( p ) ) goto again;
711: goto nomat;
712:
713:
714: case BITYPE:
715: if( setbin( p ) ) goto again;
716: /* try to replace binary ops by =ops */
717: switch(o){
718:
719: case PLUS:
720: case MINUS:
721: case MUL:
722: case DIV:
723: case MOD:
724: case AND:
725: case OR:
726: case ER:
727: case LS:
728: case RS:
729: p->in.op = ASG o;
730: goto again;
731: }
732: goto nomat;
733:
734: }
735:
736: cleanup:
737:
738: /* if it is not yet in the right state, put it there */
739:
740: if( cook & FOREFF ){
741: reclaim( p, RNULL, 0 );
742: return;
743: }
744:
745: if( p->in.op==FREE ) return;
746:
747: if( tshape( p, cook ) ) return;
748:
749: if( (m=match(p,cook) ) == MDONE ) return;
750:
751: /* we are in bad shape, try one last chance */
752: if( lastchance( p, cook ) ) goto again;
753:
754: goto nomat;
755: }
756:
757: int callflag;
758: int fregs;
759:
760: store( p ) register NODE *p; {
761:
762: /* find a subtree of p which should be stored */
763:
764: register o, ty;
765:
766: o = p->in.op;
767: ty = optype(o);
768:
769: if( ty == LTYPE ) return;
770:
771: switch( o ){
772:
773: case UNARY CALL:
774: case UNARY FORTCALL:
775: case UNARY STCALL:
776: ++callflag;
777: break;
778:
779: case UNARY MUL:
780: if( asgop(p->in.left->in.op) ) stoasg( p->in.left, UNARY MUL );
781: break;
782:
783: case CALL:
784: case FORTCALL:
785: case STCALL:
786: store( p->in.left );
787: stoarg( p->in.right, o );
788: ++callflag;
789: return;
790:
791: case COMOP:
792: markcall( p->in.right );
793: if( p->in.right->in.su > fregs ) SETSTO( p, INTEMP );
794: store( p->in.left );
795: return;
796:
797: case ANDAND:
798: case OROR:
799: case QUEST:
800: markcall( p->in.right );
801: if( p->in.right->in.su > fregs ) SETSTO( p, INTEMP );
802: case CBRANCH: /* to prevent complicated expressions on the LHS from being stored */
803: case NOT:
804: constore( p->in.left );
805: return;
806:
807: }
808:
809: if( ty == UTYPE ){
810: store( p->in.left );
811: return;
812: }
813:
814: if( asgop( p->in.right->in.op ) ) stoasg( p->in.right, o );
815:
816: if( p->in.su>fregs ){ /* must store */
817: mkadrs( p ); /* set up stotree and stocook to subtree
818: that must be stored */
819: }
820:
821: store( p->in.right );
822: store( p->in.left );
823: }
824:
825: constore( p ) register NODE *p; {
826:
827: /* store conditional expressions */
828: /* the point is, avoid storing expressions in conditional
829: conditional context, since the evaluation order is predetermined */
830:
831: switch( p->in.op ) {
832:
833: case ANDAND:
834: case OROR:
835: case QUEST:
836: markcall( p->in.right );
837: case NOT:
838: constore( p->in.left );
839: return;
840:
841: }
842:
843: store( p );
844: }
845:
846: markcall( p ) register NODE *p; { /* mark off calls below the current node */
847:
848: again:
849: switch( p->in.op ){
850:
851: case UNARY CALL:
852: case UNARY STCALL:
853: case UNARY FORTCALL:
854: case CALL:
855: case STCALL:
856: case FORTCALL:
857: ++callflag;
858: return;
859:
860: }
861:
862: switch( optype( p->in.op ) ){
863:
864: case BITYPE:
865: markcall( p->in.right );
866: case UTYPE:
867: p = p->in.left;
868: /* eliminate recursion (aren't I clever...) */
869: goto again;
870: case LTYPE:
871: return;
872: }
873:
874: }
875:
876: stoarg( p, calltype ) register NODE *p; {
877: /* arrange to store the args */
878:
879: if( p->in.op == CM ){
880: stoarg( p->in.left, calltype );
881: p = p->in.right ;
882: }
883: if( calltype == CALL ){
884: STOARG(p);
885: }
886: else if( calltype == STCALL ){
887: STOSTARG(p);
888: }
889: else {
890: STOFARG(p);
891: }
892: callflag = 0;
893: store(p);
894: # ifndef NESTCALLS
895: if( callflag ){ /* prevent two calls from being active at once */
896: SETSTO(p,INTEMP);
897: store(p); /* do again to preserve bottom up nature.... */
898: }
899: #endif
900: }
901:
902: int negrel[] = { NE, EQ, GT, GE, LT, LE, UGT, UGE, ULT, ULE } ; /* negatives of relationals */
903:
904: cbranch( p, true, false ) NODE *p; {
905: /* evaluate p for truth value, and branch to true or false
906: /* accordingly: label <0 means fall through */
907:
908: register o, lab, flab, tlab;
909:
910: lab = -1;
911:
912: switch( o=p->in.op ){
913:
914: case ULE:
915: case ULT:
916: case UGE:
917: case UGT:
918: case EQ:
919: case NE:
920: case LE:
921: case LT:
922: case GE:
923: case GT:
924: if( true < 0 ){
925: o = p->in.op = negrel[ o-EQ ];
926: true = false;
927: false = -1;
928: }
929: #ifndef NOOPT
930: if( p->in.right->in.op == ICON && p->in.right->tn.lval == 0 && p->in.right->in.name[0] == '\0' ){
931: switch( o ){
932:
933: case UGT:
934: case ULE:
935: o = p->in.op = (o==UGT)?NE:EQ;
936: case EQ:
937: case NE:
938: case LE:
939: case LT:
940: case GE:
941: case GT:
942: if( logop(p->in.left->in.op) ){
943: /* strange situation: e.g., (a!=0) == 0 */
944: /* must prevent reference to p->in.left->lable, so get 0/1 */
945: /* we could optimize, but why bother */
946: codgen( p->in.left, INAREG|INBREG );
947: }
948: codgen( p->in.left, FORCC );
949: cbgen( o, true, 'I' );
950: break;
951:
952: case UGE:
953: codgen(p->in.left, FORCC);
954: cbgen( 0, true, 'I' ); /* unconditional branch */
955: break;
956: case ULT:
957: codgen(p->in.left, FORCC);
958: }
959: }
960: else
961: #endif
962: {
963: p->bn.label = true;
964: codgen( p, FORCC );
965: }
966: if( false>=0 ) cbgen( 0, false, 'I' );
967: reclaim( p, RNULL, 0 );
968: return;
969:
970: case ANDAND:
971: lab = false<0 ? getlab() : false ;
972: cbranch( p->in.left, -1, lab );
973: cbranch( p->in.right, true, false );
974: if( false < 0 ) deflab( lab );
975: p->in.op = FREE;
976: return;
977:
978: case OROR:
979: lab = true<0 ? getlab() : true;
980: cbranch( p->in.left, lab, -1 );
981: cbranch( p->in.right, true, false );
982: if( true < 0 ) deflab( lab );
983: p->in.op = FREE;
984: return;
985:
986: case NOT:
987: cbranch( p->in.left, false, true );
988: p->in.op = FREE;
989: break;
990:
991: case COMOP:
992: codgen( p->in.left, FOREFF );
993: p->in.op = FREE;
994: cbranch( p->in.right, true, false );
995: return;
996:
997: case QUEST:
998: flab = false<0 ? getlab() : false;
999: tlab = true<0 ? getlab() : true;
1000: cbranch( p->in.left, -1, lab = getlab() );
1001: cbranch( p->in.right->in.left, tlab, flab );
1002: deflab( lab );
1003: cbranch( p->in.right->in.right, true, false );
1004: if( true < 0 ) deflab( tlab);
1005: if( false < 0 ) deflab( flab );
1006: p->in.right->in.op = FREE;
1007: p->in.op = FREE;
1008: return;
1009:
1010: case ICON:
1011: if( p->in.type != FLOAT && p->in.type != DOUBLE ){
1012:
1013: if( p->tn.lval || p->in.name[0] ){
1014: /* addresses of C objects are never 0 */
1015: if( true>=0 ) cbgen( 0, true, 'I' );
1016: }
1017: else if( false>=0 ) cbgen( 0, false, 'I' );
1018: p->in.op = FREE;
1019: return;
1020: }
1021: /* fall through to default with other strange constants */
1022:
1023: default:
1024: /* get condition codes */
1025: codgen( p, FORCC );
1026: if( true >= 0 ) cbgen( NE, true, 'I' );
1027: if( false >= 0 ) cbgen( true >= 0 ? 0 : EQ, false, 'I' );
1028: reclaim( p, RNULL, 0 );
1029: return;
1030:
1031: }
1032:
1033: }
1034:
1035: rcount(){ /* count recursions */
1036: if( ++nrecur > NRECUR ){
1037: cerror( "expression causes compiler loop: try simplifying" );
1038: }
1039:
1040: }
1041:
1042: # ifndef BUG4
1043: eprint( p, down, a, b ) NODE *p; int *a, *b; {
1044:
1045: *a = *b = down+1;
1046: while( down >= 2 ){
1047: printf( "\t" );
1048: down -= 2;
1049: }
1050: if( down-- ) printf( " " );
1051:
1052:
1053: printf( "%o) %s", p, opst[p->in.op] );
1054: switch( p->in.op ) { /* special cases */
1055:
1056: case REG:
1057: printf( " %s", rnames[p->tn.rval] );
1058: break;
1059:
1060: case ICON:
1061: case NAME:
1062: case OREG:
1063: printf( " " );
1064: adrput( p );
1065: break;
1066:
1067: case STCALL:
1068: case UNARY STCALL:
1069: case STARG:
1070: case STASG:
1071: printf( " size=%d", p->stn.stsize );
1072: printf( " align=%d", p->stn.stalign );
1073: break;
1074: }
1075:
1076: printf( ", " );
1077: tprint( p->in.type );
1078: printf( ", " );
1079: if( p->in.rall == NOPREF ) printf( "NOPREF" );
1080: else {
1081: if( p->in.rall & MUSTDO ) printf( "MUSTDO " );
1082: else printf( "PREF " );
1083: printf( "%s", rnames[p->in.rall&~MUSTDO]);
1084: }
1085: printf( ", SU= %d\n", p->in.su );
1086:
1087: }
1088: # endif
1089:
1090: # ifndef NOMAIN
1091: NODE *
1092: eread(){
1093:
1094: /* call eread recursively to get subtrees, if any */
1095:
1096: register NODE *p;
1097: register i, c;
1098: register char *pc;
1099: register j;
1100:
1101: i = rdin( 10 );
1102:
1103: p = talloc();
1104:
1105: p->in.op = i;
1106:
1107: i = optype(i);
1108:
1109: if( i == LTYPE ) p->tn.lval = rdin( 10 );
1110: if( i != BITYPE ) p->tn.rval = rdin( 10 );
1111:
1112: p->in.type = rdin(8 );
1113: p->in.rall = NOPREF; /* register allocation information */
1114:
1115: if( p->in.op == STASG || p->in.op == STARG || p->in.op == STCALL || p->in.op == UNARY STCALL ){
1116: p->stn.stsize = (rdin( 10 ) + (SZCHAR-1) )/SZCHAR;
1117: p->stn.stalign = rdin(10) / SZCHAR;
1118: if( getchar() != '\n' ) cerror( "illegal \n" );
1119: }
1120: else { /* usual case */
1121: if( p->in.op == REG ) rbusy( p->tn.rval, p->in.type ); /* non usually, but sometimes justified */
1122: #ifndef FLEXNAMES
1123: for( pc=p->in.name,j=0; ( c = getchar() ) != '\n'; ++j ){
1124: if( j < NCHNAM ) *pc++ = c;
1125: }
1126: if( j < NCHNAM ) *pc = '\0';
1127: #else
1128: { char buf[BUFSIZ];
1129: for( pc=buf,j=0; ( c = getchar() ) != '\n'; ++j ){
1130: if( j < BUFSIZ ) *pc++ = c;
1131: }
1132: if( j < BUFSIZ ) *pc = '\0';
1133: p->in.name = tstr(buf);
1134: }
1135: #endif
1136: }
1137:
1138: /* now, recursively read descendents, if any */
1139:
1140: if( i != LTYPE ) p->in.left = eread();
1141: if( i == BITYPE ) p->in.right = eread();
1142:
1143: return( p );
1144:
1145: }
1146:
1147: CONSZ
1148: rdin( base ){
1149: register sign, c;
1150: CONSZ val;
1151:
1152: sign = 1;
1153: val = 0;
1154:
1155: while( (c=getchar()) > 0 ) {
1156: if( c == '-' ){
1157: if( val != 0 ) cerror( "illegal -");
1158: sign = -sign;
1159: continue;
1160: }
1161: if( c == '\t' ) break;
1162: if( c>='0' && c<='9' ) {
1163: val *= base;
1164: if( sign > 0 )
1165: val += c-'0';
1166: else
1167: val -= c-'0';
1168: continue;
1169: }
1170: cerror( "illegal character `%c' on intermediate file", c );
1171: break;
1172: }
1173:
1174: if( c <= 0 ) {
1175: cerror( "unexpected EOF");
1176: }
1177: return( val );
1178: }
1179: # endif
1180:
1181: #ifndef FIELDOPS
1182: /* do this if there is no special hardware support for fields */
1183:
1184: ffld( p, down, down1, down2 ) NODE *p; int *down1, *down2; {
1185: /* look for fields that are not in an lvalue context, and rewrite them... */
1186: register NODE *shp;
1187: register s, o, v, ty;
1188:
1189: *down1 = asgop( p->in.op );
1190: *down2 = 0;
1191:
1192: if( !down && p->in.op == FLD ){ /* rewrite the node */
1193:
1194: if( !rewfld(p) ) return;
1195:
1196: ty = (szty(p->in.type) == 2)? LONG: INT;
1197: v = p->tn.rval;
1198: s = UPKFSZ(v);
1199: # ifdef RTOLBYTES
1200: o = UPKFOFF(v); /* amount to shift */
1201: # else
1202: o = szty(p->in.type)*SZINT - s - UPKFOFF(v); /* amount to shift */
1203: #endif
1204:
1205: /* make & mask part */
1206:
1207: p->in.left->in.type = ty;
1208:
1209: p->in.op = AND;
1210: p->in.right = talloc();
1211: p->in.right->in.op = ICON;
1212: p->in.right->in.rall = NOPREF;
1213: p->in.right->in.type = ty;
1214: p->in.right->tn.lval = 1;
1215: p->in.right->tn.rval = 0;
1216: #ifndef FLEXNAMES
1217: p->in.right->in.name[0] = '\0';
1218: #else
1219: p->in.right->in.name = "";
1220: #endif
1221: p->in.right->tn.lval <<= s;
1222: p->in.right->tn.lval--;
1223:
1224: /* now, if a shift is needed, do it */
1225:
1226: if( o != 0 ){
1227: shp = talloc();
1228: shp->in.op = RS;
1229: shp->in.rall = NOPREF;
1230: shp->in.type = ty;
1231: shp->in.left = p->in.left;
1232: shp->in.right = talloc();
1233: shp->in.right->in.op = ICON;
1234: shp->in.right->in.rall = NOPREF;
1235: shp->in.right->in.type = ty;
1236: shp->in.right->tn.rval = 0;
1237: shp->in.right->tn.lval = o; /* amount to shift */
1238: #ifndef FLEXNAMES
1239: shp->in.right->in.name[0] = '\0';
1240: #else
1241: shp->in.right->in.name = "";
1242: #endif
1243: p->in.left = shp;
1244: /* whew! */
1245: }
1246: }
1247: }
1248: #endif
1249:
1250: oreg2( p ) register NODE *p; {
1251:
1252: /* look for situations where we can turn * into OREG */
1253:
1254: NODE *q;
1255: register i;
1256: register r;
1257: register char *cp;
1258: register NODE *ql, *qr;
1259: CONSZ temp;
1260:
1261: if( p->in.op == UNARY MUL ){
1262: q = p->in.left;
1263: if( q->in.op == REG ){
1264: temp = q->tn.lval;
1265: r = q->tn.rval;
1266: cp = q->in.name;
1267: goto ormake;
1268: }
1269:
1270: if( q->in.op != PLUS && q->in.op != MINUS ) return;
1271: ql = q->in.left;
1272: qr = q->in.right;
1273:
1274: #ifdef R2REGS
1275:
1276: /* look for doubly indexed expressions */
1277:
1278: if( q->in.op == PLUS) {
1279: if( (r=base(ql))>=0 && (i=offset(qr, tlen(p)))>=0) {
1280: makeor2(p, ql, r, i);
1281: return;
1282: } else if( (r=base(qr))>=0 && (i=offset(ql, tlen(p)))>=0) {
1283: makeor2(p, qr, r, i);
1284: return;
1285: }
1286: }
1287:
1288:
1289: #endif
1290:
1291: if( (q->in.op==PLUS || q->in.op==MINUS) && qr->in.op == ICON &&
1292: ql->in.op==REG && szty(qr->in.type)==1) {
1293: temp = qr->tn.lval;
1294: if( q->in.op == MINUS ) temp = -temp;
1295: r = ql->tn.rval;
1296: temp += ql->tn.lval;
1297: cp = qr->in.name;
1298: if( *cp && ( q->in.op == MINUS || *ql->in.name ) ) return;
1299: if( !*cp ) cp = ql->in.name;
1300:
1301: ormake:
1302: if( notoff( p->in.type, r, temp, cp ) ) return;
1303: p->in.op = OREG;
1304: p->tn.rval = r;
1305: p->tn.lval = temp;
1306: #ifndef FLEXNAMES
1307: for( i=0; i<NCHNAM; ++i )
1308: p->in.name[i] = *cp++;
1309: #else
1310: p->in.name = cp;
1311: #endif
1312: tfree(q);
1313: return;
1314: }
1315: }
1316:
1317: }
1318:
1319: canon(p) NODE *p; {
1320: /* put p in canonical form */
1321: int oreg2(), sucomp();
1322:
1323: #ifndef FIELDOPS
1324: int ffld();
1325: fwalk( p, ffld, 0 ); /* look for field operators */
1326: # endif
1327: walkf( p, oreg2 ); /* look for and create OREG nodes */
1328: #ifdef MYCANON
1329: MYCANON(p); /* your own canonicalization routine(s) */
1330: #endif
1331: walkf( p, sucomp ); /* do the Sethi-Ullman computation */
1332:
1333: }
1334:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.