X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/f2b49199907905d87eae34814056e1290ec2ebf4..ad7871609881e73855d0b04da49b486cd93efca7:/usr/src/old/pcc/ccom.tahoe/local2.c diff --git a/usr/src/old/pcc/ccom.tahoe/local2.c b/usr/src/old/pcc/ccom.tahoe/local2.c index 40b991f865..158d04e4e6 100644 --- a/usr/src/old/pcc/ccom.tahoe/local2.c +++ b/usr/src/old/pcc/ccom.tahoe/local2.c @@ -1,9 +1,13 @@ #ifndef lint -static char sccsid[] = "@(#)local2.c 1.1 (Berkeley) %G%"; +static char sccsid[] = "@(#)local2.c 1.32 (Berkeley) 2/29/88"; #endif -# include "mfile2" -# include "ctype.h" +# include "pass2.h" +# include + +# define putstr(s) fputs((s), stdout) +# define ISCHAR(p) (p->in.type == UCHAR || p->in.type == CHAR) + # ifdef FORT int ftlab1, ftlab2; # endif @@ -12,6 +16,7 @@ int ftlab1, ftlab2; # define BITMASK(n) ((1L< AUTOINIT ) - printf( " subl3 $%d,fp,sp\n", spoff); + printf( " subl3 $%ld,fp,sp\n", spoff); printf( " jbr L%d\n", ftlab2); #endif ent_mask = 0; @@ -98,7 +103,8 @@ rname(r) register int r; { - ent_mask |= 1<in.type; + tq = q->in.type; + + return( (tp==FLOAT || tp==DOUBLE) != + (tq==FLOAT || tq==DOUBLE) ); +} + prtype(n) NODE *n; { switch (n->in.type) { case DOUBLE: - printf("d"); + putchar('d'); return; case FLOAT: - printf("f"); + putchar('f'); return; + case LONG: + case ULONG: case INT: case UNSIGNED: - printf("l"); + putchar('l'); return; case SHORT: case USHORT: - printf("w"); + putchar('w'); return; case CHAR: case UCHAR: - printf("b"); + putchar('b'); return; default: if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type"); else { - printf("l"); + putchar('l'); return; } } @@ -182,72 +201,108 @@ zzzcode( p, c ) register NODE *p; { cbgen( p->in.op, p->bn.label, c ); return; - case 'A': /* assignment and load (integer only) */ + case 'G': /* i *= f; asgops with int lhs and float rhs */ { - register NODE *l, *r; + register NODE *l, *r, *s; + int lt, rt; - if (xdebug) eprint(p, 0, &val, &val); - r = getlr(p, 'R'); - if (optype(p->in.op) == LTYPE || p->in.op == UNARY MUL) { - l = resc; - l->in.type = INT; - } else - l = getlr(p, 'L'); - if(r->in.type==FLOAT || r->in.type==DOUBLE - || l->in.type==FLOAT || l->in.type==DOUBLE) - cerror("float in ZA"); - if (r->in.op == ICON) - if(r->in.name[0] == '\0') { - if (r->tn.lval == 0) { - printf("clr"); - prtype(l); - printf(" "); - adrput(l); - return; - } - if (r->tn.lval < 0 && r->tn.lval >= -63) { - printf("mneg"); - prtype(l); - r->tn.lval = -r->tn.lval; - goto ops; - } -#ifdef MOVAFASTER - } else { - printf("movab"); - printf(" "); - acon(r); - printf(","); - adrput(l); - return; -#endif MOVAFASTER - } + l = p->in.left; + r = p->in.right; + s = talloc(); + rt = r->in.type; + lt = l->in.type; + + if (lt != INT && lt != UNSIGNED) { + s->in.op = SCONV; + s->in.left = l; + s->in.type = ISUNSIGNED(lt) ? UNSIGNED : INT; + zzzcode(s, 'U'); + putstr("\n\t"); + } - if (l->in.op == REG) { - if( tlen(l) < tlen(r) ) { - !ISUNSIGNED(l->in.type)? - printf("cvt"): - printf("movz"); - prtype(l); - printf("l"); - goto ops; - } else - l->in.type = INT; + if (ISUNSIGNED(lt)) { + s->in.op = SCONV; + s->in.left = lt == UNSIGNED ? l : resc; + s->in.type = rt; + unsigned_to_float(s); + } else { + putstr("cvl"); + prtype(r); + putchar('\t'); + adrput(lt == INT ? l : resc); } - if (tlen(l) == tlen(r)) { - printf("mov"); - prtype(l); - goto ops; - } else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type)) - printf("movz"); - else - printf("cvt"); - prtype(r); - prtype(l); - ops: - printf(" "); + putstr("\n\t"); + + hopcode(rt == FLOAT ? 'F' : 'D', p->in.op); + putchar('\t'); adrput(r); - printf(","); - adrput(l); + + if (ISUNSIGNED(lt)) { + putstr("\n\t"); + s->in.op = SCONV; + s->in.left = r; /* we need only the type */ + s->in.type = UNSIGNED; + float_to_unsigned(s); + } else { + putstr("\n\tcv"); + prtype(r); + putstr("l\t"); + if (lt == INT) + adrput(l); + else + adrput(resc); + } + if (lt != INT) { + putstr("\n\t"); + s->in.op = ASSIGN; + s->in.left = l; + s->in.right = resc; + s->in.type = lt; + zzzcode(s, 'U'); + } + + s->in.op = FREE; + return; + } + + case 'J': /* unsigned DIV/MOD with constant divisors */ + { + register int ck = INAREG; + int label1, label2; + + /* case constant <= 1 is handled by optim() in pass 1 */ + /* case constant < 0x80000000 is handled in table */ + switch( p->in.op ) { + /* case DIV: handled in optim2() */ + case MOD: + if( p->in.left->in.op == REG && + p->in.left->tn.rval == resc->tn.rval ) + goto asgmod; + label1 = getlab(); + expand(p, ck, "movl\tAL,A1\n\tcmpl\tA1,AR\n"); + printf("\tjlssu\tL%d\n", label1); + expand(p, ck, "\tsubl2\tAR,A1\n"); + printf("L%d:", label1); + break; + case ASG DIV: + label1 = getlab(); + label2 = getlab(); + expand(p, ck, "cmpl\tAL,AR\n"); + printf("\tjgequ\tL%d\n", label1); + expand(p, ck, "\tmovl\t$1,AL\n"); + printf("\tjbr\tL%d\nL%d:\n", label2, label1); + expand(p, ck, "\tclrl\tAL\n"); + printf("L%d:", label2); + break; + case ASG MOD: + asgmod: + label1 = getlab(); + expand(p, ck, "cmpl\tAL,AR\n"); + printf("\tjlssu\tL%d\n", label1); + expand(p, ck, "\tsubl2\tAR,AL\n"); + printf("L%d:", label1); + break; + } return; } @@ -256,17 +311,17 @@ zzzcode( p, c ) register NODE *p; { register NODE *r; if (xdebug) eprint(p, 0, &val, &val); r = p->in.right; - if( tlen(r) == sizeof(int) && r->in.type != FLOAT ) - printf("movl"); + if( tlen(r) == SZINT/SZCHAR && r->in.type != FLOAT ) + putstr("movl"); else { - printf(ISUNSIGNED(r->in.type) ? "movz" : "cvt"); + putstr(ISUNSIGNED(r->in.type) ? "movz" : "cvt"); prtype(r); - printf("l"); + putchar('l'); } return; } - case 'C': /* num bytes pushed on arg stack */ + case 'C': /* generate 'call[fs] $bytes' */ { extern int gc_numbytes; extern int xdebug; @@ -276,44 +331,79 @@ zzzcode( p, c ) register NODE *p; { printf("call%c $%d", (p->in.left->in.op==ICON && gc_numbytes<60)?'f':'s', gc_numbytes+4); - /* dont change to double (here's the only place to catch it) */ + /* don't change to double (here's the only place to catch it) */ if(p->in.type == FLOAT) rtyflg = 1; return; } case 'D': /* INCR and DECR */ - zzzcode(p->in.left, 'A'); - printf("\n "); + if (p->in.left->in.type == FLOAT) + expand(p, INAREG, "movl\tAL,A1"); + else if (p->in.left->in.type == DOUBLE) + expand(p, INAREG, "ldd\tAL\n\tstd\tA1"); + else + zzzcode(p->in.left, 'U'); + putstr("\n "); case 'E': /* INCR and DECR, FOREFF */ - if (p->in.right->tn.lval == 1) + if (p->in.right->in.op == ICON && p->in.right->tn.lval == 1) { - printf("%s", (p->in.op == INCR ? "inc" : "dec") ); + putstr(p->in.op == INCR ? "inc" : "dec"); prtype(p->in.left); - printf(" "); + putchar('\t'); adrput(p->in.left); return; } - printf("%s", (p->in.op == INCR ? "add" : "sub") ); + else if (p->in.left->in.type == FLOAT || p->in.left->in.type == DOUBLE) { + if (c == 'E' || p->in.left->in.type == FLOAT) + expand(p, INAREG, "ldZL\tAL\n\t"); + if (p->in.op == INCR) + expand(p, INAREG, "addZL\tAR\n\tstZL\tAL"); + else /* DECR */ + expand(p, INAREG, "subZL\tAR\n\tstZL\tAL"); + return; + } + putstr(p->in.op == INCR ? "add" : "sub"); prtype(p->in.left); - printf("2 "); + putstr("2 "); adrput(p->in.right); - printf(","); + putchar(','); adrput(p->in.left); return; case 'F': /* masked constant for fields */ - printf("$%d", (p->in.right->tn.lval&((1<in.right->tn.lval&((1<in.right; + if(r->in.op == ICON && r->tn.name[0] == '\0') { + putstr("movl\t"); + printf(ACONFMT, r->tn.lval & ((1<in.op == LS || p->in.op == ASG LS) - printf("shll"); + putstr("shll"); else if(ISUNSIGNED(p->in.left->in.type)) - printf("shrl"); + putstr("shrl"); else - printf("shar"); + putstr("shar"); return; case 'L': /* type of left operand */ @@ -329,124 +419,544 @@ zzzcode( p, c ) register NODE *p; { return; } - case 'M': /* initiate ediv for mod and unsigned div */ - { - register char *r; - m = getlr(p, '1')->tn.rval; - r = rname(m); - printf("\tclrl\t%s\n\tmovl\t", r); + case 'M': { /* initiate ediv for mod and unsigned div */ + putstr("clrl\t"); + adrput(resc); + putstr("\n\tmovl\t"); adrput(p->in.left); - printf(",%s\n", rname(m+1)); - if(!ISUNSIGNED(p->in.type)) { /* should be MOD */ - m = getlab(); - printf("\tjgeq\tL%d\n\tmnegl\t$1,%s\n", m, r); - deflab(m); + putchar(','); + upput(resc, SZLONG); + printf("\n\tjgeq\tL%d\n\tmnegl\t$1,", m = getlab()); + adrput(resc); + putchar('\n'); + deflab(m); + return; + } + + case 'T': { /* rounded structure length for arguments */ + int size = p->stn.stsize; + SETOFF( size, 4); + printf("movab -%d(sp),sp", size); + return; + } + + case 'S': /* structure assignment */ + stasg(p); + break; + +#ifdef I_don_t_understand_this + case 'X': /* multiplication for short and char */ + if (ISUNSIGNED(p->in.left->in.type)) + printf("\tmovz"); + else + printf("\tcvt"); + zzzcode(p, 'L'); + printf("l\t"); + adrput(p->in.left); + printf(","); + adrput(&resc[0]); + printf("\n"); + if (ISUNSIGNED(p->in.right->in.type)) + printf("\tmovz"); + else + printf("\tcvt"); + zzzcode(p, 'R'); + printf("l\t"); + adrput(p->in.right); + printf(","); + adrput(&resc[1]); + printf("\n"); + return; +#endif + + case 'U': /* SCONV */ + case 'V': /* SCONV with FORCC */ + sconv(p, c == 'V'); + break; + + case 'W': { /* SCONV or ASSIGN float/double => unsigned */ + NODE *src = p->in.op == SCONV ? p->in.left : p->in.right; + + putstr("ld"); + prtype(src); + putchar('\t'); + adrput(src); + putstr("\n\t"); + float_to_unsigned(p); + break; + } + + case 'Y': /* SCONV or ASSIGN unsigned => float/double */ + unsigned_to_float(p); /* stores into accumulator */ + putstr("\n\tst"); + prtype(p); + putchar('\t'); + if (p->in.op == SCONV) + adrput(resc); + else + adrput(p->in.left); + rtyflg = 1; + break; + +#ifdef I_don_t_understand_this + case 'Z': + p = p->in.right; + switch (p->in.type) { + case SHORT: { + short w = p->tn.lval; + p->tn.lval = w; + break; } + case CHAR: { + char c = p->tn.lval; + p->tn.lval = c; + break; } - return; + } + printf("$%d", p->tn.lval); + break; +#endif - case 'U': - /* Truncate int for type conversions: - LONG|ULONG -> CHAR|UCHAR|SHORT|USHORT - SHORT|USHORT -> CHAR|UCHAR - increment offset to correct byte */ - { - register NODE *p1; - int dif; + default: + cerror( "illegal zzzcode" ); + } +} - p1 = p->in.left; - switch( p1->in.op ){ - case NAME: - case OREG: - dif = tlen(p1)-tlen(p); - p1->tn.lval += dif; - adrput(p1); - p1->tn.lval -= dif; - return; - default: - cerror( "Illegal ZU type conversion" ); - return; +#define MOVB(dst, src, off) { \ + putstr("\tmovb\t"); upput(src, off); putchar(','); \ + upput(dst, off); putchar('\n'); \ +} +#define MOVW(dst, src, off) { \ + putstr("\tmovw\t"); upput(src, off); putchar(','); \ + upput(dst, off); putchar('\n'); \ +} +#define MOVL(dst, src, off) { \ + putstr("\tmovl\t"); upput(src, off); putchar(','); \ + upput(dst, off); putchar('\n'); \ +} +/* + * Generate code for a structure assignment. + */ +stasg(p) + register NODE *p; +{ + register NODE *l, *r; + register int size; + + switch (p->in.op) { + case STASG: /* regular assignment */ + l = p->in.left; + r = p->in.right; + break; + case STARG: /* place arg on the stack */ + l = getlr(p, '3'); + r = p->in.left; + break; + default: + cerror("STASG bad"); + /*NOTREACHED*/ + } + /* + * Pun source for use in code generation. + */ + switch (r->in.op) { + case ICON: + r->in.op = NAME; + break; + case REG: + r->in.op = OREG; + break; + default: + cerror( "STASG-r" ); + /*NOTREACHED*/ + } + size = p->stn.stsize; + if (size <= 0 || size > 65535) + cerror("structure size out of range"); + /* + * Generate optimized code based on structure size + * and alignment properties.... + */ + switch (size) { + + case 1: + putstr("\tmovb\t"); + optimized: + adrput(r); + putchar(','); + adrput(l); + putchar('\n'); + break; + + case 2: + if (p->stn.stalign != 2) { + MOVB(l, r, SZCHAR); + putstr("\tmovb\t"); + } else + putstr("\tmovw\t"); + goto optimized; + + case 4: + if (p->stn.stalign != 4) { + if (p->stn.stalign != 2) { + MOVB(l, r, 3*SZCHAR); + MOVB(l, r, 2*SZCHAR); + MOVB(l, r, 1*SZCHAR); + putstr("\tmovb\t"); + } else { + MOVW(l, r, SZSHORT); + putstr("\tmovw\t"); } + } else + putstr("\tmovl\t"); + goto optimized; + + case 6: + if (p->stn.stalign != 2) + goto movblk; + MOVW(l, r, 2*SZSHORT); + MOVW(l, r, 1*SZSHORT); + putstr("\tmovw\t"); + goto optimized; + + case 8: + if (p->stn.stalign == 4) { + MOVL(l, r, SZLONG); + putstr("\tmovl\t"); + goto optimized; } + /* fall thru...*/ - case 'T': /* rounded structure length for arguments */ + default: + movblk: + /* + * Can we ever get a register conflict with R1 here? + */ + putstr("\tmovab\t"); + if(r->in.op == OREG && r->tn.rval == R1) { - int size; - - size = p->stn.stsize; - SETOFF( size, 4); - printf("movab -%d(sp),sp", size); - return; + adrput(r); + printf(",r0\n\tmovab\t"); + adrput(l); + putstr(",r1\n"); } - - case 'S': /* structure assignment */ + else { - register NODE *l, *r; - register int size; + adrput(l); + putstr(",r1\n\tmovab\t"); + adrput(r); + printf(",r0\n"); + } + printf("\tmovl\t$%d,r2\n\tmovblk\n", size); + rname(R2); + break; + } + /* + * Reverse above pun for reclaim. + */ + if (r->in.op == NAME) + r->in.op = ICON; + else if (r->in.op == OREG) + r->in.op = REG; +} - if( p->in.op == STASG ){ - l = p->in.left; - r = p->in.right; +/* + * Convert a float or double in the accumulator into an unsigned int. + * Unlike the vax, the tahoe stores 0 into the destination + * on a conversion of > 2 ** 31, so we compensate. + */ +float_to_unsigned(p) + NODE *p; +{ + register NODE *l = p->in.left; + int label1 = getlab(); + int label2 = getlab(); + int label3 = getlab(); + NODE *src, *dst; + + if (p->in.op == SCONV) { + src = p->in.left; + dst = resc; + } else { + src = p->in.right; + dst = p->in.left; + } - } - else if( p->in.op == STARG ){ /* store an arg into a temporary */ - l = getlr( p, '3' ); - r = p->in.left; - } - else cerror( "STASG bad" ); + printf(".data\n\t.align\t2\nL%d:\n\t.long\t0x50000000", label1); + if (src->in.type == DOUBLE) + putstr(", 0x00000000 # .double"); + else + putstr(" # .float"); + putstr(" 2147483648\n\t.text\n\tcmp"); + prtype(src); + printf("\tL%d\n\tjlss\tL%d\n\tsub", label1, label2); + prtype(src); + printf("\tL%d\n\tcv", label1); + prtype(src); + putstr("l\t"); + adrput(dst); + putstr("\n\taddl2\t$-2147483648,"); + adrput(dst); + printf("\n\tjbr\tL%d\nL%d:\n\tcv", label3, label2); + prtype(src); + putstr("l\t"); + adrput(dst); + printf("\nL%d:", label3); +} - if( r->in.op == ICON ) r->in.op = NAME; - else if( r->in.op == REG ) r->in.op = OREG; - else if( r->in.op != OREG ) cerror( "STASG-r" ); +/* + * Convert an unsigned int into a float or double, leaving the result + * in the accumulator. + */ +unsigned_to_float(p) + register NODE *p; +{ + int label1 = getlab(); + int label2 = getlab(); + NODE *src, *dst; + + if (p->in.op == SCONV) { + src = p->in.left; + dst = resc; + } else { + src = p->in.right; + dst = p->in.left; + } - size = p->stn.stsize; + printf(".data\n\t.align\t2\nL%d:\n\t.long\t0x50800000", label2); + if (p->in.type == DOUBLE) + putstr(", 0x00000000 # .double"); + else + putstr(" # .float"); + putstr(" 4294967296\n\t.text\n\tmovl\t"); + adrput(src); + putchar(','); + adrput(dst); + putstr("\n\tcvl"); + prtype(p); + putchar('\t'); + adrput(dst); + printf("\n\tjgeq\tL%d\n\tadd", label1); + prtype(p); + printf("\tL%d\nL%d:", label2, label1); +} - if( size <= 0 || size > 65535 ) - cerror("structure size <0=0 or >65535"); +/* + * Prlen() is a cheap prtype()... + */ +static char convtab[SZINT/SZCHAR + 1] = { + '?', 'b', 'w', '?', 'l' +}; +#define prlen(len) putchar(convtab[len]) + + +/* + * Generate code for integral scalar conversions. + * Some of this code is designed to work around a tahoe misfeature + * that causes sign- and zero- extension to be defeated in + * certain circumstances. + * Basically if the source operand of a CVT or MOVZ instruction is + * shorter than the destination, and the source is a register + * or an immediate constant, sign- and zero- extension are + * ignored and the high bits of the source are copied. (Note + * that zero-extension is not a problem for immediate + * constants.) + * Another problem -- condition codes for a conversion with a + * register source reflect the source rather than the destination. + */ +sconv(p, forcc) + NODE *p; + int forcc; +{ + register NODE *src, *dst; + register NODE *tmp; + register int srclen, dstlen; + int srctype, dsttype; + int val; + int neg = 0; + + if (p->in.op == ASSIGN) { + src = p->in.right; + dst = p->in.left; + dstlen = tlen(dst); + dsttype = dst->in.type; + } else if (p->in.op == SCONV) { + src = p->in.left; + dst = resc; + dstlen = tlen(p); + dsttype = p->in.type; + } else /* if (p->in.op == OPLEAF) */ { + src = p; + dst = resc; + dstlen = SZINT/SZCHAR; + dsttype = ISUNSIGNED(src->in.type) ? UNSIGNED : INT; + } - switch(size) { - case 1: - printf(" movb "); - break; - case 2: - printf(" movw "); - break; - case 4: - printf(" movl "); - break; - case 8: - printf(" movl "); - upput(r); - printf(","); - upput(l); - printf("\n movl "); - break; - default: - printf(" movab "); - adrput(l); - printf(",r1\n movab "); - adrput(r); - printf(",r0\n movl $%d,r2\n movblk\n", size); - rname(2); - goto endstasg; + if (src->in.op == REG) { + srclen = SZINT/SZCHAR; + srctype = ISUNSIGNED(src->in.type) ? UNSIGNED : INT; + } else { + srclen = tlen(src); + srctype = src->in.type; + } + + if (src->in.op == ICON && src->tn.name[0] == '\0') { + if (src->tn.lval == 0) { + putstr("clr"); + prtype(dst); + putchar('\t'); + adrput(dst); + return; + } + if (dstlen < srclen) { + switch (dsttype) { + case CHAR: + src->tn.lval = (char) src->tn.lval; + break; + case UCHAR: + src->tn.lval = (unsigned char) src->tn.lval; + break; + case SHORT: + src->tn.lval = (short) src->tn.lval; + break; + case USHORT: + src->tn.lval = (unsigned short) src->tn.lval; + break; } - adrput(r); - printf(","); - adrput(l); - printf("\n"); - endstasg: - if( r->in.op == NAME ) r->in.op = ICON; - else if( r->in.op == OREG ) r->in.op = REG; + } + if (dst->in.op == REG) { + dsttype = INT; + dstlen = SZINT/SZCHAR; + } + srctype = dsttype; + srclen = dstlen; + val = -src->tn.lval & ((1 << dstlen * SZCHAR) - 1); + if ((unsigned) val < 64) { + src->tn.lval = val; + ++neg; /* MNEGx may be shorter */ + } + } + if (srclen < dstlen) { + if (srctype == CHAR && dsttype == USHORT && dst->in.op == REG) { + /* (unsigned short) c; => sign extend to 16 bits */ + putstr("cvtbl\t"); + adrput(src); + putstr(",-(sp)\n\tmovzwl\t2(sp),"); + adrput(dst); + putstr("\n\tmovab\t4(sp),sp"); + if (forcc) { + putstr("\n\ttstl\t"); + adrput(dst); } - break; + return; + } + genconv(ISUNSIGNED(srctype), + srclen, dst->in.op == REG ? SZINT/SZCHAR : dstlen, + src, dst, forcc); + return; + } - default: - cerror( "illegal zzzcode" ); + if (srclen > dstlen && dst->in.op == REG) { + /* if dst is a register, the result must look like an int */ + if (src->in.op == REG) { + if (ISUNSIGNED(dsttype)) { + val = (1 << dstlen * SZCHAR) - 1; + if (src->tn.rval == dst->tn.rval) + /* conversion in place */ + printf("andl2\t$%ld,", val); + else { + printf("andl3\t$%ld,", val); + adrput(src); + putchar(','); + } + adrput(dst); + return; + } + /* + * Sign extension in register can also be + * accomplished by shifts, but unfortunately + * shifts are extremely slow, due to the lack + * of a barrel shifter. + */ + putstr("pushl\t"); + adrput(src); + putstr("\n\tcvt"); + prlen(dstlen); + printf("l\t%d(sp),", SZINT/SZCHAR - dstlen); + adrput(dst); + putstr("\n\tmovab\t4(sp),sp"); + if (forcc) { + putstr("\n\ttstl\t"); + adrput(dst); + } + return; + } + tmp = talloc(); + if ((src->in.op == NAME) || + (src->in.op == UNARY MUL && src->in.left->in.op == ICON) || + (src->in.op == OREG && !R2TEST(src->tn.rval))) { + /* we can increment src's address & pun it */ + *tmp = *src; + tmp->tn.lval += srclen - dstlen; + } else { + /* we must store src's address */ + *tmp = *dst; + putstr("mova"); + prlen(srclen); + putchar('\t'); + adrput(src); + putchar(','); + adrput(tmp); + putstr("\n\t"); + tmp->tn.op = OREG; + tmp->tn.lval = srclen - dstlen; } + genconv(ISUNSIGNED(dsttype), dstlen, SZINT/SZCHAR, tmp, dst, forcc); + tmp->in.op = FREE; + return; + } + + genconv(neg ? -1 : ISUNSIGNED(dsttype), + srclen, dst->in.op == REG ? SZINT/SZCHAR : dstlen, + src, dst, forcc); +} + +genconv(srcflag, srclen, dstlen, src, dst, forcc) + int srcflag; + register int srclen, dstlen; + NODE *src, *dst; + int forcc; +{ + if (srclen != dstlen) { + if (srcflag > 0 && srclen < dstlen) + putstr("movz"); + else + putstr("cvt"); + prlen(srclen); + } else if (srcflag < 0) + putstr("mneg"); + else + putstr("mov"); + prlen(dstlen); + putchar('\t'); + adrput(src); + putchar(','); + adrput(dst); + + /* + * This hack is made necessary by architecture problems + * described above + */ + if (forcc && src->in.op == REG && srclen > dstlen) { + putstr("\n\ttst"); + prlen(dstlen); + putchar('\t'); + adrput(dst); } +} -rmove( rt, rs, t ) TWORD t;{ +rmove( rt, rs, t ) TWORD t; { printf( " movl %s,%s\n", rname(rs), rname(rt) ); if(t==DOUBLE) printf( " movl %s,%s\n", rname(rs+1), rname(rt+1) ); @@ -465,14 +975,18 @@ setregs(){ /* set up temporary registers */ fregs = 6; /* tbl- 6 free regs on Tahoe (0-5) */ } +#ifndef szty szty(t) TWORD t;{ /* size, in registers, needed to hold thing of type t */ return(t==DOUBLE ? 2 : 1 ); } +#endif +/*ARGSUSED*/ rewfld( p ) NODE *p; { return(1); } +/*ARGSUSED*/ callreg(p) NODE *p; { return( R0 ); } @@ -480,29 +994,41 @@ callreg(p) NODE *p; { base( p ) register NODE *p; { register int o = p->in.op; - if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */ + if( o==ICON && p->in.name[0] != '\0' ) return( 100 ); /* ie no base reg */ if( o==REG ) return( p->tn.rval ); if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON) return( p->in.left->tn.rval ); if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) return( p->tn.rval + 0200*1 ); + if( o==NAME ) return( 100 + 0200*1 ); return( -1 ); } offset( p, tyl ) register NODE *p; int tyl; { - if(tyl > 8) return( -1 ); - if( tyl==1 && p->in.op==REG && (p->in.type==INT || p->in.type==UNSIGNED) ) return( p->tn.rval ); - if( (p->in.op==LS && p->in.left->in.op==REG && (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && - (p->in.right->in.op==ICON && p->in.right->in.name[0]=='\0') - && (1<in.right->tn.lval)==tyl)) + if( tyl==1 && + p->in.op==REG && + (p->in.type==INT || p->in.type==UNSIGNED) ) + return( p->tn.rval ); + if( p->in.op==LS && + p->in.left->in.op==REG && + (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && + p->in.right->in.op==ICON && + p->in.right->in.name[0]=='\0' && + (1<in.right->tn.lval)==tyl) + return( p->in.left->tn.rval ); + if( tyl==2 && + p->in.op==PLUS && + (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && + p->in.left->in.op==REG && + p->in.right->in.op==REG && + p->in.left->tn.rval==p->in.right->tn.rval ) return( p->in.left->tn.rval ); return( -1 ); } makeor2( p, q, b, o) register NODE *p, *q; register int b, o; { register NODE *t; - register int i; NODE *f; p->in.op = OREG; @@ -513,6 +1039,7 @@ makeor2( p, q, b, o) register NODE *p, *q; register int b, o; { case ICON: case REG: case OREG: + case NAME: t = q; break; @@ -532,8 +1059,11 @@ makeor2( p, q, b, o) register NODE *p, *q; register int b, o; { p->tn.lval = t->tn.lval; #ifndef FLEXNAMES - for(i=0; iin.name[i] = t->in.name[i]; + { + register int i; + for(i=0; iin.name[i] = t->in.name[i]; + } #else p->in.name = t->in.name; #endif @@ -552,9 +1082,11 @@ canaddr( p ) NODE *p; { return(0); } +#ifndef shltype shltype( o, p ) register NODE *p; { return( o== REG || o == NAME || o == ICON || o == OREG || ( o==UNARY MUL && shumul(p->in.left)) ); } +#endif flshape( p ) NODE *p; { register int o = p->in.op; @@ -563,9 +1095,30 @@ flshape( p ) NODE *p; { return(0); } +/* INTEMP shapes must not contain any temporary registers */ shtemp( p ) register NODE *p; { + int r; + if( p->in.op == STARG ) p = p->in.left; - return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) ); + + switch (p->in.op) { + case REG: + return( !istreg(p->tn.rval) ); + case OREG: + r = p->tn.rval; + if( R2TEST(r) ) { + if( istreg(R2UPK1(r)) ) + return(0); + r = R2UPK2(r); + } + return( !istreg(r) ); + case UNARY MUL: + p = p->in.left; + return( p->in.op != UNARY MUL && shtemp(p) ); + } + + if( optype( p->in.op ) != LTYPE ) return(0); + return(1); } shumul( p ) register NODE *p; { @@ -591,8 +1144,7 @@ special( p, shape ) register NODE *p; { } adrcon( val ) CONSZ val; { - printf( "$" ); - printf( CONFMT, val ); + printf(ACONFMT, val); } conput( p ) register NODE *p; { @@ -603,7 +1155,7 @@ conput( p ) register NODE *p; { return; case REG: - printf( "%s", rname(p->tn.rval) ); + putstr(rname(p->tn.rval)); return; default: @@ -611,36 +1163,45 @@ conput( p ) register NODE *p; { } } +/*ARGSUSED*/ insput( p ) NODE *p; { cerror( "insput" ); } -upput( p ) register NODE *p; { - /* output the address of the second long in the - pair pointed to by p (for DOUBLEs)*/ +/* + * Output the address of the second item in the + * pair pointed to by p. + */ +upput(p, size) + register NODE *p; +{ CONSZ save; - if( p->in.op == FLD ){ + if (p->in.op == FLD) p = p->in.left; - } - switch( p->in.op ){ + switch (p->in.op) { case NAME: case OREG: save = p->tn.lval; - p->tn.lval += SZLONG/SZCHAR; + p->tn.lval += size/SZCHAR; adrput(p); p->tn.lval = save; - return; + break; case REG: - printf( "%s", rname(p->tn.rval+1) ); - return; + if (size == SZLONG) { + putstr(rname(p->tn.rval+1)); + break; + } + /* fall thru... */ default: - cerror( "illegal upper address" ); - } + cerror("illegal upper address op %s size %d", + opst[p->tn.op], size); + /*NOTREACHED*/ } +} adrput( p ) register NODE *p; { register int r; @@ -657,12 +1218,12 @@ adrput( p ) register NODE *p; { case ICON: /* addressable value of the constant */ - printf( "$" ); + putchar('$'); acon( p ); return; case REG: - printf( "%s", rname(p->tn.rval) ); + putstr(rname(p->tn.rval)); if(p->in.type == DOUBLE) /* for entry mask */ (void) rname(p->tn.rval+1); return; @@ -673,7 +1234,7 @@ adrput( p ) register NODE *p; { register int flags; flags = R2UPK3(r); - if( flags & 1 ) printf("*"); + if( flags & 1 ) putchar('*'); if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p); if( R2UPK1(r) != 100) printf( "(%s)", rname(R2UPK1(r)) ); printf( "[%s]", rname(R2UPK2(r)) ); @@ -682,7 +1243,7 @@ adrput( p ) register NODE *p; { if( r == FP && p->tn.lval > 0 ){ /* in the argument region */ if( p->in.name[0] != '\0' ) werror( "bad arg temp" ); printf( CONFMT, p->tn.lval ); - printf( "(fp)" ); + putstr( "(fp)" ); return; } if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p ); @@ -692,7 +1253,7 @@ adrput( p ) register NODE *p; { case UNARY MUL: /* STARNM or STARREG found */ if( tshape(p, STARNM) ) { - printf( "*" ); + putchar( '*' ); adrput( p->in.left); } return; @@ -707,23 +1268,18 @@ adrput( p ) register NODE *p; { acon( p ) register NODE *p; { /* print out a constant */ - if( p->in.name[0] == '\0' ){ + if( p->in.name[0] == '\0' ) printf( CONFMT, p->tn.lval); - } - else if( p->tn.lval == 0 ) { -#ifndef FLEXNAMES - printf( "%.8s", p->in.name ); -#else - printf( "%s", p->in.name ); -#endif - } else { #ifndef FLEXNAMES - printf( "%.8s+", p->in.name ); + printf( "%.8s", p->in.name ); #else - printf( "%s+", p->in.name ); + putstr( p->in.name ); #endif - printf( CONFMT, p->tn.lval ); + if( p->tn.lval != 0 ) { + putchar( '+' ); + printf( CONFMT, p->tn.lval ); + } } } @@ -767,6 +1323,7 @@ genfcall( p, cookie ) register NODE *p; { int gc_numbytes; /* tbl */ +/*ARGSUSED*/ gencall( p, cookie ) register NODE *p; { /* generate the call given by p */ register NODE *p1, *ptemp; @@ -840,12 +1397,12 @@ ccbranches[] = { }; /* tbl */ +/*ARGSUSED*/ cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */ - if(o != 0 && (o < EQ || o > UGT )) - cerror( "bad conditional branch: %s", opst[o] ); - printf( " j%s L%d\n", - o == 0 ? "br" : ccbranches[o-EQ], lab ); + if( o != 0 && ( o < EQ || o > UGT ) ) + cerror( "bad conditional branch: %s", opst[o] ); + printf( " j%s L%d\n", o == 0 ? "br" : ccbranches[o-EQ], lab ); } nextcook( p, cookie ) NODE *p; { @@ -856,117 +1413,474 @@ nextcook( p, cookie ) NODE *p; { return( FORREW ); } +/*ARGSUSED*/ lastchance( p, cook ) NODE *p; { /* forget it! */ return(0); } optim2( p ) register NODE *p; { -# ifdef ONEPASS /* do local tree transformations and optimizations */ -# define RV(p) p->in.right->tn.lval - register int o = p->in.op; - register int i; - /* change unsigned mods and divs to logicals (mul is done in mip & c2) */ - if(optype(o) == BITYPE && ISUNSIGNED(p->in.left->in.type) - && nncon(p->in.right) && (i=ispow2(RV(p)))>=0){ - switch(o) { - case DIV: - case ASG DIV: - p->in.op = RS; - RV(p) = i; + int o; + int i, mask; + register NODE *l, *r; + + switch( o = p->in.op ) { + + case ASG PLUS: + case ASG MINUS: + case ASG MUL: + case ASG OR: + /* simple ASG OPSIMP -- reduce range of constant rhs */ + l = p->in.left; + r = p->in.right; + if( tlen(l) < SZINT/SZCHAR && + r->in.op==ICON && r->in.name[0]==0 ){ + mask = (1 << tlen(l) * SZCHAR) - 1; + if( r->tn.lval & (mask & ~(mask >> 1)) ) + r->tn.lval |= ~mask; + else + r->tn.lval &= mask; + } + break; + + case AND: + case ASG AND: + r = p->in.right; + if( r->in.op==ICON && r->in.name[0]==0 ) { + /* check for degenerate operations */ + l = p->in.left; + mask = (1 << tlen(l) * SZCHAR) - 1; + if( o == ASG AND || ISUNSIGNED(r->in.type) ) { + i = r->tn.lval & mask; + if( i == mask ) { + /* redundant mask */ + r->in.op = FREE; + ncopy(p, l); + l->in.op = FREE; + break; + } + else if( i == 0 ) + /* all bits masked off */ + goto zero; + r->tn.lval = i; + if( tlen(l) < SZINT/SZCHAR ){ + /* sign extend */ + if( r->tn.lval & (mask & ~(mask >> 1)) ) + r->tn.lval |= ~mask; + else + r->tn.lval &= mask; + } + } + else if( r->tn.lval == mask && + tlen(l) < SZINT/SZCHAR ) { + /* use movz instead of and */ + r->in.op = SCONV; + r->in.left = l; + r->in.right = 0; + r->in.type = ENUNSIGN(l->in.type); + r->in.su = l->in.su > 1 ? l->in.su : 1; + ncopy(p, r); + p->in.left = r; + p->in.type = INT; + } + } + break; + + case SCONV: + l = p->in.left; + if( p->in.type == FLOAT || p->in.type == DOUBLE || + l->in.type == FLOAT || l->in.type == DOUBLE ) + return; + if( l->in.op == PCONV ) + return; + if( (l->in.op == CALL || l->in.op == UNARY CALL) && + l->in.type != INT && l->in.type != UNSIGNED ) + return; + + /* Only trust it to get it right if the size is the same */ + if( tlen(p) != tlen(l) ) + return; + + /* clobber conversion */ + if( l->in.op != FLD ) + l->in.type = p->in.type; + ncopy( p, l ); + l->in.op = FREE; + + break; + + case ASSIGN: + /* + * Conversions are equivalent to assignments; + * when the two operations are combined, + * we can sometimes zap the conversion. + */ + r = p->in.right; + l = p->in.left; + if ( r->in.op == SCONV && + !mixtypes(l, r) && + l->in.op != FLD && + tlen(l) == tlen(r) ) { + p->in.right = r->in.left; + r->in.op = FREE; + } + break; + + case ULE: + case ULT: + case UGE: + case UGT: + p->in.op -= (UGE-GE); + if( degenerate(p) ) break; - case MOD: - case ASG MOD: - p->in.op = AND; - RV(p)--; + p->in.op += (UGE-GE); + break; + + case EQ: + case NE: + case LE: + case LT: + case GE: + case GT: + if( p->in.left->in.op == SCONV && + p->in.right->in.op == SCONV ) { + l = p->in.left; + r = p->in.right; + if( l->in.type == DOUBLE && + l->in.left->in.type == FLOAT && + r->in.left->in.type == FLOAT ) { + /* nuke the conversions */ + p->in.left = l->in.left; + p->in.right = r->in.left; + l->in.op = FREE; + r->in.op = FREE; + } + /* more? */ + } + (void) degenerate(p); + break; + + case DIV: + if( p->in.right->in.op == ICON && + p->in.right->tn.name[0] == '\0' && + ISUNSIGNED(p->in.right->in.type) && + (unsigned) p->in.right->tn.lval >= 0x80000000 ) { + /* easy to do here, harder to do in zzzcode() */ + p->in.op = UGE; break; - default: - return; + } + case MOD: + case ASG DIV: + case ASG MOD: + /* + * optimize DIV and MOD + * + * basically we spot UCHAR and USHORT and try to do them + * as signed ints... this may need tuning for the tahoe. + */ + if( degenerate(p) ) + break; + l = p->in.left; + r = p->in.right; + if( !ISUNSIGNED(r->in.type) || + tlen(l) >= SZINT/SZCHAR || + !(tlen(r) < SZINT/SZCHAR || + (r->in.op == ICON && r->tn.name[0] == '\0')) ) + break; + if( r->in.op == ICON ) + r->tn.type = INT; + else { + NODE *t = talloc(); + t->in.left = r; + r = t; + r->in.op = SCONV; + r->in.type = INT; + r->in.right = 0; + p->in.right = r; + } + if( o == DIV || o == MOD ) { + NODE *t = talloc(); + t->in.left = l; + l = t; + l->in.op = SCONV; + l->in.type = INT; + l->in.right = 0; + p->in.left = l; + } + /* handle asgops in table */ + break; + + case RS: + case ASG RS: + case LS: + case ASG LS: + /* pick up degenerate shifts */ + l = p->in.left; + r = p->in.right; + if( !(r->in.op == ICON && r->tn.name[0] == '\0') ) + break; + i = r->tn.lval; + if( i < 0 ) + /* front end 'fixes' this? */ + if( o == LS || o == ASG LS ) + o += (RS-LS); + else + o += (LS-RS); + if( (o == RS || o == ASG RS) && + !ISUNSIGNED(l->in.type) ) + /* can't optimize signed right shifts */ + break; + if( o == LS ) { + if( i < SZINT ) + break; + } + else { + if( i < tlen(l) * SZCHAR ) + break; + } + zero: + if( !asgop( o ) ) + if( tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) { + /* no side effects */ + tfree(l); + ncopy(p, r); + r->in.op = FREE; + p->tn.lval = 0; + } + else { + p->in.op = COMOP; + r->tn.lval = 0; + } + else { + p->in.op = ASSIGN; + r->tn.lval = 0; + } + break; } - if(asgop(o)) - p->in.op = ASG p->in.op; } -# endif -} + +degenerate(p) register NODE *p; { + int o; + int result, i; + int lower, upper; + register NODE *l, *r; + + /* + * try to keep degenerate comparisons with constants + * out of the table. + */ + r = p->in.right; + l = p->in.left; + if( r->in.op != ICON || + r->tn.name[0] != '\0' || + tlen(l) >= tlen(r) ) + return (0); + switch( l->in.type ) { + case CHAR: + lower = -(1 << SZCHAR - 1); + upper = (1 << SZCHAR - 1) - 1; + break; + case UCHAR: + lower = 0; + upper = (1 << SZCHAR) - 1; + break; + case SHORT: + lower = -(1 << SZSHORT - 1); + upper = (1 << SZSHORT - 1) - 1; + break; + case USHORT: + lower = 0; + upper = (1 << SZSHORT) - 1; + break; + default: + cerror("unsupported type in degenerate()"); + } + i = r->tn.lval; + switch( o = p->in.op ) { + case DIV: + case ASG DIV: + case MOD: + case ASG MOD: + /* DIV and MOD work like EQ */ + case EQ: + case NE: + if( lower == 0 && (unsigned) i > upper ) + result = o == NE; + else if( i < lower || i > upper ) + result = o == NE; + else + return (0); + break; + case LT: + case GE: + if( lower == 0 && (unsigned) i > upper ) + result = o == LT; + else if( i <= lower ) + result = o != LT; + else if( i > upper ) + result = o == LT; + else + return (0); + break; + case LE: + case GT: + if( lower == 0 && (unsigned) i >= upper ) + result = o == LE; + else if( i < lower ) + result = o != LE; + else if( i >= upper ) + result = o == LE; + else + return (0); + break; + default: + cerror("unknown op in degenerate()"); + } + + if( o == MOD || o == ASG MOD ) { + r->in.op = FREE; + ncopy(p, l); + l->in.op = FREE; + } + else if( o != ASG DIV && tshape(l, SAREG|SNAME|SCON|SOREG|STARNM) ) { + /* no side effects */ + tfree(l); + ncopy(p, r); + r->in.op = FREE; + p->tn.lval = result; + } + else { + if( o == ASG DIV ) + p->in.op = ASSIGN; + else { + p->in.op = COMOP; + r->tn.type = INT; + } + r->tn.lval = result; + } + if( logop(o) ) + p->in.type = INT; + + return (1); + } struct functbl { int fop; + TWORD ftype; char *func; -} opfunc[] = { - DIV, "udiv", - ASG DIV, "udiv", - 0 -}; + } opfunc[] = { + DIV, TANY, "udiv", + MOD, TANY, "urem", + ASG DIV, TANY, "audiv", + ASG MOD, TANY, "aurem", + 0, 0, 0 }; hardops(p) register NODE *p; { /* change hard to do operators into function calls. */ register NODE *q; register struct functbl *f; - register int o; - register TWORD t, t1, t2; + register o; + NODE *old,*temp; o = p->in.op; + if( ! (optype(o)==BITYPE && + (ISUNSIGNED(p->in.left->in.type) || + ISUNSIGNED(p->in.right->in.type))) ) + return; for( f=opfunc; f->fop; f++ ) { if( o==f->fop ) goto convert; - } + } return; convert: - t = p->in.type; - t1 = p->in.left->in.type; - t2 = p->in.right->in.type; - if ( t1 != UNSIGNED && (t2 != UNSIGNED)) return; - - /* need to rewrite tree for ASG OP */ - /* must change ASG OP to a simple OP */ + if( p->in.right->in.op == ICON && p->in.right->tn.name[0] == '\0' ) + /* 'J' in zzzcode() -- assumes DIV or MOD operations */ + /* save a subroutine call -- use at most 5 instructions */ + return; + if( tlen(p->in.left) < SZINT/SZCHAR && tlen(p->in.right) < SZINT/SZCHAR ) + /* optim2() will modify the op into an ordinary int op */ + return; if( asgop( o ) ) { - q = talloc(); - q->in.op = NOASG ( o ); - q->in.rall = NOPREF; - q->in.type = p->in.type; - q->in.left = tcopy(p->in.left); - q->in.right = p->in.right; - p->in.op = ASSIGN; - p->in.right = q; - zappost(q->in.left); /* remove post-INCR(DECR) from new node */ - fixpre(q->in.left); /* change pre-INCR(DECR) to +/- */ - p = q; + old = NIL; + switch( p->in.left->in.op ){ + case FLD: + q = p->in.left->in.left; + /* + * rewrite (lval.fld /= rval); as + * ((*temp).fld = udiv((*(temp = &lval)).fld,rval)); + * else the compiler will evaluate lval twice. + */ + if( q->in.op == UNARY MUL ){ + /* first allocate a temp storage */ + temp = talloc(); + temp->in.op = OREG; + temp->tn.rval = TMPREG; + temp->tn.lval = BITOOR(freetemp(1)); + temp->in.type = INCREF(p->in.type); +#ifdef FLEXNAMES + temp->in.name = ""; +#else + temp->in.name[0] = '\0'; +#endif + old = q->in.left; + q->in.left = temp; + } + /* fall thru ... */ - } - /* turn logicals to compare 0 */ - else if( logop( o ) ) { - ncopy(q = talloc(), p); - p->in.left = q; - p->in.right = q = talloc(); - q->in.op = ICON; - q->in.type = INT; -#ifndef FLEXNAMES - q->in.name[0] = '\0'; + case REG: + case NAME: + case OREG: + /* change ASG OP to a simple OP */ + q = talloc(); + q->in.op = NOASG p->in.op; + q->in.rall = NOPREF; + q->in.type = p->in.type; + q->in.left = tcopy(p->in.left); + q->in.right = p->in.right; + p->in.op = ASSIGN; + p->in.right = q; + p = q; + f -= 2; /* Note: this depends on the table order */ + /* on the right side only - replace *temp with + *(temp = &lval), build the assignment node */ + if( old ){ + temp = q->in.left->in.left; /* the "*" node */ + q = talloc(); + q->in.op = ASSIGN; + q->in.left = temp->in.left; + q->in.right = old; + q->in.type = old->in.type; +#ifdef FLEXNAMES + q->in.name = ""; #else - q->in.name = ""; + q->in.name[0] = '\0'; #endif - q->tn.lval = 0; - q->tn.rval = 0; - p = p->in.left; - } + temp->in.left = q; + } + break; - /* build comma op for args to function */ - t1 = p->in.left->in.type; - t2 = 0; - if ( optype(p->in.op) == BITYPE) { - q = talloc(); - q->in.op = CM; - q->in.rall = NOPREF; - q->in.type = INT; - q->in.left = p->in.left; - q->in.right = p->in.right; - t2 = p->in.right->in.type; - } else - q = p->in.left; + case UNARY MUL: + /* avoid doing side effects twice */ + q = p->in.left; + p->in.left = q->in.left; + q->in.op = FREE; + break; + default: + cerror( "hardops: can't compute & LHS" ); + } + } + + /* build comma op for args to function */ + q = talloc(); + q->in.op = CM; + q->in.rall = NOPREF; + q->in.type = INT; + q->in.left = p->in.left; + q->in.right = p->in.right; p->in.op = CALL; p->in.right = q; @@ -976,9 +1890,9 @@ hardops(p) register NODE *p; { q->in.rall = NOPREF; q->in.type = INCREF( FTN + p->in.type ); #ifndef FLEXNAMES - strcpy( q->in.name, f->func ); + strcpy( q->in.name, f->func ); #else - q->in.name = f->func; + q->in.name = f->func; #endif q->tn.lval = 0; q->tn.rval = 0; @@ -1029,6 +1943,7 @@ fixpre(p) NODE *p; { if( ty != LTYPE ) fixpre( p->in.left ); } +/*ARGSUSED*/ NODE * addroreg(l) NODE *l; /* OREG was built in clocal() * for an auto or formal parameter @@ -1039,6 +1954,7 @@ NODE * addroreg(l) NODE *l; */ { cerror("address of OREG taken"); + /*NOTREACHED*/ } # ifndef ONEPASS @@ -1047,8 +1963,27 @@ main( argc, argv ) char *argv[]; { } # endif +strip(p) register NODE *p; { + NODE *q; + + /* strip nodes off the top when no side effects occur */ + for( ; ; ) { + switch( p->in.op ) { + case SCONV: /* remove lint tidbits */ + q = p->in.left; + ncopy( p, q ); + q->in.op = FREE; + break; + /* could probably add a few more here */ + default: + return; + } + } + } + myreader(p) register NODE *p; { + strip( p ); /* strip off operations with no side effects */ + canon( p ); /* expands r-vals for fields */ walkf( p, hardops ); /* convert ops to function calls */ - canon( p ); /* expands r-vals for fileds */ walkf( p, optim2 ); }