1 /* $OpenBSD: local.c,v 1.2 2007/11/18 17:39:55 ragge Exp $ */ 2 3 /* 4 * Copyright (c) 2007 Michael Shalayeff 5 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se). 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 32 #include "pass1.h" 33 #include "pass2.h" 34 35 /* this file contains code which is dependent on the target machine */ 36 37 #define IALLOC(sz) (isinlining ? permalloc(sz) : tmpalloc(sz)) 38 39 struct symtab *makememcpy(void); 40 char *section2string(char *, int); 41 42 /* clocal() is called to do local transformations on 43 * an expression tree preparitory to its being 44 * written out in intermediate code. 45 * 46 * the major essential job is rewriting the 47 * automatic variables and arguments in terms of 48 * REG and OREG nodes 49 * conversion ops which are not necessary are also clobbered here 50 * in addition, any special features (such as rewriting 51 * exclusive or) are easily handled here as well 52 */ 53 NODE * 54 clocal(NODE *p) 55 { 56 register struct symtab *q, *sp; 57 register NODE *r, *l, *s; 58 register int o, m, rn; 59 char *ch, name[16], *n; 60 TWORD t; 61 62 #ifdef PCC_DEBUG 63 if (xdebug) { 64 printf("clocal: %p\n", p); 65 fwalk(p, eprint, 0); 66 } 67 #endif 68 switch (o = p->n_op) { 69 70 case NAME: 71 if ((q = p->n_sp) == NULL) 72 break; /* Nothing to care about */ 73 74 switch (q->sclass) { 75 76 case PARAM: 77 /* first four integral args are in regs */ 78 rn = (q->soffset >> 5) - 8; 79 if (rn < 4) { 80 r = block(REG, NIL, NIL, p->n_type, 0, 0); 81 r->n_lval = 0; 82 switch (p->n_type) { 83 case FLOAT: 84 r->n_rval = FR7L - rn; 85 break; 86 case DOUBLE: 87 case LDOUBLE: 88 r->n_rval = FR6 - rn; 89 break; 90 case LONGLONG: 91 case ULONGLONG: 92 r->n_rval = AD1 - rn / 2; 93 break; 94 default: 95 r->n_rval = ARG0 - rn; 96 } 97 r->n_sue = p->n_sue; 98 p->n_sue = NULL; 99 nfree(p); 100 p = r; 101 break; 102 } 103 /* FALLTHROUGH */ 104 105 case AUTO: 106 /* fake up a structure reference */ 107 r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); 108 r->n_lval = 0; 109 r->n_rval = FPREG; 110 p = stref(block(STREF, r, p, 0, 0, 0)); 111 break; 112 113 case REGISTER: 114 p->n_op = REG; 115 p->n_lval = 0; 116 p->n_rval = q->soffset; 117 break; 118 119 case STATIC: 120 case EXTERN: 121 if (p->n_sp->sflags & SSTRING) 122 break; 123 124 n = p->n_sp->soname ? p->n_sp->soname : p->n_sp->sname; 125 if (strncmp(n, "__builtin", 9) == 0) 126 break; 127 128 l = block(REG, NIL, NIL, INT, 0, 0); 129 l->n_lval = 0; 130 l->n_rval = R1; 131 l = block(ASSIGN, l, p, INT, 0, 0); 132 r = xbcon(0, p->n_sp, INT); 133 p = block(UMUL, 134 block(PLUS, l, r, INT, 0, 0), 135 NIL, p->n_type, p->n_df, p->n_sue); 136 break; 137 } 138 break; 139 140 case ADDROF: 141 l = p->n_left; 142 if (!l->n_sp) 143 break; 144 145 if (l->n_sp->sclass != EXTERN && 146 l->n_sp->sclass != STATIC && 147 l->n_sp->sclass != USTATIC && 148 l->n_sp->sclass != EXTDEF) 149 break; 150 151 l = block(REG, NIL, NIL, INT, 0, 0); 152 l->n_lval = 0; 153 l->n_rval = R1; 154 l = block(ASSIGN, l, p->n_left, INT, 0, 0); 155 r = xbcon(0, p->n_left->n_sp, INT); 156 l = block(PLUS, l, r, p->n_type, p->n_df, p->n_sue); 157 nfree(p); 158 p = l; 159 break; 160 161 case CBRANCH: 162 l = p->n_left; 163 164 /* 165 * Remove unnecessary conversion ops. 166 */ 167 if (clogop(l->n_op) && l->n_left->n_op == SCONV) { 168 if (coptype(l->n_op) != BITYPE) 169 break; 170 if (l->n_right->n_op == ICON) { 171 r = l->n_left->n_left; 172 if (r->n_type >= FLOAT && r->n_type <= LDOUBLE) 173 break; 174 /* Type must be correct */ 175 t = r->n_type; 176 nfree(l->n_left); 177 l->n_left = r; 178 l->n_type = t; 179 l->n_right->n_type = t; 180 } 181 } 182 break; 183 184 case PCONV: 185 /* Remove redundant PCONV's. Be careful */ 186 l = p->n_left; 187 if (l->n_op == ICON) { 188 l->n_lval = (unsigned)l->n_lval; 189 goto delp; 190 } 191 if (l->n_type < INT || l->n_type == LONGLONG || 192 l->n_type == ULONGLONG) { 193 /* float etc? */ 194 p->n_left = block(SCONV, l, NIL, 195 UNSIGNED, 0, MKSUE(UNSIGNED)); 196 break; 197 } 198 /* if left is SCONV, cannot remove */ 199 if (l->n_op == SCONV) 200 break; 201 202 /* avoid ADDROF TEMP */ 203 if (l->n_op == ADDROF && l->n_left->n_op == TEMP) 204 break; 205 206 /* if conversion to another pointer type, just remove */ 207 if (p->n_type > BTMASK && l->n_type > BTMASK) 208 goto delp; 209 break; 210 211 delp: l->n_type = p->n_type; 212 l->n_qual = p->n_qual; 213 l->n_df = p->n_df; 214 l->n_sue = p->n_sue; 215 nfree(p); 216 p = l; 217 break; 218 219 case SCONV: 220 l = p->n_left; 221 222 if (p->n_type == l->n_type) { 223 nfree(p); 224 p = l; 225 break; 226 } 227 228 if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 && 229 btdims[p->n_type].suesize == btdims[l->n_type].suesize) { 230 if (p->n_type != FLOAT && p->n_type != DOUBLE && 231 l->n_type != FLOAT && l->n_type != DOUBLE && 232 l->n_type != LDOUBLE && p->n_type != LDOUBLE) { 233 if (l->n_op == UMUL || l->n_op == TEMP || 234 l->n_op == NAME) { 235 l->n_type = p->n_type; 236 nfree(p); 237 p = l; 238 break; 239 } 240 } 241 } 242 243 if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT && 244 coptype(l->n_op) == BITYPE) { 245 l->n_type = p->n_type; 246 nfree(p); 247 p = l; 248 break; 249 } 250 251 o = l->n_op; 252 m = p->n_type; 253 254 if (o == ICON) { 255 CONSZ val = l->n_lval; 256 257 if (!ISPTR(m)) /* Pointers don't need to be conv'd */ 258 switch (m) { 259 case BOOL: 260 l->n_lval = l->n_lval != 0; 261 break; 262 case CHAR: 263 l->n_lval = (char)val; 264 break; 265 case UCHAR: 266 l->n_lval = val & 0377; 267 break; 268 case SHORT: 269 l->n_lval = (short)val; 270 break; 271 case USHORT: 272 l->n_lval = val & 0177777; 273 break; 274 case ULONG: 275 case UNSIGNED: 276 l->n_lval = val & 0xffffffff; 277 break; 278 case LONG: 279 case INT: 280 l->n_lval = (int)val; 281 break; 282 case LONGLONG: 283 l->n_lval = (long long)val; 284 break; 285 case ULONGLONG: 286 l->n_lval = val; 287 break; 288 case VOID: 289 break; 290 case LDOUBLE: 291 case DOUBLE: 292 case FLOAT: 293 l->n_op = FCON; 294 l->n_dcon = val; 295 break; 296 default: 297 cerror("unknown type %d", m); 298 } 299 l->n_type = m; 300 l->n_sue = MKSUE(m); 301 nfree(p); 302 return l; 303 } else if (l->n_op == FCON) { 304 l->n_lval = l->n_dcon; 305 l->n_sp = NULL; 306 l->n_op = ICON; 307 l->n_type = m; 308 l->n_sue = MKSUE(m); 309 nfree(p); 310 return clocal(l); 311 } 312 313 if (DEUNSIGN(p->n_type) == SHORT && 314 DEUNSIGN(l->n_type) == SHORT) { 315 nfree(p); 316 p = l; 317 } 318 if ((p->n_type == CHAR || p->n_type == UCHAR || 319 p->n_type == SHORT || p->n_type == USHORT) && 320 (l->n_type == FLOAT || l->n_type == DOUBLE || 321 l->n_type == LDOUBLE)) { 322 p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_sue); 323 p->n_left->n_type = INT; 324 break; 325 } 326 break; 327 328 case MOD: 329 case DIV: 330 if (o == DIV && p->n_type != CHAR && p->n_type != SHORT) 331 break; 332 if (o == MOD && p->n_type != CHAR && p->n_type != SHORT) 333 break; 334 /* make it an int division by inserting conversions */ 335 p->n_left = block(SCONV, p->n_left, NIL, INT, 0, MKSUE(INT)); 336 p->n_right = block(SCONV, p->n_right, NIL, INT, 0, MKSUE(INT)); 337 p = block(SCONV, p, NIL, p->n_type, 0, MKSUE(p->n_type)); 338 p->n_left->n_type = INT; 339 break; 340 341 case PMCONV: 342 case PVCONV: 343 if( p->n_right->n_op != ICON ) cerror( "bad conversion", 0); 344 nfree(p); 345 return(buildtree(o==PMCONV?MUL:DIV, p->n_left, p->n_right)); 346 347 case LS: 348 case RS: 349 /* shift count must be in an int */ 350 if (p->n_right->n_op == ICON || p->n_right->n_lval <= 32) 351 break; /* do not do anything */ 352 if (p->n_right->n_type != INT || p->n_right->n_lval > 32) 353 p->n_right = block(SCONV, p->n_right, NIL, 354 INT, 0, MKSUE(INT)); 355 break; 356 357 #if 0 358 case FLD: 359 /* already rewritten (in ASSIGN) */ 360 if (p->n_left->n_op == TEMP) 361 break; 362 363 r = tempnode(0, p->n_type, p->n_df, p->n_sue); 364 l = block(ASSIGN, r, p->n_left, p->n_type, p->n_df, p->n_sue); 365 p->n_left = tcopy(r); 366 p = block(COMOP, l, p, p->n_type, p->n_df, p->n_sue); 367 break; 368 #endif 369 370 case FORCE: 371 /* put return value in return reg */ 372 p->n_op = ASSIGN; 373 p->n_right = p->n_left; 374 p->n_left = block(REG, NIL, NIL, p->n_type, p->n_df, p->n_sue); 375 p->n_left->n_rval = p->n_left->n_type == BOOL ? 376 RETREG(CHAR) : RETREG(p->n_type); 377 if (p->n_right->n_op != FLD) 378 break; 379 break; 380 381 case ASSIGN: 382 r = p->n_right; 383 l = p->n_left; 384 385 /* rewrite ICON#0 into %r0 */ 386 if (r->n_op == ICON && r->n_lval == 0 && 387 (l->n_op == REG || l->n_op == OREG)) { 388 r->n_op = REG; 389 r->n_rval = R0; 390 } 391 392 /* rewrite FCON#0 into %fr0 */ 393 if (r->n_op == FCON && r->n_lval == 0 && l->n_op == REG) { 394 r->n_op = REG; 395 r->n_rval = r->n_type == FLOAT? FR0L : FR0; 396 } 397 398 if (p->n_left->n_op != FLD) 399 break; 400 401 r = tempnode(0, l->n_type, l->n_df, l->n_sue); 402 p = block(COMOP, 403 block(ASSIGN, r, l->n_left, l->n_type, l->n_df, l->n_sue), 404 p, p->n_type, p->n_df, p->n_sue); 405 s = tcopy(l->n_left); 406 p = block(COMOP, p, 407 block(ASSIGN, s, tcopy(r), l->n_type, l->n_df, l->n_sue), 408 p->n_type, p->n_df, p->n_sue); 409 l->n_left = tcopy(r); 410 break; 411 412 case STASG: 413 /* memcpy(left, right, size) */ 414 sp = makememcpy(); 415 l = p->n_left; 416 /* guess struct return */ 417 if (l->n_op == NAME && ISFTN(l->n_sp->stype)) { 418 l = block(REG, NIL, NIL, VOID|PTR, 0, MKSUE(LONG)); 419 l->n_lval = 0; 420 l->n_rval = RET0; 421 } else if (l->n_op == UMUL) 422 l = tcopy(l->n_left); 423 else if (l->n_op == NAME) 424 l = block(ADDROF,tcopy(l),NIL,PTR|STRTY,0,MKSUE(LONG)); 425 l = block(CALL, block(ADDROF, 426 (s = block(NAME, NIL, NIL, FTN, 0, MKSUE(LONG))), 427 NIL, PTR|FTN, 0, MKSUE(LONG)), 428 block(CM, block(CM, l, tcopy(p->n_right), 429 STRTY|PTR, 0, MKSUE(LONG)), 430 (r = block(ICON, NIL, NIL, INT, 0, MKSUE(LONG))), 0, 0, 0), 431 INT, 0, MKSUE(LONG)); 432 r->n_lval = p->n_sue->suesize/SZCHAR; 433 s->n_sp = sp; 434 s->n_df = s->n_sp->sdf; 435 defid(s, EXTERN); 436 tfree(p); 437 p = l; 438 p->n_left = clocal(p->n_left); 439 p->n_right = clocal(p->n_right); 440 calldec(p->n_left, p->n_right); 441 funcode(p); 442 break; 443 444 case STARG: 445 /* arg = memcpy(argN-size, src, size) */ 446 sp = makememcpy(); 447 l = block(CALL, block(ADDROF, 448 (s = block(NAME, NIL, NIL, FTN, 0, MKSUE(LONG))),NIL,0,0,0), 449 block(CM, block(CM, tcopy(p), tcopy(p->n_left), 0, 0, 0), 450 (r = block(ICON, NIL, NIL, INT, 0, MKSUE(LONG))), 0, 0, 0), 451 INT, 0, MKSUE(LONG)); 452 r->n_lval = p->n_sue->suesize/SZCHAR; 453 s->n_sp = sp; 454 s->n_df = s->n_sp->sdf; 455 defid(s, EXTERN); 456 tfree(p); 457 p = l; 458 p->n_left = clocal(p->n_left); 459 calldec(p->n_left, p->n_right); 460 funcode(p); 461 break; 462 463 case STCALL: 464 case CALL: 465 for (r = p->n_right; r->n_op == CM; r = r->n_left) { 466 if (r->n_right->n_op == ASSIGN && 467 r->n_right->n_right->n_op == CALL) { 468 s = r->n_right->n_right; 469 l = tempnode(0, s->n_type, s->n_df, s->n_sue); 470 ecode(buildtree(ASSIGN, l, s)); 471 r->n_right->n_right = tcopy(l); 472 } 473 if (r->n_left->n_op == ASSIGN && 474 r->n_left->n_right->n_op == CALL) { 475 s = r->n_left->n_right; 476 l = tempnode(0, s->n_type, s->n_df, s->n_sue); 477 ecode(buildtree(ASSIGN, l, s)); 478 r->n_left->n_right = tcopy(l); 479 } 480 } 481 break; 482 } 483 484 /* second pass - rewrite long ops */ 485 switch (o) { 486 case DIV: 487 case MOD: 488 case MUL: 489 case RS: 490 case LS: 491 if (!(p->n_type == LONGLONG || p->n_type == ULONGLONG) || 492 !((o == DIV || o == MOD || o == MUL) && 493 p->n_type < FLOAT)) 494 break; 495 if (o == DIV && p->n_type == ULONGLONG) ch = "udiv"; 496 else if (o == DIV) ch = "div"; 497 else if (o == MUL) ch = "mul"; 498 else if (o == MOD && p->n_type == ULONGLONG) ch = "umod"; 499 else if (o == MOD) ch = "mod"; 500 else if (o == RS && p->n_type == ULONGLONG) ch = "lshr"; 501 else if (o == RS) ch = "ashr"; 502 else if (o == LS) ch = "ashl"; 503 else break; 504 snprintf(name, sizeof(name), "__%sdi3", ch); 505 p->n_right = block(CM, p->n_left, p->n_right, 0, 0, 0); 506 p->n_left = block(ADDROF, 507 block(NAME, NIL, NIL, FTN, 0, MKSUE(INT)), NIL, 508 PTR|FTN, 0, MKSUE(INT)); 509 p->n_left->n_left->n_sp = lookup(addname(name), 0); 510 defid(p->n_left->n_left, EXTERN); 511 p->n_left = clocal(p->n_left); 512 calldec(p->n_left, p->n_right); 513 p->n_op = CALL; 514 funcode(p); 515 break; 516 } 517 518 #ifdef PCC_DEBUG 519 if (xdebug) { 520 printf("clocal end: %p\n", p); 521 fwalk(p, eprint, 0); 522 } 523 #endif 524 return(p); 525 } 526 527 struct symtab * 528 makememcpy() 529 { 530 NODE *memcpy, *args, *t, *u; 531 struct symtab *sp; 532 533 /* TODO check that it's a func proto */ 534 if ((sp = lookup(addname("memcpy"), SNORMAL))) 535 return sp; 536 537 memcpy = block(NAME, NIL, NIL, 0, 0, MKSUE(LONG)); 538 memcpy->n_sp = sp = lookup(addname("memcpy"), SNORMAL); 539 defid(memcpy, EXTERN); 540 541 args = block(CM, block(CM, 542 block(NAME, NIL, NIL, VOID|PTR, 0, MKSUE(LONG)), 543 block(NAME, NIL, NIL, VOID|PTR, 0, MKSUE(LONG)), 0, 0, 0), 544 block(NAME, NIL, NIL, LONG, 0, MKSUE(LONG)), 0, 0, 0); 545 546 tymerge(t = block(TYPE, NIL, NIL, VOID|PTR, 0, 0), 547 (u = block(UMUL, block(CALL, memcpy, args, LONG, 0, 0), 548 NIL, LONG, 0, 0))); 549 tfree(t); 550 tfree(u); 551 552 return sp; 553 } 554 555 void 556 myp2tree(NODE *p) 557 { 558 struct symtab *sp; 559 int o = p->n_op; 560 561 if (o != FCON) 562 return; 563 564 /* Write float constants to memory */ 565 /* Should be volontary per architecture */ 566 567 #if 0 568 setloc1(RDATA); 569 defalign(p->n_type == FLOAT ? ALFLOAT : p->n_type == DOUBLE ? 570 ALDOUBLE : ALLDOUBLE ); 571 deflab1(i = getlab()); 572 #endif 573 sp = inlalloc(sizeof(struct symtab)); 574 sp->sclass = STATIC; 575 sp->ssue = MKSUE(p->n_type); 576 sp->slevel = 1; /* fake numeric label */ 577 sp->soffset = getlab(); 578 sp->sflags = 0; 579 sp->stype = p->n_type; 580 sp->squal = (CON >> TSHIFT); 581 582 defloc(sp); 583 ninval(0, btdims[p->n_type].suesize, p); 584 585 p->n_op = NAME; 586 p->n_lval = 0; 587 p->n_sp = sp; 588 589 } 590 591 /*ARGSUSED*/ 592 int 593 andable(NODE *p) 594 { 595 return(1); /* all names can have & taken on them */ 596 } 597 598 /* 599 * at the end of the arguments of a ftn, set the automatic offset 600 */ 601 void 602 cendarg() 603 { 604 /* TODO can use to generate sp/rp tree ops? */ 605 autooff = AUTOINIT; 606 } 607 608 /* 609 * Return 1 if a variable of type "t" is OK to put in register. 610 */ 611 int 612 cisreg(TWORD t) 613 { 614 return 1; 615 } 616 617 /* 618 * return a node, for structure references, which is suitable for 619 * being added to a pointer of type t, in order to be off bits offset 620 * into a structure 621 * t, d, and s are the type, dimension offset, and sizeoffset 622 * For pdp10, return the type-specific index number which calculation 623 * is based on its size. For example, short a[3] would return 3. 624 * Be careful about only handling first-level pointers, the following 625 * indirections must be fullword. 626 */ 627 NODE * 628 offcon(OFFSZ off, TWORD t, union dimfun *d, struct suedef *sue) 629 { 630 register NODE *p; 631 632 if (xdebug) 633 printf("offcon: OFFSZ %lld type %x dim %p siz %d\n", 634 off, t, d, sue->suesize); 635 636 p = bcon(0); 637 p->n_lval = off/SZCHAR; /* Default */ 638 return(p); 639 } 640 641 /* 642 * Allocate off bits on the stack. p is a tree that when evaluated 643 * is the multiply count for off, t is a storeable node where to write 644 * the allocated address. 645 */ 646 void 647 spalloc(NODE *t, NODE *p, OFFSZ off) 648 { 649 NODE *sp; 650 651 p = buildtree(MUL, p, bcon(off/SZCHAR)); /* XXX word alignment? */ 652 653 /* sub the size from sp */ 654 sp = block(REG, NIL, NIL, p->n_type, 0, MKSUE(INT)); 655 sp->n_lval = 0; 656 sp->n_rval = STKREG; 657 ecomp(buildtree(PLUSEQ, sp, p)); 658 659 /* save the address of sp */ 660 sp = block(REG, NIL, NIL, PTR+INT, t->n_df, t->n_sue); 661 sp->n_lval = 0; 662 sp->n_rval = STKREG; 663 t->n_type = sp->n_type; 664 ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */ 665 666 } 667 668 #if 0 669 /* 670 * Print out an integer constant of size size. 671 * can only be sizes <= SZINT. 672 */ 673 void 674 indata(CONSZ val, int size) 675 { 676 switch (size) { 677 case SZCHAR: 678 printf("\t.byte %d\n", (int)val & 0xff); 679 break; 680 case SZSHORT: 681 printf("\t.word %d\n", (int)val & 0xffff); 682 break; 683 case SZINT: 684 printf("\t.long %d\n", (int)val & 0xffffffff); 685 break; 686 default: 687 cerror("indata"); 688 } 689 } 690 #endif 691 692 /* 693 * Print out a string of characters. 694 * Assume that the assembler understands C-style escape 695 * sequences. Location is already set. 696 */ 697 void 698 instring(struct symtab *sp) 699 { 700 char *s, *str; 701 702 defloc(sp); 703 str = sp->sname; 704 705 /* be kind to assemblers and avoid long strings */ 706 printf("\t.ascii\t\""); 707 for (s = str; *s != 0; ) { 708 if (*s++ == '\\') { 709 (void)esccon(&s); 710 } 711 if (s - str > 64) { 712 fwrite(str, 1, s - str, stdout); 713 printf("\"\n\t.ascii\t\""); 714 str = s; 715 } 716 } 717 fwrite(str, 1, s - str, stdout); 718 printf("\\0\"\n"); 719 } 720 721 static int inbits, inval; 722 723 /* 724 * set fsz bits in sequence to zero. 725 */ 726 void 727 zbits(OFFSZ off, int fsz) 728 { 729 int m; 730 731 if (idebug) 732 printf("zbits off %lld, fsz %d inbits %d\n", off, fsz, inbits); 733 if ((m = (inbits % SZCHAR))) { 734 m = SZCHAR - m; 735 if (fsz < m) { 736 inbits += fsz; 737 return; 738 } else { 739 fsz -= m; 740 printf("\t.byte %d\n", inval); 741 inval = inbits = 0; 742 } 743 } 744 if (fsz >= SZCHAR) { 745 printf("\t.zero %d\n", fsz/SZCHAR); 746 fsz -= (fsz/SZCHAR) * SZCHAR; 747 } 748 if (fsz) { 749 inval = 0; 750 inbits = fsz; 751 } 752 } 753 754 /* 755 * Initialize a bitfield. 756 */ 757 void 758 infld(CONSZ off, int fsz, CONSZ val) 759 { 760 if (idebug) 761 printf("infld off %lld, fsz %d, val %lld inbits %d\n", 762 off, fsz, val, inbits); 763 val &= (1 << fsz)-1; 764 while (fsz + inbits >= SZCHAR) { 765 inval |= (val << inbits); 766 printf("\t.byte %d\n", inval & 255); 767 fsz -= (SZCHAR - inbits); 768 val >>= (SZCHAR - inbits); 769 inval = inbits = 0; 770 } 771 if (fsz) { 772 inval |= (val << inbits); 773 inbits += fsz; 774 } 775 } 776 777 /* 778 * print out a constant node, may be associated with a label. 779 * Do not free the node after use. 780 * off is bit offset from the beginning of the aggregate 781 * fsz is the number of bits this is referring to 782 * 783 * XXX this relies on the host fp numbers representation 784 */ 785 void 786 ninval(CONSZ off, int fsz, NODE *p) 787 { 788 union { float f; double d; long double l; int i[3]; } u; 789 struct symtab *q; 790 TWORD t; 791 int i; 792 793 t = p->n_type; 794 if (t > BTMASK) 795 t = INT; /* pointer */ 796 797 if (p->n_op != ICON && p->n_op != FCON) 798 cerror("ninval: init node not constant"); 799 800 if (p->n_op == ICON && p->n_sp != NULL && DEUNSIGN(t) != INT) 801 uerror("element not constant"); 802 803 switch (t) { 804 case LONGLONG: 805 case ULONGLONG: 806 i = (p->n_lval >> 32); 807 p->n_lval &= 0xffffffff; 808 p->n_type = INT; 809 ninval(off, 32, p); 810 p->n_lval = i; 811 ninval(off+32, 32, p); 812 break; 813 case INT: 814 case UNSIGNED: 815 printf("\t.long 0x%x", (int)p->n_lval); 816 if ((q = p->n_sp) != NULL) { 817 if ((q->sclass == STATIC && q->slevel > 0)) { 818 printf("+" LABFMT, q->soffset); 819 } else 820 printf("+%s", 821 q->soname ? q->soname : exname(q->sname)); 822 } 823 printf("\n"); 824 break; 825 case SHORT: 826 case USHORT: 827 printf("\t.short 0x%x\n", (int)p->n_lval & 0xffff); 828 break; 829 case BOOL: 830 if (p->n_lval > 1) 831 p->n_lval = p->n_lval != 0; 832 /* FALLTHROUGH */ 833 case CHAR: 834 case UCHAR: 835 /* TODO make the upper layer give an .asciz */ 836 printf("\t.byte %d\n", (int)p->n_lval & 0xff); 837 break; 838 case LDOUBLE: 839 case DOUBLE: 840 u.d = (double)p->n_dcon; 841 printf("\t.long\t0x%x,0x%x\n", u.i[0], u.i[1]); 842 break; 843 case FLOAT: 844 u.f = (float)p->n_dcon; 845 printf("\t.long\t0x%x\n", u.i[0]); 846 break; 847 default: 848 cerror("ninval"); 849 } 850 } 851 852 /* make a name look like an external name in the local machine */ 853 char * 854 exname(char *p) 855 { 856 if (p == NULL) 857 return ""; 858 return p; 859 } 860 861 /* 862 * map types which are not defined on the local machine 863 */ 864 TWORD 865 ctype(TWORD type) 866 { 867 switch (BTYPE(type)) { 868 case LONG: 869 MODTYPE(type,INT); 870 break; 871 872 case ULONG: 873 MODTYPE(type,UNSIGNED); 874 } 875 876 return (type); 877 } 878 879 void 880 calldec(NODE *f, NODE *a) 881 { 882 struct symtab *q; 883 if (f->n_op == UMUL && f->n_left->n_op == PLUS && 884 f->n_left->n_right->n_op == ICON) 885 q = f->n_left->n_right->n_sp; 886 else if (f->n_op == PLUS && f->n_right->n_op == ICON) 887 q = f->n_right->n_sp; 888 else { 889 fwalk(f, eprint, 0); 890 cerror("unknown function"); 891 return; 892 } 893 894 printf("\t.import\t%s,code\n", q->soname ? q->soname : exname(q->sname)); 895 } 896 897 void 898 extdec(struct symtab *q) 899 { 900 printf("\t.import\t%s,data\n", q->soname ? q->soname : exname(q->sname)); 901 } 902 903 /* make a common declaration for id, if reasonable */ 904 void 905 defzero(struct symtab *sp) 906 { 907 int off; 908 909 off = tsize(sp->stype, sp->sdf, sp->ssue); 910 off = (off + (SZCHAR - 1)) / SZCHAR; 911 printf("\t.%scomm\t", sp->sclass == STATIC ? "l" : ""); 912 if (sp->slevel == 0) 913 printf("%s,0%o\n", sp->soname ? sp->soname : exname(sp->sname), off); 914 else 915 printf(LABFMT ",0%o\n", sp->soffset, off); 916 } 917 918 char * 919 section2string(char *name, int len) 920 { 921 char *s; 922 int n; 923 924 if (strncmp(name, "link_set", 8) == 0) { 925 const char *postfix = ",\"aw\",@progbits"; 926 n = len + strlen(postfix) + 1; 927 s = IALLOC(n); 928 strlcpy(s, name, n); 929 strlcat(s, postfix, n); 930 return s; 931 } 932 933 return newstring(name, len); 934 } 935 936 char *nextsect; 937 char *alias; 938 int constructor; 939 int destructor; 940 941 #define SSECTION 010000 942 943 /* 944 * Give target the opportunity of handling pragmas. 945 */ 946 int 947 mypragma(char **ary) 948 { 949 if (strcmp(ary[1], "constructor") == 0 || strcmp(ary[1], "init") == 0) { 950 constructor = 1; 951 return 1; 952 } 953 if (strcmp(ary[1], "destructor") == 0 || strcmp(ary[1], "fini") == 0) { 954 destructor = 1; 955 return 1; 956 } 957 if (strcmp(ary[1], "section") == 0 && ary[2] != NULL) { 958 nextsect = section2string(ary[2], strlen(ary[2])); 959 return 1; 960 } 961 if (strcmp(ary[1], "alias") == 0 && ary[2] != NULL) { 962 alias = tmpstrdup(ary[2]); 963 return 1; 964 } 965 if (strcmp(ary[1], "ident") == 0) 966 return 1; /* Just ignore */ 967 return 0; 968 } 969 970 /* 971 * Called when a identifier has been declared, to give target last word. 972 */ 973 void 974 fixdef(struct symtab *sp) 975 { 976 if (alias != NULL && (sp->sclass != PARAM)) { 977 printf("\t.globl %s\n%s = %s\n", exname(sp->soname), 978 exname(sp->soname), exname(alias)); 979 alias = NULL; 980 } 981 if ((constructor || destructor) && (sp->sclass != PARAM)) { 982 printf("\t.section .%ctors,\"aw\",@progbits\n" 983 "\t.p2align 2\n\t.long %s\n\t.previous\n", 984 constructor ? 'c' : 'd', exname(sp->sname)); 985 constructor = destructor = 0; 986 } 987 } 988 989 void 990 pass1_lastchance(struct interpass *ip) 991 { 992 } 993