OSDN Git Service

Merge basic-improvements-branch to trunk
[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 "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 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               IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1020               break;
1021             }
1022         }
1023     }
1024 }
1025
1026 /* Function NAME is being defined, and its label has just been output.
1027    If there's already a reference to a stub for this function, we can
1028    just emit the stub label now and we don't bother emitting the stub later.  */
1029
1030 void
1031 machopic_output_possible_stub_label (file, name)
1032      FILE *file;
1033      const char *name;
1034 {
1035   tree temp;
1036
1037
1038   /* Ensure we're looking at a section-encoded name.  */
1039   if (name[0] != '!' || (name[1] != 't' && name[1] != 'T'))
1040     return;
1041
1042   for (temp = machopic_stubs;
1043        temp != NULL_TREE;
1044        temp = TREE_CHAIN (temp))
1045     {
1046       const char *sym_name;
1047
1048       sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1049       if (sym_name[0] == '!' && sym_name[1] == 'T'
1050           && ! strcmp (name+2, sym_name+2))
1051         {
1052           ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp)));
1053           /* Avoid generating a stub for this.  */
1054           TREE_USED (temp) = 0;
1055           break;
1056         }
1057     }
1058 }
1059
1060 /* Scan the list of stubs and update any recorded names whose
1061    stripped name matches the argument.  */
1062
1063 static void
1064 update_stubs (name)
1065      const char *name;
1066 {
1067   const char *name1, *name2;
1068   tree temp;
1069
1070   name1 = darwin_strip_name_encoding (name);
1071
1072   for (temp = machopic_stubs;
1073        temp != NULL_TREE; 
1074        temp = TREE_CHAIN (temp))
1075     {
1076       const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1077
1078       if (*sym_name == '!')
1079         {
1080           name2 = darwin_strip_name_encoding (sym_name);
1081           if (strcmp (name1, name2) == 0)
1082             {
1083               IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1084               break;
1085             }
1086         }
1087     }
1088 }
1089
1090 void
1091 machopic_select_section (exp, reloc, align)
1092      tree exp;
1093      int reloc;
1094      unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1095 {
1096   if (TREE_CODE (exp) == STRING_CST)
1097     {
1098       if (flag_writable_strings)
1099         data_section ();
1100       else if (TREE_STRING_LENGTH (exp) !=
1101                strlen (TREE_STRING_POINTER (exp)) + 1)
1102         readonly_data_section ();
1103       else
1104         cstring_section ();
1105     }
1106   else if (TREE_CODE (exp) == INTEGER_CST
1107            || TREE_CODE (exp) == REAL_CST)
1108     {
1109       tree size = TYPE_SIZE (TREE_TYPE (exp));
1110
1111       if (TREE_CODE (size) == INTEGER_CST &&
1112           TREE_INT_CST_LOW (size) == 4 &&
1113           TREE_INT_CST_HIGH (size) == 0)
1114         literal4_section ();
1115       else if (TREE_CODE (size) == INTEGER_CST &&
1116                TREE_INT_CST_LOW (size) == 8 &&
1117                TREE_INT_CST_HIGH (size) == 0)
1118         literal8_section ();
1119       else
1120         readonly_data_section ();
1121     }
1122   else if (TREE_CODE (exp) == CONSTRUCTOR
1123            && TREE_TYPE (exp)
1124            && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1125            && TYPE_NAME (TREE_TYPE (exp)))
1126     {
1127       tree name = TYPE_NAME (TREE_TYPE (exp));
1128       if (TREE_CODE (name) == TYPE_DECL)
1129         name = DECL_NAME (name);
1130       if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1131         objc_constant_string_object_section ();
1132       else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1133         objc_string_object_section ();
1134       else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1135         {
1136           if (TREE_SIDE_EFFECTS (exp) || (flag_pic && reloc))
1137             const_data_section ();
1138           else
1139             readonly_data_section ();
1140         }
1141       else
1142         data_section ();
1143     }
1144   else if (TREE_CODE (exp) == VAR_DECL &&
1145            DECL_NAME (exp) &&
1146            TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1147            IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1148            !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1149     {
1150       const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1151
1152       if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1153         objc_cls_meth_section ();
1154       else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1155         objc_inst_meth_section ();
1156       else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1157         objc_cat_cls_meth_section ();
1158       else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1159         objc_cat_inst_meth_section ();
1160       else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1161         objc_class_vars_section ();
1162       else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1163         objc_instance_vars_section ();
1164       else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1165         objc_cat_cls_meth_section ();
1166       else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1167         objc_class_names_section ();
1168       else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1169         objc_meth_var_names_section ();
1170       else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1171         objc_meth_var_types_section ();
1172       else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1173         objc_cls_refs_section ();
1174       else if (!strncmp (name, "_OBJC_CLASS_", 12))
1175         objc_class_section ();
1176       else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1177         objc_meta_class_section ();
1178       else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1179         objc_category_section ();
1180       else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1181         objc_selector_refs_section ();
1182       else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1183         objc_selector_fixup_section ();
1184       else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1185         objc_symbols_section ();
1186       else if (!strncmp (name, "_OBJC_MODULES", 13))
1187         objc_module_info_section ();
1188       else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1189         objc_cat_inst_meth_section ();
1190       else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1191         objc_cat_cls_meth_section ();
1192       else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1193         objc_cat_cls_meth_section ();
1194       else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1195         objc_protocol_section ();
1196       else if ((TREE_READONLY (exp) || TREE_CONSTANT (exp))
1197                && !TREE_SIDE_EFFECTS (exp))
1198         {
1199           if (flag_pic && reloc)
1200             const_data_section ();
1201           else
1202             readonly_data_section ();
1203         }
1204       else
1205         data_section ();
1206     }
1207   else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1208     {
1209       if (TREE_SIDE_EFFECTS (exp) || (flag_pic && reloc))
1210         const_data_section ();
1211       else
1212         readonly_data_section ();
1213     }
1214   else
1215     data_section ();
1216 }
1217
1218 /* This can be called with address expressions as "rtx".
1219    They must go in "const".  */
1220
1221 void
1222 machopic_select_rtx_section (mode, x, align)
1223      enum machine_mode mode;
1224      rtx x;
1225      unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1226 {
1227   if (GET_MODE_SIZE (mode) == 8)
1228     literal8_section ();
1229   else if (GET_MODE_SIZE (mode) == 4
1230            && (GET_CODE (x) == CONST_INT
1231                || GET_CODE (x) == CONST_DOUBLE))
1232     literal4_section ();
1233   else
1234     const_section ();
1235 }
1236
1237 void
1238 machopic_asm_out_constructor (symbol, priority)
1239      rtx symbol;
1240      int priority ATTRIBUTE_UNUSED;
1241 {
1242   if (flag_pic)
1243     mod_init_section ();
1244   else
1245     constructor_section ();
1246   assemble_align (POINTER_SIZE);
1247   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1248
1249   if (!flag_pic)
1250     fprintf (asm_out_file, ".reference .constructors_used\n");
1251 }
1252
1253 void
1254 machopic_asm_out_destructor (symbol, priority)
1255      rtx symbol;
1256      int priority ATTRIBUTE_UNUSED;
1257 {
1258   if (flag_pic)
1259     mod_term_section ();
1260   else
1261     destructor_section ();
1262   assemble_align (POINTER_SIZE);
1263   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1264
1265   if (!flag_pic)
1266     fprintf (asm_out_file, ".reference .destructors_used\n");
1267 }
1268
1269 void
1270 darwin_globalize_label (stream, name)
1271      FILE *stream;
1272      const char *name;
1273 {
1274   if (!!strncmp (name, "_OBJC_", 6))
1275     default_globalize_label (stream, name);
1276 }
1277
1278 /* Output a difference of two labels that will be an assembly time
1279    constant if the two labels are local.  (.long lab1-lab2 will be
1280    very different if lab1 is at the boundary between two sections; it
1281    will be relocated according to the second section, not the first,
1282    so one ends up with a difference between labels in different
1283    sections, which is bad in the dwarf2 eh context for instance.)  */
1284
1285 static int darwin_dwarf_label_counter;
1286
1287 void
1288 darwin_asm_output_dwarf_delta (file, size, lab1, lab2)
1289      FILE *file;
1290      int size ATTRIBUTE_UNUSED;
1291      const char *lab1, *lab2;
1292 {
1293   const char *p = lab1 + (lab1[0] == '*');
1294   int islocaldiff = (p[0] == 'L');
1295
1296   if (islocaldiff)
1297     fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1298   else
1299     fprintf (file, "\t%s\t", ".long");
1300   assemble_name (file, lab1);
1301   fprintf (file, "-");
1302   assemble_name (file, lab2);
1303   if (islocaldiff)
1304     fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1305 }
1306
1307 #include "gt-darwin.h"
1308