aboutsummaryrefslogtreecommitdiff
path: root/gcc/varasm.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r--gcc/varasm.c312
1 files changed, 271 insertions, 41 deletions
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 4a88412..e13efe0 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -465,10 +465,10 @@ resolve_unique_section (decl, reloc, flag_function_or_data_sections)
int flag_function_or_data_sections;
{
if (DECL_SECTION_NAME (decl) == NULL_TREE
+ && targetm.have_named_sections
&& (flag_function_or_data_sections
- || (targetm.have_named_sections
- && DECL_ONE_ONLY (decl))))
- UNIQUE_SECTION (decl, reloc);
+ || DECL_ONE_ONLY (decl)))
+ (*targetm.asm_out.unique_section) (decl, reloc);
}
#ifdef BSS_SECTION_ASM_OP
@@ -567,9 +567,8 @@ function_section (decl)
text_section ();
}
-/* Switch to section for variable DECL.
-
- RELOC is the `reloc' argument to SELECT_SECTION. */
+/* Switch to section for variable DECL. RELOC is the same as the
+ argument to SELECT_SECTION. */
void
variable_section (decl, reloc)
@@ -579,29 +578,7 @@ variable_section (decl, reloc)
if (IN_NAMED_SECTION (decl))
named_section (decl, NULL, reloc);
else
- {
- /* C++ can have const variables that get initialized from constructors,
- and thus can not be in a readonly section. We prevent this by
- verifying that the initial value is constant for objects put in a
- readonly section.
-
- error_mark_node is used by the C front end to indicate that the
- initializer has not been seen yet. In this case, we assume that
- the initializer must be constant.
-
- C++ uses error_mark_node for variables that have complicated
- initializers, but these variables go in BSS so we won't be called
- for them. */
-
-#ifdef SELECT_SECTION
- SELECT_SECTION (decl, reloc, DECL_ALIGN (decl));
-#else
- if (DECL_READONLY_SECTION (decl, reloc))
- readonly_data_section ();
- else
- data_section ();
-#endif
- }
+ (*targetm.asm_out.select_section) (decl, reloc, DECL_ALIGN (decl));
}
/* Tell assembler to switch to the section for the exception handling
@@ -3211,18 +3188,7 @@ output_constant_def_contents (exp, reloc, labelno)
if (IN_NAMED_SECTION (exp))
named_section (exp, NULL, reloc);
else
- {
- /* First switch to text section, except for writable strings. */
-#ifdef SELECT_SECTION
- SELECT_SECTION (exp, reloc, align);
-#else
- if (((TREE_CODE (exp) == STRING_CST) && flag_writable_strings)
- || (flag_pic && reloc))
- data_section ();
- else
- readonly_data_section ();
-#endif
- }
+ (*targetm.asm_out.select_section) (exp, reloc, align);
if (align > BITS_PER_UNIT)
{
@@ -5254,3 +5220,267 @@ assemble_vtable_inherit (child, parent)
output_addr_const (asm_out_file, parent);
fputc ('\n', asm_out_file);
}
+
+/* The lame default section selector. */
+
+void
+default_select_section (decl, reloc, align)
+ tree decl;
+ int reloc;
+ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
+{
+ bool readonly = false;
+
+ if (DECL_P (decl))
+ {
+ if (DECL_READONLY_SECTION (decl, reloc))
+ readonly = true;
+ }
+ else if (TREE_CODE (decl) == CONSTRUCTOR)
+ {
+ if (! ((flag_pic && reloc)
+ || !TREE_READONLY (decl)
+ || TREE_SIDE_EFFECTS (decl)
+ || !TREE_CONSTANT (decl)))
+ readonly = true;
+ }
+ else if (TREE_CODE (decl) == STRING_CST)
+ readonly = !flag_writable_strings;
+ else if (! (flag_pic && reloc))
+ readonly = true;
+
+ if (readonly)
+ readonly_data_section ();
+ else
+ data_section ();
+}
+
+/* A helper function for default_elf_select_section and
+ default_elf_unique_section. Categorizes the DECL. */
+
+enum section_category
+{
+ SECCAT_TEXT,
+
+ SECCAT_RODATA,
+ SECCAT_RODATA_MERGE_STR,
+ SECCAT_RODATA_MERGE_STR_INIT,
+ SECCAT_RODATA_MERGE_CONST,
+
+ SECCAT_DATA,
+
+ /* To optimize loading of shared programs, define following subsections
+ of data section:
+ _REL Contains data that has relocations, so they get grouped
+ together and dynamic linker will visit fewer pages in memory.
+ _RO Contains data that is otherwise read-only. This is useful
+ with prelinking as most relocations won't be dynamically
+ linked and thus stay read only.
+ _LOCAL Marks data containing relocations only to local objects.
+ These relocations will get fully resolved by prelinking. */
+ SECCAT_DATA_REL,
+ SECCAT_DATA_REL_LOCAL,
+ SECCAT_DATA_REL_RO,
+ SECCAT_DATA_REL_RO_LOCAL,
+
+ SECCAT_SDATA,
+ SECCAT_TDATA,
+
+ SECCAT_BSS,
+ SECCAT_SBSS,
+ SECCAT_TBSS
+};
+
+static enum section_category categorize_decl_for_section PARAMS ((tree, int));
+
+static enum section_category
+categorize_decl_for_section (decl, reloc)
+ tree decl;
+ int reloc;
+{
+ enum section_category ret;
+
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ return SECCAT_TEXT;
+ else if (TREE_CODE (decl) == STRING_CST)
+ {
+ if (flag_writable_strings)
+ return SECCAT_DATA;
+ else
+ return SECCAT_RODATA_MERGE_STR;
+ }
+ else if (TREE_CODE (decl) == VAR_DECL)
+ {
+ if (DECL_INITIAL (decl) == NULL
+ || DECL_INITIAL (decl) == error_mark_node)
+ ret = SECCAT_BSS;
+ else if (! TREE_READONLY (decl)
+ || TREE_SIDE_EFFECTS (decl)
+ || ! TREE_CONSTANT (DECL_INITIAL (decl)))
+ {
+ if (flag_pic && (reloc & 2))
+ ret = SECCAT_DATA_REL;
+ else if (flag_pic && reloc)
+ ret = SECCAT_DATA_REL_LOCAL;
+ else
+ ret = SECCAT_DATA;
+ }
+ else if (flag_pic && (reloc & 2))
+ ret = SECCAT_DATA_REL_RO;
+ else if (flag_pic && reloc)
+ ret = SECCAT_DATA_REL_RO_LOCAL;
+ else if (flag_merge_constants < 2)
+ /* C and C++ don't allow different variables to share the same
+ location. -fmerge-all-constants allows even that (at the
+ expense of not conforming). */
+ ret = SECCAT_RODATA;
+ else if (TREE_CODE (DECL_INITIAL (decl)) == STRING_CST)
+ ret = SECCAT_RODATA_MERGE_STR_INIT;
+ else
+ ret = SECCAT_RODATA_MERGE_CONST;
+ }
+ else if (TREE_CODE (decl) == CONSTRUCTOR)
+ {
+ if ((flag_pic && reloc)
+ || TREE_SIDE_EFFECTS (decl)
+ || ! TREE_CONSTANT (decl))
+ ret = SECCAT_DATA;
+ else
+ ret = SECCAT_RODATA;
+ }
+ else
+ ret = SECCAT_RODATA;
+
+ /* If the target uses small data sections, select it. */
+ if ((*targetm.in_small_data_p) (decl))
+ {
+ if (ret == SECCAT_BSS)
+ ret = SECCAT_SBSS;
+ else
+ ret = SECCAT_SDATA;
+ }
+
+ return ret;
+}
+
+/* Select a section based on the above categorization. */
+
+void
+default_elf_select_section (decl, reloc, align)
+ tree decl;
+ int reloc;
+ unsigned HOST_WIDE_INT align;
+{
+ switch (categorize_decl_for_section (decl, reloc))
+ {
+ case SECCAT_TEXT:
+ /* We're not supposed to be called on FUNCTION_DECLs. */
+ abort ();
+ case SECCAT_RODATA:
+ readonly_data_section ();
+ break;
+ case SECCAT_RODATA_MERGE_STR:
+ mergeable_string_section (decl, align, 0);
+ break;
+ case SECCAT_RODATA_MERGE_STR_INIT:
+ mergeable_string_section (DECL_INITIAL (decl), align, 0);
+ break;
+ case SECCAT_RODATA_MERGE_CONST:
+ mergeable_constant_section (DECL_MODE (decl), align, 0);
+ break;
+ case SECCAT_DATA:
+ data_section ();
+ break;
+ case SECCAT_DATA_REL:
+ named_section (NULL_TREE, ".data.rel", reloc);
+ break;
+ case SECCAT_DATA_REL_LOCAL:
+ named_section (NULL_TREE, ".data.rel.local", reloc);
+ break;
+ case SECCAT_DATA_REL_RO:
+ named_section (NULL_TREE, ".data.rel.ro", reloc);
+ break;
+ case SECCAT_DATA_REL_RO_LOCAL:
+ named_section (NULL_TREE, ".data.rel.ro.local", reloc);
+ break;
+ case SECCAT_SDATA:
+ named_section (NULL_TREE, ".sdata", reloc);
+ break;
+ case SECCAT_TDATA:
+ named_section (NULL_TREE, ".tdata", reloc);
+ break;
+ case SECCAT_BSS:
+#ifdef BSS_SECTION_ASM_OP
+ bss_section ();
+#else
+ named_section (NULL_TREE, ".bss", reloc);
+#endif
+ break;
+ case SECCAT_SBSS:
+ named_section (NULL_TREE, ".sbss", reloc);
+ break;
+ case SECCAT_TBSS:
+ named_section (NULL_TREE, ".tbss", reloc);
+ break;
+ default:
+ abort ();
+ }
+}
+
+/* Construct a unique section name based on the decl name and the
+ categorization performed above. */
+
+void
+default_unique_section (decl, reloc)
+ tree decl;
+ int reloc;
+{
+ bool one_only = DECL_ONE_ONLY (decl);
+ const char *prefix, *name;
+ size_t nlen, plen;
+ char *string;
+
+ switch (categorize_decl_for_section (decl, reloc))
+ {
+ case SECCAT_TEXT:
+ prefix = one_only ? ".gnu.linkonce.t." : ".text.";
+ break;
+ case SECCAT_RODATA:
+ case SECCAT_RODATA_MERGE_STR:
+ case SECCAT_RODATA_MERGE_STR_INIT:
+ case SECCAT_RODATA_MERGE_CONST:
+ prefix = one_only ? ".gnu.linkonce.r." : ".rodata.";
+ break;
+ case SECCAT_DATA:
+ case SECCAT_DATA_REL:
+ case SECCAT_DATA_REL_LOCAL:
+ case SECCAT_DATA_REL_RO:
+ case SECCAT_DATA_REL_RO_LOCAL:
+ prefix = one_only ? ".gnu.linkonce.d." : ".data.";
+ break;
+ case SECCAT_SDATA:
+ prefix = one_only ? ".gnu.linkonce.s." : ".sdata.";
+ break;
+ case SECCAT_BSS:
+ prefix = one_only ? ".gnu.linkonce.b." : ".bss.";
+ break;
+ case SECCAT_SBSS:
+ prefix = one_only ? ".gnu.linkonce.sb." : ".sbss.";
+ break;
+ case SECCAT_TDATA:
+ case SECCAT_TBSS:
+ default:
+ abort ();
+ }
+ plen = strlen (prefix);
+
+ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ STRIP_NAME_ENCODING (name, name);
+ nlen = strlen (name);
+
+ string = alloca (nlen + plen + 1);
+ memcpy (string, prefix, plen);
+ memcpy (string + plen, name, nlen + 1);
+
+ DECL_SECTION_NAME (decl) = build_string (nlen + plen, string);
+}