/* Functions for generic Darwin as target machine for GNU C compiler.
Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001, 2002, 2003, 2004,
- 2005, 2006, 2007, 2008, 2009, 2010
+ 2005, 2006, 2007, 2008, 2009, 2010, 2011
Free Software Foundation, Inc.
Contributed by Apple Computer Inc.
#include "langhooks.h"
#include "target.h"
#include "tm_p.h"
-#include "c-tree.h"
-#include "c-lang.h"
#include "diagnostic-core.h"
#include "toplev.h"
#include "hashtab.h"
functions). */
int darwin_running_cxx;
+/* Some code-gen now depends on OS major version numbers (at least). */
+int generating_for_darwin_version ;
+
/* Section names. */
section * darwin_sections[NUM_DARWIN_SECTIONS];
objc_class_vars_section,
objc_instance_vars_section,
objc_module_info_section,
- objc_symbols_section
+ objc_symbols_section,
};
+ /* ABI=1 */
+ static const enum darwin_section_enum tomarkv1[] =
+ {
+ objc1_protocol_ext_section,
+ objc1_class_ext_section,
+ objc1_prop_list_section
+ } ;
+ /* ABI=2 */
+ static const enum darwin_section_enum tomarkv2[] =
+ {
+ objc2_message_refs_section,
+ objc2_classdefs_section,
+ objc2_metadata_section,
+ objc2_classrefs_section,
+ objc2_classlist_section,
+ objc2_categorylist_section,
+ objc2_selector_refs_section,
+ objc2_nonlazy_class_section,
+ objc2_nonlazy_category_section,
+ objc2_protocollist_section,
+ objc2_protocolrefs_section,
+ objc2_super_classrefs_section,
+ objc2_image_info_section,
+ objc2_constant_string_object_section
+ } ;
size_t i;
been_here = true;
- for (i = 0; i < ARRAY_SIZE (tomark); i++)
- switch_to_section (darwin_sections[tomark[i]]);
+ if (flag_objc_abi < 2)
+ {
+ for (i = 0; i < ARRAY_SIZE (tomark); i++)
+ switch_to_section (darwin_sections[tomark[i]]);
+ if (flag_objc_abi == 1)
+ for (i = 0; i < ARRAY_SIZE (tomarkv1); i++)
+ switch_to_section (darwin_sections[tomarkv1[i]]);
+ }
+ else
+ for (i = 0; i < ARRAY_SIZE (tomarkv2); i++)
+ switch_to_section (darwin_sections[tomarkv2[i]]);
+ /* Make sure we don't get varasm.c out of sync with us. */
switch_to_section (saved_in_section);
}
output_section_asm_op (directive);
}
+
+/* Private flag applied to disable section-anchors in a particular section. */
+#define SECTION_NO_ANCHOR SECTION_MACH_DEP
+
+
/* Implement TARGET_ASM_INIT_SECTIONS. */
void
readonly_data_section = darwin_sections[const_section];
exception_section = darwin_sections[darwin_exception_section];
eh_frame_section = darwin_sections[darwin_eh_frame_section];
-
- /* Make sure that there is no conflict between the 'no anchor' section
- flag declared in darwin.h and the section flags declared in output.h. */
- gcc_assert (SECTION_NO_ANCHOR > SECTION_MACH_DEP);
}
int
return ! lprefix;
}
-
static int
machopic_data_defined_p (rtx sym_ref)
{
}
static section *
-darwin_text_section (int reloc, int weak)
-{
- if (reloc)
- return (weak
- ? darwin_sections[text_unlikely_coal_section]
- : unlikely_text_section ());
- else
- return (weak
- ? darwin_sections[text_coal_section]
- : text_section);
-}
-
-static section *
darwin_rodata_section (int weak, bool zsize)
{
return (weak
darwin_mergeable_string_section (tree exp,
unsigned HOST_WIDE_INT align)
{
- if (flag_merge_constants
+ /* Darwin's ld expects to see non-writable string literals in the .cstring
+ section. Later versions of ld check and complain when CFStrings are
+ enabled. Therefore we shall force the strings into .cstring since we
+ don't support writable ones anyway. */
+ if ((darwin_constant_cfstrings || flag_merge_constants)
&& TREE_CODE (exp) == STRING_CST
&& TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE
&& align <= 256
return readonly_data_section;
}
+section *
+darwin_tm_clone_table_section (void)
+{
+ return get_named_section (NULL,
+ "__DATA,__tm_clone_table,regular,no_dead_strip",
+ 3);
+}
+
int
machopic_reloc_rw_mask (void)
{
return MACHOPIC_INDIRECT ? 3 : 0;
}
+/* We have to deal with ObjC/C++ metadata section placement in the common
+ code, since it will also be called from LTO.
+
+ Return metadata attributes, if present (searching for ABI=2 first)
+ Return NULL_TREE if no such attributes are found. */
+
+static tree
+is_objc_metadata (tree decl)
+{
+ if (DECL_P (decl)
+ && (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == CONST_DECL)
+ && DECL_ATTRIBUTES (decl))
+ {
+ tree meta = lookup_attribute ("OBJC2META", DECL_ATTRIBUTES (decl));
+ if (meta)
+ return meta;
+ meta = lookup_attribute ("OBJC1META", DECL_ATTRIBUTES (decl));
+ if (meta)
+ return meta;
+ }
+ return NULL_TREE;
+}
+
+/* Return the section required for Objective C ABI 2 metadata. */
+static section *
+darwin_objc2_section (tree decl ATTRIBUTE_UNUSED, tree meta, section * base)
+{
+ const char *p;
+ tree ident = TREE_VALUE (meta);
+ gcc_assert (TREE_CODE (ident) == IDENTIFIER_NODE);
+ p = IDENTIFIER_POINTER (ident);
+
+ /* If we are in LTO, then we don't know the state of flag_next_runtime
+ or flag_objc_abi when the code was generated. We set these from the
+ meta-data - which is needed to deal with const string constructors. */
+
+ flag_next_runtime = 1;
+ flag_objc_abi = 2;
+
+ if (base == data_section)
+ base = darwin_sections[objc2_metadata_section];
+
+ /* Most of the OBJC2 META-data end up in the base section, so check it
+ first. */
+ if (!strncmp (p, "V2_BASE", 7))
+ return base;
+ else if (!strncmp (p, "V2_STRG", 7))
+ return darwin_sections[cstring_section];
+
+ else if (!strncmp (p, "G2_META", 7) || !strncmp (p, "G2_CLAS", 7))
+ return darwin_sections[objc2_classdefs_section];
+ else if (!strncmp (p, "V2_MREF", 7))
+ return darwin_sections[objc2_message_refs_section];
+ else if (!strncmp (p, "V2_CLRF", 7))
+ return darwin_sections[objc2_classrefs_section];
+ else if (!strncmp (p, "V2_SURF", 7))
+ return darwin_sections[objc2_super_classrefs_section];
+ else if (!strncmp (p, "V2_NLCL", 7))
+ return darwin_sections[objc2_nonlazy_class_section];
+ else if (!strncmp (p, "V2_CLAB", 7))
+ return darwin_sections[objc2_classlist_section];
+ else if (!strncmp (p, "V2_SRFS", 7))
+ return darwin_sections[objc2_selector_refs_section];
+ else if (!strncmp (p, "V2_NLCA", 7))
+ return darwin_sections[objc2_nonlazy_category_section];
+ else if (!strncmp (p, "V2_CALA", 7))
+ return darwin_sections[objc2_categorylist_section];
+
+ else if (!strncmp (p, "V2_PLST", 7))
+ return darwin_sections[objc2_protocollist_section];
+ else if (!strncmp (p, "V2_PRFS", 7))
+ return darwin_sections[objc2_protocolrefs_section];
+
+ else if (!strncmp (p, "V2_INFO", 7))
+ return darwin_sections[objc2_image_info_section];
+
+ else if (!strncmp (p, "V2_EHTY", 7))
+ return darwin_sections[data_coal_section];
+
+ else if (!strncmp (p, "V2_CSTR", 7))
+ return darwin_sections[objc2_constant_string_object_section];
+
+ /* Not recognized, default. */
+ return base;
+}
+
+/* Return the section required for Objective C ABI 0/1 metadata. */
+static section *
+darwin_objc1_section (tree decl ATTRIBUTE_UNUSED, tree meta, section * base)
+{
+ const char *p;
+ tree ident = TREE_VALUE (meta);
+ gcc_assert (TREE_CODE (ident) == IDENTIFIER_NODE);
+ p = IDENTIFIER_POINTER (ident);
+
+ /* If we are in LTO, then we don't know the state of flag_next_runtime
+ or flag_objc_abi when the code was generated. We set these from the
+ meta-data - which is needed to deal with const string constructors. */
+ flag_next_runtime = 1;
+ if (!global_options_set.x_flag_objc_abi)
+ flag_objc_abi = 1;
+
+ /* String sections first, cos there are lots of strings. */
+ if (!strncmp (p, "V1_STRG", 7))
+ return darwin_sections[cstring_section];
+ else if (!strncmp (p, "V1_CLSN", 7))
+ return darwin_sections[objc_class_names_section];
+ else if (!strncmp (p, "V1_METN", 7))
+ return darwin_sections[objc_meth_var_names_section];
+ else if (!strncmp (p, "V1_METT", 7))
+ return darwin_sections[objc_meth_var_types_section];
+
+ else if (!strncmp (p, "V1_CLAS", 7))
+ return darwin_sections[objc_class_section];
+ else if (!strncmp (p, "V1_META", 7))
+ return darwin_sections[objc_meta_class_section];
+ else if (!strncmp (p, "V1_CATG", 7))
+ return darwin_sections[objc_category_section];
+ else if (!strncmp (p, "V1_PROT", 7))
+ return darwin_sections[objc_protocol_section];
+
+ else if (!strncmp (p, "V1_CLCV", 7))
+ return darwin_sections[objc_class_vars_section];
+ else if (!strncmp (p, "V1_CLIV", 7))
+ return darwin_sections[objc_instance_vars_section];
+
+ else if (!strncmp (p, "V1_CLCM", 7))
+ return darwin_sections[objc_cls_meth_section];
+ else if (!strncmp (p, "V1_CLIM", 7))
+ return darwin_sections[objc_inst_meth_section];
+ else if (!strncmp (p, "V1_CACM", 7))
+ return darwin_sections[objc_cat_cls_meth_section];
+ else if (!strncmp (p, "V1_CAIM", 7))
+ return darwin_sections[objc_cat_inst_meth_section];
+ else if (!strncmp (p, "V1_PNSM", 7))
+ return darwin_sections[objc_cat_inst_meth_section];
+ else if (!strncmp (p, "V1_PCLM", 7))
+ return darwin_sections[objc_cat_cls_meth_section];
+
+ else if (!strncmp (p, "V1_CLPR", 7))
+ return darwin_sections[objc_cat_cls_meth_section];
+ else if (!strncmp (p, "V1_CAPR", 7))
+ return darwin_sections[objc_category_section]; /* ??? CHECK me. */
+
+ else if (!strncmp (p, "V1_PRFS", 7))
+ return darwin_sections[objc_cat_cls_meth_section];
+ else if (!strncmp (p, "V1_CLRF", 7))
+ return darwin_sections[objc_cls_refs_section];
+ else if (!strncmp (p, "V1_SRFS", 7))
+ return darwin_sections[objc_selector_refs_section];
+
+ else if (!strncmp (p, "V1_MODU", 7))
+ return darwin_sections[objc_module_info_section];
+ else if (!strncmp (p, "V1_SYMT", 7))
+ return darwin_sections[objc_symbols_section];
+ else if (!strncmp (p, "V1_INFO", 7))
+ return darwin_sections[objc_image_info_section];
+
+ else if (!strncmp (p, "V1_PLST", 7))
+ return darwin_sections[objc1_prop_list_section];
+ else if (!strncmp (p, "V1_PEXT", 7))
+ return darwin_sections[objc1_protocol_ext_section];
+ else if (!strncmp (p, "V1_CEXT", 7))
+ return darwin_sections[objc1_class_ext_section];
+
+ else if (!strncmp (p, "V2_CSTR", 7))
+ return darwin_sections[objc_constant_string_object_section];
+
+ return base;
+}
+
section *
machopic_select_section (tree decl,
int reloc,
switch (categorize_decl_for_section (decl, reloc))
{
case SECCAT_TEXT:
- {
- struct cgraph_node *node;
- if (decl && TREE_CODE (decl) == FUNCTION_DECL
- && (node = cgraph_get_node (decl)) != NULL)
- base_section = darwin_function_section (decl,
- node->frequency,
- node->only_called_at_startup,
- node->only_called_at_exit);
- if (!base_section)
- base_section = darwin_text_section (reloc, weak);
- }
+ gcc_unreachable ();
break;
case SECCAT_RODATA:
gcc_unreachable ();
}
- /* Darwin weird special cases. */
+ /* Darwin weird special cases.
+ a) OBJC Meta-data. */
+ if (DECL_P (decl)
+ && (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == CONST_DECL)
+ && DECL_ATTRIBUTES (decl))
+ {
+ tree meta = lookup_attribute ("OBJC2META", DECL_ATTRIBUTES (decl));
+ if (meta)
+ return darwin_objc2_section (decl, meta, base_section);
+ meta = lookup_attribute ("OBJC1META", DECL_ATTRIBUTES (decl));
+ if (meta)
+ return darwin_objc1_section (decl, meta, base_section);
+ meta = lookup_attribute ("OBJC1METG", DECL_ATTRIBUTES (decl));
+ if (meta)
+ return base_section; /* GNU runtime is happy with it all in one pot. */
+ }
+
+ /* b) Constant string objects. */
if (TREE_CODE (decl) == CONSTRUCTOR
&& TREE_TYPE (decl)
&& TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
+ /* FIXME: This is unsatisfactory for LTO, since it relies on other
+ metadata determining the source FE. */
if (!strcmp (IDENTIFIER_POINTER (name), "__builtin_ObjCString"))
- {
- if (flag_next_runtime)
- return darwin_sections[objc_constant_string_object_section];
- else
- return darwin_sections[objc_string_object_section];
- }
+ {
+ if (flag_next_runtime)
+ {
+ if (flag_objc_abi == 2)
+ return darwin_sections[objc2_constant_string_object_section];
+ else
+ return darwin_sections[objc_constant_string_object_section];
+ }
+ else
+ return darwin_sections[objc_string_object_section];
+ }
else if (!strcmp (IDENTIFIER_POINTER (name), "__builtin_CFString"))
return darwin_sections[cfstring_constant_object_section];
else
- return base_section;
+ return base_section;
}
+ /* c) legacy meta-data selection. */
else if (TREE_CODE (decl) == VAR_DECL
&& DECL_NAME (decl)
&& TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE
&& IDENTIFIER_POINTER (DECL_NAME (decl))
+ && flag_next_runtime
&& !strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "_OBJC_", 6))
{
const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
-
+ static bool warned_objc_46 = false;
/* We shall assert that zero-sized objects are an error in ObjC
meta-data. */
gcc_assert (tree_low_cst (DECL_SIZE_UNIT (decl), 1) != 0);
+
+ /* ??? This mechanism for determining the metadata section is
+ broken when LTO is in use, since the frontend that generated
+ the data is not identified. We will keep the capability for
+ the short term - in case any non-Objective-C programs are using
+ it to place data in specified sections. */
+ if (!warned_objc_46)
+ {
+ location_t loc = DECL_SOURCE_LOCATION (decl);
+ warning_at (loc, 0, "the use of _OBJC_-prefixed variable names"
+ " to select meta-data sections is deprecated at 4.6"
+ " and will be removed in 4.7");
+ warned_objc_46 = true;
+ }
+
if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
return darwin_sections[objc_cls_meth_section];
else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
return (!strncmp ((const char *)p, "_OBJC_", 6));
}
-/* LTO support for Mach-O. */
+/* LTO support for Mach-O.
+
+ This version uses three mach-o sections to encapsulate the (unlimited
+ number of) lto sections.
+
+ __GNU_LTO, __lto_sections contains the concatented GNU LTO section data.
+ __GNU_LTO, __section_names contains the GNU LTO section names.
+ __GNU_LTO, __section_index contains an array of values that index these.
+
+ Indexed thus:
+ <section offset from the start of __GNU_LTO, __lto_sections>,
+ <section length>
+ <name offset from the start of __GNU_LTO, __section_names,
+ <name length>.
+
+ At present, for both m32 and m64 mach-o files each of these fields is
+ represented by a uint32_t. This is because, AFAICT, a mach-o object
+ cannot exceed 4Gb because the section_64 offset field (see below) is 32bits.
+
+ uint32_t offset;
+ "offset An integer specifying the offset to this section in the file." */
+
+/* Count lto section numbers. */
+static unsigned int lto_section_num = 0;
-/* Section names for LTO sections. */
-static unsigned int lto_section_names_offset = 0;
+/* A vector of information about LTO sections, at present, we only have
+ the name. TODO: see if we can get the data length somehow. */
+typedef struct GTY (()) darwin_lto_section_e {
+ const char *sectname;
+} darwin_lto_section_e ;
+DEF_VEC_O(darwin_lto_section_e);
+DEF_VEC_ALLOC_O(darwin_lto_section_e, gc);
-/* This is the obstack which we use to allocate the many strings. */
-static struct obstack lto_section_names_obstack;
+static GTY (()) VEC (darwin_lto_section_e, gc) * lto_section_names;
-/* Segment name for LTO sections. */
+/* Segment for LTO data. */
#define LTO_SEGMENT_NAME "__GNU_LTO"
-/* Section name for LTO section names section. */
-#define LTO_NAMES_SECTION "__section_names"
+/* Section wrapper scheme (used here to wrap the unlimited number of LTO
+ sections into three Mach-O ones).
+ NOTE: These names MUST be kept in sync with those in
+ libiberty/simple-object-mach-o. */
+#define LTO_SECTS_SECTION "__wrapper_sects"
+#define LTO_NAMES_SECTION "__wrapper_names"
+#define LTO_INDEX_SECTION "__wrapper_index"
/* File to temporarily store LTO data. This is appended to asm_out_file
in darwin_end_file. */
unsigned int flags,
tree decl ATTRIBUTE_UNUSED)
{
- /* LTO sections go in a special segment __GNU_LTO. We want to replace the
- section name with something we can use to represent arbitrary-length
- names (section names in Mach-O are at most 16 characters long). */
+ /* LTO sections go in a special section that encapsulates the (unlimited)
+ number of GNU LTO sections within a single mach-o one. */
if (strncmp (name, LTO_SECTION_NAME_PREFIX,
strlen (LTO_SECTION_NAME_PREFIX)) == 0)
{
+ darwin_lto_section_e e;
/* We expect certain flags to be set... */
gcc_assert ((flags & (SECTION_DEBUG | SECTION_NAMED))
== (SECTION_DEBUG | SECTION_NAMED));
- /* Add the section name to the things to output when we end the
- current assembler output file.
- This is all not very efficient, but that doesn't matter -- this
- shouldn't be a hot path in the compiler... */
- obstack_1grow (<o_section_names_obstack, '\t');
- obstack_grow (<o_section_names_obstack, ".ascii ", 7);
- obstack_1grow (<o_section_names_obstack, '"');
- obstack_grow (<o_section_names_obstack, name, strlen (name));
- obstack_grow (<o_section_names_obstack, "\\0\"\n", 4);
-
- /* Output the dummy section name. */
- fprintf (asm_out_file, "\t# %s\n", name);
- fprintf (asm_out_file, "\t.section %s,__%08X,regular,debug\n",
- LTO_SEGMENT_NAME, lto_section_names_offset);
-
- /* Update the offset for the next section name. Make sure we stay
- within reasonable length. */
- lto_section_names_offset += strlen (name) + 1;
- gcc_assert (lto_section_names_offset > 0
- && lto_section_names_offset < ((unsigned) 1 << 31));
- }
+ /* Switch to our combined section. */
+ fprintf (asm_out_file, "\t.section %s,%s,regular,debug\n",
+ LTO_SEGMENT_NAME, LTO_SECTS_SECTION);
+ /* Output a label for the start of this sub-section. */
+ fprintf (asm_out_file, "L_GNU_LTO%d:\t;# %s\n",
+ lto_section_num, name);
+ /* We have to jump through hoops to get the values of the intra-section
+ offsets... */
+ fprintf (asm_out_file, "\t.set L$gnu$lto$offs%d,L_GNU_LTO%d-L_GNU_LTO0\n",
+ lto_section_num, lto_section_num);
+ fprintf (asm_out_file,
+ "\t.set L$gnu$lto$size%d,L_GNU_LTO%d-L_GNU_LTO%d\n",
+ lto_section_num, lto_section_num+1, lto_section_num);
+ lto_section_num++;
+ e.sectname = xstrdup (name);
+ /* Keep the names, we'll need to make a table later.
+ TODO: check that we do not revisit sections, that would break
+ the assumption of how this is done. */
+ if (lto_section_names == NULL)
+ lto_section_names = VEC_alloc (darwin_lto_section_e, gc, 16);
+ VEC_safe_push (darwin_lto_section_e, gc, lto_section_names, &e);
+ }
else if (strncmp (name, "__DWARF,", 8) == 0)
darwin_asm_dwarf_section (name, flags, decl);
else
void
darwin_emit_unwind_label (FILE *file, tree decl, int for_eh, int empty)
{
- char *lab;
-
- if (! for_eh)
+ char *lab ;
+ char buf[32];
+ static int invok_count = 0;
+ static tree last_fun_decl = NULL_TREE;
+
+ /* We use the linker to emit the .eh labels for Darwin 9 and above. */
+ if (! for_eh || generating_for_darwin_version >= 9)
return;
- lab = concat (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), ".eh", NULL);
+ /* FIXME: This only works when the eh for all sections of a function is
+ emitted at the same time. If that changes, we would need to use a lookup
+ table of some form to determine what to do. Also, we should emit the
+ unadorned label for the partition containing the public label for a
+ function. This is of limited use, probably, since we do not currently
+ enable partitioning. */
+ strcpy (buf, ".eh");
+ if (decl && TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ if (decl == last_fun_decl)
+ {
+ invok_count++;
+ snprintf (buf, 31, "$$part$$%d.eh", invok_count);
+ }
+ else
+ {
+ last_fun_decl = decl;
+ invok_count = 0;
+ }
+ }
+
+ lab = concat (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), buf, NULL);
if (TREE_PUBLIC (decl))
{
assemble_zeros (size);
}
+/* Emit a chunk of data for ObjC meta-data that got placed in BSS erroneously. */
+static void
+darwin_emit_objc_zeroed (FILE *fp, tree decl, const char *name,
+ unsigned HOST_WIDE_INT size,
+ unsigned int align, tree meta)
+{
+ section *ocs = data_section;
+
+ if (TREE_PURPOSE (meta) == get_identifier("OBJC2META"))
+ ocs = darwin_objc2_section (decl, meta, ocs);
+ else
+ ocs = darwin_objc1_section (decl, meta, ocs);
+
+ switch_to_section (ocs);
+
+ /* We shall declare that zero-sized meta-data are not valid (yet). */
+ gcc_assert (size);
+ fprintf (fp, "\t.align\t%d\n", floor_log2 (align / BITS_PER_UNIT));
+
+ /* ... and we let it deal with outputting one byte of zero for them too. */
+ darwin_asm_declare_object_name (fp, name, decl);
+ assemble_zeros (size);
+}
+
/* This routine emits 'local' storage:
When Section Anchors are off this routine emits .zerofill commands in
{
unsigned int l2align;
bool one, pub, weak;
+ tree meta;
pub = TREE_PUBLIC (decl);
one = DECL_ONE_ONLY (decl);
pub, weak, one, (unsigned long)DECL_INITIAL (decl));
#endif
+ /* ObjC metadata can get put in BSS because varasm.c decides it's BSS
+ before the target has a chance to comment. */
+ if ((meta = is_objc_metadata (decl)))
+ {
+ darwin_emit_objc_zeroed (fp, decl, name, size, DECL_ALIGN (decl), meta);
+ return;
+ }
+
/* Check that any initializer is valid. */
gcc_assert ((DECL_INITIAL (decl) == NULL)
|| (DECL_INITIAL (decl) == error_mark_node)
{
unsigned int l2align;
bool one, weak;
+ tree meta;
+
/* No corresponding var. */
if (decl==NULL)
{
TREE_PUBLIC (decl), weak, one, (unsigned long)DECL_INITIAL (decl));
#endif
+ /* ObjC metadata can get put in BSS because varasm.c decides it's BSS
+ before the target has a chance to comment. */
+ if ((meta = is_objc_metadata (decl)))
+ {
+ darwin_emit_objc_zeroed (fp, decl, name, size, DECL_ALIGN (decl), meta);
+ return;
+ }
+
/* We shouldn't be messing with this if the decl has a section name. */
gcc_assert (DECL_SECTION_NAME (decl) == NULL);
{
unsigned long l2align;
bool one, weak;
+ tree meta;
one = DECL_ONE_ONLY (decl);
weak = (DECL_P (decl)
weak , (unsigned long)DECL_INITIAL (decl));
#endif
+ /* ObjC metadata can get put in BSS because varasm.c decides it's BSS
+ before the target has a chance to comment. */
+ if ((meta = is_objc_metadata (decl)))
+ {
+ darwin_emit_objc_zeroed (fp, decl, name, size, DECL_ALIGN (decl), meta);
+ return;
+ }
+
/* We shouldn't be messing with this if the decl has a section name. */
gcc_assert (DECL_SECTION_NAME (decl) == NULL);
darwin_asm_output_dwarf_delta (file, size, lab, sname);
}
-/* Called from the within the TARGET_ASM_FILE_START for each target.
- Initialize the stuff we need for LTO long section names support. */
+/* Called from the within the TARGET_ASM_FILE_START for each target. */
void
darwin_file_start (void)
{
- /* We fill this obstack with the complete section text for the lto section
- names to write in darwin_file_end. */
- obstack_init (<o_section_names_obstack);
- lto_section_names_offset = 0;
+ /* Nothing to do. */
}
/* Called for the TARGET_ASM_FILE_END hook.
void
darwin_file_end (void)
{
- const char *lto_section_names;
-
machopic_finish (asm_out_file);
if (strcmp (lang_hooks.name, "GNU C++") == 0)
{
lto_asm_txt = buf = (char *) xmalloc (n + 1);
while (fgets (lto_asm_txt, n, lto_asm_out_file))
fputs (lto_asm_txt, asm_out_file);
+ /* Put a termination label. */
+ fprintf (asm_out_file, "\t.section %s,%s,regular,debug\n",
+ LTO_SEGMENT_NAME, LTO_SECTS_SECTION);
+ fprintf (asm_out_file, "L_GNU_LTO%d:\t;# end of lto\n",
+ lto_section_num);
+ /* Make sure our termination label stays in this section. */
+ fputs ("\t.space\t1\n", asm_out_file);
}
/* Remove the temporary file. */
free (lto_asm_out_name);
}
- /* Finish the LTO section names obstack. Don't output anything if
- there are no recorded section names. */
- obstack_1grow (<o_section_names_obstack, '\0');
- lto_section_names = XOBFINISH (<o_section_names_obstack, const char *);
- if (strlen (lto_section_names) > 0)
+ /* Output the names and indices. */
+ if (lto_section_names && VEC_length (darwin_lto_section_e, lto_section_names))
{
- fprintf (asm_out_file,
- "\t.section %s,%s,regular,debug\n",
+ int count;
+ darwin_lto_section_e *ref;
+ /* For now, we'll make the offsets 4 bytes and unaligned - we'll fix
+ the latter up ourselves. */
+ const char *op = integer_asm_op (4,0);
+
+ /* Emit the names. */
+ fprintf (asm_out_file, "\t.section %s,%s,regular,debug\n",
LTO_SEGMENT_NAME, LTO_NAMES_SECTION);
- fprintf (asm_out_file,
- "\t# Section names in %s are offsets into this table\n",
- LTO_SEGMENT_NAME);
- fprintf (asm_out_file, "%s\n", lto_section_names);
+ FOR_EACH_VEC_ELT (darwin_lto_section_e, lto_section_names, count, ref)
+ {
+ fprintf (asm_out_file, "L_GNU_LTO_NAME%d:\n", count);
+ /* We have to jump through hoops to get the values of the intra-section
+ offsets... */
+ fprintf (asm_out_file,
+ "\t.set L$gnu$lto$noff%d,L_GNU_LTO_NAME%d-L_GNU_LTO_NAME0\n",
+ count, count);
+ fprintf (asm_out_file,
+ "\t.set L$gnu$lto$nsiz%d,L_GNU_LTO_NAME%d-L_GNU_LTO_NAME%d\n",
+ count, count+1, count);
+ fprintf (asm_out_file, "\t.asciz\t\"%s\"\n", ref->sectname);
+ }
+ fprintf (asm_out_file, "L_GNU_LTO_NAME%d:\t;# end\n", lto_section_num);
+ /* make sure our termination label stays in this section. */
+ fputs ("\t.space\t1\n", asm_out_file);
+
+ /* Emit the Index. */
+ fprintf (asm_out_file, "\t.section %s,%s,regular,debug\n",
+ LTO_SEGMENT_NAME, LTO_INDEX_SECTION);
+ fputs ("\t.align\t2\n", asm_out_file);
+ fputs ("# Section offset, Section length, Name offset, Name length\n",
+ asm_out_file);
+ FOR_EACH_VEC_ELT (darwin_lto_section_e, lto_section_names, count, ref)
+ {
+ fprintf (asm_out_file, "%s L$gnu$lto$offs%d\t;# %s\n",
+ op, count, ref->sectname);
+ fprintf (asm_out_file, "%s L$gnu$lto$size%d\n", op, count);
+ fprintf (asm_out_file, "%s L$gnu$lto$noff%d\n", op, count);
+ fprintf (asm_out_file, "%s L$gnu$lto$nsiz%d\n", op, count);
+ }
}
- obstack_free (<o_section_names_obstack, NULL);
/* If we have section anchors, then we must prevent the linker from
re-arranging data. */
void
darwin_override_options (void)
{
- bool darwin9plus = (darwin_macosx_version_min
- && strverscmp (darwin_macosx_version_min, "10.5") >= 0);
+ /* Keep track of which (major) version we're generating code for. */
+ if (darwin_macosx_version_min)
+ {
+ if (strverscmp (darwin_macosx_version_min, "10.6") >= 0)
+ generating_for_darwin_version = 10;
+ else if (strverscmp (darwin_macosx_version_min, "10.5") >= 0)
+ generating_for_darwin_version = 9;
+
+ /* Earlier versions are not specifically accounted, until required. */
+ }
+
+ /* In principle, this should be c-family only. However, we really need to
+ set sensible defaults for LTO as well, since the section selection stuff
+ should check for correctness re. the ABI. TODO: check and provide the
+ flags (runtime & ABI) from the lto wrapper). */
+
+ /* Unless set, force ABI=2 for NeXT and m64, 0 otherwise. */
+ if (!global_options_set.x_flag_objc_abi)
+ global_options.x_flag_objc_abi
+ = (!flag_next_runtime)
+ ? 0
+ : (TARGET_64BIT ? 2
+ : (generating_for_darwin_version >= 9) ? 1
+ : 0);
+
+ /* Objective-C family ABI 2 is only valid for next/m64 at present. */
+ if (global_options_set.x_flag_objc_abi && flag_next_runtime)
+ {
+ if (TARGET_64BIT && global_options.x_flag_objc_abi < 2)
+ error_at (UNKNOWN_LOCATION, "%<-fobjc-abi-version%> >= 2 must be"
+ " used for %<-m64%> targets with"
+ " %<-fnext-runtime%>");
+ if (!TARGET_64BIT && global_options.x_flag_objc_abi >= 2)
+ error_at (UNKNOWN_LOCATION, "%<-fobjc-abi-version%> >= 2 is not"
+ " supported on %<-m32%> targets with"
+ " %<-fnext-runtime%>");
+ }
/* Don't emit DWARF3/4 unless specifically selected. This is a
workaround for tool bugs. */
if (!global_options_set.x_dwarf_strict)
dwarf_strict = 1;
- /* Disable -freorder-blocks-and-partition for darwin_emit_unwind_label. */
- if (flag_reorder_blocks_and_partition
- && (targetm.asm_out.emit_unwind_label == darwin_emit_unwind_label))
+ /* Do not allow unwind tables to be generated by default for m32.
+ fnon-call-exceptions will override this, regardless of what we do. */
+ if (generating_for_darwin_version < 10
+ && !global_options_set.x_flag_asynchronous_unwind_tables
+ && !TARGET_64BIT)
+ global_options.x_flag_asynchronous_unwind_tables = 0;
+
+ /* Disable -freorder-blocks-and-partition when unwind tables are being
+ emitted for Darwin < 9 (OSX 10.5).
+ The strategy is, "Unless the User has specifically set/unset an unwind
+ flag we will switch off -freorder-blocks-and-partition when unwind tables
+ will be generated". If the User specifically sets flags... we assume
+ (s)he knows why... */
+ if (generating_for_darwin_version < 9
+ && global_options_set.x_flag_reorder_blocks_and_partition
+ && ((global_options.x_flag_exceptions /* User, c++, java */
+ && !global_options_set.x_flag_exceptions) /* User specified... */
+ || (global_options.x_flag_unwind_tables
+ && !global_options_set.x_flag_unwind_tables)
+ || (global_options.x_flag_non_call_exceptions
+ && !global_options_set.x_flag_non_call_exceptions)
+ || (global_options.x_flag_asynchronous_unwind_tables
+ && !global_options_set.x_flag_asynchronous_unwind_tables)))
{
inform (input_location,
- "-freorder-blocks-and-partition does not work with exceptions "
- "on this architecture");
+ "-freorder-blocks-and-partition does not work with exceptions "
+ "on this architecture");
flag_reorder_blocks_and_partition = 0;
flag_reorder_blocks = 1;
}
}
if (flag_var_tracking
- && darwin9plus
- && debug_info_level >= DINFO_LEVEL_NORMAL
- && debug_hooks->var_location != do_nothing_debug_hooks.var_location)
+ && generating_for_darwin_version >= 9
+ && (flag_gtoggle ? (debug_info_level == DINFO_LEVEL_NONE)
+ : (debug_info_level >= DINFO_LEVEL_NORMAL))
+ && write_symbols == DWARF2_DEBUG)
flag_var_tracking_uninit = 1;
if (MACHO_DYNAMIC_NO_PIC_P)
{
if (flag_pic)
- warning (0, "-mdynamic-no-pic overrides -fpic or -fPIC");
+ warning_at (UNKNOWN_LOCATION, 0,
+ "%<-mdynamic-no-pic%> overrides %<-fpic%>, %<-fPIC%>,"
+ " %<-fpie%> or %<-fPIE%>");
flag_pic = 0;
}
else if (flag_pic == 1)
}
/* It is assumed that branch island stubs are needed for earlier systems. */
- if (!darwin9plus)
+ if (generating_for_darwin_version < 9)
darwin_emit_branch_islands = true;
else
emit_aligned_common = true; /* Later systems can support aligned common. */
darwin_running_cxx = (strstr (lang_hooks.name, "C++") != 0);
}
-/* Add $LDBL128 suffix to long double builtins. */
+#if DARWIN_PPC
+/* Add $LDBL128 suffix to long double builtins for ppc darwin. */
static void
-darwin_patch_builtin (int fncode)
+darwin_patch_builtin (enum built_in_function fncode)
{
- tree fn = built_in_decls[fncode];
+ tree fn = builtin_decl_explicit (fncode);
tree sym;
char *newname;
set_user_assembler_name (fn, newname);
- fn = implicit_built_in_decls[fncode];
+ fn = builtin_decl_implicit (fncode);
if (fn)
set_user_assembler_name (fn, newname);
}
#undef PATCH_BUILTIN_NO64
#undef PATCH_BUILTIN_VARIADIC
}
+#endif
/* CFStrings implementation. */
static GTY(()) tree cfstring_class_reference = NULL_TREE;
static GTY(()) tree pcint_type_node = NULL_TREE;
static GTY(()) tree pcchar_type_node = NULL_TREE;
-static enum built_in_function DARWIN_BUILTIN_CFSTRINGMAKECONSTANTSTRING;
+static enum built_in_function darwin_builtin_cfstring;
/* Store all constructed constant CFStrings in a hash table so that
they get uniqued properly. */
return field;
}
-void
-darwin_init_cfstring_builtins (unsigned first_avail)
+tree
+darwin_init_cfstring_builtins (unsigned builtin_cfstring)
{
tree cfsfun, fields, pccfstring_ftype_pcchar;
tree *chain = NULL;
- DARWIN_BUILTIN_CFSTRINGMAKECONSTANTSTRING =
- (enum built_in_function) first_avail;
+ darwin_builtin_cfstring =
+ (enum built_in_function) builtin_cfstring;
/* struct __builtin_CFString {
const int *isa; (will point at
DECL_LANG_SPECIFIC (cfsfun) = NULL;
(*lang_hooks.dup_lang_specific_decl) (cfsfun);
DECL_BUILT_IN_CLASS (cfsfun) = BUILT_IN_MD;
- DECL_FUNCTION_CODE (cfsfun) = DARWIN_BUILTIN_CFSTRINGMAKECONSTANTSTRING;
+ DECL_FUNCTION_CODE (cfsfun) = darwin_builtin_cfstring;
lang_hooks.builtin_function (cfsfun);
/* extern int __CFConstantStringClassReference[]; */
/* Initialize the hash table used to hold the constant CFString objects. */
cfstring_htab = htab_create_ggc (31, cfstring_hash, cfstring_eq, NULL);
+
+ return cfstring_type_node;
}
tree
{
unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
- if (fcode == DARWIN_BUILTIN_CFSTRINGMAKECONSTANTSTRING)
+ if (fcode == darwin_builtin_cfstring)
{
if (!darwin_constant_cfstrings)
{
return NULL_TREE;
}
+void
+darwin_rename_builtins (void)
+{
+ /* The system ___divdc3 routine in libSystem on darwin10 is not
+ accurate to 1ulp, ours is, so we avoid ever using the system name
+ for this routine and instead install a non-conflicting name that
+ is accurate.
+
+ When -ffast-math or -funsafe-math-optimizations is given, we can
+ use the faster version. */
+ if (!flag_unsafe_math_optimizations)
+ {
+ enum built_in_function dcode
+ = (enum built_in_function)(BUILT_IN_COMPLEX_DIV_MIN
+ + DCmode - MIN_MODE_COMPLEX_FLOAT);
+ tree fn = builtin_decl_explicit (dcode);
+ /* Fortran and c call TARGET_INIT_BUILTINS and
+ TARGET_INIT_LIBFUNCS at different times, so we have to put a
+ call into each to ensure that at least one of them is called
+ after build_common_builtin_nodes. A better fix is to add a
+ new hook to run after build_common_builtin_nodes runs. */
+ if (fn)
+ set_user_assembler_name (fn, "___ieee_divdc3");
+ fn = builtin_decl_implicit (dcode);
+ if (fn)
+ set_user_assembler_name (fn, "___ieee_divdc3");
+ }
+}
+
static hashval_t
cfstring_hash (const void *ptr)
{
darwin_function_section (tree decl, enum node_frequency freq,
bool startup, bool exit)
{
+ /* Decide if we need to put this in a coalescable section. */
+ bool weak = (decl
+ && DECL_WEAK (decl)
+ && (!DECL_ATTRIBUTES (decl)
+ || !lookup_attribute ("weak_import",
+ DECL_ATTRIBUTES (decl))));
+
+ /* If there is a specified section name, we should not be trying to
+ override. */
+ if (decl && DECL_SECTION_NAME (decl) != NULL_TREE)
+ return get_named_section (decl, NULL, 0);
+
+ /* Default when there is no function re-ordering. */
+ if (!flag_reorder_functions)
+ return (weak)
+ ? darwin_sections[text_coal_section]
+ : text_section;
+
/* Startup code should go to startup subsection unless it is
unlikely executed (this happens especially with function splitting
- where we can split away unnecesary parts of static constructors. */
+ where we can split away unnecesary parts of static constructors). */
if (startup && freq != NODE_FREQUENCY_UNLIKELY_EXECUTED)
- return get_named_text_section
- (decl, "__TEXT,__startup,regular,pure_instructions", "_startup");
+ return (weak)
+ ? darwin_sections[text_startup_coal_section]
+ : darwin_sections[text_startup_section];
/* Similarly for exit. */
if (exit && freq != NODE_FREQUENCY_UNLIKELY_EXECUTED)
- return get_named_text_section (decl,
- "__TEXT,__exit,regular,pure_instructions",
- "_exit");
+ return (weak)
+ ? darwin_sections[text_exit_coal_section]
+ : darwin_sections[text_exit_section];
/* Group cold functions together, similarly for hot code. */
switch (freq)
{
case NODE_FREQUENCY_UNLIKELY_EXECUTED:
- return get_named_text_section
- (decl,
- "__TEXT,__unlikely,regular,pure_instructions", "_unlikely");
+ return (weak)
+ ? darwin_sections[text_cold_coal_section]
+ : darwin_sections[text_cold_section];
+ break;
case NODE_FREQUENCY_HOT:
- return get_named_text_section
- (decl, "__TEXT,__hot,regular,pure_instructions", "_hot");
+ return (weak)
+ ? darwin_sections[text_hot_coal_section]
+ : darwin_sections[text_hot_section];
+ break;
default:
- return NULL;
+ return (weak)
+ ? darwin_sections[text_coal_section]
+ : text_section;
+ break;
}
}
+/* When a function is partitioned between sections, we need to insert a label
+ at the start of each new chunk - so that it may become a valid 'atom' for
+ eh and debug purposes. Without this the linker will emit warnings if one
+ tries to add line location information (since the switched fragment will
+ be anonymous). */
+
+void
+darwin_function_switched_text_sections (FILE *fp, tree decl, bool new_is_cold)
+{
+ char buf[128];
+ snprintf (buf, 128, "%s%s",new_is_cold?"__cold_sect_of_":"__hot_sect_of_",
+ IDENTIFIER_POINTER (DECL_NAME (decl)));
+ /* Make sure we pick up all the relevant quotes etc. */
+ assemble_name_raw (fp, (const char *) buf);
+ fputs (":\n", fp);
+}
+
#include "gt-darwin.h"