OSDN Git Service

* config/darwin.c (macho_indirect_data_reference): Add DImode case.
[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 (gen_macho_high (reg, orig));
337           emit_insn (gen_macho_low (reg, reg, orig));
338 #else
339            /* some other cpu -- writeme!  */
340            abort ();
341 #endif
342            return reg;
343         }
344       else if (defined)
345         {
346 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
347           rtx pic_base = machopic_function_base_sym ();
348           rtx offset = gen_rtx_CONST (Pmode,
349                                       gen_rtx_MINUS (Pmode, orig, pic_base));
350 #endif
351
352 #if defined (TARGET_TOC) /* i.e., PowerPC */
353           rtx hi_sum_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
354
355           if (reg == NULL)
356             abort ();
357
358           emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
359                               gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
360                                        gen_rtx_HIGH (Pmode, offset))));
361           emit_insn (gen_rtx_SET (Pmode, reg,
362                                   gen_rtx_LO_SUM (Pmode, hi_sum_reg, offset)));
363
364           orig = reg;
365 #else
366 #if defined (HAVE_lo_sum)
367           if (reg == 0) abort ();
368
369           emit_insn (gen_rtx_SET (VOIDmode, reg,
370                                   gen_rtx_HIGH (Pmode, offset)));
371           emit_insn (gen_rtx_SET (VOIDmode, reg,
372                                   gen_rtx_LO_SUM (Pmode, reg, offset)));
373           emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
374
375           orig = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, reg);
376 #endif
377 #endif
378           return orig;
379         }
380
381       ptr_ref = (gen_rtx_SYMBOL_REF 
382                  (Pmode, 
383                   machopic_indirection_name (orig, /*stub_p=*/false)));
384
385      SYMBOL_REF_DECL (ptr_ref) = SYMBOL_REF_DECL (orig);
386
387       ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
388       RTX_UNCHANGING_P (ptr_ref) = 1;
389
390       return ptr_ref;
391     }
392   else if (GET_CODE (orig) == CONST)
393     {
394       rtx base, result;
395
396       /* legitimize both operands of the PLUS */
397       if (GET_CODE (XEXP (orig, 0)) == PLUS)
398         {
399           base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
400                                                    reg);
401           orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
402                                                    (base == reg ? 0 : reg));
403         }
404       else
405         return orig;
406
407       if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
408         result = plus_constant (base, INTVAL (orig));
409       else
410         result = gen_rtx_PLUS (Pmode, base, orig);
411
412       if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
413         {
414           if (reg)
415             {
416               emit_move_insn (reg, result);
417               result = reg;
418             }
419           else
420             {
421               result = force_reg (GET_MODE (result), result);
422             }
423         }
424
425       return result;
426
427     }
428   else if (GET_CODE (orig) == MEM)
429     XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
430   /* When the target is i386, this code prevents crashes due to the
431      compiler's ignorance on how to move the PIC base register to
432      other registers.  (The reload phase sometimes introduces such
433      insns.)  */
434   else if (GET_CODE (orig) == PLUS
435            && GET_CODE (XEXP (orig, 0)) == REG
436            && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
437 #ifdef I386
438            /* Prevent the same register from being erroneously used
439               as both the base and index registers.  */
440            && GET_CODE (XEXP (orig, 1)) == CONST
441 #endif
442            && reg)
443     {
444       emit_move_insn (reg, XEXP (orig, 0));
445       XEXP (ptr_ref, 0) = reg;
446     }
447   return ptr_ref;
448 }
449
450 /* Transform TARGET (a MEM), which is a function call target, to the
451    corresponding symbol_stub if necessary.  Return a new MEM.  */
452
453 rtx
454 machopic_indirect_call_target (rtx target)
455 {
456   if (GET_CODE (target) != MEM)
457     return target;
458
459   if (MACHOPIC_INDIRECT 
460       && GET_CODE (XEXP (target, 0)) == SYMBOL_REF
461       && !(SYMBOL_REF_FLAGS (XEXP (target, 0))
462            & MACHO_SYMBOL_FLAG_DEFINED))
463     {
464       rtx sym_ref = XEXP (target, 0);
465       const char *stub_name = machopic_indirection_name (sym_ref, 
466                                                          /*stub_p=*/true);
467       enum machine_mode mode = GET_MODE (sym_ref);
468       tree decl = SYMBOL_REF_DECL (sym_ref);
469       
470       XEXP (target, 0) = gen_rtx_SYMBOL_REF (mode, stub_name);
471       SYMBOL_REF_DECL (XEXP (target, 0)) = decl;
472       RTX_UNCHANGING_P (target) = 1;
473     }
474
475   return target;
476 }
477
478 rtx
479 machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
480 {
481   rtx pic_ref = orig;
482
483   if (! MACHOPIC_INDIRECT)
484     return orig;
485
486   /* First handle a simple SYMBOL_REF or LABEL_REF */
487   if (GET_CODE (orig) == LABEL_REF
488       || (GET_CODE (orig) == SYMBOL_REF
489           ))
490     {
491       /* addr(foo) = &func+(foo-func) */
492       rtx pic_base;
493
494       orig = machopic_indirect_data_reference (orig, reg);
495
496       if (GET_CODE (orig) == PLUS
497           && GET_CODE (XEXP (orig, 0)) == REG)
498         {
499           if (reg == 0)
500             return force_reg (mode, orig);
501
502           emit_move_insn (reg, orig);
503           return reg;
504         }
505
506       /* if dynamic-no-pic then use 0 as the pic base  */
507       if (MACHO_DYNAMIC_NO_PIC_P)
508         pic_base = CONST0_RTX (Pmode);
509       else
510         pic_base = machopic_function_base_sym ();
511
512       if (GET_CODE (orig) == MEM)
513         {
514           if (reg == 0)
515             {
516               if (reload_in_progress)
517                 abort ();
518               else
519                 reg = gen_reg_rtx (Pmode);
520             }
521
522 #ifdef HAVE_lo_sum
523           if (MACHO_DYNAMIC_NO_PIC_P
524               && (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
525                   || GET_CODE (XEXP (orig, 0)) == LABEL_REF))
526             {
527 #if defined (TARGET_TOC)        /* ppc  */
528               rtx temp_reg = (no_new_pseudos) ? reg : gen_reg_rtx (Pmode);
529               rtx asym = XEXP (orig, 0);
530               rtx mem;
531
532               emit_insn (gen_macho_high (temp_reg, asym));
533               mem = gen_rtx_MEM (GET_MODE (orig),
534                                  gen_rtx_LO_SUM (Pmode, temp_reg, asym));
535               RTX_UNCHANGING_P (mem) = 1;
536               emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
537 #else
538               /* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic  */
539               abort ();
540 #endif
541               pic_ref = reg;
542             }
543           else
544           if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
545               || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
546             {
547               rtx offset = gen_rtx_CONST (Pmode,
548                                           gen_rtx_MINUS (Pmode,
549                                                          XEXP (orig, 0),
550                                                          pic_base));
551 #if defined (TARGET_TOC) /* i.e., PowerPC */
552               /* Generating a new reg may expose opportunities for
553                  common subexpression elimination.  */
554               rtx hi_sum_reg = no_new_pseudos ? reg : gen_reg_rtx (Pmode);
555               rtx mem;
556               rtx insn;
557               rtx sum;
558               
559               sum = gen_rtx_HIGH (Pmode, offset);
560               if (! MACHO_DYNAMIC_NO_PIC_P)
561                 sum = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, sum);
562
563               emit_insn (gen_rtx_SET (Pmode, hi_sum_reg, sum));
564
565               mem = gen_rtx_MEM (GET_MODE (orig),
566                                  gen_rtx_LO_SUM (Pmode, 
567                                                  hi_sum_reg, offset));
568               RTX_UNCHANGING_P (mem) = 1;
569               insn = emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
570               REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, pic_ref, 
571                                                     REG_NOTES (insn));
572
573               pic_ref = reg;
574 #else
575               emit_insn (gen_rtx_USE (VOIDmode,
576                                       gen_rtx_REG (Pmode, 
577                                                    PIC_OFFSET_TABLE_REGNUM)));
578
579               emit_insn (gen_rtx_SET (VOIDmode, reg,
580                                       gen_rtx_HIGH (Pmode,
581                                                     gen_rtx_CONST (Pmode, 
582                                                                    offset))));
583               emit_insn (gen_rtx_SET (VOIDmode, reg,
584                                   gen_rtx_LO_SUM (Pmode, reg,
585                                            gen_rtx_CONST (Pmode, offset))));
586               pic_ref = gen_rtx_PLUS (Pmode,
587                                       pic_offset_table_rtx, reg);
588 #endif
589             }
590           else
591 #endif  /* HAVE_lo_sum */
592             {
593               rtx pic = pic_offset_table_rtx;
594               if (GET_CODE (pic) != REG)
595                 {
596                   emit_move_insn (reg, pic);
597                   pic = reg;
598                 }
599 #if 0
600               emit_insn (gen_rtx_USE (VOIDmode,
601                                       gen_rtx_REG (Pmode, 
602                                                    PIC_OFFSET_TABLE_REGNUM)));
603 #endif
604
605               pic_ref = gen_rtx_PLUS (Pmode,
606                                       pic,
607                                       gen_rtx_CONST (Pmode,
608                                           gen_rtx_MINUS (Pmode,
609                                                          XEXP (orig, 0),
610                                                          pic_base)));
611             }
612
613 #if !defined (TARGET_TOC)
614           emit_move_insn (reg, pic_ref);
615           pic_ref = gen_rtx_MEM (GET_MODE (orig), reg);
616 #endif
617           RTX_UNCHANGING_P (pic_ref) = 1;
618         }
619       else
620         {
621
622 #ifdef HAVE_lo_sum
623           if (GET_CODE (orig) == SYMBOL_REF
624               || GET_CODE (orig) == LABEL_REF)
625             {
626               rtx offset = gen_rtx_CONST (Pmode,
627                                           gen_rtx_MINUS (Pmode, 
628                                                          orig, pic_base));
629 #if defined (TARGET_TOC) /* i.e., PowerPC */
630               rtx hi_sum_reg;
631
632               if (reg == 0)
633                 {
634                   if (reload_in_progress)
635                     abort ();
636                   else
637                     reg = gen_reg_rtx (Pmode);
638                 }
639
640               hi_sum_reg = reg;
641
642               emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
643                                       (MACHO_DYNAMIC_NO_PIC_P)
644                                       ? gen_rtx_HIGH (Pmode, offset)
645                                       : gen_rtx_PLUS (Pmode,
646                                                       pic_offset_table_rtx,
647                                                       gen_rtx_HIGH (Pmode, 
648                                                                     offset))));
649               emit_insn (gen_rtx_SET (VOIDmode, reg,
650                                       gen_rtx_LO_SUM (Pmode,
651                                                       hi_sum_reg, offset)));
652               pic_ref = reg;
653               RTX_UNCHANGING_P (pic_ref) = 1;
654 #else
655               emit_insn (gen_rtx_SET (VOIDmode, reg,
656                                       gen_rtx_HIGH (Pmode, offset)));
657               emit_insn (gen_rtx_SET (VOIDmode, reg,
658                                       gen_rtx_LO_SUM (Pmode, reg, offset)));
659               pic_ref = gen_rtx_PLUS (Pmode,
660                                       pic_offset_table_rtx, reg);
661               RTX_UNCHANGING_P (pic_ref) = 1;
662 #endif
663             }
664           else
665 #endif  /*  HAVE_lo_sum  */
666             {
667               if (GET_CODE (orig) == REG)
668                 {
669                   return orig;
670                 }
671               else
672                 {
673                   rtx pic = pic_offset_table_rtx;
674                   if (GET_CODE (pic) != REG)
675                     {
676                       emit_move_insn (reg, pic);
677                       pic = reg;
678                     }
679 #if 0
680                   emit_insn (gen_rtx_USE (VOIDmode,
681                                           pic_offset_table_rtx));
682 #endif
683                   pic_ref = gen_rtx_PLUS (Pmode,
684                                           pic,
685                                           gen_rtx_CONST (Pmode,
686                                               gen_rtx_MINUS (Pmode,
687                                                              orig, pic_base)));
688                 }
689             }
690         }
691
692       if (GET_CODE (pic_ref) != REG)
693         {
694           if (reg != 0)
695             {
696               emit_move_insn (reg, pic_ref);
697               return reg;
698             }
699           else
700             {
701               return force_reg (mode, pic_ref);
702             }
703         }
704       else
705         {
706           return pic_ref;
707         }
708     }
709
710   else if (GET_CODE (orig) == SYMBOL_REF)
711     return orig;
712
713   else if (GET_CODE (orig) == PLUS
714            && (GET_CODE (XEXP (orig, 0)) == MEM
715                || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
716                || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
717            && XEXP (orig, 0) != pic_offset_table_rtx
718            && GET_CODE (XEXP (orig, 1)) != REG)
719
720     {
721       rtx base;
722       int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
723
724       base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
725       orig = machopic_legitimize_pic_address (XEXP (orig, 1),
726                                               Pmode, (base == reg ? 0 : reg));
727       if (GET_CODE (orig) == CONST_INT)
728         {
729           pic_ref = plus_constant (base, INTVAL (orig));
730           is_complex = 1;
731         }
732       else
733         pic_ref = gen_rtx_PLUS (Pmode, base, orig);
734
735       if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
736         RTX_UNCHANGING_P (pic_ref) = 1;
737
738       if (reg && is_complex)
739         {
740           emit_move_insn (reg, pic_ref);
741           pic_ref = reg;
742         }
743       /* Likewise, should we set special REG_NOTEs here?  */
744     }
745
746   else if (GET_CODE (orig) == CONST)
747     {
748       return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
749     }
750
751   else if (GET_CODE (orig) == MEM
752            && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
753     {
754       rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
755
756       addr = gen_rtx_MEM (GET_MODE (orig), addr);
757       RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
758       emit_move_insn (reg, addr);
759       pic_ref = reg;
760     }
761
762   return pic_ref;
763 }
764
765 /* Output the stub or non-lazy pointer in *SLOT, if it has been used.
766    DATA is the FILE* for assembly output.  Called from
767    htab_traverse.  */
768
769 static int
770 machopic_output_indirection (void **slot, void *data)
771 {
772   machopic_indirection *p = *((machopic_indirection **) slot);
773   FILE *asm_out_file = (FILE *) data;
774   rtx symbol;
775   const char *sym_name;
776   const char *ptr_name;
777   
778   if (!p->used)
779     return 1;
780
781   symbol = p->symbol;
782   sym_name = XSTR (symbol, 0);
783   ptr_name = IDENTIFIER_POINTER (p->ptr_name);
784   
785   if (p->stub_p)
786     {
787       char *sym;
788       char *stub;
789
790       sym = alloca (strlen (sym_name) + 2);
791       if (sym_name[0] == '*' || sym_name[0] == '&')
792         strcpy (sym, sym_name + 1);
793       else if (sym_name[0] == '-' || sym_name[0] == '+')
794         strcpy (sym, sym_name);
795       else
796         sprintf (sym, "%s%s", user_label_prefix, sym_name);
797
798       stub = alloca (strlen (ptr_name) + 2);
799       if (ptr_name[0] == '*' || ptr_name[0] == '&')
800         strcpy (stub, ptr_name + 1);
801       else
802         sprintf (stub, "%s%s", user_label_prefix, ptr_name);
803
804       machopic_output_stub (asm_out_file, sym, stub);    
805     }
806   else if (machopic_symbol_defined_p (symbol))
807     {
808       data_section ();
809       assemble_align (GET_MODE_ALIGNMENT (Pmode));
810       assemble_label (ptr_name);
811       assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
812                         GET_MODE_SIZE (Pmode),
813                         GET_MODE_ALIGNMENT (Pmode), 1);
814     }
815   else
816     {
817       machopic_nl_symbol_ptr_section ();
818       assemble_name (asm_out_file, ptr_name);
819       fprintf (asm_out_file, ":\n");
820       
821       fprintf (asm_out_file, "\t.indirect_symbol ");
822       assemble_name (asm_out_file, sym_name);
823       fprintf (asm_out_file, "\n");
824       
825       assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
826                         GET_MODE_ALIGNMENT (Pmode), 1);
827     }
828   
829   return 1;
830 }
831
832 void
833 machopic_finish (FILE *asm_out_file)
834 {
835   if (machopic_indirections)
836     htab_traverse_noresize (machopic_indirections, 
837                             machopic_output_indirection,
838                             asm_out_file);
839 }
840
841 int
842 machopic_operand_p (rtx op)
843 {
844   if (MACHOPIC_JUST_INDIRECT)
845     {
846       while (GET_CODE (op) == CONST)
847         op = XEXP (op, 0);
848
849       if (GET_CODE (op) == SYMBOL_REF)
850         return machopic_symbol_defined_p (op);
851       else
852         return 0;
853     }
854
855   while (GET_CODE (op) == CONST)
856     op = XEXP (op, 0);
857
858   if (GET_CODE (op) == MINUS
859       && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
860       && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
861       && machopic_symbol_defined_p (XEXP (op, 0))
862       && machopic_symbol_defined_p (XEXP (op, 1)))
863       return 1;
864
865   return 0;
866 }
867
868 /* This function records whether a given name corresponds to a defined
869    or undefined function or variable, for machopic_classify_ident to
870    use later.  */
871
872 void
873 darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
874 {
875   rtx sym_ref;
876
877   /* Do the standard encoding things first.  */
878   default_encode_section_info (decl, rtl, first);
879
880   if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
881     return;
882
883   sym_ref = XEXP (rtl, 0);
884   if (TREE_CODE (decl) == VAR_DECL)
885     SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_VARIABLE;
886
887   if (!DECL_EXTERNAL (decl)
888       && (!TREE_PUBLIC (decl) || (!DECL_ONE_ONLY (decl) && !DECL_WEAK (decl)))
889       && ((TREE_STATIC (decl)
890            && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
891           || (!DECL_COMMON (decl) && DECL_INITIAL (decl)
892               && DECL_INITIAL (decl) != error_mark_node)))
893     SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
894 }
895
896 void
897 darwin_make_decl_one_only (tree decl)
898 {
899   static const char *text_section = "__TEXT,__textcoal_nt,coalesced,no_toc";
900   static const char *data_section = "__DATA,__datacoal_nt,coalesced,no_toc";
901
902   const char *sec = TREE_CODE (decl) == FUNCTION_DECL
903     ? text_section
904     : data_section;
905   TREE_PUBLIC (decl) = 1;
906   DECL_ONE_ONLY (decl) = 1;
907   DECL_SECTION_NAME (decl) = build_string (strlen (sec), sec);
908 }
909
910 void
911 darwin_mark_decl_preserved (const char *name)
912 {
913   fprintf (asm_out_file, ".no_dead_strip ");
914   assemble_name (asm_out_file, name);
915   fputc ('\n', asm_out_file);
916 }
917
918 void
919 machopic_select_section (tree exp, int reloc,
920                          unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
921 {
922   void (*base_function)(void);
923
924   if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
925     base_function = readonly_data_section;
926   else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
927     base_function = const_data_section;
928   else
929     base_function = data_section;
930
931   if (TREE_CODE (exp) == STRING_CST
932       && ((size_t) TREE_STRING_LENGTH (exp)
933           == strlen (TREE_STRING_POINTER (exp)) + 1))
934     cstring_section ();
935   else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
936            && flag_merge_constants)
937     {
938       tree size = TYPE_SIZE (TREE_TYPE (exp));
939
940       if (TREE_CODE (size) == INTEGER_CST &&
941           TREE_INT_CST_LOW (size) == 4 &&
942           TREE_INT_CST_HIGH (size) == 0)
943         literal4_section ();
944       else if (TREE_CODE (size) == INTEGER_CST &&
945                TREE_INT_CST_LOW (size) == 8 &&
946                TREE_INT_CST_HIGH (size) == 0)
947         literal8_section ();
948       else
949         base_function ();
950     }
951   else if (TREE_CODE (exp) == CONSTRUCTOR
952            && TREE_TYPE (exp)
953            && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
954            && TYPE_NAME (TREE_TYPE (exp)))
955     {
956       tree name = TYPE_NAME (TREE_TYPE (exp));
957       if (TREE_CODE (name) == TYPE_DECL)
958         name = DECL_NAME (name);
959       if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
960         objc_constant_string_object_section ();
961       else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
962         objc_string_object_section ();
963       else
964         base_function ();
965     }
966   else if (TREE_CODE (exp) == VAR_DECL &&
967            DECL_NAME (exp) &&
968            TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
969            IDENTIFIER_POINTER (DECL_NAME (exp)) &&
970            !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
971     {
972       const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
973
974       if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
975         objc_cls_meth_section ();
976       else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
977         objc_inst_meth_section ();
978       else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
979         objc_cat_cls_meth_section ();
980       else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
981         objc_cat_inst_meth_section ();
982       else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
983         objc_class_vars_section ();
984       else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
985         objc_instance_vars_section ();
986       else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
987         objc_cat_cls_meth_section ();
988       else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
989         objc_class_names_section ();
990       else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
991         objc_meth_var_names_section ();
992       else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
993         objc_meth_var_types_section ();
994       else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
995         objc_cls_refs_section ();
996       else if (!strncmp (name, "_OBJC_CLASS_", 12))
997         objc_class_section ();
998       else if (!strncmp (name, "_OBJC_METACLASS_", 16))
999         objc_meta_class_section ();
1000       else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1001         objc_category_section ();
1002       else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1003         objc_selector_refs_section ();
1004       else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1005         objc_selector_fixup_section ();
1006       else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1007         objc_symbols_section ();
1008       else if (!strncmp (name, "_OBJC_MODULES", 13))
1009         objc_module_info_section ();
1010       else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
1011         objc_image_info_section ();
1012       else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1013         objc_cat_inst_meth_section ();
1014       else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1015         objc_cat_cls_meth_section ();
1016       else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1017         objc_cat_cls_meth_section ();
1018       else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1019         objc_protocol_section ();
1020       else
1021         base_function ();
1022     }
1023   else
1024     base_function ();
1025 }
1026
1027 /* This can be called with address expressions as "rtx".
1028    They must go in "const".  */
1029
1030 void
1031 machopic_select_rtx_section (enum machine_mode mode, rtx x,
1032                              unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1033 {
1034   if (GET_MODE_SIZE (mode) == 8)
1035     literal8_section ();
1036   else if (GET_MODE_SIZE (mode) == 4
1037            && (GET_CODE (x) == CONST_INT
1038                || GET_CODE (x) == CONST_DOUBLE))
1039     literal4_section ();
1040   else if (MACHOPIC_INDIRECT
1041            && (GET_CODE (x) == SYMBOL_REF
1042                || GET_CODE (x) == CONST
1043                || GET_CODE (x) == LABEL_REF))
1044     const_data_section ();
1045   else
1046     const_section ();
1047 }
1048
1049 void
1050 machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1051 {
1052   if (MACHOPIC_INDIRECT)
1053     mod_init_section ();
1054   else
1055     constructor_section ();
1056   assemble_align (POINTER_SIZE);
1057   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1058
1059   if (! MACHOPIC_INDIRECT)
1060     fprintf (asm_out_file, ".reference .constructors_used\n");
1061 }
1062
1063 void
1064 machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1065 {
1066   if (MACHOPIC_INDIRECT)
1067     mod_term_section ();
1068   else
1069     destructor_section ();
1070   assemble_align (POINTER_SIZE);
1071   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1072
1073   if (! MACHOPIC_INDIRECT)
1074     fprintf (asm_out_file, ".reference .destructors_used\n");
1075 }
1076
1077 void
1078 darwin_globalize_label (FILE *stream, const char *name)
1079 {
1080   if (!!strncmp (name, "_OBJC_", 6))
1081     default_globalize_label (stream, name);
1082 }
1083
1084 void
1085 darwin_asm_named_section (const char *name, unsigned int flags ATTRIBUTE_UNUSED)
1086 {
1087   if (flag_reorder_blocks_and_partition)
1088     fprintf (asm_out_file, SECTION_FORMAT_STRING, name);
1089   else
1090     fprintf (asm_out_file, ".section %s\n", name);
1091 }
1092
1093 unsigned int
1094 darwin_section_type_flags (tree decl, const char *name, int reloc)
1095 {
1096   unsigned int flags = default_section_type_flags (decl, name, reloc);
1097  
1098   /* Weak or linkonce variables live in a writable section.  */
1099   if (decl != 0 && TREE_CODE (decl) != FUNCTION_DECL
1100       && (DECL_WEAK (decl) || DECL_ONE_ONLY (decl)))
1101     flags |= SECTION_WRITE;
1102   
1103   return flags;
1104 }              
1105
1106 void 
1107 darwin_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
1108 {
1109   /* Darwin does not use unique sections.  However, the target's
1110      unique_section hook is called for linkonce symbols.  We need
1111      to set an appropriate section for such symbols. */
1112   if (DECL_ONE_ONLY (decl) && !DECL_SECTION_NAME (decl))
1113     darwin_make_decl_one_only (decl);
1114 }
1115
1116 #define HAVE_DEAD_STRIP 0
1117
1118 static void
1119 no_dead_strip (FILE *file, const char *lab)
1120 {
1121   if (HAVE_DEAD_STRIP)
1122     fprintf (file, ".no_dead_strip %s\n", lab);
1123 }
1124
1125 /* Emit a label for an FDE, making it global and/or weak if appropriate. 
1126    The third parameter is nonzero if this is for exception handling.
1127    The fourth parameter is nonzero if this is just a placeholder for an
1128    FDE that we are omitting. */
1129
1130 void 
1131 darwin_emit_unwind_label (FILE *file, tree decl, int for_eh, int empty)
1132 {
1133   tree id = DECL_ASSEMBLER_NAME (decl)
1134     ? DECL_ASSEMBLER_NAME (decl)
1135     : DECL_NAME (decl);
1136
1137   const char *prefix = "_";
1138   const int prefix_len = 1;
1139
1140   const char *base = IDENTIFIER_POINTER (id);
1141   unsigned int base_len = IDENTIFIER_LENGTH (id);
1142
1143   const char *suffix = ".eh";
1144
1145   int need_quotes = name_needs_quotes (base);
1146   int quotes_len = need_quotes ? 2 : 0;
1147   char *lab;
1148
1149   if (! for_eh)
1150     suffix = ".eh1";
1151
1152   lab = xmalloc (prefix_len + base_len + strlen (suffix) + quotes_len + 1);
1153   lab[0] = '\0';
1154
1155   if (need_quotes)
1156     strcat(lab, "\"");
1157   strcat(lab, prefix);
1158   strcat(lab, base);
1159   strcat(lab, suffix);
1160   if (need_quotes)
1161     strcat(lab, "\"");
1162
1163   if (TREE_PUBLIC (decl))
1164     fprintf (file, "%s %s\n",
1165              (DECL_VISIBILITY (decl) != VISIBILITY_HIDDEN
1166               ? ".globl"
1167               : ".private_extern"),
1168              lab);
1169
1170   if (DECL_ONE_ONLY (decl) && TREE_PUBLIC (decl))
1171     fprintf (file, ".weak_definition %s\n", lab);
1172
1173   if (empty)
1174     {
1175       fprintf (file, "%s = 0\n", lab);
1176
1177       /* Mark the absolute .eh and .eh1 style labels as needed to
1178          ensure that we don't dead code strip them and keep such
1179          labels from another instantiation point until we can fix this
1180          properly with group comdat support.  */
1181       no_dead_strip (file, lab);
1182     }
1183   else
1184     fprintf (file, "%s:\n", lab);
1185
1186   free (lab);
1187 }
1188
1189 /* Generate a PC-relative reference to a Mach-O non-lazy-symbol.  */ 
1190
1191 void
1192 darwin_non_lazy_pcrel (FILE *file, rtx addr)
1193 {
1194   const char *nlp_name;
1195
1196   if (GET_CODE (addr) != SYMBOL_REF)
1197     abort ();
1198
1199   nlp_name = machopic_indirection_name (addr, /*stub_p=*/false);
1200   fputs ("\t.long\t", file);
1201   ASM_OUTPUT_LABELREF (file, nlp_name);
1202   fputs ("-.", file);
1203 }
1204
1205 /* Emit an assembler directive to set visibility for a symbol.  The
1206    only supported visibilities are VISIBILITY_DEFAULT and
1207    VISIBILITY_HIDDEN; the latter corresponds to Darwin's "private
1208    extern".  There is no MACH-O equivalent of ELF's
1209    VISIBILITY_INTERNAL or VISIBILITY_PROTECTED. */
1210
1211 void 
1212 darwin_assemble_visibility (tree decl, int vis)
1213 {
1214   if (vis == VISIBILITY_DEFAULT)
1215     ;
1216   else if (vis == VISIBILITY_HIDDEN)
1217     {
1218       fputs ("\t.private_extern ", asm_out_file);
1219       assemble_name (asm_out_file,
1220                      (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
1221       fputs ("\n", asm_out_file);
1222     }
1223   else
1224     warning ("internal and protected visibility attributes not supported"
1225              "in this configuration; ignored");
1226 }
1227
1228 /* Output a difference of two labels that will be an assembly time
1229    constant if the two labels are local.  (.long lab1-lab2 will be
1230    very different if lab1 is at the boundary between two sections; it
1231    will be relocated according to the second section, not the first,
1232    so one ends up with a difference between labels in different
1233    sections, which is bad in the dwarf2 eh context for instance.)  */
1234
1235 static int darwin_dwarf_label_counter;
1236
1237 void
1238 darwin_asm_output_dwarf_delta (FILE *file, int size ATTRIBUTE_UNUSED,
1239                                const char *lab1, const char *lab2)
1240 {
1241   int islocaldiff = (lab1[0] == '*' && lab1[1] == 'L'
1242                      && lab2[0] == '*' && lab2[1] == 'L');
1243
1244   if (islocaldiff)
1245     fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1246   else
1247     fprintf (file, "\t%s\t", ".long");
1248   assemble_name (file, lab1);
1249   fprintf (file, "-");
1250   assemble_name (file, lab2);
1251   if (islocaldiff)
1252     fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1253 }
1254
1255 void
1256 darwin_file_end (void)
1257 {
1258   machopic_finish (asm_out_file);
1259   if (strcmp (lang_hooks.name, "GNU C++") == 0)
1260     {
1261       constructor_section ();
1262       destructor_section ();
1263       ASM_OUTPUT_ALIGN (asm_out_file, 1);
1264     }
1265 }
1266
1267 #include "gt-darwin.h"