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