OSDN Git Service

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