OSDN Git Service

* config/darwin.c, config/darwin.h, config/freebsd-spec.h,
[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 #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       /* If the symbol is actually defined, we don't need a stub.  */
904       if (sym_name[0] == '!' && sym_name[1] == 'T')
905         continue;
906
907       sym_name = darwin_strip_name_encoding (sym_name);
908
909       sym = alloca (strlen (sym_name) + 2);
910       if (sym_name[0] == '*' || sym_name[0] == '&')
911         strcpy (sym, sym_name + 1);
912       else if (sym_name[0] == '-' || sym_name[0] == '+')
913         strcpy (sym, sym_name);
914       else
915         sym[0] = '_', strcpy (sym + 1, sym_name);
916
917       stub = alloca (strlen (stub_name) + 2);
918       if (stub_name[0] == '*' || stub_name[0] == '&')
919         strcpy (stub, stub_name + 1);
920       else
921         stub[0] = '_', strcpy (stub + 1, stub_name);
922
923       machopic_output_stub (asm_out_file, sym, stub);
924     }
925
926   for (temp = machopic_non_lazy_pointers;
927        temp != NULL_TREE;
928        temp = TREE_CHAIN (temp))
929     {
930       const char *const sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
931       const char *const lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
932
933       if (! TREE_USED (temp))
934         continue;
935
936       if (machopic_ident_defined_p (TREE_VALUE (temp)))
937         {
938           data_section ();
939           assemble_align (GET_MODE_ALIGNMENT (Pmode));
940           assemble_label (lazy_name);
941           assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
942                             GET_MODE_SIZE (Pmode),
943                             GET_MODE_ALIGNMENT (Pmode), 1);
944         }
945       else
946         {
947           machopic_nl_symbol_ptr_section ();
948           assemble_name (asm_out_file, lazy_name);
949           fprintf (asm_out_file, ":\n");
950
951           fprintf (asm_out_file, "\t.indirect_symbol ");
952           assemble_name (asm_out_file, sym_name);
953           fprintf (asm_out_file, "\n");
954
955           assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
956                             GET_MODE_ALIGNMENT (Pmode), 1);
957         }
958     }
959 }
960
961 int
962 machopic_operand_p (rtx op)
963 {
964   if (MACHOPIC_JUST_INDIRECT)
965     {
966       while (GET_CODE (op) == CONST)
967         op = XEXP (op, 0);
968
969       if (GET_CODE (op) == SYMBOL_REF)
970         return machopic_name_defined_p (XSTR (op, 0));
971       else
972         return 0;
973     }
974
975   while (GET_CODE (op) == CONST)
976     op = XEXP (op, 0);
977
978   if (GET_CODE (op) == MINUS
979       && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
980       && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
981       && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
982       && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
983       return 1;
984
985   return 0;
986 }
987
988 /* This function records whether a given name corresponds to a defined
989    or undefined function or variable, for machopic_classify_ident to
990    use later.  */
991
992 void
993 darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
994 {
995   char code = '\0';
996   int defined = 0;
997   rtx sym_ref;
998   const char *orig_str;
999   char *new_str;
1000   size_t len, new_len;
1001
1002   /* Do the standard encoding things first.  */
1003   default_encode_section_info (decl, rtl, first);
1004
1005   /* With the introduction of symbol_ref flags, some of the following
1006      code has become redundant and should be removed at some point.  */
1007
1008   if ((TREE_CODE (decl) == FUNCTION_DECL
1009        || TREE_CODE (decl) == VAR_DECL)
1010       && !DECL_EXTERNAL (decl)
1011       && ((TREE_STATIC (decl)
1012            && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
1013           || (DECL_INITIAL (decl)
1014               && DECL_INITIAL (decl) != error_mark_node)))
1015     defined = 1;
1016
1017   if (TREE_CODE (decl) == FUNCTION_DECL)
1018     code = (defined ? 'T' : 't');
1019   else if (TREE_CODE (decl) == VAR_DECL)
1020     code = (defined ? 'D' : 'd');
1021
1022   if (code == '\0')
1023     return;
1024
1025   sym_ref = XEXP (rtl, 0);
1026   orig_str = XSTR (sym_ref, 0);
1027   len = strlen (orig_str) + 1;
1028
1029   if (orig_str[0] == '!')
1030     {
1031       /* Already encoded; see if we need to change it.  */
1032       if (code == orig_str[1])
1033         return;
1034       /* Yes, tweak a copy of the name and put it in a new string.  */
1035       new_str = alloca (len);
1036       memcpy (new_str, orig_str, len);
1037       new_str[1] = code;
1038       XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
1039     }
1040   else
1041     {
1042       /* Add the encoding.  */
1043       new_len = len + 4;
1044       new_str = alloca (new_len);
1045       new_str[0] = '!';
1046       new_str[1] = code;
1047       new_str[2] = '_';
1048       new_str[3] = '_';
1049       memcpy (new_str + 4, orig_str, len);
1050       XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
1051     }
1052   /* The non-lazy pointer list may have captured references to the
1053      old encoded name, change them.  */
1054   if (TREE_CODE (decl) == VAR_DECL)
1055     update_non_lazy_ptrs (XSTR (sym_ref, 0));
1056   else
1057     update_stubs (XSTR (sym_ref, 0));
1058 }
1059
1060 /* Undo the effects of the above.  */
1061
1062 const char *
1063 darwin_strip_name_encoding (const char *str)
1064 {
1065   return str[0] == '!' ? str + 4 : str;
1066 }
1067
1068 /* Scan the list of non-lazy pointers and update any recorded names whose
1069    stripped name matches the argument.  */
1070
1071 static void
1072 update_non_lazy_ptrs (const char *name)
1073 {
1074   const char *name1, *name2;
1075   tree temp;
1076
1077   name1 = darwin_strip_name_encoding (name);
1078
1079   for (temp = machopic_non_lazy_pointers;
1080        temp != NULL_TREE;
1081        temp = TREE_CHAIN (temp))
1082     {
1083       const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1084
1085       if (*sym_name == '!')
1086         {
1087           name2 = darwin_strip_name_encoding (sym_name);
1088           if (strcmp (name1, name2) == 0)
1089             {
1090               /* FIXME: This breaks the identifier hash table.  */
1091               IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1092                 = (unsigned char *) name;
1093               break;
1094             }
1095         }
1096     }
1097 }
1098
1099 /* Function NAME is being defined, and its label has just been output.
1100    If there's already a reference to a stub for this function, we can
1101    just emit the stub label now and we don't bother emitting the stub later.  */
1102
1103 void
1104 machopic_output_possible_stub_label (FILE *file, const char *name)
1105 {
1106   tree temp;
1107
1108   /* Ensure we're looking at a section-encoded name.  */
1109   if (name[0] != '!' || (name[1] != 't' && name[1] != 'T'))
1110     return;
1111
1112   for (temp = machopic_stubs;
1113        temp != NULL_TREE;
1114        temp = TREE_CHAIN (temp))
1115     {
1116       const char *sym_name;
1117
1118       sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1119       if (sym_name[0] == '!' && (sym_name[1] == 'T' || sym_name[1] == 't')
1120           && ! strcmp (name+2, sym_name+2))
1121         {
1122           ASM_OUTPUT_LABEL (file, IDENTIFIER_POINTER (TREE_PURPOSE (temp)));
1123           /* Avoid generating a stub for this.  */
1124           TREE_USED (temp) = 0;
1125           break;
1126         }
1127     }
1128 }
1129
1130 /* Scan the list of stubs and update any recorded names whose
1131    stripped name matches the argument.  */
1132
1133 static void
1134 update_stubs (const char *name)
1135 {
1136   const char *name1, *name2;
1137   tree temp;
1138
1139   name1 = darwin_strip_name_encoding (name);
1140
1141   for (temp = machopic_stubs;
1142        temp != NULL_TREE;
1143        temp = TREE_CHAIN (temp))
1144     {
1145       const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1146
1147       if (*sym_name == '!')
1148         {
1149           name2 = darwin_strip_name_encoding (sym_name);
1150           if (strcmp (name1, name2) == 0)
1151             {
1152               /* FIXME: This breaks the identifier hash table.  */
1153               IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1154                 = (unsigned char *) name;
1155               break;
1156             }
1157         }
1158     }
1159 }
1160
1161 void
1162 machopic_select_section (tree exp, int reloc,
1163                          unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1164 {
1165   void (*base_function)(void);
1166
1167   if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
1168     base_function = readonly_data_section;
1169   else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1170     base_function = const_data_section;
1171   else
1172     base_function = data_section;
1173
1174   if (TREE_CODE (exp) == STRING_CST
1175       && ((size_t) TREE_STRING_LENGTH (exp)
1176           == strlen (TREE_STRING_POINTER (exp)) + 1)
1177       && ! flag_writable_strings)
1178     cstring_section ();
1179   else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
1180            && flag_merge_constants)
1181     {
1182       tree size = TYPE_SIZE (TREE_TYPE (exp));
1183
1184       if (TREE_CODE (size) == INTEGER_CST &&
1185           TREE_INT_CST_LOW (size) == 4 &&
1186           TREE_INT_CST_HIGH (size) == 0)
1187         literal4_section ();
1188       else if (TREE_CODE (size) == INTEGER_CST &&
1189                TREE_INT_CST_LOW (size) == 8 &&
1190                TREE_INT_CST_HIGH (size) == 0)
1191         literal8_section ();
1192       else
1193         base_function ();
1194     }
1195   else if (TREE_CODE (exp) == CONSTRUCTOR
1196            && TREE_TYPE (exp)
1197            && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1198            && TYPE_NAME (TREE_TYPE (exp)))
1199     {
1200       tree name = TYPE_NAME (TREE_TYPE (exp));
1201       if (TREE_CODE (name) == TYPE_DECL)
1202         name = DECL_NAME (name);
1203       if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1204         objc_constant_string_object_section ();
1205       else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1206         objc_string_object_section ();
1207       else
1208         base_function ();
1209     }
1210   else if (TREE_CODE (exp) == VAR_DECL &&
1211            DECL_NAME (exp) &&
1212            TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1213            IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1214            !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1215     {
1216       const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1217
1218       if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1219         objc_cls_meth_section ();
1220       else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1221         objc_inst_meth_section ();
1222       else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1223         objc_cat_cls_meth_section ();
1224       else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1225         objc_cat_inst_meth_section ();
1226       else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1227         objc_class_vars_section ();
1228       else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1229         objc_instance_vars_section ();
1230       else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1231         objc_cat_cls_meth_section ();
1232       else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1233         objc_class_names_section ();
1234       else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1235         objc_meth_var_names_section ();
1236       else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1237         objc_meth_var_types_section ();
1238       else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1239         objc_cls_refs_section ();
1240       else if (!strncmp (name, "_OBJC_CLASS_", 12))
1241         objc_class_section ();
1242       else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1243         objc_meta_class_section ();
1244       else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1245         objc_category_section ();
1246       else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1247         objc_selector_refs_section ();
1248       else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1249         objc_selector_fixup_section ();
1250       else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1251         objc_symbols_section ();
1252       else if (!strncmp (name, "_OBJC_MODULES", 13))
1253         objc_module_info_section ();
1254       else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
1255         objc_image_info_section ();
1256       else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1257         objc_cat_inst_meth_section ();
1258       else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1259         objc_cat_cls_meth_section ();
1260       else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1261         objc_cat_cls_meth_section ();
1262       else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1263         objc_protocol_section ();
1264       else
1265         base_function ();
1266     }
1267   else
1268     base_function ();
1269 }
1270
1271 /* This can be called with address expressions as "rtx".
1272    They must go in "const".  */
1273
1274 void
1275 machopic_select_rtx_section (enum machine_mode mode, rtx x,
1276                              unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1277 {
1278   if (GET_MODE_SIZE (mode) == 8)
1279     literal8_section ();
1280   else if (GET_MODE_SIZE (mode) == 4
1281            && (GET_CODE (x) == CONST_INT
1282                || GET_CODE (x) == CONST_DOUBLE))
1283     literal4_section ();
1284   else if (MACHOPIC_INDIRECT
1285            && (GET_CODE (x) == SYMBOL_REF
1286                || GET_CODE (x) == CONST
1287                || GET_CODE (x) == LABEL_REF))
1288     const_data_section ();
1289   else
1290     const_section ();
1291 }
1292
1293 void
1294 machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1295 {
1296   if (MACHOPIC_INDIRECT)
1297     mod_init_section ();
1298   else
1299     constructor_section ();
1300   assemble_align (POINTER_SIZE);
1301   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1302
1303   if (! MACHOPIC_INDIRECT)
1304     fprintf (asm_out_file, ".reference .constructors_used\n");
1305 }
1306
1307 void
1308 machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1309 {
1310   if (MACHOPIC_INDIRECT)
1311     mod_term_section ();
1312   else
1313     destructor_section ();
1314   assemble_align (POINTER_SIZE);
1315   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1316
1317   if (! MACHOPIC_INDIRECT)
1318     fprintf (asm_out_file, ".reference .destructors_used\n");
1319 }
1320
1321 void
1322 darwin_globalize_label (FILE *stream, const char *name)
1323 {
1324   if (!!strncmp (name, "_OBJC_", 6))
1325     default_globalize_label (stream, name);
1326 }
1327
1328 /* Emit an assembler directive to set visibility for a symbol.  The
1329    only supported visibilities are VISIBILITY_DEFAULT and
1330    VISIBILITY_HIDDEN; the latter corresponds to Darwin's "private
1331    extern".  There is no MACH-O equivalent of ELF's
1332    VISIBILITY_INTERNAL or VISIBILITY_PROTECTED. */
1333
1334 void 
1335 darwin_assemble_visibility (tree decl, int vis)
1336 {
1337   if (vis == VISIBILITY_DEFAULT)
1338     ;
1339   else if (vis == VISIBILITY_HIDDEN)
1340     {
1341       fputs ("\t.private_extern ", asm_out_file);
1342       assemble_name (asm_out_file,
1343                      (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
1344       fputs ("\n", asm_out_file);
1345     }
1346   else
1347     warning ("internal and protected visibility attributes not supported"
1348              "in this configuration; ignored");
1349 }
1350
1351 /* Output a difference of two labels that will be an assembly time
1352    constant if the two labels are local.  (.long lab1-lab2 will be
1353    very different if lab1 is at the boundary between two sections; it
1354    will be relocated according to the second section, not the first,
1355    so one ends up with a difference between labels in different
1356    sections, which is bad in the dwarf2 eh context for instance.)  */
1357
1358 static int darwin_dwarf_label_counter;
1359
1360 void
1361 darwin_asm_output_dwarf_delta (FILE *file, int size ATTRIBUTE_UNUSED,
1362                                const char *lab1, const char *lab2)
1363 {
1364   const char *p = lab1 + (lab1[0] == '*');
1365   int islocaldiff = (p[0] == 'L');
1366
1367   if (islocaldiff)
1368     fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1369   else
1370     fprintf (file, "\t%s\t", ".long");
1371   assemble_name (file, lab1);
1372   fprintf (file, "-");
1373   assemble_name (file, lab2);
1374   if (islocaldiff)
1375     fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1376 }
1377
1378 void
1379 darwin_file_end (void)
1380 {
1381   machopic_finish (asm_out_file);
1382   if (strcmp (lang_hooks.name, "GNU C++") == 0)
1383     {
1384       constructor_section ();
1385       destructor_section ();
1386       ASM_OUTPUT_ALIGN (asm_out_file, 1);
1387     }
1388 }
1389
1390 #include "gt-darwin.h"