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)
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. */
25 #include "coretypes.h"
29 #include "hard-reg-set.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "insn-flags.h"
35 #include "insn-attr.h"
42 #include "langhooks.h"
47 /* Nonzero if the user passes the -mone-byte-bool switch, which forces
48 sizeof(bool) to be 1. */
49 const char *darwin_one_byte_bool = 0;
52 name_needs_quotes (const char *name)
55 while ((c = *name++) != '\0')
56 if (! ISIDNUM (c) && c != '.' && c != '$')
62 * flag_pic = 1 ... generate only indirections
63 * flag_pic = 2 ... generate indirections and pure code
67 machopic_symbol_defined_p (rtx sym_ref)
69 return ((SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_DEFINED)
70 /* Local symbols must always be defined. */
71 || SYMBOL_REF_LOCAL_P (sym_ref));
74 /* This module assumes that (const (symbol_ref "foo")) is a legal pic
75 reference, which will not be changed. */
77 enum machopic_addr_class
78 machopic_classify_symbol (rtx sym_ref)
83 flags = SYMBOL_REF_FLAGS (sym_ref);
84 function_p = SYMBOL_REF_FUNCTION_P (sym_ref);
85 if (machopic_symbol_defined_p (sym_ref))
87 ? MACHOPIC_DEFINED_FUNCTION : MACHOPIC_DEFINED_DATA);
90 ? MACHOPIC_UNDEFINED_FUNCTION : MACHOPIC_UNDEFINED_DATA);
94 machopic_data_defined_p (rtx sym_ref)
96 switch (machopic_classify_symbol (sym_ref))
98 case MACHOPIC_DEFINED_DATA:
106 machopic_define_symbol (rtx mem)
109 if (GET_CODE (mem) != MEM)
111 sym_ref = XEXP (mem, 0);
112 SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
115 static GTY(()) char * function_base;
118 machopic_function_base_name (void)
120 /* if dynamic-no-pic is on, we should not get here */
121 if (MACHO_DYNAMIC_NO_PIC_P)
124 if (function_base == NULL)
126 (char *) ggc_alloc_string ("<pic base>", sizeof ("<pic base>"));
128 current_function_uses_pic_offset_table = 1;
130 return function_base;
133 /* Return a SYMBOL_REF for the PIC function base. */
136 machopic_function_base_sym (void)
140 sym_ref = gen_rtx_SYMBOL_REF (Pmode, machopic_function_base_name ());
141 SYMBOL_REF_FLAGS (sym_ref)
142 |= (MACHO_SYMBOL_FLAG_VARIABLE | MACHO_SYMBOL_FLAG_DEFINED);
146 static GTY(()) const char * function_base_func_name;
147 static GTY(()) int current_pic_label_num;
150 machopic_output_function_base_name (FILE *file)
152 const char *current_name;
154 /* If dynamic-no-pic is on, we should not get here. */
155 if (MACHO_DYNAMIC_NO_PIC_P)
158 IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
159 if (function_base_func_name != current_name)
161 ++current_pic_label_num;
162 function_base_func_name = current_name;
164 fprintf (file, "\"L%011d$pb\"", current_pic_label_num);
167 /* The suffix attached to non-lazy pointer symbols. */
168 #define NON_LAZY_POINTER_SUFFIX "$non_lazy_ptr"
169 /* The suffix attached to stub symbols. */
170 #define STUB_SUFFIX "$stub"
172 typedef struct machopic_indirection GTY (())
174 /* The SYMBOL_REF for the entity referenced. */
176 /* The IDENTIFIER_NODE giving the name of the stub or non-lazy
179 /* True iff this entry is for a stub (as opposed to a non-lazy
182 /* True iff this stub or pointer pointer has been referenced. */
184 } machopic_indirection;
186 /* A table mapping stub names and non-lazy pointer names to
187 SYMBOL_REFs for the stubbed-to and pointed-to entities. */
189 static GTY ((param_is (struct machopic_indirection))) htab_t
190 machopic_indirections;
192 /* Return a hash value for a SLOT in the indirections hash table. */
195 machopic_indirection_hash (const void *slot)
197 const machopic_indirection *p = (const machopic_indirection *) slot;
198 return IDENTIFIER_HASH_VALUE (p->ptr_name);
201 /* Returns true if the KEY is the same as that associated with
205 machopic_indirection_eq (const void *slot, const void *key)
207 return ((const machopic_indirection *) slot)->ptr_name == (tree) key;
210 /* Return the name of the non-lazy pointer (if STUB_P is false) or
211 stub (if STUB_B is true) corresponding to the given name. */
214 machopic_indirection_name (rtx sym_ref, bool stub_p)
217 const char *name = XSTR (sym_ref, 0);
218 int namelen = strlen (name);
220 machopic_indirection *p;
222 /* Construct the name of the non-lazy pointer or stub. */
225 int needs_quotes = name_needs_quotes (name);
226 buffer = alloca (strlen ("&L")
228 + strlen (STUB_SUFFIX)
229 + 2 /* possible quotes */
235 sprintf (buffer, "&\"L%s" STUB_SUFFIX "\"", name + 1);
237 sprintf (buffer, "&\"L%s%s" STUB_SUFFIX "\"", user_label_prefix,
240 else if (name[0] == '*')
241 sprintf (buffer, "&L%s" STUB_SUFFIX, name + 1);
243 sprintf (buffer, "&L%s%s" STUB_SUFFIX, user_label_prefix, name);
247 buffer = alloca (strlen ("&L")
248 + strlen (user_label_prefix)
250 + strlen (NON_LAZY_POINTER_SUFFIX)
253 sprintf (buffer, "&L%s" NON_LAZY_POINTER_SUFFIX, name + 1);
255 sprintf (buffer, "&L%s%s" NON_LAZY_POINTER_SUFFIX,
256 user_label_prefix, name);
259 /* See if we already have it. */
260 ptr_name = maybe_get_identifier (buffer);
261 /* If not, create a mapping from the non-lazy pointer to the
266 ptr_name = get_identifier (buffer);
267 p = (machopic_indirection *) ggc_alloc (sizeof (machopic_indirection));
269 p->ptr_name = ptr_name;
272 if (!machopic_indirections)
273 machopic_indirections
274 = htab_create_ggc (37,
275 machopic_indirection_hash,
276 machopic_indirection_eq,
278 slot = htab_find_slot_with_hash (machopic_indirections, ptr_name,
279 IDENTIFIER_HASH_VALUE (ptr_name),
281 *((machopic_indirection **) slot) = p;
284 return IDENTIFIER_POINTER (ptr_name);
287 /* Return the name of the stub for the mcount function. */
290 machopic_mcount_stub_name (void)
292 return "&L*mcount$stub";
295 /* If NAME is the name of a stub or a non-lazy pointer , mark the stub
296 or non-lazy pointer as used -- and mark the object to which the
297 pointer/stub refers as used as well, since the pointer/stub will
298 emit a reference to it. */
301 machopic_validate_stub_or_non_lazy_ptr (const char *name)
303 tree ident = get_identifier (name);
305 machopic_indirection *p;
307 p = ((machopic_indirection *)
308 (htab_find_with_hash (machopic_indirections, ident,
309 IDENTIFIER_HASH_VALUE (ident))));
313 mark_referenced (ident);
314 mark_referenced (get_identifier (XSTR (p->symbol, 0)));
318 /* Transform ORIG, which may be any data source, to the corresponding
319 source using indirections. */
322 machopic_indirect_data_reference (rtx orig, rtx reg)
326 if (! MACHOPIC_INDIRECT)
329 if (GET_CODE (orig) == SYMBOL_REF)
331 int defined = machopic_data_defined_p (orig);
333 if (defined && MACHO_DYNAMIC_NO_PIC_P)
335 #if defined (TARGET_TOC)
336 emit_insn (gen_macho_high (reg, orig));
337 emit_insn (gen_macho_low (reg, reg, orig));
339 /* some other cpu -- writeme! */
346 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
347 rtx pic_base = machopic_function_base_sym ();
348 rtx offset = gen_rtx_CONST (Pmode,
349 gen_rtx_MINUS (Pmode, orig, pic_base));
352 #if defined (TARGET_TOC) /* i.e., PowerPC */
353 rtx hi_sum_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
358 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
359 gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
360 gen_rtx_HIGH (Pmode, offset))));
361 emit_insn (gen_rtx_SET (Pmode, reg,
362 gen_rtx_LO_SUM (Pmode, hi_sum_reg, offset)));
366 #if defined (HAVE_lo_sum)
367 if (reg == 0) abort ();
369 emit_insn (gen_rtx_SET (VOIDmode, reg,
370 gen_rtx_HIGH (Pmode, offset)));
371 emit_insn (gen_rtx_SET (VOIDmode, reg,
372 gen_rtx_LO_SUM (Pmode, reg, offset)));
373 emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
375 orig = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, reg);
381 ptr_ref = (gen_rtx_SYMBOL_REF
383 machopic_indirection_name (orig, /*stub_p=*/false)));
385 SYMBOL_REF_DECL (ptr_ref) = SYMBOL_REF_DECL (orig);
387 ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
388 RTX_UNCHANGING_P (ptr_ref) = 1;
392 else if (GET_CODE (orig) == CONST)
396 /* legitimize both operands of the PLUS */
397 if (GET_CODE (XEXP (orig, 0)) == PLUS)
399 base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
401 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
402 (base == reg ? 0 : reg));
407 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
408 result = plus_constant (base, INTVAL (orig));
410 result = gen_rtx_PLUS (Pmode, base, orig);
412 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
416 emit_move_insn (reg, result);
421 result = force_reg (GET_MODE (result), result);
428 else if (GET_CODE (orig) == MEM)
429 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
430 /* When the target is i386, this code prevents crashes due to the
431 compiler's ignorance on how to move the PIC base register to
432 other registers. (The reload phase sometimes introduces such
434 else if (GET_CODE (orig) == PLUS
435 && GET_CODE (XEXP (orig, 0)) == REG
436 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
438 /* Prevent the same register from being erroneously used
439 as both the base and index registers. */
440 && GET_CODE (XEXP (orig, 1)) == CONST
444 emit_move_insn (reg, XEXP (orig, 0));
445 XEXP (ptr_ref, 0) = reg;
450 /* Transform TARGET (a MEM), which is a function call target, to the
451 corresponding symbol_stub if necessary. Return a new MEM. */
454 machopic_indirect_call_target (rtx target)
456 if (GET_CODE (target) != MEM)
459 if (MACHOPIC_INDIRECT
460 && GET_CODE (XEXP (target, 0)) == SYMBOL_REF
461 && !(SYMBOL_REF_FLAGS (XEXP (target, 0))
462 & MACHO_SYMBOL_FLAG_DEFINED))
464 rtx sym_ref = XEXP (target, 0);
465 const char *stub_name = machopic_indirection_name (sym_ref,
467 enum machine_mode mode = GET_MODE (sym_ref);
468 tree decl = SYMBOL_REF_DECL (sym_ref);
470 XEXP (target, 0) = gen_rtx_SYMBOL_REF (mode, stub_name);
471 SYMBOL_REF_DECL (XEXP (target, 0)) = decl;
472 RTX_UNCHANGING_P (target) = 1;
479 machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
483 if (! MACHOPIC_INDIRECT)
486 /* First handle a simple SYMBOL_REF or LABEL_REF */
487 if (GET_CODE (orig) == LABEL_REF
488 || (GET_CODE (orig) == SYMBOL_REF
491 /* addr(foo) = &func+(foo-func) */
494 orig = machopic_indirect_data_reference (orig, reg);
496 if (GET_CODE (orig) == PLUS
497 && GET_CODE (XEXP (orig, 0)) == REG)
500 return force_reg (mode, orig);
502 emit_move_insn (reg, orig);
506 /* if dynamic-no-pic then use 0 as the pic base */
507 if (MACHO_DYNAMIC_NO_PIC_P)
508 pic_base = CONST0_RTX (Pmode);
510 pic_base = machopic_function_base_sym ();
512 if (GET_CODE (orig) == MEM)
516 if (reload_in_progress)
519 reg = gen_reg_rtx (Pmode);
523 if (MACHO_DYNAMIC_NO_PIC_P
524 && (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
525 || GET_CODE (XEXP (orig, 0)) == LABEL_REF))
527 #if defined (TARGET_TOC) /* ppc */
528 rtx temp_reg = (no_new_pseudos) ? reg : gen_reg_rtx (Pmode);
529 rtx asym = XEXP (orig, 0);
532 emit_insn (gen_macho_high (temp_reg, asym));
533 mem = gen_rtx_MEM (GET_MODE (orig),
534 gen_rtx_LO_SUM (Pmode, temp_reg, asym));
535 RTX_UNCHANGING_P (mem) = 1;
536 emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
538 /* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic */
544 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
545 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
547 rtx offset = gen_rtx_CONST (Pmode,
548 gen_rtx_MINUS (Pmode,
551 #if defined (TARGET_TOC) /* i.e., PowerPC */
552 /* Generating a new reg may expose opportunities for
553 common subexpression elimination. */
554 rtx hi_sum_reg = no_new_pseudos ? reg : gen_reg_rtx (SImode);
559 sum = gen_rtx_HIGH (Pmode, offset);
560 if (! MACHO_DYNAMIC_NO_PIC_P)
561 sum = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, sum);
563 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg, sum));
565 mem = gen_rtx_MEM (GET_MODE (orig),
566 gen_rtx_LO_SUM (Pmode,
567 hi_sum_reg, offset));
568 RTX_UNCHANGING_P (mem) = 1;
569 insn = emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
570 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, pic_ref,
575 emit_insn (gen_rtx_USE (VOIDmode,
577 PIC_OFFSET_TABLE_REGNUM)));
579 emit_insn (gen_rtx_SET (VOIDmode, reg,
581 gen_rtx_CONST (Pmode,
583 emit_insn (gen_rtx_SET (VOIDmode, reg,
584 gen_rtx_LO_SUM (Pmode, reg,
585 gen_rtx_CONST (Pmode, offset))));
586 pic_ref = gen_rtx_PLUS (Pmode,
587 pic_offset_table_rtx, reg);
591 #endif /* HAVE_lo_sum */
593 rtx pic = pic_offset_table_rtx;
594 if (GET_CODE (pic) != REG)
596 emit_move_insn (reg, pic);
600 emit_insn (gen_rtx_USE (VOIDmode,
602 PIC_OFFSET_TABLE_REGNUM)));
605 pic_ref = gen_rtx_PLUS (Pmode,
607 gen_rtx_CONST (Pmode,
608 gen_rtx_MINUS (Pmode,
613 #if !defined (TARGET_TOC)
614 emit_move_insn (reg, pic_ref);
615 pic_ref = gen_rtx_MEM (GET_MODE (orig), reg);
617 RTX_UNCHANGING_P (pic_ref) = 1;
623 if (GET_CODE (orig) == SYMBOL_REF
624 || GET_CODE (orig) == LABEL_REF)
626 rtx offset = gen_rtx_CONST (Pmode,
627 gen_rtx_MINUS (Pmode,
629 #if defined (TARGET_TOC) /* i.e., PowerPC */
634 if (reload_in_progress)
637 reg = gen_reg_rtx (SImode);
642 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
643 (MACHO_DYNAMIC_NO_PIC_P)
644 ? gen_rtx_HIGH (Pmode, offset)
645 : gen_rtx_PLUS (Pmode,
646 pic_offset_table_rtx,
649 emit_insn (gen_rtx_SET (VOIDmode, reg,
650 gen_rtx_LO_SUM (Pmode,
651 hi_sum_reg, offset)));
653 RTX_UNCHANGING_P (pic_ref) = 1;
655 emit_insn (gen_rtx_SET (VOIDmode, reg,
656 gen_rtx_HIGH (Pmode, offset)));
657 emit_insn (gen_rtx_SET (VOIDmode, reg,
658 gen_rtx_LO_SUM (Pmode, reg, offset)));
659 pic_ref = gen_rtx_PLUS (Pmode,
660 pic_offset_table_rtx, reg);
661 RTX_UNCHANGING_P (pic_ref) = 1;
665 #endif /* HAVE_lo_sum */
667 if (GET_CODE (orig) == REG)
673 rtx pic = pic_offset_table_rtx;
674 if (GET_CODE (pic) != REG)
676 emit_move_insn (reg, pic);
680 emit_insn (gen_rtx_USE (VOIDmode,
681 pic_offset_table_rtx));
683 pic_ref = gen_rtx_PLUS (Pmode,
685 gen_rtx_CONST (Pmode,
686 gen_rtx_MINUS (Pmode,
692 if (GET_CODE (pic_ref) != REG)
696 emit_move_insn (reg, pic_ref);
701 return force_reg (mode, pic_ref);
710 else if (GET_CODE (orig) == SYMBOL_REF)
713 else if (GET_CODE (orig) == PLUS
714 && (GET_CODE (XEXP (orig, 0)) == MEM
715 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
716 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
717 && XEXP (orig, 0) != pic_offset_table_rtx
718 && GET_CODE (XEXP (orig, 1)) != REG)
722 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
724 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
725 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
726 Pmode, (base == reg ? 0 : reg));
727 if (GET_CODE (orig) == CONST_INT)
729 pic_ref = plus_constant (base, INTVAL (orig));
733 pic_ref = gen_rtx_PLUS (Pmode, base, orig);
735 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
736 RTX_UNCHANGING_P (pic_ref) = 1;
738 if (reg && is_complex)
740 emit_move_insn (reg, pic_ref);
743 /* Likewise, should we set special REG_NOTEs here? */
746 else if (GET_CODE (orig) == CONST)
748 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
751 else if (GET_CODE (orig) == MEM
752 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
754 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
756 addr = gen_rtx_MEM (GET_MODE (orig), addr);
757 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
758 emit_move_insn (reg, addr);
765 /* Output the stub or non-lazy pointer in *SLOT, if it has been used.
766 DATA is the FILE* for assembly output. Called from
770 machopic_output_indirection (void **slot, void *data)
772 machopic_indirection *p = *((machopic_indirection **) slot);
773 FILE *asm_out_file = (FILE *) data;
775 const char *sym_name;
776 const char *ptr_name;
782 sym_name = XSTR (symbol, 0);
783 ptr_name = IDENTIFIER_POINTER (p->ptr_name);
790 sym = alloca (strlen (sym_name) + 2);
791 if (sym_name[0] == '*' || sym_name[0] == '&')
792 strcpy (sym, sym_name + 1);
793 else if (sym_name[0] == '-' || sym_name[0] == '+')
794 strcpy (sym, sym_name);
796 sprintf (sym, "%s%s", user_label_prefix, sym_name);
798 stub = alloca (strlen (ptr_name) + 2);
799 if (ptr_name[0] == '*' || ptr_name[0] == '&')
800 strcpy (stub, ptr_name + 1);
802 sprintf (stub, "%s%s", user_label_prefix, ptr_name);
804 machopic_output_stub (asm_out_file, sym, stub);
806 else if (machopic_symbol_defined_p (symbol))
809 assemble_align (GET_MODE_ALIGNMENT (Pmode));
810 assemble_label (ptr_name);
811 assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
812 GET_MODE_SIZE (Pmode),
813 GET_MODE_ALIGNMENT (Pmode), 1);
817 machopic_nl_symbol_ptr_section ();
818 assemble_name (asm_out_file, ptr_name);
819 fprintf (asm_out_file, ":\n");
821 fprintf (asm_out_file, "\t.indirect_symbol ");
822 assemble_name (asm_out_file, sym_name);
823 fprintf (asm_out_file, "\n");
825 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
826 GET_MODE_ALIGNMENT (Pmode), 1);
833 machopic_finish (FILE *asm_out_file)
835 if (machopic_indirections)
836 htab_traverse_noresize (machopic_indirections,
837 machopic_output_indirection,
842 machopic_operand_p (rtx op)
844 if (MACHOPIC_JUST_INDIRECT)
846 while (GET_CODE (op) == CONST)
849 if (GET_CODE (op) == SYMBOL_REF)
850 return machopic_symbol_defined_p (op);
855 while (GET_CODE (op) == CONST)
858 if (GET_CODE (op) == MINUS
859 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
860 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
861 && machopic_symbol_defined_p (XEXP (op, 0))
862 && machopic_symbol_defined_p (XEXP (op, 1)))
868 /* This function records whether a given name corresponds to a defined
869 or undefined function or variable, for machopic_classify_ident to
873 darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
877 /* Do the standard encoding things first. */
878 default_encode_section_info (decl, rtl, first);
880 if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
883 sym_ref = XEXP (rtl, 0);
884 if (TREE_CODE (decl) == VAR_DECL)
885 SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_VARIABLE;
887 if (!DECL_EXTERNAL (decl)
888 && (!TREE_PUBLIC (decl) || (!DECL_ONE_ONLY (decl) && !DECL_WEAK (decl)))
889 && ((TREE_STATIC (decl)
890 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
891 || (!DECL_COMMON (decl) && DECL_INITIAL (decl)
892 && DECL_INITIAL (decl) != error_mark_node)))
893 SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
897 darwin_make_decl_one_only (tree decl)
899 static const char *text_section = "__TEXT,__textcoal_nt,coalesced,no_toc";
900 static const char *data_section = "__DATA,__datacoal_nt,coalesced,no_toc";
902 const char *sec = TREE_CODE (decl) == FUNCTION_DECL
905 TREE_PUBLIC (decl) = 1;
906 DECL_ONE_ONLY (decl) = 1;
907 DECL_SECTION_NAME (decl) = build_string (strlen (sec), sec);
911 machopic_select_section (tree exp, int reloc,
912 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
914 void (*base_function)(void);
916 if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
917 base_function = readonly_data_section;
918 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
919 base_function = const_data_section;
921 base_function = data_section;
923 if (TREE_CODE (exp) == STRING_CST
924 && ((size_t) TREE_STRING_LENGTH (exp)
925 == strlen (TREE_STRING_POINTER (exp)) + 1))
927 else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
928 && flag_merge_constants)
930 tree size = TYPE_SIZE (TREE_TYPE (exp));
932 if (TREE_CODE (size) == INTEGER_CST &&
933 TREE_INT_CST_LOW (size) == 4 &&
934 TREE_INT_CST_HIGH (size) == 0)
936 else if (TREE_CODE (size) == INTEGER_CST &&
937 TREE_INT_CST_LOW (size) == 8 &&
938 TREE_INT_CST_HIGH (size) == 0)
943 else if (TREE_CODE (exp) == CONSTRUCTOR
945 && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
946 && TYPE_NAME (TREE_TYPE (exp)))
948 tree name = TYPE_NAME (TREE_TYPE (exp));
949 if (TREE_CODE (name) == TYPE_DECL)
950 name = DECL_NAME (name);
951 if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
952 objc_constant_string_object_section ();
953 else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
954 objc_string_object_section ();
958 else if (TREE_CODE (exp) == VAR_DECL &&
960 TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
961 IDENTIFIER_POINTER (DECL_NAME (exp)) &&
962 !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
964 const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
966 if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
967 objc_cls_meth_section ();
968 else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
969 objc_inst_meth_section ();
970 else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
971 objc_cat_cls_meth_section ();
972 else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
973 objc_cat_inst_meth_section ();
974 else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
975 objc_class_vars_section ();
976 else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
977 objc_instance_vars_section ();
978 else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
979 objc_cat_cls_meth_section ();
980 else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
981 objc_class_names_section ();
982 else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
983 objc_meth_var_names_section ();
984 else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
985 objc_meth_var_types_section ();
986 else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
987 objc_cls_refs_section ();
988 else if (!strncmp (name, "_OBJC_CLASS_", 12))
989 objc_class_section ();
990 else if (!strncmp (name, "_OBJC_METACLASS_", 16))
991 objc_meta_class_section ();
992 else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
993 objc_category_section ();
994 else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
995 objc_selector_refs_section ();
996 else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
997 objc_selector_fixup_section ();
998 else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
999 objc_symbols_section ();
1000 else if (!strncmp (name, "_OBJC_MODULES", 13))
1001 objc_module_info_section ();
1002 else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
1003 objc_image_info_section ();
1004 else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1005 objc_cat_inst_meth_section ();
1006 else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1007 objc_cat_cls_meth_section ();
1008 else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1009 objc_cat_cls_meth_section ();
1010 else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1011 objc_protocol_section ();
1019 /* This can be called with address expressions as "rtx".
1020 They must go in "const". */
1023 machopic_select_rtx_section (enum machine_mode mode, rtx x,
1024 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1026 if (GET_MODE_SIZE (mode) == 8)
1027 literal8_section ();
1028 else if (GET_MODE_SIZE (mode) == 4
1029 && (GET_CODE (x) == CONST_INT
1030 || GET_CODE (x) == CONST_DOUBLE))
1031 literal4_section ();
1032 else if (MACHOPIC_INDIRECT
1033 && (GET_CODE (x) == SYMBOL_REF
1034 || GET_CODE (x) == CONST
1035 || GET_CODE (x) == LABEL_REF))
1036 const_data_section ();
1042 machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1044 if (MACHOPIC_INDIRECT)
1045 mod_init_section ();
1047 constructor_section ();
1048 assemble_align (POINTER_SIZE);
1049 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1051 if (! MACHOPIC_INDIRECT)
1052 fprintf (asm_out_file, ".reference .constructors_used\n");
1056 machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1058 if (MACHOPIC_INDIRECT)
1059 mod_term_section ();
1061 destructor_section ();
1062 assemble_align (POINTER_SIZE);
1063 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1065 if (! MACHOPIC_INDIRECT)
1066 fprintf (asm_out_file, ".reference .destructors_used\n");
1070 darwin_globalize_label (FILE *stream, const char *name)
1072 if (!!strncmp (name, "_OBJC_", 6))
1073 default_globalize_label (stream, name);
1077 darwin_asm_named_section (const char *name, unsigned int flags ATTRIBUTE_UNUSED)
1079 if (flag_reorder_blocks_and_partition)
1080 fprintf (asm_out_file, SECTION_FORMAT_STRING, name);
1082 fprintf (asm_out_file, ".section %s\n", name);
1086 darwin_section_type_flags (tree decl, const char *name, int reloc)
1088 unsigned int flags = default_section_type_flags (decl, name, reloc);
1090 /* Weak or linkonce variables live in a writable section. */
1091 if (decl != 0 && TREE_CODE (decl) != FUNCTION_DECL
1092 && (DECL_WEAK (decl) || DECL_ONE_ONLY (decl)))
1093 flags |= SECTION_WRITE;
1099 darwin_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
1101 /* Darwin does not use unique sections. However, the target's
1102 unique_section hook is called for linkonce symbols. We need
1103 to set an appropriate section for such symbols. */
1104 if (DECL_ONE_ONLY (decl) && !DECL_SECTION_NAME (decl))
1105 darwin_make_decl_one_only (decl);
1108 #define HAVE_DEAD_STRIP 0
1111 no_dead_strip (FILE *file, const char *lab)
1113 if (HAVE_DEAD_STRIP)
1114 fprintf (file, ".no_dead_strip %s\n", lab);
1117 /* Emit a label for an FDE, making it global and/or weak if appropriate.
1118 The third parameter is nonzero if this is for exception handling.
1119 The fourth parameter is nonzero if this is just a placeholder for an
1120 FDE that we are omitting. */
1123 darwin_emit_unwind_label (FILE *file, tree decl, int for_eh, int empty)
1125 tree id = DECL_ASSEMBLER_NAME (decl)
1126 ? DECL_ASSEMBLER_NAME (decl)
1129 const char *prefix = "_";
1130 const int prefix_len = 1;
1132 const char *base = IDENTIFIER_POINTER (id);
1133 unsigned int base_len = IDENTIFIER_LENGTH (id);
1135 const char *suffix = ".eh";
1137 int need_quotes = name_needs_quotes (base);
1138 int quotes_len = need_quotes ? 2 : 0;
1144 lab = xmalloc (prefix_len + base_len + strlen (suffix) + quotes_len + 1);
1149 strcat(lab, prefix);
1151 strcat(lab, suffix);
1155 if (TREE_PUBLIC (decl))
1156 fprintf (file, "%s %s\n",
1157 (DECL_VISIBILITY (decl) != VISIBILITY_HIDDEN
1159 : ".private_extern"),
1162 if (DECL_ONE_ONLY (decl) && TREE_PUBLIC (decl))
1163 fprintf (file, ".weak_definition %s\n", lab);
1167 fprintf (file, "%s = 0\n", lab);
1169 /* Mark the absolute .eh and .eh1 style labels as needed to
1170 ensure that we don't dead code strip them and keep such
1171 labels from another instantiation point until we can fix this
1172 properly with group comdat support. */
1173 no_dead_strip (file, lab);
1176 fprintf (file, "%s:\n", lab);
1181 /* Generate a PC-relative reference to a Mach-O non-lazy-symbol. */
1184 darwin_non_lazy_pcrel (FILE *file, rtx addr)
1186 const char *nlp_name;
1188 if (GET_CODE (addr) != SYMBOL_REF)
1191 nlp_name = machopic_indirection_name (addr, /*stub_p=*/false);
1192 fputs ("\t.long\t", file);
1193 ASM_OUTPUT_LABELREF (file, nlp_name);
1197 /* Emit an assembler directive to set visibility for a symbol. The
1198 only supported visibilities are VISIBILITY_DEFAULT and
1199 VISIBILITY_HIDDEN; the latter corresponds to Darwin's "private
1200 extern". There is no MACH-O equivalent of ELF's
1201 VISIBILITY_INTERNAL or VISIBILITY_PROTECTED. */
1204 darwin_assemble_visibility (tree decl, int vis)
1206 if (vis == VISIBILITY_DEFAULT)
1208 else if (vis == VISIBILITY_HIDDEN)
1210 fputs ("\t.private_extern ", asm_out_file);
1211 assemble_name (asm_out_file,
1212 (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
1213 fputs ("\n", asm_out_file);
1216 warning ("internal and protected visibility attributes not supported"
1217 "in this configuration; ignored");
1220 /* Output a difference of two labels that will be an assembly time
1221 constant if the two labels are local. (.long lab1-lab2 will be
1222 very different if lab1 is at the boundary between two sections; it
1223 will be relocated according to the second section, not the first,
1224 so one ends up with a difference between labels in different
1225 sections, which is bad in the dwarf2 eh context for instance.) */
1227 static int darwin_dwarf_label_counter;
1230 darwin_asm_output_dwarf_delta (FILE *file, int size ATTRIBUTE_UNUSED,
1231 const char *lab1, const char *lab2)
1233 int islocaldiff = (lab1[0] == '*' && lab1[1] == 'L'
1234 && lab2[0] == '*' && lab2[1] == 'L');
1237 fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1239 fprintf (file, "\t%s\t", ".long");
1240 assemble_name (file, lab1);
1241 fprintf (file, "-");
1242 assemble_name (file, lab2);
1244 fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1248 darwin_file_end (void)
1250 machopic_finish (asm_out_file);
1251 if (strcmp (lang_hooks.name, "GNU C++") == 0)
1253 constructor_section ();
1254 destructor_section ();
1255 ASM_OUTPUT_ALIGN (asm_out_file, 1);
1259 #include "gt-darwin.h"