OSDN Git Service

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