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