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