OSDN Git Service

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