1: # include "pass1.h" 2: 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: case LT: 71: case LE: 72: case GT: 73: case GE: 74: if(ISPTR(p->in.left->in.type) || ISPTR(p->in.right->in.type)){ 75: p->in.op += (ULT-LT); 76: } 77: break; 78: 79: case PCONV: 80: /* do pointer conversions for char and longs */ 81: ml = p->in.left->in.type; 82: if( ( ml==CHAR || ml==UCHAR || ml==LONG || ml==ULONG ) && p->in.left->in.op != ICON ) break; 83: 84: /* pointers all have the same representation; the type is inherited */ 85: p->in.left->in.type = p->in.type; 86: p->in.left->fn.cdim = p->fn.cdim; 87: p->in.left->fn.csiz = p->fn.csiz; 88: p->in.op = FREE; 89: return( p->in.left ); 90: 91: case SCONV: 92: m = (p->in.type == FLOAT || p->in.type == DOUBLE ); 93: ml = (p->in.left->in.type == FLOAT || p->in.left->in.type == DOUBLE ); 94: o = p->in.left->in.op; 95: if( (o == FCON || o == DCON) && ml && !m ) { 96: /* float type to int type */ 97: r = block( ICON, (NODE *)NULL, (NODE *)NULL, LONG, 0, 0 ); 98: if( o == FCON ) 99: r->tn.lval = (long) p->in.left->fpn.fval; 100: else 101: r->tn.lval = (long) p->in.left->dpn.dval; 102: r->tn.rval = NONAME; 103: p->in.left->in.op = FREE; 104: p->in.left = r; 105: } 106: else 107: #ifdef SPRECC 108: if ( ml || m ) 109: #else 110: if ( ml != m ) 111: #endif 112: break; 113: 114: /* now, look for conversions downwards */ 115: 116: m = p->in.type; 117: ml = p->in.left->in.type; 118: if( p->in.left->in.op == ICON ){ /* simulate the conversion here */ 119: CONSZ val; 120: val = p->in.left->tn.lval; 121: switch( m ){ 122: case CHAR: 123: p->in.left->tn.lval = (char) val; 124: break; 125: case UCHAR: 126: p->in.left->tn.lval = val & 0XFF; 127: break; 128: case UNSIGNED: 129: p->in.left->tn.lval = val & 0XFFFFL; 130: break; 131: case INT: 132: p->in.left->tn.lval = (int)val; 133: break; 134: } 135: p->in.left->in.type = m; 136: } 137: else { 138: /* meaningful ones are conversion of int to char, int to short, 139: and short to char, and unsigned version of them */ 140: if( m==CHAR || m==UCHAR ){ 141: if( ml==LONG || ml==ULONG ) break; 142: } 143: else if( m==INT || m==UNSIGNED ){ 144: if( ml==LONG || ml==ULONG ) break; 145: } 146: else if( m==LONG || m==ULONG ){ 147: if( ml!=LONG && ml!= ULONG ) break; 148: } 149: } 150: 151: /* clobber conversion */ 152: p->in.op = FREE; 153: return( p->in.left ); /* conversion gets clobbered */ 154: 155: case ASSIGN: 156: /* get rid of SCONV for assignments 157: from LONG -> CHAR|INT */ 158: if( p->in.right->in.op == SCONV ) { 159: m = p->in.right->in.type; 160: ml = p->in.right->in.left->in.type; 161: if( ( m==LONG || m==ULONG ) && 162: ml!=FLOAT && ml!=DOUBLE ) { 163: p->in.right->in.op = FREE; 164: p->in.right = p->in.right->in.left; 165: } 166: } 167: break; 168: 169: case PVCONV: 170: case PMCONV: 171: if( p->in.right->in.op != ICON ) cerror( "bad conversion", 0); 172: p->in.op = FREE; 173: return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) ); 174: 175: case PLUS: 176: case MINUS: 177: case LS: 178: case MUL: 179: /* optimize address calculations with long indexes */ 180: if( ISPTR( p->in.type ) || ISARY( p->in.type ) ) { 181: if( p->in.left->in.type==LONG || p->in.left->in.type==ULONG ) 182: p->in.left = cast( p->in.left, INT ); 183: if( p->in.right->in.type==LONG || p->in.right->in.type==ULONG ) 184: p->in.right = cast( p->in.right, INT ); 185: } 186: break; 187: 188: case FLD: 189: /* make sure that the second pass does not make the 190: descendant of a FLD operator into a doubly indexed OREG */ 191: 192: if( p->in.left->in.op == UNARY MUL 193: && (r=p->in.left->in.left)->in.op == PCONV) 194: if( r->in.left->in.op == PLUS || r->in.left->in.op == MINUS ) 195: if( ISPTR(r->in.type) ) { 196: if( ISUNSIGNED(p->in.left->in.type) ) 197: p->in.left->in.type = UCHAR; 198: else 199: p->in.left->in.type = CHAR; 200: } 201: break; 202: } 203: 204: return(p); 205: } 206: 207: andable( p ) NODE *p; { 208: return(1); /* all names can have & taken on them */ 209: } 210: 211: cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */ 212: autooff = AUTOINIT; 213: } 214: 215: cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */ 216: 217: #ifdef TRUST_REG_CHAR_AND_REG_SHORT 218: if( t==INT || t==UNSIGNED /* tbl */ 219: || t==CHAR || t==UCHAR || t==SHORT /* tbl */ 220: || t==USHORT || ISPTR(t)) return(1); /* tbl */ 221: #else 222: if( t==INT || t==UNSIGNED /* wnj */ 223: #ifdef SPRECC 224: || t==FLOAT 225: #endif 226: || ISPTR(t)) return (1); /* wnj */ 227: #endif 228: return(0); 229: } 230: 231: NODE * 232: offcon( off, t, d, s ) OFFSZ off; TWORD t; { 233: 234: /* return a node, for structure references, which is suitable for 235: being added to a pointer of type t, in order to be off bits offset 236: into a structure */ 237: 238: register NODE *p; 239: 240: /* t, d, and s are the type, dimension offset, and sizeoffset */ 241: /* in general they are necessary for offcon, but not on H'well */ 242: 243: p = bcon(0); 244: p->tn.lval = off/SZCHAR; 245: return(p); 246: 247: } 248: 249: static inwd /* current bit offsed in word */; 250: static word /* word being built from fields */; 251: 252: incode( p, sz ) register NODE *p; { 253: 254: /* generate initialization code for assigning a constant c 255: to a field of width sz */ 256: /* we assume that the proper alignment has been obtained */ 257: /* inoff is updated to have the proper final value */ 258: /* we also assume sz < SZINT */ 259: 260: if((sz+inwd) > SZINT) cerror("incode: field > int"); 261: word |= ((unsigned)(p->tn.lval<<(16-sz))) >> (16-sz-inwd); 262: inwd += sz; 263: inoff += sz; 264: if(inoff%SZINT == 0) { 265: printf( " %o\n", word); 266: word = inwd = 0; 267: } 268: } 269: 270: fincode( d, sz ) double d; { 271: /* output code to initialize space of size sz to the value d */ 272: /* the proper alignment has been obtained */ 273: /* inoff is updated to have the proper final value */ 274: /* on the target machine, write it out in octal! */ 275: 276: register int *mi = (int *)&d; 277: 278: if( sz==SZDOUBLE ) 279: printf( " %o; %o; %o; %o\n", mi[0], mi[1], mi[2], mi[3] ); 280: else 281: printf( " %o; %o\n", mi[0], mi[1] ); 282: inoff += sz; 283: } 284: 285: cinit( p, sz ) NODE *p; { 286: NODE *l; 287: 288: /* 289: * as a favor (?) to people who want to write 290: * int i = 9600/134.5; 291: * we will, under the proper circumstances, do 292: * a coersion here. 293: */ 294: switch (p->in.type) { 295: case INT: 296: case UNSIGNED: 297: l = p->in.left; 298: if (l->in.op != SCONV || 299: (l->in.left->tn.op != DCON && l->in.left->tn.op != FCON)) 300: break; 301: l->in.op = FREE; 302: l = l->in.left; 303: l->tn.lval = l->tn.op == DCON ? (long)(l->dpn.dval) : 304: (long)(l->fpn.fval); 305: l->tn.rval = NONAME; 306: l->tn.op = ICON; 307: l->tn.type = INT; 308: p->in.left = l; 309: break; 310: } 311: /* arrange for the initialization of p into a space of size sz */ 312: /* the proper alignment has been opbtained */ 313: /* inoff is updated to have the proper final value */ 314: ecode( p ); 315: inoff += sz; 316: } 317: 318: vfdzero( n ){ /* define n bits of zeros in a vfd */ 319: 320: if( n <= 0 ) return; 321: 322: inwd += n; 323: inoff += n; 324: if( inoff%ALINT ==0 ) { 325: printf( " %o\n", word ); 326: word = inwd = 0; 327: } 328: } 329: 330: char * 331: exname( p ) char *p; { 332: /* make a name look like an external name in the local machine */ 333: 334: #ifndef FLEXNAMES 335: static char text[NCHNAM+1]; 336: #else 337: static char text[256+1]; 338: #endif 339: 340: register i; 341: 342: text[0] = '_'; 343: #ifndef FLEXNAMES 344: for( i=1; *p&&i<NCHNAM; ++i ) 345: #else 346: for( i=1; *p; ++i ) 347: #endif 348: text[i] = *p++; 349: 350: text[i] = '\0'; 351: #ifndef FLEXNAMES 352: text[NCHNAM] = '\0'; /* truncate */ 353: #endif 354: 355: return( text ); 356: } 357: 358: ctype( type ) TWORD type; 359: { /* map types which are not defined on the local machine */ 360: switch( BTYPE(type) ){ 361: 362: case SHORT: 363: MODTYPE(type,INT); 364: break; 365: case USHORT: 366: MODTYPE(type,UNSIGNED); 367: } 368: return( type ); 369: } 370: 371: noinit() { /* curid is a variable which is defined but 372: is not initialized (and not a function ); 373: This routine returns the stroage class for an uninitialized declaration */ 374: 375: return(EXTERN); 376: 377: } 378: 379: commdec( id ){ /* make a common declaration for id, if reasonable */ 380: register struct symtab *q; 381: OFFSZ off, tsize(); 382: 383: q = &stab[id]; 384: printf( " .comm %s,", exname( q->sname ) ); 385: off = tsize( q->stype, q->dimoff, q->sizoff ); 386: printf( CONFMT, off/SZCHAR ); 387: printf( ".\n" ); 388: } 389: 390: isitlong( cb, ce ){ /* is lastcon to be long or short */ 391: /* cb is the first character of the representation, ce the last */ 392: 393: if( ce == 'l' || ce == 'L' || 394: lastcon >= (1L << (SZINT-1) ) ) return (1); 395: return(0); 396: } 397: 398: isitfloat( s ) char *s; { 399: union cvt { 400: double d; 401: int n[4]; 402: } cvt; 403: double atof(); 404: 405: /* avoid floating point exception for double -> float conversions */ 406: dcon = cvt.d = atof(s); 407: if( cvt.n[1] == 0 ){ 408: fcon = dcon; 409: return( FCON ); 410: } 411: return( DCON ); 412: } 413: 414: ecode( p ) NODE *p; { 415: 416: /* walk the tree and write out the nodes.. */ 417: 418: if( nerrors ) return; 419: p2tree( p ); 420: p2compile( p ); 421: } 422: 423: #ifndef ONEPASS 424: tlen(p) NODE *p; 425: { 426: switch(p->in.type) { 427: case CHAR: 428: case UCHAR: 429: return(1); 430: 431: case LONG: 432: case ULONG: 433: case FLOAT: 434: return(4); 435: 436: case DOUBLE: 437: return(8); 438: 439: default: 440: return(2); 441: } 442: } 443: #endif