OSDN Git Service

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