OSDN Git Service

2004-07-16 Andreas Krebbel <krebbel1@de.ibm.com>
[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, 2004
3    Free Software Foundation, Inc.
4    Contributed by Apple Computer Inc.
5
6 This file is part of GCC.
7
8 GCC 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 GCC 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 GCC; 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 #include "errors.h"
45
46 static int machopic_data_defined_p (const char *);
47 static void update_non_lazy_ptrs (const char *);
48 static void update_stubs (const char *);
49 static const char *machopic_non_lazy_ptr_name (const char*);
50
51 int
52 name_needs_quotes (const char *name)
53 {
54   int c;
55   while ((c = *name++) != '\0')
56     if (! ISIDNUM (c) && c != '.' && c != '$')
57       return 1;
58   return 0;
59 }
60
61 /*
62  * flag_pic = 1 ... generate only indirections
63  * flag_pic = 2 ... generate indirections and pure code
64  */
65
66 /* This module assumes that (const (symbol_ref "foo")) is a legal pic
67    reference, which will not be changed.  */
68
69 static GTY(()) tree machopic_defined_list;
70
71 enum machopic_addr_class
72 machopic_classify_ident (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   /* The PIC base symbol is always defined.  */
86   if (! strcmp (name, "<pic base>"))
87     return MACHOPIC_DEFINED_DATA;
88
89   if (name[0] != '!')
90     {
91       /* Here if no special encoding to be found.  */
92       if (lprefix)
93         {
94           const char *name = IDENTIFIER_POINTER (ident);
95           int len = strlen (name);
96
97           if ((len > 5 && !strcmp (name + len - 5, "$stub"))
98               || (len > 6 && !strcmp (name + len - 6, "$stub\"")))
99             return MACHOPIC_DEFINED_FUNCTION;
100           return MACHOPIC_DEFINED_DATA;
101         }
102
103       for (temp = machopic_defined_list;
104            temp != NULL_TREE;
105            temp = TREE_CHAIN (temp))
106         {
107           if (ident == TREE_VALUE (temp))
108             return MACHOPIC_DEFINED_DATA;
109         }
110
111       if (TREE_ASM_WRITTEN (ident))
112         return MACHOPIC_DEFINED_DATA;
113
114       return MACHOPIC_UNDEFINED;
115     }
116
117   else if (name[1] == 'D')
118     return MACHOPIC_DEFINED_DATA;
119
120   else if (name[1] == 'T')
121     return MACHOPIC_DEFINED_FUNCTION;
122
123   /* It is possible that someone is holding a "stale" name, which has
124      since been defined.  See if there is a "defined" name (i.e,
125      different from NAME only in having a '!D_' or a '!T_' instead of
126      a '!d_' or '!t_' prefix) in the identifier hash tables.  If so, say
127      that this identifier is defined.  */
128   else if (name[1] == 'd' || name[1] == 't')
129     {
130       char *new_name;
131       new_name = (char *)alloca (strlen (name) + 1);
132       strcpy (new_name, name);
133       new_name[1] = (name[1] == 'd') ? 'D' : 'T';
134       if (maybe_get_identifier (new_name) != NULL)
135         return  (name[1] == 'd') ? MACHOPIC_DEFINED_DATA
136                                  : MACHOPIC_DEFINED_FUNCTION;
137     }
138
139   for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp))
140     {
141       if (ident == TREE_VALUE (temp))
142         {
143           if (name[1] == 'T')
144             return MACHOPIC_DEFINED_FUNCTION;
145           else
146             return MACHOPIC_DEFINED_DATA;
147         }
148     }
149
150   if (name[1] == 't' || name[1] == 'T')
151     {
152       if (lprefix)
153         return MACHOPIC_DEFINED_FUNCTION;
154       else
155         return MACHOPIC_UNDEFINED_FUNCTION;
156     }
157   else
158     {
159       if (lprefix)
160         return MACHOPIC_DEFINED_DATA;
161       else
162         return MACHOPIC_UNDEFINED_DATA;
163     }
164 }
165
166
167 enum machopic_addr_class
168 machopic_classify_name (const char *name)
169 {
170   return machopic_classify_ident (get_identifier (name));
171 }
172
173 int
174 machopic_ident_defined_p (tree ident)
175 {
176   switch (machopic_classify_ident (ident))
177     {
178     case MACHOPIC_UNDEFINED:
179     case MACHOPIC_UNDEFINED_DATA:
180     case MACHOPIC_UNDEFINED_FUNCTION:
181       return 0;
182     default:
183       return 1;
184     }
185 }
186
187 static int
188 machopic_data_defined_p (const char *name)
189 {
190   switch (machopic_classify_ident (get_identifier (name)))
191     {
192     case MACHOPIC_DEFINED_DATA:
193       return 1;
194     default:
195       return 0;
196     }
197 }
198
199 int
200 machopic_name_defined_p (const char *name)
201 {
202   return machopic_ident_defined_p (get_identifier (name));
203 }
204
205 void
206 machopic_define_ident (tree ident)
207 {
208   if (!machopic_ident_defined_p (ident))
209     machopic_defined_list =
210       tree_cons (NULL_TREE, ident, machopic_defined_list);
211 }
212
213 void
214 machopic_define_name (const char *name)
215 {
216   machopic_define_ident (get_identifier (name));
217 }
218
219 static GTY(()) char * function_base;
220
221 const char *
222 machopic_function_base_name (void)
223 {
224   /* if dynamic-no-pic is on, we should not get here */
225   if (MACHO_DYNAMIC_NO_PIC_P)
226     abort ();
227
228   if (function_base == NULL)
229     function_base =
230       (char *) ggc_alloc_string ("<pic base>", sizeof ("<pic base>"));
231
232   current_function_uses_pic_offset_table = 1;
233
234   return function_base;
235 }
236
237 static GTY(()) const char * function_base_func_name;
238 static GTY(()) int current_pic_label_num;
239
240 void
241 machopic_output_function_base_name (FILE *file)
242 {
243   const char *current_name;
244
245   /* If dynamic-no-pic is on, we should not get here.  */
246   if (MACHO_DYNAMIC_NO_PIC_P)
247     abort ();
248   current_name =
249     IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
250   if (function_base_func_name != current_name)
251     {
252       ++current_pic_label_num;
253       function_base_func_name = current_name;
254     }
255   fprintf (file, "\"L%011d$pb\"", current_pic_label_num);
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 static const char *
265 machopic_non_lazy_ptr_name (const char *name)
266 {
267   const char *temp_name;
268   tree temp, ident = get_identifier (name);
269
270   for (temp = machopic_non_lazy_pointers;
271        temp != NULL_TREE;
272        temp = TREE_CHAIN (temp))
273     {
274       if (ident == TREE_VALUE (temp))
275         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
276     }
277
278   name = darwin_strip_name_encoding (name);
279
280   /* Try again, but comparing names this time.  */
281   for (temp = machopic_non_lazy_pointers;
282        temp != NULL_TREE;
283        temp = TREE_CHAIN (temp))
284     {
285       if (TREE_VALUE (temp))
286         {
287           temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
288           temp_name = darwin_strip_name_encoding (temp_name);
289           if (strcmp (name, temp_name) == 0)
290             return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
291         }
292     }
293
294   {
295     char *buffer;
296     int namelen = strlen (name);
297     int bufferlen = 0;
298     tree ptr_name;
299
300     buffer = alloca (namelen + strlen("$non_lazy_ptr") + 5);
301
302     strcpy (buffer, "&L");
303     bufferlen = 2;
304     if (name[0] == '*')
305       {
306         memcpy (buffer + bufferlen, name+1, namelen-1+1);
307         bufferlen += namelen-1;
308       }
309     else
310       {
311         strcpy (buffer + bufferlen, user_label_prefix);
312         bufferlen += strlen (user_label_prefix);
313         memcpy (buffer + bufferlen, name, namelen+1);
314         bufferlen += namelen;
315       }
316
317     memcpy (buffer + bufferlen, "$non_lazy_ptr", strlen("$non_lazy_ptr")+1);
318     bufferlen += strlen("$non_lazy_ptr");
319     ptr_name = get_identifier (buffer);
320
321     machopic_non_lazy_pointers
322       = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
323
324     TREE_USED (machopic_non_lazy_pointers) = 0;
325
326     return IDENTIFIER_POINTER (ptr_name);
327   }
328 }
329
330 static GTY(()) tree machopic_stubs;
331
332 /* Return the name of the stub corresponding to the given name,
333    generating a new stub name if necessary.  */
334
335 const char *
336 machopic_stub_name (const char *name)
337 {
338   tree temp, ident = get_identifier (name);
339   const char *tname;
340
341   for (temp = machopic_stubs;
342        temp != NULL_TREE;
343        temp = TREE_CHAIN (temp))
344     {
345       if (ident == TREE_VALUE (temp))
346         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
347       tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
348       if (strcmp (name, tname) == 0)
349         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
350       /* A library call name might not be section-encoded yet, so try
351          it against a stripped name.  */
352       if (name[0] != '!'
353           && tname[0] == '!'
354           && strcmp (name, tname + 4) == 0)
355         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
356     }
357
358   name = darwin_strip_name_encoding (name);
359
360   {
361     char *buffer;
362     int bufferlen = 0;
363     int namelen = strlen (name);
364     tree ptr_name;
365     int needs_quotes = name_needs_quotes (name);
366
367     buffer = alloca (namelen + 20);
368
369     if (needs_quotes)
370       {
371         strcpy (buffer, "&\"L");
372         bufferlen = strlen("&\"L");
373       }
374     else
375       {
376         strcpy (buffer, "&L");
377         bufferlen = strlen("&L");
378       }
379     
380     if (name[0] == '*')
381       {
382         memcpy (buffer + bufferlen, name+1, namelen - 1 +1);
383         bufferlen += namelen - 1;
384       }
385     else
386       {
387         strcpy (buffer + bufferlen, user_label_prefix);
388         bufferlen += strlen (user_label_prefix);
389         memcpy (buffer + bufferlen, name, namelen+1);
390         bufferlen += namelen;
391       }
392
393     if (needs_quotes)
394       {
395         memcpy (buffer + bufferlen, "$stub\"", strlen("$stub\"")+1);
396         bufferlen += strlen("$stub\"");
397       }
398     else
399       {
400         memcpy (buffer + bufferlen, "$stub", strlen("$stub")+1);
401         bufferlen += strlen("$stub");
402       }
403     ptr_name = get_identifier (buffer);
404
405     machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
406     TREE_USED (machopic_stubs) = 0;
407
408     return IDENTIFIER_POINTER (ptr_name);
409   }
410 }
411
412 void
413 machopic_validate_stub_or_non_lazy_ptr (const char *name, int validate_stub)
414 {
415   const char *real_name;
416   tree temp, ident = get_identifier (name), id2;
417
418     for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
419          temp != NULL_TREE;
420          temp = TREE_CHAIN (temp))
421       if (ident == TREE_PURPOSE (temp))
422         {
423           /* Mark both the stub or non-lazy pointer as well as the
424              original symbol as being referenced.  */
425           TREE_USED (temp) = 1;
426           if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
427             mark_referenced (TREE_VALUE (temp));
428           real_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
429           real_name = darwin_strip_name_encoding (real_name);
430           id2 = maybe_get_identifier (real_name);
431           if (id2)
432             mark_referenced (id2);
433         }
434 }
435
436 /* Transform ORIG, which may be any data source, to the corresponding
437    source using indirections.  */
438
439 rtx
440 machopic_indirect_data_reference (rtx orig, rtx reg)
441 {
442   rtx ptr_ref = orig;
443
444   if (! MACHOPIC_INDIRECT)
445     return orig;
446
447   if (GET_CODE (orig) == SYMBOL_REF)
448     {
449       const char *name = XSTR (orig, 0);
450       int defined = machopic_data_defined_p (name);
451
452       if (defined && MACHO_DYNAMIC_NO_PIC_P)
453         {
454 #if defined (TARGET_TOC)
455            emit_insn (gen_macho_high (reg, orig));
456            emit_insn (gen_macho_low (reg, reg, orig));
457 #else
458            /* some other cpu -- writeme!  */
459            abort ();
460 #endif
461            return reg;
462         }
463       else if (defined)
464         {
465 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
466           rtx pic_base = gen_rtx_SYMBOL_REF (Pmode,
467                                              machopic_function_base_name ());
468           rtx offset = gen_rtx_CONST (Pmode,
469                                       gen_rtx_MINUS (Pmode, orig, pic_base));
470 #endif
471
472 #if defined (TARGET_TOC) /* i.e., PowerPC */
473           rtx hi_sum_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
474
475           if (reg == NULL)
476             abort ();
477
478           emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
479                               gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
480                                        gen_rtx_HIGH (Pmode, offset))));
481           emit_insn (gen_rtx_SET (Pmode, reg,
482                                   gen_rtx_LO_SUM (Pmode, hi_sum_reg, offset)));
483
484           orig = reg;
485 #else
486 #if defined (HAVE_lo_sum)
487           if (reg == 0) abort ();
488
489           emit_insn (gen_rtx_SET (VOIDmode, reg,
490                                   gen_rtx_HIGH (Pmode, offset)));
491           emit_insn (gen_rtx_SET (VOIDmode, reg,
492                                   gen_rtx_LO_SUM (Pmode, reg, offset)));
493           emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
494
495           orig = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, reg);
496 #endif
497 #endif
498           return orig;
499         }
500
501       ptr_ref = gen_rtx_SYMBOL_REF (Pmode,
502                                     machopic_non_lazy_ptr_name (name));
503
504      SYMBOL_REF_DECL (ptr_ref) = SYMBOL_REF_DECL (orig);
505
506       ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
507       RTX_UNCHANGING_P (ptr_ref) = 1;
508
509       return ptr_ref;
510     }
511   else if (GET_CODE (orig) == CONST)
512     {
513       rtx base, result;
514
515       /* legitimize both operands of the PLUS */
516       if (GET_CODE (XEXP (orig, 0)) == PLUS)
517         {
518           base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
519                                                    reg);
520           orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
521                                                    (base == reg ? 0 : reg));
522         }
523       else
524         return orig;
525
526       if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
527         result = plus_constant (base, INTVAL (orig));
528       else
529         result = gen_rtx_PLUS (Pmode, base, orig);
530
531       if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
532         {
533           if (reg)
534             {
535               emit_move_insn (reg, result);
536               result = reg;
537             }
538           else
539             {
540               result = force_reg (GET_MODE (result), result);
541             }
542         }
543
544       return result;
545
546     }
547   else if (GET_CODE (orig) == MEM)
548     XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
549   /* When the target is i386, this code prevents crashes due to the
550      compiler's ignorance on how to move the PIC base register to
551      other registers.  (The reload phase sometimes introduces such
552      insns.)  */
553   else if (GET_CODE (orig) == PLUS
554            && GET_CODE (XEXP (orig, 0)) == REG
555            && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
556 #ifdef I386
557            /* Prevent the same register from being erroneously used
558               as both the base and index registers.  */
559            && GET_CODE (XEXP (orig, 1)) == CONST
560 #endif
561            && reg)
562     {
563       emit_move_insn (reg, XEXP (orig, 0));
564       XEXP (ptr_ref, 0) = reg;
565     }
566   return ptr_ref;
567 }
568
569 /* Transform TARGET (a MEM), which is a function call target, to the
570    corresponding symbol_stub if necessary.  Return a new MEM.  */
571
572 rtx
573 machopic_indirect_call_target (rtx target)
574 {
575   if (GET_CODE (target) != MEM)
576     return target;
577
578   if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
579     {
580       enum machine_mode mode = GET_MODE (XEXP (target, 0));
581       const char *name = XSTR (XEXP (target, 0), 0);
582
583       /* If the name is already defined, we need do nothing.  */
584       if (name[0] == '!' && name[1] == 'T')
585         return target;
586
587       if (!machopic_name_defined_p (name))
588         {
589           const char *stub_name = machopic_stub_name (name);
590           tree decl = SYMBOL_REF_DECL (XEXP (target, 0));
591
592           XEXP (target, 0) = gen_rtx_SYMBOL_REF (mode, stub_name);
593           SYMBOL_REF_DECL (XEXP (target, 0)) = decl;
594           RTX_UNCHANGING_P (target) = 1;
595         }
596     }
597
598   return target;
599 }
600
601 rtx
602 machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
603 {
604   rtx pic_ref = orig;
605
606   if (! MACHOPIC_INDIRECT)
607     return orig;
608
609   /* First handle a simple SYMBOL_REF or LABEL_REF */
610   if (GET_CODE (orig) == LABEL_REF
611       || (GET_CODE (orig) == SYMBOL_REF
612           ))
613     {
614       /* addr(foo) = &func+(foo-func) */
615       rtx pic_base;
616
617       orig = machopic_indirect_data_reference (orig, reg);
618
619       if (GET_CODE (orig) == PLUS
620           && GET_CODE (XEXP (orig, 0)) == REG)
621         {
622           if (reg == 0)
623             return force_reg (mode, orig);
624
625           emit_move_insn (reg, orig);
626           return reg;
627         }
628
629       /* if dynamic-no-pic then use 0 as the pic base  */
630       if (MACHO_DYNAMIC_NO_PIC_P)
631         pic_base = CONST0_RTX (Pmode);
632       else
633       pic_base = gen_rtx_SYMBOL_REF (Pmode, machopic_function_base_name ());
634
635       if (GET_CODE (orig) == MEM)
636         {
637           if (reg == 0)
638             {
639               if (reload_in_progress)
640                 abort ();
641               else
642                 reg = gen_reg_rtx (Pmode);
643             }
644
645 #ifdef HAVE_lo_sum
646           if (MACHO_DYNAMIC_NO_PIC_P
647               && (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
648                   || GET_CODE (XEXP (orig, 0)) == LABEL_REF))
649             {
650 #if defined (TARGET_TOC)        /* ppc  */
651               rtx temp_reg = (no_new_pseudos) ? reg : gen_reg_rtx (Pmode);
652               rtx asym = XEXP (orig, 0);
653               rtx mem;
654
655               emit_insn (gen_macho_high (temp_reg, asym));
656               mem = gen_rtx_MEM (GET_MODE (orig),
657                                  gen_rtx_LO_SUM (Pmode, temp_reg, asym));
658               RTX_UNCHANGING_P (mem) = 1;
659               emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
660 #else
661               /* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic  */
662               abort ();
663 #endif
664               pic_ref = reg;
665             }
666           else
667           if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
668               || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
669             {
670               rtx offset = gen_rtx_CONST (Pmode,
671                                           gen_rtx_MINUS (Pmode,
672                                                          XEXP (orig, 0),
673                                                          pic_base));
674 #if defined (TARGET_TOC) /* i.e., PowerPC */
675               /* Generating a new reg may expose opportunities for
676                  common subexpression elimination.  */
677               rtx hi_sum_reg = no_new_pseudos ? reg : gen_reg_rtx (SImode);
678               rtx mem;
679               rtx insn;
680               rtx sum;
681               
682               sum = gen_rtx_HIGH (Pmode, offset);
683               if (! MACHO_DYNAMIC_NO_PIC_P)
684                 sum = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, sum);
685
686               emit_insn (gen_rtx_SET (Pmode, hi_sum_reg, sum));
687
688               mem = gen_rtx_MEM (GET_MODE (orig),
689                                  gen_rtx_LO_SUM (Pmode, 
690                                                  hi_sum_reg, offset));
691               RTX_UNCHANGING_P (mem) = 1;
692               insn = emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
693               REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, pic_ref, 
694                                                     REG_NOTES (insn));
695
696               pic_ref = reg;
697 #else
698               emit_insn (gen_rtx_USE (VOIDmode,
699                                       gen_rtx_REG (Pmode, 
700                                                    PIC_OFFSET_TABLE_REGNUM)));
701
702               emit_insn (gen_rtx_SET (VOIDmode, reg,
703                                       gen_rtx_HIGH (Pmode,
704                                                     gen_rtx_CONST (Pmode, 
705                                                                    offset))));
706               emit_insn (gen_rtx_SET (VOIDmode, reg,
707                                   gen_rtx_LO_SUM (Pmode, reg,
708                                            gen_rtx_CONST (Pmode, offset))));
709               pic_ref = gen_rtx_PLUS (Pmode,
710                                       pic_offset_table_rtx, reg);
711 #endif
712             }
713           else
714 #endif  /* HAVE_lo_sum */
715             {
716               rtx pic = pic_offset_table_rtx;
717               if (GET_CODE (pic) != REG)
718                 {
719                   emit_move_insn (reg, pic);
720                   pic = reg;
721                 }
722 #if 0
723               emit_insn (gen_rtx_USE (VOIDmode,
724                                       gen_rtx_REG (Pmode, 
725                                                    PIC_OFFSET_TABLE_REGNUM)));
726 #endif
727
728               pic_ref = gen_rtx_PLUS (Pmode,
729                                       pic,
730                                       gen_rtx_CONST (Pmode,
731                                           gen_rtx_MINUS (Pmode,
732                                                          XEXP (orig, 0),
733                                                          pic_base)));
734             }
735
736 #if !defined (TARGET_TOC)
737           emit_move_insn (reg, pic_ref);
738           pic_ref = gen_rtx_MEM (GET_MODE (orig), reg);
739 #endif
740           RTX_UNCHANGING_P (pic_ref) = 1;
741         }
742       else
743         {
744
745 #ifdef HAVE_lo_sum
746           if (GET_CODE (orig) == SYMBOL_REF
747               || GET_CODE (orig) == LABEL_REF)
748             {
749               rtx offset = gen_rtx_CONST (Pmode,
750                                           gen_rtx_MINUS (Pmode, 
751                                                          orig, pic_base));
752 #if defined (TARGET_TOC) /* i.e., PowerPC */
753               rtx hi_sum_reg;
754
755               if (reg == 0)
756                 {
757                   if (reload_in_progress)
758                     abort ();
759                   else
760                     reg = gen_reg_rtx (SImode);
761                 }
762
763               hi_sum_reg = reg;
764
765               emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
766                                       (MACHO_DYNAMIC_NO_PIC_P)
767                                       ? gen_rtx_HIGH (Pmode, offset)
768                                       : gen_rtx_PLUS (Pmode,
769                                                       pic_offset_table_rtx,
770                                                       gen_rtx_HIGH (Pmode, 
771                                                                     offset))));
772               emit_insn (gen_rtx_SET (VOIDmode, reg,
773                                       gen_rtx_LO_SUM (Pmode,
774                                                       hi_sum_reg, offset)));
775               pic_ref = reg;
776               RTX_UNCHANGING_P (pic_ref) = 1;
777 #else
778               emit_insn (gen_rtx_SET (VOIDmode, reg,
779                                       gen_rtx_HIGH (Pmode, offset)));
780               emit_insn (gen_rtx_SET (VOIDmode, reg,
781                                       gen_rtx_LO_SUM (Pmode, reg, offset)));
782               pic_ref = gen_rtx_PLUS (Pmode,
783                                       pic_offset_table_rtx, reg);
784               RTX_UNCHANGING_P (pic_ref) = 1;
785 #endif
786             }
787           else
788 #endif  /*  HAVE_lo_sum  */
789             {
790               if (GET_CODE (orig) == REG)
791                 {
792                   return orig;
793                 }
794               else
795                 {
796                   rtx pic = pic_offset_table_rtx;
797                   if (GET_CODE (pic) != REG)
798                     {
799                       emit_move_insn (reg, pic);
800                       pic = reg;
801                     }
802 #if 0
803                   emit_insn (gen_rtx_USE (VOIDmode,
804                                           pic_offset_table_rtx));
805 #endif
806                   pic_ref = gen_rtx_PLUS (Pmode,
807                                           pic,
808                                           gen_rtx_CONST (Pmode,
809                                               gen_rtx_MINUS (Pmode,
810                                                              orig, pic_base)));
811                 }
812             }
813         }
814
815       if (GET_CODE (pic_ref) != REG)
816         {
817           if (reg != 0)
818             {
819               emit_move_insn (reg, pic_ref);
820               return reg;
821             }
822           else
823             {
824               return force_reg (mode, pic_ref);
825             }
826         }
827       else
828         {
829           return pic_ref;
830         }
831     }
832
833   else if (GET_CODE (orig) == SYMBOL_REF)
834     return orig;
835
836   else if (GET_CODE (orig) == PLUS
837            && (GET_CODE (XEXP (orig, 0)) == MEM
838                || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
839                || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
840            && XEXP (orig, 0) != pic_offset_table_rtx
841            && GET_CODE (XEXP (orig, 1)) != REG)
842
843     {
844       rtx base;
845       int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
846
847       base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
848       orig = machopic_legitimize_pic_address (XEXP (orig, 1),
849                                               Pmode, (base == reg ? 0 : reg));
850       if (GET_CODE (orig) == CONST_INT)
851         {
852           pic_ref = plus_constant (base, INTVAL (orig));
853           is_complex = 1;
854         }
855       else
856         pic_ref = gen_rtx_PLUS (Pmode, base, orig);
857
858       if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
859         RTX_UNCHANGING_P (pic_ref) = 1;
860
861       if (reg && is_complex)
862         {
863           emit_move_insn (reg, pic_ref);
864           pic_ref = reg;
865         }
866       /* Likewise, should we set special REG_NOTEs here?  */
867     }
868
869   else if (GET_CODE (orig) == CONST)
870     {
871       return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
872     }
873
874   else if (GET_CODE (orig) == MEM
875            && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
876     {
877       rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
878
879       addr = gen_rtx_MEM (GET_MODE (orig), addr);
880       RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
881       emit_move_insn (reg, addr);
882       pic_ref = reg;
883     }
884
885   return pic_ref;
886 }
887
888
889 void
890 machopic_finish (FILE *asm_out_file)
891 {
892   tree temp;
893
894   for (temp = machopic_stubs;
895        temp != NULL_TREE;
896        temp = TREE_CHAIN (temp))
897     {
898       const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
899       const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
900       char *sym;
901       char *stub;
902
903       if (! TREE_USED (temp))
904         continue;
905
906       sym_name = darwin_strip_name_encoding (sym_name);
907
908       sym = alloca (strlen (sym_name) + 2);
909       if (sym_name[0] == '*' || sym_name[0] == '&')
910         strcpy (sym, sym_name + 1);
911       else if (sym_name[0] == '-' || sym_name[0] == '+')
912         strcpy (sym, sym_name);
913       else
914         sprintf (sym, "%s%s", user_label_prefix, sym_name);
915
916       stub = alloca (strlen (stub_name) + 2);
917       if (stub_name[0] == '*' || stub_name[0] == '&')
918         strcpy (stub, stub_name + 1);
919       else
920         sprintf (stub, "%s%s", user_label_prefix, stub_name);
921
922       machopic_output_stub (asm_out_file, sym, stub);
923     }
924
925   for (temp = machopic_non_lazy_pointers;
926        temp != NULL_TREE;
927        temp = TREE_CHAIN (temp))
928     {
929       const char *const sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
930       const char *const lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
931
932       if (! TREE_USED (temp))
933         continue;
934
935       if (machopic_ident_defined_p (TREE_VALUE (temp)))
936         {
937           data_section ();
938           assemble_align (GET_MODE_ALIGNMENT (Pmode));
939           assemble_label (lazy_name);
940           assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
941                             GET_MODE_SIZE (Pmode),
942                             GET_MODE_ALIGNMENT (Pmode), 1);
943         }
944       else
945         {
946           machopic_nl_symbol_ptr_section ();
947           assemble_name (asm_out_file, lazy_name);
948           fprintf (asm_out_file, ":\n");
949
950           fprintf (asm_out_file, "\t.indirect_symbol ");
951           assemble_name (asm_out_file, sym_name);
952           fprintf (asm_out_file, "\n");
953
954           assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
955                             GET_MODE_ALIGNMENT (Pmode), 1);
956         }
957     }
958 }
959
960 int
961 machopic_operand_p (rtx op)
962 {
963   if (MACHOPIC_JUST_INDIRECT)
964     {
965       while (GET_CODE (op) == CONST)
966         op = XEXP (op, 0);
967
968       if (GET_CODE (op) == SYMBOL_REF)
969         return machopic_name_defined_p (XSTR (op, 0));
970       else
971         return 0;
972     }
973
974   while (GET_CODE (op) == CONST)
975     op = XEXP (op, 0);
976
977   if (GET_CODE (op) == MINUS
978       && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
979       && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
980       && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
981       && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
982       return 1;
983
984   return 0;
985 }
986
987 /* This function records whether a given name corresponds to a defined
988    or undefined function or variable, for machopic_classify_ident to
989    use later.  */
990
991 void
992 darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
993 {
994   char code = '\0';
995   int defined = 0;
996   rtx sym_ref;
997   const char *orig_str;
998   char *new_str;
999   size_t len, new_len;
1000
1001   /* Do the standard encoding things first.  */
1002   default_encode_section_info (decl, rtl, first);
1003
1004   /* With the introduction of symbol_ref flags, some of the following
1005      code has become redundant and should be removed at some point.  */
1006
1007   if ((TREE_CODE (decl) == FUNCTION_DECL
1008        || TREE_CODE (decl) == VAR_DECL)
1009       && !DECL_EXTERNAL (decl)
1010       && (!TREE_PUBLIC (decl) || (!DECL_ONE_ONLY (decl) && !DECL_WEAK (decl)))
1011       && ((TREE_STATIC (decl)
1012            && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
1013           || (!DECL_COMMON (decl) && DECL_INITIAL (decl)
1014               && DECL_INITIAL (decl) != error_mark_node)))
1015     defined = 1;
1016
1017   if (TREE_CODE (decl) == FUNCTION_DECL)
1018     code = (defined ? 'T' : 't');
1019   else if (TREE_CODE (decl) == VAR_DECL)
1020     code = (defined ? 'D' : 'd');
1021
1022   if (code == '\0')
1023     return;
1024
1025   sym_ref = XEXP (rtl, 0);
1026   orig_str = XSTR (sym_ref, 0);
1027   len = strlen (orig_str) + 1;
1028
1029   if (orig_str[0] == '!')
1030     {
1031       /* Already encoded; see if we need to change it.  */
1032       if (code == orig_str[1])
1033         return;
1034       /* Yes, tweak a copy of the name and put it in a new string.  */
1035       new_str = alloca (len);
1036       memcpy (new_str, orig_str, len);
1037       new_str[1] = code;
1038       XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
1039     }
1040   else
1041     {
1042       /* Add the encoding.  */
1043       new_len = len + 4;
1044       new_str = alloca (new_len);
1045       new_str[0] = '!';
1046       new_str[1] = code;
1047       new_str[2] = '_';
1048       new_str[3] = '_';
1049       memcpy (new_str + 4, orig_str, len);
1050       XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
1051     }
1052   /* The non-lazy pointer list may have captured references to the
1053      old encoded name, change them.  */
1054   if (TREE_CODE (decl) == VAR_DECL)
1055     update_non_lazy_ptrs (XSTR (sym_ref, 0));
1056   else
1057     update_stubs (XSTR (sym_ref, 0));
1058 }
1059
1060 /* Undo the effects of the above.  */
1061
1062 const char *
1063 darwin_strip_name_encoding (const char *str)
1064 {
1065   return str[0] == '!' ? str + 4 : str;
1066 }
1067
1068 /* Scan the list of non-lazy pointers and update any recorded names whose
1069    stripped name matches the argument.  */
1070
1071 static void
1072 update_non_lazy_ptrs (const char *name)
1073 {
1074   const char *name1, *name2;
1075   tree temp;
1076
1077   name1 = darwin_strip_name_encoding (name);
1078
1079   for (temp = machopic_non_lazy_pointers;
1080        temp != NULL_TREE;
1081        temp = TREE_CHAIN (temp))
1082     {
1083       const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1084
1085       if (*sym_name == '!')
1086         {
1087           name2 = darwin_strip_name_encoding (sym_name);
1088           if (strcmp (name1, name2) == 0)
1089             {
1090               /* FIXME: This breaks the identifier hash table.  */
1091               IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1092                 = (unsigned char *) name;
1093               break;
1094             }
1095         }
1096     }
1097 }
1098
1099 /* Scan the list of stubs and update any recorded names whose
1100    stripped name matches the argument.  */
1101
1102 static void
1103 update_stubs (const char *name)
1104 {
1105   const char *name1, *name2;
1106   tree temp;
1107
1108   name1 = darwin_strip_name_encoding (name);
1109
1110   for (temp = machopic_stubs;
1111        temp != NULL_TREE;
1112        temp = TREE_CHAIN (temp))
1113     {
1114       const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1115
1116       if (*sym_name == '!')
1117         {
1118           name2 = darwin_strip_name_encoding (sym_name);
1119           if (strcmp (name1, name2) == 0)
1120             {
1121               /* FIXME: This breaks the identifier hash table.  */
1122               IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1123                 = (unsigned char *) name;
1124               break;
1125             }
1126         }
1127     }
1128 }
1129
1130 void
1131 darwin_make_decl_one_only (tree decl)
1132 {
1133   static const char *text_section = "__TEXT,__textcoal_nt,coalesced,no_toc";
1134   static const char *data_section = "__DATA,__datacoal_nt,coalesced,no_toc";
1135
1136   const char *sec = TREE_CODE (decl) == FUNCTION_DECL
1137     ? text_section
1138     : data_section;
1139   TREE_PUBLIC (decl) = 1;
1140   DECL_ONE_ONLY (decl) = 1;
1141   DECL_SECTION_NAME (decl) = build_string (strlen (sec), sec);
1142 }
1143
1144 void
1145 machopic_select_section (tree exp, int reloc,
1146                          unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1147 {
1148   void (*base_function)(void);
1149
1150   if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
1151     base_function = readonly_data_section;
1152   else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1153     base_function = const_data_section;
1154   else
1155     base_function = data_section;
1156
1157   if (TREE_CODE (exp) == STRING_CST
1158       && ((size_t) TREE_STRING_LENGTH (exp)
1159           == strlen (TREE_STRING_POINTER (exp)) + 1))
1160     cstring_section ();
1161   else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
1162            && flag_merge_constants)
1163     {
1164       tree size = TYPE_SIZE (TREE_TYPE (exp));
1165
1166       if (TREE_CODE (size) == INTEGER_CST &&
1167           TREE_INT_CST_LOW (size) == 4 &&
1168           TREE_INT_CST_HIGH (size) == 0)
1169         literal4_section ();
1170       else if (TREE_CODE (size) == INTEGER_CST &&
1171                TREE_INT_CST_LOW (size) == 8 &&
1172                TREE_INT_CST_HIGH (size) == 0)
1173         literal8_section ();
1174       else
1175         base_function ();
1176     }
1177   else if (TREE_CODE (exp) == CONSTRUCTOR
1178            && TREE_TYPE (exp)
1179            && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1180            && TYPE_NAME (TREE_TYPE (exp)))
1181     {
1182       tree name = TYPE_NAME (TREE_TYPE (exp));
1183       if (TREE_CODE (name) == TYPE_DECL)
1184         name = DECL_NAME (name);
1185       if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1186         objc_constant_string_object_section ();
1187       else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1188         objc_string_object_section ();
1189       else
1190         base_function ();
1191     }
1192   else if (TREE_CODE (exp) == VAR_DECL &&
1193            DECL_NAME (exp) &&
1194            TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1195            IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1196            !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1197     {
1198       const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1199
1200       if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1201         objc_cls_meth_section ();
1202       else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1203         objc_inst_meth_section ();
1204       else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1205         objc_cat_cls_meth_section ();
1206       else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1207         objc_cat_inst_meth_section ();
1208       else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1209         objc_class_vars_section ();
1210       else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1211         objc_instance_vars_section ();
1212       else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1213         objc_cat_cls_meth_section ();
1214       else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1215         objc_class_names_section ();
1216       else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1217         objc_meth_var_names_section ();
1218       else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1219         objc_meth_var_types_section ();
1220       else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1221         objc_cls_refs_section ();
1222       else if (!strncmp (name, "_OBJC_CLASS_", 12))
1223         objc_class_section ();
1224       else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1225         objc_meta_class_section ();
1226       else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1227         objc_category_section ();
1228       else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1229         objc_selector_refs_section ();
1230       else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1231         objc_selector_fixup_section ();
1232       else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1233         objc_symbols_section ();
1234       else if (!strncmp (name, "_OBJC_MODULES", 13))
1235         objc_module_info_section ();
1236       else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
1237         objc_image_info_section ();
1238       else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1239         objc_cat_inst_meth_section ();
1240       else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1241         objc_cat_cls_meth_section ();
1242       else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1243         objc_cat_cls_meth_section ();
1244       else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1245         objc_protocol_section ();
1246       else
1247         base_function ();
1248     }
1249   else
1250     base_function ();
1251 }
1252
1253 /* This can be called with address expressions as "rtx".
1254    They must go in "const".  */
1255
1256 void
1257 machopic_select_rtx_section (enum machine_mode mode, rtx x,
1258                              unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1259 {
1260   if (GET_MODE_SIZE (mode) == 8)
1261     literal8_section ();
1262   else if (GET_MODE_SIZE (mode) == 4
1263            && (GET_CODE (x) == CONST_INT
1264                || GET_CODE (x) == CONST_DOUBLE))
1265     literal4_section ();
1266   else if (MACHOPIC_INDIRECT
1267            && (GET_CODE (x) == SYMBOL_REF
1268                || GET_CODE (x) == CONST
1269                || GET_CODE (x) == LABEL_REF))
1270     const_data_section ();
1271   else
1272     const_section ();
1273 }
1274
1275 void
1276 machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1277 {
1278   if (MACHOPIC_INDIRECT)
1279     mod_init_section ();
1280   else
1281     constructor_section ();
1282   assemble_align (POINTER_SIZE);
1283   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1284
1285   if (! MACHOPIC_INDIRECT)
1286     fprintf (asm_out_file, ".reference .constructors_used\n");
1287 }
1288
1289 void
1290 machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1291 {
1292   if (MACHOPIC_INDIRECT)
1293     mod_term_section ();
1294   else
1295     destructor_section ();
1296   assemble_align (POINTER_SIZE);
1297   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1298
1299   if (! MACHOPIC_INDIRECT)
1300     fprintf (asm_out_file, ".reference .destructors_used\n");
1301 }
1302
1303 void
1304 darwin_globalize_label (FILE *stream, const char *name)
1305 {
1306   if (!!strncmp (name, "_OBJC_", 6))
1307     default_globalize_label (stream, name);
1308 }
1309
1310 void
1311 darwin_asm_named_section (const char *name, unsigned int flags ATTRIBUTE_UNUSED)
1312 {
1313   if (flag_reorder_blocks_and_partition)
1314     fprintf (asm_out_file, SECTION_FORMAT_STRING, name);
1315   else
1316     fprintf (asm_out_file, ".section %s\n", name);
1317 }
1318
1319 unsigned int
1320 darwin_section_type_flags (tree decl, const char *name, int reloc)
1321 {
1322   unsigned int flags = default_section_type_flags (decl, name, reloc);
1323  
1324   /* Weak or linkonce variables live in a writable section.  */
1325   if (decl != 0 && TREE_CODE (decl) != FUNCTION_DECL
1326       && (DECL_WEAK (decl) || DECL_ONE_ONLY (decl)))
1327     flags |= SECTION_WRITE;
1328   
1329   return flags;
1330 }              
1331
1332 void 
1333 darwin_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
1334 {
1335   /* Darwin does not use unique sections.  However, the target's
1336      unique_section hook is called for linkonce symbols.  We need
1337      to set an appropriate section for such symbols. */
1338   if (DECL_ONE_ONLY (decl) && !DECL_SECTION_NAME (decl))
1339     darwin_make_decl_one_only (decl);
1340 }
1341
1342 #define HAVE_DEAD_STRIP 0
1343
1344 static void
1345 no_dead_strip (FILE *file, const char *lab)
1346 {
1347   if (HAVE_DEAD_STRIP)
1348     fprintf (file, ".no_dead_strip %s\n", lab);
1349 }
1350
1351 /* Emit a label for an FDE, making it global and/or weak if appropriate. 
1352    The third parameter is nonzero if this is for exception handling.
1353    The fourth parameter is nonzero if this is just a placeholder for an
1354    FDE that we are omitting. */
1355
1356 void 
1357 darwin_emit_unwind_label (FILE *file, tree decl, int for_eh, int empty)
1358 {
1359   tree id = DECL_ASSEMBLER_NAME (decl)
1360     ? DECL_ASSEMBLER_NAME (decl)
1361     : DECL_NAME (decl);
1362
1363   const char *prefix = "_";
1364   const int prefix_len = 1;
1365
1366   const char *base = IDENTIFIER_POINTER (id);
1367   unsigned int base_len = IDENTIFIER_LENGTH (id);
1368
1369   const char *suffix = ".eh";
1370
1371   int need_quotes = name_needs_quotes (base);
1372   int quotes_len = need_quotes ? 2 : 0;
1373   char *lab;
1374
1375   if (! for_eh)
1376     suffix = ".eh1";
1377
1378   lab = xmalloc (prefix_len + base_len + strlen (suffix) + quotes_len + 1);
1379   lab[0] = '\0';
1380
1381   if (need_quotes)
1382     strcat(lab, "\"");
1383   strcat(lab, prefix);
1384   strcat(lab, base);
1385   strcat(lab, suffix);
1386   if (need_quotes)
1387     strcat(lab, "\"");
1388
1389   if (TREE_PUBLIC (decl))
1390     fprintf (file, "%s %s\n",
1391              (DECL_VISIBILITY (decl) != VISIBILITY_HIDDEN
1392               ? ".globl"
1393               : ".private_extern"),
1394              lab);
1395
1396   if (DECL_ONE_ONLY (decl) && TREE_PUBLIC (decl))
1397     fprintf (file, ".weak_definition %s\n", lab);
1398
1399   if (empty)
1400     {
1401       fprintf (file, "%s = 0\n", lab);
1402
1403       /* Mark the absolute .eh and .eh1 style labels as needed to
1404          ensure that we don't dead code strip them and keep such
1405          labels from another instantiation point until we can fix this
1406          properly with group comdat support.  */
1407       no_dead_strip (file, lab);
1408     }
1409   else
1410     fprintf (file, "%s:\n", lab);
1411
1412   free (lab);
1413 }
1414
1415 /* Generate a PC-relative reference to a Mach-O non-lazy-symbol.  */ 
1416
1417 void
1418 darwin_non_lazy_pcrel (FILE *file, rtx addr)
1419 {
1420   const char *str;
1421   const char *nlp_name;
1422
1423   if (GET_CODE (addr) != SYMBOL_REF)
1424     abort ();
1425
1426   str = darwin_strip_name_encoding (XSTR (addr, 0));
1427   nlp_name = machopic_non_lazy_ptr_name (str);
1428   fputs ("\t.long\t", file);
1429   ASM_OUTPUT_LABELREF (file, nlp_name);
1430   fputs ("-.", file);
1431 }
1432
1433 /* Emit an assembler directive to set visibility for a symbol.  The
1434    only supported visibilities are VISIBILITY_DEFAULT and
1435    VISIBILITY_HIDDEN; the latter corresponds to Darwin's "private
1436    extern".  There is no MACH-O equivalent of ELF's
1437    VISIBILITY_INTERNAL or VISIBILITY_PROTECTED. */
1438
1439 void 
1440 darwin_assemble_visibility (tree decl, int vis)
1441 {
1442   if (vis == VISIBILITY_DEFAULT)
1443     ;
1444   else if (vis == VISIBILITY_HIDDEN)
1445     {
1446       fputs ("\t.private_extern ", asm_out_file);
1447       assemble_name (asm_out_file,
1448                      (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
1449       fputs ("\n", asm_out_file);
1450     }
1451   else
1452     warning ("internal and protected visibility attributes not supported"
1453              "in this configuration; ignored");
1454 }
1455
1456 /* Output a difference of two labels that will be an assembly time
1457    constant if the two labels are local.  (.long lab1-lab2 will be
1458    very different if lab1 is at the boundary between two sections; it
1459    will be relocated according to the second section, not the first,
1460    so one ends up with a difference between labels in different
1461    sections, which is bad in the dwarf2 eh context for instance.)  */
1462
1463 static int darwin_dwarf_label_counter;
1464
1465 void
1466 darwin_asm_output_dwarf_delta (FILE *file, int size ATTRIBUTE_UNUSED,
1467                                const char *lab1, const char *lab2)
1468 {
1469   int islocaldiff = (lab1[0] == '*' && lab1[1] == 'L'
1470                      && lab2[0] == '*' && lab2[1] == 'L');
1471
1472   if (islocaldiff)
1473     fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1474   else
1475     fprintf (file, "\t%s\t", ".long");
1476   assemble_name (file, lab1);
1477   fprintf (file, "-");
1478   assemble_name (file, lab2);
1479   if (islocaldiff)
1480     fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1481 }
1482
1483 void
1484 darwin_file_end (void)
1485 {
1486   machopic_finish (asm_out_file);
1487   if (strcmp (lang_hooks.name, "GNU C++") == 0)
1488     {
1489       constructor_section ();
1490       destructor_section ();
1491       ASM_OUTPUT_ALIGN (asm_out_file, 1);
1492     }
1493 }
1494
1495 #include "gt-darwin.h"