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