OSDN Git Service

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