OSDN Git Service

* config/m68k/m68k-none.h: Introduce new ColdFire archs.
[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
3    Free Software Foundation, Inc.
4    Contributed by Apple Computer Inc.
5
6 This file is part of GNU CC.
7
8 GNU CC 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 GNU CC 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 GNU CC; 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
45 static int machopic_data_defined_p (const char *);
46 static void update_non_lazy_ptrs (const char *);
47 static void update_stubs (const char *);
48
49 int
50 name_needs_quotes (const char *name)
51 {
52   int c;
53   while ((c = *name++) != '\0')
54     if (! ISIDNUM (c))
55       return 1;
56   return 0;
57 }
58
59 /*
60  * flag_pic = 1 ... generate only indirections
61  * flag_pic = 2 ... generate indirections and pure code
62  */
63
64 /* This module assumes that (const (symbol_ref "foo")) is a legal pic
65    reference, which will not be changed.  */
66
67 static GTY(()) tree machopic_defined_list;
68
69 enum machopic_addr_class
70 machopic_classify_ident (tree ident)
71 {
72   const char *name = IDENTIFIER_POINTER (ident);
73   int lprefix = (((name[0] == '*' || name[0] == '&')
74                   && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
75                  || (   name[0] == '_'
76                      && name[1] == 'O'
77                      && name[2] == 'B'
78                      && name[3] == 'J'
79                      && name[4] == 'C'
80                      && name[5] == '_'));
81   tree temp;
82
83   /* The PIC base symbol is always defined. */
84   if (! strcmp (name, "<pic base>"))
85     return MACHOPIC_DEFINED_DATA;
86
87   if (name[0] != '!')
88     {
89       /* Here if no special encoding to be found.  */
90       if (lprefix)
91         {
92           const char *name = IDENTIFIER_POINTER (ident);
93           int len = strlen (name);
94
95           if ((len > 5 && !strcmp (name + len - 5, "$stub"))
96               || (len > 6 && !strcmp (name + len - 6, "$stub\"")))
97             return MACHOPIC_DEFINED_FUNCTION;
98           return MACHOPIC_DEFINED_DATA;
99         }
100
101       for (temp = machopic_defined_list;
102            temp != NULL_TREE;
103            temp = TREE_CHAIN (temp))
104         {
105           if (ident == TREE_VALUE (temp))
106             return MACHOPIC_DEFINED_DATA;
107         }
108
109       if (TREE_ASM_WRITTEN (ident))
110         return MACHOPIC_DEFINED_DATA;
111
112       return MACHOPIC_UNDEFINED;
113     }
114
115   else if (name[1] == 'D')
116     return MACHOPIC_DEFINED_DATA;
117
118   else if (name[1] == 'T')
119     return MACHOPIC_DEFINED_FUNCTION;
120
121   /* It is possible that someone is holding a "stale" name, which has
122      since been defined.  See if there is a "defined" name (i.e,
123      different from NAME only in having a '!D_' or a '!T_' instead of
124      a '!d_' or '!t_' prefix) in the identifier hash tables.  If so, say
125      that this identifier is defined.  */
126   else if (name[1] == 'd' || name[1] == 't')
127     {
128       char *new_name;
129       new_name = (char *)alloca (strlen (name) + 1);
130       strcpy (new_name, name);
131       new_name[1] = (name[1] == 'd') ? 'D' : 'T';
132       if (maybe_get_identifier (new_name) != NULL)
133         return  (name[1] == 'd') ? MACHOPIC_DEFINED_DATA
134                                  : MACHOPIC_DEFINED_FUNCTION;
135     }
136
137   for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp))
138     {
139       if (ident == TREE_VALUE (temp))
140         {
141           if (name[1] == 'T')
142             return MACHOPIC_DEFINED_FUNCTION;
143           else
144             return MACHOPIC_DEFINED_DATA;
145         }
146     }
147
148   if (name[1] == 't' || name[1] == 'T')
149     {
150       if (lprefix)
151         return MACHOPIC_DEFINED_FUNCTION;
152       else
153         return MACHOPIC_UNDEFINED_FUNCTION;
154     }
155   else
156     {
157       if (lprefix)
158         return MACHOPIC_DEFINED_DATA;
159       else
160         return MACHOPIC_UNDEFINED_DATA;
161     }
162 }
163
164
165 enum machopic_addr_class
166 machopic_classify_name (const char *name)
167 {
168   return machopic_classify_ident (get_identifier (name));
169 }
170
171 int
172 machopic_ident_defined_p (tree ident)
173 {
174   switch (machopic_classify_ident (ident))
175     {
176     case MACHOPIC_UNDEFINED:
177     case MACHOPIC_UNDEFINED_DATA:
178     case MACHOPIC_UNDEFINED_FUNCTION:
179       return 0;
180     default:
181       return 1;
182     }
183 }
184
185 static int
186 machopic_data_defined_p (const char *name)
187 {
188   switch (machopic_classify_ident (get_identifier (name)))
189     {
190     case MACHOPIC_DEFINED_DATA:
191       return 1;
192     default:
193       return 0;
194     }
195 }
196
197 int
198 machopic_name_defined_p (const char *name)
199 {
200   return machopic_ident_defined_p (get_identifier (name));
201 }
202
203 void
204 machopic_define_ident (tree ident)
205 {
206   if (!machopic_ident_defined_p (ident))
207     machopic_defined_list =
208       tree_cons (NULL_TREE, ident, machopic_defined_list);
209 }
210
211 void
212 machopic_define_name (const char *name)
213 {
214   machopic_define_ident (get_identifier (name));
215 }
216
217 static GTY(()) char * function_base;
218
219 const char *
220 machopic_function_base_name (void)
221 {
222   const char *current_name;
223   /* if dynamic-no-pic is on, we should not get here */
224   if (MACHO_DYNAMIC_NO_PIC_P)
225     abort ();
226   current_name =
227     IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
228
229   if (function_base == NULL)
230     function_base =
231       (char *) ggc_alloc_string ("<pic base>", sizeof ("<pic base>"));
232
233   current_function_uses_pic_offset_table = 1;
234
235   return function_base;
236 }
237
238 static GTY(()) const char * function_base_func_name;
239 static GTY(()) int current_pic_label_num;
240
241 void
242 machopic_output_function_base_name (FILE *file)
243 {
244   const char *current_name;
245
246   /* If dynamic-no-pic is on, we should not get here. */
247   if (MACHO_DYNAMIC_NO_PIC_P)
248     abort ();
249   current_name =
250     IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
251   if (function_base_func_name != current_name)
252     {
253       ++current_pic_label_num;
254       function_base_func_name = current_name;
255     }
256   fprintf (file, "\"L%011d$pb\"", current_pic_label_num);
257 }
258
259 static GTY(()) tree machopic_non_lazy_pointers;
260
261 /* Return a non-lazy pointer name corresponding to the given name,
262    either by finding it in our list of pointer names, or by generating
263    a new one.  */
264
265 const char *
266 machopic_non_lazy_ptr_name (const char *name)
267 {
268   const char *temp_name;
269   tree temp, ident = get_identifier (name);
270
271   for (temp = machopic_non_lazy_pointers;
272        temp != NULL_TREE;
273        temp = TREE_CHAIN (temp))
274     {
275       if (ident == TREE_VALUE (temp))
276         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
277     }
278
279   name = darwin_strip_name_encoding (name);
280
281   /* Try again, but comparing names this time.  */
282   for (temp = machopic_non_lazy_pointers;
283        temp != NULL_TREE;
284        temp = TREE_CHAIN (temp))
285     {
286       if (TREE_VALUE (temp))
287         {
288           temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
289           temp_name = darwin_strip_name_encoding (temp_name);
290           if (strcmp (name, temp_name) == 0)
291             return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
292         }
293     }
294
295   {
296     char *buffer;
297     tree ptr_name;
298
299     buffer = alloca (strlen (name) + 20);
300
301     strcpy (buffer, "&L");
302     if (name[0] == '*')
303       strcat (buffer, name+1);
304     else
305       {
306         strcat (buffer, "_");
307         strcat (buffer, name);
308       }
309
310     strcat (buffer, "$non_lazy_ptr");
311     ptr_name = get_identifier (buffer);
312
313     machopic_non_lazy_pointers
314       = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
315
316     TREE_USED (machopic_non_lazy_pointers) = 0;
317
318     return IDENTIFIER_POINTER (ptr_name);
319   }
320 }
321
322 static GTY(()) tree machopic_stubs;
323
324 /* Return the name of the stub corresponding to the given name,
325    generating a new stub name if necessary.  */
326
327 const char *
328 machopic_stub_name (const char *name)
329 {
330   tree temp, ident = get_identifier (name);
331   const char *tname;
332
333   for (temp = machopic_stubs;
334        temp != NULL_TREE;
335        temp = TREE_CHAIN (temp))
336     {
337       if (ident == TREE_VALUE (temp))
338         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
339       tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
340       if (strcmp (name, tname) == 0)
341         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
342       /* A library call name might not be section-encoded yet, so try
343          it against a stripped name.  */
344       if (name[0] != '!'
345           && tname[0] == '!'
346           && strcmp (name, tname + 4) == 0)
347         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
348     }
349
350   name = darwin_strip_name_encoding (name);
351
352   {
353     char *buffer;
354     tree ptr_name;
355     int needs_quotes = name_needs_quotes (name);
356
357     buffer = alloca (strlen (name) + 20);
358
359     if (needs_quotes)
360       strcpy (buffer, "&\"L");
361     else
362       strcpy (buffer, "&L");
363     if (name[0] == '*')
364       {
365         strcat (buffer, name+1);
366       }
367     else
368       {
369         strcat (buffer, "_");
370         strcat (buffer, name);
371       }
372
373     if (needs_quotes)
374       strcat (buffer, "$stub\"");
375     else
376       strcat (buffer, "$stub");
377     ptr_name = get_identifier (buffer);
378
379     machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
380     TREE_USED (machopic_stubs) = 0;
381
382     return IDENTIFIER_POINTER (ptr_name);
383   }
384 }
385
386 void
387 machopic_validate_stub_or_non_lazy_ptr (const char *name, int validate_stub)
388 {
389   const char *real_name;
390   tree temp, ident = get_identifier (name), id2;
391
392     for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
393          temp != NULL_TREE;
394          temp = TREE_CHAIN (temp))
395       if (ident == TREE_PURPOSE (temp))
396         {
397           /* Mark both the stub or non-lazy pointer as well as the
398              original symbol as being referenced.  */
399           TREE_USED (temp) = 1;
400           if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
401             TREE_SYMBOL_REFERENCED (TREE_VALUE (temp)) = 1;
402           real_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
403           real_name = darwin_strip_name_encoding (real_name);
404           id2 = maybe_get_identifier (real_name);
405           if (id2)
406             TREE_SYMBOL_REFERENCED (id2) = 1;
407         }
408 }
409
410 /* Transform ORIG, which may be any data source, to the corresponding
411    source using indirections.  */
412
413 rtx
414 machopic_indirect_data_reference (rtx orig, rtx reg)
415 {
416   rtx ptr_ref = orig;
417
418   if (! MACHOPIC_INDIRECT)
419     return orig;
420
421   if (GET_CODE (orig) == SYMBOL_REF)
422     {
423       const char *name = XSTR (orig, 0);
424
425       int defined = machopic_data_defined_p (name);
426
427       if (defined && MACHO_DYNAMIC_NO_PIC_P)
428         {
429 #if defined (TARGET_TOC)
430            emit_insn (gen_macho_high (reg, orig));
431            emit_insn (gen_macho_low (reg, reg, orig));
432 #else
433            /* some other cpu -- writeme!  */
434            abort ();
435 #endif
436            return reg;
437         }
438       else if (defined)
439         {
440 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
441           rtx pic_base = gen_rtx (SYMBOL_REF, Pmode,
442                                   machopic_function_base_name ());
443           rtx offset = gen_rtx (CONST, Pmode,
444                                 gen_rtx (MINUS, Pmode, orig, pic_base));
445 #endif
446
447 #if defined (TARGET_TOC) /* i.e., PowerPC */
448           rtx hi_sum_reg = reg;
449
450           if (reg == NULL)
451             abort ();
452
453           emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
454                               gen_rtx (PLUS, Pmode, pic_offset_table_rtx,
455                                        gen_rtx (HIGH, Pmode, offset))));
456           emit_insn (gen_rtx (SET, Pmode, reg,
457                               gen_rtx (LO_SUM, Pmode, hi_sum_reg, offset)));
458
459           orig = reg;
460 #else
461 #if defined (HAVE_lo_sum)
462           if (reg == 0) abort ();
463
464           emit_insn (gen_rtx (SET, VOIDmode, reg,
465                               gen_rtx (HIGH, Pmode, offset)));
466           emit_insn (gen_rtx (SET, VOIDmode, reg,
467                               gen_rtx (LO_SUM, Pmode, reg, offset)));
468           emit_insn (gen_rtx (USE, VOIDmode,
469                               gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
470
471           orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg);
472 #endif
473 #endif
474           return orig;
475         }
476
477       ptr_ref = gen_rtx (SYMBOL_REF, Pmode,
478                          machopic_non_lazy_ptr_name (name));
479
480       ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
481       RTX_UNCHANGING_P (ptr_ref) = 1;
482
483       return ptr_ref;
484     }
485   else if (GET_CODE (orig) == CONST)
486     {
487       rtx base, result;
488
489       /* legitimize both operands of the PLUS */
490       if (GET_CODE (XEXP (orig, 0)) == PLUS)
491         {
492           base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
493                                                    reg);
494           orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
495                                                    (base == reg ? 0 : reg));
496         }
497       else
498         return orig;
499
500       if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
501         result = plus_constant (base, INTVAL (orig));
502       else
503         result = gen_rtx (PLUS, Pmode, base, orig);
504
505       if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
506         {
507           if (reg)
508             {
509               emit_move_insn (reg, result);
510               result = reg;
511             }
512           else
513             {
514               result = force_reg (GET_MODE (result), result);
515             }
516         }
517
518       return result;
519
520     }
521   else if (GET_CODE (orig) == MEM)
522     XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
523   /* When the target is i386, this code prevents crashes due to the
524      compiler's ignorance on how to move the PIC base register to
525      other registers.  (The reload phase sometimes introduces such
526      insns.)  */
527   else if (GET_CODE (orig) == PLUS
528            && GET_CODE (XEXP (orig, 0)) == REG
529            && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
530 #ifdef I386
531            /* Prevent the same register from being erroneously used
532               as both the base and index registers.  */
533            && GET_CODE (XEXP (orig, 1)) == CONST
534 #endif
535            && reg)
536     {
537       emit_move_insn (reg, XEXP (orig, 0));
538       XEXP (ptr_ref, 0) = reg;
539     }
540   return ptr_ref;
541 }
542
543 /* Transform TARGET (a MEM), which is a function call target, to the
544    corresponding symbol_stub if necessary.  Return a new MEM.  */
545
546 rtx
547 machopic_indirect_call_target (rtx target)
548 {
549   if (GET_CODE (target) != MEM)
550     return target;
551
552   if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
553     {
554       enum machine_mode mode = GET_MODE (XEXP (target, 0));
555       const char *name = XSTR (XEXP (target, 0), 0);
556
557       /* If the name is already defined, we need do nothing.  */
558       if (name[0] == '!' && name[1] == 'T')
559         return target;
560
561       if (!machopic_name_defined_p (name))
562         {
563           const char *stub_name = machopic_stub_name (name);
564
565           XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
566           RTX_UNCHANGING_P (target) = 1;
567         }
568     }
569
570   return target;
571 }
572
573 rtx
574 machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
575 {
576   rtx pic_ref = orig;
577
578   if (! MACHOPIC_INDIRECT)
579     return orig;
580
581   /* First handle a simple SYMBOL_REF or LABEL_REF */
582   if (GET_CODE (orig) == LABEL_REF
583       || (GET_CODE (orig) == SYMBOL_REF
584           ))
585     {
586       /* addr(foo) = &func+(foo-func) */
587       rtx pic_base;
588
589       orig = machopic_indirect_data_reference (orig, reg);
590
591       if (GET_CODE (orig) == PLUS
592           && GET_CODE (XEXP (orig, 0)) == REG)
593         {
594           if (reg == 0)
595             return force_reg (mode, orig);
596
597           emit_move_insn (reg, orig);
598           return reg;
599         }
600
601       /* if dynamic-no-pic then use 0 as the pic base  */
602       if (MACHO_DYNAMIC_NO_PIC_P)
603         pic_base = CONST0_RTX (Pmode);
604       else
605       pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ());
606
607       if (GET_CODE (orig) == MEM)
608         {
609           if (reg == 0)
610             {
611               if (reload_in_progress)
612                 abort ();
613               else
614                 reg = gen_reg_rtx (Pmode);
615             }
616
617 #ifdef HAVE_lo_sum
618           if (MACHO_DYNAMIC_NO_PIC_P
619               && (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
620                   || GET_CODE (XEXP (orig, 0)) == LABEL_REF))
621             {
622 #if defined (TARGET_TOC)        /* ppc  */
623               rtx temp_reg = (no_new_pseudos) ? reg : gen_reg_rtx (Pmode);
624               rtx asym = XEXP (orig, 0);
625               rtx mem;
626
627               emit_insn (gen_macho_high (temp_reg, asym));
628               mem = gen_rtx_MEM (GET_MODE (orig),
629                                  gen_rtx (LO_SUM, Pmode, temp_reg, asym));
630               RTX_UNCHANGING_P (mem) = 1;
631               emit_insn (gen_rtx (SET, VOIDmode, reg, mem));
632 #else
633               /* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic  */
634               abort ();
635 #endif
636               pic_ref = reg;
637             }
638           else
639           if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
640               || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
641             {
642               rtx offset = gen_rtx (CONST, Pmode,
643                                     gen_rtx (MINUS, Pmode,
644                                              XEXP (orig, 0), pic_base));
645 #if defined (TARGET_TOC) /* i.e., PowerPC */
646               /* Generating a new reg may expose opportunities for
647                  common subexpression elimination.  */
648               rtx hi_sum_reg =
649                 (reload_in_progress ? reg : gen_reg_rtx (SImode));
650
651               emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
652                                   gen_rtx (PLUS, Pmode,
653                                            pic_offset_table_rtx,
654                                            gen_rtx (HIGH, Pmode, offset))));
655               emit_insn (gen_rtx (SET, VOIDmode, reg,
656                                   gen_rtx (MEM, GET_MODE (orig),
657                                            gen_rtx (LO_SUM, Pmode,
658                                                     hi_sum_reg, offset))));
659               pic_ref = reg;
660
661 #else
662               emit_insn (gen_rtx (USE, VOIDmode,
663                               gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
664
665               emit_insn (gen_rtx (SET, VOIDmode, reg,
666                                   gen_rtx (HIGH, Pmode,
667                                            gen_rtx (CONST, Pmode, offset))));
668               emit_insn (gen_rtx (SET, VOIDmode, reg,
669                                   gen_rtx (LO_SUM, Pmode, reg,
670                                            gen_rtx (CONST, Pmode, offset))));
671               pic_ref = gen_rtx (PLUS, Pmode,
672                                  pic_offset_table_rtx, reg);
673 #endif
674             }
675           else
676 #endif  /* HAVE_lo_sum */
677             {
678               rtx pic = pic_offset_table_rtx;
679               if (GET_CODE (pic) != REG)
680                 {
681                   emit_move_insn (reg, pic);
682                   pic = reg;
683                 }
684 #if 0
685               emit_insn (gen_rtx (USE, VOIDmode,
686                                   gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
687 #endif
688
689               pic_ref = gen_rtx (PLUS, Pmode,
690                                  pic,
691                                  gen_rtx (CONST, Pmode,
692                                           gen_rtx (MINUS, Pmode,
693                                                    XEXP (orig, 0),
694                                                    pic_base)));
695             }
696
697 #if !defined (TARGET_TOC)
698           emit_move_insn (reg, pic_ref);
699           pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
700 #endif
701           RTX_UNCHANGING_P (pic_ref) = 1;
702         }
703       else
704         {
705
706 #ifdef HAVE_lo_sum
707           if (GET_CODE (orig) == SYMBOL_REF
708               || GET_CODE (orig) == LABEL_REF)
709             {
710               rtx offset = gen_rtx (CONST, Pmode,
711                                     gen_rtx (MINUS, Pmode, orig, pic_base));
712 #if defined (TARGET_TOC) /* i.e., PowerPC */
713               rtx hi_sum_reg;
714
715               if (reg == 0)
716                 {
717                   if (reload_in_progress)
718                     abort ();
719                   else
720                     reg = gen_reg_rtx (SImode);
721                 }
722
723               hi_sum_reg = reg;
724
725               emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
726                            (MACHO_DYNAMIC_NO_PIC_P)
727                                 ? gen_rtx (HIGH, Pmode, offset)
728                                 : gen_rtx (PLUS, Pmode,
729                                            pic_offset_table_rtx,
730                                            gen_rtx (HIGH, Pmode, offset))));
731               emit_insn (gen_rtx (SET, VOIDmode, reg,
732                                   gen_rtx (LO_SUM, Pmode,
733                                            hi_sum_reg, offset)));
734               pic_ref = reg;
735               RTX_UNCHANGING_P (pic_ref) = 1;
736 #else
737               emit_insn (gen_rtx (SET, VOIDmode, reg,
738                                   gen_rtx (HIGH, Pmode, offset)));
739               emit_insn (gen_rtx (SET, VOIDmode, reg,
740                                   gen_rtx (LO_SUM, Pmode, reg, offset)));
741               pic_ref = gen_rtx (PLUS, Pmode,
742                                  pic_offset_table_rtx, reg);
743               RTX_UNCHANGING_P (pic_ref) = 1;
744 #endif
745             }
746           else
747 #endif  /*  HAVE_lo_sum  */
748             {
749               if (GET_CODE (orig) == REG)
750                 {
751                   return orig;
752                 }
753               else
754                 {
755                   rtx pic = pic_offset_table_rtx;
756                   if (GET_CODE (pic) != REG)
757                     {
758                       emit_move_insn (reg, pic);
759                       pic = reg;
760                     }
761 #if 0
762                   emit_insn (gen_rtx (USE, VOIDmode,
763                                       pic_offset_table_rtx));
764 #endif
765                   pic_ref = gen_rtx (PLUS, Pmode,
766                                      pic,
767                                      gen_rtx (CONST, Pmode,
768                                               gen_rtx (MINUS, Pmode,
769                                                        orig, pic_base)));
770                 }
771             }
772         }
773
774       if (GET_CODE (pic_ref) != REG)
775         {
776           if (reg != 0)
777             {
778               emit_move_insn (reg, pic_ref);
779               return reg;
780             }
781           else
782             {
783               return force_reg (mode, pic_ref);
784             }
785         }
786       else
787         {
788           return pic_ref;
789         }
790     }
791
792   else if (GET_CODE (orig) == SYMBOL_REF)
793     return orig;
794
795   else if (GET_CODE (orig) == PLUS
796            && (GET_CODE (XEXP (orig, 0)) == MEM
797                || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
798                || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
799            && XEXP (orig, 0) != pic_offset_table_rtx
800            && GET_CODE (XEXP (orig, 1)) != REG)
801
802     {
803       rtx base;
804       int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
805
806       base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
807       orig = machopic_legitimize_pic_address (XEXP (orig, 1),
808                                               Pmode, (base == reg ? 0 : reg));
809       if (GET_CODE (orig) == CONST_INT)
810         {
811           pic_ref = plus_constant (base, INTVAL (orig));
812           is_complex = 1;
813         }
814       else
815         pic_ref = gen_rtx (PLUS, Pmode, base, orig);
816
817       if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
818         RTX_UNCHANGING_P (pic_ref) = 1;
819
820       if (reg && is_complex)
821         {
822           emit_move_insn (reg, pic_ref);
823           pic_ref = reg;
824         }
825       /* Likewise, should we set special REG_NOTEs here?  */
826     }
827
828   else if (GET_CODE (orig) == CONST)
829     {
830       return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
831     }
832
833   else if (GET_CODE (orig) == MEM
834            && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
835     {
836       rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
837
838       addr = gen_rtx (MEM, GET_MODE (orig), addr);
839       RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
840       emit_move_insn (reg, addr);
841       pic_ref = reg;
842     }
843
844   return pic_ref;
845 }
846
847
848 void
849 machopic_finish (FILE *asm_out_file)
850 {
851   tree temp;
852
853   for (temp = machopic_stubs;
854        temp != NULL_TREE;
855        temp = TREE_CHAIN (temp))
856     {
857       const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
858       const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
859       char *sym;
860       char *stub;
861
862       if (! TREE_USED (temp))
863         continue;
864
865       /* If the symbol is actually defined, we don't need a stub.  */
866       if (sym_name[0] == '!' && sym_name[1] == 'T')
867         continue;
868
869       sym_name = darwin_strip_name_encoding (sym_name);
870
871       sym = alloca (strlen (sym_name) + 2);
872       if (sym_name[0] == '*' || sym_name[0] == '&')
873         strcpy (sym, sym_name + 1);
874       else if (sym_name[0] == '-' || sym_name[0] == '+')
875         strcpy (sym, sym_name);
876       else
877         sym[0] = '_', strcpy (sym + 1, sym_name);
878
879       stub = alloca (strlen (stub_name) + 2);
880       if (stub_name[0] == '*' || stub_name[0] == '&')
881         strcpy (stub, stub_name + 1);
882       else
883         stub[0] = '_', strcpy (stub + 1, stub_name);
884
885       machopic_output_stub (asm_out_file, sym, stub);
886     }
887
888   for (temp = machopic_non_lazy_pointers;
889        temp != NULL_TREE;
890        temp = TREE_CHAIN (temp))
891     {
892       const char *const sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
893       const char *const lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
894
895       if (! TREE_USED (temp))
896         continue;
897
898       if (machopic_ident_defined_p (TREE_VALUE (temp)))
899         {
900           data_section ();
901           assemble_align (GET_MODE_ALIGNMENT (Pmode));
902           assemble_label (lazy_name);
903           assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name),
904                             GET_MODE_SIZE (Pmode),
905                             GET_MODE_ALIGNMENT (Pmode), 1);
906         }
907       else
908         {
909           machopic_nl_symbol_ptr_section ();
910           assemble_name (asm_out_file, lazy_name);
911           fprintf (asm_out_file, ":\n");
912
913           fprintf (asm_out_file, "\t.indirect_symbol ");
914           assemble_name (asm_out_file, sym_name);
915           fprintf (asm_out_file, "\n");
916
917           assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
918                             GET_MODE_ALIGNMENT (Pmode), 1);
919         }
920     }
921 }
922
923 int
924 machopic_operand_p (rtx op)
925 {
926   if (MACHOPIC_JUST_INDIRECT)
927     {
928       while (GET_CODE (op) == CONST)
929         op = XEXP (op, 0);
930
931       if (GET_CODE (op) == SYMBOL_REF)
932         return machopic_name_defined_p (XSTR (op, 0));
933       else
934         return 0;
935     }
936
937   while (GET_CODE (op) == CONST)
938     op = XEXP (op, 0);
939
940   if (GET_CODE (op) == MINUS
941       && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
942       && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
943       && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
944       && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
945       return 1;
946
947   return 0;
948 }
949
950 /* This function records whether a given name corresponds to a defined
951    or undefined function or variable, for machopic_classify_ident to
952    use later.  */
953
954 void
955 darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
956 {
957   char code = '\0';
958   int defined = 0;
959   rtx sym_ref;
960   const char *orig_str;
961   char *new_str;
962   size_t len, new_len;
963
964   /* Do the standard encoding things first.  */
965   default_encode_section_info (decl, rtl, first);
966
967   /* With the introduction of symbol_ref flags, some of the following
968      code has become redundant and should be removed at some point.  */
969
970   if ((TREE_CODE (decl) == FUNCTION_DECL
971        || TREE_CODE (decl) == VAR_DECL)
972       && !DECL_EXTERNAL (decl)
973       && ((TREE_STATIC (decl)
974            && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
975           || (DECL_INITIAL (decl)
976               && DECL_INITIAL (decl) != error_mark_node)))
977     defined = 1;
978
979   if (TREE_CODE (decl) == FUNCTION_DECL)
980     code = (defined ? 'T' : 't');
981   else if (TREE_CODE (decl) == VAR_DECL)
982     code = (defined ? 'D' : 'd');
983
984   if (code == '\0')
985     return;
986
987   sym_ref = XEXP (rtl, 0);
988   orig_str = XSTR (sym_ref, 0);
989   len = strlen (orig_str) + 1;
990
991   if (orig_str[0] == '!')
992     {
993       /* Already encoded; see if we need to change it.  */
994       if (code == orig_str[1])
995         return;
996       /* Yes, tweak a copy of the name and put it in a new string.  */
997       new_str = alloca (len);
998       memcpy (new_str, orig_str, len);
999       new_str[1] = code;
1000       XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
1001     }
1002   else
1003     {
1004       /* Add the encoding.  */
1005       new_len = len + 4;
1006       new_str = alloca (new_len);
1007       new_str[0] = '!';
1008       new_str[1] = code;
1009       new_str[2] = '_';
1010       new_str[3] = '_';
1011       memcpy (new_str + 4, orig_str, len);
1012       XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
1013     }
1014   /* The non-lazy pointer list may have captured references to the
1015      old encoded name, change them.  */
1016   if (TREE_CODE (decl) == VAR_DECL)
1017     update_non_lazy_ptrs (XSTR (sym_ref, 0));
1018   else
1019     update_stubs (XSTR (sym_ref, 0));
1020 }
1021
1022 /* Undo the effects of the above.  */
1023
1024 const char *
1025 darwin_strip_name_encoding (const char *str)
1026 {
1027   return str[0] == '!' ? str + 4 : str;
1028 }
1029
1030 /* Scan the list of non-lazy pointers and update any recorded names whose
1031    stripped name matches the argument.  */
1032
1033 static void
1034 update_non_lazy_ptrs (const char *name)
1035 {
1036   const char *name1, *name2;
1037   tree temp;
1038
1039   name1 = darwin_strip_name_encoding (name);
1040
1041   for (temp = machopic_non_lazy_pointers;
1042        temp != NULL_TREE;
1043        temp = TREE_CHAIN (temp))
1044     {
1045       const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1046
1047       if (*sym_name == '!')
1048         {
1049           name2 = darwin_strip_name_encoding (sym_name);
1050           if (strcmp (name1, name2) == 0)
1051             {
1052               /* FIXME: This breaks the identifier hash table.  */
1053               IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1054                 = (unsigned char *) name;
1055               break;
1056             }
1057         }
1058     }
1059 }
1060
1061 /* Function NAME is being defined, and its label has just been output.
1062    If there's already a reference to a stub for this function, we can
1063    just emit the stub label now and we don't bother emitting the stub later.  */
1064
1065 void
1066 machopic_output_possible_stub_label (FILE *file, const char *name)
1067 {
1068   tree temp;
1069
1070
1071   /* Ensure we're looking at a section-encoded name.  */
1072   if (name[0] != '!' || (name[1] != 't' && name[1] != 'T'))
1073     return;
1074
1075   for (temp = machopic_stubs;
1076        temp != NULL_TREE;
1077        temp = TREE_CHAIN (temp))
1078     {
1079       const char *sym_name;
1080
1081       sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1082       if (sym_name[0] == '!' && sym_name[1] == 'T'
1083           && ! strcmp (name+2, sym_name+2))
1084         {
1085           ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp)));
1086           /* Avoid generating a stub for this.  */
1087           TREE_USED (temp) = 0;
1088           break;
1089         }
1090     }
1091 }
1092
1093 /* Scan the list of stubs and update any recorded names whose
1094    stripped name matches the argument.  */
1095
1096 static void
1097 update_stubs (const char *name)
1098 {
1099   const char *name1, *name2;
1100   tree temp;
1101
1102   name1 = darwin_strip_name_encoding (name);
1103
1104   for (temp = machopic_stubs;
1105        temp != NULL_TREE;
1106        temp = TREE_CHAIN (temp))
1107     {
1108       const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1109
1110       if (*sym_name == '!')
1111         {
1112           name2 = darwin_strip_name_encoding (sym_name);
1113           if (strcmp (name1, name2) == 0)
1114             {
1115               /* FIXME: This breaks the identifier hash table.  */
1116               IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1117                 = (unsigned char *) name;
1118               break;
1119             }
1120         }
1121     }
1122 }
1123
1124 void
1125 machopic_select_section (tree exp, int reloc,
1126                          unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1127 {
1128   void (*base_function)(void);
1129
1130   if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
1131     base_function = readonly_data_section;
1132   else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1133     base_function = const_data_section;
1134   else
1135     base_function = data_section;
1136
1137   if (TREE_CODE (exp) == STRING_CST
1138       && ((size_t) TREE_STRING_LENGTH (exp)
1139           == strlen (TREE_STRING_POINTER (exp)) + 1)
1140       && ! flag_writable_strings)
1141     cstring_section ();
1142   else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
1143            && flag_merge_constants)
1144     {
1145       tree size = TYPE_SIZE (TREE_TYPE (exp));
1146
1147       if (TREE_CODE (size) == INTEGER_CST &&
1148           TREE_INT_CST_LOW (size) == 4 &&
1149           TREE_INT_CST_HIGH (size) == 0)
1150         literal4_section ();
1151       else if (TREE_CODE (size) == INTEGER_CST &&
1152                TREE_INT_CST_LOW (size) == 8 &&
1153                TREE_INT_CST_HIGH (size) == 0)
1154         literal8_section ();
1155       else
1156         base_function ();
1157     }
1158   else if (TREE_CODE (exp) == CONSTRUCTOR
1159            && TREE_TYPE (exp)
1160            && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1161            && TYPE_NAME (TREE_TYPE (exp)))
1162     {
1163       tree name = TYPE_NAME (TREE_TYPE (exp));
1164       if (TREE_CODE (name) == TYPE_DECL)
1165         name = DECL_NAME (name);
1166       if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1167         objc_constant_string_object_section ();
1168       else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1169         objc_string_object_section ();
1170       else
1171         base_function ();
1172     }
1173   else if (TREE_CODE (exp) == VAR_DECL &&
1174            DECL_NAME (exp) &&
1175            TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1176            IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1177            !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1178     {
1179       const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1180
1181       if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1182         objc_cls_meth_section ();
1183       else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1184         objc_inst_meth_section ();
1185       else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1186         objc_cat_cls_meth_section ();
1187       else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1188         objc_cat_inst_meth_section ();
1189       else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1190         objc_class_vars_section ();
1191       else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1192         objc_instance_vars_section ();
1193       else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1194         objc_cat_cls_meth_section ();
1195       else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1196         objc_class_names_section ();
1197       else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1198         objc_meth_var_names_section ();
1199       else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1200         objc_meth_var_types_section ();
1201       else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1202         objc_cls_refs_section ();
1203       else if (!strncmp (name, "_OBJC_CLASS_", 12))
1204         objc_class_section ();
1205       else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1206         objc_meta_class_section ();
1207       else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1208         objc_category_section ();
1209       else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1210         objc_selector_refs_section ();
1211       else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1212         objc_selector_fixup_section ();
1213       else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1214         objc_symbols_section ();
1215       else if (!strncmp (name, "_OBJC_MODULES", 13))
1216         objc_module_info_section ();
1217       else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1218         objc_cat_inst_meth_section ();
1219       else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1220         objc_cat_cls_meth_section ();
1221       else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1222         objc_cat_cls_meth_section ();
1223       else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1224         objc_protocol_section ();
1225       else
1226         base_function ();
1227     }
1228   else
1229     base_function ();
1230 }
1231
1232 /* This can be called with address expressions as "rtx".
1233    They must go in "const".  */
1234
1235 void
1236 machopic_select_rtx_section (enum machine_mode mode, rtx x,
1237                              unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1238 {
1239   if (GET_MODE_SIZE (mode) == 8)
1240     literal8_section ();
1241   else if (GET_MODE_SIZE (mode) == 4
1242            && (GET_CODE (x) == CONST_INT
1243                || GET_CODE (x) == CONST_DOUBLE))
1244     literal4_section ();
1245   else
1246     const_section ();
1247 }
1248
1249 void
1250 machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1251 {
1252
1253   if (MACHOPIC_INDIRECT)
1254     mod_init_section ();
1255   else
1256     constructor_section ();
1257   assemble_align (POINTER_SIZE);
1258   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1259
1260
1261   if (! MACHOPIC_INDIRECT)
1262     fprintf (asm_out_file, ".reference .constructors_used\n");
1263 }
1264
1265 void
1266 machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1267 {
1268
1269   if (MACHOPIC_INDIRECT)
1270     mod_term_section ();
1271   else
1272     destructor_section ();
1273   assemble_align (POINTER_SIZE);
1274   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1275
1276   if (! MACHOPIC_INDIRECT)
1277     fprintf (asm_out_file, ".reference .destructors_used\n");
1278 }
1279
1280 void
1281 darwin_globalize_label (FILE *stream, const char *name)
1282 {
1283   if (!!strncmp (name, "_OBJC_", 6))
1284     default_globalize_label (stream, name);
1285 }
1286
1287 /* Output a difference of two labels that will be an assembly time
1288    constant if the two labels are local.  (.long lab1-lab2 will be
1289    very different if lab1 is at the boundary between two sections; it
1290    will be relocated according to the second section, not the first,
1291    so one ends up with a difference between labels in different
1292    sections, which is bad in the dwarf2 eh context for instance.)  */
1293
1294 static int darwin_dwarf_label_counter;
1295
1296 void
1297 darwin_asm_output_dwarf_delta (FILE *file, int size ATTRIBUTE_UNUSED,
1298                                const char *lab1, const char *lab2)
1299 {
1300   const char *p = lab1 + (lab1[0] == '*');
1301   int islocaldiff = (p[0] == 'L');
1302
1303   if (islocaldiff)
1304     fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1305   else
1306     fprintf (file, "\t%s\t", ".long");
1307   assemble_name (file, lab1);
1308   fprintf (file, "-");
1309   assemble_name (file, lab2);
1310   if (islocaldiff)
1311     fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1312 }
1313
1314 void
1315 darwin_file_end (void)
1316 {
1317   machopic_finish (asm_out_file);
1318   if (strcmp (lang_hooks.name, "GNU C++") == 0)
1319     {
1320       constructor_section ();
1321       destructor_section ();
1322       ASM_OUTPUT_ALIGN (asm_out_file, 1);
1323     }
1324 }
1325
1326 #include "gt-darwin.h"