1 #ifndef lint 2 static char *sccsid ="@(#)local.c 1.8 (Berkeley) 08/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 424