OSDN Git Service

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