source: mainline/uspace/app/pcc/arch/i386/code.c@ a44424f

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a44424f was a7de7182, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 14 years ago

Added pcc source tree (contents of pcc-1.0.0.tgz)

  • Property mode set to 100644
File size: 10.6 KB
Line 
1/* $Id: code.c,v 1.56.2.1 2011/03/01 17:33:24 ragge Exp $ */
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
32int lastloc = -1;
33
34/*
35 * Define everything needed to print out some data (or text).
36 * This means segment, alignment, visibility, etc.
37 */
38void
39defloc(struct symtab *sp)
40{
41 extern char *nextsect;
42 struct attr *ap;
43 int weak = 0;
44 char *name = NULL;
45#if defined(ELFABI) || defined(PECOFFABI)
46 static char *loctbl[] = { "text", "data", "section .rodata" };
47#elif defined(MACHOABI)
48 static char *loctbl[] = { "text", "data", "const_data" };
49#endif
50 TWORD t;
51 int s, al;
52
53 if (sp == NULL) {
54 lastloc = -1;
55 return;
56 }
57 t = sp->stype;
58 s = ISFTN(t) ? PROG : ISCON(cqual(t, sp->squal)) ? RDATA : DATA;
59 if ((name = sp->soname) == NULL)
60 name = exname(sp->sname);
61#ifdef TLS
62 if (sp->sflags & STLS) {
63 if (s != DATA)
64 cerror("non-data symbol in tls section");
65 nextsect = ".tdata";
66 }
67#endif
68#ifdef GCC_COMPAT
69 {
70 if ((ap = attr_find(sp->sap, GCC_ATYP_SECTION)) != NULL)
71 nextsect = ap->sarg(0);
72 if (attr_find(sp->sap, GCC_ATYP_WEAK) != NULL)
73 weak = 1;
74 if (attr_find(sp->sap, GCC_ATYP_DESTRUCTOR)) {
75 printf("\t.section\t.dtors,\"aw\",@progbits\n");
76 printf("\t.align 4\n\t.long\t%s\n", name);
77 lastloc = -1;
78 }
79 if (attr_find(sp->sap, GCC_ATYP_CONSTRUCTOR)) {
80 printf("\t.section\t.ctors,\"aw\",@progbits\n");
81 printf("\t.align 4\n\t.long\t%s\n", name);
82 lastloc = -1;
83 }
84 if ((ap = attr_find(sp->sap, GCC_ATYP_VISIBILITY)) &&
85 strcmp(ap->sarg(0), "default"))
86 printf("\t.%s %s\n", ap->sarg(0), name);
87 }
88#endif
89#ifdef ELFABI
90 if (kflag && !ISFTN(t)) {
91 /* Must place aggregates with pointers in relocatable memory */
92 TWORD t2 = t;
93
94 while (ISARY(t2))
95 t2 = DECREF(t2);
96 if (t2 > LDOUBLE) {
97 /* put in reloc memory */
98 printf("\t.section .data.rel.local,\"aw\",@progbits\n");
99 s = lastloc = -1;
100 }
101 }
102#endif
103 if (nextsect) {
104 printf(" .section %s,\"wa\",@progbits\n", nextsect);
105 nextsect = NULL;
106 s = -1;
107 } else if (s != lastloc)
108 printf(" .%s\n", loctbl[s]);
109 lastloc = s;
110 while (ISARY(t))
111 t = DECREF(t);
112 al = ISFTN(t) ? ALINT : talign(t, sp->sap);
113 if (al > ALCHAR)
114 printf(" .align %d\n", al/ALCHAR);
115 if (weak)
116 printf(" .weak %s\n", name);
117 else if (sp->sclass == EXTDEF) {
118 printf(" .globl %s\n", name);
119#if defined(ELFABI)
120 printf("\t.type %s,@%s\n", name,
121 ISFTN(t)? "function" : "object");
122#endif
123 }
124#if defined(ELFABI)
125 if (!ISFTN(t)) {
126 if (sp->slevel == 0)
127 printf("\t.size %s,%d\n", name,
128 (int)tsize(t, sp->sdf, sp->sap)/SZCHAR);
129 else
130 printf("\t.size " LABFMT ",%d\n", sp->soffset,
131 (int)tsize(t, sp->sdf, sp->sap)/SZCHAR);
132 }
133#endif
134 if (sp->slevel == 0)
135 printf("%s:\n", name);
136 else
137 printf(LABFMT ":\n", sp->soffset);
138}
139
140/*
141 * code for the end of a function
142 * deals with struct return here
143 */
144void
145efcode()
146{
147 extern int gotnr;
148 NODE *p, *q;
149
150 gotnr = 0; /* new number for next fun */
151 if (cftnsp->stype != STRTY+FTN && cftnsp->stype != UNIONTY+FTN)
152 return;
153#if defined(os_openbsd)
154 /* struct return for small structs */
155 int sz = tsize(BTYPE(cftnsp->stype), cftnsp->sdf, cftnsp->sap);
156 if (sz == SZCHAR || sz == SZSHORT || sz == SZINT || sz == SZLONGLONG) {
157 /* Pointer to struct in eax */
158 if (sz == SZLONGLONG) {
159 q = block(OREG, NIL, NIL, INT, 0, MKAP(INT));
160 q->n_lval = 4;
161 p = block(REG, NIL, NIL, INT, 0, MKAP(INT));
162 p->n_rval = EDX;
163 ecomp(buildtree(ASSIGN, p, q));
164 }
165 if (sz < SZSHORT) sz = CHAR;
166 else if (sz > SZSHORT) sz = INT;
167 else sz = SHORT;
168 q = block(OREG, NIL, NIL, sz, 0, MKAP(sz));
169 p = block(REG, NIL, NIL, sz, 0, MKAP(sz));
170 ecomp(buildtree(ASSIGN, p, q));
171 return;
172 }
173#endif
174 /* Create struct assignment */
175 q = block(OREG, NIL, NIL, PTR+STRTY, 0, cftnsp->sap);
176 q->n_rval = EBP;
177 q->n_lval = 8; /* return buffer offset */
178 q = buildtree(UMUL, q, NIL);
179 p = block(REG, NIL, NIL, PTR+STRTY, 0, cftnsp->sap);
180 p = buildtree(UMUL, p, NIL);
181 p = buildtree(ASSIGN, q, p);
182 ecomp(p);
183
184 /* put hidden arg in eax on return */
185 q = block(OREG, NIL, NIL, INT, 0, MKAP(INT));
186 regno(q) = FPREG;
187 q->n_lval = 8;
188 p = block(REG, NIL, NIL, INT, 0, MKAP(INT));
189 regno(p) = EAX;
190 ecomp(buildtree(ASSIGN, p, q));
191}
192
193/*
194 * code for the beginning of a function; a is an array of
195 * indices in symtab for the arguments; n is the number
196 */
197void
198bfcode(struct symtab **sp, int cnt)
199{
200 extern int argstacksize;
201 struct symtab *sp2;
202 extern int gotnr;
203 NODE *n, *p;
204 int i;
205
206 if (cftnsp->stype == STRTY+FTN || cftnsp->stype == UNIONTY+FTN) {
207 /* Function returns struct, adjust arg offset */
208#if defined(os_openbsd)
209 /* OpenBSD uses non-standard return for small structs */
210 int sz = tsize(BTYPE(cftnsp->stype), cftnsp->sdf, cftnsp->sap);
211 if (sz != SZCHAR && sz != SZSHORT &&
212 sz != SZINT && sz != SZLONGLONG)
213#endif
214 for (i = 0; i < cnt; i++)
215 sp[i]->soffset += SZPOINT(INT);
216 }
217
218#ifdef GCC_COMPAT
219 if (attr_find(cftnsp->sap, GCC_ATYP_STDCALL) != NULL)
220 cftnsp->sflags |= SSTDCALL;
221#endif
222
223 /*
224 * Count the arguments
225 */
226 argstacksize = 0;
227 if (cftnsp->sflags & SSTDCALL) {
228#ifdef os_win32
229
230 char buf[256];
231 char *name;
232#endif
233
234 for (i = 0; i < cnt; i++) {
235 TWORD t = sp[i]->stype;
236 if (t == STRTY || t == UNIONTY)
237 argstacksize +=
238 tsize(t, sp[i]->sdf, sp[i]->sap);
239 else
240 argstacksize += szty(t) * SZINT / SZCHAR;
241 }
242#ifdef os_win32
243 /*
244 * mangle name in symbol table as a callee.
245 */
246 if ((name = cftnsp->soname) == NULL)
247 name = exname(cftnsp->sname);
248 snprintf(buf, 256, "%s@%d", name, argstacksize);
249 cftnsp->soname = addname(buf);
250#endif
251 }
252
253 if (kflag) {
254#define STL 200
255 char *str = inlalloc(STL);
256#if !defined(MACHOABI)
257 int l = getlab();
258#else
259 char *name;
260#endif
261
262 /* Generate extended assembler for PIC prolog */
263 p = tempnode(0, INT, 0, MKAP(INT));
264 gotnr = regno(p);
265 p = block(XARG, p, NIL, INT, 0, MKAP(INT));
266 p->n_name = "=g";
267 p = block(XASM, p, bcon(0), INT, 0, MKAP(INT));
268
269#if defined(MACHOABI)
270 if ((name = cftnsp->soname) == NULL)
271 name = cftnsp->sname;
272 if (snprintf(str, STL, "call L%s$pb\nL%s$pb:\n\tpopl %%0\n",
273 name, name) >= STL)
274 cerror("bfcode");
275#else
276 if (snprintf(str, STL,
277 "call " LABFMT "\n" LABFMT ":\n popl %%0\n"
278 " addl $_GLOBAL_OFFSET_TABLE_+[.-" LABFMT "], %%0\n",
279 l, l, l) >= STL)
280 cerror("bfcode");
281#endif
282 p->n_name = str;
283 p->n_right->n_type = STRTY;
284 ecomp(p);
285 }
286 if (xtemps == 0)
287 return;
288
289 /* put arguments in temporaries */
290 for (i = 0; i < cnt; i++) {
291 if (sp[i]->stype == STRTY || sp[i]->stype == UNIONTY ||
292 cisreg(sp[i]->stype) == 0)
293 continue;
294 if (cqual(sp[i]->stype, sp[i]->squal) & VOL)
295 continue;
296 sp2 = sp[i];
297 n = tempnode(0, sp[i]->stype, sp[i]->sdf, sp[i]->sap);
298 n = buildtree(ASSIGN, n, nametree(sp2));
299 sp[i]->soffset = regno(n->n_left);
300 sp[i]->sflags |= STNODE;
301 ecomp(n);
302 }
303}
304
305
306/*
307 * by now, the automatics and register variables are allocated
308 */
309void
310bccode()
311{
312 SETOFF(autooff, SZINT);
313}
314
315#if defined(MACHOABI)
316struct stub stublist;
317struct stub nlplist;
318#endif
319
320/* called just before final exit */
321/* flag is 1 if errors, 0 if none */
322void
323ejobcode(int flag )
324{
325#if defined(MACHOABI)
326 /*
327 * iterate over the stublist and output the PIC stubs
328` */
329 if (kflag) {
330 struct stub *p;
331
332 DLIST_FOREACH(p, &stublist, link) {
333 printf("\t.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5\n");
334 printf("L%s$stub:\n", p->name);
335 printf("\t.indirect_symbol %s\n", p->name);
336 printf("\thlt ; hlt ; hlt ; hlt ; hlt\n");
337 printf("\t.subsections_via_symbols\n");
338 }
339
340 printf("\t.section __IMPORT,__pointers,non_lazy_symbol_pointers\n");
341 DLIST_FOREACH(p, &nlplist, link) {
342 printf("L%s$non_lazy_ptr:\n", p->name);
343 printf("\t.indirect_symbol %s\n", p->name);
344 printf("\t.long 0\n");
345 }
346
347 }
348#endif
349
350#define _MKSTR(x) #x
351#define MKSTR(x) _MKSTR(x)
352#define OS MKSTR(TARGOS)
353 printf("\t.ident \"PCC: %s (%s)\"\n", PACKAGE_STRING, OS);
354}
355
356void
357bjobcode()
358{
359#if defined(MACHOABI)
360 DLIST_INIT(&stublist, link);
361 DLIST_INIT(&nlplist, link);
362#endif
363}
364
365/*
366 * Called with a function call with arguments as argument.
367 * This is done early in buildtree() and only done once.
368 * Returns p.
369 */
370NODE *
371funcode(NODE *p)
372{
373 extern int gotnr;
374 NODE *r, *l;
375
376 /* Fix function call arguments. On x86, just add funarg */
377 for (r = p->n_right; r->n_op == CM; r = r->n_left) {
378 if (r->n_right->n_op != STARG)
379 r->n_right = block(FUNARG, r->n_right, NIL,
380 r->n_right->n_type, r->n_right->n_df,
381 r->n_right->n_ap);
382 }
383 if (r->n_op != STARG) {
384 l = talloc();
385 *l = *r;
386 r->n_op = FUNARG;
387 r->n_left = l;
388 r->n_type = l->n_type;
389 }
390 if (kflag == 0)
391 return p;
392#if defined(ELFABI)
393 /* Create an ASSIGN node for ebx */
394 l = block(REG, NIL, NIL, INT, 0, MKAP(INT));
395 l->n_rval = EBX;
396 l = buildtree(ASSIGN, l, tempnode(gotnr, INT, 0, MKAP(INT)));
397 if (p->n_right->n_op != CM) {
398 p->n_right = block(CM, l, p->n_right, INT, 0, MKAP(INT));
399 } else {
400 for (r = p->n_right; r->n_left->n_op == CM; r = r->n_left)
401 ;
402 r->n_left = block(CM, l, r->n_left, INT, 0, MKAP(INT));
403 }
404#endif
405 return p;
406}
407
408/*
409 * return the alignment of field of type t
410 */
411int
412fldal(unsigned int t)
413{
414 uerror("illegal field type");
415 return(ALINT);
416}
417
418/* fix up type of field p */
419void
420fldty(struct symtab *p)
421{
422}
423
424/*
425 * XXX - fix genswitch.
426 */
427int
428mygenswitch(int num, TWORD type, struct swents **p, int n)
429{
430 return 0;
431}
Note: See TracBrowser for help on using the repository browser.