OSDN Git Service

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