1 /* $Id: code.c,v 1.56.2.1 2011/03/01 17:33:24 ragge Exp $ */
3 * Copyright (c) 2003 Anders Magnusson (ragge@ludd.luth.se).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
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.
35 * Define everything needed to print out some data (or text).
36 * This means segment, alignment, visibility, etc.
39 defloc(struct symtab
*sp
)
41 extern char *nextsect
;
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" };
58 s
= ISFTN(t
) ? PROG
: ISCON(cqual(t
, sp
->squal
)) ? RDATA
: DATA
;
59 if ((name
= sp
->soname
) == NULL
)
60 name
= exname(sp
->sname
);
62 if (sp
->sflags
& STLS
) {
64 cerror("non-data symbol in tls section");
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
)
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
);
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
);
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
);
90 if (kflag
&& !ISFTN(t
)) {
91 /* Must place aggregates with pointers in relocatable memory */
97 /* put in reloc memory */
98 printf("\t.section .data.rel.local,\"aw\",@progbits\n");
104 printf(" .section %s,\"wa\",@progbits\n", nextsect
);
107 } else if (s
!= lastloc
)
108 printf(" .%s\n", loctbl
[s
]);
112 al
= ISFTN(t
) ? ALINT
: talign(t
, sp
->sap
);
114 printf(" .align %d\n", al
/ALCHAR
);
116 printf(" .weak %s\n", name
);
117 else if (sp
->sclass
== EXTDEF
) {
118 printf(" .globl %s\n", name
);
120 printf("\t.type %s,@%s\n", name
,
121 ISFTN(t
)? "function" : "object");
127 printf("\t.size %s,%d\n", name
,
128 (int)tsize(t
, sp
->sdf
, sp
->sap
)/SZCHAR
);
130 printf("\t.size " LABFMT
",%d\n", sp
->soffset
,
131 (int)tsize(t
, sp
->sdf
, sp
->sap
)/SZCHAR
);
135 printf("%s:\n", name
);
137 printf(LABFMT
":\n", sp
->soffset
);
141 * code for the end of a function
142 * deals with struct return here
150 gotnr
= 0; /* new number for next fun */
151 if (cftnsp
->stype
!= STRTY
+FTN
&& cftnsp
->stype
!= UNIONTY
+FTN
)
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
));
161 p
= block(REG
, NIL
, NIL
, INT
, 0, MKAP(INT
));
163 ecomp(buildtree(ASSIGN
, p
, q
));
165 if (sz
< SZSHORT
) sz
= CHAR
;
166 else if (sz
> SZSHORT
) sz
= INT
;
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
));
174 /* Create struct assignment */
175 q
= block(OREG
, NIL
, NIL
, PTR
+STRTY
, 0, cftnsp
->sap
);
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
);
184 /* put hidden arg in eax on return */
185 q
= block(OREG
, NIL
, NIL
, INT
, 0, MKAP(INT
));
188 p
= block(REG
, NIL
, NIL
, INT
, 0, MKAP(INT
));
190 ecomp(buildtree(ASSIGN
, p
, q
));
194 * code for the beginning of a function; a is an array of
195 * indices in symtab for the arguments; n is the number
198 bfcode(struct symtab
**sp
, int cnt
)
200 extern int argstacksize
;
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
)
214 for (i
= 0; i
< cnt
; i
++)
215 sp
[i
]->soffset
+= SZPOINT(INT
);
219 if (attr_find(cftnsp
->sap
, GCC_ATYP_STDCALL
) != NULL
)
220 cftnsp
->sflags
|= SSTDCALL
;
224 * Count the arguments
227 if (cftnsp
->sflags
& SSTDCALL
) {
234 for (i
= 0; i
< cnt
; i
++) {
235 TWORD t
= sp
[i
]->stype
;
236 if (t
== STRTY
|| t
== UNIONTY
)
238 tsize(t
, sp
[i
]->sdf
, sp
[i
]->sap
);
240 argstacksize
+= szty(t
) * SZINT
/ SZCHAR
;
244 * mangle name in symbol table as a callee.
246 if ((name
= cftnsp
->soname
) == NULL
)
247 name
= exname(cftnsp
->sname
);
248 snprintf(buf
, 256, "%s@%d", name
, argstacksize
);
249 cftnsp
->soname
= addname(buf
);
255 char *str
= inlalloc(STL
);
256 #if !defined(MACHOABI)
262 /* Generate extended assembler for PIC prolog */
263 p
= tempnode(0, INT
, 0, MKAP(INT
));
265 p
= block(XARG
, p
, NIL
, INT
, 0, MKAP(INT
));
267 p
= block(XASM
, p
, bcon(0), INT
, 0, MKAP(INT
));
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",
276 if (snprintf(str
, STL
,
277 "call " LABFMT
"\n" LABFMT
":\n popl %%0\n"
278 " addl $_GLOBAL_OFFSET_TABLE_+[.-" LABFMT
"], %%0\n",
283 p
->n_right
->n_type
= STRTY
;
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)
294 if (cqual(sp
[i
]->stype
, sp
[i
]->squal
) & VOL
)
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
;
307 * by now, the automatics and register variables are allocated
312 SETOFF(autooff
, SZINT
);
315 #if defined(MACHOABI)
316 struct stub stublist
;
320 /* called just before final exit */
321 /* flag is 1 if errors, 0 if none */
325 #if defined(MACHOABI)
327 * iterate over the stublist and output the PIC stubs
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");
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");
351 #define MKSTR(x) _MKSTR(x)
352 #define OS MKSTR(TARGOS)
353 printf("\t.ident \"PCC: %s (%s)\"\n", PACKAGE_STRING
, OS
);
359 #if defined(MACHOABI)
360 DLIST_INIT(&stublist
, link
);
361 DLIST_INIT(&nlplist
, link
);
366 * Called with a function call with arguments as argument.
367 * This is done early in buildtree() and only done once.
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
,
383 if (r
->n_op
!= STARG
) {
388 r
->n_type
= l
->n_type
;
393 /* Create an ASSIGN node for ebx */
394 l
= block(REG
, NIL
, NIL
, INT
, 0, MKAP(INT
));
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
));
400 for (r
= p
->n_right
; r
->n_left
->n_op
== CM
; r
= r
->n_left
)
402 r
->n_left
= block(CM
, l
, r
->n_left
, INT
, 0, MKAP(INT
));
409 * return the alignment of field of type t
412 fldal(unsigned int t
)
414 uerror("illegal field type");
418 /* fix up type of field p */
420 fldty(struct symtab
*p
)
425 * XXX - fix genswitch.
428 mygenswitch(int num
, TWORD type
, struct swents
**p
, int n
)