OSDN Git Service

* c-format.c (maybe_read_dollar_number): Use safe-ctype macros
[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 (! ISIDNUM (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 const 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   const char *tname;
328
329   for (temp = machopic_stubs;
330        temp != NULL_TREE; 
331        temp = TREE_CHAIN (temp))
332     {
333       if (ident == TREE_VALUE (temp))
334         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
335       tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
336       if (strcmp (name, tname) == 0)
337         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
338       /* A library call name might not be section-encoded yet, so try
339          it against a stripped name.  */
340       if (name[0] != '!'
341           && tname[0] == '!'
342           && strcmp (name, tname + 4) == 0)
343         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
344     }
345
346   STRIP_NAME_ENCODING (name, name);
347
348   {
349     char *buffer;
350     tree ptr_name;
351     int needs_quotes = name_needs_quotes (name);
352
353     buffer = alloca (strlen (name) + 20);
354
355     if (needs_quotes)
356       strcpy (buffer, "&\"L");
357     else
358       strcpy (buffer, "&L");
359     if (name[0] == '*')
360       {
361         strcat (buffer, name+1);
362       }
363     else
364       {
365         strcat (buffer, "_");
366         strcat (buffer, name);
367       }
368
369     if (needs_quotes)
370       strcat (buffer, "$stub\"");
371     else
372       strcat (buffer, "$stub");
373     ptr_name = get_identifier (buffer);
374
375     machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
376     TREE_USED (machopic_stubs) = 0;
377
378     return IDENTIFIER_POINTER (ptr_name);
379   }
380 }
381
382 void
383 machopic_validate_stub_or_non_lazy_ptr (name, validate_stub)
384      const char *name;
385      int validate_stub;
386 {
387   char *real_name;
388   tree temp, ident = get_identifier (name), id2;
389
390     for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
391          temp != NULL_TREE;
392          temp = TREE_CHAIN (temp))
393       if (ident == TREE_PURPOSE (temp))
394         {
395           /* Mark both the stub or non-lazy pointer as well as the
396              original symbol as being referenced.  */
397           TREE_USED (temp) = 1;
398           if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
399             TREE_SYMBOL_REFERENCED (TREE_VALUE (temp)) = 1;
400           STRIP_NAME_ENCODING (real_name, IDENTIFIER_POINTER (TREE_VALUE (temp)));
401           id2 = maybe_get_identifier (real_name);
402           if (id2)
403             TREE_SYMBOL_REFERENCED (id2) = 1;
404         }
405 }
406
407 /* Transform ORIG, which may be any data source, to the corresponding
408    source using indirections.  */
409
410 rtx
411 machopic_indirect_data_reference (orig, reg)
412      rtx orig, reg;
413 {
414   rtx ptr_ref = orig;
415   
416   if (! MACHOPIC_INDIRECT)
417     return orig;
418
419   if (GET_CODE (orig) == SYMBOL_REF)
420     {
421       const char *name = XSTR (orig, 0);
422
423       if (machopic_data_defined_p (name))
424         {
425           rtx pic_base = gen_rtx (SYMBOL_REF, Pmode, 
426                                   machopic_function_base_name ());
427           rtx offset = gen_rtx (CONST, Pmode,
428                                 gen_rtx (MINUS, Pmode, orig, pic_base));
429
430 #if defined (TARGET_TOC) /* i.e., PowerPC */
431           rtx hi_sum_reg = reg;
432
433           if (reg == NULL)
434             abort ();
435
436           emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
437                               gen_rtx (PLUS, Pmode, pic_offset_table_rtx,
438                                        gen_rtx (HIGH, Pmode, offset))));
439           emit_insn (gen_rtx (SET, Pmode, reg,
440                               gen_rtx (LO_SUM, Pmode, hi_sum_reg, offset)));
441
442           orig = reg;
443 #else
444 #if defined (HAVE_lo_sum)
445           if (reg == 0) abort ();
446
447           emit_insn (gen_rtx (SET, VOIDmode, reg,
448                               gen_rtx (HIGH, Pmode, offset)));
449           emit_insn (gen_rtx (SET, VOIDmode, reg,
450                               gen_rtx (LO_SUM, Pmode, reg, offset)));
451           emit_insn (gen_rtx (USE, VOIDmode,
452                               gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
453
454           orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg);
455 #endif
456 #endif
457           return orig;
458         }
459
460       ptr_ref = gen_rtx (SYMBOL_REF, Pmode,
461                          machopic_non_lazy_ptr_name (name));
462
463       ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
464       RTX_UNCHANGING_P (ptr_ref) = 1;
465
466       return ptr_ref;
467     }
468   else if (GET_CODE (orig) == CONST)
469     {
470       rtx base, result;
471
472       /* legitimize both operands of the PLUS */
473       if (GET_CODE (XEXP (orig, 0)) == PLUS)
474         {
475           base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
476                                                    reg);
477           orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
478                                                    (base == reg ? 0 : reg));
479         }
480       else 
481         return orig;
482
483       if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
484         result = plus_constant (base, INTVAL (orig));
485       else
486         result = gen_rtx (PLUS, Pmode, base, orig);
487
488       if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
489         RTX_UNCHANGING_P (result) = 1;
490
491       if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
492         {
493           if (reg)
494             {
495               emit_move_insn (reg, result);
496               result = reg;
497             }
498           else
499             {
500               result = force_reg (GET_MODE (result), result);
501             }
502         }
503
504       return result;
505
506     }
507   else if (GET_CODE (orig) == MEM)
508     XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
509   /* When the target is i386, this code prevents crashes due to the
510      compiler's ignorance on how to move the PIC base register to
511      other registers.  (The reload phase sometimes introduces such
512      insns.)  */
513   else if (GET_CODE (orig) == PLUS
514            && GET_CODE (XEXP (orig, 0)) == REG
515            && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
516 #ifdef I386
517            /* Prevent the same register from being erroneously used
518               as both the base and index registers.  */
519            && GET_CODE (XEXP (orig, 1)) == CONST
520 #endif
521            && reg)
522     {
523       emit_move_insn (reg, XEXP (orig, 0));
524       XEXP (ptr_ref, 0) = reg;
525     }
526   return ptr_ref;
527 }
528
529 /* For MACHOPIC_INDIRECT_CALL_TARGET below, we need to beware of:
530
531         extern "C" { int f(); }
532         struct X { int f(); int g(); };
533         int X::f() { ::f(); }
534         int X::g() { ::f(); f();}
535
536   This is hairy.  Both calls to "::f()" need to be indirect (i.e., to
537   appropriate symbol stubs), but since MACHOPIC_NAME_DEFINED_P calls
538   GET_IDENTIFIER which treats "f" as "X::f", and "X::f" is indeed (being)
539   defined somewhere in "X"'s inheritance hierarchy, MACHOPIC_NAME_DEFINED_P
540   returns TRUE when called with "f", which means that
541   MACHOPIC_INDIRECT_CALL_TARGET uses an "internal" call instead of an
542   indirect one as it should.
543
544   Our quick-n-dirty solution to this is to call the following
545   FUNC_NAME_MAYBE_SCOPED routine which (only for C++) checks whether
546   FNAME -- the name of the function which we're calling -- is NOT a
547   mangled C++ name, AND if the current function being compiled is a
548   method, and if so, use an "external" or "indirect" call. 
549
550   Note that this function will be called ONLY when MACHOPIC_INDIRECT_TARGET_P
551   has already indicated that the target is NOT indirect.
552
553   This conservative solution will sometimes make indirect calls where
554   it might have been possible to make direct ones.
555
556   FUNC_NAME_MAYBE_SCOPED returns 1 to indicate a "C" name (not scoped),
557   which in turns means we should create a stub for an indirect call.
558   */
559
560 static int is_cplusplus = -1;
561
562 static int
563 func_name_maybe_scoped (fname)
564      const char *fname;
565 {
566
567   if (is_cplusplus < 0)
568     is_cplusplus = (strcmp (lang_identify (), "cplusplus") == 0);
569
570   if (is_cplusplus)
571     {
572       /* If we have a method, then check whether the function we're trying to
573          call is a "C" function.  If so, we should use an indirect call.
574
575          It turns out to be hard to tell whether "we have a method", since
576          static member functions have a TREE_CODE of FUNCTION_TYPE, as do
577          namespace-level non-member functions.  So here, we always look for
578          an extern-"C"-like name, and make stubs for them no matter the
579          calling context.  This is temporary, and leaves nagging suspicion
580          that improvements should be possible here.  (I.e., I suspect that
581          it can still sometimes make stubs where it needn't.)  */
582
583       /* if (1 || TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE) */
584         {
585           /* If fname is of the form "f__1X" or "f__Fv", it's C++.  */
586           while (*fname == '_') ++fname;        /* skip leading underscores  */
587           while (*fname != 0)
588             {
589               if (fname[0] == '_' && fname[1] == '_'
590                   && (fname[2] == 'F' || ISDIGIT (fname[2])))
591                 return 0;
592               ++fname;
593             }
594           /* Not a C++ mangled name: must be "C", in which case play safe.  */
595           return 1;
596         }
597     }
598   return 0;
599 }
600
601 /* Transform TARGET (a MEM), which is a function call target, to the
602    corresponding symbol_stub if necessary.  Return a new MEM.  */
603
604 rtx
605 machopic_indirect_call_target (target)
606      rtx target;
607 {
608   if (GET_CODE (target) != MEM)
609     return target;
610
611   if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
612     { 
613       enum machine_mode mode = GET_MODE (XEXP (target, 0));
614       const char *name = XSTR (XEXP (target, 0), 0);
615
616       if (!machopic_name_defined_p (name) || func_name_maybe_scoped (name)) 
617         {
618           const char *stub_name = machopic_stub_name (name);
619
620           XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
621           RTX_UNCHANGING_P (target) = 1;
622         } 
623     }
624
625   return target;
626 }
627
628 rtx
629 machopic_legitimize_pic_address (orig, mode, reg)
630      rtx orig, reg;
631      enum machine_mode mode;
632 {
633   rtx pic_ref = orig;
634
635   if (! MACHOPIC_PURE)
636     return orig;
637
638   /* First handle a simple SYMBOL_REF or LABEL_REF */
639   if (GET_CODE (orig) == LABEL_REF
640       || (GET_CODE (orig) == SYMBOL_REF
641           ))
642     {
643       /* addr(foo) = &func+(foo-func) */
644       rtx pic_base;
645
646       orig = machopic_indirect_data_reference (orig, reg);
647
648       if (GET_CODE (orig) == PLUS 
649           && GET_CODE (XEXP (orig, 0)) == REG)
650         {
651           if (reg == 0)
652             return force_reg (mode, orig);
653
654           emit_move_insn (reg, orig);
655           return reg;
656         }  
657
658       pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ());
659
660       if (GET_CODE (orig) == MEM)
661         {
662           if (reg == 0)
663             {
664               if (reload_in_progress)
665                 abort ();
666               else
667                 reg = gen_reg_rtx (Pmode);
668             }
669         
670 #ifdef HAVE_lo_sum
671           if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF 
672               || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
673             {
674               rtx offset = gen_rtx (CONST, Pmode,
675                                     gen_rtx (MINUS, Pmode,
676                                              XEXP (orig, 0), pic_base));
677 #if defined (TARGET_TOC) /* i.e., PowerPC */
678               /* Generating a new reg may expose opportunities for
679                  common subexpression elimination.  */
680               rtx hi_sum_reg =
681                 (reload_in_progress ? reg : gen_reg_rtx (SImode));
682
683               emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
684                                   gen_rtx (PLUS, Pmode,
685                                            pic_offset_table_rtx,
686                                            gen_rtx (HIGH, Pmode, offset))));
687               emit_insn (gen_rtx (SET, VOIDmode, reg,
688                                   gen_rtx (MEM, GET_MODE (orig),
689                                            gen_rtx (LO_SUM, Pmode, 
690                                                     hi_sum_reg, offset))));
691               pic_ref = reg;
692
693 #else
694               emit_insn (gen_rtx (USE, VOIDmode,
695                               gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
696
697               emit_insn (gen_rtx (SET, VOIDmode, reg,
698                                   gen_rtx (HIGH, Pmode, 
699                                            gen_rtx (CONST, Pmode, offset))));
700               emit_insn (gen_rtx (SET, VOIDmode, reg,
701                                   gen_rtx (LO_SUM, Pmode, reg, 
702                                            gen_rtx (CONST, Pmode, offset))));
703               pic_ref = gen_rtx (PLUS, Pmode,
704                                  pic_offset_table_rtx, reg);
705 #endif
706             }
707           else
708 #endif  /* HAVE_lo_sum */
709             {
710               rtx pic = pic_offset_table_rtx;
711               if (GET_CODE (pic) != REG)
712                 {
713                   emit_move_insn (reg, pic);
714                   pic = reg;
715                 }
716 #if 0
717               emit_insn (gen_rtx (USE, VOIDmode,
718                                   gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
719 #endif
720
721               pic_ref = gen_rtx (PLUS, Pmode,
722                                  pic, 
723                                  gen_rtx (CONST, Pmode, 
724                                           gen_rtx (MINUS, Pmode,
725                                                    XEXP (orig, 0), 
726                                                    pic_base)));
727             }
728           
729 #if !defined (TARGET_TOC)
730           RTX_UNCHANGING_P (pic_ref) = 1;
731           emit_move_insn (reg, pic_ref);
732           pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
733 #endif
734         }
735       else
736         {
737
738 #ifdef HAVE_lo_sum
739           if (GET_CODE (orig) == SYMBOL_REF 
740               || GET_CODE (orig) == LABEL_REF)
741             {
742               rtx offset = gen_rtx (CONST, Pmode,
743                                     gen_rtx (MINUS, Pmode, orig, pic_base));
744 #if defined (TARGET_TOC) /* i.e., PowerPC */
745               rtx hi_sum_reg;
746
747               if (reg == 0)
748                 {
749                   if (reload_in_progress)
750                     abort ();
751                   else
752                     reg = gen_reg_rtx (SImode);
753                 }
754         
755               hi_sum_reg = reg;
756
757               emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
758                                   gen_rtx (PLUS, Pmode,
759                                            pic_offset_table_rtx,
760                                            gen_rtx (HIGH, Pmode, offset))));
761               emit_insn (gen_rtx (SET, VOIDmode, reg,
762                                   gen_rtx (LO_SUM, Pmode,
763                                            hi_sum_reg, offset)));
764               pic_ref = reg;
765 #else
766               emit_insn (gen_rtx (SET, VOIDmode, reg,
767                                   gen_rtx (HIGH, Pmode, offset)));
768               emit_insn (gen_rtx (SET, VOIDmode, reg,
769                                   gen_rtx (LO_SUM, Pmode, reg, offset)));
770               pic_ref = gen_rtx (PLUS, Pmode,
771                                  pic_offset_table_rtx, reg);
772 #endif
773             }
774           else
775 #endif  /*  HAVE_lo_sum  */
776             {
777               if (GET_CODE (orig) == REG)
778                 {
779                   return orig;
780                 }
781               else
782                 {
783                   rtx pic = pic_offset_table_rtx;
784                   if (GET_CODE (pic) != REG)
785                     {
786                       emit_move_insn (reg, pic);
787                       pic = reg;
788                     }
789 #if 0
790                   emit_insn (gen_rtx (USE, VOIDmode,
791                                       pic_offset_table_rtx));
792 #endif
793                   pic_ref = gen_rtx (PLUS, Pmode,
794                                      pic,
795                                      gen_rtx (CONST, Pmode, 
796                                               gen_rtx (MINUS, Pmode,
797                                                        orig, pic_base)));
798                 }
799             }
800         }
801
802       RTX_UNCHANGING_P (pic_ref) = 1;
803
804       if (GET_CODE (pic_ref) != REG)
805         {
806           if (reg != 0)
807             {
808               emit_move_insn (reg, pic_ref);
809               return reg;
810             }
811           else
812             {
813               return force_reg (mode, pic_ref);
814             }
815         }
816       else
817         {
818           return pic_ref;
819         }
820     }
821
822   else if (GET_CODE (orig) == SYMBOL_REF)
823     return orig;
824
825   else if (GET_CODE (orig) == PLUS
826            && (GET_CODE (XEXP (orig, 0)) == MEM
827                || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
828                || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
829            && XEXP (orig, 0) != pic_offset_table_rtx
830            && GET_CODE (XEXP (orig, 1)) != REG)
831     
832     {
833       rtx base;
834       int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
835
836       base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
837       orig = machopic_legitimize_pic_address (XEXP (orig, 1),
838                                               Pmode, (base == reg ? 0 : reg));
839       if (GET_CODE (orig) == CONST_INT)
840         {
841           pic_ref = plus_constant (base, INTVAL (orig));
842           is_complex = 1;
843         }
844       else
845         pic_ref = gen_rtx (PLUS, Pmode, base, orig);
846
847       if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
848         RTX_UNCHANGING_P (pic_ref) = 1;
849
850       if (reg && is_complex)
851         {
852           emit_move_insn (reg, pic_ref);
853           pic_ref = reg;
854         }
855       /* Likewise, should we set special REG_NOTEs here?  */
856     }
857
858   else if (GET_CODE (orig) == CONST)
859     {
860       return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
861     }
862
863   else if (GET_CODE (orig) == MEM
864            && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
865     {
866       rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
867
868       addr = gen_rtx (MEM, GET_MODE (orig), addr);
869       RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
870       emit_move_insn (reg, addr);
871       pic_ref = reg;
872     }
873
874   return pic_ref;
875 }
876
877
878 void
879 machopic_finish (asm_out_file)
880      FILE *asm_out_file;
881 {
882   tree temp;
883
884   for (temp = machopic_stubs;
885        temp != NULL_TREE;
886        temp = TREE_CHAIN (temp))
887     {
888       char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
889       char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
890       char *sym;
891       char *stub;
892
893       if (! TREE_USED (temp))
894         continue;
895
896       STRIP_NAME_ENCODING (sym_name, sym_name);
897
898       sym = alloca (strlen (sym_name) + 2);
899       if (sym_name[0] == '*' || sym_name[0] == '&')
900         strcpy (sym, sym_name + 1);
901       else if (sym_name[0] == '-' || sym_name[0] == '+')
902         strcpy (sym, sym_name);   
903       else
904         sym[0] = '_', strcpy (sym + 1, sym_name);
905
906       stub = alloca (strlen (stub_name) + 2);
907       if (stub_name[0] == '*' || stub_name[0] == '&')
908         strcpy (stub, stub_name + 1);
909       else
910         stub[0] = '_', strcpy (stub + 1, stub_name);
911
912       machopic_output_stub (asm_out_file, sym, stub);
913     }
914
915   for (temp = machopic_non_lazy_pointers;
916        temp != NULL_TREE; 
917        temp = TREE_CHAIN (temp))
918     {
919       char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
920       char *lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
921 #if 0
922       tree decl = lookup_name_darwin (TREE_VALUE (temp));
923 #endif
924
925       if (! TREE_USED (temp))
926         continue;
927
928       if (machopic_ident_defined_p (TREE_VALUE (temp))
929 #if 0 /* add back when we have private externs */
930           || (decl && DECL_PRIVATE_EXTERN (decl))
931 #endif
932           )
933         {
934           data_section ();
935           assemble_align (GET_MODE_ALIGNMENT (Pmode));
936           assemble_label (lazy_name);
937           assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name),
938                             GET_MODE_SIZE (Pmode),
939                             GET_MODE_ALIGNMENT (Pmode), 1);
940         }
941       else
942         {
943           machopic_nl_symbol_ptr_section ();
944           assemble_name (asm_out_file, lazy_name); 
945           fprintf (asm_out_file, ":\n");
946
947           fprintf (asm_out_file, "\t.indirect_symbol ");
948           assemble_name (asm_out_file, sym_name); 
949           fprintf (asm_out_file, "\n");
950
951           assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
952                             GET_MODE_ALIGNMENT (Pmode), 1);
953         }
954     }
955 }
956
957 int 
958 machopic_operand_p (op)
959      rtx op;
960 {
961   if (MACHOPIC_JUST_INDIRECT)
962     {
963       while (GET_CODE (op) == CONST)
964         op = XEXP (op, 0);
965
966       if (GET_CODE (op) == SYMBOL_REF)
967         return machopic_name_defined_p (XSTR (op, 0));
968       else
969         return 0;
970     }
971
972   while (GET_CODE (op) == CONST)
973     op = XEXP (op, 0);
974
975   if (GET_CODE (op) == MINUS
976       && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
977       && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
978       && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
979       && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
980       return 1;
981
982 #if 0 /*def TARGET_TOC*/ /* i.e., PowerPC */
983   /* Without this statement, the compiler crashes while compiling enquire.c
984      when targetting PowerPC.  It is not known why this code is not needed
985      when targetting other processors.  */
986   else if (GET_CODE (op) == SYMBOL_REF
987            && (machopic_classify_name (XSTR (op, 0))
988                == MACHOPIC_DEFINED_FUNCTION))
989     {
990       return 1;
991     }
992 #endif
993
994   return 0;
995 }
996
997 /* This function records whether a given name corresponds to a defined
998    or undefined function or variable, for machopic_classify_ident to
999    use later.  */
1000
1001 void
1002 darwin_encode_section_info (decl)
1003      tree decl;
1004 {
1005   char code = '\0';
1006   int defined = 0;
1007   rtx sym_ref;
1008   const char *orig_str;
1009   char *new_str;
1010   size_t len, new_len;
1011
1012   if ((TREE_CODE (decl) == FUNCTION_DECL
1013        || TREE_CODE (decl) == VAR_DECL)
1014       && !DECL_EXTERNAL (decl)
1015       && ((TREE_STATIC (decl)
1016            && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
1017           || (DECL_INITIAL (decl)
1018               && DECL_INITIAL (decl) != error_mark_node)))
1019     defined = 1;
1020
1021   if (TREE_CODE (decl) == FUNCTION_DECL)
1022     code = (defined ? 'T' : 't');
1023   else if (TREE_CODE (decl) == VAR_DECL)
1024     code = (defined ? 'D' : 'd');
1025
1026   if (code == '\0')
1027     return;
1028
1029   sym_ref = XEXP (DECL_RTL (decl), 0);
1030   orig_str = XSTR (sym_ref, 0);
1031   len = strlen (orig_str) + 1;
1032
1033   if (orig_str[0] == '!')
1034     {
1035       /* Already encoded; see if we need to change it.  */
1036       if (code == orig_str[1])
1037         return;
1038       /* Yes, tweak a copy of the name and put it in a new string.  */
1039       new_str = alloca (len);
1040       memcpy (new_str, orig_str, len);
1041       new_str[1] = code;
1042       XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
1043     }
1044   else
1045     {
1046       /* Add the encoding.  */
1047       new_len = len + 4;
1048       new_str = alloca (new_len);
1049       new_str[0] = '!';
1050       new_str[1] = code;
1051       new_str[2] = '_';
1052       new_str[3] = '_';
1053       memcpy (new_str + 4, orig_str, len);
1054       XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
1055     }
1056   /* The non-lazy pointer list may have captured references to the
1057      old encoded name, change them.  */
1058   update_non_lazy_ptrs (XSTR (sym_ref, 0));
1059   update_stubs (XSTR (sym_ref, 0));
1060 }
1061
1062 /* Scan the list of non-lazy pointers and update any recorded names whose
1063    stripped name matches the argument.  */
1064
1065 static void
1066 update_non_lazy_ptrs (name)
1067      const char *name;
1068 {
1069   char *name1, *name2;
1070   tree temp;
1071
1072   STRIP_NAME_ENCODING (name1, name);
1073
1074   for (temp = machopic_non_lazy_pointers;
1075        temp != NULL_TREE; 
1076        temp = TREE_CHAIN (temp))
1077     {
1078       char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1079
1080       if (*sym_name == '!')
1081         {
1082           STRIP_NAME_ENCODING (name2, sym_name);
1083           if (strcmp (name1, name2) == 0)
1084             {
1085               IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1086               break;
1087             }
1088         }
1089     }
1090 }
1091
1092
1093 /* Scan the list of stubs and update any recorded names whose
1094    stripped name matches the argument.  */
1095
1096 static void
1097 update_stubs (name)
1098      const char *name;
1099 {
1100   char *name1, *name2;
1101   tree temp;
1102
1103   STRIP_NAME_ENCODING (name1, name);
1104
1105   for (temp = machopic_stubs;
1106        temp != NULL_TREE; 
1107        temp = TREE_CHAIN (temp))
1108     {
1109       char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1110
1111       if (*sym_name == '!')
1112         {
1113           STRIP_NAME_ENCODING (name2, sym_name);
1114           if (strcmp (name1, name2) == 0)
1115             {
1116               IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1117               break;
1118             }
1119         }
1120     }
1121 }
1122
1123 void
1124 machopic_asm_out_constructor (symbol, priority)
1125      rtx symbol;
1126      int priority ATTRIBUTE_UNUSED;
1127 {
1128   if (flag_pic)
1129     mod_init_section ();
1130   else
1131     constructor_section ();
1132   assemble_align (POINTER_SIZE);
1133   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1134
1135   if (!flag_pic)
1136     fprintf (asm_out_file, ".reference .constructors_used\n");
1137 }
1138
1139 void
1140 machopic_asm_out_destructor (symbol, priority)
1141      rtx symbol;
1142      int priority ATTRIBUTE_UNUSED;
1143 {
1144   if (flag_pic)
1145     mod_term_section ();
1146   else
1147     destructor_section ();
1148   assemble_align (POINTER_SIZE);
1149   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1150
1151   if (!flag_pic)
1152     fprintf (asm_out_file, ".reference .destructors_used\n");
1153 }