OSDN Git Service

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