OSDN Git Service

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