Quick Search:

View

Revision:
Expand:  
Changeset: MAIN:ragge:20140524151953

Diff

Diff from 1.77 to:

Annotations

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

Annotated File View

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