OSDN Git Service

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