OSDN Git Service

* darwin.c (func_name_maybe_scoped): Remove unused decl.
[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, 2002
3    Free Software Foundation, Inc.
4    Contributed by Apple Computer Inc.
5
6 This file is part of GNU CC.
7
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING.  If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.  */
22
23 #include "config.h"
24 #include "system.h"
25 #include "rtl.h"
26 #include "regs.h"
27 #include "hard-reg-set.h"
28 #include "real.h"
29 #include "insn-config.h"
30 #include "conditions.h"
31 #include "insn-flags.h"
32 #include "output.h"
33 #include "insn-attr.h"
34 #include "flags.h"
35 #include "tree.h"
36 #include "expr.h"
37 #include "reload.h"
38 #include "function.h"
39 #include "ggc.h"
40 #include "langhooks.h"
41 #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 void update_non_lazy_ptrs PARAMS ((const char *));
47 static void update_stubs 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 (! ISIDNUM (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 GTY(()) 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   /* It is possible that someone is holding a "stale" name, which has
120      since been defined.  See if there is a "defined" name (i.e,
121      different from NAME only in having a '!D_' or a '!T_' instead of
122      a '!d_' or '!t_' prefix) in the identifier hash tables.  If so, say
123      that this identifier is defined.  */
124   else if (name[1] == 'd' || name[1] == 't')
125     {
126       char *new_name;
127       new_name = (char *)alloca (strlen (name) + 1);
128       strcpy (new_name, name);
129       new_name[1] = (name[1] == 'd') ? 'D' : 'T';
130       if (maybe_get_identifier (new_name) != NULL)
131         return  (name[1] == 'd') ? MACHOPIC_DEFINED_DATA
132                                  : MACHOPIC_DEFINED_FUNCTION;
133     }
134
135   for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp))
136     {
137       if (ident == TREE_VALUE (temp))
138         {
139           if (name[1] == 'T')
140             return MACHOPIC_DEFINED_FUNCTION;
141           else
142             return MACHOPIC_DEFINED_DATA;
143         }
144     }
145   
146   if (name[1] == 't' || name[1] == 'T')
147     {
148       if (lprefix)
149         return MACHOPIC_DEFINED_FUNCTION;
150       else
151         return MACHOPIC_UNDEFINED_FUNCTION;
152     }
153   else
154     {
155       if (lprefix)
156         return MACHOPIC_DEFINED_DATA;
157       else
158         return MACHOPIC_UNDEFINED_DATA;
159     }
160 }
161
162      
163 enum machopic_addr_class
164 machopic_classify_name (name)
165      const char *name;
166 {
167   return machopic_classify_ident (get_identifier (name));
168 }
169
170 int
171 machopic_ident_defined_p (ident)
172      tree ident;
173 {
174   switch (machopic_classify_ident (ident))
175     {
176     case MACHOPIC_UNDEFINED:
177     case MACHOPIC_UNDEFINED_DATA:
178     case MACHOPIC_UNDEFINED_FUNCTION:
179       return 0;
180     default:
181       return 1;
182     }
183 }
184
185 static int
186 machopic_data_defined_p (name)
187      const char *name;
188 {
189   switch (machopic_classify_ident (get_identifier (name)))
190     {
191     case MACHOPIC_DEFINED_DATA:
192       return 1;
193     default:
194       return 0;
195     }
196 }
197
198 int
199 machopic_name_defined_p (name)
200      const char *name;
201 {
202   return machopic_ident_defined_p (get_identifier (name));
203 }
204
205 void
206 machopic_define_ident (ident)
207      tree ident;
208 {
209   if (!machopic_ident_defined_p (ident))
210     machopic_defined_list = 
211       tree_cons (NULL_TREE, ident, machopic_defined_list);
212 }
213
214 void
215 machopic_define_name (name)
216      const char *name;
217 {
218   machopic_define_ident (get_identifier (name));
219 }
220
221 /* This is a static to make inline functions work.  The rtx
222    representing the PIC base symbol always points to here. */
223
224 static char function_base[32];
225
226 static int current_pic_label_num;
227
228 const char *
229 machopic_function_base_name ()
230 {
231   static const char *name = NULL;
232   static const char *current_name;
233
234   current_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
235
236   if (name != current_name)
237     {
238       current_function_uses_pic_offset_table = 1;
239
240       /* Save mucho space and time.  Some of the C++ mangled names are over
241          700 characters long!  Note that we produce a label containing a '-'
242          if the function we're compiling is an Objective-C method, as evinced
243          by the incredibly scientific test below.  This is because code in
244          rs6000.c makes the same ugly test when loading the PIC reg.  */
245  
246       ++current_pic_label_num;
247       if (*current_name == '+' || *current_name == '-')
248         sprintf (function_base, "*\"L-%d$pb\"", current_pic_label_num);
249       else
250         sprintf (function_base, "*L%d$pb", current_pic_label_num);
251
252       name = current_name;
253     }
254
255   return function_base;
256 }
257
258 static GTY(()) tree machopic_non_lazy_pointers;
259
260 /* Return a non-lazy pointer name corresponding to the given name,
261    either by finding it in our list of pointer names, or by generating
262    a new one.  */
263
264 const char * 
265 machopic_non_lazy_ptr_name (name)
266      const char *name;
267 {
268   char *temp_name;
269   tree temp, ident = get_identifier (name);
270   
271   for (temp = machopic_non_lazy_pointers;
272        temp != NULL_TREE; 
273        temp = TREE_CHAIN (temp))
274     {
275       if (ident == TREE_VALUE (temp))
276         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
277     }
278
279   name = darwin_strip_name_encoding (name);
280
281   /* Try again, but comparing names this time.  */
282   for (temp = machopic_non_lazy_pointers;
283        temp != NULL_TREE; 
284        temp = TREE_CHAIN (temp))
285     {
286       if (TREE_VALUE (temp))
287         {
288           temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
289           temp_name = darwin_strip_name_encoding (temp_name);
290           if (strcmp (name, temp_name) == 0)
291             return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
292         }
293     }
294
295   {
296     char *buffer;
297     tree ptr_name;
298
299     buffer = alloca (strlen (name) + 20);
300
301     strcpy (buffer, "&L");
302     if (name[0] == '*')
303       strcat (buffer, name+1);
304     else
305       {
306         strcat (buffer, "_");
307         strcat (buffer, name);
308       }
309       
310     strcat (buffer, "$non_lazy_ptr");
311     ptr_name = get_identifier (buffer);
312
313     machopic_non_lazy_pointers 
314       = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
315
316     TREE_USED (machopic_non_lazy_pointers) = 0;
317
318     return IDENTIFIER_POINTER (ptr_name);
319   }
320 }
321
322 static GTY(()) tree machopic_stubs;
323
324 /* Return the name of the stub corresponding to the given name,
325    generating a new stub name if necessary.  */
326
327 const char * 
328 machopic_stub_name (name)
329      const char *name;
330 {
331   tree temp, ident = get_identifier (name);
332   const char *tname;
333
334   for (temp = machopic_stubs;
335        temp != NULL_TREE; 
336        temp = TREE_CHAIN (temp))
337     {
338       if (ident == TREE_VALUE (temp))
339         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
340       tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
341       if (strcmp (name, tname) == 0)
342         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
343       /* A library call name might not be section-encoded yet, so try
344          it against a stripped name.  */
345       if (name[0] != '!'
346           && tname[0] == '!'
347           && strcmp (name, tname + 4) == 0)
348         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
349     }
350
351   name = darwin_strip_name_encoding (name);
352
353   {
354     char *buffer;
355     tree ptr_name;
356     int needs_quotes = name_needs_quotes (name);
357
358     buffer = alloca (strlen (name) + 20);
359
360     if (needs_quotes)
361       strcpy (buffer, "&\"L");
362     else
363       strcpy (buffer, "&L");
364     if (name[0] == '*')
365       {
366         strcat (buffer, name+1);
367       }
368     else
369       {
370         strcat (buffer, "_");
371         strcat (buffer, name);
372       }
373
374     if (needs_quotes)
375       strcat (buffer, "$stub\"");
376     else
377       strcat (buffer, "$stub");
378     ptr_name = get_identifier (buffer);
379
380     machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
381     TREE_USED (machopic_stubs) = 0;
382
383     return IDENTIFIER_POINTER (ptr_name);
384   }
385 }
386
387 void
388 machopic_validate_stub_or_non_lazy_ptr (name, validate_stub)
389      const char *name;
390      int validate_stub;
391 {
392   char *real_name;
393   tree temp, ident = get_identifier (name), id2;
394
395     for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
396          temp != NULL_TREE;
397          temp = TREE_CHAIN (temp))
398       if (ident == TREE_PURPOSE (temp))
399         {
400           /* Mark both the stub or non-lazy pointer as well as the
401              original symbol as being referenced.  */
402           TREE_USED (temp) = 1;
403           if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
404             TREE_SYMBOL_REFERENCED (TREE_VALUE (temp)) = 1;
405           real_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
406           real_name = darwin_strip_name_encoding (real_name);
407           id2 = maybe_get_identifier (real_name);
408           if (id2)
409             TREE_SYMBOL_REFERENCED (id2) = 1;
410         }
411 }
412
413 /* Transform ORIG, which may be any data source, to the corresponding
414    source using indirections.  */
415
416 rtx
417 machopic_indirect_data_reference (orig, reg)
418      rtx orig, reg;
419 {
420   rtx ptr_ref = orig;
421   
422   if (! MACHOPIC_INDIRECT)
423     return orig;
424
425   if (GET_CODE (orig) == SYMBOL_REF)
426     {
427       const char *name = XSTR (orig, 0);
428
429       if (machopic_data_defined_p (name))
430         {
431           rtx pic_base = gen_rtx (SYMBOL_REF, Pmode, 
432                                   machopic_function_base_name ());
433           rtx offset = gen_rtx (CONST, Pmode,
434                                 gen_rtx (MINUS, Pmode, orig, pic_base));
435
436 #if defined (TARGET_TOC) /* i.e., PowerPC */
437           rtx hi_sum_reg = reg;
438
439           if (reg == NULL)
440             abort ();
441
442           emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
443                               gen_rtx (PLUS, Pmode, pic_offset_table_rtx,
444                                        gen_rtx (HIGH, Pmode, offset))));
445           emit_insn (gen_rtx (SET, Pmode, reg,
446                               gen_rtx (LO_SUM, Pmode, hi_sum_reg, offset)));
447
448           orig = reg;
449 #else
450 #if defined (HAVE_lo_sum)
451           if (reg == 0) abort ();
452
453           emit_insn (gen_rtx (SET, VOIDmode, reg,
454                               gen_rtx (HIGH, Pmode, offset)));
455           emit_insn (gen_rtx (SET, VOIDmode, reg,
456                               gen_rtx (LO_SUM, Pmode, reg, offset)));
457           emit_insn (gen_rtx (USE, VOIDmode,
458                               gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
459
460           orig = gen_rtx (PLUS, Pmode, pic_offset_table_rtx, reg);
461 #endif
462 #endif
463           return orig;
464         }
465
466       ptr_ref = gen_rtx (SYMBOL_REF, Pmode,
467                          machopic_non_lazy_ptr_name (name));
468
469       ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
470       RTX_UNCHANGING_P (ptr_ref) = 1;
471
472       return ptr_ref;
473     }
474   else if (GET_CODE (orig) == CONST)
475     {
476       rtx base, result;
477
478       /* legitimize both operands of the PLUS */
479       if (GET_CODE (XEXP (orig, 0)) == PLUS)
480         {
481           base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
482                                                    reg);
483           orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
484                                                    (base == reg ? 0 : reg));
485         }
486       else 
487         return orig;
488
489       if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
490         result = plus_constant (base, INTVAL (orig));
491       else
492         result = gen_rtx (PLUS, Pmode, base, orig);
493
494       if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
495         RTX_UNCHANGING_P (result) = 1;
496
497       if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
498         {
499           if (reg)
500             {
501               emit_move_insn (reg, result);
502               result = reg;
503             }
504           else
505             {
506               result = force_reg (GET_MODE (result), result);
507             }
508         }
509
510       return result;
511
512     }
513   else if (GET_CODE (orig) == MEM)
514     XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
515   /* When the target is i386, this code prevents crashes due to the
516      compiler's ignorance on how to move the PIC base register to
517      other registers.  (The reload phase sometimes introduces such
518      insns.)  */
519   else if (GET_CODE (orig) == PLUS
520            && GET_CODE (XEXP (orig, 0)) == REG
521            && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
522 #ifdef I386
523            /* Prevent the same register from being erroneously used
524               as both the base and index registers.  */
525            && GET_CODE (XEXP (orig, 1)) == CONST
526 #endif
527            && reg)
528     {
529       emit_move_insn (reg, XEXP (orig, 0));
530       XEXP (ptr_ref, 0) = reg;
531     }
532   return ptr_ref;
533 }
534
535 /* Transform TARGET (a MEM), which is a function call target, to the
536    corresponding symbol_stub if necessary.  Return a new MEM.  */
537
538 rtx
539 machopic_indirect_call_target (target)
540      rtx target;
541 {
542   if (GET_CODE (target) != MEM)
543     return target;
544
545   if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
546     { 
547       enum machine_mode mode = GET_MODE (XEXP (target, 0));
548       const char *name = XSTR (XEXP (target, 0), 0);
549
550       /* If the name is already defined, we need do nothing.  */
551       if (name[0] == '!' && name[1] == 'T')
552         return target;
553
554       if (!machopic_name_defined_p (name))
555         {
556           const char *stub_name = machopic_stub_name (name);
557
558           XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
559           RTX_UNCHANGING_P (target) = 1;
560         } 
561     }
562
563   return target;
564 }
565
566 rtx
567 machopic_legitimize_pic_address (orig, mode, reg)
568      rtx orig, reg;
569      enum machine_mode mode;
570 {
571   rtx pic_ref = orig;
572
573   if (! MACHOPIC_PURE)
574     return orig;
575
576   /* First handle a simple SYMBOL_REF or LABEL_REF */
577   if (GET_CODE (orig) == LABEL_REF
578       || (GET_CODE (orig) == SYMBOL_REF
579           ))
580     {
581       /* addr(foo) = &func+(foo-func) */
582       rtx pic_base;
583
584       orig = machopic_indirect_data_reference (orig, reg);
585
586       if (GET_CODE (orig) == PLUS 
587           && GET_CODE (XEXP (orig, 0)) == REG)
588         {
589           if (reg == 0)
590             return force_reg (mode, orig);
591
592           emit_move_insn (reg, orig);
593           return reg;
594         }  
595
596       pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ());
597
598       if (GET_CODE (orig) == MEM)
599         {
600           if (reg == 0)
601             {
602               if (reload_in_progress)
603                 abort ();
604               else
605                 reg = gen_reg_rtx (Pmode);
606             }
607         
608 #ifdef HAVE_lo_sum
609           if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF 
610               || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
611             {
612               rtx offset = gen_rtx (CONST, Pmode,
613                                     gen_rtx (MINUS, Pmode,
614                                              XEXP (orig, 0), pic_base));
615 #if defined (TARGET_TOC) /* i.e., PowerPC */
616               /* Generating a new reg may expose opportunities for
617                  common subexpression elimination.  */
618               rtx hi_sum_reg =
619                 (reload_in_progress ? reg : gen_reg_rtx (SImode));
620
621               emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
622                                   gen_rtx (PLUS, Pmode,
623                                            pic_offset_table_rtx,
624                                            gen_rtx (HIGH, Pmode, offset))));
625               emit_insn (gen_rtx (SET, VOIDmode, reg,
626                                   gen_rtx (MEM, GET_MODE (orig),
627                                            gen_rtx (LO_SUM, Pmode, 
628                                                     hi_sum_reg, offset))));
629               pic_ref = reg;
630
631 #else
632               emit_insn (gen_rtx (USE, VOIDmode,
633                               gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
634
635               emit_insn (gen_rtx (SET, VOIDmode, reg,
636                                   gen_rtx (HIGH, Pmode, 
637                                            gen_rtx (CONST, Pmode, offset))));
638               emit_insn (gen_rtx (SET, VOIDmode, reg,
639                                   gen_rtx (LO_SUM, Pmode, reg, 
640                                            gen_rtx (CONST, Pmode, offset))));
641               pic_ref = gen_rtx (PLUS, Pmode,
642                                  pic_offset_table_rtx, reg);
643 #endif
644             }
645           else
646 #endif  /* HAVE_lo_sum */
647             {
648               rtx pic = pic_offset_table_rtx;
649               if (GET_CODE (pic) != REG)
650                 {
651                   emit_move_insn (reg, pic);
652                   pic = reg;
653                 }
654 #if 0
655               emit_insn (gen_rtx (USE, VOIDmode,
656                                   gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
657 #endif
658
659               pic_ref = gen_rtx (PLUS, Pmode,
660                                  pic, 
661                                  gen_rtx (CONST, Pmode, 
662                                           gen_rtx (MINUS, Pmode,
663                                                    XEXP (orig, 0), 
664                                                    pic_base)));
665             }
666           
667 #if !defined (TARGET_TOC)
668           RTX_UNCHANGING_P (pic_ref) = 1;
669           emit_move_insn (reg, pic_ref);
670           pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
671 #endif
672         }
673       else
674         {
675
676 #ifdef HAVE_lo_sum
677           if (GET_CODE (orig) == SYMBOL_REF 
678               || GET_CODE (orig) == LABEL_REF)
679             {
680               rtx offset = gen_rtx (CONST, Pmode,
681                                     gen_rtx (MINUS, Pmode, orig, pic_base));
682 #if defined (TARGET_TOC) /* i.e., PowerPC */
683               rtx hi_sum_reg;
684
685               if (reg == 0)
686                 {
687                   if (reload_in_progress)
688                     abort ();
689                   else
690                     reg = gen_reg_rtx (SImode);
691                 }
692         
693               hi_sum_reg = reg;
694
695               emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
696                                   gen_rtx (PLUS, Pmode,
697                                            pic_offset_table_rtx,
698                                            gen_rtx (HIGH, Pmode, offset))));
699               emit_insn (gen_rtx (SET, VOIDmode, reg,
700                                   gen_rtx (LO_SUM, Pmode,
701                                            hi_sum_reg, offset)));
702               pic_ref = reg;
703 #else
704               emit_insn (gen_rtx (SET, VOIDmode, reg,
705                                   gen_rtx (HIGH, Pmode, offset)));
706               emit_insn (gen_rtx (SET, VOIDmode, reg,
707                                   gen_rtx (LO_SUM, Pmode, reg, offset)));
708               pic_ref = gen_rtx (PLUS, Pmode,
709                                  pic_offset_table_rtx, reg);
710 #endif
711             }
712           else
713 #endif  /*  HAVE_lo_sum  */
714             {
715               if (GET_CODE (orig) == REG)
716                 {
717                   return orig;
718                 }
719               else
720                 {
721                   rtx pic = pic_offset_table_rtx;
722                   if (GET_CODE (pic) != REG)
723                     {
724                       emit_move_insn (reg, pic);
725                       pic = reg;
726                     }
727 #if 0
728                   emit_insn (gen_rtx (USE, VOIDmode,
729                                       pic_offset_table_rtx));
730 #endif
731                   pic_ref = gen_rtx (PLUS, Pmode,
732                                      pic,
733                                      gen_rtx (CONST, Pmode, 
734                                               gen_rtx (MINUS, Pmode,
735                                                        orig, pic_base)));
736                 }
737             }
738         }
739
740       RTX_UNCHANGING_P (pic_ref) = 1;
741
742       if (GET_CODE (pic_ref) != REG)
743         {
744           if (reg != 0)
745             {
746               emit_move_insn (reg, pic_ref);
747               return reg;
748             }
749           else
750             {
751               return force_reg (mode, pic_ref);
752             }
753         }
754       else
755         {
756           return pic_ref;
757         }
758     }
759
760   else if (GET_CODE (orig) == SYMBOL_REF)
761     return orig;
762
763   else if (GET_CODE (orig) == PLUS
764            && (GET_CODE (XEXP (orig, 0)) == MEM
765                || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
766                || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
767            && XEXP (orig, 0) != pic_offset_table_rtx
768            && GET_CODE (XEXP (orig, 1)) != REG)
769     
770     {
771       rtx base;
772       int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
773
774       base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
775       orig = machopic_legitimize_pic_address (XEXP (orig, 1),
776                                               Pmode, (base == reg ? 0 : reg));
777       if (GET_CODE (orig) == CONST_INT)
778         {
779           pic_ref = plus_constant (base, INTVAL (orig));
780           is_complex = 1;
781         }
782       else
783         pic_ref = gen_rtx (PLUS, Pmode, base, orig);
784
785       if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
786         RTX_UNCHANGING_P (pic_ref) = 1;
787
788       if (reg && is_complex)
789         {
790           emit_move_insn (reg, pic_ref);
791           pic_ref = reg;
792         }
793       /* Likewise, should we set special REG_NOTEs here?  */
794     }
795
796   else if (GET_CODE (orig) == CONST)
797     {
798       return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
799     }
800
801   else if (GET_CODE (orig) == MEM
802            && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
803     {
804       rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
805
806       addr = gen_rtx (MEM, GET_MODE (orig), addr);
807       RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
808       emit_move_insn (reg, addr);
809       pic_ref = reg;
810     }
811
812   return pic_ref;
813 }
814
815
816 void
817 machopic_finish (asm_out_file)
818      FILE *asm_out_file;
819 {
820   tree temp;
821
822   for (temp = machopic_stubs;
823        temp != NULL_TREE;
824        temp = TREE_CHAIN (temp))
825     {
826       const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
827       const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
828       char *sym;
829       char *stub;
830
831       if (! TREE_USED (temp))
832         continue;
833
834       /* If the symbol is actually defined, we don't need a stub.  */
835       if (sym_name[0] == '!' && sym_name[1] == 'T')
836         continue;
837
838       sym_name = darwin_strip_name_encoding (sym_name);
839
840       sym = alloca (strlen (sym_name) + 2);
841       if (sym_name[0] == '*' || sym_name[0] == '&')
842         strcpy (sym, sym_name + 1);
843       else if (sym_name[0] == '-' || sym_name[0] == '+')
844         strcpy (sym, sym_name);   
845       else
846         sym[0] = '_', strcpy (sym + 1, sym_name);
847
848       stub = alloca (strlen (stub_name) + 2);
849       if (stub_name[0] == '*' || stub_name[0] == '&')
850         strcpy (stub, stub_name + 1);
851       else
852         stub[0] = '_', strcpy (stub + 1, stub_name);
853
854       machopic_output_stub (asm_out_file, sym, stub);
855     }
856
857   for (temp = machopic_non_lazy_pointers;
858        temp != NULL_TREE; 
859        temp = TREE_CHAIN (temp))
860     {
861       char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
862       char *lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
863 #if 0
864       tree decl = lookup_name_darwin (TREE_VALUE (temp));
865 #endif
866
867       if (! TREE_USED (temp))
868         continue;
869
870       if (machopic_ident_defined_p (TREE_VALUE (temp))
871 #if 0 /* add back when we have private externs */
872           || (decl && DECL_PRIVATE_EXTERN (decl))
873 #endif
874           )
875         {
876           data_section ();
877           assemble_align (GET_MODE_ALIGNMENT (Pmode));
878           assemble_label (lazy_name);
879           assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name),
880                             GET_MODE_SIZE (Pmode),
881                             GET_MODE_ALIGNMENT (Pmode), 1);
882         }
883       else
884         {
885           machopic_nl_symbol_ptr_section ();
886           assemble_name (asm_out_file, lazy_name); 
887           fprintf (asm_out_file, ":\n");
888
889           fprintf (asm_out_file, "\t.indirect_symbol ");
890           assemble_name (asm_out_file, sym_name); 
891           fprintf (asm_out_file, "\n");
892
893           assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
894                             GET_MODE_ALIGNMENT (Pmode), 1);
895         }
896     }
897 }
898
899 int 
900 machopic_operand_p (op)
901      rtx op;
902 {
903   if (MACHOPIC_JUST_INDIRECT)
904     {
905       while (GET_CODE (op) == CONST)
906         op = XEXP (op, 0);
907
908       if (GET_CODE (op) == SYMBOL_REF)
909         return machopic_name_defined_p (XSTR (op, 0));
910       else
911         return 0;
912     }
913
914   while (GET_CODE (op) == CONST)
915     op = XEXP (op, 0);
916
917   if (GET_CODE (op) == MINUS
918       && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
919       && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
920       && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
921       && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
922       return 1;
923
924 #if 0 /*def TARGET_TOC*/ /* i.e., PowerPC */
925   /* Without this statement, the compiler crashes while compiling enquire.c
926      when targetting PowerPC.  It is not known why this code is not needed
927      when targetting other processors.  */
928   else if (GET_CODE (op) == SYMBOL_REF
929            && (machopic_classify_name (XSTR (op, 0))
930                == MACHOPIC_DEFINED_FUNCTION))
931     {
932       return 1;
933     }
934 #endif
935
936   return 0;
937 }
938
939 /* This function records whether a given name corresponds to a defined
940    or undefined function or variable, for machopic_classify_ident to
941    use later.  */
942
943 void
944 darwin_encode_section_info (decl, first)
945      tree decl;
946      int first ATTRIBUTE_UNUSED;
947 {
948   char code = '\0';
949   int defined = 0;
950   rtx sym_ref;
951   const char *orig_str;
952   char *new_str;
953   size_t len, new_len;
954
955   if ((TREE_CODE (decl) == FUNCTION_DECL
956        || TREE_CODE (decl) == VAR_DECL)
957       && !DECL_EXTERNAL (decl)
958       && ((TREE_STATIC (decl)
959            && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
960           || (DECL_INITIAL (decl)
961               && DECL_INITIAL (decl) != error_mark_node)))
962     defined = 1;
963
964   if (TREE_CODE (decl) == FUNCTION_DECL)
965     code = (defined ? 'T' : 't');
966   else if (TREE_CODE (decl) == VAR_DECL)
967     code = (defined ? 'D' : 'd');
968
969   if (code == '\0')
970     return;
971
972   sym_ref = XEXP (DECL_RTL (decl), 0);
973   orig_str = XSTR (sym_ref, 0);
974   len = strlen (orig_str) + 1;
975
976   if (orig_str[0] == '!')
977     {
978       /* Already encoded; see if we need to change it.  */
979       if (code == orig_str[1])
980         return;
981       /* Yes, tweak a copy of the name and put it in a new string.  */
982       new_str = alloca (len);
983       memcpy (new_str, orig_str, len);
984       new_str[1] = code;
985       XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
986     }
987   else
988     {
989       /* Add the encoding.  */
990       new_len = len + 4;
991       new_str = alloca (new_len);
992       new_str[0] = '!';
993       new_str[1] = code;
994       new_str[2] = '_';
995       new_str[3] = '_';
996       memcpy (new_str + 4, orig_str, len);
997       XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
998     }
999   /* The non-lazy pointer list may have captured references to the
1000      old encoded name, change them.  */
1001   if (TREE_CODE (decl) == VAR_DECL)
1002     update_non_lazy_ptrs (XSTR (sym_ref, 0));
1003   else
1004     update_stubs (XSTR (sym_ref, 0));
1005 }
1006
1007 /* Undo the effects of the above.  */
1008
1009 const char *
1010 darwin_strip_name_encoding (str)
1011      const char *str;
1012 {
1013   return str[0] == '!' ? str + 4 : str;
1014 }
1015
1016 /* Scan the list of non-lazy pointers and update any recorded names whose
1017    stripped name matches the argument.  */
1018
1019 static void
1020 update_non_lazy_ptrs (name)
1021      const char *name;
1022 {
1023   const char *name1, *name2;
1024   tree temp;
1025
1026   name1 = darwin_strip_name_encoding (name);
1027
1028   for (temp = machopic_non_lazy_pointers;
1029        temp != NULL_TREE; 
1030        temp = TREE_CHAIN (temp))
1031     {
1032       char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1033
1034       if (*sym_name == '!')
1035         {
1036           name2 = darwin_strip_name_encoding (sym_name);
1037           if (strcmp (name1, name2) == 0)
1038             {
1039               IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1040               break;
1041             }
1042         }
1043     }
1044 }
1045
1046 /* Function NAME is being defined, and its label has just been output.
1047    If there's already a reference to a stub for this function, we can
1048    just emit the stub label now and we don't bother emitting the stub later. */
1049
1050 void
1051 machopic_output_possible_stub_label (file, name)
1052      FILE *file;
1053      const char *name;
1054 {
1055   tree temp;
1056
1057
1058   /* Ensure we're looking at a section-encoded name.  */
1059   if (name[0] != '!' || (name[1] != 't' && name[1] != 'T'))
1060     return;
1061
1062   for (temp = machopic_stubs;
1063        temp != NULL_TREE;
1064        temp = TREE_CHAIN (temp))
1065     {
1066       const char *sym_name;
1067
1068       sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1069       if (sym_name[0] == '!' && sym_name[1] == 'T'
1070           && ! strcmp (name+2, sym_name+2))
1071         {
1072           ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp)));
1073           /* Avoid generating a stub for this.  */
1074           TREE_USED (temp) = 0;
1075           break;
1076         }
1077     }
1078 }
1079
1080 /* Scan the list of stubs and update any recorded names whose
1081    stripped name matches the argument.  */
1082
1083 static void
1084 update_stubs (name)
1085      const char *name;
1086 {
1087   const char *name1, *name2;
1088   tree temp;
1089
1090   name1 = darwin_strip_name_encoding (name);
1091
1092   for (temp = machopic_stubs;
1093        temp != NULL_TREE; 
1094        temp = TREE_CHAIN (temp))
1095     {
1096       char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1097
1098       if (*sym_name == '!')
1099         {
1100           name2 = darwin_strip_name_encoding (sym_name);
1101           if (strcmp (name1, name2) == 0)
1102             {
1103               IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1104               break;
1105             }
1106         }
1107     }
1108 }
1109
1110 void
1111 machopic_select_section (exp, reloc, align)
1112      tree exp;
1113      int reloc;
1114      unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1115 {
1116   if (TREE_CODE (exp) == STRING_CST)
1117     {
1118       if (flag_writable_strings)
1119         data_section ();
1120       else if (TREE_STRING_LENGTH (exp) !=
1121                strlen (TREE_STRING_POINTER (exp)) + 1)
1122         readonly_data_section ();
1123       else
1124         cstring_section ();
1125     }
1126   else if (TREE_CODE (exp) == INTEGER_CST
1127            || TREE_CODE (exp) == REAL_CST)
1128     {
1129       tree size = TYPE_SIZE (TREE_TYPE (exp));
1130
1131       if (TREE_CODE (size) == INTEGER_CST &&
1132           TREE_INT_CST_LOW (size) == 4 &&
1133           TREE_INT_CST_HIGH (size) == 0)
1134         literal4_section ();
1135       else if (TREE_CODE (size) == INTEGER_CST &&
1136                TREE_INT_CST_LOW (size) == 8 &&
1137                TREE_INT_CST_HIGH (size) == 0)
1138         literal8_section ();
1139       else
1140         readonly_data_section ();
1141     }
1142   else if (TREE_CODE (exp) == CONSTRUCTOR
1143            && TREE_TYPE (exp)
1144            && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1145            && TYPE_NAME (TREE_TYPE (exp)))
1146     {
1147       tree name = TYPE_NAME (TREE_TYPE (exp));
1148       if (TREE_CODE (name) == TYPE_DECL)
1149         name = DECL_NAME (name);
1150       if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1151         objc_constant_string_object_section ();
1152       else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1153         objc_string_object_section ();
1154       else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1155         {
1156           if (TREE_SIDE_EFFECTS (exp) || flag_pic && reloc)
1157             const_data_section ();
1158           else
1159             readonly_data_section ();
1160         }
1161       else
1162         data_section ();
1163     }
1164   else if (TREE_CODE (exp) == VAR_DECL &&
1165            DECL_NAME (exp) &&
1166            TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1167            IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1168            !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1169     {
1170       const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1171
1172       if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1173         objc_cls_meth_section ();
1174       else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1175         objc_inst_meth_section ();
1176       else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1177         objc_cat_cls_meth_section ();
1178       else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1179         objc_cat_inst_meth_section ();
1180       else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1181         objc_class_vars_section ();
1182       else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1183         objc_instance_vars_section ();
1184       else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1185         objc_cat_cls_meth_section ();
1186       else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1187         objc_class_names_section ();
1188       else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1189         objc_meth_var_names_section ();
1190       else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1191         objc_meth_var_types_section ();
1192       else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1193         objc_cls_refs_section ();
1194       else if (!strncmp (name, "_OBJC_CLASS_", 12))
1195         objc_class_section ();
1196       else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1197         objc_meta_class_section ();
1198       else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1199         objc_category_section ();
1200       else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1201         objc_selector_refs_section ();
1202       else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1203         objc_selector_fixup_section ();
1204       else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1205         objc_symbols_section ();
1206       else if (!strncmp (name, "_OBJC_MODULES", 13))
1207         objc_module_info_section ();
1208       else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1209         objc_cat_inst_meth_section ();
1210       else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1211         objc_cat_cls_meth_section ();
1212       else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1213         objc_cat_cls_meth_section ();
1214       else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1215         objc_protocol_section ();
1216       else if ((TREE_READONLY (exp) || TREE_CONSTANT (exp))
1217                && !TREE_SIDE_EFFECTS (exp))
1218         {
1219           if (flag_pic && reloc)
1220             const_data_section ();
1221           else
1222             readonly_data_section ();
1223         }
1224       else
1225         data_section ();
1226     }
1227   else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1228     {
1229       if (TREE_SIDE_EFFECTS (exp) || flag_pic && reloc)
1230         const_data_section ();
1231       else
1232         readonly_data_section ();
1233     }
1234   else
1235     data_section ();
1236 }
1237
1238 /* This can be called with address expressions as "rtx".
1239    They must go in "const". */
1240
1241 void
1242 machopic_select_rtx_section (mode, x, align)
1243      enum machine_mode mode;
1244      rtx x;
1245      unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1246 {
1247   if (GET_MODE_SIZE (mode) == 8)
1248     literal8_section ();
1249   else if (GET_MODE_SIZE (mode) == 4
1250            && (GET_CODE (x) == CONST_INT
1251                || GET_CODE (x) == CONST_DOUBLE))
1252     literal4_section ();
1253   else
1254     const_section ();
1255 }
1256
1257 void
1258 machopic_asm_out_constructor (symbol, priority)
1259      rtx symbol;
1260      int priority ATTRIBUTE_UNUSED;
1261 {
1262   if (flag_pic)
1263     mod_init_section ();
1264   else
1265     constructor_section ();
1266   assemble_align (POINTER_SIZE);
1267   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1268
1269   if (!flag_pic)
1270     fprintf (asm_out_file, ".reference .constructors_used\n");
1271 }
1272
1273 void
1274 machopic_asm_out_destructor (symbol, priority)
1275      rtx symbol;
1276      int priority ATTRIBUTE_UNUSED;
1277 {
1278   if (flag_pic)
1279     mod_term_section ();
1280   else
1281     destructor_section ();
1282   assemble_align (POINTER_SIZE);
1283   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1284
1285   if (!flag_pic)
1286     fprintf (asm_out_file, ".reference .destructors_used\n");
1287 }
1288
1289 #include "gt-darwin.h"
1290