|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)local.c 1.5 (Berkeley) 1/9/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: inherit: ! 88: p->in.left->in.type = p->in.type; ! 89: p->in.left->fn.cdim = p->fn.cdim; ! 90: p->in.left->fn.csiz = p->fn.csiz; ! 91: p->in.op = FREE; ! 92: return( p->in.left ); ! 93: ! 94: case SCONV: ! 95: m = p->in.type; ! 96: ml = p->in.left->in.type; ! 97: if(m == FLOAT || m == DOUBLE) { ! 98: if(p->in.left->in.op==SCONV && ! 99: ml == DOUBLE && ! 100: p->in.left->in.left->in.type==m) { ! 101: p->in.op = p->in.left->in.op = FREE; ! 102: return(p->in.left->in.left); ! 103: } ! 104: if(p->in.left->in.op==FCON) ! 105: goto inherit; ! 106: break; ! 107: } ! 108: if(ml == FLOAT || ml == DOUBLE){ ! 109: if (p->in.left->in.op == FCON){ ! 110: p->in.left->in.op = FREE; ! 111: p->in.op = ICON; ! 112: p->tn.lval = p->in.left->fpn.fval; ! 113: p->tn.rval = NONAME; ! 114: return(p); ! 115: } ! 116: break; ! 117: } ! 118: /* now, look for conversions downwards */ ! 119: ! 120: if( p->in.left->in.op == ICON ){ /* simulate the conversion here */ ! 121: CONSZ val; ! 122: val = p->in.left->tn.lval; ! 123: switch( m ){ ! 124: case CHAR: ! 125: p->in.left->tn.lval = (char) val; ! 126: break; ! 127: case UCHAR: ! 128: p->in.left->tn.lval = val & 0XFF; ! 129: break; ! 130: case USHORT: ! 131: p->in.left->tn.lval = val & 0XFFFFL; ! 132: break; ! 133: case SHORT: ! 134: p->in.left->tn.lval = (short)val; ! 135: break; ! 136: case UNSIGNED: ! 137: p->in.left->tn.lval = val & 0xFFFFFFFFL; ! 138: break; ! 139: case INT: ! 140: p->in.left->tn.lval = (int)val; ! 141: break; ! 142: } ! 143: p->in.left->in.type = m; ! 144: } else if (tlen(p) == tlen(p->in.left)) ! 145: goto inherit; ! 146: else ! 147: break; ! 148: /* clobber conversion */ ! 149: p->in.op = FREE; ! 150: return( p->in.left ); /* conversion gets clobbered */ ! 151: break; ! 152: ! 153: case QUEST: /* the right side should be COLON */ ! 154: if((r = p->in.right)->in.op == SCONV) { ! 155: p->in.right = r->in.left; ! 156: p->in.type = r->in.left->in.type; ! 157: r->in.left = p; ! 158: return(r); ! 159: } ! 160: return(p); ! 161: ! 162: case PVCONV: ! 163: case PMCONV: ! 164: if( p->in.right->in.op != ICON ) cerror( "bad conversion", 0); ! 165: p->in.op = FREE; ! 166: return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) ); ! 167: ! 168: case FLD: ! 169: /* make sure that the second pass does not make the ! 170: descendant of a FLD operator into a doubly indexed OREG */ ! 171: ! 172: if( p->in.left->in.op == UNARY MUL ! 173: && (r=p->in.left->in.left)->in.op == PCONV) ! 174: if( r->in.left->in.op == PLUS || r->in.left->in.op == MINUS ) ! 175: if( ISPTR(r->in.type) ) { ! 176: if( ISUNSIGNED(p->in.left->in.type) ) ! 177: p->in.left->in.type = UNSIGNED; ! 178: else ! 179: p->in.left->in.type = INT; ! 180: } ! 181: break; ! 182: case FORTCALL: /* arg must be FLOAT */ ! 183: if((r = p->in.right)->in.type != FLOAT) ! 184: p->in.right = clocal(makety(r, FLOAT, 0, FLOAT)); ! 185: return(p); ! 186: } ! 187: ! 188: /* if both sides are FLOAT, so is the op */ ! 189: if(optype(o)!=LTYPE && p->in.left->in.type==DOUBLE && ! 190: (o==UNARY MINUS || optype(o)==BITYPE && p->in.right->in.type==DOUBLE)) { ! 191: r = p->in.left; ! 192: if(r->in.op==SCONV && r->in.left->in.type==FLOAT) { ! 193: if(optype(o)==BITYPE) { ! 194: r = p->in.right; ! 195: if(r->in.op==SCONV && r->in.left->in.type==FLOAT) { ! 196: r->in.op = FREE; ! 197: p->in.right = r->in.left; ! 198: } else if(r->in.op==FCON) ! 199: r->in.type = FLOAT; ! 200: else ! 201: return(p); ! 202: } ! 203: r = p->in.left; ! 204: p->in.left = r->in.left; ! 205: } else if(optype(o)==BITYPE && r->in.op==FCON) { ! 206: r = p->in.right; ! 207: if(!(r->in.op==SCONV && r->in.left->in.type==FLOAT)) ! 208: return(p); ! 209: p->in.right = r->in.left; ! 210: p->in.left->in.type = FLOAT; ! 211: } else ! 212: return(p); ! 213: if(p->in.type==DOUBLE) { ! 214: p->in.type = FLOAT; ! 215: r->in.left = p; ! 216: return(r); ! 217: } else { /* usually logop */ ! 218: r->in.op = FREE; ! 219: return(p); ! 220: } ! 221: } ! 222: return(p); ! 223: } ! 224: ! 225: andable( p ) NODE *p; { ! 226: return(1); /* all names can have & taken on them */ ! 227: } ! 228: ! 229: cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */ ! 230: autooff = AUTOINIT; ! 231: } ! 232: ! 233: cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */ ! 234: ! 235: if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* tbl */ ! 236: #ifdef REG_CHAR ! 237: || t==CHAR || t==UCHAR || t==SHORT || t==USHORT /* tbl */ ! 238: #endif ! 239: || ISPTR(t) || t == FLOAT) return (1); /* wnj */ ! 240: return(0); ! 241: } ! 242: ! 243: NODE * ! 244: offcon( off, t, d, s ) OFFSZ off; TWORD t; { ! 245: ! 246: /* return a node, for structure references, which is suitable for ! 247: being added to a pointer of type t, in order to be off bits offset ! 248: into a structure */ ! 249: ! 250: register NODE *p; ! 251: ! 252: /* t, d, and s are the type, dimension offset, and sizeoffset */ ! 253: /* in general they are necessary for offcon, but not on H'well */ ! 254: ! 255: p = bcon(0); ! 256: p->tn.lval = off/SZCHAR; ! 257: return(p); ! 258: ! 259: } ! 260: ! 261: ! 262: static inwd /* current bit offsed in word */; ! 263: static CONSZ word /* word being built from fields */; ! 264: ! 265: incode( p, sz ) register NODE *p; { ! 266: ! 267: /* generate initialization code for assigning a constant c ! 268: to a field of width sz */ ! 269: /* we assume that the proper alignment has been obtained */ ! 270: /* inoff is updated to have the proper final value */ ! 271: /* we also assume sz < SZINT */ ! 272: ! 273: inwd += sz; ! 274: if(inwd > SZINT) cerror("incode: field > int"); ! 275: word |= (p->tn.lval&((1L<<sz)-1)) << (SZINT-inwd); ! 276: inoff += sz; ! 277: if(inoff%SZINT == 0) { ! 278: printf( " .long 0x%X\n", word); ! 279: word = inwd = 0; ! 280: } ! 281: } ! 282: ! 283: fincode( d, sz ) double d; register int sz; { ! 284: /* ! 285: * output code to initialize space of size sz to the value d ! 286: * the proper alignment has been obtained ! 287: * inoff is updated to have the proper final value. ! 288: */ ! 289: ! 290: register struct sh4 { ! 291: unsigned short sh[4]; ! 292: } *x; ! 293: float f; ! 294: ! 295: if(sz == SZFLOAT) { /* force rounding */ ! 296: f = d; ! 297: d = f; ! 298: } ! 299: ! 300: x = (struct sh4 *)&d; ! 301: printf(" .long 0x%04x%04x", x->sh[0], x->sh[1]); ! 302: if(sz == SZDOUBLE) { ! 303: printf(", 0x%04x%04x", x->sh[2], x->sh[3]); ! 304: printf(" # .double %.17g\n", d); ! 305: } else ! 306: printf(" # .float %.8g\n", d); ! 307: inoff += sz; ! 308: } ! 309: ! 310: cinit( p, sz ) NODE *p; { ! 311: NODE *l; ! 312: ! 313: /* ! 314: * as a favor (?) to people who want to write ! 315: * int i = 9600/134.5; ! 316: * we will, under the proper circumstances, do ! 317: * a coersion here. ! 318: */ ! 319: switch (p->in.type) { ! 320: case INT: ! 321: case UNSIGNED: ! 322: l = p->in.left; ! 323: if (l->in.op != SCONV || ! 324: (l->in.left->tn.op != DCON && l->in.left->tn.op != FCON)) ! 325: break; ! 326: l->in.op = FREE; ! 327: l = l->in.left; ! 328: l->tn.lval = l->tn.op == DCON ? (long)(l->dpn.dval) : ! 329: (long)(l->fpn.fval); ! 330: l->tn.rval = NONAME; ! 331: l->tn.op = ICON; ! 332: l->tn.type = INT; ! 333: p->in.left = l; ! 334: break; ! 335: } ! 336: /* arrange for the initialization of p into a space of ! 337: size sz */ ! 338: /* the proper alignment has been opbtained */ ! 339: /* inoff is updated to have the proper final value */ ! 340: ecode( p ); ! 341: inoff += sz; ! 342: } ! 343: ! 344: vfdzero( n ){ /* define n bits of zeros in a vfd */ ! 345: ! 346: if( n <= 0 ) return; ! 347: ! 348: inwd += n; ! 349: inoff += n; ! 350: if( inoff%ALINT ==0 ) { ! 351: printf( " .long 0x%X\n", word ); ! 352: word = inwd = 0; ! 353: } ! 354: } ! 355: ! 356: char * ! 357: exname( p ) char *p; { ! 358: /* make a name look like an external name in the local machine */ ! 359: ! 360: #ifndef FLEXNAMES ! 361: static char text[NCHNAM+1]; ! 362: #else ! 363: static char text[BUFSIZ+1]; ! 364: #endif ! 365: ! 366: register int i; ! 367: ! 368: text[0] = '_'; ! 369: #ifndef FLEXNAMES ! 370: for( i=1; *p&&i<NCHNAM; ++i ) ! 371: #else ! 372: for( i=1; *p; ++i ) ! 373: #endif ! 374: text[i] = *p++; ! 375: ! 376: text[i] = '\0'; ! 377: #ifndef FLEXNAMES ! 378: text[NCHNAM] = '\0'; /* truncate */ ! 379: #endif ! 380: ! 381: return( text ); ! 382: } ! 383: ! 384: ctype( type )TWORD type;{ /* map types which are not defined on the local machine */ ! 385: switch( BTYPE(type) ){ ! 386: ! 387: case LONG: ! 388: MODTYPE(type,INT); ! 389: break; ! 390: ! 391: case ULONG: ! 392: MODTYPE(type,UNSIGNED); ! 393: } ! 394: return( type ); ! 395: } ! 396: ! 397: noinit() { /* curid is a variable which is defined but ! 398: is not initialized (and not a function ); ! 399: This routine returns the stroage class for an uninitialized declaration */ ! 400: ! 401: return(EXTERN); ! 402: ! 403: } ! 404: ! 405: commdec( id ){ /* make a common declaration for id, if reasonable */ ! 406: register struct symtab *q; ! 407: OFFSZ off, tsize(); ! 408: ! 409: q = &stab[id]; ! 410: printf( " .comm %s,", exname( q->sname ) ); ! 411: off = tsize( q->stype, q->dimoff, q->sizoff ); ! 412: printf( "%d\n" /*CONFMT*/, off/SZCHAR ); ! 413: } ! 414: ! 415: prtdcon(p) ! 416: register NODE *p; ! 417: { ! 418: register int o = p->in.op; ! 419: int i; ! 420: ! 421: if (o != DCON && o != FCON) ! 422: return; ! 423: /* ! 424: * Clobber constants of value zero so ! 425: * we can generate more efficient code. ! 426: */ ! 427: if ((o == DCON && p->dpn.dval == 0) || ! 428: (o == FCON && p->fpn.fval == 0)) { ! 429: p->in.op = ICON; ! 430: p->tn.rval = NONAME; ! 431: return; ! 432: } ! 433: locctr(DATA); ! 434: defalign(o == DCON ? ALDOUBLE : ALFLOAT); ! 435: deflab(i = getlab()); ! 436: if (o == FCON) ! 437: fincode(p->fpn.fval, SZFLOAT); ! 438: else ! 439: fincode(p->dpn.dval, SZDOUBLE); ! 440: p->tn.lval = 0; ! 441: p->tn.rval = -i; ! 442: p->in.type = (o == DCON ? DOUBLE : FLOAT); ! 443: p->in.op = NAME; ! 444: } ! 445: ! 446: isitfloat( s ) char *s; { ! 447: union cvt { ! 448: double d; ! 449: int n[2]; ! 450: } cvt; ! 451: double atof(); ! 452: ! 453: /* avoid floating point exception for double -> float conversions */ ! 454: dcon = cvt.d = atof(s); ! 455: if( cvt.n[1] == 0 ){ ! 456: fcon = dcon; ! 457: return( FCON ); ! 458: } ! 459: return( DCON ); ! 460: } ! 461: ! 462: ecode( p ) NODE *p; { ! 463: ! 464: /* walk the tree and write out the nodes.. */ ! 465: ! 466: if( nerrors ) return; ! 467: p2tree( p ); ! 468: p2compile( p ); ! 469: } ! 470: ! 471: #ifndef ONEPASS ! 472: tlen(p) NODE *p; ! 473: { ! 474: switch(p->in.type) { ! 475: case CHAR: ! 476: case UCHAR: ! 477: return(1); ! 478: ! 479: case SHORT: ! 480: case USHORT: ! 481: return(2); ! 482: ! 483: case DOUBLE: ! 484: return(8); ! 485: ! 486: default: ! 487: return(4); ! 488: } ! 489: } ! 490: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.