OSDN Git Service

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