OSDN Git Service

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