OSDN Git Service

* config/darwin.c (machopic_indirect_data_reference): Mark
[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       machopic_define_symbol (ptr_ref);
466
467       return ptr_ref;
468     }
469   else if (GET_CODE (orig) == CONST)
470     {
471       rtx base, result;
472
473       /* legitimize both operands of the PLUS */
474       if (GET_CODE (XEXP (orig, 0)) == PLUS)
475         {
476           base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
477                                                    reg);
478           orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
479                                                    (base == reg ? 0 : reg));
480         }
481       else
482         return orig;
483
484       if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
485         result = plus_constant (base, INTVAL (orig));
486       else
487         result = gen_rtx_PLUS (Pmode, base, orig);
488
489       if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
490         {
491           if (reg)
492             {
493               emit_move_insn (reg, result);
494               result = reg;
495             }
496           else
497             {
498               result = force_reg (GET_MODE (result), result);
499             }
500         }
501
502       return result;
503
504     }
505   else if (GET_CODE (orig) == MEM)
506     XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
507   /* When the target is i386, this code prevents crashes due to the
508      compiler's ignorance on how to move the PIC base register to
509      other registers.  (The reload phase sometimes introduces such
510      insns.)  */
511   else if (GET_CODE (orig) == PLUS
512            && GET_CODE (XEXP (orig, 0)) == REG
513            && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
514 #ifdef I386
515            /* Prevent the same register from being erroneously used
516               as both the base and index registers.  */
517            && GET_CODE (XEXP (orig, 1)) == CONST
518 #endif
519            && reg)
520     {
521       emit_move_insn (reg, XEXP (orig, 0));
522       XEXP (ptr_ref, 0) = reg;
523     }
524   return ptr_ref;
525 }
526
527 /* Transform TARGET (a MEM), which is a function call target, to the
528    corresponding symbol_stub if necessary.  Return a new MEM.  */
529
530 rtx
531 machopic_indirect_call_target (rtx target)
532 {
533   if (GET_CODE (target) != MEM)
534     return target;
535
536   if (MACHOPIC_INDIRECT 
537       && GET_CODE (XEXP (target, 0)) == SYMBOL_REF
538       && !(SYMBOL_REF_FLAGS (XEXP (target, 0))
539            & MACHO_SYMBOL_FLAG_DEFINED))
540     {
541       rtx sym_ref = XEXP (target, 0);
542       const char *stub_name = machopic_indirection_name (sym_ref, 
543                                                          /*stub_p=*/true);
544       enum machine_mode mode = GET_MODE (sym_ref);
545       tree decl = SYMBOL_REF_DECL (sym_ref);
546       
547       XEXP (target, 0) = gen_rtx_SYMBOL_REF (mode, stub_name);
548       SYMBOL_REF_DECL (XEXP (target, 0)) = decl;
549       MEM_READONLY_P (target) = 1;
550       MEM_NOTRAP_P (target) = 1;
551     }
552
553   return target;
554 }
555
556 rtx
557 machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
558 {
559   rtx pic_ref = orig;
560
561   if (! MACHOPIC_INDIRECT)
562     return orig;
563
564   /* First handle a simple SYMBOL_REF or LABEL_REF */
565   if (GET_CODE (orig) == LABEL_REF
566       || (GET_CODE (orig) == SYMBOL_REF
567           ))
568     {
569       /* addr(foo) = &func+(foo-func) */
570       rtx pic_base;
571
572       orig = machopic_indirect_data_reference (orig, reg);
573
574       if (GET_CODE (orig) == PLUS
575           && GET_CODE (XEXP (orig, 0)) == REG)
576         {
577           if (reg == 0)
578             return force_reg (mode, orig);
579
580           emit_move_insn (reg, orig);
581           return reg;
582         }
583
584       /* if dynamic-no-pic then use 0 as the pic base  */
585       if (MACHO_DYNAMIC_NO_PIC_P)
586         pic_base = CONST0_RTX (Pmode);
587       else
588         pic_base = machopic_function_base_sym ();
589
590       if (GET_CODE (orig) == MEM)
591         {
592           if (reg == 0)
593             {
594               if (reload_in_progress)
595                 abort ();
596               else
597                 reg = gen_reg_rtx (Pmode);
598             }
599
600 #ifdef HAVE_lo_sum
601           if (MACHO_DYNAMIC_NO_PIC_P
602               && (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
603                   || GET_CODE (XEXP (orig, 0)) == LABEL_REF))
604             {
605 #if defined (TARGET_TOC)        /* ppc  */
606               rtx temp_reg = (no_new_pseudos) ? reg : gen_reg_rtx (Pmode);
607               rtx asym = XEXP (orig, 0);
608               rtx mem;
609
610               emit_insn (mode == DImode
611                          ? gen_macho_high_di (temp_reg, asym)
612                          : gen_macho_high (temp_reg, asym));
613               mem = gen_const_mem (GET_MODE (orig),
614                                    gen_rtx_LO_SUM (Pmode, temp_reg, asym));
615               emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
616 #else
617               /* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic  */
618               abort ();
619 #endif
620               pic_ref = reg;
621             }
622           else
623           if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
624               || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
625             {
626               rtx offset = gen_rtx_CONST (Pmode,
627                                           gen_rtx_MINUS (Pmode,
628                                                          XEXP (orig, 0),
629                                                          pic_base));
630 #if defined (TARGET_TOC) /* i.e., PowerPC */
631               /* Generating a new reg may expose opportunities for
632                  common subexpression elimination.  */
633               rtx hi_sum_reg = no_new_pseudos ? reg : gen_reg_rtx (Pmode);
634               rtx mem;
635               rtx insn;
636               rtx sum;
637               
638               sum = gen_rtx_HIGH (Pmode, offset);
639               if (! MACHO_DYNAMIC_NO_PIC_P)
640                 sum = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, sum);
641
642               emit_insn (gen_rtx_SET (Pmode, hi_sum_reg, sum));
643
644               mem = gen_const_mem (GET_MODE (orig),
645                                   gen_rtx_LO_SUM (Pmode, 
646                                                   hi_sum_reg, offset));
647               insn = emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
648               REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, pic_ref, 
649                                                     REG_NOTES (insn));
650
651               pic_ref = reg;
652 #else
653               emit_insn (gen_rtx_USE (VOIDmode,
654                                       gen_rtx_REG (Pmode, 
655                                                    PIC_OFFSET_TABLE_REGNUM)));
656
657               emit_insn (gen_rtx_SET (VOIDmode, reg,
658                                       gen_rtx_HIGH (Pmode,
659                                                     gen_rtx_CONST (Pmode, 
660                                                                    offset))));
661               emit_insn (gen_rtx_SET (VOIDmode, reg,
662                                   gen_rtx_LO_SUM (Pmode, reg,
663                                            gen_rtx_CONST (Pmode, offset))));
664               pic_ref = gen_rtx_PLUS (Pmode,
665                                       pic_offset_table_rtx, reg);
666 #endif
667             }
668           else
669 #endif  /* HAVE_lo_sum */
670             {
671               rtx pic = pic_offset_table_rtx;
672               if (GET_CODE (pic) != REG)
673                 {
674                   emit_move_insn (reg, pic);
675                   pic = reg;
676                 }
677 #if 0
678               emit_insn (gen_rtx_USE (VOIDmode,
679                                       gen_rtx_REG (Pmode, 
680                                                    PIC_OFFSET_TABLE_REGNUM)));
681 #endif
682
683               pic_ref = gen_rtx_PLUS (Pmode,
684                                       pic,
685                                       gen_rtx_CONST (Pmode,
686                                           gen_rtx_MINUS (Pmode,
687                                                          XEXP (orig, 0),
688                                                          pic_base)));
689             }
690
691 #if !defined (TARGET_TOC)
692           emit_move_insn (reg, pic_ref);
693           pic_ref = gen_const_mem (GET_MODE (orig), reg);
694 #endif
695         }
696       else
697         {
698
699 #ifdef HAVE_lo_sum
700           if (GET_CODE (orig) == SYMBOL_REF
701               || GET_CODE (orig) == LABEL_REF)
702             {
703               rtx offset = gen_rtx_CONST (Pmode,
704                                           gen_rtx_MINUS (Pmode, 
705                                                          orig, pic_base));
706 #if defined (TARGET_TOC) /* i.e., PowerPC */
707               rtx hi_sum_reg;
708
709               if (reg == 0)
710                 {
711                   if (reload_in_progress)
712                     abort ();
713                   else
714                     reg = gen_reg_rtx (Pmode);
715                 }
716
717               hi_sum_reg = reg;
718
719               emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
720                                       (MACHO_DYNAMIC_NO_PIC_P)
721                                       ? gen_rtx_HIGH (Pmode, offset)
722                                       : gen_rtx_PLUS (Pmode,
723                                                       pic_offset_table_rtx,
724                                                       gen_rtx_HIGH (Pmode, 
725                                                                     offset))));
726               emit_insn (gen_rtx_SET (VOIDmode, reg,
727                                       gen_rtx_LO_SUM (Pmode,
728                                                       hi_sum_reg, offset)));
729               pic_ref = reg;
730 #else
731               emit_insn (gen_rtx_SET (VOIDmode, reg,
732                                       gen_rtx_HIGH (Pmode, offset)));
733               emit_insn (gen_rtx_SET (VOIDmode, reg,
734                                       gen_rtx_LO_SUM (Pmode, reg, offset)));
735               pic_ref = gen_rtx_PLUS (Pmode,
736                                       pic_offset_table_rtx, reg);
737 #endif
738             }
739           else
740 #endif  /*  HAVE_lo_sum  */
741             {
742               if (GET_CODE (orig) == REG)
743                 {
744                   return orig;
745                 }
746               else
747                 {
748                   rtx pic = pic_offset_table_rtx;
749                   if (GET_CODE (pic) != REG)
750                     {
751                       emit_move_insn (reg, pic);
752                       pic = reg;
753                     }
754 #if 0
755                   emit_insn (gen_rtx_USE (VOIDmode,
756                                           pic_offset_table_rtx));
757 #endif
758                   pic_ref = gen_rtx_PLUS (Pmode,
759                                           pic,
760                                           gen_rtx_CONST (Pmode,
761                                               gen_rtx_MINUS (Pmode,
762                                                              orig, pic_base)));
763                 }
764             }
765         }
766
767       if (GET_CODE (pic_ref) != REG)
768         {
769           if (reg != 0)
770             {
771               emit_move_insn (reg, pic_ref);
772               return reg;
773             }
774           else
775             {
776               return force_reg (mode, pic_ref);
777             }
778         }
779       else
780         {
781           return pic_ref;
782         }
783     }
784
785   else if (GET_CODE (orig) == SYMBOL_REF)
786     return orig;
787
788   else if (GET_CODE (orig) == PLUS
789            && (GET_CODE (XEXP (orig, 0)) == MEM
790                || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
791                || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
792            && XEXP (orig, 0) != pic_offset_table_rtx
793            && GET_CODE (XEXP (orig, 1)) != REG)
794
795     {
796       rtx base;
797       int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
798
799       base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
800       orig = machopic_legitimize_pic_address (XEXP (orig, 1),
801                                               Pmode, (base == reg ? 0 : reg));
802       if (GET_CODE (orig) == CONST_INT)
803         {
804           pic_ref = plus_constant (base, INTVAL (orig));
805           is_complex = 1;
806         }
807       else
808         pic_ref = gen_rtx_PLUS (Pmode, base, orig);
809
810       if (reg && is_complex)
811         {
812           emit_move_insn (reg, pic_ref);
813           pic_ref = reg;
814         }
815       /* Likewise, should we set special REG_NOTEs here?  */
816     }
817
818   else if (GET_CODE (orig) == CONST)
819     {
820       return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
821     }
822
823   else if (GET_CODE (orig) == MEM
824            && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
825     {
826       rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
827       addr = replace_equiv_address (orig, addr);
828       emit_move_insn (reg, addr);
829       pic_ref = reg;
830     }
831
832   return pic_ref;
833 }
834
835 /* Output the stub or non-lazy pointer in *SLOT, if it has been used.
836    DATA is the FILE* for assembly output.  Called from
837    htab_traverse.  */
838
839 static int
840 machopic_output_indirection (void **slot, void *data)
841 {
842   machopic_indirection *p = *((machopic_indirection **) slot);
843   FILE *asm_out_file = (FILE *) data;
844   rtx symbol;
845   const char *sym_name;
846   const char *ptr_name;
847   
848   if (!p->used)
849     return 1;
850
851   symbol = p->symbol;
852   sym_name = XSTR (symbol, 0);
853   ptr_name = IDENTIFIER_POINTER (p->ptr_name);
854   
855   if (p->stub_p)
856     {
857       char *sym;
858       char *stub;
859
860       sym = alloca (strlen (sym_name) + 2);
861       if (sym_name[0] == '*' || sym_name[0] == '&')
862         strcpy (sym, sym_name + 1);
863       else if (sym_name[0] == '-' || sym_name[0] == '+')
864         strcpy (sym, sym_name);
865       else
866         sprintf (sym, "%s%s", user_label_prefix, sym_name);
867
868       stub = alloca (strlen (ptr_name) + 2);
869       if (ptr_name[0] == '*' || ptr_name[0] == '&')
870         strcpy (stub, ptr_name + 1);
871       else
872         sprintf (stub, "%s%s", user_label_prefix, ptr_name);
873
874       machopic_output_stub (asm_out_file, sym, stub);    
875     }
876   else if (! indirect_data (symbol)
877            && machopic_symbol_defined_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 void
986 darwin_make_decl_one_only (tree decl)
987 {
988   static const char *text_section = "__TEXT,__textcoal_nt,coalesced,no_toc";
989   static const char *data_section = "__DATA,__datacoal_nt,coalesced,no_toc";
990
991   const char *sec = TREE_CODE (decl) == FUNCTION_DECL
992     ? text_section
993     : data_section;
994   TREE_PUBLIC (decl) = 1;
995   DECL_ONE_ONLY (decl) = 1;
996   DECL_SECTION_NAME (decl) = build_string (strlen (sec), sec);
997 }
998
999 void
1000 darwin_mark_decl_preserved (const char *name)
1001 {
1002   fprintf (asm_out_file, ".no_dead_strip ");
1003   assemble_name (asm_out_file, name);
1004   fputc ('\n', asm_out_file);
1005 }
1006
1007 void
1008 machopic_select_section (tree exp, int reloc,
1009                          unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1010 {
1011   void (*base_function)(void);
1012
1013   if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
1014     base_function = readonly_data_section;
1015   else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1016     base_function = const_data_section;
1017   else
1018     base_function = data_section;
1019
1020   if (TREE_CODE (exp) == STRING_CST
1021       && ((size_t) TREE_STRING_LENGTH (exp)
1022           == strlen (TREE_STRING_POINTER (exp)) + 1))
1023     cstring_section ();
1024   else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
1025            && flag_merge_constants)
1026     {
1027       tree size = TYPE_SIZE (TREE_TYPE (exp));
1028
1029       if (TREE_CODE (size) == INTEGER_CST &&
1030           TREE_INT_CST_LOW (size) == 4 &&
1031           TREE_INT_CST_HIGH (size) == 0)
1032         literal4_section ();
1033       else if (TREE_CODE (size) == INTEGER_CST &&
1034                TREE_INT_CST_LOW (size) == 8 &&
1035                TREE_INT_CST_HIGH (size) == 0)
1036         literal8_section ();
1037       else
1038         base_function ();
1039     }
1040   else if (TREE_CODE (exp) == CONSTRUCTOR
1041            && TREE_TYPE (exp)
1042            && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1043            && TYPE_NAME (TREE_TYPE (exp)))
1044     {
1045       tree name = TYPE_NAME (TREE_TYPE (exp));
1046       if (TREE_CODE (name) == TYPE_DECL)
1047         name = DECL_NAME (name);
1048       if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1049         objc_constant_string_object_section ();
1050       else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1051         objc_string_object_section ();
1052       else
1053         base_function ();
1054     }
1055   else if (TREE_CODE (exp) == VAR_DECL &&
1056            DECL_NAME (exp) &&
1057            TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1058            IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1059            !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1060     {
1061       const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1062
1063       if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1064         objc_cls_meth_section ();
1065       else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1066         objc_inst_meth_section ();
1067       else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1068         objc_cat_cls_meth_section ();
1069       else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1070         objc_cat_inst_meth_section ();
1071       else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1072         objc_class_vars_section ();
1073       else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1074         objc_instance_vars_section ();
1075       else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1076         objc_cat_cls_meth_section ();
1077       else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1078         objc_class_names_section ();
1079       else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1080         objc_meth_var_names_section ();
1081       else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1082         objc_meth_var_types_section ();
1083       else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1084         objc_cls_refs_section ();
1085       else if (!strncmp (name, "_OBJC_CLASS_", 12))
1086         objc_class_section ();
1087       else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1088         objc_meta_class_section ();
1089       else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1090         objc_category_section ();
1091       else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1092         objc_selector_refs_section ();
1093       else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1094         objc_selector_fixup_section ();
1095       else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1096         objc_symbols_section ();
1097       else if (!strncmp (name, "_OBJC_MODULES", 13))
1098         objc_module_info_section ();
1099       else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
1100         objc_image_info_section ();
1101       else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1102         objc_cat_inst_meth_section ();
1103       else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1104         objc_cat_cls_meth_section ();
1105       else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1106         objc_cat_cls_meth_section ();
1107       else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1108         objc_protocol_section ();
1109       else
1110         base_function ();
1111     }
1112   else
1113     base_function ();
1114 }
1115
1116 /* This can be called with address expressions as "rtx".
1117    They must go in "const".  */
1118
1119 void
1120 machopic_select_rtx_section (enum machine_mode mode, rtx x,
1121                              unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1122 {
1123   if (GET_MODE_SIZE (mode) == 8)
1124     literal8_section ();
1125   else if (GET_MODE_SIZE (mode) == 4
1126            && (GET_CODE (x) == CONST_INT
1127                || GET_CODE (x) == CONST_DOUBLE))
1128     literal4_section ();
1129   else if (MACHOPIC_INDIRECT
1130            && (GET_CODE (x) == SYMBOL_REF
1131                || GET_CODE (x) == CONST
1132                || GET_CODE (x) == LABEL_REF))
1133     const_data_section ();
1134   else
1135     const_section ();
1136 }
1137
1138 void
1139 machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1140 {
1141   if (MACHOPIC_INDIRECT)
1142     mod_init_section ();
1143   else
1144     constructor_section ();
1145   assemble_align (POINTER_SIZE);
1146   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1147
1148   if (! MACHOPIC_INDIRECT)
1149     fprintf (asm_out_file, ".reference .constructors_used\n");
1150 }
1151
1152 void
1153 machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1154 {
1155   if (MACHOPIC_INDIRECT)
1156     mod_term_section ();
1157   else
1158     destructor_section ();
1159   assemble_align (POINTER_SIZE);
1160   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1161
1162   if (! MACHOPIC_INDIRECT)
1163     fprintf (asm_out_file, ".reference .destructors_used\n");
1164 }
1165
1166 void
1167 darwin_globalize_label (FILE *stream, const char *name)
1168 {
1169   if (!!strncmp (name, "_OBJC_", 6))
1170     default_globalize_label (stream, name);
1171 }
1172
1173 void
1174 darwin_asm_named_section (const char *name, unsigned int flags ATTRIBUTE_UNUSED)
1175 {
1176   fprintf (asm_out_file, ".section %s\n", name);
1177 }
1178
1179 unsigned int
1180 darwin_section_type_flags (tree decl, const char *name, int reloc)
1181 {
1182   unsigned int flags = default_section_type_flags (decl, name, reloc);
1183  
1184   /* Weak or linkonce variables live in a writable section.  */
1185   if (decl != 0 && TREE_CODE (decl) != FUNCTION_DECL
1186       && (DECL_WEAK (decl) || DECL_ONE_ONLY (decl)))
1187     flags |= SECTION_WRITE;
1188   
1189   return flags;
1190 }              
1191
1192 void 
1193 darwin_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
1194 {
1195   /* Darwin does not use unique sections.  However, the target's
1196      unique_section hook is called for linkonce symbols.  We need
1197      to set an appropriate section for such symbols. */
1198   if (DECL_ONE_ONLY (decl) && !DECL_SECTION_NAME (decl))
1199     darwin_make_decl_one_only (decl);
1200 }
1201
1202 #define HAVE_DEAD_STRIP 0
1203
1204 static void
1205 no_dead_strip (FILE *file, const char *lab)
1206 {
1207   if (HAVE_DEAD_STRIP)
1208     fprintf (file, ".no_dead_strip %s\n", lab);
1209 }
1210
1211 /* Emit a label for an FDE, making it global and/or weak if appropriate. 
1212    The third parameter is nonzero if this is for exception handling.
1213    The fourth parameter is nonzero if this is just a placeholder for an
1214    FDE that we are omitting. */
1215
1216 void 
1217 darwin_emit_unwind_label (FILE *file, tree decl, int for_eh, int empty)
1218 {
1219   tree id = DECL_ASSEMBLER_NAME (decl)
1220     ? DECL_ASSEMBLER_NAME (decl)
1221     : DECL_NAME (decl);
1222
1223   const char *prefix = "_";
1224   const int prefix_len = 1;
1225
1226   const char *base = IDENTIFIER_POINTER (id);
1227   unsigned int base_len = IDENTIFIER_LENGTH (id);
1228
1229   const char *suffix = ".eh";
1230
1231   int need_quotes = name_needs_quotes (base);
1232   int quotes_len = need_quotes ? 2 : 0;
1233   char *lab;
1234
1235   if (! for_eh)
1236     suffix = ".eh1";
1237
1238   lab = xmalloc (prefix_len + base_len + strlen (suffix) + quotes_len + 1);
1239   lab[0] = '\0';
1240
1241   if (need_quotes)
1242     strcat(lab, "\"");
1243   strcat(lab, prefix);
1244   strcat(lab, base);
1245   strcat(lab, suffix);
1246   if (need_quotes)
1247     strcat(lab, "\"");
1248
1249   if (TREE_PUBLIC (decl))
1250     fprintf (file, "%s %s\n",
1251              (DECL_VISIBILITY (decl) != VISIBILITY_HIDDEN
1252               ? ".globl"
1253               : ".private_extern"),
1254              lab);
1255
1256   if (DECL_ONE_ONLY (decl) && TREE_PUBLIC (decl))
1257     fprintf (file, ".weak_definition %s\n", lab);
1258
1259   if (empty)
1260     {
1261       fprintf (file, "%s = 0\n", lab);
1262
1263       /* Mark the absolute .eh and .eh1 style labels as needed to
1264          ensure that we don't dead code strip them and keep such
1265          labels from another instantiation point until we can fix this
1266          properly with group comdat support.  */
1267       no_dead_strip (file, lab);
1268     }
1269   else
1270     fprintf (file, "%s:\n", lab);
1271
1272   free (lab);
1273 }
1274
1275 /* Generate a PC-relative reference to a Mach-O non-lazy-symbol.  */ 
1276
1277 void
1278 darwin_non_lazy_pcrel (FILE *file, rtx addr)
1279 {
1280   const char *nlp_name;
1281
1282   if (GET_CODE (addr) != SYMBOL_REF)
1283     abort ();
1284
1285   nlp_name = machopic_indirection_name (addr, /*stub_p=*/false);
1286   fputs ("\t.long\t", file);
1287   ASM_OUTPUT_LABELREF (file, nlp_name);
1288   fputs ("-.", file);
1289 }
1290
1291 /* Emit an assembler directive to set visibility for a symbol.  The
1292    only supported visibilities are VISIBILITY_DEFAULT and
1293    VISIBILITY_HIDDEN; the latter corresponds to Darwin's "private
1294    extern".  There is no MACH-O equivalent of ELF's
1295    VISIBILITY_INTERNAL or VISIBILITY_PROTECTED. */
1296
1297 void 
1298 darwin_assemble_visibility (tree decl, int vis)
1299 {
1300   if (vis == VISIBILITY_DEFAULT)
1301     ;
1302   else if (vis == VISIBILITY_HIDDEN)
1303     {
1304       fputs ("\t.private_extern ", asm_out_file);
1305       assemble_name (asm_out_file,
1306                      (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
1307       fputs ("\n", asm_out_file);
1308     }
1309   else
1310     warning ("internal and protected visibility attributes not supported"
1311              "in this configuration; ignored");
1312 }
1313
1314 /* Output a difference of two labels that will be an assembly time
1315    constant if the two labels are local.  (.long lab1-lab2 will be
1316    very different if lab1 is at the boundary between two sections; it
1317    will be relocated according to the second section, not the first,
1318    so one ends up with a difference between labels in different
1319    sections, which is bad in the dwarf2 eh context for instance.)  */
1320
1321 static int darwin_dwarf_label_counter;
1322
1323 void
1324 darwin_asm_output_dwarf_delta (FILE *file, int size ATTRIBUTE_UNUSED,
1325                                const char *lab1, const char *lab2)
1326 {
1327   int islocaldiff = (lab1[0] == '*' && lab1[1] == 'L'
1328                      && lab2[0] == '*' && lab2[1] == 'L');
1329
1330   if (islocaldiff)
1331     fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1332   else
1333     fprintf (file, "\t%s\t", ".long");
1334   assemble_name (file, lab1);
1335   fprintf (file, "-");
1336   assemble_name (file, lab2);
1337   if (islocaldiff)
1338     fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1339 }
1340
1341 void
1342 darwin_file_end (void)
1343 {
1344   machopic_finish (asm_out_file);
1345   if (strcmp (lang_hooks.name, "GNU C++") == 0)
1346     {
1347       constructor_section ();
1348       destructor_section ();
1349       ASM_OUTPUT_ALIGN (asm_out_file, 1);
1350     }
1351   fprintf (asm_out_file, "\t.subsections_via_symbols\n");
1352 }
1353
1354 /* True, iff we're generating fast turn around debugging code.  When
1355    true, we arrange for function prologues to start with 4 nops so
1356    that gdb may insert code to redirect them, and for data to accessed
1357    indirectly.  The runtime uses this indirection to forward
1358    references for data to the original instance of that data.  */
1359
1360 int darwin_fix_and_continue;
1361 const char *darwin_fix_and_continue_switch;
1362
1363 #include "gt-darwin.h"