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 (GET_MODE (orig) == DImode
337 ? gen_macho_high_di (reg, orig)
338 : gen_macho_high (reg, orig));
339 emit_insn (GET_MODE (orig) == DImode
340 ? gen_macho_low_di (reg, reg, orig)
341 : gen_macho_low (reg, reg, orig));
343 /* some other cpu -- writeme! */
350 #if defined (TARGET_TOC) || defined (HAVE_lo_sum)
351 rtx pic_base = machopic_function_base_sym ();
352 rtx offset = gen_rtx_CONST (Pmode,
353 gen_rtx_MINUS (Pmode, orig, pic_base));
356 #if defined (TARGET_TOC) /* i.e., PowerPC */
357 rtx hi_sum_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
362 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
363 gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
364 gen_rtx_HIGH (Pmode, offset))));
365 emit_insn (gen_rtx_SET (Pmode, reg,
366 gen_rtx_LO_SUM (Pmode, hi_sum_reg, offset)));
370 #if defined (HAVE_lo_sum)
371 if (reg == 0) abort ();
373 emit_insn (gen_rtx_SET (VOIDmode, reg,
374 gen_rtx_HIGH (Pmode, offset)));
375 emit_insn (gen_rtx_SET (VOIDmode, reg,
376 gen_rtx_LO_SUM (Pmode, reg, offset)));
377 emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
379 orig = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, reg);
385 ptr_ref = (gen_rtx_SYMBOL_REF
387 machopic_indirection_name (orig, /*stub_p=*/false)));
389 SYMBOL_REF_DECL (ptr_ref) = SYMBOL_REF_DECL (orig);
391 ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
392 RTX_UNCHANGING_P (ptr_ref) = 1;
396 else if (GET_CODE (orig) == CONST)
400 /* legitimize both operands of the PLUS */
401 if (GET_CODE (XEXP (orig, 0)) == PLUS)
403 base = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 0),
405 orig = machopic_indirect_data_reference (XEXP (XEXP (orig, 0), 1),
406 (base == reg ? 0 : reg));
411 if (MACHOPIC_PURE && GET_CODE (orig) == CONST_INT)
412 result = plus_constant (base, INTVAL (orig));
414 result = gen_rtx_PLUS (Pmode, base, orig);
416 if (MACHOPIC_JUST_INDIRECT && GET_CODE (base) == MEM)
420 emit_move_insn (reg, result);
425 result = force_reg (GET_MODE (result), result);
432 else if (GET_CODE (orig) == MEM)
433 XEXP (ptr_ref, 0) = machopic_indirect_data_reference (XEXP (orig, 0), reg);
434 /* When the target is i386, this code prevents crashes due to the
435 compiler's ignorance on how to move the PIC base register to
436 other registers. (The reload phase sometimes introduces such
438 else if (GET_CODE (orig) == PLUS
439 && GET_CODE (XEXP (orig, 0)) == REG
440 && REGNO (XEXP (orig, 0)) == PIC_OFFSET_TABLE_REGNUM
442 /* Prevent the same register from being erroneously used
443 as both the base and index registers. */
444 && GET_CODE (XEXP (orig, 1)) == CONST
448 emit_move_insn (reg, XEXP (orig, 0));
449 XEXP (ptr_ref, 0) = reg;
454 /* Transform TARGET (a MEM), which is a function call target, to the
455 corresponding symbol_stub if necessary. Return a new MEM. */
458 machopic_indirect_call_target (rtx target)
460 if (GET_CODE (target) != MEM)
463 if (MACHOPIC_INDIRECT
464 && GET_CODE (XEXP (target, 0)) == SYMBOL_REF
465 && !(SYMBOL_REF_FLAGS (XEXP (target, 0))
466 & MACHO_SYMBOL_FLAG_DEFINED))
468 rtx sym_ref = XEXP (target, 0);
469 const char *stub_name = machopic_indirection_name (sym_ref,
471 enum machine_mode mode = GET_MODE (sym_ref);
472 tree decl = SYMBOL_REF_DECL (sym_ref);
474 XEXP (target, 0) = gen_rtx_SYMBOL_REF (mode, stub_name);
475 SYMBOL_REF_DECL (XEXP (target, 0)) = decl;
476 RTX_UNCHANGING_P (target) = 1;
483 machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
487 if (! MACHOPIC_INDIRECT)
490 /* First handle a simple SYMBOL_REF or LABEL_REF */
491 if (GET_CODE (orig) == LABEL_REF
492 || (GET_CODE (orig) == SYMBOL_REF
495 /* addr(foo) = &func+(foo-func) */
498 orig = machopic_indirect_data_reference (orig, reg);
500 if (GET_CODE (orig) == PLUS
501 && GET_CODE (XEXP (orig, 0)) == REG)
504 return force_reg (mode, orig);
506 emit_move_insn (reg, orig);
510 /* if dynamic-no-pic then use 0 as the pic base */
511 if (MACHO_DYNAMIC_NO_PIC_P)
512 pic_base = CONST0_RTX (Pmode);
514 pic_base = machopic_function_base_sym ();
516 if (GET_CODE (orig) == MEM)
520 if (reload_in_progress)
523 reg = gen_reg_rtx (Pmode);
527 if (MACHO_DYNAMIC_NO_PIC_P
528 && (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
529 || GET_CODE (XEXP (orig, 0)) == LABEL_REF))
531 #if defined (TARGET_TOC) /* ppc */
532 rtx temp_reg = (no_new_pseudos) ? reg : gen_reg_rtx (Pmode);
533 rtx asym = XEXP (orig, 0);
536 emit_insn (mode == DImode
537 ? gen_macho_high_di (temp_reg, asym)
538 : gen_macho_high (temp_reg, asym));
539 mem = gen_rtx_MEM (GET_MODE (orig),
540 gen_rtx_LO_SUM (Pmode, temp_reg, asym));
541 RTX_UNCHANGING_P (mem) = 1;
542 emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
544 /* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic */
550 if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
551 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
553 rtx offset = gen_rtx_CONST (Pmode,
554 gen_rtx_MINUS (Pmode,
557 #if defined (TARGET_TOC) /* i.e., PowerPC */
558 /* Generating a new reg may expose opportunities for
559 common subexpression elimination. */
560 rtx hi_sum_reg = no_new_pseudos ? reg : gen_reg_rtx (Pmode);
565 sum = gen_rtx_HIGH (Pmode, offset);
566 if (! MACHO_DYNAMIC_NO_PIC_P)
567 sum = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, sum);
569 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg, sum));
571 mem = gen_rtx_MEM (GET_MODE (orig),
572 gen_rtx_LO_SUM (Pmode,
573 hi_sum_reg, offset));
574 RTX_UNCHANGING_P (mem) = 1;
575 insn = emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
576 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, pic_ref,
581 emit_insn (gen_rtx_USE (VOIDmode,
583 PIC_OFFSET_TABLE_REGNUM)));
585 emit_insn (gen_rtx_SET (VOIDmode, reg,
587 gen_rtx_CONST (Pmode,
589 emit_insn (gen_rtx_SET (VOIDmode, reg,
590 gen_rtx_LO_SUM (Pmode, reg,
591 gen_rtx_CONST (Pmode, offset))));
592 pic_ref = gen_rtx_PLUS (Pmode,
593 pic_offset_table_rtx, reg);
597 #endif /* HAVE_lo_sum */
599 rtx pic = pic_offset_table_rtx;
600 if (GET_CODE (pic) != REG)
602 emit_move_insn (reg, pic);
606 emit_insn (gen_rtx_USE (VOIDmode,
608 PIC_OFFSET_TABLE_REGNUM)));
611 pic_ref = gen_rtx_PLUS (Pmode,
613 gen_rtx_CONST (Pmode,
614 gen_rtx_MINUS (Pmode,
619 #if !defined (TARGET_TOC)
620 emit_move_insn (reg, pic_ref);
621 pic_ref = gen_rtx_MEM (GET_MODE (orig), reg);
623 RTX_UNCHANGING_P (pic_ref) = 1;
629 if (GET_CODE (orig) == SYMBOL_REF
630 || GET_CODE (orig) == LABEL_REF)
632 rtx offset = gen_rtx_CONST (Pmode,
633 gen_rtx_MINUS (Pmode,
635 #if defined (TARGET_TOC) /* i.e., PowerPC */
640 if (reload_in_progress)
643 reg = gen_reg_rtx (Pmode);
648 emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
649 (MACHO_DYNAMIC_NO_PIC_P)
650 ? gen_rtx_HIGH (Pmode, offset)
651 : gen_rtx_PLUS (Pmode,
652 pic_offset_table_rtx,
655 emit_insn (gen_rtx_SET (VOIDmode, reg,
656 gen_rtx_LO_SUM (Pmode,
657 hi_sum_reg, offset)));
659 RTX_UNCHANGING_P (pic_ref) = 1;
661 emit_insn (gen_rtx_SET (VOIDmode, reg,
662 gen_rtx_HIGH (Pmode, offset)));
663 emit_insn (gen_rtx_SET (VOIDmode, reg,
664 gen_rtx_LO_SUM (Pmode, reg, offset)));
665 pic_ref = gen_rtx_PLUS (Pmode,
666 pic_offset_table_rtx, reg);
667 RTX_UNCHANGING_P (pic_ref) = 1;
671 #endif /* HAVE_lo_sum */
673 if (GET_CODE (orig) == REG)
679 rtx pic = pic_offset_table_rtx;
680 if (GET_CODE (pic) != REG)
682 emit_move_insn (reg, pic);
686 emit_insn (gen_rtx_USE (VOIDmode,
687 pic_offset_table_rtx));
689 pic_ref = gen_rtx_PLUS (Pmode,
691 gen_rtx_CONST (Pmode,
692 gen_rtx_MINUS (Pmode,
698 if (GET_CODE (pic_ref) != REG)
702 emit_move_insn (reg, pic_ref);
707 return force_reg (mode, pic_ref);
716 else if (GET_CODE (orig) == SYMBOL_REF)
719 else if (GET_CODE (orig) == PLUS
720 && (GET_CODE (XEXP (orig, 0)) == MEM
721 || GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
722 || GET_CODE (XEXP (orig, 0)) == LABEL_REF)
723 && XEXP (orig, 0) != pic_offset_table_rtx
724 && GET_CODE (XEXP (orig, 1)) != REG)
728 int is_complex = (GET_CODE (XEXP (orig, 0)) == MEM);
730 base = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
731 orig = machopic_legitimize_pic_address (XEXP (orig, 1),
732 Pmode, (base == reg ? 0 : reg));
733 if (GET_CODE (orig) == CONST_INT)
735 pic_ref = plus_constant (base, INTVAL (orig));
739 pic_ref = gen_rtx_PLUS (Pmode, base, orig);
741 if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
742 RTX_UNCHANGING_P (pic_ref) = 1;
744 if (reg && is_complex)
746 emit_move_insn (reg, pic_ref);
749 /* Likewise, should we set special REG_NOTEs here? */
752 else if (GET_CODE (orig) == CONST)
754 return machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
757 else if (GET_CODE (orig) == MEM
758 && GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
760 rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
762 addr = gen_rtx_MEM (GET_MODE (orig), addr);
763 RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
764 emit_move_insn (reg, addr);
771 /* Output the stub or non-lazy pointer in *SLOT, if it has been used.
772 DATA is the FILE* for assembly output. Called from
776 machopic_output_indirection (void **slot, void *data)
778 machopic_indirection *p = *((machopic_indirection **) slot);
779 FILE *asm_out_file = (FILE *) data;
781 const char *sym_name;
782 const char *ptr_name;
788 sym_name = XSTR (symbol, 0);
789 ptr_name = IDENTIFIER_POINTER (p->ptr_name);
796 sym = alloca (strlen (sym_name) + 2);
797 if (sym_name[0] == '*' || sym_name[0] == '&')
798 strcpy (sym, sym_name + 1);
799 else if (sym_name[0] == '-' || sym_name[0] == '+')
800 strcpy (sym, sym_name);
802 sprintf (sym, "%s%s", user_label_prefix, sym_name);
804 stub = alloca (strlen (ptr_name) + 2);
805 if (ptr_name[0] == '*' || ptr_name[0] == '&')
806 strcpy (stub, ptr_name + 1);
808 sprintf (stub, "%s%s", user_label_prefix, ptr_name);
810 machopic_output_stub (asm_out_file, sym, stub);
812 else if (machopic_symbol_defined_p (symbol))
815 assemble_align (GET_MODE_ALIGNMENT (Pmode));
816 assemble_label (ptr_name);
817 assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
818 GET_MODE_SIZE (Pmode),
819 GET_MODE_ALIGNMENT (Pmode), 1);
823 machopic_nl_symbol_ptr_section ();
824 assemble_name (asm_out_file, ptr_name);
825 fprintf (asm_out_file, ":\n");
827 fprintf (asm_out_file, "\t.indirect_symbol ");
828 assemble_name (asm_out_file, sym_name);
829 fprintf (asm_out_file, "\n");
831 assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
832 GET_MODE_ALIGNMENT (Pmode), 1);
839 machopic_finish (FILE *asm_out_file)
841 if (machopic_indirections)
842 htab_traverse_noresize (machopic_indirections,
843 machopic_output_indirection,
848 machopic_operand_p (rtx op)
850 if (MACHOPIC_JUST_INDIRECT)
852 while (GET_CODE (op) == CONST)
855 if (GET_CODE (op) == SYMBOL_REF)
856 return machopic_symbol_defined_p (op);
861 while (GET_CODE (op) == CONST)
864 if (GET_CODE (op) == MINUS
865 && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
866 && GET_CODE (XEXP (op, 1)) == SYMBOL_REF
867 && machopic_symbol_defined_p (XEXP (op, 0))
868 && machopic_symbol_defined_p (XEXP (op, 1)))
874 /* This function records whether a given name corresponds to a defined
875 or undefined function or variable, for machopic_classify_ident to
879 darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
883 /* Do the standard encoding things first. */
884 default_encode_section_info (decl, rtl, first);
886 if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
889 sym_ref = XEXP (rtl, 0);
890 if (TREE_CODE (decl) == VAR_DECL)
891 SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_VARIABLE;
893 if (!DECL_EXTERNAL (decl)
894 && (!TREE_PUBLIC (decl) || (!DECL_ONE_ONLY (decl) && !DECL_WEAK (decl)))
895 && ((TREE_STATIC (decl)
896 && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
897 || (!DECL_COMMON (decl) && DECL_INITIAL (decl)
898 && DECL_INITIAL (decl) != error_mark_node)))
899 SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
903 darwin_make_decl_one_only (tree decl)
905 static const char *text_section = "__TEXT,__textcoal_nt,coalesced,no_toc";
906 static const char *data_section = "__DATA,__datacoal_nt,coalesced,no_toc";
908 const char *sec = TREE_CODE (decl) == FUNCTION_DECL
911 TREE_PUBLIC (decl) = 1;
912 DECL_ONE_ONLY (decl) = 1;
913 DECL_SECTION_NAME (decl) = build_string (strlen (sec), sec);
917 machopic_select_section (tree exp, int reloc,
918 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
920 void (*base_function)(void);
922 if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
923 base_function = readonly_data_section;
924 else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
925 base_function = const_data_section;
927 base_function = data_section;
929 if (TREE_CODE (exp) == STRING_CST
930 && ((size_t) TREE_STRING_LENGTH (exp)
931 == strlen (TREE_STRING_POINTER (exp)) + 1))
933 else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
934 && flag_merge_constants)
936 tree size = TYPE_SIZE (TREE_TYPE (exp));
938 if (TREE_CODE (size) == INTEGER_CST &&
939 TREE_INT_CST_LOW (size) == 4 &&
940 TREE_INT_CST_HIGH (size) == 0)
942 else if (TREE_CODE (size) == INTEGER_CST &&
943 TREE_INT_CST_LOW (size) == 8 &&
944 TREE_INT_CST_HIGH (size) == 0)
949 else if (TREE_CODE (exp) == CONSTRUCTOR
951 && TREE_CODE (TREE_TYPE (exp)) == RECORD_TYPE
952 && TYPE_NAME (TREE_TYPE (exp)))
954 tree name = TYPE_NAME (TREE_TYPE (exp));
955 if (TREE_CODE (name) == TYPE_DECL)
956 name = DECL_NAME (name);
957 if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
958 objc_constant_string_object_section ();
959 else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
960 objc_string_object_section ();
964 else if (TREE_CODE (exp) == VAR_DECL &&
966 TREE_CODE (DECL_NAME (exp)) == IDENTIFIER_NODE &&
967 IDENTIFIER_POINTER (DECL_NAME (exp)) &&
968 !strncmp (IDENTIFIER_POINTER (DECL_NAME (exp)), "_OBJC_", 6))
970 const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
972 if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
973 objc_cls_meth_section ();
974 else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
975 objc_inst_meth_section ();
976 else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
977 objc_cat_cls_meth_section ();
978 else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
979 objc_cat_inst_meth_section ();
980 else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
981 objc_class_vars_section ();
982 else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
983 objc_instance_vars_section ();
984 else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
985 objc_cat_cls_meth_section ();
986 else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
987 objc_class_names_section ();
988 else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
989 objc_meth_var_names_section ();
990 else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
991 objc_meth_var_types_section ();
992 else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
993 objc_cls_refs_section ();
994 else if (!strncmp (name, "_OBJC_CLASS_", 12))
995 objc_class_section ();
996 else if (!strncmp (name, "_OBJC_METACLASS_", 16))
997 objc_meta_class_section ();
998 else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
999 objc_category_section ();
1000 else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
1001 objc_selector_refs_section ();
1002 else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
1003 objc_selector_fixup_section ();
1004 else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
1005 objc_symbols_section ();
1006 else if (!strncmp (name, "_OBJC_MODULES", 13))
1007 objc_module_info_section ();
1008 else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
1009 objc_image_info_section ();
1010 else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
1011 objc_cat_inst_meth_section ();
1012 else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
1013 objc_cat_cls_meth_section ();
1014 else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
1015 objc_cat_cls_meth_section ();
1016 else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
1017 objc_protocol_section ();
1025 /* This can be called with address expressions as "rtx".
1026 They must go in "const". */
1029 machopic_select_rtx_section (enum machine_mode mode, rtx x,
1030 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
1032 if (GET_MODE_SIZE (mode) == 8)
1033 literal8_section ();
1034 else if (GET_MODE_SIZE (mode) == 4
1035 && (GET_CODE (x) == CONST_INT
1036 || GET_CODE (x) == CONST_DOUBLE))
1037 literal4_section ();
1038 else if (MACHOPIC_INDIRECT
1039 && (GET_CODE (x) == SYMBOL_REF
1040 || GET_CODE (x) == CONST
1041 || GET_CODE (x) == LABEL_REF))
1042 const_data_section ();
1048 machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1050 if (MACHOPIC_INDIRECT)
1051 mod_init_section ();
1053 constructor_section ();
1054 assemble_align (POINTER_SIZE);
1055 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1057 if (! MACHOPIC_INDIRECT)
1058 fprintf (asm_out_file, ".reference .constructors_used\n");
1062 machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
1064 if (MACHOPIC_INDIRECT)
1065 mod_term_section ();
1067 destructor_section ();
1068 assemble_align (POINTER_SIZE);
1069 assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
1071 if (! MACHOPIC_INDIRECT)
1072 fprintf (asm_out_file, ".reference .destructors_used\n");
1076 darwin_globalize_label (FILE *stream, const char *name)
1078 if (!!strncmp (name, "_OBJC_", 6))
1079 default_globalize_label (stream, name);
1083 darwin_asm_named_section (const char *name, unsigned int flags ATTRIBUTE_UNUSED)
1085 if (flag_reorder_blocks_and_partition)
1086 fprintf (asm_out_file, SECTION_FORMAT_STRING, name);
1088 fprintf (asm_out_file, ".section %s\n", name);
1092 darwin_section_type_flags (tree decl, const char *name, int reloc)
1094 unsigned int flags = default_section_type_flags (decl, name, reloc);
1096 /* Weak or linkonce variables live in a writable section. */
1097 if (decl != 0 && TREE_CODE (decl) != FUNCTION_DECL
1098 && (DECL_WEAK (decl) || DECL_ONE_ONLY (decl)))
1099 flags |= SECTION_WRITE;
1105 darwin_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
1107 /* Darwin does not use unique sections. However, the target's
1108 unique_section hook is called for linkonce symbols. We need
1109 to set an appropriate section for such symbols. */
1110 if (DECL_ONE_ONLY (decl) && !DECL_SECTION_NAME (decl))
1111 darwin_make_decl_one_only (decl);
1114 #define HAVE_DEAD_STRIP 0
1117 no_dead_strip (FILE *file, const char *lab)
1119 if (HAVE_DEAD_STRIP)
1120 fprintf (file, ".no_dead_strip %s\n", lab);
1123 /* Emit a label for an FDE, making it global and/or weak if appropriate.
1124 The third parameter is nonzero if this is for exception handling.
1125 The fourth parameter is nonzero if this is just a placeholder for an
1126 FDE that we are omitting. */
1129 darwin_emit_unwind_label (FILE *file, tree decl, int for_eh, int empty)
1131 tree id = DECL_ASSEMBLER_NAME (decl)
1132 ? DECL_ASSEMBLER_NAME (decl)
1135 const char *prefix = "_";
1136 const int prefix_len = 1;
1138 const char *base = IDENTIFIER_POINTER (id);
1139 unsigned int base_len = IDENTIFIER_LENGTH (id);
1141 const char *suffix = ".eh";
1143 int need_quotes = name_needs_quotes (base);
1144 int quotes_len = need_quotes ? 2 : 0;
1150 lab = xmalloc (prefix_len + base_len + strlen (suffix) + quotes_len + 1);
1155 strcat(lab, prefix);
1157 strcat(lab, suffix);
1161 if (TREE_PUBLIC (decl))
1162 fprintf (file, "%s %s\n",
1163 (DECL_VISIBILITY (decl) != VISIBILITY_HIDDEN
1165 : ".private_extern"),
1168 if (DECL_ONE_ONLY (decl) && TREE_PUBLIC (decl))
1169 fprintf (file, ".weak_definition %s\n", lab);
1173 fprintf (file, "%s = 0\n", lab);
1175 /* Mark the absolute .eh and .eh1 style labels as needed to
1176 ensure that we don't dead code strip them and keep such
1177 labels from another instantiation point until we can fix this
1178 properly with group comdat support. */
1179 no_dead_strip (file, lab);
1182 fprintf (file, "%s:\n", lab);
1187 /* Generate a PC-relative reference to a Mach-O non-lazy-symbol. */
1190 darwin_non_lazy_pcrel (FILE *file, rtx addr)
1192 const char *nlp_name;
1194 if (GET_CODE (addr) != SYMBOL_REF)
1197 nlp_name = machopic_indirection_name (addr, /*stub_p=*/false);
1198 fputs ("\t.long\t", file);
1199 ASM_OUTPUT_LABELREF (file, nlp_name);
1203 /* Emit an assembler directive to set visibility for a symbol. The
1204 only supported visibilities are VISIBILITY_DEFAULT and
1205 VISIBILITY_HIDDEN; the latter corresponds to Darwin's "private
1206 extern". There is no MACH-O equivalent of ELF's
1207 VISIBILITY_INTERNAL or VISIBILITY_PROTECTED. */
1210 darwin_assemble_visibility (tree decl, int vis)
1212 if (vis == VISIBILITY_DEFAULT)
1214 else if (vis == VISIBILITY_HIDDEN)
1216 fputs ("\t.private_extern ", asm_out_file);
1217 assemble_name (asm_out_file,
1218 (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))));
1219 fputs ("\n", asm_out_file);
1222 warning ("internal and protected visibility attributes not supported"
1223 "in this configuration; ignored");
1226 /* Output a difference of two labels that will be an assembly time
1227 constant if the two labels are local. (.long lab1-lab2 will be
1228 very different if lab1 is at the boundary between two sections; it
1229 will be relocated according to the second section, not the first,
1230 so one ends up with a difference between labels in different
1231 sections, which is bad in the dwarf2 eh context for instance.) */
1233 static int darwin_dwarf_label_counter;
1236 darwin_asm_output_dwarf_delta (FILE *file, int size ATTRIBUTE_UNUSED,
1237 const char *lab1, const char *lab2)
1239 int islocaldiff = (lab1[0] == '*' && lab1[1] == 'L'
1240 && lab2[0] == '*' && lab2[1] == 'L');
1243 fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
1245 fprintf (file, "\t%s\t", ".long");
1246 assemble_name (file, lab1);
1247 fprintf (file, "-");
1248 assemble_name (file, lab2);
1250 fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
1254 darwin_file_end (void)
1256 machopic_finish (asm_out_file);
1257 if (strcmp (lang_hooks.name, "GNU C++") == 0)
1259 constructor_section ();
1260 destructor_section ();
1261 ASM_OUTPUT_ALIGN (asm_out_file, 1);
1265 #include "gt-darwin.h"