Commit | Line | Data |
---|---|---|
3c5d933b SJ |
1 | # include "mfile2" |
2 | ||
3 | int fltused = 0; | |
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 | return( shltype(p->left->op, p->left ) ); | |
10 | ||
11 | } | |
12 | ||
13 | deltest( p ) register NODE *p; { | |
14 | /* should we delay the INCR or DECR operation p */ | |
15 | if( p->op == INCR && p->left->op == REG && spsz( p->left->type, p->right->lval ) ){ | |
16 | /* STARREG */ | |
17 | return( 0 ); | |
18 | } | |
19 | ||
20 | p = p->left; | |
21 | if( p->op == UNARY MUL ) p = p->left; | |
22 | return( p->op == NAME || p->op == OREG || p->op == REG ); | |
23 | } | |
24 | ||
25 | mkadrs(p) register NODE *p; { | |
26 | register o; | |
27 | ||
28 | o = p->op; | |
29 | ||
30 | if( asgop(o) ){ | |
31 | if( p->left->su >= p->right->su ){ | |
32 | if( p->left->op == UNARY MUL ){ | |
33 | if( p->left->su > 0 ) | |
34 | SETSTO( p->left->left, INTEMP ); | |
35 | else { | |
36 | if( p->right->su > 0 ) SETSTO( p->right, INTEMP ); | |
37 | else cerror( "store finds both sides trivial" ); | |
38 | } | |
39 | } | |
40 | else if( p->left->op == FLD && p->left->left->op == UNARY MUL ){ | |
41 | SETSTO( p->left->left->left, INTEMP ); | |
42 | } | |
43 | else { /* should be only structure assignment */ | |
44 | SETSTO( p->left, INTEMP ); | |
45 | } | |
46 | } | |
47 | else SETSTO( p->right, INTEMP ); | |
48 | } | |
49 | else { | |
50 | if( p->left->su > p->right->su ){ | |
51 | SETSTO( p->left, INTEMP ); | |
52 | } | |
53 | else { | |
54 | SETSTO( p->right, INTEMP ); | |
55 | } | |
56 | } | |
57 | } | |
58 | ||
59 | notoff( t, r, off, cp) TWORD t; CONSZ off; char *cp; { | |
60 | /* is it legal to make an OREG or NAME entry which has an | |
61 | /* offset of off, (from a register of r), if the | |
62 | /* resulting thing had type t */ | |
63 | ||
64 | /* return( 1 ); /* NO */ | |
65 | return(0); /* YES */ | |
66 | } | |
67 | ||
68 | # define max(x,y) ((x)<(y)?(y):(x)) | |
69 | # define min(x,y) ((x)<(y)?(x):(y)) | |
70 | ||
71 | ||
72 | # define ZCHAR 01 | |
73 | # define ZLONG 02 | |
74 | # define ZFLOAT 04 | |
75 | ||
76 | zum( p, zap ) register NODE *p; { | |
77 | /* zap Sethi-Ullman number for chars, longs, floats */ | |
78 | /* in the case of longs, only STARNM's are zapped */ | |
79 | /* ZCHAR, ZLONG, ZFLOAT are used to select the zapping */ | |
80 | ||
81 | register su; | |
82 | ||
83 | su = p->su; | |
84 | ||
85 | switch( p->type ){ | |
86 | ||
87 | case CHAR: | |
88 | case UCHAR: | |
89 | if( !(zap&ZCHAR) ) break; | |
90 | if( su == 0 ) p->su = su = 1; | |
91 | break; | |
92 | ||
93 | case LONG: | |
94 | case ULONG: | |
95 | if( !(zap&ZLONG) ) break; | |
96 | if( p->op == UNARY MUL && su == 0 ) p->su = su = 2; | |
97 | break; | |
98 | ||
99 | case FLOAT: | |
100 | if( !(zap&ZFLOAT) ) break; | |
101 | if( su == 0 ) p->su = su = 1; | |
102 | ||
103 | } | |
104 | ||
105 | return( su ); | |
106 | } | |
107 | ||
108 | sucomp( p ) register NODE *p; { | |
109 | ||
110 | /* set the su field in the node to the sethi-ullman | |
111 | number, or local equivalent */ | |
112 | ||
113 | register o, ty, sul, sur; | |
114 | register nr; | |
115 | ||
116 | ty = optype( o=p->op); | |
117 | nr = szty( p->type ); | |
118 | p->su = 0; | |
119 | ||
120 | if( ty == LTYPE ) { | |
121 | if( p->type==FLOAT ) p->su = 1; | |
122 | return; | |
123 | } | |
124 | else if( ty == UTYPE ){ | |
125 | switch( o ) { | |
126 | case UNARY CALL: | |
127 | case UNARY STCALL: | |
128 | p->su = fregs; /* all regs needed */ | |
129 | return; | |
130 | ||
131 | case UNARY MUL: | |
132 | if( shumul( p->left ) ) return; | |
133 | ||
134 | default: | |
135 | p->su = max( p->left->su, nr); | |
136 | return; | |
137 | } | |
138 | } | |
139 | ||
140 | ||
141 | /* If rhs needs n, lhs needs m, regular su computation */ | |
142 | ||
143 | sul = p->left->su; | |
144 | sur = p->right->su; | |
145 | ||
146 | if( o == ASSIGN ){ | |
147 | asop: /* also used for +=, etc., to memory */ | |
148 | if( sul==0 ){ | |
149 | /* don't need to worry about the left side */ | |
150 | p->su = max( sur, nr ); | |
151 | } | |
152 | else { | |
153 | /* right, left address, op */ | |
154 | if( sur == 0 ){ | |
155 | /* just get the lhs address into a register, and mov */ | |
156 | /* the `nr' covers the case where value is in reg afterwards */ | |
157 | p->su = max( sul, nr ); | |
158 | } | |
159 | else { | |
160 | /* right, left address, op */ | |
161 | p->su = max( sur, nr+sul ); | |
162 | } | |
163 | } | |
164 | return; | |
165 | } | |
166 | ||
167 | if( o == CALL || o == STCALL ){ | |
168 | /* in effect, takes all free registers */ | |
169 | p->su = fregs; | |
170 | return; | |
171 | } | |
172 | ||
173 | if( o == STASG ){ | |
174 | /* right, then left */ | |
175 | p->su = max( max( sul+nr, sur), fregs ); | |
176 | return; | |
177 | } | |
178 | ||
179 | if( logop(o) ){ | |
180 | /* do the harder side, then the easier side, into registers */ | |
181 | /* left then right, max(sul,sur+nr) */ | |
182 | /* right then left, max(sur,sul+nr) */ | |
183 | /* to hold both sides in regs: nr+nr */ | |
184 | nr = szty( p->left->type ); | |
185 | sul = zum( p->left, ZLONG|ZCHAR|ZFLOAT ); | |
186 | sur = zum( p->right, ZLONG|ZCHAR|ZFLOAT ); | |
187 | p->su = min( max(sul,sur+nr), max(sur,sul+nr) ); | |
188 | return; | |
189 | } | |
190 | ||
191 | if( asgop(o) ){ | |
192 | /* computed by doing right, doing left address, doing left, op, and store */ | |
193 | switch( o ) { | |
194 | case INCR: | |
195 | case DECR: | |
196 | /* do as binary op */ | |
197 | break; | |
198 | ||
199 | case ASG DIV: | |
200 | case ASG MOD: | |
201 | case ASG MUL: | |
202 | if( p->type!=FLOAT && p->type!=DOUBLE ) nr = fregs; | |
203 | goto gencase; | |
204 | ||
205 | case ASG PLUS: | |
206 | case ASG MINUS: | |
207 | case ASG AND: /* really bic */ | |
208 | case ASG OR: | |
209 | if( p->type == INT || p->type == UNSIGNED || ISPTR(p->type) ) goto asop; | |
210 | ||
211 | gencase: | |
212 | default: | |
213 | sur = zum( p->right, ZCHAR|ZLONG|ZFLOAT ); | |
214 | if( sur == 0 ){ /* easy case: if addressable, | |
215 | do left value, op, store */ | |
216 | if( sul == 0 ) p->su = nr; | |
217 | /* harder: left adr, val, op, store */ | |
218 | else p->su = max( sul, nr+1 ); | |
219 | } | |
220 | else { /* do right, left adr, left value, op, store */ | |
221 | if( sul == 0 ){ /* right, left value, op, store */ | |
222 | p->su = max( sur, nr+nr ); | |
223 | } | |
224 | else { | |
225 | p->su = max( sur, max( sul+nr, 1+nr+nr ) ); | |
226 | } | |
227 | } | |
228 | return; | |
229 | } | |
230 | } | |
231 | ||
232 | switch( o ){ | |
233 | case ANDAND: | |
234 | case OROR: | |
235 | case QUEST: | |
236 | case COLON: | |
237 | case COMOP: | |
238 | p->su = max( max(sul,sur), nr); | |
239 | return; | |
240 | } | |
241 | ||
242 | if( ( o==DIV || o==MOD || o==MUL ) | |
243 | && p->type!=FLOAT && p->type!=DOUBLE ) nr = fregs; | |
244 | if( o==PLUS || o==MUL || o==OR || o==ER ){ | |
245 | /* AND is ruined by the hardware */ | |
246 | /* permute: get the harder on the left */ | |
247 | ||
248 | register rt, lt; | |
249 | ||
250 | if( istnode( p->left ) || sul > sur ) goto noswap; /* don't do it! */ | |
251 | ||
252 | /* look for a funny type on the left, one on the right */ | |
253 | ||
254 | ||
255 | lt = p->left->type; | |
256 | rt = p->right->type; | |
257 | ||
258 | if( rt == FLOAT && lt == DOUBLE ) goto swap; | |
259 | ||
260 | if( (rt==CHAR||rt==UCHAR) && (lt==INT||lt==UNSIGNED||ISPTR(lt)) ) goto swap; | |
261 | ||
262 | if( lt==LONG || lt==ULONG ){ | |
263 | if( rt==LONG || rt==ULONG ){ | |
264 | /* if one is a STARNM, swap */ | |
265 | if( p->left->op == UNARY MUL && sul==0 ) goto noswap; | |
266 | if( p->right->op == UNARY MUL && p->left->op != UNARY MUL ) goto swap; | |
267 | goto noswap; | |
268 | } | |
269 | else if( p->left->op == UNARY MUL && sul == 0 ) goto noswap; | |
270 | else goto swap; /* put long on right, unless STARNM */ | |
271 | } | |
272 | ||
273 | /* we are finished with the type stuff now; if one is addressable, | |
274 | put it on the right */ | |
275 | if( sul == 0 && sur != 0 ){ | |
276 | ||
277 | NODE *s; | |
278 | int ssu; | |
279 | ||
280 | swap: | |
281 | ssu = sul; sul = sur; sur = ssu; | |
282 | s = p->left; p->left = p->right; p->right = s; | |
283 | } | |
284 | } | |
285 | noswap: | |
286 | ||
287 | sur = zum( p->right, ZCHAR|ZLONG|ZFLOAT ); | |
288 | if( sur == 0 ){ | |
289 | /* get left value into a register, do op */ | |
290 | p->su = max( nr, sul ); | |
291 | } | |
292 | else { | |
293 | /* do harder into a register, then easier */ | |
294 | p->su = max( nr+nr, min( max( sul, nr+sur ), max( sur, nr+sul ) ) ); | |
295 | } | |
296 | } | |
297 | ||
298 | int radebug = 0; | |
299 | ||
300 | mkrall( p, r ) register NODE *p; { | |
301 | /* insure that the use of p gets done with register r; in effect, */ | |
302 | /* simulate offstar */ | |
303 | ||
304 | if( p->op == FLD ){ | |
305 | p->left->rall = p->rall; | |
306 | p = p->left; | |
307 | } | |
308 | ||
309 | if( p->op != UNARY MUL ) return; /* no more to do */ | |
310 | p = p->left; | |
311 | if( p->op == UNARY MUL ){ | |
312 | p->rall = r; | |
313 | p = p->left; | |
314 | } | |
315 | if( p->op == PLUS && p->right->op == ICON ){ | |
316 | p->rall = r; | |
317 | p = p->left; | |
318 | } | |
319 | rallo( p, r ); | |
320 | } | |
321 | ||
322 | rallo( p, down ) register NODE *p; { | |
323 | /* do register allocation */ | |
324 | register o, type, down1, down2, ty; | |
325 | ||
326 | if( radebug ) printf( "rallo( %o, %o )\n", p, down ); | |
327 | ||
328 | down2 = NOPREF; | |
329 | p->rall = down; | |
330 | down1 = ( down &= ~MUSTDO ); | |
331 | ||
332 | ty = optype( o = p->op ); | |
333 | type = p->type; | |
334 | ||
335 | ||
336 | if( type == DOUBLE || type == FLOAT ){ | |
337 | if( o == FORCE ) down1 = FR0|MUSTDO; | |
338 | ++fltused; | |
339 | } | |
340 | else switch( o ) { | |
341 | case ASSIGN: | |
342 | down1 = NOPREF; | |
343 | down2 = down; | |
344 | break; | |
345 | ||
346 | case ASG MUL: | |
347 | case ASG DIV: | |
348 | case ASG MOD: | |
349 | /* keep the addresses out of the hair of (r0,r1) */ | |
350 | if(fregs == 2 ){ | |
351 | /* lhs in (r0,r1), nothing else matters */ | |
352 | down1 = R1|MUSTDO; | |
353 | down2 = NOPREF; | |
354 | break; | |
355 | } | |
356 | /* at least 3 regs free */ | |
357 | /* compute lhs in (r0,r1), address of left in r2 */ | |
358 | p->left->rall = R1|MUSTDO; | |
359 | mkrall( p->left, R2|MUSTDO ); | |
360 | /* now, deal with right */ | |
361 | if( fregs == 3 ) rallo( p->right, NOPREF ); | |
362 | else { | |
363 | /* put address of long or value here */ | |
364 | p->right->rall = R3|MUSTDO; | |
365 | mkrall( p->right, R3|MUSTDO ); | |
366 | } | |
367 | return; | |
368 | ||
369 | case MUL: | |
370 | case DIV: | |
371 | case MOD: | |
372 | rallo( p->left, R1|MUSTDO ); | |
373 | ||
374 | if( fregs == 2 ){ | |
375 | rallo( p->right, NOPREF ); | |
376 | return; | |
377 | } | |
378 | /* compute addresses, stay away from (r0,r1) */ | |
379 | ||
380 | p->right->rall = (fregs==3) ? R2|MUSTDO : R3|MUSTDO ; | |
381 | mkrall( p->right, R2|MUSTDO ); | |
382 | return; | |
383 | ||
384 | case CALL: | |
385 | case STASG: | |
386 | case EQ: | |
387 | case NE: | |
388 | case GT: | |
389 | case GE: | |
390 | case LT: | |
391 | case LE: | |
392 | case NOT: | |
393 | case ANDAND: | |
394 | case OROR: | |
395 | down1 = NOPREF; | |
396 | break; | |
397 | ||
398 | case FORCE: | |
399 | down1 = R0|MUSTDO; | |
400 | break; | |
401 | ||
402 | } | |
403 | ||
404 | if( ty != LTYPE ) rallo( p->left, down1 ); | |
405 | if( ty == BITYPE ) rallo( p->right, down2 ); | |
406 | ||
407 | } | |
408 | ||
409 | offstar( p ) register NODE *p; { | |
410 | /* handle indirections */ | |
411 | ||
412 | if( p->op == UNARY MUL ) p = p->left; | |
413 | ||
414 | if( p->op == PLUS || p->op == MINUS ){ | |
415 | if( p->right->op == ICON ){ | |
416 | order( p->left , INTAREG|INAREG ); | |
417 | return; | |
418 | } | |
419 | } | |
420 | order( p, INTAREG|INAREG ); | |
421 | } | |
422 | ||
423 | setincr( p ) NODE *p; { | |
424 | return( 0 ); /* for the moment, don't bother */ | |
425 | } | |
426 | ||
427 | niceuty( p ) register NODE *p; { | |
428 | register TWORD t; | |
429 | ||
430 | return( p->op == UNARY MUL && (t=p->type)!=CHAR && | |
431 | t!= UCHAR && t!= FLOAT && | |
432 | shumul( p->left) != STARREG ); | |
433 | } | |
434 | setbin( p ) register NODE *p; { | |
435 | register NODE *r, *l; | |
436 | ||
437 | r = p->right; | |
438 | l = p->left; | |
439 | ||
440 | if( p->right->su == 0 ){ /* rhs is addressable */ | |
441 | if( logop( p->op ) ){ | |
442 | if( l->op == UNARY MUL && l->type != FLOAT && shumul( l->left ) != STARREG ) offstar( l->left ); | |
443 | else order( l, INAREG|INTAREG|INBREG|INTBREG|INTEMP ); | |
444 | return( 1 ); | |
445 | } | |
446 | if( !istnode( l ) ){ | |
447 | order( l, INTAREG|INTBREG ); | |
448 | return( 1 ); | |
449 | } | |
450 | /* rewrite */ | |
451 | return( 0 ); | |
452 | } | |
453 | /* now, rhs is complicated: must do both sides into registers */ | |
454 | /* do the harder side first */ | |
455 | ||
456 | if( logop( p->op ) ){ | |
457 | /* relational: do both sides into regs if need be */ | |
458 | ||
459 | if( r->su > l->su ){ | |
460 | if( niceuty(r) ){ | |
461 | offstar( r->left ); | |
462 | return( 1 ); | |
463 | } | |
464 | else if( !istnode( r ) ){ | |
465 | order( r, INTAREG|INAREG|INTBREG|INBREG|INTEMP ); | |
466 | return( 1 ); | |
467 | } | |
468 | } | |
469 | if( niceuty(l) ){ | |
470 | offstar( l->left ); | |
471 | return( 1 ); | |
472 | } | |
473 | else if( niceuty(r) ){ | |
474 | offstar( r->left ); | |
475 | return( 1 ); | |
476 | } | |
477 | else if( !istnode( l ) ){ | |
478 | order( l, INTAREG|INAREG|INTBREG|INBREG|INTEMP ); | |
479 | return( 1 ); | |
480 | } | |
481 | if( !istnode( r ) ){ | |
482 | order( r, INTAREG|INAREG|INTBREG|INBREG|INTEMP ); | |
483 | return( 1 ); | |
484 | } | |
485 | cerror( "setbin can't deal with %s", opst[p->op] ); | |
486 | } | |
487 | ||
488 | /* ordinary operator */ | |
489 | ||
490 | if( !istnode(r) && r->su > l->su ){ | |
491 | /* if there is a chance of making it addressable, try it... */ | |
492 | if( niceuty(r) ){ | |
493 | offstar( r->left ); | |
494 | return( 1 ); /* hopefully, it is addressable by now */ | |
495 | } | |
496 | order( r, INTAREG|INAREG|INTBREG|INBREG|INTEMP ); /* anything goes on rhs */ | |
497 | return( 1 ); | |
498 | } | |
499 | else { | |
500 | if( !istnode( l ) ){ | |
501 | order( l, INTAREG|INTBREG ); | |
502 | return( 1 ); | |
503 | } | |
504 | /* rewrite */ | |
505 | return( 0 ); | |
506 | } | |
507 | } | |
508 | ||
509 | setstr( p ) register NODE *p; { /* structure assignment */ | |
510 | if( p->right->op != REG ){ | |
511 | order( p->right, INTAREG ); | |
512 | return(1); | |
513 | } | |
514 | p = p->left; | |
515 | if( p->op != NAME && p->op != OREG ){ | |
516 | if( p->op != UNARY MUL ) cerror( "bad setstr" ); | |
517 | order( p->left, INTAREG ); | |
518 | return( 1 ); | |
519 | } | |
520 | return( 0 ); | |
521 | } | |
522 | ||
523 | setasg( p ) register NODE *p; { | |
524 | /* setup for assignment operator */ | |
525 | ||
526 | if( p->right->su != 0 && p->right->op != REG ) { | |
527 | if( p->right->op == UNARY MUL ) | |
528 | offstar( p->right->left ); | |
529 | else | |
530 | order( p->right, INAREG|INBREG|SOREG|SNAME|SCON ); | |
531 | return(1); | |
532 | } | |
533 | if( p->right->op != REG && ( p->type == FLOAT || p->type == DOUBLE ) ) { | |
534 | order( p->right, INBREG ); | |
535 | return(1); | |
536 | } | |
537 | if( p->left->op == UNARY MUL && !tshape( p->left, STARREG|STARNM ) ){ | |
538 | offstar( p->left->left ); | |
539 | return(1); | |
540 | } | |
541 | if( p->left->op == FLD && p->left->left->op == UNARY MUL ){ | |
542 | offstar( p->left->left->left ); | |
543 | return(1); | |
544 | } | |
545 | /* if things are really strange, get rhs into a register */ | |
546 | if( p->right->op != REG ){ | |
547 | order( p->right, INAREG|INBREG ); | |
548 | return( 1 ); | |
549 | } | |
550 | return(0); | |
551 | } | |
552 | ||
553 | setasop( p ) register NODE *p; { | |
554 | /* setup for =ops */ | |
555 | register sul, sur; | |
556 | register NODE *q, *p2; | |
557 | ||
558 | sul = p->left->su; | |
559 | sur = p->right->su; | |
560 | ||
561 | switch( p->op ){ | |
562 | ||
563 | case ASG PLUS: | |
564 | case ASG OR: | |
565 | case ASG MINUS: | |
566 | if( p->type != INT && p->type != UNSIGNED && !ISPTR(p->type) ) break; | |
567 | if( p->right->type == CHAR || p->right->type == UCHAR ){ | |
568 | order( p->right, INAREG ); | |
569 | return( 1 ); | |
570 | } | |
571 | break; | |
572 | ||
573 | case ASG ER: | |
574 | if( sul == 0 || p->left->op == REG ){ | |
575 | if( p->left->type == CHAR || p->left->type == UCHAR ) goto rew; /* rewrite */ | |
576 | order( p->right, INAREG|INBREG ); | |
577 | return( 1 ); | |
578 | } | |
579 | goto leftadr; | |
580 | } | |
581 | ||
582 | if( sur == 0 ){ | |
583 | ||
584 | leftadr: | |
585 | /* easy case: if addressable, do left value, op, store */ | |
586 | if( sul == 0 ) goto rew; /* rewrite */ | |
587 | ||
588 | /* harder; make aleft address, val, op, and store */ | |
589 | ||
590 | if( p->left->op == UNARY MUL ){ | |
591 | offstar( p->left->left ); | |
592 | return( 1 ); | |
593 | } | |
594 | if( p->left->op == FLD && p->left->left->op == UNARY MUL ){ | |
595 | offstar( p->left->left->left ); | |
596 | return( 1 ); | |
597 | } | |
598 | rew: /* rewrite, accounting for autoincrement and autodecrement */ | |
599 | ||
600 | q = p->left; | |
601 | if( q->op == FLD ) q = q->left; | |
602 | if( q->op != UNARY MUL || shumul(q->left) != STARREG ) return(0); /* let reader.c do it */ | |
603 | ||
604 | /* mimic code from reader.c */ | |
605 | ||
606 | p2 = tcopy( p ); | |
607 | p->op = ASSIGN; | |
608 | reclaim( p->right, RNULL, 0 ); | |
609 | p->right = p2; | |
610 | ||
611 | /* now, zap INCR on right, ASG MINUS on left */ | |
612 | ||
613 | if( q->left->op == INCR ){ | |
614 | q = p2->left; | |
615 | if( q->op == FLD ) q = q->left; | |
616 | if( q->left->op != INCR ) cerror( "bad incr rewrite" ); | |
617 | } | |
618 | else if( q->left->op != ASG MINUS ) cerror( " bad -= rewrite" ); | |
619 | ||
620 | q->left->right->op = FREE; | |
621 | q->left->op = FREE; | |
622 | q->left = q->left->left; | |
623 | ||
624 | /* now, resume reader.c rewriting code */ | |
625 | ||
626 | canon(p); | |
627 | rallo( p, p->rall ); | |
628 | order( p2->left, INTBREG|INTAREG ); | |
629 | order( p2, INTBREG|INTAREG ); | |
630 | return( 1 ); | |
631 | } | |
632 | ||
633 | /* harder case: do right, left address, left value, op, store */ | |
634 | ||
635 | if( p->right->op == UNARY MUL ){ | |
636 | offstar( p->right->left ); | |
637 | return( 1 ); | |
638 | } | |
639 | /* sur> 0, since otherwise, done above */ | |
640 | if( p->right->op == REG ) goto leftadr; /* make lhs addressable */ | |
641 | order( p->right, INAREG|INBREG ); | |
642 | return( 1 ); | |
643 | } | |
644 | ||
645 | int crslab = 10000; | |
646 | ||
647 | getlab(){ | |
648 | return( crslab++ ); | |
649 | } | |
650 | ||
651 | deflab( l ){ | |
652 | printf( "L%d:\n", l ); | |
653 | } | |
654 | ||
655 | genargs( p) register NODE *p; { | |
656 | register size; | |
657 | ||
658 | /* generate code for the arguments */ | |
659 | ||
660 | /* first, do the arguments on the right (last->first) */ | |
661 | while( p->op == CM ){ | |
662 | genargs( p->right ); | |
663 | p->op = FREE; | |
664 | p = p->left; | |
665 | } | |
666 | ||
667 | if( p->op == STARG ){ /* structure valued argument */ | |
668 | ||
669 | size = p->stsize; | |
670 | if( p->left->op == ICON ){ | |
671 | /* make into a name node */ | |
672 | p->op = FREE; | |
673 | p= p->left; | |
674 | p->op = NAME; | |
675 | } | |
676 | else { | |
677 | /* make it look beautiful... */ | |
678 | p->op = UNARY MUL; | |
679 | canon( p ); /* turn it into an oreg */ | |
680 | if( p->op != OREG ){ | |
681 | offstar( p->left ); | |
682 | canon( p ); | |
683 | if( p->op != OREG ) cerror( "stuck starg" ); | |
684 | } | |
685 | } | |
686 | ||
687 | p->lval += size; /* end of structure */ | |
688 | /* put on stack backwards */ | |
689 | for( ; size>0; size -= 2 ){ | |
690 | p->lval -= 2; | |
691 | expand( p, RNOP, " mov AR,Z-\n" ); | |
692 | } | |
693 | reclaim( p, RNULL, 0 ); | |
694 | return; | |
695 | } | |
696 | ||
697 | /* ordinary case */ | |
698 | ||
699 | order( p, FORARG ); | |
700 | } | |
701 | ||
702 | argsize( p ) register NODE *p; { | |
703 | register t; | |
704 | t = 0; | |
705 | if( p->op == CM ){ | |
706 | t = argsize( p->left ); | |
707 | p = p->right; | |
708 | } | |
709 | if( p->type == DOUBLE || p->type == FLOAT ){ | |
710 | SETOFF( t, 2 ); | |
711 | return( t+8 ); | |
712 | } | |
713 | else if( p->type == LONG || p->type == ULONG ) { | |
714 | SETOFF( t, 2); | |
715 | return( t+4 ); | |
716 | } | |
717 | else if( p->op == STARG ){ | |
718 | SETOFF( t, p->stalign ); /* alignment */ | |
719 | return( t + p->stsize ); /* size */ | |
720 | } | |
721 | else { | |
722 | SETOFF( t, 2 ); | |
723 | return( t+2 ); | |
724 | } | |
725 | } |