1 /* $Id: local.c,v 1.130.2.3 2011/03/30 16:35:36 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.
32 /* this file contains code which is dependent on the target machine */
36 * Check if a constant is too large for a type.
39 toolarge(TWORD t
, CONSZ con
)
46 break; /* cannot be too large */
47 #define SCHK(i) case i: if (con > MAX_##i || con < MIN_##i) return 1; break
48 #define UCHK(i) case i: if (ucon > MAX_##i) return 1; break
66 * Keep track of PIC stubs.
70 addstub(struct stub
*list
, char *name
)
74 DLIST_FOREACH(s
, list
, link
) {
75 if (strcmp(s
->name
, name
) == 0)
79 s
= permalloc(sizeof(struct stub
));
80 s
->name
= permalloc(strlen(name
) + 1);
81 strcpy(s
->name
, name
);
82 DLIST_INSERT_BEFORE(list
, s
, link
);
87 #define IALLOC(sz) (isinlining ? permalloc(sz) : tmpalloc(sz))
90 * Make a symtab entry for PIC use.
92 static struct symtab
*
93 picsymtab(char *p
, char *s
, char *s2
)
95 struct symtab
*sp
= IALLOC(sizeof(struct symtab
));
96 size_t len
= strlen(p
) + strlen(s
) + strlen(s2
) + 1;
98 sp
->sname
= sp
->soname
= IALLOC(len
);
99 strlcpy(sp
->soname
, p
, len
);
100 strlcat(sp
->soname
, s
, len
);
101 strlcat(sp
->soname
, s2
, len
);
104 sp
->sflags
= sp
->slevel
= 0;
116 if ((name
= p
->n_sp
->soname
) == NULL
)
117 name
= exname(p
->n_sp
->sname
);
119 sp
= picsymtab("__imp_", name
, "");
120 q
= xbcon(0, sp
, PTR
+VOID
);
121 q
= block(UMUL
, q
, 0, PTR
|VOID
, 0, MKAP(VOID
));
122 q
= block(UMUL
, q
, 0, p
->n_type
, p
->n_df
, p
->n_ap
);
123 q
->n_sp
= p
->n_sp
; /* for init */
130 int gotnr
; /* tempnum for GOT register */
134 * Create a reference for an extern variable.
146 q
= tempnode(gotnr
, PTR
|VOID
, 0, MKAP(VOID
));
147 if ((name
= p
->n_sp
->soname
) == NULL
)
148 name
= p
->n_sp
->sname
;
149 sp
= picsymtab("", name
, "@GOT");
151 if (attr_find(p
->n_sp
->sap
, GCC_ATYP_STDCALL
) != NULL
)
152 p
->n_sp
->sflags
|= SSTDCALL
;
154 sp
->sflags
= p
->n_sp
->sflags
& SSTDCALL
;
155 r
= xbcon(0, sp
, INT
);
156 q
= buildtree(PLUS
, q
, r
);
157 q
= block(UMUL
, q
, 0, PTR
|VOID
, 0, MKAP(VOID
));
158 q
= block(UMUL
, q
, 0, p
->n_type
, p
->n_df
, p
->n_ap
);
159 q
->n_sp
= p
->n_sp
; /* for init */
163 #elif defined(MACHOABI)
167 char buf2
[256], *name
, *pspn
;
169 if ((name
= cftnsp
->soname
) == NULL
)
170 name
= cftnsp
->sname
;
171 if ((pspn
= p
->n_sp
->soname
) == NULL
)
172 pspn
= exname(p
->n_sp
->sname
);
173 if (p
->n_sp
->sclass
== EXTDEF
) {
174 snprintf(buf2
, 256, "-L%s$pb", name
);
175 sp
= picsymtab("", pspn
, buf2
);
177 snprintf(buf2
, 256, "$non_lazy_ptr-L%s$pb", name
);
178 sp
= picsymtab("L", pspn
, buf2
);
179 addstub(&nlplist
, pspn
);
181 q
= tempnode(gotnr
, PTR
+VOID
, 0, MKAP(VOID
));
182 r
= xbcon(0, sp
, INT
);
183 q
= buildtree(PLUS
, q
, r
);
185 if (p
->n_sp
->sclass
!= EXTDEF
)
186 q
= block(UMUL
, q
, 0, PTR
+VOID
, 0, MKAP(VOID
));
187 q
= block(UMUL
, q
, 0, p
->n_type
, p
->n_df
, p
->n_ap
);
188 q
->n_sp
= p
->n_sp
; /* for init */
192 #elif defined(PECOFFABI)
201 * Create a reference for a static variable.
212 q
= tempnode(gotnr
, PTR
|VOID
, 0, MKAP(VOID
));
213 if (p
->n_sp
->slevel
> 0) {
215 snprintf(buf
, 32, LABFMT
, (int)p
->n_sp
->soffset
);
216 sp
= picsymtab("", buf
, "@GOTOFF");
219 if ((name
= p
->n_sp
->soname
) == NULL
)
220 name
= p
->n_sp
->sname
;
221 sp
= picsymtab("", name
, "@GOTOFF");
225 sp
->stype
= p
->n_sp
->stype
;
226 r
= xbcon(0, sp
, INT
);
227 q
= buildtree(PLUS
, q
, r
);
228 q
= block(UMUL
, q
, 0, p
->n_type
, p
->n_df
, p
->n_ap
);
229 q
->n_sp
= p
->n_sp
; /* for init */
233 #elif defined(MACHOABI)
239 snprintf(buf2
, 256, "-L%s$pb",
240 cftnsp
->soname
? cftnsp
->soname
: cftnsp
->sname
);
242 if (p
->n_sp
->slevel
> 0) {
244 snprintf(buf1
, 32, LABFMT
, (int)p
->n_sp
->soffset
);
245 sp
= picsymtab("", buf1
, buf2
);
248 if ((name
= p
->n_sp
->soname
) == NULL
)
249 name
= p
->n_sp
->sname
;
250 sp
= picsymtab("", exname(name
), buf2
);
253 sp
->stype
= p
->n_sp
->stype
;
254 q
= tempnode(gotnr
, PTR
+VOID
, 0, MKAP(VOID
));
255 r
= xbcon(0, sp
, INT
);
256 q
= buildtree(PLUS
, q
, r
);
257 q
= block(UMUL
, q
, 0, p
->n_type
, p
->n_df
, p
->n_ap
);
262 #elif defined(PECOFFABI)
272 * Create a reference for a TLS variable.
278 struct symtab
*sp
, *sp2
;
283 * leal var@TLSGD(%ebx),%eax
284 * call ___tls_get_addr@PLT
287 /* calc address of var@TLSGD */
288 q
= tempnode(gotnr
, PTR
|VOID
, 0, MKAP(VOID
));
289 if ((name
= p
->n_sp
->soname
) == NULL
)
290 name
= p
->n_sp
->sname
;
291 sp
= picsymtab("", name
, "@TLSGD");
292 r
= xbcon(0, sp
, INT
);
293 q
= buildtree(PLUS
, q
, r
);
296 r
= block(REG
, NIL
, NIL
, PTR
|VOID
, 0, MKAP(VOID
));
298 q
= buildtree(ASSIGN
, r
, q
);
300 /* call ___tls_get_addr */
301 sp2
= lookup("___tls_get_addr@PLT", 0);
302 sp2
->stype
= EXTERN
|INT
|FTN
;
304 r
= buildtree(ADDROF
, r
, NIL
);
305 r
= block(UCALL
, r
, NIL
, INT
, 0, MKAP(INT
));
307 /* fusion both parts together */
308 q
= buildtree(COMOP
, q
, r
);
309 q
= block(UMUL
, q
, 0, p
->n_type
, p
->n_df
, p
->n_ap
);
310 q
->n_sp
= p
->n_sp
; /* for init */
320 struct symtab
*sp
, *sp2
;
321 int ext
= p
->n_sp
->sclass
;
324 if ((name
= p
->n_sp
->soname
) == NULL
)
325 name
= p
->n_sp
->sname
;
326 sp
= picsymtab("", name
,
327 ext
== EXTERN
? "@INDNTPOFF" : "@NTPOFF");
328 q
= xbcon(0, sp
, INT
);
330 q
= block(UMUL
, q
, NIL
, PTR
|VOID
, 0, MKAP(VOID
));
332 sp2
= lookup("%gs:0", 0);
333 sp2
->stype
= EXTERN
|INT
;
336 q
= buildtree(PLUS
, q
, r
);
337 q
= block(UMUL
, q
, 0, p
->n_type
, p
->n_df
, p
->n_ap
);
338 q
->n_sp
= p
->n_sp
; /* for init */
350 return (tlsnonpic(p
));
354 /* clocal() is called to do local transformations on
355 * an expression tree preparitory to its being
356 * written out in intermediate code.
358 * the major essential job is rewriting the
359 * automatic variables and arguments in terms of
361 * conversion ops which are not necessary are also clobbered here
362 * in addition, any special features (such as rewriting
363 * exclusive or) are easily handled here as well
369 register struct symtab
*q
;
370 register NODE
*r
, *l
;
371 #if defined(os_openbsd)
372 register NODE
*s
, *n
;
379 printf("clocal: %p\n", p
);
383 switch( o
= p
->n_op
){
386 if ((q
= p
->n_sp
) == NULL
)
387 return p
; /* Nothing to care about */
393 /* fake up a structure reference */
394 r
= block(REG
, NIL
, NIL
, PTR
+STRTY
, 0, 0);
397 p
= stref(block(STREF
, r
, p
, 0, 0, 0));
406 if (q
->sflags
& STLS
) {
415 } else if (blevel
> 0)
422 p
->n_rval
= q
->soffset
;
428 if (q
->sflags
& STLS
) {
435 if (q
->sflags
& SDLLINDIRECT
)
447 if (kflag
== 0 || blevel
== 0)
449 /* char arrays may end up here */
451 if (l
->n_op
!= NAME
||
452 (l
->n_type
!= ARY
+CHAR
&& l
->n_type
!= ARY
+WCHAR_TYPE
))
455 p
= picstatic(p
->n_left
);
458 cerror("ADDROF error");
469 /* Change to CALL node with ebx as argument */
470 l
= block(REG
, NIL
, NIL
, INT
, 0, MKAP(INT
));
472 p
->n_right
= buildtree(ASSIGN
, l
,
473 tempnode(gotnr
, INT
, 0, MKAP(INT
)));
474 p
->n_op
-= (UCALL
-CALL
);
478 #if defined(MACHOABI)
481 if (p
->n_type
== VOID
)
484 r
= tempnode(0, p
->n_type
, p
->n_df
, p
->n_ap
);
486 p
= buildtree(COMOP
, buildtree(ASSIGN
, r
, p
), l
);
492 /* XXX breaks sometimes */
497 * Remove unnecessary conversion ops.
499 if (!clogop(l
->n_op
) || l
->n_left
->n_op
!= SCONV
)
501 if (coptype(l
->n_op
) != BITYPE
)
503 if (l
->n_right
->n_op
!= ICON
)
505 r
= l
->n_left
->n_left
;
506 if (r
->n_type
>= FLOAT
)
508 if (toolarge(r
->n_type
, l
->n_right
->n_lval
))
510 l
->n_right
->n_type
= r
->n_type
;
511 if (l
->n_op
>= ULE
&& l
->n_op
<= UGT
)
512 l
->n_op
-= (UGT
-ULE
);
513 p
->n_left
= buildtree(l
->n_op
, r
, l
->n_right
);
520 /* Remove redundant PCONV's. Be careful */
522 if (l
->n_op
== ICON
) {
523 l
->n_lval
= (unsigned)l
->n_lval
;
526 if (l
->n_type
< INT
|| l
->n_type
== LONGLONG
||
527 l
->n_type
== ULONGLONG
) {
529 p
->n_left
= block(SCONV
, l
, NIL
,
530 UNSIGNED
, 0, MKAP(UNSIGNED
));
533 /* if left is SCONV, cannot remove */
534 if (l
->n_op
== SCONV
)
537 /* avoid ADDROF TEMP */
538 if (l
->n_op
== ADDROF
&& l
->n_left
->n_op
== TEMP
)
541 /* if conversion to another pointer type, just remove */
542 if (p
->n_type
> BTMASK
&& l
->n_type
> BTMASK
)
546 delp
: l
->n_type
= p
->n_type
;
547 l
->n_qual
= p
->n_qual
;
555 if (p
->n_left
->n_op
== COMOP
)
556 break; /* may propagate wrong type later */
559 if (p
->n_type
== l
->n_type
) {
564 if ((p
->n_type
& TMASK
) == 0 && (l
->n_type
& TMASK
) == 0 &&
565 btattr
[p
->n_type
].atypsz
== btattr
[l
->n_type
].atypsz
) {
566 if (p
->n_type
!= FLOAT
&& p
->n_type
!= DOUBLE
&&
567 l
->n_type
!= FLOAT
&& l
->n_type
!= DOUBLE
&&
568 l
->n_type
!= LDOUBLE
&& p
->n_type
!= LDOUBLE
) {
569 if (l
->n_op
== NAME
|| l
->n_op
== UMUL
||
571 l
->n_type
= p
->n_type
;
578 if (DEUNSIGN(p
->n_type
) == INT
&& DEUNSIGN(l
->n_type
) == INT
&&
579 coptype(l
->n_op
) == BITYPE
&& l
->n_op
!= COMOP
&&
581 l
->n_type
= p
->n_type
;
590 CONSZ val
= l
->n_lval
;
592 if (!ISPTR(m
)) /* Pointers don't need to be conv'd */
595 l
->n_lval
= nncon(l
) ? (l
->n_lval
!= 0) : 1;
599 l
->n_lval
= (char)val
;
602 l
->n_lval
= val
& 0377;
605 l
->n_lval
= (short)val
;
608 l
->n_lval
= val
& 0177777;
612 l
->n_lval
= val
& 0xffffffff;
616 l
->n_lval
= (int)val
;
619 l
->n_lval
= (long long)val
;
633 cerror("unknown type %d", m
);
639 } else if (l
->n_op
== FCON
) {
640 l
->n_lval
= (CONSZ
)l
->n_dcon
;
648 if (DEUNSIGN(p
->n_type
) == SHORT
&&
649 DEUNSIGN(l
->n_type
) == SHORT
) {
653 if ((p
->n_type
== CHAR
|| p
->n_type
== UCHAR
||
654 p
->n_type
== SHORT
|| p
->n_type
== USHORT
) &&
655 (l
->n_type
== FLOAT
|| l
->n_type
== DOUBLE
||
656 l
->n_type
== LDOUBLE
)) {
657 p
= block(SCONV
, p
, NIL
, p
->n_type
, p
->n_df
, p
->n_ap
);
658 p
->n_left
->n_type
= INT
;
665 if (o
== DIV
&& p
->n_type
!= CHAR
&& p
->n_type
!= SHORT
)
667 if (o
== MOD
&& p
->n_type
!= CHAR
&& p
->n_type
!= SHORT
)
669 /* make it an int division by inserting conversions */
670 p
->n_left
= block(SCONV
, p
->n_left
, NIL
, INT
, 0, MKAP(INT
));
671 p
->n_right
= block(SCONV
, p
->n_right
, NIL
, INT
, 0, MKAP(INT
));
672 p
= block(SCONV
, p
, NIL
, p
->n_type
, 0, MKAP(p
->n_type
));
673 p
->n_left
->n_type
= INT
;
679 p
= buildtree(o
== PMCONV
? MUL
: DIV
, p
->n_left
, p
->n_right
);
684 /* put return value in return reg */
686 p
->n_right
= p
->n_left
;
687 p
->n_left
= block(REG
, NIL
, NIL
, p
->n_type
, 0, MKAP(INT
));
688 p
->n_left
->n_rval
= p
->n_left
->n_type
== BOOL
?
689 RETREG(CHAR
) : RETREG(p
->n_type
);
694 /* shift count must be in a char */
695 if (p
->n_right
->n_type
== CHAR
|| p
->n_right
->n_type
== UCHAR
)
697 p
->n_right
= block(SCONV
, p
->n_right
, NIL
, CHAR
, 0, MKAP(CHAR
));
699 #if defined(os_openbsd)
700 /* If not using pcc struct return */
703 if (r
->n_op
!= STCALL
&& r
->n_op
!= USTCALL
)
705 m
= tsize(BTYPE(r
->n_type
), r
->n_df
, r
->n_ap
);
708 else if (m
== SZSHORT
)
712 else if (m
== SZLONGLONG
)
717 l
= buildtree(ADDROF
, p
->n_left
, NIL
);
720 r
->n_op
-= (STCALL
-CALL
);
723 /* r = long, l = &struct */
725 n
= tempnode(0, m
, r
->n_df
, r
->n_ap
);
726 r
= buildtree(ASSIGN
, ccopy(n
), r
);
728 s
= tempnode(0, l
->n_type
, l
->n_df
, l
->n_ap
);
729 l
= buildtree(ASSIGN
, ccopy(s
), l
);
731 p
= buildtree(COMOP
, r
, l
);
734 block(NAME
, NIL
, NIL
, m
|PTR
, 0, MKAP(m
)), ccopy(s
));
739 r
= buildtree(ASSIGN
, buildtree(UMUL
, r
, NIL
), n
);
740 p
= buildtree(COMOP
, p
, r
);
741 p
= buildtree(COMOP
, p
, s
);
747 printf("clocal end: %p\n", p
);
755 * Change CALL references to either direct (static) or PLT.
758 fixnames(NODE
*p
, void *arg
)
760 #if !defined(PECOFFABI)
768 if ((cdope(p
->n_op
) & CALLFLG
) == 0)
774 q
= q
->n_left
, isu
= 1;
776 if (q
->n_op
== PLUS
&& q
->n_left
->n_op
== TEMP
&&
777 q
->n_right
->n_op
== ICON
) {
778 sp
= q
->n_right
->n_sp
;
781 return; /* nothing to do */
782 if (sp
->sclass
== STATIC
&& !ISFTN(sp
->stype
))
783 return; /* function pointer */
785 if (sp
->sclass
!= STATIC
&& sp
->sclass
!= EXTERN
&&
786 sp
->sclass
!= EXTDEF
)
791 if (sp
->soname
== NULL
||
792 (c
= strstr(sp
->soname
, "@GOT")) == NULL
)
795 memcpy(c
, "@PLT", sizeof("@PLT"));
799 #elif defined(MACHOABI)
801 if (sp
->soname
== NULL
||
802 ((c
= strstr(sp
->soname
, "$non_lazy_ptr")) == NULL
&&
803 (c
= strstr(sp
->soname
, "-L")) == NULL
))
807 addstub(&stublist
, sp
->soname
+1);
817 nfree(p
->n_left
->n_left
);
825 static void mangle(NODE
*p
);
840 sp
= IALLOC(sizeof(struct symtab
));
842 sp
->sap
= MKAP(p
->n_type
);
843 sp
->slevel
= 1; /* fake numeric label */
844 sp
->soffset
= getlab();
846 sp
->stype
= p
->n_type
;
847 sp
->squal
= (CON
>> TSHIFT
);
850 ninval(0, sp
->sap
->atypsz
, p
);
861 return(1); /* all names can have & taken on them */
865 * at the end of the arguments of a ftn, set the automatic offset
874 * Return 1 if a variable of type type is OK to put in register.
879 if (t
== FLOAT
|| t
== DOUBLE
|| t
== LDOUBLE
)
880 return 0; /* not yet */
885 * return a node, for structure references, which is suitable for
886 * being added to a pointer of type t, in order to be off bits offset
888 * t, d, and s are the type, dimension offset, and sizeoffset
889 * For pdp10, return the type-specific index number which calculation
890 * is based on its size. For example, short a[3] would return 3.
891 * Be careful about only handling first-level pointers, the following
892 * indirections must be fullword.
895 offcon(OFFSZ off
, TWORD t
, union dimfun
*d
, struct attr
*ap
)
900 printf("offcon: OFFSZ %lld type %x dim %p siz %d\n",
904 p
->n_lval
= off
/SZCHAR
; /* Default */
909 * Allocate off bits on the stack. p is a tree that when evaluated
910 * is the multiply count for off, t is a storeable node where to write
911 * the allocated address.
914 spalloc(NODE
*t
, NODE
*p
, OFFSZ off
)
918 p
= buildtree(MUL
, p
, bcon(off
/SZCHAR
)); /* XXX word alignment? */
920 /* sub the size from sp */
921 sp
= block(REG
, NIL
, NIL
, p
->n_type
, 0, MKAP(INT
));
924 ecomp(buildtree(MINUSEQ
, sp
, p
));
927 /* align to 16 bytes */
928 sp
= block(REG
, NIL
, NIL
, p
->n_type
, 0, MKAP(INT
));
931 ecomp(buildtree(PLUSEQ
, sp
, bcon(15)));
933 sp
= block(REG
, NIL
, NIL
, p
->n_type
, 0, MKAP(INT
));
936 ecomp(buildtree(RSEQ
, sp
, bcon(4)));
938 sp
= block(REG
, NIL
, NIL
, p
->n_type
, 0, MKAP(INT
));
941 ecomp(buildtree(LSEQ
, sp
, bcon(4)));
945 /* save the address of sp */
946 sp
= block(REG
, NIL
, NIL
, PTR
+INT
, t
->n_df
, t
->n_ap
);
949 t
->n_type
= sp
->n_type
;
950 ecomp(buildtree(ASSIGN
, t
, sp
)); /* Emit! */
955 * Print out a string of characters.
956 * Assume that the assembler understands C-style escape
960 instring(struct symtab
*sp
)
962 char *s
, *str
= sp
->sname
;
964 #if defined(ELFABI) || defined(PECOFFABI)
968 #elif defined(MACHOABI)
971 if (lastloc
!= STRNG
)
972 printf(" .cstring\n");
974 printf("\t.p2align 2\n");
975 printf(LABFMT
":\n", sp
->soffset
);
979 /* be kind to assemblers and avoid long strings */
980 printf("\t.ascii \"");
981 for (s
= str
; *s
!= 0; ) {
986 fwrite(str
, 1, s
- str
, stdout
);
987 printf("\"\n\t.ascii \"");
991 fwrite(str
, 1, s
- str
, stdout
);
995 static int inbits
, inval
;
998 * set fsz bits in sequence to zero.
1001 zbits(OFFSZ off
, int fsz
)
1006 printf("zbits off %lld, fsz %d inbits %d\n", off
, fsz
, inbits
);
1007 if ((m
= (inbits
% SZCHAR
))) {
1014 printf("\t.byte %d\n", inval
);
1018 if (fsz
>= SZCHAR
) {
1020 printf("\t.space %d\n", fsz
/SZCHAR
);
1022 printf("\t.zero %d\n", fsz
/SZCHAR
);
1024 fsz
-= (fsz
/SZCHAR
) * SZCHAR
;
1033 * Initialize a bitfield.
1036 infld(CONSZ off
, int fsz
, CONSZ val
)
1039 printf("infld off %lld, fsz %d, val %lld inbits %d\n",
1040 off
, fsz
, val
, inbits
);
1041 val
&= ((CONSZ
)1 << fsz
)-1;
1042 while (fsz
+ inbits
>= SZCHAR
) {
1043 inval
|= (int)(val
<< inbits
);
1044 printf("\t.byte %d\n", inval
& 255);
1045 fsz
-= (SZCHAR
- inbits
);
1046 val
>>= (SZCHAR
- inbits
);
1050 inval
|= (int)(val
<< inbits
);
1056 * print out a constant node, may be associated with a label.
1057 * Do not free the node after use.
1058 * off is bit offset from the beginning of the aggregate
1059 * fsz is the number of bits this is referring to
1062 ninval(CONSZ off
, int fsz
, NODE
*p
)
1064 union { float f
; double d
; long double l
; int i
[3]; } u
;
1066 #if defined(ELFABI) || defined(MACHOABI)
1074 t
= INT
; /* pointer */
1076 while (p
->n_op
== SCONV
|| p
->n_op
== PCONV
) {
1077 NODE
*l
= p
->n_left
;
1078 l
->n_type
= p
->n_type
;
1082 if (kflag
&& (p
->n_op
== PLUS
|| p
->n_op
== UMUL
)) {
1083 if (p
->n_op
== UMUL
)
1088 if (q
->soname
!= NULL
) {
1091 if ((c
= strstr(q
->soname
, "@GOT")) != NULL
)
1092 *c
= 0; /* ignore GOT ref here */
1093 #elif defined(MACHOABI)
1095 if ((c
= strstr(q
->soname
, "$non_lazy_ptr")) != NULL
) {
1096 q
->soname
++; /* skip "L" */
1097 *c
= 0; /* ignore GOT ref here */
1098 } else if ((c
= strstr(q
->soname
, "-L")) != NULL
)
1099 *c
= 0; /* ignore GOT ref here */
1103 if (p
->n_op
!= ICON
&& p
->n_op
!= FCON
)
1104 cerror("ninval: init node not constant");
1106 if (p
->n_op
== ICON
&& p
->n_sp
!= NULL
&& DEUNSIGN(t
) != INT
)
1107 uerror("element not constant");
1112 i
= (int)(p
->n_lval
>> 32);
1113 p
->n_lval
&= 0xffffffff;
1117 ninval(off
+32, 32, p
);
1121 printf("\t.long %d", (int)p
->n_lval
);
1122 if ((q
= p
->n_sp
) != NULL
) {
1123 if ((q
->sclass
== STATIC
&& q
->slevel
> 0)) {
1124 printf("+" LABFMT
, q
->soffset
);
1127 if ((name
= q
->soname
) == NULL
)
1128 name
= exname(q
->sname
);
1129 printf("+%s", name
);
1137 printf("\t.2byte 0x%x\n", (int)p
->n_lval
& 0xffff);
1139 printf("\t.short 0x%x\n", (int)p
->n_lval
& 0xffff);
1144 p
->n_lval
= p
->n_lval
!= 0;
1148 printf("\t.byte %d\n", (int)p
->n_lval
& 0xff);
1152 u
.l
= (long double)p
->n_dcon
;
1153 #if defined(HOST_BIG_ENDIAN)
1154 /* XXX probably broken on most hosts */
1155 printf("\t.long\t0x%x,0x%x,0x%x\n", u
.i
[2], u
.i
[1], u
.i
[0]);
1157 printf("\t.long\t%d,%d,%d\n", u
.i
[0], u
.i
[1], u
.i
[2] & 0177777);
1161 u
.d
= (double)p
->n_dcon
;
1162 #if defined(HOST_BIG_ENDIAN)
1163 printf("\t.long\t0x%x,0x%x\n", u
.i
[1], u
.i
[0]);
1165 printf("\t.long\t%d,%d\n", u
.i
[0], u
.i
[1]);
1169 u
.f
= (float)p
->n_dcon
;
1170 printf("\t.long\t%d\n", u
.i
[0]);
1177 /* make a name look like an external name in the local machine */
1181 #if defined(PECOFFABI) || defined(MACHOABI)
1184 static char text
[NCHNAM
+1];
1191 for (i
=1; *p
&& i
<NCHNAM
; ++i
)
1195 text
[NCHNAM
] = '\0'; /* truncate */
1201 return (p
== NULL
? "" : p
);
1207 * map types which are not defined on the local machine
1212 switch (BTYPE(type
)) {
1218 MODTYPE(type
,UNSIGNED
);
1225 calldec(NODE
*p
, NODE
*q
)
1230 extdec(struct symtab
*q
)
1234 /* make a common declaration for id, if reasonable */
1236 defzero(struct symtab
*sp
)
1243 if (sp
->sflags
& STLS
) {
1244 if (sp
->sclass
== EXTERN
)
1245 sp
->sclass
= EXTDEF
;
1246 simpleinit(sp
, bcon(0));
1251 if ((name
= sp
->soname
) == NULL
)
1252 name
= exname(sp
->sname
);
1253 al
= talign(sp
->stype
, sp
->sap
)/SZCHAR
;
1254 off
= (int)tsize(sp
->stype
, sp
->sdf
, sp
->sap
);
1255 off
= (off
+(SZCHAR
-1))/SZCHAR
;
1259 if ((ap
= attr_find(sp
->sap
, GCC_ATYP_VISIBILITY
)) &&
1260 strcmp(ap
->sarg(0), "default"))
1261 printf("\t.%s %s\n", ap
->sarg(0), name
);
1264 printf(" .%scomm ", sp
->sclass
== STATIC
? "l" : "");
1265 if (sp
->slevel
== 0)
1266 printf("%s,0%o", name
, off
);
1268 printf(LABFMT
",0%o", sp
->soffset
, off
);
1269 if (sp
->sclass
!= STATIC
) {
1272 #elif defined(MACHOABI)
1273 printf(",%d", ispow2(al
));
1280 section2string(char *name
, int len
)
1286 if (strncmp(name
, "link_set", 8) == 0) {
1287 const char *postfix
= ",\"aw\",@progbits";
1288 n
= len
+ strlen(postfix
) + 1;
1290 strlcpy(s
, name
, n
);
1291 strlcat(s
, postfix
, n
);
1296 return newstring(name
, len
);
1305 static int dllindirect
;
1308 static int constructor
;
1309 static int destructor
;
1312 * Give target the opportunity of handling pragmas.
1317 char *a2
= pragtok(NULL
);
1320 if (strcmp(str
, "tls") == 0 && a2
== NULL
) {
1325 if (strcmp(str
, "stdcall") == 0) {
1329 if (strcmp(str
, "cdecl") == 0) {
1334 if (strcmp(str
, "fastcall") == 0) {
1338 if (strcmp(str
, "dllimport") == 0) {
1342 if (strcmp(str
, "dllexport") == 0) {
1347 if (strcmp(str
, "constructor") == 0 || strcmp(str
, "init") == 0) {
1351 if (strcmp(str
, "destructor") == 0 || strcmp(str
, "fini") == 0) {
1355 if (strcmp(str
, "section") == 0 && a2
!= NULL
) {
1356 nextsect
= section2string(a2
, strlen(a2
));
1359 if (strcmp(str
, "alias") == 0 && a2
!= NULL
) {
1360 alias
= tmpstrdup(a2
);
1363 if (strcmp(str
, "ident") == 0)
1364 return 1; /* Just ignore */
1370 * Called when a identifier has been declared.
1373 fixdef(struct symtab
*sp
)
1377 /* may have sanity checks here */
1382 if ((ap
= attr_find(sp
->sap
, GCC_ATYP_ALIAS
)) != NULL
) {
1383 char *an
= ap
->sarg(0);
1384 char *sn
= sp
->soname
? sp
->soname
: sp
->sname
;
1387 v
= attr_find(sp
->sap
, GCC_ATYP_WEAK
) ? "weak" : "globl";
1388 printf("\t.%s %s\n", v
, sn
);
1389 printf("\t.set %s,%s\n", sn
, an
);
1392 if (alias
!= NULL
&& (sp
->sclass
!= PARAM
)) {
1394 if ((name
= sp
->soname
) == NULL
)
1395 name
= exname(sp
->sname
);
1396 printf("\t.globl %s\n", name
);
1397 printf("%s = ", name
);
1398 printf("%s\n", exname(alias
));
1401 if ((constructor
|| destructor
) && (sp
->sclass
!= PARAM
)) {
1403 printf("\t.section .%ctors,\"aw\",@progbits\n",
1404 constructor
? 'c' : 'd');
1405 #elif defined(PECOFFABI)
1406 printf("\t.section .%ctors,\"w\"\n",
1407 constructor
? 'c' : 'd');
1408 #elif defined(MACHOABI)
1411 printf("\t.mod_init_func\n");
1413 printf("\t.mod_term_func\n");
1416 printf("\t.constructor\n");
1418 printf("\t.destructor\n");
1421 printf("\t.p2align 2\n");
1422 printf("\t.long %s\n", exname(sp
->sname
));
1424 printf("\t.text\n");
1426 printf("\t.previous\n");
1428 constructor
= destructor
= 0;
1430 if (stdcall && (sp
->sclass
!= PARAM
)) {
1431 sp
->sflags
|= SSTDCALL
;
1435 if (dllindirect
&& (sp
->sclass
!= PARAM
)) {
1436 sp
->sflags
|= SDLLINDIRECT
;
1443 i386_builtin_return_address(NODE
*f
, NODE
*a
, TWORD rt
)
1447 if (a
== NULL
|| a
->n_op
!= ICON
)
1450 nframes
= (int)a
->n_lval
;
1455 f
= block(REG
, NIL
, NIL
, PTR
+VOID
, 0, MKAP(VOID
));
1459 f
= block(UMUL
, f
, NIL
, PTR
+VOID
, 0, MKAP(VOID
));
1461 f
= block(PLUS
, f
, bcon(4), INCREF(PTR
+VOID
), 0, MKAP(VOID
));
1462 f
= buildtree(UMUL
, f
, NIL
);
1466 uerror("bad argument to __builtin_return_address");
1471 i386_builtin_frame_address(NODE
*f
, NODE
*a
, TWORD rt
)
1475 if (a
== NULL
|| a
->n_op
!= ICON
)
1478 nframes
= (int)a
->n_lval
;
1483 f
= block(REG
, NIL
, NIL
, PTR
+VOID
, 0, MKAP(VOID
));
1487 f
= block(UMUL
, f
, NIL
, PTR
+VOID
, 0, MKAP(VOID
));
1491 uerror("bad argument to __builtin_frame_address");
1496 * Postfix external functions with the arguments size.
1503 if (p
->n_op
== NAME
|| p
->n_op
== ICON
) {
1504 p
->n_flags
= 0; /* for later setting of STDCALL */
1506 if (p
->n_sp
->sflags
& SSTDCALL
)
1507 p
->n_flags
= FSTDCALL
;
1509 } else if (p
->n_op
== TEMP
)
1510 p
->n_flags
= 0; /* STDCALL fun ptr not allowed */
1512 if (p
->n_op
!= CALL
&& p
->n_op
!= STCALL
&&
1513 p
->n_op
!= UCALL
&& p
->n_op
!= USTCALL
)
1519 while (cdope(l
->n_op
) & CALLFLG
)
1521 if (l
->n_op
== TEMP
)
1523 if (l
->n_op
== ADDROF
)
1525 if (l
->n_sp
== NULL
)
1528 if (attr_find(l
->n_sp
->sap
, GCC_ATYP_STDCALL
) != NULL
)
1529 l
->n_sp
->sflags
|= SSTDCALL
;
1532 if (l
->n_sp
->sflags
& SSTDCALL
) {
1533 if (strchr(l
->n_name
, '@') == NULL
) {
1539 if (p
->n_op
== CALL
|| p
->n_op
== STCALL
) {
1540 for (r
= p
->n_right
;
1541 r
->n_op
== CM
; r
= r
->n_left
) {
1543 if (t
== STRTY
|| t
== UNIONTY
)
1544 size
+= tsize(t
, r
->n_df
, r
->n_ap
);
1546 size
+= szty(t
) * SZINT
/ SZCHAR
;
1549 if (t
== STRTY
|| t
== UNIONTY
)
1550 size
+= tsize(t
, r
->n_df
, r
->n_ap
);
1552 size
+= szty(t
) * SZINT
/ SZCHAR
;
1554 snprintf(buf
, 256, "%s@%d", l
->n_name
, size
);
1555 l
->n_name
= IALLOC(strlen(buf
) + 1);
1556 strcpy(l
->n_name
, buf
);
1563 pass1_lastchance(struct interpass
*ip
)
1565 if (ip
->type
== IP_NODE
&&
1566 (ip
->ip_node
->n_op
== CALL
|| ip
->ip_node
->n_op
== UCALL
) &&
1567 ISFTY(ip
->ip_node
->n_type
))
1568 ip
->ip_node
->n_flags
= FFPPOP
;
1570 if (ip
->type
== IP_EPILOG
) {
1571 struct interpass_prolog
*ipp
= (struct interpass_prolog
*)ip
;
1572 ipp
->ipp_argstacksize
= argstacksize
;