OSDN Git Service

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