Quick Search:

Mode

Context

Displaying the whole file. None | Less | More | Full

Other Diffs

Ignore

Blank Lines Whitespace: Expand:

Diff

1.79
 
1.80
 
MAIN:gmcgarry:20140604071802
 
code.c
_>11 /*      $Id$    */
 22 /*
 33  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
 44  * All rights reserved.
 55  *
 66  * Redistribution and use in source and binary forms, with or without
 77  * modification, are permitted provided that the following conditions
 88  * are met:
 99  * 1. Redistributions of source code must retain the above copyright
 1010  *    notice, this list of conditions and the following disclaimer.
 1111  * 2. Redistributions in binary form must reproduce the above copyright
 1212  *    notice, this list of conditions and the following disclaimer in the
 1313  *    documentation and/or other materials provided with the distribution.
 1414  * 3. The name of the author may not be used to endorse or promote products
 1515  *    derived from this software without specific prior written permission
 1616  *
 1717  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 1818  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 1919  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 2020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 2121  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 2222  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 2323  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 2424  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 2525  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 2626  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 2727  */
 2828 
 2929 
 3030 # include "pass1.h"
 3131 
 3232 /*
 3333  * Print out assembler segment name.
 3434  */
 3535 void
 3636 setseg(int seg, char *name)
 3737 {
 3838         switch (seg) {
 3939         case PROG: name = ".text"; break;
 4040         case DATA:
 4141         case LDATA: name = ".data"; break;
 4242         case UDATA: break;
 4343 #ifdef MACHOABI
 4444         case PICLDATA:
 4545         case PICDATA: name = ".section .data.rel.rw,\"aw\""; break;
 4646         case PICRDATA: name = ".section .data.rel.ro,\"aw\""; break;
 4747         case STRNG: name = ".cstring"; break;
 4848         case RDATA: name = ".const_data"; break;
 4949 #else
 5050         case PICLDATA: name = ".section .data.rel.local,\"aw\",@progbits";break;
 5151         case PICDATA: name = ".section .data.rel.rw,\"aw\",@progbits"; break;
 5252         case PICRDATA: name = ".section .data.rel.ro,\"aw\",@progbits"; break;
 5353         case STRNG:
 5454 #ifdef AOUTABI
 5555         case RDATA: name = ".data"; break;
 5656 #else
 5757         case RDATA: name = ".section .rodata"; break;
 5858 #endif
 5959 #endif
 6060         case TLSDATA: name = ".section .tdata,\"awT\",@progbits"; break;
 6161         case TLSUDATA: name = ".section .tbss,\"awT\",@nobits"; break;
<> 62+#ifdef MACHOABI
  63+        case CTORS: name = ".mod_init_func\n\t.align 2"; break;
  64+        case DTORS: name = ".mod_term_func\n\t.align 2"; break;
  65+#else
6266         case CTORS: name = ".section\t.ctors,\"aw\",@progbits"; break;
 6367         case DTORS: name = ".section\t.dtors,\"aw\",@progbits"; break;
<> 68+#endif
<_6469         case NMSEG:
 6570                 printf("\t.section %s,\"a%c\",@progbits\n", name,
 6671                     cftnsp ? 'x' : 'w');
 6772                 return;
 6873         }
 6974         printf("\t%s\n", name);
 7075 }
 7176 
 7277 #ifdef MACHOABI
 7378 void
 7479 defalign(int al)
 7580 {
 7681         printf("\t.align %d\n", ispow2(al/ALCHAR));
 7782 }
 7883 #endif
 7984 
 8085 /*
 8186  * Define everything needed to print out some data (or text).
 8287  * This means segment, alignment, visibility, etc.
 8388  */
 8489 void
 8590 defloc(struct symtab *sp)
 8691 {
 8792         char *name;
 8893 
 8994         if ((name = sp->soname) == NULL)
 9095                 name = exname(sp->sname);
 9196         if (sp->sclass == EXTDEF) {
 9297                 printf("        .globl %s\n", name);
 9398 #if defined(ELFABI)
 9499                 printf("\t.type %s,@%s\n", name,
 95100                     ISFTN(sp->stype)? "function" : "object");
 96101 #endif
 97102         }
 98103 #if defined(ELFABI)
 99104         if (!ISFTN(sp->stype)) {
 100105                 if (sp->slevel == 0)
 101106                         printf("\t.size %s,%d\n", name,
 102107                             (int)tsize(sp->stype, sp->sdf, sp->sap)/SZCHAR);
 103108                 else
 104109                         printf("\t.size " LABFMT ",%d\n", sp->soffset,
 105110                             (int)tsize(sp->stype, sp->sdf, sp->sap)/SZCHAR);
 106111         }
 107112 #endif
 108113         if (sp->slevel == 0)
 109114                 printf("%s:\n", name);
 110115         else
 111116                 printf(LABFMT ":\n", sp->soffset);
 112117 }
 113118 
 114119 int structrettemp;
 115120 
 116121 /*
 117122  * code for the end of a function
 118123  * deals with struct return here
 119124  */
 120125 void
 121126 efcode(void)
 122127 {
 123128         extern int gotnr;
 124129         NODE *p, *q;
 125130 
 126131         gotnr = 0;      /* new number for next fun */
 127132         if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN)
 128133                 return;
 129134 #if defined(os_openbsd)
 130135         /* struct return for small structs */
 131136         int sz = tsize(BTYPE(cftnsp->stype), cftnsp->sdf, cftnsp->sap);
 132137         if (sz == SZCHAR || sz == SZSHORT || sz == SZINT || sz == SZLONGLONG) {
 133138                 /* Pointer to struct in eax */
 134139                 if (sz == SZLONGLONG) {
 135140                         q = block(OREG, NIL, NIL, INT, 0, 0);
 136141                         q->n_lval = 4;
 137142                         p = block(REG, NIL, NIL, INT, 0, 0);
 138143                         p->n_rval = EDX;
 139144                         ecomp(buildtree(ASSIGN, p, q));
 140145                 }
 141146                 if (sz < SZSHORT) sz = CHAR;
 142147                 else if (sz > SZSHORT) sz = INT;
 143148                 else sz = SHORT;
 144149                 q = block(OREG, NIL, NIL, sz, 0, 0);
 145150                 p = block(REG, NIL, NIL, sz, 0, 0);
 146151                 ecomp(buildtree(ASSIGN, p, q));
 147152                 return;
 148153         }
 149154 #endif
 150155         /* Create struct assignment */
 151156         q = tempnode(structrettemp, PTR+STRTY, 0, cftnsp->sap);
 152157         q = buildtree(UMUL, q, NIL);
 153158         p = block(REG, NIL, NIL, PTR+STRTY, 0, cftnsp->sap);
 154159         p = buildtree(UMUL, p, NIL);
 155160         p = buildtree(ASSIGN, q, p);
 156161         ecomp(p);
 157162 
 158163         /* put hidden arg in eax on return */
 159164         q = tempnode(structrettemp, INT, 0, 0);
 160165         p = block(REG, NIL, NIL, INT, 0, 0);
 161166         regno(p) = EAX;
 162167         ecomp(buildtree(ASSIGN, p, q));
 163168 }
 164169 
 165170 static TWORD longregs[] = { EAXEDX, EDXECX };
 166171 static TWORD regpregs[] = { EAX, EDX, ECX };
 167172 static TWORD charregs[] = { AL, DL, CL };
 168173 
 169174 /*
 170175  * code for the beginning of a function; a is an array of
 171176  * indices in symtab for the arguments; n is the number
 172177  *
 173178  * Classifying args on i386; not simple:
 174179  * - Args may be on stack or in registers (regparm)
 175180  * - There may be a hidden first arg, unless OpenBSD struct return.
 176181  * - Regparm syntax is not well documented.
 177182  * - There may be stdcall functions, where the called function pops stack
 178183  * - ...probably more
 179184  */
 180185 void
 181186 bfcode(struct symtab **sp, int cnt)
 182187 {
 183188         extern int argstacksize;
 184189 #ifdef GCC_COMPAT
 185190         struct attr *ap;
 186191 #endif
 187192         struct symtab *sp2;
 188193         extern int gotnr;
 189194         NODE *n, *p;
 190195         int i, regparmarg;
 191196         int argbase, nrarg, sz;
 192197 
 193198         /* Take care of PIC stuff first */
 194199         if (kflag) {
 195200 #define STL     200
 196201                 char *str = inlalloc(STL);
 197202 #if !defined(MACHOABI)
 198203                 int l = getlab();
 199204 #else
 200205                 char *name;
 201206 #endif
 202207 
 203208                 /* Generate extended assembler for PIC prolog */
 204209                 p = tempnode(0, INT, 0, 0);
 205210                 gotnr = regno(p);
 206211                 p = block(XARG, p, NIL, INT, 0, 0);
 207212                 p->n_name = "=g";
 208213                 p = block(XASM, p, bcon(0), INT, 0, 0);
 209214 
 210215 #if defined(MACHOABI)
 211216                 if ((name = cftnsp->soname) == NULL)
 212217                         name = cftnsp->sname;
 213218                 if (snprintf(str, STL, "call L%s$pb\nL%s$pb:\n\tpopl %%0\n",
 214219                     name, name) >= STL)
 215220                         cerror("bfcode");
 216221 #else
 217222                 if (snprintf(str, STL,
 218223                     "call " LABFMT "\n" LABFMT ":\n\tpopl %%0\n"
 219224                     "\taddl $_GLOBAL_OFFSET_TABLE_+[.-" LABFMT "], %%0\n",
 220225                     l, l, l) >= STL)
 221226                         cerror("bfcode");
 222227 #endif
 223228                 p->n_name = str;
 224229                 p->n_right->n_type = STRTY;
 225230                 ecomp(p);
 226231         }
 227232 
 228233         argbase = ARGINIT;
 229234         nrarg = regparmarg = 0;
 230235 
 231236 #ifdef GCC_COMPAT
 232237         if (attr_find(cftnsp->sap, GCC_ATYP_STDCALL) != NULL)
 233238                 cftnsp->sflags |= SSTDCALL;
 234239         if ((ap = attr_find(cftnsp->sap, GCC_ATYP_REGPARM)))
 235240                 regparmarg = ap->iarg(0);
 236241 #endif
 237242 
 238243         /* Function returns struct, create return arg node */
 239244         if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) {
 240245 #if defined(os_openbsd)
 241246                 /* OpenBSD uses non-standard return for small structs */
 242247                 int sz = tsize(BTYPE(cftnsp->stype), cftnsp->sdf, cftnsp->sap);
 243248                 if (sz <= SZLONGLONG)
 244249 #endif
 245250                 {
 246251                         if (regparmarg) {
 247252                                 n = block(REG, 0, 0, INT, 0, 0);
 248253                                 regno(n) = regpregs[nrarg++];
 249254                         } else {
 250255                                 n = block(OREG, 0, 0, INT, 0, 0);
 251256                                 n->n_lval = argbase/SZCHAR;
 252257                                 argbase += SZINT;
 253258                                 regno(n) = FPREG;
 254259                         }
 255260                         p = tempnode(0, INT, 0, 0);
 256261                         structrettemp = regno(p);
 257262                         p = buildtree(ASSIGN, p, n);
 258263                         ecomp(p);
 259264                 }
 260265         }
 261266 
 262267         /*
 263268          * Find where all params are so that they end up at the right place.
 264269          * At the same time recalculate their arg offset on stack.
 265270          * We also get the "pop size" for stdcall.
 266271          */
 267272         for (i = 0; i < cnt; i++) {
 268273                 sp2 = sp[i];
 269274                 sz = tsize(sp2->stype, sp2->sdf, sp2->sap);
 270275 
 271276                 SETOFF(sz, SZINT);
 272277 
 273278                 if (cisreg(sp2->stype) == 0 ||
 274279                     ((regparmarg - nrarg) * SZINT < sz)) {      /* not in reg */
 275280                         sp2->soffset = argbase;
 276281                         argbase += sz;
 277282                         nrarg = regparmarg;     /* no more in reg either */
 278283                 } else {                                        /* in reg */
 279284                         sp2->soffset = nrarg;
 280285                         nrarg += sz/SZINT;
 281286                         sp2->sclass = REGISTER;
 282287                 }
 283288         }
 284289 
 285290         /*
 286291          * Now (argbase - ARGINIT) is used space on stack.
 287292          * Move (if necessary) the args to something new.
 288293          */
 289294         for (i = 0; i < cnt; i++) {
 290295                 int reg, j;
 291296 
 292297                 sp2 = sp[i];
 293298 
 294299                 if (ISSOU(sp2->stype) && sp2->sclass == REGISTER) {
 295300                         /* must move to stack */
 296301                         sz = tsize(sp2->stype, sp2->sdf, sp2->sap);
 297302                         SETOFF(sz, SZINT);
 298303                         SETOFF(autooff, SZINT);
 299304                         reg = sp2->soffset;
 300305                         sp2->sclass = AUTO;
 301306                         sp2->soffset = NOOFFSET;
 302307                         oalloc(sp2, &autooff);
 303308                         for (j = 0; j < sz/SZCHAR; j += 4) {
 304309                                 p = block(OREG, 0, 0, INT, 0, 0);
 305310                                 p->n_lval = sp2->soffset/SZCHAR + j;
 306311                                 regno(p) = FPREG;
 307312                                 n = block(REG, 0, 0, INT, 0, 0);
 308313                                 regno(n) = regpregs[reg++];
 309314                                 p = block(ASSIGN, p, n, INT, 0, 0);
 310315                                 ecomp(p);
 311316                         }
 312317                 } else if (cisreg(sp2->stype) && !ISSOU(sp2->stype) &&
 313318                     ((cqual(sp2->stype, sp2->squal) & VOL) == 0)) {
 314319                         /* just put rest in temps */
 315320                         if (sp2->sclass == REGISTER) {
 316321                                 n = block(REG, 0, 0, sp2->stype,
 317322                                     sp2->sdf, sp2->sap);
 318323                                 if (ISLONGLONG(sp2->stype))
 319324                                         regno(n) = longregs[sp2->soffset];
 320325                                 else if (DEUNSIGN(sp2->stype) == CHAR || sp2->stype == BOOL)
 321326                                         regno(n) = charregs[sp2->soffset];
 322327                                 else
 323328                                         regno(n) = regpregs[sp2->soffset];
 324329                         } else {
 325330                                 n = block(OREG, 0, 0, sp2->stype,
 326331                                     sp2->sdf, sp2->sap);
 327332                                 n->n_lval = sp2->soffset/SZCHAR;
 328333                                 regno(n) = FPREG;
 329334                         }
 330335                         p = tempnode(0, sp2->stype, sp2->sdf, sp2->sap);
 331336                         sp2->soffset = regno(p);
 332337                         sp2->sflags |= STNODE;
 333338                         n = buildtree(ASSIGN, p, n);
 334339                         ecomp(n);
 335340                 }
 336341         }
 337342 
 338343         argstacksize = 0;
 339344         if (cftnsp->sflags & SSTDCALL) {
 340345                 argstacksize = (argbase - ARGINIT)/SZCHAR;
 341346 #ifdef os_win32
 342347 
 343348                 char buf[256];
 344349                 char *name;
 345350                 /*
 346351                  * mangle name in symbol table as a callee.
 347352                  */
 348353                 if ((name = cftnsp->soname) == NULL)
 349354                         name = exname(cftnsp->sname);
 350355                 snprintf(buf, 256, "%s@%d", name, argstacksize);
 351356                 cftnsp->soname = addname(buf);
 352357 #endif
 353358         }
 354359 
 355360 }
 356361 
 357362 #if defined(MACHOABI)
 358363 struct stub stublist;
 359364 struct stub nlplist;
 360365 #endif
 361366 
 362367 /* called just before final exit */
 363368 /* flag is 1 if errors, 0 if none */
 364369 void
 365370 ejobcode(int flag)
 366371 {
 367372 #if defined(MACHOABI)
 368373         /*
 369374          * iterate over the stublist and output the PIC stubs
 370375 `        */
 371376         if (kflag) {
 372377                 struct stub *p;
 373378 
 374379                 DLIST_FOREACH(p, &stublist, link) {
 375380                         printf("\t.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5\n");
 376381                         printf("L%s$stub:\n", p->name);
 377382                         printf("\t.indirect_symbol %s\n", p->name);
 378383                         printf("\thlt ; hlt ; hlt ; hlt ; hlt\n");
 379384                         printf("\t.subsections_via_symbols\n");
 380385                 }
 381386 
 382387                 printf("\t.section __IMPORT,__pointers,non_lazy_symbol_pointers\n");
 383388                 DLIST_FOREACH(p, &nlplist, link) {
 384389                         printf("L%s$non_lazy_ptr:\n", p->name);
 385390                         printf("\t.indirect_symbol %s\n", p->name);
 386391                         printf("\t.long 0\n");
 387392                 }
 388393 
 389394         }
 390395 #endif
 391396 
 392397         printf("\t.ident \"PCC: %s\"\n", VERSSTR);
 393398 }
 394399 
 395400 void
 396401 bjobcode(void)
 397402 {
 398403 #ifdef os_sunos
 399404         astypnames[SHORT] = astypnames[USHORT] = "\t.2byte";
 400405 #endif
 401406         astypnames[INT] = astypnames[UNSIGNED] = "\t.long";
 402407 #if defined(MACHOABI)
 403408         DLIST_INIT(&stublist, link);
 404409         DLIST_INIT(&nlplist, link);
 405410 #endif
 406411 }
 407412 
 408413 /*
 409414  * Convert FUNARG to assign in case of regparm.
 410415  */
 411416 static int regcvt, rparg;
 412417 static void
 413418 addreg(NODE *p)
 414419 {
 415420         TWORD t;
 416421         NODE *q;
 417422         int sz, r;
 418423 
 419424         sz = tsize(p->n_type, p->n_df, p->n_ap)/SZCHAR;
 420425         sz = (sz + 3) >> 2;     /* sz in regs */
 421426         if ((regcvt+sz) > rparg) {
 422427                 regcvt = rparg;
 423428                 return;
 424429         }
 425430         if (sz > 2)
 426431                 uerror("cannot put struct in 3 regs (yet)");
 427432 
 428433         if (sz == 2)
 429434                 r = regcvt == 0 ? EAXEDX : EDXECX;
 430435         else
 431436                 r = regcvt == 0 ? EAX : regcvt == 1 ? EDX : ECX;
 432437 
 433438         if (p->n_op == FUNARG) {
 434439                 /* at most 2 regs */
 435440                 if (p->n_type < INT) {
 436441                         p->n_left = ccast(p->n_left, INT, 0, 0, 0);
 437442                         p->n_type = INT;
 438443                 }
 439444 
 440445                 p->n_op = ASSIGN;
 441446                 p->n_right = p->n_left;
 442447         } else if (p->n_op == STARG) {
 443448                 /* convert to ptr, put in reg */
 444449                 q = p->n_left;
 445450                 t = sz == 2 ? LONGLONG : INT;
 446451                 q = cast(q, INCREF(t), 0);
 447452                 q = buildtree(UMUL, q, NIL);
 448453                 p->n_op = ASSIGN;
 449454                 p->n_type = t;
 450455                 p->n_right = q;
 451456         } else
 452457                 cerror("addreg");
 453458         p->n_left = block(REG, 0, 0, p->n_type, 0, 0);
 454459         regno(p->n_left) = r;
 455460         regcvt += sz;
 456461 }
 457462 
 458463 /*
 459464  * Called with a function call with arguments as argument.
 460465  * This is done early in buildtree() and only done once.
 461466  * Returns p.
 462467  */
 463468 NODE *
 464469 funcode(NODE *p)
 465470 {
 466471         extern int gotnr;
 467472 #ifdef GCC_COMPAT
 468473         struct attr *ap;
 469474 #endif
 470475         NODE *r, *l;
 471476         TWORD t = DECREF(DECREF(p->n_left->n_type));
 472477         int stcall;
 473478 
 474479         stcall = ISSOU(t);
 475480         /*
 476481          * We may have to prepend:
 477482          * - Hidden arg0 for struct return (in reg or on stack).
 478483          * - ebx in case of PIC code.
 479484          */
 480485 
 481486         /* Fix function call arguments. On x86, just add funarg */
 482487         for (r = p->n_right; r->n_op == CM; r = r->n_left) {
 483488                 if (r->n_right->n_op != STARG)
 484489                         r->n_right = block(FUNARG, r->n_right, NIL,
 485490                             r->n_right->n_type, r->n_right->n_df,
 486491                             r->n_right->n_ap);
 487492         }
 488493         if (r->n_op != STARG) {
 489494                 l = talloc();
 490495                 *l = *r;
 491496                 r->n_op = FUNARG;
 492497                 r->n_left = l;
 493498                 r->n_type = l->n_type;
 494499         }
 495500         if (stcall) {
 496501                 /* Prepend a placeholder for struct address. */
 497502                 /* Use EBP, can never show up under normal circumstances */
 498503                 l = talloc();
 499504                 *l = *r;
 500505                 r->n_op = CM;
 501506                 r->n_right = l;
 502507                 r->n_type = INT;
 503508                 l = block(REG, 0, 0, INCREF(VOID), 0, 0);
 504509                 regno(l) = EBP;
 505510                 l = block(FUNARG, l, 0, INCREF(VOID), 0, 0);
 506511                 r->n_left = l;
 507512         }
 508513 
 509514 #ifdef GCC_COMPAT
 510515         if ((ap = attr_find(p->n_left->n_ap, GCC_ATYP_REGPARM)))
 511516                 rparg = ap->iarg(0);
 512517         else
 513518 #endif
 514519                 rparg = 0;
 515520 
 516521         regcvt = 0;
 517522         if (rparg)
 518523                 listf(p->n_right, addreg);
 519524 
 520525         if (kflag == 0)
 521526                 return p;
 522527 
 523528 #if defined(ELFABI)
 524529         /* Create an ASSIGN node for ebx */
 525530         l = block(REG, NIL, NIL, INT, 0, 0);
 526531         l->n_rval = EBX;
 527532         l = buildtree(ASSIGN, l, tempnode(gotnr, INT, 0, 0));
 528533         if (p->n_right->n_op != CM) {
 529534                 p->n_right = block(CM, l, p->n_right, INT, 0, 0);
 530535         } else {
 531536                 for (r = p->n_right; r->n_left->n_op == CM; r = r->n_left)
 532537                         ;
 533538                 r->n_left = block(CM, l, r->n_left, INT, 0, 0);
 534539         }
 535540 #endif
 536541         return p;
 537542 }
 538543 
 539544 /* fix up type of field p */
 540545 void
 541546 fldty(struct symtab *p)
 542547 {
 543548 }
 544549 
 545550 /*
 546551  * XXX - fix genswitch.
 547552  */
 548553 int
 549554 mygenswitch(int num, TWORD type, struct swents **p, int n)
 550555 {
 551556         return 0;
 552557 }
 553558 
 554559 NODE *  
 555560 builtin_return_address(const struct bitable *bt, NODE *a)
 556561 {       
 557562         int nframes;
 558563         NODE *f;
 559564         
 560565         if (a->n_op != ICON)
 561566                 goto bad;
 562567 
 563568         nframes = (int)a->n_lval;
 564569  
 565570         tfree(a);       
 566571                         
 567572         f = block(REG, NIL, NIL, PTR+VOID, 0, 0);
 568573         regno(f) = FPREG;
 569574  
 570575         while (nframes--)
 571576                 f = block(UMUL, f, NIL, PTR+VOID, 0, 0);
 572577                                    
 573578         f = block(PLUS, f, bcon(4), INCREF(PTR+VOID), 0, 0);
 574579         f = buildtree(UMUL, f, NIL);    
 575580   
 576581         return f;
 577582 bad:                                            
 578583         uerror("bad argument to __builtin_return_address");
 579584         return bcon(0);
 580585 }
 581586 
 582587 NODE *
 583588 builtin_frame_address(const struct bitable *bt, NODE *a)
 584589 {
 585590         int nframes;
 586591         NODE *f;
 587592 
 588593         if (a->n_op != ICON)
 589594                 goto bad;
 590595 
 591596         nframes = (int)a->n_lval;
 592597 
 593598         tfree(a);
 594599 
 595600         f = block(REG, NIL, NIL, PTR+VOID, 0, 0);
 596601         regno(f) = FPREG;
 597602 
 598603         while (nframes--)
 599604                 f = block(UMUL, f, NIL, PTR+VOID, 0, 0);
 600605 
 601606         return f;
 602607 bad:
 603608         uerror("bad argument to __builtin_frame_address");
 604609         return bcon(0);
 605610 }
 606611 
 607612 /*
 608613  * Return "canonical frame address".
 609614  */
 610615 NODE *
 611616 builtin_cfa(const struct bitable *bt, NODE *a)
 612617 {
 613618         uerror("missing builtin_cfa");
 614619         return bcon(0);
 615620 }
 616621 
FishEye: Open Source License registered to PCC.
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2014-12-20 14:41 +0100