OSDN Git Service

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