OSDN Git Service

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