1: #ifndef lint 2: static char *sccsid ="@(#)local.c 1.8 (Berkeley) 8/23/85"; 3: #endif lint 4: 5: # include "pass1.h" 6: 7: /* this file contains code which is dependent on the target machine */ 8: 9: NODE * 10: cast( p, t ) register NODE *p; TWORD t; { 11: /* cast node p to type t */ 12: 13: p = buildtree( CAST, block( NAME, NIL, NIL, t, 0, (int)t ), p ); 14: p->in.left->in.op = FREE; 15: p->in.op = FREE; 16: return( p->in.right ); 17: } 18: 19: NODE * 20: clocal(p) NODE *p; { 21: 22: /* this is called to do local transformations on 23: an expression tree preparitory to its being 24: written out in intermediate code. 25: */ 26: 27: /* the major essential job is rewriting the 28: automatic variables and arguments in terms of 29: REG and OREG nodes */ 30: /* conversion ops which are not necessary are also clobbered here */ 31: /* in addition, any special features (such as rewriting 32: exclusive or) are easily handled here as well */ 33: 34: register struct symtab *q; 35: register NODE *r; 36: register o; 37: register m, ml; 38: 39: switch( o = p->in.op ){ 40: 41: case NAME: 42: if( p->tn.rval < 0 ) { /* already processed; ignore... */ 43: return(p); 44: } 45: q = &stab[p->tn.rval]; 46: switch( q->sclass ){ 47: 48: case AUTO: 49: case PARAM: 50: /* fake up a structure reference */ 51: r = block( REG, NIL, NIL, PTR+STRTY, 0, 0 ); 52: r->tn.lval = 0; 53: r->tn.rval = (q->sclass==AUTO?STKREG:ARGREG); 54: p = stref( block( STREF, r, p, 0, 0, 0 ) ); 55: break; 56: 57: case ULABEL: 58: case LABEL: 59: case STATIC: 60: if( q->slevel == 0 ) break; 61: p->tn.lval = 0; 62: p->tn.rval = -q->offset; 63: break; 64: 65: case REGISTER: 66: p->in.op = REG; 67: p->tn.lval = 0; 68: p->tn.rval = q->offset; 69: break; 70: 71: } 72: break; 73: 74: case PCONV: 75: /* do pointer conversions for char and longs */ 76: ml = p->in.left->in.type; 77: if( ( ml==CHAR || ml==UCHAR || ml==SHORT || ml==USHORT ) && p->in.left->in.op != ICON ) break; 78: 79: /* pointers all have the same representation; the type is inherited */ 80: 81: p->in.left->in.type = p->in.type; 82: p->in.left->fn.cdim = p->fn.cdim; 83: p->in.left->fn.csiz = p->fn.csiz; 84: p->in.op = FREE; 85: return( p->in.left ); 86: 87: case SCONV: 88: m = (p->in.type == FLOAT || p->in.type == DOUBLE ); 89: ml = (p->in.left->in.type == FLOAT || p->in.left->in.type == DOUBLE ); 90: o = p->in.left->in.op; 91: if( (o == FCON || o == DCON) && ml && !m ) { 92: /* float type to int type */ 93: r = block( ICON, (NODE *)NULL, (NODE *)NULL, INT, 0, 0 ); 94: if( o == FCON ) 95: r->tn.lval = (int) p->in.left->fpn.fval; 96: else 97: r->tn.lval = (int) p->in.left->dpn.dval; 98: r->tn.rval = NONAME; 99: p->in.left->in.op = FREE; 100: p->in.left = r; 101: } 102: else 103: #ifdef SPRECC 104: if ( ml || m ) 105: #else 106: if ( ml != m ) 107: #endif 108: break; 109: 110: /* now, look for conversions downwards */ 111: 112: m = p->in.type; 113: ml = p->in.left->in.type; 114: if( p->in.left->in.op == ICON ){ /* simulate the conversion here */ 115: CONSZ val; 116: val = p->in.left->tn.lval; 117: switch( m ){ 118: case CHAR: 119: p->in.left->tn.lval = (char) val; 120: break; 121: case UCHAR: 122: p->in.left->tn.lval = val & 0XFF; 123: break; 124: case USHORT: 125: p->in.left->tn.lval = val & 0XFFFFL; 126: break; 127: case SHORT: 128: p->in.left->tn.lval = (short)val; 129: break; 130: case UNSIGNED: 131: p->in.left->tn.lval = val & 0xFFFFFFFFL; 132: break; 133: case INT: 134: p->in.left->tn.lval = (int)val; 135: break; 136: } 137: p->in.left->in.type = m; 138: } 139: else if( m != FLOAT && m != DOUBLE ) 140: break; 141: 142: /* clobber conversion */ 143: p->in.op = FREE; 144: return( p->in.left ); /* conversion gets clobbered */ 145: 146: case PVCONV: 147: case PMCONV: 148: if( p->in.right->in.op != ICON ) cerror( "bad conversion", 0); 149: p->in.op = FREE; 150: return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) ); 151: 152: case RS: 153: case ASG RS: 154: /* convert >> to << with negative shift count */ 155: /* only if type of left operand is not unsigned */ 156: 157: if( ISUNSIGNED(p->in.left->in.type) ) break; 158: if( p->in.right->in.op != UNARY MINUS ) 159: p->in.right = buildtree( UNARY MINUS, p->in.right, NIL ); 160: else { 161: r = p->in.right; 162: p->in.right = p->in.right->in.left; 163: r->in.op = FREE; 164: } 165: if( p->in.op == RS ) p->in.op = LS; 166: else p->in.op = ASG LS; 167: break; 168: 169: case FLD: 170: /* make sure that the second pass does not make the 171: descendant of a FLD operator into a doubly indexed OREG */ 172: 173: if( p->in.left->in.op == UNARY MUL 174: && (r=p->in.left->in.left)->in.op == PCONV) 175: if( r->in.left->in.op == PLUS || r->in.left->in.op == MINUS ) 176: if( ISPTR(r->in.type) ) { 177: if( ISUNSIGNED(p->in.left->in.type) ) 178: p->in.left->in.type = UCHAR; 179: else 180: p->in.left->in.type = CHAR; 181: } 182: break; 183: } 184: 185: return(p); 186: } 187: 188: andable( p ) NODE *p; { 189: return(1); /* all names can have & taken on them */ 190: } 191: 192: cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */ 193: autooff = AUTOINIT; 194: } 195: 196: cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */ 197: 198: #ifdef TRUST_REG_CHAR_AND_REG_SHORT 199: if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* tbl */ 200: || t==CHAR || t==UCHAR || t==SHORT /* tbl */ 201: || t==USHORT || ISPTR(t)) return(1); /* tbl */ 202: #else 203: if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* wnj */ 204: #ifdef SPRECC 205: || t==FLOAT 206: #endif 207: || ISPTR(t)) return (1); /* wnj */ 208: #endif 209: return(0); 210: } 211: 212: NODE * 213: offcon( off, t, d, s ) OFFSZ off; TWORD t; { 214: 215: /* return a node, for structure references, which is suitable for 216: being added to a pointer of type t, in order to be off bits offset 217: into a structure */ 218: 219: register NODE *p; 220: 221: /* t, d, and s are the type, dimension offset, and sizeoffset */ 222: /* in general they are necessary for offcon, but not on H'well */ 223: 224: p = bcon(0); 225: p->tn.lval = off/SZCHAR; 226: return(p); 227: 228: } 229: 230: 231: static inwd /* current bit offsed in word */; 232: static word /* word being built from fields */; 233: 234: incode( p, sz ) register NODE *p; { 235: 236: /* generate initialization code for assigning a constant c 237: to a field of width sz */ 238: /* we assume that the proper alignment has been obtained */ 239: /* inoff is updated to have the proper final value */ 240: /* we also assume sz < SZINT */ 241: 242: if((sz+inwd) > SZINT) cerror("incode: field > int"); 243: word |= ((unsigned)(p->tn.lval<<(32-sz))) >> (32-sz-inwd); 244: inwd += sz; 245: inoff += sz; 246: if(inoff%SZINT == 0) { 247: printf( " .long 0x%x\n", word); 248: word = inwd = 0; 249: } 250: } 251: 252: fincode( d, sz ) double d; { 253: /* output code to initialize space of size sz to the value d */ 254: /* the proper alignment has been obtained */ 255: /* inoff is updated to have the proper final value */ 256: /* on the target machine, write it out in octal! */ 257: 258: 259: printf(" %s 0%c%.20e\n", sz == SZDOUBLE ? ".double" : ".float", 260: sz == SZDOUBLE ? 'd' : 'f', d); 261: inoff += sz; 262: } 263: 264: cinit( p, sz ) NODE *p; { 265: NODE *l; 266: 267: /* 268: * as a favor (?) to people who want to write 269: * int i = 9600/134.5; 270: * we will, under the proper circumstances, do 271: * a coersion here. 272: */ 273: switch (p->in.type) { 274: case INT: 275: case UNSIGNED: 276: l = p->in.left; 277: if (l->in.op != SCONV || 278: (l->in.left->tn.op != DCON && l->in.left->tn.op != FCON)) 279: break; 280: l->in.op = FREE; 281: l = l->in.left; 282: l->tn.lval = l->tn.op == DCON ? (long)(l->dpn.dval) : 283: (long)(l->fpn.fval); 284: l->tn.rval = NONAME; 285: l->tn.op = ICON; 286: l->tn.type = INT; 287: p->in.left = l; 288: break; 289: } 290: /* arrange for the initialization of p into a space of size sz */ 291: /* the proper alignment has been opbtained */ 292: /* inoff is updated to have the proper final value */ 293: ecode( p ); 294: inoff += sz; 295: } 296: 297: vfdzero( n ){ /* define n bits of zeros in a vfd */ 298: 299: if( n <= 0 ) return; 300: 301: inwd += n; 302: inoff += n; 303: if( inoff%ALINT ==0 ) { 304: printf( " .long 0x%x\n", word ); 305: word = inwd = 0; 306: } 307: } 308: 309: char * 310: exname( p ) char *p; { 311: /* make a name look like an external name in the local machine */ 312: 313: #ifndef FLEXNAMES 314: static char text[NCHNAM+1]; 315: #else 316: static char text[BUFSIZ+1]; 317: #endif 318: 319: register i; 320: 321: text[0] = '_'; 322: #ifndef FLEXNAMES 323: for( i=1; *p&&i<NCHNAM; ++i ) 324: #else 325: for( i=1; *p; ++i ) 326: #endif 327: text[i] = *p++; 328: 329: text[i] = '\0'; 330: #ifndef FLEXNAMES 331: text[NCHNAM] = '\0'; /* truncate */ 332: #endif 333: 334: return( text ); 335: } 336: 337: ctype( type ) TWORD type; 338: { /* map types which are not defined on the local machine */ 339: switch( BTYPE(type) ){ 340: 341: case LONG: 342: MODTYPE(type,INT); 343: break; 344: 345: case ULONG: 346: MODTYPE(type,UNSIGNED); 347: } 348: return( type ); 349: } 350: 351: noinit() { /* curid is a variable which is defined but 352: is not initialized (and not a function ); 353: This routine returns the stroage class for an uninitialized declaration */ 354: 355: return(EXTERN); 356: 357: } 358: 359: commdec( id ){ /* make a common declaration for id, if reasonable */ 360: register struct symtab *q; 361: OFFSZ off, tsize(); 362: 363: q = &stab[id]; 364: printf( " .comm %s,", exname( q->sname ) ); 365: off = tsize( q->stype, q->dimoff, q->sizoff ); 366: printf( CONFMT, off/SZCHAR ); 367: printf( "\n" ); 368: } 369: 370: isitlong( cb, ce ){ /* is lastcon to be long or short */ 371: /* cb is the first character of the representation, ce the last */ 372: 373: if( ce == 'l' || ce == 'L' || 374: lastcon >= (1L << (SZINT-1) ) ) return (1); 375: return(0); 376: } 377: 378: 379: isitfloat( s ) char *s; { 380: union cvt { 381: double d; 382: int n[2]; 383: } cvt; 384: double atof(); 385: 386: /* avoid floating point exception for double -> float conversions */ 387: dcon = cvt.d = atof(s); 388: if( cvt.n[1] == 0 ){ 389: fcon = dcon; 390: return( FCON ); 391: } 392: return( DCON ); 393: } 394: 395: ecode( p ) NODE *p; { 396: 397: /* walk the tree and write out the nodes.. */ 398: 399: if( nerrors ) return; 400: p2tree( p ); 401: p2compile( p ); 402: } 403: 404: #ifndef ONEPASS 405: tlen(p) NODE *p; 406: { 407: switch(p->in.type) { 408: case CHAR: 409: case UCHAR: 410: return(1); 411: 412: case SHORT: 413: case USHORT: 414: return(2); 415: 416: case DOUBLE: 417: return(8); 418: 419: default: 420: return(4); 421: } 422: } 423: #endif