xref: /openbsd/gnu/gcc/gcc/config/darwin.c (revision 404b540a)
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