117742Sralph # ifndef lint 2*23536Sbloom static char *sccsid ="@(#)local2.c 1.11 (Berkeley) 06/18/85"; 317742Sralph # endif 417742Sralph 518556Sralph # include "pass2.h" 69702Slinton # include "ctype.h" 79702Slinton # ifdef FORT 89702Slinton int ftlab1, ftlab2; 99702Slinton # endif 109702Slinton /* a lot of the machine dependent parts of the second pass */ 119702Slinton 129702Slinton # define BITMASK(n) ((1L<<n)-1) 139702Slinton 149702Slinton where(c){ 159702Slinton fprintf( stderr, "%s, line %d: ", filename, lineno ); 169702Slinton } 179702Slinton 189702Slinton lineid( l, fn ) char *fn; { 199702Slinton /* identify line l and file fn */ 209702Slinton printf( "# line %d, file %s\n", l, fn ); 219702Slinton } 229702Slinton 239702Slinton 249702Slinton eobl2(){ 259702Slinton OFFSZ spoff; /* offset from stack pointer */ 269702Slinton #ifdef FORT 279702Slinton spoff = maxoff; 289702Slinton if( spoff >= AUTOINIT ) spoff -= AUTOINIT; 299702Slinton spoff /= SZCHAR; 309702Slinton SETOFF(spoff,4); 319702Slinton #ifndef FLEXNAMES 329702Slinton printf( " .set .F%d,%ld\n", ftnno, spoff ); 339702Slinton #else 349702Slinton /* SHOULD BE L%d ... ftnno but must change pc/f77 */ 359702Slinton printf( " .set LF%d,%ld\n", ftnno, spoff ); 369702Slinton #endif 379702Slinton #else 389702Slinton extern int ftlab1, ftlab2; 399702Slinton 409702Slinton spoff = maxoff; 419702Slinton if( spoff >= AUTOINIT ) spoff -= AUTOINIT; 429702Slinton spoff /= SZCHAR; 439702Slinton SETOFF(spoff,4); 449702Slinton printf( "L%d:\n", ftlab1); 459702Slinton if( spoff!=0 ) 469702Slinton if( spoff < 64 ) 479702Slinton printf( " subl2 $%ld,sp\n", spoff); 489702Slinton else 499702Slinton printf( " movab -%ld(sp),sp\n", spoff); 509702Slinton printf( " jbr L%d\n", ftlab2); 519702Slinton #endif 529702Slinton maxargs = -1; 539702Slinton } 549702Slinton 559702Slinton struct hoptab { int opmask; char * opstring; } ioptab[] = { 569702Slinton 579702Slinton ASG PLUS, "add", 589702Slinton ASG MINUS, "sub", 599702Slinton ASG MUL, "mul", 609702Slinton ASG DIV, "div", 619702Slinton ASG OR, "bis", 629702Slinton ASG ER, "xor", 639702Slinton ASG AND, "bic", 649702Slinton PLUS, "add", 659702Slinton MINUS, "sub", 669702Slinton MUL, "mul", 679702Slinton DIV, "div", 689702Slinton OR, "bis", 699702Slinton ER, "xor", 709702Slinton AND, "bic", 719702Slinton -1, "" }; 729702Slinton 739702Slinton hopcode( f, o ){ 749702Slinton /* output the appropriate string from the above table */ 759702Slinton 769702Slinton register struct hoptab *q; 779702Slinton 789702Slinton for( q = ioptab; q->opmask>=0; ++q ){ 799702Slinton if( q->opmask == o ){ 809702Slinton printf( "%s", q->opstring ); 819702Slinton /* tbl 829702Slinton if( f == 'F' ) printf( "e" ); 839702Slinton else if( f == 'D' ) printf( "d" ); 849702Slinton tbl */ 859702Slinton /* tbl */ 869702Slinton switch( f ) { 879702Slinton case 'L': 889702Slinton case 'W': 899702Slinton case 'B': 909702Slinton case 'D': 919702Slinton case 'F': 929702Slinton printf("%c", tolower(f)); 939702Slinton break; 949702Slinton 959702Slinton } 969702Slinton /* tbl */ 979702Slinton return; 989702Slinton } 999702Slinton } 1009702Slinton cerror( "no hoptab for %s", opst[o] ); 1019702Slinton } 1029702Slinton 1039702Slinton char * 1049702Slinton rnames[] = { /* keyed to register number tokens */ 1059702Slinton 1069702Slinton "r0", "r1", 1079702Slinton "r2", "r3", "r4", "r5", 1089702Slinton "r6", "r7", "r8", "r9", "r10", "r11", 1099702Slinton "ap", "fp", "sp", "pc", 1109702Slinton 1119702Slinton }; 1129702Slinton 1139702Slinton int rstatus[] = { 1149702Slinton SAREG|STAREG, SAREG|STAREG, 1159702Slinton SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, 1169702Slinton SAREG, SAREG, SAREG, SAREG, SAREG, SAREG, 1179702Slinton SAREG, SAREG, SAREG, SAREG, 1189702Slinton 1199702Slinton }; 1209702Slinton 1219702Slinton tlen(p) NODE *p; 1229702Slinton { 1239702Slinton switch(p->in.type) { 1249702Slinton case CHAR: 1259702Slinton case UCHAR: 1269702Slinton return(1); 1279702Slinton 1289702Slinton case SHORT: 1299702Slinton case USHORT: 1309702Slinton return(2); 1319702Slinton 1329702Slinton case DOUBLE: 1339702Slinton return(8); 1349702Slinton 1359702Slinton default: 1369702Slinton return(4); 1379702Slinton } 1389702Slinton } 1399702Slinton 1409702Slinton mixtypes(p, q) NODE *p, *q; 1419702Slinton { 14216181Sralph register TWORD tp, tq; 1439702Slinton 1449702Slinton tp = p->in.type; 1459702Slinton tq = q->in.type; 1469702Slinton 1479702Slinton return( (tp==FLOAT || tp==DOUBLE) != 1489702Slinton (tq==FLOAT || tq==DOUBLE) ); 1499702Slinton } 1509702Slinton 1519702Slinton prtype(n) NODE *n; 1529702Slinton { 1539702Slinton switch (n->in.type) 1549702Slinton { 1559702Slinton case DOUBLE: 1569702Slinton printf("d"); 1579702Slinton return; 1589702Slinton 1599702Slinton case FLOAT: 1609702Slinton printf("f"); 1619702Slinton return; 1629702Slinton 1639702Slinton case LONG: 1649702Slinton case ULONG: 1659702Slinton case INT: 1669702Slinton case UNSIGNED: 1679702Slinton printf("l"); 1689702Slinton return; 1699702Slinton 1709702Slinton case SHORT: 1719702Slinton case USHORT: 1729702Slinton printf("w"); 1739702Slinton return; 1749702Slinton 1759702Slinton case CHAR: 1769702Slinton case UCHAR: 1779702Slinton printf("b"); 1789702Slinton return; 1799702Slinton 1809702Slinton default: 1819702Slinton if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type"); 1829702Slinton else { 1839702Slinton printf("l"); 1849702Slinton return; 1859702Slinton } 1869702Slinton } 1879702Slinton } 1889702Slinton 1899702Slinton zzzcode( p, c ) register NODE *p; { 1909702Slinton register m; 1919702Slinton CONSZ val; 1929702Slinton switch( c ){ 1939702Slinton 1949702Slinton case 'N': /* logical ops, turned into 0-1 */ 1959702Slinton /* use register given by register 1 */ 1969702Slinton cbgen( 0, m=getlab(), 'I' ); 1979702Slinton deflab( p->bn.label ); 1989702Slinton printf( " clrl %s\n", rnames[getlr( p, '1' )->tn.rval] ); 1999702Slinton deflab( m ); 2009702Slinton return; 2019702Slinton 2029702Slinton case 'I': 2039702Slinton case 'P': 2049702Slinton cbgen( p->in.op, p->bn.label, c ); 2059702Slinton return; 2069702Slinton 2079702Slinton case 'A': 2089702Slinton { 2099702Slinton register NODE *l, *r; 2109702Slinton 2119702Slinton if (xdebug) eprint(p, 0, &val, &val); 2129702Slinton r = getlr(p, 'R'); 21316181Sralph if (p->in.op == ASSIGN) 21416181Sralph l = getlr(p, 'L'); 21517208Sralph else if (p->in.op == SCONV) { 2169702Slinton l = resc; 21717742Sralph #if defined(FORT) || defined(SPRECC) 21816181Sralph l->in.type = r->in.type; 21916181Sralph #else 22016181Sralph l->in.type = r->in.type==FLOAT ? DOUBLE : r->in.type; 22116181Sralph #endif 22216181Sralph r = getlr(p, 'L'); 22316181Sralph } 22417208Sralph else { /* OPLTYPE */ 22516181Sralph l = resc; 22617742Sralph #if defined(FORT) || defined(SPRECC) 22716181Sralph l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT); 22816181Sralph #else 2299702Slinton l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? DOUBLE : INT); 23016181Sralph #endif 2319702Slinton } 2329702Slinton if (r->in.op == ICON) 23317208Sralph if (r->in.name[0] == '\0') { 23417208Sralph if (r->tn.lval == 0) { 2359702Slinton printf("clr"); 2369702Slinton prtype(l); 2379702Slinton printf(" "); 2389702Slinton adrput(l); 2399702Slinton return; 2409702Slinton } 24117208Sralph if (r->tn.lval < 0 && r->tn.lval >= -63) { 2429702Slinton printf("mneg"); 2439702Slinton prtype(l); 2449702Slinton r->tn.lval = -r->tn.lval; 2459702Slinton goto ops; 2469702Slinton } 24717208Sralph if (r->tn.lval < 0) 24817208Sralph r->in.type = r->tn.lval >= -128 ? CHAR 2499702Slinton : (r->tn.lval >= -32768 ? SHORT 25017208Sralph : INT); 25117208Sralph else if (l->in.type == FLOAT || 25217208Sralph l->in.type == DOUBLE) 25317208Sralph r->in.type = r->tn.lval <= 63 ? INT 25417208Sralph : (r->tn.lval <= 127 ? CHAR 25517208Sralph : (r->tn.lval <= 32767 ? SHORT 25617208Sralph : INT)); 25717208Sralph else 25817208Sralph r->in.type = r->tn.lval <= 63 ? INT 25917208Sralph : (r->tn.lval <= 127 ? CHAR 2609702Slinton : (r->tn.lval <= 255 ? UCHAR 2619702Slinton : (r->tn.lval <= 32767 ? SHORT 2629702Slinton : (r->tn.lval <= 65535 ? USHORT 26317208Sralph : INT)))); 2649702Slinton } 26517208Sralph else { 26616181Sralph printf("moval"); 26716181Sralph printf(" "); 26816181Sralph acon(r); 26916181Sralph printf(","); 27016181Sralph adrput(l); 27116181Sralph return; 27216181Sralph } 2739702Slinton 274*23536Sbloom if (p->in.op == SCONV && 275*23536Sbloom !(l->in.type == FLOAT || l->in.type == DOUBLE) && 276*23536Sbloom !mixtypes(l, r)) { 277*23536Sbloom /* 278*23536Sbloom * Because registers must always contain objects 279*23536Sbloom * of the same width as INTs, we may have to 280*23536Sbloom * perform two conversions to get an INT. Can 281*23536Sbloom * the conversions be collapsed into one? 282*23536Sbloom */ 283*23536Sbloom if (m = collapsible(l, r)) 284*23536Sbloom r->in.type = m; 285*23536Sbloom else { 286*23536Sbloom /* 287*23536Sbloom * Two steps are required. 288*23536Sbloom */ 289*23536Sbloom NODE *x = &resc[1]; 290*23536Sbloom 291*23536Sbloom *x = *l; 292*23536Sbloom if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type)) 29316181Sralph printf("movz"); 2949702Slinton else 2959702Slinton printf("cvt"); 296*23536Sbloom prtype(r); 297*23536Sbloom prtype(x); 298*23536Sbloom printf("\t"); 299*23536Sbloom adrput(r); 300*23536Sbloom printf(","); 301*23536Sbloom adrput(x); 302*23536Sbloom printf("\n\t"); 303*23536Sbloom r = x; 3049702Slinton } 305*23536Sbloom l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT); 3069702Slinton } 307*23536Sbloom 30817208Sralph if (!mixtypes(l,r)) { 30917208Sralph if (tlen(l) == tlen(r)) { 3109702Slinton printf("mov"); 31117742Sralph #ifdef FORT 31217742Sralph if (Oflag) 31317742Sralph prtype(l); 31417742Sralph else { 31517742Sralph if (l->in.type == DOUBLE) 31617742Sralph printf("q"); 31717742Sralph else if(l->in.type == FLOAT) 31817742Sralph printf("l"); 31917742Sralph else 32017742Sralph prtype(l); 32117742Sralph } 32217742Sralph #else 3239702Slinton prtype(l); 32417742Sralph #endif FORT 3259702Slinton goto ops; 3269702Slinton } 3279702Slinton else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type)) 3289702Slinton printf("movz"); 3299702Slinton else 3309702Slinton printf("cvt"); 3319702Slinton } 3329702Slinton else 3339702Slinton printf("cvt"); 3349702Slinton prtype(r); 3359702Slinton prtype(l); 3369702Slinton ops: 3379702Slinton printf(" "); 3389702Slinton adrput(r); 3399702Slinton printf(","); 3409702Slinton adrput(l); 3419702Slinton return; 3429702Slinton } 3439702Slinton 3449702Slinton case 'B': /* get oreg value in temp register for left shift */ 3459702Slinton { 3469702Slinton register NODE *r; 3479702Slinton if (xdebug) eprint(p, 0, &val, &val); 3489702Slinton r = p->in.right; 3499702Slinton if( tlen(r) == sizeof(int) && r->in.type != FLOAT ) 3509702Slinton printf("movl"); 3519702Slinton else { 3529702Slinton printf("cvt"); 3539702Slinton prtype(r); 3549702Slinton printf("l"); 3559702Slinton } 3569702Slinton return; 3579702Slinton } 3589702Slinton 3599702Slinton case 'C': /* num words pushed on arg stack */ 3609702Slinton { 3619702Slinton extern int gc_numbytes; 3629702Slinton extern int xdebug; 3639702Slinton 3649702Slinton if (xdebug) printf("->%d<-",gc_numbytes); 3659702Slinton 3669702Slinton printf("$%d", gc_numbytes/(SZLONG/SZCHAR) ); 3679702Slinton return; 3689702Slinton } 3699702Slinton 3709702Slinton case 'D': /* INCR and DECR */ 3719702Slinton zzzcode(p->in.left, 'A'); 3729702Slinton printf("\n "); 3739702Slinton 3749702Slinton case 'E': /* INCR and DECR, FOREFF */ 3759702Slinton if (p->in.right->tn.lval == 1) 3769702Slinton { 3779702Slinton printf("%s", (p->in.op == INCR ? "inc" : "dec") ); 3789702Slinton prtype(p->in.left); 3799702Slinton printf(" "); 3809702Slinton adrput(p->in.left); 3819702Slinton return; 3829702Slinton } 3839702Slinton printf("%s", (p->in.op == INCR ? "add" : "sub") ); 3849702Slinton prtype(p->in.left); 3859702Slinton printf("2 "); 3869702Slinton adrput(p->in.right); 3879702Slinton printf(","); 3889702Slinton adrput(p->in.left); 3899702Slinton return; 3909702Slinton 3919702Slinton case 'F': /* register type of right operand */ 3929702Slinton { 3939702Slinton register NODE *n; 3949702Slinton extern int xdebug; 3959702Slinton register int ty; 3969702Slinton 3979702Slinton n = getlr( p, 'R' ); 3989702Slinton ty = n->in.type; 3999702Slinton 4009702Slinton if (xdebug) printf("->%d<-", ty); 4019702Slinton 4029702Slinton if ( ty==DOUBLE) printf("d"); 4039702Slinton else if ( ty==FLOAT ) printf("f"); 4049702Slinton else printf("l"); 4059702Slinton return; 4069702Slinton } 4079702Slinton 4089702Slinton case 'L': /* type of left operand */ 4099702Slinton case 'R': /* type of right operand */ 4109702Slinton { 4119702Slinton register NODE *n; 4129702Slinton extern int xdebug; 4139702Slinton 41416181Sralph n = getlr( p, c ); 4159702Slinton if (xdebug) printf("->%d<-", n->in.type); 4169702Slinton 4179702Slinton prtype(n); 4189702Slinton return; 4199702Slinton } 4209702Slinton 4219702Slinton case 'Z': /* complement mask for bit instr */ 4229702Slinton printf("$%ld", ~p->in.right->tn.lval); 4239702Slinton return; 4249702Slinton 4259702Slinton case 'U': /* 32 - n, for unsigned right shifts */ 4269702Slinton printf("$%d", 32 - p->in.right->tn.lval ); 4279702Slinton return; 4289702Slinton 4299702Slinton case 'T': /* rounded structure length for arguments */ 4309702Slinton { 4319702Slinton int size; 4329702Slinton 4339702Slinton size = p->stn.stsize; 4349702Slinton SETOFF( size, 4); 4359702Slinton printf("$%d", size); 4369702Slinton return; 4379702Slinton } 4389702Slinton 4399702Slinton case 'S': /* structure assignment */ 4409702Slinton { 4419702Slinton register NODE *l, *r; 4429702Slinton register size; 4439702Slinton 4449702Slinton if( p->in.op == STASG ){ 4459702Slinton l = p->in.left; 4469702Slinton r = p->in.right; 4479702Slinton 4489702Slinton } 4499702Slinton else if( p->in.op == STARG ){ /* store an arg into a temporary */ 4509702Slinton r = p->in.left; 4519702Slinton } 4529702Slinton else cerror( "STASG bad" ); 4539702Slinton 4549702Slinton if( r->in.op == ICON ) r->in.op = NAME; 4559702Slinton else if( r->in.op == REG ) r->in.op = OREG; 4569702Slinton else if( r->in.op != OREG ) cerror( "STASG-r" ); 4579702Slinton 4589702Slinton size = p->stn.stsize; 4599702Slinton 4609702Slinton if( size <= 0 || size > 65535 ) 4619702Slinton cerror("structure size <0=0 or >65535"); 4629702Slinton 4639702Slinton switch(size) { 4649702Slinton case 1: 4659702Slinton printf(" movb "); 4669702Slinton break; 4679702Slinton case 2: 4689702Slinton printf(" movw "); 4699702Slinton break; 4709702Slinton case 4: 4719702Slinton printf(" movl "); 4729702Slinton break; 4739702Slinton case 8: 4749702Slinton printf(" movq "); 4759702Slinton break; 4769702Slinton default: 4779702Slinton printf(" movc3 $%d,", size); 4789702Slinton break; 4799702Slinton } 4809702Slinton adrput(r); 48116418Sralph if( p->in.op == STASG ){ 48216418Sralph printf(","); 48316418Sralph adrput(l); 48416418Sralph printf("\n"); 48516418Sralph } 48616418Sralph else 48716418Sralph printf(",(sp)\n"); 4889702Slinton 4899702Slinton if( r->in.op == NAME ) r->in.op = ICON; 4909702Slinton else if( r->in.op == OREG ) r->in.op = REG; 4919702Slinton 4929702Slinton } 4939702Slinton break; 4949702Slinton 4959702Slinton default: 4969702Slinton cerror( "illegal zzzcode" ); 4979702Slinton } 4989702Slinton } 4999702Slinton 500*23536Sbloom /* 501*23536Sbloom * collapsible(dest, src) -- if a conversion with a register destination 502*23536Sbloom * can be accomplished in one instruction, return the type of src 503*23536Sbloom * that will do the job correctly; otherwise return 0. Note that 504*23536Sbloom * a register must always end up having type INT or UNSIGNED. 505*23536Sbloom */ 506*23536Sbloom int 507*23536Sbloom collapsible(dest, src) 508*23536Sbloom NODE *dest, *src; 509*23536Sbloom { 510*23536Sbloom int st = src->in.type; 511*23536Sbloom int dt = dest->in.type; 512*23536Sbloom int newt = 0; 513*23536Sbloom 514*23536Sbloom /* 515*23536Sbloom * Are there side effects of evaluating src? 516*23536Sbloom * If the derived type will not be the same size as src, 517*23536Sbloom * we have to use two steps. 518*23536Sbloom */ 519*23536Sbloom if (tlen(src) > tlen(dest) && tshape(src, STARREG)) 520*23536Sbloom return (0); 521*23536Sbloom 522*23536Sbloom /* 523*23536Sbloom * Can we get an object of dest's type by punning src? 524*23536Sbloom * Praises be to great Cthulhu for little-endian machines... 525*23536Sbloom */ 526*23536Sbloom if (st == CHAR && dt == USHORT) 527*23536Sbloom /* 528*23536Sbloom * Special case -- we must sign-extend to 16 bits. 529*23536Sbloom */ 530*23536Sbloom return (0); 531*23536Sbloom 532*23536Sbloom if (tlen(src) < tlen(dest)) 533*23536Sbloom newt = st; 534*23536Sbloom else 535*23536Sbloom newt = dt; 536*23536Sbloom 537*23536Sbloom return (newt); 538*23536Sbloom } 539*23536Sbloom 54017742Sralph rmove( rt, rs, t ) TWORD t; { 5419702Slinton printf( " %s %s,%s\n", 54217742Sralph #ifdef FORT 54317742Sralph !Oflag ? (t==DOUBLE ? "movq" : "movl") : 54417742Sralph #endif 5459702Slinton (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")), 5469702Slinton rnames[rs], rnames[rt] ); 5479702Slinton } 5489702Slinton 5499702Slinton struct respref 5509702Slinton respref[] = { 5519702Slinton INTAREG|INTBREG, INTAREG|INTBREG, 5529702Slinton INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON, 5539702Slinton INTEMP, INTEMP, 5549702Slinton FORARG, FORARG, 5559702Slinton INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM, 5569702Slinton 0, 0 }; 5579702Slinton 5589702Slinton setregs(){ /* set up temporary registers */ 5599702Slinton fregs = 6; /* tbl- 6 free regs on VAX (0-5) */ 5609702Slinton ; 5619702Slinton } 5629702Slinton 56317742Sralph szty(t) TWORD t; { /* size, in registers, needed to hold thing of type t */ 56417742Sralph #if defined(FORT) || defined(SPRECC) 56516181Sralph return( (t==DOUBLE) ? 2 : 1 ); 56616181Sralph #else 5679702Slinton return( (t==DOUBLE||t==FLOAT) ? 2 : 1 ); 56816181Sralph #endif 5699702Slinton } 5709702Slinton 5719702Slinton rewfld( p ) NODE *p; { 5729702Slinton return(1); 5739702Slinton } 5749702Slinton 5759702Slinton callreg(p) NODE *p; { 5769702Slinton return( R0 ); 5779702Slinton } 5789702Slinton 5799702Slinton base( p ) register NODE *p; { 5809702Slinton register int o = p->in.op; 5819702Slinton 5829702Slinton if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */ 5839702Slinton if( o==REG ) return( p->tn.rval ); 5849702Slinton if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON) 5859702Slinton return( p->in.left->tn.rval ); 5869702Slinton if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 5879702Slinton return( p->tn.rval + 0200*1 ); 5889702Slinton if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 ); 5899702Slinton if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 ); 5909702Slinton if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG 5919702Slinton && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 5929702Slinton return( p->in.left->in.left->tn.rval + 0200*(1+2) ); 5939702Slinton return( -1 ); 5949702Slinton } 5959702Slinton 5969702Slinton offset( p, tyl ) register NODE *p; int tyl; { 5979702Slinton 5989702Slinton if( tyl==1 && p->in.op==REG && (p->in.type==INT || p->in.type==UNSIGNED) ) return( p->tn.rval ); 5999702Slinton if( (p->in.op==LS && p->in.left->in.op==REG && (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 6009702Slinton (p->in.right->in.op==ICON && p->in.right->in.name[0]=='\0') 6019702Slinton && (1<<p->in.right->tn.lval)==tyl)) 6029702Slinton return( p->in.left->tn.rval ); 6039702Slinton return( -1 ); 6049702Slinton } 6059702Slinton 6069702Slinton makeor2( p, q, b, o) register NODE *p, *q; register int b, o; { 6079702Slinton register NODE *t; 6089702Slinton register int i; 6099702Slinton NODE *f; 6109702Slinton 6119702Slinton p->in.op = OREG; 6129702Slinton f = p->in.left; /* have to free this subtree later */ 6139702Slinton 6149702Slinton /* init base */ 6159702Slinton switch (q->in.op) { 6169702Slinton case ICON: 6179702Slinton case REG: 6189702Slinton case OREG: 6199702Slinton t = q; 6209702Slinton break; 6219702Slinton 6229702Slinton case MINUS: 6239702Slinton q->in.right->tn.lval = -q->in.right->tn.lval; 6249702Slinton case PLUS: 6259702Slinton t = q->in.right; 6269702Slinton break; 6279702Slinton 6289702Slinton case INCR: 6299702Slinton case ASG MINUS: 6309702Slinton t = q->in.left; 6319702Slinton break; 6329702Slinton 6339702Slinton case UNARY MUL: 6349702Slinton t = q->in.left->in.left; 6359702Slinton break; 6369702Slinton 6379702Slinton default: 6389702Slinton cerror("illegal makeor2"); 6399702Slinton } 6409702Slinton 6419702Slinton p->tn.lval = t->tn.lval; 6429702Slinton #ifndef FLEXNAMES 6439702Slinton for(i=0; i<NCHNAM; ++i) 6449702Slinton p->in.name[i] = t->in.name[i]; 6459702Slinton #else 6469702Slinton p->in.name = t->in.name; 6479702Slinton #endif 6489702Slinton 6499702Slinton /* init offset */ 6509702Slinton p->tn.rval = R2PACK( (b & 0177), o, (b>>7) ); 6519702Slinton 6529702Slinton tfree(f); 6539702Slinton return; 6549702Slinton } 6559702Slinton 6569702Slinton canaddr( p ) NODE *p; { 6579702Slinton register int o = p->in.op; 6589702Slinton 6599702Slinton if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1); 6609702Slinton return(0); 6619702Slinton } 6629702Slinton 6639702Slinton shltype( o, p ) register NODE *p; { 6649702Slinton return( o== REG || o == NAME || o == ICON || o == OREG || ( o==UNARY MUL && shumul(p->in.left)) ); 6659702Slinton } 6669702Slinton 6679702Slinton flshape( p ) register NODE *p; { 6689702Slinton return( p->in.op == REG || p->in.op == NAME || p->in.op == ICON || 6699702Slinton (p->in.op == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) ); 6709702Slinton } 6719702Slinton 6729702Slinton shtemp( p ) register NODE *p; { 6739702Slinton if( p->in.op == STARG ) p = p->in.left; 6749702Slinton return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) ); 6759702Slinton } 6769702Slinton 6779702Slinton shumul( p ) register NODE *p; { 6789702Slinton register o; 6799702Slinton extern int xdebug; 6809702Slinton 6819702Slinton if (xdebug) { 6829702Slinton printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op); 6839702Slinton printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval); 6849702Slinton } 6859702Slinton 6869702Slinton 6879702Slinton o = p->in.op; 6889702Slinton if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM ); 6899702Slinton 6909702Slinton if( ( o == INCR || o == ASG MINUS ) && 6919702Slinton ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) && 6929702Slinton p->in.right->in.name[0] == '\0' ) 6939702Slinton { 69417659Sralph switch (p->in.type) 6959702Slinton { 6969702Slinton case CHAR|PTR: 6979702Slinton case UCHAR|PTR: 6989702Slinton o = 1; 6999702Slinton break; 7009702Slinton 7019702Slinton case SHORT|PTR: 7029702Slinton case USHORT|PTR: 7039702Slinton o = 2; 7049702Slinton break; 7059702Slinton 7069702Slinton case INT|PTR: 7079702Slinton case UNSIGNED|PTR: 7089702Slinton case LONG|PTR: 7099702Slinton case ULONG|PTR: 7109702Slinton case FLOAT|PTR: 7119702Slinton o = 4; 7129702Slinton break; 7139702Slinton 7149702Slinton case DOUBLE|PTR: 7159702Slinton o = 8; 7169702Slinton break; 7179702Slinton 7189702Slinton default: 71917742Sralph if ( ISPTR(p->in.type) && 72017742Sralph ISPTR(DECREF(p->in.type)) ) { 7219702Slinton o = 4; 7229702Slinton break; 7239702Slinton } 7249702Slinton else return(0); 7259702Slinton } 7269702Slinton return( p->in.right->tn.lval == o ? STARREG : 0); 7279702Slinton } 7289702Slinton 7299702Slinton return( 0 ); 7309702Slinton } 7319702Slinton 7329702Slinton adrcon( val ) CONSZ val; { 7339702Slinton printf( "$" ); 7349702Slinton printf( CONFMT, val ); 7359702Slinton } 7369702Slinton 7379702Slinton conput( p ) register NODE *p; { 7389702Slinton switch( p->in.op ){ 7399702Slinton 7409702Slinton case ICON: 7419702Slinton acon( p ); 7429702Slinton return; 7439702Slinton 7449702Slinton case REG: 7459702Slinton printf( "%s", rnames[p->tn.rval] ); 7469702Slinton return; 7479702Slinton 7489702Slinton default: 7499702Slinton cerror( "illegal conput" ); 7509702Slinton } 7519702Slinton } 7529702Slinton 7539702Slinton insput( p ) register NODE *p; { 7549702Slinton cerror( "insput" ); 7559702Slinton } 7569702Slinton 7579702Slinton upput( p ) register NODE *p; { 7589702Slinton cerror( "upput" ); 7599702Slinton } 7609702Slinton 7619702Slinton adrput( p ) register NODE *p; { 7629702Slinton register int r; 7639702Slinton /* output an address, with offsets, from p */ 7649702Slinton 7659702Slinton if( p->in.op == FLD ){ 7669702Slinton p = p->in.left; 7679702Slinton } 7689702Slinton switch( p->in.op ){ 7699702Slinton 7709702Slinton case NAME: 7719702Slinton acon( p ); 7729702Slinton return; 7739702Slinton 7749702Slinton case ICON: 7759702Slinton /* addressable value of the constant */ 7769702Slinton printf( "$" ); 7779702Slinton acon( p ); 7789702Slinton return; 7799702Slinton 7809702Slinton case REG: 7819702Slinton printf( "%s", rnames[p->tn.rval] ); 7829702Slinton return; 7839702Slinton 7849702Slinton case OREG: 7859702Slinton r = p->tn.rval; 7869702Slinton if( R2TEST(r) ){ /* double indexing */ 7879702Slinton register int flags; 7889702Slinton 7899702Slinton flags = R2UPK3(r); 7909702Slinton if( flags & 1 ) printf("*"); 7919702Slinton if( flags & 4 ) printf("-"); 7929702Slinton if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p); 7939702Slinton if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] ); 7949702Slinton if( flags & 2 ) printf("+"); 7959702Slinton printf( "[%s]", rnames[R2UPK2(r)] ); 7969702Slinton return; 7979702Slinton } 7989702Slinton if( r == AP ){ /* in the argument region */ 7999702Slinton if( p->tn.lval <= 0 || p->in.name[0] != '\0' ) werror( "bad arg temp" ); 8009702Slinton printf( CONFMT, p->tn.lval ); 8019702Slinton printf( "(ap)" ); 8029702Slinton return; 8039702Slinton } 8049702Slinton if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p ); 8059702Slinton printf( "(%s)", rnames[p->tn.rval] ); 8069702Slinton return; 8079702Slinton 8089702Slinton case UNARY MUL: 8099702Slinton /* STARNM or STARREG found */ 8109702Slinton if( tshape(p, STARNM) ) { 8119702Slinton printf( "*" ); 8129702Slinton adrput( p->in.left); 8139702Slinton } 8149702Slinton else { /* STARREG - really auto inc or dec */ 8159702Slinton register NODE *q; 8169702Slinton 8179702Slinton /* tbl 8189702Slinton p = p->in.left; 8199702Slinton p->in.left->in.op = OREG; 8209702Slinton if( p->in.op == INCR ) { 8219702Slinton adrput( p->in.left ); 8229702Slinton printf( "+" ); 8239702Slinton } 8249702Slinton else { 8259702Slinton printf( "-" ); 8269702Slinton adrput( p->in.left ); 8279702Slinton } 8289702Slinton tbl */ 82917659Sralph q = p->in.left; 83017742Sralph if( q->in.right->tn.lval != tlen(p) ) 83117742Sralph cerror("adrput: bad auto-increment/decrement"); 83217659Sralph printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"), 83317659Sralph rnames[q->in.left->tn.rval], 83417659Sralph (q->in.op==INCR ? "+" : "") ); 8359702Slinton p->in.op = OREG; 83617659Sralph p->tn.rval = q->in.left->tn.rval; 83717659Sralph p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0); 8389702Slinton #ifndef FLEXNAMES 8399702Slinton p->in.name[0] = '\0'; 8409702Slinton #else 8419702Slinton p->in.name = ""; 8429702Slinton #endif 8439702Slinton tfree(q); 8449702Slinton } 8459702Slinton return; 8469702Slinton 8479702Slinton default: 8489702Slinton cerror( "illegal address" ); 8499702Slinton return; 8509702Slinton 8519702Slinton } 8529702Slinton 8539702Slinton } 8549702Slinton 8559702Slinton acon( p ) register NODE *p; { /* print out a constant */ 8569702Slinton 8579702Slinton if( p->in.name[0] == '\0' ){ 8589702Slinton printf( CONFMT, p->tn.lval); 8599702Slinton } 8609702Slinton else if( p->tn.lval == 0 ) { 8619702Slinton #ifndef FLEXNAMES 8629702Slinton printf( "%.8s", p->in.name ); 8639702Slinton #else 8649702Slinton printf( "%s", p->in.name ); 8659702Slinton #endif 8669702Slinton } 8679702Slinton else { 8689702Slinton #ifndef FLEXNAMES 8699702Slinton printf( "%.8s+", p->in.name ); 8709702Slinton #else 8719702Slinton printf( "%s+", p->in.name ); 8729702Slinton #endif 8739702Slinton printf( CONFMT, p->tn.lval ); 8749702Slinton } 8759702Slinton } 8769702Slinton 8779702Slinton /* 8789702Slinton aacon( p ) register NODE *p; { /* print out a constant */ 8799702Slinton /* 8809702Slinton 8819702Slinton if( p->in.name[0] == '\0' ){ 8829702Slinton printf( CONFMT, p->tn.lval); 8839702Slinton return( 0 ); 8849702Slinton } 8859702Slinton else if( p->tn.lval == 0 ) { 8869702Slinton #ifndef FLEXNAMES 8879702Slinton printf( "$%.8s", p->in.name ); 8889702Slinton #else 8899702Slinton printf( "$%s", p->in.name ); 8909702Slinton #endif 8919702Slinton return( 1 ); 8929702Slinton } 8939702Slinton else { 8949702Slinton printf( "$(" ); 8959702Slinton printf( CONFMT, p->tn.lval ); 8969702Slinton printf( "+" ); 8979702Slinton #ifndef FLEXNAMES 8989702Slinton printf( "%.8s)", p->in.name ); 8999702Slinton #else 9009702Slinton printf( "%s)", p->in.name ); 9019702Slinton #endif 9029702Slinton return(1); 9039702Slinton } 9049702Slinton } 9059702Slinton */ 9069702Slinton 9079702Slinton genscall( p, cookie ) register NODE *p; { 9089702Slinton /* structure valued call */ 9099702Slinton return( gencall( p, cookie ) ); 9109702Slinton } 9119702Slinton 9129702Slinton /* tbl */ 9139702Slinton int gc_numbytes; 9149702Slinton /* tbl */ 9159702Slinton 9169702Slinton gencall( p, cookie ) register NODE *p; { 9179702Slinton /* generate the call given by p */ 91816418Sralph register NODE *p1; 9199702Slinton register temp, temp1; 9209702Slinton register m; 9219702Slinton 9229702Slinton if( p->in.right ) temp = argsize( p->in.right ); 9239702Slinton else temp = 0; 9249702Slinton 9259702Slinton if( p->in.op == STCALL || p->in.op == UNARY STCALL ){ 9269702Slinton /* set aside room for structure return */ 9279702Slinton 9289702Slinton if( p->stn.stsize > temp ) temp1 = p->stn.stsize; 9299702Slinton else temp1 = temp; 9309702Slinton } 9319702Slinton 9329702Slinton if( temp > maxargs ) maxargs = temp; 9339702Slinton SETOFF(temp1,4); 9349702Slinton 9359702Slinton if( p->in.right ){ /* make temp node, put offset in, and generate args */ 93616418Sralph genargs( p->in.right ); 9379702Slinton } 9389702Slinton 9399702Slinton p1 = p->in.left; 9409702Slinton if( p1->in.op != ICON ){ 9419702Slinton if( p1->in.op != REG ){ 9429702Slinton if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){ 9439702Slinton if( p1->in.op != NAME ){ 9449702Slinton order( p1, INAREG ); 9459702Slinton } 9469702Slinton } 9479702Slinton } 9489702Slinton } 9499702Slinton 9509702Slinton /* 9519702Slinton if( p1->in.op == REG && p->tn.rval == R5 ){ 9529702Slinton cerror( "call register overwrite" ); 9539702Slinton } 9549702Slinton */ 9559702Slinton /* tbl 9569702Slinton setup gc_numbytes so reference to ZC works */ 9579702Slinton 9589702Slinton gc_numbytes = temp&(0x3ff); 9599702Slinton /* tbl */ 9609702Slinton 9619702Slinton p->in.op = UNARY CALL; 9629702Slinton m = match( p, INTAREG|INTBREG ); 9639702Slinton 9649702Slinton /* compensate for deficiency in 'ret' instruction ... wah,kre */ 9659702Slinton /* (plus in assignment to gc_numbytes above, for neatness only) */ 9669702Slinton if (temp >= 1024) 9679702Slinton printf(" addl2 $%d,sp\n", (temp&(~0x3ff))); 9689702Slinton 9699702Slinton /* tbl 9709702Slinton switch( temp ) { 9719702Slinton case 0: 9729702Slinton break; 9739702Slinton case 2: 9749702Slinton printf( " tst (sp)+\n" ); 9759702Slinton break; 9769702Slinton case 4: 9779702Slinton printf( " cmp (sp)+,(sp)+\n" ); 9789702Slinton break; 9799702Slinton default: 9809702Slinton printf( " add $%d,sp\n", temp); 9819702Slinton } 9829702Slinton tbl */ 9839702Slinton return(m != MDONE); 9849702Slinton } 9859702Slinton 9869702Slinton /* tbl */ 9879702Slinton char * 9889702Slinton ccbranches[] = { 9899702Slinton " jeql L%d\n", 9909702Slinton " jneq L%d\n", 9919702Slinton " jleq L%d\n", 9929702Slinton " jlss L%d\n", 9939702Slinton " jgeq L%d\n", 9949702Slinton " jgtr L%d\n", 9959702Slinton " jlequ L%d\n", 9969702Slinton " jlssu L%d\n", 9979702Slinton " jgequ L%d\n", 9989702Slinton " jgtru L%d\n", 9999702Slinton }; 10009702Slinton /* tbl */ 10019702Slinton 10029702Slinton cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */ 10039702Slinton 10049702Slinton /* tbl */ 10059702Slinton if( o == 0 ) printf( " jbr L%d\n", lab ); 10069702Slinton /* tbl */ 10079702Slinton else { 10089702Slinton if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] ); 10099702Slinton printf( ccbranches[o-EQ], lab ); 10109702Slinton } 10119702Slinton } 10129702Slinton 10139702Slinton nextcook( p, cookie ) NODE *p; { 10149702Slinton /* we have failed to match p with cookie; try another */ 10159702Slinton if( cookie == FORREW ) return( 0 ); /* hopeless! */ 10169702Slinton if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG ); 10179702Slinton if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG ); 10189702Slinton return( FORREW ); 10199702Slinton } 10209702Slinton 10219702Slinton lastchance( p, cook ) NODE *p; { 10229702Slinton /* forget it! */ 10239702Slinton return(0); 10249702Slinton } 10259702Slinton 10269702Slinton optim2( p ) register NODE *p; { 10279702Slinton /* do local tree transformations and optimizations */ 10289702Slinton 102916181Sralph register NODE *l, *r; 103016181Sralph int m, ml; 10319702Slinton 10329702Slinton switch( p->in.op ) { 10339702Slinton 10349702Slinton case AND: 103519933Smckusick /* commute L and R to eliminate complements and constants */ 103616181Sralph if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 || 103716181Sralph l->in.op == COMPL ) { 10389702Slinton p->in.left = p->in.right; 103916181Sralph p->in.right = l; 10409702Slinton } 10419702Slinton case ASG AND: 10429702Slinton /* change meaning of AND to ~R&L - bic on pdp11 */ 10439702Slinton r = p->in.right; 104419933Smckusick if( r->in.op==ICON && r->in.name[0]==0 ) { /* complement constant */ 10459702Slinton r->tn.lval = ~r->tn.lval; 10469702Slinton } 10479702Slinton else if( r->in.op==COMPL ) { /* ~~A => A */ 10489702Slinton r->in.op = FREE; 10499702Slinton p->in.right = r->in.left; 10509702Slinton } 10519702Slinton else { /* insert complement node */ 105216181Sralph p->in.right = l = talloc(); 105316181Sralph l->in.op = COMPL; 105416181Sralph l->in.rall = NOPREF; 105516181Sralph l->in.type = r->in.type; 105616181Sralph l->in.left = r; 105716181Sralph l->in.right = NULL; 10589702Slinton } 10599702Slinton break; 10609702Slinton 106116181Sralph case SCONV: 106219933Smckusick l = p->in.left; 106317742Sralph #if defined(FORT) || defined(SPRECC) 106416573Sralph if( p->in.type == FLOAT || p->in.type == DOUBLE || 106519933Smckusick l->in.type == FLOAT || l->in.type == DOUBLE ) 106619933Smckusick return; 106716573Sralph #else 106819933Smckusick if( mixtypes(p, l) ) return; 106916573Sralph #endif 107019933Smckusick /* Only trust it to get it right if the size is the same */ 107119933Smckusick if( tlen(p) != tlen(l) ) 107219933Smckusick return; 107316181Sralph 107416181Sralph /* clobber conversion */ 107519933Smckusick if( l->in.op != FLD ) 107616181Sralph l->in.type = p->in.type; 107716181Sralph ncopy( p, l ); 107816181Sralph l->in.op = FREE; 107919933Smckusick 108016181Sralph break; 108116181Sralph 10829702Slinton } 10839702Slinton } 10849702Slinton 108517742Sralph NODE * addroreg(l) NODE *l; 10869702Slinton /* OREG was built in clocal() 10879702Slinton * for an auto or formal parameter 10889702Slinton * now its address is being taken 10899702Slinton * local code must unwind it 10909702Slinton * back to PLUS/MINUS REG ICON 10919702Slinton * according to local conventions 10929702Slinton */ 10939702Slinton { 10949702Slinton cerror("address of OREG taken"); 109517742Sralph /*NOTREACHED*/ 10969702Slinton } 10979702Slinton 10989702Slinton 10999702Slinton 11009702Slinton # ifndef ONEPASS 11019702Slinton main( argc, argv ) char *argv[]; { 11029702Slinton return( mainp2( argc, argv ) ); 11039702Slinton } 11049702Slinton # endif 11059702Slinton 11069702Slinton 11079702Slinton /* added by jwf */ 11089702Slinton struct functbl { 11099702Slinton int fop; 11109702Slinton TWORD ftype; 11119702Slinton char *func; 11129702Slinton } opfunc[] = { 11139702Slinton DIV, TANY, "udiv", 11149702Slinton MOD, TANY, "urem", 111517715Sralph ASG DIV, TANY, "audiv", 111617715Sralph ASG MOD, TANY, "aurem", 11179702Slinton 0, 0, 0 }; 11189702Slinton 11199702Slinton hardops(p) register NODE *p; { 11209702Slinton /* change hard to do operators into function calls. */ 11219702Slinton register NODE *q; 11229702Slinton register struct functbl *f; 11239702Slinton register o; 112417742Sralph NODE *old,*temp; 11259702Slinton 11269702Slinton o = p->in.op; 112717742Sralph if( ! (optype(o)==BITYPE && 112817742Sralph (ISUNSIGNED(p->in.left->in.type) || 112917742Sralph ISUNSIGNED(p->in.right->in.type))) ) 113017742Sralph return; 11319702Slinton 11329702Slinton for( f=opfunc; f->fop; f++ ) { 11339702Slinton if( o==f->fop ) goto convert; 11349702Slinton } 11359702Slinton return; 11369702Slinton 11379702Slinton convert: 11389702Slinton if( asgop( o ) ) { 113917742Sralph old = NIL; 114017715Sralph switch( p->in.left->in.op ){ 114117742Sralph case FLD: 114217742Sralph q = p->in.left->in.left; 114317742Sralph /* 114417742Sralph * rewrite (lval.fld /= rval); as 114517742Sralph * ((*temp).fld = udiv((*(temp = &lval)).fld,rval)); 114617742Sralph * else the compiler will evaluate lval twice. 114717742Sralph */ 114817742Sralph if( q->in.op == UNARY MUL ){ 114917742Sralph /* first allocate a temp storage */ 115017742Sralph temp = talloc(); 115117742Sralph temp->in.op = OREG; 115217742Sralph temp->tn.rval = TMPREG; 115317742Sralph temp->tn.lval = BITOOR(freetemp(1)); 115417742Sralph temp->in.type = INCREF(p->in.type); 115517742Sralph #ifdef FLEXNAMES 115617742Sralph temp->in.name = ""; 115717742Sralph #else 115817742Sralph temp->in.name[0] = '\0'; 115917742Sralph #endif 116017742Sralph old = q->in.left; 116117742Sralph q->in.left = temp; 116217742Sralph } 116317742Sralph /* fall thru ... */ 116417742Sralph 116517715Sralph case REG: 116617715Sralph case NAME: 116717715Sralph case OREG: 116817715Sralph /* change ASG OP to a simple OP */ 116917715Sralph q = talloc(); 117017715Sralph q->in.op = NOASG p->in.op; 117117715Sralph q->in.rall = NOPREF; 117217715Sralph q->in.type = p->in.type; 117317715Sralph q->in.left = tcopy(p->in.left); 117417715Sralph q->in.right = p->in.right; 117517715Sralph p->in.op = ASSIGN; 117617715Sralph p->in.right = q; 117717715Sralph p = q; 117817715Sralph f -= 2; /* Note: this depends on the table order */ 117917742Sralph /* on the right side only - replace *temp with 118017742Sralph *(temp = &lval), build the assignment node */ 118117742Sralph if( old ){ 118217742Sralph temp = q->in.left->in.left; /* the "*" node */ 118317742Sralph q = talloc(); 118417742Sralph q->in.op = ASSIGN; 118517742Sralph q->in.left = temp->in.left; 118617742Sralph q->in.right = old; 118717742Sralph q->in.type = old->in.type; 118817742Sralph #ifdef FLEXNAMES 118917742Sralph q->in.name = ""; 119017742Sralph #else 119117742Sralph q->in.name[0] = '\0'; 119217742Sralph #endif 119317742Sralph temp->in.left = q; 119417742Sralph } 119517715Sralph break; 11969702Slinton 119717715Sralph case UNARY MUL: 119817715Sralph /* avoid doing side effects twice */ 119917715Sralph q = p->in.left; 120017715Sralph p->in.left = q->in.left; 120117715Sralph q->in.op = FREE; 120217715Sralph break; 120317715Sralph 120417715Sralph default: 120517715Sralph cerror( "hardops: can't compute & LHS" ); 120617715Sralph } 120717742Sralph } 120817715Sralph 12099702Slinton /* build comma op for args to function */ 12109702Slinton q = talloc(); 12119702Slinton q->in.op = CM; 12129702Slinton q->in.rall = NOPREF; 12139702Slinton q->in.type = INT; 12149702Slinton q->in.left = p->in.left; 12159702Slinton q->in.right = p->in.right; 12169702Slinton p->in.op = CALL; 12179702Slinton p->in.right = q; 12189702Slinton 12199702Slinton /* put function name in left node of call */ 12209702Slinton p->in.left = q = talloc(); 12219702Slinton q->in.op = ICON; 12229702Slinton q->in.rall = NOPREF; 12239702Slinton q->in.type = INCREF( FTN + p->in.type ); 12249702Slinton #ifndef FLEXNAMES 12259702Slinton strcpy( q->in.name, f->func ); 12269702Slinton #else 12279702Slinton q->in.name = f->func; 12289702Slinton #endif 12299702Slinton q->tn.lval = 0; 12309702Slinton q->tn.rval = 0; 12319702Slinton 12329702Slinton } 12339702Slinton 123417742Sralph zappost(p) NODE *p; { 123517742Sralph /* look for ++ and -- operators and remove them */ 123617742Sralph 123717742Sralph register o, ty; 123817742Sralph register NODE *q; 123917742Sralph o = p->in.op; 124017742Sralph ty = optype( o ); 124117742Sralph 124217742Sralph switch( o ){ 124317742Sralph 124417742Sralph case INCR: 124517742Sralph case DECR: 124617742Sralph q = p->in.left; 124717742Sralph p->in.right->in.op = FREE; /* zap constant */ 124817742Sralph ncopy( p, q ); 124917742Sralph q->in.op = FREE; 125017742Sralph return; 125117742Sralph 125217742Sralph } 125317742Sralph 125417742Sralph if( ty == BITYPE ) zappost( p->in.right ); 125517742Sralph if( ty != LTYPE ) zappost( p->in.left ); 125617742Sralph } 125717742Sralph 125817742Sralph fixpre(p) NODE *p; { 125917742Sralph 126017742Sralph register o, ty; 126117742Sralph o = p->in.op; 126217742Sralph ty = optype( o ); 126317742Sralph 126417742Sralph switch( o ){ 126517742Sralph 126617742Sralph case ASG PLUS: 126717742Sralph p->in.op = PLUS; 126817742Sralph break; 126917742Sralph case ASG MINUS: 127017742Sralph p->in.op = MINUS; 127117742Sralph break; 127217742Sralph } 127317742Sralph 127417742Sralph if( ty == BITYPE ) fixpre( p->in.right ); 127517742Sralph if( ty != LTYPE ) fixpre( p->in.left ); 127617742Sralph } 127717742Sralph 12789702Slinton myreader(p) register NODE *p; { 127917742Sralph canon( p ); /* expands r-vals for fields */ 12809702Slinton walkf( p, hardops ); /* convert ops to function calls */ 12819702Slinton walkf( p, optim2 ); 12829702Slinton /* jwf toff = 0; /* stack offset swindle */ 12839702Slinton } 1284