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