1 #ifndef lint 2 static char *sccsid ="@(#)local.c 1.10 (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 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 /*ARGSUSED*/ 189 andable( p ) NODE *p; { 190 return(1); /* all names can have & taken on them */ 191 } 192 193 cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */ 194 autooff = AUTOINIT; 195 } 196 197 cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */ 198 199 #ifdef TRUST_REG_CHAR_AND_REG_SHORT 200 if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* tbl */ 201 || t==CHAR || t==UCHAR || t==SHORT /* tbl */ 202 || t==USHORT || ISPTR(t)) return(1); /* tbl */ 203 #else 204 if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* wnj */ 205 #ifdef SPRECC 206 || t==FLOAT 207 #endif 208 || ISPTR(t)) return (1); /* wnj */ 209 #endif 210 return(0); 211 } 212 213 /*ARGSUSED*/ 214 NODE * 215 offcon( off, t, d, s ) OFFSZ off; TWORD t; { 216 217 /* return a node, for structure references, which is suitable for 218 being added to a pointer of type t, in order to be off bits offset 219 into a structure */ 220 221 register NODE *p; 222 223 /* t, d, and s are the type, dimension offset, and sizeoffset */ 224 /* in general they are necessary for offcon, but not on VAX */ 225 226 p = bcon(0); 227 p->tn.lval = off/SZCHAR; 228 return(p); 229 230 } 231 232 233 static inwd /* current bit offsed in word */; 234 static word /* word being built from fields */; 235 236 incode( p, sz ) register NODE *p; { 237 238 /* generate initialization code for assigning a constant c 239 to a field of width sz */ 240 /* we assume that the proper alignment has been obtained */ 241 /* inoff is updated to have the proper final value */ 242 /* we also assume sz < SZINT */ 243 244 if (nerrors) return; 245 if((sz+inwd) > SZINT) cerror("incode: field > int"); 246 word |= ((unsigned)(p->tn.lval<<(32-sz))) >> (32-sz-inwd); 247 inwd += sz; 248 inoff += sz; 249 if(inoff%SZINT == 0) { 250 printf( " .long 0x%x\n", word); 251 word = inwd = 0; 252 } 253 } 254 255 fincode( d, sz ) double d; { 256 /* output code to initialize space of size sz to the value d */ 257 /* the proper alignment has been obtained */ 258 /* inoff is updated to have the proper final value */ 259 /* on the target machine, write it out in octal! */ 260 261 262 if (nerrors) return; 263 printf(" %s 0%c%.20e\n", sz == SZDOUBLE ? ".double" : ".float", 264 sz == SZDOUBLE ? 'd' : 'f', d); 265 inoff += sz; 266 } 267 268 cinit( p, sz ) NODE *p; { 269 NODE *l; 270 271 /* 272 * as a favor (?) to people who want to write 273 * int i = 9600/134.5; 274 * we will, under the proper circumstances, do 275 * a coersion here. 276 */ 277 switch (p->in.type) { 278 case INT: 279 case UNSIGNED: 280 l = p->in.left; 281 if (l->in.op != SCONV || 282 (l->in.left->tn.op != DCON && l->in.left->tn.op != FCON)) 283 break; 284 l->in.op = FREE; 285 l = l->in.left; 286 l->tn.lval = l->tn.op == DCON ? (long)(l->dpn.dval) : 287 (long)(l->fpn.fval); 288 l->tn.rval = NONAME; 289 l->tn.op = ICON; 290 l->tn.type = INT; 291 p->in.left = l; 292 break; 293 } 294 /* arrange for the initialization of p into a space of size sz */ 295 /* the proper alignment has been opbtained */ 296 /* inoff is updated to have the proper final value */ 297 ecode( p ); 298 inoff += sz; 299 } 300 301 vfdzero( n ){ /* define n bits of zeros in a vfd */ 302 303 if( n <= 0 ) return; 304 305 if (nerrors) return; 306 inwd += n; 307 inoff += n; 308 if( inoff%ALINT ==0 ) { 309 printf( " .long 0x%x\n", word ); 310 word = inwd = 0; 311 } 312 } 313 314 char * 315 exname( p ) char *p; { 316 /* make a name look like an external name in the local machine */ 317 318 #ifndef FLEXNAMES 319 static char text[NCHNAM+1]; 320 #else 321 static char text[BUFSIZ+1]; 322 #endif 323 324 register i; 325 326 text[0] = '_'; 327 #ifndef FLEXNAMES 328 for( i=1; *p&&i<NCHNAM; ++i ) 329 #else 330 for( i=1; *p; ++i ) 331 #endif 332 text[i] = *p++; 333 334 text[i] = '\0'; 335 #ifndef FLEXNAMES 336 text[NCHNAM] = '\0'; /* truncate */ 337 #endif 338 339 return( text ); 340 } 341 342 ctype( type ) TWORD type; 343 { /* map types which are not defined on the local machine */ 344 switch( BTYPE(type) ){ 345 346 case LONG: 347 MODTYPE(type,INT); 348 break; 349 350 case ULONG: 351 MODTYPE(type,UNSIGNED); 352 } 353 return( type ); 354 } 355 356 noinit() { /* curid is a variable which is defined but 357 is not initialized (and not a function ); 358 This routine returns the stroage class for an uninitialized declaration */ 359 360 return(EXTERN); 361 362 } 363 364 commdec( id ){ /* make a common declaration for id, if reasonable */ 365 register struct symtab *q; 366 OFFSZ off, tsize(); 367 368 if (nerrors) return; 369 q = &stab[id]; 370 printf( " .comm %s,", exname( q->sname ) ); 371 off = tsize( q->stype, q->dimoff, q->sizoff ); 372 printf( CONFMT, off/SZCHAR ); 373 printf( "\n" ); 374 } 375 376 /*ARGSUSED*/ 377 isitlong( cb, ce ){ /* is lastcon to be long or short */ 378 /* cb is the first character of the representation, ce the last */ 379 380 if( ce == 'l' || ce == 'L' || 381 lastcon >= (1L << (SZINT-1) ) ) return (1); 382 return(0); 383 } 384 385 386 isitfloat( s ) char *s; { 387 union cvt { 388 double d; 389 int n[2]; 390 } cvt; 391 double atof(); 392 393 /* avoid floating point exception for double -> float conversions */ 394 dcon = cvt.d = atof(s); 395 if( cvt.n[1] == 0 ){ 396 fcon = dcon; 397 return( FCON ); 398 } 399 return( DCON ); 400 } 401 402 ecode( p ) NODE *p; { 403 404 /* walk the tree and write out the nodes.. */ 405 406 if( nerrors ) return; 407 p2tree( p ); 408 p2compile( p ); 409 } 410 411 #ifndef ONEPASS 412 tlen(p) NODE *p; 413 { 414 switch(p->in.type) { 415 case CHAR: 416 case UCHAR: 417 return(1); 418 419 case SHORT: 420 case USHORT: 421 return(2); 422 423 case DOUBLE: 424 return(8); 425 426 default: 427 return(4); 428 } 429 } 430 #endif 431