Commit 5e1b4477 by Bernd Edlinger Committed by Bernd Edlinger

varasm.c (output_constant): Add new parameter merge_strings.

2018-10-04  Bernd Edlinger  <bernd.edlinger@hotmail.de>

        * varasm.c (output_constant): Add new parameter merge_strings.
        Make strings properly zero terminated in merge string sections.
        (mergeable_string_section): Don't fail if the last char is non-zero.
        (assemble_variable_contents): Handle merge string sections.
        (assemble_variable): Likewise.
        (assemble_constant_contents): Likewise.
        (output_constant_def_contents): Likewise.
        (output_constructor_array_range,
        output_constructor_regular_field): Adjust call to output_constant.
        (output_object_block): Adjust call to assemble_constant_contents
        and assemble_variable_contents.

testsuie:
2018-10-04  Bernd Edlinger  <bernd.edlinger@hotmail.de>

        * gnat.dg/string_merge1.adb: New test.
        * gnat.dg/string_merge2.adb: New test.
        * gcc.dg/merge-all-constants-1.c: Adjust test.
        * gcc.dg/merge-all-constants-2.c: New test.

From-SVN: r264850
parent a81a0bfa
2018-10-04 Bernd Edlinger <bernd.edlinger@hotmail.de>
* varasm.c (output_constant): Add new parameter merge_strings.
Make strings properly zero terminated in merge string sections.
(mergeable_string_section): Don't fail if the last char is non-zero.
(assemble_variable_contents): Handle merge string sections.
(assemble_variable): Likewise.
(assemble_constant_contents): Likewise.
(output_constant_def_contents): Likewise.
(output_constructor_array_range,
output_constructor_regular_field): Adjust call to output_constant.
(output_object_block): Adjust call to assemble_constant_contents
and assemble_variable_contents.
2018-10-04 Martin Liska <mliska@suse.cz> 2018-10-04 Martin Liska <mliska@suse.cz>
PR c/87483 PR c/87483
2018-10-04 Bernd Edlinger <bernd.edlinger@hotmail.de>
* gnat.dg/string_merge1.adb: New test.
* gnat.dg/string_merge2.adb: New test.
* gcc.dg/merge-all-constants-1.c: Adjust test.
* gcc.dg/merge-all-constants-2.c: New test.
2018-10-04 Bill Seurer <seurer@linux.vnet.ibm.com> 2018-10-04 Bill Seurer <seurer@linux.vnet.ibm.com>
PR target/87486 PR target/87486
......
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-w -O2 -fmerge-all-constants" } */ /* { dg-options "-w -O2 -fmerge-all-constants" } */
const char str1[36] = "0123456789abcdefghijklmnopqrstuvwxyz"; const char str1[36] = "\000123456789abcdefghijklmnopqrstuvwxyz";
const char str2[38] = "0123456789abcdefghijklmnopqrstuvwxyz"; const char str2[38] = "0123456789abcdefghijklmnopqrstuvwxyz";
const char str3[10] = "0123456789abcdefghijklmnopqrstuvwxyz"; const char str3[10] = "\000123456789abcdefghijklmnopqrstuvwxyz";
/* { dg-final { scan-assembler-not "\.rodata\.str" } } */ /* { dg-final { scan-assembler-not "\\.rodata\\.str" } } */
/* { dg-do compile } */
/* { dg-options "-w -O2 -fmerge-all-constants" } */
const char str1[36] = "0123456789abcdefghijklmnopqrstuvwxyz";
const char str2[37] = "0123456789abcdefghijklmnopqrstuvwxyz";
const char str3[10] = "0123456789abcdefghijklmnopqrstuvwxyz";
/* { dg-final { scan-assembler-not "\\.rodata\[\n\r\]" } } */
-- { dg-do compile }
-- { dg-options "-O1 -fmerge-all-constants" }
procedure String_Merge1 is
procedure Process (X : String);
pragma Import (Ada, Process);
begin
Process ("ABCD");
end;
-- We expect something like:
-- .section .rodata.str1.1,"aMS",@progbits,1
-- .LC1:
-- .string "ABCD"
-- { dg-final { scan-assembler-times "\\.rodata\\.str" 1 } }
-- { dg-final { scan-assembler-times "\\.string" 1 } }
-- { dg-final { scan-assembler-times "\"ABCD\"" 1 } }
-- { dg-do compile }
-- { dg-options "-O1 -fmerge-all-constants" }
procedure String_Merge2 is
procedure Process (X : String);
pragma Import (Ada, Process);
begin
Process ("ABCD" & Ascii.NUL);
end;
-- We expect something like:
-- .section .rodata.str1.1,"aMS",@progbits,1
-- .LC1:
-- .string "ABCD"
-- { dg-final { scan-assembler-times "\\.rodata\\.str" 1 } }
-- { dg-final { scan-assembler-times "\\.string" 1 } }
-- { dg-final { scan-assembler-times "\"ABCD\"" 1 } }
...@@ -111,7 +111,7 @@ static int compare_constant (const tree, const tree); ...@@ -111,7 +111,7 @@ static int compare_constant (const tree, const tree);
static void output_constant_def_contents (rtx); static void output_constant_def_contents (rtx);
static void output_addressed_constants (tree); static void output_addressed_constants (tree);
static unsigned HOST_WIDE_INT output_constant (tree, unsigned HOST_WIDE_INT, static unsigned HOST_WIDE_INT output_constant (tree, unsigned HOST_WIDE_INT,
unsigned int, bool); unsigned int, bool, bool);
static void globalize_decl (tree); static void globalize_decl (tree);
static bool decl_readonly_section_1 (enum section_category); static bool decl_readonly_section_1 (enum section_category);
#ifdef BSS_SECTION_ASM_OP #ifdef BSS_SECTION_ASM_OP
...@@ -804,8 +804,8 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED, ...@@ -804,8 +804,8 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED,
&& TREE_CODE (decl) == STRING_CST && TREE_CODE (decl) == STRING_CST
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
&& align <= 256 && align <= 256
&& (len = int_size_in_bytes (TREE_TYPE (decl))) > 0 && (len = int_size_in_bytes (TREE_TYPE (decl))) >= 0
&& TREE_STRING_LENGTH (decl) >= len) && TREE_STRING_LENGTH (decl) == len)
{ {
scalar_int_mode mode; scalar_int_mode mode;
unsigned int modesize; unsigned int modesize;
...@@ -835,7 +835,7 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED, ...@@ -835,7 +835,7 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED,
if (j == unit) if (j == unit)
break; break;
} }
if (i == len - unit) if (i == len - unit || (unit == 1 && i == len))
{ {
sprintf (name, "%s.str%d.%d", prefix, sprintf (name, "%s.str%d.%d", prefix,
modesize / 8, (int) (align / 8)); modesize / 8, (int) (align / 8));
...@@ -2117,7 +2117,7 @@ assemble_noswitch_variable (tree decl, const char *name, section *sect, ...@@ -2117,7 +2117,7 @@ assemble_noswitch_variable (tree decl, const char *name, section *sect,
static void static void
assemble_variable_contents (tree decl, const char *name, assemble_variable_contents (tree decl, const char *name,
bool dont_output_data) bool dont_output_data, bool merge_strings)
{ {
/* Do any machine/system dependent processing of the object. */ /* Do any machine/system dependent processing of the object. */
#ifdef ASM_DECLARE_OBJECT_NAME #ifdef ASM_DECLARE_OBJECT_NAME
...@@ -2140,7 +2140,7 @@ assemble_variable_contents (tree decl, const char *name, ...@@ -2140,7 +2140,7 @@ assemble_variable_contents (tree decl, const char *name,
output_constant (DECL_INITIAL (decl), output_constant (DECL_INITIAL (decl),
tree_to_uhwi (DECL_SIZE_UNIT (decl)), tree_to_uhwi (DECL_SIZE_UNIT (decl)),
get_variable_align (decl), get_variable_align (decl),
false); false, merge_strings);
else else
/* Leave space for it. */ /* Leave space for it. */
assemble_zeros (tree_to_uhwi (DECL_SIZE_UNIT (decl))); assemble_zeros (tree_to_uhwi (DECL_SIZE_UNIT (decl)));
...@@ -2316,7 +2316,9 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, ...@@ -2316,7 +2316,9 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
switch_to_section (sect); switch_to_section (sect);
if (align > BITS_PER_UNIT) if (align > BITS_PER_UNIT)
ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT)); ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
assemble_variable_contents (decl, name, dont_output_data); assemble_variable_contents (decl, name, dont_output_data,
(sect->common.flags & SECTION_MERGE)
&& (sect->common.flags & SECTION_STRINGS));
if (asan_protected) if (asan_protected)
{ {
unsigned HOST_WIDE_INT int size unsigned HOST_WIDE_INT int size
...@@ -3471,7 +3473,8 @@ maybe_output_constant_def_contents (struct constant_descriptor_tree *desc, ...@@ -3471,7 +3473,8 @@ maybe_output_constant_def_contents (struct constant_descriptor_tree *desc,
constant's alignment in bits. */ constant's alignment in bits. */
static void static void
assemble_constant_contents (tree exp, const char *label, unsigned int align) assemble_constant_contents (tree exp, const char *label, unsigned int align,
bool merge_strings)
{ {
HOST_WIDE_INT size; HOST_WIDE_INT size;
...@@ -3481,7 +3484,7 @@ assemble_constant_contents (tree exp, const char *label, unsigned int align) ...@@ -3481,7 +3484,7 @@ assemble_constant_contents (tree exp, const char *label, unsigned int align)
targetm.asm_out.declare_constant_name (asm_out_file, label, exp, size); targetm.asm_out.declare_constant_name (asm_out_file, label, exp, size);
/* Output the value of EXP. */ /* Output the value of EXP. */
output_constant (exp, size, align, false); output_constant (exp, size, align, false, merge_strings);
targetm.asm_out.decl_end (); targetm.asm_out.decl_end ();
} }
...@@ -3522,10 +3525,13 @@ output_constant_def_contents (rtx symbol) ...@@ -3522,10 +3525,13 @@ output_constant_def_contents (rtx symbol)
|| (VAR_P (decl) && DECL_IN_CONSTANT_POOL (decl)) || (VAR_P (decl) && DECL_IN_CONSTANT_POOL (decl))
? DECL_ALIGN (decl) ? DECL_ALIGN (decl)
: symtab_node::get (decl)->definition_alignment ()); : symtab_node::get (decl)->definition_alignment ());
switch_to_section (get_constant_section (exp, align)); section *sect = get_constant_section (exp, align);
switch_to_section (sect);
if (align > BITS_PER_UNIT) if (align > BITS_PER_UNIT)
ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT)); ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
assemble_constant_contents (exp, XSTR (symbol, 0), align); assemble_constant_contents (exp, XSTR (symbol, 0), align,
(sect->common.flags & SECTION_MERGE)
&& (sect->common.flags & SECTION_STRINGS));
if (asan_protected) if (asan_protected)
{ {
HOST_WIDE_INT size = get_constant_size (exp); HOST_WIDE_INT size = get_constant_size (exp);
...@@ -4838,7 +4844,7 @@ output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int, bool, ...@@ -4838,7 +4844,7 @@ output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int, bool,
static unsigned HOST_WIDE_INT static unsigned HOST_WIDE_INT
output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align, output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
bool reverse) bool reverse, bool merge_strings)
{ {
enum tree_code code; enum tree_code code;
unsigned HOST_WIDE_INT thissize; unsigned HOST_WIDE_INT thissize;
...@@ -4953,10 +4959,11 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align, ...@@ -4953,10 +4959,11 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
break; break;
case COMPLEX_TYPE: case COMPLEX_TYPE:
output_constant (TREE_REALPART (exp), thissize / 2, align, reverse); output_constant (TREE_REALPART (exp), thissize / 2, align,
reverse, false);
output_constant (TREE_IMAGPART (exp), thissize / 2, output_constant (TREE_IMAGPART (exp), thissize / 2,
min_align (align, BITS_PER_UNIT * (thissize / 2)), min_align (align, BITS_PER_UNIT * (thissize / 2)),
reverse); reverse, false);
break; break;
case ARRAY_TYPE: case ARRAY_TYPE:
...@@ -4966,8 +4973,11 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align, ...@@ -4966,8 +4973,11 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
case CONSTRUCTOR: case CONSTRUCTOR:
return output_constructor (exp, size, align, reverse, NULL); return output_constructor (exp, size, align, reverse, NULL);
case STRING_CST: case STRING_CST:
thissize thissize = (unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp);
= MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp), size); if (merge_strings
&& (thissize == 0
|| TREE_STRING_POINTER (exp) [thissize - 1] != '\0'))
thissize++;
gcc_checking_assert (check_string_literal (exp, size)); gcc_checking_assert (check_string_literal (exp, size));
assemble_string (TREE_STRING_POINTER (exp), thissize); assemble_string (TREE_STRING_POINTER (exp), thissize);
break; break;
...@@ -4977,14 +4987,14 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align, ...@@ -4977,14 +4987,14 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
unsigned int nalign = MIN (align, GET_MODE_ALIGNMENT (inner)); unsigned int nalign = MIN (align, GET_MODE_ALIGNMENT (inner));
int elt_size = GET_MODE_SIZE (inner); int elt_size = GET_MODE_SIZE (inner);
output_constant (VECTOR_CST_ELT (exp, 0), elt_size, align, output_constant (VECTOR_CST_ELT (exp, 0), elt_size, align,
reverse); reverse, false);
thissize = elt_size; thissize = elt_size;
/* Static constants must have a fixed size. */ /* Static constants must have a fixed size. */
unsigned int nunits = VECTOR_CST_NELTS (exp).to_constant (); unsigned int nunits = VECTOR_CST_NELTS (exp).to_constant ();
for (unsigned int i = 1; i < nunits; i++) for (unsigned int i = 1; i < nunits; i++)
{ {
output_constant (VECTOR_CST_ELT (exp, i), elt_size, nalign, output_constant (VECTOR_CST_ELT (exp, i), elt_size, nalign,
reverse); reverse, false);
thissize += elt_size; thissize += elt_size;
} }
break; break;
...@@ -5105,8 +5115,8 @@ output_constructor_array_range (oc_local_state *local) ...@@ -5105,8 +5115,8 @@ output_constructor_array_range (oc_local_state *local)
if (local->val == NULL_TREE) if (local->val == NULL_TREE)
assemble_zeros (fieldsize); assemble_zeros (fieldsize);
else else
fieldsize fieldsize = output_constant (local->val, fieldsize, align2,
= output_constant (local->val, fieldsize, align2, local->reverse); local->reverse, false);
/* Count its size. */ /* Count its size. */
local->total_bytes += fieldsize; local->total_bytes += fieldsize;
...@@ -5201,8 +5211,8 @@ output_constructor_regular_field (oc_local_state *local) ...@@ -5201,8 +5211,8 @@ output_constructor_regular_field (oc_local_state *local)
if (local->val == NULL_TREE) if (local->val == NULL_TREE)
assemble_zeros (fieldsize); assemble_zeros (fieldsize);
else else
fieldsize fieldsize = output_constant (local->val, fieldsize, align2,
= output_constant (local->val, fieldsize, align2, local->reverse); local->reverse, false);
/* Count its size. */ /* Count its size. */
local->total_bytes += fieldsize; local->total_bytes += fieldsize;
...@@ -7618,8 +7628,8 @@ output_object_block (struct object_block *block) ...@@ -7618,8 +7628,8 @@ output_object_block (struct object_block *block)
{ {
HOST_WIDE_INT size; HOST_WIDE_INT size;
decl = SYMBOL_REF_DECL (symbol); decl = SYMBOL_REF_DECL (symbol);
assemble_constant_contents assemble_constant_contents (DECL_INITIAL (decl), XSTR (symbol, 0),
(DECL_INITIAL (decl), XSTR (symbol, 0), DECL_ALIGN (decl)); DECL_ALIGN (decl), false);
size = get_constant_size (DECL_INITIAL (decl)); size = get_constant_size (DECL_INITIAL (decl));
offset += size; offset += size;
...@@ -7636,7 +7646,7 @@ output_object_block (struct object_block *block) ...@@ -7636,7 +7646,7 @@ output_object_block (struct object_block *block)
{ {
HOST_WIDE_INT size; HOST_WIDE_INT size;
decl = SYMBOL_REF_DECL (symbol); decl = SYMBOL_REF_DECL (symbol);
assemble_variable_contents (decl, XSTR (symbol, 0), false); assemble_variable_contents (decl, XSTR (symbol, 0), false, false);
size = tree_to_uhwi (DECL_SIZE_UNIT (decl)); size = tree_to_uhwi (DECL_SIZE_UNIT (decl));
offset += size; offset += size;
if ((flag_sanitize & SANITIZE_ADDRESS) if ((flag_sanitize & SANITIZE_ADDRESS)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment