]>
Commit | Line | Data |
---|---|---|
fbb03002 PS |
1 | From: "H dot J dot Lu" <hjl at lucon dot org> |
2 | Subject: RFC: PATCH: PR middle-end/20218: Can't use __attribute__ ((visibility ("hidden"))) to hide a symbol | |
3 | ||
4 | This is the first attempt to to fix PR 20218. It keeps a list of | |
5 | referenced global symbols and outputs non-default visibility at the | |
6 | end. I only verified it on Linux/ia32, Linux/x86_64 and Linux/ia64. | |
7 | ||
8 | ||
9 | 2005-02-28 H.J. Lu <hongjiu.lu@intel.com> | |
10 | ||
11 | PR middle-end/20218 | |
12 | * config/elfos.h (ASM_OUTPUT_EXTERNAL): New. | |
13 | (TARGET_ASM_FILE_END): New. | |
14 | * config/i386/i386-protos.h (ix86_elf_file_end): New. | |
15 | * config/i386/i386.c (ix86_elf_file_end): New. | |
16 | * config/i386/linux.h (TARGET_ASM_FILE_END): Defined. | |
17 | * config/i386/linux64.h (TARGET_ASM_FILE_END): Likewise. | |
18 | * config/ia64/hpux.h (TARGET_ASM_FILE_END): Removed. | |
19 | * config/ia64/ia64.c (ia64_hpux_add_extern_decl): Removed. | |
20 | (ia64_hpux_file_end): Renamed to ... | |
21 | (ia64_file_end): This. Handle symbol with non-default | |
22 | visibility. | |
23 | (TARGET_ASM_FILE_END): Defined. | |
24 | (ia64_asm_output_external): Rewritten. | |
25 | (extern_func_list): Removed. | |
26 | (extern_func_head): Likewise. | |
27 | * output.h (extern_symbol_list): New. | |
28 | (extern_symbol_head): New. | |
29 | (default_elf_asm_output_external): New. | |
30 | (default_elf_asm_output_external_1): New. | |
31 | (default_elf_asm_file_end): New. | |
32 | (maybe_assemble_visibility): New. | |
33 | * varasm.c (maybe_assemble_visibility): Make it extern and | |
34 | return int. | |
35 | (extern_symbol_head): New. | |
36 | (default_elf_asm_output_external_1): New. | |
37 | (default_elf_asm_output_external): New. | |
38 | (default_elf_asm_file_end): New. | |
39 | ||
40 | --- gcc/config/elfos.h.global 2004-10-18 09:14:38.000000000 -0700 | |
41 | +++ gcc/config/elfos.h 2005-02-28 12:23:53.013906179 -0800 | |
42 | @@ -487,3 +487,17 @@ Boston, MA 02111-1307, USA. */ | |
43 | fprintf ((FILE), "\"\n"); \ | |
44 | } \ | |
45 | while (0) | |
46 | + | |
47 | +/* A C statement (sans semicolon) to output to the stdio stream STREAM | |
48 | + any text necessary for declaring the name of an external symbol | |
49 | + named NAME whch is referenced in this compilation but not defined. | |
50 | + It is needed to properly support non-default visibility. */ | |
51 | + | |
52 | +#ifndef ASM_OUTPUT_EXTERNAL | |
53 | +#define ASM_OUTPUT_EXTERNAL(FILE, DECL, NAME) \ | |
54 | + default_elf_asm_output_external (FILE, DECL, NAME) | |
55 | +#endif | |
56 | + | |
57 | +#ifndef TARGET_ASM_FILE_END | |
58 | +#define TARGET_ASM_FILE_END default_elf_asm_file_end | |
59 | +#endif | |
60 | --- gcc/config/i386/i386-protos.h.global 2005-02-01 17:41:25.000000000 -0800 | |
61 | +++ gcc/config/i386/i386-protos.h 2005-02-28 13:10:37.406053326 -0800 | |
62 | @@ -28,6 +28,7 @@ extern int ix86_frame_pointer_required ( | |
63 | extern void ix86_setup_frame_addresses (void); | |
64 | ||
65 | extern void ix86_file_end (void); | |
66 | +extern void ix86_elf_file_end (void); | |
67 | extern HOST_WIDE_INT ix86_initial_elimination_offset (int, int); | |
68 | extern void ix86_expand_prologue (void); | |
69 | extern void ix86_expand_epilogue (int); | |
70 | --- gcc/config/i386/i386.c.global 2005-02-27 22:26:51.000000000 -0800 | |
71 | +++ gcc/config/i386/i386.c 2005-02-28 13:09:58.402099944 -0800 | |
72 | @@ -3937,6 +3937,13 @@ ix86_file_end (void) | |
73 | file_end_indicate_exec_stack (); | |
74 | } | |
75 | ||
76 | +void | |
77 | +ix86_elf_file_end (void) | |
78 | +{ | |
79 | + ix86_file_end (); | |
80 | + default_elf_asm_file_end (); | |
81 | +} | |
82 | + | |
83 | /* Emit code for the SET_GOT patterns. */ | |
84 | ||
85 | const char * | |
86 | --- gcc/config/i386/linux.h.global 2004-11-28 17:04:42.000000000 -0800 | |
87 | +++ gcc/config/i386/linux.h 2005-02-28 13:12:28.068734976 -0800 | |
88 | @@ -185,3 +185,6 @@ Boston, MA 02111-1307, USA. */ | |
89 | ||
90 | /* This macro may be overridden in i386/k*bsd-gnu.h. */ | |
91 | #define REG_NAME(reg) reg | |
92 | + | |
93 | +#undef TARGET_ASM_FILE_END | |
94 | +#define TARGET_ASM_FILE_END ix86_elf_file_end | |
95 | --- gcc/config/i386/linux64.h.global 2004-11-28 17:04:42.000000000 -0800 | |
96 | +++ gcc/config/i386/linux64.h 2005-02-28 13:22:53.285839795 -0800 | |
97 | @@ -73,3 +73,6 @@ Boston, MA 02111-1307, USA. */ | |
98 | ||
99 | /* This macro may be overridden in i386/k*bsd-gnu.h. */ | |
100 | #define REG_NAME(reg) reg | |
101 | + | |
102 | +#undef TARGET_ASM_FILE_END | |
103 | +#define TARGET_ASM_FILE_END ix86_elf_file_end | |
104 | --- gcc/config/ia64/hpux.h.global 2005-02-27 22:10:57.000000000 -0800 | |
105 | +++ gcc/config/ia64/hpux.h 2005-02-28 11:28:57.000000000 -0800 | |
106 | @@ -152,10 +152,6 @@ do { \ | |
107 | definitions, so do not use them in gthr-posix.h. */ | |
108 | #define GTHREAD_USE_WEAK 0 | |
109 | ||
110 | -/* Put out the needed function declarations at the end. */ | |
111 | - | |
112 | -#define TARGET_ASM_FILE_END ia64_hpux_file_end | |
113 | - | |
114 | #undef CTORS_SECTION_ASM_OP | |
115 | #define CTORS_SECTION_ASM_OP "\t.section\t.init_array,\t\"aw\",\"init_array\"" | |
116 | ||
117 | --- gcc/config/ia64/ia64.c.global 2005-02-23 11:26:35.000000000 -0800 | |
118 | +++ gcc/config/ia64/ia64.c 2005-02-28 13:37:55.304919908 -0800 | |
119 | @@ -248,6 +248,7 @@ static void bundling (FILE *, int, rtx, | |
120 | static void ia64_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, | |
121 | HOST_WIDE_INT, tree); | |
122 | static void ia64_file_start (void); | |
123 | +static void ia64_file_end (void); | |
124 | ||
125 | static void ia64_select_rtx_section (enum machine_mode, rtx, | |
126 | unsigned HOST_WIDE_INT); | |
127 | @@ -259,10 +260,6 @@ static void ia64_rwreloc_select_rtx_sect | |
128 | unsigned HOST_WIDE_INT) | |
129 | ATTRIBUTE_UNUSED; | |
130 | static unsigned int ia64_section_type_flags (tree, const char *, int); | |
131 | -static void ia64_hpux_add_extern_decl (tree decl) | |
132 | - ATTRIBUTE_UNUSED; | |
133 | -static void ia64_hpux_file_end (void) | |
134 | - ATTRIBUTE_UNUSED; | |
135 | static void ia64_init_libfuncs (void) | |
136 | ATTRIBUTE_UNUSED; | |
137 | static void ia64_hpux_init_libfuncs (void) | |
138 | @@ -374,6 +371,9 @@ static const struct attribute_spec ia64_ | |
139 | #undef TARGET_ASM_FILE_START | |
140 | #define TARGET_ASM_FILE_START ia64_file_start | |
141 | ||
142 | +#undef TARGET_ASM_FILE_END | |
143 | +#define TARGET_ASM_FILE_END ia64_file_end | |
144 | + | |
145 | #undef TARGET_RTX_COSTS | |
146 | #define TARGET_RTX_COSTS ia64_rtx_costs | |
147 | #undef TARGET_ADDRESS_COST | |
148 | @@ -4493,41 +4493,21 @@ ia64_secondary_reload_class (enum reg_cl | |
149 | void | |
150 | ia64_asm_output_external (FILE *file, tree decl, const char *name) | |
151 | { | |
152 | - int save_referenced; | |
153 | - | |
154 | - /* GNU as does not need anything here, but the HP linker does need | |
155 | - something for external functions. */ | |
156 | - | |
157 | - if (TARGET_GNU_AS | |
158 | - && (!TARGET_HPUX_LD | |
159 | - || TREE_CODE (decl) != FUNCTION_DECL | |
160 | - || strstr (name, "__builtin_") == name)) | |
161 | - return; | |
162 | - | |
163 | /* ??? The Intel assembler creates a reference that needs to be satisfied by | |
164 | the linker when we do this, so we need to be careful not to do this for | |
165 | builtin functions which have no library equivalent. Unfortunately, we | |
166 | can't tell here whether or not a function will actually be called by | |
167 | expand_expr, so we pull in library functions even if we may not need | |
168 | them later. */ | |
169 | - if (! strcmp (name, "__builtin_next_arg") | |
170 | - || ! strcmp (name, "alloca") | |
171 | - || ! strcmp (name, "__builtin_constant_p") | |
172 | - || ! strcmp (name, "__builtin_args_info")) | |
173 | + if (TREE_CODE (decl) == FUNCTION_DECL | |
174 | + && ((TARGET_GNU_AS && strstr (name, "__builtin_") == name) | |
175 | + || (!strcmp (name, "__builtin_next_arg") | |
176 | + || ! strcmp (name, "alloca") | |
177 | + || ! strcmp (name, "__builtin_constant_p") | |
178 | + || ! strcmp (name, "__builtin_args_info")))) | |
179 | return; | |
180 | ||
181 | - if (TARGET_HPUX_LD) | |
182 | - ia64_hpux_add_extern_decl (decl); | |
183 | - else | |
184 | - { | |
185 | - /* assemble_name will set TREE_SYMBOL_REFERENCED, so we must save and | |
186 | - restore it. */ | |
187 | - save_referenced = TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)); | |
188 | - if (TREE_CODE (decl) == FUNCTION_DECL) | |
189 | - ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function"); | |
190 | - (*targetm.asm_out.globalize_label) (file, name); | |
191 | - TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) = save_referenced; | |
192 | - } | |
193 | + default_elf_asm_output_external_1 (decl); | |
194 | } | |
195 | \f | |
196 | /* Parse the -mfixed-range= option string. */ | |
197 | @@ -8472,36 +8452,16 @@ ia64_hpux_function_arg_padding (enum mac | |
198 | return DEFAULT_FUNCTION_ARG_PADDING (mode, type); | |
199 | } | |
200 | ||
201 | -/* Linked list of all external functions that are to be emitted by GCC. | |
202 | - We output the name if and only if TREE_SYMBOL_REFERENCED is set in | |
203 | - order to avoid putting out names that are never really used. */ | |
204 | - | |
205 | -struct extern_func_list GTY(()) | |
206 | -{ | |
207 | - struct extern_func_list *next; | |
208 | - tree decl; | |
209 | -}; | |
210 | - | |
211 | -static GTY(()) struct extern_func_list *extern_func_head; | |
212 | - | |
213 | -static void | |
214 | -ia64_hpux_add_extern_decl (tree decl) | |
215 | -{ | |
216 | - struct extern_func_list *p = ggc_alloc (sizeof (struct extern_func_list)); | |
217 | - | |
218 | - p->decl = decl; | |
219 | - p->next = extern_func_head; | |
220 | - extern_func_head = p; | |
221 | -} | |
222 | - | |
223 | /* Print out the list of used global functions. */ | |
224 | ||
225 | static void | |
226 | -ia64_hpux_file_end (void) | |
227 | +ia64_file_end (void) | |
228 | { | |
229 | - struct extern_func_list *p; | |
230 | + struct extern_symbol_list *p; | |
231 | + int hpld = TARGET_HPUX_LD; | |
232 | + int gas = TARGET_GNU_AS; | |
233 | ||
234 | - for (p = extern_func_head; p; p = p->next) | |
235 | + for (p = extern_symbol_head; p; p = p->next) | |
236 | { | |
237 | tree decl = p->decl; | |
238 | tree id = DECL_ASSEMBLER_NAME (decl); | |
239 | @@ -8510,18 +8470,27 @@ ia64_hpux_file_end (void) | |
240 | abort (); | |
241 | ||
242 | if (!TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (id)) | |
243 | - { | |
244 | + { | |
245 | + int vis = maybe_assemble_visibility (decl); | |
246 | const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0); | |
247 | ||
248 | + /* GNU as does not need anything here, but the HP linker | |
249 | + does need something for external functions. */ | |
250 | + if ((hpld || !gas) | |
251 | + && TREE_CODE (decl) == FUNCTION_DECL) | |
252 | + { | |
253 | + ASM_OUTPUT_TYPE_DIRECTIVE (asm_out_file, name, | |
254 | + "function"); | |
255 | + (*targetm.asm_out.globalize_label) (asm_out_file, name); | |
256 | + } | |
257 | + else if (vis && !gas) | |
258 | + (*targetm.asm_out.globalize_label) (asm_out_file, name); | |
259 | + | |
260 | TREE_ASM_WRITTEN (decl) = 1; | |
261 | - (*targetm.asm_out.globalize_label) (asm_out_file, name); | |
262 | - fputs (TYPE_ASM_OP, asm_out_file); | |
263 | - assemble_name (asm_out_file, name); | |
264 | - fprintf (asm_out_file, "," TYPE_OPERAND_FMT "\n", "function"); | |
265 | } | |
266 | } | |
267 | ||
268 | - extern_func_head = 0; | |
269 | + extern_symbol_head = 0; | |
270 | } | |
271 | ||
272 | /* Set SImode div/mod functions, init_integral_libfuncs only initializes | |
273 | --- gcc/output.h.global 2005-01-19 09:55:57.000000000 -0800 | |
274 | +++ gcc/output.h 2005-02-28 13:20:05.017611574 -0800 | |
275 | @@ -517,6 +517,23 @@ extern void default_file_start (void); | |
276 | extern void file_end_indicate_exec_stack (void); | |
277 | extern bool default_valid_pointer_mode (enum machine_mode); | |
278 | ||
279 | +/* Linked list of all external symbols that are to be emitted by | |
280 | + GCC. */ | |
281 | + | |
282 | +struct extern_symbol_list GTY(()) | |
283 | +{ | |
284 | + struct extern_symbol_list *next; | |
285 | + tree decl; | |
286 | +}; | |
287 | + | |
288 | +extern GTY(()) struct extern_symbol_list *extern_symbol_head; | |
289 | + | |
290 | +extern void default_elf_asm_output_external (FILE *file, tree, | |
291 | + const char *); | |
292 | +extern void default_elf_asm_output_external_1 (tree); | |
293 | +extern void default_elf_asm_file_end (void); | |
294 | +extern int maybe_assemble_visibility (tree); | |
295 | + | |
296 | extern int default_address_cost (rtx); | |
297 | ||
298 | /* dbxout helper functions */ | |
299 | --- gcc/varasm.c.global 2005-02-27 22:26:51.000000000 -0800 | |
300 | +++ gcc/varasm.c 2005-02-28 13:17:40.865263064 -0800 | |
301 | @@ -137,7 +137,6 @@ static unsigned HOST_WIDE_INT array_size | |
302 | static unsigned min_align (unsigned, unsigned); | |
303 | static void output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int); | |
304 | static void globalize_decl (tree); | |
305 | -static void maybe_assemble_visibility (tree); | |
306 | static int in_named_entry_eq (const void *, const void *); | |
307 | static hashval_t in_named_entry_hash (const void *); | |
308 | #ifdef BSS_SECTION_ASM_OP | |
309 | @@ -4535,13 +4534,18 @@ default_assemble_visibility (tree decl, | |
310 | ||
311 | /* A helper function to call assemble_visibility when needed for a decl. */ | |
312 | ||
313 | -static void | |
314 | +int | |
315 | maybe_assemble_visibility (tree decl) | |
316 | { | |
317 | enum symbol_visibility vis = DECL_VISIBILITY (decl); | |
318 | ||
319 | if (vis != VISIBILITY_DEFAULT) | |
320 | - targetm.asm_out.visibility (decl, vis); | |
321 | + { | |
322 | + targetm.asm_out.visibility (decl, vis); | |
323 | + return 1; | |
324 | + } | |
325 | + else | |
326 | + return 0; | |
327 | } | |
328 | ||
329 | /* Returns 1 if the target configuration supports defining public symbols | |
330 | @@ -5360,4 +5364,62 @@ file_end_indicate_exec_stack (void) | |
331 | named_section_flags (".note.GNU-stack", flags); | |
332 | } | |
333 | ||
334 | +struct extern_symbol_list *extern_symbol_head; | |
335 | + | |
336 | +void | |
337 | +default_elf_asm_output_external_1 (tree decl) | |
338 | +{ | |
339 | + struct extern_symbol_list *p | |
340 | + = ggc_alloc (sizeof (struct extern_symbol_list)); | |
341 | + | |
342 | + p->decl = decl; | |
343 | + p->next = extern_symbol_head; | |
344 | + extern_symbol_head = p; | |
345 | +} | |
346 | + | |
347 | +/* Emit text to declare externally defined symbols. It is needed to | |
348 | + properly support non-default visibility. */ | |
349 | + | |
350 | +void | |
351 | +default_elf_asm_output_external (FILE *file ATTRIBUTE_UNUSED, | |
352 | + tree decl, | |
353 | + const char *name) | |
354 | +{ | |
355 | + /* Ignore builtin functions. */ | |
356 | + if (TREE_CODE (decl) == FUNCTION_DECL | |
357 | + && strstr (name, "__builtin_") == name) | |
358 | + return; | |
359 | + else | |
360 | + default_elf_asm_output_external_1 (decl); | |
361 | +} | |
362 | + | |
363 | +/* Print out the list of referenced global symbols with non-default | |
364 | + visibility. */ | |
365 | + | |
366 | +void | |
367 | +default_elf_asm_file_end (void) | |
368 | +{ | |
369 | + struct extern_symbol_list *p; | |
370 | + | |
371 | + for (p = extern_symbol_head; p; p = p->next) | |
372 | + { | |
373 | + tree decl = p->decl; | |
374 | + tree id = DECL_ASSEMBLER_NAME (decl); | |
375 | + | |
376 | + if (!id) | |
377 | + abort (); | |
378 | + | |
379 | + /* We output the name if and only if TREE_SYMBOL_REFERENCED is | |
380 | + set in order to avoid putting out names that are never really | |
381 | + used. */ | |
382 | + if (!TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (id)) | |
383 | + { | |
384 | + maybe_assemble_visibility (decl); | |
385 | + TREE_ASM_WRITTEN (decl) = 1; | |
386 | + } | |
387 | + } | |
388 | + | |
389 | + extern_symbol_head = 0; | |
390 | +} | |
391 | + | |
392 | #include "gt-varasm.h" |