OSDN Git Service

* varasm.c (make_decl_rtl): Remove call to REDO_SECTION_INFO_P;
[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
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 "rtl.h"
26 #include "regs.h"
27 #include "hard-reg-set.h"
28 #include "real.h"
29 #include "insn-config.h"
30 #include "conditions.h"
31 #include "insn-flags.h"
32 #include "output.h"
33 #include "insn-attr.h"
34 #include "flags.h"
35 #include "tree.h"
36 #include "expr.h"
37 #include "reload.h"
38 #include "function.h"
39 #include "ggc.h"
40 #include "langhooks.h"
41
42 #include "darwin-protos.h"
43
44 extern void machopic_output_stub PARAMS ((FILE *, const char *, const char *));
45
46 static int machopic_data_defined_p PARAMS ((const char *));
47 static int func_name_maybe_scoped PARAMS ((const char *));
48 static void update_non_lazy_ptrs PARAMS ((const char *));
49 static void update_stubs PARAMS ((const char *));
50
51 int
52 name_needs_quotes (name)
53      const char *name;
54 {
55   int c;
56   while ((c = *name++) != '\0')
57     if (! ISIDNUM (c))
58       return 1;
59   return 0;
60 }
61
62 /* 
63  * flag_pic = 1 ... generate only indirections
64  * flag_pic = 2 ... generate indirections and pure code
65  */
66
67 /* This module assumes that (const (symbol_ref "foo")) is a legal pic
68    reference, which will not be changed.  */
69
70 static tree machopic_defined_list;
71
72 enum machopic_addr_class
73 machopic_classify_ident (ident)
74      tree ident;
75 {
76   const char *name = IDENTIFIER_POINTER (ident);
77   int lprefix = (((name[0] == '*' || name[0] == '&')
78                   && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
79                  || (   name[0] == '_' 
80                      && name[1] == 'O' 
81                      && name[2] == 'B' 
82                      && name[3] == 'J'
83                      && name[4] == 'C'
84                      && name[5] == '_'));
85   tree temp;
86
87   if (name[0] != '!')
88     {
89       /* Here if no special encoding to be found.  */
90       if (lprefix)
91         {
92           const char *name = IDENTIFIER_POINTER (ident);
93           int len = strlen (name);
94
95           if ((len > 5 && !strcmp (name + len - 5, "$stub"))
96               || (len > 6 && !strcmp (name + len - 6, "$stub\"")))
97             return MACHOPIC_DEFINED_FUNCTION;
98           return MACHOPIC_DEFINED_DATA;
99         }
100
101       for (temp = machopic_defined_list;
102            temp != NULL_TREE;
103            temp = TREE_CHAIN (temp))
104         {
105           if (ident == TREE_VALUE (temp))
106             return MACHOPIC_DEFINED_DATA;
107         }
108
109       if (TREE_ASM_WRITTEN (ident))
110         return MACHOPIC_DEFINED_DATA;
111
112       return MACHOPIC_UNDEFINED;
113     }
114
115   else if (name[1] == 'D')
116     return MACHOPIC_DEFINED_DATA;
117
118   else if (name[1] == 'T')
119     return MACHOPIC_DEFINED_FUNCTION;
120
121   /* It is possible that someone is holding a "stale" name, which has
122      since been defined.  See if there is a "defined" name (i.e,
123      different from NAME only in having a '!D_' or a '!T_' instead of
124      a '!d_' or '!t_' prefix) in the identifier hash tables.  If so, say
125      that this identifier is defined.  */
126   else if (name[1] == 'd' || name[1] == 't')
127     {
128       char *new_name;
129       new_name = (char *)alloca (strlen (name) + 1);
130       strcpy (new_name, name);
131       new_name[1] = (name[1] == 'd') ? 'D' : 'T';
132       if (maybe_get_identifier (new_name) != NULL)
133         return  (name[1] == 'd') ? MACHOPIC_DEFINED_DATA
134                                  : MACHOPIC_DEFINED_FUNCTION;
135     }
136
137   for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp))
138     {
139       if (ident == TREE_VALUE (temp))
140         {
141           if (name[1] == 'T')
142             return MACHOPIC_DEFINED_FUNCTION;
143           else
144             return MACHOPIC_DEFINED_DATA;
145         }
146     }
147   
148   if (name[1] == 't' || name[1] == 'T')
149     {
150       if (lprefix)
151         return MACHOPIC_DEFINED_FUNCTION;
152       else
153         return MACHOPIC_UNDEFINED_FUNCTION;
154     }
155   else
156     {
157       if (lprefix)
158         return MACHOPIC_DEFINED_DATA;
159       else
160         return MACHOPIC_UNDEFINED_DATA;
161     }
162 }
163
164      
165 enum machopic_addr_class
166 machopic_classify_name (name)
167      const char *name;
168 {
169   return machopic_classify_ident (get_identifier (name));
170 }
171
172 int
173 machopic_ident_defined_p (ident)
174      tree ident;
175 {
176   switch (machopic_classify_ident (ident))
177     {
178     case MACHOPIC_UNDEFINED:
179     case MACHOPIC_UNDEFINED_DATA:
180     case MACHOPIC_UNDEFINED_FUNCTION:
181       return 0;
182     default:
183       return 1;
184     }
185 }
186
187 static int
188 machopic_data_defined_p (name)
189      const char *name;
190 {
191   switch (machopic_classify_ident (get_identifier (name)))
192     {
193     case MACHOPIC_DEFINED_DATA:
194       return 1;
195     default:
196       return 0;
197     }
198 }
199
200 int
201 machopic_name_defined_p (name)
202      const char *name;
203 {
204   return machopic_ident_defined_p (get_identifier (name));
205 }
206
207 void
208 machopic_define_ident (ident)
209      tree ident;
210 {
211   if (!machopic_ident_defined_p (ident))
212     machopic_defined_list = 
213       tree_cons (NULL_TREE, ident, machopic_defined_list);
214 }
215
216 void
217 machopic_define_name (name)
218      const char *name;
219 {
220   machopic_define_ident (get_identifier (name));
221 }
222
223 /* This is a static to make inline functions work.  The rtx
224    representing the PIC base symbol always points to here. */
225
226 static char function_base[32];
227
228 static int current_pic_label_num;
229
230 char *
231 machopic_function_base_name ()
232 {
233   static const char *name = NULL;
234   static const char *current_name;
235
236   current_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
237
238   if (name != current_name)
239     {
240       current_function_uses_pic_offset_table = 1;
241
242       /* Save mucho space and time.  Some of the C++ mangled names are over
243          700 characters long!  Note that we produce a label containing a '-'
244          if the function we're compiling is an Objective-C method, as evinced
245          by the incredibly scientific test below.  This is because code in
246          rs6000.c makes the same ugly test when loading the PIC reg.  */
247  
248       ++current_pic_label_num;
249       if (*current_name == '+' || *current_name == '-')
250         sprintf (function_base, "*\"L-%d$pb\"", current_pic_label_num);
251       else
252         sprintf (function_base, "*L%d$pb", current_pic_label_num);
253
254       name = current_name;
255     }
256
257   return function_base;
258 }
259
260 static tree machopic_non_lazy_pointers = NULL;
261
262 /* Return a non-lazy pointer name corresponding to the given name,
263    either by finding it in our list of pointer names, or by generating
264    a new one.  */
265
266 char * 
267 machopic_non_lazy_ptr_name (name)
268      const char *name;
269 {
270   char *temp_name;
271   tree temp, ident = get_identifier (name);
272   
273   for (temp = machopic_non_lazy_pointers;
274        temp != NULL_TREE; 
275        temp = TREE_CHAIN (temp))
276     {
277       if (ident == TREE_VALUE (temp))
278         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
279     }
280
281   STRIP_NAME_ENCODING (name, name);
282
283   /* Try again, but comparing names this time.  */
284   for (temp = machopic_non_lazy_pointers;
285        temp != NULL_TREE; 
286        temp = TREE_CHAIN (temp))
287     {
288       if (TREE_VALUE (temp))
289         {
290           temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
291           STRIP_NAME_ENCODING (temp_name, temp_name);
292           if (strcmp (name, temp_name) == 0)
293             return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
294         }
295     }
296
297   {
298     char *buffer;
299     tree ptr_name;
300
301     buffer = alloca (strlen (name) + 20);
302
303     strcpy (buffer, "&L");
304     if (name[0] == '*')
305       strcat (buffer, name+1);
306     else
307       {
308         strcat (buffer, "_");
309         strcat (buffer, name);
310       }
311       
312     strcat (buffer, "$non_lazy_ptr");
313     ptr_name = get_identifier (buffer);
314
315     machopic_non_lazy_pointers 
316       = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
317
318     TREE_USED (machopic_non_lazy_pointers) = 0;
319
320     return IDENTIFIER_POINTER (ptr_name);
321   }
322 }
323
324 static tree machopic_stubs = 0;
325
326 /* Make sure the GC knows about our homemade lists.  */
327
328 void
329 machopic_add_gc_roots ()
330 {
331   ggc_add_tree_root (&machopic_defined_list, 1);
332   ggc_add_tree_root (&machopic_non_lazy_pointers, 1);
333   ggc_add_tree_root (&machopic_stubs, 1);
334 }
335
336 /* Return the name of the stub corresponding to the given name,
337    generating a new stub name if necessary.  */
338
339 char * 
340 machopic_stub_name (name)
341      const char *name;
342 {
343   tree temp, ident = get_identifier (name);
344   const char *tname;
345
346   for (temp = machopic_stubs;
347        temp != NULL_TREE; 
348        temp = TREE_CHAIN (temp))
349     {
350       if (ident == TREE_VALUE (temp))
351         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
352       tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
353       if (strcmp (name, tname) == 0)
354         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
355       /* A library call name might not be section-encoded yet, so try
356          it against a stripped name.  */
357       if (name[0] != '!'
358           && tname[0] == '!'
359           && strcmp (name, tname + 4) == 0)
360         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
361     }
362
363   STRIP_NAME_ENCODING (name, name);
364
365   {
366     char *buffer;
367     tree ptr_name;
368     int needs_quotes = name_needs_quotes (name);
369
370     buffer = alloca (strlen (name) + 20);
371
372     if (needs_quotes)
373       strcpy (buffer, "&\"L");
374     else
375       strcpy (buffer, "&L");
376     if (name[0] == '*')
377       {
378         strcat (buffer, name+1);
379       }
380     else
381       {
382         strcat (buffer, "_");
383         strcat (buffer, name);
384       }
385
386     if (needs_quotes)
387       strcat (buffer, "$stub\"");
388     else
389       strcat (buffer, "$stub");
390     ptr_name = get_identifier (buffer);
391
392     machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
393     TREE_USED (machopic_stubs) = 0;
394
395     return IDENTIFIER_POINTER (ptr_name);
396   }
397 }
398
399 void
400 machopic_validate_stub_or_non_lazy_ptr (name, validate_stub)
401      const char *name;
402      int validate_stub;
403 {
404   char *real_name;
405   tree temp, ident = get_identifier (name), id2;
406
407     for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
408          temp != NULL_TREE;
409          temp = TREE_CHAIN (temp))
410       if (ident == TREE_PURPOSE (temp))
411         {
412           /* Mark both the stub or non-lazy pointer as well as the
413              original symbol as being referenced.  */
414           TREE_USED (temp) = 1;
415           if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
416             TREE_SYMBOL_REFERENCED (TREE_VALUE (temp)) = 1;
417           STRIP_NAME_ENCODING (real_name, IDENTIFIER_POINTER (TREE_VALUE (temp)));
418           id2 = maybe_get_identifier (real_name);
419           if (id2)
420             TREE_SYMBOL_REFERENCED (id2) = 1;
421         }
422 }
423
424 /* Transform ORIG, which may be any data source, to the corresponding
425    source using indirections.  */
426
427 rtx
428 machopic_indirect_data_reference (orig, reg)
429      rtx orig, reg;
430 {
431   rtx ptr_ref = orig;
432   
433   if (! MACHOPIC_INDIRECT)
434     return orig;
435
436   if (GET_CODE (orig) == SYMBOL_REF)
437     {
438       const char *name = XSTR (orig, 0);
439
440       if (machopic_data_defined_p (name))
441         {
442           rtx pic_base = gen_rtx (SYMBOL_REF, Pmode, 
443                                   machopic_function_base_name ());
444           rtx offset = gen_rtx (CONST, Pmode,
445                                 gen_rtx (MINUS, Pmode, orig, pic_base));
446
447 #if defined (TARGET_TOC) /* i.e., PowerPC */
448           rtx hi_sum_reg = reg;
449
450           if (reg == NULL)
451             abort ();
452
453           emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
454                               gen_rtx (PLUS, Pmode, pic_offset_table_rtx,
455                                        gen_rtx (HIGH, Pmode, offset))));
456           emit_insn (gen_rtx (SET, Pmode, reg,
457                               gen_rtx (LO_SUM, Pmode, hi_sum_reg, offset)));
458
459           orig = reg;
460 #else
461 #if defined (HAVE_lo_sum)
462           if (reg == 0) abort ();
463
464           emit_insn (gen_rtx (SET, VOIDmode, reg,
465                               gen_rtx (HIGH, Pmode, offset)));
466           emit_insn (gen_rtx (SET, VOIDmode, reg,
467                               gen_rtx (LO_SUM, Pmode, reg, offset)));
468           emit_insn (gen_rtx (USE, VOIDmode,
469                               gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
470
471           orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg);
472 #endif
473 #endif
474           return orig;
475         }
476
477       ptr_ref = gen_rtx (SYMBOL_REF, Pmode,
478                          machopic_non_lazy_ptr_name (name));
479
480       ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
481       RTX_UNCHANGING_P (ptr_ref) = 1;
482
483       return ptr_ref;
484     }
485   else if (GET_CODE (orig) == CONST)
486     {
487       rtx base, result;
488
489       /* legitimize both operands of the PLUS */
490       if (GET_CODE (XEXP (orig, 0)) == PLUS)
491         {
492           base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
493                                                    reg);
494           orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
495                                                    (base == reg ? 0 : reg));
496         }
497       else 
498         return orig;
499
500       if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
501         result = plus_constant (base, INTVAL (orig));
502       else
503         result = gen_rtx (PLUS, Pmode, base, orig);
504
505       if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
506         RTX_UNCHANGING_P (result) = 1;
507
508       if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
509         {
510           if (reg)
511             {
512               emit_move_insn (reg, result);
513               result = reg;
514             }
515           else
516             {
517               result = force_reg (GET_MODE (result), result);
518             }
519         }
520
521       return result;
522
523     }
524   else if (GET_CODE (orig) == MEM)
525     XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
526   /* When the target is i386, this code prevents crashes due to the
527      compiler's ignorance on how to move the PIC base register to
528      other registers.  (The reload phase sometimes introduces such
529      insns.)  */
530   else if (GET_CODE (orig) == PLUS
531            && GET_CODE (XEXP (orig, 0)) == REG
532            && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
533 #ifdef I386
534            /* Prevent the same register from being erroneously used
535               as both the base and index registers.  */
536            && GET_CODE (XEXP (orig, 1)) == CONST
537 #endif
538            && reg)
539     {
540       emit_move_insn (reg, XEXP (orig, 0));
541       XEXP (ptr_ref, 0) = reg;
542     }
543   return ptr_ref;
544 }
545
546 /* Transform TARGET (a MEM), which is a function call target, to the
547    corresponding symbol_stub if necessary.  Return a new MEM.  */
548
549 rtx
550 machopic_indirect_call_target (target)
551      rtx target;
552 {
553   if (GET_CODE (target) != MEM)
554     return target;
555
556   if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
557     { 
558       enum machine_mode mode = GET_MODE (XEXP (target, 0));
559       const char *name = XSTR (XEXP (target, 0), 0);
560
561       /* If the name is already defined, we need do nothing.  */
562       if (name[0] == '!' && name[1] == 'T')
563         return target;
564
565       if (!machopic_name_defined_p (name))
566         {
567           const char *stub_name = machopic_stub_name (name);
568
569           XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
570           RTX_UNCHANGING_P (target) = 1;
571         } 
572     }
573
574   return target;
575 }
576
577 rtx
578 machopic_legitimize_pic_address (orig, mode, reg)
579      rtx orig, reg;
580      enum machine_mode mode;
581 {
582   rtx pic_ref = orig;
583
584   if (! MACHOPIC_PURE)
585     return orig;
586
587   /* First handle a simple SYMBOL_REF or LABEL_REF */
588   if (GET_CODE (orig) == LABEL_REF
589       || (GET_CODE (orig) == SYMBOL_REF
590           ))
591     {
592       /* addr(foo) = &func+(foo-func) */
593       rtx pic_base;
594
595       orig = machopic_indirect_data_reference (orig, reg);
596
597       if (GET_CODE (orig) == PLUS 
598           && GET_CODE (XEXP (orig, 0)) == REG)
599         {
600           if (reg == 0)
601             return force_reg (mode, orig);
602
603           emit_move_insn (reg, orig);
604           return reg;
605         }  
606
607       pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ());
608
609       if (GET_CODE (orig) == MEM)
610         {
611           if (reg == 0)
612             {
613               if (reload_in_progress)
614                 abort ();
615               else
616                 reg = gen_reg_rtx (Pmode);
617             }
618         
619 #ifdef HAVE_lo_sum
620           if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF 
621               || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
622             {
623               rtx offset = gen_rtx (CONST, Pmode,
624                                     gen_rtx (MINUS, Pmode,
625                                              XEXP (orig, 0), pic_base));
626 #if defined (TARGET_TOC) /* i.e., PowerPC */
627               /* Generating a new reg may expose opportunities for
628                  common subexpression elimination.  */
629               rtx hi_sum_reg =
630                 (reload_in_progress ? reg : gen_reg_rtx (SImode));
631
632               emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
633                                   gen_rtx (PLUS, Pmode,
634                                            pic_offset_table_rtx,
635                                            gen_rtx (HIGH, Pmode, offset))));
636               emit_insn (gen_rtx (SET, VOIDmode, reg,
637                                   gen_rtx (MEM, GET_MODE (orig),
638                                            gen_rtx (LO_SUM, Pmode, 
639                                                     hi_sum_reg, offset))));
640               pic_ref = reg;
641
642 #else
643               emit_insn (gen_rtx (USE, VOIDmode,
644                               gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
645
646               emit_insn (gen_rtx (SET, VOIDmode, reg,
647                                   gen_rtx (HIGH, Pmode, 
648                                            gen_rtx (CONST, Pmode, offset))));
649               emit_insn (gen_rtx (SET, VOIDmode, reg,
650                                   gen_rtx (LO_SUM, Pmode, reg, 
651                                            gen_rtx (CONST, Pmode, offset))));
652               pic_ref = gen_rtx (PLUS, Pmode,
653                                  pic_offset_table_rtx, reg);
654 #endif
655             }
656           else
657 #endif  /* HAVE_lo_sum */
658             {
659               rtx pic = pic_offset_table_rtx;
660               if (GET_CODE (pic) != REG)
661                 {
662                   emit_move_insn (reg, pic);
663                   pic = reg;
664                 }
665 #if 0
666               emit_insn (gen_rtx (USE, VOIDmode,
667                                   gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
668 #endif
669
670               pic_ref = gen_rtx (PLUS, Pmode,
671                                  pic, 
672                                  gen_rtx (CONST, Pmode, 
673                                           gen_rtx (MINUS, Pmode,
674                                                    XEXP (orig, 0), 
675                                                    pic_base)));
676             }
677           
678 #if !defined (TARGET_TOC)
679           RTX_UNCHANGING_P (pic_ref) = 1;
680           emit_move_insn (reg, pic_ref);
681           pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
682 #endif
683         }
684       else
685         {
686
687 #ifdef HAVE_lo_sum
688           if (GET_CODE (orig) == SYMBOL_REF 
689               || GET_CODE (orig) == LABEL_REF)
690             {
691               rtx offset = gen_rtx (CONST, Pmode,
692                                     gen_rtx (MINUS, Pmode, orig, pic_base));
693 #if defined (TARGET_TOC) /* i.e., PowerPC */
694               rtx hi_sum_reg;
695
696               if (reg == 0)
697                 {
698                   if (reload_in_progress)
699                     abort ();
700                   else
701                     reg = gen_reg_rtx (SImode);
702                 }
703         
704               hi_sum_reg = reg;
705
706               emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
707                                   gen_rtx (PLUS, Pmode,
708                                            pic_offset_table_rtx,
709                                            gen_rtx (HIGH, Pmode, offset))));
710               emit_insn (gen_rtx (SET, VOIDmode, reg,
711                                   gen_rtx (LO_SUM, Pmode,
712                                            hi_sum_reg, offset)));
713               pic_ref = reg;
714 #else
715               emit_insn (gen_rtx (SET, VOIDmode, reg,
716                                   gen_rtx (HIGH, Pmode, offset)));
717               emit_insn (gen_rtx (SET, VOIDmode, reg,
718                                   gen_rtx (LO_SUM, Pmode, reg, offset)));
719               pic_ref = gen_rtx (PLUS, Pmode,
720                                  pic_offset_table_rtx, reg);
721 #endif
722             }
723           else
724 #endif  /*  HAVE_lo_sum  */
725             {
726               if (GET_CODE (orig) == REG)
727                 {
728                   return orig;
729                 }
730               else
731                 {
732                   rtx pic = pic_offset_table_rtx;
733                   if (GET_CODE (pic) != REG)
734                     {
735                       emit_move_insn (reg, pic);
736                       pic = reg;
737                     }
738 #if 0
739                   emit_insn (gen_rtx (USE, VOIDmode,
740                                       pic_offset_table_rtx));
741 #endif
742                   pic_ref = gen_rtx (PLUS, Pmode,
743                                      pic,
744                                      gen_rtx (CONST, Pmode, 
745                                               gen_rtx (MINUS, Pmode,
746                                                        orig, pic_base)));
747                 }
748             }
749         }
750
751       RTX_UNCHANGING_P (pic_ref) = 1;
752
753       if (GET_CODE (pic_ref) != REG)
754         {
755           if (reg != 0)
756             {
757               emit_move_insn (reg, pic_ref);
758               return reg;
759             }
760           else
761             {
762               return force_reg (mode, pic_ref);
763             }
764         }
765       else
766         {
767           return pic_ref;
768         }
769     }
770
771   else if (GET_CODE (orig) == SYMBOL_REF)
772     return orig;
773
774   else if (GET_CODE (orig) == PLUS
775            && (GET_CODE (XEXP (orig, 0)) == MEM
776                || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
777                || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
778            && XEXP (orig, 0) != pic_offset_table_rtx
779            && GET_CODE (XEXP (orig, 1)) != REG)
780     
781     {
782       rtx base;
783       int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
784
785       base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
786       orig = machopic_legitimize_pic_address (XEXP (orig, 1),
787                                               Pmode, (base == reg ? 0 : reg));
788       if (GET_CODE (orig) == CONST_INT)
789         {
790           pic_ref = plus_constant (base, INTVAL (orig));
791           is_complex = 1;
792         }
793       else
794         pic_ref = gen_rtx (PLUS, Pmode, base, orig);
795
796       if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
797         RTX_UNCHANGING_P (pic_ref) = 1;
798
799       if (reg && is_complex)
800         {
801           emit_move_insn (reg, pic_ref);
802           pic_ref = reg;
803         }
804       /* Likewise, should we set special REG_NOTEs here?  */
805     }
806
807   else if (GET_CODE (orig) == CONST)
808     {
809       return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
810     }
811
812   else if (GET_CODE (orig) == MEM
813            && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
814     {
815       rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
816
817       addr = gen_rtx (MEM, GET_MODE (orig), addr);
818       RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
819       emit_move_insn (reg, addr);
820       pic_ref = reg;
821     }
822
823   return pic_ref;
824 }
825
826
827 void
828 machopic_finish (asm_out_file)
829      FILE *asm_out_file;
830 {
831   tree temp;
832
833   for (temp = machopic_stubs;
834        temp != NULL_TREE;
835        temp = TREE_CHAIN (temp))
836     {
837       const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
838       const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
839       char *sym;
840       char *stub;
841
842       if (! TREE_USED (temp))
843         continue;
844
845       /* If the symbol is actually defined, we don't need a stub.  */
846       if (sym_name[0] == '!' && sym_name[1] == 'T')
847         continue;
848
849       STRIP_NAME_ENCODING (sym_name, sym_name);
850
851       sym = alloca (strlen (sym_name) + 2);
852       if (sym_name[0] == '*' || sym_name[0] == '&')
853         strcpy (sym, sym_name + 1);
854       else if (sym_name[0] == '-' || sym_name[0] == '+')
855         strcpy (sym, sym_name);   
856       else
857         sym[0] = '_', strcpy (sym + 1, sym_name);
858
859       stub = alloca (strlen (stub_name) + 2);
860       if (stub_name[0] == '*' || stub_name[0] == '&')
861         strcpy (stub, stub_name + 1);
862       else
863         stub[0] = '_', strcpy (stub + 1, stub_name);
864
865       machopic_output_stub (asm_out_file, sym, stub);
866     }
867
868   for (temp = machopic_non_lazy_pointers;
869        temp != NULL_TREE; 
870        temp = TREE_CHAIN (temp))
871     {
872       char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
873       char *lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
874 #if 0
875       tree decl = lookup_name_darwin (TREE_VALUE (temp));
876 #endif
877
878       if (! TREE_USED (temp))
879         continue;
880
881       if (machopic_ident_defined_p (TREE_VALUE (temp))
882 #if 0 /* add back when we have private externs */
883           || (decl && DECL_PRIVATE_EXTERN (decl))
884 #endif
885           )
886         {
887           data_section ();
888           assemble_align (GET_MODE_ALIGNMENT (Pmode));
889           assemble_label (lazy_name);
890           assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name),
891                             GET_MODE_SIZE (Pmode),
892                             GET_MODE_ALIGNMENT (Pmode), 1);
893         }
894       else
895         {
896           machopic_nl_symbol_ptr_section ();
897           assemble_name (asm_out_file, lazy_name); 
898           fprintf (asm_out_file, ":\n");
899
900           fprintf (asm_out_file, "\t.indirect_symbol ");
901           assemble_name (asm_out_file, sym_name); 
902           fprintf (asm_out_file, "\n");
903
904           assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
905                             GET_MODE_ALIGNMENT (Pmode), 1);
906         }
907     }
908 }
909
910 int 
911 machopic_operand_p (op)
912      rtx op;
913 {
914   if (MACHOPIC_JUST_INDIRECT)
915     {
916       while (GET_CODE (op) == CONST)
917         op = XEXP (op, 0);
918
919       if (GET_CODE (op) == SYMBOL_REF)
920         return machopic_name_defined_p (XSTR (op, 0));
921       else
922         return 0;
923     }
924
925   while (GET_CODE (op) == CONST)
926     op = XEXP (op, 0);
927
928   if (GET_CODE (op) == MINUS
929       && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
930       && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
931       && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
932       && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
933       return 1;
934
935 #if 0 /*def TARGET_TOC*/ /* i.e., PowerPC */
936   /* Without this statement, the compiler crashes while compiling enquire.c
937      when targetting PowerPC.  It is not known why this code is not needed
938      when targetting other processors.  */
939   else if (GET_CODE (op) == SYMBOL_REF
940            && (machopic_classify_name (XSTR (op, 0))
941                == MACHOPIC_DEFINED_FUNCTION))
942     {
943       return 1;
944     }
945 #endif
946
947   return 0;
948 }
949
950 /* This function records whether a given name corresponds to a defined
951    or undefined function or variable, for machopic_classify_ident to
952    use later.  */
953
954 void
955 darwin_encode_section_info (decl, first)
956      tree decl;
957      int first ATTRIBUTE_UNUSED;
958 {
959   char code = '\0';
960   int defined = 0;
961   rtx sym_ref;
962   const char *orig_str;
963   char *new_str;
964   size_t len, new_len;
965
966   if ((TREE_CODE (decl) == FUNCTION_DECL
967        || TREE_CODE (decl) == VAR_DECL)
968       && !DECL_EXTERNAL (decl)
969       && ((TREE_STATIC (decl)
970            && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
971           || (DECL_INITIAL (decl)
972               && DECL_INITIAL (decl) != error_mark_node)))
973     defined = 1;
974
975   if (TREE_CODE (decl) == FUNCTION_DECL)
976     code = (defined ? 'T' : 't');
977   else if (TREE_CODE (decl) == VAR_DECL)
978     code = (defined ? 'D' : 'd');
979
980   if (code == '\0')
981     return;
982
983   sym_ref = XEXP (DECL_RTL (decl), 0);
984   orig_str = XSTR (sym_ref, 0);
985   len = strlen (orig_str) + 1;
986
987   if (orig_str[0] == '!')
988     {
989       /* Already encoded; see if we need to change it.  */
990       if (code == orig_str[1])
991         return;
992       /* Yes, tweak a copy of the name and put it in a new string.  */
993       new_str = alloca (len);
994       memcpy (new_str, orig_str, len);
995       new_str[1] = code;
996       XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
997     }
998   else
999     {
1000       /* Add the encoding.  */
1001       new_len = len + 4;
1002       new_str = alloca (new_len);
1003       new_str[0] = '!';
1004       new_str[1] = code;
1005       new_str[2] = '_';
1006       new_str[3] = '_';
1007       memcpy (new_str + 4, orig_str, len);
1008       XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
1009     }
1010   /* The non-lazy pointer list may have captured references to the
1011      old encoded name, change them.  */
1012   if (TREE_CODE (decl) == VAR_DECL)
1013     update_non_lazy_ptrs (XSTR (sym_ref, 0));
1014   else
1015     update_stubs (XSTR (sym_ref, 0));
1016 }
1017
1018 /* Scan the list of non-lazy pointers and update any recorded names whose
1019    stripped name matches the argument.  */
1020
1021 static void
1022 update_non_lazy_ptrs (name)
1023      const char *name;
1024 {
1025   const char *name1, *name2;
1026   tree temp;
1027
1028   STRIP_NAME_ENCODING (name1, name);
1029
1030   for (temp = machopic_non_lazy_pointers;
1031        temp != NULL_TREE; 
1032        temp = TREE_CHAIN (temp))
1033     {
1034       char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1035
1036       if (*sym_name == '!')
1037         {
1038           STRIP_NAME_ENCODING (name2, sym_name);
1039           if (strcmp (name1, name2) == 0)
1040             {
1041               IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1042               break;
1043             }
1044         }
1045     }
1046 }
1047
1048 /* Function NAME is being defined, and its label has just been output.
1049    If there's already a reference to a stub for this function, we can
1050    just emit the stub label now and we don't bother emitting the stub later. */
1051
1052 void
1053 machopic_output_possible_stub_label (file, name)
1054      FILE *file;
1055      const char *name;
1056 {
1057   tree temp;
1058
1059
1060   /* Ensure we're looking at a section-encoded name.  */
1061   if (name[0] != '!' || (name[1] != 't' && name[1] != 'T'))
1062     return;
1063
1064   for (temp = machopic_stubs;
1065        temp != NULL_TREE;
1066        temp = TREE_CHAIN (temp))
1067     {
1068       const char *sym_name;
1069
1070       sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1071       if (sym_name[0] == '!' && sym_name[1] == 'T'
1072           && ! strcmp (name+2, sym_name+2))
1073         {
1074           ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp)));
1075           /* Avoid generating a stub for this.  */
1076           TREE_USED (temp) = 0;
1077           break;
1078         }
1079     }
1080 }
1081
1082 /* Scan the list of stubs and update any recorded names whose
1083    stripped name matches the argument.  */
1084
1085 static void
1086 update_stubs (name)
1087      const char *name;
1088 {
1089   const char *name1, *name2;
1090   tree temp;
1091
1092   STRIP_NAME_ENCODING (name1, name);
1093
1094   for (temp = machopic_stubs;
1095        temp != NULL_TREE; 
1096        temp = TREE_CHAIN (temp))
1097     {
1098       char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1099
1100       if (*sym_name == '!')
1101         {
1102           STRIP_NAME_ENCODING (name2, sym_name);
1103           if (strcmp (name1, name2) == 0)
1104             {
1105               IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1106               break;
1107             }
1108         }
1109     }
1110 }
1111
1112 void
1113 machopic_asm_out_constructor (symbol, priority)
1114      rtx symbol;
1115      int priority ATTRIBUTE_UNUSED;
1116 {
1117   if (flag_pic)
1118     mod_init_section ();
1119   else
1120     constructor_section ();
1121   assemble_align (POINTER_SIZE);
1122   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1123
1124   if (!flag_pic)
1125     fprintf (asm_out_file, ".reference .constructors_used\n");
1126 }
1127
1128 void
1129 machopic_asm_out_destructor (symbol, priority)
1130      rtx symbol;
1131      int priority ATTRIBUTE_UNUSED;
1132 {
1133   if (flag_pic)
1134     mod_term_section ();
1135   else
1136     destructor_section ();
1137   assemble_align (POINTER_SIZE);
1138   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1139
1140   if (!flag_pic)
1141     fprintf (asm_out_file, ".reference .destructors_used\n");
1142 }