OSDN Git Service

Basic support for 64-bit Darwin.
[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 machopic_select_section (tree exp, int reloc,
918                          unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
919 {
920   void (*base_function)(void);
921
922   if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
923     base_function = readonly_data_section;
924   else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
925     base_function = const_data_section;
926   else
927     base_function = data_section;
928
929   if (TREE_CODE (exp) == STRING_CST
930       && ((size_t) TREE_STRING_LENGTH (exp)
931           == strlen (TREE_STRING_POINTER (exp)) + 1))
932     cstring_section ();
933   else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
934            && flag_merge_constants)
935     {
936       tree size = TYPE_SIZE (TREE_TYPE (exp));
937
938       if (TREE_CODE (size) == INTEGER_CST &&
939           TREE_INT_CST_LOW (size) == 4 &&
940           TREE_INT_CST_HIGH (size) == 0)
941         literal4_section ();
942       else if (TREE_CODE (size) == INTEGER_CST &&
943                TREE_INT_CST_LOW (size) == 8 &&
944                TREE_INT_CST_HIGH (size) == 0)
945         literal8_section ();
946       else
947         base_function ();
948     }
949   else if (TREE_CODE (exp) == CONSTRUCTOR
950            && TREE_TYPE (exp)
951            && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
952            && TYPE_NAME (TREE_TYPE (exp)))
953     {
954       tree name = TYPE_NAME (TREE_TYPE (exp));
955       if (TREE_CODE (name) == TYPE_DECL)
956         name = DECL_NAME (name);
957       if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
958         objc_constant_string_object_section ();
959       else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
960         objc_string_object_section ();
961       else
962         base_function ();
963     }
964   else if (TREE_CODE (exp) == VAR_DECL &&
965            DECL_NAME (exp) &&
966            TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
967            IDENTIFIER_POINTER (DECL_NAME (exp)) &&
968            !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
969     {
970       const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
971
972       if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
973         objc_cls_meth_section ();
974       else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
975         objc_inst_meth_section ();
976       else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
977         objc_cat_cls_meth_section ();
978       else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
979         objc_cat_inst_meth_section ();
980       else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
981         objc_class_vars_section ();
982       else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
983         objc_instance_vars_section ();
984       else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
985         objc_cat_cls_meth_section ();
986       else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
987         objc_class_names_section ();
988       else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
989         objc_meth_var_names_section ();
990       else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
991         objc_meth_var_types_section ();
992       else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
993         objc_cls_refs_section ();
994       else if (!strncmp (name, "_OBJC_CLASS_", 12))
995         objc_class_section ();
996       else if (!strncmp (name, "_OBJC_METACLASS_", 16))
997         objc_meta_class_section ();
998       else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
999         objc_category_section ();
1000       else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1001         objc_selector_refs_section ();
1002       else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1003         objc_selector_fixup_section ();
1004       else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1005         objc_symbols_section ();
1006       else if (!strncmp (name, "_OBJC_MODULES", 13))
1007         objc_module_info_section ();
1008       else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
1009         objc_image_info_section ();
1010       else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1011         objc_cat_inst_meth_section ();
1012       else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1013         objc_cat_cls_meth_section ();
1014       else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1015         objc_cat_cls_meth_section ();
1016       else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1017         objc_protocol_section ();
1018       else
1019         base_function ();
1020     }
1021   else
1022     base_function ();
1023 }
1024
1025 /* This can be called with address expressions as "rtx".
1026    They must go in "const".  */
1027
1028 void
1029 machopic_select_rtx_section (enum machine_mode mode, rtx x,
1030                              unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1031 {
1032   if (GET_MODE_SIZE (mode) == 8)
1033     literal8_section ();
1034   else if (GET_MODE_SIZE (mode) == 4
1035            && (GET_CODE (x) == CONST_INT
1036                || GET_CODE (x) == CONST_DOUBLE))
1037     literal4_section ();
1038   else if (MACHOPIC_INDIRECT
1039            && (GET_CODE (x) == SYMBOL_REF
1040                || GET_CODE (x) == CONST
1041                || GET_CODE (x) == LABEL_REF))
1042     const_data_section ();
1043   else
1044     const_section ();
1045 }
1046
1047 void
1048 machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1049 {
1050   if (MACHOPIC_INDIRECT)
1051     mod_init_section ();
1052   else
1053     constructor_section ();
1054   assemble_align (POINTER_SIZE);
1055   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1056
1057   if (! MACHOPIC_INDIRECT)
1058     fprintf (asm_out_file, ".reference .constructors_used\n");
1059 }
1060
1061 void
1062 machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1063 {
1064   if (MACHOPIC_INDIRECT)
1065     mod_term_section ();
1066   else
1067     destructor_section ();
1068   assemble_align (POINTER_SIZE);
1069   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1070
1071   if (! MACHOPIC_INDIRECT)
1072     fprintf (asm_out_file, ".reference .destructors_used\n");
1073 }
1074
1075 void
1076 darwin_globalize_label (FILE *stream, const char *name)
1077 {
1078   if (!!strncmp (name, "_OBJC_", 6))
1079     default_globalize_label (stream, name);
1080 }
1081
1082 void
1083 darwin_asm_named_section (const char *name, unsigned int flags ATTRIBUTE_UNUSED)
1084 {
1085   if (flag_reorder_blocks_and_partition)
1086     fprintf (asm_out_file, SECTION_FORMAT_STRING, name);
1087   else
1088     fprintf (asm_out_file, ".section %s\n", name);
1089 }
1090
1091 unsigned int
1092 darwin_section_type_flags (tree decl, const char *name, int reloc)
1093 {
1094   unsigned int flags = default_section_type_flags (decl, name, reloc);
1095  
1096   /* Weak or linkonce variables live in a writable section.  */
1097   if (decl != 0 && TREE_CODE (decl) != FUNCTION_DECL
1098       && (DECL_WEAK (decl) || DECL_ONE_ONLY (decl)))
1099     flags |= SECTION_WRITE;
1100   
1101   return flags;
1102 }              
1103
1104 void 
1105 darwin_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
1106 {
1107   /* Darwin does not use unique sections.  However, the target's
1108      unique_section hook is called for linkonce symbols.  We need
1109      to set an appropriate section for such symbols. */
1110   if (DECL_ONE_ONLY (decl) && !DECL_SECTION_NAME (decl))
1111     darwin_make_decl_one_only (decl);
1112 }
1113
1114 #define HAVE_DEAD_STRIP 0
1115
1116 static void
1117 no_dead_strip (FILE *file, const char *lab)
1118 {
1119   if (HAVE_DEAD_STRIP)
1120     fprintf (file, ".no_dead_strip %s\n", lab);
1121 }
1122
1123 /* Emit a label for an FDE, making it global and/or weak if appropriate. 
1124    The third parameter is nonzero if this is for exception handling.
1125    The fourth parameter is nonzero if this is just a placeholder for an
1126    FDE that we are omitting. */
1127
1128 void 
1129 darwin_emit_unwind_label (FILE *file, tree decl, int for_eh, int empty)
1130 {
1131   tree id = DECL_ASSEMBLER_NAME (decl)
1132     ? DECL_ASSEMBLER_NAME (decl)
1133     : DECL_NAME (decl);
1134
1135   const char *prefix = "_";
1136   const int prefix_len = 1;
1137
1138   const char *base = IDENTIFIER_POINTER (id);
1139   unsigned int base_len = IDENTIFIER_LENGTH (id);
1140
1141   const char *suffix = ".eh";
1142
1143   int need_quotes = name_needs_quotes (base);
1144   int quotes_len = need_quotes ? 2 : 0;
1145   char *lab;
1146
1147   if (! for_eh)
1148     suffix = ".eh1";
1149
1150   lab = xmalloc (prefix_len + base_len + strlen (suffix) + quotes_len + 1);
1151   lab[0] = '\0';
1152
1153   if (need_quotes)
1154     strcat(lab, "\"");
1155   strcat(lab, prefix);
1156   strcat(lab, base);
1157   strcat(lab, suffix);
1158   if (need_quotes)
1159     strcat(lab, "\"");
1160
1161   if (TREE_PUBLIC (decl))
1162     fprintf (file, "%s %s\n",
1163              (DECL_VISIBILITY (decl) != VISIBILITY_HIDDEN
1164               ? ".globl"
1165               : ".private_extern"),
1166              lab);
1167
1168   if (DECL_ONE_ONLY (decl) && TREE_PUBLIC (decl))
1169     fprintf (file, ".weak_definition %s\n", lab);
1170
1171   if (empty)
1172     {
1173       fprintf (file, "%s = 0\n", lab);
1174
1175       /* Mark the absolute .eh and .eh1 style labels as needed to
1176          ensure that we don't dead code strip them and keep such
1177          labels from another instantiation point until we can fix this
1178          properly with group comdat support.  */
1179       no_dead_strip (file, lab);
1180     }
1181   else
1182     fprintf (file, "%s:\n", lab);
1183
1184   free (lab);
1185 }
1186
1187 /* Generate a PC-relative reference to a Mach-O non-lazy-symbol.  */ 
1188
1189 void
1190 darwin_non_lazy_pcrel (FILE *file, rtx addr)
1191 {
1192   const char *nlp_name;
1193
1194   if (GET_CODE (addr) != SYMBOL_REF)
1195     abort ();
1196
1197   nlp_name = machopic_indirection_name (addr, /*stub_p=*/false);
1198   fputs ("\t.long\t", file);
1199   ASM_OUTPUT_LABELREF (file, nlp_name);
1200   fputs ("-.", file);
1201 }
1202
1203 /* Emit an assembler directive to set visibility for a symbol.  The
1204    only supported visibilities are VISIBILITY_DEFAULT and
1205    VISIBILITY_HIDDEN; the latter corresponds to Darwin's "private
1206    extern".  There is no MACH-O equivalent of ELF's
1207    VISIBILITY_INTERNAL or VISIBILITY_PROTECTED. */
1208
1209 void 
1210 darwin_assemble_visibility (tree decl, int vis)
1211 {
1212   if (vis == VISIBILITY_DEFAULT)
1213     ;
1214   else if (vis == VISIBILITY_HIDDEN)
1215     {
1216       fputs ("\t.private_extern ", asm_out_file);
1217       assemble_name (asm_out_file,
1218                      (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
1219       fputs ("\n", asm_out_file);
1220     }
1221   else
1222     warning ("internal and protected visibility attributes not supported"
1223              "in this configuration; ignored");
1224 }
1225
1226 /* Output a difference of two labels that will be an assembly time
1227    constant if the two labels are local.  (.long lab1-lab2 will be
1228    very different if lab1 is at the boundary between two sections; it
1229    will be relocated according to the second section, not the first,
1230    so one ends up with a difference between labels in different
1231    sections, which is bad in the dwarf2 eh context for instance.)  */
1232
1233 static int darwin_dwarf_label_counter;
1234
1235 void
1236 darwin_asm_output_dwarf_delta (FILE *file, int size ATTRIBUTE_UNUSED,
1237                                const char *lab1, const char *lab2)
1238 {
1239   int islocaldiff = (lab1[0] == '*' && lab1[1] == 'L'
1240                      && lab2[0] == '*' && lab2[1] == 'L');
1241
1242   if (islocaldiff)
1243     fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1244   else
1245     fprintf (file, "\t%s\t", ".long");
1246   assemble_name (file, lab1);
1247   fprintf (file, "-");
1248   assemble_name (file, lab2);
1249   if (islocaldiff)
1250     fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1251 }
1252
1253 void
1254 darwin_file_end (void)
1255 {
1256   machopic_finish (asm_out_file);
1257   if (strcmp (lang_hooks.name, "GNU C++") == 0)
1258     {
1259       constructor_section ();
1260       destructor_section ();
1261       ASM_OUTPUT_ALIGN (asm_out_file, 1);
1262     }
1263 }
1264
1265 #include "gt-darwin.h"