OSDN Git Service

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