117738Sralph #ifndef lint 2*24417Smckusick static char *sccsid ="@(#)local.c 1.8 (Berkeley) 08/23/85"; 317738Sralph #endif lint 417738Sralph 518555Sralph # include "pass1.h" 69701Slinton 79701Slinton /* this file contains code which is dependent on the target machine */ 89701Slinton 99701Slinton NODE * 109701Slinton cast( p, t ) register NODE *p; TWORD t; { 119701Slinton /* cast node p to type t */ 129701Slinton 139701Slinton p = buildtree( CAST, block( NAME, NIL, NIL, t, 0, (int)t ), p ); 149701Slinton p->in.left->in.op = FREE; 159701Slinton p->in.op = FREE; 169701Slinton return( p->in.right ); 179701Slinton } 189701Slinton 199701Slinton NODE * 209701Slinton clocal(p) NODE *p; { 219701Slinton 229701Slinton /* this is called to do local transformations on 239701Slinton an expression tree preparitory to its being 249701Slinton written out in intermediate code. 259701Slinton */ 269701Slinton 279701Slinton /* the major essential job is rewriting the 289701Slinton automatic variables and arguments in terms of 299701Slinton REG and OREG nodes */ 309701Slinton /* conversion ops which are not necessary are also clobbered here */ 319701Slinton /* in addition, any special features (such as rewriting 329701Slinton exclusive or) are easily handled here as well */ 339701Slinton 349701Slinton register struct symtab *q; 359701Slinton register NODE *r; 369701Slinton register o; 379701Slinton register m, ml; 389701Slinton 399701Slinton switch( o = p->in.op ){ 409701Slinton 419701Slinton case NAME: 429701Slinton if( p->tn.rval < 0 ) { /* already processed; ignore... */ 439701Slinton return(p); 449701Slinton } 459701Slinton q = &stab[p->tn.rval]; 469701Slinton switch( q->sclass ){ 479701Slinton 489701Slinton case AUTO: 499701Slinton case PARAM: 509701Slinton /* fake up a structure reference */ 519701Slinton r = block( REG, NIL, NIL, PTR+STRTY, 0, 0 ); 529701Slinton r->tn.lval = 0; 539701Slinton r->tn.rval = (q->sclass==AUTO?STKREG:ARGREG); 549701Slinton p = stref( block( STREF, r, p, 0, 0, 0 ) ); 559701Slinton break; 569701Slinton 579701Slinton case ULABEL: 589701Slinton case LABEL: 599701Slinton case STATIC: 609701Slinton if( q->slevel == 0 ) break; 619701Slinton p->tn.lval = 0; 629701Slinton p->tn.rval = -q->offset; 639701Slinton break; 649701Slinton 659701Slinton case REGISTER: 669701Slinton p->in.op = REG; 679701Slinton p->tn.lval = 0; 689701Slinton p->tn.rval = q->offset; 699701Slinton break; 709701Slinton 719701Slinton } 729701Slinton break; 739701Slinton 749701Slinton case PCONV: 759701Slinton /* do pointer conversions for char and longs */ 769701Slinton ml = p->in.left->in.type; 779701Slinton if( ( ml==CHAR || ml==UCHAR || ml==SHORT || ml==USHORT ) && p->in.left->in.op != ICON ) break; 789701Slinton 799701Slinton /* pointers all have the same representation; the type is inherited */ 809701Slinton 819701Slinton p->in.left->in.type = p->in.type; 829701Slinton p->in.left->fn.cdim = p->fn.cdim; 839701Slinton p->in.left->fn.csiz = p->fn.csiz; 849701Slinton p->in.op = FREE; 859701Slinton return( p->in.left ); 869701Slinton 879701Slinton case SCONV: 889701Slinton m = (p->in.type == FLOAT || p->in.type == DOUBLE ); 899701Slinton ml = (p->in.left->in.type == FLOAT || p->in.left->in.type == DOUBLE ); 9017738Sralph o = p->in.left->in.op; 9117738Sralph if( (o == FCON || o == DCON) && ml && !m ) { 9217738Sralph /* float type to int type */ 9317738Sralph r = block( ICON, (NODE *)NULL, (NODE *)NULL, INT, 0, 0 ); 9417738Sralph if( o == FCON ) 9517738Sralph r->tn.lval = (int) p->in.left->fpn.fval; 9617738Sralph else 9717738Sralph r->tn.lval = (int) p->in.left->dpn.dval; 9817738Sralph r->tn.rval = NONAME; 9917738Sralph p->in.left->in.op = FREE; 10017738Sralph p->in.left = r; 10117738Sralph } 10217738Sralph else 10317738Sralph #ifdef SPRECC 10417738Sralph if ( ml || m ) 10517738Sralph #else 10617738Sralph if ( ml != m ) 10717738Sralph #endif 10817738Sralph break; 1099701Slinton 1109701Slinton /* now, look for conversions downwards */ 1119701Slinton 1129701Slinton m = p->in.type; 1139701Slinton ml = p->in.left->in.type; 1149701Slinton if( p->in.left->in.op == ICON ){ /* simulate the conversion here */ 1159701Slinton CONSZ val; 1169701Slinton val = p->in.left->tn.lval; 1179701Slinton switch( m ){ 1189701Slinton case CHAR: 1199701Slinton p->in.left->tn.lval = (char) val; 1209701Slinton break; 1219701Slinton case UCHAR: 1229701Slinton p->in.left->tn.lval = val & 0XFF; 1239701Slinton break; 1249701Slinton case USHORT: 1259701Slinton p->in.left->tn.lval = val & 0XFFFFL; 1269701Slinton break; 1279701Slinton case SHORT: 1289701Slinton p->in.left->tn.lval = (short)val; 1299701Slinton break; 1309701Slinton case UNSIGNED: 1319701Slinton p->in.left->tn.lval = val & 0xFFFFFFFFL; 1329701Slinton break; 1339701Slinton case INT: 1349701Slinton p->in.left->tn.lval = (int)val; 1359701Slinton break; 1369701Slinton } 1379701Slinton p->in.left->in.type = m; 1389701Slinton } 13916189Sralph else if( m != FLOAT && m != DOUBLE ) 14016181Sralph break; 1419701Slinton 1429701Slinton /* clobber conversion */ 1439701Slinton p->in.op = FREE; 1449701Slinton return( p->in.left ); /* conversion gets clobbered */ 1459701Slinton 1469701Slinton case PVCONV: 1479701Slinton case PMCONV: 1489701Slinton if( p->in.right->in.op != ICON ) cerror( "bad conversion", 0); 1499701Slinton p->in.op = FREE; 1509701Slinton return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) ); 1519701Slinton 1529701Slinton case RS: 1539701Slinton case ASG RS: 1549701Slinton /* convert >> to << with negative shift count */ 1559701Slinton /* only if type of left operand is not unsigned */ 1569701Slinton 1579701Slinton if( ISUNSIGNED(p->in.left->in.type) ) break; 15817738Sralph if( p->in.right->in.op != UNARY MINUS ) 15917738Sralph p->in.right = buildtree( UNARY MINUS, p->in.right, NIL ); 16017738Sralph else { 16117738Sralph r = p->in.right; 16217738Sralph p->in.right = p->in.right->in.left; 16317738Sralph r->in.op = FREE; 16417738Sralph } 1659701Slinton if( p->in.op == RS ) p->in.op = LS; 1669701Slinton else p->in.op = ASG LS; 1679701Slinton break; 1689701Slinton 1699701Slinton case FLD: 1709701Slinton /* make sure that the second pass does not make the 1719701Slinton descendant of a FLD operator into a doubly indexed OREG */ 1729701Slinton 1739701Slinton if( p->in.left->in.op == UNARY MUL 1749701Slinton && (r=p->in.left->in.left)->in.op == PCONV) 1759701Slinton if( r->in.left->in.op == PLUS || r->in.left->in.op == MINUS ) 1769701Slinton if( ISPTR(r->in.type) ) { 1779701Slinton if( ISUNSIGNED(p->in.left->in.type) ) 1789701Slinton p->in.left->in.type = UCHAR; 1799701Slinton else 1809701Slinton p->in.left->in.type = CHAR; 1819701Slinton } 1829701Slinton break; 1839701Slinton } 1849701Slinton 1859701Slinton return(p); 1869701Slinton } 1879701Slinton 1889701Slinton andable( p ) NODE *p; { 1899701Slinton return(1); /* all names can have & taken on them */ 1909701Slinton } 1919701Slinton 1929701Slinton cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */ 1939701Slinton autooff = AUTOINIT; 1949701Slinton } 1959701Slinton 1969701Slinton cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */ 1979701Slinton 1989701Slinton #ifdef TRUST_REG_CHAR_AND_REG_SHORT 1999701Slinton if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* tbl */ 2009701Slinton || t==CHAR || t==UCHAR || t==SHORT /* tbl */ 2019701Slinton || t==USHORT || ISPTR(t)) return(1); /* tbl */ 2029701Slinton #else 2039701Slinton if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* wnj */ 20417738Sralph #ifdef SPRECC 20517738Sralph || t==FLOAT 20617738Sralph #endif 2079701Slinton || ISPTR(t)) return (1); /* wnj */ 2089701Slinton #endif 2099701Slinton return(0); 2109701Slinton } 2119701Slinton 2129701Slinton NODE * 2139701Slinton offcon( off, t, d, s ) OFFSZ off; TWORD t; { 2149701Slinton 2159701Slinton /* return a node, for structure references, which is suitable for 2169701Slinton being added to a pointer of type t, in order to be off bits offset 2179701Slinton into a structure */ 2189701Slinton 2199701Slinton register NODE *p; 2209701Slinton 2219701Slinton /* t, d, and s are the type, dimension offset, and sizeoffset */ 2229701Slinton /* in general they are necessary for offcon, but not on H'well */ 2239701Slinton 2249701Slinton p = bcon(0); 2259701Slinton p->tn.lval = off/SZCHAR; 2269701Slinton return(p); 2279701Slinton 2289701Slinton } 2299701Slinton 2309701Slinton 2319701Slinton static inwd /* current bit offsed in word */; 2329701Slinton static word /* word being built from fields */; 2339701Slinton 2349701Slinton incode( p, sz ) register NODE *p; { 2359701Slinton 2369701Slinton /* generate initialization code for assigning a constant c 2379701Slinton to a field of width sz */ 2389701Slinton /* we assume that the proper alignment has been obtained */ 2399701Slinton /* inoff is updated to have the proper final value */ 2409701Slinton /* we also assume sz < SZINT */ 2419701Slinton 2429701Slinton if((sz+inwd) > SZINT) cerror("incode: field > int"); 2439701Slinton word |= ((unsigned)(p->tn.lval<<(32-sz))) >> (32-sz-inwd); 2449701Slinton inwd += sz; 2459701Slinton inoff += sz; 2469701Slinton if(inoff%SZINT == 0) { 2479701Slinton printf( " .long 0x%x\n", word); 2489701Slinton word = inwd = 0; 2499701Slinton } 2509701Slinton } 2519701Slinton 2529701Slinton fincode( d, sz ) double d; { 2539701Slinton /* output code to initialize space of size sz to the value d */ 2549701Slinton /* the proper alignment has been obtained */ 2559701Slinton /* inoff is updated to have the proper final value */ 2569701Slinton /* on the target machine, write it out in octal! */ 2579701Slinton 2589701Slinton 2599701Slinton printf(" %s 0%c%.20e\n", sz == SZDOUBLE ? ".double" : ".float", 2609701Slinton sz == SZDOUBLE ? 'd' : 'f', d); 2619701Slinton inoff += sz; 2629701Slinton } 2639701Slinton 2649701Slinton cinit( p, sz ) NODE *p; { 26518437Smckusick NODE *l; 26618437Smckusick 26718437Smckusick /* 26818437Smckusick * as a favor (?) to people who want to write 26918437Smckusick * int i = 9600/134.5; 27018437Smckusick * we will, under the proper circumstances, do 27118437Smckusick * a coersion here. 27218437Smckusick */ 27318437Smckusick switch (p->in.type) { 27418437Smckusick case INT: 27518437Smckusick case UNSIGNED: 27618437Smckusick l = p->in.left; 27718555Sralph if (l->in.op != SCONV || 27818555Sralph (l->in.left->tn.op != DCON && l->in.left->tn.op != FCON)) 27918555Sralph break; 28018437Smckusick l->in.op = FREE; 28118437Smckusick l = l->in.left; 28218555Sralph l->tn.lval = l->tn.op == DCON ? (long)(l->dpn.dval) : 28318555Sralph (long)(l->fpn.fval); 28418437Smckusick l->tn.rval = NONAME; 28518437Smckusick l->tn.op = ICON; 28618437Smckusick l->tn.type = INT; 28718437Smckusick p->in.left = l; 28818437Smckusick break; 28918437Smckusick } 29018437Smckusick /* arrange for the initialization of p into a space of size sz */ 2919701Slinton /* the proper alignment has been opbtained */ 2929701Slinton /* inoff is updated to have the proper final value */ 2939701Slinton ecode( p ); 2949701Slinton inoff += sz; 2959701Slinton } 2969701Slinton 2979701Slinton vfdzero( n ){ /* define n bits of zeros in a vfd */ 2989701Slinton 2999701Slinton if( n <= 0 ) return; 3009701Slinton 3019701Slinton inwd += n; 3029701Slinton inoff += n; 3039701Slinton if( inoff%ALINT ==0 ) { 3049701Slinton printf( " .long 0x%x\n", word ); 3059701Slinton word = inwd = 0; 3069701Slinton } 3079701Slinton } 3089701Slinton 3099701Slinton char * 3109701Slinton exname( p ) char *p; { 3119701Slinton /* make a name look like an external name in the local machine */ 3129701Slinton 3139701Slinton #ifndef FLEXNAMES 3149701Slinton static char text[NCHNAM+1]; 3159701Slinton #else 3169701Slinton static char text[BUFSIZ+1]; 3179701Slinton #endif 3189701Slinton 3199701Slinton register i; 3209701Slinton 3219701Slinton text[0] = '_'; 3229701Slinton #ifndef FLEXNAMES 323*24417Smckusick for( i=1; *p&&i<NCHNAM; ++i ) 3249701Slinton #else 325*24417Smckusick for( i=1; *p; ++i ) 3269701Slinton #endif 3279701Slinton text[i] = *p++; 3289701Slinton 3299701Slinton text[i] = '\0'; 3309701Slinton #ifndef FLEXNAMES 3319701Slinton text[NCHNAM] = '\0'; /* truncate */ 3329701Slinton #endif 3339701Slinton 3349701Slinton return( text ); 3359701Slinton } 3369701Slinton 33717738Sralph ctype( type ) TWORD type; 33817738Sralph { /* map types which are not defined on the local machine */ 3399701Slinton switch( BTYPE(type) ){ 3409701Slinton 3419701Slinton case LONG: 3429701Slinton MODTYPE(type,INT); 3439701Slinton break; 3449701Slinton 3459701Slinton case ULONG: 3469701Slinton MODTYPE(type,UNSIGNED); 3479701Slinton } 3489701Slinton return( type ); 3499701Slinton } 3509701Slinton 35117738Sralph noinit() { /* curid is a variable which is defined but 3529701Slinton is not initialized (and not a function ); 3539701Slinton This routine returns the stroage class for an uninitialized declaration */ 3549701Slinton 3559701Slinton return(EXTERN); 3569701Slinton 3579701Slinton } 3589701Slinton 3599701Slinton commdec( id ){ /* make a common declaration for id, if reasonable */ 3609701Slinton register struct symtab *q; 3619701Slinton OFFSZ off, tsize(); 3629701Slinton 3639701Slinton q = &stab[id]; 3649701Slinton printf( " .comm %s,", exname( q->sname ) ); 3659701Slinton off = tsize( q->stype, q->dimoff, q->sizoff ); 3669701Slinton printf( CONFMT, off/SZCHAR ); 3679701Slinton printf( "\n" ); 3689701Slinton } 3699701Slinton 3709701Slinton isitlong( cb, ce ){ /* is lastcon to be long or short */ 3719701Slinton /* cb is the first character of the representation, ce the last */ 3729701Slinton 3739701Slinton if( ce == 'l' || ce == 'L' || 3749701Slinton lastcon >= (1L << (SZINT-1) ) ) return (1); 3759701Slinton return(0); 3769701Slinton } 3779701Slinton 3789701Slinton 3799701Slinton isitfloat( s ) char *s; { 38018555Sralph union cvt { 38118555Sralph double d; 38218555Sralph int n[2]; 38318555Sralph } cvt; 3849701Slinton double atof(); 38518555Sralph 38618555Sralph /* avoid floating point exception for double -> float conversions */ 38718555Sralph dcon = cvt.d = atof(s); 38818555Sralph if( cvt.n[1] == 0 ){ 38918555Sralph fcon = dcon; 39018555Sralph return( FCON ); 39118555Sralph } 39218555Sralph return( DCON ); 3939701Slinton } 3949701Slinton 3959701Slinton ecode( p ) NODE *p; { 3969701Slinton 3979701Slinton /* walk the tree and write out the nodes.. */ 3989701Slinton 3999701Slinton if( nerrors ) return; 4009701Slinton p2tree( p ); 4019701Slinton p2compile( p ); 4029701Slinton } 4039701Slinton 4049701Slinton #ifndef ONEPASS 4059701Slinton tlen(p) NODE *p; 4069701Slinton { 4079701Slinton switch(p->in.type) { 4089701Slinton case CHAR: 4099701Slinton case UCHAR: 4109701Slinton return(1); 4119701Slinton 4129701Slinton case SHORT: 4139701Slinton case USHORT: 4149701Slinton return(2); 4159701Slinton 4169701Slinton case DOUBLE: 4179701Slinton return(8); 4189701Slinton 4199701Slinton default: 4209701Slinton return(4); 4219701Slinton } 4229701Slinton } 4239701Slinton #endif 424