|
|
1.1 root 1: static char *sccsid ="%W% (Berkeley) %G%";
2: # include "mfile2"
3:
4: int maxargs = { -1 };
5:
6: stoasg( p, o ) register NODE *p; {
7: /* should the assignment op p be stored,
8: given that it lies as the right operand of o
9: (or the left, if o==UNARY MUL) */
10: /*
11: if( p->in.op == INCR || p->in.op == DECR ) return;
12: if( o==UNARY MUL && p->in.left->in.op == REG && !isbreg(p->in.left->tn.rval) ) SETSTO(p,INAREG);
13: */
14: }
15:
16: deltest( p ) register NODE *p; {
17: /* should we delay the INCR or DECR operation p */
18: p = p->in.left;
19: return( p->in.op == REG || p->in.op == NAME || p->in.op == OREG );
20: }
21:
22: autoincr( p ) NODE *p; {
23: register NODE *q = p->in.left, *r;
24:
25: if( q->in.op == INCR && (r=q->in.left)->in.op == REG &&
26: ISPTR(q->in.type) && p->in.type == DECREF(q->in.type) &&
27: tlen(p) == q->in.right->tn.lval ) return(1);
28:
29: return(0);
30: }
31:
32: mkadrs(p) register NODE *p; {
33: register o;
34:
35: o = p->in.op;
36:
37: if( asgop(o) ){
38: if( p->in.left->in.su >= p->in.right->in.su ){
39: if( p->in.left->in.op == UNARY MUL ){
40: SETSTO( p->in.left->in.left, INTEMP );
41: }
42: else if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){
43: SETSTO( p->in.left->in.left->in.left, INTEMP );
44: }
45: else { /* should be only structure assignment */
46: SETSTO( p->in.left, INTEMP );
47: }
48: }
49: else SETSTO( p->in.right, INTEMP );
50: }
51: else {
52: if( p->in.left->in.su > p->in.right->in.su ){
53: SETSTO( p->in.left, INTEMP );
54: }
55: else {
56: SETSTO( p->in.right, INTEMP );
57: }
58: }
59: }
60:
61: notoff( t, r, off, cp) CONSZ off; char *cp; {
62: /* is it legal to make an OREG or NAME entry which has an
63: /* offset of off, (from a register of r), if the
64: /* resulting thing had type t */
65:
66: /* if( r == R0 ) return( 1 ); /* NO */
67: return(0); /* YES */
68: }
69:
70: # define max(x,y) ((x)<(y)?(y):(x))
71:
72: sucomp( p ) register NODE *p; {
73:
74: /* set the su field in the node to the sethi-ullman
75: number, or local equivalent */
76:
77: register o, ty, sul, sur, r;
78:
79: o = p->in.op;
80: ty = optype( o );
81: p->in.su = szty( p->in.type ); /* 2 for float or double, else 1 */;
82:
83: if( ty == LTYPE ){
84: if( o == OREG ){
85: r = p->tn.rval;
86: /* oreg cost is (worst case) 1 + number of temp registers used */
87: if( R2TEST(r) ){
88: if( R2UPK1(r)!=100 && istreg(R2UPK1(r)) ) ++p->in.su;
89: if( istreg(R2UPK2(r)) ) ++p->in.su;
90: }
91: else {
92: if( istreg( r ) ) ++p->in.su;
93: }
94: }
95: if( p->in.su == szty(p->in.type) &&
96: (p->in.op!=REG || !istreg(p->tn.rval)) &&
97: (p->in.type==INT || p->in.type==UNSIGNED || p->in.type==DOUBLE) )
98: p->in.su = 0;
99: return;
100: }
101:
102: else if( ty == UTYPE ){
103: switch( o ) {
104: case UNARY CALL:
105: case UNARY STCALL:
106: p->in.su = fregs; /* all regs needed */
107: return;
108:
109: default:
110: p->in.su = p->in.left->in.su + (szty( p->in.type ) > 1 ? 2 : 0) ;
111: return;
112: }
113: }
114:
115:
116: /* If rhs needs n, lhs needs m, regular su computation */
117:
118: sul = p->in.left->in.su;
119: sur = p->in.right->in.su;
120:
121: if( o == ASSIGN ){
122: /* computed by doing right, then left (if not in mem), then doing it */
123: p->in.su = max(sur,sul+1);
124: return;
125: }
126:
127: if( o == CALL || o == STCALL ){
128: /* in effect, takes all free registers */
129: p->in.su = fregs;
130: return;
131: }
132:
133: if( o == STASG ){
134: /* right, then left */
135: p->in.su = max( max( 1+sul, sur), fregs );
136: return;
137: }
138:
139: if( asgop(o) ){
140: /* computed by doing right, doing left address, doing left, op, and store */
141: p->in.su = max(sur,sul+2);
142: /*
143: if( o==ASG MUL || o==ASG DIV || o==ASG MOD) p->in.su = max(p->in.su,fregs);
144: */
145: return;
146: }
147:
148: switch( o ){
149: case ANDAND:
150: case OROR:
151: case QUEST:
152: case COLON:
153: case COMOP:
154: p->in.su = max( max(sul,sur), 1);
155: return;
156:
157: case PLUS:
158: case OR:
159: case ER:
160: /* commutative ops; put harder on left */
161: if( p->in.right->in.su > p->in.left->in.su && !istnode(p->in.left) ){
162: register NODE *temp;
163: temp = p->in.left;
164: p->in.left = p->in.right;
165: p->in.right = temp;
166: }
167: break;
168: }
169:
170: /* binary op, computed by left, then right, then do op */
171: p->in.su = max(sul,szty(p->in.right->in.type)+sur);
172: /*
173: if( o==MUL||o==DIV||o==MOD) p->in.su = max(p->in.su,fregs);
174: */
175:
176: }
177:
178: int radebug = 0;
179:
180: rallo( p, down ) NODE *p; {
181: /* do register allocation */
182: register o, type, down1, down2, ty;
183:
184: if( radebug ) printf( "rallo( %o, %d )\n", p, down );
185:
186: down2 = NOPREF;
187: p->in.rall = down;
188: down1 = ( down &= ~MUSTDO );
189:
190: ty = optype( o = p->in.op );
191: type = p->in.type;
192:
193:
194: if( type == DOUBLE || type == FLOAT ){
195: if( o == FORCE ) down1 = R0|MUSTDO;
196: }
197: else switch( o ) {
198: case ASSIGN:
199: down1 = NOPREF;
200: down2 = down;
201: break;
202:
203: /*
204: case MUL:
205: case DIV:
206: case MOD:
207: down1 = R3|MUSTDO;
208: down2 = R5|MUSTDO;
209: break;
210:
211: case ASG MUL:
212: case ASG DIV:
213: case ASG MOD:
214: p->in.left->in.rall = down1 = R3|MUSTDO;
215: if( p->in.left->in.op == UNARY MUL ){
216: rallo( p->in.left->in.left, R4|MUSTDO );
217: }
218: else if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){
219: rallo( p->in.left->in.left->in.left, R4|MUSTDO );
220: }
221: else rallo( p->in.left, R3|MUSTDO );
222: rallo( p->in.right, R5|MUSTDO );
223: return;
224: */
225:
226: case CALL:
227: case STASG:
228: case EQ:
229: case NE:
230: case GT:
231: case GE:
232: case LT:
233: case LE:
234: case NOT:
235: case ANDAND:
236: case OROR:
237: down1 = NOPREF;
238: break;
239:
240: case FORCE:
241: down1 = R0|MUSTDO;
242: break;
243:
244: }
245:
246: if( ty != LTYPE ) rallo( p->in.left, down1 );
247: if( ty == BITYPE ) rallo( p->in.right, down2 );
248:
249: }
250:
251: offstar( p ) register NODE *p; {
252: if( p->in.op == PLUS ) {
253: if( p->in.left->in.su == fregs ) {
254: order( p->in.left, INTAREG|INAREG );
255: return;
256: } else if( p->in.right->in.su == fregs ) {
257: order( p->in.right, INTAREG|INAREG );
258: return;
259: }
260: if( p->in.left->in.op==LS &&
261: (p->in.left->in.left->in.op!=REG || tlen(p->in.left->in.left)!=sizeof(int) ) ) {
262: order( p->in.left->in.left, INTAREG|INAREG );
263: return;
264: }
265: if( p->in.right->in.op==LS &&
266: (p->in.right->in.left->in.op!=REG || tlen(p->in.right->in.left)!=sizeof(int) ) ) {
267: order( p->in.right->in.left, INTAREG|INAREG );
268: return;
269: }
270: if( p->in.type == (PTR|CHAR) || p->in.type == (PTR|UCHAR) ) {
271: if( p->in.left->in.op!=REG || tlen(p->in.left)!=sizeof(int) ) {
272: order( p->in.left, INTAREG|INAREG );
273: return;
274: }
275: else if( p->in.right->in.op!=REG || tlen(p->in.right)!=sizeof(int) ) {
276: order(p->in.right, INTAREG|INAREG);
277: return;
278: }
279: }
280: }
281: if( p->in.op == PLUS || p->in.op == MINUS ){
282: if( p->in.right->in.op == ICON ){
283: p = p->in.left;
284: order( p , INTAREG|INAREG);
285: return;
286: }
287: }
288:
289: if( p->in.op == UNARY MUL && !canaddr(p) ) {
290: offstar( p->in.left );
291: return;
292: }
293:
294: order( p, INTAREG|INAREG );
295: }
296:
297: setincr( p ) register NODE *p; {
298: p = p->in.left;
299: if( p->in.op == UNARY MUL ){
300: offstar( p );
301: return( 1 );
302: }
303: return( 0 );
304: }
305:
306: setbin( p ) register NODE *p; {
307: register ro, rt;
308:
309: rt = p->in.right->in.type;
310: ro = p->in.right->in.op;
311:
312: if( canaddr( p->in.left ) && !canaddr( p->in.right ) ) { /* address rhs */
313: if( ro == UNARY MUL ) {
314: offstar( p->in.right->in.left );
315: return(1);
316: } else {
317: order( p->in.right, INAREG|INTAREG|SOREG );
318: return(1);
319: }
320: }
321: if( !istnode( p->in.left) ) { /* try putting LHS into a reg */
322: /* order( p->in.left, logop(p->in.op)?(INAREG|INBREG|INTAREG|INTBREG|SOREG):(INTAREG|INTBREG|SOREG) );*/
323: order( p->in.left, INAREG|INTAREG|INBREG|INTBREG|SOREG );
324: return(1);
325: }
326: else if( ro == UNARY MUL && rt != CHAR && rt != UCHAR ){
327: offstar( p->in.right->in.left );
328: return(1);
329: }
330: else if( rt == CHAR || rt == UCHAR || rt == SHORT || rt == USHORT || (ro != REG &&
331: ro != NAME && ro != OREG && ro != ICON ) ){
332: order( p->in.right, INAREG|INBREG );
333: return(1);
334: }
335: /*
336: else if( logop(p->in.op) && rt==USHORT ){ /* must get rhs into register */
337: /*
338: order( p->in.right, INAREG );
339: return( 1 );
340: }
341: */
342: return(0);
343: }
344:
345: setstr( p ) register NODE *p; { /* structure assignment */
346: if( p->in.right->in.op != REG ){
347: order( p->in.right, INTAREG );
348: return(1);
349: }
350: p = p->in.left;
351: if( p->in.op != NAME && p->in.op != OREG ){
352: if( p->in.op != UNARY MUL ) cerror( "bad setstr" );
353: order( p->in.left, INTAREG );
354: return( 1 );
355: }
356: return( 0 );
357: }
358:
359: setasg( p ) register NODE *p; {
360: /* setup for assignment operator */
361:
362: if( !canaddr(p->in.right) ) {
363: if( p->in.right->in.op == UNARY MUL )
364: offstar(p->in.right->in.left);
365: else
366: order( p->in.right, INAREG|INBREG|SOREG );
367: return(1);
368: }
369: if( p->in.left->in.op == UNARY MUL ) {
370: offstar( p->in.left->in.left );
371: return(1);
372: }
373: if( p->in.left->in.op == FLD && p->in.left->in.left->in.op == UNARY MUL ){
374: offstar( p->in.left->in.left->in.left );
375: return(1);
376: }
377: /* FLD patch */
378: if( p->in.left->in.op == FLD && !(p->in.right->in.type==INT || p->in.right->in.type==UNSIGNED)) {
379: order( p->in.right, INAREG);
380: return(1);
381: }
382: /* end of FLD patch */
383: return(0);
384: }
385:
386: setasop( p ) register NODE *p; {
387: /* setup for =ops */
388: register rt, ro;
389:
390: rt = p->in.right->in.type;
391: ro = p->in.right->in.op;
392:
393: if( ro == UNARY MUL && rt != CHAR ){
394: offstar( p->in.right->in.left );
395: return(1);
396: }
397: if( ( rt == CHAR || rt == SHORT || rt == UCHAR || rt == USHORT ||
398: ( ro != REG && ro != ICON && ro != NAME && ro != OREG ) ) ){
399: order( p->in.right, INAREG|INBREG );
400: return(1);
401: }
402: /*
403: if( (p->in.op == ASG LS || p->in.op == ASG RS) && ro != ICON && ro != REG ){
404: order( p->in.right, INAREG );
405: return(1);
406: }
407: */
408:
409:
410: p = p->in.left;
411: if( p->in.op == FLD ) p = p->in.left;
412:
413: switch( p->in.op ){
414:
415: case REG:
416: case ICON:
417: case NAME:
418: case OREG:
419: return(0);
420:
421: case UNARY MUL:
422: if( p->in.left->in.op==OREG )
423: return(0);
424: else
425: offstar( p->in.left );
426: return(1);
427:
428: }
429: cerror( "illegal setasop" );
430: }
431:
432: int crslab = 9999; /* Honeywell */
433:
434: getlab(){
435: return( crslab-- );
436: }
437:
438: deflab( l ){
439: printf( "L%d:\n", l );
440: }
441:
442: genargs( p, ptemp ) register NODE *p, *ptemp; {
443: register NODE *pasg;
444: register align;
445: register size;
446: register TWORD type;
447:
448: /* generate code for the arguments */
449:
450: /* first, do the arguments on the right */
451: while( p->in.op == CM ){
452: genargs( p->in.right, ptemp );
453: p->in.op = FREE;
454: p = p->in.left;
455: }
456:
457: if( p->in.op == STARG ){ /* structure valued argument */
458:
459: size = p->stn.stsize;
460: align = p->stn.stalign;
461: if( p->in.left->in.op == ICON ){
462: p->in.op = FREE;
463: p= p->in.left;
464: }
465: else {
466: /* make it look beautiful... */
467: p->in.op = UNARY MUL;
468: canon( p ); /* turn it into an oreg */
469: if( p->in.op != OREG ){
470: offstar( p->in.left );
471: canon( p );
472: if( p->in.op != OREG ){
473: offstar( p->in.left );
474: canon( p );
475: if( p->in.op != OREG ) cerror( "stuck starg" );
476: }
477: }
478: }
479:
480:
481: ptemp->tn.lval = 0; /* all moves to (sp) */
482:
483: pasg = talloc();
484: pasg->in.op = STASG;
485: pasg->stn.stsize = size;
486: pasg->stn.stalign = align;
487: pasg->in.right = p;
488: pasg->in.left = tcopy( ptemp );
489:
490: /* the following line is done only with the knowledge
491: that it will be undone by the STASG node, with the
492: offset (lval) field retained */
493:
494: if( p->in.op == OREG ) p->in.op = REG; /* only for temporaries */
495:
496: order( pasg, FORARG );
497: ptemp->tn.lval += size;
498: return;
499: }
500:
501: /* ordinary case */
502:
503: order( p, FORARG );
504: }
505:
506: argsize( p ) register NODE *p; {
507: register t;
508: t = 0;
509: if( p->in.op == CM ){
510: t = argsize( p->in.left );
511: p = p->in.right;
512: }
513: if( p->in.type == DOUBLE || p->in.type == FLOAT ){
514: SETOFF( t, 4 );
515: return( t+8 );
516: }
517: else if( p->in.op == STARG ){
518: SETOFF( t, 4 ); /* alignment */
519: return( t + ((p->stn.stsize+3)/4)*4 ); /* size */
520: }
521: else {
522: SETOFF( t, 4 );
523: return( t+4 );
524: }
525: }
526:
527:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.