From 5e1b4477fa0c1eca86d2b67808ffee5ac969acd4 Mon Sep 17 00:00:00 2001 From: Bernd Edlinger Date: Thu, 4 Oct 2018 17:34:56 +0000 Subject: [PATCH] varasm.c (output_constant): Add new parameter merge_strings. 2018-10-04 Bernd Edlinger * 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 * 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 --- gcc/ChangeLog | 14 +++++ gcc/testsuite/ChangeLog | 7 +++ gcc/testsuite/gcc.dg/merge-all-constants-1.c | 6 +- gcc/testsuite/gcc.dg/merge-all-constants-2.c | 8 +++ gcc/testsuite/gnat.dg/string_merge1.adb | 19 +++++++ gcc/testsuite/gnat.dg/string_merge2.adb | 19 +++++++ gcc/varasm.c | 60 ++++++++++++-------- 7 files changed, 105 insertions(+), 28 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/merge-all-constants-2.c create mode 100644 gcc/testsuite/gnat.dg/string_merge1.adb create mode 100644 gcc/testsuite/gnat.dg/string_merge2.adb diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d0112655d3c..0f6cbedbf0c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,17 @@ +2018-10-04 Bernd Edlinger + + * 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 PR c/87483 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cd10feec8b3..f15042f64b0 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2018-10-04 Bernd Edlinger + + * 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 PR target/87486 diff --git a/gcc/testsuite/gcc.dg/merge-all-constants-1.c b/gcc/testsuite/gcc.dg/merge-all-constants-1.c index 5c9cd06e925..53f6c4d0a0a 100644 --- a/gcc/testsuite/gcc.dg/merge-all-constants-1.c +++ b/gcc/testsuite/gcc.dg/merge-all-constants-1.c @@ -1,8 +1,8 @@ /* { dg-do compile } */ /* { dg-options "-w -O2 -fmerge-all-constants" } */ -const char str1[36] = "0123456789abcdefghijklmnopqrstuvwxyz"; +const char str1[36] = "\000123456789abcdefghijklmnopqrstuvwxyz"; 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" } } */ diff --git a/gcc/testsuite/gcc.dg/merge-all-constants-2.c b/gcc/testsuite/gcc.dg/merge-all-constants-2.c new file mode 100644 index 00000000000..fbdb2bb5172 --- /dev/null +++ b/gcc/testsuite/gcc.dg/merge-all-constants-2.c @@ -0,0 +1,8 @@ +/* { 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\]" } } */ diff --git a/gcc/testsuite/gnat.dg/string_merge1.adb b/gcc/testsuite/gnat.dg/string_merge1.adb new file mode 100644 index 00000000000..f67c7c15601 --- /dev/null +++ b/gcc/testsuite/gnat.dg/string_merge1.adb @@ -0,0 +1,19 @@ +-- { 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 } } diff --git a/gcc/testsuite/gnat.dg/string_merge2.adb b/gcc/testsuite/gnat.dg/string_merge2.adb new file mode 100644 index 00000000000..bbec00501c0 --- /dev/null +++ b/gcc/testsuite/gnat.dg/string_merge2.adb @@ -0,0 +1,19 @@ +-- { 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 } } diff --git a/gcc/varasm.c b/gcc/varasm.c index e46bc5930fc..c789a03e1f3 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -111,7 +111,7 @@ static int compare_constant (const tree, const tree); static void output_constant_def_contents (rtx); static void output_addressed_constants (tree); 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 bool decl_readonly_section_1 (enum section_category); #ifdef BSS_SECTION_ASM_OP @@ -804,8 +804,8 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED, && TREE_CODE (decl) == STRING_CST && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE && align <= 256 - && (len = int_size_in_bytes (TREE_TYPE (decl))) > 0 - && TREE_STRING_LENGTH (decl) >= len) + && (len = int_size_in_bytes (TREE_TYPE (decl))) >= 0 + && TREE_STRING_LENGTH (decl) == len) { scalar_int_mode mode; unsigned int modesize; @@ -835,7 +835,7 @@ mergeable_string_section (tree decl ATTRIBUTE_UNUSED, if (j == unit) break; } - if (i == len - unit) + if (i == len - unit || (unit == 1 && i == len)) { sprintf (name, "%s.str%d.%d", prefix, modesize / 8, (int) (align / 8)); @@ -2117,7 +2117,7 @@ assemble_noswitch_variable (tree decl, const char *name, section *sect, static void 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. */ #ifdef ASM_DECLARE_OBJECT_NAME @@ -2140,7 +2140,7 @@ assemble_variable_contents (tree decl, const char *name, output_constant (DECL_INITIAL (decl), tree_to_uhwi (DECL_SIZE_UNIT (decl)), get_variable_align (decl), - false); + false, merge_strings); else /* Leave space for it. */ assemble_zeros (tree_to_uhwi (DECL_SIZE_UNIT (decl))); @@ -2316,7 +2316,9 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, switch_to_section (sect); if (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) { unsigned HOST_WIDE_INT int size @@ -3471,7 +3473,8 @@ maybe_output_constant_def_contents (struct constant_descriptor_tree *desc, constant's alignment in bits. */ 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; @@ -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); /* Output the value of EXP. */ - output_constant (exp, size, align, false); + output_constant (exp, size, align, false, merge_strings); targetm.asm_out.decl_end (); } @@ -3522,10 +3525,13 @@ output_constant_def_contents (rtx symbol) || (VAR_P (decl) && DECL_IN_CONSTANT_POOL (decl)) ? DECL_ALIGN (decl) : 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) 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) { HOST_WIDE_INT size = get_constant_size (exp); @@ -4838,7 +4844,7 @@ output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int, bool, static unsigned HOST_WIDE_INT output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align, - bool reverse) + bool reverse, bool merge_strings) { enum tree_code code; unsigned HOST_WIDE_INT thissize; @@ -4953,10 +4959,11 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align, break; 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, min_align (align, BITS_PER_UNIT * (thissize / 2)), - reverse); + reverse, false); break; case ARRAY_TYPE: @@ -4966,8 +4973,11 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align, case CONSTRUCTOR: return output_constructor (exp, size, align, reverse, NULL); case STRING_CST: - thissize - = MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp), size); + thissize = (unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp); + if (merge_strings + && (thissize == 0 + || TREE_STRING_POINTER (exp) [thissize - 1] != '\0')) + thissize++; gcc_checking_assert (check_string_literal (exp, size)); assemble_string (TREE_STRING_POINTER (exp), thissize); break; @@ -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)); int elt_size = GET_MODE_SIZE (inner); output_constant (VECTOR_CST_ELT (exp, 0), elt_size, align, - reverse); + reverse, false); thissize = elt_size; /* Static constants must have a fixed size. */ unsigned int nunits = VECTOR_CST_NELTS (exp).to_constant (); for (unsigned int i = 1; i < nunits; i++) { output_constant (VECTOR_CST_ELT (exp, i), elt_size, nalign, - reverse); + reverse, false); thissize += elt_size; } break; @@ -5105,8 +5115,8 @@ output_constructor_array_range (oc_local_state *local) if (local->val == NULL_TREE) assemble_zeros (fieldsize); else - fieldsize - = output_constant (local->val, fieldsize, align2, local->reverse); + fieldsize = output_constant (local->val, fieldsize, align2, + local->reverse, false); /* Count its size. */ local->total_bytes += fieldsize; @@ -5201,8 +5211,8 @@ output_constructor_regular_field (oc_local_state *local) if (local->val == NULL_TREE) assemble_zeros (fieldsize); else - fieldsize - = output_constant (local->val, fieldsize, align2, local->reverse); + fieldsize = output_constant (local->val, fieldsize, align2, + local->reverse, false); /* Count its size. */ local->total_bytes += fieldsize; @@ -7618,8 +7628,8 @@ output_object_block (struct object_block *block) { HOST_WIDE_INT size; decl = SYMBOL_REF_DECL (symbol); - assemble_constant_contents - (DECL_INITIAL (decl), XSTR (symbol, 0), DECL_ALIGN (decl)); + assemble_constant_contents (DECL_INITIAL (decl), XSTR (symbol, 0), + DECL_ALIGN (decl), false); size = get_constant_size (DECL_INITIAL (decl)); offset += size; @@ -7636,7 +7646,7 @@ output_object_block (struct object_block *block) { HOST_WIDE_INT size; 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)); offset += size; if ((flag_sanitize & SANITIZE_ADDRESS) -- 2.30.2