Commit | Line | Data |
---|---|---|
fbf70ca6 | 1 | #ifndef lint |
1c15e888 | 2 | static char sccsid[] = "@(#)order.c 1.8 (Berkeley) 8/26/88"; |
fbf70ca6 SL |
3 | #endif |
4 | ||
f8a5269a | 5 | # include "pass2.h" |
fbf70ca6 SL |
6 | |
7 | int maxargs = { -1 }; | |
8 | ||
e7c77527 | 9 | /*ARGSUSED*/ |
fbf70ca6 SL |
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 | ||
e7c77527 | 22 | /*ARGSUSED*/ |
fbf70ca6 SL |
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 | ||
e7c77527 | 57 | /*ARGSUSED*/ |
fbf70ca6 SL |
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)) && | |
8a2e495c DS |
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) || | |
8548594d | 98 | ISARY(p->in.type)) ) |
fbf70ca6 SL |
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){ | |
e0720a2a | 147 | p->in.su = max(max(sul,(sul!=0)+2),sur+1); |
fbf70ca6 SL |
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: | |
e0720a2a | 180 | p->in.su = max(max(sul,(sul!=0)+2),sur+1); |
fbf70ca6 | 181 | return; |
fbf70ca6 SL |
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 | ||
fbf70ca6 SL |
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 && | |
8a2e495c | 242 | (p->in.left->in.left->in.op!=REG || tlen(p->in.left->in.left)!=SZINT/SZCHAR ) ) { |
fbf70ca6 SL |
243 | order( p->in.left->in.left, INTAREG|INAREG ); |
244 | return; | |
245 | } | |
246 | if( p->in.right->in.op==LS && | |
8a2e495c | 247 | (p->in.right->in.left->in.op!=REG || tlen(p->in.right->in.left)!=SZINT/SZCHAR ) ) { |
fbf70ca6 SL |
248 | order( p->in.right->in.left, INTAREG|INAREG ); |
249 | return; | |
250 | } | |
251 | if( p->in.type == (PTR|CHAR) || p->in.type == (PTR|UCHAR) ) { | |
8a2e495c | 252 | if( p->in.left->in.op!=REG || tlen(p->in.left)!=SZINT/SZCHAR ) { |
fbf70ca6 SL |
253 | order( p->in.left, INTAREG|INAREG ); |
254 | return; | |
255 | } | |
8a2e495c | 256 | else if( p->in.right->in.op!=REG || tlen(p->in.right)!=SZINT/SZCHAR ) { |
fbf70ca6 SL |
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 | ||
fbf70ca6 SL |
278 | setincr( p ) register NODE *p; { |
279 | p = p->in.left; | |
280 | if( p->in.op == UNARY MUL ){ | |
8a2e495c | 281 | offstar( p->in.left ); |
fbf70ca6 SL |
282 | return( 1 ); |
283 | } | |
284 | return( 0 ); | |
285 | } | |
286 | ||
fbf70ca6 SL |
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 | ||
fbf70ca6 SL |
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 | ||
fbf70ca6 SL |
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" ); | |
8a2e495c | 398 | /*NOTREACHED*/ |
fbf70ca6 SL |
399 | } |
400 | ||
e7c77527 | 401 | int crslab = 99999; /* Tahoe */ |
fbf70ca6 SL |
402 | |
403 | getlab(){ | |
404 | return( crslab-- ); | |
405 | } | |
406 | ||
407 | deflab( l ){ | |
38cb9d5a | 408 | if (nerrors) return; |
fbf70ca6 SL |
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; | |
26655c9e | 416 | int count; |
fbf70ca6 SL |
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 */ | |
26655c9e | 439 | for( count = 0; p->in.op != OREG && count < 10; ++count ){ |
fbf70ca6 SL |
440 | offstar( p->in.left ); |
441 | canon( p ); | |
fbf70ca6 | 442 | } |
26655c9e | 443 | if( p->in.op != OREG ) cerror( "stuck starg" ); |
fbf70ca6 SL |
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 | } |