OSDN Git Service

978fdde7e49966c6ab40e0a62548ba1bcda41f3c
[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       /* 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     cstring_section ();
1178   else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
1179            && flag_merge_constants)
1180     {
1181       tree size = TYPE_SIZE (TREE_TYPE (exp));
1182
1183       if (TREE_CODE (size) == INTEGER_CST &&
1184           TREE_INT_CST_LOW (size) == 4 &&
1185           TREE_INT_CST_HIGH (size) == 0)
1186         literal4_section ();
1187       else if (TREE_CODE (size) == INTEGER_CST &&
1188                TREE_INT_CST_LOW (size) == 8 &&
1189                TREE_INT_CST_HIGH (size) == 0)
1190         literal8_section ();
1191       else
1192         base_function ();
1193     }
1194   else if (TREE_CODE (exp) == CONSTRUCTOR
1195            && TREE_TYPE (exp)
1196            && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1197            && TYPE_NAME (TREE_TYPE (exp)))
1198     {
1199       tree name = TYPE_NAME (TREE_TYPE (exp));
1200       if (TREE_CODE (name) == TYPE_DECL)
1201         name = DECL_NAME (name);
1202       if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1203         objc_constant_string_object_section ();
1204       else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1205         objc_string_object_section ();
1206       else
1207         base_function ();
1208     }
1209   else if (TREE_CODE (exp) == VAR_DECL &&
1210            DECL_NAME (exp) &&
1211            TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1212            IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1213            !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1214     {
1215       const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1216
1217       if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1218         objc_cls_meth_section ();
1219       else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1220         objc_inst_meth_section ();
1221       else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1222         objc_cat_cls_meth_section ();
1223       else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1224         objc_cat_inst_meth_section ();
1225       else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1226         objc_class_vars_section ();
1227       else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1228         objc_instance_vars_section ();
1229       else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1230         objc_cat_cls_meth_section ();
1231       else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1232         objc_class_names_section ();
1233       else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1234         objc_meth_var_names_section ();
1235       else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1236         objc_meth_var_types_section ();
1237       else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1238         objc_cls_refs_section ();
1239       else if (!strncmp (name, "_OBJC_CLASS_", 12))
1240         objc_class_section ();
1241       else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1242         objc_meta_class_section ();
1243       else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1244         objc_category_section ();
1245       else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1246         objc_selector_refs_section ();
1247       else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1248         objc_selector_fixup_section ();
1249       else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1250         objc_symbols_section ();
1251       else if (!strncmp (name, "_OBJC_MODULES", 13))
1252         objc_module_info_section ();
1253       else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
1254         objc_image_info_section ();
1255       else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1256         objc_cat_inst_meth_section ();
1257       else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1258         objc_cat_cls_meth_section ();
1259       else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1260         objc_cat_cls_meth_section ();
1261       else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1262         objc_protocol_section ();
1263       else
1264         base_function ();
1265     }
1266   else
1267     base_function ();
1268 }
1269
1270 /* This can be called with address expressions as "rtx".
1271    They must go in "const".  */
1272
1273 void
1274 machopic_select_rtx_section (enum machine_mode mode, rtx x,
1275                              unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1276 {
1277   if (GET_MODE_SIZE (mode) == 8)
1278     literal8_section ();
1279   else if (GET_MODE_SIZE (mode) == 4
1280            && (GET_CODE (x) == CONST_INT
1281                || GET_CODE (x) == CONST_DOUBLE))
1282     literal4_section ();
1283   else if (MACHOPIC_INDIRECT
1284            && (GET_CODE (x) == SYMBOL_REF
1285                || GET_CODE (x) == CONST
1286                || GET_CODE (x) == LABEL_REF))
1287     const_data_section ();
1288   else
1289     const_section ();
1290 }
1291
1292 void
1293 machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1294 {
1295   if (MACHOPIC_INDIRECT)
1296     mod_init_section ();
1297   else
1298     constructor_section ();
1299   assemble_align (POINTER_SIZE);
1300   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1301
1302   if (! MACHOPIC_INDIRECT)
1303     fprintf (asm_out_file, ".reference .constructors_used\n");
1304 }
1305
1306 void
1307 machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1308 {
1309   if (MACHOPIC_INDIRECT)
1310     mod_term_section ();
1311   else
1312     destructor_section ();
1313   assemble_align (POINTER_SIZE);
1314   assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1315
1316   if (! MACHOPIC_INDIRECT)
1317     fprintf (asm_out_file, ".reference .destructors_used\n");
1318 }
1319
1320 void
1321 darwin_globalize_label (FILE *stream, const char *name)
1322 {
1323   if (!!strncmp (name, "_OBJC_", 6))
1324     default_globalize_label (stream, name);
1325 }
1326
1327 /* Emit an assembler directive to set visibility for a symbol.  The
1328    only supported visibilities are VISIBILITY_DEFAULT and
1329    VISIBILITY_HIDDEN; the latter corresponds to Darwin's "private
1330    extern".  There is no MACH-O equivalent of ELF's
1331    VISIBILITY_INTERNAL or VISIBILITY_PROTECTED. */
1332
1333 void 
1334 darwin_assemble_visibility (tree decl, int vis)
1335 {
1336   if (vis == VISIBILITY_DEFAULT)
1337     ;
1338   else if (vis == VISIBILITY_HIDDEN)
1339     {
1340       fputs ("\t.private_extern ", asm_out_file);
1341       assemble_name (asm_out_file,
1342                      (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
1343       fputs ("\n", asm_out_file);
1344     }
1345   else
1346     warning ("internal and protected visibility attributes not supported"
1347              "in this configuration; ignored");
1348 }
1349
1350 /* Output a difference of two labels that will be an assembly time
1351    constant if the two labels are local.  (.long lab1-lab2 will be
1352    very different if lab1 is at the boundary between two sections; it
1353    will be relocated according to the second section, not the first,
1354    so one ends up with a difference between labels in different
1355    sections, which is bad in the dwarf2 eh context for instance.)  */
1356
1357 static int darwin_dwarf_label_counter;
1358
1359 void
1360 darwin_asm_output_dwarf_delta (FILE *file, int size ATTRIBUTE_UNUSED,
1361                                const char *lab1, const char *lab2)
1362 {
1363   const char *p = lab1 + (lab1[0] == '*');
1364   int islocaldiff = (p[0] == 'L');
1365
1366   if (islocaldiff)
1367     fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1368   else
1369     fprintf (file, "\t%s\t", ".long");
1370   assemble_name (file, lab1);
1371   fprintf (file, "-");
1372   assemble_name (file, lab2);
1373   if (islocaldiff)
1374     fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1375 }
1376
1377 void
1378 darwin_file_end (void)
1379 {
1380   machopic_finish (asm_out_file);
1381   if (strcmp (lang_hooks.name, "GNU C++") == 0)
1382     {
1383       constructor_section ();
1384       destructor_section ();
1385       ASM_OUTPUT_ALIGN (asm_out_file, 1);
1386     }
1387 }
1388
1389 #include "gt-darwin.h"