1*16181Sralph static char *sccsid ="@(#)local.c 1.3 (Berkeley) 03/14/84"; 29701Slinton # include "mfile1" 39701Slinton 49701Slinton /* this file contains code which is dependent on the target machine */ 59701Slinton 69701Slinton NODE * 79701Slinton cast( p, t ) register NODE *p; TWORD t; { 89701Slinton /* cast node p to type t */ 99701Slinton 109701Slinton p = buildtree( CAST, block( NAME, NIL, NIL, t, 0, (int)t ), p ); 119701Slinton p->in.left->in.op = FREE; 129701Slinton p->in.op = FREE; 139701Slinton return( p->in.right ); 149701Slinton } 159701Slinton 169701Slinton NODE * 179701Slinton clocal(p) NODE *p; { 189701Slinton 199701Slinton /* this is called to do local transformations on 209701Slinton an expression tree preparitory to its being 219701Slinton written out in intermediate code. 229701Slinton */ 239701Slinton 249701Slinton /* the major essential job is rewriting the 259701Slinton automatic variables and arguments in terms of 269701Slinton REG and OREG nodes */ 279701Slinton /* conversion ops which are not necessary are also clobbered here */ 289701Slinton /* in addition, any special features (such as rewriting 299701Slinton exclusive or) are easily handled here as well */ 309701Slinton 319701Slinton register struct symtab *q; 329701Slinton register NODE *r; 339701Slinton register o; 349701Slinton register m, ml; 359701Slinton 369701Slinton switch( o = p->in.op ){ 379701Slinton 389701Slinton case NAME: 399701Slinton if( p->tn.rval < 0 ) { /* already processed; ignore... */ 409701Slinton return(p); 419701Slinton } 429701Slinton q = &stab[p->tn.rval]; 439701Slinton switch( q->sclass ){ 449701Slinton 459701Slinton case AUTO: 469701Slinton case PARAM: 479701Slinton /* fake up a structure reference */ 489701Slinton r = block( REG, NIL, NIL, PTR+STRTY, 0, 0 ); 499701Slinton r->tn.lval = 0; 509701Slinton r->tn.rval = (q->sclass==AUTO?STKREG:ARGREG); 519701Slinton p = stref( block( STREF, r, p, 0, 0, 0 ) ); 529701Slinton break; 539701Slinton 549701Slinton case ULABEL: 559701Slinton case LABEL: 569701Slinton case STATIC: 579701Slinton if( q->slevel == 0 ) break; 589701Slinton p->tn.lval = 0; 599701Slinton p->tn.rval = -q->offset; 609701Slinton break; 619701Slinton 629701Slinton case REGISTER: 639701Slinton p->in.op = REG; 649701Slinton p->tn.lval = 0; 659701Slinton p->tn.rval = q->offset; 669701Slinton break; 679701Slinton 689701Slinton } 699701Slinton break; 709701Slinton 719701Slinton case PCONV: 729701Slinton /* do pointer conversions for char and longs */ 739701Slinton ml = p->in.left->in.type; 749701Slinton if( ( ml==CHAR || ml==UCHAR || ml==SHORT || ml==USHORT ) && p->in.left->in.op != ICON ) break; 759701Slinton 769701Slinton /* pointers all have the same representation; the type is inherited */ 779701Slinton 789701Slinton inherit: 799701Slinton p->in.left->in.type = p->in.type; 809701Slinton p->in.left->fn.cdim = p->fn.cdim; 819701Slinton p->in.left->fn.csiz = p->fn.csiz; 829701Slinton p->in.op = FREE; 839701Slinton return( p->in.left ); 849701Slinton 859701Slinton case SCONV: 869701Slinton m = (p->in.type == FLOAT || p->in.type == DOUBLE ); 879701Slinton ml = (p->in.left->in.type == FLOAT || p->in.left->in.type == DOUBLE ); 889701Slinton if( m != ml ) break; 899701Slinton 909701Slinton /* now, look for conversions downwards */ 919701Slinton 929701Slinton m = p->in.type; 939701Slinton ml = p->in.left->in.type; 949701Slinton if( p->in.left->in.op == ICON ){ /* simulate the conversion here */ 959701Slinton CONSZ val; 969701Slinton val = p->in.left->tn.lval; 979701Slinton switch( m ){ 989701Slinton case CHAR: 999701Slinton p->in.left->tn.lval = (char) val; 1009701Slinton break; 1019701Slinton case UCHAR: 1029701Slinton p->in.left->tn.lval = val & 0XFF; 1039701Slinton break; 1049701Slinton case USHORT: 1059701Slinton p->in.left->tn.lval = val & 0XFFFFL; 1069701Slinton break; 1079701Slinton case SHORT: 1089701Slinton p->in.left->tn.lval = (short)val; 1099701Slinton break; 1109701Slinton case UNSIGNED: 1119701Slinton p->in.left->tn.lval = val & 0xFFFFFFFFL; 1129701Slinton break; 1139701Slinton case INT: 1149701Slinton p->in.left->tn.lval = (int)val; 1159701Slinton break; 1169701Slinton } 1179701Slinton p->in.left->in.type = m; 1189701Slinton } 119*16181Sralph else 120*16181Sralph break; 1219701Slinton 1229701Slinton /* clobber conversion */ 1239701Slinton p->in.op = FREE; 1249701Slinton return( p->in.left ); /* conversion gets clobbered */ 1259701Slinton 1269701Slinton case PVCONV: 1279701Slinton case PMCONV: 1289701Slinton if( p->in.right->in.op != ICON ) cerror( "bad conversion", 0); 1299701Slinton p->in.op = FREE; 1309701Slinton return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) ); 1319701Slinton 1329701Slinton case RS: 1339701Slinton case ASG RS: 1349701Slinton /* convert >> to << with negative shift count */ 1359701Slinton /* only if type of left operand is not unsigned */ 1369701Slinton 1379701Slinton if( ISUNSIGNED(p->in.left->in.type) ) break; 1389701Slinton p->in.right = buildtree( UNARY MINUS, p->in.right, NIL ); 1399701Slinton if( p->in.op == RS ) p->in.op = LS; 1409701Slinton else p->in.op = ASG LS; 1419701Slinton break; 1429701Slinton 1439701Slinton case FLD: 1449701Slinton /* make sure that the second pass does not make the 1459701Slinton descendant of a FLD operator into a doubly indexed OREG */ 1469701Slinton 1479701Slinton if( p->in.left->in.op == UNARY MUL 1489701Slinton && (r=p->in.left->in.left)->in.op == PCONV) 1499701Slinton if( r->in.left->in.op == PLUS || r->in.left->in.op == MINUS ) 1509701Slinton if( ISPTR(r->in.type) ) { 1519701Slinton if( ISUNSIGNED(p->in.left->in.type) ) 1529701Slinton p->in.left->in.type = UCHAR; 1539701Slinton else 1549701Slinton p->in.left->in.type = CHAR; 1559701Slinton } 1569701Slinton break; 1579701Slinton } 1589701Slinton 1599701Slinton return(p); 1609701Slinton } 1619701Slinton 1629701Slinton andable( p ) NODE *p; { 1639701Slinton return(1); /* all names can have & taken on them */ 1649701Slinton } 1659701Slinton 1669701Slinton cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */ 1679701Slinton autooff = AUTOINIT; 1689701Slinton } 1699701Slinton 1709701Slinton cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */ 1719701Slinton 1729701Slinton #ifdef TRUST_REG_CHAR_AND_REG_SHORT 1739701Slinton if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* tbl */ 1749701Slinton || t==CHAR || t==UCHAR || t==SHORT /* tbl */ 1759701Slinton || t==USHORT || ISPTR(t)) return(1); /* tbl */ 1769701Slinton #else 1779701Slinton if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* wnj */ 1789701Slinton || ISPTR(t)) return (1); /* wnj */ 1799701Slinton #endif 1809701Slinton return(0); 1819701Slinton } 1829701Slinton 1839701Slinton NODE * 1849701Slinton offcon( off, t, d, s ) OFFSZ off; TWORD t; { 1859701Slinton 1869701Slinton /* return a node, for structure references, which is suitable for 1879701Slinton being added to a pointer of type t, in order to be off bits offset 1889701Slinton into a structure */ 1899701Slinton 1909701Slinton register NODE *p; 1919701Slinton 1929701Slinton /* t, d, and s are the type, dimension offset, and sizeoffset */ 1939701Slinton /* in general they are necessary for offcon, but not on H'well */ 1949701Slinton 1959701Slinton p = bcon(0); 1969701Slinton p->tn.lval = off/SZCHAR; 1979701Slinton return(p); 1989701Slinton 1999701Slinton } 2009701Slinton 2019701Slinton 2029701Slinton static inwd /* current bit offsed in word */; 2039701Slinton static word /* word being built from fields */; 2049701Slinton 2059701Slinton incode( p, sz ) register NODE *p; { 2069701Slinton 2079701Slinton /* generate initialization code for assigning a constant c 2089701Slinton to a field of width sz */ 2099701Slinton /* we assume that the proper alignment has been obtained */ 2109701Slinton /* inoff is updated to have the proper final value */ 2119701Slinton /* we also assume sz < SZINT */ 2129701Slinton 2139701Slinton if((sz+inwd) > SZINT) cerror("incode: field > int"); 2149701Slinton word |= ((unsigned)(p->tn.lval<<(32-sz))) >> (32-sz-inwd); 2159701Slinton inwd += sz; 2169701Slinton inoff += sz; 2179701Slinton if(inoff%SZINT == 0) { 2189701Slinton printf( " .long 0x%x\n", word); 2199701Slinton word = inwd = 0; 2209701Slinton } 2219701Slinton } 2229701Slinton 2239701Slinton fincode( d, sz ) double d; { 2249701Slinton /* output code to initialize space of size sz to the value d */ 2259701Slinton /* the proper alignment has been obtained */ 2269701Slinton /* inoff is updated to have the proper final value */ 2279701Slinton /* on the target machine, write it out in octal! */ 2289701Slinton 2299701Slinton 2309701Slinton printf(" %s 0%c%.20e\n", sz == SZDOUBLE ? ".double" : ".float", 2319701Slinton sz == SZDOUBLE ? 'd' : 'f', d); 2329701Slinton inoff += sz; 2339701Slinton } 2349701Slinton 2359701Slinton cinit( p, sz ) NODE *p; { 2369701Slinton /* arrange for the initialization of p into a space of 2379701Slinton size sz */ 2389701Slinton /* the proper alignment has been opbtained */ 2399701Slinton /* inoff is updated to have the proper final value */ 2409701Slinton ecode( p ); 2419701Slinton inoff += sz; 2429701Slinton } 2439701Slinton 2449701Slinton vfdzero( n ){ /* define n bits of zeros in a vfd */ 2459701Slinton 2469701Slinton if( n <= 0 ) return; 2479701Slinton 2489701Slinton inwd += n; 2499701Slinton inoff += n; 2509701Slinton if( inoff%ALINT ==0 ) { 2519701Slinton printf( " .long 0x%x\n", word ); 2529701Slinton word = inwd = 0; 2539701Slinton } 2549701Slinton } 2559701Slinton 2569701Slinton char * 2579701Slinton exname( p ) char *p; { 2589701Slinton /* make a name look like an external name in the local machine */ 2599701Slinton 2609701Slinton #ifndef FLEXNAMES 2619701Slinton static char text[NCHNAM+1]; 2629701Slinton #else 2639701Slinton static char text[BUFSIZ+1]; 2649701Slinton #endif 2659701Slinton 2669701Slinton register i; 2679701Slinton 2689701Slinton text[0] = '_'; 2699701Slinton #ifndef FLEXNAMES 2709701Slinton for( i=1; *p&&i<NCHNAM; ++i ){ 2719701Slinton #else 2729701Slinton for( i=1; *p; ++i ){ 2739701Slinton #endif 2749701Slinton text[i] = *p++; 2759701Slinton } 2769701Slinton 2779701Slinton text[i] = '\0'; 2789701Slinton #ifndef FLEXNAMES 2799701Slinton text[NCHNAM] = '\0'; /* truncate */ 2809701Slinton #endif 2819701Slinton 2829701Slinton return( text ); 2839701Slinton } 2849701Slinton 2859701Slinton ctype( type ){ /* map types which are not defined on the local machine */ 2869701Slinton switch( BTYPE(type) ){ 2879701Slinton 2889701Slinton case LONG: 2899701Slinton MODTYPE(type,INT); 2909701Slinton break; 2919701Slinton 2929701Slinton case ULONG: 2939701Slinton MODTYPE(type,UNSIGNED); 2949701Slinton } 2959701Slinton return( type ); 2969701Slinton } 2979701Slinton 2989701Slinton noinit( t ) { /* curid is a variable which is defined but 2999701Slinton is not initialized (and not a function ); 3009701Slinton This routine returns the stroage class for an uninitialized declaration */ 3019701Slinton 3029701Slinton return(EXTERN); 3039701Slinton 3049701Slinton } 3059701Slinton 3069701Slinton commdec( id ){ /* make a common declaration for id, if reasonable */ 3079701Slinton register struct symtab *q; 3089701Slinton OFFSZ off, tsize(); 3099701Slinton 3109701Slinton q = &stab[id]; 3119701Slinton printf( " .comm %s,", exname( q->sname ) ); 3129701Slinton off = tsize( q->stype, q->dimoff, q->sizoff ); 3139701Slinton printf( CONFMT, off/SZCHAR ); 3149701Slinton printf( "\n" ); 3159701Slinton } 3169701Slinton 3179701Slinton isitlong( cb, ce ){ /* is lastcon to be long or short */ 3189701Slinton /* cb is the first character of the representation, ce the last */ 3199701Slinton 3209701Slinton if( ce == 'l' || ce == 'L' || 3219701Slinton lastcon >= (1L << (SZINT-1) ) ) return (1); 3229701Slinton return(0); 3239701Slinton } 3249701Slinton 3259701Slinton 3269701Slinton isitfloat( s ) char *s; { 3279701Slinton double atof(); 3289701Slinton dcon = atof(s); 3299701Slinton return( FCON ); 3309701Slinton } 3319701Slinton 3329701Slinton ecode( p ) NODE *p; { 3339701Slinton 3349701Slinton /* walk the tree and write out the nodes.. */ 3359701Slinton 3369701Slinton if( nerrors ) return; 3379701Slinton p2tree( p ); 3389701Slinton p2compile( p ); 3399701Slinton } 3409701Slinton 3419701Slinton #ifndef ONEPASS 3429701Slinton tlen(p) NODE *p; 3439701Slinton { 3449701Slinton switch(p->in.type) { 3459701Slinton case CHAR: 3469701Slinton case UCHAR: 3479701Slinton return(1); 3489701Slinton 3499701Slinton case SHORT: 3509701Slinton case USHORT: 3519701Slinton return(2); 3529701Slinton 3539701Slinton case DOUBLE: 3549701Slinton return(8); 3559701Slinton 3569701Slinton default: 3579701Slinton return(4); 3589701Slinton } 3599701Slinton } 3609701Slinton #endif 361