|
|
1.1 ! root 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.