OSDN Git Service

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