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