OSDN Git Service

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