OSDN Git Service

Daily bump.
[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, 2003
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 "coretypes.h"
26 #include "tm.h"
27 #include "rtl.h"
28 #include "regs.h"
29 #include "hard-reg-set.h"
30 #include "real.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "insn-flags.h"
34 #include "output.h"
35 #include "insn-attr.h"
36 #include "flags.h"
37 #include "tree.h"
38 #include "expr.h"
39 #include "reload.h"
40 #include "function.h"
41 #include "ggc.h"
42 #include "langhooks.h"
43 #include "tm_p.h"
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 GTY(()) 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   const 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   const 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 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
432           rtx pic_base = gen_rtx (SYMBOL_REF, Pmode, 
433                                   machopic_function_base_name ());
434           rtx offset = gen_rtx (CONST, Pmode,
435                                 gen_rtx (MINUS, Pmode, orig, pic_base));
436 #endif
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 (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
497         {
498           if (reg)
499             {
500               emit_move_insn (reg, result);
501               result = reg;
502             }
503           else
504             {
505               result = force_reg (GET_MODE (result), result);
506             }
507         }
508
509       return result;
510
511     }
512   else if (GET_CODE (orig) == MEM)
513     XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
514   /* When the target is i386, this code prevents crashes due to the
515      compiler's ignorance on how to move the PIC base register to
516      other registers.  (The reload phase sometimes introduces such
517      insns.)  */
518   else if (GET_CODE (orig) == PLUS
519            && GET_CODE (XEXP (orig, 0)) == REG
520            && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
521 #ifdef I386
522            /* Prevent the same register from being erroneously used
523               as both the base and index registers.  */
524            && GET_CODE (XEXP (orig, 1)) == CONST
525 #endif
526            && reg)
527     {
528       emit_move_insn (reg, XEXP (orig, 0));
529       XEXP (ptr_ref, 0) = reg;
530     }
531   return ptr_ref;
532 }
533
534 /* Transform TARGET (a MEM), which is a function call target, to the
535    corresponding symbol_stub if necessary.  Return a new MEM.  */
536
537 rtx
538 machopic_indirect_call_target (target)
539      rtx target;
540 {
541   if (GET_CODE (target) != MEM)
542     return target;
543
544   if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
545     { 
546       enum machine_mode mode = GET_MODE (XEXP (target, 0));
547       const char *name = XSTR (XEXP (target, 0), 0);
548
549       /* If the name is already defined, we need do nothing.  */
550       if (name[0] == '!' && name[1] == 'T')
551         return target;
552
553       if (!machopic_name_defined_p (name))
554         {
555           const char *stub_name = machopic_stub_name (name);
556
557           XEXP (target, 0) = gen_rtx (SYMBOL_REF, mode, stub_name);
558           RTX_UNCHANGING_P (target) = 1;
559         } 
560     }
561
562   return target;
563 }
564
565 rtx
566 machopic_legitimize_pic_address (orig, mode, reg)
567      rtx orig, reg;
568      enum machine_mode mode;
569 {
570   rtx pic_ref = orig;
571
572   if (! MACHOPIC_PURE)
573     return orig;
574
575   /* First handle a simple SYMBOL_REF or LABEL_REF */
576   if (GET_CODE (orig) == LABEL_REF
577       || (GET_CODE (orig) == SYMBOL_REF
578           ))
579     {
580       /* addr(foo) = &func+(foo-func) */
581       rtx pic_base;
582
583       orig = machopic_indirect_data_reference (orig, reg);
584
585       if (GET_CODE (orig) == PLUS 
586           && GET_CODE (XEXP (orig, 0)) == REG)
587         {
588           if (reg == 0)
589             return force_reg (mode, orig);
590
591           emit_move_insn (reg, orig);
592           return reg;
593         }  
594
595       pic_base = gen_rtx (SYMBOL_REF, Pmode, machopic_function_base_name ());
596
597       if (GET_CODE (orig) == MEM)
598         {
599           if (reg == 0)
600             {
601               if (reload_in_progress)
602                 abort ();
603               else
604                 reg = gen_reg_rtx (Pmode);
605             }
606         
607 #ifdef HAVE_lo_sum
608           if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF 
609               || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
610             {
611               rtx offset = gen_rtx (CONST, Pmode,
612                                     gen_rtx (MINUS, Pmode,
613                                              XEXP (orig, 0), pic_base));
614 #if defined (TARGET_TOC) /* i.e., PowerPC */
615               /* Generating a new reg may expose opportunities for
616                  common subexpression elimination.  */
617               rtx hi_sum_reg =
618                 (reload_in_progress ? reg : gen_reg_rtx (SImode));
619
620               emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
621                                   gen_rtx (PLUS, Pmode,
622                                            pic_offset_table_rtx,
623                                            gen_rtx (HIGH, Pmode, offset))));
624               emit_insn (gen_rtx (SET, VOIDmode, reg,
625                                   gen_rtx (MEM, GET_MODE (orig),
626                                            gen_rtx (LO_SUM, Pmode, 
627                                                     hi_sum_reg, offset))));
628               pic_ref = reg;
629
630 #else
631               emit_insn (gen_rtx (USE, VOIDmode,
632                               gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM)));
633
634               emit_insn (gen_rtx (SET, VOIDmode, reg,
635                                   gen_rtx (HIGH, Pmode, 
636                                            gen_rtx (CONST, Pmode, offset))));
637               emit_insn (gen_rtx (SET, VOIDmode, reg,
638                                   gen_rtx (LO_SUM, Pmode, reg, 
639                                            gen_rtx (CONST, Pmode, offset))));
640               pic_ref = gen_rtx (PLUS, Pmode,
641                                  pic_offset_table_rtx, reg);
642 #endif
643             }
644           else
645 #endif  /* HAVE_lo_sum */
646             {
647               rtx pic = pic_offset_table_rtx;
648               if (GET_CODE (pic) != REG)
649                 {
650                   emit_move_insn (reg, pic);
651                   pic = reg;
652                 }
653 #if 0
654               emit_insn (gen_rtx (USE, VOIDmode,
655                                   gen_rtx (REG, Pmode, PIC_OFFSET_TABLE_REGNUM)));
656 #endif
657
658               pic_ref = gen_rtx (PLUS, Pmode,
659                                  pic, 
660                                  gen_rtx (CONST, Pmode, 
661                                           gen_rtx (MINUS, Pmode,
662                                                    XEXP (orig, 0), 
663                                                    pic_base)));
664             }
665           
666 #if !defined (TARGET_TOC)
667           emit_move_insn (reg, pic_ref);
668           pic_ref = gen_rtx (MEM, GET_MODE (orig), reg);
669 #endif
670           RTX_UNCHANGING_P (pic_ref) = 1;
671         }
672       else
673         {
674
675 #ifdef HAVE_lo_sum
676           if (GET_CODE (orig) == SYMBOL_REF 
677               || GET_CODE (orig) == LABEL_REF)
678             {
679               rtx offset = gen_rtx (CONST, Pmode,
680                                     gen_rtx (MINUS, Pmode, orig, pic_base));
681 #if defined (TARGET_TOC) /* i.e., PowerPC */
682               rtx hi_sum_reg;
683
684               if (reg == 0)
685                 {
686                   if (reload_in_progress)
687                     abort ();
688                   else
689                     reg = gen_reg_rtx (SImode);
690                 }
691         
692               hi_sum_reg = reg;
693
694               emit_insn (gen_rtx (SET, Pmode, hi_sum_reg,
695                                   gen_rtx (PLUS, Pmode,
696                                            pic_offset_table_rtx,
697                                            gen_rtx (HIGH, Pmode, offset))));
698               emit_insn (gen_rtx (SET, VOIDmode, reg,
699                                   gen_rtx (LO_SUM, Pmode,
700                                            hi_sum_reg, offset)));
701               pic_ref = reg;
702               RTX_UNCHANGING_P (pic_ref) = 1;
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               RTX_UNCHANGING_P (pic_ref) = 1;
711 #endif
712             }
713           else
714 #endif  /*  HAVE_lo_sum  */
715             {
716               if (GET_CODE (orig) == REG)
717                 {
718                   return orig;
719                 }
720               else
721                 {
722                   rtx pic = pic_offset_table_rtx;
723                   if (GET_CODE (pic) != REG)
724                     {
725                       emit_move_insn (reg, pic);
726                       pic = reg;
727                     }
728 #if 0
729                   emit_insn (gen_rtx (USE, VOIDmode,
730                                       pic_offset_table_rtx));
731 #endif
732                   pic_ref = gen_rtx (PLUS, Pmode,
733                                      pic,
734                                      gen_rtx (CONST, Pmode, 
735                                               gen_rtx (MINUS, Pmode,
736                                                        orig, pic_base)));
737                 }
738             }
739         }
740
741       if (GET_CODE (pic_ref) != REG)
742         {
743           if (reg != 0)
744             {
745               emit_move_insn (reg, pic_ref);
746               return reg;
747             }
748           else
749             {
750               return force_reg (mode, pic_ref);
751             }
752         }
753       else
754         {
755           return pic_ref;
756         }
757     }
758
759   else if (GET_CODE (orig) == SYMBOL_REF)
760     return orig;
761
762   else if (GET_CODE (orig) == PLUS
763            && (GET_CODE (XEXP (orig, 0)) == MEM
764                || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
765                || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
766            && XEXP (orig, 0) != pic_offset_table_rtx
767            && GET_CODE (XEXP (orig, 1)) != REG)
768     
769     {
770       rtx base;
771       int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
772
773       base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
774       orig = machopic_legitimize_pic_address (XEXP (orig, 1),
775                                               Pmode, (base == reg ? 0 : reg));
776       if (GET_CODE (orig) == CONST_INT)
777         {
778           pic_ref = plus_constant (base, INTVAL (orig));
779           is_complex = 1;
780         }
781       else
782         pic_ref = gen_rtx (PLUS, Pmode, base, orig);
783
784       if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
785         RTX_UNCHANGING_P (pic_ref) = 1;
786
787       if (reg && is_complex)
788         {
789           emit_move_insn (reg, pic_ref);
790           pic_ref = reg;
791         }
792       /* Likewise, should we set special REG_NOTEs here?  */
793     }
794
795   else if (GET_CODE (orig) == CONST)
796     {
797       return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
798     }
799
800   else if (GET_CODE (orig) == MEM
801            && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
802     {
803       rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
804
805       addr = gen_rtx (MEM, GET_MODE (orig), addr);
806       RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
807       emit_move_insn (reg, addr);
808       pic_ref = reg;
809     }
810
811   return pic_ref;
812 }
813
814
815 void
816 machopic_finish (asm_out_file)
817      FILE *asm_out_file;
818 {
819   tree temp;
820
821   for (temp = machopic_stubs;
822        temp != NULL_TREE;
823        temp = TREE_CHAIN (temp))
824     {
825       const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
826       const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
827       char *sym;
828       char *stub;
829
830       if (! TREE_USED (temp))
831         continue;
832
833       /* If the symbol is actually defined, we don't need a stub.  */
834       if (sym_name[0] == '!' && sym_name[1] == 'T')
835         continue;
836
837       sym_name = darwin_strip_name_encoding (sym_name);
838
839       sym = alloca (strlen (sym_name) + 2);
840       if (sym_name[0] == '*' || sym_name[0] == '&')
841         strcpy (sym, sym_name + 1);
842       else if (sym_name[0] == '-' || sym_name[0] == '+')
843         strcpy (sym, sym_name);   
844       else
845         sym[0] = '_', strcpy (sym + 1, sym_name);
846
847       stub = alloca (strlen (stub_name) + 2);
848       if (stub_name[0] == '*' || stub_name[0] == '&')
849         strcpy (stub, stub_name + 1);
850       else
851         stub[0] = '_', strcpy (stub + 1, stub_name);
852
853       machopic_output_stub (asm_out_file, sym, stub);
854     }
855
856   for (temp = machopic_non_lazy_pointers;
857        temp != NULL_TREE; 
858        temp = TREE_CHAIN (temp))
859     {
860       const char *const sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
861       const char *const lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
862
863       if (! TREE_USED (temp))
864         continue;
865
866       if (machopic_ident_defined_p (TREE_VALUE (temp)))
867         {
868           data_section ();
869           assemble_align (GET_MODE_ALIGNMENT (Pmode));
870           assemble_label (lazy_name);
871           assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name),
872                             GET_MODE_SIZE (Pmode),
873                             GET_MODE_ALIGNMENT (Pmode), 1);
874         }
875       else
876         {
877           machopic_nl_symbol_ptr_section ();
878           assemble_name (asm_out_file, lazy_name); 
879           fprintf (asm_out_file, ":\n");
880
881           fprintf (asm_out_file, "\t.indirect_symbol ");
882           assemble_name (asm_out_file, sym_name); 
883           fprintf (asm_out_file, "\n");
884
885           assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
886                             GET_MODE_ALIGNMENT (Pmode), 1);
887         }
888     }
889 }
890
891 int 
892 machopic_operand_p (op)
893      rtx op;
894 {
895   if (MACHOPIC_JUST_INDIRECT)
896     {
897       while (GET_CODE (op) == CONST)
898         op = XEXP (op, 0);
899
900       if (GET_CODE (op) == SYMBOL_REF)
901         return machopic_name_defined_p (XSTR (op, 0));
902       else
903         return 0;
904     }
905
906   while (GET_CODE (op) == CONST)
907     op = XEXP (op, 0);
908
909   if (GET_CODE (op) == MINUS
910       && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
911       && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
912       && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
913       && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
914       return 1;
915
916   return 0;
917 }
918
919 /* This function records whether a given name corresponds to a defined
920    or undefined function or variable, for machopic_classify_ident to
921    use later.  */
922
923 void
924 darwin_encode_section_info (decl, first)
925      tree decl;
926      int first ATTRIBUTE_UNUSED;
927 {
928   char code = '\0';
929   int defined = 0;
930   rtx sym_ref;
931   const char *orig_str;
932   char *new_str;
933   size_t len, new_len;
934
935   if ((TREE_CODE (decl) == FUNCTION_DECL
936        || TREE_CODE (decl) == VAR_DECL)
937       && !DECL_EXTERNAL (decl)
938       && ((TREE_STATIC (decl)
939            && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
940           || (DECL_INITIAL (decl)
941               && DECL_INITIAL (decl) != error_mark_node)))
942     defined = 1;
943
944   if (TREE_CODE (decl) == FUNCTION_DECL)
945     code = (defined ? 'T' : 't');
946   else if (TREE_CODE (decl) == VAR_DECL)
947     code = (defined ? 'D' : 'd');
948
949   if (code == '\0')
950     return;
951
952   sym_ref = XEXP (DECL_RTL (decl), 0);
953   orig_str = XSTR (sym_ref, 0);
954   len = strlen (orig_str) + 1;
955
956   if (orig_str[0] == '!')
957     {
958       /* Already encoded; see if we need to change it.  */
959       if (code == orig_str[1])
960         return;
961       /* Yes, tweak a copy of the name and put it in a new string.  */
962       new_str = alloca (len);
963       memcpy (new_str, orig_str, len);
964       new_str[1] = code;
965       XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
966     }
967   else
968     {
969       /* Add the encoding.  */
970       new_len = len + 4;
971       new_str = alloca (new_len);
972       new_str[0] = '!';
973       new_str[1] = code;
974       new_str[2] = '_';
975       new_str[3] = '_';
976       memcpy (new_str + 4, orig_str, len);
977       XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
978     }
979   /* The non-lazy pointer list may have captured references to the
980      old encoded name, change them.  */
981   if (TREE_CODE (decl) == VAR_DECL)
982     update_non_lazy_ptrs (XSTR (sym_ref, 0));
983   else
984     update_stubs (XSTR (sym_ref, 0));
985 }
986
987 /* Undo the effects of the above.  */
988
989 const char *
990 darwin_strip_name_encoding (str)
991      const char *str;
992 {
993   return str[0] == '!' ? str + 4 : str;
994 }
995
996 /* Scan the list of non-lazy pointers and update any recorded names whose
997    stripped name matches the argument.  */
998
999 static void
1000 update_non_lazy_ptrs (name)
1001      const char *name;
1002 {
1003   const char *name1, *name2;
1004   tree temp;
1005
1006   name1 = darwin_strip_name_encoding (name);
1007
1008   for (temp = machopic_non_lazy_pointers;
1009        temp != NULL_TREE; 
1010        temp = TREE_CHAIN (temp))
1011     {
1012       const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1013
1014       if (*sym_name == '!')
1015         {
1016           name2 = darwin_strip_name_encoding (sym_name);
1017           if (strcmp (name1, name2) == 0)
1018             {
1019               /* FIXME: This breaks the identifier hash table.  */
1020               IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str 
1021                 = (unsigned char *) name;
1022               break;
1023             }
1024         }
1025     }
1026 }
1027
1028 /* Function NAME is being defined, and its label has just been output.
1029    If there's already a reference to a stub for this function, we can
1030    just emit the stub label now and we don't bother emitting the stub later.  */
1031
1032 void
1033 machopic_output_possible_stub_label (file, name)
1034      FILE *file;
1035      const char *name;
1036 {
1037   tree temp;
1038
1039
1040   /* Ensure we're looking at a section-encoded name.  */
1041   if (name[0] != '!' || (name[1] != 't' && name[1] != 'T'))
1042     return;
1043
1044   for (temp = machopic_stubs;
1045        temp != NULL_TREE;
1046        temp = TREE_CHAIN (temp))
1047     {
1048       const char *sym_name;
1049
1050       sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1051       if (sym_name[0] == '!' && sym_name[1] == 'T'
1052           && ! strcmp (name+2, sym_name+2))
1053         {
1054           ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp)));
1055           /* Avoid generating a stub for this.  */
1056           TREE_USED (temp) = 0;
1057           break;
1058         }
1059     }
1060 }
1061
1062 /* Scan the list of stubs and update any recorded names whose
1063    stripped name matches the argument.  */
1064
1065 static void
1066 update_stubs (name)
1067      const char *name;
1068 {
1069   const char *name1, *name2;
1070   tree temp;
1071
1072   name1 = darwin_strip_name_encoding (name);
1073
1074   for (temp = machopic_stubs;
1075        temp != NULL_TREE; 
1076        temp = TREE_CHAIN (temp))
1077     {
1078       const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1079
1080       if (*sym_name == '!')
1081         {
1082           name2 = darwin_strip_name_encoding (sym_name);
1083           if (strcmp (name1, name2) == 0)
1084             {
1085               /* FIXME: This breaks the identifier hash table.  */
1086               IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str 
1087                 = (unsigned char *) name;
1088               break;
1089             }
1090         }
1091     }
1092 }
1093
1094 void
1095 machopic_select_section (exp, reloc, align)
1096      tree exp;
1097      int reloc;
1098      unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1099 {
1100   if (TREE_CODE (exp) == STRING_CST)
1101     {
1102       if (flag_writable_strings)
1103         data_section ();
1104       else if ((size_t) TREE_STRING_LENGTH (exp) !=
1105                strlen (TREE_STRING_POINTER (exp)) + 1)
1106         readonly_data_section ();
1107       else
1108         cstring_section ();
1109     }
1110   else if (TREE_CODE (exp) == INTEGER_CST
1111            || TREE_CODE (exp) == REAL_CST)
1112     {
1113       tree size = TYPE_SIZE (TREE_TYPE (exp));
1114
1115       if (TREE_CODE (size) == INTEGER_CST &&
1116           TREE_INT_CST_LOW (size) == 4 &&
1117           TREE_INT_CST_HIGH (size) == 0)
1118         literal4_section ();
1119       else if (TREE_CODE (size) == INTEGER_CST &&
1120                TREE_INT_CST_LOW (size) == 8 &&
1121                TREE_INT_CST_HIGH (size) == 0)
1122         literal8_section ();
1123       else
1124         readonly_data_section ();
1125     }
1126   else if (TREE_CODE (exp) == CONSTRUCTOR
1127            && TREE_TYPE (exp)
1128            && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1129            && TYPE_NAME (TREE_TYPE (exp)))
1130     {
1131       tree name = TYPE_NAME (TREE_TYPE (exp));
1132       if (TREE_CODE (name) == TYPE_DECL)
1133         name = DECL_NAME (name);
1134       if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1135         objc_constant_string_object_section ();
1136       else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1137         objc_string_object_section ();
1138       else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1139         {
1140           if (TREE_SIDE_EFFECTS (exp) || (flag_pic && reloc))
1141             const_data_section ();
1142           else
1143             readonly_data_section ();
1144         }
1145       else
1146         data_section ();
1147     }
1148   else if (TREE_CODE (exp) == VAR_DECL &&
1149            DECL_NAME (exp) &&
1150            TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1151            IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1152            !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1153     {
1154       const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1155
1156       if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1157         objc_cls_meth_section ();
1158       else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1159         objc_inst_meth_section ();
1160       else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1161         objc_cat_cls_meth_section ();
1162       else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1163         objc_cat_inst_meth_section ();
1164       else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1165         objc_class_vars_section ();
1166       else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1167         objc_instance_vars_section ();
1168       else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1169         objc_cat_cls_meth_section ();
1170       else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1171         objc_class_names_section ();
1172       else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1173         objc_meth_var_names_section ();
1174       else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1175         objc_meth_var_types_section ();
1176       else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1177         objc_cls_refs_section ();
1178       else if (!strncmp (name, "_OBJC_CLASS_", 12))
1179         objc_class_section ();
1180       else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1181         objc_meta_class_section ();
1182       else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1183         objc_category_section ();
1184       else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1185         objc_selector_refs_section ();
1186       else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1187         objc_selector_fixup_section ();
1188       else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1189         objc_symbols_section ();
1190       else if (!strncmp (name, "_OBJC_MODULES", 13))
1191         objc_module_info_section ();
1192       else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1193         objc_cat_inst_meth_section ();
1194       else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1195         objc_cat_cls_meth_section ();
1196       else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1197         objc_cat_cls_meth_section ();
1198       else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1199         objc_protocol_section ();
1200       else if ((TREE_READONLY (exp) || TREE_CONSTANT (exp))
1201                && !TREE_SIDE_EFFECTS (exp))
1202         {
1203           if (flag_pic && reloc)
1204             const_data_section ();
1205           else
1206             readonly_data_section ();
1207         }
1208       else
1209         data_section ();
1210     }
1211   else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1212     {
1213       if (TREE_SIDE_EFFECTS (exp) || (flag_pic && reloc))
1214         const_data_section ();
1215       else
1216         readonly_data_section ();
1217     }
1218   else
1219     data_section ();
1220 }
1221
1222 /* This can be called with address expressions as "rtx".
1223    They must go in "const".  */
1224
1225 void
1226 machopic_select_rtx_section (mode, x, align)
1227      enum machine_mode mode;
1228      rtx x;
1229      unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1230 {
1231   if (GET_MODE_SIZE (mode) == 8)
1232     literal8_section ();
1233   else if (GET_MODE_SIZE (mode) == 4
1234            && (GET_CODE (x) == CONST_INT
1235                || GET_CODE (x) == CONST_DOUBLE))
1236     literal4_section ();
1237   else
1238     const_section ();
1239 }
1240
1241 void
1242 machopic_asm_out_constructor (symbol, priority)
1243      rtx symbol;
1244      int priority ATTRIBUTE_UNUSED;
1245 {
1246   if (flag_pic)
1247     mod_init_section ();
1248   else
1249     constructor_section ();
1250   assemble_align (POINTER_SIZE);
1251   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1252
1253   if (!flag_pic)
1254     fprintf (asm_out_file, ".reference .constructors_used\n");
1255 }
1256
1257 void
1258 machopic_asm_out_destructor (symbol, priority)
1259      rtx symbol;
1260      int priority ATTRIBUTE_UNUSED;
1261 {
1262   if (flag_pic)
1263     mod_term_section ();
1264   else
1265     destructor_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 .destructors_used\n");
1271 }
1272
1273 void
1274 darwin_globalize_label (stream, name)
1275      FILE *stream;
1276      const char *name;
1277 {
1278   if (!!strncmp (name, "_OBJC_", 6))
1279     default_globalize_label (stream, name);
1280 }
1281
1282 /* Output a difference of two labels that will be an assembly time
1283    constant if the two labels are local.  (.long lab1-lab2 will be
1284    very different if lab1 is at the boundary between two sections; it
1285    will be relocated according to the second section, not the first,
1286    so one ends up with a difference between labels in different
1287    sections, which is bad in the dwarf2 eh context for instance.)  */
1288
1289 static int darwin_dwarf_label_counter;
1290
1291 void
1292 darwin_asm_output_dwarf_delta (file, size, lab1, lab2)
1293      FILE *file;
1294      int size ATTRIBUTE_UNUSED;
1295      const char *lab1, *lab2;
1296 {
1297   const char *p = lab1 + (lab1[0] == '*');
1298   int islocaldiff = (p[0] == 'L');
1299
1300   if (islocaldiff)
1301     fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1302   else
1303     fprintf (file, "\t%s\t", ".long");
1304   assemble_name (file, lab1);
1305   fprintf (file, "-");
1306   assemble_name (file, lab2);
1307   if (islocaldiff)
1308     fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1309 }
1310
1311 #include "gt-darwin.h"
1312