OSDN Git Service

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