OSDN Git Service

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