OSDN Git Service

* s390-modes.def [CCL1, CCL2, CCT1, CCT2, CCT3, CCUR, CCSR]: Declare
[pf3gnuchains/gcc-fork.git] / gcc / config / darwin.c
1 /* Functions for generic Darwin as target machine for GNU C compiler.
2    Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001, 2002
3    Free Software Foundation, Inc.
4    Contributed by Apple Computer Inc.
5
6 This file is part of GNU CC.
7
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING.  If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA.  */
22
23 #include "config.h"
24 #include "system.h"
25 #include "rtl.h"
26 #include "regs.h"
27 #include "hard-reg-set.h"
28 #include "real.h"
29 #include "insn-config.h"
30 #include "conditions.h"
31 #include "insn-flags.h"
32 #include "output.h"
33 #include "insn-attr.h"
34 #include "flags.h"
35 #include "tree.h"
36 #include "expr.h"
37 #include "reload.h"
38 #include "function.h"
39 #include "ggc.h"
40 #include "langhooks.h"
41 #include "darwin-protos.h"
42
43 extern void machopic_output_stub PARAMS ((FILE *, const char *, const char *));
44
45 static int machopic_data_defined_p PARAMS ((const char *));
46 static void update_non_lazy_ptrs PARAMS ((const char *));
47 static void update_stubs PARAMS ((const char *));
48
49 int
50 name_needs_quotes (name)
51      const char *name;
52 {
53   int c;
54   while ((c = *name++) != '\0')
55     if (! ISIDNUM (c))
56       return 1;
57   return 0;
58 }
59
60 /* 
61  * flag_pic = 1 ... generate only indirections
62  * flag_pic = 2 ... generate indirections and pure code
63  */
64
65 /* This module assumes that (const (symbol_ref "foo")) is a legal pic
66    reference, which will not be changed.  */
67
68 static GTY(()) tree machopic_defined_list;
69
70 enum machopic_addr_class
71 machopic_classify_ident (ident)
72      tree ident;
73 {
74   const char *name = IDENTIFIER_POINTER (ident);
75   int lprefix = (((name[0] == '*' || name[0] == '&')
76                   && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
77                  || (   name[0] == '_' 
78                      && name[1] == 'O' 
79                      && name[2] == 'B' 
80                      && name[3] == 'J'
81                      && name[4] == 'C'
82                      && name[5] == '_'));
83   tree temp;
84
85   if (name[0] != '!')
86     {
87       /* Here if no special encoding to be found.  */
88       if (lprefix)
89         {
90           const char *name = IDENTIFIER_POINTER (ident);
91           int len = strlen (name);
92
93           if ((len > 5 && !strcmp (name + len - 5, "$stub"))
94               || (len > 6 && !strcmp (name + len - 6, "$stub\"")))
95             return MACHOPIC_DEFINED_FUNCTION;
96           return MACHOPIC_DEFINED_DATA;
97         }
98
99       for (temp = machopic_defined_list;
100            temp != NULL_TREE;
101            temp = TREE_CHAIN (temp))
102         {
103           if (ident == TREE_VALUE (temp))
104             return MACHOPIC_DEFINED_DATA;
105         }
106
107       if (TREE_ASM_WRITTEN (ident))
108         return MACHOPIC_DEFINED_DATA;
109
110       return MACHOPIC_UNDEFINED;
111     }
112
113   else if (name[1] == 'D')
114     return MACHOPIC_DEFINED_DATA;
115
116   else if (name[1] == 'T')
117     return MACHOPIC_DEFINED_FUNCTION;
118
119   /* It is possible that someone is holding a "stale" name, which has
120      since been defined.  See if there is a "defined" name (i.e,
121      different from NAME only in having a '!D_' or a '!T_' instead of
122      a '!d_' or '!t_' prefix) in the identifier hash tables.  If so, say
123      that this identifier is defined.  */
124   else if (name[1] == 'd' || name[1] == 't')
125     {
126       char *new_name;
127       new_name = (char *)alloca (strlen (name) + 1);
128       strcpy (new_name, name);
129       new_name[1] = (name[1] == 'd') ? 'D' : 'T';
130       if (maybe_get_identifier (new_name) != NULL)
131         return  (name[1] == 'd') ? MACHOPIC_DEFINED_DATA
132                                  : MACHOPIC_DEFINED_FUNCTION;
133     }
134
135   for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp))
136     {
137       if (ident == TREE_VALUE (temp))
138         {
139           if (name[1] == 'T')
140             return MACHOPIC_DEFINED_FUNCTION;
141           else
142             return MACHOPIC_DEFINED_DATA;
143         }
144     }
145   
146   if (name[1] == 't' || name[1] == 'T')
147     {
148       if (lprefix)
149         return MACHOPIC_DEFINED_FUNCTION;
150       else
151         return MACHOPIC_UNDEFINED_FUNCTION;
152     }
153   else
154     {
155       if (lprefix)
156         return MACHOPIC_DEFINED_DATA;
157       else
158         return MACHOPIC_UNDEFINED_DATA;
159     }
160 }
161
162      
163 enum machopic_addr_class
164 machopic_classify_name (name)
165      const char *name;
166 {
167   return machopic_classify_ident (get_identifier (name));
168 }
169
170 int
171 machopic_ident_defined_p (ident)
172      tree ident;
173 {
174   switch (machopic_classify_ident (ident))
175     {
176     case MACHOPIC_UNDEFINED:
177     case MACHOPIC_UNDEFINED_DATA:
178     case MACHOPIC_UNDEFINED_FUNCTION:
179       return 0;
180     default:
181       return 1;
182     }
183 }
184
185 static int
186 machopic_data_defined_p (name)
187      const char *name;
188 {
189   switch (machopic_classify_ident (get_identifier (name)))
190     {
191     case MACHOPIC_DEFINED_DATA:
192       return 1;
193     default:
194       return 0;
195     }
196 }
197
198 int
199 machopic_name_defined_p (name)
200      const char *name;
201 {
202   return machopic_ident_defined_p (get_identifier (name));
203 }
204
205 void
206 machopic_define_ident (ident)
207      tree ident;
208 {
209   if (!machopic_ident_defined_p (ident))
210     machopic_defined_list = 
211       tree_cons (NULL_TREE, ident, machopic_defined_list);
212 }
213
214 void
215 machopic_define_name (name)
216      const char *name;
217 {
218   machopic_define_ident (get_identifier (name));
219 }
220
221 /* This is a static to make inline functions work.  The rtx
222    representing the PIC base symbol always points to here. */
223
224 static char function_base[32];
225
226 static int current_pic_label_num;
227
228 const char *
229 machopic_function_base_name ()
230 {
231   static const char *name = NULL;
232   static const char *current_name;
233
234   current_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
235
236   if (name != current_name)
237     {
238       current_function_uses_pic_offset_table = 1;
239
240       /* Save mucho space and time.  Some of the C++ mangled names are over
241          700 characters long!  Note that we produce a label containing a '-'
242          if the function we're compiling is an Objective-C method, as evinced
243          by the incredibly scientific test below.  This is because code in
244          rs6000.c makes the same ugly test when loading the PIC reg.  */
245  
246       ++current_pic_label_num;
247       if (*current_name == '+' || *current_name == '-')
248         sprintf (function_base, "*\"L-%d$pb\"", current_pic_label_num);
249       else
250         sprintf (function_base, "*L%d$pb", current_pic_label_num);
251
252       name = current_name;
253     }
254
255   return function_base;
256 }
257
258 static GTY(()) tree machopic_non_lazy_pointers;
259
260 /* Return a non-lazy pointer name corresponding to the given name,
261    either by finding it in our list of pointer names, or by generating
262    a new one.  */
263
264 const char * 
265 machopic_non_lazy_ptr_name (name)
266      const char *name;
267 {
268   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 #if 0
863       tree decl = lookup_name_darwin (TREE_VALUE (temp));
864 #endif
865
866       if (! TREE_USED (temp))
867         continue;
868
869       if (machopic_ident_defined_p (TREE_VALUE (temp))
870 #if 0 /* add back when we have private externs */
871           || (decl && DECL_PRIVATE_EXTERN (decl))
872 #endif
873           )
874         {
875           data_section ();
876           assemble_align (GET_MODE_ALIGNMENT (Pmode));
877           assemble_label (lazy_name);
878           assemble_integer (gen_rtx (SYMBOL_REF, Pmode, sym_name),
879                             GET_MODE_SIZE (Pmode),
880                             GET_MODE_ALIGNMENT (Pmode), 1);
881         }
882       else
883         {
884           machopic_nl_symbol_ptr_section ();
885           assemble_name (asm_out_file, lazy_name); 
886           fprintf (asm_out_file, ":\n");
887
888           fprintf (asm_out_file, "\t.indirect_symbol ");
889           assemble_name (asm_out_file, sym_name); 
890           fprintf (asm_out_file, "\n");
891
892           assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
893                             GET_MODE_ALIGNMENT (Pmode), 1);
894         }
895     }
896 }
897
898 int 
899 machopic_operand_p (op)
900      rtx op;
901 {
902   if (MACHOPIC_JUST_INDIRECT)
903     {
904       while (GET_CODE (op) == CONST)
905         op = XEXP (op, 0);
906
907       if (GET_CODE (op) == SYMBOL_REF)
908         return machopic_name_defined_p (XSTR (op, 0));
909       else
910         return 0;
911     }
912
913   while (GET_CODE (op) == CONST)
914     op = XEXP (op, 0);
915
916   if (GET_CODE (op) == MINUS
917       && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
918       && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
919       && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
920       && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
921       return 1;
922
923 #if 0 /*def TARGET_TOC*/ /* i.e., PowerPC */
924   /* Without this statement, the compiler crashes while compiling enquire.c
925      when targetting PowerPC.  It is not known why this code is not needed
926      when targetting other processors.  */
927   else if (GET_CODE (op) == SYMBOL_REF
928            && (machopic_classify_name (XSTR (op, 0))
929                == MACHOPIC_DEFINED_FUNCTION))
930     {
931       return 1;
932     }
933 #endif
934
935   return 0;
936 }
937
938 /* This function records whether a given name corresponds to a defined
939    or undefined function or variable, for machopic_classify_ident to
940    use later.  */
941
942 void
943 darwin_encode_section_info (decl, first)
944      tree decl;
945      int first ATTRIBUTE_UNUSED;
946 {
947   char code = '\0';
948   int defined = 0;
949   rtx sym_ref;
950   const char *orig_str;
951   char *new_str;
952   size_t len, new_len;
953
954   if ((TREE_CODE (decl) == FUNCTION_DECL
955        || TREE_CODE (decl) == VAR_DECL)
956       && !DECL_EXTERNAL (decl)
957       && ((TREE_STATIC (decl)
958            && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
959           || (DECL_INITIAL (decl)
960               && DECL_INITIAL (decl) != error_mark_node)))
961     defined = 1;
962
963   if (TREE_CODE (decl) == FUNCTION_DECL)
964     code = (defined ? 'T' : 't');
965   else if (TREE_CODE (decl) == VAR_DECL)
966     code = (defined ? 'D' : 'd');
967
968   if (code == '\0')
969     return;
970
971   sym_ref = XEXP (DECL_RTL (decl), 0);
972   orig_str = XSTR (sym_ref, 0);
973   len = strlen (orig_str) + 1;
974
975   if (orig_str[0] == '!')
976     {
977       /* Already encoded; see if we need to change it.  */
978       if (code == orig_str[1])
979         return;
980       /* Yes, tweak a copy of the name and put it in a new string.  */
981       new_str = alloca (len);
982       memcpy (new_str, orig_str, len);
983       new_str[1] = code;
984       XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
985     }
986   else
987     {
988       /* Add the encoding.  */
989       new_len = len + 4;
990       new_str = alloca (new_len);
991       new_str[0] = '!';
992       new_str[1] = code;
993       new_str[2] = '_';
994       new_str[3] = '_';
995       memcpy (new_str + 4, orig_str, len);
996       XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
997     }
998   /* The non-lazy pointer list may have captured references to the
999      old encoded name, change them.  */
1000   if (TREE_CODE (decl) == VAR_DECL)
1001     update_non_lazy_ptrs (XSTR (sym_ref, 0));
1002   else
1003     update_stubs (XSTR (sym_ref, 0));
1004 }
1005
1006 /* Undo the effects of the above.  */
1007
1008 const char *
1009 darwin_strip_name_encoding (str)
1010      const char *str;
1011 {
1012   return str[0] == '!' ? str + 4 : str;
1013 }
1014
1015 /* Scan the list of non-lazy pointers and update any recorded names whose
1016    stripped name matches the argument.  */
1017
1018 static void
1019 update_non_lazy_ptrs (name)
1020      const char *name;
1021 {
1022   const char *name1, *name2;
1023   tree temp;
1024
1025   name1 = darwin_strip_name_encoding (name);
1026
1027   for (temp = machopic_non_lazy_pointers;
1028        temp != NULL_TREE; 
1029        temp = TREE_CHAIN (temp))
1030     {
1031       const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1032
1033       if (*sym_name == '!')
1034         {
1035           name2 = darwin_strip_name_encoding (sym_name);
1036           if (strcmp (name1, name2) == 0)
1037             {
1038               IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1039               break;
1040             }
1041         }
1042     }
1043 }
1044
1045 /* Function NAME is being defined, and its label has just been output.
1046    If there's already a reference to a stub for this function, we can
1047    just emit the stub label now and we don't bother emitting the stub later. */
1048
1049 void
1050 machopic_output_possible_stub_label (file, name)
1051      FILE *file;
1052      const char *name;
1053 {
1054   tree temp;
1055
1056
1057   /* Ensure we're looking at a section-encoded name.  */
1058   if (name[0] != '!' || (name[1] != 't' && name[1] != 'T'))
1059     return;
1060
1061   for (temp = machopic_stubs;
1062        temp != NULL_TREE;
1063        temp = TREE_CHAIN (temp))
1064     {
1065       const char *sym_name;
1066
1067       sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1068       if (sym_name[0] == '!' && sym_name[1] == 'T'
1069           && ! strcmp (name+2, sym_name+2))
1070         {
1071           ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp)));
1072           /* Avoid generating a stub for this.  */
1073           TREE_USED (temp) = 0;
1074           break;
1075         }
1076     }
1077 }
1078
1079 /* Scan the list of stubs and update any recorded names whose
1080    stripped name matches the argument.  */
1081
1082 static void
1083 update_stubs (name)
1084      const char *name;
1085 {
1086   const char *name1, *name2;
1087   tree temp;
1088
1089   name1 = darwin_strip_name_encoding (name);
1090
1091   for (temp = machopic_stubs;
1092        temp != NULL_TREE; 
1093        temp = TREE_CHAIN (temp))
1094     {
1095       const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1096
1097       if (*sym_name == '!')
1098         {
1099           name2 = darwin_strip_name_encoding (sym_name);
1100           if (strcmp (name1, name2) == 0)
1101             {
1102               IDENTIFIER_POINTER (TREE_VALUE (temp)) = name;
1103               break;
1104             }
1105         }
1106     }
1107 }
1108
1109 void
1110 machopic_select_section (exp, reloc, align)
1111      tree exp;
1112      int reloc;
1113      unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1114 {
1115   if (TREE_CODE (exp) == STRING_CST)
1116     {
1117       if (flag_writable_strings)
1118         data_section ();
1119       else if (TREE_STRING_LENGTH (exp) !=
1120                strlen (TREE_STRING_POINTER (exp)) + 1)
1121         readonly_data_section ();
1122       else
1123         cstring_section ();
1124     }
1125   else if (TREE_CODE (exp) == INTEGER_CST
1126            || TREE_CODE (exp) == REAL_CST)
1127     {
1128       tree size = TYPE_SIZE (TREE_TYPE (exp));
1129
1130       if (TREE_CODE (size) == INTEGER_CST &&
1131           TREE_INT_CST_LOW (size) == 4 &&
1132           TREE_INT_CST_HIGH (size) == 0)
1133         literal4_section ();
1134       else if (TREE_CODE (size) == INTEGER_CST &&
1135                TREE_INT_CST_LOW (size) == 8 &&
1136                TREE_INT_CST_HIGH (size) == 0)
1137         literal8_section ();
1138       else
1139         readonly_data_section ();
1140     }
1141   else if (TREE_CODE (exp) == CONSTRUCTOR
1142            && TREE_TYPE (exp)
1143            && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1144            && TYPE_NAME (TREE_TYPE (exp)))
1145     {
1146       tree name = TYPE_NAME (TREE_TYPE (exp));
1147       if (TREE_CODE (name) == TYPE_DECL)
1148         name = DECL_NAME (name);
1149       if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1150         objc_constant_string_object_section ();
1151       else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1152         objc_string_object_section ();
1153       else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1154         {
1155           if (TREE_SIDE_EFFECTS (exp) || (flag_pic && reloc))
1156             const_data_section ();
1157           else
1158             readonly_data_section ();
1159         }
1160       else
1161         data_section ();
1162     }
1163   else if (TREE_CODE (exp) == VAR_DECL &&
1164            DECL_NAME (exp) &&
1165            TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1166            IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1167            !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1168     {
1169       const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1170
1171       if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1172         objc_cls_meth_section ();
1173       else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1174         objc_inst_meth_section ();
1175       else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1176         objc_cat_cls_meth_section ();
1177       else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1178         objc_cat_inst_meth_section ();
1179       else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1180         objc_class_vars_section ();
1181       else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1182         objc_instance_vars_section ();
1183       else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1184         objc_cat_cls_meth_section ();
1185       else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1186         objc_class_names_section ();
1187       else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1188         objc_meth_var_names_section ();
1189       else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1190         objc_meth_var_types_section ();
1191       else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1192         objc_cls_refs_section ();
1193       else if (!strncmp (name, "_OBJC_CLASS_", 12))
1194         objc_class_section ();
1195       else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1196         objc_meta_class_section ();
1197       else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1198         objc_category_section ();
1199       else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1200         objc_selector_refs_section ();
1201       else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1202         objc_selector_fixup_section ();
1203       else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1204         objc_symbols_section ();
1205       else if (!strncmp (name, "_OBJC_MODULES", 13))
1206         objc_module_info_section ();
1207       else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1208         objc_cat_inst_meth_section ();
1209       else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1210         objc_cat_cls_meth_section ();
1211       else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1212         objc_cat_cls_meth_section ();
1213       else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1214         objc_protocol_section ();
1215       else if ((TREE_READONLY (exp) || TREE_CONSTANT (exp))
1216                && !TREE_SIDE_EFFECTS (exp))
1217         {
1218           if (flag_pic && reloc)
1219             const_data_section ();
1220           else
1221             readonly_data_section ();
1222         }
1223       else
1224         data_section ();
1225     }
1226   else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1227     {
1228       if (TREE_SIDE_EFFECTS (exp) || (flag_pic && reloc))
1229         const_data_section ();
1230       else
1231         readonly_data_section ();
1232     }
1233   else
1234     data_section ();
1235 }
1236
1237 /* This can be called with address expressions as "rtx".
1238    They must go in "const". */
1239
1240 void
1241 machopic_select_rtx_section (mode, x, align)
1242      enum machine_mode mode;
1243      rtx x;
1244      unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
1245 {
1246   if (GET_MODE_SIZE (mode) == 8)
1247     literal8_section ();
1248   else if (GET_MODE_SIZE (mode) == 4
1249            && (GET_CODE (x) == CONST_INT
1250                || GET_CODE (x) == CONST_DOUBLE))
1251     literal4_section ();
1252   else
1253     const_section ();
1254 }
1255
1256 void
1257 machopic_asm_out_constructor (symbol, priority)
1258      rtx symbol;
1259      int priority ATTRIBUTE_UNUSED;
1260 {
1261   if (flag_pic)
1262     mod_init_section ();
1263   else
1264     constructor_section ();
1265   assemble_align (POINTER_SIZE);
1266   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1267
1268   if (!flag_pic)
1269     fprintf (asm_out_file, ".reference .constructors_used\n");
1270 }
1271
1272 void
1273 machopic_asm_out_destructor (symbol, priority)
1274      rtx symbol;
1275      int priority ATTRIBUTE_UNUSED;
1276 {
1277   if (flag_pic)
1278     mod_term_section ();
1279   else
1280     destructor_section ();
1281   assemble_align (POINTER_SIZE);
1282   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1283
1284   if (!flag_pic)
1285     fprintf (asm_out_file, ".reference .destructors_used\n");
1286 }
1287
1288 #include "gt-darwin.h"
1289