* config/ia64/ia64.md: Define new attribute "empty".
[official-gcc.git] / gcc / config / darwin.c
blob63c75df7c8e3af8c4a9f260d62940a1a97126133
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.
6 This file is part of GCC.
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.
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.
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. */
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"
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*);
51 int
52 name_needs_quotes (const char *name)
54 int c;
55 while ((c = *name++) != '\0')
56 if (! ISIDNUM (c) && c != '.' && c != '$')
57 return 1;
58 return 0;
62 * flag_pic = 1 ... generate only indirections
63 * flag_pic = 2 ... generate indirections and pure code
66 /* This module assumes that (const (symbol_ref "foo")) is a legal pic
67 reference, which will not be changed. */
69 static GTY(()) tree machopic_defined_list;
71 enum machopic_addr_class
72 machopic_classify_ident (tree ident)
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;
85 /* The PIC base symbol is always defined. */
86 if (! strcmp (name, "<pic base>"))
87 return MACHOPIC_DEFINED_DATA;
89 if (name[0] != '!')
91 /* Here if no special encoding to be found. */
92 if (lprefix)
94 const char *name = IDENTIFIER_POINTER (ident);
95 int len = strlen (name);
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;
103 for (temp = machopic_defined_list;
104 temp != NULL_TREE;
105 temp = TREE_CHAIN (temp))
107 if (ident == TREE_VALUE (temp))
108 return MACHOPIC_DEFINED_DATA;
111 if (TREE_ASM_WRITTEN (ident))
112 return MACHOPIC_DEFINED_DATA;
114 return MACHOPIC_UNDEFINED;
117 else if (name[1] == 'D')
118 return MACHOPIC_DEFINED_DATA;
120 else if (name[1] == 'T')
121 return MACHOPIC_DEFINED_FUNCTION;
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')
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;
139 for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp))
141 if (ident == TREE_VALUE (temp))
143 if (name[1] == 'T')
144 return MACHOPIC_DEFINED_FUNCTION;
145 else
146 return MACHOPIC_DEFINED_DATA;
150 if (name[1] == 't' || name[1] == 'T')
152 if (lprefix)
153 return MACHOPIC_DEFINED_FUNCTION;
154 else
155 return MACHOPIC_UNDEFINED_FUNCTION;
157 else
159 if (lprefix)
160 return MACHOPIC_DEFINED_DATA;
161 else
162 return MACHOPIC_UNDEFINED_DATA;
167 enum machopic_addr_class
168 machopic_classify_name (const char *name)
170 return machopic_classify_ident (get_identifier (name));
174 machopic_ident_defined_p (tree ident)
176 switch (machopic_classify_ident (ident))
178 case MACHOPIC_UNDEFINED:
179 case MACHOPIC_UNDEFINED_DATA:
180 case MACHOPIC_UNDEFINED_FUNCTION:
181 return 0;
182 default:
183 return 1;
187 static int
188 machopic_data_defined_p (const char *name)
190 switch (machopic_classify_ident (get_identifier (name)))
192 case MACHOPIC_DEFINED_DATA:
193 return 1;
194 default:
195 return 0;
200 machopic_name_defined_p (const char *name)
202 return machopic_ident_defined_p (get_identifier (name));
205 void
206 machopic_define_ident (tree ident)
208 if (!machopic_ident_defined_p (ident))
209 machopic_defined_list =
210 tree_cons (NULL_TREE, ident, machopic_defined_list);
213 void
214 machopic_define_name (const char *name)
216 machopic_define_ident (get_identifier (name));
219 static GTY(()) char * function_base;
221 const char *
222 machopic_function_base_name (void)
224 /* if dynamic-no-pic is on, we should not get here */
225 if (MACHO_DYNAMIC_NO_PIC_P)
226 abort ();
228 if (function_base == NULL)
229 function_base =
230 (char *) ggc_alloc_string ("<pic base>", sizeof ("<pic base>"));
232 current_function_uses_pic_offset_table = 1;
234 return function_base;
237 static GTY(()) const char * function_base_func_name;
238 static GTY(()) int current_pic_label_num;
240 void
241 machopic_output_function_base_name (FILE *file)
243 const char *current_name;
245 /* If dynamic-no-pic is on, we should not get here. */
246 if (MACHO_DYNAMIC_NO_PIC_P)
247 abort ();
248 current_name =
249 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
250 if (function_base_func_name != current_name)
252 ++current_pic_label_num;
253 function_base_func_name = current_name;
255 fprintf (file, "\"L%011d$pb\"", current_pic_label_num);
258 static GTY(()) tree machopic_non_lazy_pointers;
260 /* Return a non-lazy pointer name corresponding to the given name,
261 either by finding it in our list of pointer names, or by generating
262 a new one. */
264 static const char *
265 machopic_non_lazy_ptr_name (const char *name)
267 const char *temp_name;
268 tree temp, ident = get_identifier (name);
270 for (temp = machopic_non_lazy_pointers;
271 temp != NULL_TREE;
272 temp = TREE_CHAIN (temp))
274 if (ident == TREE_VALUE (temp))
275 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
278 name = darwin_strip_name_encoding (name);
280 /* Try again, but comparing names this time. */
281 for (temp = machopic_non_lazy_pointers;
282 temp != NULL_TREE;
283 temp = TREE_CHAIN (temp))
285 if (TREE_VALUE (temp))
287 temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
288 temp_name = darwin_strip_name_encoding (temp_name);
289 if (strcmp (name, temp_name) == 0)
290 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
295 char *buffer;
296 int namelen = strlen (name);
297 int bufferlen = 0;
298 tree ptr_name;
300 buffer = alloca (namelen + strlen("$non_lazy_ptr") + 5);
302 strcpy (buffer, "&L");
303 bufferlen = 2;
304 if (name[0] == '*')
306 memcpy (buffer + bufferlen, name+1, namelen-1+1);
307 bufferlen += namelen-1;
309 else
311 buffer[bufferlen] = '_';
312 memcpy (buffer + bufferlen +1, name, namelen+1);
313 bufferlen += namelen +1;
316 memcpy (buffer + bufferlen, "$non_lazy_ptr", strlen("$non_lazy_ptr")+1);
317 bufferlen += strlen("$non_lazy_ptr");
318 ptr_name = get_identifier (buffer);
320 machopic_non_lazy_pointers
321 = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
323 TREE_USED (machopic_non_lazy_pointers) = 0;
325 return IDENTIFIER_POINTER (ptr_name);
329 static GTY(()) tree machopic_stubs;
331 /* Return the name of the stub corresponding to the given name,
332 generating a new stub name if necessary. */
334 const char *
335 machopic_stub_name (const char *name)
337 tree temp, ident = get_identifier (name);
338 const char *tname;
340 for (temp = machopic_stubs;
341 temp != NULL_TREE;
342 temp = TREE_CHAIN (temp))
344 if (ident == TREE_VALUE (temp))
345 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
346 tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
347 if (strcmp (name, tname) == 0)
348 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
349 /* A library call name might not be section-encoded yet, so try
350 it against a stripped name. */
351 if (name[0] != '!'
352 && tname[0] == '!'
353 && strcmp (name, tname + 4) == 0)
354 return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
357 name = darwin_strip_name_encoding (name);
360 char *buffer;
361 int bufferlen = 0;
362 int namelen = strlen (name);
363 tree ptr_name;
364 int needs_quotes = name_needs_quotes (name);
366 buffer = alloca (namelen + 20);
368 if (needs_quotes)
370 strcpy (buffer, "&\"L");
371 bufferlen = strlen("&\"L");
373 else
375 strcpy (buffer, "&L");
376 bufferlen = strlen("&L");
379 if (name[0] == '*')
381 memcpy (buffer + bufferlen, name+1, namelen - 1 +1);
382 bufferlen += namelen - 1;
384 else
386 buffer[bufferlen] = '_';
387 memcpy (buffer + bufferlen +1, name, namelen+1);
388 bufferlen += namelen +1;
391 if (needs_quotes)
393 memcpy (buffer + bufferlen, "$stub\"", strlen("$stub\"")+1);
394 bufferlen += strlen("$stub\"");
396 else
398 memcpy (buffer + bufferlen, "$stub", strlen("$stub")+1);
399 bufferlen += strlen("$stub");
401 ptr_name = get_identifier (buffer);
403 machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
404 TREE_USED (machopic_stubs) = 0;
406 return IDENTIFIER_POINTER (ptr_name);
410 void
411 machopic_validate_stub_or_non_lazy_ptr (const char *name, int validate_stub)
413 const char *real_name;
414 tree temp, ident = get_identifier (name), id2;
416 for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
417 temp != NULL_TREE;
418 temp = TREE_CHAIN (temp))
419 if (ident == TREE_PURPOSE (temp))
421 /* Mark both the stub or non-lazy pointer as well as the
422 original symbol as being referenced. */
423 TREE_USED (temp) = 1;
424 if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
425 mark_referenced (TREE_VALUE (temp));
426 real_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
427 real_name = darwin_strip_name_encoding (real_name);
428 id2 = maybe_get_identifier (real_name);
429 if (id2)
430 mark_referenced (id2);
434 /* Transform ORIG, which may be any data source, to the corresponding
435 source using indirections. */
438 machopic_indirect_data_reference (rtx orig, rtx reg)
440 rtx ptr_ref = orig;
442 if (! MACHOPIC_INDIRECT)
443 return orig;
445 if (GET_CODE (orig) == SYMBOL_REF)
447 const char *name = XSTR (orig, 0);
448 int defined = machopic_data_defined_p (name);
450 if (defined && MACHO_DYNAMIC_NO_PIC_P)
452 #if defined (TARGET_TOC)
453 emit_insn (gen_macho_high (reg, orig));
454 emit_insn (gen_macho_low (reg, reg, orig));
455 #else
456 /* some other cpu -- writeme! */
457 abort ();
458 #endif
459 return reg;
461 else if (defined)
463 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
464 rtx pic_base = gen_rtx_SYMBOL_REF (Pmode,
465 machopic_function_base_name ());
466 rtx offset = gen_rtx_CONST (Pmode,
467 gen_rtx_MINUS (Pmode, orig, pic_base));
468 #endif
470 #if defined (TARGET_TOC) /* i.e., PowerPC */
471 rtx hi_sum_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
473 if (reg == NULL)
474 abort ();
476 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
477 gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
478 gen_rtx_HIGH (Pmode, offset))));
479 emit_insn (gen_rtx_SET (Pmode, reg,
480 gen_rtx_LO_SUM (Pmode, hi_sum_reg, offset)));
482 orig = reg;
483 #else
484 #if defined (HAVE_lo_sum)
485 if (reg == 0) abort ();
487 emit_insn (gen_rtx_SET (VOIDmode, reg,
488 gen_rtx_HIGH (Pmode, offset)));
489 emit_insn (gen_rtx_SET (VOIDmode, reg,
490 gen_rtx_LO_SUM (Pmode, reg, offset)));
491 emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
493 orig = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, reg);
494 #endif
495 #endif
496 return orig;
499 ptr_ref = gen_rtx_SYMBOL_REF (Pmode,
500 machopic_non_lazy_ptr_name (name));
502 SYMBOL_REF_DECL (ptr_ref) = SYMBOL_REF_DECL (orig);
504 ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
505 RTX_UNCHANGING_P (ptr_ref) = 1;
507 return ptr_ref;
509 else if (GET_CODE (orig) == CONST)
511 rtx base, result;
513 /* legitimize both operands of the PLUS */
514 if (GET_CODE (XEXP (orig, 0)) == PLUS)
516 base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
517 reg);
518 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
519 (base == reg ? 0 : reg));
521 else
522 return orig;
524 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
525 result = plus_constant (base, INTVAL (orig));
526 else
527 result = gen_rtx_PLUS (Pmode, base, orig);
529 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
531 if (reg)
533 emit_move_insn (reg, result);
534 result = reg;
536 else
538 result = force_reg (GET_MODE (result), result);
542 return result;
545 else if (GET_CODE (orig) == MEM)
546 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
547 /* When the target is i386, this code prevents crashes due to the
548 compiler's ignorance on how to move the PIC base register to
549 other registers. (The reload phase sometimes introduces such
550 insns.) */
551 else if (GET_CODE (orig) == PLUS
552 && GET_CODE (XEXP (orig, 0)) == REG
553 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
554 #ifdef I386
555 /* Prevent the same register from being erroneously used
556 as both the base and index registers. */
557 && GET_CODE (XEXP (orig, 1)) == CONST
558 #endif
559 && reg)
561 emit_move_insn (reg, XEXP (orig, 0));
562 XEXP (ptr_ref, 0) = reg;
564 return ptr_ref;
567 /* Transform TARGET (a MEM), which is a function call target, to the
568 corresponding symbol_stub if necessary. Return a new MEM. */
571 machopic_indirect_call_target (rtx target)
573 if (GET_CODE (target) != MEM)
574 return target;
576 if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
578 enum machine_mode mode = GET_MODE (XEXP (target, 0));
579 const char *name = XSTR (XEXP (target, 0), 0);
581 /* If the name is already defined, we need do nothing. */
582 if (name[0] == '!' && name[1] == 'T')
583 return target;
585 if (!machopic_name_defined_p (name))
587 const char *stub_name = machopic_stub_name (name);
588 tree decl = SYMBOL_REF_DECL (XEXP (target, 0));
590 XEXP (target, 0) = gen_rtx_SYMBOL_REF (mode, stub_name);
591 SYMBOL_REF_DECL (XEXP (target, 0)) = decl;
592 RTX_UNCHANGING_P (target) = 1;
596 return target;
600 machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
602 rtx pic_ref = orig;
604 if (! MACHOPIC_INDIRECT)
605 return orig;
607 /* First handle a simple SYMBOL_REF or LABEL_REF */
608 if (GET_CODE (orig) == LABEL_REF
609 || (GET_CODE (orig) == SYMBOL_REF
612 /* addr(foo) = &func+(foo-func) */
613 rtx pic_base;
615 orig = machopic_indirect_data_reference (orig, reg);
617 if (GET_CODE (orig) == PLUS
618 && GET_CODE (XEXP (orig, 0)) == REG)
620 if (reg == 0)
621 return force_reg (mode, orig);
623 emit_move_insn (reg, orig);
624 return reg;
627 /* if dynamic-no-pic then use 0 as the pic base */
628 if (MACHO_DYNAMIC_NO_PIC_P)
629 pic_base = CONST0_RTX (Pmode);
630 else
631 pic_base = gen_rtx_SYMBOL_REF (Pmode, machopic_function_base_name ());
633 if (GET_CODE (orig) == MEM)
635 if (reg == 0)
637 if (reload_in_progress)
638 abort ();
639 else
640 reg = gen_reg_rtx (Pmode);
643 #ifdef HAVE_lo_sum
644 if (MACHO_DYNAMIC_NO_PIC_P
645 && (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
646 || GET_CODE (XEXP (orig, 0)) == LABEL_REF))
648 #if defined (TARGET_TOC) /* ppc */
649 rtx temp_reg = (no_new_pseudos) ? reg : gen_reg_rtx (Pmode);
650 rtx asym = XEXP (orig, 0);
651 rtx mem;
653 emit_insn (gen_macho_high (temp_reg, asym));
654 mem = gen_rtx_MEM (GET_MODE (orig),
655 gen_rtx_LO_SUM (Pmode, temp_reg, asym));
656 RTX_UNCHANGING_P (mem) = 1;
657 emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
658 #else
659 /* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic */
660 abort ();
661 #endif
662 pic_ref = reg;
664 else
665 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
666 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
668 rtx offset = gen_rtx_CONST (Pmode,
669 gen_rtx_MINUS (Pmode,
670 XEXP (orig, 0),
671 pic_base));
672 #if defined (TARGET_TOC) /* i.e., PowerPC */
673 /* Generating a new reg may expose opportunities for
674 common subexpression elimination. */
675 rtx hi_sum_reg = no_new_pseudos ? reg : gen_reg_rtx (SImode);
676 rtx mem;
677 rtx insn;
678 rtx sum;
680 sum = gen_rtx_HIGH (Pmode, offset);
681 if (! MACHO_DYNAMIC_NO_PIC_P)
682 sum = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, sum);
684 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg, sum));
686 mem = gen_rtx_MEM (GET_MODE (orig),
687 gen_rtx_LO_SUM (Pmode,
688 hi_sum_reg, offset));
689 RTX_UNCHANGING_P (mem) = 1;
690 insn = emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
691 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, pic_ref,
692 REG_NOTES (insn));
694 pic_ref = reg;
695 #else
696 emit_insn (gen_rtx_USE (VOIDmode,
697 gen_rtx_REG (Pmode,
698 PIC_OFFSET_TABLE_REGNUM)));
700 emit_insn (gen_rtx_SET (VOIDmode, reg,
701 gen_rtx_HIGH (Pmode,
702 gen_rtx_CONST (Pmode,
703 offset))));
704 emit_insn (gen_rtx_SET (VOIDmode, reg,
705 gen_rtx_LO_SUM (Pmode, reg,
706 gen_rtx_CONST (Pmode, offset))));
707 pic_ref = gen_rtx_PLUS (Pmode,
708 pic_offset_table_rtx, reg);
709 #endif
711 else
712 #endif /* HAVE_lo_sum */
714 rtx pic = pic_offset_table_rtx;
715 if (GET_CODE (pic) != REG)
717 emit_move_insn (reg, pic);
718 pic = reg;
720 #if 0
721 emit_insn (gen_rtx_USE (VOIDmode,
722 gen_rtx_REG (Pmode,
723 PIC_OFFSET_TABLE_REGNUM)));
724 #endif
726 pic_ref = gen_rtx_PLUS (Pmode,
727 pic,
728 gen_rtx_CONST (Pmode,
729 gen_rtx_MINUS (Pmode,
730 XEXP (orig, 0),
731 pic_base)));
734 #if !defined (TARGET_TOC)
735 emit_move_insn (reg, pic_ref);
736 pic_ref = gen_rtx_MEM (GET_MODE (orig), reg);
737 #endif
738 RTX_UNCHANGING_P (pic_ref) = 1;
740 else
743 #ifdef HAVE_lo_sum
744 if (GET_CODE (orig) == SYMBOL_REF
745 || GET_CODE (orig) == LABEL_REF)
747 rtx offset = gen_rtx_CONST (Pmode,
748 gen_rtx_MINUS (Pmode,
749 orig, pic_base));
750 #if defined (TARGET_TOC) /* i.e., PowerPC */
751 rtx hi_sum_reg;
753 if (reg == 0)
755 if (reload_in_progress)
756 abort ();
757 else
758 reg = gen_reg_rtx (SImode);
761 hi_sum_reg = reg;
763 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
764 (MACHO_DYNAMIC_NO_PIC_P)
765 ? gen_rtx_HIGH (Pmode, offset)
766 : gen_rtx_PLUS (Pmode,
767 pic_offset_table_rtx,
768 gen_rtx_HIGH (Pmode,
769 offset))));
770 emit_insn (gen_rtx_SET (VOIDmode, reg,
771 gen_rtx_LO_SUM (Pmode,
772 hi_sum_reg, offset)));
773 pic_ref = reg;
774 RTX_UNCHANGING_P (pic_ref) = 1;
775 #else
776 emit_insn (gen_rtx_SET (VOIDmode, reg,
777 gen_rtx_HIGH (Pmode, offset)));
778 emit_insn (gen_rtx_SET (VOIDmode, reg,
779 gen_rtx_LO_SUM (Pmode, reg, offset)));
780 pic_ref = gen_rtx_PLUS (Pmode,
781 pic_offset_table_rtx, reg);
782 RTX_UNCHANGING_P (pic_ref) = 1;
783 #endif
785 else
786 #endif /* HAVE_lo_sum */
788 if (GET_CODE (orig) == REG)
790 return orig;
792 else
794 rtx pic = pic_offset_table_rtx;
795 if (GET_CODE (pic) != REG)
797 emit_move_insn (reg, pic);
798 pic = reg;
800 #if 0
801 emit_insn (gen_rtx_USE (VOIDmode,
802 pic_offset_table_rtx));
803 #endif
804 pic_ref = gen_rtx_PLUS (Pmode,
805 pic,
806 gen_rtx_CONST (Pmode,
807 gen_rtx_MINUS (Pmode,
808 orig, pic_base)));
813 if (GET_CODE (pic_ref) != REG)
815 if (reg != 0)
817 emit_move_insn (reg, pic_ref);
818 return reg;
820 else
822 return force_reg (mode, pic_ref);
825 else
827 return pic_ref;
831 else if (GET_CODE (orig) == SYMBOL_REF)
832 return orig;
834 else if (GET_CODE (orig) == PLUS
835 && (GET_CODE (XEXP (orig, 0)) == MEM
836 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
837 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
838 && XEXP (orig, 0) != pic_offset_table_rtx
839 && GET_CODE (XEXP (orig, 1)) != REG)
842 rtx base;
843 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
845 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
846 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
847 Pmode, (base == reg ? 0 : reg));
848 if (GET_CODE (orig) == CONST_INT)
850 pic_ref = plus_constant (base, INTVAL (orig));
851 is_complex = 1;
853 else
854 pic_ref = gen_rtx_PLUS (Pmode, base, orig);
856 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
857 RTX_UNCHANGING_P (pic_ref) = 1;
859 if (reg && is_complex)
861 emit_move_insn (reg, pic_ref);
862 pic_ref = reg;
864 /* Likewise, should we set special REG_NOTEs here? */
867 else if (GET_CODE (orig) == CONST)
869 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
872 else if (GET_CODE (orig) == MEM
873 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
875 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
877 addr = gen_rtx_MEM (GET_MODE (orig), addr);
878 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
879 emit_move_insn (reg, addr);
880 pic_ref = reg;
883 return pic_ref;
887 void
888 machopic_finish (FILE *asm_out_file)
890 tree temp;
892 for (temp = machopic_stubs;
893 temp != NULL_TREE;
894 temp = TREE_CHAIN (temp))
896 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
897 const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
898 char *sym;
899 char *stub;
901 if (! TREE_USED (temp))
902 continue;
904 sym_name = darwin_strip_name_encoding (sym_name);
906 sym = alloca (strlen (sym_name) + 2);
907 if (sym_name[0] == '*' || sym_name[0] == '&')
908 strcpy (sym, sym_name + 1);
909 else if (sym_name[0] == '-' || sym_name[0] == '+')
910 strcpy (sym, sym_name);
911 else
912 sym[0] = '_', strcpy (sym + 1, sym_name);
914 stub = alloca (strlen (stub_name) + 2);
915 if (stub_name[0] == '*' || stub_name[0] == '&')
916 strcpy (stub, stub_name + 1);
917 else
918 stub[0] = '_', strcpy (stub + 1, stub_name);
920 machopic_output_stub (asm_out_file, sym, stub);
923 for (temp = machopic_non_lazy_pointers;
924 temp != NULL_TREE;
925 temp = TREE_CHAIN (temp))
927 const char *const sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
928 const char *const lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
930 if (! TREE_USED (temp))
931 continue;
933 if (machopic_ident_defined_p (TREE_VALUE (temp)))
935 data_section ();
936 assemble_align (GET_MODE_ALIGNMENT (Pmode));
937 assemble_label (lazy_name);
938 assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
939 GET_MODE_SIZE (Pmode),
940 GET_MODE_ALIGNMENT (Pmode), 1);
942 else
944 machopic_nl_symbol_ptr_section ();
945 assemble_name (asm_out_file, lazy_name);
946 fprintf (asm_out_file, ":\n");
948 fprintf (asm_out_file, "\t.indirect_symbol ");
949 assemble_name (asm_out_file, sym_name);
950 fprintf (asm_out_file, "\n");
952 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
953 GET_MODE_ALIGNMENT (Pmode), 1);
959 machopic_operand_p (rtx op)
961 if (MACHOPIC_JUST_INDIRECT)
963 while (GET_CODE (op) == CONST)
964 op = XEXP (op, 0);
966 if (GET_CODE (op) == SYMBOL_REF)
967 return machopic_name_defined_p (XSTR (op, 0));
968 else
969 return 0;
972 while (GET_CODE (op) == CONST)
973 op = XEXP (op, 0);
975 if (GET_CODE (op) == MINUS
976 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
977 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
978 && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
979 && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
980 return 1;
982 return 0;
985 /* This function records whether a given name corresponds to a defined
986 or undefined function or variable, for machopic_classify_ident to
987 use later. */
989 void
990 darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
992 char code = '\0';
993 int defined = 0;
994 rtx sym_ref;
995 const char *orig_str;
996 char *new_str;
997 size_t len, new_len;
999 /* Do the standard encoding things first. */
1000 default_encode_section_info (decl, rtl, first);
1002 /* With the introduction of symbol_ref flags, some of the following
1003 code has become redundant and should be removed at some point. */
1005 if ((TREE_CODE (decl) == FUNCTION_DECL
1006 || TREE_CODE (decl) == VAR_DECL)
1007 && !DECL_EXTERNAL (decl)
1008 && (!TREE_PUBLIC (decl) || (!DECL_ONE_ONLY (decl) && !DECL_WEAK (decl)))
1009 && ((TREE_STATIC (decl)
1010 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
1011 || (!DECL_COMMON (decl) && DECL_INITIAL (decl)
1012 && DECL_INITIAL (decl) != error_mark_node)))
1013 defined = 1;
1015 if (TREE_CODE (decl) == FUNCTION_DECL)
1016 code = (defined ? 'T' : 't');
1017 else if (TREE_CODE (decl) == VAR_DECL)
1018 code = (defined ? 'D' : 'd');
1020 if (code == '\0')
1021 return;
1023 sym_ref = XEXP (rtl, 0);
1024 orig_str = XSTR (sym_ref, 0);
1025 len = strlen (orig_str) + 1;
1027 if (orig_str[0] == '!')
1029 /* Already encoded; see if we need to change it. */
1030 if (code == orig_str[1])
1031 return;
1032 /* Yes, tweak a copy of the name and put it in a new string. */
1033 new_str = alloca (len);
1034 memcpy (new_str, orig_str, len);
1035 new_str[1] = code;
1036 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
1038 else
1040 /* Add the encoding. */
1041 new_len = len + 4;
1042 new_str = alloca (new_len);
1043 new_str[0] = '!';
1044 new_str[1] = code;
1045 new_str[2] = '_';
1046 new_str[3] = '_';
1047 memcpy (new_str + 4, orig_str, len);
1048 XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
1050 /* The non-lazy pointer list may have captured references to the
1051 old encoded name, change them. */
1052 if (TREE_CODE (decl) == VAR_DECL)
1053 update_non_lazy_ptrs (XSTR (sym_ref, 0));
1054 else
1055 update_stubs (XSTR (sym_ref, 0));
1058 /* Undo the effects of the above. */
1060 const char *
1061 darwin_strip_name_encoding (const char *str)
1063 return str[0] == '!' ? str + 4 : str;
1066 /* Scan the list of non-lazy pointers and update any recorded names whose
1067 stripped name matches the argument. */
1069 static void
1070 update_non_lazy_ptrs (const char *name)
1072 const char *name1, *name2;
1073 tree temp;
1075 name1 = darwin_strip_name_encoding (name);
1077 for (temp = machopic_non_lazy_pointers;
1078 temp != NULL_TREE;
1079 temp = TREE_CHAIN (temp))
1081 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1083 if (*sym_name == '!')
1085 name2 = darwin_strip_name_encoding (sym_name);
1086 if (strcmp (name1, name2) == 0)
1088 /* FIXME: This breaks the identifier hash table. */
1089 IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1090 = (unsigned char *) name;
1091 break;
1097 /* Scan the list of stubs and update any recorded names whose
1098 stripped name matches the argument. */
1100 static void
1101 update_stubs (const char *name)
1103 const char *name1, *name2;
1104 tree temp;
1106 name1 = darwin_strip_name_encoding (name);
1108 for (temp = machopic_stubs;
1109 temp != NULL_TREE;
1110 temp = TREE_CHAIN (temp))
1112 const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
1114 if (*sym_name == '!')
1116 name2 = darwin_strip_name_encoding (sym_name);
1117 if (strcmp (name1, name2) == 0)
1119 /* FIXME: This breaks the identifier hash table. */
1120 IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
1121 = (unsigned char *) name;
1122 break;
1128 void
1129 darwin_make_decl_one_only (tree decl)
1131 static const char *text_section = "__TEXT,__textcoal_nt,coalesced,no_toc";
1132 static const char *data_section = "__DATA,__datacoal_nt,coalesced,no_toc";
1134 const char *sec = TREE_CODE (decl) == FUNCTION_DECL
1135 ? text_section
1136 : data_section;
1137 TREE_PUBLIC (decl) = 1;
1138 DECL_ONE_ONLY (decl) = 1;
1139 DECL_SECTION_NAME (decl) = build_string (strlen (sec), sec);
1142 void
1143 machopic_select_section (tree exp, int reloc,
1144 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1146 void (*base_function)(void);
1148 if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
1149 base_function = readonly_data_section;
1150 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
1151 base_function = const_data_section;
1152 else
1153 base_function = data_section;
1155 if (TREE_CODE (exp) == STRING_CST
1156 && ((size_t) TREE_STRING_LENGTH (exp)
1157 == strlen (TREE_STRING_POINTER (exp)) + 1))
1158 cstring_section ();
1159 else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
1160 && flag_merge_constants)
1162 tree size = TYPE_SIZE (TREE_TYPE (exp));
1164 if (TREE_CODE (size) == INTEGER_CST &&
1165 TREE_INT_CST_LOW (size) == 4 &&
1166 TREE_INT_CST_HIGH (size) == 0)
1167 literal4_section ();
1168 else if (TREE_CODE (size) == INTEGER_CST &&
1169 TREE_INT_CST_LOW (size) == 8 &&
1170 TREE_INT_CST_HIGH (size) == 0)
1171 literal8_section ();
1172 else
1173 base_function ();
1175 else if (TREE_CODE (exp) == CONSTRUCTOR
1176 && TREE_TYPE (exp)
1177 && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
1178 && TYPE_NAME (TREE_TYPE (exp)))
1180 tree name = TYPE_NAME (TREE_TYPE (exp));
1181 if (TREE_CODE (name) == TYPE_DECL)
1182 name = DECL_NAME (name);
1183 if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
1184 objc_constant_string_object_section ();
1185 else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
1186 objc_string_object_section ();
1187 else
1188 base_function ();
1190 else if (TREE_CODE (exp) == VAR_DECL &&
1191 DECL_NAME (exp) &&
1192 TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
1193 IDENTIFIER_POINTER (DECL_NAME (exp)) &&
1194 !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
1196 const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
1198 if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
1199 objc_cls_meth_section ();
1200 else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
1201 objc_inst_meth_section ();
1202 else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
1203 objc_cat_cls_meth_section ();
1204 else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
1205 objc_cat_inst_meth_section ();
1206 else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
1207 objc_class_vars_section ();
1208 else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
1209 objc_instance_vars_section ();
1210 else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
1211 objc_cat_cls_meth_section ();
1212 else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
1213 objc_class_names_section ();
1214 else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
1215 objc_meth_var_names_section ();
1216 else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
1217 objc_meth_var_types_section ();
1218 else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
1219 objc_cls_refs_section ();
1220 else if (!strncmp (name, "_OBJC_CLASS_", 12))
1221 objc_class_section ();
1222 else if (!strncmp (name, "_OBJC_METACLASS_", 16))
1223 objc_meta_class_section ();
1224 else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
1225 objc_category_section ();
1226 else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1227 objc_selector_refs_section ();
1228 else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1229 objc_selector_fixup_section ();
1230 else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1231 objc_symbols_section ();
1232 else if (!strncmp (name, "_OBJC_MODULES", 13))
1233 objc_module_info_section ();
1234 else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
1235 objc_image_info_section ();
1236 else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1237 objc_cat_inst_meth_section ();
1238 else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1239 objc_cat_cls_meth_section ();
1240 else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1241 objc_cat_cls_meth_section ();
1242 else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1243 objc_protocol_section ();
1244 else
1245 base_function ();
1247 else
1248 base_function ();
1251 /* This can be called with address expressions as "rtx".
1252 They must go in "const". */
1254 void
1255 machopic_select_rtx_section (enum machine_mode mode, rtx x,
1256 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1258 if (GET_MODE_SIZE (mode) == 8)
1259 literal8_section ();
1260 else if (GET_MODE_SIZE (mode) == 4
1261 && (GET_CODE (x) == CONST_INT
1262 || GET_CODE (x) == CONST_DOUBLE))
1263 literal4_section ();
1264 else if (MACHOPIC_INDIRECT
1265 && (GET_CODE (x) == SYMBOL_REF
1266 || GET_CODE (x) == CONST
1267 || GET_CODE (x) == LABEL_REF))
1268 const_data_section ();
1269 else
1270 const_section ();
1273 void
1274 machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1276 if (MACHOPIC_INDIRECT)
1277 mod_init_section ();
1278 else
1279 constructor_section ();
1280 assemble_align (POINTER_SIZE);
1281 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1283 if (! MACHOPIC_INDIRECT)
1284 fprintf (asm_out_file, ".reference .constructors_used\n");
1287 void
1288 machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1290 if (MACHOPIC_INDIRECT)
1291 mod_term_section ();
1292 else
1293 destructor_section ();
1294 assemble_align (POINTER_SIZE);
1295 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1297 if (! MACHOPIC_INDIRECT)
1298 fprintf (asm_out_file, ".reference .destructors_used\n");
1301 void
1302 darwin_globalize_label (FILE *stream, const char *name)
1304 if (!!strncmp (name, "_OBJC_", 6))
1305 default_globalize_label (stream, name);
1308 void
1309 darwin_asm_named_section (const char *name, unsigned int flags ATTRIBUTE_UNUSED)
1311 if (flag_reorder_blocks_and_partition)
1312 fprintf (asm_out_file, SECTION_FORMAT_STRING, name);
1313 else
1314 fprintf (asm_out_file, ".section %s\n", name);
1317 unsigned int
1318 darwin_section_type_flags (tree decl, const char *name, int reloc)
1320 unsigned int flags = default_section_type_flags (decl, name, reloc);
1322 /* Weak or linkonce variables live in a writable section. */
1323 if (decl != 0 && TREE_CODE (decl) != FUNCTION_DECL
1324 && (DECL_WEAK (decl) || DECL_ONE_ONLY (decl)))
1325 flags |= SECTION_WRITE;
1327 return flags;
1330 void
1331 darwin_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
1333 /* Darwin does not use unique sections. However, the target's
1334 unique_section hook is called for linkonce symbols. We need
1335 to set an appropriate section for such symbols. */
1336 if (DECL_ONE_ONLY (decl) && !DECL_SECTION_NAME (decl))
1337 darwin_make_decl_one_only (decl);
1340 /* Emit a label for an FDE, making it global and/or weak if appropriate.
1341 The third parameter is nonzero if this is for exception handling.
1342 The fourth parameter is nonzero if this is just a placeholder for an
1343 FDE that we are omitting. */
1345 void
1346 darwin_emit_unwind_label (FILE *file, tree decl, int for_eh, int empty)
1348 tree id = DECL_ASSEMBLER_NAME (decl)
1349 ? DECL_ASSEMBLER_NAME (decl)
1350 : DECL_NAME (decl);
1352 const char *prefix = "_";
1353 const int prefix_len = 1;
1355 const char *base = IDENTIFIER_POINTER (id);
1356 unsigned int base_len = IDENTIFIER_LENGTH (id);
1358 const char *suffix = ".eh";
1360 int need_quotes = name_needs_quotes (base);
1361 int quotes_len = need_quotes ? 2 : 0;
1362 char *lab;
1364 if (! for_eh)
1365 suffix = ".eh1";
1367 lab = xmalloc (prefix_len + base_len + strlen (suffix) + quotes_len + 1);
1368 lab[0] = '\0';
1370 if (need_quotes)
1371 strcat(lab, "\"");
1372 strcat(lab, prefix);
1373 strcat(lab, base);
1374 strcat(lab, suffix);
1375 if (need_quotes)
1376 strcat(lab, "\"");
1378 if (TREE_PUBLIC (decl))
1379 fprintf (file, "%s %s\n",
1380 (DECL_VISIBILITY (decl) != VISIBILITY_HIDDEN
1381 ? ".globl"
1382 : ".private_extern"),
1383 lab);
1385 if (DECL_ONE_ONLY (decl) && TREE_PUBLIC (decl))
1386 fprintf (file, ".weak_definition %s\n", lab);
1388 if (empty)
1389 fprintf (file, "%s = 0\n", lab);
1390 else
1391 fprintf (file, "%s:\n", lab);
1393 free (lab);
1396 /* Generate a PC-relative reference to a Mach-O non-lazy-symbol. */
1398 void
1399 darwin_non_lazy_pcrel (FILE *file, rtx addr)
1401 const char *str;
1402 const char *nlp_name;
1404 if (GET_CODE (addr) != SYMBOL_REF)
1405 abort ();
1407 str = darwin_strip_name_encoding (XSTR (addr, 0));
1408 nlp_name = machopic_non_lazy_ptr_name (str);
1409 fputs ("\t.long\t", file);
1410 ASM_OUTPUT_LABELREF (file, nlp_name);
1411 fputs ("-.", file);
1414 /* Emit an assembler directive to set visibility for a symbol. The
1415 only supported visibilities are VISIBILITY_DEFAULT and
1416 VISIBILITY_HIDDEN; the latter corresponds to Darwin's "private
1417 extern". There is no MACH-O equivalent of ELF's
1418 VISIBILITY_INTERNAL or VISIBILITY_PROTECTED. */
1420 void
1421 darwin_assemble_visibility (tree decl, int vis)
1423 if (vis == VISIBILITY_DEFAULT)
1425 else if (vis == VISIBILITY_HIDDEN)
1427 fputs ("\t.private_extern ", asm_out_file);
1428 assemble_name (asm_out_file,
1429 (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
1430 fputs ("\n", asm_out_file);
1432 else
1433 warning ("internal and protected visibility attributes not supported"
1434 "in this configuration; ignored");
1437 /* Output a difference of two labels that will be an assembly time
1438 constant if the two labels are local. (.long lab1-lab2 will be
1439 very different if lab1 is at the boundary between two sections; it
1440 will be relocated according to the second section, not the first,
1441 so one ends up with a difference between labels in different
1442 sections, which is bad in the dwarf2 eh context for instance.) */
1444 static int darwin_dwarf_label_counter;
1446 void
1447 darwin_asm_output_dwarf_delta (FILE *file, int size ATTRIBUTE_UNUSED,
1448 const char *lab1, const char *lab2)
1450 int islocaldiff = (lab1[0] == '*' && lab1[1] == 'L'
1451 && lab2[0] == '*' && lab2[1] == 'L');
1453 if (islocaldiff)
1454 fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1455 else
1456 fprintf (file, "\t%s\t", ".long");
1457 assemble_name (file, lab1);
1458 fprintf (file, "-");
1459 assemble_name (file, lab2);
1460 if (islocaldiff)
1461 fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1464 void
1465 darwin_file_end (void)
1467 machopic_finish (asm_out_file);
1468 if (strcmp (lang_hooks.name, "GNU C++") == 0)
1470 constructor_section ();
1471 destructor_section ();
1472 ASM_OUTPUT_ALIGN (asm_out_file, 1);
1476 #include "gt-darwin.h"