OSDN Git Service

* doc/invoke.texi (-mfix-and-continue): Add support for
[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 poiinters 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           /* Local symbols must always be defined.  */
102           || SYMBOL_REF_LOCAL_P (sym_ref));
103 }
104
105 /* This module assumes that (const (symbol_ref "foo")) is a legal pic
106    reference, which will not be changed.  */
107
108 enum machopic_addr_class
109 machopic_classify_symbol (rtx sym_ref)
110 {
111   int flags;
112   bool function_p;
113
114   flags = SYMBOL_REF_FLAGS (sym_ref);
115   function_p = SYMBOL_REF_FUNCTION_P (sym_ref);
116   if (machopic_symbol_defined_p (sym_ref))
117     return (function_p 
118             ? MACHOPIC_DEFINED_FUNCTION : MACHOPIC_DEFINED_DATA);
119   else
120     return (function_p 
121             ? MACHOPIC_UNDEFINED_FUNCTION : MACHOPIC_UNDEFINED_DATA);
122 }
123
124 #ifndef TARGET_FIX_AND_CONTINUE
125 #define TARGET_FIX_AND_CONTINUE 0
126 #endif
127
128 /* Indicate when fix-and-continue style code generation is being used
129    and when a reference to data should be indirected so that it can be
130    rebound in a new translation unit to refernce the original instance
131    of that data.  Symbol names that are for code generation local to
132    the translation unit are bound to the new translation unit;
133    currently this means symbols that begin with L or _OBJC_;
134    otherwise, we indicate that an indirect reference should be made to
135    permit the runtime to rebind new instances of the translation unit
136    to the original instance of the data.  */
137
138 static int
139 indirect_data (rtx sym_ref)
140 {
141   int lprefix;
142   const char *name;
143
144   /* If we aren't generating fix-and-continue code, don't do anything special.  */
145   if (TARGET_FIX_AND_CONTINUE == 0)
146     return 0;
147
148   /* Otherwise, all symbol except symbols that begin with L or _OBJC_
149      are indirected.  Symbols that begin with L and _OBJC_ are always
150      bound to the current translation unit as they are used for
151      generated local data of the translation unit.  */
152
153   name = XSTR (sym_ref, 0);
154
155   lprefix = (((name[0] == '*' || name[0] == '&')
156               && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
157              || (strncmp (name, "_OBJC_", 6)));
158
159   return ! lprefix;
160 }
161
162
163 static int
164 machopic_data_defined_p (rtx sym_ref)
165 {
166   if (indirect_data (sym_ref))
167     return 0;
168
169   switch (machopic_classify_symbol (sym_ref))
170     {
171     case MACHOPIC_DEFINED_DATA:
172       return 1;
173     default:
174       return 0;
175     }
176 }
177
178 void
179 machopic_define_symbol (rtx mem)
180 {
181   rtx sym_ref;
182   if (GET_CODE (mem) != MEM)
183     abort ();
184   sym_ref = XEXP (mem, 0);
185   SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
186 }
187
188 static GTY(()) char * function_base;
189
190 const char *
191 machopic_function_base_name (void)
192 {
193   /* if dynamic-no-pic is on, we should not get here */
194   if (MACHO_DYNAMIC_NO_PIC_P)
195     abort ();
196
197   if (function_base == NULL)
198     function_base =
199       (char *) ggc_alloc_string ("<pic base>", sizeof ("<pic base>"));
200
201   current_function_uses_pic_offset_table = 1;
202
203   return function_base;
204 }
205
206 /* Return a SYMBOL_REF for the PIC function base.  */
207
208 rtx
209 machopic_function_base_sym (void)
210 {
211   rtx sym_ref;
212
213   sym_ref = gen_rtx_SYMBOL_REF (Pmode, machopic_function_base_name ());
214   SYMBOL_REF_FLAGS (sym_ref) 
215     |= (MACHO_SYMBOL_FLAG_VARIABLE | MACHO_SYMBOL_FLAG_DEFINED);
216   return sym_ref;
217 }
218
219 static GTY(()) const char * function_base_func_name;
220 static GTY(()) int current_pic_label_num;
221
222 void
223 machopic_output_function_base_name (FILE *file)
224 {
225   const char *current_name;
226
227   /* If dynamic-no-pic is on, we should not get here.  */
228   if (MACHO_DYNAMIC_NO_PIC_P)
229     abort ();
230   current_name =
231     IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
232   if (function_base_func_name != current_name)
233     {
234       ++current_pic_label_num;
235       function_base_func_name = current_name;
236     }
237   fprintf (file, "\"L%011d$pb\"", current_pic_label_num);
238 }
239
240 /* The suffix attached to non-lazy pointer symbols.  */
241 #define NON_LAZY_POINTER_SUFFIX "$non_lazy_ptr"
242 /* The suffix attached to stub symbols.  */
243 #define STUB_SUFFIX "$stub"
244
245 typedef struct machopic_indirection GTY (())
246 {
247   /* The SYMBOL_REF for the entity referenced.  */
248   rtx symbol;
249   /* The IDENTIFIER_NODE giving the name of the stub or non-lazy
250      pointer.  */
251   tree ptr_name;
252   /* True iff this entry is for a stub (as opposed to a non-lazy
253      pointer).  */
254   bool stub_p;
255   /* True iff this stub or pointer pointer has been referenced.  */
256   bool used;
257 } machopic_indirection;
258
259 /* A table mapping stub names and non-lazy pointer names to
260    SYMBOL_REFs for the stubbed-to and pointed-to entities.  */
261
262 static GTY ((param_is (struct machopic_indirection))) htab_t 
263   machopic_indirections;
264
265 /* Return a hash value for a SLOT in the indirections hash table.  */
266
267 static hashval_t
268 machopic_indirection_hash (const void *slot)
269 {
270   const machopic_indirection *p = (const machopic_indirection *) slot;
271   return IDENTIFIER_HASH_VALUE (p->ptr_name);
272 }
273
274 /* Returns true if the KEY is the same as that associated with
275    SLOT.  */
276
277 static int
278 machopic_indirection_eq (const void *slot, const void *key)
279 {
280   return ((const machopic_indirection *) slot)->ptr_name == (tree) key;
281 }
282
283 /* Return the name of the non-lazy pointer (if STUB_P is false) or
284    stub (if STUB_B is true) corresponding to the given name.  */
285
286 const char *
287 machopic_indirection_name (rtx sym_ref, bool stub_p)
288 {
289   char *buffer;
290   const char *name = XSTR (sym_ref, 0);
291   int namelen = strlen (name);
292   tree ptr_name;
293   machopic_indirection *p;
294   
295   /* Construct the name of the non-lazy pointer or stub.  */
296   if (stub_p)
297     {
298       int needs_quotes = name_needs_quotes (name);
299       buffer = alloca (strlen ("&L")
300                        + namelen
301                        + strlen (STUB_SUFFIX)
302                        + 2 /* possible quotes */
303                        + 1 /* '\0' */);
304
305       if (needs_quotes)
306         {
307           if (name[0] == '*')
308             sprintf (buffer, "&\"L%s" STUB_SUFFIX "\"", name + 1);
309           else
310             sprintf (buffer, "&\"L%s%s" STUB_SUFFIX "\"", user_label_prefix, 
311                      name);
312         }
313       else if (name[0] == '*')
314         sprintf (buffer, "&L%s" STUB_SUFFIX, name + 1);
315       else
316         sprintf (buffer, "&L%s%s" STUB_SUFFIX, user_label_prefix, name);
317     }
318   else
319     {
320       buffer = alloca (strlen ("&L")
321                        + strlen (user_label_prefix)
322                        + namelen
323                        + strlen (NON_LAZY_POINTER_SUFFIX)
324                        + 1 /* '\0' */);
325       if (name[0] == '*')
326         sprintf (buffer, "&L%s" NON_LAZY_POINTER_SUFFIX, name + 1);
327       else
328         sprintf (buffer, "&L%s%s" NON_LAZY_POINTER_SUFFIX, 
329                  user_label_prefix, name);
330     }
331
332   /* See if we already have it.  */
333   ptr_name = maybe_get_identifier (buffer);
334   /* If not, create a mapping from the non-lazy pointer to the
335      SYMBOL_REF.  */
336   if (!ptr_name)
337     {
338       void **slot;
339       ptr_name = get_identifier (buffer);
340       p = (machopic_indirection *) ggc_alloc (sizeof (machopic_indirection));
341       p->symbol = sym_ref;
342       p->ptr_name = ptr_name;
343       p->stub_p = stub_p;
344       p->used = 0;
345       if (!machopic_indirections)
346         machopic_indirections 
347           = htab_create_ggc (37, 
348                              machopic_indirection_hash,
349                              machopic_indirection_eq,
350                              /*htab_del=*/NULL);
351       slot = htab_find_slot_with_hash (machopic_indirections, ptr_name,
352                                        IDENTIFIER_HASH_VALUE (ptr_name),
353                                        INSERT);
354       *((machopic_indirection **) slot) = p;
355     }
356   
357   return IDENTIFIER_POINTER (ptr_name);
358 }
359
360 /* Return the name of the stub for the mcount function.  */
361
362 const char*
363 machopic_mcount_stub_name (void)
364 {
365   return "&L*mcount$stub";
366 }
367
368 /* If NAME is the name of a stub or a non-lazy pointer , mark the stub
369    or non-lazy pointer as used -- and mark the object to which the
370    pointer/stub refers as used as well, since the pointer/stub will
371    emit a reference to it.  */
372
373 void
374 machopic_validate_stub_or_non_lazy_ptr (const char *name)
375 {
376   tree ident = get_identifier (name);
377
378   machopic_indirection *p;
379   
380   p = ((machopic_indirection *) 
381        (htab_find_with_hash (machopic_indirections, ident,
382                              IDENTIFIER_HASH_VALUE (ident))));
383   if (p)
384     {
385       p->used = 1;
386       mark_referenced (ident);
387       mark_referenced (get_identifier (XSTR (p->symbol, 0)));
388     }
389 }
390
391 /* Transform ORIG, which may be any data source, to the corresponding
392    source using indirections.  */
393
394 rtx
395 machopic_indirect_data_reference (rtx orig, rtx reg)
396 {
397   rtx ptr_ref = orig;
398
399   if (! MACHOPIC_INDIRECT)
400     return orig;
401
402   if (GET_CODE (orig) == SYMBOL_REF)
403     {
404       int defined = machopic_data_defined_p (orig);
405
406       if (defined && MACHO_DYNAMIC_NO_PIC_P)
407         {
408 #if defined (TARGET_TOC)
409           emit_insn (GET_MODE (orig) == DImode
410                      ? gen_macho_high_di (reg, orig)
411                      : gen_macho_high (reg, orig));
412           emit_insn (GET_MODE (orig) == DImode
413                      ? gen_macho_low_di (reg, reg, orig)
414                      : gen_macho_low (reg, reg, orig));
415 #else
416            /* some other cpu -- writeme!  */
417            abort ();
418 #endif
419            return reg;
420         }
421       else if (defined)
422         {
423 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
424           rtx pic_base = machopic_function_base_sym ();
425           rtx offset = gen_rtx_CONST (Pmode,
426                                       gen_rtx_MINUS (Pmode, orig, pic_base));
427 #endif
428
429 #if defined (TARGET_TOC) /* i.e., PowerPC */
430           rtx hi_sum_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
431
432           if (reg == NULL)
433             abort ();
434
435           emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
436                               gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
437                                        gen_rtx_HIGH (Pmode, offset))));
438           emit_insn (gen_rtx_SET (Pmode, reg,
439                                   gen_rtx_LO_SUM (Pmode, hi_sum_reg, offset)));
440
441           orig = reg;
442 #else
443 #if defined (HAVE_lo_sum)
444           if (reg == 0) abort ();
445
446           emit_insn (gen_rtx_SET (VOIDmode, reg,
447                                   gen_rtx_HIGH (Pmode, offset)));
448           emit_insn (gen_rtx_SET (VOIDmode, reg,
449                                   gen_rtx_LO_SUM (Pmode, reg, offset)));
450           emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
451
452           orig = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, reg);
453 #endif
454 #endif
455           return orig;
456         }
457
458       ptr_ref = (gen_rtx_SYMBOL_REF 
459                  (Pmode, 
460                   machopic_indirection_name (orig, /*stub_p=*/false)));
461
462       SYMBOL_REF_DECL (ptr_ref) = SYMBOL_REF_DECL (orig);
463
464       ptr_ref = gen_const_mem (Pmode, 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     {
878       data_section ();
879       assemble_align (GET_MODE_ALIGNMENT (Pmode));
880       assemble_label (ptr_name);
881       assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
882                         GET_MODE_SIZE (Pmode),
883                         GET_MODE_ALIGNMENT (Pmode), 1);
884     }
885   else
886     {
887       rtx init = const0_rtx;
888
889       machopic_nl_symbol_ptr_section ();
890       assemble_name (asm_out_file, ptr_name);
891       fprintf (asm_out_file, ":\n");
892       
893       fprintf (asm_out_file, "\t.indirect_symbol ");
894       assemble_name (asm_out_file, sym_name);
895       fprintf (asm_out_file, "\n");
896       
897       /* Variables that are marked with MACHO_SYMBOL_STATIC need to
898          have their symbol name instead of 0 in the second entry of
899          the non-lazy symbol pointer data structure when they are
900          defined.  This allows the runtime to rebind newer instances
901          of the translation unit with the original instance of the
902          data.  */
903
904       if ((SYMBOL_REF_FLAGS (symbol) & MACHO_SYMBOL_STATIC)
905           && machopic_symbol_defined_p (symbol))
906         init = gen_rtx_SYMBOL_REF (Pmode, sym_name);
907
908       assemble_integer (init, GET_MODE_SIZE (Pmode),
909                         GET_MODE_ALIGNMENT (Pmode), 1);
910     }
911   
912   return 1;
913 }
914
915 void
916 machopic_finish (FILE *asm_out_file)
917 {
918   if (machopic_indirections)
919     htab_traverse_noresize (machopic_indirections,
920                             machopic_output_indirection,
921                             asm_out_file);
922 }
923
924 int
925 machopic_operand_p (rtx op)
926 {
927   if (MACHOPIC_JUST_INDIRECT)
928     {
929       while (GET_CODE (op) == CONST)
930         op = XEXP (op, 0);
931
932       if (GET_CODE (op) == SYMBOL_REF)
933         return machopic_symbol_defined_p (op);
934       else
935         return 0;
936     }
937
938   while (GET_CODE (op) == CONST)
939     op = XEXP (op, 0);
940
941   if (GET_CODE (op) == MINUS
942       && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
943       && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
944       && machopic_symbol_defined_p (XEXP (op, 0))
945       && machopic_symbol_defined_p (XEXP (op, 1)))
946       return 1;
947
948   return 0;
949 }
950
951 /* This function records whether a given name corresponds to a defined
952    or undefined function or variable, for machopic_classify_ident to
953    use later.  */
954
955 void
956 darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
957 {
958   rtx sym_ref;
959
960   /* Do the standard encoding things first.  */
961   default_encode_section_info (decl, rtl, first);
962
963   if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
964     return;
965
966   sym_ref = XEXP (rtl, 0);
967   if (TREE_CODE (decl) == VAR_DECL)
968     SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_VARIABLE;
969
970   if (!DECL_EXTERNAL (decl)
971       && (!TREE_PUBLIC (decl) || (!DECL_ONE_ONLY (decl) && !DECL_WEAK (decl)))
972       && ((TREE_STATIC (decl)
973            && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
974           || (!DECL_COMMON (decl) && DECL_INITIAL (decl)
975               && DECL_INITIAL (decl) != error_mark_node)))
976     SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
977
978   if (TREE_CODE (decl) == VAR_DECL
979       && indirect_data (sym_ref)
980       && ! TREE_PUBLIC (decl))
981     SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_STATIC;
982 }
983
984 void
985 darwin_make_decl_one_only (tree decl)
986 {
987   static const char *text_section = "__TEXT,__textcoal_nt,coalesced,no_toc";
988   static const char *data_section = "__DATA,__datacoal_nt,coalesced,no_toc";
989
990   const char *sec = TREE_CODE (decl) == FUNCTION_DECL
991     ? text_section
992     : data_section;
993   TREE_PUBLIC (decl) = 1;
994   DECL_ONE_ONLY (decl) = 1;
995   DECL_SECTION_NAME (decl) = build_string (strlen (sec), sec);
996 }
997
998 void
999 darwin_mark_decl_preserved (const char *name)
1000 {
1001   fprintf (asm_out_file, ".no_dead_strip ");
1002   assemble_name (asm_out_file, name);
1003   fputc ('\n', asm_out_file);
1004 }
1005
1006 void
1007 machopic_select_section (tree exp, int reloc,
1008                          unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1009 {
1010   void (*base_function)(void);
1011
1012   if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
1013     base_function = readonly_data_section;
1014   else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1015     base_function = const_data_section;
1016   else
1017     base_function = data_section;
1018
1019   if (TREE_CODE (exp) == STRING_CST
1020       && ((size_t) TREE_STRING_LENGTH (exp)
1021           == strlen (TREE_STRING_POINTER (exp)) + 1))
1022     cstring_section ();
1023   else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
1024            && flag_merge_constants)
1025     {
1026       tree size = TYPE_SIZE (TREE_TYPE (exp));
1027
1028       if (TREE_CODE (size) == INTEGER_CST &&
1029           TREE_INT_CST_LOW (size) == 4 &&
1030           TREE_INT_CST_HIGH (size) == 0)
1031         literal4_section ();
1032       else if (TREE_CODE (size) == INTEGER_CST &&
1033                TREE_INT_CST_LOW (size) == 8 &&
1034                TREE_INT_CST_HIGH (size) == 0)
1035         literal8_section ();
1036       else
1037         base_function ();
1038     }
1039   else if (TREE_CODE (exp) == CONSTRUCTOR
1040            && TREE_TYPE (exp)
1041            && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1042            && TYPE_NAME (TREE_TYPE (exp)))
1043     {
1044       tree name = TYPE_NAME (TREE_TYPE (exp));
1045       if (TREE_CODE (name) == TYPE_DECL)
1046         name = DECL_NAME (name);
1047       if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1048         objc_constant_string_object_section ();
1049       else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1050         objc_string_object_section ();
1051       else
1052         base_function ();
1053     }
1054   else if (TREE_CODE (exp) == VAR_DECL &&
1055            DECL_NAME (exp) &&
1056            TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1057            IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1058            !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1059     {
1060       const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1061
1062       if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1063         objc_cls_meth_section ();
1064       else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1065         objc_inst_meth_section ();
1066       else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1067         objc_cat_cls_meth_section ();
1068       else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1069         objc_cat_inst_meth_section ();
1070       else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1071         objc_class_vars_section ();
1072       else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1073         objc_instance_vars_section ();
1074       else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1075         objc_cat_cls_meth_section ();
1076       else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1077         objc_class_names_section ();
1078       else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1079         objc_meth_var_names_section ();
1080       else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1081         objc_meth_var_types_section ();
1082       else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1083         objc_cls_refs_section ();
1084       else if (!strncmp (name, "_OBJC_CLASS_", 12))
1085         objc_class_section ();
1086       else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1087         objc_meta_class_section ();
1088       else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1089         objc_category_section ();
1090       else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1091         objc_selector_refs_section ();
1092       else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1093         objc_selector_fixup_section ();
1094       else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1095         objc_symbols_section ();
1096       else if (!strncmp (name, "_OBJC_MODULES", 13))
1097         objc_module_info_section ();
1098       else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
1099         objc_image_info_section ();
1100       else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1101         objc_cat_inst_meth_section ();
1102       else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1103         objc_cat_cls_meth_section ();
1104       else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1105         objc_cat_cls_meth_section ();
1106       else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1107         objc_protocol_section ();
1108       else
1109         base_function ();
1110     }
1111   else
1112     base_function ();
1113 }
1114
1115 /* This can be called with address expressions as "rtx".
1116    They must go in "const".  */
1117
1118 void
1119 machopic_select_rtx_section (enum machine_mode mode, rtx x,
1120                              unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1121 {
1122   if (GET_MODE_SIZE (mode) == 8)
1123     literal8_section ();
1124   else if (GET_MODE_SIZE (mode) == 4
1125            && (GET_CODE (x) == CONST_INT
1126                || GET_CODE (x) == CONST_DOUBLE))
1127     literal4_section ();
1128   else if (MACHOPIC_INDIRECT
1129            && (GET_CODE (x) == SYMBOL_REF
1130                || GET_CODE (x) == CONST
1131                || GET_CODE (x) == LABEL_REF))
1132     const_data_section ();
1133   else
1134     const_section ();
1135 }
1136
1137 void
1138 machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1139 {
1140   if (MACHOPIC_INDIRECT)
1141     mod_init_section ();
1142   else
1143     constructor_section ();
1144   assemble_align (POINTER_SIZE);
1145   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1146
1147   if (! MACHOPIC_INDIRECT)
1148     fprintf (asm_out_file, ".reference .constructors_used\n");
1149 }
1150
1151 void
1152 machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1153 {
1154   if (MACHOPIC_INDIRECT)
1155     mod_term_section ();
1156   else
1157     destructor_section ();
1158   assemble_align (POINTER_SIZE);
1159   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1160
1161   if (! MACHOPIC_INDIRECT)
1162     fprintf (asm_out_file, ".reference .destructors_used\n");
1163 }
1164
1165 void
1166 darwin_globalize_label (FILE *stream, const char *name)
1167 {
1168   if (!!strncmp (name, "_OBJC_", 6))
1169     default_globalize_label (stream, name);
1170 }
1171
1172 void
1173 darwin_asm_named_section (const char *name, unsigned int flags ATTRIBUTE_UNUSED)
1174 {
1175   fprintf (asm_out_file, ".section %s\n", name);
1176 }
1177
1178 unsigned int
1179 darwin_section_type_flags (tree decl, const char *name, int reloc)
1180 {
1181   unsigned int flags = default_section_type_flags (decl, name, reloc);
1182  
1183   /* Weak or linkonce variables live in a writable section.  */
1184   if (decl != 0 && TREE_CODE (decl) != FUNCTION_DECL
1185       && (DECL_WEAK (decl) || DECL_ONE_ONLY (decl)))
1186     flags |= SECTION_WRITE;
1187   
1188   return flags;
1189 }              
1190
1191 void 
1192 darwin_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
1193 {
1194   /* Darwin does not use unique sections.  However, the target's
1195      unique_section hook is called for linkonce symbols.  We need
1196      to set an appropriate section for such symbols. */
1197   if (DECL_ONE_ONLY (decl) && !DECL_SECTION_NAME (decl))
1198     darwin_make_decl_one_only (decl);
1199 }
1200
1201 #define HAVE_DEAD_STRIP 0
1202
1203 static void
1204 no_dead_strip (FILE *file, const char *lab)
1205 {
1206   if (HAVE_DEAD_STRIP)
1207     fprintf (file, ".no_dead_strip %s\n", lab);
1208 }
1209
1210 /* Emit a label for an FDE, making it global and/or weak if appropriate. 
1211    The third parameter is nonzero if this is for exception handling.
1212    The fourth parameter is nonzero if this is just a placeholder for an
1213    FDE that we are omitting. */
1214
1215 void 
1216 darwin_emit_unwind_label (FILE *file, tree decl, int for_eh, int empty)
1217 {
1218   tree id = DECL_ASSEMBLER_NAME (decl)
1219     ? DECL_ASSEMBLER_NAME (decl)
1220     : DECL_NAME (decl);
1221
1222   const char *prefix = "_";
1223   const int prefix_len = 1;
1224
1225   const char *base = IDENTIFIER_POINTER (id);
1226   unsigned int base_len = IDENTIFIER_LENGTH (id);
1227
1228   const char *suffix = ".eh";
1229
1230   int need_quotes = name_needs_quotes (base);
1231   int quotes_len = need_quotes ? 2 : 0;
1232   char *lab;
1233
1234   if (! for_eh)
1235     suffix = ".eh1";
1236
1237   lab = xmalloc (prefix_len + base_len + strlen (suffix) + quotes_len + 1);
1238   lab[0] = '\0';
1239
1240   if (need_quotes)
1241     strcat(lab, "\"");
1242   strcat(lab, prefix);
1243   strcat(lab, base);
1244   strcat(lab, suffix);
1245   if (need_quotes)
1246     strcat(lab, "\"");
1247
1248   if (TREE_PUBLIC (decl))
1249     fprintf (file, "%s %s\n",
1250              (DECL_VISIBILITY (decl) != VISIBILITY_HIDDEN
1251               ? ".globl"
1252               : ".private_extern"),
1253              lab);
1254
1255   if (DECL_ONE_ONLY (decl) && TREE_PUBLIC (decl))
1256     fprintf (file, ".weak_definition %s\n", lab);
1257
1258   if (empty)
1259     {
1260       fprintf (file, "%s = 0\n", lab);
1261
1262       /* Mark the absolute .eh and .eh1 style labels as needed to
1263          ensure that we don't dead code strip them and keep such
1264          labels from another instantiation point until we can fix this
1265          properly with group comdat support.  */
1266       no_dead_strip (file, lab);
1267     }
1268   else
1269     fprintf (file, "%s:\n", lab);
1270
1271   free (lab);
1272 }
1273
1274 /* Generate a PC-relative reference to a Mach-O non-lazy-symbol.  */ 
1275
1276 void
1277 darwin_non_lazy_pcrel (FILE *file, rtx addr)
1278 {
1279   const char *nlp_name;
1280
1281   if (GET_CODE (addr) != SYMBOL_REF)
1282     abort ();
1283
1284   nlp_name = machopic_indirection_name (addr, /*stub_p=*/false);
1285   fputs ("\t.long\t", file);
1286   ASM_OUTPUT_LABELREF (file, nlp_name);
1287   fputs ("-.", file);
1288 }
1289
1290 /* Emit an assembler directive to set visibility for a symbol.  The
1291    only supported visibilities are VISIBILITY_DEFAULT and
1292    VISIBILITY_HIDDEN; the latter corresponds to Darwin's "private
1293    extern".  There is no MACH-O equivalent of ELF's
1294    VISIBILITY_INTERNAL or VISIBILITY_PROTECTED. */
1295
1296 void 
1297 darwin_assemble_visibility (tree decl, int vis)
1298 {
1299   if (vis == VISIBILITY_DEFAULT)
1300     ;
1301   else if (vis == VISIBILITY_HIDDEN)
1302     {
1303       fputs ("\t.private_extern ", asm_out_file);
1304       assemble_name (asm_out_file,
1305                      (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
1306       fputs ("\n", asm_out_file);
1307     }
1308   else
1309     warning ("internal and protected visibility attributes not supported"
1310              "in this configuration; ignored");
1311 }
1312
1313 /* Output a difference of two labels that will be an assembly time
1314    constant if the two labels are local.  (.long lab1-lab2 will be
1315    very different if lab1 is at the boundary between two sections; it
1316    will be relocated according to the second section, not the first,
1317    so one ends up with a difference between labels in different
1318    sections, which is bad in the dwarf2 eh context for instance.)  */
1319
1320 static int darwin_dwarf_label_counter;
1321
1322 void
1323 darwin_asm_output_dwarf_delta (FILE *file, int size ATTRIBUTE_UNUSED,
1324                                const char *lab1, const char *lab2)
1325 {
1326   int islocaldiff = (lab1[0] == '*' && lab1[1] == 'L'
1327                      && lab2[0] == '*' && lab2[1] == 'L');
1328
1329   if (islocaldiff)
1330     fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1331   else
1332     fprintf (file, "\t%s\t", ".long");
1333   assemble_name (file, lab1);
1334   fprintf (file, "-");
1335   assemble_name (file, lab2);
1336   if (islocaldiff)
1337     fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1338 }
1339
1340 void
1341 darwin_file_end (void)
1342 {
1343   machopic_finish (asm_out_file);
1344   if (strcmp (lang_hooks.name, "GNU C++") == 0)
1345     {
1346       constructor_section ();
1347       destructor_section ();
1348       ASM_OUTPUT_ALIGN (asm_out_file, 1);
1349     }
1350   fprintf (asm_out_file, "\t.subsections_via_symbols\n");
1351 }
1352
1353 /* True, iff we're generating fast turn around debugging code.  When
1354    true, we arrange for function prologues to start with 4 nops so
1355    that gdb may insert code to redirect them, and for data to accessed
1356    indirectly.  The runtime uses this indirection to forward
1357    references for data to the original instance of that data.  */
1358
1359 int darwin_fix_and_continue;
1360 const char *darwin_fix_and_continue_switch;
1361
1362 #include "gt-darwin.h"