1 #ifndef lint 2 static char sccsid[] = "@(#)local.c 1.10 (Berkeley) 12/10/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 p->in.left->in.type = p->in.type; 88 p->in.left->fn.cdim = p->fn.cdim; 89 p->in.left->fn.csiz = p->fn.csiz; 90 p->in.op = FREE; 91 return( p->in.left ); 92 93 case SCONV: 94 m = p->in.type; 95 ml = p->in.left->in.type; 96 if(m == ml) 97 goto clobber; 98 o = p->in.left->in.op; 99 if(m == FLOAT || m == DOUBLE) { 100 if(o==SCONV && 101 ml == DOUBLE && 102 p->in.left->in.left->in.type==m) { 103 p->in.op = p->in.left->in.op = FREE; 104 return(p->in.left->in.left); 105 } 106 /* see makety() for constant conversions */ 107 break; 108 } 109 if(ml == FLOAT || ml == DOUBLE){ 110 if(o != FCON && o != DCON) 111 break; 112 ml = ISUNSIGNED(m) ? UNSIGNED : INT; /* LONG? */ 113 r = block( ICON, (NODE *)NULL, (NODE *)NULL, ml, 0, 0 ); 114 if( o == FCON ) 115 r->tn.lval = ml == INT ? 116 (int) p->in.left->fpn.fval : 117 (unsigned) p->in.left->fpn.fval; 118 else 119 r->tn.lval = ml == INT ? 120 (int) p->in.left->dpn.dval : 121 (unsigned) p->in.left->dpn.dval; 122 r->tn.rval = NONAME; 123 p->in.left->in.op = FREE; 124 p->in.left = r; 125 o = ICON; 126 if( m == ml ) 127 goto clobber; 128 } 129 /* now, look for conversions downwards */ 130 131 if( o == ICON ){ /* simulate the conversion here */ 132 CONSZ val; 133 val = p->in.left->tn.lval; 134 switch( m ){ 135 case CHAR: 136 p->in.left->tn.lval = (char) val; 137 break; 138 case UCHAR: 139 p->in.left->tn.lval = val & 0XFF; 140 break; 141 case USHORT: 142 p->in.left->tn.lval = val & 0XFFFFL; 143 break; 144 case SHORT: 145 p->in.left->tn.lval = (short)val; 146 break; 147 case UNSIGNED: 148 p->in.left->tn.lval = val & 0xFFFFFFFFL; 149 break; 150 case INT: 151 p->in.left->tn.lval = (int)val; 152 break; 153 } 154 p->in.left->in.type = m; 155 } 156 else 157 break; 158 159 clobber: 160 p->in.op = FREE; 161 return( p->in.left ); /* conversion gets clobbered */ 162 163 case PVCONV: 164 case PMCONV: 165 if( p->in.right->in.op != ICON ) cerror( "bad conversion", 0); 166 p->in.op = FREE; 167 return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) ); 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 = UNSIGNED; 179 else 180 p->in.left->in.type = INT; 181 } 182 break; 183 case FORTCALL: /* arg must be FLOAT */ 184 if((r = p->in.right)->in.type != FLOAT) 185 p->in.right = clocal(makety(r, FLOAT, 0, FLOAT)); 186 return(p); 187 } 188 189 return(p); 190 } 191 192 /*ARGSUSED*/ 193 andable( p ) NODE *p; { 194 return(1); /* all names can have & taken on them */ 195 } 196 197 cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */ 198 autooff = AUTOINIT; 199 } 200 201 cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */ 202 203 if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* tbl */ 204 #ifdef REG_CHAR 205 || t==CHAR || t==UCHAR || t==SHORT || t==USHORT /* tbl */ 206 #endif 207 || ISPTR(t) || t == FLOAT) return (1); /* wnj */ 208 return(0); 209 } 210 211 /*ARGSUSED*/ 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 Tahoe */ 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 CONSZ 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(nerrors) return; 243 inwd += sz; 244 if(inwd > SZINT) cerror("incode: field > int"); 245 word |= (p->tn.lval&((1L<<sz)-1)) << (SZINT-inwd); 246 inoff += sz; 247 if(inoff%SZINT == 0) { 248 printf( " .long 0x%lx\n", word); 249 word = inwd = 0; 250 } 251 } 252 253 fincode( d, sz ) double d; register int sz; { 254 /* 255 * output code to initialize space of size sz to the value d 256 * the proper alignment has been obtained 257 * inoff is updated to have the proper final value. 258 */ 259 260 register struct sh4 { 261 unsigned short sh[4]; 262 } *x; 263 float f; 264 265 if (nerrors) return; 266 if(sz == SZFLOAT) { /* force rounding */ 267 f = d; 268 d = f; 269 } 270 271 x = (struct sh4 *)&d; 272 printf(" .long 0x%04x%04x", x->sh[0], x->sh[1]); 273 if(sz == SZDOUBLE) { 274 printf(", 0x%04x%04x", x->sh[2], x->sh[3]); 275 printf(" # .double %.17g\n", d); 276 } else 277 printf(" # .float %.8g\n", d); 278 inoff += sz; 279 } 280 281 cinit( p, sz ) NODE *p; { 282 NODE *l; 283 284 /* 285 * as a favor (?) to people who want to write 286 * int i = 9600/134.5; 287 * we will, under the proper circumstances, do 288 * a coercion here. 289 */ 290 switch (p->in.type) { 291 case INT: 292 case UNSIGNED: 293 l = p->in.left; 294 if (l->in.op != SCONV || 295 (l->in.left->tn.op != DCON && l->in.left->tn.op != FCON)) 296 break; 297 l->in.op = FREE; 298 l = l->in.left; 299 l->tn.lval = l->tn.op == DCON ? (long)(l->dpn.dval) : 300 (long)(l->fpn.fval); 301 l->tn.rval = NONAME; 302 l->tn.op = ICON; 303 l->tn.type = INT; 304 p->in.left = l; 305 break; 306 } 307 /* arrange for the initialization of p into a space of size sz */ 308 /* the proper alignment has been opbtained */ 309 /* inoff is updated to have the proper final value */ 310 ecode( p ); 311 inoff += sz; 312 } 313 314 vfdzero( n ){ /* define n bits of zeros in a vfd */ 315 316 if( n <= 0 ) return; 317 318 if (nerrors) return; 319 inwd += n; 320 inoff += n; 321 if( inoff%ALINT ==0 ) { 322 printf( " .long 0x%lx\n", word ); 323 word = inwd = 0; 324 } 325 } 326 327 char * 328 exname( p ) char *p; { 329 /* make a name look like an external name in the local machine */ 330 331 #ifndef FLEXNAMES 332 static char text[NCHNAM+1]; 333 #else 334 static char text[BUFSIZ+1]; 335 #endif 336 337 register int i; 338 339 text[0] = '_'; 340 #ifndef FLEXNAMES 341 for( i=1; *p&&i<NCHNAM; ++i ) 342 #else 343 for( i=1; *p; ++i ) 344 #endif 345 text[i] = *p++; 346 347 text[i] = '\0'; 348 #ifndef FLEXNAMES 349 text[NCHNAM] = '\0'; /* truncate */ 350 #endif 351 352 return( text ); 353 } 354 355 ctype( type ) TWORD type; 356 { /* map types which are not defined on the local machine */ 357 switch( BTYPE(type) ){ 358 359 case LONG: 360 MODTYPE(type,INT); 361 break; 362 363 case ULONG: 364 MODTYPE(type,UNSIGNED); 365 } 366 return( type ); 367 } 368 369 noinit() { /* curid is a variable which is defined but 370 is not initialized (and not a function ); 371 This routine returns the stroage class for an uninitialized declaration */ 372 373 return(EXTERN); 374 375 } 376 377 commdec( id ){ /* make a common declaration for id, if reasonable */ 378 register struct symtab *q; 379 OFFSZ off, tsize(); 380 381 if (nerrors) return; 382 q = &stab[id]; 383 printf( " .comm %s,", exname( q->sname ) ); 384 off = tsize( q->stype, q->dimoff, q->sizoff ); 385 printf( "%d\n" /*CONFMT*/, off/SZCHAR ); 386 } 387 388 prtdcon(p) 389 register NODE *p; 390 { 391 register int o = p->in.op; 392 int i; 393 394 if (o != DCON && o != FCON) 395 return; 396 /* 397 * Clobber constants of value zero so 398 * we can generate more efficient code. 399 */ 400 if ((o == DCON && p->dpn.dval == 0) || 401 (o == FCON && p->fpn.fval == 0)) { 402 p->in.op = ICON; 403 p->tn.rval = NONAME; 404 return; 405 } 406 locctr(DATA); 407 defalign(o == DCON ? ALDOUBLE : ALFLOAT); 408 deflab(i = getlab()); 409 if (o == FCON) 410 fincode(p->fpn.fval, SZFLOAT); 411 else 412 fincode(p->dpn.dval, SZDOUBLE); 413 p->tn.lval = 0; 414 p->tn.rval = -i; 415 p->in.type = (o == DCON ? DOUBLE : FLOAT); 416 p->in.op = NAME; 417 } 418 419 ecode( p ) NODE *p; { 420 421 /* walk the tree and write out the nodes.. */ 422 423 if( nerrors ) return; 424 p2tree( p ); 425 p2compile( p ); 426 } 427 428 #ifndef ONEPASS 429 tlen(p) NODE *p; 430 { 431 switch(p->in.type) { 432 case CHAR: 433 case UCHAR: 434 return(1); 435 436 case SHORT: 437 case USHORT: 438 return(SZSHORT/SZCHAR); 439 440 case DOUBLE: 441 return(SZDOUBLE/SZCHAR); 442 443 default: 444 return(SZINT/SZCHAR); 445 } 446 } 447 #endif 448