1/* Id: local.c,v 1.12 2011/06/05 10:29:10 ragge Exp */ 2/* $NetBSD$ */ 3/* 4 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 29#include "pass1.h" 30 31/* this file contains code which is dependent on the target machine */ 32 33/* clocal() is called to do local transformations on 34 * an expression tree preparitory to its being 35 * written out in intermediate code. 36 * 37 * the major essential job is rewriting the 38 * automatic variables and arguments in terms of 39 * REG and OREG nodes 40 * conversion ops which are not necessary are also clobbered here 41 * in addition, any special features (such as rewriting 42 * exclusive or) are easily handled here as well 43 */ 44NODE * 45clocal(NODE *p) 46{ 47 48 register struct symtab *q; 49 register NODE *r, *l; 50 register int o; 51 int m; 52 53#ifdef PCC_DEBUG 54 if (xdebug) { 55 printf("clocal: %p\n", p); 56 fwalk(p, eprint, 0); 57 } 58#endif 59 switch( o = p->n_op ){ 60 61 case NAME: 62 if ((q = p->n_sp) == NULL) 63 return p; /* Nothing to care about */ 64 65 switch (q->sclass) { 66 67 case PARAM: 68 case AUTO: 69 /* fake up a structure reference */ 70 r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); 71 r->n_lval = 0; 72 r->n_rval = FPREG; 73 p = stref(block(STREF, r, p, 0, 0, 0)); 74 break; 75 76 case STATIC: 77 if (q->slevel == 0) 78 break; 79 p->n_lval = 0; 80 break; 81 82 case REGISTER: 83 p->n_op = REG; 84 p->n_lval = 0; 85 p->n_rval = q->soffset; 86 break; 87 88 case EXTERN: 89 case EXTDEF: 90 break; 91 } 92 break; 93 94 case PCONV: 95 /* Remove redundant PCONV's. Be careful */ 96 l = p->n_left; 97 if (l->n_op == ICON) { 98 l->n_lval = (unsigned)l->n_lval; 99 goto delp; 100 } 101 if (l->n_type < INT || l->n_type == LONGLONG || 102 l->n_type == ULONGLONG) { 103 /* float etc? */ 104 p->n_left = block(SCONV, l, NIL, UNSIGNED, 0, 0); 105 break; 106 } 107 /* if left is SCONV, cannot remove */ 108 if (l->n_op == SCONV) 109 break; 110 111 /* avoid ADDROF TEMP */ 112 if (l->n_op == ADDROF && l->n_left->n_op == TEMP) 113 break; 114 115 /* if conversion to another pointer type, just remove */ 116 if (p->n_type > BTMASK && l->n_type > BTMASK) 117 goto delp; 118 break; 119 120 delp: l->n_type = p->n_type; 121 l->n_qual = p->n_qual; 122 l->n_df = p->n_df; 123 l->n_sue = p->n_sue; 124 nfree(p); 125 p = l; 126 break; 127 128 case SCONV: 129 l = p->n_left; 130 131#if 0 132 if (p->n_type == l->n_type) { 133 nfree(p); 134 return l; 135 } 136 137 if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 && 138 btdims[p->n_type].suesize == btdims[l->n_type].suesize) { 139 if (p->n_type != FLOAT && p->n_type != DOUBLE && 140 l->n_type != FLOAT && l->n_type != DOUBLE && 141 l->n_type != LDOUBLE && p->n_type != LDOUBLE) { 142 if (l->n_op == NAME || l->n_op == UMUL || 143 l->n_op == TEMP) { 144 l->n_type = p->n_type; 145 nfree(p); 146 return l; 147 } 148 } 149 } 150 151 if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT && 152 coptype(l->n_op) == BITYPE) { 153 l->n_type = p->n_type; 154 nfree(p); 155 return l; 156 } 157#endif 158 o = l->n_op; 159 m = p->n_type; 160 161 if (o == ICON) { 162 CONSZ val = l->n_lval; 163 164 if (!ISPTR(m)) /* Pointers don't need to be conv'd */ 165 switch (m) { 166 case BOOL: 167 l->n_lval = l->n_lval != 0; 168 break; 169 case CHAR: 170 l->n_lval = (char)val; 171 break; 172 case UCHAR: 173 l->n_lval = val & 0377; 174 break; 175 case INT: 176 l->n_lval = (short)val; 177 break; 178 case UNSIGNED: 179 l->n_lval = val & 0177777; 180 break; 181 case ULONG: 182 l->n_lval = val & 0xffffffff; 183 break; 184 case LONG: 185 l->n_lval = (long)val; 186 break; 187 case LONGLONG: 188 l->n_lval = (long long)val; 189 break; 190 case ULONGLONG: 191 l->n_lval = val; 192 break; 193 case VOID: 194 break; 195 case LDOUBLE: 196 case DOUBLE: 197 case FLOAT: 198 l->n_op = FCON; 199 l->n_dcon = FLOAT_CAST(val, l->n_type); 200 break; 201 default: 202 cerror("unknown type %d", m); 203 } 204 l->n_type = m; 205 l->n_sue = 0; 206 nfree(p); 207 return l; 208 } else if (l->n_op == FCON) { 209 l->n_lval = FLOAT_VAL(l->n_dcon); 210 l->n_sp = NULL; 211 l->n_op = ICON; 212 l->n_type = m; 213 l->n_sue = 0; 214 nfree(p); 215 return clocal(l); 216 } 217 if (DEUNSIGN(p->n_type) == INT && 218 DEUNSIGN(l->n_type) == INT) { 219 nfree(p); 220 p = l; 221 } 222 break; 223 224 case CBRANCH: 225 l = p->n_left; 226 if (coptype(l->n_op) != BITYPE) 227 break; 228 if (l->n_left->n_op != SCONV || l->n_right->n_op != ICON) 229 break; 230 if ((r = l->n_left->n_left)->n_type > INT) 231 break; 232 /* compare with constant without casting */ 233 nfree(l->n_left); 234 l->n_left = r; 235 l->n_right->n_type = l->n_left->n_type; 236 break; 237 238 case STASG: /* struct assignment, modify left */ 239 l = p->n_left; 240 if (l->n_type == STRTY) 241 p->n_left = buildtree(ADDROF, l, NIL); 242 break; 243 244 case FORCE: 245 /* put return value in return reg */ 246 p->n_op = ASSIGN; 247 p->n_right = p->n_left; 248 p->n_left = block(REG, NIL, NIL, p->n_type, 0, 0); 249 p->n_left->n_rval = p->n_left->n_type == BOOL ? 250 RETREG(CHAR) : RETREG(p->n_type); 251 break; 252 253 } 254#ifdef PCC_DEBUG 255 if (xdebug) { 256 printf("clocal end: %p\n", p); 257 fwalk(p, eprint, 0); 258 } 259#endif 260 return(p); 261} 262 263void 264myp2tree(NODE *p) 265{ 266 struct symtab *sp; 267 268 if (p->n_op != FCON) 269 return; 270 271 sp = inlalloc(sizeof(struct symtab)); 272 sp->sclass = STATIC; 273 sp->ssue = 0; 274 sp->slevel = 1; /* fake numeric label */ 275 sp->soffset = getlab(); 276 sp->sflags = 0; 277 sp->stype = p->n_type; 278 sp->squal = (CON >> TSHIFT); 279 280 defloc(sp); 281 ninval(0, sp->ssue->suesize, p); 282 283 p->n_op = NAME; 284 p->n_lval = 0; 285 p->n_sp = sp; 286} 287 288/*ARGSUSED*/ 289int 290andable(NODE *p) 291{ 292 return(1); /* all names can have & taken on them */ 293} 294 295/* 296 * Return 1 if a variable of type type is OK to put in register. 297 */ 298int 299cisreg(TWORD t) 300{ 301 if (t == FLOAT || t == DOUBLE || t == LDOUBLE || 302 t == LONGLONG || t == ULONGLONG) 303 return 0; /* not yet */ 304 return 1; 305} 306 307/* 308 * Allocate off bits on the stack. p is a tree that when evaluated 309 * is the multiply count for off, t is a storeable node where to write 310 * the allocated address. 311 */ 312void 313spalloc(NODE *t, NODE *p, OFFSZ off) 314{ 315 NODE *sp; 316 317 p = buildtree(MUL, p, bcon(off/SZCHAR)); /* XXX word alignment? */ 318 319 /* sub the size from sp */ 320 sp = block(REG, NIL, NIL, p->n_type, 0, 0); 321 sp->n_lval = 0; 322 sp->n_rval = STKREG; 323 ecomp(buildtree(MINUSEQ, sp, p)); 324 325 /* save the address of sp */ 326 sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue); 327 sp->n_lval = 0; 328 sp->n_rval = STKREG; 329 t->n_type = sp->n_type; 330 ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */ 331 332} 333 334/* 335 * Print out a string of characters. 336 * Assume that the assembler understands C-style escape 337 * sequences. 338 */ 339void 340instring(struct symtab *sp) 341{ 342 char *s; 343 int val, cnt; 344 345 defloc(sp); 346 347 for (cnt = 0, s = sp->sname; *s != 0; ) { 348 if (cnt++ == 0) 349 printf(".byte "); 350 if (*s++ == '\\') 351 val = esccon(&s); 352 else 353 val = s[-1]; 354 printf("%o", val & 0377); 355 if (cnt > 15) { 356 cnt = 0; 357 printf("\n"); 358 } else 359 printf(","); 360 } 361 printf("%s0\n", cnt ? "" : ".byte "); 362} 363 364static int inbits, xinval; 365 366/* 367 * set fsz bits in sequence to zero. 368 */ 369void 370zbits(OFFSZ off, int fsz) 371{ 372 int m; 373 374 if (idebug) 375 printf("zbits off %lld, fsz %d inbits %d\n", off, fsz, inbits); 376 if ((m = (inbits % SZCHAR))) { 377 m = SZCHAR - m; 378 if (fsz < m) { 379 inbits += fsz; 380 return; 381 } else { 382 fsz -= m; 383 printf("\t.byte %d\n", xinval); 384 xinval = inbits = 0; 385 } 386 } 387 if (fsz >= SZCHAR) { 388 printf(".=.+%o\n", fsz/SZCHAR); 389 fsz -= (fsz/SZCHAR) * SZCHAR; 390 } 391 if (fsz) { 392 xinval = 0; 393 inbits = fsz; 394 } 395} 396 397/* 398 * Initialize a bitfield. 399 */ 400void 401infld(CONSZ off, int fsz, CONSZ val) 402{ 403 if (idebug) 404 printf("infld off %lld, fsz %d, val %lld inbits %d\n", 405 off, fsz, val, inbits); 406 val &= ((CONSZ)1 << fsz)-1; 407 while (fsz + inbits >= SZCHAR) { 408 xinval |= (val << inbits); 409 printf("\t.byte %d\n", xinval & 255); 410 fsz -= (SZCHAR - inbits); 411 val >>= (SZCHAR - inbits); 412 xinval = inbits = 0; 413 } 414 if (fsz) { 415 xinval |= (val << inbits); 416 inbits += fsz; 417 } 418} 419 420/* 421 * print out a constant node, may be associated with a label. 422 * Do not free the node after use. 423 * off is bit offset from the beginning of the aggregate 424 * fsz is the number of bits this is referring to 425 */ 426int 427ninval(CONSZ off, int fsz, NODE *p) 428{ 429#ifdef __pdp11__ 430 union { float f; double d; short s[4]; int i[2]; } u; 431#endif 432 struct symtab *q; 433 TWORD t; 434 int i; 435 436 t = p->n_type; 437 if (t > BTMASK) 438 p->n_type = t = INT; /* pointer */ 439 440 if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT) 441 uerror("element not constant"); 442 443 switch (t) { 444 case LONGLONG: 445 case ULONGLONG: 446 i = (p->n_lval >> 32); 447 p->n_lval &= 0xffffffff; 448 p->n_type = INT; 449 ninval(off, 32, p); 450 p->n_lval = i; 451 ninval(off+32, 32, p); 452 break; 453 case LONG: 454 case ULONG: 455 printf("%o ; %o\n", (int)((p->n_lval >> 16) & 0177777), 456 (int)(p->n_lval & 0177777)); 457 break; 458 case INT: 459 case UNSIGNED: 460 printf("%o", (int)(p->n_lval & 0177777)); 461 if ((q = p->n_sp) != NULL) { 462 if ((q->sclass == STATIC && q->slevel > 0)) { 463 printf("+" LABFMT, q->soffset); 464 } else { 465 printf("+%s", q->soname ? q->soname : exname(q->sname)); 466 } 467 } 468 printf("\n"); 469 break; 470#ifdef __pdp11__ 471 case FLOAT: 472 u.f = (float)p->n_dcon; 473 printf("%o ; %o\n", u.i[0], u.i[1]); 474 break; 475 case LDOUBLE: 476 case DOUBLE: 477 u.d = (double)p->n_dcon; 478 printf("%o ; %o ; %o ; %o\n", u.i[0], u.i[1], u.i[2], u.i[3]); 479 break; 480#else 481 /* cross-compiling */ 482 case FLOAT: 483 printf("%o ; %o\n", p->n_dcon.fd1, p->n_dcon.fd2); 484 break; 485 case LDOUBLE: 486 case DOUBLE: 487 printf("%o ; %o ; %o ; %o\n", p->n_dcon.fd1, p->n_dcon.fd2, 488 p->n_dcon.fd3, p->n_dcon.fd4); 489 break; 490#endif 491 default: 492 return 0; 493 } 494 return 1; 495} 496 497/* make a name look like an external name in the local machine */ 498char * 499exname(char *p) 500{ 501#define NCHNAM 256 502 static char text[NCHNAM+1]; 503 int i; 504 505 if (p == NULL) 506 return ""; 507 508 text[0] = '_'; 509 for (i=1; *p && i<NCHNAM; ++i) 510 text[i] = *p++; 511 512 text[i] = '\0'; 513 text[NCHNAM] = '\0'; /* truncate */ 514 515 return (text); 516 517} 518 519/* 520 * map types which are not defined on the local machine 521 */ 522TWORD 523ctype(TWORD type) 524{ 525 switch (BTYPE(type)) { 526 case SHORT: 527 MODTYPE(type,INT); 528 break; 529 530 case USHORT: 531 MODTYPE(type,UNSIGNED); 532 break; 533 534 case LDOUBLE: 535 MODTYPE(type,DOUBLE); 536 break; 537 538 } 539 return (type); 540} 541 542void 543calldec(NODE *p, NODE *q) 544{ 545} 546 547void 548extdec(struct symtab *q) 549{ 550} 551 552/* make a common declaration for id, if reasonable */ 553void 554defzero(struct symtab *sp) 555{ 556 extern int lastloc; 557 char *n; 558 int off; 559 560 off = tsize(sp->stype, sp->sdf, sp->ssue); 561 off = (off+(SZCHAR-1))/SZCHAR; 562 n = sp->soname ? sp->soname : exname(sp->sname); 563 if (sp->sclass == STATIC) { 564 printf(".bss\n"); 565 if (sp->slevel == 0) 566 printf("%s:", n); 567 else 568 printf(LABFMT ":", sp->soffset); 569 printf(" .=.+%o\n", off); 570 lastloc = -1; 571 return; 572 } 573 printf(".comm "); 574 if (sp->slevel == 0) 575 printf("%s,0%o\n", n, off); 576 else 577 printf(LABFMT ",0%o\n", sp->soffset, off); 578} 579 580/* 581 * Give target the opportunity of handling pragmas. 582 */ 583int 584mypragma(char *str) 585{ 586 return 0; 587} 588 589/* 590 * Called when a identifier has been declared. 591 */ 592void 593fixdef(struct symtab *sp) 594{ 595} 596 597void 598pass1_lastchance(struct interpass *ip) 599{ 600} 601