aboutsummaryrefslogtreecommitdiff
path: root/gcc/varasm.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/varasm.cc')
-rw-r--r--gcc/varasm.cc87
1 files changed, 69 insertions, 18 deletions
diff --git a/gcc/varasm.cc b/gcc/varasm.cc
index 8266282..0d78f5b 100644
--- a/gcc/varasm.cc
+++ b/gcc/varasm.cc
@@ -871,7 +871,7 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED,
if (HAVE_GAS_SHF_MERGE && flag_merge_constants
&& TREE_CODE (decl) == STRING_CST
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
- && align <= 256
+ && align <= MAX_MERGEABLE_BITSIZE
&& (len = int_size_in_bytes (TREE_TYPE (decl))) > 0
&& TREE_STRING_LENGTH (decl) == len)
{
@@ -885,7 +885,7 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED,
mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (TREE_TYPE (decl)));
modesize = GET_MODE_BITSIZE (mode);
- if (modesize >= 8 && modesize <= 256
+ if (modesize >= 8 && modesize <= MAX_MERGEABLE_BITSIZE
&& (modesize & (modesize - 1)) == 0)
{
if (align < modesize)
@@ -906,8 +906,8 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED,
if (i == len - unit || (unit == 1 && i == len))
{
sprintf (name, "%s.str%d.%d", prefix,
- modesize / 8, (int) (align / 8));
- flags |= (modesize / 8) | SECTION_MERGE | SECTION_STRINGS;
+ modesize / BITS_PER_UNIT, (int) (align / BITS_PER_UNIT));
+ flags |= (modesize / BITS_PER_UNIT) | SECTION_MERGE | SECTION_STRINGS;
return get_section (name, flags, NULL);
}
}
@@ -919,27 +919,59 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED,
/* Return the section to use for constant merging. */
section *
-mergeable_constant_section (machine_mode mode ATTRIBUTE_UNUSED,
- unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED,
- unsigned int flags ATTRIBUTE_UNUSED)
+mergeable_constant_section (unsigned HOST_WIDE_INT size_bits,
+ unsigned HOST_WIDE_INT align,
+ unsigned int flags)
{
+ unsigned HOST_WIDE_INT newsize;
+ newsize = HOST_WIDE_INT_1U << ceil_log2 (size_bits);
if (HAVE_GAS_SHF_MERGE && flag_merge_constants
- && mode != VOIDmode
- && mode != BLKmode
- && known_le (GET_MODE_BITSIZE (mode), align)
+ && newsize <= MAX_MERGEABLE_BITSIZE
&& align >= 8
- && align <= 256
+ && align <= newsize
&& (align & (align - 1)) == 0)
{
const char *prefix = function_mergeable_rodata_prefix ();
char *name = (char *) alloca (strlen (prefix) + 30);
- sprintf (name, "%s.cst%d", prefix, (int) (align / 8));
- flags |= (align / 8) | SECTION_MERGE;
+ sprintf (name, "%s.cst%d", prefix, (int) (newsize / BITS_PER_UNIT));
+ flags |= (newsize / BITS_PER_UNIT) | SECTION_MERGE;
return get_section (name, flags, NULL);
}
return readonly_data_section;
}
+
+
+/* Return the section to use for constant merging. Like the above
+ but the size stored as a tree. */
+static section *
+mergeable_constant_section (tree size_bits,
+ unsigned HOST_WIDE_INT align,
+ unsigned int flags)
+{
+ if (!size_bits || !tree_fits_uhwi_p (size_bits))
+ return readonly_data_section;
+ return mergeable_constant_section (tree_to_uhwi (size_bits), align, flags);
+}
+
+
+/* Return the section to use for constant merging. Like the above
+ but given a mode rather than the size. */
+
+section *
+mergeable_constant_section (machine_mode mode,
+ unsigned HOST_WIDE_INT align,
+ unsigned int flags)
+{
+ /* If the mode is unknown (BLK or VOID), then return a non mergable section. */
+ if (mode == BLKmode || mode == VOIDmode)
+ return readonly_data_section;
+ unsigned HOST_WIDE_INT size;
+ if (!GET_MODE_BITSIZE (mode).is_constant (&size))
+ return readonly_data_section;
+ return mergeable_constant_section (size, align, flags);
+}
+
/* Given NAME, a putative register name, discard any customary prefixes. */
@@ -2445,6 +2477,19 @@ assemble_variable_contents (tree decl, const char *name,
else
/* Leave space for it. */
assemble_zeros (tree_to_uhwi (DECL_SIZE_UNIT (decl)));
+ /* For mergeable section, make sure the section is zero filled up to
+ the entity size of the section. */
+ if (in_section
+ && (in_section->common.flags & SECTION_MERGE)
+ && tree_fits_uhwi_p (DECL_SIZE_UNIT (decl))
+ && ((in_section->common.flags & SECTION_ENTSIZE)
+ > tree_to_uhwi (DECL_SIZE_UNIT (decl))))
+ {
+ unsigned HOST_WIDE_INT entsize, declsize;
+ entsize = (in_section->common.flags & SECTION_ENTSIZE);
+ declsize = tree_to_uhwi (DECL_SIZE_UNIT (decl));
+ assemble_zeros (entsize - declsize);
+ }
targetm.asm_out.decl_end ();
}
}
@@ -4405,10 +4450,16 @@ output_constant_pool_1 (class constant_descriptor_rtx *desc,
/* Make sure all constants in SECTION_MERGE and not SECTION_STRINGS
sections have proper size. */
- if (align > GET_MODE_BITSIZE (desc->mode)
- && in_section
- && (in_section->common.flags & SECTION_MERGE))
- assemble_align (align);
+ if (in_section
+ && (in_section->common.flags & SECTION_MERGE)
+ && ((in_section->common.flags & SECTION_ENTSIZE)
+ > GET_MODE_SIZE (desc->mode)))
+ {
+ unsigned HOST_WIDE_INT entsize, constsize;
+ entsize = (in_section->common.flags & SECTION_ENTSIZE);
+ constsize = GET_MODE_SIZE (desc->mode);
+ assemble_zeros (entsize - constsize);
+ }
#ifdef ASM_OUTPUT_SPECIAL_POOL_ENTRY
done:
@@ -7453,7 +7504,7 @@ default_elf_select_section (tree decl, int reloc,
case SECCAT_RODATA_MERGE_STR_INIT:
return mergeable_string_section (DECL_INITIAL (decl), align, 0);
case SECCAT_RODATA_MERGE_CONST:
- return mergeable_constant_section (DECL_MODE (decl), align, 0);
+ return mergeable_constant_section (DECL_SIZE (decl), align, 0);
case SECCAT_SRODATA:
sname = ".sdata2";
break;