1/* Id: local.c,v 1.66 2012/03/23 17:03:09 ragge Exp */ 2/* $NetBSD: local.c,v 1.1.1.3.4.1 2012/04/03 16:36:21 riz Exp $ */ 3/* 4 * Copyright (c) 2008 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 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 30#include "pass1.h" 31 32/* this file contains code which is dependent on the target machine */ 33 34/* 35 * Check if a constant is too large for a type. 36 */ 37#ifdef notyet 38static int 39toolarge(TWORD t, CONSZ con) 40{ 41 U_CONSZ ucon = con; 42 43 switch (t) { 44 case ULONG: 45 case LONG: 46 case ULONGLONG: 47 case LONGLONG: 48 break; /* cannot be too large */ 49#define SCHK(i) case i: if (con > MAX_##i || con < MIN_##i) return 1; break 50#define UCHK(i) case i: if (ucon > MAX_##i) return 1; break 51 SCHK(INT); 52 SCHK(SHORT); 53 case BOOL: 54 SCHK(CHAR); 55 UCHK(UNSIGNED); 56 UCHK(USHORT); 57 UCHK(UCHAR); 58 default: 59 cerror("toolarge"); 60 } 61 return 0; 62} 63#endif 64 65#define IALLOC(sz) (isinlining ? permalloc(sz) : tmpalloc(sz)) 66 67/* 68 * Make a symtab entry for PIC use. 69 */ 70static struct symtab * 71picsymtab(char *p, char *s, char *s2) 72{ 73 struct symtab *sp = IALLOC(sizeof(struct symtab)); 74 size_t len = strlen(p) + strlen(s) + strlen(s2) + 1; 75 76 sp->sname = sp->soname = IALLOC(len); 77 strlcpy(sp->soname, p, len); 78 strlcat(sp->soname, s, len); 79 strlcat(sp->soname, s2, len); 80 sp->sclass = EXTERN; 81 sp->sflags = sp->slevel = 0; 82 return sp; 83} 84 85int gotnr; /* tempnum for GOT register */ 86int argstacksize; 87 88/* 89 * Create a reference for an extern variable or function. 90 */ 91static NODE * 92picext(NODE *p) 93{ 94#if defined(ELFABI) 95 96 NODE *q; 97 struct symtab *sp; 98 char *c; 99 100 if (p->n_sp->sflags & SBEENHERE) 101 return p; 102 103 c = p->n_sp->soname ? p->n_sp->soname : exname(p->n_sp->sname); 104 sp = picsymtab("", c, "@GOTPCREL"); 105 sp->sflags |= SBEENHERE; 106 q = block(NAME, NIL, NIL, INCREF(p->n_type), p->n_df, p->n_ap); 107 q->n_sp = sp; 108 q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap); 109 q->n_sp = sp; 110 nfree(p); 111 return q; 112 113#elif defined(MACHOABI) 114 115 return p; 116 117#endif 118} 119 120static NODE * 121cmop(NODE *l, NODE *r) 122{ 123 return block(CM, l, r, INT, 0, 0); 124} 125 126static NODE * 127mkx(char *s, NODE *p) 128{ 129 p = block(XARG, p, NIL, INT, 0, 0); 130 p->n_name = s; 131 return p; 132} 133 134static char * 135mk3str(char *s1, char *s2, char *s3) 136{ 137 int len = strlen(s1) + strlen(s2) + strlen(s3) + 1; 138 char *sd; 139 140 sd = inlalloc(len); 141 strlcpy(sd, s1, len); 142 strlcat(sd, s2, len); 143 strlcat(sd, s3, len); 144 return sd; 145} 146 147/* 148 * Create a reference for a TLS variable. 149 * This is the "General dynamic" version. 150 */ 151static NODE * 152tlspic(NODE *p) 153{ 154 NODE *q, *r, *s; 155 char *s1, *s2; 156 157 /* 158 * .byte 0x66 159 * leaq x@TLSGD(%rip),%rdi 160 * .word 0x6666 161 * rex64 162 * call __tls_get_addr@PLT 163 */ 164 165 /* Need the .byte stuff around. Why? */ 166 /* Use inline assembler */ 167 q = mkx("%rdx", bcon(0)); 168 q = cmop(q, mkx("%rcx", bcon(0))); 169 q = cmop(q, mkx("%rsi", bcon(0))); 170 q = cmop(q, mkx("%rdi", bcon(0))); 171 q = cmop(q, mkx("%r8", bcon(0))); 172 q = cmop(q, mkx("%r9", bcon(0))); 173 q = cmop(q, mkx("%r10", bcon(0))); 174 q = cmop(q, mkx("%r11", bcon(0))); 175 176 s = ccopy(r = tempnode(0, INCREF(p->n_type), p->n_df, p->n_ap)); 177 r = mkx("=a", r); 178 r = block(XASM, r, q, INT, 0, 0); 179 180 /* Create the magic string */ 181 s1 = ".byte 0x66\n\tleaq "; 182 s2 = "@TLSGD(%%rip),%%rdi\n" 183 "\t.word 0x6666\n\trex64\n\tcall __tls_get_addr@PLT"; 184 if (p->n_sp->soname == NULL) 185 p->n_sp->soname = p->n_sp->sname; 186 r->n_name = mk3str(s1, p->n_sp->soname, s2); 187 188 r = block(COMOP, r, s, INCREF(p->n_type), p->n_df, p->n_ap); 189 r = buildtree(UMUL, r, NIL); 190 tfree(p); 191 return r; 192} 193 194/* 195 * The "initial exec" tls model. 196 */ 197static NODE * 198tlsinitialexec(NODE *p) 199{ 200 NODE *q, *r, *s; 201 char *s1, *s2; 202 203 /* 204 * movq %fs:0,%rax 205 * addq x@GOTTPOFF(%rip),%rax 206 */ 207 208 q = bcon(0); 209 q->n_type = STRTY; 210 211 s = ccopy(r = tempnode(0, INCREF(p->n_type), p->n_df, p->n_ap)); 212 r = mkx("=r", r); 213 r = block(XASM, r, q, INT, 0, 0); 214 215 s1 = "movq %%fs:0,%0\n\taddq "; 216 s2 = "@GOTTPOFF(%%rip),%0"; 217 if (p->n_sp->soname == NULL) 218 p->n_sp->soname = p->n_sp->sname; 219 r->n_name = mk3str(s1, p->n_sp->soname, s2); 220 221 r = block(COMOP, r, s, INCREF(p->n_type), p->n_df, p->n_ap); 222 r = buildtree(UMUL, r, NIL); 223 tfree(p); 224 return r; 225} 226 227static NODE * 228tlsref(NODE *p) 229{ 230 struct symtab *sp = p->n_sp; 231 struct attr *ga; 232 char *c; 233 234 if ((ga = attr_find(sp->sap, GCC_ATYP_TLSMODEL)) != NULL) { 235 c = ga->sarg(0); 236 if (strcmp(c, "initial-exec") == 0) 237 return tlsinitialexec(p); 238 else if (strcmp(c, "global-dynamic") == 0) 239 ; 240 else 241 werror("unsupported tls model '%s'", c); 242 } 243 return tlspic(p); 244} 245 246/* clocal() is called to do local transformations on 247 * an expression tree preparitory to its being 248 * written out in intermediate code. 249 * 250 * the major essential job is rewriting the 251 * automatic variables and arguments in terms of 252 * REG and OREG nodes 253 * conversion ops which are not necessary are also clobbered here 254 * in addition, any special features (such as rewriting 255 * exclusive or) are easily handled here as well 256 */ 257NODE * 258clocal(NODE *p) 259{ 260 261 register struct symtab *q; 262 register NODE *r, *l; 263 register int o; 264 register int m; 265 TWORD t; 266 267#ifdef PCC_DEBUG 268 if (xdebug) { 269 printf("clocal: %p\n", p); 270 fwalk(p, eprint, 0); 271 } 272#endif 273 switch( o = p->n_op ){ 274 275 case NAME: 276 if ((q = p->n_sp) == NULL) 277 return p; /* Nothing to care about */ 278 279 switch (q->sclass) { 280 281 case PARAM: 282 case AUTO: 283 /* fake up a structure reference */ 284 r = block(REG, NIL, NIL, PTR+STRTY, 0, 0); 285 r->n_lval = 0; 286 r->n_rval = FPREG; 287 p = stref(block(STREF, r, p, 0, 0, 0)); 288 break; 289 290 case USTATIC: 291 if (kflag == 0) 292 break; 293 /* FALLTHROUGH */ 294 case STATIC: 295#ifdef TLS 296 if (q->sflags & STLS) { 297 p = tlsref(p); 298 break; 299 } 300#endif 301 break; 302 303 case REGISTER: 304 p->n_op = REG; 305 p->n_lval = 0; 306 p->n_rval = q->soffset; 307 break; 308 309 case EXTERN: 310 case EXTDEF: 311 if (q->sflags & STLS) { 312 p = tlsref(p); 313 break; 314 } 315 if (kflag == 0 || statinit) 316 break; 317 if (blevel > 0) 318 p = picext(p); 319 break; 320 } 321 break; 322 323 case UCALL: 324 case USTCALL: 325 /* For now, always clear eax */ 326 l = block(REG, NIL, NIL, INT, 0, 0); 327 regno(l) = RAX; 328 p->n_right = clocal(buildtree(ASSIGN, l, bcon(0))); 329 p->n_op -= (UCALL-CALL); 330 break; 331 332 case SCONV: 333 /* Special-case shifts */ 334 if (p->n_type == LONG && (l = p->n_left)->n_op == LS && 335 l->n_type == INT && l->n_right->n_op == ICON) { 336 p->n_left = l->n_left; 337 p = buildtree(LS, p, l->n_right); 338 nfree(l); 339 break; 340 } 341 342 l = p->n_left; 343 344 /* Float conversions may need extra casts */ 345 if (p->n_type == FLOAT || p->n_type == DOUBLE || 346 p->n_type == LDOUBLE) { 347 if (l->n_type < INT || l->n_type == BOOL) { 348 p->n_left = block(SCONV, l, NIL, 349 ISUNSIGNED(l->n_type) ? UNSIGNED : INT, 350 l->n_df, l->n_ap); 351 break; 352 } 353 } 354 355 if (p->n_type == l->n_type) { 356 nfree(p); 357 return l; 358 } 359 360 if ((p->n_type & TMASK) == 0 && (l->n_type & TMASK) == 0 && 361 tsize(p->n_type, p->n_df, p->n_ap) == 362 tsize(l->n_type, l->n_df, l->n_ap)) { 363 if (p->n_type != FLOAT && p->n_type != DOUBLE && 364 l->n_type != FLOAT && l->n_type != DOUBLE && 365 l->n_type != LDOUBLE && p->n_type != LDOUBLE) { 366 if (l->n_op == NAME || l->n_op == UMUL || 367 l->n_op == TEMP) { 368 l->n_type = p->n_type; 369 nfree(p); 370 return l; 371 } 372 } 373 } 374 375 if (DEUNSIGN(p->n_type) == INT && DEUNSIGN(l->n_type) == INT && 376 coptype(l->n_op) == BITYPE && l->n_op != COMOP && 377 l->n_op != QUEST) { 378 l->n_type = p->n_type; 379 nfree(p); 380 return l; 381 } 382 383 o = l->n_op; 384 m = p->n_type; 385 386 if (o == ICON) { 387 CONSZ val = l->n_lval; 388 389 if (!ISPTR(m)) /* Pointers don't need to be conv'd */ 390 switch (m) { 391 case BOOL: 392 l->n_lval = nncon(l) ? (l->n_lval != 0) : 1; 393 l->n_sp = NULL; 394 break; 395 case CHAR: 396 l->n_lval = (char)val; 397 break; 398 case UCHAR: 399 l->n_lval = val & 0377; 400 break; 401 case SHORT: 402 l->n_lval = (short)val; 403 break; 404 case USHORT: 405 l->n_lval = val & 0177777; 406 break; 407 case UNSIGNED: 408 l->n_lval = val & 0xffffffff; 409 break; 410 case INT: 411 l->n_lval = (int)val; 412 break; 413 case LONG: 414 case LONGLONG: 415 l->n_lval = (long long)val; 416 break; 417 case ULONG: 418 case ULONGLONG: 419 l->n_lval = val; 420 break; 421 case VOID: 422 break; 423 case LDOUBLE: 424 case DOUBLE: 425 case FLOAT: 426 l->n_op = FCON; 427 l->n_dcon = val; 428 break; 429 default: 430 cerror("unknown type %d", m); 431 } 432 l->n_type = m; 433 l->n_ap = NULL; 434 nfree(p); 435 return l; 436 } else if (l->n_op == FCON) { 437 if (p->n_type == BOOL) 438 l->n_lval = l->n_dcon != 0.0; 439 else 440 l->n_lval = l->n_dcon; 441 l->n_sp = NULL; 442 l->n_op = ICON; 443 l->n_type = m; 444 l->n_ap = NULL; 445 nfree(p); 446 return clocal(l); 447 } 448 if ((p->n_type == CHAR || p->n_type == UCHAR || 449 p->n_type == SHORT || p->n_type == USHORT) && 450 (l->n_type == FLOAT || l->n_type == DOUBLE || 451 l->n_type == LDOUBLE)) { 452 p = block(SCONV, p, NIL, p->n_type, p->n_df, p->n_ap); 453 p->n_left->n_type = INT; 454 return p; 455 } 456 break; 457 458 case MOD: 459 case DIV: 460 if (o == DIV && p->n_type != CHAR && p->n_type != SHORT) 461 break; 462 if (o == MOD && p->n_type != CHAR && p->n_type != SHORT) 463 break; 464 /* make it an int division by inserting conversions */ 465 p->n_left = makety(p->n_left, INT, 0, 0, 0); 466 p->n_right = makety(p->n_right, INT, 0, 0, 0); 467 p = makety(p, p->n_type, 0, 0, 0); 468 p->n_left->n_type = INT; 469 break; 470 471 case FORCE: 472 /* put return value in return reg */ 473 p->n_op = ASSIGN; 474 p->n_right = p->n_left; 475 p->n_left = block(REG, NIL, NIL, p->n_type, 0, 0); 476 t = p->n_type; 477 if (ISITY(t)) 478 t = t - (FIMAG-FLOAT); 479 p->n_left->n_rval = p->n_left->n_type == BOOL ? 480 RETREG(CHAR) : RETREG(t); 481 break; 482 483 case LS: 484 case RS: 485 /* shift count must be in a char */ 486 if (p->n_right->n_type == CHAR || p->n_right->n_type == UCHAR) 487 break; 488 p->n_right = makety(p->n_right, CHAR, 0, 0, 0); 489 break; 490 } 491#ifdef PCC_DEBUG 492 if (xdebug) { 493 printf("clocal end: %p\n", p); 494 fwalk(p, eprint, 0); 495 } 496#endif 497 return(p); 498} 499 500void 501myp2tree(NODE *p) 502{ 503 struct symtab *sp, sps; 504 static int dblxor, fltxor; 505 506 if (p->n_op == UMINUS && (p->n_type == FLOAT || p->n_type == DOUBLE)) { 507 /* Store xor code for sign change */ 508 if (dblxor == 0) { 509 dblxor = getlab(); 510 fltxor = getlab(); 511 sps.stype = LDOUBLE; 512 sps.squal = CON >> TSHIFT; 513 sps.sflags = sps.sclass = 0; 514 sps.sname = sps.soname = ""; 515 sps.slevel = 1; 516 sps.sap = NULL; 517 sps.soffset = dblxor; 518 locctr(DATA, &sps); 519 defloc(&sps); 520 printf("\t.long 0,0x80000000,0,0\n"); 521 printf(LABFMT ":\n", fltxor); 522 printf("\t.long 0x80000000,0,0,0\n"); 523 } 524 p->n_label = p->n_type == FLOAT ? fltxor : dblxor; 525 return; 526 } 527 if (kflag && (cdope(p->n_op) & CALLFLG) && p->n_left->n_op == NAME) { 528 /* Convert @GOTPCREL to @PLT */ 529 char *s; 530 531 sp = p->n_left->n_sp; 532 if ((s = strstr(sp->sname, "@GOTPCREL")) != NULL) { 533 strcpy(s, "@PLT"); 534 p->n_left->n_op = ICON; 535 } 536 return; 537 } 538 if (p->n_op != FCON) 539 return; 540 541#ifdef mach_amd64 542 { 543 /* Do not loose negative zeros */ 544 long long *llp = (long long *)(&p->n_dcon); 545 short *ssp = (short *)&llp[1]; 546 if (*llp == 0 && *ssp == 0) 547 return; 548 } 549#else 550#error fixme 551#endif 552 553 /* XXX should let float constants follow */ 554 sp = IALLOC(sizeof(struct symtab)); 555 sp->sclass = STATIC; 556 sp->sap = NULL; 557 sp->slevel = 1; /* fake numeric label */ 558 sp->soffset = getlab(); 559 sp->sflags = 0; 560 sp->stype = p->n_type; 561 sp->squal = (CON >> TSHIFT); 562 sp->sname = sp->soname = NULL; 563 564 locctr(DATA, sp); 565 defloc(sp); 566 ninval(0, tsize(sp->stype, sp->sdf, sp->sap), p); 567 568 p->n_op = NAME; 569 p->n_lval = 0; 570 p->n_sp = sp; 571} 572 573/* 574 * Convert ADDROF NAME to ICON? 575 */ 576int 577andable(NODE *p) 578{ 579 if (p->n_sp->sclass == STATIC || p->n_sp->sclass == USTATIC) 580 return 1; 581 return !kflag; 582} 583 584/* 585 * Return 1 if a variable of type type is OK to put in register. 586 */ 587int 588cisreg(TWORD t) 589{ 590 if (t == LDOUBLE) 591 return 0; 592 return 1; 593} 594 595/* 596 * Allocate off bits on the stack. p is a tree that when evaluated 597 * is the multiply count for off, t is a storeable node where to write 598 * the allocated address. 599 */ 600void 601spalloc(NODE *t, NODE *p, OFFSZ off) 602{ 603 NODE *sp; 604 605 p = buildtree(MUL, p, bcon(off/SZCHAR)); 606 p = buildtree(PLUS, p, bcon(30)); 607 p = buildtree(AND, p, xbcon(-16, NULL, LONG)); 608 609 /* sub the size from sp */ 610 sp = block(REG, NIL, NIL, p->n_type, 0, 0); 611 sp->n_lval = 0; 612 sp->n_rval = STKREG; 613 ecomp(buildtree(MINUSEQ, sp, p)); 614 615 /* save the address of sp */ 616 sp = block(REG, NIL, NIL, PTR+LONG, t->n_df, t->n_ap); 617 sp->n_lval = 0; 618 sp->n_rval = STKREG; 619 t->n_type = sp->n_type; 620 ecomp(buildtree(ASSIGN, t, sp)); /* Emit! */ 621 622} 623 624/* 625 * print out a constant node, may be associated with a label. 626 * Do not free the node after use. 627 * off is bit offset from the beginning of the aggregate 628 * fsz is the number of bits this is referring to 629 */ 630int 631ninval(CONSZ off, int fsz, NODE *p) 632{ 633 union { float f; double d; long double l; int i[3]; } u; 634 635 switch (p->n_type) { 636 case LDOUBLE: 637 u.i[2] = 0; 638 u.l = (long double)p->n_dcon; 639#if defined(HOST_BIG_ENDIAN) 640 /* XXX probably broken on most hosts */ 641 printf("\t.long\t0x%x,0x%x,0x%x,0\n", u.i[2], u.i[1], u.i[0]); 642#else 643 printf("\t.long\t0x%x,0x%x,0x%x,0\n", u.i[0], u.i[1], u.i[2]); 644#endif 645 break; 646 case DOUBLE: 647 u.d = (double)p->n_dcon; 648#if defined(HOST_BIG_ENDIAN) 649 printf("\t.long\t0x%x,0x%x\n", u.i[1], u.i[0]); 650#else 651 printf("\t.long\t0x%x,0x%x\n", u.i[0], u.i[1]); 652#endif 653 break; 654 case FLOAT: 655 u.f = (float)p->n_dcon; 656 printf("\t.long\t0x%x\n", u.i[0]); 657 break; 658 default: 659 return 0; 660 } 661 return 1; 662} 663 664/* make a name look like an external name in the local machine */ 665char * 666exname(char *p) 667{ 668#ifdef MACHOABI 669 670#define NCHNAM 256 671 static char text[NCHNAM+1]; 672 int i; 673 674 if (p == NULL) 675 return ""; 676 677 text[0] = '_'; 678 for (i=1; *p && i<NCHNAM; ++i) 679 text[i] = *p++; 680 681 text[i] = '\0'; 682 text[NCHNAM] = '\0'; /* truncate */ 683 684 return (text); 685#else 686 return (p == NULL ? "" : p); 687#endif 688} 689 690/* 691 * map types which are not defined on the local machine 692 */ 693TWORD 694ctype(TWORD type) 695{ 696 switch (BTYPE(type)) { 697 case LONGLONG: 698 MODTYPE(type,LONG); 699 break; 700 701 case ULONGLONG: 702 MODTYPE(type,ULONG); 703 704 } 705 return (type); 706} 707 708void 709calldec(NODE *p, NODE *q) 710{ 711} 712 713void 714extdec(struct symtab *q) 715{ 716} 717 718/* make a common declaration for id, if reasonable */ 719void 720defzero(struct symtab *sp) 721{ 722 int off, al; 723 char *name; 724 725 if ((name = sp->soname) == NULL) 726 name = exname(sp->sname); 727 off = tsize(sp->stype, sp->sdf, sp->sap); 728 SETOFF(off,SZCHAR); 729 off /= SZCHAR; 730 al = talign(sp->stype, sp->sap)/SZCHAR; 731 732 if (sp->sclass == STATIC) { 733 if (sp->slevel == 0) { 734 printf("\t.local %s\n", name); 735 } else 736 printf("\t.local " LABFMT "\n", sp->soffset); 737 } 738 if (sp->slevel == 0) { 739 printf("\t.comm %s,0%o,%d\n", name, off, al); 740 } else 741 printf("\t.comm " LABFMT ",0%o,%d\n", sp->soffset, off, al); 742} 743 744static char * 745section2string(char *name, int len) 746{ 747 char *s; 748 int n; 749 750 if (strncmp(name, "link_set", 8) == 0) { 751 const char *postfix = ",\"aw\",@progbits"; 752 n = len + strlen(postfix) + 1; 753 s = IALLOC(n); 754 strlcpy(s, name, n); 755 strlcat(s, postfix, n); 756 return s; 757 } 758 759 return newstring(name, len); 760} 761 762char *nextsect; 763static int gottls; 764static char *alias; 765static int constructor; 766static int destructor; 767 768/* 769 * Give target the opportunity of handling pragmas. 770 */ 771int 772mypragma(char *str) 773{ 774 char *a2 = pragtok(NULL); 775 776 if (strcmp(str, "tls") == 0 && a2 == NULL) { 777 gottls = 1; 778 return 1; 779 } 780 if (strcmp(str, "constructor") == 0 || strcmp(str, "init") == 0) { 781 constructor = 1; 782 return 1; 783 } 784 if (strcmp(str, "destructor") == 0 || strcmp(str, "fini") == 0) { 785 destructor = 1; 786 return 1; 787 } 788 if (strcmp(str, "section") == 0 && a2 != NULL) { 789 nextsect = section2string(a2, strlen(a2)); 790 return 1; 791 } 792 if (strcmp(str, "alias") == 0 && a2 != NULL) { 793 alias = tmpstrdup(a2); 794 return 1; 795 } 796 797 return 0; 798} 799 800/* 801 * Called when a identifier has been declared. 802 */ 803void 804fixdef(struct symtab *sp) 805{ 806 struct attr *ga; 807 808 /* may have sanity checks here */ 809 if (gottls) 810 sp->sflags |= STLS; 811 gottls = 0; 812 813#ifdef HAVE_WEAKREF 814 /* not many as'es have this directive */ 815 if ((ga = gcc_get_attr(sp->sap, GCC_ATYP_WEAKREF)) != NULL) { 816 char *wr = ga->a1.sarg; 817 char *sn = sp->soname ? sp->soname : sp->sname; 818 if (wr == NULL) { 819 if ((ga = gcc_get_attr(sp->sap, GCC_ATYP_ALIAS))) { 820 wr = ga->a1.sarg; 821 } 822 } 823 if (wr == NULL) 824 printf("\t.weak %s\n", sn); 825 else 826 printf("\t.weakref %s,%s\n", sn, wr); 827 } else 828#endif 829 if ((ga = attr_find(sp->sap, GCC_ATYP_ALIAS)) != NULL) { 830 char *an = ga->sarg(0); 831 char *sn = sp->soname ? sp->soname : sp->sname; 832 char *v; 833 834 v = attr_find(sp->sap, GCC_ATYP_WEAK) ? "weak" : "globl"; 835 printf("\t.%s %s\n", v, sn); 836 printf("\t.set %s,%s\n", sn, an); 837 } 838 if (alias != NULL && (sp->sclass != PARAM)) { 839 printf("\t.globl %s\n", exname(sp->soname)); 840 printf("%s = ", exname(sp->soname)); 841 printf("%s\n", exname(alias)); 842 alias = NULL; 843 } 844 if ((constructor || destructor) && (sp->sclass != PARAM)) { 845 NODE *p = talloc(); 846 847 p->n_op = NAME; 848 p->n_sp = 849 (struct symtab *)(constructor ? "constructor" : "destructor"); 850 sp->sap = attr_add(sp->sap, gcc_attr_parse(p)); 851 constructor = destructor = 0; 852 } 853} 854 855NODE * 856i386_builtin_return_address(NODE *f, NODE *a, TWORD t) 857{ 858 int nframes; 859 860 if (a == NULL || a->n_op != ICON) 861 goto bad; 862 863 nframes = a->n_lval; 864 865 tfree(f); 866 tfree(a); 867 868 f = block(REG, NIL, NIL, PTR+VOID, 0, 0); 869 regno(f) = FPREG; 870 871 while (nframes--) 872 f = block(UMUL, f, NIL, PTR+VOID, 0, 0); 873 874 f = block(PLUS, f, bcon(4), INCREF(PTR+VOID), 0, 0); 875 f = buildtree(UMUL, f, NIL); 876 877 return f; 878bad: 879 uerror("bad argument to __builtin_return_address"); 880 return bcon(0); 881} 882 883NODE * 884i386_builtin_frame_address(NODE *f, NODE *a, TWORD t) 885{ 886 int nframes; 887 888 if (a == NULL || a->n_op != ICON) 889 goto bad; 890 891 nframes = a->n_lval; 892 893 tfree(f); 894 tfree(a); 895 896 f = block(REG, NIL, NIL, PTR+VOID, 0, 0); 897 regno(f) = FPREG; 898 899 while (nframes--) 900 f = block(UMUL, f, NIL, PTR+VOID, 0, 0); 901 902 return f; 903bad: 904 uerror("bad argument to __builtin_frame_address"); 905 return bcon(0); 906} 907 908void 909pass1_lastchance(struct interpass *ip) 910{ 911} 912