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