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

Defined functions

andable defined in line 188; never used
cast defined in line 9; never used
cendarg defined in line 192; never used
cinit defined in line 264; never used
cisreg defined in line 196; never used
clocal defined in line 19; never used
commdec defined in line 359; never used
ctype defined in line 337; never used
ecode defined in line 395; used 1 times
exname defined in line 309; used 4 times
fincode defined in line 252; never used
incode defined in line 234; never used
isitfloat defined in line 379; never used
isitlong defined in line 370; never used
noinit defined in line 351; never used
offcon defined in line 212; never used
tlen defined in line 405; used 5 times
vfdzero defined in line 297; never used

Defined variables

sccsid defined in line 2; never used

Defined union's

cvt defined in line 380; never used
Last modified: 1985-08-25
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1229
Valid CSS Valid XHTML 1.0 Strict