OSDN Git Service

Enabled linkonce support for Darwin.
[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   const char *current_name;
225   /* if dynamic-no-pic is on, we should not get here */
226   if (MACHO_DYNAMIC_NO_PIC_P)
227     abort ();
228   current_name =
229     IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
230
231   if (function_base == NULL)
232     function_base =
233       (char *) ggc_alloc_string ("<pic base>", sizeof ("<pic base>"));
234
235   current_function_uses_pic_offset_table = 1;
236
237   return function_base;
238 }
239
240 static GTY(()) const char * function_base_func_name;
241 static GTY(()) int current_pic_label_num;
242
243 void
244 machopic_output_function_base_name (FILE *file)
245 {
246   const char *current_name;
247
248   /* If dynamic-no-pic is on, we should not get here.  */
249   if (MACHO_DYNAMIC_NO_PIC_P)
250     abort ();
251   current_name =
252     IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
253   if (function_base_func_name != current_name)
254     {
255       ++current_pic_label_num;
256       function_base_func_name = current_name;
257     }
258   fprintf (file, "\"L%011d$pb\"", current_pic_label_num);
259 }
260
261 static GTY(()) tree machopic_non_lazy_pointers;
262
263 /* Return a non-lazy pointer name corresponding to the given name,
264    either by finding it in our list of pointer names, or by generating
265    a new one.  */
266
267 static const char *
268 machopic_non_lazy_ptr_name (const char *name)
269 {
270   const char *temp_name;
271   tree temp, ident = get_identifier (name);
272
273   for (temp = machopic_non_lazy_pointers;
274        temp != NULL_TREE;
275        temp = TREE_CHAIN (temp))
276     {
277       if (ident == TREE_VALUE (temp))
278         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
279     }
280
281   name = darwin_strip_name_encoding (name);
282
283   /* Try again, but comparing names this time.  */
284   for (temp = machopic_non_lazy_pointers;
285        temp != NULL_TREE;
286        temp = TREE_CHAIN (temp))
287     {
288       if (TREE_VALUE (temp))
289         {
290           temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
291           temp_name = darwin_strip_name_encoding (temp_name);
292           if (strcmp (name, temp_name) == 0)
293             return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
294         }
295     }
296
297   {
298     char *buffer;
299     int namelen = strlen (name);
300     int bufferlen = 0;
301     tree ptr_name;
302
303     buffer = alloca (namelen + strlen("$non_lazy_ptr") + 5);
304
305     strcpy (buffer, "&L");
306     bufferlen = 2;
307     if (name[0] == '*')
308       {
309         memcpy (buffer + bufferlen, name+1, namelen-1+1);
310         bufferlen += namelen-1;
311       }
312     else
313       {
314         buffer[bufferlen] = '_';
315         memcpy (buffer + bufferlen +1, name, namelen+1);
316         bufferlen += namelen +1;
317       }
318
319     memcpy (buffer + bufferlen, "$non_lazy_ptr", strlen("$non_lazy_ptr")+1);
320     bufferlen += strlen("$non_lazy_ptr");
321     ptr_name = get_identifier (buffer);
322
323     machopic_non_lazy_pointers
324       = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
325
326     TREE_USED (machopic_non_lazy_pointers) = 0;
327
328     return IDENTIFIER_POINTER (ptr_name);
329   }
330 }
331
332 static GTY(()) tree machopic_stubs;
333
334 /* Return the name of the stub corresponding to the given name,
335    generating a new stub name if necessary.  */
336
337 const char *
338 machopic_stub_name (const char *name)
339 {
340   tree temp, ident = get_identifier (name);
341   const char *tname;
342
343   for (temp = machopic_stubs;
344        temp != NULL_TREE;
345        temp = TREE_CHAIN (temp))
346     {
347       if (ident == TREE_VALUE (temp))
348         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
349       tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
350       if (strcmp (name, tname) == 0)
351         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
352       /* A library call name might not be section-encoded yet, so try
353          it against a stripped name.  */
354       if (name[0] != '!'
355           && tname[0] == '!'
356           && strcmp (name, tname + 4) == 0)
357         return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
358     }
359
360   name = darwin_strip_name_encoding (name);
361
362   {
363     char *buffer;
364     int bufferlen = 0;
365     int namelen = strlen (name);
366     tree ptr_name;
367     int needs_quotes = name_needs_quotes (name);
368
369     buffer = alloca (namelen + 20);
370
371     if (needs_quotes)
372       {
373         strcpy (buffer, "&\"L");
374         bufferlen = strlen("&\"L");
375       }
376     else
377       {
378         strcpy (buffer, "&L");
379         bufferlen = strlen("&L");
380       }
381     
382     if (name[0] == '*')
383       {
384         memcpy (buffer + bufferlen, name+1, namelen - 1 +1);
385         bufferlen += namelen - 1;
386       }
387     else
388       {
389         buffer[bufferlen] = '_';
390         memcpy (buffer + bufferlen +1, name, namelen+1);
391         bufferlen += namelen +1;
392       }
393
394     if (needs_quotes)
395       {
396         memcpy (buffer + bufferlen, "$stub\"", strlen("$stub\"")+1);
397         bufferlen += strlen("$stub\"");
398       }
399     else
400       {
401         memcpy (buffer + bufferlen, "$stub", strlen("$stub")+1);
402         bufferlen += strlen("$stub");
403       }
404     ptr_name = get_identifier (buffer);
405
406     machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
407     TREE_USED (machopic_stubs) = 0;
408
409     return IDENTIFIER_POINTER (ptr_name);
410   }
411 }
412
413 void
414 machopic_validate_stub_or_non_lazy_ptr (const char *name, int validate_stub)
415 {
416   const char *real_name;
417   tree temp, ident = get_identifier (name), id2;
418
419     for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
420          temp != NULL_TREE;
421          temp = TREE_CHAIN (temp))
422       if (ident == TREE_PURPOSE (temp))
423         {
424           /* Mark both the stub or non-lazy pointer as well as the
425              original symbol as being referenced.  */
426           TREE_USED (temp) = 1;
427           if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
428             mark_referenced (TREE_VALUE (temp));
429           real_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
430           real_name = darwin_strip_name_encoding (real_name);
431           id2 = maybe_get_identifier (real_name);
432           if (id2)
433             mark_referenced (id2);
434         }
435 }
436
437 /* Transform ORIG, which may be any data source, to the corresponding
438    source using indirections.  */
439
440 rtx
441 machopic_indirect_data_reference (rtx orig, rtx reg)
442 {
443   rtx ptr_ref = orig;
444
445   if (! MACHOPIC_INDIRECT)
446     return orig;
447
448   if (GET_CODE (orig) == SYMBOL_REF)
449     {
450       const char *name = XSTR (orig, 0);
451       int defined = machopic_data_defined_p (name);
452
453       if (defined && MACHO_DYNAMIC_NO_PIC_P)
454         {
455 #if defined (TARGET_TOC)
456            emit_insn (gen_macho_high (reg, orig));
457            emit_insn (gen_macho_low (reg, reg, orig));
458 #else
459            /* some other cpu -- writeme!  */
460            abort ();
461 #endif
462            return reg;
463         }
464       else if (defined)
465         {
466 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
467           rtx pic_base = gen_rtx_SYMBOL_REF (Pmode,
468                                              machopic_function_base_name ());
469           rtx offset = gen_rtx_CONST (Pmode,
470                                       gen_rtx_MINUS (Pmode, orig, pic_base));
471 #endif
472
473 #if defined (TARGET_TOC) /* i.e., PowerPC */
474           rtx hi_sum_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
475
476           if (reg == NULL)
477             abort ();
478
479           emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
480                               gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
481                                        gen_rtx_HIGH (Pmode, offset))));
482           emit_insn (gen_rtx_SET (Pmode, reg,
483                                   gen_rtx_LO_SUM (Pmode, hi_sum_reg, offset)));
484
485           orig = reg;
486 #else
487 #if defined (HAVE_lo_sum)
488           if (reg == 0) abort ();
489
490           emit_insn (gen_rtx_SET (VOIDmode, reg,
491                                   gen_rtx_HIGH (Pmode, offset)));
492           emit_insn (gen_rtx_SET (VOIDmode, reg,
493                                   gen_rtx_LO_SUM (Pmode, reg, offset)));
494           emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
495
496           orig = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, reg);
497 #endif
498 #endif
499           return orig;
500         }
501
502       ptr_ref = gen_rtx_SYMBOL_REF (Pmode,
503                                     machopic_non_lazy_ptr_name (name));
504
505       ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
506       RTX_UNCHANGING_P (ptr_ref) = 1;
507
508       return ptr_ref;
509     }
510   else if (GET_CODE (orig) == CONST)
511     {
512       rtx base, result;
513
514       /* legitimize both operands of the PLUS */
515       if (GET_CODE (XEXP (orig, 0)) == PLUS)
516         {
517           base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
518                                                    reg);
519           orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
520                                                    (base == reg ? 0 : reg));
521         }
522       else
523         return orig;
524
525       if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
526         result = plus_constant (base, INTVAL (orig));
527       else
528         result = gen_rtx_PLUS (Pmode, base, orig);
529
530       if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
531         {
532           if (reg)
533             {
534               emit_move_insn (reg, result);
535               result = reg;
536             }
537           else
538             {
539               result = force_reg (GET_MODE (result), result);
540             }
541         }
542
543       return result;
544
545     }
546   else if (GET_CODE (orig) == MEM)
547     XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
548   /* When the target is i386, this code prevents crashes due to the
549      compiler's ignorance on how to move the PIC base register to
550      other registers.  (The reload phase sometimes introduces such
551      insns.)  */
552   else if (GET_CODE (orig) == PLUS
553            && GET_CODE (XEXP (orig, 0)) == REG
554            && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
555 #ifdef I386
556            /* Prevent the same register from being erroneously used
557               as both the base and index registers.  */
558            && GET_CODE (XEXP (orig, 1)) == CONST
559 #endif
560            && reg)
561     {
562       emit_move_insn (reg, XEXP (orig, 0));
563       XEXP (ptr_ref, 0) = reg;
564     }
565   return ptr_ref;
566 }
567
568 /* Transform TARGET (a MEM), which is a function call target, to the
569    corresponding symbol_stub if necessary.  Return a new MEM.  */
570
571 rtx
572 machopic_indirect_call_target (rtx target)
573 {
574   if (GET_CODE (target) != MEM)
575     return target;
576
577   if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
578     {
579       enum machine_mode mode = GET_MODE (XEXP (target, 0));
580       const char *name = XSTR (XEXP (target, 0), 0);
581
582       /* If the name is already defined, we need do nothing.  */
583       if (name[0] == '!' && name[1] == 'T')
584         return target;
585
586       if (!machopic_name_defined_p (name))
587         {
588           const char *stub_name = machopic_stub_name (name);
589
590           XEXP (target, 0) = gen_rtx_SYMBOL_REF (mode, stub_name);
591           RTX_UNCHANGING_P (target) = 1;
592         }
593     }
594
595   return target;
596 }
597
598 rtx
599 machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
600 {
601   rtx pic_ref = orig;
602
603   if (! MACHOPIC_INDIRECT)
604     return orig;
605
606   /* First handle a simple SYMBOL_REF or LABEL_REF */
607   if (GET_CODE (orig) == LABEL_REF
608       || (GET_CODE (orig) == SYMBOL_REF
609           ))
610     {
611       /* addr(foo) = &func+(foo-func) */
612       rtx pic_base;
613
614       orig = machopic_indirect_data_reference (orig, reg);
615
616       if (GET_CODE (orig) == PLUS
617           && GET_CODE (XEXP (orig, 0)) == REG)
618         {
619           if (reg == 0)
620             return force_reg (mode, orig);
621
622           emit_move_insn (reg, orig);
623           return reg;
624         }
625
626       /* if dynamic-no-pic then use 0 as the pic base  */
627       if (MACHO_DYNAMIC_NO_PIC_P)
628         pic_base = CONST0_RTX (Pmode);
629       else
630       pic_base = gen_rtx_SYMBOL_REF (Pmode, machopic_function_base_name ());
631
632       if (GET_CODE (orig) == MEM)
633         {
634           if (reg == 0)
635             {
636               if (reload_in_progress)
637                 abort ();
638               else
639                 reg = gen_reg_rtx (Pmode);
640             }
641
642 #ifdef HAVE_lo_sum
643           if (MACHO_DYNAMIC_NO_PIC_P
644               && (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
645                   || GET_CODE (XEXP (orig, 0)) == LABEL_REF))
646             {
647 #if defined (TARGET_TOC)        /* ppc  */
648               rtx temp_reg = (no_new_pseudos) ? reg : gen_reg_rtx (Pmode);
649               rtx asym = XEXP (orig, 0);
650               rtx mem;
651
652               emit_insn (gen_macho_high (temp_reg, asym));
653               mem = gen_rtx_MEM (GET_MODE (orig),
654                                  gen_rtx_LO_SUM (Pmode, temp_reg, asym));
655               RTX_UNCHANGING_P (mem) = 1;
656               emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
657 #else
658               /* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic  */
659               abort ();
660 #endif
661               pic_ref = reg;
662             }
663           else
664           if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
665               || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
666             {
667               rtx offset = gen_rtx_CONST (Pmode,
668                                           gen_rtx_MINUS (Pmode,
669                                                          XEXP (orig, 0),
670                                                          pic_base));
671 #if defined (TARGET_TOC) /* i.e., PowerPC */
672               /* Generating a new reg may expose opportunities for
673                  common subexpression elimination.  */
674               rtx hi_sum_reg = no_new_pseudos ? reg : gen_reg_rtx (SImode);
675               rtx mem;
676               rtx insn;
677               rtx sum;
678               
679               sum = gen_rtx_HIGH (Pmode, offset);
680               if (! MACHO_DYNAMIC_NO_PIC_P)
681                 sum = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, sum);
682
683               emit_insn (gen_rtx_SET (Pmode, hi_sum_reg, sum));
684
685               mem = gen_rtx_MEM (GET_MODE (orig),
686                                  gen_rtx_LO_SUM (Pmode, 
687                                                  hi_sum_reg, offset));
688               RTX_UNCHANGING_P (mem) = 1;
689               insn = emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
690               REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, pic_ref, 
691                                                     REG_NOTES (insn));
692
693               pic_ref = reg;
694 #else
695               emit_insn (gen_rtx_USE (VOIDmode,
696                                       gen_rtx_REG (Pmode, 
697                                                    PIC_OFFSET_TABLE_REGNUM)));
698
699               emit_insn (gen_rtx_SET (VOIDmode, reg,
700                                       gen_rtx_HIGH (Pmode,
701                                                     gen_rtx_CONST (Pmode, 
702                                                                    offset))));
703               emit_insn (gen_rtx_SET (VOIDmode, reg,
704                                   gen_rtx_LO_SUM (Pmode, reg,
705                                            gen_rtx_CONST (Pmode, offset))));
706               pic_ref = gen_rtx_PLUS (Pmode,
707                                       pic_offset_table_rtx, reg);
708 #endif
709             }
710           else
711 #endif  /* HAVE_lo_sum */
712             {
713               rtx pic = pic_offset_table_rtx;
714               if (GET_CODE (pic) != REG)
715                 {
716                   emit_move_insn (reg, pic);
717                   pic = reg;
718                 }
719 #if 0
720               emit_insn (gen_rtx_USE (VOIDmode,
721                                       gen_rtx_REG (Pmode, 
722                                                    PIC_OFFSET_TABLE_REGNUM)));
723 #endif
724
725               pic_ref = gen_rtx_PLUS (Pmode,
726                                       pic,
727                                       gen_rtx_CONST (Pmode,
728                                           gen_rtx_MINUS (Pmode,
729                                                          XEXP (orig, 0),
730                                                          pic_base)));
731             }
732
733 #if !defined (TARGET_TOC)
734           emit_move_insn (reg, pic_ref);
735           pic_ref = gen_rtx_MEM (GET_MODE (orig), reg);
736 #endif
737           RTX_UNCHANGING_P (pic_ref) = 1;
738         }
739       else
740         {
741
742 #ifdef HAVE_lo_sum
743           if (GET_CODE (orig) == SYMBOL_REF
744               || GET_CODE (orig) == LABEL_REF)
745             {
746               rtx offset = gen_rtx_CONST (Pmode,
747                                           gen_rtx_MINUS (Pmode, 
748                                                          orig, pic_base));
749 #if defined (TARGET_TOC) /* i.e., PowerPC */
750               rtx hi_sum_reg;
751
752               if (reg == 0)
753                 {
754                   if (reload_in_progress)
755                     abort ();
756                   else
757                     reg = gen_reg_rtx (SImode);
758                 }
759
760               hi_sum_reg = reg;
761
762               emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
763                                       (MACHO_DYNAMIC_NO_PIC_P)
764                                       ? gen_rtx_HIGH (Pmode, offset)
765                                       : gen_rtx_PLUS (Pmode,
766                                                       pic_offset_table_rtx,
767                                                       gen_rtx_HIGH (Pmode, 
768                                                                     offset))));
769               emit_insn (gen_rtx_SET (VOIDmode, reg,
770                                       gen_rtx_LO_SUM (Pmode,
771                                                       hi_sum_reg, offset)));
772               pic_ref = reg;
773               RTX_UNCHANGING_P (pic_ref) = 1;
774 #else
775               emit_insn (gen_rtx_SET (VOIDmode, reg,
776                                       gen_rtx_HIGH (Pmode, offset)));
777               emit_insn (gen_rtx_SET (VOIDmode, reg,
778                                       gen_rtx_LO_SUM (Pmode, reg, offset)));
779               pic_ref = gen_rtx_PLUS (Pmode,
780                                       pic_offset_table_rtx, reg);
781               RTX_UNCHANGING_P (pic_ref) = 1;
782 #endif
783             }
784           else
785 #endif  /*  HAVE_lo_sum  */
786             {
787               if (GET_CODE (orig) == REG)
788                 {
789                   return orig;
790                 }
791               else
792                 {
793                   rtx pic = pic_offset_table_rtx;
794                   if (GET_CODE (pic) != REG)
795                     {
796                       emit_move_insn (reg, pic);
797                       pic = reg;
798                     }
799 #if 0
800                   emit_insn (gen_rtx_USE (VOIDmode,
801                                           pic_offset_table_rtx));
802 #endif
803                   pic_ref = gen_rtx_PLUS (Pmode,
804                                           pic,
805                                           gen_rtx_CONST (Pmode,
806                                               gen_rtx_MINUS (Pmode,
807                                                              orig, pic_base)));
808                 }
809             }
810         }
811
812       if (GET_CODE (pic_ref) != REG)
813         {
814           if (reg != 0)
815             {
816               emit_move_insn (reg, pic_ref);
817               return reg;
818             }
819           else
820             {
821               return force_reg (mode, pic_ref);
822             }
823         }
824       else
825         {
826           return pic_ref;
827         }
828     }
829
830   else if (GET_CODE (orig) == SYMBOL_REF)
831     return orig;
832
833   else if (GET_CODE (orig) == PLUS
834            && (GET_CODE (XEXP (orig, 0)) == MEM
835                || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
836                || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
837            && XEXP (orig, 0) != pic_offset_table_rtx
838            && GET_CODE (XEXP (orig, 1)) != REG)
839
840     {
841       rtx base;
842       int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
843
844       base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
845       orig = machopic_legitimize_pic_address (XEXP (orig, 1),
846                                               Pmode, (base == reg ? 0 : reg));
847       if (GET_CODE (orig) == CONST_INT)
848         {
849           pic_ref = plus_constant (base, INTVAL (orig));
850           is_complex = 1;
851         }
852       else
853         pic_ref = gen_rtx_PLUS (Pmode, base, orig);
854
855       if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
856         RTX_UNCHANGING_P (pic_ref) = 1;
857
858       if (reg && is_complex)
859         {
860           emit_move_insn (reg, pic_ref);
861           pic_ref = reg;
862         }
863       /* Likewise, should we set special REG_NOTEs here?  */
864     }
865
866   else if (GET_CODE (orig) == CONST)
867     {
868       return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
869     }
870
871   else if (GET_CODE (orig) == MEM
872            && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
873     {
874       rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
875
876       addr = gen_rtx_MEM (GET_MODE (orig), addr);
877       RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
878       emit_move_insn (reg, addr);
879       pic_ref = reg;
880     }
881
882   return pic_ref;
883 }
884
885
886 void
887 machopic_finish (FILE *asm_out_file)
888 {
889   tree temp;
890
891   for (temp = machopic_stubs;
892        temp != NULL_TREE;
893        temp = TREE_CHAIN (temp))
894     {
895       const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
896       const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
897       char *sym;
898       char *stub;
899
900       if (! TREE_USED (temp))
901         continue;
902
903       sym_name = darwin_strip_name_encoding (sym_name);
904
905       sym = alloca (strlen (sym_name) + 2);
906       if (sym_name[0] == '*' || sym_name[0] == '&')
907         strcpy (sym, sym_name + 1);
908       else if (sym_name[0] == '-' || sym_name[0] == '+')
909         strcpy (sym, sym_name);
910       else
911         sym[0] = '_', strcpy (sym + 1, sym_name);
912
913       stub = alloca (strlen (stub_name) + 2);
914       if (stub_name[0] == '*' || stub_name[0] == '&')
915         strcpy (stub, stub_name + 1);
916       else
917         stub[0] = '_', strcpy (stub + 1, stub_name);
918
919       machopic_output_stub (asm_out_file, sym, stub);
920     }
921
922   for (temp = machopic_non_lazy_pointers;
923        temp != NULL_TREE;
924        temp = TREE_CHAIN (temp))
925     {
926       const char *const sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
927       const char *const lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
928
929       if (! TREE_USED (temp))
930         continue;
931
932       if (machopic_ident_defined_p (TREE_VALUE (temp)))
933         {
934           data_section ();
935           assemble_align (GET_MODE_ALIGNMENT (Pmode));
936           assemble_label (lazy_name);
937           assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
938                             GET_MODE_SIZE (Pmode),
939                             GET_MODE_ALIGNMENT (Pmode), 1);
940         }
941       else
942         {
943           machopic_nl_symbol_ptr_section ();
944           assemble_name (asm_out_file, lazy_name);
945           fprintf (asm_out_file, ":\n");
946
947           fprintf (asm_out_file, "\t.indirect_symbol ");
948           assemble_name (asm_out_file, sym_name);
949           fprintf (asm_out_file, "\n");
950
951           assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
952                             GET_MODE_ALIGNMENT (Pmode), 1);
953         }
954     }
955 }
956
957 int
958 machopic_operand_p (rtx op)
959 {
960   if (MACHOPIC_JUST_INDIRECT)
961     {
962       while (GET_CODE (op) == CONST)
963         op = XEXP (op, 0);
964
965       if (GET_CODE (op) == SYMBOL_REF)
966         return machopic_name_defined_p (XSTR (op, 0));
967       else
968         return 0;
969     }
970
971   while (GET_CODE (op) == CONST)
972     op = XEXP (op, 0);
973
974   if (GET_CODE (op) == MINUS
975       && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
976       && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
977       && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
978       && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
979       return 1;
980
981   return 0;
982 }
983
984 /* This function records whether a given name corresponds to a defined
985    or undefined function or variable, for machopic_classify_ident to
986    use later.  */
987
988 void
989 darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
990 {
991   char code = '\0';
992   int defined = 0;
993   rtx sym_ref;
994   const char *orig_str;
995   char *new_str;
996   size_t len, new_len;
997
998   /* Do the standard encoding things first.  */
999   default_encode_section_info (decl, rtl, first);
1000
1001   /* With the introduction of symbol_ref flags, some of the following
1002      code has become redundant and should be removed at some point.  */
1003
1004   if ((TREE_CODE (decl) == FUNCTION_DECL
1005        || TREE_CODE (decl) == VAR_DECL)
1006       && !DECL_EXTERNAL (decl)
1007       && (!TREE_PUBLIC (decl) || (!DECL_ONE_ONLY (decl) && !DECL_WEAK (decl)))
1008       && ((TREE_STATIC (decl)
1009            && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
1010           || (DECL_INITIAL (decl)
1011               && DECL_INITIAL (decl) != error_mark_node)))
1012     defined = 1;
1013
1014   if (TREE_CODE (decl) == FUNCTION_DECL)
1015     code = (defined ? 'T' : 't');
1016   else if (TREE_CODE (decl) == VAR_DECL)
1017     code = (defined ? 'D' : 'd');
1018
1019   if (code == '\0')
1020     return;
1021
1022   sym_ref = XEXP (rtl, 0);
1023   orig_str = XSTR (sym_ref, 0);
1024   len = strlen (orig_str) + 1;
1025
1026   if (orig_str[0] == '!')
1027     {
1028       /* Already encoded; see if we need to change it.  */
1029       if (code == orig_str[1])
1030         return;
1031       /* Yes, tweak a copy of the name and put it in a new string.  */
1032       new_str = alloca (len);
1033       memcpy (new_str, orig_str, len);
1034       new_str[1] = code;
1035       XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
1036     }
1037   else
1038     {
1039       /* Add the encoding.  */
1040       new_len = len + 4;
1041       new_str = alloca (new_len);
1042       new_str[0] = '!';
1043       new_str[1] = code;
1044       new_str[2] = '_';
1045       new_str[3] = '_';
1046       memcpy (new_str + 4, orig_str, len);
1047       XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
1048     }
1049   /* The non-lazy pointer list may have captured references to the
1050      old encoded name, change them.  */
1051   if (TREE_CODE (decl) == VAR_DECL)
1052     update_non_lazy_ptrs (XSTR (sym_ref, 0));
1053   else
1054     update_stubs (XSTR (sym_ref, 0));
1055 }
1056
1057 /* Undo the effects of the above.  */
1058
1059 const char *
1060 darwin_strip_name_encoding (const char *str)
1061 {
1062   return str[0] == '!' ? str + 4 : str;
1063 }
1064
1065 /* Scan the list of non-lazy pointers and update any recorded names whose
1066    stripped name matches the argument.  */
1067
1068 static void
1069 update_non_lazy_ptrs (const char *name)
1070 {
1071   const char *name1, *name2;
1072   tree temp;
1073
1074   name1 = darwin_strip_name_encoding (name);
1075
1076   for (temp = machopic_non_lazy_pointers;
1077        temp != NULL_TREE;
1078        temp = TREE_CHAIN (temp))
1079     {
1080       const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1081
1082       if (*sym_name == '!')
1083         {
1084           name2 = darwin_strip_name_encoding (sym_name);
1085           if (strcmp (name1, name2) == 0)
1086             {
1087               /* FIXME: This breaks the identifier hash table.  */
1088               IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1089                 = (unsigned char *) name;
1090               break;
1091             }
1092         }
1093     }
1094 }
1095
1096 /* Scan the list of stubs and update any recorded names whose
1097    stripped name matches the argument.  */
1098
1099 static void
1100 update_stubs (const char *name)
1101 {
1102   const char *name1, *name2;
1103   tree temp;
1104
1105   name1 = darwin_strip_name_encoding (name);
1106
1107   for (temp = machopic_stubs;
1108        temp != NULL_TREE;
1109        temp = TREE_CHAIN (temp))
1110     {
1111       const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1112
1113       if (*sym_name == '!')
1114         {
1115           name2 = darwin_strip_name_encoding (sym_name);
1116           if (strcmp (name1, name2) == 0)
1117             {
1118               /* FIXME: This breaks the identifier hash table.  */
1119               IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1120                 = (unsigned char *) name;
1121               break;
1122             }
1123         }
1124     }
1125 }
1126
1127 void
1128 darwin_make_decl_one_only (tree decl)
1129 {
1130   static const char *text_section = "__TEXT,__textcoal_nt,coalesced,no_toc";
1131   static const char *data_section = "__DATA,__datacoal_nt,coalesced,no_toc";
1132
1133   const char *sec = TREE_CODE (decl) == FUNCTION_DECL
1134     ? text_section
1135     : data_section;
1136   TREE_PUBLIC (decl) = 1;
1137   DECL_ONE_ONLY (decl) = 1;
1138   DECL_SECTION_NAME (decl) = build_string (strlen (sec), sec);
1139 }
1140
1141 void
1142 machopic_select_section (tree exp, int reloc,
1143                          unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1144 {
1145   void (*base_function)(void);
1146
1147   if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
1148     base_function = readonly_data_section;
1149   else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1150     base_function = const_data_section;
1151   else
1152     base_function = data_section;
1153
1154   if (TREE_CODE (exp) == STRING_CST
1155       && ((size_t) TREE_STRING_LENGTH (exp)
1156           == strlen (TREE_STRING_POINTER (exp)) + 1))
1157     cstring_section ();
1158   else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
1159            && flag_merge_constants)
1160     {
1161       tree size = TYPE_SIZE (TREE_TYPE (exp));
1162
1163       if (TREE_CODE (size) == INTEGER_CST &&
1164           TREE_INT_CST_LOW (size) == 4 &&
1165           TREE_INT_CST_HIGH (size) == 0)
1166         literal4_section ();
1167       else if (TREE_CODE (size) == INTEGER_CST &&
1168                TREE_INT_CST_LOW (size) == 8 &&
1169                TREE_INT_CST_HIGH (size) == 0)
1170         literal8_section ();
1171       else
1172         base_function ();
1173     }
1174   else if (TREE_CODE (exp) == CONSTRUCTOR
1175            && TREE_TYPE (exp)
1176            && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1177            && TYPE_NAME (TREE_TYPE (exp)))
1178     {
1179       tree name = TYPE_NAME (TREE_TYPE (exp));
1180       if (TREE_CODE (name) == TYPE_DECL)
1181         name = DECL_NAME (name);
1182       if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1183         objc_constant_string_object_section ();
1184       else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1185         objc_string_object_section ();
1186       else
1187         base_function ();
1188     }
1189   else if (TREE_CODE (exp) == VAR_DECL &&
1190            DECL_NAME (exp) &&
1191            TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1192            IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1193            !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1194     {
1195       const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1196
1197       if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1198         objc_cls_meth_section ();
1199       else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1200         objc_inst_meth_section ();
1201       else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1202         objc_cat_cls_meth_section ();
1203       else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1204         objc_cat_inst_meth_section ();
1205       else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1206         objc_class_vars_section ();
1207       else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1208         objc_instance_vars_section ();
1209       else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1210         objc_cat_cls_meth_section ();
1211       else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1212         objc_class_names_section ();
1213       else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1214         objc_meth_var_names_section ();
1215       else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1216         objc_meth_var_types_section ();
1217       else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1218         objc_cls_refs_section ();
1219       else if (!strncmp (name, "_OBJC_CLASS_", 12))
1220         objc_class_section ();
1221       else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1222         objc_meta_class_section ();
1223       else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1224         objc_category_section ();
1225       else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1226         objc_selector_refs_section ();
1227       else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1228         objc_selector_fixup_section ();
1229       else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1230         objc_symbols_section ();
1231       else if (!strncmp (name, "_OBJC_MODULES", 13))
1232         objc_module_info_section ();
1233       else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
1234         objc_image_info_section ();
1235       else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1236         objc_cat_inst_meth_section ();
1237       else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1238         objc_cat_cls_meth_section ();
1239       else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1240         objc_cat_cls_meth_section ();
1241       else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1242         objc_protocol_section ();
1243       else
1244         base_function ();
1245     }
1246   else
1247     base_function ();
1248 }
1249
1250 /* This can be called with address expressions as "rtx".
1251    They must go in "const".  */
1252
1253 void
1254 machopic_select_rtx_section (enum machine_mode mode, rtx x,
1255                              unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1256 {
1257   if (GET_MODE_SIZE (mode) == 8)
1258     literal8_section ();
1259   else if (GET_MODE_SIZE (mode) == 4
1260            && (GET_CODE (x) == CONST_INT
1261                || GET_CODE (x) == CONST_DOUBLE))
1262     literal4_section ();
1263   else if (MACHOPIC_INDIRECT
1264            && (GET_CODE (x) == SYMBOL_REF
1265                || GET_CODE (x) == CONST
1266                || GET_CODE (x) == LABEL_REF))
1267     const_data_section ();
1268   else
1269     const_section ();
1270 }
1271
1272 void
1273 machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1274 {
1275   if (MACHOPIC_INDIRECT)
1276     mod_init_section ();
1277   else
1278     constructor_section ();
1279   assemble_align (POINTER_SIZE);
1280   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1281
1282   if (! MACHOPIC_INDIRECT)
1283     fprintf (asm_out_file, ".reference .constructors_used\n");
1284 }
1285
1286 void
1287 machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1288 {
1289   if (MACHOPIC_INDIRECT)
1290     mod_term_section ();
1291   else
1292     destructor_section ();
1293   assemble_align (POINTER_SIZE);
1294   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1295
1296   if (! MACHOPIC_INDIRECT)
1297     fprintf (asm_out_file, ".reference .destructors_used\n");
1298 }
1299
1300 void
1301 darwin_globalize_label (FILE *stream, const char *name)
1302 {
1303   if (!!strncmp (name, "_OBJC_", 6))
1304     default_globalize_label (stream, name);
1305 }
1306
1307 void
1308 darwin_asm_named_section (const char *name, unsigned int flags ATTRIBUTE_UNUSED)
1309 {
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"