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