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