117742Sralph # ifndef lint 2*24418Smckusick static char *sccsid ="@(#)local2.c 1.12 (Berkeley) 08/23/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 12*24418Smckusick # define putstr(s) fputs((s), stdout) 13*24418Smckusick 149702Slinton # define BITMASK(n) ((1L<<n)-1) 159702Slinton 169702Slinton where(c){ 179702Slinton fprintf( stderr, "%s, line %d: ", filename, lineno ); 189702Slinton } 199702Slinton 209702Slinton lineid( l, fn ) char *fn; { 219702Slinton /* identify line l and file fn */ 229702Slinton printf( "# line %d, file %s\n", l, fn ); 239702Slinton } 249702Slinton 259702Slinton 269702Slinton eobl2(){ 279702Slinton OFFSZ spoff; /* offset from stack pointer */ 289702Slinton #ifdef FORT 299702Slinton spoff = maxoff; 309702Slinton if( spoff >= AUTOINIT ) spoff -= AUTOINIT; 319702Slinton spoff /= SZCHAR; 329702Slinton SETOFF(spoff,4); 339702Slinton #ifndef FLEXNAMES 349702Slinton printf( " .set .F%d,%ld\n", ftnno, spoff ); 359702Slinton #else 369702Slinton /* SHOULD BE L%d ... ftnno but must change pc/f77 */ 379702Slinton printf( " .set LF%d,%ld\n", ftnno, spoff ); 389702Slinton #endif 399702Slinton #else 409702Slinton extern int ftlab1, ftlab2; 419702Slinton 429702Slinton spoff = maxoff; 439702Slinton if( spoff >= AUTOINIT ) spoff -= AUTOINIT; 449702Slinton spoff /= SZCHAR; 459702Slinton SETOFF(spoff,4); 469702Slinton printf( "L%d:\n", ftlab1); 479702Slinton if( spoff!=0 ) 489702Slinton if( spoff < 64 ) 499702Slinton printf( " subl2 $%ld,sp\n", spoff); 509702Slinton else 519702Slinton printf( " movab -%ld(sp),sp\n", spoff); 529702Slinton printf( " jbr L%d\n", ftlab2); 539702Slinton #endif 549702Slinton maxargs = -1; 559702Slinton } 569702Slinton 579702Slinton struct hoptab { int opmask; char * opstring; } ioptab[] = { 589702Slinton 599702Slinton ASG PLUS, "add", 609702Slinton ASG MINUS, "sub", 619702Slinton ASG MUL, "mul", 629702Slinton ASG DIV, "div", 639702Slinton ASG OR, "bis", 649702Slinton ASG ER, "xor", 659702Slinton ASG AND, "bic", 669702Slinton PLUS, "add", 679702Slinton MINUS, "sub", 689702Slinton MUL, "mul", 699702Slinton DIV, "div", 709702Slinton OR, "bis", 719702Slinton ER, "xor", 729702Slinton AND, "bic", 739702Slinton -1, "" }; 749702Slinton 759702Slinton hopcode( f, o ){ 769702Slinton /* output the appropriate string from the above table */ 779702Slinton 789702Slinton register struct hoptab *q; 799702Slinton 809702Slinton for( q = ioptab; q->opmask>=0; ++q ){ 819702Slinton if( q->opmask == o ){ 82*24418Smckusick putstr( q->opstring ); 839702Slinton /* tbl 84*24418Smckusick if( f == 'F' ) putchar( 'e' ); 85*24418Smckusick else if( f == 'D' ) putchar( 'd' ); 869702Slinton tbl */ 879702Slinton /* tbl */ 889702Slinton switch( f ) { 899702Slinton case 'L': 909702Slinton case 'W': 919702Slinton case 'B': 929702Slinton case 'D': 939702Slinton case 'F': 94*24418Smckusick putchar(tolower(f)); 959702Slinton break; 969702Slinton 979702Slinton } 989702Slinton /* tbl */ 999702Slinton return; 1009702Slinton } 1019702Slinton } 1029702Slinton cerror( "no hoptab for %s", opst[o] ); 1039702Slinton } 1049702Slinton 1059702Slinton char * 1069702Slinton rnames[] = { /* keyed to register number tokens */ 1079702Slinton 1089702Slinton "r0", "r1", 1099702Slinton "r2", "r3", "r4", "r5", 1109702Slinton "r6", "r7", "r8", "r9", "r10", "r11", 1119702Slinton "ap", "fp", "sp", "pc", 1129702Slinton 1139702Slinton }; 1149702Slinton 1159702Slinton int rstatus[] = { 1169702Slinton SAREG|STAREG, SAREG|STAREG, 1179702Slinton SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, SAREG|STAREG, 1189702Slinton SAREG, SAREG, SAREG, SAREG, SAREG, SAREG, 1199702Slinton SAREG, SAREG, SAREG, SAREG, 1209702Slinton 1219702Slinton }; 1229702Slinton 1239702Slinton tlen(p) NODE *p; 1249702Slinton { 1259702Slinton switch(p->in.type) { 1269702Slinton case CHAR: 1279702Slinton case UCHAR: 1289702Slinton return(1); 1299702Slinton 1309702Slinton case SHORT: 1319702Slinton case USHORT: 1329702Slinton return(2); 1339702Slinton 1349702Slinton case DOUBLE: 1359702Slinton return(8); 1369702Slinton 1379702Slinton default: 1389702Slinton return(4); 1399702Slinton } 1409702Slinton } 1419702Slinton 1429702Slinton mixtypes(p, q) NODE *p, *q; 1439702Slinton { 14416181Sralph register TWORD tp, tq; 1459702Slinton 1469702Slinton tp = p->in.type; 1479702Slinton tq = q->in.type; 1489702Slinton 1499702Slinton return( (tp==FLOAT || tp==DOUBLE) != 1509702Slinton (tq==FLOAT || tq==DOUBLE) ); 1519702Slinton } 1529702Slinton 1539702Slinton prtype(n) NODE *n; 1549702Slinton { 1559702Slinton switch (n->in.type) 1569702Slinton { 1579702Slinton case DOUBLE: 158*24418Smckusick putchar('d'); 1599702Slinton return; 1609702Slinton 1619702Slinton case FLOAT: 162*24418Smckusick putchar('f'); 1639702Slinton return; 1649702Slinton 1659702Slinton case LONG: 1669702Slinton case ULONG: 1679702Slinton case INT: 1689702Slinton case UNSIGNED: 169*24418Smckusick putchar('l'); 1709702Slinton return; 1719702Slinton 1729702Slinton case SHORT: 1739702Slinton case USHORT: 174*24418Smckusick putchar('w'); 1759702Slinton return; 1769702Slinton 1779702Slinton case CHAR: 1789702Slinton case UCHAR: 179*24418Smckusick putchar('b'); 1809702Slinton return; 1819702Slinton 1829702Slinton default: 1839702Slinton if ( !ISPTR( n->in.type ) ) cerror("zzzcode- bad type"); 1849702Slinton else { 185*24418Smckusick putchar('l'); 1869702Slinton return; 1879702Slinton } 1889702Slinton } 1899702Slinton } 1909702Slinton 1919702Slinton zzzcode( p, c ) register NODE *p; { 1929702Slinton register m; 1939702Slinton CONSZ val; 1949702Slinton switch( c ){ 1959702Slinton 1969702Slinton case 'N': /* logical ops, turned into 0-1 */ 1979702Slinton /* use register given by register 1 */ 1989702Slinton cbgen( 0, m=getlab(), 'I' ); 1999702Slinton deflab( p->bn.label ); 2009702Slinton printf( " clrl %s\n", rnames[getlr( p, '1' )->tn.rval] ); 2019702Slinton deflab( m ); 2029702Slinton return; 2039702Slinton 2049702Slinton case 'I': 2059702Slinton case 'P': 2069702Slinton cbgen( p->in.op, p->bn.label, c ); 2079702Slinton return; 2089702Slinton 2099702Slinton case 'A': 2109702Slinton { 2119702Slinton register NODE *l, *r; 2129702Slinton 2139702Slinton if (xdebug) eprint(p, 0, &val, &val); 2149702Slinton r = getlr(p, 'R'); 21516181Sralph if (p->in.op == ASSIGN) 21616181Sralph l = getlr(p, 'L'); 21717208Sralph else if (p->in.op == SCONV) { 2189702Slinton l = resc; 21917742Sralph #if defined(FORT) || defined(SPRECC) 22016181Sralph l->in.type = r->in.type; 22116181Sralph #else 22216181Sralph l->in.type = r->in.type==FLOAT ? DOUBLE : r->in.type; 22316181Sralph #endif 22416181Sralph r = getlr(p, 'L'); 22516181Sralph } 22617208Sralph else { /* OPLTYPE */ 22716181Sralph l = resc; 22817742Sralph #if defined(FORT) || defined(SPRECC) 22916181Sralph l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? r->in.type : INT); 23016181Sralph #else 2319702Slinton l->in.type = (r->in.type==FLOAT || r->in.type==DOUBLE ? DOUBLE : INT); 23216181Sralph #endif 2339702Slinton } 2349702Slinton if (r->in.op == ICON) 23517208Sralph if (r->in.name[0] == '\0') { 23617208Sralph if (r->tn.lval == 0) { 237*24418Smckusick putstr("clr"); 2389702Slinton prtype(l); 239*24418Smckusick putchar('\t'); 2409702Slinton adrput(l); 2419702Slinton return; 2429702Slinton } 24317208Sralph if (r->tn.lval < 0 && r->tn.lval >= -63) { 244*24418Smckusick putstr("mneg"); 2459702Slinton prtype(l); 2469702Slinton r->tn.lval = -r->tn.lval; 2479702Slinton goto ops; 2489702Slinton } 24917208Sralph if (r->tn.lval < 0) 25017208Sralph r->in.type = r->tn.lval >= -128 ? CHAR 2519702Slinton : (r->tn.lval >= -32768 ? SHORT 25217208Sralph : INT); 25317208Sralph else if (l->in.type == FLOAT || 25417208Sralph l->in.type == DOUBLE) 25517208Sralph r->in.type = r->tn.lval <= 63 ? INT 25617208Sralph : (r->tn.lval <= 127 ? CHAR 25717208Sralph : (r->tn.lval <= 32767 ? SHORT 25817208Sralph : INT)); 25917208Sralph else 26017208Sralph r->in.type = r->tn.lval <= 63 ? INT 26117208Sralph : (r->tn.lval <= 127 ? CHAR 2629702Slinton : (r->tn.lval <= 255 ? UCHAR 2639702Slinton : (r->tn.lval <= 32767 ? SHORT 2649702Slinton : (r->tn.lval <= 65535 ? USHORT 26517208Sralph : INT)))); 2669702Slinton } 26717208Sralph else { 268*24418Smckusick putstr("moval"); 269*24418Smckusick putchar('\t'); 27016181Sralph acon(r); 271*24418Smckusick putchar(','); 27216181Sralph adrput(l); 27316181Sralph return; 27416181Sralph } 2759702Slinton 27623536Sbloom if (p->in.op == SCONV && 27723536Sbloom !(l->in.type == FLOAT || l->in.type == DOUBLE) && 27823536Sbloom !mixtypes(l, r)) { 27923536Sbloom /* 28023536Sbloom * Because registers must always contain objects 28123536Sbloom * of the same width as INTs, we may have to 28223536Sbloom * perform two conversions to get an INT. Can 28323536Sbloom * the conversions be collapsed into one? 28423536Sbloom */ 28523536Sbloom if (m = collapsible(l, r)) 28623536Sbloom r->in.type = m; 28723536Sbloom else { 28823536Sbloom /* 28923536Sbloom * Two steps are required. 29023536Sbloom */ 29123536Sbloom NODE *x = &resc[1]; 29223536Sbloom 29323536Sbloom *x = *l; 29423536Sbloom if (tlen(x) > tlen(r) && ISUNSIGNED(r->in.type)) 295*24418Smckusick putstr("movz"); 2969702Slinton else 297*24418Smckusick putstr("cvt"); 29823536Sbloom prtype(r); 29923536Sbloom prtype(x); 300*24418Smckusick putchar('\t'); 30123536Sbloom adrput(r); 302*24418Smckusick putchar(','); 30323536Sbloom adrput(x); 304*24418Smckusick putchar('\n'); 305*24418Smckusick putchar('\t'); 30623536Sbloom r = x; 3079702Slinton } 30823536Sbloom l->in.type = (ISUNSIGNED(l->in.type) ? UNSIGNED : INT); 3099702Slinton } 31023536Sbloom 31117208Sralph if (!mixtypes(l,r)) { 31217208Sralph if (tlen(l) == tlen(r)) { 313*24418Smckusick putstr("mov"); 31417742Sralph #ifdef FORT 31517742Sralph if (Oflag) 31617742Sralph prtype(l); 31717742Sralph else { 31817742Sralph if (l->in.type == DOUBLE) 319*24418Smckusick putchar('q'); 32017742Sralph else if(l->in.type == FLOAT) 321*24418Smckusick putchar('l'); 32217742Sralph else 32317742Sralph prtype(l); 32417742Sralph } 32517742Sralph #else 3269702Slinton prtype(l); 32717742Sralph #endif FORT 3289702Slinton goto ops; 3299702Slinton } 3309702Slinton else if (tlen(l) > tlen(r) && ISUNSIGNED(r->in.type)) 331*24418Smckusick putstr("movz"); 3329702Slinton else 333*24418Smckusick putstr("cvt"); 3349702Slinton } 3359702Slinton else 336*24418Smckusick putstr("cvt"); 3379702Slinton prtype(r); 3389702Slinton prtype(l); 3399702Slinton ops: 340*24418Smckusick putchar('\t'); 3419702Slinton adrput(r); 342*24418Smckusick putchar(','); 3439702Slinton adrput(l); 3449702Slinton return; 3459702Slinton } 3469702Slinton 3479702Slinton case 'B': /* get oreg value in temp register for left shift */ 3489702Slinton { 3499702Slinton register NODE *r; 3509702Slinton if (xdebug) eprint(p, 0, &val, &val); 3519702Slinton r = p->in.right; 3529702Slinton if( tlen(r) == sizeof(int) && r->in.type != FLOAT ) 353*24418Smckusick putstr("movl"); 3549702Slinton else { 355*24418Smckusick putstr("cvt"); 3569702Slinton prtype(r); 357*24418Smckusick putchar('l'); 3589702Slinton } 3599702Slinton return; 3609702Slinton } 3619702Slinton 3629702Slinton case 'C': /* num words pushed on arg stack */ 3639702Slinton { 3649702Slinton extern int gc_numbytes; 3659702Slinton extern int xdebug; 3669702Slinton 3679702Slinton if (xdebug) printf("->%d<-",gc_numbytes); 3689702Slinton 3699702Slinton printf("$%d", gc_numbytes/(SZLONG/SZCHAR) ); 3709702Slinton return; 3719702Slinton } 3729702Slinton 3739702Slinton case 'D': /* INCR and DECR */ 3749702Slinton zzzcode(p->in.left, 'A'); 375*24418Smckusick putchar('\n'); 376*24418Smckusick putchar('\t'); 3779702Slinton 3789702Slinton case 'E': /* INCR and DECR, FOREFF */ 3799702Slinton if (p->in.right->tn.lval == 1) 3809702Slinton { 381*24418Smckusick putstr( p->in.op == INCR ? "inc" : "dec" ); 3829702Slinton prtype(p->in.left); 383*24418Smckusick putchar('\t'); 3849702Slinton adrput(p->in.left); 3859702Slinton return; 3869702Slinton } 387*24418Smckusick putstr( p->in.op == INCR ? "add" : "sub" ); 3889702Slinton prtype(p->in.left); 389*24418Smckusick putchar('2'); 390*24418Smckusick putchar('\t'); 3919702Slinton adrput(p->in.right); 392*24418Smckusick putchar(','); 3939702Slinton adrput(p->in.left); 3949702Slinton return; 3959702Slinton 3969702Slinton case 'F': /* register type of right operand */ 3979702Slinton { 3989702Slinton register NODE *n; 3999702Slinton extern int xdebug; 4009702Slinton register int ty; 4019702Slinton 4029702Slinton n = getlr( p, 'R' ); 4039702Slinton ty = n->in.type; 4049702Slinton 4059702Slinton if (xdebug) printf("->%d<-", ty); 4069702Slinton 407*24418Smckusick if ( ty==DOUBLE) putchar('d'); 408*24418Smckusick else if ( ty==FLOAT ) putchar('f'); 409*24418Smckusick else putchar('l'); 4109702Slinton return; 4119702Slinton } 4129702Slinton 4139702Slinton case 'L': /* type of left operand */ 4149702Slinton case 'R': /* type of right operand */ 4159702Slinton { 4169702Slinton register NODE *n; 4179702Slinton extern int xdebug; 4189702Slinton 41916181Sralph n = getlr( p, c ); 4209702Slinton if (xdebug) printf("->%d<-", n->in.type); 4219702Slinton 4229702Slinton prtype(n); 4239702Slinton return; 4249702Slinton } 4259702Slinton 4269702Slinton case 'Z': /* complement mask for bit instr */ 4279702Slinton printf("$%ld", ~p->in.right->tn.lval); 4289702Slinton return; 4299702Slinton 4309702Slinton case 'U': /* 32 - n, for unsigned right shifts */ 4319702Slinton printf("$%d", 32 - p->in.right->tn.lval ); 4329702Slinton return; 4339702Slinton 4349702Slinton case 'T': /* rounded structure length for arguments */ 4359702Slinton { 4369702Slinton int size; 4379702Slinton 4389702Slinton size = p->stn.stsize; 4399702Slinton SETOFF( size, 4); 4409702Slinton printf("$%d", size); 4419702Slinton return; 4429702Slinton } 4439702Slinton 4449702Slinton case 'S': /* structure assignment */ 4459702Slinton { 4469702Slinton register NODE *l, *r; 4479702Slinton register size; 4489702Slinton 4499702Slinton if( p->in.op == STASG ){ 4509702Slinton l = p->in.left; 4519702Slinton r = p->in.right; 4529702Slinton 4539702Slinton } 4549702Slinton else if( p->in.op == STARG ){ /* store an arg into a temporary */ 4559702Slinton r = p->in.left; 4569702Slinton } 4579702Slinton else cerror( "STASG bad" ); 4589702Slinton 4599702Slinton if( r->in.op == ICON ) r->in.op = NAME; 4609702Slinton else if( r->in.op == REG ) r->in.op = OREG; 4619702Slinton else if( r->in.op != OREG ) cerror( "STASG-r" ); 4629702Slinton 4639702Slinton size = p->stn.stsize; 4649702Slinton 4659702Slinton if( size <= 0 || size > 65535 ) 4669702Slinton cerror("structure size <0=0 or >65535"); 4679702Slinton 4689702Slinton switch(size) { 4699702Slinton case 1: 470*24418Smckusick putstr(" movb "); 4719702Slinton break; 4729702Slinton case 2: 473*24418Smckusick putstr(" movw "); 4749702Slinton break; 4759702Slinton case 4: 476*24418Smckusick putstr(" movl "); 4779702Slinton break; 4789702Slinton case 8: 479*24418Smckusick putstr(" movq "); 4809702Slinton break; 4819702Slinton default: 4829702Slinton printf(" movc3 $%d,", size); 4839702Slinton break; 4849702Slinton } 4859702Slinton adrput(r); 48616418Sralph if( p->in.op == STASG ){ 487*24418Smckusick putchar(','); 48816418Sralph adrput(l); 489*24418Smckusick putchar('\n'); 49016418Sralph } 49116418Sralph else 492*24418Smckusick putstr(",(sp)\n"); 4939702Slinton 4949702Slinton if( r->in.op == NAME ) r->in.op = ICON; 4959702Slinton else if( r->in.op == OREG ) r->in.op = REG; 4969702Slinton 4979702Slinton } 4989702Slinton break; 4999702Slinton 5009702Slinton default: 5019702Slinton cerror( "illegal zzzcode" ); 5029702Slinton } 5039702Slinton } 5049702Slinton 50523536Sbloom /* 50623536Sbloom * collapsible(dest, src) -- if a conversion with a register destination 50723536Sbloom * can be accomplished in one instruction, return the type of src 50823536Sbloom * that will do the job correctly; otherwise return 0. Note that 50923536Sbloom * a register must always end up having type INT or UNSIGNED. 51023536Sbloom */ 51123536Sbloom int 51223536Sbloom collapsible(dest, src) 51323536Sbloom NODE *dest, *src; 51423536Sbloom { 51523536Sbloom int st = src->in.type; 51623536Sbloom int dt = dest->in.type; 51723536Sbloom int newt = 0; 51823536Sbloom 51923536Sbloom /* 52023536Sbloom * Are there side effects of evaluating src? 52123536Sbloom * If the derived type will not be the same size as src, 522*24418Smckusick * we may have to use two steps. 52323536Sbloom */ 524*24418Smckusick if (tlen(src) > tlen(dest)) { 525*24418Smckusick if (tshape(src, STARREG)) 526*24418Smckusick return (0); 527*24418Smckusick if (src->in.op == OREG && R2TEST(src->tn.rval)) 528*24418Smckusick return (0); 529*24418Smckusick } 53023536Sbloom 53123536Sbloom /* 53223536Sbloom * Can we get an object of dest's type by punning src? 53323536Sbloom * Praises be to great Cthulhu for little-endian machines... 53423536Sbloom */ 53523536Sbloom if (st == CHAR && dt == USHORT) 53623536Sbloom /* 53723536Sbloom * Special case -- we must sign-extend to 16 bits. 53823536Sbloom */ 53923536Sbloom return (0); 54023536Sbloom 54123536Sbloom if (tlen(src) < tlen(dest)) 54223536Sbloom newt = st; 54323536Sbloom else 54423536Sbloom newt = dt; 54523536Sbloom 54623536Sbloom return (newt); 54723536Sbloom } 54823536Sbloom 54917742Sralph rmove( rt, rs, t ) TWORD t; { 5509702Slinton printf( " %s %s,%s\n", 55117742Sralph #ifdef FORT 55217742Sralph !Oflag ? (t==DOUBLE ? "movq" : "movl") : 55317742Sralph #endif 5549702Slinton (t==FLOAT ? "movf" : (t==DOUBLE ? "movd" : "movl")), 5559702Slinton rnames[rs], rnames[rt] ); 5569702Slinton } 5579702Slinton 5589702Slinton struct respref 5599702Slinton respref[] = { 5609702Slinton INTAREG|INTBREG, INTAREG|INTBREG, 5619702Slinton INAREG|INBREG, INAREG|INBREG|SOREG|STARREG|STARNM|SNAME|SCON, 5629702Slinton INTEMP, INTEMP, 5639702Slinton FORARG, FORARG, 5649702Slinton INTEMP, INTAREG|INAREG|INTBREG|INBREG|SOREG|STARREG|STARNM, 5659702Slinton 0, 0 }; 5669702Slinton 5679702Slinton setregs(){ /* set up temporary registers */ 5689702Slinton fregs = 6; /* tbl- 6 free regs on VAX (0-5) */ 5699702Slinton ; 5709702Slinton } 5719702Slinton 5729702Slinton rewfld( p ) NODE *p; { 5739702Slinton return(1); 5749702Slinton } 5759702Slinton 5769702Slinton callreg(p) NODE *p; { 5779702Slinton return( R0 ); 5789702Slinton } 5799702Slinton 5809702Slinton base( p ) register NODE *p; { 5819702Slinton register int o = p->in.op; 5829702Slinton 5839702Slinton if( (o==ICON && p->in.name[0] != '\0')) return( 100 ); /* ie no base reg */ 5849702Slinton if( o==REG ) return( p->tn.rval ); 5859702Slinton if( (o==PLUS || o==MINUS) && p->in.left->in.op == REG && p->in.right->in.op==ICON) 5869702Slinton return( p->in.left->tn.rval ); 5879702Slinton if( o==OREG && !R2TEST(p->tn.rval) && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 5889702Slinton return( p->tn.rval + 0200*1 ); 5899702Slinton if( o==INCR && p->in.left->in.op==REG ) return( p->in.left->tn.rval + 0200*2 ); 5909702Slinton if( o==ASG MINUS && p->in.left->in.op==REG) return( p->in.left->tn.rval + 0200*4 ); 5919702Slinton if( o==UNARY MUL && p->in.left->in.op==INCR && p->in.left->in.left->in.op==REG 5929702Slinton && (p->in.type==INT || p->in.type==UNSIGNED || ISPTR(p->in.type)) ) 5939702Slinton return( p->in.left->in.left->tn.rval + 0200*(1+2) ); 5949702Slinton return( -1 ); 5959702Slinton } 5969702Slinton 5979702Slinton offset( p, tyl ) register NODE *p; int tyl; { 5989702Slinton 599*24418Smckusick if( tyl==1 && 600*24418Smckusick p->in.op==REG && 601*24418Smckusick (p->in.type==INT || p->in.type==UNSIGNED) ) 602*24418Smckusick return( p->tn.rval ); 603*24418Smckusick if( p->in.op==LS && 604*24418Smckusick p->in.left->in.op==REG && 605*24418Smckusick (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 606*24418Smckusick p->in.right->in.op==ICON && 607*24418Smckusick p->in.right->in.name[0]=='\0' && 608*24418Smckusick (1<<p->in.right->tn.lval)==tyl) 6099702Slinton return( p->in.left->tn.rval ); 610*24418Smckusick if( tyl==2 && 611*24418Smckusick p->in.op==PLUS && 612*24418Smckusick (p->in.left->in.type==INT || p->in.left->in.type==UNSIGNED) && 613*24418Smckusick p->in.left->in.op==REG && 614*24418Smckusick p->in.right->in.op==REG && 615*24418Smckusick p->in.left->tn.rval==p->in.right->tn.rval ) 616*24418Smckusick return( p->in.left->tn.rval ); 6179702Slinton return( -1 ); 6189702Slinton } 6199702Slinton 6209702Slinton makeor2( p, q, b, o) register NODE *p, *q; register int b, o; { 6219702Slinton register NODE *t; 6229702Slinton register int i; 6239702Slinton NODE *f; 6249702Slinton 6259702Slinton p->in.op = OREG; 6269702Slinton f = p->in.left; /* have to free this subtree later */ 6279702Slinton 6289702Slinton /* init base */ 6299702Slinton switch (q->in.op) { 6309702Slinton case ICON: 6319702Slinton case REG: 6329702Slinton case OREG: 6339702Slinton t = q; 6349702Slinton break; 6359702Slinton 6369702Slinton case MINUS: 6379702Slinton q->in.right->tn.lval = -q->in.right->tn.lval; 6389702Slinton case PLUS: 6399702Slinton t = q->in.right; 6409702Slinton break; 6419702Slinton 6429702Slinton case INCR: 6439702Slinton case ASG MINUS: 6449702Slinton t = q->in.left; 6459702Slinton break; 6469702Slinton 6479702Slinton case UNARY MUL: 6489702Slinton t = q->in.left->in.left; 6499702Slinton break; 6509702Slinton 6519702Slinton default: 6529702Slinton cerror("illegal makeor2"); 6539702Slinton } 6549702Slinton 6559702Slinton p->tn.lval = t->tn.lval; 6569702Slinton #ifndef FLEXNAMES 6579702Slinton for(i=0; i<NCHNAM; ++i) 6589702Slinton p->in.name[i] = t->in.name[i]; 6599702Slinton #else 6609702Slinton p->in.name = t->in.name; 6619702Slinton #endif 6629702Slinton 6639702Slinton /* init offset */ 6649702Slinton p->tn.rval = R2PACK( (b & 0177), o, (b>>7) ); 6659702Slinton 6669702Slinton tfree(f); 6679702Slinton return; 6689702Slinton } 6699702Slinton 6709702Slinton canaddr( p ) NODE *p; { 6719702Slinton register int o = p->in.op; 6729702Slinton 6739702Slinton if( o==NAME || o==REG || o==ICON || o==OREG || (o==UNARY MUL && shumul(p->in.left)) ) return(1); 6749702Slinton return(0); 6759702Slinton } 6769702Slinton 6779702Slinton flshape( p ) register NODE *p; { 6789702Slinton return( p->in.op == REG || p->in.op == NAME || p->in.op == ICON || 6799702Slinton (p->in.op == OREG && (!R2TEST(p->tn.rval) || tlen(p) == 1)) ); 6809702Slinton } 6819702Slinton 6829702Slinton shtemp( p ) register NODE *p; { 6839702Slinton if( p->in.op == STARG ) p = p->in.left; 6849702Slinton return( p->in.op==NAME || p->in.op ==ICON || p->in.op == OREG || (p->in.op==UNARY MUL && shumul(p->in.left)) ); 6859702Slinton } 6869702Slinton 6879702Slinton shumul( p ) register NODE *p; { 6889702Slinton register o; 6899702Slinton extern int xdebug; 6909702Slinton 6919702Slinton if (xdebug) { 6929702Slinton printf("\nshumul:op=%d,lop=%d,rop=%d", p->in.op, p->in.left->in.op, p->in.right->in.op); 6939702Slinton printf(" prname=%s,plty=%d, prlval=%D\n", p->in.right->in.name, p->in.left->in.type, p->in.right->tn.lval); 6949702Slinton } 6959702Slinton 6969702Slinton 6979702Slinton o = p->in.op; 6989702Slinton if( o == NAME || (o == OREG && !R2TEST(p->tn.rval)) || o == ICON ) return( STARNM ); 6999702Slinton 7009702Slinton if( ( o == INCR || o == ASG MINUS ) && 7019702Slinton ( p->in.left->in.op == REG && p->in.right->in.op == ICON ) && 7029702Slinton p->in.right->in.name[0] == '\0' ) 7039702Slinton { 70417659Sralph switch (p->in.type) 7059702Slinton { 7069702Slinton case CHAR|PTR: 7079702Slinton case UCHAR|PTR: 7089702Slinton o = 1; 7099702Slinton break; 7109702Slinton 7119702Slinton case SHORT|PTR: 7129702Slinton case USHORT|PTR: 7139702Slinton o = 2; 7149702Slinton break; 7159702Slinton 7169702Slinton case INT|PTR: 7179702Slinton case UNSIGNED|PTR: 7189702Slinton case LONG|PTR: 7199702Slinton case ULONG|PTR: 7209702Slinton case FLOAT|PTR: 7219702Slinton o = 4; 7229702Slinton break; 7239702Slinton 7249702Slinton case DOUBLE|PTR: 7259702Slinton o = 8; 7269702Slinton break; 7279702Slinton 7289702Slinton default: 72917742Sralph if ( ISPTR(p->in.type) && 73017742Sralph ISPTR(DECREF(p->in.type)) ) { 7319702Slinton o = 4; 7329702Slinton break; 7339702Slinton } 7349702Slinton else return(0); 7359702Slinton } 7369702Slinton return( p->in.right->tn.lval == o ? STARREG : 0); 7379702Slinton } 7389702Slinton 7399702Slinton return( 0 ); 7409702Slinton } 7419702Slinton 7429702Slinton adrcon( val ) CONSZ val; { 743*24418Smckusick putchar( '$' ); 7449702Slinton printf( CONFMT, val ); 7459702Slinton } 7469702Slinton 7479702Slinton conput( p ) register NODE *p; { 7489702Slinton switch( p->in.op ){ 7499702Slinton 7509702Slinton case ICON: 7519702Slinton acon( p ); 7529702Slinton return; 7539702Slinton 7549702Slinton case REG: 755*24418Smckusick putstr( rnames[p->tn.rval] ); 7569702Slinton return; 7579702Slinton 7589702Slinton default: 7599702Slinton cerror( "illegal conput" ); 7609702Slinton } 7619702Slinton } 7629702Slinton 7639702Slinton insput( p ) register NODE *p; { 7649702Slinton cerror( "insput" ); 7659702Slinton } 7669702Slinton 7679702Slinton upput( p ) register NODE *p; { 7689702Slinton cerror( "upput" ); 7699702Slinton } 7709702Slinton 7719702Slinton adrput( p ) register NODE *p; { 7729702Slinton register int r; 7739702Slinton /* output an address, with offsets, from p */ 7749702Slinton 7759702Slinton if( p->in.op == FLD ){ 7769702Slinton p = p->in.left; 7779702Slinton } 7789702Slinton switch( p->in.op ){ 7799702Slinton 7809702Slinton case NAME: 7819702Slinton acon( p ); 7829702Slinton return; 7839702Slinton 7849702Slinton case ICON: 7859702Slinton /* addressable value of the constant */ 786*24418Smckusick putchar( '$' ); 7879702Slinton acon( p ); 7889702Slinton return; 7899702Slinton 7909702Slinton case REG: 791*24418Smckusick putstr( rnames[p->tn.rval] ); 7929702Slinton return; 7939702Slinton 7949702Slinton case OREG: 7959702Slinton r = p->tn.rval; 7969702Slinton if( R2TEST(r) ){ /* double indexing */ 7979702Slinton register int flags; 7989702Slinton 7999702Slinton flags = R2UPK3(r); 800*24418Smckusick if( flags & 1 ) putchar('*'); 801*24418Smckusick if( flags & 4 ) putchar('-'); 8029702Slinton if( p->tn.lval != 0 || p->in.name[0] != '\0' ) acon(p); 8039702Slinton if( R2UPK1(r) != 100) printf( "(%s)", rnames[R2UPK1(r)] ); 804*24418Smckusick if( flags & 2 ) putchar('+'); 8059702Slinton printf( "[%s]", rnames[R2UPK2(r)] ); 8069702Slinton return; 8079702Slinton } 8089702Slinton if( r == AP ){ /* in the argument region */ 8099702Slinton if( p->tn.lval <= 0 || p->in.name[0] != '\0' ) werror( "bad arg temp" ); 8109702Slinton printf( CONFMT, p->tn.lval ); 811*24418Smckusick putstr( "(ap)" ); 8129702Slinton return; 8139702Slinton } 8149702Slinton if( p->tn.lval != 0 || p->in.name[0] != '\0') acon( p ); 8159702Slinton printf( "(%s)", rnames[p->tn.rval] ); 8169702Slinton return; 8179702Slinton 8189702Slinton case UNARY MUL: 8199702Slinton /* STARNM or STARREG found */ 8209702Slinton if( tshape(p, STARNM) ) { 821*24418Smckusick putchar( '*' ); 8229702Slinton adrput( p->in.left); 8239702Slinton } 8249702Slinton else { /* STARREG - really auto inc or dec */ 8259702Slinton register NODE *q; 8269702Slinton 8279702Slinton /* tbl 8289702Slinton p = p->in.left; 8299702Slinton p->in.left->in.op = OREG; 8309702Slinton if( p->in.op == INCR ) { 8319702Slinton adrput( p->in.left ); 832*24418Smckusick putchar( '+' ); 8339702Slinton } 8349702Slinton else { 835*24418Smckusick putchar( '-' ); 8369702Slinton adrput( p->in.left ); 8379702Slinton } 8389702Slinton tbl */ 83917659Sralph q = p->in.left; 84017742Sralph if( q->in.right->tn.lval != tlen(p) ) 84117742Sralph cerror("adrput: bad auto-increment/decrement"); 84217659Sralph printf("%s(%s)%s", (q->in.op==INCR ? "" : "-"), 84317659Sralph rnames[q->in.left->tn.rval], 84417659Sralph (q->in.op==INCR ? "+" : "") ); 8459702Slinton p->in.op = OREG; 84617659Sralph p->tn.rval = q->in.left->tn.rval; 84717659Sralph p->tn.lval = (q->in.op == INCR ? -q->in.right->tn.lval : 0); 8489702Slinton #ifndef FLEXNAMES 8499702Slinton p->in.name[0] = '\0'; 8509702Slinton #else 8519702Slinton p->in.name = ""; 8529702Slinton #endif 8539702Slinton tfree(q); 8549702Slinton } 8559702Slinton return; 8569702Slinton 8579702Slinton default: 8589702Slinton cerror( "illegal address" ); 8599702Slinton return; 8609702Slinton 8619702Slinton } 8629702Slinton 8639702Slinton } 8649702Slinton 8659702Slinton acon( p ) register NODE *p; { /* print out a constant */ 8669702Slinton 8679702Slinton if( p->in.name[0] == '\0' ){ 8689702Slinton printf( CONFMT, p->tn.lval); 8699702Slinton } 8709702Slinton else if( p->tn.lval == 0 ) { 8719702Slinton #ifndef FLEXNAMES 8729702Slinton printf( "%.8s", p->in.name ); 8739702Slinton #else 874*24418Smckusick putstr( p->in.name ); 8759702Slinton #endif 8769702Slinton } 8779702Slinton else { 8789702Slinton #ifndef FLEXNAMES 8799702Slinton printf( "%.8s+", p->in.name ); 8809702Slinton #else 8819702Slinton printf( "%s+", p->in.name ); 8829702Slinton #endif 8839702Slinton printf( CONFMT, p->tn.lval ); 8849702Slinton } 8859702Slinton } 8869702Slinton 8879702Slinton /* 8889702Slinton aacon( p ) register NODE *p; { /* print out a constant */ 8899702Slinton /* 8909702Slinton 8919702Slinton if( p->in.name[0] == '\0' ){ 8929702Slinton printf( CONFMT, p->tn.lval); 8939702Slinton return( 0 ); 8949702Slinton } 8959702Slinton else if( p->tn.lval == 0 ) { 8969702Slinton #ifndef FLEXNAMES 8979702Slinton printf( "$%.8s", p->in.name ); 8989702Slinton #else 8999702Slinton printf( "$%s", p->in.name ); 9009702Slinton #endif 9019702Slinton return( 1 ); 9029702Slinton } 9039702Slinton else { 9049702Slinton printf( "$(" ); 9059702Slinton printf( CONFMT, p->tn.lval ); 9069702Slinton printf( "+" ); 9079702Slinton #ifndef FLEXNAMES 9089702Slinton printf( "%.8s)", p->in.name ); 9099702Slinton #else 9109702Slinton printf( "%s)", p->in.name ); 9119702Slinton #endif 9129702Slinton return(1); 9139702Slinton } 9149702Slinton } 9159702Slinton */ 9169702Slinton 9179702Slinton genscall( p, cookie ) register NODE *p; { 9189702Slinton /* structure valued call */ 9199702Slinton return( gencall( p, cookie ) ); 9209702Slinton } 9219702Slinton 9229702Slinton /* tbl */ 9239702Slinton int gc_numbytes; 9249702Slinton /* tbl */ 9259702Slinton 9269702Slinton gencall( p, cookie ) register NODE *p; { 9279702Slinton /* generate the call given by p */ 92816418Sralph register NODE *p1; 9299702Slinton register temp, temp1; 9309702Slinton register m; 9319702Slinton 9329702Slinton if( p->in.right ) temp = argsize( p->in.right ); 9339702Slinton else temp = 0; 9349702Slinton 9359702Slinton if( p->in.op == STCALL || p->in.op == UNARY STCALL ){ 9369702Slinton /* set aside room for structure return */ 9379702Slinton 9389702Slinton if( p->stn.stsize > temp ) temp1 = p->stn.stsize; 9399702Slinton else temp1 = temp; 9409702Slinton } 9419702Slinton 9429702Slinton if( temp > maxargs ) maxargs = temp; 9439702Slinton SETOFF(temp1,4); 9449702Slinton 9459702Slinton if( p->in.right ){ /* make temp node, put offset in, and generate args */ 94616418Sralph genargs( p->in.right ); 9479702Slinton } 9489702Slinton 9499702Slinton p1 = p->in.left; 9509702Slinton if( p1->in.op != ICON ){ 9519702Slinton if( p1->in.op != REG ){ 9529702Slinton if( p1->in.op != OREG || R2TEST(p1->tn.rval) ){ 9539702Slinton if( p1->in.op != NAME ){ 9549702Slinton order( p1, INAREG ); 9559702Slinton } 9569702Slinton } 9579702Slinton } 9589702Slinton } 9599702Slinton 9609702Slinton /* 9619702Slinton if( p1->in.op == REG && p->tn.rval == R5 ){ 9629702Slinton cerror( "call register overwrite" ); 9639702Slinton } 9649702Slinton */ 9659702Slinton /* tbl 9669702Slinton setup gc_numbytes so reference to ZC works */ 9679702Slinton 9689702Slinton gc_numbytes = temp&(0x3ff); 9699702Slinton /* tbl */ 9709702Slinton 9719702Slinton p->in.op = UNARY CALL; 9729702Slinton m = match( p, INTAREG|INTBREG ); 9739702Slinton 9749702Slinton /* compensate for deficiency in 'ret' instruction ... wah,kre */ 9759702Slinton /* (plus in assignment to gc_numbytes above, for neatness only) */ 9769702Slinton if (temp >= 1024) 9779702Slinton printf(" addl2 $%d,sp\n", (temp&(~0x3ff))); 9789702Slinton 9799702Slinton /* tbl 9809702Slinton switch( temp ) { 9819702Slinton case 0: 9829702Slinton break; 9839702Slinton case 2: 9849702Slinton printf( " tst (sp)+\n" ); 9859702Slinton break; 9869702Slinton case 4: 9879702Slinton printf( " cmp (sp)+,(sp)+\n" ); 9889702Slinton break; 9899702Slinton default: 9909702Slinton printf( " add $%d,sp\n", temp); 9919702Slinton } 9929702Slinton tbl */ 9939702Slinton return(m != MDONE); 9949702Slinton } 9959702Slinton 9969702Slinton /* tbl */ 9979702Slinton char * 9989702Slinton ccbranches[] = { 9999702Slinton " jeql L%d\n", 10009702Slinton " jneq L%d\n", 10019702Slinton " jleq L%d\n", 10029702Slinton " jlss L%d\n", 10039702Slinton " jgeq L%d\n", 10049702Slinton " jgtr L%d\n", 10059702Slinton " jlequ L%d\n", 10069702Slinton " jlssu L%d\n", 10079702Slinton " jgequ L%d\n", 10089702Slinton " jgtru L%d\n", 10099702Slinton }; 10109702Slinton /* tbl */ 10119702Slinton 10129702Slinton cbgen( o, lab, mode ) { /* printf conditional and unconditional branches */ 10139702Slinton 10149702Slinton /* tbl */ 10159702Slinton if( o == 0 ) printf( " jbr L%d\n", lab ); 10169702Slinton /* tbl */ 10179702Slinton else { 10189702Slinton if( o > UGT ) cerror( "bad conditional branch: %s", opst[o] ); 10199702Slinton printf( ccbranches[o-EQ], lab ); 10209702Slinton } 10219702Slinton } 10229702Slinton 10239702Slinton nextcook( p, cookie ) NODE *p; { 10249702Slinton /* we have failed to match p with cookie; try another */ 10259702Slinton if( cookie == FORREW ) return( 0 ); /* hopeless! */ 10269702Slinton if( !(cookie&(INTAREG|INTBREG)) ) return( INTAREG|INTBREG ); 10279702Slinton if( !(cookie&INTEMP) && asgop(p->in.op) ) return( INTEMP|INAREG|INTAREG|INTBREG|INBREG ); 10289702Slinton return( FORREW ); 10299702Slinton } 10309702Slinton 10319702Slinton lastchance( p, cook ) NODE *p; { 10329702Slinton /* forget it! */ 10339702Slinton return(0); 10349702Slinton } 10359702Slinton 10369702Slinton optim2( p ) register NODE *p; { 10379702Slinton /* do local tree transformations and optimizations */ 10389702Slinton 103916181Sralph register NODE *l, *r; 104016181Sralph int m, ml; 10419702Slinton 10429702Slinton switch( p->in.op ) { 10439702Slinton 10449702Slinton case AND: 104519933Smckusick /* commute L and R to eliminate complements and constants */ 104616181Sralph if( (l = p->in.left)->in.op == ICON && l->in.name[0] == 0 || 104716181Sralph l->in.op == COMPL ) { 10489702Slinton p->in.left = p->in.right; 104916181Sralph p->in.right = l; 10509702Slinton } 10519702Slinton case ASG AND: 10529702Slinton /* change meaning of AND to ~R&L - bic on pdp11 */ 10539702Slinton r = p->in.right; 105419933Smckusick if( r->in.op==ICON && r->in.name[0]==0 ) { /* complement constant */ 10559702Slinton r->tn.lval = ~r->tn.lval; 10569702Slinton } 10579702Slinton else if( r->in.op==COMPL ) { /* ~~A => A */ 10589702Slinton r->in.op = FREE; 10599702Slinton p->in.right = r->in.left; 10609702Slinton } 10619702Slinton else { /* insert complement node */ 106216181Sralph p->in.right = l = talloc(); 106316181Sralph l->in.op = COMPL; 106416181Sralph l->in.rall = NOPREF; 106516181Sralph l->in.type = r->in.type; 106616181Sralph l->in.left = r; 106716181Sralph l->in.right = NULL; 10689702Slinton } 10699702Slinton break; 10709702Slinton 107116181Sralph case SCONV: 107219933Smckusick l = p->in.left; 107317742Sralph #if defined(FORT) || defined(SPRECC) 107416573Sralph if( p->in.type == FLOAT || p->in.type == DOUBLE || 107519933Smckusick l->in.type == FLOAT || l->in.type == DOUBLE ) 107619933Smckusick return; 107716573Sralph #else 107819933Smckusick if( mixtypes(p, l) ) return; 107916573Sralph #endif 108019933Smckusick /* Only trust it to get it right if the size is the same */ 108119933Smckusick if( tlen(p) != tlen(l) ) 108219933Smckusick return; 108316181Sralph 108416181Sralph /* clobber conversion */ 108519933Smckusick if( l->in.op != FLD ) 108616181Sralph l->in.type = p->in.type; 108716181Sralph ncopy( p, l ); 108816181Sralph l->in.op = FREE; 108919933Smckusick 109016181Sralph break; 109116181Sralph 1092*24418Smckusick case ASSIGN: 1093*24418Smckusick /* 1094*24418Smckusick * Conversions are equivalent to assignments; 1095*24418Smckusick * when the two operations are combined, 1096*24418Smckusick * we can sometimes zap the conversion. 1097*24418Smckusick */ 1098*24418Smckusick r = p->in.right; 1099*24418Smckusick l = p->in.left; 1100*24418Smckusick if ( r->in.op == SCONV && 1101*24418Smckusick !mixtypes(l, r) && 1102*24418Smckusick tlen(l) == tlen(r) ) { 1103*24418Smckusick p->in.right = r->in.left; 1104*24418Smckusick r->in.op = FREE; 1105*24418Smckusick } 1106*24418Smckusick break; 1107*24418Smckusick 11089702Slinton } 11099702Slinton } 11109702Slinton 111117742Sralph NODE * addroreg(l) NODE *l; 11129702Slinton /* OREG was built in clocal() 11139702Slinton * for an auto or formal parameter 11149702Slinton * now its address is being taken 11159702Slinton * local code must unwind it 11169702Slinton * back to PLUS/MINUS REG ICON 11179702Slinton * according to local conventions 11189702Slinton */ 11199702Slinton { 11209702Slinton cerror("address of OREG taken"); 112117742Sralph /*NOTREACHED*/ 11229702Slinton } 11239702Slinton 11249702Slinton 11259702Slinton 11269702Slinton # ifndef ONEPASS 11279702Slinton main( argc, argv ) char *argv[]; { 11289702Slinton return( mainp2( argc, argv ) ); 11299702Slinton } 11309702Slinton # endif 11319702Slinton 11329702Slinton 11339702Slinton /* added by jwf */ 11349702Slinton struct functbl { 11359702Slinton int fop; 11369702Slinton TWORD ftype; 11379702Slinton char *func; 11389702Slinton } opfunc[] = { 11399702Slinton DIV, TANY, "udiv", 11409702Slinton MOD, TANY, "urem", 114117715Sralph ASG DIV, TANY, "audiv", 114217715Sralph ASG MOD, TANY, "aurem", 11439702Slinton 0, 0, 0 }; 11449702Slinton 11459702Slinton hardops(p) register NODE *p; { 11469702Slinton /* change hard to do operators into function calls. */ 11479702Slinton register NODE *q; 11489702Slinton register struct functbl *f; 11499702Slinton register o; 115017742Sralph NODE *old,*temp; 11519702Slinton 11529702Slinton o = p->in.op; 115317742Sralph if( ! (optype(o)==BITYPE && 115417742Sralph (ISUNSIGNED(p->in.left->in.type) || 115517742Sralph ISUNSIGNED(p->in.right->in.type))) ) 115617742Sralph return; 11579702Slinton 11589702Slinton for( f=opfunc; f->fop; f++ ) { 11599702Slinton if( o==f->fop ) goto convert; 11609702Slinton } 11619702Slinton return; 11629702Slinton 11639702Slinton convert: 11649702Slinton if( asgop( o ) ) { 116517742Sralph old = NIL; 116617715Sralph switch( p->in.left->in.op ){ 116717742Sralph case FLD: 116817742Sralph q = p->in.left->in.left; 116917742Sralph /* 117017742Sralph * rewrite (lval.fld /= rval); as 117117742Sralph * ((*temp).fld = udiv((*(temp = &lval)).fld,rval)); 117217742Sralph * else the compiler will evaluate lval twice. 117317742Sralph */ 117417742Sralph if( q->in.op == UNARY MUL ){ 117517742Sralph /* first allocate a temp storage */ 117617742Sralph temp = talloc(); 117717742Sralph temp->in.op = OREG; 117817742Sralph temp->tn.rval = TMPREG; 117917742Sralph temp->tn.lval = BITOOR(freetemp(1)); 118017742Sralph temp->in.type = INCREF(p->in.type); 118117742Sralph #ifdef FLEXNAMES 118217742Sralph temp->in.name = ""; 118317742Sralph #else 118417742Sralph temp->in.name[0] = '\0'; 118517742Sralph #endif 118617742Sralph old = q->in.left; 118717742Sralph q->in.left = temp; 118817742Sralph } 118917742Sralph /* fall thru ... */ 119017742Sralph 119117715Sralph case REG: 119217715Sralph case NAME: 119317715Sralph case OREG: 119417715Sralph /* change ASG OP to a simple OP */ 119517715Sralph q = talloc(); 119617715Sralph q->in.op = NOASG p->in.op; 119717715Sralph q->in.rall = NOPREF; 119817715Sralph q->in.type = p->in.type; 119917715Sralph q->in.left = tcopy(p->in.left); 120017715Sralph q->in.right = p->in.right; 120117715Sralph p->in.op = ASSIGN; 120217715Sralph p->in.right = q; 120317715Sralph p = q; 120417715Sralph f -= 2; /* Note: this depends on the table order */ 120517742Sralph /* on the right side only - replace *temp with 120617742Sralph *(temp = &lval), build the assignment node */ 120717742Sralph if( old ){ 120817742Sralph temp = q->in.left->in.left; /* the "*" node */ 120917742Sralph q = talloc(); 121017742Sralph q->in.op = ASSIGN; 121117742Sralph q->in.left = temp->in.left; 121217742Sralph q->in.right = old; 121317742Sralph q->in.type = old->in.type; 121417742Sralph #ifdef FLEXNAMES 121517742Sralph q->in.name = ""; 121617742Sralph #else 121717742Sralph q->in.name[0] = '\0'; 121817742Sralph #endif 121917742Sralph temp->in.left = q; 122017742Sralph } 122117715Sralph break; 12229702Slinton 122317715Sralph case UNARY MUL: 122417715Sralph /* avoid doing side effects twice */ 122517715Sralph q = p->in.left; 122617715Sralph p->in.left = q->in.left; 122717715Sralph q->in.op = FREE; 122817715Sralph break; 122917715Sralph 123017715Sralph default: 123117715Sralph cerror( "hardops: can't compute & LHS" ); 123217715Sralph } 123317742Sralph } 123417715Sralph 12359702Slinton /* build comma op for args to function */ 12369702Slinton q = talloc(); 12379702Slinton q->in.op = CM; 12389702Slinton q->in.rall = NOPREF; 12399702Slinton q->in.type = INT; 12409702Slinton q->in.left = p->in.left; 12419702Slinton q->in.right = p->in.right; 12429702Slinton p->in.op = CALL; 12439702Slinton p->in.right = q; 12449702Slinton 12459702Slinton /* put function name in left node of call */ 12469702Slinton p->in.left = q = talloc(); 12479702Slinton q->in.op = ICON; 12489702Slinton q->in.rall = NOPREF; 12499702Slinton q->in.type = INCREF( FTN + p->in.type ); 12509702Slinton #ifndef FLEXNAMES 12519702Slinton strcpy( q->in.name, f->func ); 12529702Slinton #else 12539702Slinton q->in.name = f->func; 12549702Slinton #endif 12559702Slinton q->tn.lval = 0; 12569702Slinton q->tn.rval = 0; 12579702Slinton 12589702Slinton } 12599702Slinton 126017742Sralph zappost(p) NODE *p; { 126117742Sralph /* look for ++ and -- operators and remove them */ 126217742Sralph 126317742Sralph register o, ty; 126417742Sralph register NODE *q; 126517742Sralph o = p->in.op; 126617742Sralph ty = optype( o ); 126717742Sralph 126817742Sralph switch( o ){ 126917742Sralph 127017742Sralph case INCR: 127117742Sralph case DECR: 127217742Sralph q = p->in.left; 127317742Sralph p->in.right->in.op = FREE; /* zap constant */ 127417742Sralph ncopy( p, q ); 127517742Sralph q->in.op = FREE; 127617742Sralph return; 127717742Sralph 127817742Sralph } 127917742Sralph 128017742Sralph if( ty == BITYPE ) zappost( p->in.right ); 128117742Sralph if( ty != LTYPE ) zappost( p->in.left ); 128217742Sralph } 128317742Sralph 128417742Sralph fixpre(p) NODE *p; { 128517742Sralph 128617742Sralph register o, ty; 128717742Sralph o = p->in.op; 128817742Sralph ty = optype( o ); 128917742Sralph 129017742Sralph switch( o ){ 129117742Sralph 129217742Sralph case ASG PLUS: 129317742Sralph p->in.op = PLUS; 129417742Sralph break; 129517742Sralph case ASG MINUS: 129617742Sralph p->in.op = MINUS; 129717742Sralph break; 129817742Sralph } 129917742Sralph 130017742Sralph if( ty == BITYPE ) fixpre( p->in.right ); 130117742Sralph if( ty != LTYPE ) fixpre( p->in.left ); 130217742Sralph } 130317742Sralph 1304*24418Smckusick strip(p) register NODE *p; { 1305*24418Smckusick NODE *q; 1306*24418Smckusick 1307*24418Smckusick /* strip nodes off the top when no side effects occur */ 1308*24418Smckusick for( ; ; ) { 1309*24418Smckusick switch( p->in.op ) { 1310*24418Smckusick case SCONV: /* remove lint tidbits */ 1311*24418Smckusick q = p->in.left; 1312*24418Smckusick ncopy( p, q ); 1313*24418Smckusick q->in.op = FREE; 1314*24418Smckusick break; 1315*24418Smckusick /* could probably add a few more here */ 1316*24418Smckusick default: 1317*24418Smckusick return; 1318*24418Smckusick } 1319*24418Smckusick } 1320*24418Smckusick } 1321*24418Smckusick 13229702Slinton myreader(p) register NODE *p; { 1323*24418Smckusick strip( p ); /* strip off operations with no side effects */ 132417742Sralph canon( p ); /* expands r-vals for fields */ 13259702Slinton walkf( p, hardops ); /* convert ops to function calls */ 13269702Slinton walkf( p, optim2 ); 13279702Slinton /* jwf toff = 0; /* stack offset swindle */ 13289702Slinton } 1329