OSDN Git Service

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