1 static char *sccsid ="@(#)local.c 1.2 (Berkeley) 12/18/82"; 2 # include "mfile1" 3 4 /* this file contains code which is dependent on the target machine */ 5 6 NODE * 7 cast( p, t ) register NODE *p; TWORD t; { 8 /* cast node p to type t */ 9 10 p = buildtree( CAST, block( NAME, NIL, NIL, t, 0, (int)t ), p ); 11 p->in.left->in.op = FREE; 12 p->in.op = FREE; 13 return( p->in.right ); 14 } 15 16 NODE * 17 clocal(p) NODE *p; { 18 19 /* this is called to do local transformations on 20 an expression tree preparitory to its being 21 written out in intermediate code. 22 */ 23 24 /* the major essential job is rewriting the 25 automatic variables and arguments in terms of 26 REG and OREG nodes */ 27 /* conversion ops which are not necessary are also clobbered here */ 28 /* in addition, any special features (such as rewriting 29 exclusive or) are easily handled here as well */ 30 31 register struct symtab *q; 32 register NODE *r; 33 register o; 34 register m, ml; 35 36 switch( o = p->in.op ){ 37 38 case NAME: 39 if( p->tn.rval < 0 ) { /* already processed; ignore... */ 40 return(p); 41 } 42 q = &stab[p->tn.rval]; 43 switch( q->sclass ){ 44 45 case AUTO: 46 case PARAM: 47 /* fake up a structure reference */ 48 r = block( REG, NIL, NIL, PTR+STRTY, 0, 0 ); 49 r->tn.lval = 0; 50 r->tn.rval = (q->sclass==AUTO?STKREG:ARGREG); 51 p = stref( block( STREF, r, p, 0, 0, 0 ) ); 52 break; 53 54 case ULABEL: 55 case LABEL: 56 case STATIC: 57 if( q->slevel == 0 ) break; 58 p->tn.lval = 0; 59 p->tn.rval = -q->offset; 60 break; 61 62 case REGISTER: 63 p->in.op = REG; 64 p->tn.lval = 0; 65 p->tn.rval = q->offset; 66 break; 67 68 } 69 break; 70 71 case PCONV: 72 /* do pointer conversions for char and longs */ 73 ml = p->in.left->in.type; 74 if( ( ml==CHAR || ml==UCHAR || ml==SHORT || ml==USHORT ) && p->in.left->in.op != ICON ) break; 75 76 /* pointers all have the same representation; the type is inherited */ 77 78 inherit: 79 p->in.left->in.type = p->in.type; 80 p->in.left->fn.cdim = p->fn.cdim; 81 p->in.left->fn.csiz = p->fn.csiz; 82 p->in.op = FREE; 83 return( p->in.left ); 84 85 case SCONV: 86 m = (p->in.type == FLOAT || p->in.type == DOUBLE ); 87 ml = (p->in.left->in.type == FLOAT || p->in.left->in.type == DOUBLE ); 88 if( m != ml ) break; 89 90 /* now, look for conversions downwards */ 91 92 m = p->in.type; 93 ml = p->in.left->in.type; 94 if( p->in.left->in.op == ICON ){ /* simulate the conversion here */ 95 CONSZ val; 96 val = p->in.left->tn.lval; 97 switch( m ){ 98 case CHAR: 99 p->in.left->tn.lval = (char) val; 100 break; 101 case UCHAR: 102 p->in.left->tn.lval = val & 0XFF; 103 break; 104 case USHORT: 105 p->in.left->tn.lval = val & 0XFFFFL; 106 break; 107 case SHORT: 108 p->in.left->tn.lval = (short)val; 109 break; 110 case UNSIGNED: 111 p->in.left->tn.lval = val & 0xFFFFFFFFL; 112 break; 113 case INT: 114 p->in.left->tn.lval = (int)val; 115 break; 116 } 117 p->in.left->in.type = m; 118 } 119 else { 120 /* meaningful ones are conversion of int to char, int to short, 121 and short to char, and unsigned version of them */ 122 if( m==CHAR || m==UCHAR ){ 123 if( ml!=CHAR && ml!= UCHAR ) break; 124 } 125 else if( m==SHORT || m==USHORT ){ 126 if( ml!=CHAR && ml!=UCHAR && ml!=SHORT && ml!=USHORT ) break; 127 } 128 } 129 130 /* clobber conversion */ 131 if( tlen(p) == tlen(p->in.left) ) goto inherit; 132 p->in.op = FREE; 133 return( p->in.left ); /* conversion gets clobbered */ 134 135 case PVCONV: 136 case PMCONV: 137 if( p->in.right->in.op != ICON ) cerror( "bad conversion", 0); 138 p->in.op = FREE; 139 return( buildtree( o==PMCONV?MUL:DIV, p->in.left, p->in.right ) ); 140 141 case RS: 142 case ASG RS: 143 /* convert >> to << with negative shift count */ 144 /* only if type of left operand is not unsigned */ 145 146 if( ISUNSIGNED(p->in.left->in.type) ) break; 147 p->in.right = buildtree( UNARY MINUS, p->in.right, NIL ); 148 if( p->in.op == RS ) p->in.op = LS; 149 else p->in.op = ASG LS; 150 break; 151 152 case FLD: 153 /* make sure that the second pass does not make the 154 descendant of a FLD operator into a doubly indexed OREG */ 155 156 if( p->in.left->in.op == UNARY MUL 157 && (r=p->in.left->in.left)->in.op == PCONV) 158 if( r->in.left->in.op == PLUS || r->in.left->in.op == MINUS ) 159 if( ISPTR(r->in.type) ) { 160 if( ISUNSIGNED(p->in.left->in.type) ) 161 p->in.left->in.type = UCHAR; 162 else 163 p->in.left->in.type = CHAR; 164 } 165 break; 166 } 167 168 return(p); 169 } 170 171 andable( p ) NODE *p; { 172 return(1); /* all names can have & taken on them */ 173 } 174 175 cendarg(){ /* at the end of the arguments of a ftn, set the automatic offset */ 176 autooff = AUTOINIT; 177 } 178 179 cisreg( t ) TWORD t; { /* is an automatic variable of type t OK for a register variable */ 180 181 #ifdef TRUST_REG_CHAR_AND_REG_SHORT 182 if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* tbl */ 183 || t==CHAR || t==UCHAR || t==SHORT /* tbl */ 184 || t==USHORT || ISPTR(t)) return(1); /* tbl */ 185 #else 186 if( t==INT || t==UNSIGNED || t==LONG || t==ULONG /* wnj */ 187 || ISPTR(t)) return (1); /* wnj */ 188 #endif 189 return(0); 190 } 191 192 NODE * 193 offcon( off, t, d, s ) OFFSZ off; TWORD t; { 194 195 /* return a node, for structure references, which is suitable for 196 being added to a pointer of type t, in order to be off bits offset 197 into a structure */ 198 199 register NODE *p; 200 201 /* t, d, and s are the type, dimension offset, and sizeoffset */ 202 /* in general they are necessary for offcon, but not on H'well */ 203 204 p = bcon(0); 205 p->tn.lval = off/SZCHAR; 206 return(p); 207 208 } 209 210 211 static inwd /* current bit offsed in word */; 212 static word /* word being built from fields */; 213 214 incode( p, sz ) register NODE *p; { 215 216 /* generate initialization code for assigning a constant c 217 to a field of width sz */ 218 /* we assume that the proper alignment has been obtained */ 219 /* inoff is updated to have the proper final value */ 220 /* we also assume sz < SZINT */ 221 222 if((sz+inwd) > SZINT) cerror("incode: field > int"); 223 word |= ((unsigned)(p->tn.lval<<(32-sz))) >> (32-sz-inwd); 224 inwd += sz; 225 inoff += sz; 226 if(inoff%SZINT == 0) { 227 printf( " .long 0x%x\n", word); 228 word = inwd = 0; 229 } 230 } 231 232 fincode( d, sz ) double d; { 233 /* output code to initialize space of size sz to the value d */ 234 /* the proper alignment has been obtained */ 235 /* inoff is updated to have the proper final value */ 236 /* on the target machine, write it out in octal! */ 237 238 239 printf(" %s 0%c%.20e\n", sz == SZDOUBLE ? ".double" : ".float", 240 sz == SZDOUBLE ? 'd' : 'f', d); 241 inoff += sz; 242 } 243 244 cinit( p, sz ) NODE *p; { 245 /* arrange for the initialization of p into a space of 246 size sz */ 247 /* the proper alignment has been opbtained */ 248 /* inoff is updated to have the proper final value */ 249 ecode( p ); 250 inoff += sz; 251 } 252 253 vfdzero( n ){ /* define n bits of zeros in a vfd */ 254 255 if( n <= 0 ) return; 256 257 inwd += n; 258 inoff += n; 259 if( inoff%ALINT ==0 ) { 260 printf( " .long 0x%x\n", word ); 261 word = inwd = 0; 262 } 263 } 264 265 char * 266 exname( p ) char *p; { 267 /* make a name look like an external name in the local machine */ 268 269 #ifndef FLEXNAMES 270 static char text[NCHNAM+1]; 271 #else 272 static char text[BUFSIZ+1]; 273 #endif 274 275 register i; 276 277 text[0] = '_'; 278 #ifndef FLEXNAMES 279 for( i=1; *p&&i<NCHNAM; ++i ){ 280 #else 281 for( i=1; *p; ++i ){ 282 #endif 283 text[i] = *p++; 284 } 285 286 text[i] = '\0'; 287 #ifndef FLEXNAMES 288 text[NCHNAM] = '\0'; /* truncate */ 289 #endif 290 291 return( text ); 292 } 293 294 ctype( type ){ /* map types which are not defined on the local machine */ 295 switch( BTYPE(type) ){ 296 297 case LONG: 298 MODTYPE(type,INT); 299 break; 300 301 case ULONG: 302 MODTYPE(type,UNSIGNED); 303 } 304 return( type ); 305 } 306 307 noinit( t ) { /* curid is a variable which is defined but 308 is not initialized (and not a function ); 309 This routine returns the stroage class for an uninitialized declaration */ 310 311 return(EXTERN); 312 313 } 314 315 commdec( id ){ /* make a common declaration for id, if reasonable */ 316 register struct symtab *q; 317 OFFSZ off, tsize(); 318 319 q = &stab[id]; 320 printf( " .comm %s,", exname( q->sname ) ); 321 off = tsize( q->stype, q->dimoff, q->sizoff ); 322 printf( CONFMT, off/SZCHAR ); 323 printf( "\n" ); 324 } 325 326 isitlong( cb, ce ){ /* is lastcon to be long or short */ 327 /* cb is the first character of the representation, ce the last */ 328 329 if( ce == 'l' || ce == 'L' || 330 lastcon >= (1L << (SZINT-1) ) ) return (1); 331 return(0); 332 } 333 334 335 isitfloat( s ) char *s; { 336 double atof(); 337 dcon = atof(s); 338 return( FCON ); 339 } 340 341 ecode( p ) NODE *p; { 342 343 /* walk the tree and write out the nodes.. */ 344 345 if( nerrors ) return; 346 p2tree( p ); 347 p2compile( p ); 348 } 349 350 #ifndef ONEPASS 351 tlen(p) NODE *p; 352 { 353 switch(p->in.type) { 354 case CHAR: 355 case UCHAR: 356 return(1); 357 358 case SHORT: 359 case USHORT: 360 return(2); 361 362 case DOUBLE: 363 return(8); 364 365 default: 366 return(4); 367 } 368 } 369 #endif 370