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