1*404b540aSrobert /* Functions for generic Darwin as target machine for GNU C compiler.
2*404b540aSrobert Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001, 2002, 2003, 2004,
3*404b540aSrobert 2005
4*404b540aSrobert Free Software Foundation, Inc.
5*404b540aSrobert Contributed by Apple Computer Inc.
6*404b540aSrobert
7*404b540aSrobert This file is part of GCC.
8*404b540aSrobert
9*404b540aSrobert GCC is free software; you can redistribute it and/or modify
10*404b540aSrobert it under the terms of the GNU General Public License as published by
11*404b540aSrobert the Free Software Foundation; either version 2, or (at your option)
12*404b540aSrobert any later version.
13*404b540aSrobert
14*404b540aSrobert GCC is distributed in the hope that it will be useful,
15*404b540aSrobert but WITHOUT ANY WARRANTY; without even the implied warranty of
16*404b540aSrobert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17*404b540aSrobert GNU General Public License for more details.
18*404b540aSrobert
19*404b540aSrobert You should have received a copy of the GNU General Public License
20*404b540aSrobert along with GCC; see the file COPYING. If not, write to
21*404b540aSrobert the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22*404b540aSrobert Boston, MA 02110-1301, USA. */
23*404b540aSrobert
24*404b540aSrobert #include "config.h"
25*404b540aSrobert #include "system.h"
26*404b540aSrobert #include "coretypes.h"
27*404b540aSrobert #include "tm.h"
28*404b540aSrobert #include "rtl.h"
29*404b540aSrobert #include "regs.h"
30*404b540aSrobert #include "hard-reg-set.h"
31*404b540aSrobert #include "real.h"
32*404b540aSrobert #include "insn-config.h"
33*404b540aSrobert #include "conditions.h"
34*404b540aSrobert #include "insn-flags.h"
35*404b540aSrobert #include "output.h"
36*404b540aSrobert #include "insn-attr.h"
37*404b540aSrobert #include "flags.h"
38*404b540aSrobert #include "tree.h"
39*404b540aSrobert #include "expr.h"
40*404b540aSrobert #include "reload.h"
41*404b540aSrobert #include "function.h"
42*404b540aSrobert #include "ggc.h"
43*404b540aSrobert #include "langhooks.h"
44*404b540aSrobert #include "target.h"
45*404b540aSrobert #include "tm_p.h"
46*404b540aSrobert #include "toplev.h"
47*404b540aSrobert #include "hashtab.h"
48*404b540aSrobert
49*404b540aSrobert /* Darwin supports a feature called fix-and-continue, which is used
50*404b540aSrobert for rapid turn around debugging. When code is compiled with the
51*404b540aSrobert -mfix-and-continue flag, two changes are made to the generated code
52*404b540aSrobert that allow the system to do things that it would normally not be
53*404b540aSrobert able to do easily. These changes allow gdb to load in
54*404b540aSrobert recompilation of a translation unit that has been changed into a
55*404b540aSrobert running program and replace existing functions and methods of that
56*404b540aSrobert translation unit with versions of those functions and methods
57*404b540aSrobert from the newly compiled translation unit. The new functions access
58*404b540aSrobert the existing static symbols from the old translation unit, if the
59*404b540aSrobert symbol existed in the unit to be replaced, and from the new
60*404b540aSrobert translation unit, otherwise.
61*404b540aSrobert
62*404b540aSrobert The changes are to insert 5 nops at the beginning of all functions
63*404b540aSrobert and to use indirection to get at static symbols. The 5 nops
64*404b540aSrobert are required by consumers of the generated code. Currently, gdb
65*404b540aSrobert uses this to patch in a jump to the overriding function, this
66*404b540aSrobert allows all uses of the old name to forward to the replacement,
67*404b540aSrobert including existing function pointers and virtual methods. See
68*404b540aSrobert rs6000_emit_prologue for the code that handles the nop insertions.
69*404b540aSrobert
70*404b540aSrobert The added indirection allows gdb to redirect accesses to static
71*404b540aSrobert symbols from the newly loaded translation unit to the existing
72*404b540aSrobert symbol, if any. @code{static} symbols are special and are handled by
73*404b540aSrobert setting the second word in the .non_lazy_symbol_pointer data
74*404b540aSrobert structure to symbol. See indirect_data for the code that handles
75*404b540aSrobert the extra indirection, and machopic_output_indirection and its use
76*404b540aSrobert of MACHO_SYMBOL_STATIC for the code that handles @code{static}
77*404b540aSrobert symbol indirection. */
78*404b540aSrobert
79*404b540aSrobert /* Section names. */
80*404b540aSrobert section * darwin_sections[NUM_DARWIN_SECTIONS];
81*404b540aSrobert
82*404b540aSrobert /* True if we're setting __attribute__ ((ms_struct)). */
83*404b540aSrobert int darwin_ms_struct = false;
84*404b540aSrobert
85*404b540aSrobert /* A get_unnamed_section callback used to switch to an ObjC section.
86*404b540aSrobert DIRECTIVE is as for output_section_asm_op. */
87*404b540aSrobert
88*404b540aSrobert static void
output_objc_section_asm_op(const void * directive)89*404b540aSrobert output_objc_section_asm_op (const void *directive)
90*404b540aSrobert {
91*404b540aSrobert static bool been_here = false;
92*404b540aSrobert
93*404b540aSrobert if (! been_here)
94*404b540aSrobert {
95*404b540aSrobert static const enum darwin_section_enum tomark[] =
96*404b540aSrobert {
97*404b540aSrobert /* written, cold -> hot */
98*404b540aSrobert objc_cat_cls_meth_section,
99*404b540aSrobert objc_cat_inst_meth_section,
100*404b540aSrobert objc_string_object_section,
101*404b540aSrobert objc_constant_string_object_section,
102*404b540aSrobert objc_selector_refs_section,
103*404b540aSrobert objc_selector_fixup_section,
104*404b540aSrobert objc_cls_refs_section,
105*404b540aSrobert objc_class_section,
106*404b540aSrobert objc_meta_class_section,
107*404b540aSrobert /* shared, hot -> cold */
108*404b540aSrobert objc_cls_meth_section,
109*404b540aSrobert objc_inst_meth_section,
110*404b540aSrobert objc_protocol_section,
111*404b540aSrobert objc_class_names_section,
112*404b540aSrobert objc_meth_var_types_section,
113*404b540aSrobert objc_meth_var_names_section,
114*404b540aSrobert objc_category_section,
115*404b540aSrobert objc_class_vars_section,
116*404b540aSrobert objc_instance_vars_section,
117*404b540aSrobert objc_module_info_section,
118*404b540aSrobert objc_symbols_section
119*404b540aSrobert };
120*404b540aSrobert size_t i;
121*404b540aSrobert
122*404b540aSrobert been_here = true;
123*404b540aSrobert for (i = 0; i < ARRAY_SIZE (tomark); i++)
124*404b540aSrobert switch_to_section (darwin_sections[tomark[i]]);
125*404b540aSrobert }
126*404b540aSrobert output_section_asm_op (directive);
127*404b540aSrobert }
128*404b540aSrobert
129*404b540aSrobert /* Implement TARGET_ASM_INIT_SECTIONS. */
130*404b540aSrobert
131*404b540aSrobert void
darwin_init_sections(void)132*404b540aSrobert darwin_init_sections (void)
133*404b540aSrobert {
134*404b540aSrobert #define DEF_SECTION(NAME, FLAGS, DIRECTIVE, OBJC) \
135*404b540aSrobert darwin_sections[NAME] = \
136*404b540aSrobert get_unnamed_section (FLAGS, (OBJC \
137*404b540aSrobert ? output_objc_section_asm_op \
138*404b540aSrobert : output_section_asm_op), \
139*404b540aSrobert "\t" DIRECTIVE);
140*404b540aSrobert #include "config/darwin-sections.def"
141*404b540aSrobert #undef DEF_SECTION
142*404b540aSrobert
143*404b540aSrobert readonly_data_section = darwin_sections[const_section];
144*404b540aSrobert exception_section = darwin_sections[darwin_exception_section];
145*404b540aSrobert eh_frame_section = darwin_sections[darwin_eh_frame_section];
146*404b540aSrobert }
147*404b540aSrobert
148*404b540aSrobert int
name_needs_quotes(const char * name)149*404b540aSrobert name_needs_quotes (const char *name)
150*404b540aSrobert {
151*404b540aSrobert int c;
152*404b540aSrobert while ((c = *name++) != '\0')
153*404b540aSrobert if (! ISIDNUM (c) && c != '.' && c != '$')
154*404b540aSrobert return 1;
155*404b540aSrobert return 0;
156*404b540aSrobert }
157*404b540aSrobert
158*404b540aSrobert /* Return true if SYM_REF can be used without an indirection. */
159*404b540aSrobert static int
machopic_symbol_defined_p(rtx sym_ref)160*404b540aSrobert machopic_symbol_defined_p (rtx sym_ref)
161*404b540aSrobert {
162*404b540aSrobert if (SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_DEFINED)
163*404b540aSrobert return true;
164*404b540aSrobert
165*404b540aSrobert /* If a symbol references local and is not an extern to this
166*404b540aSrobert file, then the symbol might be able to declared as defined. */
167*404b540aSrobert if (SYMBOL_REF_LOCAL_P (sym_ref) && ! SYMBOL_REF_EXTERNAL_P (sym_ref))
168*404b540aSrobert {
169*404b540aSrobert /* If the symbol references a variable and the variable is a
170*404b540aSrobert common symbol, then this symbol is not defined. */
171*404b540aSrobert if (SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_VARIABLE)
172*404b540aSrobert {
173*404b540aSrobert tree decl = SYMBOL_REF_DECL (sym_ref);
174*404b540aSrobert if (!decl)
175*404b540aSrobert return true;
176*404b540aSrobert if (DECL_COMMON (decl))
177*404b540aSrobert return false;
178*404b540aSrobert }
179*404b540aSrobert return true;
180*404b540aSrobert }
181*404b540aSrobert return false;
182*404b540aSrobert }
183*404b540aSrobert
184*404b540aSrobert /* This module assumes that (const (symbol_ref "foo")) is a legal pic
185*404b540aSrobert reference, which will not be changed. */
186*404b540aSrobert
187*404b540aSrobert enum machopic_addr_class
machopic_classify_symbol(rtx sym_ref)188*404b540aSrobert machopic_classify_symbol (rtx sym_ref)
189*404b540aSrobert {
190*404b540aSrobert int flags;
191*404b540aSrobert bool function_p;
192*404b540aSrobert
193*404b540aSrobert flags = SYMBOL_REF_FLAGS (sym_ref);
194*404b540aSrobert function_p = SYMBOL_REF_FUNCTION_P (sym_ref);
195*404b540aSrobert if (machopic_symbol_defined_p (sym_ref))
196*404b540aSrobert return (function_p
197*404b540aSrobert ? MACHOPIC_DEFINED_FUNCTION : MACHOPIC_DEFINED_DATA);
198*404b540aSrobert else
199*404b540aSrobert return (function_p
200*404b540aSrobert ? MACHOPIC_UNDEFINED_FUNCTION : MACHOPIC_UNDEFINED_DATA);
201*404b540aSrobert }
202*404b540aSrobert
203*404b540aSrobert #ifndef TARGET_FIX_AND_CONTINUE
204*404b540aSrobert #define TARGET_FIX_AND_CONTINUE 0
205*404b540aSrobert #endif
206*404b540aSrobert
207*404b540aSrobert /* Indicate when fix-and-continue style code generation is being used
208*404b540aSrobert and when a reference to data should be indirected so that it can be
209*404b540aSrobert rebound in a new translation unit to reference the original instance
210*404b540aSrobert of that data. Symbol names that are for code generation local to
211*404b540aSrobert the translation unit are bound to the new translation unit;
212*404b540aSrobert currently this means symbols that begin with L or _OBJC_;
213*404b540aSrobert otherwise, we indicate that an indirect reference should be made to
214*404b540aSrobert permit the runtime to rebind new instances of the translation unit
215*404b540aSrobert to the original instance of the data. */
216*404b540aSrobert
217*404b540aSrobert static int
indirect_data(rtx sym_ref)218*404b540aSrobert indirect_data (rtx sym_ref)
219*404b540aSrobert {
220*404b540aSrobert int lprefix;
221*404b540aSrobert const char *name;
222*404b540aSrobert
223*404b540aSrobert /* If we aren't generating fix-and-continue code, don't do anything special. */
224*404b540aSrobert if (TARGET_FIX_AND_CONTINUE == 0)
225*404b540aSrobert return 0;
226*404b540aSrobert
227*404b540aSrobert /* Otherwise, all symbol except symbols that begin with L or _OBJC_
228*404b540aSrobert are indirected. Symbols that begin with L and _OBJC_ are always
229*404b540aSrobert bound to the current translation unit as they are used for
230*404b540aSrobert generated local data of the translation unit. */
231*404b540aSrobert
232*404b540aSrobert name = XSTR (sym_ref, 0);
233*404b540aSrobert
234*404b540aSrobert lprefix = (((name[0] == '*' || name[0] == '&')
235*404b540aSrobert && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
236*404b540aSrobert || (strncmp (name, "_OBJC_", 6) == 0));
237*404b540aSrobert
238*404b540aSrobert return ! lprefix;
239*404b540aSrobert }
240*404b540aSrobert
241*404b540aSrobert
242*404b540aSrobert static int
machopic_data_defined_p(rtx sym_ref)243*404b540aSrobert machopic_data_defined_p (rtx sym_ref)
244*404b540aSrobert {
245*404b540aSrobert if (indirect_data (sym_ref))
246*404b540aSrobert return 0;
247*404b540aSrobert
248*404b540aSrobert switch (machopic_classify_symbol (sym_ref))
249*404b540aSrobert {
250*404b540aSrobert case MACHOPIC_DEFINED_DATA:
251*404b540aSrobert case MACHOPIC_DEFINED_FUNCTION:
252*404b540aSrobert return 1;
253*404b540aSrobert default:
254*404b540aSrobert return 0;
255*404b540aSrobert }
256*404b540aSrobert }
257*404b540aSrobert
258*404b540aSrobert void
machopic_define_symbol(rtx mem)259*404b540aSrobert machopic_define_symbol (rtx mem)
260*404b540aSrobert {
261*404b540aSrobert rtx sym_ref;
262*404b540aSrobert
263*404b540aSrobert gcc_assert (GET_CODE (mem) == MEM);
264*404b540aSrobert sym_ref = XEXP (mem, 0);
265*404b540aSrobert SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
266*404b540aSrobert }
267*404b540aSrobert
268*404b540aSrobert static GTY(()) char * function_base;
269*404b540aSrobert
270*404b540aSrobert const char *
machopic_function_base_name(void)271*404b540aSrobert machopic_function_base_name (void)
272*404b540aSrobert {
273*404b540aSrobert /* if dynamic-no-pic is on, we should not get here */
274*404b540aSrobert gcc_assert (!MACHO_DYNAMIC_NO_PIC_P);
275*404b540aSrobert
276*404b540aSrobert if (function_base == NULL)
277*404b540aSrobert function_base =
278*404b540aSrobert (char *) ggc_alloc_string ("<pic base>", sizeof ("<pic base>"));
279*404b540aSrobert
280*404b540aSrobert current_function_uses_pic_offset_table = 1;
281*404b540aSrobert
282*404b540aSrobert return function_base;
283*404b540aSrobert }
284*404b540aSrobert
285*404b540aSrobert /* Return a SYMBOL_REF for the PIC function base. */
286*404b540aSrobert
287*404b540aSrobert rtx
machopic_function_base_sym(void)288*404b540aSrobert machopic_function_base_sym (void)
289*404b540aSrobert {
290*404b540aSrobert rtx sym_ref;
291*404b540aSrobert
292*404b540aSrobert sym_ref = gen_rtx_SYMBOL_REF (Pmode, machopic_function_base_name ());
293*404b540aSrobert SYMBOL_REF_FLAGS (sym_ref)
294*404b540aSrobert |= (MACHO_SYMBOL_FLAG_VARIABLE | MACHO_SYMBOL_FLAG_DEFINED);
295*404b540aSrobert return sym_ref;
296*404b540aSrobert }
297*404b540aSrobert
298*404b540aSrobert /* Return either ORIG or (const:P (minus:P ORIG PIC_BASE)), depending
299*404b540aSrobert on whether pic_base is NULL or not. */
300*404b540aSrobert static inline rtx
gen_pic_offset(rtx orig,rtx pic_base)301*404b540aSrobert gen_pic_offset (rtx orig, rtx pic_base)
302*404b540aSrobert {
303*404b540aSrobert if (!pic_base)
304*404b540aSrobert return orig;
305*404b540aSrobert else
306*404b540aSrobert return gen_rtx_CONST (Pmode, gen_rtx_MINUS (Pmode, orig, pic_base));
307*404b540aSrobert }
308*404b540aSrobert
309*404b540aSrobert static GTY(()) const char * function_base_func_name;
310*404b540aSrobert static GTY(()) int current_pic_label_num;
311*404b540aSrobert
312*404b540aSrobert void
machopic_output_function_base_name(FILE * file)313*404b540aSrobert machopic_output_function_base_name (FILE *file)
314*404b540aSrobert {
315*404b540aSrobert const char *current_name;
316*404b540aSrobert
317*404b540aSrobert /* If dynamic-no-pic is on, we should not get here. */
318*404b540aSrobert gcc_assert (!MACHO_DYNAMIC_NO_PIC_P);
319*404b540aSrobert current_name =
320*404b540aSrobert IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
321*404b540aSrobert if (function_base_func_name != current_name)
322*404b540aSrobert {
323*404b540aSrobert ++current_pic_label_num;
324*404b540aSrobert function_base_func_name = current_name;
325*404b540aSrobert }
326*404b540aSrobert fprintf (file, "\"L%011d$pb\"", current_pic_label_num);
327*404b540aSrobert }
328*404b540aSrobert
329*404b540aSrobert /* The suffix attached to non-lazy pointer symbols. */
330*404b540aSrobert #define NON_LAZY_POINTER_SUFFIX "$non_lazy_ptr"
331*404b540aSrobert /* The suffix attached to stub symbols. */
332*404b540aSrobert #define STUB_SUFFIX "$stub"
333*404b540aSrobert
334*404b540aSrobert typedef struct machopic_indirection GTY (())
335*404b540aSrobert {
336*404b540aSrobert /* The SYMBOL_REF for the entity referenced. */
337*404b540aSrobert rtx symbol;
338*404b540aSrobert /* The name of the stub or non-lazy pointer. */
339*404b540aSrobert const char * ptr_name;
340*404b540aSrobert /* True iff this entry is for a stub (as opposed to a non-lazy
341*404b540aSrobert pointer). */
342*404b540aSrobert bool stub_p;
343*404b540aSrobert /* True iff this stub or pointer pointer has been referenced. */
344*404b540aSrobert bool used;
345*404b540aSrobert } machopic_indirection;
346*404b540aSrobert
347*404b540aSrobert /* A table mapping stub names and non-lazy pointer names to
348*404b540aSrobert SYMBOL_REFs for the stubbed-to and pointed-to entities. */
349*404b540aSrobert
350*404b540aSrobert static GTY ((param_is (struct machopic_indirection))) htab_t
351*404b540aSrobert machopic_indirections;
352*404b540aSrobert
353*404b540aSrobert /* Return a hash value for a SLOT in the indirections hash table. */
354*404b540aSrobert
355*404b540aSrobert static hashval_t
machopic_indirection_hash(const void * slot)356*404b540aSrobert machopic_indirection_hash (const void *slot)
357*404b540aSrobert {
358*404b540aSrobert const machopic_indirection *p = (const machopic_indirection *) slot;
359*404b540aSrobert return htab_hash_string (p->ptr_name);
360*404b540aSrobert }
361*404b540aSrobert
362*404b540aSrobert /* Returns true if the KEY is the same as that associated with
363*404b540aSrobert SLOT. */
364*404b540aSrobert
365*404b540aSrobert static int
machopic_indirection_eq(const void * slot,const void * key)366*404b540aSrobert machopic_indirection_eq (const void *slot, const void *key)
367*404b540aSrobert {
368*404b540aSrobert return strcmp (((const machopic_indirection *) slot)->ptr_name, key) == 0;
369*404b540aSrobert }
370*404b540aSrobert
371*404b540aSrobert /* Return the name of the non-lazy pointer (if STUB_P is false) or
372*404b540aSrobert stub (if STUB_B is true) corresponding to the given name. */
373*404b540aSrobert
374*404b540aSrobert const char *
machopic_indirection_name(rtx sym_ref,bool stub_p)375*404b540aSrobert machopic_indirection_name (rtx sym_ref, bool stub_p)
376*404b540aSrobert {
377*404b540aSrobert char *buffer;
378*404b540aSrobert const char *name = XSTR (sym_ref, 0);
379*404b540aSrobert size_t namelen = strlen (name);
380*404b540aSrobert machopic_indirection *p;
381*404b540aSrobert void ** slot;
382*404b540aSrobert bool saw_star = false;
383*404b540aSrobert bool needs_quotes;
384*404b540aSrobert const char *suffix;
385*404b540aSrobert const char *prefix = user_label_prefix;
386*404b540aSrobert const char *quote = "";
387*404b540aSrobert tree id;
388*404b540aSrobert
389*404b540aSrobert id = maybe_get_identifier (name);
390*404b540aSrobert if (id)
391*404b540aSrobert {
392*404b540aSrobert tree id_orig = id;
393*404b540aSrobert
394*404b540aSrobert while (IDENTIFIER_TRANSPARENT_ALIAS (id))
395*404b540aSrobert id = TREE_CHAIN (id);
396*404b540aSrobert if (id != id_orig)
397*404b540aSrobert {
398*404b540aSrobert name = IDENTIFIER_POINTER (id);
399*404b540aSrobert namelen = strlen (name);
400*404b540aSrobert }
401*404b540aSrobert }
402*404b540aSrobert
403*404b540aSrobert if (name[0] == '*')
404*404b540aSrobert {
405*404b540aSrobert saw_star = true;
406*404b540aSrobert prefix = "";
407*404b540aSrobert ++name;
408*404b540aSrobert --namelen;
409*404b540aSrobert }
410*404b540aSrobert
411*404b540aSrobert needs_quotes = name_needs_quotes (name);
412*404b540aSrobert if (needs_quotes)
413*404b540aSrobert {
414*404b540aSrobert quote = "\"";
415*404b540aSrobert }
416*404b540aSrobert
417*404b540aSrobert if (stub_p)
418*404b540aSrobert suffix = STUB_SUFFIX;
419*404b540aSrobert else
420*404b540aSrobert suffix = NON_LAZY_POINTER_SUFFIX;
421*404b540aSrobert
422*404b540aSrobert buffer = alloca (strlen ("&L")
423*404b540aSrobert + strlen (prefix)
424*404b540aSrobert + namelen
425*404b540aSrobert + strlen (suffix)
426*404b540aSrobert + 2 * strlen (quote)
427*404b540aSrobert + 1 /* '\0' */);
428*404b540aSrobert
429*404b540aSrobert /* Construct the name of the non-lazy pointer or stub. */
430*404b540aSrobert sprintf (buffer, "&%sL%s%s%s%s", quote, prefix, name, suffix, quote);
431*404b540aSrobert
432*404b540aSrobert if (!machopic_indirections)
433*404b540aSrobert machopic_indirections = htab_create_ggc (37,
434*404b540aSrobert machopic_indirection_hash,
435*404b540aSrobert machopic_indirection_eq,
436*404b540aSrobert /*htab_del=*/NULL);
437*404b540aSrobert
438*404b540aSrobert slot = htab_find_slot_with_hash (machopic_indirections, buffer,
439*404b540aSrobert htab_hash_string (buffer), INSERT);
440*404b540aSrobert if (*slot)
441*404b540aSrobert {
442*404b540aSrobert p = (machopic_indirection *) *slot;
443*404b540aSrobert }
444*404b540aSrobert else
445*404b540aSrobert {
446*404b540aSrobert p = (machopic_indirection *) ggc_alloc (sizeof (machopic_indirection));
447*404b540aSrobert p->symbol = sym_ref;
448*404b540aSrobert p->ptr_name = xstrdup (buffer);
449*404b540aSrobert p->stub_p = stub_p;
450*404b540aSrobert p->used = false;
451*404b540aSrobert *slot = p;
452*404b540aSrobert }
453*404b540aSrobert
454*404b540aSrobert return p->ptr_name;
455*404b540aSrobert }
456*404b540aSrobert
457*404b540aSrobert /* Return the name of the stub for the mcount function. */
458*404b540aSrobert
459*404b540aSrobert const char*
machopic_mcount_stub_name(void)460*404b540aSrobert machopic_mcount_stub_name (void)
461*404b540aSrobert {
462*404b540aSrobert rtx symbol = gen_rtx_SYMBOL_REF (Pmode, "*mcount");
463*404b540aSrobert return machopic_indirection_name (symbol, /*stub_p=*/true);
464*404b540aSrobert }
465*404b540aSrobert
466*404b540aSrobert /* If NAME is the name of a stub or a non-lazy pointer , mark the stub
467*404b540aSrobert or non-lazy pointer as used -- and mark the object to which the
468*404b540aSrobert pointer/stub refers as used as well, since the pointer/stub will
469*404b540aSrobert emit a reference to it. */
470*404b540aSrobert
471*404b540aSrobert void
machopic_validate_stub_or_non_lazy_ptr(const char * name)472*404b540aSrobert machopic_validate_stub_or_non_lazy_ptr (const char *name)
473*404b540aSrobert {
474*404b540aSrobert machopic_indirection *p;
475*404b540aSrobert
476*404b540aSrobert p = ((machopic_indirection *)
477*404b540aSrobert (htab_find_with_hash (machopic_indirections, name,
478*404b540aSrobert htab_hash_string (name))));
479*404b540aSrobert if (p && ! p->used)
480*404b540aSrobert {
481*404b540aSrobert const char *real_name;
482*404b540aSrobert tree id;
483*404b540aSrobert
484*404b540aSrobert p->used = true;
485*404b540aSrobert
486*404b540aSrobert /* Do what output_addr_const will do when we actually call it. */
487*404b540aSrobert if (SYMBOL_REF_DECL (p->symbol))
488*404b540aSrobert mark_decl_referenced (SYMBOL_REF_DECL (p->symbol));
489*404b540aSrobert
490*404b540aSrobert real_name = targetm.strip_name_encoding (XSTR (p->symbol, 0));
491*404b540aSrobert
492*404b540aSrobert id = maybe_get_identifier (real_name);
493*404b540aSrobert if (id)
494*404b540aSrobert mark_referenced (id);
495*404b540aSrobert }
496*404b540aSrobert }
497*404b540aSrobert
498*404b540aSrobert /* Transform ORIG, which may be any data source, to the corresponding
499*404b540aSrobert source using indirections. */
500*404b540aSrobert
501*404b540aSrobert rtx
machopic_indirect_data_reference(rtx orig,rtx reg)502*404b540aSrobert machopic_indirect_data_reference (rtx orig, rtx reg)
503*404b540aSrobert {
504*404b540aSrobert rtx ptr_ref = orig;
505*404b540aSrobert
506*404b540aSrobert if (! MACHOPIC_INDIRECT)
507*404b540aSrobert return orig;
508*404b540aSrobert
509*404b540aSrobert if (GET_CODE (orig) == SYMBOL_REF)
510*404b540aSrobert {
511*404b540aSrobert int defined = machopic_data_defined_p (orig);
512*404b540aSrobert
513*404b540aSrobert if (defined && MACHO_DYNAMIC_NO_PIC_P)
514*404b540aSrobert {
515*404b540aSrobert #if defined (TARGET_TOC)
516*404b540aSrobert /* Create a new register for CSE opportunities. */
517*404b540aSrobert rtx hi_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
518*404b540aSrobert emit_insn (gen_macho_high (hi_reg, orig));
519*404b540aSrobert emit_insn (gen_macho_low (reg, hi_reg, orig));
520*404b540aSrobert #else
521*404b540aSrobert /* some other cpu -- writeme! */
522*404b540aSrobert gcc_unreachable ();
523*404b540aSrobert #endif
524*404b540aSrobert return reg;
525*404b540aSrobert }
526*404b540aSrobert else if (defined)
527*404b540aSrobert {
528*404b540aSrobert #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
529*404b540aSrobert rtx pic_base = machopic_function_base_sym ();
530*404b540aSrobert rtx offset = gen_pic_offset (orig, pic_base);
531*404b540aSrobert #endif
532*404b540aSrobert
533*404b540aSrobert #if defined (TARGET_TOC) /* i.e., PowerPC */
534*404b540aSrobert rtx hi_sum_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
535*404b540aSrobert
536*404b540aSrobert gcc_assert (reg);
537*404b540aSrobert
538*404b540aSrobert emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
539*404b540aSrobert gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
540*404b540aSrobert gen_rtx_HIGH (Pmode, offset))));
541*404b540aSrobert emit_insn (gen_rtx_SET (Pmode, reg,
542*404b540aSrobert gen_rtx_LO_SUM (Pmode, hi_sum_reg, offset)));
543*404b540aSrobert
544*404b540aSrobert orig = reg;
545*404b540aSrobert #else
546*404b540aSrobert #if defined (HAVE_lo_sum)
547*404b540aSrobert gcc_assert (reg);
548*404b540aSrobert
549*404b540aSrobert emit_insn (gen_rtx_SET (VOIDmode, reg,
550*404b540aSrobert gen_rtx_HIGH (Pmode, offset)));
551*404b540aSrobert emit_insn (gen_rtx_SET (VOIDmode, reg,
552*404b540aSrobert gen_rtx_LO_SUM (Pmode, reg, offset)));
553*404b540aSrobert emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
554*404b540aSrobert
555*404b540aSrobert orig = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, reg);
556*404b540aSrobert #endif
557*404b540aSrobert #endif
558*404b540aSrobert return orig;
559*404b540aSrobert }
560*404b540aSrobert
561*404b540aSrobert ptr_ref = (gen_rtx_SYMBOL_REF
562*404b540aSrobert (Pmode,
563*404b540aSrobert machopic_indirection_name (orig, /*stub_p=*/false)));
564*404b540aSrobert
565*404b540aSrobert SYMBOL_REF_DATA (ptr_ref) = SYMBOL_REF_DATA (orig);
566*404b540aSrobert
567*404b540aSrobert ptr_ref = gen_const_mem (Pmode, ptr_ref);
568*404b540aSrobert machopic_define_symbol (ptr_ref);
569*404b540aSrobert
570*404b540aSrobert return ptr_ref;
571*404b540aSrobert }
572*404b540aSrobert else if (GET_CODE (orig) == CONST)
573*404b540aSrobert {
574*404b540aSrobert rtx base, result;
575*404b540aSrobert
576*404b540aSrobert /* legitimize both operands of the PLUS */
577*404b540aSrobert if (GET_CODE (XEXP (orig, 0)) == PLUS)
578*404b540aSrobert {
579*404b540aSrobert base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
580*404b540aSrobert reg);
581*404b540aSrobert orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
582*404b540aSrobert (base == reg ? 0 : reg));
583*404b540aSrobert }
584*404b540aSrobert else
585*404b540aSrobert return orig;
586*404b540aSrobert
587*404b540aSrobert if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
588*404b540aSrobert result = plus_constant (base, INTVAL (orig));
589*404b540aSrobert else
590*404b540aSrobert result = gen_rtx_PLUS (Pmode, base, orig);
591*404b540aSrobert
592*404b540aSrobert if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
593*404b540aSrobert {
594*404b540aSrobert if (reg)
595*404b540aSrobert {
596*404b540aSrobert emit_move_insn (reg, result);
597*404b540aSrobert result = reg;
598*404b540aSrobert }
599*404b540aSrobert else
600*404b540aSrobert {
601*404b540aSrobert result = force_reg (GET_MODE (result), result);
602*404b540aSrobert }
603*404b540aSrobert }
604*404b540aSrobert
605*404b540aSrobert return result;
606*404b540aSrobert
607*404b540aSrobert }
608*404b540aSrobert else if (GET_CODE (orig) == MEM)
609*404b540aSrobert XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
610*404b540aSrobert /* When the target is i386, this code prevents crashes due to the
611*404b540aSrobert compiler's ignorance on how to move the PIC base register to
612*404b540aSrobert other registers. (The reload phase sometimes introduces such
613*404b540aSrobert insns.) */
614*404b540aSrobert else if (GET_CODE (orig) == PLUS
615*404b540aSrobert && GET_CODE (XEXP (orig, 0)) == REG
616*404b540aSrobert && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
617*404b540aSrobert #ifdef I386
618*404b540aSrobert /* Prevent the same register from being erroneously used
619*404b540aSrobert as both the base and index registers. */
620*404b540aSrobert && GET_CODE (XEXP (orig, 1)) == CONST
621*404b540aSrobert #endif
622*404b540aSrobert && reg)
623*404b540aSrobert {
624*404b540aSrobert emit_move_insn (reg, XEXP (orig, 0));
625*404b540aSrobert XEXP (ptr_ref, 0) = reg;
626*404b540aSrobert }
627*404b540aSrobert return ptr_ref;
628*404b540aSrobert }
629*404b540aSrobert
630*404b540aSrobert /* Transform TARGET (a MEM), which is a function call target, to the
631*404b540aSrobert corresponding symbol_stub if necessary. Return a new MEM. */
632*404b540aSrobert
633*404b540aSrobert rtx
machopic_indirect_call_target(rtx target)634*404b540aSrobert machopic_indirect_call_target (rtx target)
635*404b540aSrobert {
636*404b540aSrobert if (GET_CODE (target) != MEM)
637*404b540aSrobert return target;
638*404b540aSrobert
639*404b540aSrobert if (MACHOPIC_INDIRECT
640*404b540aSrobert && GET_CODE (XEXP (target, 0)) == SYMBOL_REF
641*404b540aSrobert && !(SYMBOL_REF_FLAGS (XEXP (target, 0))
642*404b540aSrobert & MACHO_SYMBOL_FLAG_DEFINED))
643*404b540aSrobert {
644*404b540aSrobert rtx sym_ref = XEXP (target, 0);
645*404b540aSrobert const char *stub_name = machopic_indirection_name (sym_ref,
646*404b540aSrobert /*stub_p=*/true);
647*404b540aSrobert enum machine_mode mode = GET_MODE (sym_ref);
648*404b540aSrobert
649*404b540aSrobert XEXP (target, 0) = gen_rtx_SYMBOL_REF (mode, stub_name);
650*404b540aSrobert SYMBOL_REF_DATA (XEXP (target, 0)) = SYMBOL_REF_DATA (sym_ref);
651*404b540aSrobert MEM_READONLY_P (target) = 1;
652*404b540aSrobert MEM_NOTRAP_P (target) = 1;
653*404b540aSrobert }
654*404b540aSrobert
655*404b540aSrobert return target;
656*404b540aSrobert }
657*404b540aSrobert
658*404b540aSrobert rtx
machopic_legitimize_pic_address(rtx orig,enum machine_mode mode,rtx reg)659*404b540aSrobert machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
660*404b540aSrobert {
661*404b540aSrobert rtx pic_ref = orig;
662*404b540aSrobert
663*404b540aSrobert if (! MACHOPIC_INDIRECT)
664*404b540aSrobert return orig;
665*404b540aSrobert
666*404b540aSrobert /* First handle a simple SYMBOL_REF or LABEL_REF */
667*404b540aSrobert if (GET_CODE (orig) == LABEL_REF
668*404b540aSrobert || (GET_CODE (orig) == SYMBOL_REF
669*404b540aSrobert ))
670*404b540aSrobert {
671*404b540aSrobert /* addr(foo) = &func+(foo-func) */
672*404b540aSrobert rtx pic_base;
673*404b540aSrobert
674*404b540aSrobert orig = machopic_indirect_data_reference (orig, reg);
675*404b540aSrobert
676*404b540aSrobert if (GET_CODE (orig) == PLUS
677*404b540aSrobert && GET_CODE (XEXP (orig, 0)) == REG)
678*404b540aSrobert {
679*404b540aSrobert if (reg == 0)
680*404b540aSrobert return force_reg (mode, orig);
681*404b540aSrobert
682*404b540aSrobert emit_move_insn (reg, orig);
683*404b540aSrobert return reg;
684*404b540aSrobert }
685*404b540aSrobert
686*404b540aSrobert /* if dynamic-no-pic we don't have a pic base */
687*404b540aSrobert if (MACHO_DYNAMIC_NO_PIC_P)
688*404b540aSrobert pic_base = NULL;
689*404b540aSrobert else
690*404b540aSrobert pic_base = machopic_function_base_sym ();
691*404b540aSrobert
692*404b540aSrobert if (GET_CODE (orig) == MEM)
693*404b540aSrobert {
694*404b540aSrobert if (reg == 0)
695*404b540aSrobert {
696*404b540aSrobert gcc_assert (!reload_in_progress);
697*404b540aSrobert reg = gen_reg_rtx (Pmode);
698*404b540aSrobert }
699*404b540aSrobert
700*404b540aSrobert #ifdef HAVE_lo_sum
701*404b540aSrobert if (MACHO_DYNAMIC_NO_PIC_P
702*404b540aSrobert && (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
703*404b540aSrobert || GET_CODE (XEXP (orig, 0)) == LABEL_REF))
704*404b540aSrobert {
705*404b540aSrobert #if defined (TARGET_TOC) /* ppc */
706*404b540aSrobert rtx temp_reg = (no_new_pseudos) ? reg : gen_reg_rtx (Pmode);
707*404b540aSrobert rtx asym = XEXP (orig, 0);
708*404b540aSrobert rtx mem;
709*404b540aSrobert
710*404b540aSrobert emit_insn (gen_macho_high (temp_reg, asym));
711*404b540aSrobert mem = gen_const_mem (GET_MODE (orig),
712*404b540aSrobert gen_rtx_LO_SUM (Pmode, temp_reg, asym));
713*404b540aSrobert emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
714*404b540aSrobert #else
715*404b540aSrobert /* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic */
716*404b540aSrobert gcc_unreachable ();
717*404b540aSrobert #endif
718*404b540aSrobert pic_ref = reg;
719*404b540aSrobert }
720*404b540aSrobert else
721*404b540aSrobert if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
722*404b540aSrobert || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
723*404b540aSrobert {
724*404b540aSrobert rtx offset = gen_pic_offset (XEXP (orig, 0), pic_base);
725*404b540aSrobert #if defined (TARGET_TOC) /* i.e., PowerPC */
726*404b540aSrobert /* Generating a new reg may expose opportunities for
727*404b540aSrobert common subexpression elimination. */
728*404b540aSrobert rtx hi_sum_reg = no_new_pseudos ? reg : gen_reg_rtx (Pmode);
729*404b540aSrobert rtx mem;
730*404b540aSrobert rtx insn;
731*404b540aSrobert rtx sum;
732*404b540aSrobert
733*404b540aSrobert sum = gen_rtx_HIGH (Pmode, offset);
734*404b540aSrobert if (! MACHO_DYNAMIC_NO_PIC_P)
735*404b540aSrobert sum = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, sum);
736*404b540aSrobert
737*404b540aSrobert emit_insn (gen_rtx_SET (Pmode, hi_sum_reg, sum));
738*404b540aSrobert
739*404b540aSrobert mem = gen_const_mem (GET_MODE (orig),
740*404b540aSrobert gen_rtx_LO_SUM (Pmode,
741*404b540aSrobert hi_sum_reg, offset));
742*404b540aSrobert insn = emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
743*404b540aSrobert REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, pic_ref,
744*404b540aSrobert REG_NOTES (insn));
745*404b540aSrobert
746*404b540aSrobert pic_ref = reg;
747*404b540aSrobert #else
748*404b540aSrobert emit_insn (gen_rtx_USE (VOIDmode,
749*404b540aSrobert gen_rtx_REG (Pmode,
750*404b540aSrobert PIC_OFFSET_TABLE_REGNUM)));
751*404b540aSrobert
752*404b540aSrobert emit_insn (gen_rtx_SET (VOIDmode, reg,
753*404b540aSrobert gen_rtx_HIGH (Pmode,
754*404b540aSrobert gen_rtx_CONST (Pmode,
755*404b540aSrobert offset))));
756*404b540aSrobert emit_insn (gen_rtx_SET (VOIDmode, reg,
757*404b540aSrobert gen_rtx_LO_SUM (Pmode, reg,
758*404b540aSrobert gen_rtx_CONST (Pmode, offset))));
759*404b540aSrobert pic_ref = gen_rtx_PLUS (Pmode,
760*404b540aSrobert pic_offset_table_rtx, reg);
761*404b540aSrobert #endif
762*404b540aSrobert }
763*404b540aSrobert else
764*404b540aSrobert #endif /* HAVE_lo_sum */
765*404b540aSrobert {
766*404b540aSrobert rtx pic = pic_offset_table_rtx;
767*404b540aSrobert if (GET_CODE (pic) != REG)
768*404b540aSrobert {
769*404b540aSrobert emit_move_insn (reg, pic);
770*404b540aSrobert pic = reg;
771*404b540aSrobert }
772*404b540aSrobert #if 0
773*404b540aSrobert emit_insn (gen_rtx_USE (VOIDmode,
774*404b540aSrobert gen_rtx_REG (Pmode,
775*404b540aSrobert PIC_OFFSET_TABLE_REGNUM)));
776*404b540aSrobert #endif
777*404b540aSrobert
778*404b540aSrobert if (reload_in_progress)
779*404b540aSrobert regs_ever_live[REGNO (pic)] = 1;
780*404b540aSrobert pic_ref = gen_rtx_PLUS (Pmode, pic,
781*404b540aSrobert gen_pic_offset (XEXP (orig, 0),
782*404b540aSrobert pic_base));
783*404b540aSrobert }
784*404b540aSrobert
785*404b540aSrobert #if !defined (TARGET_TOC)
786*404b540aSrobert emit_move_insn (reg, pic_ref);
787*404b540aSrobert pic_ref = gen_const_mem (GET_MODE (orig), reg);
788*404b540aSrobert #endif
789*404b540aSrobert }
790*404b540aSrobert else
791*404b540aSrobert {
792*404b540aSrobert
793*404b540aSrobert #ifdef HAVE_lo_sum
794*404b540aSrobert if (GET_CODE (orig) == SYMBOL_REF
795*404b540aSrobert || GET_CODE (orig) == LABEL_REF)
796*404b540aSrobert {
797*404b540aSrobert rtx offset = gen_pic_offset (orig, pic_base);
798*404b540aSrobert #if defined (TARGET_TOC) /* i.e., PowerPC */
799*404b540aSrobert rtx hi_sum_reg;
800*404b540aSrobert
801*404b540aSrobert if (reg == 0)
802*404b540aSrobert {
803*404b540aSrobert gcc_assert (!reload_in_progress);
804*404b540aSrobert reg = gen_reg_rtx (Pmode);
805*404b540aSrobert }
806*404b540aSrobert
807*404b540aSrobert hi_sum_reg = reg;
808*404b540aSrobert
809*404b540aSrobert emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
810*404b540aSrobert (MACHO_DYNAMIC_NO_PIC_P)
811*404b540aSrobert ? gen_rtx_HIGH (Pmode, offset)
812*404b540aSrobert : gen_rtx_PLUS (Pmode,
813*404b540aSrobert pic_offset_table_rtx,
814*404b540aSrobert gen_rtx_HIGH (Pmode,
815*404b540aSrobert offset))));
816*404b540aSrobert emit_insn (gen_rtx_SET (VOIDmode, reg,
817*404b540aSrobert gen_rtx_LO_SUM (Pmode,
818*404b540aSrobert hi_sum_reg, offset)));
819*404b540aSrobert pic_ref = reg;
820*404b540aSrobert #else
821*404b540aSrobert emit_insn (gen_rtx_SET (VOIDmode, reg,
822*404b540aSrobert gen_rtx_HIGH (Pmode, offset)));
823*404b540aSrobert emit_insn (gen_rtx_SET (VOIDmode, reg,
824*404b540aSrobert gen_rtx_LO_SUM (Pmode, reg, offset)));
825*404b540aSrobert pic_ref = gen_rtx_PLUS (Pmode,
826*404b540aSrobert pic_offset_table_rtx, reg);
827*404b540aSrobert #endif
828*404b540aSrobert }
829*404b540aSrobert else
830*404b540aSrobert #endif /* HAVE_lo_sum */
831*404b540aSrobert {
832*404b540aSrobert if (REG_P (orig)
833*404b540aSrobert || GET_CODE (orig) == SUBREG)
834*404b540aSrobert {
835*404b540aSrobert return orig;
836*404b540aSrobert }
837*404b540aSrobert else
838*404b540aSrobert {
839*404b540aSrobert rtx pic = pic_offset_table_rtx;
840*404b540aSrobert if (GET_CODE (pic) != REG)
841*404b540aSrobert {
842*404b540aSrobert emit_move_insn (reg, pic);
843*404b540aSrobert pic = reg;
844*404b540aSrobert }
845*404b540aSrobert #if 0
846*404b540aSrobert emit_insn (gen_rtx_USE (VOIDmode,
847*404b540aSrobert pic_offset_table_rtx));
848*404b540aSrobert #endif
849*404b540aSrobert if (reload_in_progress)
850*404b540aSrobert regs_ever_live[REGNO (pic)] = 1;
851*404b540aSrobert pic_ref = gen_rtx_PLUS (Pmode,
852*404b540aSrobert pic,
853*404b540aSrobert gen_pic_offset (orig, pic_base));
854*404b540aSrobert }
855*404b540aSrobert }
856*404b540aSrobert }
857*404b540aSrobert
858*404b540aSrobert if (GET_CODE (pic_ref) != REG)
859*404b540aSrobert {
860*404b540aSrobert if (reg != 0)
861*404b540aSrobert {
862*404b540aSrobert emit_move_insn (reg, pic_ref);
863*404b540aSrobert return reg;
864*404b540aSrobert }
865*404b540aSrobert else
866*404b540aSrobert {
867*404b540aSrobert return force_reg (mode, pic_ref);
868*404b540aSrobert }
869*404b540aSrobert }
870*404b540aSrobert else
871*404b540aSrobert {
872*404b540aSrobert return pic_ref;
873*404b540aSrobert }
874*404b540aSrobert }
875*404b540aSrobert
876*404b540aSrobert else if (GET_CODE (orig) == SYMBOL_REF)
877*404b540aSrobert return orig;
878*404b540aSrobert
879*404b540aSrobert else if (GET_CODE (orig) == PLUS
880*404b540aSrobert && (GET_CODE (XEXP (orig, 0)) == MEM
881*404b540aSrobert || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
882*404b540aSrobert || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
883*404b540aSrobert && XEXP (orig, 0) != pic_offset_table_rtx
884*404b540aSrobert && GET_CODE (XEXP (orig, 1)) != REG)
885*404b540aSrobert
886*404b540aSrobert {
887*404b540aSrobert rtx base;
888*404b540aSrobert int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
889*404b540aSrobert
890*404b540aSrobert base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
891*404b540aSrobert orig = machopic_legitimize_pic_address (XEXP (orig, 1),
892*404b540aSrobert Pmode, (base == reg ? 0 : reg));
893*404b540aSrobert if (GET_CODE (orig) == CONST_INT)
894*404b540aSrobert {
895*404b540aSrobert pic_ref = plus_constant (base, INTVAL (orig));
896*404b540aSrobert is_complex = 1;
897*404b540aSrobert }
898*404b540aSrobert else
899*404b540aSrobert pic_ref = gen_rtx_PLUS (Pmode, base, orig);
900*404b540aSrobert
901*404b540aSrobert if (reg && is_complex)
902*404b540aSrobert {
903*404b540aSrobert emit_move_insn (reg, pic_ref);
904*404b540aSrobert pic_ref = reg;
905*404b540aSrobert }
906*404b540aSrobert /* Likewise, should we set special REG_NOTEs here? */
907*404b540aSrobert }
908*404b540aSrobert
909*404b540aSrobert else if (GET_CODE (orig) == CONST)
910*404b540aSrobert {
911*404b540aSrobert return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
912*404b540aSrobert }
913*404b540aSrobert
914*404b540aSrobert else if (GET_CODE (orig) == MEM
915*404b540aSrobert && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
916*404b540aSrobert {
917*404b540aSrobert rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
918*404b540aSrobert addr = replace_equiv_address (orig, addr);
919*404b540aSrobert emit_move_insn (reg, addr);
920*404b540aSrobert pic_ref = reg;
921*404b540aSrobert }
922*404b540aSrobert
923*404b540aSrobert return pic_ref;
924*404b540aSrobert }
925*404b540aSrobert
926*404b540aSrobert /* Output the stub or non-lazy pointer in *SLOT, if it has been used.
927*404b540aSrobert DATA is the FILE* for assembly output. Called from
928*404b540aSrobert htab_traverse. */
929*404b540aSrobert
930*404b540aSrobert static int
machopic_output_indirection(void ** slot,void * data)931*404b540aSrobert machopic_output_indirection (void **slot, void *data)
932*404b540aSrobert {
933*404b540aSrobert machopic_indirection *p = *((machopic_indirection **) slot);
934*404b540aSrobert FILE *asm_out_file = (FILE *) data;
935*404b540aSrobert rtx symbol;
936*404b540aSrobert const char *sym_name;
937*404b540aSrobert const char *ptr_name;
938*404b540aSrobert
939*404b540aSrobert if (!p->used)
940*404b540aSrobert return 1;
941*404b540aSrobert
942*404b540aSrobert symbol = p->symbol;
943*404b540aSrobert sym_name = XSTR (symbol, 0);
944*404b540aSrobert ptr_name = p->ptr_name;
945*404b540aSrobert
946*404b540aSrobert if (p->stub_p)
947*404b540aSrobert {
948*404b540aSrobert char *sym;
949*404b540aSrobert char *stub;
950*404b540aSrobert tree id;
951*404b540aSrobert
952*404b540aSrobert id = maybe_get_identifier (sym_name);
953*404b540aSrobert if (id)
954*404b540aSrobert {
955*404b540aSrobert tree id_orig = id;
956*404b540aSrobert
957*404b540aSrobert while (IDENTIFIER_TRANSPARENT_ALIAS (id))
958*404b540aSrobert id = TREE_CHAIN (id);
959*404b540aSrobert if (id != id_orig)
960*404b540aSrobert sym_name = IDENTIFIER_POINTER (id);
961*404b540aSrobert }
962*404b540aSrobert
963*404b540aSrobert sym = alloca (strlen (sym_name) + 2);
964*404b540aSrobert if (sym_name[0] == '*' || sym_name[0] == '&')
965*404b540aSrobert strcpy (sym, sym_name + 1);
966*404b540aSrobert else if (sym_name[0] == '-' || sym_name[0] == '+')
967*404b540aSrobert strcpy (sym, sym_name);
968*404b540aSrobert else
969*404b540aSrobert sprintf (sym, "%s%s", user_label_prefix, sym_name);
970*404b540aSrobert
971*404b540aSrobert stub = alloca (strlen (ptr_name) + 2);
972*404b540aSrobert if (ptr_name[0] == '*' || ptr_name[0] == '&')
973*404b540aSrobert strcpy (stub, ptr_name + 1);
974*404b540aSrobert else
975*404b540aSrobert sprintf (stub, "%s%s", user_label_prefix, ptr_name);
976*404b540aSrobert
977*404b540aSrobert machopic_output_stub (asm_out_file, sym, stub);
978*404b540aSrobert }
979*404b540aSrobert else if (! indirect_data (symbol)
980*404b540aSrobert && (machopic_symbol_defined_p (symbol)
981*404b540aSrobert || SYMBOL_REF_LOCAL_P (symbol)))
982*404b540aSrobert {
983*404b540aSrobert switch_to_section (data_section);
984*404b540aSrobert assemble_align (GET_MODE_ALIGNMENT (Pmode));
985*404b540aSrobert assemble_label (ptr_name);
986*404b540aSrobert assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
987*404b540aSrobert GET_MODE_SIZE (Pmode),
988*404b540aSrobert GET_MODE_ALIGNMENT (Pmode), 1);
989*404b540aSrobert }
990*404b540aSrobert else
991*404b540aSrobert {
992*404b540aSrobert rtx init = const0_rtx;
993*404b540aSrobert
994*404b540aSrobert switch_to_section (darwin_sections[machopic_nl_symbol_ptr_section]);
995*404b540aSrobert assemble_name (asm_out_file, ptr_name);
996*404b540aSrobert fprintf (asm_out_file, ":\n");
997*404b540aSrobert
998*404b540aSrobert fprintf (asm_out_file, "\t.indirect_symbol ");
999*404b540aSrobert assemble_name (asm_out_file, sym_name);
1000*404b540aSrobert fprintf (asm_out_file, "\n");
1001*404b540aSrobert
1002*404b540aSrobert /* Variables that are marked with MACHO_SYMBOL_STATIC need to
1003*404b540aSrobert have their symbol name instead of 0 in the second entry of
1004*404b540aSrobert the non-lazy symbol pointer data structure when they are
1005*404b540aSrobert defined. This allows the runtime to rebind newer instances
1006*404b540aSrobert of the translation unit with the original instance of the
1007*404b540aSrobert symbol. */
1008*404b540aSrobert
1009*404b540aSrobert if ((SYMBOL_REF_FLAGS (symbol) & MACHO_SYMBOL_STATIC)
1010*404b540aSrobert && machopic_symbol_defined_p (symbol))
1011*404b540aSrobert init = gen_rtx_SYMBOL_REF (Pmode, sym_name);
1012*404b540aSrobert
1013*404b540aSrobert assemble_integer (init, GET_MODE_SIZE (Pmode),
1014*404b540aSrobert GET_MODE_ALIGNMENT (Pmode), 1);
1015*404b540aSrobert }
1016*404b540aSrobert
1017*404b540aSrobert return 1;
1018*404b540aSrobert }
1019*404b540aSrobert
1020*404b540aSrobert void
machopic_finish(FILE * asm_out_file)1021*404b540aSrobert machopic_finish (FILE *asm_out_file)
1022*404b540aSrobert {
1023*404b540aSrobert if (machopic_indirections)
1024*404b540aSrobert htab_traverse_noresize (machopic_indirections,
1025*404b540aSrobert machopic_output_indirection,
1026*404b540aSrobert asm_out_file);
1027*404b540aSrobert }
1028*404b540aSrobert
1029*404b540aSrobert int
machopic_operand_p(rtx op)1030*404b540aSrobert machopic_operand_p (rtx op)
1031*404b540aSrobert {
1032*404b540aSrobert if (MACHOPIC_JUST_INDIRECT)
1033*404b540aSrobert {
1034*404b540aSrobert while (GET_CODE (op) == CONST)
1035*404b540aSrobert op = XEXP (op, 0);
1036*404b540aSrobert
1037*404b540aSrobert if (GET_CODE (op) == SYMBOL_REF)
1038*404b540aSrobert return machopic_symbol_defined_p (op);
1039*404b540aSrobert else
1040*404b540aSrobert return 0;
1041*404b540aSrobert }
1042*404b540aSrobert
1043*404b540aSrobert while (GET_CODE (op) == CONST)
1044*404b540aSrobert op = XEXP (op, 0);
1045*404b540aSrobert
1046*404b540aSrobert if (GET_CODE (op) == MINUS
1047*404b540aSrobert && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
1048*404b540aSrobert && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
1049*404b540aSrobert && machopic_symbol_defined_p (XEXP (op, 0))
1050*404b540aSrobert && machopic_symbol_defined_p (XEXP (op, 1)))
1051*404b540aSrobert return 1;
1052*404b540aSrobert
1053*404b540aSrobert return 0;
1054*404b540aSrobert }
1055*404b540aSrobert
1056*404b540aSrobert /* This function records whether a given name corresponds to a defined
1057*404b540aSrobert or undefined function or variable, for machopic_classify_ident to
1058*404b540aSrobert use later. */
1059*404b540aSrobert
1060*404b540aSrobert void
darwin_encode_section_info(tree decl,rtx rtl,int first ATTRIBUTE_UNUSED)1061*404b540aSrobert darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
1062*404b540aSrobert {
1063*404b540aSrobert rtx sym_ref;
1064*404b540aSrobert
1065*404b540aSrobert /* Do the standard encoding things first. */
1066*404b540aSrobert default_encode_section_info (decl, rtl, first);
1067*404b540aSrobert
1068*404b540aSrobert if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
1069*404b540aSrobert return;
1070*404b540aSrobert
1071*404b540aSrobert sym_ref = XEXP (rtl, 0);
1072*404b540aSrobert if (TREE_CODE (decl) == VAR_DECL)
1073*404b540aSrobert SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_VARIABLE;
1074*404b540aSrobert
1075*404b540aSrobert if (!DECL_EXTERNAL (decl)
1076*404b540aSrobert && (!TREE_PUBLIC (decl) || !DECL_WEAK (decl))
1077*404b540aSrobert && ! lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
1078*404b540aSrobert && ((TREE_STATIC (decl)
1079*404b540aSrobert && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
1080*404b540aSrobert || (!DECL_COMMON (decl) && DECL_INITIAL (decl)
1081*404b540aSrobert && DECL_INITIAL (decl) != error_mark_node)))
1082*404b540aSrobert SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
1083*404b540aSrobert
1084*404b540aSrobert if (! TREE_PUBLIC (decl))
1085*404b540aSrobert SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_STATIC;
1086*404b540aSrobert }
1087*404b540aSrobert
1088*404b540aSrobert void
darwin_mark_decl_preserved(const char * name)1089*404b540aSrobert darwin_mark_decl_preserved (const char *name)
1090*404b540aSrobert {
1091*404b540aSrobert fprintf (asm_out_file, ".no_dead_strip ");
1092*404b540aSrobert assemble_name (asm_out_file, name);
1093*404b540aSrobert fputc ('\n', asm_out_file);
1094*404b540aSrobert }
1095*404b540aSrobert
1096*404b540aSrobert int
machopic_reloc_rw_mask(void)1097*404b540aSrobert machopic_reloc_rw_mask (void)
1098*404b540aSrobert {
1099*404b540aSrobert return MACHOPIC_INDIRECT ? 3 : 0;
1100*404b540aSrobert }
1101*404b540aSrobert
1102*404b540aSrobert section *
machopic_select_section(tree exp,int reloc,unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)1103*404b540aSrobert machopic_select_section (tree exp, int reloc,
1104*404b540aSrobert unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1105*404b540aSrobert {
1106*404b540aSrobert section *base_section;
1107*404b540aSrobert bool weak_p = (DECL_P (exp) && DECL_WEAK (exp)
1108*404b540aSrobert && (lookup_attribute ("weak", DECL_ATTRIBUTES (exp))
1109*404b540aSrobert || ! lookup_attribute ("weak_import",
1110*404b540aSrobert DECL_ATTRIBUTES (exp))));
1111*404b540aSrobert
1112*404b540aSrobert if (TREE_CODE (exp) == FUNCTION_DECL)
1113*404b540aSrobert {
1114*404b540aSrobert if (reloc == 1)
1115*404b540aSrobert base_section = (weak_p
1116*404b540aSrobert ? darwin_sections[text_unlikely_coal_section]
1117*404b540aSrobert : unlikely_text_section ());
1118*404b540aSrobert else
1119*404b540aSrobert base_section = weak_p ? darwin_sections[text_coal_section] : text_section;
1120*404b540aSrobert }
1121*404b540aSrobert else if (decl_readonly_section (exp, reloc))
1122*404b540aSrobert base_section = weak_p ? darwin_sections[const_coal_section] : darwin_sections[const_section];
1123*404b540aSrobert else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1124*404b540aSrobert base_section = weak_p ? darwin_sections[const_data_coal_section] : darwin_sections[const_data_section];
1125*404b540aSrobert else
1126*404b540aSrobert base_section = weak_p ? darwin_sections[data_coal_section] : data_section;
1127*404b540aSrobert
1128*404b540aSrobert if (TREE_CODE (exp) == STRING_CST
1129*404b540aSrobert && ((size_t) TREE_STRING_LENGTH (exp)
1130*404b540aSrobert == strlen (TREE_STRING_POINTER (exp)) + 1))
1131*404b540aSrobert return darwin_sections[cstring_section];
1132*404b540aSrobert else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
1133*404b540aSrobert && flag_merge_constants)
1134*404b540aSrobert {
1135*404b540aSrobert tree size = TYPE_SIZE_UNIT (TREE_TYPE (exp));
1136*404b540aSrobert
1137*404b540aSrobert if (TREE_CODE (size) == INTEGER_CST &&
1138*404b540aSrobert TREE_INT_CST_LOW (size) == 4 &&
1139*404b540aSrobert TREE_INT_CST_HIGH (size) == 0)
1140*404b540aSrobert return darwin_sections[literal4_section];
1141*404b540aSrobert else if (TREE_CODE (size) == INTEGER_CST &&
1142*404b540aSrobert TREE_INT_CST_LOW (size) == 8 &&
1143*404b540aSrobert TREE_INT_CST_HIGH (size) == 0)
1144*404b540aSrobert return darwin_sections[literal8_section];
1145*404b540aSrobert else if (TARGET_64BIT
1146*404b540aSrobert && TREE_CODE (size) == INTEGER_CST
1147*404b540aSrobert && TREE_INT_CST_LOW (size) == 16
1148*404b540aSrobert && TREE_INT_CST_HIGH (size) == 0)
1149*404b540aSrobert return darwin_sections[literal16_section];
1150*404b540aSrobert else
1151*404b540aSrobert return base_section;
1152*404b540aSrobert }
1153*404b540aSrobert else if (TREE_CODE (exp) == CONSTRUCTOR
1154*404b540aSrobert && TREE_TYPE (exp)
1155*404b540aSrobert && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1156*404b540aSrobert && TYPE_NAME (TREE_TYPE (exp)))
1157*404b540aSrobert {
1158*404b540aSrobert tree name = TYPE_NAME (TREE_TYPE (exp));
1159*404b540aSrobert if (TREE_CODE (name) == TYPE_DECL)
1160*404b540aSrobert name = DECL_NAME (name);
1161*404b540aSrobert
1162*404b540aSrobert if (!strcmp (IDENTIFIER_POINTER (name), "__builtin_ObjCString"))
1163*404b540aSrobert {
1164*404b540aSrobert if (flag_next_runtime)
1165*404b540aSrobert return darwin_sections[objc_constant_string_object_section];
1166*404b540aSrobert else
1167*404b540aSrobert return darwin_sections[objc_string_object_section];
1168*404b540aSrobert }
1169*404b540aSrobert else
1170*404b540aSrobert return base_section;
1171*404b540aSrobert }
1172*404b540aSrobert else if (TREE_CODE (exp) == VAR_DECL &&
1173*404b540aSrobert DECL_NAME (exp) &&
1174*404b540aSrobert TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1175*404b540aSrobert IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1176*404b540aSrobert !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1177*404b540aSrobert {
1178*404b540aSrobert const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1179*404b540aSrobert
1180*404b540aSrobert if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1181*404b540aSrobert return darwin_sections[objc_cls_meth_section];
1182*404b540aSrobert else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1183*404b540aSrobert return darwin_sections[objc_inst_meth_section];
1184*404b540aSrobert else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1185*404b540aSrobert return darwin_sections[objc_cat_cls_meth_section];
1186*404b540aSrobert else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1187*404b540aSrobert return darwin_sections[objc_cat_inst_meth_section];
1188*404b540aSrobert else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1189*404b540aSrobert return darwin_sections[objc_class_vars_section];
1190*404b540aSrobert else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1191*404b540aSrobert return darwin_sections[objc_instance_vars_section];
1192*404b540aSrobert else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1193*404b540aSrobert return darwin_sections[objc_cat_cls_meth_section];
1194*404b540aSrobert else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1195*404b540aSrobert return darwin_sections[objc_class_names_section];
1196*404b540aSrobert else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1197*404b540aSrobert return darwin_sections[objc_meth_var_names_section];
1198*404b540aSrobert else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1199*404b540aSrobert return darwin_sections[objc_meth_var_types_section];
1200*404b540aSrobert else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1201*404b540aSrobert return darwin_sections[objc_cls_refs_section];
1202*404b540aSrobert else if (!strncmp (name, "_OBJC_CLASS_", 12))
1203*404b540aSrobert return darwin_sections[objc_class_section];
1204*404b540aSrobert else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1205*404b540aSrobert return darwin_sections[objc_meta_class_section];
1206*404b540aSrobert else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1207*404b540aSrobert return darwin_sections[objc_category_section];
1208*404b540aSrobert else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1209*404b540aSrobert return darwin_sections[objc_selector_refs_section];
1210*404b540aSrobert else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1211*404b540aSrobert return darwin_sections[objc_selector_fixup_section];
1212*404b540aSrobert else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1213*404b540aSrobert return darwin_sections[objc_symbols_section];
1214*404b540aSrobert else if (!strncmp (name, "_OBJC_MODULES", 13))
1215*404b540aSrobert return darwin_sections[objc_module_info_section];
1216*404b540aSrobert else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
1217*404b540aSrobert return darwin_sections[objc_image_info_section];
1218*404b540aSrobert else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1219*404b540aSrobert return darwin_sections[objc_cat_inst_meth_section];
1220*404b540aSrobert else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1221*404b540aSrobert return darwin_sections[objc_cat_cls_meth_section];
1222*404b540aSrobert else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1223*404b540aSrobert return darwin_sections[objc_cat_cls_meth_section];
1224*404b540aSrobert else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1225*404b540aSrobert return darwin_sections[objc_protocol_section];
1226*404b540aSrobert else
1227*404b540aSrobert return base_section;
1228*404b540aSrobert }
1229*404b540aSrobert else
1230*404b540aSrobert return base_section;
1231*404b540aSrobert }
1232*404b540aSrobert
1233*404b540aSrobert /* This can be called with address expressions as "rtx".
1234*404b540aSrobert They must go in "const". */
1235*404b540aSrobert
1236*404b540aSrobert section *
machopic_select_rtx_section(enum machine_mode mode,rtx x,unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)1237*404b540aSrobert machopic_select_rtx_section (enum machine_mode mode, rtx x,
1238*404b540aSrobert unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1239*404b540aSrobert {
1240*404b540aSrobert if (GET_MODE_SIZE (mode) == 8
1241*404b540aSrobert && (GET_CODE (x) == CONST_INT
1242*404b540aSrobert || GET_CODE (x) == CONST_DOUBLE))
1243*404b540aSrobert return darwin_sections[literal8_section];
1244*404b540aSrobert else if (GET_MODE_SIZE (mode) == 4
1245*404b540aSrobert && (GET_CODE (x) == CONST_INT
1246*404b540aSrobert || GET_CODE (x) == CONST_DOUBLE))
1247*404b540aSrobert return darwin_sections[literal4_section];
1248*404b540aSrobert else if (TARGET_64BIT
1249*404b540aSrobert && GET_MODE_SIZE (mode) == 16
1250*404b540aSrobert && (GET_CODE (x) == CONST_INT
1251*404b540aSrobert || GET_CODE (x) == CONST_DOUBLE
1252*404b540aSrobert || GET_CODE (x) == CONST_VECTOR))
1253*404b540aSrobert return darwin_sections[literal16_section];
1254*404b540aSrobert else if (MACHOPIC_INDIRECT
1255*404b540aSrobert && (GET_CODE (x) == SYMBOL_REF
1256*404b540aSrobert || GET_CODE (x) == CONST
1257*404b540aSrobert || GET_CODE (x) == LABEL_REF))
1258*404b540aSrobert return darwin_sections[const_data_section];
1259*404b540aSrobert else
1260*404b540aSrobert return darwin_sections[const_section];
1261*404b540aSrobert }
1262*404b540aSrobert
1263*404b540aSrobert void
machopic_asm_out_constructor(rtx symbol,int priority ATTRIBUTE_UNUSED)1264*404b540aSrobert machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1265*404b540aSrobert {
1266*404b540aSrobert if (MACHOPIC_INDIRECT)
1267*404b540aSrobert switch_to_section (darwin_sections[mod_init_section]);
1268*404b540aSrobert else
1269*404b540aSrobert switch_to_section (darwin_sections[constructor_section]);
1270*404b540aSrobert assemble_align (POINTER_SIZE);
1271*404b540aSrobert assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1272*404b540aSrobert
1273*404b540aSrobert if (! MACHOPIC_INDIRECT)
1274*404b540aSrobert fprintf (asm_out_file, ".reference .constructors_used\n");
1275*404b540aSrobert }
1276*404b540aSrobert
1277*404b540aSrobert void
machopic_asm_out_destructor(rtx symbol,int priority ATTRIBUTE_UNUSED)1278*404b540aSrobert machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1279*404b540aSrobert {
1280*404b540aSrobert if (MACHOPIC_INDIRECT)
1281*404b540aSrobert switch_to_section (darwin_sections[mod_term_section]);
1282*404b540aSrobert else
1283*404b540aSrobert switch_to_section (darwin_sections[destructor_section]);
1284*404b540aSrobert assemble_align (POINTER_SIZE);
1285*404b540aSrobert assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1286*404b540aSrobert
1287*404b540aSrobert if (! MACHOPIC_INDIRECT)
1288*404b540aSrobert fprintf (asm_out_file, ".reference .destructors_used\n");
1289*404b540aSrobert }
1290*404b540aSrobert
1291*404b540aSrobert void
darwin_globalize_label(FILE * stream,const char * name)1292*404b540aSrobert darwin_globalize_label (FILE *stream, const char *name)
1293*404b540aSrobert {
1294*404b540aSrobert if (!!strncmp (name, "_OBJC_", 6))
1295*404b540aSrobert default_globalize_label (stream, name);
1296*404b540aSrobert }
1297*404b540aSrobert
1298*404b540aSrobert void
darwin_asm_named_section(const char * name,unsigned int flags ATTRIBUTE_UNUSED,tree decl ATTRIBUTE_UNUSED)1299*404b540aSrobert darwin_asm_named_section (const char *name,
1300*404b540aSrobert unsigned int flags ATTRIBUTE_UNUSED,
1301*404b540aSrobert tree decl ATTRIBUTE_UNUSED)
1302*404b540aSrobert {
1303*404b540aSrobert fprintf (asm_out_file, "\t.section %s\n", name);
1304*404b540aSrobert }
1305*404b540aSrobert
1306*404b540aSrobert void
darwin_unique_section(tree decl ATTRIBUTE_UNUSED,int reloc ATTRIBUTE_UNUSED)1307*404b540aSrobert darwin_unique_section (tree decl ATTRIBUTE_UNUSED, int reloc ATTRIBUTE_UNUSED)
1308*404b540aSrobert {
1309*404b540aSrobert /* Darwin does not use unique sections. */
1310*404b540aSrobert }
1311*404b540aSrobert
1312*404b540aSrobert /* Handle __attribute__ ((apple_kext_compatibility)).
1313*404b540aSrobert This only applies to darwin kexts for 2.95 compatibility -- it shrinks the
1314*404b540aSrobert vtable for classes with this attribute (and their descendants) by not
1315*404b540aSrobert outputting the new 3.0 nondeleting destructor. This means that such
1316*404b540aSrobert objects CANNOT be allocated on the stack or as globals UNLESS they have
1317*404b540aSrobert a completely empty `operator delete'.
1318*404b540aSrobert Luckily, this fits in with the Darwin kext model.
1319*404b540aSrobert
1320*404b540aSrobert This attribute also disables gcc3's potential overlaying of derived
1321*404b540aSrobert class data members on the padding at the end of the base class. */
1322*404b540aSrobert
1323*404b540aSrobert tree
darwin_handle_kext_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)1324*404b540aSrobert darwin_handle_kext_attribute (tree *node, tree name,
1325*404b540aSrobert tree args ATTRIBUTE_UNUSED,
1326*404b540aSrobert int flags ATTRIBUTE_UNUSED,
1327*404b540aSrobert bool *no_add_attrs)
1328*404b540aSrobert {
1329*404b540aSrobert /* APPLE KEXT stuff -- only applies with pure static C++ code. */
1330*404b540aSrobert if (! TARGET_KEXTABI)
1331*404b540aSrobert {
1332*404b540aSrobert warning (0, "%<%s%> 2.95 vtable-compatability attribute applies "
1333*404b540aSrobert "only when compiling a kext", IDENTIFIER_POINTER (name));
1334*404b540aSrobert
1335*404b540aSrobert *no_add_attrs = true;
1336*404b540aSrobert }
1337*404b540aSrobert else if (TREE_CODE (*node) != RECORD_TYPE)
1338*404b540aSrobert {
1339*404b540aSrobert warning (0, "%<%s%> 2.95 vtable-compatability attribute applies "
1340*404b540aSrobert "only to C++ classes", IDENTIFIER_POINTER (name));
1341*404b540aSrobert
1342*404b540aSrobert *no_add_attrs = true;
1343*404b540aSrobert }
1344*404b540aSrobert
1345*404b540aSrobert return NULL_TREE;
1346*404b540aSrobert }
1347*404b540aSrobert
1348*404b540aSrobert /* Handle a "weak_import" attribute; arguments as in
1349*404b540aSrobert struct attribute_spec.handler. */
1350*404b540aSrobert
1351*404b540aSrobert tree
darwin_handle_weak_import_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)1352*404b540aSrobert darwin_handle_weak_import_attribute (tree *node, tree name,
1353*404b540aSrobert tree ARG_UNUSED (args),
1354*404b540aSrobert int ARG_UNUSED (flags),
1355*404b540aSrobert bool * no_add_attrs)
1356*404b540aSrobert {
1357*404b540aSrobert if (TREE_CODE (*node) != FUNCTION_DECL && TREE_CODE (*node) != VAR_DECL)
1358*404b540aSrobert {
1359*404b540aSrobert warning (OPT_Wattributes, "%qs attribute ignored",
1360*404b540aSrobert IDENTIFIER_POINTER (name));
1361*404b540aSrobert *no_add_attrs = true;
1362*404b540aSrobert }
1363*404b540aSrobert else
1364*404b540aSrobert declare_weak (*node);
1365*404b540aSrobert
1366*404b540aSrobert return NULL_TREE;
1367*404b540aSrobert }
1368*404b540aSrobert
1369*404b540aSrobert static void
no_dead_strip(FILE * file,const char * lab)1370*404b540aSrobert no_dead_strip (FILE *file, const char *lab)
1371*404b540aSrobert {
1372*404b540aSrobert fprintf (file, ".no_dead_strip %s\n", lab);
1373*404b540aSrobert }
1374*404b540aSrobert
1375*404b540aSrobert /* Emit a label for an FDE, making it global and/or weak if appropriate.
1376*404b540aSrobert The third parameter is nonzero if this is for exception handling.
1377*404b540aSrobert The fourth parameter is nonzero if this is just a placeholder for an
1378*404b540aSrobert FDE that we are omitting. */
1379*404b540aSrobert
1380*404b540aSrobert void
darwin_emit_unwind_label(FILE * file,tree decl,int for_eh,int empty)1381*404b540aSrobert darwin_emit_unwind_label (FILE *file, tree decl, int for_eh, int empty)
1382*404b540aSrobert {
1383*404b540aSrobert const char *base;
1384*404b540aSrobert char *lab;
1385*404b540aSrobert bool need_quotes;
1386*404b540aSrobert
1387*404b540aSrobert if (DECL_ASSEMBLER_NAME_SET_P (decl))
1388*404b540aSrobert base = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
1389*404b540aSrobert else
1390*404b540aSrobert base = IDENTIFIER_POINTER (DECL_NAME (decl));
1391*404b540aSrobert
1392*404b540aSrobert base = targetm.strip_name_encoding (base);
1393*404b540aSrobert need_quotes = name_needs_quotes (base);
1394*404b540aSrobert
1395*404b540aSrobert if (! for_eh)
1396*404b540aSrobert return;
1397*404b540aSrobert
1398*404b540aSrobert lab = concat (need_quotes ? "\"" : "", user_label_prefix, base, ".eh",
1399*404b540aSrobert need_quotes ? "\"" : "", NULL);
1400*404b540aSrobert
1401*404b540aSrobert if (TREE_PUBLIC (decl))
1402*404b540aSrobert fprintf (file, "\t%s %s\n",
1403*404b540aSrobert (DECL_VISIBILITY (decl) != VISIBILITY_HIDDEN
1404*404b540aSrobert ? ".globl"
1405*404b540aSrobert : ".private_extern"),
1406*404b540aSrobert lab);
1407*404b540aSrobert
1408*404b540aSrobert if (DECL_WEAK (decl))
1409*404b540aSrobert fprintf (file, "\t.weak_definition %s\n", lab);
1410*404b540aSrobert
1411*404b540aSrobert if (empty)
1412*404b540aSrobert {
1413*404b540aSrobert fprintf (file, "%s = 0\n", lab);
1414*404b540aSrobert
1415*404b540aSrobert /* Mark the absolute .eh and .eh1 style labels as needed to
1416*404b540aSrobert ensure that we don't dead code strip them and keep such
1417*404b540aSrobert labels from another instantiation point until we can fix this
1418*404b540aSrobert properly with group comdat support. */
1419*404b540aSrobert no_dead_strip (file, lab);
1420*404b540aSrobert }
1421*404b540aSrobert else
1422*404b540aSrobert fprintf (file, "%s:\n", lab);
1423*404b540aSrobert
1424*404b540aSrobert free (lab);
1425*404b540aSrobert }
1426*404b540aSrobert
1427*404b540aSrobert static GTY(()) unsigned long except_table_label_num;
1428*404b540aSrobert
1429*404b540aSrobert void
darwin_emit_except_table_label(FILE * file)1430*404b540aSrobert darwin_emit_except_table_label (FILE *file)
1431*404b540aSrobert {
1432*404b540aSrobert char section_start_label[30];
1433*404b540aSrobert
1434*404b540aSrobert ASM_GENERATE_INTERNAL_LABEL (section_start_label, "GCC_except_table",
1435*404b540aSrobert except_table_label_num++);
1436*404b540aSrobert ASM_OUTPUT_LABEL (file, section_start_label);
1437*404b540aSrobert }
1438*404b540aSrobert /* Generate a PC-relative reference to a Mach-O non-lazy-symbol. */
1439*404b540aSrobert
1440*404b540aSrobert void
darwin_non_lazy_pcrel(FILE * file,rtx addr)1441*404b540aSrobert darwin_non_lazy_pcrel (FILE *file, rtx addr)
1442*404b540aSrobert {
1443*404b540aSrobert const char *nlp_name;
1444*404b540aSrobert
1445*404b540aSrobert gcc_assert (GET_CODE (addr) == SYMBOL_REF);
1446*404b540aSrobert
1447*404b540aSrobert nlp_name = machopic_indirection_name (addr, /*stub_p=*/false);
1448*404b540aSrobert fputs ("\t.long\t", file);
1449*404b540aSrobert ASM_OUTPUT_LABELREF (file, nlp_name);
1450*404b540aSrobert fputs ("-.", file);
1451*404b540aSrobert }
1452*404b540aSrobert
1453*404b540aSrobert /* Emit an assembler directive to set visibility for a symbol. The
1454*404b540aSrobert only supported visibilities are VISIBILITY_DEFAULT and
1455*404b540aSrobert VISIBILITY_HIDDEN; the latter corresponds to Darwin's "private
1456*404b540aSrobert extern". There is no MACH-O equivalent of ELF's
1457*404b540aSrobert VISIBILITY_INTERNAL or VISIBILITY_PROTECTED. */
1458*404b540aSrobert
1459*404b540aSrobert void
darwin_assemble_visibility(tree decl,int vis)1460*404b540aSrobert darwin_assemble_visibility (tree decl, int vis)
1461*404b540aSrobert {
1462*404b540aSrobert if (vis == VISIBILITY_DEFAULT)
1463*404b540aSrobert ;
1464*404b540aSrobert else if (vis == VISIBILITY_HIDDEN)
1465*404b540aSrobert {
1466*404b540aSrobert fputs ("\t.private_extern ", asm_out_file);
1467*404b540aSrobert assemble_name (asm_out_file,
1468*404b540aSrobert (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
1469*404b540aSrobert fputs ("\n", asm_out_file);
1470*404b540aSrobert }
1471*404b540aSrobert else
1472*404b540aSrobert warning (OPT_Wattributes, "internal and protected visibility attributes "
1473*404b540aSrobert "not supported in this configuration; ignored");
1474*404b540aSrobert }
1475*404b540aSrobert
1476*404b540aSrobert /* Output a difference of two labels that will be an assembly time
1477*404b540aSrobert constant if the two labels are local. (.long lab1-lab2 will be
1478*404b540aSrobert very different if lab1 is at the boundary between two sections; it
1479*404b540aSrobert will be relocated according to the second section, not the first,
1480*404b540aSrobert so one ends up with a difference between labels in different
1481*404b540aSrobert sections, which is bad in the dwarf2 eh context for instance.) */
1482*404b540aSrobert
1483*404b540aSrobert static int darwin_dwarf_label_counter;
1484*404b540aSrobert
1485*404b540aSrobert void
darwin_asm_output_dwarf_delta(FILE * file,int size,const char * lab1,const char * lab2)1486*404b540aSrobert darwin_asm_output_dwarf_delta (FILE *file, int size,
1487*404b540aSrobert const char *lab1, const char *lab2)
1488*404b540aSrobert {
1489*404b540aSrobert int islocaldiff = (lab1[0] == '*' && lab1[1] == 'L'
1490*404b540aSrobert && lab2[0] == '*' && lab2[1] == 'L');
1491*404b540aSrobert const char *directive = (size == 8 ? ".quad" : ".long");
1492*404b540aSrobert
1493*404b540aSrobert if (islocaldiff)
1494*404b540aSrobert fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1495*404b540aSrobert else
1496*404b540aSrobert fprintf (file, "\t%s\t", directive);
1497*404b540aSrobert assemble_name_raw (file, lab1);
1498*404b540aSrobert fprintf (file, "-");
1499*404b540aSrobert assemble_name_raw (file, lab2);
1500*404b540aSrobert if (islocaldiff)
1501*404b540aSrobert fprintf (file, "\n\t%s L$set$%d", directive, darwin_dwarf_label_counter++);
1502*404b540aSrobert }
1503*404b540aSrobert
1504*404b540aSrobert /* Output labels for the start of the DWARF sections if necessary. */
1505*404b540aSrobert void
darwin_file_start(void)1506*404b540aSrobert darwin_file_start (void)
1507*404b540aSrobert {
1508*404b540aSrobert if (write_symbols == DWARF2_DEBUG)
1509*404b540aSrobert {
1510*404b540aSrobert static const char * const debugnames[] =
1511*404b540aSrobert {
1512*404b540aSrobert DEBUG_FRAME_SECTION,
1513*404b540aSrobert DEBUG_INFO_SECTION,
1514*404b540aSrobert DEBUG_ABBREV_SECTION,
1515*404b540aSrobert DEBUG_ARANGES_SECTION,
1516*404b540aSrobert DEBUG_MACINFO_SECTION,
1517*404b540aSrobert DEBUG_LINE_SECTION,
1518*404b540aSrobert DEBUG_LOC_SECTION,
1519*404b540aSrobert DEBUG_PUBNAMES_SECTION,
1520*404b540aSrobert DEBUG_STR_SECTION,
1521*404b540aSrobert DEBUG_RANGES_SECTION
1522*404b540aSrobert };
1523*404b540aSrobert size_t i;
1524*404b540aSrobert
1525*404b540aSrobert for (i = 0; i < ARRAY_SIZE (debugnames); i++)
1526*404b540aSrobert {
1527*404b540aSrobert int namelen;
1528*404b540aSrobert
1529*404b540aSrobert switch_to_section (get_section (debugnames[i], SECTION_DEBUG, NULL));
1530*404b540aSrobert
1531*404b540aSrobert gcc_assert (strncmp (debugnames[i], "__DWARF,", 8) == 0);
1532*404b540aSrobert gcc_assert (strchr (debugnames[i] + 8, ','));
1533*404b540aSrobert
1534*404b540aSrobert namelen = strchr (debugnames[i] + 8, ',') - (debugnames[i] + 8);
1535*404b540aSrobert fprintf (asm_out_file, "Lsection%.*s:\n", namelen, debugnames[i] + 8);
1536*404b540aSrobert }
1537*404b540aSrobert }
1538*404b540aSrobert }
1539*404b540aSrobert
1540*404b540aSrobert /* Output an offset in a DWARF section on Darwin. On Darwin, DWARF section
1541*404b540aSrobert offsets are not represented using relocs in .o files; either the
1542*404b540aSrobert section never leaves the .o file, or the linker or other tool is
1543*404b540aSrobert responsible for parsing the DWARF and updating the offsets. */
1544*404b540aSrobert
1545*404b540aSrobert void
darwin_asm_output_dwarf_offset(FILE * file,int size,const char * lab,section * base)1546*404b540aSrobert darwin_asm_output_dwarf_offset (FILE *file, int size, const char * lab,
1547*404b540aSrobert section *base)
1548*404b540aSrobert {
1549*404b540aSrobert char sname[64];
1550*404b540aSrobert int namelen;
1551*404b540aSrobert
1552*404b540aSrobert gcc_assert (base->common.flags & SECTION_NAMED);
1553*404b540aSrobert gcc_assert (strncmp (base->named.name, "__DWARF,", 8) == 0);
1554*404b540aSrobert gcc_assert (strchr (base->named.name + 8, ','));
1555*404b540aSrobert
1556*404b540aSrobert namelen = strchr (base->named.name + 8, ',') - (base->named.name + 8);
1557*404b540aSrobert sprintf (sname, "*Lsection%.*s", namelen, base->named.name + 8);
1558*404b540aSrobert darwin_asm_output_dwarf_delta (file, size, lab, sname);
1559*404b540aSrobert }
1560*404b540aSrobert
1561*404b540aSrobert void
darwin_file_end(void)1562*404b540aSrobert darwin_file_end (void)
1563*404b540aSrobert {
1564*404b540aSrobert machopic_finish (asm_out_file);
1565*404b540aSrobert if (strcmp (lang_hooks.name, "GNU C++") == 0)
1566*404b540aSrobert {
1567*404b540aSrobert switch_to_section (darwin_sections[constructor_section]);
1568*404b540aSrobert switch_to_section (darwin_sections[destructor_section]);
1569*404b540aSrobert ASM_OUTPUT_ALIGN (asm_out_file, 1);
1570*404b540aSrobert }
1571*404b540aSrobert fprintf (asm_out_file, "\t.subsections_via_symbols\n");
1572*404b540aSrobert }
1573*404b540aSrobert
1574*404b540aSrobert /* TODO: Add a language hook for identifying if a decl is a vtable. */
1575*404b540aSrobert #define DARWIN_VTABLE_P(DECL) 0
1576*404b540aSrobert
1577*404b540aSrobert /* Cross-module name binding. Darwin does not support overriding
1578*404b540aSrobert functions at dynamic-link time, except for vtables in kexts. */
1579*404b540aSrobert
1580*404b540aSrobert bool
darwin_binds_local_p(tree decl)1581*404b540aSrobert darwin_binds_local_p (tree decl)
1582*404b540aSrobert {
1583*404b540aSrobert return default_binds_local_p_1 (decl,
1584*404b540aSrobert TARGET_KEXTABI && DARWIN_VTABLE_P (decl));
1585*404b540aSrobert }
1586*404b540aSrobert
1587*404b540aSrobert #if 0
1588*404b540aSrobert /* See TARGET_ASM_OUTPUT_ANCHOR for why we can't do this yet. */
1589*404b540aSrobert /* The Darwin's implementation of TARGET_ASM_OUTPUT_ANCHOR. Define the
1590*404b540aSrobert anchor relative to ".", the current section position. We cannot use
1591*404b540aSrobert the default one because ASM_OUTPUT_DEF is wrong for Darwin. */
1592*404b540aSrobert
1593*404b540aSrobert void
1594*404b540aSrobert darwin_asm_output_anchor (rtx symbol)
1595*404b540aSrobert {
1596*404b540aSrobert fprintf (asm_out_file, "\t.set\t");
1597*404b540aSrobert assemble_name (asm_out_file, XSTR (symbol, 0));
1598*404b540aSrobert fprintf (asm_out_file, ", . + " HOST_WIDE_INT_PRINT_DEC "\n",
1599*404b540aSrobert SYMBOL_REF_BLOCK_OFFSET (symbol));
1600*404b540aSrobert }
1601*404b540aSrobert #endif
1602*404b540aSrobert
1603*404b540aSrobert /* Set the darwin specific attributes on TYPE. */
1604*404b540aSrobert void
darwin_set_default_type_attributes(tree type)1605*404b540aSrobert darwin_set_default_type_attributes (tree type)
1606*404b540aSrobert {
1607*404b540aSrobert if (darwin_ms_struct
1608*404b540aSrobert && TREE_CODE (type) == RECORD_TYPE)
1609*404b540aSrobert TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("ms_struct"),
1610*404b540aSrobert NULL_TREE,
1611*404b540aSrobert TYPE_ATTRIBUTES (type));
1612*404b540aSrobert }
1613*404b540aSrobert
1614*404b540aSrobert /* True, iff we're generating code for loadable kernel extentions. */
1615*404b540aSrobert
1616*404b540aSrobert bool
darwin_kextabi_p(void)1617*404b540aSrobert darwin_kextabi_p (void) {
1618*404b540aSrobert return flag_apple_kext;
1619*404b540aSrobert }
1620*404b540aSrobert
1621*404b540aSrobert void
darwin_override_options(void)1622*404b540aSrobert darwin_override_options (void)
1623*404b540aSrobert {
1624*404b540aSrobert if (flag_apple_kext && strcmp (lang_hooks.name, "GNU C++") != 0)
1625*404b540aSrobert {
1626*404b540aSrobert warning (0, "command line option %<-fapple-kext%> is only valid for C++");
1627*404b540aSrobert flag_apple_kext = 0;
1628*404b540aSrobert }
1629*404b540aSrobert if (flag_mkernel || flag_apple_kext)
1630*404b540aSrobert {
1631*404b540aSrobert /* -mkernel implies -fapple-kext for C++ */
1632*404b540aSrobert if (strcmp (lang_hooks.name, "GNU C++") == 0)
1633*404b540aSrobert flag_apple_kext = 1;
1634*404b540aSrobert
1635*404b540aSrobert flag_no_common = 1;
1636*404b540aSrobert
1637*404b540aSrobert /* No EH in kexts. */
1638*404b540aSrobert flag_exceptions = 0;
1639*404b540aSrobert /* No -fnon-call-exceptions data in kexts. */
1640*404b540aSrobert flag_non_call_exceptions = 0;
1641*404b540aSrobert }
1642*404b540aSrobert }
1643*404b540aSrobert
1644*404b540aSrobert #include "gt-darwin.h"
1645