]>
Commit | Line | Data |
---|---|---|
cb805c2d | 1 | /* Routines for GCC for ARM/pe. |
ae46c4e0 | 2 | Copyright (C) 1995, 1996, 2000, 2001, 2002 Free Software Foundation, Inc. |
cb805c2d NC |
3 | Contributed by Doug Evans (dje@cygnus.com). |
4 | ||
4f448245 | 5 | This file is part of GCC. |
cb805c2d | 6 | |
4f448245 NC |
7 | GCC is free software; you can redistribute it and/or modify it |
8 | under the terms of the GNU General Public License as published | |
9 | by the Free Software Foundation; either version 2, or (at your | |
10 | option) any later version. | |
cb805c2d | 11 | |
4f448245 NC |
12 | GCC is distributed in the hope that it will be useful, but WITHOUT |
13 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
14 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public | |
15 | License for more details. | |
cb805c2d | 16 | |
4f448245 NC |
17 | You should have received a copy of the GNU General Public License |
18 | along with GCC; see the file COPYING. If not, write to | |
19 | the Free Software Foundation, 59 Temple Place - Suite 330, | |
20 | Boston, MA 02111-1307, USA. */ | |
cb805c2d | 21 | |
cb805c2d | 22 | #include "config.h" |
c27ba912 | 23 | #include "system.h" |
4977bab6 ZW |
24 | #include "coretypes.h" |
25 | #include "tm.h" | |
cb805c2d NC |
26 | #include "rtl.h" |
27 | #include "output.h" | |
28 | #include "flags.h" | |
29 | #include "tree.h" | |
30 | #include "expr.h" | |
b020fd92 | 31 | #include "toplev.h" |
d5b7b3ae | 32 | #include "tm_p.h" |
cb805c2d NC |
33 | |
34 | extern int current_function_anonymous_args; | |
35 | ||
cb805c2d | 36 | \f |
825dda42 | 37 | /* Return nonzero if DECL is a dllexport'd object. */ |
cb805c2d NC |
38 | |
39 | tree current_class_type; /* FIXME */ | |
40 | ||
41 | int | |
42 | arm_dllexport_p (decl) | |
43 | tree decl; | |
44 | { | |
45 | tree exp; | |
46 | ||
47 | if (TREE_CODE (decl) != VAR_DECL | |
48 | && TREE_CODE (decl) != FUNCTION_DECL) | |
49 | return 0; | |
91d231cb | 50 | exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)); |
cb805c2d NC |
51 | if (exp) |
52 | return 1; | |
53 | ||
cb805c2d NC |
54 | return 0; |
55 | } | |
56 | ||
825dda42 | 57 | /* Return nonzero if DECL is a dllimport'd object. */ |
cb805c2d NC |
58 | |
59 | int | |
60 | arm_dllimport_p (decl) | |
61 | tree decl; | |
62 | { | |
63 | tree imp; | |
64 | ||
65 | if (TREE_CODE (decl) == FUNCTION_DECL | |
66 | && TARGET_NOP_FUN_DLLIMPORT) | |
67 | return 0; | |
68 | ||
69 | if (TREE_CODE (decl) != VAR_DECL | |
70 | && TREE_CODE (decl) != FUNCTION_DECL) | |
71 | return 0; | |
91d231cb | 72 | imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)); |
cb805c2d NC |
73 | if (imp) |
74 | return 1; | |
75 | ||
cb805c2d NC |
76 | return 0; |
77 | } | |
78 | ||
825dda42 | 79 | /* Return nonzero if SYMBOL is marked as being dllexport'd. */ |
cb805c2d NC |
80 | |
81 | int | |
82 | arm_dllexport_name_p (symbol) | |
3cce094d | 83 | const char * symbol; |
cb805c2d | 84 | { |
c27ba912 | 85 | return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'e' && symbol[2] == '.'; |
cb805c2d NC |
86 | } |
87 | ||
825dda42 | 88 | /* Return nonzero if SYMBOL is marked as being dllimport'd. */ |
cb805c2d NC |
89 | |
90 | int | |
91 | arm_dllimport_name_p (symbol) | |
3cce094d | 92 | const char * symbol; |
cb805c2d | 93 | { |
c27ba912 | 94 | return symbol[0] == ARM_PE_FLAG_CHAR && symbol[1] == 'i' && symbol[2] == '.'; |
cb805c2d NC |
95 | } |
96 | ||
97 | /* Mark a DECL as being dllexport'd. | |
98 | Note that we override the previous setting (eg: dllimport). */ | |
99 | ||
100 | void | |
101 | arm_mark_dllexport (decl) | |
102 | tree decl; | |
103 | { | |
3cce094d | 104 | const char * oldname; |
cb805c2d NC |
105 | char * newname; |
106 | rtx rtlname; | |
107 | tree idp; | |
108 | ||
109 | rtlname = XEXP (DECL_RTL (decl), 0); | |
110 | if (GET_CODE (rtlname) == SYMBOL_REF) | |
111 | oldname = XSTR (rtlname, 0); | |
112 | else if (GET_CODE (rtlname) == MEM | |
113 | && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF) | |
114 | oldname = XSTR (XEXP (rtlname, 0), 0); | |
115 | else | |
116 | abort (); | |
117 | if (arm_dllimport_name_p (oldname)) | |
118 | oldname += 9; | |
119 | else if (arm_dllexport_name_p (oldname)) | |
120 | return; /* already done */ | |
121 | ||
122 | newname = alloca (strlen (oldname) + 4); | |
c27ba912 | 123 | sprintf (newname, "%ce.%s", ARM_PE_FLAG_CHAR, oldname); |
cb805c2d NC |
124 | |
125 | /* We pass newname through get_identifier to ensure it has a unique | |
126 | address. RTL processing can sometimes peek inside the symbol ref | |
127 | and compare the string's addresses to see if two symbols are | |
128 | identical. */ | |
129 | /* ??? At least I think that's why we do this. */ | |
130 | idp = get_identifier (newname); | |
131 | ||
132 | XEXP (DECL_RTL (decl), 0) = | |
f1c25d3b | 133 | gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp)); |
cb805c2d NC |
134 | } |
135 | ||
136 | /* Mark a DECL as being dllimport'd. */ | |
137 | ||
138 | void | |
139 | arm_mark_dllimport (decl) | |
140 | tree decl; | |
141 | { | |
3cce094d | 142 | const char * oldname; |
cb805c2d NC |
143 | char * newname; |
144 | tree idp; | |
145 | rtx rtlname, newrtl; | |
146 | ||
147 | rtlname = XEXP (DECL_RTL (decl), 0); | |
148 | ||
149 | if (GET_CODE (rtlname) == SYMBOL_REF) | |
150 | oldname = XSTR (rtlname, 0); | |
151 | else if (GET_CODE (rtlname) == MEM | |
152 | && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF) | |
153 | oldname = XSTR (XEXP (rtlname, 0), 0); | |
154 | else | |
155 | abort (); | |
156 | ||
157 | if (arm_dllexport_name_p (oldname)) | |
158 | abort (); /* this shouldn't happen */ | |
159 | else if (arm_dllimport_name_p (oldname)) | |
160 | return; /* already done */ | |
161 | ||
162 | /* ??? One can well ask why we're making these checks here, | |
163 | and that would be a good question. */ | |
164 | ||
165 | /* Imported variables can't be initialized. */ | |
166 | if (TREE_CODE (decl) == VAR_DECL | |
167 | && !DECL_VIRTUAL_P (decl) | |
168 | && DECL_INITIAL (decl)) | |
169 | { | |
ddd2d57e | 170 | error ("%Jinitialized variable '%D' is marked dllimport", decl, decl); |
cb805c2d NC |
171 | return; |
172 | } | |
173 | /* Nor can they be static. */ | |
174 | if (TREE_CODE (decl) == VAR_DECL | |
175 | /* ??? Is this test for vtables needed? */ | |
176 | && !DECL_VIRTUAL_P (decl) | |
177 | && 0 /*???*/) | |
178 | { | |
ddd2d57e | 179 | error ("%Jstatic variable '%D' is marked dllimport", decl, decl); |
cb805c2d NC |
180 | return; |
181 | } | |
182 | ||
183 | /* `extern' needn't be specified with dllimport. | |
184 | Specify `extern' now and hope for the best. Sigh. */ | |
185 | if (TREE_CODE (decl) == VAR_DECL | |
186 | /* ??? Is this test for vtables needed? */ | |
187 | && !DECL_VIRTUAL_P (decl)) | |
188 | { | |
189 | DECL_EXTERNAL (decl) = 1; | |
190 | TREE_PUBLIC (decl) = 1; | |
191 | } | |
192 | ||
193 | newname = alloca (strlen (oldname) + 11); | |
c27ba912 | 194 | sprintf (newname, "%ci.__imp_%s", ARM_PE_FLAG_CHAR, oldname); |
cb805c2d NC |
195 | |
196 | /* We pass newname through get_identifier to ensure it has a unique | |
197 | address. RTL processing can sometimes peek inside the symbol ref | |
198 | and compare the string's addresses to see if two symbols are | |
199 | identical. */ | |
200 | /* ??? At least I think that's why we do this. */ | |
201 | idp = get_identifier (newname); | |
202 | ||
f1c25d3b KH |
203 | newrtl = gen_rtx_MEM (Pmode, |
204 | gen_rtx_SYMBOL_REF (Pmode, | |
205 | IDENTIFIER_POINTER (idp))); | |
cb805c2d NC |
206 | XEXP (DECL_RTL (decl), 0) = newrtl; |
207 | } | |
208 | ||
cb805c2d | 209 | void |
c6a2438a | 210 | arm_pe_encode_section_info (decl, rtl, first) |
cb805c2d | 211 | tree decl; |
c6a2438a | 212 | rtx rtl; |
b2003250 | 213 | int first ATTRIBUTE_UNUSED; |
cb805c2d | 214 | { |
fb49053f | 215 | /* This bit is copied from arm_encode_section_info. */ |
cb805c2d NC |
216 | if (optimize > 0 && TREE_CONSTANT (decl) |
217 | && (!flag_writable_strings || TREE_CODE (decl) != STRING_CST)) | |
c6a2438a | 218 | SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1; |
cb805c2d NC |
219 | |
220 | /* Mark the decl so we can tell from the rtl whether the object is | |
221 | dllexport'd or dllimport'd. */ | |
222 | if (arm_dllexport_p (decl)) | |
223 | arm_mark_dllexport (decl); | |
224 | else if (arm_dllimport_p (decl)) | |
225 | arm_mark_dllimport (decl); | |
226 | /* It might be that DECL has already been marked as dllimport, but a | |
227 | subsequent definition nullified that. The attribute is gone but | |
228 | DECL_RTL still has @i.__imp_foo. We need to remove that. */ | |
229 | else if ((TREE_CODE (decl) == FUNCTION_DECL | |
230 | || TREE_CODE (decl) == VAR_DECL) | |
231 | && DECL_RTL (decl) != NULL_RTX | |
232 | && GET_CODE (DECL_RTL (decl)) == MEM | |
233 | && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM | |
234 | && GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF | |
235 | && arm_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0))) | |
236 | { | |
3cce094d | 237 | const char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0); |
cb805c2d | 238 | tree idp = get_identifier (oldname + 9); |
f1c25d3b | 239 | rtx newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp)); |
cb805c2d NC |
240 | |
241 | XEXP (DECL_RTL (decl), 0) = newrtl; | |
242 | ||
243 | /* We previously set TREE_PUBLIC and DECL_EXTERNAL. | |
244 | ??? We leave these alone for now. */ | |
245 | } | |
246 | } | |
247 | ||
cb805c2d NC |
248 | void |
249 | arm_pe_unique_section (decl, reloc) | |
250 | tree decl; | |
251 | int reloc; | |
252 | { | |
253 | int len; | |
ec940faa | 254 | const char * name; |
cb805c2d | 255 | char * string; |
adf97f58 | 256 | const char * prefix; |
cb805c2d NC |
257 | |
258 | name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); | |
772c5265 | 259 | name = arm_strip_name_encoding (name); |
cb805c2d NC |
260 | |
261 | /* The object is put in, for example, section .text$foo. | |
262 | The linker will then ultimately place them in .text | |
263 | (everything from the $ on is stripped). */ | |
264 | if (TREE_CODE (decl) == FUNCTION_DECL) | |
265 | prefix = ".text$"; | |
4e4d733e | 266 | else if (decl_readonly_section (decl, reloc)) |
cb805c2d NC |
267 | prefix = ".rdata$"; |
268 | else | |
269 | prefix = ".data$"; | |
270 | len = strlen (name) + strlen (prefix); | |
271 | string = alloca (len + 1); | |
272 | sprintf (string, "%s%s", prefix, name); | |
273 | ||
274 | DECL_SECTION_NAME (decl) = build_string (len, string); | |
275 | } |