aboutsummaryrefslogtreecommitdiff
path: root/gcc/varasm.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r--gcc/varasm.c137
1 files changed, 125 insertions, 12 deletions
diff --git a/gcc/varasm.c b/gcc/varasm.c
index a95994c..defa0c6 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -560,7 +560,7 @@ variable_section (decl, reloc)
for them. */
#ifdef SELECT_SECTION
- SELECT_SECTION (decl, reloc);
+ SELECT_SECTION (decl, reloc, DECL_ALIGN (decl));
#else
if (DECL_READONLY_SECTION (decl, reloc))
readonly_data_section ();
@@ -587,6 +587,111 @@ exception_section ()
readonly_data_section ();
#endif
}
+
+/* Tell assembler to switch to the section for string merging. */
+
+void
+mergeable_string_section (decl, align, flags)
+ tree decl ATTRIBUTE_UNUSED;
+ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
+ unsigned int flags ATTRIBUTE_UNUSED;
+{
+#ifdef HAVE_GAS_SHF_MERGE
+ if (flag_merge_constants
+ && TREE_CODE (decl) == STRING_CST
+ && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
+ && align <= 256
+ && TREE_STRING_LENGTH (decl) >= int_size_in_bytes (TREE_TYPE (decl)))
+ {
+ enum machine_mode mode;
+ unsigned int modesize;
+ const char *str;
+ int i, j, len, unit;
+ char name[30];
+
+ mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (decl)));
+ modesize = GET_MODE_BITSIZE (mode);
+ if (modesize >= 8 && modesize <= 256
+ && (modesize & (modesize - 1)) == 0)
+ {
+ if (align < modesize)
+ align = modesize;
+
+ str = TREE_STRING_POINTER (decl);
+ len = TREE_STRING_LENGTH (decl);
+ unit = GET_MODE_SIZE (mode);
+
+ /* Check for embedded NUL characters. */
+ for (i = 0; i < len; i += unit)
+ {
+ for (j = 0; j < unit; j++)
+ if (str [i + j] != '\0')
+ break;
+ if (j == unit)
+ break;
+ }
+ if (i == len - unit)
+ {
+ sprintf (name, ".rodata.str%d.%d", modesize / 8,
+ (int) (align / 8));
+ flags |= (modesize / 8) | SECTION_MERGE | SECTION_STRINGS;
+ if (!i && modesize < align)
+ {
+ /* A "" string with requested alignment greater than
+ character size might cause a problem:
+ if some other string required even bigger
+ alignment than "", then linker might think the
+ "" is just part of padding after some other string
+ and not put it into the hash table initially.
+ But this means "" could have smaller alignment
+ than requested. */
+#ifdef ASM_OUTPUT_SECTION_START
+ named_section_flags (name, flags);
+ ASM_OUTPUT_SECTION_START (asm_out_file);
+#else
+ readonly_data_section ();
+#endif
+ return;
+ }
+
+ named_section_flags (name, flags);
+ return;
+ }
+ }
+ }
+#endif
+ readonly_data_section ();
+}
+
+/* Tell assembler to switch to the section for constant merging. */
+
+void
+mergeable_constant_section (mode, align, flags)
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED;
+ unsigned int flags ATTRIBUTE_UNUSED;
+{
+#ifdef HAVE_GAS_SHF_MERGE
+ unsigned int modesize = GET_MODE_BITSIZE (mode);
+
+ if (flag_merge_constants
+ && mode != VOIDmode
+ && mode != BLKmode
+ && modesize <= align
+ && align >= 8
+ && align <= 256
+ && (align & (align - 1)) == 0)
+ {
+ char name[24];
+
+ sprintf (name, ".rodata.cst%d", (int) (align / 8));
+ flags |= (align / 8) | SECTION_MERGE;
+ named_section_flags (name, flags);
+ return;
+ }
+#endif
+ readonly_data_section ();
+}
/* Given NAME, a putative register name, discard any customary prefixes. */
@@ -3305,13 +3410,19 @@ output_constant_def_contents (exp, reloc, labelno)
{
int align;
+ /* Align the location counter as required by EXP's data type. */
+ align = TYPE_ALIGN (TREE_TYPE (exp));
+#ifdef CONSTANT_ALIGNMENT
+ align = CONSTANT_ALIGNMENT (exp, align);
+#endif
+
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);
+ SELECT_SECTION (exp, reloc, align);
#else
if (((TREE_CODE (exp) == STRING_CST) && flag_writable_strings)
|| (flag_pic && reloc))
@@ -3321,12 +3432,6 @@ output_constant_def_contents (exp, reloc, labelno)
#endif
}
- /* Align the location counter as required by EXP's data type. */
- align = TYPE_ALIGN (TREE_TYPE (exp));
-#ifdef CONSTANT_ALIGNMENT
- align = CONSTANT_ALIGNMENT (exp, align);
-#endif
-
if (align > BITS_PER_UNIT)
ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
@@ -3877,7 +3982,7 @@ output_constant_pool (fnname, fndecl)
/* First switch to correct section. */
#ifdef SELECT_RTX_SECTION
- SELECT_RTX_SECTION (pool->mode, x);
+ SELECT_RTX_SECTION (pool->mode, x, pool->align);
#else
readonly_data_section ();
#endif
@@ -5060,7 +5165,7 @@ default_elf_asm_named_section (name, flags)
const char *name;
unsigned int flags;
{
- char flagchars[8], *f = flagchars;
+ char flagchars[10], *f = flagchars;
const char *type;
if (!(flags & SECTION_DEBUG))
@@ -5071,6 +5176,10 @@ default_elf_asm_named_section (name, flags)
*f++ = 'x';
if (flags & SECTION_SMALL)
*f++ = 's';
+ if (flags & SECTION_MERGE)
+ *f++ = 'M';
+ if (flags & SECTION_STRINGS)
+ *f++ = 'S';
*f = '\0';
if (flags & SECTION_BSS)
@@ -5078,8 +5187,12 @@ default_elf_asm_named_section (name, flags)
else
type = "progbits";
- fprintf (asm_out_file, "\t.section\t%s,\"%s\",@%s\n",
- name, flagchars, type);
+ if (flags & SECTION_ENTSIZE)
+ fprintf (asm_out_file, "\t.section\t%s,\"%s\",@%s,%d\n",
+ name, flagchars, type, flags & SECTION_ENTSIZE);
+ else
+ fprintf (asm_out_file, "\t.section\t%s,\"%s\",@%s\n",
+ name, flagchars, type);
}
void