Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:gmcgarry:20140604071802

Diff

Diff from 1.80 to:

Annotations

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

Annotated File View

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