Commit | Line | Data |
---|---|---|
fbf70ca6 SL |
1 | #ifndef lint |
2 | static char sccsid[] = "@(#)order.c 1.1 (Berkeley) %G%"; | |
3 | #endif | |
4 | ||
5 | # include "mfile2" | |
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 | } |