OSDN Git Service

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