Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:plunky:20140529181125

Diff

Diff from 1.79 to:

Annotations

Annotate by Age | Author | Mixed | None
/fisheye/browse/pcc/pcc/arch/i386/code.c

Annotated File View

plunky
1.79
1 /*      $Id: code.c,v 1.79 2014/05/29 18:11:25 plunky Exp $     */
ragge
1.1
2 /*
3  * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission
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 /*
ragge
1.65
33  * Print out assembler segment name.
ragge
1.1
34  */
35 void
ragge
1.65
36 setseg(int segchar *name)
ragge
1.1
37 {
ragge
1.65
38         switch (seg) {
39         case PROGname = ".text"break;
40         case DATA:
41         case LDATAname = ".data"break;
42         case UDATAbreak;
gmcgarry
1.57
43 #ifdef MACHOABI
ragge
1.65
44         case PICLDATA:
45         case PICDATAname = ".section .data.rel.rw,\"aw\""break;
46         case PICRDATAname = ".section .data.rel.ro,\"aw\""break;
47         case STRNGname = ".cstring"break;
48         case RDATAname = ".const_data"break;
49 #else
50         case PICLDATAname = ".section .data.rel.local,\"aw\",@progbits";break;
51         case PICDATAname = ".section .data.rel.rw,\"aw\",@progbits"break;
52         case PICRDATAname = ".section .data.rel.ro,\"aw\",@progbits"break;
53         case STRNG:
54 #ifdef AOUTABI
55         case RDATAname = ".data"break;
gmcgarry
1.57
56 #else
ragge
1.65
57         case RDATAname = ".section .rodata"break;
gmcgarry
1.57
58 #endif
59 #endif
ragge
1.65
60         case TLSDATAname = ".section .tdata,\"awT\",@progbits"break;
61         case TLSUDATAname = ".section .tbss,\"awT\",@nobits"break;
62         case CTORSname = ".section\t.ctors,\"aw\",@progbits"break;
63         case DTORSname = ".section\t.dtors,\"aw\",@progbits"break;
64         case NMSEG
ragge
1.70
65                 printf("\t.section %s,\"a%c\",@progbits\n"name,
66                     cftnsp ? 'x' : 'w');
ragge
1.65
67                 return;
ragge
1.53
68         }
ragge
1.65
69         printf("\t%s\n"name);
70 }
71
gmcgarry
1.57
72 #ifdef MACHOABI
ragge
1.65
73 void
74 defalign(int al)
75 {
76         printf("\t.align %d\n"ispow2(al/ALCHAR));
77 }
gmcgarry
1.57
78 #endif
ragge
1.65
79
80 /*
81  * Define everything needed to print out some data (or text).
82  * This means segment, alignment, visibility, etc.
83  */
84 void
85 defloc(struct symtab *sp)
86 {
87         char *name;
88
89         if ((name = sp->soname) == NULL)
90                 name = exname(sp->sname);
91         if (sp->sclass == EXTDEF) {
ragge
1.41
92                 printf("        .globl %s\n"name);
gmcgarry
1.30
93 #if defined(ELFABI)
mickey
1.49
94                 printf("\t.type %s,@%s\n"name,
ragge
1.65
95                     ISFTN(sp->stype)? "function" : "object");
gmcgarry
1.30
96 #endif
mickey
1.49
97         }
ragge
1.58
98 #if defined(ELFABI)
ragge
1.65
99         if (!ISFTN(sp->stype)) {
ragge
1.58
100                 if (sp->slevel == 0)
101                         printf("\t.size %s,%d\n"name,
ragge
1.65
102                             (int)tsize(sp->stypesp->sdfsp->sap)/SZCHAR);
ragge
1.58
103                 else
104                         printf("\t.size " LABFMT ",%d\n"sp->soffset,
ragge
1.65
105                             (int)tsize(sp->stypesp->sdfsp->sap)/SZCHAR);
ragge
1.58
106         }
107 #endif
ragge
1.24
108         if (sp->slevel == 0)
ragge
1.41
109                 printf("%s:\n"name);
ragge
1.24
110         else
111                 printf(LABFMT ":\n"sp->soffset);
ragge
1.6
112 }
113
ragge
1.75
114 int structrettemp;
115
ragge
1.6
116 /*
ragge
1.1
117  * code for the end of a function
ragge
1.4
118  * deals with struct return here
ragge
1.1
119  */
120 void
plunky
1.68
121 efcode(void)
ragge
1.1
122 {
ragge
1.16
123         extern int gotnr;
ragge
1.4
124         NODE *p, *q;
125
ragge
1.16
126         gotnr = 0;      /* new number for next fun */
ragge
1.4
127         if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN)
128                 return;
ragge
1.48
129 #if defined(os_openbsd)
130         /* struct return for small structs */
ragge
1.56
131         int sz = tsize(BTYPE(cftnsp->stype), cftnsp->sdfcftnsp->sap);
ragge
1.48
132         if (sz == SZCHAR || sz == SZSHORT || sz == SZINT || sz == SZLONGLONG) {
133                 /* Pointer to struct in eax */
134                 if (sz == SZLONGLONG) {
ragge
1.60
135                         q = block(OREGNILNILINT00);
ragge
1.48
136                         q->n_lval = 4;
ragge
1.60
137                         p = block(REGNILNILINT00);
ragge
1.48
138                         p->n_rval = EDX;
139                         ecomp(buildtree(ASSIGNpq));
140                 }
141                 if (sz < SZSHORTsz = CHAR;
142                 else if (sz > SZSHORTsz = INT;
143                 else sz = SHORT;
ragge
1.60
144                 q = block(OREGNILNILsz00);
145                 p = block(REGNILNILsz00);
ragge
1.48
146                 ecomp(buildtree(ASSIGNpq));
147                 return;
148         }
149 #endif
ragge
1.18
150         /* Create struct assignment */
ragge
1.75
151         q = tempnode(structrettempPTR+STRTY0cftnsp->sap);
ragge
1.18
152         q = buildtree(UMULqNIL);
ragge
1.56
153         p = block(REGNILNILPTR+STRTY0cftnsp->sap);
ragge
1.18
154         p = buildtree(UMULpNIL);
155         p = buildtree(ASSIGNqp);
156         ecomp(p);
ragge
1.55
157
158         /* put hidden arg in eax on return */
ragge
1.75
159         q = tempnode(structrettempINT00);
ragge
1.60
160         p = block(REGNILNILINT00);
ragge
1.55
161         regno(p) = EAX;
162         ecomp(buildtree(ASSIGNpq));
ragge
1.1
163 }
164
ragge
1.78
165 static TWORD longregs[] = { EAXEDXEDXECX };
ragge
1.75
166 static TWORD regpregs[] = { EAXEDXECX };
ragge
1.78
167 static TWORD charregs[] = { ALDLCL };
ragge
1.75
168
ragge
1.1
169 /*
170  * code for the beginning of a function; a is an array of
ragge
1.2
171  * indices in symtab for the arguments; n is the number
ragge
1.75
172  *
173  * Classifying args on i386; not simple:
174  * - Args may be on stack or in registers (regparm)
175  * - There may be a hidden first arg, unless OpenBSD struct return.
176  * - Regparm syntax is not well documented.
177  * - There may be stdcall functions, where the called function pops stack
178  * - ...probably more
ragge
1.1
179  */
180 void
ragge
1.17
181 bfcode(struct symtab **spint cnt)
ragge
1.1
182 {
gmcgarry
1.30
183         extern int argstacksize;
ragge
1.72
184 #ifdef GCC_COMPAT
ragge
1.71
185         struct attr *ap;
ragge
1.72
186 #endif
ragge
1.29
187         struct symtab *sp2;
ragge
1.17
188         extern int gotnr;
189         NODE *n, *p;
ragge
1.71
190         int iregparmarg;
ragge
1.75
191         int argbasenrargsz;
192
193         /* Take care of PIC stuff first */
194         if (kflag) {
195 #define STL     200
196                 char *str = inlalloc(STL);
197 #if !defined(MACHOABI)
198                 int l = getlab();
199 #else
200                 char *name;
201 #endif
202
203                 /* Generate extended assembler for PIC prolog */
204                 p = tempnode(0INT00);
205                 gotnr = regno(p);
206                 p = block(XARGpNILINT00);
207                 p->n_name = "=g";
208                 p = block(XASMpbcon(0), INT00);
209
210 #if defined(MACHOABI)
211                 if ((name = cftnsp->soname) == NULL)
212                         name = cftnsp->sname;
213                 if (snprintf(strSTL"call L%s$pb\nL%s$pb:\n\tpopl %%0\n",
214                     namename) >= STL)
215                         cerror("bfcode");
216 #else
217                 if (snprintf(strSTL,
plunky
1.76
218                     "call " LABFMT "\n" LABFMT ":\n\tpopl %%0\n"
219                     "\taddl $_GLOBAL_OFFSET_TABLE_+[.-" LABFMT "], %%0\n",
ragge
1.75
220                     lll) >= STL)
221                         cerror("bfcode");
222 #endif
223                 p->n_name = str;
224                 p->n_right->n_type = STRTY;
225                 ecomp(p);
226         }
227
228         argbase = ARGINIT;
229         nrarg = regparmarg = 0;
ragge
1.4
230
ragge
1.75
231 #ifdef GCC_COMPAT
232         if (attr_find(cftnsp->sapGCC_ATYP_STDCALL) != NULL)
233                 cftnsp->sflags |= SSTDCALL;
234         if ((ap = attr_find(cftnsp->sapGCC_ATYP_REGPARM)))
235                 regparmarg = ap->iarg(0);
236 #endif
237
238         /* Function returns struct, create return arg node */
ragge
1.17
239         if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) {
ragge
1.48
240 #if defined(os_openbsd)
241                 /* OpenBSD uses non-standard return for small structs */
ragge
1.56
242                 int sz = tsize(BTYPE(cftnsp->stype), cftnsp->sdfcftnsp->sap);
ragge
1.75
243                 if (sz <= SZLONGLONG)
ragge
1.48
244 #endif
ragge
1.75
245                 {
246                         if (regparmarg) {
247                                 n = block(REG00INT00);
248                                 regno(n) = regpregs[nrarg++];
249                         } else {
250                                 n = block(OREG00INT00);
ragge
1.77
251                                 n->n_lval = argbase/SZCHAR;
ragge
1.75
252                                 argbase += SZINT;
253                                 regno(n) = FPREG;
254                         }
255                         p = tempnode(0INT00);
256                         structrettemp = regno(p);
257                         p = buildtree(ASSIGNpn);
258                         ecomp(p);
259                 }
ragge
1.17
260         }
gmcgarry
1.30
261
262         /*
ragge
1.75
263          * Find where all params are so that they end up at the right place.
264          * At the same time recalculate their arg offset on stack.
265          * We also get the "pop size" for stdcall.
gmcgarry
1.30
266          */
ragge
1.75
267         for (i = 0i < cnti++) {
268                 sp2 = sp[i];
269                 sz = tsize(sp2->stypesp2->sdfsp2->sap);
ragge
1.52
270
ragge
1.75
271                 SETOFF(szSZINT);
ragge
1.52
272
ragge
1.75
273                 if (cisreg(sp2->stype) == 0 ||
274                     ((regparmarg - nrarg) * SZINT < sz)) {      /* not in reg */
275                         sp2->soffset = argbase;
276                         argbase += sz;
277                         nrarg = regparmarg;     /* no more in reg either */
278                 } else {                                        /* in reg */
279                         sp2->soffset = nrarg;
280                         nrarg += sz/SZINT;
281                         sp2->sclass = REGISTER;
gmcgarry
1.30
282                 }
283         }
284
ragge
1.75
285         /*
286          * Now (argbase - ARGINIT) is used space on stack.
287          * Move (if necessary) the args to something new.
288          */
289         for (i = 0i < cnti++) {
290                 int regj;
ragge
1.34
291
ragge
1.75
292                 sp2 = sp[i];
gmcgarry
1.44
293
ragge
1.75
294                 if (ISSOU(sp2->stype) && sp2->sclass == REGISTER) {
295                         /* must move to stack */
296                         sz = tsize(sp2->stypesp2->sdfsp2->sap);
297                         SETOFF(szSZINT);
298                         SETOFF(autooffSZINT);
299                         reg = sp2->soffset;
300                         sp2->sclass = AUTO;
301                         sp2->soffset = NOOFFSET;
302                         oalloc(sp2, &autooff);
303                         for (j = 0j < sz/SZCHARj += 4) {
304                                 p = block(OREG00INT00);
305                                 p->n_lval = sp2->soffset/SZCHAR + j;
306                                 regno(p) = FPREG;
307                                 n = block(REG00INT00);
308                                 regno(n) = regpregs[reg++];
309                                 p = block(ASSIGNpnINT00);
310                                 ecomp(p);
311                         }
312                 } else if (cisreg(sp2->stype) && !ISSOU(sp2->stype) &&
313                     ((cqual(sp2->stypesp2->squal) & VOL) == 0)) {
314                         /* just put rest in temps */
315                         if (sp2->sclass == REGISTER) {
316                                 n = block(REG00sp2->stype,
317                                     sp2->sdfsp2->sap);
318                                 if (ISLONGLONG(sp2->stype))
319                                         regno(n) = longregs[sp2->soffset];
plunky
1.79
320                                 else if (DEUNSIGN(sp2->stype) == CHAR || sp2->stype == BOOL)
ragge
1.78
321                                         regno(n) = charregs[sp2->soffset];
ragge
1.75
322                                 else
323                                         regno(n) = regpregs[sp2->soffset];
324                         } else {
325                                 n = block(OREG00sp2->stype,
326                                     sp2->sdfsp2->sap);
327                                 n->n_lval = sp2->soffset/SZCHAR;
328                                 regno(n) = FPREG;
329                         }
330                         p = tempnode(0sp2->stypesp2->sdfsp2->sap);
331                         sp2->soffset = regno(p);
332                         sp2->sflags |= STNODE;
333                         n = buildtree(ASSIGNpn);
334                         ecomp(n);
335                 }
ragge
1.17
336         }
ragge
1.75
337
338         argstacksize = 0;
339         if (cftnsp->sflags & SSTDCALL) {
340                 argstacksize = (argbase - ARGINIT)/SZCHAR;
341 #ifdef os_win32
342
343                 char buf[256];
344                 char *name;
345                 /*
346                  * mangle name in symbol table as a callee.
347                  */
348                 if ((name = cftnsp->soname) == NULL)
349                         name = exname(cftnsp->sname);
350                 snprintf(buf256"%s@%d"nameargstacksize);
351                 cftnsp->soname = addname(buf);
ragge
1.72
352 #endif
ragge
1.75
353         }
ragge
1.17
354
ragge
1.1
355 }
356
gmcgarry
1.28
357 #if defined(MACHOABI)
358 struct stub stublist;
359 struct stub nlplist;
360 #endif
361
ragge
1.1
362 /* called just before final exit */
363 /* flag is 1 if errors, 0 if none */
364 void
plunky
1.68
365 ejobcode(int flag)
ragge
1.1
366 {
gmcgarry
1.28
367 #if defined(MACHOABI)
368         /*
369          * iterate over the stublist and output the PIC stubs
370 `        */
371         if (kflag) {
372                 struct stub *p;
373
374                 DLIST_FOREACH(p, &stublistlink) {
375                         printf("\t.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5\n");
376                         printf("L%s$stub:\n"p->name);
pantzer
1.42
377                         printf("\t.indirect_symbol %s\n"p->name);
gmcgarry
1.28
378                         printf("\thlt ; hlt ; hlt ; hlt ; hlt\n");
379                         printf("\t.subsections_via_symbols\n");
380                 }
381
382                 printf("\t.section __IMPORT,__pointers,non_lazy_symbol_pointers\n");
383                 DLIST_FOREACH(p, &nlplistlink) {
384                         printf("L%s$non_lazy_ptr:\n"p->name);
pantzer
1.42
385                         printf("\t.indirect_symbol %s\n"p->name);
gmcgarry
1.28
386                         printf("\t.long 0\n");
387                 }
388
389         }
390 #endif
391
plunky
1.62
392         printf("\t.ident \"PCC: %s\"\n"VERSSTR);
ragge
1.1
393 }
394
pj
1.8
395 void
plunky
1.68
396 bjobcode(void)
pj
1.8
397 {
ragge
1.64
398 #ifdef os_sunos
399         astypnames[SHORT] = astypnames[USHORT] = "\t.2byte";
400 #endif
401         astypnames[INT] = astypnames[UNSIGNED] = "\t.long";
gmcgarry
1.28
402 #if defined(MACHOABI)
403         DLIST_INIT(&stublistlink);
404         DLIST_INIT(&nlplistlink);
405 #endif
pj
1.8
406 }
407
ragge
1.1
408 /*
ragge
1.73
409  * Convert FUNARG to assign in case of regparm.
410  */
411 static int regcvtrparg;
412 static void
413 addreg(NODE *p)
414 {
ragge
1.77
415         TWORD t;
416         NODE *q;
417         int szr;
418
419         sz = tsize(p->n_typep->n_dfp->n_ap)/SZCHAR;
420         sz = (sz + 3) >> 2;     /* sz in regs */
421         if ((regcvt+sz) > rparg) {
422                 regcvt = rparg;
ragge
1.73
423                 return;
ragge
1.74
424         }
ragge
1.77
425         if (sz > 2)
426                 uerror("cannot put struct in 3 regs (yet)");
427
428         if (sz == 2)
429                 r = regcvt == 0 ? EAXEDX : EDXECX;
430         else
431                 r = regcvt == 0 ? EAX : regcvt == 1 ? EDX : ECX;
432
433         if (p->n_op == FUNARG) {
434                 /* at most 2 regs */
435                 if (p->n_type < INT) {
436                         p->n_left = ccast(p->n_leftINT000);
437                         p->n_type = INT;
438                 }
439
440                 p->n_op = ASSIGN;
441                 p->n_right = p->n_left;
442         } else if (p->n_op == STARG) {
443                 /* convert to ptr, put in reg */
444                 q = p->n_left;
445                 t = sz == 2 ? LONGLONG : INT;
446                 q = cast(qINCREF(t), 0);
447                 q = buildtree(UMULqNIL);
448                 p->n_op = ASSIGN;
449                 p->n_type = t;
450                 p->n_right = q;
451         } else
452                 cerror("addreg");
ragge
1.73
453         p->n_left = block(REG00p->n_type00);
ragge
1.77
454         regno(p->n_left) = r;
455         regcvt += sz;
ragge
1.73
456 }
457
458 /*
ragge
1.17
459  * Called with a function call with arguments as argument.
460  * This is done early in buildtree() and only done once.
461  * Returns p.
462  */
463 NODE *
464 funcode(NODE *p)
465 {
466         extern int gotnr;
ragge
1.72
467 #ifdef GCC_COMPAT
ragge
1.71
468         struct attr *ap;
ragge
1.72
469 #endif
ragge
1.17
470         NODE *r, *l;
ragge
1.77
471         TWORD t = DECREF(DECREF(p->n_left->n_type));
472         int stcall;
473
474         stcall = ISSOU(t);
475         /*
476          * We may have to prepend:
477          * - Hidden arg0 for struct return (in reg or on stack).
478          * - ebx in case of PIC code.
479          */
ragge
1.17
480
481         /* Fix function call arguments. On x86, just add funarg */
482         for (r = p->n_rightr->n_op == CMr = r->n_left) {
483                 if (r->n_right->n_op != STARG)
484                         r->n_right = block(FUNARGr->n_rightNIL,
485                             r->n_right->n_typer->n_right->n_df,
ragge
1.56
486                             r->n_right->n_ap);
ragge
1.17
487         }
488         if (r->n_op != STARG) {
489                 l = talloc();
490                 *l = *r;
491                 r->n_op = FUNARG;
492                 r->n_left = l;
493                 r->n_type = l->n_type;
494         }
ragge
1.77
495         if (stcall) {
496                 /* Prepend a placeholder for struct address. */
497                 /* Use EBP, can never show up under normal circumstances */
498                 l = talloc();
499                 *l = *r;
500                 r->n_op = CM;
501                 r->n_right = l;
502                 r->n_type = INT;
503                 l = block(REG00INCREF(VOID), 00);
504                 regno(l) = EBP;
505                 l = block(FUNARGl0INCREF(VOID), 00);
506                 r->n_left = l;
507         }
ragge
1.71
508
ragge
1.72
509 #ifdef GCC_COMPAT
ragge
1.71
510         if ((ap = attr_find(p->n_left->n_apGCC_ATYP_REGPARM)))
ragge
1.73
511                 rparg = ap->iarg(0);
ragge
1.71
512         else
ragge
1.72
513 #endif
ragge
1.73
514                 rparg = 0;
515
516         regcvt = 0;
517         if (rparg)
518                 listf(p->n_rightaddreg);
ragge
1.71
519
ragge
1.17
520         if (kflag == 0)
521                 return p;
ragge
1.77
522
gmcgarry
1.28
523 #if defined(ELFABI)
ragge
1.17
524         /* Create an ASSIGN node for ebx */
ragge
1.60
525         l = block(REGNILNILINT00);
ragge
1.17
526         l->n_rval = EBX;
ragge
1.60
527         l = buildtree(ASSIGNltempnode(gotnrINT00));
ragge
1.17
528         if (p->n_right->n_op != CM) {
ragge
1.60
529                 p->n_right = block(CMlp->n_rightINT00);
ragge
1.17
530         } else {
531                 for (r = p->n_rightr->n_left->n_op == CMr = r->n_left)
532                         ;
ragge
1.60
533                 r->n_left = block(CMlr->n_leftINT00);
ragge
1.17
534         }
gmcgarry
1.28
535 #endif
ragge
1.17
536         return p;
537 }
538
ragge
1.1
539 /* fix up type of field p */
540 void
541 fldty(struct symtab *p)
542 {
543 }
544
stefan
1.19
545 /*
ragge
1.1
546  * XXX - fix genswitch.
547  */
stefan
1.19
548 int
549 mygenswitch(int numTWORD typestruct swents **pint n)
ragge
1.1
550 {
stefan
1.19
551         return 0;
ragge
1.1
552 }
ragge
1.69
553
554 NODE *  
555 builtin_return_address(const struct bitable *btNODE *a)
556 {       
557         int nframes;
558         NODE *f
559         
560         if (a->n_op != ICON)
561                 goto bad;
562
563         nframes = (int)a->n_lval;
564   
565         tfree(a);       
566                         
567         f = block(REGNILNILPTR+VOID00);
568         regno(f) = FPREG;
569  
570         while (nframes--)
571                 f = block(UMULfNILPTR+VOID00);
572                                     
573         f = block(PLUSfbcon(4), INCREF(PTR+VOID), 00);
574         f = buildtree(UMULfNIL);    
575    
576         return f;
577 bad:                                            
578         uerror("bad argument to __builtin_return_address");
579         return bcon(0);
580 }
581
582 NODE *
583 builtin_frame_address(const struct bitable *btNODE *a)
584 {
585         int nframes;
586         NODE *f;
587
588         if (a->n_op != ICON)
589                 goto bad;
590
591         nframes = (int)a->n_lval;
592
593         tfree(a);
594
595         f = block(REGNILNILPTR+VOID00);
596         regno(f) = FPREG;
597
598         while (nframes--)
599                 f = block(UMULfNILPTR+VOID00);
600
601         return f;
602 bad:
603         uerror("bad argument to __builtin_frame_address");
604         return bcon(0);
605 }
606
607 /*
608  * Return "canonical frame address".
609  */
610 NODE *
611 builtin_cfa(const struct bitable *btNODE *a)
612 {
613         uerror("missing builtin_cfa");
614         return bcon(0);
615 }
616
FishEye: Open Source License registered to PCC.
Your maintenance has expired. You can renew your license at http://www.atlassian.com/fisheye/renew
Atlassian FishEye, CVS analysis. (Version:1.6.3 Build:build-336 2008-11-04) - Administration - Page generated 2014-10-01 18:22 +0200