utah rcsid 1.10 87/04/18 18:20:15: Another screwup -- must distinguish
[unix-history] / usr / src / old / pcc / ccom.tahoe / local2.c
CommitLineData
f2b49199 1#ifndef lint
082edec2 2static char sccsid[] = "@(#)local2.c 1.19 (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;
714
715 if (p->in.op == ASSIGN) {
7999919c
DS
716 src = p->in.right;
717 dst = p->in.left;
52b983f1
DS
718 dstlen = tlen(dst);
719 dsttype = dst->in.type;
7999919c
DS
720 } else if (p->in.op == SCONV) {
721 src = p->in.left;
722 dst = resc;
52b983f1
DS
723 dstlen = tlen(p);
724 dsttype = p->in.type;
7999919c
DS
725 } else /* if (p->in.op == OPLEAF) */ {
726 src = p;
727 dst = resc;
728 dstlen = SZINT/SZCHAR;
729 dsttype = ISUNSIGNED(src->in.type) ? UNSIGNED : INT;
52b983f1
DS
730 }
731
26ab1ae0
DS
732 if (src->in.op == REG) {
733 srclen = SZINT/SZCHAR;
734 srctype = ISUNSIGNED(src->in.type) ? UNSIGNED : INT;
735 } else {
736 srclen = tlen(src);
737 srctype = src->in.type;
738 }
739
082edec2
DS
740 if (src->in.op == ICON &&
741#ifdef FLEXNAMES
742 (src->tn.name == NULL || *src->tn.name == '\0')
743#else
744 src->tn.name[0] == '\0'
745#endif
746 ) {
26ab1ae0
DS
747 if (src->tn.lval == 0) {
748 putstr("clr");
749 prtype(dst);
750 putchar('\t');
751 adrput(dst);
752 return;
753 }
754 if (dstlen < srclen) {
755 switch (dsttype) {
756 case CHAR:
757 src->tn.lval = (char) src->tn.lval;
758 break;
759 case UCHAR:
760 src->tn.lval = (unsigned char) src->tn.lval;
761 break;
762 case SHORT:
763 src->tn.lval = (short) src->tn.lval;
764 break;
765 case USHORT:
766 src->tn.lval = (unsigned short) src->tn.lval;
767 break;
768 }
769 }
770 if (dst->in.op == REG) {
771 dsttype = INT;
772 dstlen = SZINT/SZCHAR;
773 }
774 srctype = dsttype;
775 srclen = dstlen;
776 }
52b983f1
DS
777
778 if (srclen < dstlen) {
779 if (srctype == CHAR && dsttype == USHORT && dst->in.op == REG) {
780 /* (unsigned short) c; => sign extend to 16 bits */
c3446016 781 putstr("cvtbl\t");
52b983f1
DS
782 adrput(src);
783 putstr(",-(sp)\n\tmovzwl\t2(sp),");
784 adrput(dst);
785 putstr("\n\tmovab\t4(sp),sp");
786 if (forcc) {
787 /* inverted test */
788 putstr("\n\tcmpl\t$0,");
789 adrput(dst);
790 }
791 return;
792 }
793 genconv(ISUNSIGNED(srctype),
794 srclen, dst->in.op == REG ? SZINT/SZCHAR : dstlen,
795 src, dst);
796 return;
797 }
798
799 if (srclen > dstlen && dst->in.op == REG) {
26ab1ae0 800 /* if dst is a register, the result must look like an int */
52b983f1
DS
801 if (src->in.op == REG) {
802 if (ISUNSIGNED(dsttype)) {
803 val = (1 << dstlen * SZCHAR) - 1;
804 if (src->tn.rval == dst->tn.rval)
805 /* conversion in place */
c3446016 806 printf("andl2\t$%#x,", val);
52b983f1 807 else {
c3446016 808 printf("andl3\t$%#x,", val);
52b983f1
DS
809 adrput(src);
810 putchar(',');
811 }
812 adrput(dst);
813 return;
814 }
26ab1ae0
DS
815 /*
816 * Sign extension in register can also be
817 * accomplished by shifts, but unfortunately
818 * shifts are extremely slow, due to the lack
819 * of a barrel shifter.
820 */
821 putstr("pushl\t");
52b983f1 822 adrput(src);
26ab1ae0
DS
823 putstr("\n\tcvt");
824 prlen(dstlen);
825 printf("l\t%d(sp),", SZINT/SZCHAR - dstlen);
52b983f1 826 adrput(dst);
26ab1ae0
DS
827 putstr("\n\tmovab\t4(sp),sp");
828 if (forcc) {
829 /* inverted test */
830 putstr("\n\tcmpl\t$0,");
831 adrput(dst);
832 }
52b983f1
DS
833 return;
834 }
835 tmp = talloc();
836 if ((src->in.op == UNARY MUL &&
837 ((src->in.left->in.op == NAME ||
838 (src->in.left->in.op == ICON)))) ||
839 (src->in.op == OREG && !R2TEST(src->tn.rval))) {
840 /* we can increment src's address & pun it */
841 *tmp = *src;
842 tmp->tn.lval += srclen - dstlen;
843 } else {
844 /* we must store src's address */
845 *tmp = *dst;
26ab1ae0
DS
846 putstr("mova");
847 prlen(srclen);
848 putchar('\t');
52b983f1
DS
849 adrput(src);
850 putchar(',');
851 adrput(tmp);
c3446016 852 putstr("\n\t");
52b983f1
DS
853 tmp->tn.op = OREG;
854 tmp->tn.lval = srclen - dstlen;
855 }
856 genconv(ISUNSIGNED(dsttype), dstlen, SZINT/SZCHAR, tmp, dst);
857 tmp->in.op = FREE;
858 return;
859 }
860
861 genconv(ISUNSIGNED(dsttype),
862 srclen, dst->in.op == REG ? SZINT/SZCHAR : dstlen,
863 src, dst);
864}
865
866genconv(usrc, srclen, dstlen, src, dst)
26ab1ae0
DS
867 int usrc;
868 register int srclen, dstlen;
52b983f1
DS
869 NODE *src, *dst;
870{
52b983f1
DS
871 if (srclen != dstlen) {
872 if (usrc && srclen < dstlen)
c3446016 873 putstr("movz");
52b983f1 874 else
c3446016 875 putstr("cvt");
26ab1ae0 876 prlen(srclen);
52b983f1 877 } else
c3446016 878 putstr("mov");
26ab1ae0 879 prlen(dstlen);
52b983f1
DS
880 putchar('\t');
881 adrput(src);
882 putchar(',');
883 adrput(dst);
884}
f1824a4b 885
f2b49199
SL
886rmove( rt, rs, t ) TWORD t;{
887 printf( " movl %s,%s\n", rname(rs), rname(rt) );
888 if(t==DOUBLE)
889 printf( " movl %s,%s\n", rname(rs+1), rname(rt+1) );
890 }
891
892struct respref
893respref[] = {
894 INTAREG|INTBREG, INTAREG|INTBREG,
895 INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON,
896 INTEMP, INTEMP,
897 FORARG, FORARG,
898 INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM,
899 0, 0 };
900
901setregs(){ /* set up temporary registers */
902 fregs = 6; /* tbl- 6 free regs on Tahoe (0-5) */
903 }
904
ebdd0416 905#ifndef szty
f2b49199
SL
906szty(t) TWORD t;{ /* size, in registers, needed to hold thing of type t */
907 return(t==DOUBLE ? 2 : 1 );
908 }
ebdd0416 909#endif
f2b49199
SL
910
911rewfld( p ) NODE *p; {
912 return(1);
913 }
914
915callreg(p) NODE *p; {
916 return( R0 );
917 }
918
919base( p ) register NODE *p; {
920 register int o = p->in.op;
921
922 if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */
923 if( o==REG ) return( p->tn.rval );
924 if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON)
925 return( p->in.left->tn.rval );
926 if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) )
927 return( p->tn.rval + 0200*1 );
928 return( -1 );
929 }
930
931offset( p, tyl ) register NODE *p; int tyl; {
932
933 if(tyl > 8) return( -1 );
934 if( tyl==1 && p->in.op==REG && (p->in.type==INT || p->in.type==UNSIGNED) ) return( p->tn.rval );
935 if( (p->in.op==LS && p->in.left->in.op==REG && (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) &&
936 (p->in.right->in.op==ICON && p->in.right->in.name[0]=='\0')
937 && (1<<p->in.right->tn.lval)==tyl))
938 return( p->in.left->tn.rval );
939 return( -1 );
940 }
941
942makeor2( p, q, b, o) register NODE *p, *q; register int b, o; {
943 register NODE *t;
944 register int i;
945 NODE *f;
946
947 p->in.op = OREG;
948 f = p->in.left; /* have to free this subtree later */
949
950 /* init base */
951 switch (q->in.op) {
952 case ICON:
953 case REG:
954 case OREG:
955 t = q;
956 break;
957
958 case MINUS:
959 q->in.right->tn.lval = -q->in.right->tn.lval;
960 case PLUS:
961 t = q->in.right;
962 break;
963
964 case UNARY MUL:
965 t = q->in.left->in.left;
966 break;
967
968 default:
969 cerror("illegal makeor2");
970 }
971
972 p->tn.lval = t->tn.lval;
973#ifndef FLEXNAMES
974 for(i=0; i<NCHNAM; ++i)
975 p->in.name[i] = t->in.name[i];
976#else
977 p->in.name = t->in.name;
978#endif
979
980 /* init offset */
981 p->tn.rval = R2PACK( (b & 0177), o, (b>>7) );
982
983 tfree(f);
984 return;
985 }
986
987canaddr( p ) NODE *p; {
988 register int o = p->in.op;
989
990 if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
991 return(0);
992 }
993
ebdd0416 994#ifndef shltype
f2b49199
SL
995shltype( o, p ) register NODE *p; {
996 return( o== REG || o == NAME || o == ICON || o == OREG || ( o==UNARY MUL && shumul(p->in.left)) );
997 }
ebdd0416 998#endif
f2b49199
SL
999
1000flshape( p ) NODE *p; {
1001 register int o = p->in.op;
1002
1003 if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1);
1004 return(0);
1005 }
1006
1007shtemp( p ) register NODE *p; {
1008 if( p->in.op == STARG ) p = p->in.left;
1009 return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) );
1010 }
1011
1012shumul( p ) register NODE *p; {
1013 register int o;
1014 extern int xdebug;
1015
1016 if (xdebug) {
1017 printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op);
1018 printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval);
1019 }
1020
1021 o = p->in.op;
1022 if(( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON )
1023 && p->in.type != PTR+DOUBLE)
1024 return( STARNM );
1025
1026 return( 0 );
1027 }
1028
1029special( p, shape ) register NODE *p; {
1030 if( shape==SIREG && p->in.op == OREG && R2TEST(p->tn.rval) ) return(1);
1031 else return(0);
1032}
1033
1034adrcon( val ) CONSZ val; {
7412b41b 1035 printf(ACONFMT, val);
f2b49199
SL
1036 }
1037
1038conput( p ) register NODE *p; {
1039 switch( p->in.op ){
1040
1041 case ICON:
1042 acon( p );
1043 return;
1044
1045 case REG:
895241c8 1046 putstr(rname(p->tn.rval));
f2b49199
SL
1047 return;
1048
1049 default:
1050 cerror( "illegal conput" );
1051 }
1052 }
1053
1054insput( p ) NODE *p; {
1055 cerror( "insput" );
1056 }
1057
f2b49199
SL
1058adrput( p ) register NODE *p; {
1059 register int r;
1060 /* output an address, with offsets, from p */
1061
1062 if( p->in.op == FLD ){
1063 p = p->in.left;
1064 }
1065 switch( p->in.op ){
1066
1067 case NAME:
1068 acon( p );
1069 return;
1070
1071 case ICON:
1072 /* addressable value of the constant */
895241c8 1073 putchar('$');
f2b49199
SL
1074 acon( p );
1075 return;
1076
1077 case REG:
895241c8 1078 putstr(rname(p->tn.rval));
f2b49199
SL
1079 if(p->in.type == DOUBLE) /* for entry mask */
1080 (void) rname(p->tn.rval+1);
1081 return;
1082
1083 case OREG:
1084 r = p->tn.rval;
1085 if( R2TEST(r) ){ /* double indexing */
1086 register int flags;
1087
1088 flags = R2UPK3(r);
895241c8 1089 if( flags & 1 ) putchar('*');
f2b49199
SL
1090 if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p);
1091 if( R2UPK1(r) != 100) printf( "(%s)", rname(R2UPK1(r)) );
1092 printf( "[%s]", rname(R2UPK2(r)) );
1093 return;
1094 }
1095 if( r == FP && p->tn.lval > 0 ){ /* in the argument region */
1096 if( p->in.name[0] != '\0' ) werror( "bad arg temp" );
1097 printf( CONFMT, p->tn.lval );
895241c8 1098 putstr( "(fp)" );
f2b49199
SL
1099 return;
1100 }
1101 if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p );
1102 printf( "(%s)", rname(p->tn.rval) );
1103 return;
1104
1105 case UNARY MUL:
1106 /* STARNM or STARREG found */
1107 if( tshape(p, STARNM) ) {
895241c8 1108 putchar( '*' );
f2b49199
SL
1109 adrput( p->in.left);
1110 }
1111 return;
1112
1113 default:
1114 cerror( "illegal address" );
1115 return;
1116
1117 }
1118
1119 }
1120
1121acon( p ) register NODE *p; { /* print out a constant */
1122
1123 if( p->in.name[0] == '\0' ){
1124 printf( CONFMT, p->tn.lval);
895241c8
SL
1125 return;
1126 } else {
f2b49199
SL
1127#ifndef FLEXNAMES
1128 printf( "%.8s", p->in.name );
1129#else
895241c8 1130 putstr(p->in.name);
f2b49199 1131#endif
895241c8
SL
1132 if (p->tn.lval != 0) {
1133 putchar('+');
1134 printf(CONFMT, p->tn.lval);
f2b49199 1135 }
895241c8 1136 }
f2b49199
SL
1137 }
1138
1139genscall( p, cookie ) register NODE *p; {
1140 /* structure valued call */
1141 return( gencall( p, cookie ) );
1142 }
1143
1144genfcall( p, cookie ) register NODE *p; {
1145 register NODE *p1;
1146 register int m;
1147 static char *funcops[6] = {
1148 "sin", "cos", "sqrt", "exp", "log", "atan"
1149 };
1150
1151 /* generate function opcodes */
1152 if(p->in.op==UNARY FORTCALL && p->in.type==FLOAT &&
1153 (p1 = p->in.left)->in.op==ICON &&
1154 p1->tn.lval==0 && p1->in.type==INCREF(FTN|FLOAT)) {
1155#ifdef FLEXNAMES
1156 p1->in.name++;
1157#else
1158 strcpy(p1->in.name, p1->in.name[1]);
1159#endif
1160 for(m=0; m<6; m++)
1161 if(!strcmp(p1->in.name, funcops[m]))
1162 break;
1163 if(m >= 6)
1164 uerror("no opcode for fortarn function %s", p1->in.name);
1165 } else
1166 uerror("illegal type of fortarn function");
1167 p1 = p->in.right;
1168 p->in.op = FORTCALL;
1169 if(!canaddr(p1))
1170 order( p1, INAREG|INBREG|SOREG|STARREG|STARNM );
1171 m = match( p, INTAREG|INTBREG );
1172 return(m != MDONE);
1173}
1174
1175/* tbl */
1176int gc_numbytes;
1177/* tbl */
1178
1179gencall( p, cookie ) register NODE *p; {
1180 /* generate the call given by p */
1181 register NODE *p1, *ptemp;
1182 register int temp, temp1;
1183 register int m;
1184
1185 if( p->in.right ) temp = argsize( p->in.right );
1186 else temp = 0;
1187
1188 if( p->in.op == STCALL || p->in.op == UNARY STCALL ){
1189 /* set aside room for structure return */
1190
1191 if( p->stn.stsize > temp ) temp1 = p->stn.stsize;
1192 else temp1 = temp;
1193 }
1194
1195 if( temp > maxargs ) maxargs = temp;
1196 SETOFF(temp1,4);
1197
1198 if( p->in.right ){ /* make temp node, put offset in, and generate args */
1199 ptemp = talloc();
1200 ptemp->in.op = OREG;
1201 ptemp->tn.lval = -1;
1202 ptemp->tn.rval = SP;
1203#ifndef FLEXNAMES
1204 ptemp->in.name[0] = '\0';
1205#else
1206 ptemp->in.name = "";
1207#endif
1208 ptemp->in.rall = NOPREF;
1209 ptemp->in.su = 0;
1210 genargs( p->in.right, ptemp );
1211 ptemp->in.op = FREE;
1212 }
1213
1214 p1 = p->in.left;
1215 if( p1->in.op != ICON ){
1216 if( p1->in.op != REG ){
1217 if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){
1218 if( p1->in.op != NAME ){
1219 order( p1, INAREG );
1220 }
1221 }
1222 }
1223 }
1224
1225/* tbl
1226 setup gc_numbytes so reference to ZC works */
1227
1228 gc_numbytes = temp&(0x3ff);
1229
1230 p->in.op = UNARY CALL;
1231 m = match( p, INTAREG|INTBREG );
1232
1233 return(m != MDONE);
1234 }
1235
1236/* tbl */
1237char *
1238ccbranches[] = {
1239 "eql",
1240 "neq",
1241 "leq",
1242 "lss",
1243 "geq",
1244 "gtr",
1245 "lequ",
1246 "lssu",
1247 "gequ",
1248 "gtru",
1249 };
1250/* tbl */
1251
1252cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */
1253
1254 if(o != 0 && (o < EQ || o > UGT ))
1255 cerror( "bad conditional branch: %s", opst[o] );
1256 printf( " j%s L%d\n",
1257 o == 0 ? "br" : ccbranches[o-EQ], lab );
1258 }
1259
1260nextcook( p, cookie ) NODE *p; {
1261 /* we have failed to match p with cookie; try another */
1262 if( cookie == FORREW ) return( 0 ); /* hopeless! */
1263 if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG );
1264 if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG );
1265 return( FORREW );
1266 }
1267
1268lastchance( p, cook ) NODE *p; {
1269 /* forget it! */
1270 return(0);
1271 }
1272
1273optim2( p ) register NODE *p; {
1274# ifdef ONEPASS
1275 /* do local tree transformations and optimizations */
1276# define RV(p) p->in.right->tn.lval
ebdd0416 1277# define nncon(p) ((p)->in.op == ICON && (p)->in.name[0] == 0)
f1824a4b
SL
1278 register int o, i;
1279 register NODE *l, *r;
f2b49199 1280
f1824a4b
SL
1281 switch (o = p->in.op) {
1282
1283 case DIV: case ASG DIV:
1284 case MOD: case ASG MOD:
1285 /*
1286 * Change unsigned mods and divs to
1287 * logicals (mul is done in mip & c2)
1288 */
1289 if (ISUNSIGNED(p->in.left->in.type) && nncon(p->in.right) &&
1290 (i = ispow2(RV(p))) >= 0) {
1291 if (o == DIV || o == ASG DIV) {
1292 p->in.op = RS;
1293 RV(p) = i;
1294 } else {
1295 p->in.op = AND;
1296 RV(p)--;
1297 }
1298 if (asgop(o))
1299 p->in.op = ASG p->in.op;
1300 }
1301 return;
1302
1303 case SCONV:
1304 l = p->in.left;
7999919c
DS
1305 if (anyfloat(p, l)) {
1306 /* save some labor later */
1307 NODE *t = talloc();
1308
1309 if (p->in.type == UCHAR || p->in.type == USHORT) {
1310 *t = *p;
1311 t->in.type = UNSIGNED;
1312 p->in.left = t;
1313 } else if (l->in.type == UCHAR || l->in.type == USHORT) {
1314 *t = *p;
1315 t->in.type = INT;
1316 p->in.left = t;
1317 }
1318 } else if (l->in.op != PCONV &&
cf280fdd 1319 l->in.op != CALL && l->in.op != UNARY CALL &&
f1824a4b 1320 tlen(p) == tlen(l)) {
7999919c 1321 /* clobber conversions w/o side effects */
f1824a4b
SL
1322 if (l->in.op != FLD)
1323 l->in.type = p->in.type;
1324 ncopy(p, l);
1325 l->in.op = FREE;
1326 }
1327 return;
1328
1329 case ASSIGN:
1330 /*
1331 * Try to zap storage conversions of non-float items.
1332 */
1333 r = p->in.right;
33027801 1334 if (r->in.op == SCONV) {
f1824a4b 1335 int wdest, wconv, wsrc;
33027801
DS
1336
1337 if (anyfloat(r, r->in.left)) {
1338 /* let the code table handle two cases */
1339 if (p->in.left->in.type == UNSIGNED &&
1340 r->in.type == UNSIGNED) {
1341 p->in.right = r->in.left;
1342 r->in.op = FREE;
1343 } else if ((p->in.left->in.type == FLOAT ||
1344 p->in.left->in.type == DOUBLE) &&
1345 p->in.left->in.type == r->in.type &&
1346 r->in.left->in.type == UNSIGNED) {
1347 p->in.right = r->in.left;
1348 r->in.op = FREE;
1349 }
1350 return;
1351 }
f1824a4b
SL
1352 wdest = tlen(p->in.left);
1353 wconv = tlen(r);
1354 /*
1355 * If size doesn't change across assignment or
1356 * conversion expands src before shrinking again
1357 * due to the assignment, delete conversion so
1358 * code generator can create optimal code.
1359 */
1360 if (wdest == wconv ||
1361 (wdest == (wsrc = tlen(r->in.left)) && wconv > wsrc)) {
1362 p->in.right = r->in.left;
1363 r->in.op = FREE;
1364 }
f2b49199 1365 }
f1824a4b 1366 return;
f2b49199
SL
1367 }
1368# endif
1369}
1370
1371struct functbl {
1372 int fop;
20018a56 1373 TWORD ftype;
f2b49199 1374 char *func;
20018a56
DS
1375 } opfunc[] = {
1376 DIV, TANY, "udiv",
1377 MOD, TANY, "urem",
1378 ASG DIV, TANY, "audiv",
1379 ASG MOD, TANY, "aurem",
1380 0, 0, 0 };
f2b49199
SL
1381
1382hardops(p) register NODE *p; {
1383 /* change hard to do operators into function calls. */
1384 register NODE *q;
1385 register struct functbl *f;
20018a56
DS
1386 register o;
1387 NODE *old,*temp;
f2b49199
SL
1388
1389 o = p->in.op;
20018a56
DS
1390 if( ! (optype(o)==BITYPE &&
1391 (ISUNSIGNED(p->in.left->in.type) ||
1392 ISUNSIGNED(p->in.right->in.type))) )
1393 return;
f2b49199
SL
1394
1395 for( f=opfunc; f->fop; f++ ) {
1396 if( o==f->fop ) goto convert;
20018a56 1397 }
f2b49199
SL
1398 return;
1399
1400 convert:
f2b49199 1401 if( asgop( o ) ) {
20018a56
DS
1402 old = NIL;
1403 switch( p->in.left->in.op ){
1404 case FLD:
1405 q = p->in.left->in.left;
1406 /*
1407 * rewrite (lval.fld /= rval); as
1408 * ((*temp).fld = udiv((*(temp = &lval)).fld,rval));
1409 * else the compiler will evaluate lval twice.
1410 */
1411 if( q->in.op == UNARY MUL ){
1412 /* first allocate a temp storage */
1413 temp = talloc();
1414 temp->in.op = OREG;
1415 temp->tn.rval = TMPREG;
1416 temp->tn.lval = BITOOR(freetemp(1));
1417 temp->in.type = INCREF(p->in.type);
1418#ifdef FLEXNAMES
1419 temp->in.name = "";
1420#else
1421 temp->in.name[0] = '\0';
1422#endif
1423 old = q->in.left;
1424 q->in.left = temp;
1425 }
1426 /* fall thru ... */
f2b49199 1427
20018a56
DS
1428 case REG:
1429 case NAME:
1430 case OREG:
1431 /* change ASG OP to a simple OP */
1432 q = talloc();
1433 q->in.op = NOASG p->in.op;
1434 q->in.rall = NOPREF;
1435 q->in.type = p->in.type;
1436 q->in.left = tcopy(p->in.left);
1437 q->in.right = p->in.right;
1438 p->in.op = ASSIGN;
1439 p->in.right = q;
1440 p = q;
1441 f -= 2; /* Note: this depends on the table order */
1442 /* on the right side only - replace *temp with
1443 *(temp = &lval), build the assignment node */
1444 if( old ){
1445 temp = q->in.left->in.left; /* the "*" node */
1446 q = talloc();
1447 q->in.op = ASSIGN;
1448 q->in.left = temp->in.left;
1449 q->in.right = old;
1450 q->in.type = old->in.type;
1451#ifdef FLEXNAMES
1452 q->in.name = "";
f2b49199 1453#else
20018a56 1454 q->in.name[0] = '\0';
f2b49199 1455#endif
20018a56
DS
1456 temp->in.left = q;
1457 }
1458 break;
f2b49199 1459
20018a56
DS
1460 case UNARY MUL:
1461 /* avoid doing side effects twice */
1462 q = p->in.left;
1463 p->in.left = q->in.left;
1464 q->in.op = FREE;
1465 break;
1466
1467 default:
1468 cerror( "hardops: can't compute & LHS" );
1469 }
1470 }
f2b49199 1471
20018a56
DS
1472 /* build comma op for args to function */
1473 q = talloc();
1474 q->in.op = CM;
1475 q->in.rall = NOPREF;
1476 q->in.type = INT;
1477 q->in.left = p->in.left;
1478 q->in.right = p->in.right;
f2b49199
SL
1479 p->in.op = CALL;
1480 p->in.right = q;
1481
1482 /* put function name in left node of call */
1483 p->in.left = q = talloc();
1484 q->in.op = ICON;
1485 q->in.rall = NOPREF;
1486 q->in.type = INCREF( FTN + p->in.type );
1487#ifndef FLEXNAMES
20018a56 1488 strcpy( q->in.name, f->func );
f2b49199 1489#else
20018a56 1490 q->in.name = f->func;
f2b49199
SL
1491#endif
1492 q->tn.lval = 0;
1493 q->tn.rval = 0;
1494
1495 }
1496
1497zappost(p) NODE *p; {
1498 /* look for ++ and -- operators and remove them */
1499
1500 register int o, ty;
1501 register NODE *q;
1502 o = p->in.op;
1503 ty = optype( o );
1504
1505 switch( o ){
1506
1507 case INCR:
1508 case DECR:
1509 q = p->in.left;
1510 p->in.right->in.op = FREE; /* zap constant */
1511 ncopy( p, q );
1512 q->in.op = FREE;
1513 return;
1514
1515 }
1516
1517 if( ty == BITYPE ) zappost( p->in.right );
1518 if( ty != LTYPE ) zappost( p->in.left );
1519}
1520
1521fixpre(p) NODE *p; {
1522
1523 register int o, ty;
1524 o = p->in.op;
1525 ty = optype( o );
1526
1527 switch( o ){
1528
1529 case ASG PLUS:
1530 p->in.op = PLUS;
1531 break;
1532 case ASG MINUS:
1533 p->in.op = MINUS;
1534 break;
1535 }
1536
1537 if( ty == BITYPE ) fixpre( p->in.right );
1538 if( ty != LTYPE ) fixpre( p->in.left );
1539}
1540
1541NODE * addroreg(l) NODE *l;
1542 /* OREG was built in clocal()
1543 * for an auto or formal parameter
1544 * now its address is being taken
1545 * local code must unwind it
1546 * back to PLUS/MINUS REG ICON
1547 * according to local conventions
1548 */
1549{
1550 cerror("address of OREG taken");
1551}
1552
1553# ifndef ONEPASS
1554main( argc, argv ) char *argv[]; {
1555 return( mainp2( argc, argv ) );
1556 }
1557# endif
1558
f1824a4b
SL
1559strip(p) register NODE *p; {
1560 NODE *q;
1561
1562 /* strip nodes off the top when no side effects occur */
1563 for( ; ; ) {
1564 switch( p->in.op ) {
1565 case SCONV: /* remove lint tidbits */
1566 q = p->in.left;
1567 ncopy( p, q );
1568 q->in.op = FREE;
1569 break;
1570 /* could probably add a few more here */
1571 default:
1572 return;
1573 }
1574 }
1575 }
1576
f2b49199 1577myreader(p) register NODE *p; {
f1824a4b 1578 strip( p ); /* strip off operations with no side effects */
f2b49199
SL
1579 walkf( p, hardops ); /* convert ops to function calls */
1580 canon( p ); /* expands r-vals for fileds */
1581 walkf( p, optim2 );
1582 }