varasm.c (output_constant): Add new parameter merge_strings.
authorBernd Edlinger <bernd.edlinger@hotmail.de>
Thu, 4 Oct 2018 17:34:56 +0000 (17:34 +0000)
committerBernd Edlinger <edlinger@gcc.gnu.org>
Thu, 4 Oct 2018 17:34:56 +0000 (17:34 +0000)
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

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/merge-all-constants-1.c
gcc/testsuite/gcc.dg/merge-all-constants-2.c [new file with mode: 0644]
gcc/testsuite/gnat.dg/string_merge1.adb [new file with mode: 0644]
gcc/testsuite/gnat.dg/string_merge2.adb [new file with mode: 0644]
gcc/varasm.c

index d0112655d3c2aaa2f438d8aa9fe3a402d6706f26..0f6cbedbf0c91e9850efac81607b0c9b0a7f5ee7 100644 (file)
@@ -1,3 +1,17 @@
+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>
 
        PR c/87483
index cd10feec8b389b8b434500fc8686f0f746b03a6d..f15042f64b0cc407e10aab8b40bf2eab03e883c6 100644 (file)
@@ -1,3 +1,10 @@
+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>
 
        PR target/87486
index 5c9cd06e925e366993d798a04d00ab0da24c4273..53f6c4d0a0a029535693cf86ae4a1a6a20c0ea80 100644 (file)
@@ -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 (file)
index 0000000..fbdb2bb
--- /dev/null
@@ -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 (file)
index 0000000..f67c7c1
--- /dev/null
@@ -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 (file)
index 0000000..bbec005
--- /dev/null
@@ -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 } }
index e46bc5930fc9c112086e3af025535c8d04f8c841..c789a03e1f3403f37f4f00a7d124f3e7e8f5e4ed 100644 (file)
@@ -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)