utah rcsid 1.12 87/05/02 13:58:32: Don't delete double => int conversions
[unix-history] / usr / src / old / pcc / ccom.tahoe / local2.c
CommitLineData
f2b49199 1#ifndef lint
c2c596e4 2static char sccsid[] = "@(#)local2.c 1.21 (Berkeley) %G%";
f2b49199
SL
3#endif
4
ebdd0416
SL
5# include "pass2.h"
6# include <ctype.h>
895241c8
SL
7
8# define putstr(s) fputs((s), stdout)
73fe5b3f 9# define ISCHAR(p) (p->in.type == UCHAR || p->in.type == CHAR)
895241c8 10
f2b49199
SL
11# ifdef FORT
12int ftlab1, ftlab2;
13# endif
14/* a lot of the machine dependent parts of the second pass */
15
16# define BITMASK(n) ((1L<<n)-1)
17
18# ifndef ONEPASS
19where(c){
20 fprintf( stderr, "%s, line %d: ", filename, lineno );
21 }
22# endif
23
24lineid( l, fn ) char *fn; {
25 /* identify line l and file fn */
26 printf( "# line %d, file %s\n", l, fn );
27 }
28
29int ent_mask;
30
31eobl2(){
32 register OFFSZ spoff; /* offset from stack pointer */
33#ifndef FORT
34 extern int ftlab1, ftlab2;
35#endif
36
37 spoff = maxoff;
38 spoff /= SZCHAR;
39 SETOFF(spoff,4);
40#ifdef FORT
41#ifndef FLEXNAMES
42 printf( " .set .F%d,%d\n", ftnno, spoff );
43#else
44 /* SHOULD BE L%d ... ftnno but must change pc/f77 */
45 printf( " .set LF%d,%d\n", ftnno, spoff );
46#endif
47 printf( " .set LWM%d,0x%x\n", ftnno, ent_mask&0x1ffc|0x1000);
48#else
49 printf( " .set L%d,0x%x\n", ftnno, ent_mask&0x1ffc);
50 printf( "L%d:\n", ftlab1);
51 if( maxoff > AUTOINIT )
52 printf( " subl3 $%d,fp,sp\n", spoff);
53 printf( " jbr L%d\n", ftlab2);
54#endif
55 ent_mask = 0;
56 maxargs = -1;
57 }
58
59struct hoptab { int opmask; char * opstring; } ioptab[] = {
60
61 PLUS, "add",
62 MINUS, "sub",
63 MUL, "mul",
64 DIV, "div",
65 MOD, "div",
66 OR, "or",
67 ER, "xor",
68 AND, "and",
69 -1, "" };
70
71hopcode( f, o ){
72 /* output the appropriate string from the above table */
73
74 register struct hoptab *q;
75
76 if(asgop(o))
77 o = NOASG o;
78 for( q = ioptab; q->opmask>=0; ++q ){
79 if( q->opmask == o ){
80 if(f == 'E')
81 printf( "e%s", q->opstring);
82 else
83 printf( "%s%c", q->opstring, tolower(f));
84 return;
85 }
86 }
87 cerror( "no hoptab for %s", opst[o] );
88 }
89
90char *
91rnames[] = { /* keyed to register number tokens */
92
93 "r0", "r1",
94 "r2", "r3", "r4", "r5",
95 "r6", "r7", "r8", "r9", "r10", "r11",
96 "r12", "fp", "sp", "pc",
97 };
98
99/* output register name and update entry mask */
100char *
101rname(r)
102 register int r;
103{
104
105 ent_mask |= 1<<r;
106 return(rnames[r]);
107}
108
109int rstatus[] = {
110 SAREG|STAREG, SAREG|STAREG,
111 SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG,
112 SAREG, SAREG, SAREG, SAREG, SAREG, SAREG,
113 SAREG, SAREG, SAREG, SAREG,
114 };
115
116tlen(p) NODE *p;
117{
118 switch(p->in.type) {
119 case CHAR:
120 case UCHAR:
121 return(1);
122
123 case SHORT:
124 case USHORT:
125 return(2);
126
127 case DOUBLE:
128 return(8);
129
130 default:
131 return(4);
132 }
133}
134
f1824a4b
SL
135anyfloat(p, q)
136 NODE *p, *q;
137{
138 register TWORD tp, tq;
139
140 tp = p->in.type;
141 tq = q->in.type;
142 return (tp == FLOAT || tp == DOUBLE || tq == FLOAT || tq == DOUBLE);
143}
144
f2b49199
SL
145prtype(n) NODE *n;
146{
147 switch (n->in.type)
148 {
149
150 case DOUBLE:
895241c8 151 putchar('d');
f2b49199
SL
152 return;
153
154 case FLOAT:
895241c8 155 putchar('f');
f2b49199
SL
156 return;
157
158 case INT:
159 case UNSIGNED:
895241c8 160 putchar('l');
f2b49199
SL
161 return;
162
163 case SHORT:
164 case USHORT:
895241c8 165 putchar('w');
f2b49199
SL
166 return;
167
168 case CHAR:
169 case UCHAR:
895241c8 170 putchar('b');
f2b49199
SL
171 return;
172
173 default:
174 if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type");
175 else {
895241c8 176 putchar('l');
f2b49199
SL
177 return;
178 }
179 }
180}
181
182zzzcode( p, c ) register NODE *p; {
183 register int m;
184 int val;
185 switch( c ){
186
187 case 'N': /* logical ops, turned into 0-1 */
188 /* use register given by register 1 */
189 cbgen( 0, m=getlab(), 'I' );
190 deflab( p->bn.label );
191 printf( " clrl %s\n", rname(getlr( p, '1' )->tn.rval) );
192 deflab( m );
193 return;
194
195 case 'P':
196 cbgen( p->in.op, p->bn.label, c );
197 return;
198
8acf7c89 199 case 'G': /* i *= f; asgops with int lhs and float rhs */
f2b49199 200 {
8acf7c89
DS
201 register NODE *l, *r, *s;
202 int lt, rt;
f2b49199 203
8acf7c89
DS
204 l = p->in.left;
205 r = p->in.right;
206 s = talloc();
207 rt = r->in.type;
208 lt = l->in.type;
209
210 if (lt != INT && lt != UNSIGNED) {
211 s->in.op = SCONV;
212 s->in.left = l;
213 s->in.type = ISUNSIGNED(lt) ? UNSIGNED : INT;
214 zzzcode(s, 'U');
215 putstr("\n\t");
216 }
f2b49199 217
8acf7c89
DS
218 if (ISUNSIGNED(lt)) {
219 s->in.op = SCONV;
220 s->in.left = lt == UNSIGNED ? l : resc;
221 s->in.type = rt;
222 unsigned_to_float(s);
223 } else {
224 putstr("cvl");
225 prtype(r);
226 putchar('\t');
227 adrput(lt == INT ? l : resc);
f2b49199 228 }
8acf7c89
DS
229 putstr("\n\t");
230
231 hopcode(rt == FLOAT ? 'F' : 'D', p->in.op);
895241c8 232 putchar('\t');
f2b49199 233 adrput(r);
8acf7c89
DS
234
235 if (ISUNSIGNED(lt)) {
236 putstr("\n\t");
237 s->in.op = SCONV;
238 s->in.left = r; /* we need only the type */
239 s->in.type = UNSIGNED;
240 float_to_unsigned(s);
241 } else {
242 putstr("\n\tcv");
243 prtype(r);
244 putstr("l\t");
245 if (lt == INT)
246 adrput(l);
247 else
248 adrput(resc);
249 }
250 if (lt != INT) {
251 putstr("\n\t");
252 s->in.op = ASSIGN;
253 s->in.left = l;
254 s->in.right = resc;
255 s->in.type = lt;
256 zzzcode(s, 'U');
257 }
258
259 s->in.op = FREE;
f2b49199
SL
260 return;
261 }
262
263 case 'B': /* get oreg value in temp register for shift */
264 {
265 register NODE *r;
266 if (xdebug) eprint(p, 0, &val, &val);
267 r = p->in.right;
268 if( tlen(r) == sizeof(int) && r->in.type != FLOAT )
895241c8 269 putstr("movl");
f2b49199 270 else {
895241c8 271 putstr(ISUNSIGNED(r->in.type) ? "movz" : "cvt");
f2b49199 272 prtype(r);
895241c8 273 putchar('l');
f2b49199
SL
274 }
275 return;
276 }
277
278 case 'C': /* num bytes pushed on arg stack */
279 {
280 extern int gc_numbytes;
281 extern int xdebug;
282
283 if (xdebug) printf("->%d<-",gc_numbytes);
284
285 printf("call%c $%d",
286 (p->in.left->in.op==ICON && gc_numbytes<60)?'f':'s',
287 gc_numbytes+4);
288 /* dont change to double (here's the only place to catch it) */
289 if(p->in.type == FLOAT)
290 rtyflg = 1;
291 return;
292 }
293
294 case 'D': /* INCR and DECR */
8acf7c89 295 zzzcode(p->in.left, 'U');
895241c8 296 putstr("\n ");
f2b49199
SL
297
298 case 'E': /* INCR and DECR, FOREFF */
299 if (p->in.right->tn.lval == 1)
300 {
895241c8 301 putstr(p->in.op == INCR ? "inc" : "dec");
f2b49199 302 prtype(p->in.left);
895241c8 303 putchar('\t');
f2b49199
SL
304 adrput(p->in.left);
305 return;
306 }
895241c8 307 putstr(p->in.op == INCR ? "add" : "sub");
f2b49199 308 prtype(p->in.left);
895241c8 309 putstr("2 ");
f2b49199 310 adrput(p->in.right);
895241c8 311 putchar(',');
f2b49199
SL
312 adrput(p->in.left);
313 return;
314
315 case 'F': /* masked constant for fields */
7412b41b 316 printf(ACONFMT, (p->in.right->tn.lval&((1<<fldsz)-1))<<fldshf);
f2b49199
SL
317 return;
318
319 case 'H': /* opcode for shift */
320 if(p->in.op == LS || p->in.op == ASG LS)
895241c8 321 putstr("shll");
f2b49199 322 else if(ISUNSIGNED(p->in.left->in.type))
895241c8 323 putstr("shrl");
f2b49199 324 else
895241c8 325 putstr("shar");
f2b49199
SL
326 return;
327
328 case 'L': /* type of left operand */
329 case 'R': /* type of right operand */
330 {
331 register NODE *n;
332 extern int xdebug;
333
334 n = getlr ( p, c);
335 if (xdebug) printf("->%d<-", n->in.type);
336
337 prtype(n);
338 return;
339 }
340
f1824a4b 341 case 'M': { /* initiate ediv for mod and unsigned div */
f2b49199
SL
342 register char *r;
343 m = getlr(p, '1')->tn.rval;
344 r = rname(m);
345 printf("\tclrl\t%s\n\tmovl\t", r);
346 adrput(p->in.left);
347 printf(",%s\n", rname(m+1));
348 if(!ISUNSIGNED(p->in.type)) { /* should be MOD */
349 m = getlab();
350 printf("\tjgeq\tL%d\n\tmnegl\t$1,%s\n", m, r);
351 deflab(m);
352 }
f2b49199 353 return;
f1824a4b 354 }
f2b49199 355
f1824a4b
SL
356 case 'T': { /* rounded structure length for arguments */
357 int size = p->stn.stsize;
f2b49199
SL
358 SETOFF( size, 4);
359 printf("movab -%d(sp),sp", size);
360 return;
f1824a4b 361 }
f2b49199
SL
362
363 case 'S': /* structure assignment */
1d43595d
SL
364 stasg(p);
365 break;
f2b49199 366
73fe5b3f
SL
367 case 'X': /* multiplication for short and char */
368 if (ISUNSIGNED(p->in.left->in.type))
369 printf("\tmovz");
370 else
371 printf("\tcvt");
372 zzzcode(p, 'L');
373 printf("l\t");
374 adrput(p->in.left);
375 printf(",");
376 adrput(&resc[0]);
377 printf("\n");
378 if (ISUNSIGNED(p->in.right->in.type))
379 printf("\tmovz");
380 else
381 printf("\tcvt");
382 zzzcode(p, 'R');
383 printf("l\t");
384 adrput(p->in.right);
385 printf(",");
386 adrput(&resc[1]);
387 printf("\n");
388 return;
389
f1824a4b
SL
390 case 'U': /* SCONV */
391 case 'V': /* SCONV with FORCC */
392 sconv(p, c == 'V');
393 break;
394
7999919c
DS
395 case 'W': { /* SCONV or ASSIGN float/double => unsigned */
396 NODE *src = p->in.op == SCONV ? p->in.left : p->in.right;
397
8acf7c89 398 putstr("ld");
7999919c 399 prtype(src);
8acf7c89 400 putchar('\t');
7999919c 401 adrput(src);
8acf7c89
DS
402 putstr("\n\t");
403 float_to_unsigned(p);
404 break;
7999919c 405 }
8acf7c89 406
7999919c 407 case 'Y': /* SCONV or ASSIGN unsigned => float/double */
8acf7c89
DS
408 unsigned_to_float(p); /* stores into accumulator */
409 putstr("\n\tst");
410 prtype(p);
411 putchar('\t');
7999919c
DS
412 if (p->in.op == SCONV)
413 adrput(resc);
414 else
415 adrput(p->in.left);
416 rtyflg = 1;
8acf7c89
DS
417 break;
418
f1824a4b
SL
419 case 'Z':
420 p = p->in.right;
421 switch (p->in.type) {
422 case SHORT: {
423 short w = p->tn.lval;
424 p->tn.lval = w;
425 break;
426 }
427 case CHAR: {
428 char c = p->tn.lval;
429 p->tn.lval = c;
430 break;
431 }
432 }
433 printf("$%d", p->tn.lval);
434 break;
435
1d43595d
SL
436 default:
437 cerror( "illegal zzzcode" );
1d43595d 438 }
f1824a4b 439}
f2b49199 440
1d43595d 441#define MOVB(dst, src, off) { \
895241c8 442 putstr("\tmovb\t"); upput(src, off); putchar(','); \
1d43595d
SL
443 upput(dst, off); putchar('\n'); \
444}
445#define MOVW(dst, src, off) { \
895241c8 446 putstr("\tmovw\t"); upput(src, off); putchar(','); \
1d43595d
SL
447 upput(dst, off); putchar('\n'); \
448}
449#define MOVL(dst, src, off) { \
895241c8 450 putstr("\tmovl\t"); upput(src, off); putchar(','); \
1d43595d
SL
451 upput(dst, off); putchar('\n'); \
452}
453/*
454 * Generate code for a structure assignment.
455 */
456stasg(p)
457 register NODE *p;
458{
459 register NODE *l, *r;
460 register int size;
461
462 switch (p->in.op) {
463 case STASG: /* regular assignment */
464 l = p->in.left;
465 r = p->in.right;
466 break;
467 case STARG: /* place arg on the stack */
468 l = getlr(p, '3');
469 r = p->in.left;
470 break;
471 default:
472 cerror("STASG bad");
473 /*NOTREACHED*/
474 }
475 /*
476 * Pun source for use in code generation.
477 */
478 switch (r->in.op) {
479 case ICON:
480 r->in.op = NAME;
481 break;
482 case REG:
483 r->in.op = OREG;
484 break;
485 default:
486 cerror( "STASG-r" );
487 /*NOTREACHED*/
488 }
489 size = p->stn.stsize;
490 if (size <= 0 || size > 65535)
491 cerror("structure size out of range");
492 /*
493 * Generate optimized code based on structure size
494 * and alignment properties....
495 */
496 switch (size) {
497
498 case 1:
895241c8 499 putstr("\tmovb\t");
1d43595d
SL
500 optimized:
501 adrput(r);
895241c8 502 putchar(',');
1d43595d 503 adrput(l);
895241c8 504 putchar('\n');
1d43595d
SL
505 break;
506
507 case 2:
508 if (p->stn.stalign != 2) {
509 MOVB(l, r, SZCHAR);
895241c8 510 putstr("\tmovb\t");
1d43595d 511 } else
895241c8 512 putstr("\tmovw\t");
1d43595d
SL
513 goto optimized;
514
515 case 4:
516 if (p->stn.stalign != 4) {
517 if (p->stn.stalign != 2) {
518 MOVB(l, r, 3*SZCHAR);
519 MOVB(l, r, 2*SZCHAR);
520 MOVB(l, r, 1*SZCHAR);
895241c8 521 putstr("\tmovb\t");
1d43595d
SL
522 } else {
523 MOVW(l, r, SZSHORT);
895241c8 524 putstr("\tmovw\t");
f2b49199 525 }
1d43595d 526 } else
895241c8 527 putstr("\tmovl\t");
1d43595d
SL
528 goto optimized;
529
530 case 6:
531 if (p->stn.stalign != 2)
532 goto movblk;
533 MOVW(l, r, 2*SZSHORT);
534 MOVW(l, r, 1*SZSHORT);
895241c8 535 putstr("\tmovw\t");
1d43595d
SL
536 goto optimized;
537
538 case 8:
539 if (p->stn.stalign == 4) {
540 MOVL(l, r, SZLONG);
895241c8 541 putstr("\tmovl\t");
1d43595d
SL
542 goto optimized;
543 }
544 /* fall thru...*/
f2b49199 545
1d43595d
SL
546 default:
547 movblk:
548 /*
549 * Can we ever get a register conflict with R1 here?
550 */
895241c8 551 putstr("\tmovab\t");
1d43595d 552 adrput(l);
895241c8 553 putstr(",r1\n\tmovab\t");
1d43595d
SL
554 adrput(r);
555 printf(",r0\n\tmovl\t$%d,r2\n\tmovblk\n", size);
556 rname(R2);
f2b49199 557 break;
1d43595d
SL
558 }
559 /*
560 * Reverse above pun for reclaim.
561 */
562 if (r->in.op == NAME)
563 r->in.op = ICON;
564 else if (r->in.op == OREG)
565 r->in.op = REG;
566}
f2b49199 567
1d43595d
SL
568/*
569 * Output the address of the second item in the
570 * pair pointed to by p.
571 */
572upput(p, size)
573 register NODE *p;
574{
575 CONSZ save;
576
577 if (p->in.op == FLD)
578 p = p->in.left;
579 switch (p->in.op) {
580
581 case NAME:
582 case OREG:
583 save = p->tn.lval;
584 p->tn.lval += size/SZCHAR;
585 adrput(p);
586 p->tn.lval = save;
587 break;
588
589 case REG:
590 if (size == SZLONG) {
895241c8 591 putstr(rname(p->tn.rval+1));
1d43595d 592 break;
f2b49199 593 }
1d43595d
SL
594 /* fall thru... */
595
596 default:
597 cerror("illegal upper address op %s size %d",
598 opst[p->tn.op], size);
599 /*NOTREACHED*/
f2b49199 600 }
1d43595d 601}
f2b49199 602
8acf7c89
DS
603/*
604 * Convert a float or double in the accumulator into an unsigned int.
605 * Unlike the vax, the tahoe stores 0 into the destination
606 * on a conversion of > 2 ** 31, so we compensate.
607 */
608float_to_unsigned(p)
609 NODE *p;
610{
611 register NODE *l = p->in.left;
612 int label1 = getlab();
613 int label2 = getlab();
614 int label3 = getlab();
7999919c
DS
615 NODE *src, *dst;
616
617 if (p->in.op == SCONV) {
618 src = p->in.left;
619 dst = resc;
620 } else {
621 src = p->in.right;
622 dst = p->in.left;
623 }
8acf7c89
DS
624
625 printf(".data\n\t.align\t2\nL%d:\n\t.long\t0x50000000", label1);
7999919c
DS
626 if (src->in.type == DOUBLE)
627 putstr(", 0x00000000 # .double");
628 else
629 putstr(" # .float");
630 putstr(" 2147483648\n\t.text\n\tcmp");
631 prtype(src);
8acf7c89 632 printf("\tL%d\n\tjlss\tL%d\n\tsub", label1, label2);
7999919c 633 prtype(src);
8acf7c89 634 printf("\tL%d\n\tcv", label1);
7999919c 635 prtype(src);
8acf7c89 636 putstr("l\t");
7999919c 637 adrput(dst);
8acf7c89 638 putstr("\n\taddl2\t$-2147483648,");
7999919c 639 adrput(dst);
8acf7c89 640 printf("\n\tjbr\tL%d\nL%d:\n\tcv", label3, label2);
7999919c 641 prtype(src);
8acf7c89 642 putstr("l\t");
7999919c 643 adrput(dst);
8acf7c89
DS
644 printf("\nL%d:", label3);
645}
646
647/*
648 * Convert an unsigned int into a float or double, leaving the result
649 * in the accumulator.
650 */
651unsigned_to_float(p)
652 register NODE *p;
653{
654 int label1 = getlab();
655 int label2 = getlab();
7999919c
DS
656 NODE *src, *dst;
657
658 if (p->in.op == SCONV) {
659 src = p->in.left;
660 dst = resc;
661 } else {
662 src = p->in.right;
663 dst = p->in.left;
664 }
8acf7c89
DS
665
666 printf(".data\n\t.align\t2\nL%d:\n\t.long\t0x50800000", label2);
667 if (p->in.type == DOUBLE)
7999919c
DS
668 putstr(", 0x00000000 # .double");
669 else
670 putstr(" # .float");
671 putstr(" 4294967296\n\t.text\n\tmovl\t");
672 adrput(src);
8acf7c89 673 putchar(',');
7999919c 674 adrput(dst);
8acf7c89
DS
675 putstr("\n\tcvl");
676 prtype(p);
677 putchar('\t');
7999919c
DS
678 adrput(dst);
679 printf("\n\tjgeq\tL%d\n\tadd", label1);
680 prtype(p);
681 printf("\tL%d\nL%d:", label2, label1);
8acf7c89
DS
682}
683
26ab1ae0
DS
684/*
685 * Prlen() is a cheap prtype()...
686 */
687static char convtab[SZINT/SZCHAR + 1] = {
688 '?', 'b', 'w', '?', 'l'
689};
690#define prlen(len) putchar(convtab[len])
691
692
52b983f1
DS
693/*
694 * Generate code for integral scalar conversions.
26ab1ae0
DS
695 * Some of this code is designed to work around a tahoe misfeature
696 * that causes sign- and zero- extension to be defeated in
697 * certain circumstances.
698 * Basically if the source operand of a CVT or MOVZ instruction is
699 * shorter than the destination, and the source is a register
700 * or an immediate constant, sign- and zero- extension are
701 * ignored and the high bits of the source are copied. (Note
702 * that zero-extension is not a problem for immediate
703 * constants.)
52b983f1
DS
704 */
705sconv(p, forcc)
706 NODE *p;
707 int forcc;
708{
709 register NODE *src, *dst;
710 register NODE *tmp;
711 register int srclen, dstlen;
712 int srctype, dsttype;
713 int val;
a1eb6a2f 714 int neg = 0;
52b983f1
DS
715
716 if (p->in.op == ASSIGN) {
7999919c
DS
717 src = p->in.right;
718 dst = p->in.left;
52b983f1
DS
719 dstlen = tlen(dst);
720 dsttype = dst->in.type;
7999919c
DS
721 } else if (p->in.op == SCONV) {
722 src = p->in.left;
723 dst = resc;
52b983f1
DS
724 dstlen = tlen(p);
725 dsttype = p->in.type;
7999919c
DS
726 } else /* if (p->in.op == OPLEAF) */ {
727 src = p;
728 dst = resc;
729 dstlen = SZINT/SZCHAR;
730 dsttype = ISUNSIGNED(src->in.type) ? UNSIGNED : INT;
52b983f1
DS
731 }
732
26ab1ae0
DS
733 if (src->in.op == REG) {
734 srclen = SZINT/SZCHAR;
735 srctype = ISUNSIGNED(src->in.type) ? UNSIGNED : INT;
736 } else {
737 srclen = tlen(src);
738 srctype = src->in.type;
739 }
740
a1eb6a2f 741 if (src->in.op == ICON && src->tn.name[0] == '\0') {
26ab1ae0
DS
742 if (src->tn.lval == 0) {
743 putstr("clr");
744 prtype(dst);
745 putchar('\t');
746 adrput(dst);
747 return;
748 }
749 if (dstlen < srclen) {
750 switch (dsttype) {
751 case CHAR:
752 src->tn.lval = (char) src->tn.lval;
753 break;
754 case UCHAR:
755 src->tn.lval = (unsigned char) src->tn.lval;
756 break;
757 case SHORT:
758 src->tn.lval = (short) src->tn.lval;
759 break;
760 case USHORT:
761 src->tn.lval = (unsigned short) src->tn.lval;
762 break;
763 }
764 }
765 if (dst->in.op == REG) {
766 dsttype = INT;
767 dstlen = SZINT/SZCHAR;
768 }
769 srctype = dsttype;
770 srclen = dstlen;
a1eb6a2f
DS
771 if ((val = src->tn.lval) & 1 << dstlen * SZCHAR - 1) {
772 src->tn.lval = -(val | ~((1 << dstlen * SZCHAR) - 1));
773 ++neg; /* MNEGx may be shorter */
774 }
26ab1ae0 775 }
52b983f1
DS
776
777 if (srclen < dstlen) {
778 if (srctype == CHAR && dsttype == USHORT && dst->in.op == REG) {
779 /* (unsigned short) c; => sign extend to 16 bits */
c3446016 780 putstr("cvtbl\t");
52b983f1
DS
781 adrput(src);
782 putstr(",-(sp)\n\tmovzwl\t2(sp),");
783 adrput(dst);
784 putstr("\n\tmovab\t4(sp),sp");
785 if (forcc) {
786 /* inverted test */
787 putstr("\n\tcmpl\t$0,");
788 adrput(dst);
789 }
790 return;
791 }
792 genconv(ISUNSIGNED(srctype),
793 srclen, dst->in.op == REG ? SZINT/SZCHAR : dstlen,
794 src, dst);
795 return;
796 }
797
798 if (srclen > dstlen && dst->in.op == REG) {
26ab1ae0 799 /* if dst is a register, the result must look like an int */
52b983f1
DS
800 if (src->in.op == REG) {
801 if (ISUNSIGNED(dsttype)) {
802 val = (1 << dstlen * SZCHAR) - 1;
803 if (src->tn.rval == dst->tn.rval)
804 /* conversion in place */
c3446016 805 printf("andl2\t$%#x,", val);
52b983f1 806 else {
c3446016 807 printf("andl3\t$%#x,", val);
52b983f1
DS
808 adrput(src);
809 putchar(',');
810 }
811 adrput(dst);
812 return;
813 }
26ab1ae0
DS
814 /*
815 * Sign extension in register can also be
816 * accomplished by shifts, but unfortunately
817 * shifts are extremely slow, due to the lack
818 * of a barrel shifter.
819 */
820 putstr("pushl\t");
52b983f1 821 adrput(src);
26ab1ae0
DS
822 putstr("\n\tcvt");
823 prlen(dstlen);
824 printf("l\t%d(sp),", SZINT/SZCHAR - dstlen);
52b983f1 825 adrput(dst);
26ab1ae0
DS
826 putstr("\n\tmovab\t4(sp),sp");
827 if (forcc) {
828 /* inverted test */
829 putstr("\n\tcmpl\t$0,");
830 adrput(dst);
831 }
52b983f1
DS
832 return;
833 }
834 tmp = talloc();
835 if ((src->in.op == UNARY MUL &&
836 ((src->in.left->in.op == NAME ||
837 (src->in.left->in.op == ICON)))) ||
838 (src->in.op == OREG && !R2TEST(src->tn.rval))) {
839 /* we can increment src's address & pun it */
840 *tmp = *src;
841 tmp->tn.lval += srclen - dstlen;
842 } else {
843 /* we must store src's address */
844 *tmp = *dst;
26ab1ae0
DS
845 putstr("mova");
846 prlen(srclen);
847 putchar('\t');
52b983f1
DS
848 adrput(src);
849 putchar(',');
850 adrput(tmp);
c3446016 851 putstr("\n\t");
52b983f1
DS
852 tmp->tn.op = OREG;
853 tmp->tn.lval = srclen - dstlen;
854 }
855 genconv(ISUNSIGNED(dsttype), dstlen, SZINT/SZCHAR, tmp, dst);
856 tmp->in.op = FREE;
857 return;
858 }
859
a1eb6a2f 860 genconv(neg ? -1 : ISUNSIGNED(dsttype),
52b983f1
DS
861 srclen, dst->in.op == REG ? SZINT/SZCHAR : dstlen,
862 src, dst);
863}
864
a1eb6a2f
DS
865genconv(srcflag, srclen, dstlen, src, dst)
866 int srcflag;
26ab1ae0 867 register int srclen, dstlen;
52b983f1
DS
868 NODE *src, *dst;
869{
52b983f1 870 if (srclen != dstlen) {
a1eb6a2f 871 if (srcflag > 0 && srclen < dstlen)
c3446016 872 putstr("movz");
52b983f1 873 else
c3446016 874 putstr("cvt");
26ab1ae0 875 prlen(srclen);
a1eb6a2f
DS
876 } else if (srcflag < 0)
877 putstr("mneg");
878 else
c3446016 879 putstr("mov");
26ab1ae0 880 prlen(dstlen);
52b983f1
DS
881 putchar('\t');
882 adrput(src);
883 putchar(',');
884 adrput(dst);
885}
f1824a4b 886
f2b49199
SL
887rmove( rt, rs, t ) TWORD t;{
888 printf( " movl %s,%s\n", rname(rs), rname(rt) );
889 if(t==DOUBLE)
890 printf( " movl %s,%s\n", rname(rs+1), rname(rt+1) );
891 }
892
893struct respref
894respref[] = {
895 INTAREG|INTBREG, INTAREG|INTBREG,
896 INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
897 INTEMP, INTEMP,
898 FORARG, FORARG,
899 INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
900 0, 0 };
901
902setregs(){ /* set up temporary registers */
903 fregs = 6; /* tbl- 6 free regs on Tahoe (0-5) */
904 }
905
ebdd0416 906#ifndef szty
f2b49199
SL
907szty(t) TWORD t;{ /* size, in registers, needed to hold thing of type t */
908 return(t==DOUBLE ? 2 : 1 );
909 }
ebdd0416 910#endif
f2b49199
SL
911
912rewfld( p ) NODE *p; {
913 return(1);
914 }
915
916callreg(p) NODE *p; {
917 return( R0 );
918 }
919
920base( p ) register NODE *p; {
921 register int o = p->in.op;
922
923 if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */
924 if( o==REG ) return( p->tn.rval );
925 if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
926 return( p->in.left->tn.rval );
927 if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
928 return( p->tn.rval + 0200*1 );
929 return( -1 );
930 }
931
932offset( p, tyl ) register NODE *p; int tyl; {
933
934 if(tyl > 8) return( -1 );
935 if( tyl==1 && p->in.op==REG && (p->in.type==INT || p->in.type==UNSIGNED) ) return( p->tn.rval );
936 if( (p->in.op==LS && p->in.left->in.op==REG && (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
937 (p->in.right->in.op==ICON && p->in.right->in.name[0]=='\0')
938 && (1<<p->in.right->tn.lval)==tyl))
939 return( p->in.left->tn.rval );
940 return( -1 );
941 }
942
943makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
944 register NODE *t;
945 register int i;
946 NODE *f;
947
948 p->in.op = OREG;
949 f = p->in.left; /* have to free this subtree later */
950
951 /* init base */
952 switch (q->in.op) {
953 case ICON:
954 case REG:
955 case OREG:
956 t = q;
957 break;
958
959 case MINUS:
960 q->in.right->tn.lval = -q->in.right->tn.lval;
961 case PLUS:
962 t = q->in.right;
963 break;
964
965 case UNARY MUL:
966 t = q->in.left->in.left;
967 break;
968
969 default:
970 cerror("illegal makeor2");
971 }
972
973 p->tn.lval = t->tn.lval;
974#ifndef FLEXNAMES
975 for(i=0; i<NCHNAM; ++i)
976 p->in.name[i] = t->in.name[i];
977#else
978 p->in.name = t->in.name;
979#endif
980
981 /* init offset */
982 p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
983
984 tfree(f);
985 return;
986 }
987
988canaddr( p ) NODE *p; {
989 register int o = p->in.op;
990
991 if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
992 return(0);
993 }
994
ebdd0416 995#ifndef shltype
f2b49199
SL
996shltype( o, p ) register NODE *p; {
997 return( o== REG || o == NAME || o == ICON || o == OREG || ( o==UNARY MUL && shumul(p->in.left)) );
998 }
ebdd0416 999#endif
f2b49199
SL
1000
1001flshape( p ) NODE *p; {
1002 register int o = p->in.op;
1003
1004 if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
1005 return(0);
1006 }
1007
1008shtemp( p ) register NODE *p; {
1009 if( p->in.op == STARG ) p = p->in.left;
1010 return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) );
1011 }
1012
1013shumul( p ) register NODE *p; {
1014 register int o;
1015 extern int xdebug;
1016
1017 if (xdebug) {
1018 printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op);
1019 printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval);
1020 }
1021
1022 o = p->in.op;
1023 if(( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON )
1024 && p->in.type != PTR+DOUBLE)
1025 return( STARNM );
1026
1027 return( 0 );
1028 }
1029
1030special( p, shape ) register NODE *p; {
1031 if( shape==SIREG && p->in.op == OREG && R2TEST(p->tn.rval) ) return(1);
1032 else return(0);
1033}
1034
1035adrcon( val ) CONSZ val; {
7412b41b 1036 printf(ACONFMT, val);
f2b49199
SL
1037 }
1038
1039conput( p ) register NODE *p; {
1040 switch( p->in.op ){
1041
1042 case ICON:
1043 acon( p );
1044 return;
1045
1046 case REG:
895241c8 1047 putstr(rname(p->tn.rval));
f2b49199
SL
1048 return;
1049
1050 default:
1051 cerror( "illegal conput" );
1052 }
1053 }
1054
1055insput( p ) NODE *p; {
1056 cerror( "insput" );
1057 }
1058
f2b49199
SL
1059adrput( p ) register NODE *p; {
1060 register int r;
1061 /* output an address, with offsets, from p */
1062
1063 if( p->in.op == FLD ){
1064 p = p->in.left;
1065 }
1066 switch( p->in.op ){
1067
1068 case NAME:
1069 acon( p );
1070 return;
1071
1072 case ICON:
1073 /* addressable value of the constant */
895241c8 1074 putchar('$');
f2b49199
SL
1075 acon( p );
1076 return;
1077
1078 case REG:
895241c8 1079 putstr(rname(p->tn.rval));
f2b49199
SL
1080 if(p->in.type == DOUBLE) /* for entry mask */
1081 (void) rname(p->tn.rval+1);
1082 return;
1083
1084 case OREG:
1085 r = p->tn.rval;
1086 if( R2TEST(r) ){ /* double indexing */
1087 register int flags;
1088
1089 flags = R2UPK3(r);
895241c8 1090 if( flags & 1 ) putchar('*');
f2b49199
SL
1091 if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
1092 if( R2UPK1(r) != 100) printf( "(%s)", rname(R2UPK1(r)) );
1093 printf( "[%s]", rname(R2UPK2(r)) );
1094 return;
1095 }
1096 if( r == FP && p->tn.lval > 0 ){ /* in the argument region */
1097 if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
1098 printf( CONFMT, p->tn.lval );
895241c8 1099 putstr( "(fp)" );
f2b49199
SL
1100 return;
1101 }
1102 if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
1103 printf( "(%s)", rname(p->tn.rval) );
1104 return;
1105
1106 case UNARY MUL:
1107 /* STARNM or STARREG found */
1108 if( tshape(p, STARNM) ) {
895241c8 1109 putchar( '*' );
f2b49199
SL
1110 adrput( p->in.left);
1111 }
1112 return;
1113
1114 default:
1115 cerror( "illegal address" );
1116 return;
1117
1118 }
1119
1120 }
1121
1122acon( p ) register NODE *p; { /* print out a constant */
1123
1124 if( p->in.name[0] == '\0' ){
1125 printf( CONFMT, p->tn.lval);
895241c8
SL
1126 return;
1127 } else {
f2b49199
SL
1128#ifndef FLEXNAMES
1129 printf( "%.8s", p->in.name );
1130#else
895241c8 1131 putstr(p->in.name);
f2b49199 1132#endif
895241c8
SL
1133 if (p->tn.lval != 0) {
1134 putchar('+');
1135 printf(CONFMT, p->tn.lval);
f2b49199 1136 }
895241c8 1137 }
f2b49199
SL
1138 }
1139
1140genscall( p, cookie ) register NODE *p; {
1141 /* structure valued call */
1142 return( gencall( p, cookie ) );
1143 }
1144
1145genfcall( p, cookie ) register NODE *p; {
1146 register NODE *p1;
1147 register int m;
1148 static char *funcops[6] = {
1149 "sin", "cos", "sqrt", "exp", "log", "atan"
1150 };
1151
1152 /* generate function opcodes */
1153 if(p->in.op==UNARY FORTCALL && p->in.type==FLOAT &&
1154 (p1 = p->in.left)->in.op==ICON &&
1155 p1->tn.lval==0 && p1->in.type==INCREF(FTN|FLOAT)) {
1156#ifdef FLEXNAMES
1157 p1->in.name++;
1158#else
1159 strcpy(p1->in.name, p1->in.name[1]);
1160#endif
1161 for(m=0; m<6; m++)
1162 if(!strcmp(p1->in.name, funcops[m]))
1163 break;
1164 if(m >= 6)
1165 uerror("no opcode for fortarn function %s", p1->in.name);
1166 } else
1167 uerror("illegal type of fortarn function");
1168 p1 = p->in.right;
1169 p->in.op = FORTCALL;
1170 if(!canaddr(p1))
1171 order( p1, INAREG|INBREG|SOREG|STARREG|STARNM );
1172 m = match( p, INTAREG|INTBREG );
1173 return(m != MDONE);
1174}
1175
1176/* tbl */
1177int gc_numbytes;
1178/* tbl */
1179
1180gencall( p, cookie ) register NODE *p; {
1181 /* generate the call given by p */
1182 register NODE *p1, *ptemp;
1183 register int temp, temp1;
1184 register int m;
1185
1186 if( p->in.right ) temp = argsize( p->in.right );
1187 else temp = 0;
1188
1189 if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
1190 /* set aside room for structure return */
1191
1192 if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
1193 else temp1 = temp;
1194 }
1195
1196 if( temp > maxargs ) maxargs = temp;
1197 SETOFF(temp1,4);
1198
1199 if( p->in.right ){ /* make temp node, put offset in, and generate args */
1200 ptemp = talloc();
1201 ptemp->in.op = OREG;
1202 ptemp->tn.lval = -1;
1203 ptemp->tn.rval = SP;
1204#ifndef FLEXNAMES
1205 ptemp->in.name[0] = '\0';
1206#else
1207 ptemp->in.name = "";
1208#endif
1209 ptemp->in.rall = NOPREF;
1210 ptemp->in.su = 0;
1211 genargs( p->in.right, ptemp );
1212 ptemp->in.op = FREE;
1213 }
1214
1215 p1 = p->in.left;
1216 if( p1->in.op != ICON ){
1217 if( p1->in.op != REG ){
1218 if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
1219 if( p1->in.op != NAME ){
1220 order( p1, INAREG );
1221 }
1222 }
1223 }
1224 }
1225
1226/* tbl
1227 setup gc_numbytes so reference to ZC works */
1228
1229 gc_numbytes = temp&(0x3ff);
1230
1231 p->in.op = UNARY CALL;
1232 m = match( p, INTAREG|INTBREG );
1233
1234 return(m != MDONE);
1235 }
1236
1237/* tbl */
1238char *
1239ccbranches[] = {
1240 "eql",
1241 "neq",
1242 "leq",
1243 "lss",
1244 "geq",
1245 "gtr",
1246 "lequ",
1247 "lssu",
1248 "gequ",
1249 "gtru",
1250 };
1251/* tbl */
1252
1253cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */
1254
1255 if(o != 0 && (o < EQ || o > UGT ))
1256 cerror( "bad conditional branch: %s", opst[o] );
1257 printf( " j%s L%d\n",
1258 o == 0 ? "br" : ccbranches[o-EQ], lab );
1259 }
1260
1261nextcook( p, cookie ) NODE *p; {
1262 /* we have failed to match p with cookie; try another */
1263 if( cookie == FORREW ) return( 0 ); /* hopeless! */
1264 if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
1265 if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
1266 return( FORREW );
1267 }
1268
1269lastchance( p, cook ) NODE *p; {
1270 /* forget it! */
1271 return(0);
1272 }
1273
1274optim2( p ) register NODE *p; {
1275# ifdef ONEPASS
1276 /* do local tree transformations and optimizations */
1277# define RV(p) p->in.right->tn.lval
ebdd0416 1278# define nncon(p) ((p)->in.op == ICON && (p)->in.name[0] == 0)
f1824a4b
SL
1279 register int o, i;
1280 register NODE *l, *r;
f2b49199 1281
f1824a4b
SL
1282 switch (o = p->in.op) {
1283
1284 case DIV: case ASG DIV:
1285 case MOD: case ASG MOD:
1286 /*
1287 * Change unsigned mods and divs to
1288 * logicals (mul is done in mip & c2)
1289 */
1290 if (ISUNSIGNED(p->in.left->in.type) && nncon(p->in.right) &&
1291 (i = ispow2(RV(p))) >= 0) {
1292 if (o == DIV || o == ASG DIV) {
1293 p->in.op = RS;
1294 RV(p) = i;
1295 } else {
1296 p->in.op = AND;
1297 RV(p)--;
1298 }
1299 if (asgop(o))
1300 p->in.op = ASG p->in.op;
1301 }
1302 return;
1303
1304 case SCONV:
1305 l = p->in.left;
7999919c
DS
1306 if (anyfloat(p, l)) {
1307 /* save some labor later */
1308 NODE *t = talloc();
1309
1310 if (p->in.type == UCHAR || p->in.type == USHORT) {
1311 *t = *p;
1312 t->in.type = UNSIGNED;
1313 p->in.left = t;
1314 } else if (l->in.type == UCHAR || l->in.type == USHORT) {
1315 *t = *p;
1316 t->in.type = INT;
1317 p->in.left = t;
1318 }
1319 } else if (l->in.op != PCONV &&
cf280fdd 1320 l->in.op != CALL && l->in.op != UNARY CALL &&
f1824a4b 1321 tlen(p) == tlen(l)) {
7999919c 1322 /* clobber conversions w/o side effects */
f1824a4b
SL
1323 if (l->in.op != FLD)
1324 l->in.type = p->in.type;
1325 ncopy(p, l);
1326 l->in.op = FREE;
1327 }
1328 return;
1329
1330 case ASSIGN:
1331 /*
1332 * Try to zap storage conversions of non-float items.
1333 */
1334 r = p->in.right;
33027801 1335 if (r->in.op == SCONV) {
f1824a4b 1336 int wdest, wconv, wsrc;
33027801 1337
c2c596e4
DS
1338 if (p->in.left->in.op == FLD)
1339 return;
33027801
DS
1340 if (anyfloat(r, r->in.left)) {
1341 /* let the code table handle two cases */
1342 if (p->in.left->in.type == UNSIGNED &&
1343 r->in.type == UNSIGNED) {
1344 p->in.right = r->in.left;
1345 r->in.op = FREE;
1346 } else if ((p->in.left->in.type == FLOAT ||
1347 p->in.left->in.type == DOUBLE) &&
1348 p->in.left->in.type == r->in.type &&
1349 r->in.left->in.type == UNSIGNED) {
1350 p->in.right = r->in.left;
1351 r->in.op = FREE;
1352 }
1353 return;
1354 }
f1824a4b
SL
1355 wdest = tlen(p->in.left);
1356 wconv = tlen(r);
1357 /*
1358 * If size doesn't change across assignment or
1359 * conversion expands src before shrinking again
1360 * due to the assignment, delete conversion so
1361 * code generator can create optimal code.
1362 */
1363 if (wdest == wconv ||
1364 (wdest == (wsrc = tlen(r->in.left)) && wconv > wsrc)) {
1365 p->in.right = r->in.left;
1366 r->in.op = FREE;
1367 }
f2b49199 1368 }
f1824a4b 1369 return;
f2b49199
SL
1370 }
1371# endif
1372}
1373
1374struct functbl {
1375 int fop;
20018a56 1376 TWORD ftype;
f2b49199 1377 char *func;
20018a56
DS
1378 } opfunc[] = {
1379 DIV, TANY, "udiv",
1380 MOD, TANY, "urem",
1381 ASG DIV, TANY, "audiv",
1382 ASG MOD, TANY, "aurem",
1383 0, 0, 0 };
f2b49199
SL
1384
1385hardops(p) register NODE *p; {
1386 /* change hard to do operators into function calls. */
1387 register NODE *q;
1388 register struct functbl *f;
20018a56
DS
1389 register o;
1390 NODE *old,*temp;
f2b49199
SL
1391
1392 o = p->in.op;
20018a56
DS
1393 if( ! (optype(o)==BITYPE &&
1394 (ISUNSIGNED(p->in.left->in.type) ||
1395 ISUNSIGNED(p->in.right->in.type))) )
1396 return;
f2b49199
SL
1397
1398 for( f=opfunc; f->fop; f++ ) {
1399 if( o==f->fop ) goto convert;
20018a56 1400 }
f2b49199
SL
1401 return;
1402
1403 convert:
f2b49199 1404 if( asgop( o ) ) {
20018a56
DS
1405 old = NIL;
1406 switch( p->in.left->in.op ){
1407 case FLD:
1408 q = p->in.left->in.left;
1409 /*
1410 * rewrite (lval.fld /= rval); as
1411 * ((*temp).fld = udiv((*(temp = &lval)).fld,rval));
1412 * else the compiler will evaluate lval twice.
1413 */
1414 if( q->in.op == UNARY MUL ){
1415 /* first allocate a temp storage */
1416 temp = talloc();
1417 temp->in.op = OREG;
1418 temp->tn.rval = TMPREG;
1419 temp->tn.lval = BITOOR(freetemp(1));
1420 temp->in.type = INCREF(p->in.type);
1421#ifdef FLEXNAMES
1422 temp->in.name = "";
1423#else
1424 temp->in.name[0] = '\0';
1425#endif
1426 old = q->in.left;
1427 q->in.left = temp;
1428 }
1429 /* fall thru ... */
f2b49199 1430
20018a56
DS
1431 case REG:
1432 case NAME:
1433 case OREG:
1434 /* change ASG OP to a simple OP */
1435 q = talloc();
1436 q->in.op = NOASG p->in.op;
1437 q->in.rall = NOPREF;
1438 q->in.type = p->in.type;
1439 q->in.left = tcopy(p->in.left);
1440 q->in.right = p->in.right;
1441 p->in.op = ASSIGN;
1442 p->in.right = q;
1443 p = q;
1444 f -= 2; /* Note: this depends on the table order */
1445 /* on the right side only - replace *temp with
1446 *(temp = &lval), build the assignment node */
1447 if( old ){
1448 temp = q->in.left->in.left; /* the "*" node */
1449 q = talloc();
1450 q->in.op = ASSIGN;
1451 q->in.left = temp->in.left;
1452 q->in.right = old;
1453 q->in.type = old->in.type;
1454#ifdef FLEXNAMES
1455 q->in.name = "";
f2b49199 1456#else
20018a56 1457 q->in.name[0] = '\0';
f2b49199 1458#endif
20018a56
DS
1459 temp->in.left = q;
1460 }
1461 break;
f2b49199 1462
20018a56
DS
1463 case UNARY MUL:
1464 /* avoid doing side effects twice */
1465 q = p->in.left;
1466 p->in.left = q->in.left;
1467 q->in.op = FREE;
1468 break;
1469
1470 default:
1471 cerror( "hardops: can't compute & LHS" );
1472 }
1473 }
f2b49199 1474
20018a56
DS
1475 /* build comma op for args to function */
1476 q = talloc();
1477 q->in.op = CM;
1478 q->in.rall = NOPREF;
1479 q->in.type = INT;
1480 q->in.left = p->in.left;
1481 q->in.right = p->in.right;
f2b49199
SL
1482 p->in.op = CALL;
1483 p->in.right = q;
1484
1485 /* put function name in left node of call */
1486 p->in.left = q = talloc();
1487 q->in.op = ICON;
1488 q->in.rall = NOPREF;
1489 q->in.type = INCREF( FTN + p->in.type );
1490#ifndef FLEXNAMES
20018a56 1491 strcpy( q->in.name, f->func );
f2b49199 1492#else
20018a56 1493 q->in.name = f->func;
f2b49199
SL
1494#endif
1495 q->tn.lval = 0;
1496 q->tn.rval = 0;
1497
1498 }
1499
1500zappost(p) NODE *p; {
1501 /* look for ++ and -- operators and remove them */
1502
1503 register int o, ty;
1504 register NODE *q;
1505 o = p->in.op;
1506 ty = optype( o );
1507
1508 switch( o ){
1509
1510 case INCR:
1511 case DECR:
1512 q = p->in.left;
1513 p->in.right->in.op = FREE; /* zap constant */
1514 ncopy( p, q );
1515 q->in.op = FREE;
1516 return;
1517
1518 }
1519
1520 if( ty == BITYPE ) zappost( p->in.right );
1521 if( ty != LTYPE ) zappost( p->in.left );
1522}
1523
1524fixpre(p) NODE *p; {
1525
1526 register int o, ty;
1527 o = p->in.op;
1528 ty = optype( o );
1529
1530 switch( o ){
1531
1532 case ASG PLUS:
1533 p->in.op = PLUS;
1534 break;
1535 case ASG MINUS:
1536 p->in.op = MINUS;
1537 break;
1538 }
1539
1540 if( ty == BITYPE ) fixpre( p->in.right );
1541 if( ty != LTYPE ) fixpre( p->in.left );
1542}
1543
1544NODE * addroreg(l) NODE *l;
1545 /* OREG was built in clocal()
1546 * for an auto or formal parameter
1547 * now its address is being taken
1548 * local code must unwind it
1549 * back to PLUS/MINUS REG ICON
1550 * according to local conventions
1551 */
1552{
1553 cerror("address of OREG taken");
1554}
1555
1556# ifndef ONEPASS
1557main( argc, argv ) char *argv[]; {
1558 return( mainp2( argc, argv ) );
1559 }
1560# endif
1561
f1824a4b
SL
1562strip(p) register NODE *p; {
1563 NODE *q;
1564
1565 /* strip nodes off the top when no side effects occur */
1566 for( ; ; ) {
1567 switch( p->in.op ) {
1568 case SCONV: /* remove lint tidbits */
1569 q = p->in.left;
1570 ncopy( p, q );
1571 q->in.op = FREE;
1572 break;
1573 /* could probably add a few more here */
1574 default:
1575 return;
1576 }
1577 }
1578 }
1579
f2b49199 1580myreader(p) register NODE *p; {
f1824a4b 1581 strip( p ); /* strip off operations with no side effects */
f2b49199
SL
1582 walkf( p, hardops ); /* convert ops to function calls */
1583 canon( p ); /* expands r-vals for fileds */
1584 walkf( p, optim2 );
1585 }