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