|
|
1.1 root 1: # include "mfile2.h"
2:
3: /* some storage declarations */
4:
5: int lflag;
6: int e2debug;
7: int udebug;
8: int fast;
9:
10: /* maxtemp is the maximum size (in bits) needed for temps so far */
11: /* maxarg is ditto for outgoing arguments */
12: /* maxboff is ditto for automatic variables */
13:
14: int maxtemp;
15: extern int maxarg;
16: int maxboff;
17: NODE *condit();
18:
19: NODE *
20: force(p)
21: register NODE *p;
22: {
23: register NODE *q, *r;
24: if( !p ) cerror( "force" );
25: q = talloc();
26: *q = *p;
27: r = talloc();
28: *r = *p;
29: q->tn.op = ASSIGN;
30: q->in.right = p;
31: q->in.left = r;
32: r->tn.op = QNODE;
33: r->tn.rval = callreg(p); /* the reg where the value will be forced */
34: return( q );
35: }
36:
37: int odebug = 0, rdebug = 0, sdebug = 0;
38:
39: p2init( argc, argv )
40: char *argv[];
41: {
42: /* set the values of the pass 2 arguments */
43:
44: register int c; extern int syncstdio;
45: register char *cp;
46: register files;
47:
48: allo0(); /* free all regs */
49: files = 0;
50:
51: for( c=1; c<argc; ++c )
52: {
53: if( *(cp=argv[c]) == '-' )
54: {
55: while( *++cp )
56: {
57: switch(++syncstdio, *cp)
58: {
59:
60: case 'X': /* pass1 flags */
61: while( *++cp )
62: {
63: /* VOID */
64: }
65: --syncstdio;
66: --cp;
67: break;
68: # ifdef GDEBUG
69: #define LL_TOP 0 /* from mfile1.h */
70: case 'g': /* another stab in the back */
71: {
72: extern int gdebug;
73: extern int wloop_level, floop_level;
74: gdebug = !gdebug;
75: wloop_level = LL_TOP; /* natural */
76: floop_level = LL_TOP; /* loops */
77: } /* fall through */
78: # endif
79: case 'l': /* linenos */
80: --syncstdio;
81: ++lflag;
82: break;
83:
84: default:
85: cerror( "bad option: %c", *cp );
86: }
87: }
88: }
89: else files = 1; /* assumed to be a ftitle */
90: }
91:
92: mkdope();
93: return( files );
94: }
95:
96: NODE *
97: dlabel( p, l )
98: register NODE *p;
99: {
100: /* define a label after p is executed */
101: register NODE *q;
102:
103: /* condit will throw away things, fix here
104: /* if( !p ) cerror( "dlabel" );
105: */
106: if (!p) /* create conventional dumb subtree */
107: {
108: p = talloc();
109: p->tn.op = ICON;
110: p->tn.name = NULL;
111: p->tn.lval = 0;
112: p->tn.type = TINT;
113: }
114: q = talloc();
115: q->tn.type = p->tn.type;
116: q->in.left = p;
117: q->tn.op = GENLAB;
118: q->bn.label = l;
119: return( q );
120: }
121:
122:
123: NODE *
124: genbr( o, l, p )
125: register NODE *p;
126: register o,l;
127: {
128: /* after evaluating p, generate a branch to l */
129: /* if o is 0, unconditional */
130: register NODE *q;
131: if( !p ) cerror( "genbr" );
132: if( l < 0 ) cerror( "genbr1" );
133: q = talloc();
134: q->tn.op = o?GENBR:GENUBR;
135: q->tn.type = p->tn.type;
136: q->in.left = p;
137: q->bn.label = l;
138: q->bn.lop = o;
139: if( o && logop(p->tn.op) &&
140: (p->tn.op != ANDAND)
141: && (p->tn.op != OROR)
142: ) p->tn.op = CMP;
143: return( q );
144: }
145:
146:
147: static NODE *
148: oreff(p)
149: register NODE *p;
150: {
151: register NODE *r, *l;
152: NODE *condit(), *seq();
153: int lab, t, f;
154: /* oreff is called if an || op is evaluated with goal=CEFF
155: The rhs of || ops should be executed only if the
156: lhs is false. Since our goal is CEFF, we don't need
157: a result of the ||, but we need to
158: preserve that dependancy with this special case */
159:
160: /* We must catch this case before its children are
161: condit() and change the goal on it left child to CCC */
162:
163: if (tcond(p->in.left)) {
164: tfree(p->in.right);
165: p->in.op = FREE;
166: p = condit( p->in.left, CEFF, -1, -1);
167: } else if (fcond(p->in.left)) {
168: p->in.op = COMOP;
169: p = condit( p, CEFF, -1, -1);
170: } else {
171: lab = getlab();
172: l = condit( p->in.left, CCC, lab, -1);
173: r = condit( p->in.right, CEFF, -1, -1);
174: p->in.op = FREE;
175: p = seq(l, r); /* put r after l */
176: p = dlabel(p, lab);
177: }
178: return p;
179: }
180: static NODE *
181: andeff(p)
182: register NODE *p;
183: {
184: register NODE *r, *l;
185: NODE *condit();
186: int lab, t, f;
187: /* andeff is called if an && op is evaluated with goal=CEFF
188: The rhs of && ops should be executed only if the
189: lhs is true. Since our goal is CEFF, we don't need
190: a result of the &&, but we need to
191: preserve that dependancy with this special case */
192:
193: /* We must catch this case before its children are
194: condit() and change the goal on it left child to CCC */
195:
196: if (fcond(p->in.left)) {
197: tfree(p->in.right);
198: p->in.op = FREE;
199: p = condit( p->in.left, CEFF, -1, -1);
200: } else if (tcond(p->in.left)) {
201: p->in.op = COMOP;
202: p = condit( p, CEFF, -1, -1);
203: } else {
204: lab = getlab();
205: p->in.op = FREE;
206: l = condit( p->in.left, CCC, -1, lab);
207: r = condit( p->in.right, CEFF, -1, -1);
208: p = seq(l, r); /* put r after l */
209: p = dlabel(p, lab);
210: }
211: return p;
212: }
213: int negrel[] =
214: {
215: NE, EQ, GT, GE, LT, LE, UGT, UGE, ULT, ULE
216: } ; /* negatives of relationals */
217:
218: tcond( p )
219: register NODE *p;
220: {
221: /* return 1 if p is always true, 0 otherwise */
222: register o = p->tn.op;
223: register NODE *q;
224:
225: switch( o )
226: {
227:
228: case ICON:
229: return( p->tn.lval || p->tn.name != (char *) 0 );
230:
231: case COMOP:
232: return( tcond( p->in.right ) );
233:
234: case ANDAND:
235: return( tcond( p->in.left ) && tcond( p->in.right ) );
236:
237: case OROR:
238: return( tcond( p->in.left ) || tcond( p->in.right ) );
239:
240: case NOT:
241: return( fcond( p->in.left ) );
242:
243: case QUEST:
244: q = p->in.right;
245: if( tcond( p->in.left ) ) return( tcond( q->in.left ) );
246: if( fcond( p->in.left ) ) return( tcond( q->in.right ) );
247: return( tcond( q->in.left ) && tcond( q->in.right ) );
248:
249: default:
250: return( 0 );
251: }
252: }
253:
254: fcond( p )
255: register NODE *p;
256: {
257: /* return 1 if p is always false, 0 otherwise */
258: register o = p->tn.op;
259: register NODE *q;
260:
261: switch( o )
262: {
263:
264: case ICON:
265: return( !p->tn.lval && p->tn.name == (char *) 0 );
266:
267: case COMOP:
268: return( fcond( p->in.right ) );
269:
270: case ANDAND:
271: return( fcond( p->in.left ) || fcond( p->in.right ) );
272:
273: case OROR:
274: return( fcond( p->in.left ) && fcond( p->in.right ) );
275:
276: case NOT:
277: return( tcond( p->in.left ) );
278:
279: case QUEST:
280: q = p->in.right;
281: if( tcond( p->in.left ) ) return( fcond( q->in.left ) );
282: if( fcond( p->in.left ) ) return( fcond( q->in.right ) );
283: return( fcond( q->in.left ) && fcond( q->in.right ) );
284:
285: default:
286: return( 0 );
287: }
288: }
289:
290: NODE *
291: rcomma( p )
292: register NODE *p;
293: {
294: /* p is a COMOP; return the shrunken version thereof */
295:
296: if( p->tn.op != COMOP ) cerror( "rcomma" );
297:
298: if( p->in.left && p->in.right ) return( p );
299: p->tn.op = FREE;
300: if( !p->in.left ) return( p->in.right );
301: return( p->in.left );
302: }
303:
304: NODE *
305: seq( p1, p2 )
306: register NODE *p1, *p2;
307: {
308: /* execute p then q */
309: register NODE *q;
310:
311: q = talloc();
312: if (!p1) return p2;
313: if (!p2) return p1;
314: q->in.op = COMOP;
315: /*q->in.type = p2->in.right->in.type; why? */
316: q->in.type = p2->in.type;
317: q->in.left = p1;
318: q->in.right = p2;
319: return q;
320: }
321:
322: NODE *
323: gtb( p, l )
324: register NODE *p;
325: register l;
326: {
327: register NODE *q;
328: /* replace p by a trivial branch to l */
329: /* if l is -1, return NULL */
330: q = condit( p, CEFF, -1, -1 );
331: if( l<0 ) return( q );
332: if( !q )
333: {
334: q = talloc();
335: q->tn.op = ICON;
336: q->tn.lval = 0;
337: q->tn.name = (char *) 0;
338: q->tn.type = TINT;
339: }
340: return( genbr( 0, l, q ) );
341: }
342:
343: NODE *
344: condit( p, goal, t, f )
345: register NODE *p;
346: register goal,t,f;
347: {
348: /* generate code for conditionals in terms of GENLAB and GENBR nodes */
349: /* goal is either CEFF, NRGS, or CCC */
350: /* also, delete stuff that never needs get done */
351: /* if goal==CEFF, return of null means nothing to be done */
352:
353: register o, lt, lf, l;
354: register NODE *q, *q1, *q2;
355:
356: o = p->tn.op;
357:
358: if( o == CBRANCH )
359: {
360: p->in.right->tn.op = p->tn.op = FREE;
361: l = p->in.right->tn.lval;
362: p = p->in.left;
363: if( fcond( p ) ) return( gtb(p,l) );
364: if( tcond( p ) ) return( gtb(p,-1) );
365: return( condit( p, CCC, -1, l ) );
366: }
367:
368: /* a convenient place to diddle a few special ops */
369: if( callop(o) )
370: {
371: if( optype(o) == UTYPE ) p->stn.argsize = 0;
372: else p->stn.argsize = argsize(p->in.right);
373: if( goal==CEFF ) goal = NRGS;
374: /* flow on, so that we can handle if( f(...) )... */
375: }
376: else if( goal==CEFF && (asgop(o) || o==STASG || o==INIT)) goal=NRGS;
377:
378: /* do a bit of optimization */
379:
380: if( goal == NRGS )
381: {
382: if( logop(o) )
383: {
384: /* must make p into ( p ? 1 : 0 ), then recompile */
385: q1 = talloc();
386: q1->tn.op = ICON;
387: q1->tn.name = (char *) 0;
388: q1->tn.lval = 1;
389: q1->tn.type = p->tn.type;
390: q2 = talloc();
391: *q2 = *q1;
392: q2->tn.lval = 0;
393: q = talloc();
394: q->tn.op = COLON;
395: q->tn.type = p->tn.type;
396: q->in.left = q1;
397: q->in.right = q2;
398: q1 = talloc();
399: q1->tn.op = o = QUEST;
400: q1->tn.type = p->tn.type;
401: q1->in.left = p;
402: q1->in.right = q;
403: p = q1; /* flow on, and compile */
404: }
405: }
406:
407: if( goal != CCC )
408: {
409: if( o == QUEST )
410: {
411: /* rewrite ? : when goal not CCC */
412: lf = getlab();
413: l = getlab();
414: p->tn.op = COMOP;
415: q = p->in.right;
416: q1 = condit( q->in.left, goal, -1, -1 );
417: q->in.right = condit( q->in.right, goal, -1, -1 );
418: if( tcond( p->in.left ) )
419: {
420: q->tn.op = FREE;
421: tfree( q->in.right );
422: p->in.right = q1;
423: p->in.left=condit( p->in.left, CEFF, -1, -1 );
424: return( rcomma( p ) );
425: }
426: if( fcond( p->in.left ) )
427: {
428: q->tn.op = FREE;
429: tfree( q1 );
430: p->in.right = q->in.right;
431: p->in.left=condit( p->in.left, CEFF, -1, -1 );
432: return( rcomma( p ) );
433: }
434: if( !q1 )
435: {
436: if( !q->in.right )
437: {
438: /* may still have work to do
439: ** if left side of ? has effect
440: */
441: q1 = condit(p->in.left, goal,
442: -1, -1);
443: if (!q1)
444: {
445: tfree( p->in.left );
446: }
447: p->tn.op = q->tn.op = FREE;
448: return( q1 );
449: }
450: /* rhs done if condition is false */
451: p->in.left = condit( p->in.left, CCC, l, -1 );
452: p->in.right = dlabel( q->in.right, l );
453: q->tn.op = FREE;
454: return( p );
455: }
456: else if( !q->in.right )
457: {
458: /* lhs done if condition is true */
459: p->in.left=condit( p->in.left, CCC, -1, lf );
460: p->in.right = dlabel( q1, lf );
461: q->tn.op = FREE;
462: return( p );
463: }
464:
465: /* both sides exist and the condition is nontrivial */
466: p->in.left = condit( p->in.left, CCC, -1, lf );
467: q1 = force(q1);
468: q->in.right = force(q->in.right);
469: q1 = genbr( 0, l, q1 );
470: q->in.left = dlabel( q1, lf );
471: q->tn.op = COMOP;
472: return( dlabel( p, l ) );
473: }
474:
475: if( goal == CEFF )
476: {
477: /* some things may disappear */
478: switch( o )
479: {
480:
481: case CBRANCH:
482: case GENBR:
483: case GENUBR:
484: case CALL:
485: case UNARY CALL:
486: case FORTCALL:
487: case UNARY FORTCALL:
488: case STCALL:
489: case UNARY STCALL:
490: case STASG:
491: case INIT:
492: case MOD: /* do these for the side effects */
493: case DIV:
494: goal = NRGS;
495: }
496: }
497:
498: /* The rhs of && and || ops are executed only if the
499: result is not clear from the lhs. If our goal is
500: CEFF, we don't need a result, but we need to
501: preserve that dependancy. So special case it. */
502: if (goal==CEFF) {
503: if (o == ANDAND) return andeff(p);
504: if (o == OROR) return oreff(p);
505: }
506: /* This next batch of code wanders over the tree getting
507: rid of code which is for effect only and has no
508: effect */
509: switch( optype(o) )
510: {
511: case LTYPE:
512: if( goal == CEFF )
513: {
514: p->tn.op = FREE;
515: return( NIL );
516: }
517: break;
518:
519: case BITYPE:
520: p->in.right = condit( p->in.right, goal, -1, -1 );
521: case UTYPE:
522: p->in.left = condit( p->in.left, o==COMOP?CEFF:goal,
523: -1, -1 );
524: }
525: /* If we are only interested in effects, we quit here */
526: if( goal == CEFF || o==COMOP )
527: {
528: /* lhs or rhs may have disappeared */
529: /* op need not get done */
530:
531: switch( optype(o) )
532: {
533:
534: case BITYPE:
535: p->tn.op = COMOP;
536: p = rcomma(p);
537: return ( p );
538:
539: case UTYPE:
540: /* don't throw out prepass's labels */
541: if(p->in.op == GENLAB)
542: return(p);
543: p->tn.op = FREE;
544: return( p->in.left );
545:
546: case LTYPE:
547: p->tn.op = FREE;
548: return( NIL );
549: }
550: }
551: return( p );
552: }
553:
554: /* goal must = CCC from here on */
555:
556: switch( o )
557: {
558:
559: case ULE:
560: case ULT:
561: case UGE:
562: case UGT:
563: case EQ:
564: case NE:
565: case LE:
566: case LT:
567: case GE:
568: case GT:
569: if(t<0 )
570: {
571: o = p->tn.op = negrel[o-EQ];
572: t = f;
573: f = -1;
574: }
575:
576: #ifndef NOOPT
577: if( p->in.right->in.op == ICON &&
578: p->in.right->tn.lval == 0 &&
579: p->in.right->in.name == (char *) 0 )
580: {
581: /* if chars are unsigned, do these optimizations
582: as if this is an unsigned compare*/
583: #ifndef CHSIGN
584: if (
585: ( p->in.left->tn.type == TCHAR ||
586: ( p->in.left->in.op == CONV &&
587: p->in.left->in.left->tn.type == TCHAR ) )
588: && o >= LE && o <= GT)
589: o += UGT - GT;
590: #endif
591:
592: /* the question here is whether we can assume that */
593: /* unconditional branches preserve condition codes */
594: /* if this turned out to be no, we would have to */
595: /* explicitly handle this case here */
596:
597: switch( o )
598: {
599:
600: case UGT:
601: case ULE:
602: o = p->in.op = (o==UGT)?NE:EQ;
603: case EQ:
604: case NE:
605: case LE:
606: case LT:
607: case GE:
608: case GT:
609: if( logop( p->in.left->tn.op ) )
610: {
611: /* situation like (a==0)==0 */
612: /* ignore optimization */
613: goto noopt;
614: }
615: break;
616:
617: case ULT: /* never succeeds */
618: return( gtb( p, f ) );
619:
620: case UGE:
621: /* always succeeds */
622: return( gtb( p, t ) );
623: }
624: p->tn.op = p->in.right->tn.op = FREE;
625: p = condit( p->in.left, NRGS, -1, -1 );
626: p = genbr( o, t, p );
627: if( f<0 ) return( p );
628: else return( genbr( 0, f, p ) );
629: }
630: noopt:
631: # endif
632:
633: p->in.left = condit( p->in.left, NRGS, -1, -1 );
634: p->in.right = condit( p->in.right, NRGS, -1, -1 );
635: p = genbr( o, t, p );
636: if( f>=0 ) p = genbr( 0, f, p );
637: return( p );
638:
639: case COMOP:
640: p->in.left = condit( p->in.left, CEFF, -1, -1 );
641: p->in.right = condit( p->in.right, CCC, t, f );
642: return( rcomma( p ) );
643:
644: case NOT:
645: p->tn.op = FREE;
646: return( condit( p->in.left, CCC, f, t ) );
647:
648: case ANDAND:
649: lf = f<0 ? getlab() : f;
650: lt = t<0 ? getlab() : t;
651: p->tn.op = COMOP;
652: if( tcond( p->in.left ) )
653: {
654: /* left is always true */
655: p->in.left = condit( p->in.left, CEFF, -1, -1 );
656: p->in.right = condit( p->in.right, CCC, t, f );
657: }
658: else {
659: /* lhs not always true */
660: if( tcond( p->in.right ) )
661: {
662: /* rhs is always true */
663: p->in.right =
664: condit( p->in.right, CEFF, -1, -1 );
665: if (p->in.right) {
666: /* const with sideeffect */
667: p->in.left =
668: condit( p->in.left, CCC, -1,lf);
669: p->in.right = condit( p->in.right,
670: CCC, t, t );
671: } else
672: p->in.left =
673: condit( p->in.left, CCC, t, f );
674: } else {
675: p->in.left =
676: condit( p->in.left, CCC, -1, lf );
677: p->in.right =
678: condit( p->in.right, CCC, t, f );
679: }
680: }
681: q = rcomma( p );
682: if( f<0 ) q = dlabel( q, lf );
683: if( t<0 ) q = dlabel( q, lt );
684: return( q );
685:
686: case OROR:
687: lf = f<0 ? getlab() : f;
688: lt = t<0 ? getlab() : t;
689: p->tn.op = COMOP;
690: if( fcond( p->in.left ) )
691: {
692: /* left is always false */
693: p->in.left = condit( p->in.left, CEFF, -1, -1 );
694: p->in.right = condit( p->in.right, CCC, t, f );
695: }
696: else {
697: /* left is not always false */
698: if( fcond( p->in.right ) )
699: {
700: /* right always false */
701: p->in.right =
702: condit( p->in.right, CEFF, -1, -1 );
703: if (p->in.right) {
704: /* const with sideeffect */
705: p->in.left =
706: condit( p->in.left, CCC, lt,-1);
707: /* This may generate a superfluous
708: test. Tough. */
709: p->in.right = condit( p->in.right,
710: CCC, f, f );
711: } else
712: p->in.left =
713: condit( p->in.left, CCC, t, f );
714: } else {
715: p->in.left =
716: condit( p->in.left, CCC, lt, -1 );
717: p->in.right =
718: condit( p->in.right, CCC, t, f );
719: }
720: }
721: p = rcomma( p );
722: if( f<0 ) p = dlabel( p, lf );
723: if( t<0 ) p = dlabel( p, lt );
724: return( p );
725:
726: case QUEST:
727: lf = f<0 ? getlab() : f;
728: lt = t<0 ? getlab() : t;
729: p->in.left = condit( p->in.left, CCC, -1, l=getlab() );
730: q = p->in.right;
731: q1 = condit( q->in.left, goal, lt, lf );
732: q->in.left = dlabel( q1, l );
733: q->in.right = condit( q->in.right, goal, t, f );
734: p->tn.op = COMOP;
735: q->tn.op = COMOP;
736: if( t<0 ) p = dlabel( p, lt );
737: if( f<0 ) p = dlabel( p, lf );
738: return( p );
739:
740: default:
741: /* get the condition codes, generate the branch */
742: switch( optype(o) )
743: {
744: case BITYPE:
745: p->in.right = condit( p->in.right, NRGS, -1, -1 );
746: case UTYPE:
747: p->in.left = condit( p->in.left, NRGS, -1, -1 );
748: }
749: if( t>=0 ) p = genbr( NE, t, p );
750: if( f>=0 ) p = genbr( (t>=0)?0:EQ, f, p );
751: return( p );
752: }
753: }
754:
755: p2compile( p )
756: register NODE *p;
757: {
758: if( lflag ) lineid(p->ln.lineno ? p->ln.lineno : lineno, ftitle );
759: tmpoff = 0; /* expression at top level reuses temps */
760: /* generate code for the tree p */
761:
762: /* eliminate the conditionals */
763: if(p)
764: p = condit( p, CEFF, -1, -1 );
765: if( p )
766: {
767: /* expression does something */
768: /* generate the code */
769: pjwreader(p);
770: pjwend(p);
771: }
772: allchk();
773: /* tcheck will be done by the first pass at the end of a ftn. */
774: /* first pass will do it... */
775: }
776:
777: p2bbeg( aoff, myreg )
778: register aoff,myreg;
779: {
780: static int myftn = -1;
781: SETOFF( aoff, ALSTACK );
782: if( myftn != ftnno )
783: {
784: /* beginning of function */
785: maxboff = aoff;
786: myftn = ftnno;
787: maxtemp = 0;
788: maxarg = 0;
789: }
790: else
791: {
792: if( aoff > maxboff ) maxboff = aoff;
793: }
794: # ifdef SETREGS
795: SETREGS(myreg);
796: # endif
797: }
798:
799: p2bend()
800: {
801: SETOFF( maxboff, ALSTACK );
802: SETOFF( maxarg, ALSTACK );
803: SETOFF( maxtemp, ALSTACK );
804: eobl2();
805: maxboff = maxarg = maxtemp = 0;
806: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.