OSDN Git Service

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