|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)local.c 1.10 (Berkeley) 12/10/87"; ! 3: #endif ! 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 = STKREG; ! 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: #ifdef REG_CHAR ! 60: m = p->in.type; ! 61: if( m==CHAR || m==SHORT ) ! 62: p->in.type = INT; ! 63: else if( m==UCHAR || m==USHORT ) ! 64: p->in.type = UNSIGNED; ! 65: #endif ! 66: break; ! 67: ! 68: } ! 69: break; ! 70: ! 71: case LT: ! 72: case LE: ! 73: case GT: ! 74: case GE: ! 75: if( ISPTR( p->in.left->in.type ) || ISPTR( p->in.right->in.type ) ){ ! 76: p->in.op += (ULT-LT); ! 77: } ! 78: break; ! 79: ! 80: case PCONV: ! 81: /* do pointer conversions for char and longs */ ! 82: ml = p->in.left->in.type; ! 83: if( ( ml==CHAR || ml==UCHAR || ml==SHORT || ml==USHORT ) && p->in.left->in.op != ICON ) break; ! 84: ! 85: /* pointers all have the same representation; the type is inherited */ ! 86: ! 87: p->in.left->in.type = p->in.type; ! 88: p->in.left->fn.cdim = p->fn.cdim; ! 89: p->in.left->fn.csiz = p->fn.csiz; ! 90: p->in.op = FREE; ! 91: return( p->in.left ); ! 92: ! 93: case SCONV: ! 94: m = p->in.type; ! 95: ml = p->in.left->in.type; ! 96: if(m == ml) ! 97: goto clobber; ! 98: o = p->in.left->in.op; ! 99: if(m == FLOAT || m == DOUBLE) { ! 100: if(o==SCONV && ! 101: ml == DOUBLE && ! 102: p->in.left->in.left->in.type==m) { ! 103: p->in.op = p->in.left->in.op = FREE; ! 104: return(p->in.left->in.left); ! 105: } ! 106: /* see makety() for constant conversions */ ! 107: break; ! 108: } ! 109: if(ml == FLOAT || ml == DOUBLE){ ! 110: if(o != FCON && o != DCON) ! 111: break; ! 112: ml = ISUNSIGNED(m) ? UNSIGNED : INT; /* LONG? */ ! 113: r = block( ICON, (NODE *)NULL, (NODE *)NULL, ml, 0, 0 ); ! 114: if( o == FCON ) ! 115: r->tn.lval = ml == INT ? ! 116: (int) p->in.left->fpn.fval : ! 117: (unsigned) p->in.left->fpn.fval; ! 118: else ! 119: r->tn.lval = ml == INT ? ! 120: (int) p->in.left->dpn.dval : ! 121: (unsigned) p->in.left->dpn.dval; ! 122: r->tn.rval = NONAME; ! 123: p->in.left->in.op = FREE; ! 124: p->in.left = r; ! 125: o = ICON; ! 126: if( m == ml ) ! 127: goto clobber; ! 128: } ! 129: /* now, look for conversions downwards */ ! 130: ! 131: if( o == ICON ){ /* simulate the conversion here */ ! 132: CONSZ val; ! 133: val = p->in.left->tn.lval; ! 134: switch( m ){ ! 135: case CHAR: ! 136: p->in.left->tn.lval = (char) val; ! 137: break; ! 138: case UCHAR: ! 139: p->in.left->tn.lval = val & 0XFF; ! 140: break; ! 141: case USHORT: ! 142: p->in.left->tn.lval = val & 0XFFFFL; ! 143: break; ! 144: case SHORT: ! 145: p->in.left->tn.lval = (short)val; ! 146: break; ! 147: case UNSIGNED: ! 148: p->in.left->tn.lval = val & 0xFFFFFFFFL; ! 149: break; ! 150: case INT: ! 151: p->in.left->tn.lval = (int)val; ! 152: break; ! 153: } ! 154: p->in.left->in.type = m; ! 155: } ! 156: else ! 157: break; ! 158: ! 159: clobber: ! 160: p->in.op = FREE; ! 161: return( p->in.left ); /* conversion gets clobbered */ ! 162: ! 163: case PVCONV: ! 164: case PMCONV: ! 165: if( p->in.right->in.op != ICON ) cerror( "bad conversion", 0); ! 166: p->in.op = FREE; ! 167: return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) ); ! 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 = UNSIGNED; ! 179: else ! 180: p->in.left->in.type = INT; ! 181: } ! 182: break; ! 183: case FORTCALL: /* arg must be FLOAT */ ! 184: if((r = p->in.right)->in.type != FLOAT) ! 185: p->in.right = clocal(makety(r, FLOAT, 0, FLOAT)); ! 186: return(p); ! 187: } ! 188: ! 189: return(p); ! 190: } ! 191: ! 192: /*ARGSUSED*/ ! 193: andable( p ) NODE *p; { ! 194: return(1); /* all names can have & taken on them */ ! 195: } ! 196: ! 197: cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */ ! 198: autooff = AUTOINIT; ! 199: } ! 200: ! 201: cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */ ! 202: ! 203: if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* tbl */ ! 204: #ifdef REG_CHAR ! 205: || t==CHAR || t==UCHAR || t==SHORT || t==USHORT /* tbl */ ! 206: #endif ! 207: || ISPTR(t) || t == FLOAT) return (1); /* wnj */ ! 208: return(0); ! 209: } ! 210: ! 211: /*ARGSUSED*/ ! 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 Tahoe */ ! 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 CONSZ 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(nerrors) return; ! 243: inwd += sz; ! 244: if(inwd > SZINT) cerror("incode: field > int"); ! 245: word |= (p->tn.lval&((1L<<sz)-1)) << (SZINT-inwd); ! 246: inoff += sz; ! 247: if(inoff%SZINT == 0) { ! 248: printf( " .long 0x%lx\n", word); ! 249: word = inwd = 0; ! 250: } ! 251: } ! 252: ! 253: fincode( d, sz ) double d; register int sz; { ! 254: /* ! 255: * output code to initialize space of size sz to the value d ! 256: * the proper alignment has been obtained ! 257: * inoff is updated to have the proper final value. ! 258: */ ! 259: ! 260: register struct sh4 { ! 261: unsigned short sh[4]; ! 262: } *x; ! 263: float f; ! 264: ! 265: if (nerrors) return; ! 266: if(sz == SZFLOAT) { /* force rounding */ ! 267: f = d; ! 268: d = f; ! 269: } ! 270: ! 271: x = (struct sh4 *)&d; ! 272: printf(" .long 0x%04x%04x", x->sh[0], x->sh[1]); ! 273: if(sz == SZDOUBLE) { ! 274: printf(", 0x%04x%04x", x->sh[2], x->sh[3]); ! 275: printf(" # .double %.17g\n", d); ! 276: } else ! 277: printf(" # .float %.8g\n", d); ! 278: inoff += sz; ! 279: } ! 280: ! 281: cinit( p, sz ) NODE *p; { ! 282: NODE *l; ! 283: ! 284: /* ! 285: * as a favor (?) to people who want to write ! 286: * int i = 9600/134.5; ! 287: * we will, under the proper circumstances, do ! 288: * a coercion here. ! 289: */ ! 290: switch (p->in.type) { ! 291: case INT: ! 292: case UNSIGNED: ! 293: l = p->in.left; ! 294: if (l->in.op != SCONV || ! 295: (l->in.left->tn.op != DCON && l->in.left->tn.op != FCON)) ! 296: break; ! 297: l->in.op = FREE; ! 298: l = l->in.left; ! 299: l->tn.lval = l->tn.op == DCON ? (long)(l->dpn.dval) : ! 300: (long)(l->fpn.fval); ! 301: l->tn.rval = NONAME; ! 302: l->tn.op = ICON; ! 303: l->tn.type = INT; ! 304: p->in.left = l; ! 305: break; ! 306: } ! 307: /* arrange for the initialization of p into a space of size sz */ ! 308: /* the proper alignment has been opbtained */ ! 309: /* inoff is updated to have the proper final value */ ! 310: ecode( p ); ! 311: inoff += sz; ! 312: } ! 313: ! 314: vfdzero( n ){ /* define n bits of zeros in a vfd */ ! 315: ! 316: if( n <= 0 ) return; ! 317: ! 318: if (nerrors) return; ! 319: inwd += n; ! 320: inoff += n; ! 321: if( inoff%ALINT ==0 ) { ! 322: printf( " .long 0x%lx\n", word ); ! 323: word = inwd = 0; ! 324: } ! 325: } ! 326: ! 327: char * ! 328: exname( p ) char *p; { ! 329: /* make a name look like an external name in the local machine */ ! 330: ! 331: #ifndef FLEXNAMES ! 332: static char text[NCHNAM+1]; ! 333: #else ! 334: static char text[BUFSIZ+1]; ! 335: #endif ! 336: ! 337: register int i; ! 338: ! 339: text[0] = '_'; ! 340: #ifndef FLEXNAMES ! 341: for( i=1; *p&&i<NCHNAM; ++i ) ! 342: #else ! 343: for( i=1; *p; ++i ) ! 344: #endif ! 345: text[i] = *p++; ! 346: ! 347: text[i] = '\0'; ! 348: #ifndef FLEXNAMES ! 349: text[NCHNAM] = '\0'; /* truncate */ ! 350: #endif ! 351: ! 352: return( text ); ! 353: } ! 354: ! 355: ctype( type ) TWORD type; ! 356: { /* map types which are not defined on the local machine */ ! 357: switch( BTYPE(type) ){ ! 358: ! 359: case LONG: ! 360: MODTYPE(type,INT); ! 361: break; ! 362: ! 363: case ULONG: ! 364: MODTYPE(type,UNSIGNED); ! 365: } ! 366: return( type ); ! 367: } ! 368: ! 369: noinit() { /* curid is a variable which is defined but ! 370: is not initialized (and not a function ); ! 371: This routine returns the stroage class for an uninitialized declaration */ ! 372: ! 373: return(EXTERN); ! 374: ! 375: } ! 376: ! 377: commdec( id ){ /* make a common declaration for id, if reasonable */ ! 378: register struct symtab *q; ! 379: OFFSZ off, tsize(); ! 380: ! 381: if (nerrors) return; ! 382: q = &stab[id]; ! 383: printf( " .comm %s,", exname( q->sname ) ); ! 384: off = tsize( q->stype, q->dimoff, q->sizoff ); ! 385: printf( "%d\n" /*CONFMT*/, off/SZCHAR ); ! 386: } ! 387: ! 388: prtdcon(p) ! 389: register NODE *p; ! 390: { ! 391: register int o = p->in.op; ! 392: int i; ! 393: ! 394: if (o != DCON && o != FCON) ! 395: return; ! 396: /* ! 397: * Clobber constants of value zero so ! 398: * we can generate more efficient code. ! 399: */ ! 400: if ((o == DCON && p->dpn.dval == 0) || ! 401: (o == FCON && p->fpn.fval == 0)) { ! 402: p->in.op = ICON; ! 403: p->tn.rval = NONAME; ! 404: return; ! 405: } ! 406: locctr(DATA); ! 407: defalign(o == DCON ? ALDOUBLE : ALFLOAT); ! 408: deflab(i = getlab()); ! 409: if (o == FCON) ! 410: fincode(p->fpn.fval, SZFLOAT); ! 411: else ! 412: fincode(p->dpn.dval, SZDOUBLE); ! 413: p->tn.lval = 0; ! 414: p->tn.rval = -i; ! 415: p->in.type = (o == DCON ? DOUBLE : FLOAT); ! 416: p->in.op = NAME; ! 417: } ! 418: ! 419: ecode( p ) NODE *p; { ! 420: ! 421: /* walk the tree and write out the nodes.. */ ! 422: ! 423: if( nerrors ) return; ! 424: p2tree( p ); ! 425: p2compile( p ); ! 426: } ! 427: ! 428: #ifndef ONEPASS ! 429: tlen(p) NODE *p; ! 430: { ! 431: switch(p->in.type) { ! 432: case CHAR: ! 433: case UCHAR: ! 434: return(1); ! 435: ! 436: case SHORT: ! 437: case USHORT: ! 438: return(SZSHORT/SZCHAR); ! 439: ! 440: case DOUBLE: ! 441: return(SZDOUBLE/SZCHAR); ! 442: ! 443: default: ! 444: return(SZINT/SZCHAR); ! 445: } ! 446: } ! 447: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.