OSDN Git Service

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