OSDN Git Service

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