diff options
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r-- | gcc/varasm.c | 312 |
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); +} |