public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] convert braced initializers to strings (PR 71625)
@ 2018-07-30 23:51 Martin Sebor
  2018-07-31 13:39 ` Jason Merrill
  2018-08-06 16:41 ` Martin Sebor
  0 siblings, 2 replies; 45+ messages in thread
From: Martin Sebor @ 2018-07-30 23:51 UTC (permalink / raw)
  To: Gcc Patch List; +Cc: Jason Merrill, Joseph Myers

[-- Attachment #1: Type: text/plain, Size: 946 bytes --]

The middle-end contains code to determine the lengths of constant
character arrays initialized by string literals.  The code is used
in a number of optimizations and warnings.

However, the code is unable to deal with constant arrays initialized
using the braced initializer syntax, as in

   const char a[] = { '1', '2', '\0' };

The attached patch extends the C and C++ front-ends to convert such
initializers into a STRING_CST form.

The goal of this work is to both enable existing optimizations for
such arrays, and to help detect bugs due to using non-nul terminated
arrays where nul-terminated strings are expected.  The latter is
an extension of the GCC 8 _Wstringop-overflow and
-Wstringop-truncation warnings that help detect or prevent reading
past the end of dynamically created character arrays.  Future work
includes detecting potential past-the-end reads from uninitialized
local character arrays.

Tested on x86_64-linux.

Martin

[-- Attachment #2: gcc-71625.diff --]
[-- Type: text/x-patch, Size: 10206 bytes --]

PR tree-optimization/71625 - missing strlen optimization on different array initialization style

gcc/c/ChangeLog:

	PR tree-optimization/71625
	* c-parser.c (c_parser_declaration_or_fndef): Call
	convert_braced_list_to_string.

gcc/c-family/ChangeLog:

	PR tree-optimization/71625
	* c-common.c (convert_braced_list_to_string): New function.
	* c-common.h (convert_braced_list_to_string): Declare it.

gcc/cp/ChangeLog:

	PR tree-optimization/71625
	* parser.c (cp_parser_init_declarator):  Call
	convert_braced_list_to_string.

gcc/testsuite/ChangeLog:

	PR tree-optimization/71625
	* g++.dg/init/string2.C: New test.
	* g++.dg/init/string3.C: New test.
	* gcc.dg/strlenopt-55.c: New test.

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 422d668..9a93175 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -8345,4 +8345,72 @@ maybe_add_include_fixit (rich_location *richloc, const char *header)
   free (text);
 }
 
+/* Attempt to convert a braced array initializer list CTOR into
+   a STRING_CST for convenience and efficiency.  When non-null,
+   use EVAL to attempt to evalue constants (used by C++).
+   MAXELTS gives the maximum number of elements to accept.
+   Return the converted string on success or null on failure.  */
+
+tree
+convert_braced_list_to_string (tree ctor, tree (*eval)(tree),
+			       unsigned HOST_WIDE_INT maxelts)
+{
+  unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (ctor);
+
+  auto_vec<char> str;
+  str.reserve (nelts + 1);
+
+  unsigned HOST_WIDE_INT i;
+  tree index, value;
+
+  FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), i, index, value)
+    {
+      unsigned HOST_WIDE_INT idx = index ? tree_to_uhwi (index) : i;
+
+      /* auto_vec is limited to UINT_MAX elements.  */
+      if (idx > UINT_MAX)
+	return NULL_TREE;
+
+      /* Attempt to evaluate constants.  */
+      if (eval)
+	value = eval (value);
+
+      /* Avoid non-constant initializers.  */
+     if (!tree_fits_uhwi_p (value))
+	return NULL_TREE;
+
+      /* Skip over embedded nuls.  */
+      unsigned val = tree_to_uhwi (value);
+      if (!val)
+	continue;
+
+      /* Bail if the CTOR has a block of more than 256 embedded nuls
+	 due to implicitly initialized elements.  */
+      unsigned nelts = (idx - str.length ()) + 1;
+      if (nelts > 256)
+	return NULL_TREE;
+
+      if (nelts > 1)
+	{
+	  str.reserve (idx);
+	  str.quick_grow_cleared (idx);
+	}
+
+      if (idx > maxelts)
+	return NULL_TREE;
+
+      str.safe_insert (idx, val);
+    }
+
+  /* Append a nul for the empty initializer { } and for the last
+     explicit initializer in the loop above that is a nul.  */
+  if (!nelts || str.length () < i)
+    str.safe_push (0);
+
+  /* Build a string literal but return the embedded STRING_CST.  */
+  tree res = build_string_literal (str.length (), str.begin ());
+  res = TREE_OPERAND (TREE_OPERAND (res, 0), 0);
+  return res;
+}
+
 #include "gt-c-family-c-common.h"
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index fcec95b..343a1ae 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1331,6 +1331,8 @@ extern void maybe_add_include_fixit (rich_location *, const char *);
 extern void maybe_suggest_missing_token_insertion (rich_location *richloc,
 						   enum cpp_ttype token_type,
 						   location_t prev_token_loc);
+extern tree convert_braced_list_to_string (tree, tree (*)(tree) = NULL,
+					   unsigned HOST_WIDE_INT = -1);
 
 #if CHECKING_P
 namespace selftest {
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 7a92628..e12d270 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -2126,6 +2126,23 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	      if (d != error_mark_node)
 		{
 		  maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
+
+		  /* Convert a string CONSTRUCTOR into a STRING_CST.  */
+		  tree valtype = TREE_TYPE (init.value);
+		  if (TREE_CODE (init.value) == CONSTRUCTOR
+		      && TREE_CODE (valtype) == ARRAY_TYPE)
+		    {
+		      valtype = TREE_TYPE (valtype);
+		      if (TYPE_STRING_FLAG (valtype))
+			if (tree str
+			    = convert_braced_list_to_string (init.value))
+			  {
+			    /* Replace the initializer with the string
+			       constant.  The resu*/
+			    init.value = str;
+			  }
+		    }
+
 		  finish_decl (d, init_loc, init.value,
 			       init.original_type, asm_name);
 		}
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index d44a6b8..c35c2f1 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -19825,6 +19825,32 @@ cp_parser_init_declarator (cp_parser* parser,
 	    finish_lambda_scope ();
 	  if (initializer == error_mark_node)
 	    cp_parser_skip_to_end_of_statement (parser);
+	  else if (decl)
+	    {
+	      tree valtype = TREE_TYPE (decl);
+	      if (TREE_CODE (valtype) == ARRAY_TYPE
+		  && TYPE_STRING_FLAG (TREE_TYPE (valtype))
+		  && TYPE_MAIN_VARIANT (TREE_TYPE (valtype)) == char_type_node)
+		{
+		  /* If the array has an explicit bound, use it to
+		     constrain the size of the string.  */
+		  unsigned HOST_WIDE_INT maxelts = HOST_WIDE_INT_M1U;
+		  if (tree nelts = DECL_SIZE_UNIT (decl))
+		    if (tree_fits_uhwi_p (nelts))
+		      maxelts = tree_to_uhwi (nelts);
+
+		  /* Convert a string CONSTRUCTOR into a STRING_CST.  */
+		  if (TREE_CODE (initializer) == CONSTRUCTOR
+		      && TREE_TYPE (initializer) == init_list_type_node)
+		    {
+		      if (tree str
+			  = convert_braced_list_to_string (initializer,
+						   scalar_constant_value,
+						   maxelts))
+			initializer = str;
+		    }
+		}
+	    }
 	}
     }
 
diff --git a/gcc/testsuite/g++.dg/init/string2.C b/gcc/testsuite/g++.dg/init/string2.C
new file mode 100644
index 0000000..acb2f5b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/string2.C
@@ -0,0 +1,49 @@
+// PR tree-optimization/71625 - missing strlen optimization on different
+// array initialization style
+//
+// Verify that strlen() calls with constant character array arguments
+// initialized with string constants are folded.  (This is a small
+// subset of pr63989).
+// { dg-do compile }
+// { dg-options "-O0 -fdump-tree-gimple" }
+
+const char a0[] = { 'a', 'b', 'c', '\0' };
+
+int len0 ()
+{
+  return __builtin_strlen (a0);
+}
+
+const char c = 0;
+const char a1[] = { 'a', 'b', 'c', c };
+
+int len1 ()
+{
+  return __builtin_strlen (a1);
+}
+
+#if 0
+
+// The following aren't handled.
+
+const char &cref = c;
+const char a2[] = { 'a', 'b', 'c', cref };
+
+int len2 ()
+{
+  return __builtin_strlen (a2);
+}
+
+
+const char* const cptr = &cref;
+const char a3[] = { 'a', 'b', 'c', *cptr };
+
+int len3 ()
+{
+  return __builtin_strlen (a3);
+}
+
+#endif
+
+// { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
diff --git a/gcc/testsuite/g++.dg/init/string3.C b/gcc/testsuite/g++.dg/init/string3.C
new file mode 100644
index 0000000..f7c7f2f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/string3.C
@@ -0,0 +1,37 @@
+// PR tree-optimization/71625 - missing strlen optimization on different
+// array initialization style
+//
+// Verify that strlen() call with a constant character array argument
+// initialized with non-constant elements isn't folded.  (This is a small
+// subset of pr63989).
+//
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-optimized" }
+
+
+extern const char c;
+const char a0[] = { 'a', 'b', 'c', c };
+
+int len0 ()
+{
+  return __builtin_strlen (a0);
+}
+
+const char &ref = c;
+const char a1[] = { 'a', 'b', 'c', ref };
+
+int len1 ()
+{
+  return __builtin_strlen (a1);
+}
+
+const char* const ptr = &c;
+const char a2[] = { 'a', 'b', 'c', *ptr };
+
+int len2 ()
+{
+  return __builtin_strlen (a2);
+}
+
+// { dg-final { scan-tree-dump-times "strlen" 3 "optimized" } }
diff --git a/gcc/testsuite/gcc.dg/strlenopt-55.c b/gcc/testsuite/gcc.dg/strlenopt-55.c
new file mode 100644
index 0000000..68c7f1d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-55.c
@@ -0,0 +1,83 @@
+/* PR tree-optimization/71625 - missing strlen optimization on different
+   array initialization style
+
+   Verify that strlen() of braced initialized array is folded
+   { dg-do compile }
+   { dg-options "-O0 -Wall -fdump-tree-gimple -fdump-tree-optimized" } */
+
+#include "strlenopt.h"
+
+const char a2_implicit[2] = { };
+const char a3_implicit[3] = { };
+
+const char a3_nul[3] = { 0 };
+const char a5_nul1[3] = { [1] = 0 };
+const char a7_nul2[3] = { [2] = 0 };
+
+const char ax_2_nul[] = { '1', '2', '\0' };
+const char ax_3_nul[] = { '1', '2', '3', '\0' };
+
+const char ax_3_des_nul[] = { [3] = 0, [2] = '3', [1] = '2', [0] = '1' };
+
+const char ax_3[] = { '1', '2', '3' };
+const char a3_3[3] = { '1', '2', '3' };
+
+const char a100_3[] = { '1', '2', '3', [100] = '\0' };
+
+#define CONCAT(x, y) x ## y
+#define CAT(x, y) CONCAT (x, y)
+#define FAILNAME(name) CAT (call_ ## name ##_on_line_, __LINE__)
+
+#define FAIL(name) do {				\
+    extern void FAILNAME (name) (void);		\
+    FAILNAME (name)();				\
+  } while (0)
+
+/* Macro to emit a call to funcation named
+   call_in_true_branch_not_eliminated_on_line_NNN()
+   for each call that's expected to be eliminated.  The dg-final
+   scan-tree-dump-time directive at the bottom of the test verifies
+   that no such call appears in output.  */
+#define ELIM(expr)							\
+  if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
+
+#define T(s, n) ELIM (strlen (s) == n)
+
+void test_nulstring (void)
+{
+  T (a2_implicit, 0);
+  T (a3_implicit, 0);
+
+  T (a3_nul, 0);
+  T (a5_nul1, 0);
+  T (a7_nul2, 0);
+
+  T (ax_2_nul, 2);
+  T (ax_3_nul, 3);
+  T (ax_3_des_nul, 3);
+
+  T (a100_3, 3);
+}
+
+/* Verify that excessively large initializers don't run out of
+   memory.  */
+
+const char large_string[] = { 'a', [__INT_MAX__] = '\0' };
+
+const int test_large_string (void)
+{
+  return large_string[0] + large_string[__INT_MAX__ - 1];
+}
+
+
+const char very_large_string[] = { 'a', [__LONG_MAX__ / 2] = '\0' };
+
+const int test_very_large_string (void)
+{
+  return very_large_string[0] + very_large_string[__LONG_MAX__ / 2 - 1];
+}
+
+
+/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated" 0 "optimized" } } */

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-07-30 23:51 [PATCH] convert braced initializers to strings (PR 71625) Martin Sebor
@ 2018-07-31 13:39 ` Jason Merrill
  2018-07-31 14:49   ` Martin Sebor
  2018-08-06 16:41 ` Martin Sebor
  1 sibling, 1 reply; 45+ messages in thread
From: Jason Merrill @ 2018-07-31 13:39 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Gcc Patch List, Joseph Myers

On Tue, Jul 31, 2018 at 9:51 AM, Martin Sebor <msebor@gmail.com> wrote:
> The middle-end contains code to determine the lengths of constant
> character arrays initialized by string literals.  The code is used
> in a number of optimizations and warnings.
>
> However, the code is unable to deal with constant arrays initialized
> using the braced initializer syntax, as in
>
>   const char a[] = { '1', '2', '\0' };
>
> The attached patch extends the C and C++ front-ends to convert such
> initializers into a STRING_CST form.
>
> The goal of this work is to both enable existing optimizations for
> such arrays, and to help detect bugs due to using non-nul terminated
> arrays where nul-terminated strings are expected.  The latter is
> an extension of the GCC 8 _Wstringop-overflow and
> -Wstringop-truncation warnings that help detect or prevent reading
> past the end of dynamically created character arrays.  Future work
> includes detecting potential past-the-end reads from uninitialized
> local character arrays.

>   && TYPE_MAIN_VARIANT (TREE_TYPE (valtype)) == char_type_node)

Why? Don't we want this for other character types as well?

Jason

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-07-31 13:39 ` Jason Merrill
@ 2018-07-31 14:49   ` Martin Sebor
  2018-08-07  8:58     ` Jason Merrill
  0 siblings, 1 reply; 45+ messages in thread
From: Martin Sebor @ 2018-07-31 14:49 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Gcc Patch List, Joseph Myers

On 07/31/2018 07:38 AM, Jason Merrill wrote:
> On Tue, Jul 31, 2018 at 9:51 AM, Martin Sebor <msebor@gmail.com> wrote:
>> The middle-end contains code to determine the lengths of constant
>> character arrays initialized by string literals.  The code is used
>> in a number of optimizations and warnings.
>>
>> However, the code is unable to deal with constant arrays initialized
>> using the braced initializer syntax, as in
>>
>>   const char a[] = { '1', '2', '\0' };
>>
>> The attached patch extends the C and C++ front-ends to convert such
>> initializers into a STRING_CST form.
>>
>> The goal of this work is to both enable existing optimizations for
>> such arrays, and to help detect bugs due to using non-nul terminated
>> arrays where nul-terminated strings are expected.  The latter is
>> an extension of the GCC 8 _Wstringop-overflow and
>> -Wstringop-truncation warnings that help detect or prevent reading
>> past the end of dynamically created character arrays.  Future work
>> includes detecting potential past-the-end reads from uninitialized
>> local character arrays.
>
>>   && TYPE_MAIN_VARIANT (TREE_TYPE (valtype)) == char_type_node)
>
> Why? Don't we want this for other character types as well?

It suppresses narrowing warnings for things like

   signed char a[] = { 0xff };

(there are a couple of tests that exercise this).

At the same time, STRING_CST is supposed to be able to represent
strings of any integer type so there should be a way to make it
work.  On the flip side, recent discussions of changes in this
area suggest there may be bugs in the wide character handling of
STRING_CST so those would need to be fixed before relying on it
for robust support.

In any case, if you have a suggestion for how to make it work for
at least the narrow character types I'll adjust the patch.

Martin

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-07-30 23:51 [PATCH] convert braced initializers to strings (PR 71625) Martin Sebor
  2018-07-31 13:39 ` Jason Merrill
@ 2018-08-06 16:41 ` Martin Sebor
  2018-08-06 17:04   ` Joseph Myers
  1 sibling, 1 reply; 45+ messages in thread
From: Martin Sebor @ 2018-08-06 16:41 UTC (permalink / raw)
  To: Gcc Patch List; +Cc: Jason Merrill, Joseph Myers

Ping: https://gcc.gnu.org/ml/gcc-patches/2018-07/msg01884.html

On 07/30/2018 05:51 PM, Martin Sebor wrote:
> The middle-end contains code to determine the lengths of constant
> character arrays initialized by string literals.  The code is used
> in a number of optimizations and warnings.
>
> However, the code is unable to deal with constant arrays initialized
> using the braced initializer syntax, as in
>
>   const char a[] = { '1', '2', '\0' };
>
> The attached patch extends the C and C++ front-ends to convert such
> initializers into a STRING_CST form.
>
> The goal of this work is to both enable existing optimizations for
> such arrays, and to help detect bugs due to using non-nul terminated
> arrays where nul-terminated strings are expected.  The latter is
> an extension of the GCC 8 _Wstringop-overflow and
> -Wstringop-truncation warnings that help detect or prevent reading
> past the end of dynamically created character arrays.  Future work
> includes detecting potential past-the-end reads from uninitialized
> local character arrays.
>
> Tested on x86_64-linux.
>
> Martin

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-06 16:41 ` Martin Sebor
@ 2018-08-06 17:04   ` Joseph Myers
  2018-08-07  2:02     ` Martin Sebor
  0 siblings, 1 reply; 45+ messages in thread
From: Joseph Myers @ 2018-08-06 17:04 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Gcc Patch List, Jason Merrill

On Mon, 6 Aug 2018, Martin Sebor wrote:

> Ping: https://gcc.gnu.org/ml/gcc-patches/2018-07/msg01884.html

I'd expect testcases with signed char and unsigned char as well, if those 
work for C, including tests for signed char where some of the initializers 
are negative.  (Tests that actual array contents are still correct after 
this conversion, as well as that the optimizations occur, would also be a 
good idea.)

The c-parser.c patch adds a comment that ends in the middle of a word.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-06 17:04   ` Joseph Myers
@ 2018-08-07  2:02     ` Martin Sebor
  2018-08-07 11:31       ` Joseph Myers
  0 siblings, 1 reply; 45+ messages in thread
From: Martin Sebor @ 2018-08-07  2:02 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Gcc Patch List, Jason Merrill

[-- Attachment #1: Type: text/plain, Size: 992 bytes --]

On 08/06/2018 11:04 AM, Joseph Myers wrote:
> On Mon, 6 Aug 2018, Martin Sebor wrote:
>
>> Ping: https://gcc.gnu.org/ml/gcc-patches/2018-07/msg01884.html
>
> I'd expect testcases with signed char and unsigned char as well, if those
> work for C, including tests for signed char where some of the initializers
> are negative.  (Tests that actual array contents are still correct after
> this conversion, as well as that the optimizations occur, would also be a
> good idea.)
>
> The c-parser.c patch adds a comment that ends in the middle of a word.

Thanks.  Adding more tests revealed a couple of oversights:
1) using tree_fits_uhwi_p excluded initializers with negative
values,
2) skipping embedded nuls made it possible to create a string
with fewer elements than the initializer array, which caused
arrays with unspecified bound to be smaller than they would
have been otherwise

The attached update fixes both of these and makes the C/C++
front-end code simpler and more alike.

Martin


[-- Attachment #2: gcc-71625.diff --]
[-- Type: text/x-patch, Size: 19309 bytes --]

PR tree-optimization/71625 - missing strlen optimization on different array initialization style

gcc/c/ChangeLog:

	PR tree-optimization/71625
	* c-parser.c (c_parser_declaration_or_fndef): Call
	braced_list_to_string.

gcc/c-family/ChangeLog:

	PR tree-optimization/71625
	* c-common.c (braced_list_to_string): New function.
	* c-common.h (braced_list_to_string): Declare it.

gcc/cp/ChangeLog:

	PR tree-optimization/71625
	* parser.c (cp_parser_init_declarator):  Call braced_list_to_string.

gcc/testsuite/ChangeLog:

	PR tree-optimization/71625
	* g++.dg/init/string2.C: New test.
	* g++.dg/init/string3.C: New test.
	* gcc.dg/strlenopt-55.c: New test.

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
Index: gcc/c/c-parser.c
===================================================================
--- gcc/c/c-parser.c	(revision 263341)
+++ gcc/c/c-parser.c	(working copy)
@@ -2126,6 +2126,24 @@ c_parser_declaration_or_fndef (c_parser *parser, b
 	      if (d != error_mark_node)
 		{
 		  maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
+
+		  /* Convert a string CONSTRUCTOR into a STRING_CST.  */
+		  tree valtype = TREE_TYPE (init.value);
+		  if (TREE_CODE (init.value) == CONSTRUCTOR
+		      && TREE_CODE (valtype) == ARRAY_TYPE)
+		    {
+		      if (TYPE_STRING_FLAG (TREE_TYPE (valtype)))
+			{
+			  if (tree str = braced_list_to_string (valtype,
+								init.value))
+			    {
+			      /* Replace the initializer with the string
+				 constant.  */
+			      init.value = str;
+			    }
+			}
+		    }
+
 		  finish_decl (d, init_loc, init.value,
 			       init.original_type, asm_name);
 		}
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(revision 263341)
+++ gcc/c-family/c-common.c	(working copy)
@@ -8509,4 +8509,83 @@ maybe_add_include_fixit (rich_location *richloc, c
   free (text);
 }
 
+/* Attempt to convert a braced array initializer list CTOR for array
+   TYPE into a STRING_CST for convenience and efficiency.  When non-null,
+   use EVAL to attempt to evalue constants (used by C++).  Return
+   the converted string on success or null on failure.  */
+
+tree
+braced_list_to_string (tree type, tree ctor, tree (*eval)(tree))
+{
+  /* If the array has an explicit bound, use it to constrain the size
+     of the string.  If it doesn't, be sure to create a string that's
+     as long as implied by the index of the last zero specified via
+     a designator, as in:
+       const char a[] = { [7] = 0 };  */
+  unsigned HOST_WIDE_INT maxelts = HOST_WIDE_INT_M1U;
+  if (tree nelts = TYPE_SIZE_UNIT (type))
+    if (tree_fits_uhwi_p (nelts))
+      {
+	maxelts = tree_to_uhwi (nelts);
+	maxelts /= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
+      }
+
+  unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (ctor);
+
+  auto_vec<char> str;
+  str.reserve (nelts + 1);
+
+  unsigned HOST_WIDE_INT i;
+  tree index, value;
+
+  FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), i, index, value)
+    {
+      unsigned HOST_WIDE_INT idx = index ? tree_to_uhwi (index) : i;
+
+      /* auto_vec is limited to UINT_MAX elements.  */
+      if (idx > UINT_MAX)
+	return NULL_TREE;
+
+      /* Attempt to evaluate constants.  */
+      if (eval)
+	value = eval (value);
+
+      /* Avoid non-constant initializers.  */
+     if (!tree_fits_shwi_p (value))
+	return NULL_TREE;
+
+      /* Skip over embedded nuls.  */
+      unsigned val = tree_to_shwi (value);
+      if (!val && i + 1 < nelts)
+	continue;
+
+      /* Bail if the CTOR has a block of more than 256 embedded nuls
+	 due to implicitly initialized elements.  */
+      unsigned nelts = (idx - str.length ()) + 1;
+      if (nelts > 256)
+	return NULL_TREE;
+
+      if (nelts > 1)
+	{
+	  str.reserve (idx);
+	  str.quick_grow_cleared (idx);
+	}
+
+      if (idx > maxelts)
+	return NULL_TREE;
+
+      str.safe_insert (idx, val);
+    }
+
+  if (!nelts || str.length () < i)
+    /* Append a nul for the empty initializer { } and for the last
+       explicit initializer in the loop above that is a nul.  */
+    str.safe_push (0);
+
+  /* Build a string literal but return the embedded STRING_CST.  */
+  tree res = build_string_literal (str.length (), str.begin ());
+  res = TREE_OPERAND (TREE_OPERAND (res, 0), 0);
+  return res;
+}
+
 #include "gt-c-family-c-common.h"
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(revision 263341)
+++ gcc/c-family/c-common.h	(working copy)
@@ -1331,6 +1331,7 @@ extern void maybe_add_include_fixit (rich_location
 extern void maybe_suggest_missing_token_insertion (rich_location *richloc,
 						   enum cpp_ttype token_type,
 						   location_t prev_token_loc);
+extern tree braced_list_to_string (tree, tree, tree (*)(tree) = NULL);
 
 #if CHECKING_P
 namespace selftest {
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 263341)
+++ gcc/cp/parser.c	(working copy)
@@ -19825,6 +19825,24 @@ cp_parser_init_declarator (cp_parser* parser,
 	    finish_lambda_scope ();
 	  if (initializer == error_mark_node)
 	    cp_parser_skip_to_end_of_statement (parser);
+	  else if (decl)
+	    {
+	      tree valtype = TREE_TYPE (decl);
+	      if (TREE_CODE (valtype) == ARRAY_TYPE
+		  && TYPE_STRING_FLAG (TREE_TYPE (valtype))
+		  && TYPE_MAIN_VARIANT (TREE_TYPE (valtype)) == char_type_node)
+		{
+		  /* Convert a string CONSTRUCTOR into a STRING_CST.  */
+		  if (TREE_CODE (initializer) == CONSTRUCTOR
+		      && TREE_TYPE (initializer) == init_list_type_node)
+		    {
+		      if (tree str
+			  = braced_list_to_string (valtype, initializer,
+						   scalar_constant_value))
+			initializer = str;
+		    }
+		}
+	    }
 	}
     }
 
Index: gcc/testsuite/g++.dg/init/string2.C
===================================================================
--- gcc/testsuite/g++.dg/init/string2.C	(nonexistent)
+++ gcc/testsuite/g++.dg/init/string2.C	(working copy)
@@ -0,0 +1,48 @@
+// PR tree-optimization/71625 - missing strlen optimization on different
+// array initialization style
+//
+// Verify that strlen() calls with constant character array arguments
+// initialized with string constants are folded.  (This is a small
+// subset of pr63989).
+// { dg-do compile }
+// { dg-options "-O0 -fdump-tree-gimple" }
+
+const char a0[] = { 'a', 'b', 'c', '\0' };
+
+int len0 ()
+{
+  return __builtin_strlen (a0);
+}
+
+const char c = 0;
+const char a1[] = { 'a', 'b', 'c', c };
+
+int len1 ()
+{
+  return __builtin_strlen (a1);
+}
+
+#if 0
+
+// The following aren't handled.
+
+const char &cref = c;
+const char a2[] = { 'a', 'b', 'c', cref };
+
+int len2 ()
+{
+  return __builtin_strlen (a2);
+}
+
+
+const char* const cptr = &cref;
+const char a3[] = { 'a', 'b', 'c', *cptr };
+
+int len3 ()
+{
+  return __builtin_strlen (a3);
+}
+
+#endif
+
+// { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
Index: gcc/testsuite/g++.dg/init/string3.C
===================================================================
--- gcc/testsuite/g++.dg/init/string3.C	(nonexistent)
+++ gcc/testsuite/g++.dg/init/string3.C	(working copy)
@@ -0,0 +1,36 @@
+// PR tree-optimization/71625 - missing strlen optimization on different
+// array initialization style
+//
+// Verify that strlen() call with a constant character array argument
+// initialized with non-constant elements isn't folded.  (This is a small
+// subset of pr63989).
+//
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-optimized" }
+
+
+extern const char c;
+const char a0[] = { 'a', 'b', 'c', c };
+
+int len0 ()
+{
+  return __builtin_strlen (a0);
+}
+
+const char &ref = c;
+const char a1[] = { 'a', 'b', 'c', ref };
+
+int len1 ()
+{
+  return __builtin_strlen (a1);
+}
+
+const char* const ptr = &c;
+const char a2[] = { 'a', 'b', 'c', *ptr };
+
+int len2 ()
+{
+  return __builtin_strlen (a2);
+}
+
+// { dg-final { scan-tree-dump-times "strlen" 3 "optimized" } }
Index: gcc/testsuite/gcc.dg/strlenopt-55.c
===================================================================
--- gcc/testsuite/gcc.dg/strlenopt-55.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/strlenopt-55.c	(working copy)
@@ -0,0 +1,227 @@
+/* PR tree-optimization/71625 - missing strlen optimization on different
+   array initialization style
+
+   Verify that strlen() of braced initialized array is folded
+   { dg-do compile }
+   { dg-options "-O1 -Wall -fdump-tree-gimple -fdump-tree-optimized" } */
+
+#include "strlenopt.h"
+
+#define S								\
+  "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"	\
+  "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"	\
+  "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"	\
+  "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"	\
+  "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"	\
+  "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"	\
+  "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"	\
+  "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"	\
+  "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"	\
+  "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"	\
+  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"	\
+  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"	\
+  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"	\
+  "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"	\
+  "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"	\
+  "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+
+/* Arrays of char, signed char, and unsigned char to verify that
+   the length and contents of all are the same as that of the string
+   literal above.  */
+
+const char c256[] = {
+  S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10],
+  S[11], S[12], S[13], S[14], S[15], S[16], S[17], S[18], S[19], S[20],
+  S[21], S[22], S[23], S[24], S[25], S[26], S[27], S[28], S[29], S[30],
+  S[31], S[32], S[33], S[34], S[35], S[36], S[37], S[38], S[39], S[40],
+  S[41], S[42], S[43], S[44], S[45], S[46], S[47], S[48], S[49], S[50],
+  S[51], S[52], S[53], S[54], S[55], S[56], S[57], S[58], S[59], S[60],
+  S[61], S[62], S[63], S[64], S[65], S[66], S[67], S[68], S[69], S[70],
+  S[71], S[72], S[73], S[74], S[75], S[76], S[77], S[78], S[79], S[80],
+  S[81], S[82], S[83], S[84], S[85], S[86], S[87], S[88], S[89], S[90],
+  S[91], S[92], S[93], S[94], S[95], S[96], S[97], S[98], S[99], S[100],
+  S[101], S[102], S[103], S[104], S[105], S[106], S[107], S[108], S[109],
+  S[110], S[111], S[112], S[113], S[114], S[115], S[116], S[117], S[118],
+  S[119], S[120], S[121], S[122], S[123], S[124], S[125], S[126], S[127],
+  S[128], S[129], S[130], S[131], S[132], S[133], S[134], S[135], S[136],
+  S[137], S[138], S[139], S[140], S[141], S[142], S[143], S[144], S[145],
+  S[146], S[147], S[148], S[149], S[150], S[151], S[152], S[153], S[154],
+  S[155], S[156], S[157], S[158], S[159], S[160], S[161], S[162], S[163],
+  S[164], S[165], S[166], S[167], S[168], S[169], S[170], S[171], S[172],
+  S[173], S[174], S[175], S[176], S[177], S[178], S[179], S[180], S[181],
+  S[182], S[183], S[184], S[185], S[186], S[187], S[188], S[189], S[190],
+  S[191], S[192], S[193], S[194], S[195], S[196], S[197], S[198], S[199],
+  S[200], S[201], S[202], S[203], S[204], S[205], S[206], S[207], S[208],
+  S[209], S[210], S[211], S[212], S[213], S[214], S[215], S[216], S[217],
+  S[218], S[219], S[220], S[221], S[222], S[223], S[224], S[225], S[226],
+  S[227], S[228], S[229], S[230], S[231], S[232], S[233], S[234], S[235],
+  S[236], S[237], S[238], S[239], S[240], S[241], S[242], S[243], S[244],
+  S[245], S[246], S[247], S[248], S[249], S[250], S[251], S[252], S[253],
+  S[254], S[255] /* = NUL */
+};
+
+const signed char sc256[] = {
+  S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10],
+  S[11], S[12], S[13], S[14], S[15], S[16], S[17], S[18], S[19], S[20],
+  S[21], S[22], S[23], S[24], S[25], S[26], S[27], S[28], S[29], S[30],
+  S[31], S[32], S[33], S[34], S[35], S[36], S[37], S[38], S[39], S[40],
+  S[41], S[42], S[43], S[44], S[45], S[46], S[47], S[48], S[49], S[50],
+  S[51], S[52], S[53], S[54], S[55], S[56], S[57], S[58], S[59], S[60],
+  S[61], S[62], S[63], S[64], S[65], S[66], S[67], S[68], S[69], S[70],
+  S[71], S[72], S[73], S[74], S[75], S[76], S[77], S[78], S[79], S[80],
+  S[81], S[82], S[83], S[84], S[85], S[86], S[87], S[88], S[89], S[90],
+  S[91], S[92], S[93], S[94], S[95], S[96], S[97], S[98], S[99], S[100],
+  S[101], S[102], S[103], S[104], S[105], S[106], S[107], S[108], S[109],
+  S[110], S[111], S[112], S[113], S[114], S[115], S[116], S[117], S[118],
+  S[119], S[120], S[121], S[122], S[123], S[124], S[125], S[126], S[127],
+  S[128], S[129], S[130], S[131], S[132], S[133], S[134], S[135], S[136],
+  S[137], S[138], S[139], S[140], S[141], S[142], S[143], S[144], S[145],
+  S[146], S[147], S[148], S[149], S[150], S[151], S[152], S[153], S[154],
+  S[155], S[156], S[157], S[158], S[159], S[160], S[161], S[162], S[163],
+  S[164], S[165], S[166], S[167], S[168], S[169], S[170], S[171], S[172],
+  S[173], S[174], S[175], S[176], S[177], S[178], S[179], S[180], S[181],
+  S[182], S[183], S[184], S[185], S[186], S[187], S[188], S[189], S[190],
+  S[191], S[192], S[193], S[194], S[195], S[196], S[197], S[198], S[199],
+  S[200], S[201], S[202], S[203], S[204], S[205], S[206], S[207], S[208],
+  S[209], S[210], S[211], S[212], S[213], S[214], S[215], S[216], S[217],
+  S[218], S[219], S[220], S[221], S[222], S[223], S[224], S[225], S[226],
+  S[227], S[228], S[229], S[230], S[231], S[232], S[233], S[234], S[235],
+  S[236], S[237], S[238], S[239], S[240], S[241], S[242], S[243], S[244],
+  S[245], S[246], S[247], S[248], S[249], S[250], S[251], S[252], S[253],
+  S[254], S[255] /* = NUL */
+};
+
+const unsigned char uc256[] = {
+  S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10],
+  S[11], S[12], S[13], S[14], S[15], S[16], S[17], S[18], S[19], S[20],
+  S[21], S[22], S[23], S[24], S[25], S[26], S[27], S[28], S[29], S[30],
+  S[31], S[32], S[33], S[34], S[35], S[36], S[37], S[38], S[39], S[40],
+  S[41], S[42], S[43], S[44], S[45], S[46], S[47], S[48], S[49], S[50],
+  S[51], S[52], S[53], S[54], S[55], S[56], S[57], S[58], S[59], S[60],
+  S[61], S[62], S[63], S[64], S[65], S[66], S[67], S[68], S[69], S[70],
+  S[71], S[72], S[73], S[74], S[75], S[76], S[77], S[78], S[79], S[80],
+  S[81], S[82], S[83], S[84], S[85], S[86], S[87], S[88], S[89], S[90],
+  S[91], S[92], S[93], S[94], S[95], S[96], S[97], S[98], S[99], S[100],
+  S[101], S[102], S[103], S[104], S[105], S[106], S[107], S[108], S[109],
+  S[110], S[111], S[112], S[113], S[114], S[115], S[116], S[117], S[118],
+  S[119], S[120], S[121], S[122], S[123], S[124], S[125], S[126], S[127],
+  S[128], S[129], S[130], S[131], S[132], S[133], S[134], S[135], S[136],
+  S[137], S[138], S[139], S[140], S[141], S[142], S[143], S[144], S[145],
+  S[146], S[147], S[148], S[149], S[150], S[151], S[152], S[153], S[154],
+  S[155], S[156], S[157], S[158], S[159], S[160], S[161], S[162], S[163],
+  S[164], S[165], S[166], S[167], S[168], S[169], S[170], S[171], S[172],
+  S[173], S[174], S[175], S[176], S[177], S[178], S[179], S[180], S[181],
+  S[182], S[183], S[184], S[185], S[186], S[187], S[188], S[189], S[190],
+  S[191], S[192], S[193], S[194], S[195], S[196], S[197], S[198], S[199],
+  S[200], S[201], S[202], S[203], S[204], S[205], S[206], S[207], S[208],
+  S[209], S[210], S[211], S[212], S[213], S[214], S[215], S[216], S[217],
+  S[218], S[219], S[220], S[221], S[222], S[223], S[224], S[225], S[226],
+  S[227], S[228], S[229], S[230], S[231], S[232], S[233], S[234], S[235],
+  S[236], S[237], S[238], S[239], S[240], S[241], S[242], S[243], S[244],
+  S[245], S[246], S[247], S[248], S[249], S[250], S[251], S[252], S[253],
+  S[254], S[255] /* = NUL */
+};
+
+const __CHAR16_TYPE__ c16_4[] = {
+  1, 0x7fff, 0x8000, 0xffff,
+  0x10000   /* { dg-warning "\\\[-Woverflow]" } */
+};
+
+const char a2_implicit[2] = { };
+const char a3_implicit[3] = { };
+
+const char a3_nul[3] = { 0 };
+const char a5_nul1[3] = { [1] = 0 };
+const char a7_nul2[3] = { [2] = 0 };
+
+const char ax_2_nul[] = { '1', '2', '\0' };
+const char ax_3_nul[] = { '1', '2', '3', '\0' };
+
+const char ax_3_des_nul[] = { [3] = 0, [2] = '3', [1] = '2', [0] = '1' };
+
+const char ax_3[] = { '1', '2', '3' };
+const char a3_3[3] = { '1', '2', '3' };
+
+const char a100_3[] = { '1', '2', '3', [100] = '\0' };
+
+#define CONCAT(x, y) x ## y
+#define CAT(x, y) CONCAT (x, y)
+#define FAILNAME(name) CAT (call_ ## name ##_on_line_, __LINE__)
+
+#define FAIL(name) do {				\
+    extern void FAILNAME (name) (void);		\
+    FAILNAME (name)();				\
+  } while (0)
+
+/* Macro to emit a call to funcation named
+   call_in_true_branch_not_eliminated_on_line_NNN()
+   for each call that's expected to be eliminated.  The dg-final
+   scan-tree-dump-time directive at the bottom of the test verifies
+   that no such call appears in output.  */
+#define ELIM(expr)							\
+  if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
+
+#define T(s, n) ELIM (strlen (s) == n)
+
+void test_nulstring (void)
+{
+  T (a2_implicit, 0);
+  T (a3_implicit, 0);
+
+  T (a3_nul, 0);
+  T (a5_nul1, 0);
+  T (a7_nul2, 0);
+
+  T (ax_2_nul, 2);
+  T (ax_3_nul, 3);
+  T (ax_3_des_nul, 3);
+
+  T (a100_3, 3);
+
+  /* Verify that all three character arrays have the same length
+     as the string literal they are initialized with.  */
+  T (S, 255);
+  T (c256, 255);
+  T ((const char*)sc256, 255);
+  T ((const char*)uc256, 255);
+
+  /* Verify that all three character arrays have the same contents
+     as the string literal they are initialized with.  */
+  ELIM (0 == memcmp (c256, S, sizeof c256));
+  ELIM (0 == memcmp (c256, (const char*)sc256, sizeof c256));
+  ELIM (0 == memcmp (c256, (const char*)uc256, sizeof c256));
+
+  ELIM (0 == strcmp (c256, (const char*)sc256));
+  ELIM (0 == strcmp (c256, (const char*)uc256));
+
+  /* Verify that the char16_t array has the expected contents.  */
+  ELIM (c16_4[0] == 1 && c16_4[1] == 0x7fff
+	&& c16_4[2] == 0x8000 && c16_4[3] == 0xffff
+	&& c16_4[4] == 0);
+}
+
+/* Verify that excessively large initializers don't run out of
+   memory.  Also verify that the they have the expected size and
+   contents.  */
+
+#define MAX (__PTRDIFF_MAX__ - 1)
+
+const char large_string[] = { 'a', [1234] = 'b', [MAX] = '\0' };
+
+const void test_large_string_size (void)
+{
+  ELIM (sizeof large_string == MAX + 1);
+
+  /* The following expressions are not folded without optimization.  */
+  ELIM ('a'  == large_string[0]);
+  ELIM ('\0' == large_string[1233]);
+  ELIM ('b'  == large_string[1234]);
+  ELIM ('\0' == large_string[1235]);
+  ELIM ('\0' == large_string[MAX - 1]);
+}
+
+
+/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "memcmp" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "strcmp" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated" 0 "optimized" } } */

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-07-31 14:49   ` Martin Sebor
@ 2018-08-07  8:58     ` Jason Merrill
  2018-08-07 23:04       ` Martin Sebor
  0 siblings, 1 reply; 45+ messages in thread
From: Jason Merrill @ 2018-08-07  8:58 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Gcc Patch List, Joseph Myers

On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor <msebor@gmail.com> wrote:
> On 07/31/2018 07:38 AM, Jason Merrill wrote:
>>
>> On Tue, Jul 31, 2018 at 9:51 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>
>>> The middle-end contains code to determine the lengths of constant
>>> character arrays initialized by string literals.  The code is used
>>> in a number of optimizations and warnings.
>>>
>>> However, the code is unable to deal with constant arrays initialized
>>> using the braced initializer syntax, as in
>>>
>>>   const char a[] = { '1', '2', '\0' };
>>>
>>> The attached patch extends the C and C++ front-ends to convert such
>>> initializers into a STRING_CST form.
>>>
>>> The goal of this work is to both enable existing optimizations for
>>> such arrays, and to help detect bugs due to using non-nul terminated
>>> arrays where nul-terminated strings are expected.  The latter is
>>> an extension of the GCC 8 _Wstringop-overflow and
>>> -Wstringop-truncation warnings that help detect or prevent reading
>>> past the end of dynamically created character arrays.  Future work
>>> includes detecting potential past-the-end reads from uninitialized
>>> local character arrays.
>>
>>
>>>   && TYPE_MAIN_VARIANT (TREE_TYPE (valtype)) == char_type_node)
>>
>>
>> Why? Don't we want this for other character types as well?
>
> It suppresses narrowing warnings for things like
>
>   signed char a[] = { 0xff };
>
> (there are a couple of tests that exercise this).

Why is plain char different in this respect?  Presumably one of

char a[] = { -1 };
char b[] = { 0xff };

should give the same narrowing warning, depending on whether char is signed.

> At the same time, STRING_CST is supposed to be able to represent
> strings of any integer type so there should be a way to make it
> work.  On the flip side, recent discussions of changes in this
> area suggest there may be bugs in the wide character handling of
> STRING_CST so those would need to be fixed before relying on it
> for robust support.
>
> In any case, if you have a suggestion for how to make it work for
> at least the narrow character types I'll adjust the patch.

I suppose braced_list_to_string should call check_narrowing for C++.

Currently it uses tree_fits_shwi_p (signed host_wide_int) and then
stores the extracted value in a host unsigned int, which is then
converted to host char.  Does the right thing happen for -fsigned-char
or targets with a different character set?

Jason

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-07  2:02     ` Martin Sebor
@ 2018-08-07 11:31       ` Joseph Myers
  2018-08-07 23:05         ` Martin Sebor
  0 siblings, 1 reply; 45+ messages in thread
From: Joseph Myers @ 2018-08-07 11:31 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Gcc Patch List, Jason Merrill

On Tue, 7 Aug 2018, Martin Sebor wrote:

> 2) skipping embedded nuls made it possible to create a string
> with fewer elements than the initializer array, which caused
> arrays with unspecified bound to be smaller than they would
> have been otherwise

I think there should be explicit tests of sizeof for arrays with 
unspecified bound - to make sure both that it isn't any smaller than it 
should be, but also that any NULs implicitly added for a STRING_CST don't 
make the arrays any larger than their size should be for the originally 
given initializer that doesn't have a 0 as the last element.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-07  8:58     ` Jason Merrill
@ 2018-08-07 23:04       ` Martin Sebor
  2018-08-08 11:09         ` Jason Merrill
  0 siblings, 1 reply; 45+ messages in thread
From: Martin Sebor @ 2018-08-07 23:04 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Gcc Patch List, Joseph Myers

[-- Attachment #1: Type: text/plain, Size: 3011 bytes --]

On 08/07/2018 02:57 AM, Jason Merrill wrote:
> On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor <msebor@gmail.com> wrote:
>> On 07/31/2018 07:38 AM, Jason Merrill wrote:
>>>
>>> On Tue, Jul 31, 2018 at 9:51 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>>
>>>> The middle-end contains code to determine the lengths of constant
>>>> character arrays initialized by string literals.  The code is used
>>>> in a number of optimizations and warnings.
>>>>
>>>> However, the code is unable to deal with constant arrays initialized
>>>> using the braced initializer syntax, as in
>>>>
>>>>   const char a[] = { '1', '2', '\0' };
>>>>
>>>> The attached patch extends the C and C++ front-ends to convert such
>>>> initializers into a STRING_CST form.
>>>>
>>>> The goal of this work is to both enable existing optimizations for
>>>> such arrays, and to help detect bugs due to using non-nul terminated
>>>> arrays where nul-terminated strings are expected.  The latter is
>>>> an extension of the GCC 8 _Wstringop-overflow and
>>>> -Wstringop-truncation warnings that help detect or prevent reading
>>>> past the end of dynamically created character arrays.  Future work
>>>> includes detecting potential past-the-end reads from uninitialized
>>>> local character arrays.
>>>
>>>
>>>>   && TYPE_MAIN_VARIANT (TREE_TYPE (valtype)) == char_type_node)
>>>
>>>
>>> Why? Don't we want this for other character types as well?
>>
>> It suppresses narrowing warnings for things like
>>
>>   signed char a[] = { 0xff };
>>
>> (there are a couple of tests that exercise this).
>
> Why is plain char different in this respect?  Presumably one of
>
> char a[] = { -1 };
> char b[] = { 0xff };
>
> should give the same narrowing warning, depending on whether char is signed.

Right.  I've added more tests to verify that it does.

>> At the same time, STRING_CST is supposed to be able to represent
>> strings of any integer type so there should be a way to make it
>> work.  On the flip side, recent discussions of changes in this
>> area suggest there may be bugs in the wide character handling of
>> STRING_CST so those would need to be fixed before relying on it
>> for robust support.
>>
>> In any case, if you have a suggestion for how to make it work for
>> at least the narrow character types I'll adjust the patch.
>
> I suppose braced_list_to_string should call check_narrowing for C++.

I see.  I've made that change.  That has made it possible to
convert arrays of all character types.  Thanks!

> Currently it uses tree_fits_shwi_p (signed host_wide_int) and then
> stores the extracted value in a host unsigned int, which is then
> converted to host char.  Does the right thing happen for -fsigned-char
> or targets with a different character set?

I believe so.  I've added tests for these too (ASCII and EBCDIC)
and also changed the type of the extracted value to HWI to match
(it doesn't change the results of the tests).

Attached is an updated patch with these changes plus more tests
as suggested by Joseph.

Martin

[-- Attachment #2: gcc-71625.diff --]
[-- Type: text/x-patch, Size: 22717 bytes --]

PR tree-optimization/71625 - missing strlen optimization on different array initialization style

gcc/c/ChangeLog:

	PR tree-optimization/71625
	* c-parser.c (c_parser_declaration_or_fndef): Call
	braced_list_to_string.

gcc/c-family/ChangeLog:

	PR tree-optimization/71625
	* c-common.c (braced_list_to_string): New function.
	* c-common.h (braced_list_to_string): Declare it.

gcc/cp/ChangeLog:

	PR tree-optimization/71625
	* parser.c (cp_parser_init_declarator):  Call braced_list_to_string.
	(eval_check_narrowing): New function.

gcc/testsuite/ChangeLog:

	PR tree-optimization/71625
	* g++.dg/init/string2.C: New test.
	* g++.dg/init/string3.C: New test.
	* gcc.dg/strlenopt-55.c: New test.
	* gcc.dg/strlenopt-56.c: New test.

Index: gcc/c/c-parser.c
===================================================================
--- gcc/c/c-parser.c	(revision 263372)
+++ gcc/c/c-parser.c	(working copy)
@@ -2126,6 +2126,15 @@ c_parser_declaration_or_fndef (c_parser *parser, b
 	      if (d != error_mark_node)
 		{
 		  maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
+
+		  /* Try to convert a string CONSTRUCTOR into a STRING_CST.  */
+		  tree valtype = TREE_TYPE (init.value);
+		  if (TREE_CODE (init.value) == CONSTRUCTOR
+		      && TREE_CODE (valtype) == ARRAY_TYPE
+		      && TYPE_STRING_FLAG (TREE_TYPE (valtype)))
+		    if (tree str = braced_list_to_string (valtype, init.value))
+		      init.value = str;
+
 		  finish_decl (d, init_loc, init.value,
 			       init.original_type, asm_name);
 		}
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(revision 263372)
+++ gcc/c-family/c-common.c	(working copy)
@@ -8509,4 +8509,84 @@ maybe_add_include_fixit (rich_location *richloc, c
   free (text);
 }
 
+/* Attempt to convert a braced array initializer list CTOR for array
+   TYPE into a STRING_CST for convenience and efficiency.  When non-null,
+   use EVAL to attempt to evalue constants (used by C++).  Return
+   the converted string on success or null on failure.  */
+
+tree
+braced_list_to_string (tree type, tree ctor, tree (*eval)(tree, tree))
+{
+  /* If the array has an explicit bound, use it to constrain the size
+     of the string.  If it doesn't, be sure to create a string that's
+     as long as implied by the index of the last zero specified via
+     a designator, as in:
+       const char a[] = { [7] = 0 };  */
+  unsigned HOST_WIDE_INT maxelts = HOST_WIDE_INT_M1U;
+  if (tree nelts = TYPE_SIZE_UNIT (type))
+    if (tree_fits_uhwi_p (nelts))
+      {
+	maxelts = tree_to_uhwi (nelts);
+	maxelts /= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
+      }
+
+  unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (ctor);
+  tree eltype = TREE_TYPE (type);
+
+  auto_vec<char> str;
+  str.reserve (nelts + 1);
+
+  unsigned HOST_WIDE_INT i;
+  tree index, value;
+
+  FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), i, index, value)
+    {
+      unsigned HOST_WIDE_INT idx = index ? tree_to_uhwi (index) : i;
+
+      /* auto_vec is limited to UINT_MAX elements.  */
+      if (idx > UINT_MAX)
+	return NULL_TREE;
+
+      /* Attempt to evaluate constants.  */
+      if (eval)
+	value = eval (eltype, value);
+
+      /* Avoid non-constant initializers.  */
+     if (!tree_fits_shwi_p (value))
+	return NULL_TREE;
+
+      /* Skip over embedded nuls.  */
+      HOST_WIDE_INT val = tree_to_shwi (value);
+      if (!val && i + 1 < nelts)
+	continue;
+
+      /* Bail if the CTOR has a block of more than 256 embedded nuls
+	 due to implicitly initialized elements.  */
+      unsigned nelts = (idx - str.length ()) + 1;
+      if (nelts > 256)
+	return NULL_TREE;
+
+      if (nelts > 1)
+	{
+	  str.reserve (idx);
+	  str.quick_grow_cleared (idx);
+	}
+
+      if (idx > maxelts)
+	return NULL_TREE;
+
+      str.safe_insert (idx, val);
+    }
+
+  if (!nelts || str.length () < i)
+    /* Append a nul for the empty initializer { } and for the last
+       explicit initializer in the loop above that is a nul.  */
+    str.safe_push (0);
+
+  /* Build a string literal but return the embedded STRING_CST.  */
+  tree res = build_string_literal (str.length (), str.begin ());
+  res = TREE_OPERAND (TREE_OPERAND (res, 0), 0);
+  return res;
+}
+
 #include "gt-c-family-c-common.h"
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(revision 263372)
+++ gcc/c-family/c-common.h	(working copy)
@@ -1331,6 +1331,7 @@ extern void maybe_add_include_fixit (rich_location
 extern void maybe_suggest_missing_token_insertion (rich_location *richloc,
 						   enum cpp_ttype token_type,
 						   location_t prev_token_loc);
+extern tree braced_list_to_string (tree, tree, tree (*)(tree, tree) = NULL);
 
 #if CHECKING_P
 namespace selftest {
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 263372)
+++ gcc/cp/parser.c	(working copy)
@@ -19419,6 +19419,30 @@ strip_declarator_types (tree type, cp_declarator *
   return type;
 }
 
+/* Attempt to determine the constant VALUE of integral type and convert
+   it to TYPE, issuing narrowing warnings/errors as necessary.  Return
+   the constant result or null on failure.  Callback for
+   braced_list_to_string.  */
+
+static tree
+eval_check_narrowing (tree type, tree value)
+{
+  if (tree valtype = TREE_TYPE (value))
+    {
+      if (TREE_CODE (valtype) != INTEGER_TYPE)
+	return NULL_TREE;
+    }
+  else
+    return NULL_TREE;
+
+  value = scalar_constant_value (value);
+  if (!value)
+    return NULL_TREE;
+
+  check_narrowing (type, value, tf_warning_or_error);
+  return value;
+}
+
 /* Declarators [gram.dcl.decl] */
 
 /* Parse an init-declarator.
@@ -19825,6 +19849,18 @@ cp_parser_init_declarator (cp_parser* parser,
 	    finish_lambda_scope ();
 	  if (initializer == error_mark_node)
 	    cp_parser_skip_to_end_of_statement (parser);
+	  else if (decl)
+	    {
+	      /* Try to convert a string CONSTRUCTOR into a STRING_CST.  */
+	      tree valtype = TREE_TYPE (decl);
+	      if (TREE_CODE (valtype) == ARRAY_TYPE
+		  && TYPE_STRING_FLAG (TREE_TYPE (valtype))
+		  && TREE_CODE (initializer) == CONSTRUCTOR
+		  && TREE_TYPE (initializer) == init_list_type_node)
+		if (tree str = braced_list_to_string (valtype, initializer,
+						      eval_check_narrowing))
+		  initializer = str;
+	    }
 	}
     }
 
Index: gcc/testsuite/g++.dg/init/string2.C
===================================================================
--- gcc/testsuite/g++.dg/init/string2.C	(nonexistent)
+++ gcc/testsuite/g++.dg/init/string2.C	(working copy)
@@ -0,0 +1,85 @@
+// PR tree-optimization/71625 - missing strlen optimization on different
+// array initialization style
+//
+// Verify that strlen() calls with constant character array arguments
+// initialized with string constants are folded.  (This is a small
+// subset of pr63989).
+// { dg-do compile }
+// { dg-options "-O0 -Wno-error=narrowing -fdump-tree-gimple" }
+
+#define A(expr) do { typedef char A[-1 + 2 * !!(expr)]; } while (0)
+
+const char a0[] = { 'a', 'b', 'c', '\0' };
+
+int len0 ()
+{
+  return __builtin_strlen (a0);
+}
+
+// Verify that narrowing warnings are preserved.
+const signed char
+sa0[] = { 'a', 'b', 255, '\0' };   // { dg-warning "\\\[\(-Wnarrowing|-Woverflow\)" "" { target { ! c++98_only } } }
+
+int lens0 ()
+{
+  return __builtin_strlen ((const char*)sa0);
+}
+
+const unsigned char
+ua0[] = { 'a', 'b', -1, '\0' };   // { dg-warning "\\\[\(-Wnarrowing|-Woverflow\)" "" { target { ! c++98_only } } }
+
+int lenu0 ()
+{
+  return __builtin_strlen ((const char*)ua0);
+}
+
+const char c = 0;
+const char a1[] = { 'a', 'b', 'c', c };
+
+int len1 ()
+{
+  return __builtin_strlen (a1);
+}
+
+const wchar_t ws4[] = { 1, 2, 3, 4 };
+const wchar_t ws7[] = { 1, 2, 3, 4, 0, 0, 0 };
+const wchar_t ws9[9] = { 1, 2, 3, 4, 0 };
+
+void wsize ()
+{
+  A (sizeof ws4 == 4 * sizeof *ws4);
+  A (ws4[0] == 1 && ws4[1] == 2 && ws4[2] == 3 && ws4[3] == 4);
+
+  A (sizeof ws7 == 7 * sizeof *ws7);
+  A (ws7[0] == 1 && ws7[1] == 2 && ws7[2] == 3 && ws7[4] == 4
+     && !ws7[5] && !ws7[6]);
+
+  A (sizeof ws9 == 9 * sizeof *ws9);
+  A (ws9[0] == 1 && ws9[1] == 2 && ws9[2] == 3 && ws9[4] == 4
+     && !ws9[5] && !ws9[6] && !ws9[7] && !ws9[8]);
+}
+
+#if 0
+
+// The following aren't handled.
+
+const char &cref = c;
+const char a2[] = { 'a', 'b', 'c', cref };
+
+int len2 ()
+{
+  return __builtin_strlen (a2);
+}
+
+
+const char* const cptr = &cref;
+const char a3[] = { 'a', 'b', 'c', *cptr };
+
+int len3 ()
+{
+  return __builtin_strlen (a3);
+}
+
+#endif
+
+// { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
Index: gcc/testsuite/g++.dg/init/string3.C
===================================================================
--- gcc/testsuite/g++.dg/init/string3.C	(nonexistent)
+++ gcc/testsuite/g++.dg/init/string3.C	(working copy)
@@ -0,0 +1,36 @@
+// PR tree-optimization/71625 - missing strlen optimization on different
+// array initialization style
+//
+// Verify that strlen() call with a constant character array argument
+// initialized with non-constant elements isn't folded.  (This is a small
+// subset of pr63989).
+//
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-optimized" }
+
+
+extern const char c;
+const char a0[] = { 'a', 'b', 'c', c };
+
+int len0 ()
+{
+  return __builtin_strlen (a0);
+}
+
+const char &ref = c;
+const char a1[] = { 'a', 'b', 'c', ref };
+
+int len1 ()
+{
+  return __builtin_strlen (a1);
+}
+
+const char* const ptr = &c;
+const char a2[] = { 'a', 'b', 'c', *ptr };
+
+int len2 ()
+{
+  return __builtin_strlen (a2);
+}
+
+// { dg-final { scan-tree-dump-times "strlen" 3 "optimized" } }
Index: gcc/testsuite/gcc.dg/strlenopt-55.c
===================================================================
--- gcc/testsuite/gcc.dg/strlenopt-55.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/strlenopt-55.c	(working copy)
@@ -0,0 +1,230 @@
+/* PR tree-optimization/71625 - missing strlen optimization on different
+   array initialization style
+
+   Verify that strlen() of braced initialized array is folded
+   { dg-do compile }
+   { dg-options "-O1 -Wall -fdump-tree-gimple -fdump-tree-optimized" } */
+
+#include "strlenopt.h"
+
+#define S								\
+  "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"	\
+  "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"	\
+  "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"	\
+  "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"	\
+  "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"	\
+  "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"	\
+  "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"	\
+  "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"	\
+  "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"	\
+  "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"	\
+  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"	\
+  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"	\
+  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"	\
+  "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"	\
+  "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"	\
+  "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+
+/* Arrays of char, signed char, and unsigned char to verify that
+   the length and contents of all are the same as that of the string
+   literal above.  */
+
+const char c256[] = {
+  S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10],
+  S[11], S[12], S[13], S[14], S[15], S[16], S[17], S[18], S[19], S[20],
+  S[21], S[22], S[23], S[24], S[25], S[26], S[27], S[28], S[29], S[30],
+  S[31], S[32], S[33], S[34], S[35], S[36], S[37], S[38], S[39], S[40],
+  S[41], S[42], S[43], S[44], S[45], S[46], S[47], S[48], S[49], S[50],
+  S[51], S[52], S[53], S[54], S[55], S[56], S[57], S[58], S[59], S[60],
+  S[61], S[62], S[63], S[64], S[65], S[66], S[67], S[68], S[69], S[70],
+  S[71], S[72], S[73], S[74], S[75], S[76], S[77], S[78], S[79], S[80],
+  S[81], S[82], S[83], S[84], S[85], S[86], S[87], S[88], S[89], S[90],
+  S[91], S[92], S[93], S[94], S[95], S[96], S[97], S[98], S[99], S[100],
+  S[101], S[102], S[103], S[104], S[105], S[106], S[107], S[108], S[109],
+  S[110], S[111], S[112], S[113], S[114], S[115], S[116], S[117], S[118],
+  S[119], S[120], S[121], S[122], S[123], S[124], S[125], S[126], S[127],
+  S[128], S[129], S[130], S[131], S[132], S[133], S[134], S[135], S[136],
+  S[137], S[138], S[139], S[140], S[141], S[142], S[143], S[144], S[145],
+  S[146], S[147], S[148], S[149], S[150], S[151], S[152], S[153], S[154],
+  S[155], S[156], S[157], S[158], S[159], S[160], S[161], S[162], S[163],
+  S[164], S[165], S[166], S[167], S[168], S[169], S[170], S[171], S[172],
+  S[173], S[174], S[175], S[176], S[177], S[178], S[179], S[180], S[181],
+  S[182], S[183], S[184], S[185], S[186], S[187], S[188], S[189], S[190],
+  S[191], S[192], S[193], S[194], S[195], S[196], S[197], S[198], S[199],
+  S[200], S[201], S[202], S[203], S[204], S[205], S[206], S[207], S[208],
+  S[209], S[210], S[211], S[212], S[213], S[214], S[215], S[216], S[217],
+  S[218], S[219], S[220], S[221], S[222], S[223], S[224], S[225], S[226],
+  S[227], S[228], S[229], S[230], S[231], S[232], S[233], S[234], S[235],
+  S[236], S[237], S[238], S[239], S[240], S[241], S[242], S[243], S[244],
+  S[245], S[246], S[247], S[248], S[249], S[250], S[251], S[252], S[253],
+  S[254], S[255] /* = NUL */
+};
+
+const signed char sc256[] = {
+  S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10],
+  S[11], S[12], S[13], S[14], S[15], S[16], S[17], S[18], S[19], S[20],
+  S[21], S[22], S[23], S[24], S[25], S[26], S[27], S[28], S[29], S[30],
+  S[31], S[32], S[33], S[34], S[35], S[36], S[37], S[38], S[39], S[40],
+  S[41], S[42], S[43], S[44], S[45], S[46], S[47], S[48], S[49], S[50],
+  S[51], S[52], S[53], S[54], S[55], S[56], S[57], S[58], S[59], S[60],
+  S[61], S[62], S[63], S[64], S[65], S[66], S[67], S[68], S[69], S[70],
+  S[71], S[72], S[73], S[74], S[75], S[76], S[77], S[78], S[79], S[80],
+  S[81], S[82], S[83], S[84], S[85], S[86], S[87], S[88], S[89], S[90],
+  S[91], S[92], S[93], S[94], S[95], S[96], S[97], S[98], S[99], S[100],
+  S[101], S[102], S[103], S[104], S[105], S[106], S[107], S[108], S[109],
+  S[110], S[111], S[112], S[113], S[114], S[115], S[116], S[117], S[118],
+  S[119], S[120], S[121], S[122], S[123], S[124], S[125], S[126], S[127],
+  S[128], S[129], S[130], S[131], S[132], S[133], S[134], S[135], S[136],
+  S[137], S[138], S[139], S[140], S[141], S[142], S[143], S[144], S[145],
+  S[146], S[147], S[148], S[149], S[150], S[151], S[152], S[153], S[154],
+  S[155], S[156], S[157], S[158], S[159], S[160], S[161], S[162], S[163],
+  S[164], S[165], S[166], S[167], S[168], S[169], S[170], S[171], S[172],
+  S[173], S[174], S[175], S[176], S[177], S[178], S[179], S[180], S[181],
+  S[182], S[183], S[184], S[185], S[186], S[187], S[188], S[189], S[190],
+  S[191], S[192], S[193], S[194], S[195], S[196], S[197], S[198], S[199],
+  S[200], S[201], S[202], S[203], S[204], S[205], S[206], S[207], S[208],
+  S[209], S[210], S[211], S[212], S[213], S[214], S[215], S[216], S[217],
+  S[218], S[219], S[220], S[221], S[222], S[223], S[224], S[225], S[226],
+  S[227], S[228], S[229], S[230], S[231], S[232], S[233], S[234], S[235],
+  S[236], S[237], S[238], S[239], S[240], S[241], S[242], S[243], S[244],
+  S[245], S[246], S[247], S[248], S[249], S[250], S[251], S[252], S[253],
+  S[254], S[255] /* = NUL */
+};
+
+const unsigned char uc256[] = {
+  S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10],
+  S[11], S[12], S[13], S[14], S[15], S[16], S[17], S[18], S[19], S[20],
+  S[21], S[22], S[23], S[24], S[25], S[26], S[27], S[28], S[29], S[30],
+  S[31], S[32], S[33], S[34], S[35], S[36], S[37], S[38], S[39], S[40],
+  S[41], S[42], S[43], S[44], S[45], S[46], S[47], S[48], S[49], S[50],
+  S[51], S[52], S[53], S[54], S[55], S[56], S[57], S[58], S[59], S[60],
+  S[61], S[62], S[63], S[64], S[65], S[66], S[67], S[68], S[69], S[70],
+  S[71], S[72], S[73], S[74], S[75], S[76], S[77], S[78], S[79], S[80],
+  S[81], S[82], S[83], S[84], S[85], S[86], S[87], S[88], S[89], S[90],
+  S[91], S[92], S[93], S[94], S[95], S[96], S[97], S[98], S[99], S[100],
+  S[101], S[102], S[103], S[104], S[105], S[106], S[107], S[108], S[109],
+  S[110], S[111], S[112], S[113], S[114], S[115], S[116], S[117], S[118],
+  S[119], S[120], S[121], S[122], S[123], S[124], S[125], S[126], S[127],
+  S[128], S[129], S[130], S[131], S[132], S[133], S[134], S[135], S[136],
+  S[137], S[138], S[139], S[140], S[141], S[142], S[143], S[144], S[145],
+  S[146], S[147], S[148], S[149], S[150], S[151], S[152], S[153], S[154],
+  S[155], S[156], S[157], S[158], S[159], S[160], S[161], S[162], S[163],
+  S[164], S[165], S[166], S[167], S[168], S[169], S[170], S[171], S[172],
+  S[173], S[174], S[175], S[176], S[177], S[178], S[179], S[180], S[181],
+  S[182], S[183], S[184], S[185], S[186], S[187], S[188], S[189], S[190],
+  S[191], S[192], S[193], S[194], S[195], S[196], S[197], S[198], S[199],
+  S[200], S[201], S[202], S[203], S[204], S[205], S[206], S[207], S[208],
+  S[209], S[210], S[211], S[212], S[213], S[214], S[215], S[216], S[217],
+  S[218], S[219], S[220], S[221], S[222], S[223], S[224], S[225], S[226],
+  S[227], S[228], S[229], S[230], S[231], S[232], S[233], S[234], S[235],
+  S[236], S[237], S[238], S[239], S[240], S[241], S[242], S[243], S[244],
+  S[245], S[246], S[247], S[248], S[249], S[250], S[251], S[252], S[253],
+  S[254], S[255] /* = NUL */
+};
+
+const __CHAR16_TYPE__ c16_4[] = {
+  1, 0x7fff, 0x8000, 0xffff,
+  0x10000   /* { dg-warning "\\\[-Woverflow]" } */
+};
+
+const char a2_implicit[2] = { };
+const char a3_implicit[3] = { };
+
+const char a3_nul[3] = { 0 };
+const char a5_nul1[3] = { [1] = 0 };
+const char a7_nul2[3] = { [2] = 0 };
+
+const char ax_2_nul[] = { '1', '2', '\0' };
+const char ax_3_nul[] = { '1', '2', '3', '\0' };
+
+const char ax_3_des_nul[] = { [3] = 0, [2] = '3', [1] = '2', [0] = '1' };
+
+const char ax_3[] = { '1', '2', '3' };
+const char a3_3[3] = { '1', '2', '3' };
+
+const char ax_100_3[] = { '1', '2', '3', [100] = '\0' };
+
+#define CONCAT(x, y) x ## y
+#define CAT(x, y) CONCAT (x, y)
+#define FAILNAME(name) CAT (call_ ## name ##_on_line_, __LINE__)
+
+#define FAIL(name) do {				\
+    extern void FAILNAME (name) (void);		\
+    FAILNAME (name)();				\
+  } while (0)
+
+/* Macro to emit a call to funcation named
+   call_in_true_branch_not_eliminated_on_line_NNN()
+   for each call that's expected to be eliminated.  The dg-final
+   scan-tree-dump-time directive at the bottom of the test verifies
+   that no such call appears in output.  */
+#define ELIM(expr)							\
+  if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
+
+#define T(s, n) ELIM (strlen (s) == n)
+
+void test_nulstring (void)
+{
+  T (a2_implicit, 0);
+  T (a3_implicit, 0);
+
+  T (a3_nul, 0);
+  T (a5_nul1, 0);
+  T (a7_nul2, 0);
+
+  T (ax_2_nul, 2);
+  T (ax_3_nul, 3);
+  T (ax_3_des_nul, 3);
+
+  T (ax_100_3, 3);
+  T (ax_100_3 + 4, 0);
+  ELIM (101 == sizeof ax_100_3);
+  ELIM ('\0' == ax_100_3[100]);
+
+  /* Verify that all three character arrays have the same length
+     as the string literal they are initialized with.  */
+  T (S, 255);
+  T (c256, 255);
+  T ((const char*)sc256, 255);
+  T ((const char*)uc256, 255);
+
+  /* Verify that all three character arrays have the same contents
+     as the string literal they are initialized with.  */
+  ELIM (0 == memcmp (c256, S, sizeof c256));
+  ELIM (0 == memcmp (c256, (const char*)sc256, sizeof c256));
+  ELIM (0 == memcmp (c256, (const char*)uc256, sizeof c256));
+
+  ELIM (0 == strcmp (c256, (const char*)sc256));
+  ELIM (0 == strcmp (c256, (const char*)uc256));
+
+  /* Verify that the char16_t array has the expected contents.  */
+  ELIM (c16_4[0] == 1 && c16_4[1] == 0x7fff
+	&& c16_4[2] == 0x8000 && c16_4[3] == 0xffff
+	&& c16_4[4] == 0);
+}
+
+/* Verify that excessively large initializers don't run out of
+   memory.  Also verify that the they have the expected size and
+   contents.  */
+
+#define MAX (__PTRDIFF_MAX__ - 1)
+
+const char large_string[] = { 'a', [1234] = 'b', [MAX] = '\0' };
+
+const void test_large_string_size (void)
+{
+  ELIM (sizeof large_string == MAX + 1);
+
+  /* The following expressions are not folded without optimization.  */
+  ELIM ('a'  == large_string[0]);
+  ELIM ('\0' == large_string[1233]);
+  ELIM ('b'  == large_string[1234]);
+  ELIM ('\0' == large_string[1235]);
+  ELIM ('\0' == large_string[MAX - 1]);
+}
+
+
+/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "memcmp" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "strcmp" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated" 0 "optimized" } } */
Index: gcc/testsuite/gcc.dg/strlenopt-56.c
===================================================================
--- gcc/testsuite/gcc.dg/strlenopt-56.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/strlenopt-56.c	(working copy)
@@ -0,0 +1,50 @@
+/* PR tree-optimization/71625 - conversion of braced initializers to strings
+   Verify that array elements have the expected values regardless of sign
+   and non-ASCII execution character set.
+   { dg-do compile }
+   { dg-require-iconv "IBM1047" }
+   { dg-options "-O -Wall -fexec-charset=IBM1047 -fdump-tree-gimple -fdump-tree-optimized" } */
+
+#include "strlenopt.h"
+
+const char a[] = { 'a', 129, 0 };
+const signed char b[] = { 'b', 130, 0 };
+const unsigned char c[] = { 'c', 131, 0 };
+
+const char s[] = "a\201";
+const signed char ss[] = "b\202";
+const unsigned char us[] = "c\203";
+
+
+#define A(expr)   ((expr) ? (void)0 : __builtin_abort ())
+
+void test_values (void)
+{
+  A (a[0] == a[1]);
+  A (a[1] == 'a');
+
+  A (b[0] == b[1]);
+  A (b[1] == (signed char)'b');
+
+  A (c[0] == c[1]);
+  A (c[1] == (unsigned char)'c');
+}
+
+void test_lengths (void)
+{
+  A (2 == strlen (a));
+  A (2 == strlen ((const char*)b));
+  A (2 == strlen ((const char*)c));
+}
+
+void test_contents (void)
+{
+  A (0 == strcmp (a, s));
+  A (0 == strcmp ((const char*)b, (const char*)ss));
+  A (0 == strcmp ((const char*)c, (const char*)us));
+}
+
+
+/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "strcmp" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "abort" 0 "optimized" } } */

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-07 11:31       ` Joseph Myers
@ 2018-08-07 23:05         ` Martin Sebor
  0 siblings, 0 replies; 45+ messages in thread
From: Martin Sebor @ 2018-08-07 23:05 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Gcc Patch List, Jason Merrill

On 08/07/2018 05:31 AM, Joseph Myers wrote:
> On Tue, 7 Aug 2018, Martin Sebor wrote:
>
>> 2) skipping embedded nuls made it possible to create a string
>> with fewer elements than the initializer array, which caused
>> arrays with unspecified bound to be smaller than they would
>> have been otherwise
>
> I think there should be explicit tests of sizeof for arrays with
> unspecified bound - to make sure both that it isn't any smaller than it
> should be, but also that any NULs implicitly added for a STRING_CST don't
> make the arrays any larger than their size should be for the originally
> given initializer that doesn't have a 0 as the last element.

I added some more tests to the latest revision of the patch.
Please see it in my other response.

Thanks
Martin

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-07 23:04       ` Martin Sebor
@ 2018-08-08 11:09         ` Jason Merrill
  2018-08-09  0:17           ` Martin Sebor
  0 siblings, 1 reply; 45+ messages in thread
From: Jason Merrill @ 2018-08-08 11:09 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Gcc Patch List, Joseph Myers

On Wed, Aug 8, 2018 at 9:04 AM, Martin Sebor <msebor@gmail.com> wrote:
> On 08/07/2018 02:57 AM, Jason Merrill wrote:
>>
>> On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>
>>> On 07/31/2018 07:38 AM, Jason Merrill wrote:
>>>>
>>>>
>>>> On Tue, Jul 31, 2018 at 9:51 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>>>
>>>>>
>>>>> The middle-end contains code to determine the lengths of constant
>>>>> character arrays initialized by string literals.  The code is used
>>>>> in a number of optimizations and warnings.
>>>>>
>>>>> However, the code is unable to deal with constant arrays initialized
>>>>> using the braced initializer syntax, as in
>>>>>
>>>>>   const char a[] = { '1', '2', '\0' };
>>>>>
>>>>> The attached patch extends the C and C++ front-ends to convert such
>>>>> initializers into a STRING_CST form.
>>>>>
>>>>> The goal of this work is to both enable existing optimizations for
>>>>> such arrays, and to help detect bugs due to using non-nul terminated
>>>>> arrays where nul-terminated strings are expected.  The latter is
>>>>> an extension of the GCC 8 _Wstringop-overflow and
>>>>> -Wstringop-truncation warnings that help detect or prevent reading
>>>>> past the end of dynamically created character arrays.  Future work
>>>>> includes detecting potential past-the-end reads from uninitialized
>>>>> local character arrays.
>>>>
>>>>
>>>>
>>>>>   && TYPE_MAIN_VARIANT (TREE_TYPE (valtype)) == char_type_node)
>>>>
>>>>
>>>>
>>>> Why? Don't we want this for other character types as well?
>>>
>>>
>>> It suppresses narrowing warnings for things like
>>>
>>>   signed char a[] = { 0xff };
>>>
>>> (there are a couple of tests that exercise this).
>>
>>
>> Why is plain char different in this respect?  Presumably one of
>>
>> char a[] = { -1 };
>> char b[] = { 0xff };
>>
>> should give the same narrowing warning, depending on whether char is
>> signed.
>
>
> Right.  I've added more tests to verify that it does.
>
>>> At the same time, STRING_CST is supposed to be able to represent
>>> strings of any integer type so there should be a way to make it
>>> work.  On the flip side, recent discussions of changes in this
>>> area suggest there may be bugs in the wide character handling of
>>> STRING_CST so those would need to be fixed before relying on it
>>> for robust support.
>>>
>>> In any case, if you have a suggestion for how to make it work for
>>> at least the narrow character types I'll adjust the patch.
>>
>>
>> I suppose braced_list_to_string should call check_narrowing for C++.
>
>
> I see.  I've made that change.  That has made it possible to
> convert arrays of all character types.  Thanks!
>
>> Currently it uses tree_fits_shwi_p (signed host_wide_int) and then
>> stores the extracted value in a host unsigned int, which is then
>> converted to host char.  Does the right thing happen for -fsigned-char
>> or targets with a different character set?
>
> I believe so.  I've added tests for these too (ASCII and EBCDIC)
> and also changed the type of the extracted value to HWI to match
> (it doesn't change the results of the tests).
>
> Attached is an updated patch with these changes plus more tests
> as suggested by Joseph.

Great.  Can we also move the call to braced_list_to_string into
check_initializer, so it works for templates as well?  As a case just
before the block that calls reshape_init seems appropriate.

Jason

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-08 11:09         ` Jason Merrill
@ 2018-08-09  0:17           ` Martin Sebor
  2018-08-09 22:07             ` Joseph Myers
                               ` (2 more replies)
  0 siblings, 3 replies; 45+ messages in thread
From: Martin Sebor @ 2018-08-09  0:17 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Gcc Patch List, Joseph Myers

[-- Attachment #1: Type: text/plain, Size: 4313 bytes --]

On 08/08/2018 05:08 AM, Jason Merrill wrote:
> On Wed, Aug 8, 2018 at 9:04 AM, Martin Sebor <msebor@gmail.com> wrote:
>> On 08/07/2018 02:57 AM, Jason Merrill wrote:
>>>
>>> On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>>
>>>> On 07/31/2018 07:38 AM, Jason Merrill wrote:
>>>>>
>>>>>
>>>>> On Tue, Jul 31, 2018 at 9:51 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>>>>
>>>>>>
>>>>>> The middle-end contains code to determine the lengths of constant
>>>>>> character arrays initialized by string literals.  The code is used
>>>>>> in a number of optimizations and warnings.
>>>>>>
>>>>>> However, the code is unable to deal with constant arrays initialized
>>>>>> using the braced initializer syntax, as in
>>>>>>
>>>>>>   const char a[] = { '1', '2', '\0' };
>>>>>>
>>>>>> The attached patch extends the C and C++ front-ends to convert such
>>>>>> initializers into a STRING_CST form.
>>>>>>
>>>>>> The goal of this work is to both enable existing optimizations for
>>>>>> such arrays, and to help detect bugs due to using non-nul terminated
>>>>>> arrays where nul-terminated strings are expected.  The latter is
>>>>>> an extension of the GCC 8 _Wstringop-overflow and
>>>>>> -Wstringop-truncation warnings that help detect or prevent reading
>>>>>> past the end of dynamically created character arrays.  Future work
>>>>>> includes detecting potential past-the-end reads from uninitialized
>>>>>> local character arrays.
>>>>>
>>>>>
>>>>>
>>>>>>   && TYPE_MAIN_VARIANT (TREE_TYPE (valtype)) == char_type_node)
>>>>>
>>>>>
>>>>>
>>>>> Why? Don't we want this for other character types as well?
>>>>
>>>>
>>>> It suppresses narrowing warnings for things like
>>>>
>>>>   signed char a[] = { 0xff };
>>>>
>>>> (there are a couple of tests that exercise this).
>>>
>>>
>>> Why is plain char different in this respect?  Presumably one of
>>>
>>> char a[] = { -1 };
>>> char b[] = { 0xff };
>>>
>>> should give the same narrowing warning, depending on whether char is
>>> signed.
>>
>>
>> Right.  I've added more tests to verify that it does.
>>
>>>> At the same time, STRING_CST is supposed to be able to represent
>>>> strings of any integer type so there should be a way to make it
>>>> work.  On the flip side, recent discussions of changes in this
>>>> area suggest there may be bugs in the wide character handling of
>>>> STRING_CST so those would need to be fixed before relying on it
>>>> for robust support.
>>>>
>>>> In any case, if you have a suggestion for how to make it work for
>>>> at least the narrow character types I'll adjust the patch.
>>>
>>>
>>> I suppose braced_list_to_string should call check_narrowing for C++.
>>
>>
>> I see.  I've made that change.  That has made it possible to
>> convert arrays of all character types.  Thanks!
>>
>>> Currently it uses tree_fits_shwi_p (signed host_wide_int) and then
>>> stores the extracted value in a host unsigned int, which is then
>>> converted to host char.  Does the right thing happen for -fsigned-char
>>> or targets with a different character set?
>>
>> I believe so.  I've added tests for these too (ASCII and EBCDIC)
>> and also changed the type of the extracted value to HWI to match
>> (it doesn't change the results of the tests).
>>
>> Attached is an updated patch with these changes plus more tests
>> as suggested by Joseph.
>
> Great.  Can we also move the call to braced_list_to_string into
> check_initializer, so it works for templates as well?  As a case just
> before the block that calls reshape_init seems appropriate.

Done in the attached patch.  I've also avoided dealing with
zero-length arrays and added tests to make sure their size
stays is regardless of the form of their initializer and
the appropriate warnings are issued.

Using build_string() rather than build_string_literal() needed
a tweak in digest_init_r().  It didn't break anything but since
the array type may not have a domain yet, neither will the
string.  It looks like that may get adjusted later on but I've
temporarily guarded the code with #if 1.  If the change is
fine I'll remove the #if before committing.

This initial patch only handles narrow character initializers
(i.e., those with TYPE_STRING_FLAG set).  Once this gets some
exposure I'd like to extend it to other character types,
including wchar_t.

Martin

[-- Attachment #2: gcc-71625.diff --]
[-- Type: text/x-patch, Size: 27489 bytes --]

PR tree-optimization/71625 - missing strlen optimization on different array initialization style

gcc/c/ChangeLog:

	PR tree-optimization/71625
	* c-parser.c (c_parser_declaration_or_fndef): Call
	braced_list_to_string.

gcc/c-family/ChangeLog:

	PR tree-optimization/71625
	* c-common.c (braced_list_to_string): New function.
	* c-common.h (braced_list_to_string): Declare it.

gcc/cp/ChangeLog:

	PR tree-optimization/71625
	* decl.c (check_initializer):  Call braced_list_to_string.
	(eval_check_narrowing): New function.
	* gcc/cp/typeck2.c (digest_init_r): Accept strings literals
	as initilizers for all narrow character types.

gcc/testsuite/ChangeLog:

	PR tree-optimization/71625
	* g++.dg/init/string2.C: New test.
	* g++.dg/init/string3.C: New test.
	* g++.dg/init/string4.C: New test.
	* gcc.dg/init-string-3.c: New test.
	* gcc.dg/strlenopt-55.c: New test.
	* gcc.dg/strlenopt-56.c: New test.
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index d919605..b10d9c9 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -8509,4 +8509,102 @@ maybe_add_include_fixit (rich_location *richloc, const char *header)
   free (text);
 }
 
+/* Attempt to convert a braced array initializer list CTOR for array
+   TYPE into a STRING_CST for convenience and efficiency.  When non-null,
+   use EVAL to attempt to evalue constants (used by C++).  Return
+   the converted string on success or null on failure.  */
+
+tree
+braced_list_to_string (tree type, tree ctor, tree (*eval)(tree, tree))
+{
+  unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (ctor);
+
+  /* If the array has an explicit bound, use it to constrain the size
+     of the string.  If it doesn't, be sure to create a string that's
+     as long as implied by the index of the last zero specified via
+     a designator, as in:
+       const char a[] = { [7] = 0 };  */
+  unsigned HOST_WIDE_INT maxelts = HOST_WIDE_INT_M1U;
+  if (tree size = TYPE_SIZE_UNIT (type))
+    {
+      if (tree_fits_uhwi_p (size))
+	{
+	  maxelts = tree_to_uhwi (size);
+	  maxelts /= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
+
+	  /* Avoid converting initializers for zero-length arrays.  */
+	  if (!maxelts)
+	    return NULL_TREE;
+	}
+    }
+  else if (!nelts)
+    /* Avoid handling the undefined/erroneous case of an empty
+       initializer for an arrays with unspecified bound.  */
+    return NULL_TREE;
+
+  tree eltype = TREE_TYPE (type);
+
+  auto_vec<char> str;
+  str.reserve (nelts + 1);
+
+  unsigned HOST_WIDE_INT i;
+  tree index, value;
+
+  FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), i, index, value)
+    {
+      unsigned HOST_WIDE_INT idx = index ? tree_to_uhwi (index) : i;
+
+      /* auto_vec is limited to UINT_MAX elements.  */
+      if (idx > UINT_MAX)
+	return NULL_TREE;
+
+      /* Attempt to evaluate constants.  */
+      if (eval)
+	value = eval (eltype, value);
+
+      /* Avoid non-constant initializers.  */
+     if (!tree_fits_shwi_p (value))
+	return NULL_TREE;
+
+      /* Skip over embedded nuls except the last one (initializer
+	 elements are in ascending order of indices).  */
+      HOST_WIDE_INT val = tree_to_shwi (value);
+      if (!val && i + 1 < nelts)
+	continue;
+
+      /* Bail if the CTOR has a block of more than 256 embedded nuls
+	 due to implicitly initialized elements.  */
+      unsigned nchars = (idx - str.length ()) + 1;
+      if (nchars > 256)
+	return NULL_TREE;
+
+      if (nchars > 1)
+	{
+	  str.reserve (idx);
+	  str.quick_grow_cleared (idx);
+	}
+
+      if (idx > maxelts)
+	return NULL_TREE;
+
+      str.safe_insert (idx, val);
+    }
+
+  if (!nelts)
+    /* Append a nul for the empty initializer { }.  */
+    str.safe_push (0);
+
+#if 1
+  /* Build a STRING_CST with the same type as the array, which
+     may be an array of unknown bound.  */
+  tree res = build_string (str.length (), str.begin ());
+  TREE_TYPE (res) = type;
+#else
+  /* Build a string literal but return the embedded STRING_CST.  */
+  tree res = build_string_literal (str.length (), str.begin (), eltype);
+  res = TREE_OPERAND (TREE_OPERAND (res, 0), 0);
+#endif
+  return res;
+}
+
 #include "gt-c-family-c-common.h"
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index fcec95b..8a802bb 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -1331,6 +1331,7 @@ extern void maybe_add_include_fixit (rich_location *, const char *);
 extern void maybe_suggest_missing_token_insertion (rich_location *richloc,
 						   enum cpp_ttype token_type,
 						   location_t prev_token_loc);
+extern tree braced_list_to_string (tree, tree, tree (*)(tree, tree) = NULL);
 
 #if CHECKING_P
 namespace selftest {
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 7a92628..5ad4f57 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -2126,6 +2126,15 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
 	      if (d != error_mark_node)
 		{
 		  maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
+
+		  /* Try to convert a string CONSTRUCTOR into a STRING_CST.  */
+		  tree valtype = TREE_TYPE (init.value);
+		  if (TREE_CODE (init.value) == CONSTRUCTOR
+		      && TREE_CODE (valtype) == ARRAY_TYPE
+		      && TYPE_STRING_FLAG (TREE_TYPE (valtype)))
+		    if (tree str = braced_list_to_string (valtype, init.value))
+		      init.value = str;
+
 		  finish_decl (d, init_loc, init.value,
 			       init.original_type, asm_name);
 		}
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 78ebbde..d2c5b5d 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6282,6 +6282,30 @@ build_aggr_init_full_exprs (tree decl, tree init, int flags)
   return build_aggr_init (decl, init, flags, tf_warning_or_error);
 }
 
+/* Attempt to determine the constant VALUE of integral type and convert
+   it to TYPE, issuing narrowing warnings/errors as necessary.  Return
+   the constant result or null on failure.  Callback for
+   braced_list_to_string.  */
+
+static tree
+eval_check_narrowing (tree type, tree value)
+{
+  if (tree valtype = TREE_TYPE (value))
+    {
+      if (TREE_CODE (valtype) != INTEGER_TYPE)
+	return NULL_TREE;
+    }
+  else
+    return NULL_TREE;
+
+  value = scalar_constant_value (value);
+  if (!value)
+    return NULL_TREE;
+
+  check_narrowing (type, value, tf_warning_or_error);
+  return value;
+}
+
 /* Verify INIT (the initializer for DECL), and record the
    initialization in DECL_INITIAL, if appropriate.  CLEANUP is as for
    grok_reference_init.
@@ -6397,7 +6421,18 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
 	    }
 	  else
 	    {
-	      init = reshape_init (type, init, tf_warning_or_error);
+	      /* Try to convert a string CONSTRUCTOR into a STRING_CST.  */
+	      tree valtype = TREE_TYPE (decl);
+	      if (TREE_CODE (valtype) == ARRAY_TYPE
+		  && TYPE_STRING_FLAG (TREE_TYPE (valtype))
+		  && TREE_CODE (init) == CONSTRUCTOR
+		  && TREE_TYPE (init) == init_list_type_node)
+		if (tree str = braced_list_to_string (valtype, init,
+						      eval_check_narrowing))
+		  init = str;
+
+	      if (TREE_CODE (init) != STRING_CST)
+		init = reshape_init (type, init, tf_warning_or_error);
 	      flags |= LOOKUP_NO_NARROWING;
 	    }
 	}
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 7763d53..72515d9 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1056,7 +1056,9 @@ digest_init_r (tree type, tree init, int nested, int flags,
 
 	  if (TYPE_PRECISION (typ1) == BITS_PER_UNIT)
 	    {
-	      if (char_type != char_type_node)
+	      if (char_type != char_type_node
+		  && char_type != signed_char_type_node
+		  && char_type != unsigned_char_type_node)
 		{
 		  if (complain & tf_error)
 		    error_at (loc, "char-array initialized from wide string");
diff --git a/gcc/testsuite/g++.dg/init/string2.C b/gcc/testsuite/g++.dg/init/string2.C
new file mode 100644
index 0000000..5da13bd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/string2.C
@@ -0,0 +1,104 @@
+// PR tree-optimization/71625 - missing strlen optimization on different
+// array initialization style
+//
+// Verify that strlen() calls with constant character array arguments
+// initialized with string constants are folded.  (This is a small
+// subset of pr71625).
+// { dg-do compile }
+// { dg-options "-O0 -Wno-error=narrowing -fdump-tree-gimple" }
+
+#define A(expr) do { typedef char A[-1 + 2 * !!(expr)]; } while (0)
+
+/* This is undefined but accepted without -Wpedantic.  Verify that
+   the size is zero.  */
+const char ax[] = { };
+
+void size0 ()
+{
+  A (sizeof ax == 0);
+}
+
+const char a0[] = { 'a', 'b', 'c', '\0' };
+
+int len0 ()
+{
+  return __builtin_strlen (a0);
+}
+
+// Verify that narrowing warnings are preserved.
+const signed char
+sa0[] = { 'a', 'b', 255, '\0' };    // { dg-warning "\\\[\(-Wnarrowing|-Woverflow\)" "" { target { ! c++98_only } } }
+
+int lens0 ()
+{
+  return __builtin_strlen ((const char*)sa0);
+}
+
+const unsigned char
+ua0[] = { 'a', 'b', -1, '\0' };     // { dg-warning "\\\[\(-Wnarrowing|-Woverflow\)" "" { target { ! c++98_only } } }
+
+int lenu0 ()
+{
+  return __builtin_strlen ((const char*)ua0);
+}
+
+const char c = 0;
+const char a1[] = { 'a', 'b', 'c', c };
+
+int len1 ()
+{
+  return __builtin_strlen (a1);
+}
+
+template <class T>
+int tmplen ()
+{
+  static const T
+    a[] = { 1, 2, 333, 0 };         // { dg-warning "\\\[\(-Wnarrowing|-Woverflow\)" "" { target { ! c++98_only } } }
+  return __builtin_strlen (a);
+}
+
+template int tmplen<char>();
+
+const wchar_t ws4[] = { 1, 2, 3, 4 };
+const wchar_t ws7[] = { 1, 2, 3, 4, 0, 0, 0 };
+const wchar_t ws9[9] = { 1, 2, 3, 4, 0 };
+
+void wsize ()
+{
+  A (sizeof ws4 == 4 * sizeof *ws4);
+  A (ws4[0] == 1 && ws4[1] == 2 && ws4[2] == 3 && ws4[3] == 4);
+
+  A (sizeof ws7 == 7 * sizeof *ws7);
+  A (ws7[0] == 1 && ws7[1] == 2 && ws7[2] == 3 && ws7[4] == 4
+     && !ws7[5] && !ws7[6]);
+
+  A (sizeof ws9 == 9 * sizeof *ws9);
+  A (ws9[0] == 1 && ws9[1] == 2 && ws9[2] == 3 && ws9[4] == 4
+     && !ws9[5] && !ws9[6] && !ws9[7] && !ws9[8]);
+}
+
+#if 0
+
+// The following aren't handled.
+
+const char &cref = c;
+const char a2[] = { 'a', 'b', 'c', cref };
+
+int len2 ()
+{
+  return __builtin_strlen (a2);
+}
+
+
+const char* const cptr = &cref;
+const char a3[] = { 'a', 'b', 'c', *cptr };
+
+int len3 ()
+{
+  return __builtin_strlen (a3);
+}
+
+#endif
+
+// { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
diff --git a/gcc/testsuite/g++.dg/init/string3.C b/gcc/testsuite/g++.dg/init/string3.C
new file mode 100644
index 0000000..8212e81
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/string3.C
@@ -0,0 +1,35 @@
+// PR tree-optimization/71625 - missing strlen optimization on different
+// array initialization style
+//
+// Verify that strlen() call with a constant character array argument
+// initialized with non-constant elements isn't folded.
+//
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-optimized" }
+
+
+extern const char c;
+const char a0[] = { 'a', 'b', 'c', c };
+
+int len0 ()
+{
+  return __builtin_strlen (a0);
+}
+
+const char &ref = c;
+const char a1[] = { 'a', 'b', 'c', ref };
+
+int len1 ()
+{
+  return __builtin_strlen (a1);
+}
+
+const char* const ptr = &c;
+const char a2[] = { 'a', 'b', 'c', *ptr };
+
+int len2 ()
+{
+  return __builtin_strlen (a2);
+}
+
+// { dg-final { scan-tree-dump-times "strlen" 3 "optimized" } }
diff --git a/gcc/testsuite/g++.dg/init/string4.C b/gcc/testsuite/g++.dg/init/string4.C
new file mode 100644
index 0000000..5df4176
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/string4.C
@@ -0,0 +1,60 @@
+// PR tree-optimization/71625 - missing strlen optimization on different
+// array initialization style
+
+// Verify that zero-length array initialization results in the expected
+// array sizes and in the expected diagnostics.  See init-string-3.c
+// for the corresponding C test.
+
+// { dg-do compile }
+// { dg-options "-Wall -Wno-unused-local-typedefs -fpermissive" }
+
+#define A(expr) typedef char A[-1 + 2 * !!(expr)];
+
+const char a[] = { };
+
+A (sizeof a == 0);
+
+
+const char b[0] = { };
+
+A (sizeof b == 0);
+
+// Also verify that the error is "too many initializers for
+// 'const char [0]'" and not "initializer-string is too long."
+const char c[0] = { 1 };      // { dg-error "too many initializers for .const char \\\[0]" }
+
+A (sizeof c == 0);
+
+
+void test_auto_empty (void)
+{
+  const char a[] = { };
+
+  A (sizeof a == 0);
+}
+
+void test_auto_zero_length (void)
+{
+  const char a[0] = { };
+
+  A (sizeof a == 0);
+
+  const char b[0] = { 0 };    // { dg-error "too many initializers" }
+
+  A (sizeof b == 0);
+
+  const char c[0] = "";       // { dg-warning "too long" }
+
+  A (sizeof c == 0);
+}
+
+
+void test_compound_zero_length (void)
+{
+  A (sizeof (const char[]){ } == 0);
+  A (sizeof (const char[0]){ } == 0);
+  A (sizeof (const char[0]){ 0 } == 0);    // { dg-error "too many" }
+  A (sizeof (const char[0]){ 1 } == 0);    // { dg-error "too many" }
+  A (sizeof (const char[0]){ "" } == 0);   // { dg-warning "too long" }
+  A (sizeof (const char[0]){ "1" } == 0);  // { dg-warning "too long" }
+}
diff --git a/gcc/testsuite/gcc.dg/init-string-3.c b/gcc/testsuite/gcc.dg/init-string-3.c
new file mode 100644
index 0000000..e955f2e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/init-string-3.c
@@ -0,0 +1,58 @@
+/* PR tree-optimization/71625 - missing strlen optimization on different
+   array initialization style
+
+   Verify that zero-length array initialization results in the expected
+   array sizes.
+
+   { dg-do compile }
+   { dg-options "-Wall -Wno-unused-local-typedefs" }  */
+
+#define A(expr) typedef char A[-1 + 2 * !!(expr)];
+
+const char a[] = { };
+
+A (sizeof a == 0);
+
+
+const char b[0] = { };
+
+A (sizeof b == 0);
+
+
+const char c[0] = { 1 };    /* { dg-warning "excess elements" } */
+
+A (sizeof c == 0);
+
+
+void test_auto_empty (void)
+{
+  const char a[] = { };
+
+  A (sizeof a == 0);
+}
+
+void test_auto_zero_length (void)
+{
+  const char a[0] = { };
+
+  A (sizeof a == 0);
+
+  const char b[0] = { 0 };    /* { dg-warning "excess elements" } */
+
+  A (sizeof b == 0);
+
+  const char c[0] = "";
+
+  A (sizeof c == 0);
+}
+
+
+void test_compound_zero_length (void)
+{
+  A (sizeof (const char[]){ } == 0);
+  A (sizeof (const char[0]){ } == 0);
+  A (sizeof (const char[0]){ 0 } == 0);   /* { dg-warning "excess elements" } */
+  A (sizeof (const char[0]){ 1 } == 0);   /* { dg-warning "excess elements" } */
+  A (sizeof (const char[0]){ "" } == 0);
+  A (sizeof (const char[0]){ "1" } == 0);  /* { dg-warning "too long" } */
+}
diff --git a/gcc/testsuite/gcc.dg/strlenopt-55.c b/gcc/testsuite/gcc.dg/strlenopt-55.c
new file mode 100644
index 0000000..d5a0295
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-55.c
@@ -0,0 +1,230 @@
+/* PR tree-optimization/71625 - missing strlen optimization on different
+   array initialization style
+
+   Verify that strlen() of braced initialized array is folded
+   { dg-do compile }
+   { dg-options "-O1 -Wall -fdump-tree-gimple -fdump-tree-optimized" } */
+
+#include "strlenopt.h"
+
+#define S								\
+  "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"	\
+  "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"	\
+  "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"	\
+  "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"	\
+  "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f"	\
+  "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f"	\
+  "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"	\
+  "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"	\
+  "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"	\
+  "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"	\
+  "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf"	\
+  "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"	\
+  "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"	\
+  "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"	\
+  "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef"	\
+  "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
+
+/* Arrays of char, signed char, and unsigned char to verify that
+   the length and contents of all are the same as that of the string
+   literal above.  */
+
+const char c256[] = {
+  S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10],
+  S[11], S[12], S[13], S[14], S[15], S[16], S[17], S[18], S[19], S[20],
+  S[21], S[22], S[23], S[24], S[25], S[26], S[27], S[28], S[29], S[30],
+  S[31], S[32], S[33], S[34], S[35], S[36], S[37], S[38], S[39], S[40],
+  S[41], S[42], S[43], S[44], S[45], S[46], S[47], S[48], S[49], S[50],
+  S[51], S[52], S[53], S[54], S[55], S[56], S[57], S[58], S[59], S[60],
+  S[61], S[62], S[63], S[64], S[65], S[66], S[67], S[68], S[69], S[70],
+  S[71], S[72], S[73], S[74], S[75], S[76], S[77], S[78], S[79], S[80],
+  S[81], S[82], S[83], S[84], S[85], S[86], S[87], S[88], S[89], S[90],
+  S[91], S[92], S[93], S[94], S[95], S[96], S[97], S[98], S[99], S[100],
+  S[101], S[102], S[103], S[104], S[105], S[106], S[107], S[108], S[109],
+  S[110], S[111], S[112], S[113], S[114], S[115], S[116], S[117], S[118],
+  S[119], S[120], S[121], S[122], S[123], S[124], S[125], S[126], S[127],
+  S[128], S[129], S[130], S[131], S[132], S[133], S[134], S[135], S[136],
+  S[137], S[138], S[139], S[140], S[141], S[142], S[143], S[144], S[145],
+  S[146], S[147], S[148], S[149], S[150], S[151], S[152], S[153], S[154],
+  S[155], S[156], S[157], S[158], S[159], S[160], S[161], S[162], S[163],
+  S[164], S[165], S[166], S[167], S[168], S[169], S[170], S[171], S[172],
+  S[173], S[174], S[175], S[176], S[177], S[178], S[179], S[180], S[181],
+  S[182], S[183], S[184], S[185], S[186], S[187], S[188], S[189], S[190],
+  S[191], S[192], S[193], S[194], S[195], S[196], S[197], S[198], S[199],
+  S[200], S[201], S[202], S[203], S[204], S[205], S[206], S[207], S[208],
+  S[209], S[210], S[211], S[212], S[213], S[214], S[215], S[216], S[217],
+  S[218], S[219], S[220], S[221], S[222], S[223], S[224], S[225], S[226],
+  S[227], S[228], S[229], S[230], S[231], S[232], S[233], S[234], S[235],
+  S[236], S[237], S[238], S[239], S[240], S[241], S[242], S[243], S[244],
+  S[245], S[246], S[247], S[248], S[249], S[250], S[251], S[252], S[253],
+  S[254], S[255] /* = NUL */
+};
+
+const signed char sc256[] = {
+  S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10],
+  S[11], S[12], S[13], S[14], S[15], S[16], S[17], S[18], S[19], S[20],
+  S[21], S[22], S[23], S[24], S[25], S[26], S[27], S[28], S[29], S[30],
+  S[31], S[32], S[33], S[34], S[35], S[36], S[37], S[38], S[39], S[40],
+  S[41], S[42], S[43], S[44], S[45], S[46], S[47], S[48], S[49], S[50],
+  S[51], S[52], S[53], S[54], S[55], S[56], S[57], S[58], S[59], S[60],
+  S[61], S[62], S[63], S[64], S[65], S[66], S[67], S[68], S[69], S[70],
+  S[71], S[72], S[73], S[74], S[75], S[76], S[77], S[78], S[79], S[80],
+  S[81], S[82], S[83], S[84], S[85], S[86], S[87], S[88], S[89], S[90],
+  S[91], S[92], S[93], S[94], S[95], S[96], S[97], S[98], S[99], S[100],
+  S[101], S[102], S[103], S[104], S[105], S[106], S[107], S[108], S[109],
+  S[110], S[111], S[112], S[113], S[114], S[115], S[116], S[117], S[118],
+  S[119], S[120], S[121], S[122], S[123], S[124], S[125], S[126], S[127],
+  S[128], S[129], S[130], S[131], S[132], S[133], S[134], S[135], S[136],
+  S[137], S[138], S[139], S[140], S[141], S[142], S[143], S[144], S[145],
+  S[146], S[147], S[148], S[149], S[150], S[151], S[152], S[153], S[154],
+  S[155], S[156], S[157], S[158], S[159], S[160], S[161], S[162], S[163],
+  S[164], S[165], S[166], S[167], S[168], S[169], S[170], S[171], S[172],
+  S[173], S[174], S[175], S[176], S[177], S[178], S[179], S[180], S[181],
+  S[182], S[183], S[184], S[185], S[186], S[187], S[188], S[189], S[190],
+  S[191], S[192], S[193], S[194], S[195], S[196], S[197], S[198], S[199],
+  S[200], S[201], S[202], S[203], S[204], S[205], S[206], S[207], S[208],
+  S[209], S[210], S[211], S[212], S[213], S[214], S[215], S[216], S[217],
+  S[218], S[219], S[220], S[221], S[222], S[223], S[224], S[225], S[226],
+  S[227], S[228], S[229], S[230], S[231], S[232], S[233], S[234], S[235],
+  S[236], S[237], S[238], S[239], S[240], S[241], S[242], S[243], S[244],
+  S[245], S[246], S[247], S[248], S[249], S[250], S[251], S[252], S[253],
+  S[254], S[255] /* = NUL */
+};
+
+const unsigned char uc256[] = {
+  S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], S[8], S[9], S[10],
+  S[11], S[12], S[13], S[14], S[15], S[16], S[17], S[18], S[19], S[20],
+  S[21], S[22], S[23], S[24], S[25], S[26], S[27], S[28], S[29], S[30],
+  S[31], S[32], S[33], S[34], S[35], S[36], S[37], S[38], S[39], S[40],
+  S[41], S[42], S[43], S[44], S[45], S[46], S[47], S[48], S[49], S[50],
+  S[51], S[52], S[53], S[54], S[55], S[56], S[57], S[58], S[59], S[60],
+  S[61], S[62], S[63], S[64], S[65], S[66], S[67], S[68], S[69], S[70],
+  S[71], S[72], S[73], S[74], S[75], S[76], S[77], S[78], S[79], S[80],
+  S[81], S[82], S[83], S[84], S[85], S[86], S[87], S[88], S[89], S[90],
+  S[91], S[92], S[93], S[94], S[95], S[96], S[97], S[98], S[99], S[100],
+  S[101], S[102], S[103], S[104], S[105], S[106], S[107], S[108], S[109],
+  S[110], S[111], S[112], S[113], S[114], S[115], S[116], S[117], S[118],
+  S[119], S[120], S[121], S[122], S[123], S[124], S[125], S[126], S[127],
+  S[128], S[129], S[130], S[131], S[132], S[133], S[134], S[135], S[136],
+  S[137], S[138], S[139], S[140], S[141], S[142], S[143], S[144], S[145],
+  S[146], S[147], S[148], S[149], S[150], S[151], S[152], S[153], S[154],
+  S[155], S[156], S[157], S[158], S[159], S[160], S[161], S[162], S[163],
+  S[164], S[165], S[166], S[167], S[168], S[169], S[170], S[171], S[172],
+  S[173], S[174], S[175], S[176], S[177], S[178], S[179], S[180], S[181],
+  S[182], S[183], S[184], S[185], S[186], S[187], S[188], S[189], S[190],
+  S[191], S[192], S[193], S[194], S[195], S[196], S[197], S[198], S[199],
+  S[200], S[201], S[202], S[203], S[204], S[205], S[206], S[207], S[208],
+  S[209], S[210], S[211], S[212], S[213], S[214], S[215], S[216], S[217],
+  S[218], S[219], S[220], S[221], S[222], S[223], S[224], S[225], S[226],
+  S[227], S[228], S[229], S[230], S[231], S[232], S[233], S[234], S[235],
+  S[236], S[237], S[238], S[239], S[240], S[241], S[242], S[243], S[244],
+  S[245], S[246], S[247], S[248], S[249], S[250], S[251], S[252], S[253],
+  S[254], S[255] /* = NUL */
+};
+
+const __CHAR16_TYPE__ c16_4[] = {
+  1, 0x7fff, 0x8000, 0xffff,
+  0x10000   /* { dg-warning "\\\[-Woverflow]" } */
+};
+
+const char a2_implicit[2] = { };
+const char a3_implicit[3] = { };
+
+const char a3_nul[3] = { 0 };
+const char a5_nul1[3] = { [1] = 0 };
+const char a7_nul2[3] = { [2] = 0 };
+
+const char ax_2_nul[] = { '1', '2', '\0' };
+const char ax_3_nul[] = { '1', '2', '3', '\0' };
+
+const char ax_3_des_nul[] = { [3] = 0, [2] = '3', [1] = '2', [0] = '1' };
+
+const char ax_3[] = { '1', '2', '3' };
+const char a3_3[3] = { '1', '2', '3' };
+
+const char ax_100_3[] = { '1', '2', '3', [100] = '\0' };
+
+#define CONCAT(x, y) x ## y
+#define CAT(x, y) CONCAT (x, y)
+#define FAILNAME(name) CAT (call_ ## name ##_on_line_, __LINE__)
+
+#define FAIL(name) do {				\
+    extern void FAILNAME (name) (void);		\
+    FAILNAME (name)();				\
+  } while (0)
+
+/* Macro to emit a call to funcation named
+   call_in_true_branch_not_eliminated_on_line_NNN()
+   for each call that's expected to be eliminated.  The dg-final
+   scan-tree-dump-time directive at the bottom of the test verifies
+   that no such call appears in output.  */
+#define ELIM(expr)							\
+  if (!(expr)) FAIL (in_true_branch_not_eliminated); else (void)0
+
+#define T(s, n) ELIM (strlen (s) == n)
+
+void test_nulstring (void)
+{
+  T (a2_implicit, 0);
+  T (a3_implicit, 0);
+
+  T (a3_nul, 0);
+  T (a5_nul1, 0);
+  T (a7_nul2, 0);
+
+  T (ax_2_nul, 2);
+  T (ax_3_nul, 3);
+  T (ax_3_des_nul, 3);
+
+  T (ax_100_3, 3);
+  T (ax_100_3 + 4, 0);
+  ELIM (101 == sizeof ax_100_3);
+  ELIM ('\0' == ax_100_3[100]);
+
+  /* Verify that all three character arrays have the same length
+     as the string literal they are initialized with.  */
+  T (S, 255);
+  T (c256, 255);
+  T ((const char*)sc256, 255);
+  T ((const char*)uc256, 255);
+
+  /* Verify that all three character arrays have the same contents
+     as the string literal they are initialized with.  */
+  ELIM (0 == memcmp (c256, S, sizeof c256));
+  ELIM (0 == memcmp (c256, (const char*)sc256, sizeof c256));
+  ELIM (0 == memcmp (c256, (const char*)uc256, sizeof c256));
+
+  ELIM (0 == strcmp (c256, (const char*)sc256));
+  ELIM (0 == strcmp (c256, (const char*)uc256));
+
+  /* Verify that the char16_t array has the expected contents.  */
+  ELIM (c16_4[0] == 1 && c16_4[1] == 0x7fff
+	&& c16_4[2] == 0x8000 && c16_4[3] == 0xffff
+	&& c16_4[4] == 0);
+}
+
+/* Verify that excessively large initializers don't run out of
+   memory.  Also verify that the they have the expected size and
+   contents.  */
+
+#define MAX (__PTRDIFF_MAX__ - 1)
+
+const char large_string[] = { 'a', [1234] = 'b', [MAX] = '\0' };
+
+const void test_large_string_size (void)
+{
+  ELIM (sizeof large_string == MAX + 1);
+
+  /* The following expressions are not folded without optimization.  */
+  ELIM ('a'  == large_string[0]);
+  ELIM ('\0' == large_string[1233]);
+  ELIM ('b'  == large_string[1234]);
+  ELIM ('\0' == large_string[1235]);
+  ELIM ('\0' == large_string[MAX - 1]);
+}
+
+
+/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "memcmp" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "strcmp" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "call_in_true_branch_not_eliminated" 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/strlenopt-56.c b/gcc/testsuite/gcc.dg/strlenopt-56.c
new file mode 100644
index 0000000..39a532b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strlenopt-56.c
@@ -0,0 +1,50 @@
+/* PR tree-optimization/71625 - conversion of braced initializers to strings
+   Verify that array elements have the expected values regardless of sign
+   and non-ASCII execution character set.
+   { dg-do compile }
+   { dg-require-iconv "IBM1047" }
+   { dg-options "-O -Wall -fexec-charset=IBM1047 -fdump-tree-gimple -fdump-tree-optimized" } */
+
+#include "strlenopt.h"
+
+const char a[] = { 'a', 129, 0 };
+const signed char b[] = { 'b', 130, 0 };
+const unsigned char c[] = { 'c', 131, 0 };
+
+const char s[] = "a\201";
+const signed char ss[] = "b\202";
+const unsigned char us[] = "c\203";
+
+
+#define A(expr)   ((expr) ? (void)0 : __builtin_abort ())
+
+void test_values (void)
+{
+  A (a[0] == a[1]);
+  A (a[1] == 'a');
+
+  A (b[0] == b[1]);
+  A (b[1] == (signed char)'b');
+
+  A (c[0] == c[1]);
+  A (c[1] == (unsigned char)'c');
+}
+
+void test_lengths (void)
+{
+  A (2 == strlen (a));
+  A (2 == strlen ((const char*)b));
+  A (2 == strlen ((const char*)c));
+}
+
+void test_contents (void)
+{
+  A (0 == strcmp (a, s));
+  A (0 == strcmp ((const char*)b, (const char*)ss));
+  A (0 == strcmp ((const char*)c, (const char*)us));
+}
+
+
+/* { dg-final { scan-tree-dump-times "strlen" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "strcmp" 0 "gimple" } }
+   { dg-final { scan-tree-dump-times "abort" 0 "optimized" } } */

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-09  0:17           ` Martin Sebor
@ 2018-08-09 22:07             ` Joseph Myers
  2018-08-13 10:36             ` Jason Merrill
  2018-08-14 13:27             ` James Greenhalgh
  2 siblings, 0 replies; 45+ messages in thread
From: Joseph Myers @ 2018-08-09 22:07 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Jason Merrill, Gcc Patch List

On Wed, 8 Aug 2018, Martin Sebor wrote:

> Done in the attached patch.  I've also avoided dealing with
> zero-length arrays and added tests to make sure their size
> stays is regardless of the form of their initializer and
> the appropriate warnings are issued.

The C front-end changes in this patch version are OK.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-09  0:17           ` Martin Sebor
  2018-08-09 22:07             ` Joseph Myers
@ 2018-08-13 10:36             ` Jason Merrill
  2018-08-14 13:27             ` James Greenhalgh
  2 siblings, 0 replies; 45+ messages in thread
From: Jason Merrill @ 2018-08-13 10:36 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Gcc Patch List, Joseph Myers

On 08/09/2018 12:17 PM, Martin Sebor wrote:
> Using build_string() rather than build_string_literal() needed
> a tweak in digest_init_r().  It didn't break anything but since
> the array type may not have a domain yet, neither will the
> string.  It looks like that may get adjusted later on but I've
> temporarily guarded the code with #if 1.  If the change is
> fine I'll remove the #if before committing. 

The digest_init_r change seems to follow from allowing STRING_CST of 
signed char, so yes, it's fine.

> +		  && TREE_CODE (init) == CONSTRUCTOR
> +		  && TREE_TYPE (init) == init_list_type_node)

This is BRACE_ENCLOSED_INITIALIZER_P.

OK with that change.

Jason

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-09  0:17           ` Martin Sebor
  2018-08-09 22:07             ` Joseph Myers
  2018-08-13 10:36             ` Jason Merrill
@ 2018-08-14 13:27             ` James Greenhalgh
  2018-08-14 15:08               ` Martin Sebor
  2018-08-14 21:14               ` [PATCH] convert braced initializers to strings (PR 71625) Joseph Myers
  2 siblings, 2 replies; 45+ messages in thread
From: James Greenhalgh @ 2018-08-14 13:27 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Jason Merrill, Gcc Patch List, Joseph Myers, nd

On Wed, Aug 08, 2018 at 07:17:07PM -0500, Martin Sebor wrote:
> On 08/08/2018 05:08 AM, Jason Merrill wrote:
> > On Wed, Aug 8, 2018 at 9:04 AM, Martin Sebor <msebor@gmail.com> wrote:
> >> On 08/07/2018 02:57 AM, Jason Merrill wrote:
> >>>
> >>> On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor <msebor@gmail.com> wrote:
> >>>>
> >>>> On 07/31/2018 07:38 AM, Jason Merrill wrote:

<snip>

> Done in the attached patch.  I've also avoided dealing with
> zero-length arrays and added tests to make sure their size
> stays is regardless of the form of their initializer and
> the appropriate warnings are issued.
> 
> Using build_string() rather than build_string_literal() needed
> a tweak in digest_init_r().  It didn't break anything but since
> the array type may not have a domain yet, neither will the
> string.  It looks like that may get adjusted later on but I've
> temporarily guarded the code with #if 1.  If the change is
> fine I'll remove the #if before committing.
> 
> This initial patch only handles narrow character initializers
> (i.e., those with TYPE_STRING_FLAG set).  Once this gets some
> exposure I'd like to extend it to other character types,
> including wchar_t.

Hi Martin,

This causes issues for the AArch64 tests (full list below).

I see an error message on the following construct:

  void foo (void)
  {
    __Poly8_t x[4] = { 1, 2, 3, 4 };
  }

  init.c:3:20: error: array of inappropriate type initialized from string constant
  3 |   __Poly8_t x[4] = { 1, 2, 3, 4 };
    |

__Poly8_t is a type we define in our backend, through a convoluted set of
functions, which operates a lot like an unsigned, QI mode type.

A second set of tests fail due to changed inlining behaviour for functions
with char array initialization:

  gcc.target/aarch64/vset_lane_1.c
  gcc.target/aarch64/vneg_s.c
  gcc.target/aarch64/vclz.c

Thanks,
James

-----

New failures in: 


gcc.target/aarch64/advsimd-intrinsics/vmax.c
gcc.target/aarch64/simd/vzipqp8_1.c
gcc.target/aarch64/vldN_dup_1.c
gcc.target/aarch64/advsimd-intrinsics/vcle.c
gcc.target/aarch64/advsimd-intrinsics/vadd.c
gcc.target/aarch64/advsimd-intrinsics/vhadd.c
gcc.target/aarch64/advsimd-intrinsics/vmull_n.c
gcc.target/aarch64/advsimd-intrinsics/vrndn.c
gcc.target/aarch64/simd/vtrnqp8_1.c
gcc.target/aarch64/advsimd-intrinsics/vpadal.c
gcc.target/aarch64/advsimd-intrinsics/vtrn_half.c
gcc.target/aarch64/advsimd-intrinsics/vqdmlal_n.c
gcc.target/aarch64/advsimd-intrinsics/vqdmulh.c
gcc.target/aarch64/advsimd-intrinsics/vqsub.c
gcc.target/aarch64/advsimd-intrinsics/vqdmlal_lane.c
gcc.target/aarch64/advsimd-intrinsics/vqdmlsl_n.c
gcc.target/aarch64/advsimd-intrinsics/vuzp_half.c
gcc.target/aarch64/advsimd-intrinsics/vst1_lane.c
gcc.target/aarch64/advsimd-intrinsics/vmla_lane.c
gcc.target/aarch64/advsimd-intrinsics/vqdmulh_lane.c
gcc.target/aarch64/advsimd-intrinsics/vrsqrte.c
gcc.target/aarch64/advsimd-intrinsics/vneg.c
gcc.target/aarch64/simd/vuzpqp8_1.c
gcc.target/aarch64/advsimd-intrinsics/vcale.c
gcc.target/aarch64/advsimd-intrinsics/vmla_n.c
gcc.target/aarch64/advsimd-intrinsics/vsub.c
gcc.target/aarch64/advsimd-intrinsics/vrev.c
gcc.target/aarch64/advsimd-intrinsics/vmul.c
gcc.target/aarch64/advsimd-intrinsics/vldX.c
gcc.target/aarch64/advsimd-intrinsics/vsubl.c
gcc.target/aarch64/advsimd-intrinsics/vfms.c
gcc.target/aarch64/advsimd-intrinsics/vmlsl.c
gcc.target/aarch64/advsimd-intrinsics/vsli_n.c
gcc.target/aarch64/advsimd-intrinsics/vcombine.c
gcc.target/aarch64/advsimd-intrinsics/vmul_n.c
gcc.target/aarch64/advsimd-intrinsics/vldX_dup.c
gcc.target/aarch64/advsimd-intrinsics/vpaddl.c
gcc.target/aarch64/advsimd-intrinsics/vqshrn_n.c
gcc.target/aarch64/advsimd-intrinsics/vstX_lane.c
gcc.target/aarch64/advsimd-intrinsics/vqtbX.c
gcc.target/aarch64/advsimd-intrinsics/vext.c
gcc.target/aarch64/advsimd-intrinsics/vtrn.c
gcc.target/aarch64/advsimd-intrinsics/vtst.c
gcc.target/aarch64/advsimd-intrinsics/vbic.c
gcc.target/aarch64/advsimd-intrinsics/vqdmlsl.c
gcc.target/aarch64/advsimd-intrinsics/vqshl.c
gcc.target/aarch64/advsimd-intrinsics/vrsqrts.c
gcc.target/aarch64/advsimd-intrinsics/vqdmull_n.c
gcc.target/aarch64/advsimd-intrinsics/vqdmlsl_lane.c
gcc.target/aarch64/advsimd-intrinsics/vqdmulh_n.c
gcc.target/aarch64/advsimd-intrinsics/vsubw.c
gcc.target/aarch64/advsimd-intrinsics/vdup_lane.c
gcc.target/aarch64/advsimd-intrinsics/vget_high.c
gcc.target/aarch64/advsimd-intrinsics/vuzp.c
gcc.target/aarch64/advsimd-intrinsics/vqshl_n.c
gcc.target/aarch64/advsimd-intrinsics/vrsra_n.c
gcc.target/aarch64/advsimd-intrinsics/vcgt.c
gcc.target/aarch64/advsimd-intrinsics/vld1_dup.c
gcc.target/aarch64/advsimd-intrinsics/vaddhn.c
gcc.target/aarch64/advsimd-intrinsics/vqshlu_n.c
gcc.target/aarch64/advsimd-intrinsics/vabs.c
gcc.target/aarch64/advsimd-intrinsics/vshll_n.c
gcc.target/aarch64/advsimd-intrinsics/vsubhn.c
gcc.target/aarch64/advsimd-intrinsics/vmlal.c
gcc.target/aarch64/advsimd-intrinsics/vqdmlal.c
gcc.target/aarch64/advsimd-intrinsics/vrecpe.c
gcc.target/aarch64/advsimd-intrinsics/vqneg.c
gcc.target/aarch64/advsimd-intrinsics/veor.c
gcc.target/aarch64/simd/extq_p8_1.c
gcc.target/aarch64/advsimd-intrinsics/vclz.c
gcc.target/aarch64/simd/ext_p8_1.c
gcc.target/aarch64/advsimd-intrinsics/vqrdmulh_lane.c
gcc.target/aarch64/advsimd-intrinsics/vqrshl.c
gcc.target/aarch64/advsimd-intrinsics/vqrshrun_n.c
gcc.target/aarch64/advsimd-intrinsics/vqrshrn_n.c
gcc.target/aarch64/advsimd-intrinsics/vceq.c
gcc.target/aarch64/advsimd-intrinsics/vrndm.c
gcc.target/aarch64/advsimd-intrinsics/vmlsl_n.c
gcc.target/aarch64/advsimd-intrinsics/vmlal_n.c
gcc.target/aarch64/advsimd-intrinsics/vqmovun.c
gcc.target/aarch64/advsimd-intrinsics/vrshr_n.c
gcc.target/aarch64/advsimd-intrinsics/vmls_n.c
gcc.target/aarch64/advsimd-intrinsics/vmlsl_lane.c
gcc.target/aarch64/advsimd-intrinsics/vqdmull_lane.c
gcc.target/aarch64/advsimd-intrinsics/vfms_vfma_n.c
gcc.target/aarch64/advsimd-intrinsics/vorr.c
gcc.target/aarch64/advsimd-intrinsics/vaddl.c
gcc.target/aarch64/advsimd-intrinsics/vmovl.c
gcc.target/aarch64/advsimd-intrinsics/vbsl.c
gcc.target/aarch64/advsimd-intrinsics/vld1_lane.c
gcc.target/aarch64/advsimd-intrinsics/vqmovn.c
gcc.target/aarch64/advsimd-intrinsics/vcalt.c
gcc.target/aarch64/advsimd-intrinsics/vmul_lane.c
gcc.target/aarch64/advsimd-intrinsics/vqshrun_n.c
gcc.target/aarch64/advsimd-intrinsics/vset_lane.c
gcc.target/aarch64/advsimd-intrinsics/vrsubhn.c
gcc.target/aarch64/advsimd-intrinsics/vshl_n.c
gcc.target/aarch64/advsimd-intrinsics/vmovn.c
gcc.target/aarch64/advsimd-intrinsics/vcls.c
gcc.target/aarch64/advsimd-intrinsics/vcage.c
gcc.target/aarch64/advsimd-intrinsics/vcnt.c
gcc.target/aarch64/advsimd-intrinsics/vmull.c
gcc.target/aarch64/simd/vuzpp8_1.c
gcc.target/aarch64/advsimd-intrinsics/vreinterpret_p64.c
gcc.target/aarch64/advsimd-intrinsics/vfma.c
gcc.target/aarch64/advsimd-intrinsics/vld1.c
gcc.target/aarch64/advsimd-intrinsics/vhsub.c
gcc.target/aarch64/advsimd-intrinsics/vget_low.c
gcc.target/aarch64/advsimd-intrinsics/p64_p128.c
gcc.target/aarch64/advsimd-intrinsics/vcvt.c
gcc.target/aarch64/advsimd-intrinsics/vqdmull.c
gcc.target/aarch64/advsimd-intrinsics/vmvn.c
gcc.target/aarch64/advsimd-intrinsics/vmin.c
gcc.target/aarch64/advsimd-intrinsics/vaba.c
gcc.target/aarch64/advsimd-intrinsics/vqrdmulh_n.c
gcc.target/aarch64/simd/vtrnp8_1.c
gcc.target/aarch64/advsimd-intrinsics/vcagt.c
gcc.target/aarch64/advsimd-intrinsics/vdup-vmov.c
gcc.target/aarch64/advsimd-intrinsics/vrhadd.c
gcc.target/aarch64/advsimd-intrinsics/vabal.c
gcc.target/aarch64/advsimd-intrinsics/vrshrn_n.c
gcc.target/aarch64/advsimd-intrinsics/vpmax.c
gcc.target/aarch64/advsimd-intrinsics/vmls.c
gcc.target/aarch64/advsimd-intrinsics/vshrn_n.c
gcc.target/aarch64/advsimd-intrinsics/vrnd.c
gcc.target/aarch64/advsimd-intrinsics/vabd.c
gcc.target/aarch64/simd/vzipp8_1.c
gcc.target/aarch64/advsimd-intrinsics/vduph_lane.c
gcc.target/aarch64/advsimd-intrinsics/vreinterpret_p128.c
gcc.target/aarch64/advsimd-intrinsics/vrshl.c
gcc.target/aarch64/advsimd-intrinsics/vcreate.c
gcc.target/aarch64/advsimd-intrinsics/vqabs.c
gcc.target/aarch64/advsimd-intrinsics/vmull_lane.c
gcc.target/aarch64/advsimd-intrinsics/vreinterpret.c
gcc.target/aarch64/advsimd-intrinsics/vmlal_lane.c
gcc.target/aarch64/advsimd-intrinsics/vshr_n.c
gcc.target/aarch64/advsimd-intrinsics/vzip.c
gcc.target/aarch64/vldN_lane_1.c
gcc.target/aarch64/advsimd-intrinsics/vabdl.c
gcc.target/aarch64/advsimd-intrinsics/vpmin.c
gcc.target/aarch64/advsimd-intrinsics/vqadd.c
gcc.target/aarch64/advsimd-intrinsics/vzip_half.c
gcc.target/aarch64/advsimd-intrinsics/vand.c
gcc.target/aarch64/advsimd-intrinsics/vpadd.c
gcc.target/aarch64/advsimd-intrinsics/vrndx.c
gcc.target/aarch64/advsimd-intrinsics/vmla.c
gcc.target/aarch64/advsimd-intrinsics/vsra_n.c
gcc.target/aarch64/advsimd-intrinsics/vget_lane.c
gcc.target/aarch64/advsimd-intrinsics/vqrdmulh.c
gcc.target/aarch64/advsimd-intrinsics/vrndp.c
gcc.target/aarch64/advsimd-intrinsics/vmls_lane.c
gcc.target/aarch64/advsimd-intrinsics/vclt.c
gcc.target/aarch64/advsimd-intrinsics/vfma_n.c
gcc.target/aarch64/advsimd-intrinsics/vaddw.c
gcc.target/aarch64/advsimd-intrinsics/vsri_n.c
gcc.target/aarch64/advsimd-intrinsics/vorn.c
gcc.target/aarch64/advsimd-intrinsics/vcvt_f16.c
gcc.target/aarch64/advsimd-intrinsics/vldX_lane.c
gcc.target/aarch64/advsimd-intrinsics/vcge.c
gcc.target/aarch64/advsimd-intrinsics/vshl.c
gcc.target/aarch64/advsimd-intrinsics/vtbX.c
gcc.target/aarch64/advsimd-intrinsics/vraddhn.c
gcc.target/aarch64/advsimd-intrinsics/vrnda.c
gcc.target/aarch64/advsimd-intrinsics/vrecps.c





> 
> Martin

> PR tree-optimization/71625 - missing strlen optimization on different array initialization style
> 
> gcc/c/ChangeLog:
> 
> 	PR tree-optimization/71625
> 	* c-parser.c (c_parser_declaration_or_fndef): Call
> 	braced_list_to_string.
> 
> gcc/c-family/ChangeLog:
> 
> 	PR tree-optimization/71625
> 	* c-common.c (braced_list_to_string): New function.
> 	* c-common.h (braced_list_to_string): Declare it.
> 
> gcc/cp/ChangeLog:
> 
> 	PR tree-optimization/71625
> 	* decl.c (check_initializer):  Call braced_list_to_string.
> 	(eval_check_narrowing): New function.
> 	* gcc/cp/typeck2.c (digest_init_r): Accept strings literals
> 	as initilizers for all narrow character types.
> 
> gcc/testsuite/ChangeLog:
> 
> 	PR tree-optimization/71625
> 	* g++.dg/init/string2.C: New test.
> 	* g++.dg/init/string3.C: New test.
> 	* g++.dg/init/string4.C: New test.
> 	* gcc.dg/init-string-3.c: New test.
> 	* gcc.dg/strlenopt-55.c: New test.
> 	* gcc.dg/strlenopt-56.c: New test.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-14 13:27             ` James Greenhalgh
@ 2018-08-14 15:08               ` Martin Sebor
  2018-08-14 15:24                 ` Martin Sebor
  2018-08-14 21:14               ` [PATCH] convert braced initializers to strings (PR 71625) Joseph Myers
  1 sibling, 1 reply; 45+ messages in thread
From: Martin Sebor @ 2018-08-14 15:08 UTC (permalink / raw)
  To: James Greenhalgh; +Cc: Jason Merrill, Gcc Patch List, Joseph Myers, nd

On 08/14/2018 07:27 AM, James Greenhalgh wrote:
> On Wed, Aug 08, 2018 at 07:17:07PM -0500, Martin Sebor wrote:
>> On 08/08/2018 05:08 AM, Jason Merrill wrote:
>>> On Wed, Aug 8, 2018 at 9:04 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>> On 08/07/2018 02:57 AM, Jason Merrill wrote:
>>>>>
>>>>> On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>>>>
>>>>>> On 07/31/2018 07:38 AM, Jason Merrill wrote:
>
> <snip>
>
>> Done in the attached patch.  I've also avoided dealing with
>> zero-length arrays and added tests to make sure their size
>> stays is regardless of the form of their initializer and
>> the appropriate warnings are issued.
>>
>> Using build_string() rather than build_string_literal() needed
>> a tweak in digest_init_r().  It didn't break anything but since
>> the array type may not have a domain yet, neither will the
>> string.  It looks like that may get adjusted later on but I've
>> temporarily guarded the code with #if 1.  If the change is
>> fine I'll remove the #if before committing.
>>
>> This initial patch only handles narrow character initializers
>> (i.e., those with TYPE_STRING_FLAG set).  Once this gets some
>> exposure I'd like to extend it to other character types,
>> including wchar_t.
>
> Hi Martin,
>
> This causes issues for the AArch64 tests (full list below).
>
> I see an error message on the following construct:
>
>   void foo (void)
>   {
>     __Poly8_t x[4] = { 1, 2, 3, 4 };
>   }
>
>   init.c:3:20: error: array of inappropriate type initialized from string constant
>   3 |   __Poly8_t x[4] = { 1, 2, 3, 4 };
>     |
>
> __Poly8_t is a type we define in our backend, through a convoluted set of
> functions, which operates a lot like an unsigned, QI mode type.

I see the error with my aarch64 cross-compiler .  The new code
that does the conversion of array initializers to STRING_CSTs
looks for the TYPE_STRING_FLAG() to be set on the type of
the array elements.  Perhaps __Poly8_t should not have the flag
set?  (If it needs it then I think we'd have to only consider
named character types.)

> A second set of tests fail due to changed inlining behaviour for functions
> with char array initialization:
>
>   gcc.target/aarch64/vset_lane_1.c
>   gcc.target/aarch64/vneg_s.c
>   gcc.target/aarch64/vclz.c

I'm not sure what's going on here.  The tests are very big and
take forever to compile with an aarch64 cross-compiler, and I'm
not sure what to look for.  Can you provide a smaller test case
that shows the issue?

Martin

>
> Thanks,
> James
>
> -----
>
> New failures in:
>
>
> gcc.target/aarch64/advsimd-intrinsics/vmax.c
> gcc.target/aarch64/simd/vzipqp8_1.c
> gcc.target/aarch64/vldN_dup_1.c
> gcc.target/aarch64/advsimd-intrinsics/vcle.c
> gcc.target/aarch64/advsimd-intrinsics/vadd.c
> gcc.target/aarch64/advsimd-intrinsics/vhadd.c
> gcc.target/aarch64/advsimd-intrinsics/vmull_n.c
> gcc.target/aarch64/advsimd-intrinsics/vrndn.c
> gcc.target/aarch64/simd/vtrnqp8_1.c
> gcc.target/aarch64/advsimd-intrinsics/vpadal.c
> gcc.target/aarch64/advsimd-intrinsics/vtrn_half.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmlal_n.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmulh.c
> gcc.target/aarch64/advsimd-intrinsics/vqsub.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmlal_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmlsl_n.c
> gcc.target/aarch64/advsimd-intrinsics/vuzp_half.c
> gcc.target/aarch64/advsimd-intrinsics/vst1_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vmla_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmulh_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vrsqrte.c
> gcc.target/aarch64/advsimd-intrinsics/vneg.c
> gcc.target/aarch64/simd/vuzpqp8_1.c
> gcc.target/aarch64/advsimd-intrinsics/vcale.c
> gcc.target/aarch64/advsimd-intrinsics/vmla_n.c
> gcc.target/aarch64/advsimd-intrinsics/vsub.c
> gcc.target/aarch64/advsimd-intrinsics/vrev.c
> gcc.target/aarch64/advsimd-intrinsics/vmul.c
> gcc.target/aarch64/advsimd-intrinsics/vldX.c
> gcc.target/aarch64/advsimd-intrinsics/vsubl.c
> gcc.target/aarch64/advsimd-intrinsics/vfms.c
> gcc.target/aarch64/advsimd-intrinsics/vmlsl.c
> gcc.target/aarch64/advsimd-intrinsics/vsli_n.c
> gcc.target/aarch64/advsimd-intrinsics/vcombine.c
> gcc.target/aarch64/advsimd-intrinsics/vmul_n.c
> gcc.target/aarch64/advsimd-intrinsics/vldX_dup.c
> gcc.target/aarch64/advsimd-intrinsics/vpaddl.c
> gcc.target/aarch64/advsimd-intrinsics/vqshrn_n.c
> gcc.target/aarch64/advsimd-intrinsics/vstX_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vqtbX.c
> gcc.target/aarch64/advsimd-intrinsics/vext.c
> gcc.target/aarch64/advsimd-intrinsics/vtrn.c
> gcc.target/aarch64/advsimd-intrinsics/vtst.c
> gcc.target/aarch64/advsimd-intrinsics/vbic.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmlsl.c
> gcc.target/aarch64/advsimd-intrinsics/vqshl.c
> gcc.target/aarch64/advsimd-intrinsics/vrsqrts.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmull_n.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmlsl_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmulh_n.c
> gcc.target/aarch64/advsimd-intrinsics/vsubw.c
> gcc.target/aarch64/advsimd-intrinsics/vdup_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vget_high.c
> gcc.target/aarch64/advsimd-intrinsics/vuzp.c
> gcc.target/aarch64/advsimd-intrinsics/vqshl_n.c
> gcc.target/aarch64/advsimd-intrinsics/vrsra_n.c
> gcc.target/aarch64/advsimd-intrinsics/vcgt.c
> gcc.target/aarch64/advsimd-intrinsics/vld1_dup.c
> gcc.target/aarch64/advsimd-intrinsics/vaddhn.c
> gcc.target/aarch64/advsimd-intrinsics/vqshlu_n.c
> gcc.target/aarch64/advsimd-intrinsics/vabs.c
> gcc.target/aarch64/advsimd-intrinsics/vshll_n.c
> gcc.target/aarch64/advsimd-intrinsics/vsubhn.c
> gcc.target/aarch64/advsimd-intrinsics/vmlal.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmlal.c
> gcc.target/aarch64/advsimd-intrinsics/vrecpe.c
> gcc.target/aarch64/advsimd-intrinsics/vqneg.c
> gcc.target/aarch64/advsimd-intrinsics/veor.c
> gcc.target/aarch64/simd/extq_p8_1.c
> gcc.target/aarch64/advsimd-intrinsics/vclz.c
> gcc.target/aarch64/simd/ext_p8_1.c
> gcc.target/aarch64/advsimd-intrinsics/vqrdmulh_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vqrshl.c
> gcc.target/aarch64/advsimd-intrinsics/vqrshrun_n.c
> gcc.target/aarch64/advsimd-intrinsics/vqrshrn_n.c
> gcc.target/aarch64/advsimd-intrinsics/vceq.c
> gcc.target/aarch64/advsimd-intrinsics/vrndm.c
> gcc.target/aarch64/advsimd-intrinsics/vmlsl_n.c
> gcc.target/aarch64/advsimd-intrinsics/vmlal_n.c
> gcc.target/aarch64/advsimd-intrinsics/vqmovun.c
> gcc.target/aarch64/advsimd-intrinsics/vrshr_n.c
> gcc.target/aarch64/advsimd-intrinsics/vmls_n.c
> gcc.target/aarch64/advsimd-intrinsics/vmlsl_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmull_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vfms_vfma_n.c
> gcc.target/aarch64/advsimd-intrinsics/vorr.c
> gcc.target/aarch64/advsimd-intrinsics/vaddl.c
> gcc.target/aarch64/advsimd-intrinsics/vmovl.c
> gcc.target/aarch64/advsimd-intrinsics/vbsl.c
> gcc.target/aarch64/advsimd-intrinsics/vld1_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vqmovn.c
> gcc.target/aarch64/advsimd-intrinsics/vcalt.c
> gcc.target/aarch64/advsimd-intrinsics/vmul_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vqshrun_n.c
> gcc.target/aarch64/advsimd-intrinsics/vset_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vrsubhn.c
> gcc.target/aarch64/advsimd-intrinsics/vshl_n.c
> gcc.target/aarch64/advsimd-intrinsics/vmovn.c
> gcc.target/aarch64/advsimd-intrinsics/vcls.c
> gcc.target/aarch64/advsimd-intrinsics/vcage.c
> gcc.target/aarch64/advsimd-intrinsics/vcnt.c
> gcc.target/aarch64/advsimd-intrinsics/vmull.c
> gcc.target/aarch64/simd/vuzpp8_1.c
> gcc.target/aarch64/advsimd-intrinsics/vreinterpret_p64.c
> gcc.target/aarch64/advsimd-intrinsics/vfma.c
> gcc.target/aarch64/advsimd-intrinsics/vld1.c
> gcc.target/aarch64/advsimd-intrinsics/vhsub.c
> gcc.target/aarch64/advsimd-intrinsics/vget_low.c
> gcc.target/aarch64/advsimd-intrinsics/p64_p128.c
> gcc.target/aarch64/advsimd-intrinsics/vcvt.c
> gcc.target/aarch64/advsimd-intrinsics/vqdmull.c
> gcc.target/aarch64/advsimd-intrinsics/vmvn.c
> gcc.target/aarch64/advsimd-intrinsics/vmin.c
> gcc.target/aarch64/advsimd-intrinsics/vaba.c
> gcc.target/aarch64/advsimd-intrinsics/vqrdmulh_n.c
> gcc.target/aarch64/simd/vtrnp8_1.c
> gcc.target/aarch64/advsimd-intrinsics/vcagt.c
> gcc.target/aarch64/advsimd-intrinsics/vdup-vmov.c
> gcc.target/aarch64/advsimd-intrinsics/vrhadd.c
> gcc.target/aarch64/advsimd-intrinsics/vabal.c
> gcc.target/aarch64/advsimd-intrinsics/vrshrn_n.c
> gcc.target/aarch64/advsimd-intrinsics/vpmax.c
> gcc.target/aarch64/advsimd-intrinsics/vmls.c
> gcc.target/aarch64/advsimd-intrinsics/vshrn_n.c
> gcc.target/aarch64/advsimd-intrinsics/vrnd.c
> gcc.target/aarch64/advsimd-intrinsics/vabd.c
> gcc.target/aarch64/simd/vzipp8_1.c
> gcc.target/aarch64/advsimd-intrinsics/vduph_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vreinterpret_p128.c
> gcc.target/aarch64/advsimd-intrinsics/vrshl.c
> gcc.target/aarch64/advsimd-intrinsics/vcreate.c
> gcc.target/aarch64/advsimd-intrinsics/vqabs.c
> gcc.target/aarch64/advsimd-intrinsics/vmull_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vreinterpret.c
> gcc.target/aarch64/advsimd-intrinsics/vmlal_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vshr_n.c
> gcc.target/aarch64/advsimd-intrinsics/vzip.c
> gcc.target/aarch64/vldN_lane_1.c
> gcc.target/aarch64/advsimd-intrinsics/vabdl.c
> gcc.target/aarch64/advsimd-intrinsics/vpmin.c
> gcc.target/aarch64/advsimd-intrinsics/vqadd.c
> gcc.target/aarch64/advsimd-intrinsics/vzip_half.c
> gcc.target/aarch64/advsimd-intrinsics/vand.c
> gcc.target/aarch64/advsimd-intrinsics/vpadd.c
> gcc.target/aarch64/advsimd-intrinsics/vrndx.c
> gcc.target/aarch64/advsimd-intrinsics/vmla.c
> gcc.target/aarch64/advsimd-intrinsics/vsra_n.c
> gcc.target/aarch64/advsimd-intrinsics/vget_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vqrdmulh.c
> gcc.target/aarch64/advsimd-intrinsics/vrndp.c
> gcc.target/aarch64/advsimd-intrinsics/vmls_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vclt.c
> gcc.target/aarch64/advsimd-intrinsics/vfma_n.c
> gcc.target/aarch64/advsimd-intrinsics/vaddw.c
> gcc.target/aarch64/advsimd-intrinsics/vsri_n.c
> gcc.target/aarch64/advsimd-intrinsics/vorn.c
> gcc.target/aarch64/advsimd-intrinsics/vcvt_f16.c
> gcc.target/aarch64/advsimd-intrinsics/vldX_lane.c
> gcc.target/aarch64/advsimd-intrinsics/vcge.c
> gcc.target/aarch64/advsimd-intrinsics/vshl.c
> gcc.target/aarch64/advsimd-intrinsics/vtbX.c
> gcc.target/aarch64/advsimd-intrinsics/vraddhn.c
> gcc.target/aarch64/advsimd-intrinsics/vrnda.c
> gcc.target/aarch64/advsimd-intrinsics/vrecps.c
>
>
>
>
>
>>
>> Martin
>
>> PR tree-optimization/71625 - missing strlen optimization on different array initialization style
>>
>> gcc/c/ChangeLog:
>>
>> 	PR tree-optimization/71625
>> 	* c-parser.c (c_parser_declaration_or_fndef): Call
>> 	braced_list_to_string.
>>
>> gcc/c-family/ChangeLog:
>>
>> 	PR tree-optimization/71625
>> 	* c-common.c (braced_list_to_string): New function.
>> 	* c-common.h (braced_list_to_string): Declare it.
>>
>> gcc/cp/ChangeLog:
>>
>> 	PR tree-optimization/71625
>> 	* decl.c (check_initializer):  Call braced_list_to_string.
>> 	(eval_check_narrowing): New function.
>> 	* gcc/cp/typeck2.c (digest_init_r): Accept strings literals
>> 	as initilizers for all narrow character types.
>>
>> gcc/testsuite/ChangeLog:
>>
>> 	PR tree-optimization/71625
>> 	* g++.dg/init/string2.C: New test.
>> 	* g++.dg/init/string3.C: New test.
>> 	* g++.dg/init/string4.C: New test.
>> 	* gcc.dg/init-string-3.c: New test.
>> 	* gcc.dg/strlenopt-55.c: New test.
>> 	* gcc.dg/strlenopt-56.c: New test.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-14 15:08               ` Martin Sebor
@ 2018-08-14 15:24                 ` Martin Sebor
  2018-08-15  2:34                   ` Martin Sebor
  0 siblings, 1 reply; 45+ messages in thread
From: Martin Sebor @ 2018-08-14 15:24 UTC (permalink / raw)
  To: James Greenhalgh; +Cc: Jason Merrill, Gcc Patch List, Joseph Myers, nd

On 08/14/2018 09:08 AM, Martin Sebor wrote:
> On 08/14/2018 07:27 AM, James Greenhalgh wrote:
>> On Wed, Aug 08, 2018 at 07:17:07PM -0500, Martin Sebor wrote:
>>> On 08/08/2018 05:08 AM, Jason Merrill wrote:
>>>> On Wed, Aug 8, 2018 at 9:04 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>>> On 08/07/2018 02:57 AM, Jason Merrill wrote:
>>>>>>
>>>>>> On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor <msebor@gmail.com>
>>>>>> wrote:
>>>>>>>
>>>>>>> On 07/31/2018 07:38 AM, Jason Merrill wrote:
>>
>> <snip>
>>
>>> Done in the attached patch.  I've also avoided dealing with
>>> zero-length arrays and added tests to make sure their size
>>> stays is regardless of the form of their initializer and
>>> the appropriate warnings are issued.
>>>
>>> Using build_string() rather than build_string_literal() needed
>>> a tweak in digest_init_r().  It didn't break anything but since
>>> the array type may not have a domain yet, neither will the
>>> string.  It looks like that may get adjusted later on but I've
>>> temporarily guarded the code with #if 1.  If the change is
>>> fine I'll remove the #if before committing.
>>>
>>> This initial patch only handles narrow character initializers
>>> (i.e., those with TYPE_STRING_FLAG set).  Once this gets some
>>> exposure I'd like to extend it to other character types,
>>> including wchar_t.
>>
>> Hi Martin,
>>
>> This causes issues for the AArch64 tests (full list below).
>>
>> I see an error message on the following construct:
>>
>>   void foo (void)
>>   {
>>     __Poly8_t x[4] = { 1, 2, 3, 4 };
>>   }
>>
>>   init.c:3:20: error: array of inappropriate type initialized from
>> string constant
>>   3 |   __Poly8_t x[4] = { 1, 2, 3, 4 };
>>     |
>>
>> __Poly8_t is a type we define in our backend, through a convoluted set of
>> functions, which operates a lot like an unsigned, QI mode type.
>
> I see the error with my aarch64 cross-compiler .  The new code
> that does the conversion of array initializers to STRING_CSTs
> looks for the TYPE_STRING_FLAG() to be set on the type of
> the array elements.  Perhaps __Poly8_t should not have the flag
> set?  (If it needs it then I think we'd have to only consider
> named character types.)

The change below gets rid of the compilation error.  I don't
know if it's appropriate for the aarch64 back end:

Index: gcc/config/aarch64/aarch64-builtins.c
===================================================================
--- gcc/config/aarch64/aarch64-builtins.c	(revision 263537)
+++ gcc/config/aarch64/aarch64-builtins.c	(working copy)
@@ -643,6 +643,7 @@ aarch64_init_simd_builtin_types (void)
    /* Poly types are a world of their own.  */
    aarch64_simd_types[Poly8_t].eltype = aarch64_simd_types[Poly8_t].itype =
      build_distinct_type_copy (unsigned_intQI_type_node);
+  TYPE_STRING_FLAG (aarch64_simd_types[Poly8_t].eltype) = false;
    aarch64_simd_types[Poly16_t].eltype = 
aarch64_simd_types[Poly16_t].itype =
      build_distinct_type_copy (unsigned_intHI_type_node);
    aarch64_simd_types[Poly64_t].eltype = 
aarch64_simd_types[Poly64_t].itype =


>> A second set of tests fail due to changed inlining behaviour for
>> functions
>> with char array initialization:
>>
>>   gcc.target/aarch64/vset_lane_1.c
>>   gcc.target/aarch64/vneg_s.c
>>   gcc.target/aarch64/vclz.c
>
> I'm not sure what's going on here.  The tests are very big and
> take forever to compile with an aarch64 cross-compiler, and I'm
> not sure what to look for.  Can you provide a smaller test case
> that shows the issue?
>
> Martin
>
>>
>> Thanks,
>> James
>>
>> -----
>>
>> New failures in:
>>
>>
>> gcc.target/aarch64/advsimd-intrinsics/vmax.c
>> gcc.target/aarch64/simd/vzipqp8_1.c
>> gcc.target/aarch64/vldN_dup_1.c
>> gcc.target/aarch64/advsimd-intrinsics/vcle.c
>> gcc.target/aarch64/advsimd-intrinsics/vadd.c
>> gcc.target/aarch64/advsimd-intrinsics/vhadd.c
>> gcc.target/aarch64/advsimd-intrinsics/vmull_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vrndn.c
>> gcc.target/aarch64/simd/vtrnqp8_1.c
>> gcc.target/aarch64/advsimd-intrinsics/vpadal.c
>> gcc.target/aarch64/advsimd-intrinsics/vtrn_half.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmlal_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmulh.c
>> gcc.target/aarch64/advsimd-intrinsics/vqsub.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmlal_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmlsl_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vuzp_half.c
>> gcc.target/aarch64/advsimd-intrinsics/vst1_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vmla_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmulh_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vrsqrte.c
>> gcc.target/aarch64/advsimd-intrinsics/vneg.c
>> gcc.target/aarch64/simd/vuzpqp8_1.c
>> gcc.target/aarch64/advsimd-intrinsics/vcale.c
>> gcc.target/aarch64/advsimd-intrinsics/vmla_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vsub.c
>> gcc.target/aarch64/advsimd-intrinsics/vrev.c
>> gcc.target/aarch64/advsimd-intrinsics/vmul.c
>> gcc.target/aarch64/advsimd-intrinsics/vldX.c
>> gcc.target/aarch64/advsimd-intrinsics/vsubl.c
>> gcc.target/aarch64/advsimd-intrinsics/vfms.c
>> gcc.target/aarch64/advsimd-intrinsics/vmlsl.c
>> gcc.target/aarch64/advsimd-intrinsics/vsli_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vcombine.c
>> gcc.target/aarch64/advsimd-intrinsics/vmul_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vldX_dup.c
>> gcc.target/aarch64/advsimd-intrinsics/vpaddl.c
>> gcc.target/aarch64/advsimd-intrinsics/vqshrn_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vstX_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vqtbX.c
>> gcc.target/aarch64/advsimd-intrinsics/vext.c
>> gcc.target/aarch64/advsimd-intrinsics/vtrn.c
>> gcc.target/aarch64/advsimd-intrinsics/vtst.c
>> gcc.target/aarch64/advsimd-intrinsics/vbic.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmlsl.c
>> gcc.target/aarch64/advsimd-intrinsics/vqshl.c
>> gcc.target/aarch64/advsimd-intrinsics/vrsqrts.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmull_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmlsl_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmulh_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vsubw.c
>> gcc.target/aarch64/advsimd-intrinsics/vdup_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vget_high.c
>> gcc.target/aarch64/advsimd-intrinsics/vuzp.c
>> gcc.target/aarch64/advsimd-intrinsics/vqshl_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vrsra_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vcgt.c
>> gcc.target/aarch64/advsimd-intrinsics/vld1_dup.c
>> gcc.target/aarch64/advsimd-intrinsics/vaddhn.c
>> gcc.target/aarch64/advsimd-intrinsics/vqshlu_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vabs.c
>> gcc.target/aarch64/advsimd-intrinsics/vshll_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vsubhn.c
>> gcc.target/aarch64/advsimd-intrinsics/vmlal.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmlal.c
>> gcc.target/aarch64/advsimd-intrinsics/vrecpe.c
>> gcc.target/aarch64/advsimd-intrinsics/vqneg.c
>> gcc.target/aarch64/advsimd-intrinsics/veor.c
>> gcc.target/aarch64/simd/extq_p8_1.c
>> gcc.target/aarch64/advsimd-intrinsics/vclz.c
>> gcc.target/aarch64/simd/ext_p8_1.c
>> gcc.target/aarch64/advsimd-intrinsics/vqrdmulh_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vqrshl.c
>> gcc.target/aarch64/advsimd-intrinsics/vqrshrun_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vqrshrn_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vceq.c
>> gcc.target/aarch64/advsimd-intrinsics/vrndm.c
>> gcc.target/aarch64/advsimd-intrinsics/vmlsl_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vmlal_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vqmovun.c
>> gcc.target/aarch64/advsimd-intrinsics/vrshr_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vmls_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vmlsl_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmull_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vfms_vfma_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vorr.c
>> gcc.target/aarch64/advsimd-intrinsics/vaddl.c
>> gcc.target/aarch64/advsimd-intrinsics/vmovl.c
>> gcc.target/aarch64/advsimd-intrinsics/vbsl.c
>> gcc.target/aarch64/advsimd-intrinsics/vld1_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vqmovn.c
>> gcc.target/aarch64/advsimd-intrinsics/vcalt.c
>> gcc.target/aarch64/advsimd-intrinsics/vmul_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vqshrun_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vset_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vrsubhn.c
>> gcc.target/aarch64/advsimd-intrinsics/vshl_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vmovn.c
>> gcc.target/aarch64/advsimd-intrinsics/vcls.c
>> gcc.target/aarch64/advsimd-intrinsics/vcage.c
>> gcc.target/aarch64/advsimd-intrinsics/vcnt.c
>> gcc.target/aarch64/advsimd-intrinsics/vmull.c
>> gcc.target/aarch64/simd/vuzpp8_1.c
>> gcc.target/aarch64/advsimd-intrinsics/vreinterpret_p64.c
>> gcc.target/aarch64/advsimd-intrinsics/vfma.c
>> gcc.target/aarch64/advsimd-intrinsics/vld1.c
>> gcc.target/aarch64/advsimd-intrinsics/vhsub.c
>> gcc.target/aarch64/advsimd-intrinsics/vget_low.c
>> gcc.target/aarch64/advsimd-intrinsics/p64_p128.c
>> gcc.target/aarch64/advsimd-intrinsics/vcvt.c
>> gcc.target/aarch64/advsimd-intrinsics/vqdmull.c
>> gcc.target/aarch64/advsimd-intrinsics/vmvn.c
>> gcc.target/aarch64/advsimd-intrinsics/vmin.c
>> gcc.target/aarch64/advsimd-intrinsics/vaba.c
>> gcc.target/aarch64/advsimd-intrinsics/vqrdmulh_n.c
>> gcc.target/aarch64/simd/vtrnp8_1.c
>> gcc.target/aarch64/advsimd-intrinsics/vcagt.c
>> gcc.target/aarch64/advsimd-intrinsics/vdup-vmov.c
>> gcc.target/aarch64/advsimd-intrinsics/vrhadd.c
>> gcc.target/aarch64/advsimd-intrinsics/vabal.c
>> gcc.target/aarch64/advsimd-intrinsics/vrshrn_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vpmax.c
>> gcc.target/aarch64/advsimd-intrinsics/vmls.c
>> gcc.target/aarch64/advsimd-intrinsics/vshrn_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vrnd.c
>> gcc.target/aarch64/advsimd-intrinsics/vabd.c
>> gcc.target/aarch64/simd/vzipp8_1.c
>> gcc.target/aarch64/advsimd-intrinsics/vduph_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vreinterpret_p128.c
>> gcc.target/aarch64/advsimd-intrinsics/vrshl.c
>> gcc.target/aarch64/advsimd-intrinsics/vcreate.c
>> gcc.target/aarch64/advsimd-intrinsics/vqabs.c
>> gcc.target/aarch64/advsimd-intrinsics/vmull_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vreinterpret.c
>> gcc.target/aarch64/advsimd-intrinsics/vmlal_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vshr_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vzip.c
>> gcc.target/aarch64/vldN_lane_1.c
>> gcc.target/aarch64/advsimd-intrinsics/vabdl.c
>> gcc.target/aarch64/advsimd-intrinsics/vpmin.c
>> gcc.target/aarch64/advsimd-intrinsics/vqadd.c
>> gcc.target/aarch64/advsimd-intrinsics/vzip_half.c
>> gcc.target/aarch64/advsimd-intrinsics/vand.c
>> gcc.target/aarch64/advsimd-intrinsics/vpadd.c
>> gcc.target/aarch64/advsimd-intrinsics/vrndx.c
>> gcc.target/aarch64/advsimd-intrinsics/vmla.c
>> gcc.target/aarch64/advsimd-intrinsics/vsra_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vget_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vqrdmulh.c
>> gcc.target/aarch64/advsimd-intrinsics/vrndp.c
>> gcc.target/aarch64/advsimd-intrinsics/vmls_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vclt.c
>> gcc.target/aarch64/advsimd-intrinsics/vfma_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vaddw.c
>> gcc.target/aarch64/advsimd-intrinsics/vsri_n.c
>> gcc.target/aarch64/advsimd-intrinsics/vorn.c
>> gcc.target/aarch64/advsimd-intrinsics/vcvt_f16.c
>> gcc.target/aarch64/advsimd-intrinsics/vldX_lane.c
>> gcc.target/aarch64/advsimd-intrinsics/vcge.c
>> gcc.target/aarch64/advsimd-intrinsics/vshl.c
>> gcc.target/aarch64/advsimd-intrinsics/vtbX.c
>> gcc.target/aarch64/advsimd-intrinsics/vraddhn.c
>> gcc.target/aarch64/advsimd-intrinsics/vrnda.c
>> gcc.target/aarch64/advsimd-intrinsics/vrecps.c
>>
>>
>>
>>
>>
>>>
>>> Martin
>>
>>> PR tree-optimization/71625 - missing strlen optimization on different
>>> array initialization style
>>>
>>> gcc/c/ChangeLog:
>>>
>>>     PR tree-optimization/71625
>>>     * c-parser.c (c_parser_declaration_or_fndef): Call
>>>     braced_list_to_string.
>>>
>>> gcc/c-family/ChangeLog:
>>>
>>>     PR tree-optimization/71625
>>>     * c-common.c (braced_list_to_string): New function.
>>>     * c-common.h (braced_list_to_string): Declare it.
>>>
>>> gcc/cp/ChangeLog:
>>>
>>>     PR tree-optimization/71625
>>>     * decl.c (check_initializer):  Call braced_list_to_string.
>>>     (eval_check_narrowing): New function.
>>>     * gcc/cp/typeck2.c (digest_init_r): Accept strings literals
>>>     as initilizers for all narrow character types.
>>>
>>> gcc/testsuite/ChangeLog:
>>>
>>>     PR tree-optimization/71625
>>>     * g++.dg/init/string2.C: New test.
>>>     * g++.dg/init/string3.C: New test.
>>>     * g++.dg/init/string4.C: New test.
>>>     * gcc.dg/init-string-3.c: New test.
>>>     * gcc.dg/strlenopt-55.c: New test.
>>>     * gcc.dg/strlenopt-56.c: New test.
>

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-14 13:27             ` James Greenhalgh
  2018-08-14 15:08               ` Martin Sebor
@ 2018-08-14 21:14               ` Joseph Myers
  2018-08-14 22:18                 ` Martin Sebor
  1 sibling, 1 reply; 45+ messages in thread
From: Joseph Myers @ 2018-08-14 21:14 UTC (permalink / raw)
  To: James Greenhalgh; +Cc: Martin Sebor, Jason Merrill, Gcc Patch List, nd

On Tue, 14 Aug 2018, James Greenhalgh wrote:

> Hi Martin,
> 
> This causes issues for the AArch64 tests (full list below).

This change (r263511) also breaks the glibc build for alpha-linux-gnu with 
build-many-glibcs.py (using mainline GCC and binutils).  The error I see 
is:

/scratch/jmyers/glibc-bot/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/../../../../alpha-glibc-linux-gnu/bin/ld: 
/scratch/jmyers/glibc-bot/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/libc.a(plural.o): 
in function `__gettextparse':
/scratch/jmyers/glibc-bot/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:1108:(.text+0x218): 
relocation truncated to fit: GPRELHIGH against `.sdata'
/scratch/jmyers/glibc-bot/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/../../../../alpha-glibc-linux-gnu/bin/ld: 
/scratch/jmyers/glibc-bot/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:1348:(.text+0x300): 
relocation truncated to fit: GPRELHIGH against `.sdata'
collect2: error: ld returned 1 exit status
../Rules:224: recipe for target 
'/scratch/jmyers/glibc-bot/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/elf/sln' 
failed
make[3]: *** 
[/scratch/jmyers/glibc-bot/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/elf/sln] 
Error 1

This is with Bison 3.0.4, should the version used to produce intl/plural.c 
prove relevant.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-14 21:14               ` [PATCH] convert braced initializers to strings (PR 71625) Joseph Myers
@ 2018-08-14 22:18                 ` Martin Sebor
  2018-08-15 12:07                   ` Joseph Myers
  0 siblings, 1 reply; 45+ messages in thread
From: Martin Sebor @ 2018-08-14 22:18 UTC (permalink / raw)
  To: Joseph Myers, James Greenhalgh; +Cc: Jason Merrill, Gcc Patch List, nd

On 08/14/2018 03:14 PM, Joseph Myers wrote:
> On Tue, 14 Aug 2018, James Greenhalgh wrote:
>
>> Hi Martin,
>>
>> This causes issues for the AArch64 tests (full list below).
>
> This change (r263511) also breaks the glibc build for alpha-linux-gnu with
> build-many-glibcs.py (using mainline GCC and binutils).  The error I see
> is:
>
> /scratch/jmyers/glibc-bot/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/../../../../alpha-glibc-linux-gnu/bin/ld:
> /scratch/jmyers/glibc-bot/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/libc.a(plural.o):
> in function `__gettextparse':
> /scratch/jmyers/glibc-bot/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:1108:(.text+0x218):
> relocation truncated to fit: GPRELHIGH against `.sdata'
> /scratch/jmyers/glibc-bot/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/../../../../alpha-glibc-linux-gnu/bin/ld:
> /scratch/jmyers/glibc-bot/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:1348:(.text+0x300):
> relocation truncated to fit: GPRELHIGH against `.sdata'
> collect2: error: ld returned 1 exit status
> ../Rules:224: recipe for target
> '/scratch/jmyers/glibc-bot/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/elf/sln'
> failed
> make[3]: ***
> [/scratch/jmyers/glibc-bot/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/elf/sln]
> Error 1
>
> This is with Bison 3.0.4, should the version used to produce intl/plural.c
> prove relevant.

Can you send me the translation unit and the options it was compiled
with that triggered the errors?

Thanks
Martin

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-14 15:24                 ` Martin Sebor
@ 2018-08-15  2:34                   ` Martin Sebor
  2018-08-15 10:29                     ` James Greenhalgh
  0 siblings, 1 reply; 45+ messages in thread
From: Martin Sebor @ 2018-08-15  2:34 UTC (permalink / raw)
  To: James Greenhalgh; +Cc: Jason Merrill, Gcc Patch List, Joseph Myers, nd

On 08/14/2018 09:24 AM, Martin Sebor wrote:
> On 08/14/2018 09:08 AM, Martin Sebor wrote:
>> On 08/14/2018 07:27 AM, James Greenhalgh wrote:
>>> On Wed, Aug 08, 2018 at 07:17:07PM -0500, Martin Sebor wrote:
>>>> On 08/08/2018 05:08 AM, Jason Merrill wrote:
>>>>> On Wed, Aug 8, 2018 at 9:04 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>>>> On 08/07/2018 02:57 AM, Jason Merrill wrote:
>>>>>>>
>>>>>>> On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor <msebor@gmail.com>
>>>>>>> wrote:
>>>>>>>>
>>>>>>>> On 07/31/2018 07:38 AM, Jason Merrill wrote:
>>>
>>> <snip>
>>>
>>>> Done in the attached patch.  I've also avoided dealing with
>>>> zero-length arrays and added tests to make sure their size
>>>> stays is regardless of the form of their initializer and
>>>> the appropriate warnings are issued.
>>>>
>>>> Using build_string() rather than build_string_literal() needed
>>>> a tweak in digest_init_r().  It didn't break anything but since
>>>> the array type may not have a domain yet, neither will the
>>>> string.  It looks like that may get adjusted later on but I've
>>>> temporarily guarded the code with #if 1.  If the change is
>>>> fine I'll remove the #if before committing.
>>>>
>>>> This initial patch only handles narrow character initializers
>>>> (i.e., those with TYPE_STRING_FLAG set).  Once this gets some
>>>> exposure I'd like to extend it to other character types,
>>>> including wchar_t.
>>>
>>> Hi Martin,
>>>
>>> This causes issues for the AArch64 tests (full list below).
>>>
>>> I see an error message on the following construct:
>>>
>>>   void foo (void)
>>>   {
>>>     __Poly8_t x[4] = { 1, 2, 3, 4 };
>>>   }
>>>
>>>   init.c:3:20: error: array of inappropriate type initialized from
>>> string constant
>>>   3 |   __Poly8_t x[4] = { 1, 2, 3, 4 };
>>>     |
>>>
>>> __Poly8_t is a type we define in our backend, through a convoluted
>>> set of
>>> functions, which operates a lot like an unsigned, QI mode type.
>>
>> I see the error with my aarch64 cross-compiler .  The new code
>> that does the conversion of array initializers to STRING_CSTs
>> looks for the TYPE_STRING_FLAG() to be set on the type of
>> the array elements.  Perhaps __Poly8_t should not have the flag
>> set?  (If it needs it then I think we'd have to only consider
>> named character types.)
>
> The change below gets rid of the compilation error.  I don't
> know if it's appropriate for the aarch64 back end:
>
> Index: gcc/config/aarch64/aarch64-builtins.c
> ===================================================================
> --- gcc/config/aarch64/aarch64-builtins.c    (revision 263537)
> +++ gcc/config/aarch64/aarch64-builtins.c    (working copy)
> @@ -643,6 +643,7 @@ aarch64_init_simd_builtin_types (void)
>    /* Poly types are a world of their own.  */
>    aarch64_simd_types[Poly8_t].eltype = aarch64_simd_types[Poly8_t].itype =
>      build_distinct_type_copy (unsigned_intQI_type_node);
> +  TYPE_STRING_FLAG (aarch64_simd_types[Poly8_t].eltype) = false;
>    aarch64_simd_types[Poly16_t].eltype =
> aarch64_simd_types[Poly16_t].itype =
>      build_distinct_type_copy (unsigned_intHI_type_node);
>    aarch64_simd_types[Poly64_t].eltype =
> aarch64_simd_types[Poly64_t].itype =
>
>
>>> A second set of tests fail due to changed inlining behaviour for
>>> functions
>>> with char array initialization:
>>>
>>>   gcc.target/aarch64/vset_lane_1.c
>>>   gcc.target/aarch64/vneg_s.c
>>>   gcc.target/aarch64/vclz.c
>>
>> I'm not sure what's going on here.  The tests are very big and
>> take forever to compile with an aarch64 cross-compiler, and I'm
>> not sure what to look for.  Can you provide a smaller test case
>> that shows the issue?

I wonder if these changes might be due to the same problem:
the tests define and initialize arrays of the Int8x16_t type
which is initialized to intQI_type_node, i.e., the signed
form of Poly8_t.  Does the conversion to STRING_CST cause
a performance degradation or is it just that the tests end
up with equivalent but slightly different assembly?

The tests also use int8_t and uint8_t for the expected results.
Those are typedefs for signed and unsigned char, respectively.
Is the conversion to strings for those fine?

Martin

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-15  2:34                   ` Martin Sebor
@ 2018-08-15 10:29                     ` James Greenhalgh
  2018-08-15 15:04                       ` Richard Biener
  2018-08-15 15:51                       ` Martin Sebor
  0 siblings, 2 replies; 45+ messages in thread
From: James Greenhalgh @ 2018-08-15 10:29 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Jason Merrill, Gcc Patch List, Joseph Myers, nd

On Tue, Aug 14, 2018 at 09:34:08PM -0500, Martin Sebor wrote:
> On 08/14/2018 09:24 AM, Martin Sebor wrote:
> > On 08/14/2018 09:08 AM, Martin Sebor wrote:
> >> On 08/14/2018 07:27 AM, James Greenhalgh wrote:
> >>> On Wed, Aug 08, 2018 at 07:17:07PM -0500, Martin Sebor wrote:
> >>>> On 08/08/2018 05:08 AM, Jason Merrill wrote:
> >>>>> On Wed, Aug 8, 2018 at 9:04 AM, Martin Sebor <msebor@gmail.com> wrote:
> >>>>>> On 08/07/2018 02:57 AM, Jason Merrill wrote:
> >>>>>>>
> >>>>>>> On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor <msebor@gmail.com>
> >>>>>>> wrote:
> >>>>>>>>
> >>>>>>>> On 07/31/2018 07:38 AM, Jason Merrill wrote:
> >>>
> >>> <snip>
> >>>
> >>>> Done in the attached patch.  I've also avoided dealing with
> >>>> zero-length arrays and added tests to make sure their size
> >>>> stays is regardless of the form of their initializer and
> >>>> the appropriate warnings are issued.
> >>>>
> >>>> Using build_string() rather than build_string_literal() needed
> >>>> a tweak in digest_init_r().  It didn't break anything but since
> >>>> the array type may not have a domain yet, neither will the
> >>>> string.  It looks like that may get adjusted later on but I've
> >>>> temporarily guarded the code with #if 1.  If the change is
> >>>> fine I'll remove the #if before committing.
> >>>>
> >>>> This initial patch only handles narrow character initializers
> >>>> (i.e., those with TYPE_STRING_FLAG set).  Once this gets some
> >>>> exposure I'd like to extend it to other character types,
> >>>> including wchar_t.
> >>>
> >>> Hi Martin,
> >>>
> >>> This causes issues for the AArch64 tests (full list below).
> >>>
> >>> I see an error message on the following construct:
> >>>
> >>>   void foo (void)
> >>>   {
> >>>     __Poly8_t x[4] = { 1, 2, 3, 4 };
> >>>   }
> >>>
> >>>   init.c:3:20: error: array of inappropriate type initialized from
> >>> string constant
> >>>   3 |   __Poly8_t x[4] = { 1, 2, 3, 4 };
> >>>     |
> >>>
> >>> __Poly8_t is a type we define in our backend, through a convoluted
> >>> set of
> >>> functions, which operates a lot like an unsigned, QI mode type.
> >>
> >> I see the error with my aarch64 cross-compiler .  The new code
> >> that does the conversion of array initializers to STRING_CSTs
> >> looks for the TYPE_STRING_FLAG() to be set on the type of
> >> the array elements.  Perhaps __Poly8_t should not have the flag
> >> set?  (If it needs it then I think we'd have to only consider
> >> named character types.)
> >
> > The change below gets rid of the compilation error.  I don't
> > know if it's appropriate for the aarch64 back end:
> >
> > Index: gcc/config/aarch64/aarch64-builtins.c
> > ===================================================================
> > --- gcc/config/aarch64/aarch64-builtins.c    (revision 263537)
> > +++ gcc/config/aarch64/aarch64-builtins.c    (working copy)
> > @@ -643,6 +643,7 @@ aarch64_init_simd_builtin_types (void)
> >    /* Poly types are a world of their own.  */
> >    aarch64_simd_types[Poly8_t].eltype = aarch64_simd_types[Poly8_t].itype =
> >      build_distinct_type_copy (unsigned_intQI_type_node);
> > +  TYPE_STRING_FLAG (aarch64_simd_types[Poly8_t].eltype) = false;
> >    aarch64_simd_types[Poly16_t].eltype =
> > aarch64_simd_types[Poly16_t].itype =
> >      build_distinct_type_copy (unsigned_intHI_type_node);
> >    aarch64_simd_types[Poly64_t].eltype =
> > aarch64_simd_types[Poly64_t].itype =

This fix seems correct to me, the poly types are not strings. Looking at
other uses of TYPE_STRING_FLAG this change doesn't seem like it would have
impact on parsing or code generation.

OK for trunk.

> >>> A second set of tests fail due to changed inlining behaviour for
> >>> functions
> >>> with char array initialization:
> >>>
> >>>   gcc.target/aarch64/vset_lane_1.c
> >>>   gcc.target/aarch64/vneg_s.c
> >>>   gcc.target/aarch64/vclz.c
> >>
> >> I'm not sure what's going on here.  The tests are very big and
> >> take forever to compile with an aarch64 cross-compiler, and I'm
> >> not sure what to look for.  Can you provide a smaller test case
> >> that shows the issue?
> 
> I wonder if these changes might be due to the same problem:
> the tests define and initialize arrays of the Int8x16_t type
> which is initialized to intQI_type_node, i.e., the signed
> form of Poly8_t.  Does the conversion to STRING_CST cause
> a performance degradation or is it just that the tests end
> up with equivalent but slightly different assembly?

These tests aren't looking at performance, just expecting to see certain
instructions emitted. The only change is that now the int8x16_t forms are
inlined (so the scan-assembler-times fails with two matches, one expected,
one in the inlined function body copy).

The difference seems to be in the initialization cost of the input data set.

Before your patch:

  int8_tD.3359 test_set0D.21541[8];
  int8_tD.3359 answ_set0D.21542[8];

      test_set0D.21541[0] = 0;
      test_set0D.21541[1] = 1;
      test_set0D.21541[2] = -1;
      test_set0D.21541[3] = 10;
      test_set0D.21541[4] = -10;
      test_set0D.21541[5] = 0;
      test_set0D.21541[6] = 127;
      test_set0D.21541[7] = -128;
      answ_set0D.21542[0] = 0;
      answ_set0D.21542[1] = -1;
      answ_set0D.21542[2] = 1;
      answ_set0D.21542[3] = -10;
      answ_set0D.21542[4] = 10;
      answ_set0D.21542[5] = 0;
      answ_set0D.21542[6] = -127;
      answ_set0D.21542[7] = -128;

After your patch:

  int8_tD.3357 test_set0D.21539[8];
  int8_tD.3357 answ_set0D.21540[8];

      test_set0D.21539 = "";
      answ_set0D.21540 = "";

I think that is probably what you expected to happen; but the impact on
inlining might not have been. Probably, we want to just change these tests
to explicitly disable inlining. The tests appear to execute correctly.

The print in the dump file is a bit unusual; presumably the impact of having
non-printing characters in my initializer list - but less helpful output for
it.

Off topic; these tests are quick to copmpile on my cross and native
compilers. Do you have additional checking enabled?

Thanks,
James

> 
> The tests also use int8_t and uint8_t for the expected results.
> Those are typedefs for signed and unsigned char, respectively.
> Is the conversion to strings for those fine?
> 
> Martin

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-14 22:18                 ` Martin Sebor
@ 2018-08-15 12:07                   ` Joseph Myers
  2018-08-15 21:02                     ` Martin Sebor
  0 siblings, 1 reply; 45+ messages in thread
From: Joseph Myers @ 2018-08-15 12:07 UTC (permalink / raw)
  To: Martin Sebor; +Cc: James Greenhalgh, Jason Merrill, Gcc Patch List, nd

[-- Attachment #1: Type: text/plain, Size: 2549 bytes --]

On Tue, 14 Aug 2018, Martin Sebor wrote:

> > This is with Bison 3.0.4, should the version used to produce intl/plural.c
> > prove relevant.
> 
> Can you send me the translation unit and the options it was compiled
> with that triggered the errors?

I've attached plural.i.  The error is a static link error linking sln, but 
maybe comparing results of compiling plural.i before and after the changes 
may be enlightening (unless it's actually a difference in code elsewhere 
in glibc causing a link error reported in plural.o).

Compiled with:

alpha-glibc-linux-gnu-gcc 
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c 
-c -std=gnu11 -fgnu89-inline  -O2 -Wall -Werror -Wundef -Wwrite-strings 
-fmerge-all-constants -fno-stack-protector -frounding-math -g 
-Wstrict-prototypes -Wold-style-definition -fno-math-errno 
-mlong-double-128 -mieee -mfp-rounding-mode=d     -ftls-model=initial-exec      
-I../include 
-I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl  
-I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu  
-I../sysdeps/unix/sysv/linux/alpha/alpha  
-I../sysdeps/unix/sysv/linux/alpha/fpu  -I../sysdeps/alpha/fpu  
-I../sysdeps/unix/sysv/linux/alpha  -I../sysdeps/alpha/nptl  
-I../sysdeps/unix/sysv/linux/wordsize-64  -I../sysdeps/ieee754/ldbl-64-128  
-I../sysdeps/ieee754/ldbl-opt  -I../sysdeps/unix/sysv/linux/include 
-I../sysdeps/unix/sysv/linux  -I../sysdeps/nptl  -I../sysdeps/pthread  
-I../sysdeps/gnu  -I../sysdeps/unix/inet  -I../sysdeps/unix/sysv  
-I../sysdeps/unix/alpha  -I../sysdeps/unix  -I../sysdeps/posix  
-I../sysdeps/alpha  -I../sysdeps/wordsize-64  
-I../sysdeps/ieee754/ldbl-128  -I../sysdeps/ieee754/dbl-64/wordsize-64  
-I../sysdeps/ieee754/dbl-64  -I../sysdeps/ieee754/flt-32  
-I../sysdeps/ieee754  -I../sysdeps/generic  -I.. -I../libio -I.   
-D_LIBC_REENTRANT -include 
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/libc-modules.h 
-DMODULE_NAME=libc -include ../include/libc-symbols.h       
-DTOP_NAMESPACE=glibc -D'LOCALEDIR="/usr/share/locale"' 
-D'LOCALE_ALIAS_PATH="/usr/share/locale"' -o 
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o 
-MD -MP -MF 
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o.dt 
-MT 
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o

-- 
Joseph S. Myers
joseph@codesourcery.com

[-- Attachment #2: Type: text/plain, Size: 111776 bytes --]

# 1 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
# 1 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc-src/alpha-linux-gnu/intl//"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "../include/stdc-predef.h" 1
# 1 "<command-line>" 2
# 1 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/libc-modules.h" 1
# 1 "<command-line>" 2
# 1 "./../include/libc-symbols.h" 1
# 85 "./../include/libc-symbols.h"
# 1 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/config.h" 1
# 86 "./../include/libc-symbols.h" 2
# 847 "./../include/libc-symbols.h"
# 1 "../sysdeps/generic/symbol-hacks.h" 1
# 848 "./../include/libc-symbols.h" 2
# 1 "<command-line>" 2
# 1 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
# 1 "plural.y"
# 29 "plural.y"
# 1 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/config.h" 1
# 30 "plural.y" 2


# 1 "/scratch/jmyers/glibc/many9/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/include/stddef.h" 1 3 4
# 143 "/scratch/jmyers/glibc/many9/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/include/stddef.h" 3 4

# 143 "/scratch/jmyers/glibc/many9/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/include/stddef.h" 3 4
typedef long int ptrdiff_t;
# 209 "/scratch/jmyers/glibc/many9/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/include/stddef.h" 3 4
typedef long unsigned int size_t;
# 321 "/scratch/jmyers/glibc/many9/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/include/stddef.h" 3 4
typedef int wchar_t;
# 415 "/scratch/jmyers/glibc/many9/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/include/stddef.h" 3 4
typedef struct {
  long long __max_align_ll __attribute__((__aligned__(__alignof__(long long))));
  long double __max_align_ld __attribute__((__aligned__(__alignof__(long double))));
# 426 "/scratch/jmyers/glibc/many9/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/include/stddef.h" 3 4
} max_align_t;
# 33 "plural.y" 2
# 1 "../include/stdlib.h" 1



# 1 "/scratch/jmyers/glibc/many9/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/include/stddef.h" 1 3 4
# 5 "../include/stdlib.h" 2

# 1 "../stdlib/stdlib.h" 1
# 25 "../stdlib/stdlib.h"
# 1 "../bits/libc-header-start.h" 1
# 33 "../bits/libc-header-start.h"
# 1 "../include/features.h" 1
# 428 "../include/features.h"
# 1 "../include/sys/cdefs.h" 1


# 1 "../misc/sys/cdefs.h" 1
# 442 "../misc/sys/cdefs.h"
# 1 "../sysdeps/unix/sysv/linux/alpha/bits/wordsize.h" 1
# 443 "../misc/sys/cdefs.h" 2
# 1 "../sysdeps/ieee754/ldbl-opt/bits/long-double.h" 1
# 444 "../misc/sys/cdefs.h" 2
# 4 "../include/sys/cdefs.h" 2
# 12 "../include/sys/cdefs.h"

# 12 "../include/sys/cdefs.h"
extern void __chk_fail (void) __attribute__ ((__noreturn__));
extern __typeof (__chk_fail) __chk_fail __attribute__ ((visibility ("hidden")));

# 429 "../include/features.h" 2
# 452 "../include/features.h"
# 1 "../include/gnu/stubs.h" 1
# 453 "../include/features.h" 2
# 34 "../bits/libc-header-start.h" 2
# 26 "../stdlib/stdlib.h" 2





# 1 "/scratch/jmyers/glibc/many9/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/include/stddef.h" 1 3 4
# 32 "../stdlib/stdlib.h" 2







# 1 "../sysdeps/unix/sysv/linux/bits/waitflags.h" 1
# 40 "../stdlib/stdlib.h" 2
# 1 "../bits/waitstatus.h" 1
# 41 "../stdlib/stdlib.h" 2
# 55 "../stdlib/stdlib.h"
# 1 "../sysdeps/ieee754/ldbl-128/bits/floatn.h" 1
# 23 "../sysdeps/ieee754/ldbl-128/bits/floatn.h"
# 1 "../sysdeps/ieee754/ldbl-opt/bits/long-double.h" 1
# 24 "../sysdeps/ieee754/ldbl-128/bits/floatn.h" 2
# 95 "../sysdeps/ieee754/ldbl-128/bits/floatn.h"
# 1 "../bits/floatn-common.h" 1
# 24 "../bits/floatn-common.h"
# 1 "../sysdeps/ieee754/ldbl-opt/bits/long-double.h" 1
# 25 "../bits/floatn-common.h" 2
# 96 "../sysdeps/ieee754/ldbl-128/bits/floatn.h" 2
# 56 "../stdlib/stdlib.h" 2


typedef struct
  {
    int quot;
    int rem;
  } div_t;



typedef struct
  {
    long int quot;
    long int rem;
  } ldiv_t;





__extension__ typedef struct
  {
    long long int quot;
    long long int rem;
  } lldiv_t;
# 97 "../stdlib/stdlib.h"
extern size_t __ctype_get_mb_cur_max (void) __attribute__ ((__nothrow__ )) ;



extern double atof (const char *__nptr)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;

extern int atoi (const char *__nptr)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;

extern long int atol (const char *__nptr)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;



__extension__ extern long long int atoll (const char *__nptr)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;



extern double strtod (const char *__restrict __nptr,
        char **__restrict __endptr)
     __attribute__ ((__nothrow__ )) ;



extern float strtof (const char *__restrict __nptr,
       char **__restrict __endptr) __attribute__ ((__nothrow__ )) ;

extern long double strtold (const char *__restrict __nptr,
       char **__restrict __endptr)
     __attribute__ ((__nothrow__ )) ;
# 140 "../stdlib/stdlib.h"
extern _Float32 strtof32 (const char *__restrict __nptr,
     char **__restrict __endptr)
     __attribute__ ((__nothrow__ )) ;



extern _Float64 strtof64 (const char *__restrict __nptr,
     char **__restrict __endptr)
     __attribute__ ((__nothrow__ )) ;



extern _Float128 strtof128 (const char *__restrict __nptr,
       char **__restrict __endptr)
     __attribute__ ((__nothrow__ )) ;



extern _Float32x strtof32x (const char *__restrict __nptr,
       char **__restrict __endptr)
     __attribute__ ((__nothrow__ )) ;



extern _Float64x strtof64x (const char *__restrict __nptr,
       char **__restrict __endptr)
     __attribute__ ((__nothrow__ )) ;
# 176 "../stdlib/stdlib.h"
extern long int strtol (const char *__restrict __nptr,
   char **__restrict __endptr, int __base)
     __attribute__ ((__nothrow__ )) ;

extern unsigned long int strtoul (const char *__restrict __nptr,
      char **__restrict __endptr, int __base)
     __attribute__ ((__nothrow__ )) ;



__extension__
extern long long int strtoq (const char *__restrict __nptr,
        char **__restrict __endptr, int __base)
     __attribute__ ((__nothrow__ )) ;

__extension__
extern unsigned long long int strtouq (const char *__restrict __nptr,
           char **__restrict __endptr, int __base)
     __attribute__ ((__nothrow__ )) ;




__extension__
extern long long int strtoll (const char *__restrict __nptr,
         char **__restrict __endptr, int __base)
     __attribute__ ((__nothrow__ )) ;

__extension__
extern unsigned long long int strtoull (const char *__restrict __nptr,
     char **__restrict __endptr, int __base)
     __attribute__ ((__nothrow__ )) ;




extern int strfromd (char *__dest, size_t __size, const char *__format,
       double __f)
     __attribute__ ((__nothrow__ )) ;

extern int strfromf (char *__dest, size_t __size, const char *__format,
       float __f)
     __attribute__ ((__nothrow__ )) ;

extern int strfroml (char *__dest, size_t __size, const char *__format,
       long double __f)
     __attribute__ ((__nothrow__ )) ;
# 232 "../stdlib/stdlib.h"
extern int strfromf32 (char *__dest, size_t __size, const char * __format,
         _Float32 __f)
     __attribute__ ((__nothrow__ )) ;



extern int strfromf64 (char *__dest, size_t __size, const char * __format,
         _Float64 __f)
     __attribute__ ((__nothrow__ )) ;



extern int strfromf128 (char *__dest, size_t __size, const char * __format,
   _Float128 __f)
     __attribute__ ((__nothrow__ )) ;



extern int strfromf32x (char *__dest, size_t __size, const char * __format,
   _Float32x __f)
     __attribute__ ((__nothrow__ )) ;



extern int strfromf64x (char *__dest, size_t __size, const char * __format,
   _Float64x __f)
     __attribute__ ((__nothrow__ )) ;
# 272 "../stdlib/stdlib.h"
# 1 "../include/bits/types/locale_t.h" 1
# 1 "../locale/bits/types/locale_t.h" 1
# 22 "../locale/bits/types/locale_t.h"
# 1 "../include/bits/types/__locale_t.h" 1
# 1 "../locale/bits/types/__locale_t.h" 1
# 28 "../locale/bits/types/__locale_t.h"
struct __locale_struct
{

  struct __locale_data *__locales[13];


  const unsigned short int *__ctype_b;
  const int *__ctype_tolower;
  const int *__ctype_toupper;


  const char *__names[13];
};

typedef struct __locale_struct *__locale_t;
# 1 "../include/bits/types/__locale_t.h" 2
# 23 "../locale/bits/types/locale_t.h" 2

typedef __locale_t locale_t;
# 1 "../include/bits/types/locale_t.h" 2
# 273 "../stdlib/stdlib.h" 2

extern long int strtol_l (const char *__restrict __nptr,
     char **__restrict __endptr, int __base,
     locale_t __loc) __attribute__ ((__nothrow__ )) ;

extern unsigned long int strtoul_l (const char *__restrict __nptr,
        char **__restrict __endptr,
        int __base, locale_t __loc)
     __attribute__ ((__nothrow__ )) ;

__extension__
extern long long int strtoll_l (const char *__restrict __nptr,
    char **__restrict __endptr, int __base,
    locale_t __loc)
     __attribute__ ((__nothrow__ )) ;

__extension__
extern unsigned long long int strtoull_l (const char *__restrict __nptr,
       char **__restrict __endptr,
       int __base, locale_t __loc)
     __attribute__ ((__nothrow__ )) ;

extern double strtod_l (const char *__restrict __nptr,
   char **__restrict __endptr, locale_t __loc)
     __attribute__ ((__nothrow__ )) ;

extern float strtof_l (const char *__restrict __nptr,
         char **__restrict __endptr, locale_t __loc)
     __attribute__ ((__nothrow__ )) ;

extern long double strtold_l (const char *__restrict __nptr,
         char **__restrict __endptr,
         locale_t __loc)
     __attribute__ ((__nothrow__ )) ;
# 316 "../stdlib/stdlib.h"
extern _Float32 strtof32_l (const char *__restrict __nptr,
       char **__restrict __endptr,
       locale_t __loc)
     __attribute__ ((__nothrow__ )) ;



extern _Float64 strtof64_l (const char *__restrict __nptr,
       char **__restrict __endptr,
       locale_t __loc)
     __attribute__ ((__nothrow__ )) ;



extern _Float128 strtof128_l (const char *__restrict __nptr,
         char **__restrict __endptr,
         locale_t __loc)
     __attribute__ ((__nothrow__ )) ;



extern _Float32x strtof32x_l (const char *__restrict __nptr,
         char **__restrict __endptr,
         locale_t __loc)
     __attribute__ ((__nothrow__ )) ;



extern _Float64x strtof64x_l (const char *__restrict __nptr,
         char **__restrict __endptr,
         locale_t __loc)
     __attribute__ ((__nothrow__ )) ;
# 360 "../stdlib/stdlib.h"
extern __inline int
__attribute__ ((__nothrow__ )) atoi (const char *__nptr)
{
  return (int) strtol (__nptr, (char **) 
# 363 "../stdlib/stdlib.h" 3 4
                                        ((void *)0)
# 363 "../stdlib/stdlib.h"
                                            , 10);
}
extern __inline long int
__attribute__ ((__nothrow__ )) atol (const char *__nptr)
{
  return strtol (__nptr, (char **) 
# 368 "../stdlib/stdlib.h" 3 4
                                  ((void *)0)
# 368 "../stdlib/stdlib.h"
                                      , 10);
}


__extension__ extern __inline long long int
__attribute__ ((__nothrow__ )) atoll (const char *__nptr)
{
  return strtoll (__nptr, (char **) 
# 375 "../stdlib/stdlib.h" 3 4
                                   ((void *)0)
# 375 "../stdlib/stdlib.h"
                                       , 10);
}
# 385 "../stdlib/stdlib.h"
extern char *l64a (long int __n) __attribute__ ((__nothrow__ )) ;


extern long int a64l (const char *__s)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;




# 1 "../include/sys/types.h" 1
# 1 "../posix/sys/types.h" 1
# 27 "../posix/sys/types.h"


# 1 "../include/bits/types.h" 1
# 1 "../posix/bits/types.h" 1
# 27 "../posix/bits/types.h"
# 1 "../sysdeps/unix/sysv/linux/alpha/bits/wordsize.h" 1
# 28 "../posix/bits/types.h" 2


typedef unsigned char __u_char;
typedef unsigned short int __u_short;
typedef unsigned int __u_int;
typedef unsigned long int __u_long;


typedef signed char __int8_t;
typedef unsigned char __uint8_t;
typedef signed short int __int16_t;
typedef unsigned short int __uint16_t;
typedef signed int __int32_t;
typedef unsigned int __uint32_t;

typedef signed long int __int64_t;
typedef unsigned long int __uint64_t;






typedef __int8_t __int_least8_t;
typedef __uint8_t __uint_least8_t;
typedef __int16_t __int_least16_t;
typedef __uint16_t __uint_least16_t;
typedef __int32_t __int_least32_t;
typedef __uint32_t __uint_least32_t;
typedef __int64_t __int_least64_t;
typedef __uint64_t __uint_least64_t;



typedef long int __quad_t;
typedef unsigned long int __u_quad_t;







typedef long int __intmax_t;
typedef unsigned long int __uintmax_t;
# 140 "../posix/bits/types.h"
# 1 "../sysdeps/unix/sysv/linux/alpha/bits/typesizes.h" 1
# 141 "../posix/bits/types.h" 2


typedef unsigned long int __dev_t;
typedef unsigned int __uid_t;
typedef unsigned int __gid_t;
typedef unsigned int __ino_t;
typedef unsigned long int __ino64_t;
typedef unsigned int __mode_t;
typedef unsigned int __nlink_t;
typedef long int __off_t;
typedef long int __off64_t;
typedef int __pid_t;
typedef struct { int __val[2]; } __fsid_t;
typedef long int __clock_t;
typedef unsigned long int __rlim_t;
typedef unsigned long int __rlim64_t;
typedef unsigned int __id_t;
typedef long int __time_t;
typedef unsigned int __useconds_t;
typedef long int __suseconds_t;

typedef int __daddr_t;
typedef int __key_t;


typedef int __clockid_t;


typedef void * __timer_t;


typedef unsigned int __blksize_t;




typedef unsigned int __blkcnt_t;
typedef unsigned long int __blkcnt64_t;


typedef int __fsblkcnt_t;
typedef long int __fsblkcnt64_t;


typedef unsigned int __fsfilcnt_t;
typedef unsigned long int __fsfilcnt64_t;


typedef int __fsword_t;

typedef long int __ssize_t;


typedef long int __syscall_slong_t;

typedef unsigned long int __syscall_ulong_t;



typedef __off64_t __loff_t;
typedef char *__caddr_t;


typedef long int __intptr_t;


typedef unsigned int __socklen_t;




typedef int __sig_atomic_t;
# 1 "../include/bits/types.h" 2
# 30 "../posix/sys/types.h" 2



typedef __u_char u_char;
typedef __u_short u_short;
typedef __u_int u_int;
typedef __u_long u_long;
typedef __quad_t quad_t;
typedef __u_quad_t u_quad_t;
typedef __fsid_t fsid_t;


typedef __loff_t loff_t;




typedef __ino_t ino_t;






typedef __ino64_t ino64_t;




typedef __dev_t dev_t;




typedef __gid_t gid_t;




typedef __mode_t mode_t;




typedef __nlink_t nlink_t;




typedef __uid_t uid_t;





typedef __off_t off_t;






typedef __off64_t off64_t;




typedef __pid_t pid_t;





typedef __id_t id_t;




typedef __ssize_t ssize_t;





typedef __daddr_t daddr_t;
typedef __caddr_t caddr_t;





typedef __key_t key_t;




# 1 "../include/bits/types/clock_t.h" 1
# 1 "../time/bits/types/clock_t.h" 1



# 1 "../include/bits/types.h" 1
# 5 "../time/bits/types/clock_t.h" 2


typedef __clock_t clock_t;
# 1 "../include/bits/types/clock_t.h" 2
# 127 "../posix/sys/types.h" 2

# 1 "../include/bits/types/clockid_t.h" 1
# 1 "../time/bits/types/clockid_t.h" 1



# 1 "../include/bits/types.h" 1
# 5 "../time/bits/types/clockid_t.h" 2


typedef __clockid_t clockid_t;
# 1 "../include/bits/types/clockid_t.h" 2
# 129 "../posix/sys/types.h" 2
# 1 "../include/bits/types/time_t.h" 1
# 1 "../time/bits/types/time_t.h" 1



# 1 "../include/bits/types.h" 1
# 5 "../time/bits/types/time_t.h" 2


typedef __time_t time_t;
# 1 "../include/bits/types/time_t.h" 2
# 130 "../posix/sys/types.h" 2
# 1 "../include/bits/types/timer_t.h" 1
# 1 "../time/bits/types/timer_t.h" 1



# 1 "../include/bits/types.h" 1
# 5 "../time/bits/types/timer_t.h" 2


typedef __timer_t timer_t;
# 1 "../include/bits/types/timer_t.h" 2
# 131 "../posix/sys/types.h" 2



typedef __useconds_t useconds_t;



typedef __suseconds_t suseconds_t;





# 1 "/scratch/jmyers/glibc/many9/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/include/stddef.h" 1 3 4
# 145 "../posix/sys/types.h" 2



typedef unsigned long int ulong;
typedef unsigned short int ushort;
typedef unsigned int uint;




# 1 "../bits/stdint-intn.h" 1
# 22 "../bits/stdint-intn.h"
# 1 "../include/bits/types.h" 1
# 23 "../bits/stdint-intn.h" 2

typedef __int8_t int8_t;
typedef __int16_t int16_t;
typedef __int32_t int32_t;
typedef __int64_t int64_t;
# 156 "../posix/sys/types.h" 2
# 177 "../posix/sys/types.h"
typedef unsigned int u_int8_t __attribute__ ((__mode__ (__QI__)));
typedef unsigned int u_int16_t __attribute__ ((__mode__ (__HI__)));
typedef unsigned int u_int32_t __attribute__ ((__mode__ (__SI__)));
typedef unsigned int u_int64_t __attribute__ ((__mode__ (__DI__)));

typedef int register_t __attribute__ ((__mode__ (__word__)));
# 193 "../posix/sys/types.h"
# 1 "../include/endian.h" 1
# 1 "../string/endian.h" 1
# 36 "../string/endian.h"
# 1 "../sysdeps/alpha/bits/endian.h" 1
# 37 "../string/endian.h" 2
# 60 "../string/endian.h"
# 1 "../bits/byteswap.h" 1
# 27 "../bits/byteswap.h"
# 1 "../include/bits/types.h" 1
# 28 "../bits/byteswap.h" 2





static __inline __uint16_t
__bswap_16 (__uint16_t __bsx)
{

  return __builtin_bswap16 (__bsx);



}






static __inline __uint32_t
__bswap_32 (__uint32_t __bsx)
{

  return __builtin_bswap32 (__bsx);



}
# 69 "../bits/byteswap.h"
__extension__ static __inline __uint64_t
__bswap_64 (__uint64_t __bsx)
{

  return __builtin_bswap64 (__bsx);



}
# 61 "../string/endian.h" 2
# 1 "../bits/uintn-identity.h" 1
# 26 "../bits/uintn-identity.h"
# 1 "../include/bits/types.h" 1
# 27 "../bits/uintn-identity.h" 2





static __inline __uint16_t
__uint16_identity (__uint16_t __x)
{
  return __x;
}

static __inline __uint32_t
__uint32_identity (__uint32_t __x)
{
  return __x;
}

static __inline __uint64_t
__uint64_identity (__uint64_t __x)
{
  return __x;
}
# 62 "../string/endian.h" 2
# 2 "../include/endian.h" 2
# 194 "../posix/sys/types.h" 2


# 1 "../include/sys/select.h" 1

# 1 "../misc/sys/select.h" 1
# 27 "../misc/sys/select.h"
# 1 "../include/bits/types.h" 1
# 28 "../misc/sys/select.h" 2


# 1 "../bits/select.h" 1
# 31 "../misc/sys/select.h" 2


# 1 "../include/bits/types/sigset_t.h" 1
# 1 "../signal/bits/types/sigset_t.h" 1



# 1 "../sysdeps/unix/sysv/linux/bits/types/__sigset_t.h" 1




typedef struct
{
  unsigned long int __val[(1024 / (8 * sizeof (unsigned long int)))];
} __sigset_t;
# 5 "../signal/bits/types/sigset_t.h" 2


typedef __sigset_t sigset_t;
# 1 "../include/bits/types/sigset_t.h" 2
# 34 "../misc/sys/select.h" 2


# 1 "../include/bits/types/time_t.h" 1
# 37 "../misc/sys/select.h" 2
# 1 "../include/bits/types/struct_timeval.h" 1
# 1 "../time/bits/types/struct_timeval.h" 1



# 1 "../include/bits/types.h" 1
# 5 "../time/bits/types/struct_timeval.h" 2



struct timeval
{
  __time_t tv_sec;
  __suseconds_t tv_usec;
};
# 1 "../include/bits/types/struct_timeval.h" 2
# 38 "../misc/sys/select.h" 2

# 1 "../include/bits/types/struct_timespec.h" 1
# 1 "../time/bits/types/struct_timespec.h" 1




# 1 "../include/bits/types.h" 1
# 6 "../time/bits/types/struct_timespec.h" 2



struct timespec
{
  __time_t tv_sec;
  __syscall_slong_t tv_nsec;
};
# 1 "../include/bits/types/struct_timespec.h" 2
# 40 "../misc/sys/select.h" 2
# 49 "../misc/sys/select.h"
typedef long int __fd_mask;
# 59 "../misc/sys/select.h"
typedef struct
  {



    __fd_mask fds_bits[1024 / (8 * (int) sizeof (__fd_mask))];





  } fd_set;






typedef __fd_mask fd_mask;
# 91 "../misc/sys/select.h"

# 101 "../misc/sys/select.h"
extern int select (int __nfds, fd_set *__restrict __readfds,
     fd_set *__restrict __writefds,
     fd_set *__restrict __exceptfds,
     struct timeval *__restrict __timeout);
# 113 "../misc/sys/select.h"
extern int pselect (int __nfds, fd_set *__restrict __readfds,
      fd_set *__restrict __writefds,
      fd_set *__restrict __exceptfds,
      const struct timespec *__restrict __timeout,
      const __sigset_t *__restrict __sigmask);
# 126 "../misc/sys/select.h"

# 3 "../include/sys/select.h" 2



extern int __pselect (int __nfds, fd_set *__readfds,
        fd_set *__writefds, fd_set *__exceptfds,
        const struct timespec *__timeout,
        const __sigset_t *__sigmask);

extern int __select (int __nfds, fd_set *__restrict __readfds,
       fd_set *__restrict __writefds,
       fd_set *__restrict __exceptfds,
       struct timeval *__restrict __timeout);
extern __typeof (__select) __select __attribute__ ((visibility ("hidden")));
# 197 "../posix/sys/types.h" 2





typedef __blksize_t blksize_t;






typedef __blkcnt_t blkcnt_t;



typedef __fsblkcnt_t fsblkcnt_t;



typedef __fsfilcnt_t fsfilcnt_t;
# 236 "../posix/sys/types.h"
typedef __blkcnt64_t blkcnt64_t;
typedef __fsblkcnt64_t fsblkcnt64_t;
typedef __fsfilcnt64_t fsfilcnt64_t;





# 1 "../sysdeps/nptl/bits/pthreadtypes.h" 1
# 23 "../sysdeps/nptl/bits/pthreadtypes.h"
# 1 "../sysdeps/nptl/bits/thread-shared-types.h" 1
# 77 "../sysdeps/nptl/bits/thread-shared-types.h"
# 1 "../sysdeps/alpha/nptl/bits/pthreadtypes-arch.h" 1
# 42 "../sysdeps/alpha/nptl/bits/pthreadtypes-arch.h"
struct __pthread_rwlock_arch_t
{
  unsigned int __readers;
  unsigned int __writers;
  unsigned int __wrphase_futex;
  unsigned int __writers_futex;
  unsigned int __pad3;
  unsigned int __pad4;
  int __cur_writer;
  int __shared;
  unsigned long int __pad1;
  unsigned long int __pad2;


  unsigned int __flags;
};
# 78 "../sysdeps/nptl/bits/thread-shared-types.h" 2




typedef struct __pthread_internal_list
{
  struct __pthread_internal_list *__prev;
  struct __pthread_internal_list *__next;
} __pthread_list_t;
# 118 "../sysdeps/nptl/bits/thread-shared-types.h"
struct __pthread_mutex_s
{
  int __lock ;
  unsigned int __count;
  int __owner;

  unsigned int __nusers;



  int __kind;
 




  int __spins;
  __pthread_list_t __list;
# 145 "../sysdeps/nptl/bits/thread-shared-types.h"
 
};




struct __pthread_cond_s
{
  __extension__ union
  {
    __extension__ unsigned long long int __wseq;
    struct
    {
      unsigned int __low;
      unsigned int __high;
    } __wseq32;
  };
  __extension__ union
  {
    __extension__ unsigned long long int __g1_start;
    struct
    {
      unsigned int __low;
      unsigned int __high;
    } __g1_start32;
  };
  unsigned int __g_refs[2] ;
  unsigned int __g_size[2];
  unsigned int __g1_orig_size;
  unsigned int __wrefs;
  unsigned int __g_signals[2];
};
# 24 "../sysdeps/nptl/bits/pthreadtypes.h" 2



typedef unsigned long int pthread_t;




typedef union
{
  char __size[4];
  int __align;
} pthread_mutexattr_t;




typedef union
{
  char __size[4];
  int __align;
} pthread_condattr_t;



typedef unsigned int pthread_key_t;



typedef int pthread_once_t;


union pthread_attr_t
{
  char __size[56];
  long int __align;
};

typedef union pthread_attr_t pthread_attr_t;




typedef union
{
  struct __pthread_mutex_s __data;
  char __size[40];
  long int __align;
} pthread_mutex_t;


typedef union
{
  struct __pthread_cond_s __data;
  char __size[48];
  __extension__ long long int __align;
} pthread_cond_t;





typedef union
{
  struct __pthread_rwlock_arch_t __data;
  char __size[56];
  long int __align;
} pthread_rwlock_t;

typedef union
{
  char __size[8];
  long int __align;
} pthread_rwlockattr_t;





typedef volatile int pthread_spinlock_t;




typedef union
{
  char __size[32];
  long int __align;
} pthread_barrier_t;

typedef union
{
  char __size[4];
  int __align;
} pthread_barrierattr_t;
# 245 "../posix/sys/types.h" 2



# 1 "../include/sys/types.h" 2
# 395 "../stdlib/stdlib.h" 2






extern long int random (void) __attribute__ ((__nothrow__ ));


extern void srandom (unsigned int __seed) __attribute__ ((__nothrow__ ));





extern char *initstate (unsigned int __seed, char *__statebuf,
   size_t __statelen) __attribute__ ((__nothrow__ )) ;



extern char *setstate (char *__statebuf) __attribute__ ((__nothrow__ )) ;







struct random_data
  {
    int32_t *fptr;
    int32_t *rptr;
    int32_t *state;
    int rand_type;
    int rand_deg;
    int rand_sep;
    int32_t *end_ptr;
  };

extern int random_r (struct random_data *__restrict __buf,
       int32_t *__restrict __result) __attribute__ ((__nothrow__ )) ;

extern int srandom_r (unsigned int __seed, struct random_data *__buf)
     __attribute__ ((__nothrow__ )) ;

extern int initstate_r (unsigned int __seed, char *__restrict __statebuf,
   size_t __statelen,
   struct random_data *__restrict __buf)
     __attribute__ ((__nothrow__ )) ;

extern int setstate_r (char *__restrict __statebuf,
         struct random_data *__restrict __buf)
     __attribute__ ((__nothrow__ )) ;





extern int rand (void) __attribute__ ((__nothrow__ ));

extern void srand (unsigned int __seed) __attribute__ ((__nothrow__ ));



extern int rand_r (unsigned int *__seed) __attribute__ ((__nothrow__ ));







extern double drand48 (void) __attribute__ ((__nothrow__ ));
extern double erand48 (unsigned short int __xsubi[3]) __attribute__ ((__nothrow__ )) ;


extern long int lrand48 (void) __attribute__ ((__nothrow__ ));
extern long int nrand48 (unsigned short int __xsubi[3])
     __attribute__ ((__nothrow__ )) ;


extern long int mrand48 (void) __attribute__ ((__nothrow__ ));
extern long int jrand48 (unsigned short int __xsubi[3])
     __attribute__ ((__nothrow__ )) ;


extern void srand48 (long int __seedval) __attribute__ ((__nothrow__ ));
extern unsigned short int *seed48 (unsigned short int __seed16v[3])
     __attribute__ ((__nothrow__ )) ;
extern void lcong48 (unsigned short int __param[7]) __attribute__ ((__nothrow__ )) ;





struct drand48_data
  {
    unsigned short int __x[3];
    unsigned short int __old_x[3];
    unsigned short int __c;
    unsigned short int __init;
    __extension__ unsigned long long int __a;

  };


extern int drand48_r (struct drand48_data *__restrict __buffer,
        double *__restrict __result) __attribute__ ((__nothrow__ )) ;
extern int erand48_r (unsigned short int __xsubi[3],
        struct drand48_data *__restrict __buffer,
        double *__restrict __result) __attribute__ ((__nothrow__ )) ;


extern int lrand48_r (struct drand48_data *__restrict __buffer,
        long int *__restrict __result)
     __attribute__ ((__nothrow__ )) ;
extern int nrand48_r (unsigned short int __xsubi[3],
        struct drand48_data *__restrict __buffer,
        long int *__restrict __result)
     __attribute__ ((__nothrow__ )) ;


extern int mrand48_r (struct drand48_data *__restrict __buffer,
        long int *__restrict __result)
     __attribute__ ((__nothrow__ )) ;
extern int jrand48_r (unsigned short int __xsubi[3],
        struct drand48_data *__restrict __buffer,
        long int *__restrict __result)
     __attribute__ ((__nothrow__ )) ;


extern int srand48_r (long int __seedval, struct drand48_data *__buffer)
     __attribute__ ((__nothrow__ )) ;

extern int seed48_r (unsigned short int __seed16v[3],
       struct drand48_data *__buffer) __attribute__ ((__nothrow__ )) ;

extern int lcong48_r (unsigned short int __param[7],
        struct drand48_data *__buffer)
     __attribute__ ((__nothrow__ )) ;




extern void *malloc (size_t __size) __attribute__ ((__nothrow__ )) __attribute__ ((__malloc__)) ;

extern void *calloc (size_t __nmemb, size_t __size)
     __attribute__ ((__nothrow__ )) __attribute__ ((__malloc__)) ;






extern void *realloc (void *__ptr, size_t __size)
     __attribute__ ((__nothrow__ )) __attribute__ ((__warn_unused_result__));







extern void *reallocarray (void *__ptr, size_t __nmemb, size_t __size)
     __attribute__ ((__nothrow__ )) __attribute__ ((__warn_unused_result__));



extern void free (void *__ptr) __attribute__ ((__nothrow__ ));


# 1 "../include/alloca.h" 1


# 1 "../stdlib/alloca.h" 1
# 24 "../stdlib/alloca.h"
# 1 "/scratch/jmyers/glibc/many9/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/include/stddef.h" 1 3 4
# 25 "../stdlib/alloca.h" 2







extern void *alloca (size_t __size) __attribute__ ((__nothrow__ ));






# 4 "../include/alloca.h" 2



# 1 "../include/stackinfo.h" 1
# 24 "../include/stackinfo.h"
# 1 "../sysdeps/alpha/stackinfo.h" 1
# 24 "../sysdeps/alpha/stackinfo.h"
# 1 "../include/elf.h" 1

# 1 "../elf/elf.h" 1
# 24 "../elf/elf.h"




# 1 "../sysdeps/generic/stdint.h" 1
# 26 "../sysdeps/generic/stdint.h"
# 1 "../bits/libc-header-start.h" 1
# 27 "../sysdeps/generic/stdint.h" 2
# 1 "../include/bits/types.h" 1
# 28 "../sysdeps/generic/stdint.h" 2
# 1 "../bits/wchar.h" 1
# 29 "../sysdeps/generic/stdint.h" 2
# 1 "../sysdeps/unix/sysv/linux/alpha/bits/wordsize.h" 1
# 30 "../sysdeps/generic/stdint.h" 2







# 1 "../bits/stdint-uintn.h" 1
# 22 "../bits/stdint-uintn.h"
# 1 "../include/bits/types.h" 1
# 23 "../bits/stdint-uintn.h" 2

typedef __uint8_t uint8_t;
typedef __uint16_t uint16_t;
typedef __uint32_t uint32_t;
typedef __uint64_t uint64_t;
# 38 "../sysdeps/generic/stdint.h" 2





typedef __int_least8_t int_least8_t;
typedef __int_least16_t int_least16_t;
typedef __int_least32_t int_least32_t;
typedef __int_least64_t int_least64_t;


typedef __uint_least8_t uint_least8_t;
typedef __uint_least16_t uint_least16_t;
typedef __uint_least32_t uint_least32_t;
typedef __uint_least64_t uint_least64_t;





typedef signed char int_fast8_t;

typedef long int int_fast16_t;
typedef long int int_fast32_t;
typedef long int int_fast64_t;
# 71 "../sysdeps/generic/stdint.h"
typedef unsigned char uint_fast8_t;

typedef unsigned long int uint_fast16_t;
typedef unsigned long int uint_fast32_t;
typedef unsigned long int uint_fast64_t;
# 87 "../sysdeps/generic/stdint.h"
typedef long int intptr_t;


typedef unsigned long int uintptr_t;
# 101 "../sysdeps/generic/stdint.h"
typedef __intmax_t intmax_t;
typedef __uintmax_t uintmax_t;
# 29 "../elf/elf.h" 2


typedef uint16_t Elf32_Half;
typedef uint16_t Elf64_Half;


typedef uint32_t Elf32_Word;
typedef int32_t Elf32_Sword;
typedef uint32_t Elf64_Word;
typedef int32_t Elf64_Sword;


typedef uint64_t Elf32_Xword;
typedef int64_t Elf32_Sxword;
typedef uint64_t Elf64_Xword;
typedef int64_t Elf64_Sxword;


typedef uint32_t Elf32_Addr;
typedef uint64_t Elf64_Addr;


typedef uint32_t Elf32_Off;
typedef uint64_t Elf64_Off;


typedef uint16_t Elf32_Section;
typedef uint16_t Elf64_Section;


typedef Elf32_Half Elf32_Versym;
typedef Elf64_Half Elf64_Versym;






typedef struct
{
  unsigned char e_ident[(16)];
  Elf32_Half e_type;
  Elf32_Half e_machine;
  Elf32_Word e_version;
  Elf32_Addr e_entry;
  Elf32_Off e_phoff;
  Elf32_Off e_shoff;
  Elf32_Word e_flags;
  Elf32_Half e_ehsize;
  Elf32_Half e_phentsize;
  Elf32_Half e_phnum;
  Elf32_Half e_shentsize;
  Elf32_Half e_shnum;
  Elf32_Half e_shstrndx;
} Elf32_Ehdr;

typedef struct
{
  unsigned char e_ident[(16)];
  Elf64_Half e_type;
  Elf64_Half e_machine;
  Elf64_Word e_version;
  Elf64_Addr e_entry;
  Elf64_Off e_phoff;
  Elf64_Off e_shoff;
  Elf64_Word e_flags;
  Elf64_Half e_ehsize;
  Elf64_Half e_phentsize;
  Elf64_Half e_phnum;
  Elf64_Half e_shentsize;
  Elf64_Half e_shnum;
  Elf64_Half e_shstrndx;
} Elf64_Ehdr;
# 384 "../elf/elf.h"
typedef struct
{
  Elf32_Word sh_name;
  Elf32_Word sh_type;
  Elf32_Word sh_flags;
  Elf32_Addr sh_addr;
  Elf32_Off sh_offset;
  Elf32_Word sh_size;
  Elf32_Word sh_link;
  Elf32_Word sh_info;
  Elf32_Word sh_addralign;
  Elf32_Word sh_entsize;
} Elf32_Shdr;

typedef struct
{
  Elf64_Word sh_name;
  Elf64_Word sh_type;
  Elf64_Xword sh_flags;
  Elf64_Addr sh_addr;
  Elf64_Off sh_offset;
  Elf64_Xword sh_size;
  Elf64_Word sh_link;
  Elf64_Word sh_info;
  Elf64_Xword sh_addralign;
  Elf64_Xword sh_entsize;
} Elf64_Shdr;
# 491 "../elf/elf.h"
typedef struct
{
  Elf32_Word ch_type;
  Elf32_Word ch_size;
  Elf32_Word ch_addralign;
} Elf32_Chdr;

typedef struct
{
  Elf64_Word ch_type;
  Elf64_Word ch_reserved;
  Elf64_Xword ch_size;
  Elf64_Xword ch_addralign;
} Elf64_Chdr;
# 518 "../elf/elf.h"
typedef struct
{
  Elf32_Word st_name;
  Elf32_Addr st_value;
  Elf32_Word st_size;
  unsigned char st_info;
  unsigned char st_other;
  Elf32_Section st_shndx;
} Elf32_Sym;

typedef struct
{
  Elf64_Word st_name;
  unsigned char st_info;
  unsigned char st_other;
  Elf64_Section st_shndx;
  Elf64_Addr st_value;
  Elf64_Xword st_size;
} Elf64_Sym;




typedef struct
{
  Elf32_Half si_boundto;
  Elf32_Half si_flags;
} Elf32_Syminfo;

typedef struct
{
  Elf64_Half si_boundto;
  Elf64_Half si_flags;
} Elf64_Syminfo;
# 633 "../elf/elf.h"
typedef struct
{
  Elf32_Addr r_offset;
  Elf32_Word r_info;
} Elf32_Rel;






typedef struct
{
  Elf64_Addr r_offset;
  Elf64_Xword r_info;
} Elf64_Rel;



typedef struct
{
  Elf32_Addr r_offset;
  Elf32_Word r_info;
  Elf32_Sword r_addend;
} Elf32_Rela;

typedef struct
{
  Elf64_Addr r_offset;
  Elf64_Xword r_info;
  Elf64_Sxword r_addend;
} Elf64_Rela;
# 678 "../elf/elf.h"
typedef struct
{
  Elf32_Word p_type;
  Elf32_Off p_offset;
  Elf32_Addr p_vaddr;
  Elf32_Addr p_paddr;
  Elf32_Word p_filesz;
  Elf32_Word p_memsz;
  Elf32_Word p_flags;
  Elf32_Word p_align;
} Elf32_Phdr;

typedef struct
{
  Elf64_Word p_type;
  Elf64_Word p_flags;
  Elf64_Off p_offset;
  Elf64_Addr p_vaddr;
  Elf64_Addr p_paddr;
  Elf64_Xword p_filesz;
  Elf64_Xword p_memsz;
  Elf64_Xword p_align;
} Elf64_Phdr;
# 819 "../elf/elf.h"
typedef struct
{
  Elf32_Sword d_tag;
  union
    {
      Elf32_Word d_val;
      Elf32_Addr d_ptr;
    } d_un;
} Elf32_Dyn;

typedef struct
{
  Elf64_Sxword d_tag;
  union
    {
      Elf64_Xword d_val;
      Elf64_Addr d_ptr;
    } d_un;
} Elf64_Dyn;
# 998 "../elf/elf.h"
typedef struct
{
  Elf32_Half vd_version;
  Elf32_Half vd_flags;
  Elf32_Half vd_ndx;
  Elf32_Half vd_cnt;
  Elf32_Word vd_hash;
  Elf32_Word vd_aux;
  Elf32_Word vd_next;

} Elf32_Verdef;

typedef struct
{
  Elf64_Half vd_version;
  Elf64_Half vd_flags;
  Elf64_Half vd_ndx;
  Elf64_Half vd_cnt;
  Elf64_Word vd_hash;
  Elf64_Word vd_aux;
  Elf64_Word vd_next;

} Elf64_Verdef;
# 1040 "../elf/elf.h"
typedef struct
{
  Elf32_Word vda_name;
  Elf32_Word vda_next;

} Elf32_Verdaux;

typedef struct
{
  Elf64_Word vda_name;
  Elf64_Word vda_next;

} Elf64_Verdaux;




typedef struct
{
  Elf32_Half vn_version;
  Elf32_Half vn_cnt;
  Elf32_Word vn_file;

  Elf32_Word vn_aux;
  Elf32_Word vn_next;

} Elf32_Verneed;

typedef struct
{
  Elf64_Half vn_version;
  Elf64_Half vn_cnt;
  Elf64_Word vn_file;

  Elf64_Word vn_aux;
  Elf64_Word vn_next;

} Elf64_Verneed;
# 1087 "../elf/elf.h"
typedef struct
{
  Elf32_Word vna_hash;
  Elf32_Half vna_flags;
  Elf32_Half vna_other;
  Elf32_Word vna_name;
  Elf32_Word vna_next;

} Elf32_Vernaux;

typedef struct
{
  Elf64_Word vna_hash;
  Elf64_Half vna_flags;
  Elf64_Half vna_other;
  Elf64_Word vna_name;
  Elf64_Word vna_next;

} Elf64_Vernaux;
# 1121 "../elf/elf.h"
typedef struct
{
  uint32_t a_type;
  union
    {
      uint32_t a_val;



    } a_un;
} Elf32_auxv_t;

typedef struct
{
  uint64_t a_type;
  union
    {
      uint64_t a_val;



    } a_un;
} Elf64_auxv_t;
# 1220 "../elf/elf.h"
typedef struct
{
  Elf32_Word n_namesz;
  Elf32_Word n_descsz;
  Elf32_Word n_type;
} Elf32_Nhdr;

typedef struct
{
  Elf64_Word n_namesz;
  Elf64_Word n_descsz;
  Elf64_Word n_type;
} Elf64_Nhdr;
# 1340 "../elf/elf.h"
typedef struct
{
  Elf32_Xword m_value;
  Elf32_Word m_info;
  Elf32_Word m_poffset;
  Elf32_Half m_repeat;
  Elf32_Half m_stride;
} Elf32_Move;

typedef struct
{
  Elf64_Xword m_value;
  Elf64_Xword m_info;
  Elf64_Xword m_poffset;
  Elf64_Half m_repeat;
  Elf64_Half m_stride;
} Elf64_Move;
# 1729 "../elf/elf.h"
typedef union
{
  struct
    {
      Elf32_Word gt_current_g_value;
      Elf32_Word gt_unused;
    } gt_header;
  struct
    {
      Elf32_Word gt_g_value;
      Elf32_Word gt_bytes;
    } gt_entry;
} Elf32_gptab;



typedef struct
{
  Elf32_Word ri_gprmask;
  Elf32_Word ri_cprmask[4];
  Elf32_Sword ri_gp_value;
} Elf32_RegInfo;



typedef struct
{
  unsigned char kind;

  unsigned char size;
  Elf32_Section section;

  Elf32_Word info;
} Elf_Options;
# 1805 "../elf/elf.h"
typedef struct
{
  Elf32_Word hwp_flags1;
  Elf32_Word hwp_flags2;
} Elf_Options_Hw;
# 1971 "../elf/elf.h"
typedef struct
{
  Elf32_Word l_name;
  Elf32_Word l_time_stamp;
  Elf32_Word l_checksum;
  Elf32_Word l_version;
  Elf32_Word l_flags;
} Elf32_Lib;

typedef struct
{
  Elf64_Word l_name;
  Elf64_Word l_time_stamp;
  Elf64_Word l_checksum;
  Elf64_Word l_version;
  Elf64_Word l_flags;
} Elf64_Lib;
# 2002 "../elf/elf.h"
typedef Elf32_Addr Elf32_Conflict;

typedef struct
{

  Elf32_Half version;

  unsigned char isa_level;

  unsigned char isa_rev;

  unsigned char gpr_size;

  unsigned char cpr1_size;

  unsigned char cpr2_size;

  unsigned char fp_abi;

  Elf32_Word isa_ext;

  Elf32_Word ases;

  Elf32_Word flags1;
  Elf32_Word flags2;
} Elf_MIPS_ABIFlags_v0;
# 2078 "../elf/elf.h"
enum
{

  Val_GNU_MIPS_ABI_FP_ANY = 0,

  Val_GNU_MIPS_ABI_FP_DOUBLE = 1,

  Val_GNU_MIPS_ABI_FP_SINGLE = 2,

  Val_GNU_MIPS_ABI_FP_SOFT = 3,

  Val_GNU_MIPS_ABI_FP_OLD_64 = 4,

  Val_GNU_MIPS_ABI_FP_XX = 5,

  Val_GNU_MIPS_ABI_FP_64 = 6,

  Val_GNU_MIPS_ABI_FP_64A = 7,

  Val_GNU_MIPS_ABI_FP_MAX = 7
};
# 3928 "../elf/elf.h"

# 3 "../include/elf.h" 2



# 1 "../include/libc-pointer-arith.h" 1
# 7 "../include/elf.h" 2
# 20 "../include/elf.h"
# 1 "../sysdeps/alpha/dl-dtprocnum.h" 1
# 21 "../include/elf.h" 2
# 25 "../sysdeps/alpha/stackinfo.h" 2
# 25 "../include/stackinfo.h" 2
# 8 "../include/alloca.h" 2




extern void *__alloca (size_t __size);





extern int __libc_use_alloca (size_t size) __attribute__ ((const));
extern int __libc_alloca_cutoff (size_t size) __attribute__ ((const));
extern __typeof (__libc_alloca_cutoff) __libc_alloca_cutoff __attribute__ ((visibility ("hidden")));



# 1 "../sysdeps/pthread/allocalim.h" 1
# 19 "../sysdeps/pthread/allocalim.h"
# 1 "../include/alloca.h" 1
# 20 "../sysdeps/pthread/allocalim.h" 2
# 1 "../include/limits.h" 1
# 26 "../include/limits.h"
# 1 "../bits/libc-header-start.h" 1
# 27 "../include/limits.h" 2
# 124 "../include/limits.h"
# 1 "/scratch/jmyers/glibc/many9/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/include-fixed/limits.h" 1 3 4
# 125 "../include/limits.h" 2
# 183 "../include/limits.h"
# 1 "../include/bits/posix1_lim.h" 1
# 1 "../posix/bits/posix1_lim.h" 1
# 27 "../posix/bits/posix1_lim.h"
# 1 "../sysdeps/unix/sysv/linux/alpha/bits/wordsize.h" 1
# 28 "../posix/bits/posix1_lim.h" 2
# 161 "../posix/bits/posix1_lim.h"
# 1 "../sysdeps/unix/sysv/linux/alpha/bits/local_lim.h" 1
# 38 "../sysdeps/unix/sysv/linux/alpha/bits/local_lim.h"
# 1 "/scratch/jmyers/glibc/many9/install/compilers/alpha-linux-gnu/sysroot/usr/include/linux/limits.h" 1 3 4
# 39 "../sysdeps/unix/sysv/linux/alpha/bits/local_lim.h" 2
# 162 "../posix/bits/posix1_lim.h" 2
# 1 "../include/bits/posix1_lim.h" 2
# 184 "../include/limits.h" 2



# 1 "../include/bits/posix2_lim.h" 1
# 1 "../posix/bits/posix2_lim.h" 1
# 1 "../include/bits/posix2_lim.h" 2
# 188 "../include/limits.h" 2



# 1 "../include/bits/xopen_lim.h" 1
# 64 "../include/bits/xopen_lim.h"
# 1 "../sysdeps/unix/sysv/linux/bits/uio_lim.h" 1
# 65 "../include/bits/xopen_lim.h" 2
# 192 "../include/limits.h" 2
# 21 "../sysdeps/pthread/allocalim.h" 2


extern __inline __attribute__ ((__always_inline__))
int
__libc_use_alloca (size_t size)
{
  return (__builtin_expect ((__libc_alloca_cutoff (size)), 1)

          || __builtin_expect ((size <= 24576 / 4), 1)

   );
}
# 25 "../include/alloca.h" 2
# 567 "../stdlib/stdlib.h" 2





extern void *valloc (size_t __size) __attribute__ ((__nothrow__ )) __attribute__ ((__malloc__)) ;




extern int posix_memalign (void **__memptr, size_t __alignment, size_t __size)
     __attribute__ ((__nothrow__ )) ;




extern void *aligned_alloc (size_t __alignment, size_t __size)
     __attribute__ ((__nothrow__ )) __attribute__ ((__malloc__)) __attribute__ ((__alloc_size__ (2))) ;



extern void abort (void) __attribute__ ((__nothrow__ )) __attribute__ ((__noreturn__));



extern int atexit (void (*__func) (void)) __attribute__ ((__nothrow__ )) ;







extern int at_quick_exit (void (*__func) (void)) __attribute__ ((__nothrow__ )) ;






extern int on_exit (void (*__func) (int __status, void *__arg), void *__arg)
     __attribute__ ((__nothrow__ )) ;





extern void exit (int __status) __attribute__ ((__nothrow__ )) __attribute__ ((__noreturn__));





extern void quick_exit (int __status) __attribute__ ((__nothrow__ )) __attribute__ ((__noreturn__));





extern void _Exit (int __status) __attribute__ ((__nothrow__ )) __attribute__ ((__noreturn__));




extern char *getenv (const char *__name) __attribute__ ((__nothrow__ )) ;




extern char *secure_getenv (const char *__name)
     __attribute__ ((__nothrow__ )) ;






extern int putenv (char *__string) __attribute__ ((__nothrow__ )) ;





extern int setenv (const char *__name, const char *__value, int __replace)
     __attribute__ ((__nothrow__ )) ;


extern int unsetenv (const char *__name) __attribute__ ((__nothrow__ )) ;






extern int clearenv (void) __attribute__ ((__nothrow__ ));
# 672 "../stdlib/stdlib.h"
extern char *mktemp (char *__template) __attribute__ ((__nothrow__ )) ;
# 685 "../stdlib/stdlib.h"
extern int mkstemp (char *__template) ;
# 695 "../stdlib/stdlib.h"
extern int mkstemp64 (char *__template) ;
# 707 "../stdlib/stdlib.h"
extern int mkstemps (char *__template, int __suffixlen) ;
# 717 "../stdlib/stdlib.h"
extern int mkstemps64 (char *__template, int __suffixlen)
     ;
# 728 "../stdlib/stdlib.h"
extern char *mkdtemp (char *__template) __attribute__ ((__nothrow__ )) ;
# 739 "../stdlib/stdlib.h"
extern int mkostemp (char *__template, int __flags) ;
# 749 "../stdlib/stdlib.h"
extern int mkostemp64 (char *__template, int __flags) ;
# 759 "../stdlib/stdlib.h"
extern int mkostemps (char *__template, int __suffixlen, int __flags)
     ;
# 771 "../stdlib/stdlib.h"
extern int mkostemps64 (char *__template, int __suffixlen, int __flags)
     ;
# 781 "../stdlib/stdlib.h"
extern int system (const char *__command) ;





extern char *canonicalize_file_name (const char *__name)
     __attribute__ ((__nothrow__ )) ;
# 797 "../stdlib/stdlib.h"
extern char *realpath (const char *__restrict __name,
         char *__restrict __resolved) __attribute__ ((__nothrow__ )) ;






typedef int (*__compar_fn_t) (const void *, const void *);


typedef __compar_fn_t comparison_fn_t;



typedef int (*__compar_d_fn_t) (const void *, const void *, void *);




extern void *bsearch (const void *__key, const void *__base,
        size_t __nmemb, size_t __size, __compar_fn_t __compar)
     ;


# 1 "../bits/stdlib-bsearch.h" 1
# 19 "../bits/stdlib-bsearch.h"
extern __inline void *
bsearch (const void *__key, const void *__base, size_t __nmemb, size_t __size,
  __compar_fn_t __compar)
{
  size_t __l, __u, __idx;
  const void *__p;
  int __comparison;

  __l = 0;
  __u = __nmemb;
  while (__l < __u)
    {
      __idx = (__l + __u) / 2;
      __p = (void *) (((const char *) __base) + (__idx * __size));
      __comparison = (*__compar) (__key, __p);
      if (__comparison < 0)
 __u = __idx;
      else if (__comparison > 0)
 __l = __idx + 1;
      else
 return (void *) __p;
    }

  return 
# 42 "../bits/stdlib-bsearch.h" 3 4
        ((void *)0)
# 42 "../bits/stdlib-bsearch.h"
            ;
}
# 823 "../stdlib/stdlib.h" 2




extern void qsort (void *__base, size_t __nmemb, size_t __size,
     __compar_fn_t __compar) ;

extern void qsort_r (void *__base, size_t __nmemb, size_t __size,
       __compar_d_fn_t __compar, void *__arg)
  ;




extern int abs (int __x) __attribute__ ((__nothrow__ )) __attribute__ ((__const__)) ;
extern long int labs (long int __x) __attribute__ ((__nothrow__ )) __attribute__ ((__const__)) ;


__extension__ extern long long int llabs (long long int __x)
     __attribute__ ((__nothrow__ )) __attribute__ ((__const__)) ;






extern div_t div (int __numer, int __denom)
     __attribute__ ((__nothrow__ )) __attribute__ ((__const__)) ;
extern ldiv_t ldiv (long int __numer, long int __denom)
     __attribute__ ((__nothrow__ )) __attribute__ ((__const__)) ;


__extension__ extern lldiv_t lldiv (long long int __numer,
        long long int __denom)
     __attribute__ ((__nothrow__ )) __attribute__ ((__const__)) ;
# 869 "../stdlib/stdlib.h"
extern char *ecvt (double __value, int __ndigit, int *__restrict __decpt,
     int *__restrict __sign) __attribute__ ((__nothrow__ )) ;




extern char *fcvt (double __value, int __ndigit, int *__restrict __decpt,
     int *__restrict __sign) __attribute__ ((__nothrow__ )) ;




extern char *gcvt (double __value, int __ndigit, char *__buf)
     __attribute__ ((__nothrow__ )) ;




extern char *qecvt (long double __value, int __ndigit,
      int *__restrict __decpt, int *__restrict __sign)
     __attribute__ ((__nothrow__ )) ;
extern char *qfcvt (long double __value, int __ndigit,
      int *__restrict __decpt, int *__restrict __sign)
     __attribute__ ((__nothrow__ )) ;
extern char *qgcvt (long double __value, int __ndigit, char *__buf)
     __attribute__ ((__nothrow__ )) ;




extern int ecvt_r (double __value, int __ndigit, int *__restrict __decpt,
     int *__restrict __sign, char *__restrict __buf,
     size_t __len) __attribute__ ((__nothrow__ )) ;
extern int fcvt_r (double __value, int __ndigit, int *__restrict __decpt,
     int *__restrict __sign, char *__restrict __buf,
     size_t __len) __attribute__ ((__nothrow__ )) ;

extern int qecvt_r (long double __value, int __ndigit,
      int *__restrict __decpt, int *__restrict __sign,
      char *__restrict __buf, size_t __len)
     __attribute__ ((__nothrow__ )) ;
extern int qfcvt_r (long double __value, int __ndigit,
      int *__restrict __decpt, int *__restrict __sign,
      char *__restrict __buf, size_t __len)
     __attribute__ ((__nothrow__ )) ;





extern int mblen (const char *__s, size_t __n) __attribute__ ((__nothrow__ ));


extern int mbtowc (wchar_t *__restrict __pwc,
     const char *__restrict __s, size_t __n) __attribute__ ((__nothrow__ ));


extern int wctomb (char *__s, wchar_t __wchar) __attribute__ ((__nothrow__ ));



extern size_t mbstowcs (wchar_t *__restrict __pwcs,
   const char *__restrict __s, size_t __n) __attribute__ ((__nothrow__ ));

extern size_t wcstombs (char *__restrict __s,
   const wchar_t *__restrict __pwcs, size_t __n)
     __attribute__ ((__nothrow__ ));







extern int rpmatch (const char *__response) __attribute__ ((__nothrow__ )) ;
# 954 "../stdlib/stdlib.h"
extern int getsubopt (char **__restrict __optionp,
        char *const *__restrict __tokens,
        char **__restrict __valuep)
     __attribute__ ((__nothrow__ )) ;







extern int posix_openpt (int __oflag) ;







extern int grantpt (int __fd) __attribute__ ((__nothrow__ ));



extern int unlockpt (int __fd) __attribute__ ((__nothrow__ ));




extern char *ptsname (int __fd) __attribute__ ((__nothrow__ )) ;






extern int ptsname_r (int __fd, char *__buf, size_t __buflen)
     __attribute__ ((__nothrow__ )) ;


extern int getpt (void);






extern int getloadavg (double __loadavg[], int __nelem)
     __attribute__ ((__nothrow__ )) ;
# 1010 "../stdlib/stdlib.h"
# 1 "../include/bits/stdlib-float.h" 1





# 1 "../stdlib/bits/stdlib-float.h" 1
# 24 "../stdlib/bits/stdlib-float.h"
extern __inline double
__attribute__ ((__nothrow__ )) atof (const char *__nptr)
{
  return strtod (__nptr, (char **) 
# 27 "../stdlib/bits/stdlib-float.h" 3 4
                                  ((void *)0)
# 27 "../stdlib/bits/stdlib-float.h"
                                      );
}
# 7 "../include/bits/stdlib-float.h" 2
# 1011 "../stdlib/stdlib.h" 2
# 1020 "../stdlib/stdlib.h"

# 7 "../include/stdlib.h" 2



# 1 "../include/sys/stat.h" 1

# 1 "../io/sys/stat.h" 1
# 27 "../io/sys/stat.h"
# 1 "../include/bits/types.h" 1
# 28 "../io/sys/stat.h" 2


# 1 "../include/bits/types/struct_timespec.h" 1
# 31 "../io/sys/stat.h" 2






# 1 "../include/bits/types/time_t.h" 1
# 38 "../io/sys/stat.h" 2
# 99 "../io/sys/stat.h"


# 1 "../sysdeps/unix/sysv/linux/alpha/bits/stat.h" 1
# 69 "../sysdeps/unix/sysv/linux/alpha/bits/stat.h"
struct stat
  {
    __dev_t st_dev;



    __ino_t st_ino;
    int __pad0;

    __dev_t st_rdev;
    __off_t st_size;



    __blkcnt_t st_blocks;
    int __pad1;

    __mode_t st_mode;
    __uid_t st_uid;
    __gid_t st_gid;
    __blksize_t st_blksize;
    __nlink_t st_nlink;
    int __pad2;
    __extension__ union { struct timespec st_atim; struct { __time_t st_atime; unsigned long st_atimensec; }; };
    __extension__ union { struct timespec st_mtim; struct { __time_t st_mtime; unsigned long st_mtimensec; }; };
    __extension__ union { struct timespec st_ctim; struct { __time_t st_ctime; unsigned long st_ctimensec; }; };
    long __glibc_reserved[3];
  };



struct stat64
  {
    __dev_t st_dev;
    __ino64_t st_ino;
    __dev_t st_rdev;
    __off_t st_size;
    __blkcnt64_t st_blocks;
    __mode_t st_mode;
    __uid_t st_uid;
    __gid_t st_gid;
    __blksize_t st_blksize;
    __nlink_t st_nlink;
    int __pad0;
    __extension__ union { struct timespec st_atim; struct { __time_t st_atime; unsigned long st_atimensec; }; };
    __extension__ union { struct timespec st_mtim; struct { __time_t st_mtime; unsigned long st_mtimensec; }; };
    __extension__ union { struct timespec st_ctim; struct { __time_t st_ctime; unsigned long st_ctimensec; }; };
    long __glibc_reserved[3];
  };
# 102 "../io/sys/stat.h" 2
# 205 "../io/sys/stat.h"
extern int stat (const char *__restrict __file,
   struct stat *__restrict __buf) __attribute__ ((__nothrow__ )) ;



extern int fstat (int __fd, struct stat *__buf) __attribute__ ((__nothrow__ )) ;
# 224 "../io/sys/stat.h"
extern int stat64 (const char *__restrict __file,
     struct stat64 *__restrict __buf) __attribute__ ((__nothrow__ )) ;
extern int fstat64 (int __fd, struct stat64 *__buf) __attribute__ ((__nothrow__ )) ;







extern int fstatat (int __fd, const char *__restrict __file,
      struct stat *__restrict __buf, int __flag)
     __attribute__ ((__nothrow__ )) ;
# 249 "../io/sys/stat.h"
extern int fstatat64 (int __fd, const char *__restrict __file,
        struct stat64 *__restrict __buf, int __flag)
     __attribute__ ((__nothrow__ )) ;







extern int lstat (const char *__restrict __file,
    struct stat *__restrict __buf) __attribute__ ((__nothrow__ )) ;
# 272 "../io/sys/stat.h"
extern int lstat64 (const char *__restrict __file,
      struct stat64 *__restrict __buf)
     __attribute__ ((__nothrow__ )) ;





extern int chmod (const char *__file, __mode_t __mode)
     __attribute__ ((__nothrow__ )) ;





extern int lchmod (const char *__file, __mode_t __mode)
     __attribute__ ((__nothrow__ )) ;




extern int fchmod (int __fd, __mode_t __mode) __attribute__ ((__nothrow__ ));





extern int fchmodat (int __fd, const char *__file, __mode_t __mode,
       int __flag)
     __attribute__ ((__nothrow__ )) ;






extern __mode_t umask (__mode_t __mask) __attribute__ ((__nothrow__ ));




extern __mode_t getumask (void) __attribute__ ((__nothrow__ ));



extern int mkdir (const char *__path, __mode_t __mode)
     __attribute__ ((__nothrow__ )) ;





extern int mkdirat (int __fd, const char *__path, __mode_t __mode)
     __attribute__ ((__nothrow__ )) ;






extern int mknod (const char *__path, __mode_t __mode, __dev_t __dev)
     __attribute__ ((__nothrow__ )) ;





extern int mknodat (int __fd, const char *__path, __mode_t __mode,
      __dev_t __dev) __attribute__ ((__nothrow__ )) ;





extern int mkfifo (const char *__path, __mode_t __mode)
     __attribute__ ((__nothrow__ )) ;





extern int mkfifoat (int __fd, const char *__path, __mode_t __mode)
     __attribute__ ((__nothrow__ )) ;





extern int utimensat (int __fd, const char *__path,
        const struct timespec __times[2],
        int __flags)
     __attribute__ ((__nothrow__ )) ;




extern int futimens (int __fd, const struct timespec __times[2]) __attribute__ ((__nothrow__ ));
# 395 "../io/sys/stat.h"
extern int __fxstat (int __ver, int __fildes, struct stat *__stat_buf)
     __attribute__ ((__nothrow__ )) ;
extern int __xstat (int __ver, const char *__filename,
      struct stat *__stat_buf) __attribute__ ((__nothrow__ )) ;
extern int __lxstat (int __ver, const char *__filename,
       struct stat *__stat_buf) __attribute__ ((__nothrow__ )) ;
extern int __fxstatat (int __ver, int __fildes, const char *__filename,
         struct stat *__stat_buf, int __flag)
     __attribute__ ((__nothrow__ )) ;
# 428 "../io/sys/stat.h"
extern int __fxstat64 (int __ver, int __fildes, struct stat64 *__stat_buf)
     __attribute__ ((__nothrow__ )) ;
extern int __xstat64 (int __ver, const char *__filename,
        struct stat64 *__stat_buf) __attribute__ ((__nothrow__ )) ;
extern int __lxstat64 (int __ver, const char *__filename,
         struct stat64 *__stat_buf) __attribute__ ((__nothrow__ )) ;
extern int __fxstatat64 (int __ver, int __fildes, const char *__filename,
    struct stat64 *__stat_buf, int __flag)
     __attribute__ ((__nothrow__ )) ;

extern int __xmknod (int __ver, const char *__path, __mode_t __mode,
       __dev_t *__dev) __attribute__ ((__nothrow__ )) ;

extern int __xmknodat (int __ver, int __fd, const char *__path,
         __mode_t __mode, __dev_t *__dev)
     __attribute__ ((__nothrow__ )) ;


# 1 "../include/bits/statx.h" 1
# 1 "../io/bits/statx.h" 1
# 25 "../io/bits/statx.h"
struct statx_timestamp
{
  __int64_t tv_sec;
  __uint32_t tv_nsec;
  __int32_t __statx_timestamp_pad1[1];
};





struct statx
{
  __uint32_t stx_mask;
  __uint32_t stx_blksize;
  __uint64_t stx_attributes;
  __uint32_t stx_nlink;
  __uint32_t stx_uid;
  __uint32_t stx_gid;
  __uint16_t stx_mode;
  __uint16_t __statx_pad1[1];
  __uint64_t stx_ino;
  __uint64_t stx_size;
  __uint64_t stx_blocks;
  __uint64_t stx_attributes_mask;
  struct statx_timestamp stx_atime;
  struct statx_timestamp stx_btime;
  struct statx_timestamp stx_ctime;
  struct statx_timestamp stx_mtime;
  __uint32_t stx_rdev_major;
  __uint32_t stx_rdev_minor;
  __uint32_t stx_dev_major;
  __uint32_t stx_dev_minor;
  __uint64_t __statx_pad2[14];
};
# 84 "../io/bits/statx.h"



int statx (int __dirfd, const char *__restrict __path, int __flags,
           unsigned int __mask, struct statx *__restrict __buf)
  __attribute__ ((__nothrow__ )) ;


# 1 "../include/bits/statx.h" 2
# 447 "../io/sys/stat.h" 2





extern __inline int
__attribute__ ((__nothrow__ )) stat (const char *__path, struct stat *__statbuf)
{
  return __xstat (3, __path, __statbuf);
}


extern __inline int
__attribute__ ((__nothrow__ )) lstat (const char *__path, struct stat *__statbuf)
{
  return __lxstat (3, __path, __statbuf);
}


extern __inline int
__attribute__ ((__nothrow__ )) fstat (int __fd, struct stat *__statbuf)
{
  return __fxstat (3, __fd, __statbuf);
}


extern __inline int
__attribute__ ((__nothrow__ )) fstatat (int __fd, const char *__filename, struct stat *__statbuf, int __flag)

{
  return __fxstatat (3, __fd, __filename, __statbuf, __flag);
}



extern __inline int
__attribute__ ((__nothrow__ )) mknod (const char *__path, __mode_t __mode, __dev_t __dev)
{
  return __xmknod (0, __path, __mode, &__dev);
}



extern __inline int
__attribute__ ((__nothrow__ )) mknodat (int __fd, const char *__path, __mode_t __mode, __dev_t __dev)

{
  return __xmknodat (0, __fd, __path, __mode, &__dev);
}





extern __inline int
__attribute__ ((__nothrow__ )) stat64 (const char *__path, struct stat64 *__statbuf)
{
  return __xstat64 (3, __path, __statbuf);
}


extern __inline int
__attribute__ ((__nothrow__ )) lstat64 (const char *__path, struct stat64 *__statbuf)
{
  return __lxstat64 (3, __path, __statbuf);
}


extern __inline int
__attribute__ ((__nothrow__ )) fstat64 (int __fd, struct stat64 *__statbuf)
{
  return __fxstat64 (3, __fd, __statbuf);
}


extern __inline int
__attribute__ ((__nothrow__ )) fstatat64 (int __fd, const char *__filename, struct stat64 *__statbuf, int __flag)

{
  return __fxstatat64 (3, __fd, __filename, __statbuf, __flag);
}







# 3 "../include/sys/stat.h" 2



extern int __stat (const char *__file, struct stat *__buf);
extern int __fstat (int __fd, struct stat *__buf);
extern int __lstat (const char *__file, struct stat *__buf);
extern int __chmod (const char *__file, __mode_t __mode);
extern __typeof (__chmod) __chmod __attribute__ ((visibility ("hidden")));
extern int __fchmod (int __fd, __mode_t __mode);
extern __mode_t __umask (__mode_t __mask);
extern int __mkdir (const char *__path, __mode_t __mode);
extern __typeof (__mkdir) __mkdir __attribute__ ((visibility ("hidden")));
extern int __mknod (const char *__path,
      __mode_t __mode, __dev_t __dev);

extern __typeof (__fxstat) __fxstat __attribute__ ((visibility ("hidden")));
extern __typeof (__fxstat64) __fxstat64 __attribute__ ((visibility ("hidden")));
extern __typeof (__lxstat) __lxstat __attribute__ ((visibility ("hidden")));
extern __typeof (__lxstat64) __lxstat64 __attribute__ ((visibility ("hidden")));
extern __typeof (__xstat) __xstat __attribute__ ((visibility ("hidden")));
extern __typeof (__xstat64) __xstat64 __attribute__ ((visibility ("hidden")));

extern __inline__ int __stat (const char *__path, struct stat *__statbuf)
{
  return __xstat (3, __path, __statbuf);
}
extern __typeof (__xmknod) __xmknod __attribute__ ((visibility ("hidden")));
extern __inline__ int __mknod (const char *__path, __mode_t __mode,
          __dev_t __dev)
{
  return __xmknod (0, __path, __mode, &__dev);
}
extern __typeof (__xmknodat) __xmknodat __attribute__ ((visibility ("hidden")));

extern __typeof (__fxstatat) __fxstatat __attribute__ ((visibility ("hidden")));
extern __typeof (__fxstatat64) __fxstatat64 __attribute__ ((visibility ("hidden")));
# 11 "../include/stdlib.h" 2

extern __typeof (strtol_l) __strtol_l;
extern __typeof (strtoul_l) __strtoul_l;
extern __typeof (strtoll_l) __strtoll_l;
extern __typeof (strtoull_l) __strtoull_l;
extern __typeof (strtod_l) __strtod_l;
extern __typeof (strtof_l) __strtof_l;
extern __typeof (strtold_l) __strtold_l;
extern __typeof (__strtol_l) __strtol_l __attribute__ ((visibility ("hidden")));
extern __typeof (__strtoul_l) __strtoul_l __attribute__ ((visibility ("hidden")));
extern __typeof (__strtoll_l) __strtoll_l __attribute__ ((visibility ("hidden")));
extern __typeof (__strtoull_l) __strtoull_l __attribute__ ((visibility ("hidden")));
extern __typeof (__strtod_l) __strtod_l __attribute__ ((visibility ("hidden")));
extern __typeof (__strtof_l) __strtof_l __attribute__ ((visibility ("hidden")));
extern __typeof (__strtold_l) __strtold_l __attribute__ ((visibility ("hidden")));

extern __typeof (exit) exit __attribute__ ((visibility ("hidden")));
extern __typeof (abort) abort __attribute__ ((visibility ("hidden")));
extern __typeof (getenv) getenv __attribute__ ((visibility ("hidden")));
extern __typeof (secure_getenv) __libc_secure_getenv;
extern __typeof (__libc_secure_getenv) __libc_secure_getenv __attribute__ ((visibility ("hidden")));
extern __typeof (bsearch) bsearch __attribute__ ((visibility ("hidden")));
extern __typeof (qsort) qsort __attribute__ ((visibility ("hidden")));
extern __typeof (qsort_r) __qsort_r;
extern __typeof (__qsort_r) __qsort_r __attribute__ ((visibility ("hidden")));
extern __typeof (lrand48_r) lrand48_r __attribute__ ((visibility ("hidden")));
extern __typeof (wctomb) wctomb __attribute__ ((visibility ("hidden")));

extern long int __random (void) ;
extern void __srandom (unsigned int __seed);
extern char *__initstate (unsigned int __seed, char *__statebuf,
     size_t __statelen);
extern char *__setstate (char *__statebuf);
extern int __random_r (struct random_data *__buf, int32_t *__result)
     ;
extern int __srandom_r (unsigned int __seed, struct random_data *__buf)
     ;
extern int __initstate_r (unsigned int __seed, char *__statebuf,
     size_t __statelen, struct random_data *__buf)
     ;
extern int __setstate_r (char *__statebuf, struct random_data *__buf)
     ;
extern int __rand_r (unsigned int *__seed);
extern int __erand48_r (unsigned short int __xsubi[3],
   struct drand48_data *__buffer, double *__result)
     ;
extern int __nrand48_r (unsigned short int __xsubi[3],
   struct drand48_data *__buffer,
   long int *__result) ;
extern int __jrand48_r (unsigned short int __xsubi[3],
   struct drand48_data *__buffer,
   long int *__result) ;
extern int __srand48_r (long int __seedval,
   struct drand48_data *__buffer) ;
extern int __seed48_r (unsigned short int __seed16v[3],
         struct drand48_data *__buffer) ;
extern int __lcong48_r (unsigned short int __param[7],
   struct drand48_data *__buffer) ;


extern int __drand48_iterate (unsigned short int __xsubi[3],
         struct drand48_data *__buffer)
     ;


extern struct drand48_data __libc_drand48_data ;

extern int __setenv (const char *__name, const char *__value, int __replace)
     ;
extern int __unsetenv (const char *__name) ;
extern int __clearenv (void) ;
extern char *__mktemp (char *__template) __attribute__ ((__nothrow__ )) ;
extern char *__canonicalize_file_name (const char *__name);
extern char *__realpath (const char *__name, char *__resolved);
extern __typeof (__realpath) __realpath __attribute__ ((visibility ("hidden")));
extern int __ptsname_r (int __fd, char *__buf, size_t __buflen)
     ;

extern int __ptsname_internal (int fd, char *buf, size_t buflen,
          struct stat64 *stp) ;

extern int __getpt (void);
extern int __posix_openpt (int __oflag) ;

extern int __add_to_environ (const char *name, const char *value,
        const char *combines, int replace)
     ;
extern void _quicksort (void *const pbase, size_t total_elems,
   size_t size, __compar_d_fn_t cmp, void *arg);

extern int __on_exit (void (*__func) (int __status, void *__arg), void *__arg);

extern int __cxa_atexit (void (*func) (void *), void *arg, void *d);
extern __typeof (__cxa_atexit) __cxa_atexit __attribute__ ((visibility ("hidden")));;

extern int __cxa_thread_atexit_impl (void (*func) (void *), void *arg,
         void *d);
extern void __call_tls_dtors (void)

  __attribute__ ((weak))

  ;
extern __typeof (__call_tls_dtors) __call_tls_dtors __attribute__ ((visibility ("hidden")));

extern void __cxa_finalize (void *d);

extern int __posix_memalign (void **memptr, size_t alignment, size_t size);

extern void *__libc_memalign (size_t alignment, size_t size)
     __attribute__ ((__malloc__));

extern void *__libc_reallocarray (void *__ptr, size_t __nmemb, size_t __size)
     __attribute__ ((__nothrow__ )) __attribute__ ((__warn_unused_result__));
extern __typeof (__libc_reallocarray) __libc_reallocarray __attribute__ ((visibility ("hidden")));

extern int __libc_system (const char *line);


extern double __strtod_internal (const char *__restrict __nptr,
     char **__restrict __endptr, int __group)
     __attribute__ ((__nothrow__ )) ;
extern float __strtof_internal (const char *__restrict __nptr,
    char **__restrict __endptr, int __group)
     __attribute__ ((__nothrow__ )) ;
extern long double __strtold_internal (const char *__restrict __nptr,
           char **__restrict __endptr,
           int __group)
     __attribute__ ((__nothrow__ )) ;
extern long int __strtol_internal (const char *__restrict __nptr,
       char **__restrict __endptr,
       int __base, int __group)
     __attribute__ ((__nothrow__ )) ;
extern unsigned long int __strtoul_internal (const char *__restrict __nptr,
          char **__restrict __endptr,
          int __base, int __group)
     __attribute__ ((__nothrow__ )) ;
__extension__
extern long long int __strtoll_internal (const char *__restrict __nptr,
      char **__restrict __endptr,
      int __base, int __group)
     __attribute__ ((__nothrow__ )) ;
__extension__
extern unsigned long long int __strtoull_internal (const char *
         __restrict __nptr,
         char **__restrict __endptr,
         int __base, int __group)
     __attribute__ ((__nothrow__ )) ;
extern __typeof (__strtof_internal) __strtof_internal __attribute__ ((visibility ("hidden")));
extern __typeof (__strtod_internal) __strtod_internal __attribute__ ((visibility ("hidden")));
extern __typeof (__strtold_internal) __strtold_internal __attribute__ ((visibility ("hidden")));
extern __typeof (__strtol_internal) __strtol_internal __attribute__ ((visibility ("hidden")));
extern __typeof (__strtoll_internal) __strtoll_internal __attribute__ ((visibility ("hidden")));
extern __typeof (__strtoul_internal) __strtoul_internal __attribute__ ((visibility ("hidden")));
extern __typeof (__strtoull_internal) __strtoull_internal __attribute__ ((visibility ("hidden")));

extern double ____strtod_l_internal (const char *__restrict __nptr,
         char **__restrict __endptr, int __group,
         locale_t __loc);
extern float ____strtof_l_internal (const char *__restrict __nptr,
        char **__restrict __endptr, int __group,
        locale_t __loc);
extern long double ____strtold_l_internal (const char *__restrict __nptr,
        char **__restrict __endptr,
        int __group, locale_t __loc);
extern long int ____strtol_l_internal (const char *__restrict __nptr,
           char **__restrict __endptr,
           int __base, int __group,
           locale_t __loc);
extern unsigned long int ____strtoul_l_internal (const char *
       __restrict __nptr,
       char **__restrict __endptr,
       int __base, int __group,
       locale_t __loc);
__extension__
extern long long int ____strtoll_l_internal (const char *__restrict __nptr,
          char **__restrict __endptr,
          int __base, int __group,
          locale_t __loc);
__extension__
extern unsigned long long int ____strtoull_l_internal (const char *
             __restrict __nptr,
             char **
             __restrict __endptr,
             int __base, int __group,
             locale_t __loc);

extern __typeof (____strtof_l_internal) ____strtof_l_internal __attribute__ ((visibility ("hidden")));
extern __typeof (____strtod_l_internal) ____strtod_l_internal __attribute__ ((visibility ("hidden")));
extern __typeof (____strtold_l_internal) ____strtold_l_internal __attribute__ ((visibility ("hidden")));
extern __typeof (____strtol_l_internal) ____strtol_l_internal __attribute__ ((visibility ("hidden")));
extern __typeof (____strtoll_l_internal) ____strtoll_l_internal __attribute__ ((visibility ("hidden")));
extern __typeof (____strtoul_l_internal) ____strtoul_l_internal __attribute__ ((visibility ("hidden")));
extern __typeof (____strtoull_l_internal) ____strtoull_l_internal __attribute__ ((visibility ("hidden")));

extern __typeof (strtof) strtof __attribute__ ((visibility ("hidden")));
extern __typeof (strtod) strtod __attribute__ ((visibility ("hidden")));
extern __typeof (strtold) strtold __attribute__ ((visibility ("hidden")));
extern __typeof (strtol) strtol __attribute__ ((visibility ("hidden")));
extern __typeof (strtoll) strtoll __attribute__ ((visibility ("hidden")));
extern __typeof (strtoul) strtoul __attribute__ ((visibility ("hidden")));
extern __typeof (strtoull) strtoull __attribute__ ((visibility ("hidden")));

extern __typeof (atoi) atoi __attribute__ ((visibility ("hidden")));

extern float __strtof_nan (const char *, char **, char);
extern double __strtod_nan (const char *, char **, char);
extern long double __strtold_nan (const char *, char **, char);
extern float __wcstof_nan (const wchar_t *, wchar_t **, wchar_t);
extern double __wcstod_nan (const wchar_t *, wchar_t **, wchar_t);
extern long double __wcstold_nan (const wchar_t *, wchar_t **, wchar_t);

extern __typeof (__strtof_nan) __strtof_nan __attribute__ ((visibility ("hidden")));
extern __typeof (__strtod_nan) __strtod_nan __attribute__ ((visibility ("hidden")));
extern __typeof (__strtold_nan) __strtold_nan __attribute__ ((visibility ("hidden")));
extern __typeof (__wcstof_nan) __wcstof_nan __attribute__ ((visibility ("hidden")));
extern __typeof (__wcstod_nan) __wcstod_nan __attribute__ ((visibility ("hidden")));
extern __typeof (__wcstold_nan) __wcstold_nan __attribute__ ((visibility ("hidden")));
# 256 "../include/stdlib.h"
extern char *__ecvt (double __value, int __ndigit, int *__restrict __decpt,
       int *__restrict __sign);
extern char *__fcvt (double __value, int __ndigit, int *__restrict __decpt,
       int *__restrict __sign);
extern char *__gcvt (double __value, int __ndigit, char *__buf);
extern int __ecvt_r (double __value, int __ndigit, int *__restrict __decpt,
       int *__restrict __sign, char *__restrict __buf,
       size_t __len);
extern __typeof (__ecvt_r) __ecvt_r __attribute__ ((visibility ("hidden")));
extern int __fcvt_r (double __value, int __ndigit, int *__restrict __decpt,
       int *__restrict __sign, char *__restrict __buf,
       size_t __len);
extern __typeof (__fcvt_r) __fcvt_r __attribute__ ((visibility ("hidden")));
extern char *__qecvt (long double __value, int __ndigit,
        int *__restrict __decpt, int *__restrict __sign);
extern char *__qfcvt (long double __value, int __ndigit,
        int *__restrict __decpt, int *__restrict __sign);
extern char *__qgcvt (long double __value, int __ndigit, char *__buf);
extern int __qecvt_r (long double __value, int __ndigit,
        int *__restrict __decpt, int *__restrict __sign,
        char *__restrict __buf, size_t __len);
extern __typeof (__qecvt_r) __qecvt_r __attribute__ ((visibility ("hidden")));
extern int __qfcvt_r (long double __value, int __ndigit,
        int *__restrict __decpt, int *__restrict __sign,
        char *__restrict __buf, size_t __len);
extern __typeof (__qfcvt_r) __qfcvt_r __attribute__ ((visibility ("hidden")));






extern void *__default_morecore (ptrdiff_t) __attribute__ ((__nothrow__ ));
extern __typeof (__default_morecore) __default_morecore __attribute__ ((visibility ("hidden")));

struct abort_msg_s
{
  unsigned int size;
  char msg[0];
};
extern struct abort_msg_s *__abort_msg;
extern __typeof (__abort_msg) __abort_msg __attribute__ ((visibility ("hidden")));
# 34 "plural.y" 2
# 1 "../include/string.h" 1





# 1 "../include/sys/types.h" 1
# 7 "../include/string.h" 2

extern void *__memccpy (void *__dest, const void *__src,
   int __c, size_t __n);

extern size_t __strnlen (const char *__string, size_t __maxlen)
     __attribute__ ((__pure__));

extern char *__strsep (char **__stringp, const char *__delim);
extern __typeof (__strsep) __strsep __attribute__ ((visibility ("hidden")));

extern int __strverscmp (const char *__s1, const char *__s2)
     __attribute__ ((__pure__));

extern int __strncasecmp (const char *__s1, const char *__s2,
     size_t __n)
     __attribute__ ((__pure__));

extern int __strcasecmp (const char *__s1, const char *__s2)
     __attribute__ ((__pure__));

extern char *__strcasestr (const char *__haystack, const char *__needle)
     __attribute__ ((__pure__));

extern char *__strdup (const char *__string)
     __attribute__ ((__malloc__));
extern char *__strndup (const char *__string, size_t __n)
     __attribute__ ((__malloc__));

extern void *__rawmemchr (const void *__s, int __c)
     __attribute__ ((__pure__));

extern char *__strchrnul (const char *__s, int __c)
     __attribute__ ((__pure__));

extern void *__memrchr (const void *__s, int __c, size_t __n)
     __attribute__ ((__pure__));

extern void *__memchr (const void *__s, int __c, size_t __n)
     __attribute__ ((__pure__));

extern void __bzero (void *__s, size_t __n) __attribute__ ((__nothrow__ )) ;

extern int __ffs (int __i) __attribute__ ((const));

extern char *__strerror_r (int __errnum, char *__buf, size_t __buflen);


void __strerror_thread_freeres (void) ;


# 1 "../sysdeps/generic/string_private.h" 1
# 58 "../include/string.h" 2


# 1 "../string/string.h" 1
# 26 "../string/string.h"
# 1 "../bits/libc-header-start.h" 1
# 27 "../string/string.h" 2






# 1 "/scratch/jmyers/glibc/many9/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/include/stddef.h" 1 3 4
# 34 "../string/string.h" 2
# 42 "../string/string.h"
extern void *memcpy (void *__restrict __dest, const void *__restrict __src,
       size_t __n) __attribute__ ((__nothrow__ )) ;


extern void *memmove (void *__dest, const void *__src, size_t __n)
     __attribute__ ((__nothrow__ )) ;





extern void *memccpy (void *__restrict __dest, const void *__restrict __src,
        int __c, size_t __n)
     __attribute__ ((__nothrow__ )) ;




extern void *memset (void *__s, int __c, size_t __n) __attribute__ ((__nothrow__ )) ;


extern int memcmp (const void *__s1, const void *__s2, size_t __n)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;
# 90 "../string/string.h"
extern void *memchr (const void *__s, int __c, size_t __n)
      __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;
# 103 "../string/string.h"
extern void *rawmemchr (const void *__s, int __c)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;
# 114 "../string/string.h"
extern void *memrchr (const void *__s, int __c, size_t __n)
      __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;





extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
     __attribute__ ((__nothrow__ )) ;

extern char *strncpy (char *__restrict __dest,
        const char *__restrict __src, size_t __n)
     __attribute__ ((__nothrow__ )) ;


extern char *strcat (char *__restrict __dest, const char *__restrict __src)
     __attribute__ ((__nothrow__ )) ;

extern char *strncat (char *__restrict __dest, const char *__restrict __src,
        size_t __n) __attribute__ ((__nothrow__ )) ;


extern int strcmp (const char *__s1, const char *__s2)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;

extern int strncmp (const char *__s1, const char *__s2, size_t __n)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;


extern int strcoll (const char *__s1, const char *__s2)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;

extern size_t strxfrm (char *__restrict __dest,
         const char *__restrict __src, size_t __n)
     __attribute__ ((__nothrow__ )) ;



# 1 "../include/bits/types/locale_t.h" 1
# 153 "../string/string.h" 2


extern int strcoll_l (const char *__s1, const char *__s2, locale_t __l)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;


extern size_t strxfrm_l (char *__dest, const char *__src, size_t __n,
    locale_t __l) __attribute__ ((__nothrow__ )) ;





extern char *strdup (const char *__s)
     __attribute__ ((__nothrow__ )) __attribute__ ((__malloc__)) ;






extern char *strndup (const char *__string, size_t __n)
     __attribute__ ((__nothrow__ )) __attribute__ ((__malloc__)) ;
# 225 "../string/string.h"
extern char *strchr (const char *__s, int __c)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;
# 252 "../string/string.h"
extern char *strrchr (const char *__s, int __c)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;
# 265 "../string/string.h"
extern char *strchrnul (const char *__s, int __c)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;





extern size_t strcspn (const char *__s, const char *__reject)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;


extern size_t strspn (const char *__s, const char *__accept)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;
# 302 "../string/string.h"
extern char *strpbrk (const char *__s, const char *__accept)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;
# 329 "../string/string.h"
extern char *strstr (const char *__haystack, const char *__needle)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;




extern char *strtok (char *__restrict __s, const char *__restrict __delim)
     __attribute__ ((__nothrow__ )) ;



extern char *__strtok_r (char *__restrict __s,
    const char *__restrict __delim,
    char **__restrict __save_ptr)
     __attribute__ ((__nothrow__ )) ;

extern char *strtok_r (char *__restrict __s, const char *__restrict __delim,
         char **__restrict __save_ptr)
     __attribute__ ((__nothrow__ )) ;
# 359 "../string/string.h"
extern char *strcasestr (const char *__haystack, const char *__needle)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;







extern void *memmem (const void *__haystack, size_t __haystacklen,
       const void *__needle, size_t __needlelen)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;



extern void *__mempcpy (void *__restrict __dest,
   const void *__restrict __src, size_t __n)
     __attribute__ ((__nothrow__ )) ;
extern void *mempcpy (void *__restrict __dest,
        const void *__restrict __src, size_t __n)
     __attribute__ ((__nothrow__ )) ;




extern size_t strlen (const char *__s)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;




extern size_t strnlen (const char *__string, size_t __maxlen)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;




extern char *strerror (int __errnum) __attribute__ ((__nothrow__ ));
# 420 "../string/string.h"
extern char *strerror_r (int __errnum, char *__buf, size_t __buflen)
     __attribute__ ((__nothrow__ )) ;





extern char *strerror_l (int __errnum, locale_t __l) __attribute__ ((__nothrow__ ));



# 1 "../include/strings.h" 1
# 1 "../string/strings.h" 1
# 23 "../string/strings.h"
# 1 "/scratch/jmyers/glibc/many9/install/compilers/alpha-linux-gnu/lib/gcc/alpha-glibc-linux-gnu/9.0.0/include/stddef.h" 1 3 4
# 24 "../string/strings.h" 2










extern int bcmp (const void *__s1, const void *__s2, size_t __n)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;


extern void bcopy (const void *__src, void *__dest, size_t __n)
  __attribute__ ((__nothrow__ )) ;


extern void bzero (void *__s, size_t __n) __attribute__ ((__nothrow__ )) ;
# 68 "../string/strings.h"
extern char *index (const char *__s, int __c)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;
# 96 "../string/strings.h"
extern char *rindex (const char *__s, int __c)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;






extern int ffs (int __i) __attribute__ ((__nothrow__ )) __attribute__ ((__const__));





extern int ffsl (long int __l) __attribute__ ((__nothrow__ )) __attribute__ ((__const__));
__extension__ extern int ffsll (long long int __ll)
     __attribute__ ((__nothrow__ )) __attribute__ ((__const__));



extern int strcasecmp (const char *__s1, const char *__s2)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;


extern int strncasecmp (const char *__s1, const char *__s2, size_t __n)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;



# 1 "../include/bits/types/locale_t.h" 1
# 126 "../string/strings.h" 2


extern int strcasecmp_l (const char *__s1, const char *__s2, locale_t __loc)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;



extern int strncasecmp_l (const char *__s1, const char *__s2,
     size_t __n, locale_t __loc)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;



# 1 "../include/strings.h" 2
# 432 "../string/string.h" 2



extern void explicit_bzero (void *__s, size_t __n) __attribute__ ((__nothrow__ )) ;



extern char *strsep (char **__restrict __stringp,
       const char *__restrict __delim)
     __attribute__ ((__nothrow__ )) ;




extern char *strsignal (int __sig) __attribute__ ((__nothrow__ ));


extern char *__stpcpy (char *__restrict __dest, const char *__restrict __src)
     __attribute__ ((__nothrow__ )) ;
extern char *stpcpy (char *__restrict __dest, const char *__restrict __src)
     __attribute__ ((__nothrow__ )) ;



extern char *__stpncpy (char *__restrict __dest,
   const char *__restrict __src, size_t __n)
     __attribute__ ((__nothrow__ )) ;
extern char *stpncpy (char *__restrict __dest,
        const char *__restrict __src, size_t __n)
     __attribute__ ((__nothrow__ )) ;




extern int strverscmp (const char *__s1, const char *__s2)
     __attribute__ ((__nothrow__ )) __attribute__ ((__pure__)) ;


extern char *strfry (char *__string) __attribute__ ((__nothrow__ )) ;


extern void *memfrob (void *__s, size_t __n) __attribute__ ((__nothrow__ )) ;
# 486 "../string/string.h"
extern char *basename (const char *__filename) __attribute__ ((__nothrow__ )) ;
# 498 "../string/string.h"

# 61 "../include/string.h" 2


extern __typeof (strcoll_l) __strcoll_l;
extern __typeof (strxfrm_l) __strxfrm_l;
extern __typeof (strcasecmp_l) __strcasecmp_l;
extern __typeof (strncasecmp_l) __strncasecmp_l;
# 82 "../include/string.h"
extern __typeof (__mempcpy) __mempcpy __attribute__ ((visibility ("hidden")));



extern __typeof (__stpcpy) __stpcpy __attribute__ ((visibility ("hidden")));



extern __typeof (__stpncpy) __stpncpy __attribute__ ((visibility ("hidden")));
extern __typeof (__rawmemchr) __rawmemchr __attribute__ ((visibility ("hidden")));
extern __typeof (__strcasecmp) __strcasecmp __attribute__ ((visibility ("hidden")));
extern __typeof (__strcasecmp_l) __strcasecmp_l __attribute__ ((visibility ("hidden")));
extern __typeof (__strncasecmp_l) __strncasecmp_l __attribute__ ((visibility ("hidden")));
extern __typeof (strncat) __strncat;
extern __typeof (__strncat) __strncat __attribute__ ((visibility ("hidden")));
extern __typeof (__strdup) __strdup __attribute__ ((visibility ("hidden")));
extern __typeof (__strndup) __strndup __attribute__ ((visibility ("hidden")));
extern __typeof (__strerror_r) __strerror_r __attribute__ ((visibility ("hidden")));
extern __typeof (__strverscmp) __strverscmp __attribute__ ((visibility ("hidden")));
extern __typeof (basename) basename __attribute__ ((visibility ("hidden")));
extern char *__basename (const char *__filename) __attribute__ ((__nothrow__ )) ;
extern __typeof (__basename) __basename __attribute__ ((visibility ("hidden")));
extern __typeof (strcoll) strcoll __attribute__ ((visibility ("hidden")));
extern __typeof (__strcoll_l) __strcoll_l __attribute__ ((visibility ("hidden")));
extern __typeof (__strxfrm_l) __strxfrm_l __attribute__ ((visibility ("hidden")));
extern __typeof (__strtok_r) __strtok_r __attribute__ ((visibility ("hidden")));
extern char *__strsep_g (char **__stringp, const char *__delim);
extern __typeof (__strsep_g) __strsep_g __attribute__ ((visibility ("hidden")));
extern __typeof (strnlen) strnlen __attribute__ ((visibility ("hidden")));
extern __typeof (__strnlen) __strnlen __attribute__ ((visibility ("hidden")));
extern __typeof (memmem) memmem __attribute__ ((visibility ("hidden")));
extern __typeof (memmem) __memmem;
extern __typeof (__memmem) __memmem __attribute__ ((visibility ("hidden")));
extern __typeof (__ffs) __ffs __attribute__ ((visibility ("hidden")));



void __explicit_bzero_chk_internal (void *, size_t, size_t)
  __attribute__ ((__nothrow__ )) ;







extern __typeof (memchr) memchr __attribute__ ((visibility ("hidden")));
extern __typeof (memcpy) memcpy __attribute__ ((visibility ("hidden")));
extern __typeof (mempcpy) mempcpy __attribute__ ((visibility ("hidden")));
extern __typeof (memcmp) memcmp __attribute__ ((visibility ("hidden")));
extern __typeof (memmove) memmove __attribute__ ((visibility ("hidden")));
extern __typeof (memset) memset __attribute__ ((visibility ("hidden")));
extern __typeof (strcat) strcat __attribute__ ((visibility ("hidden")));
extern __typeof (strchr) strchr __attribute__ ((visibility ("hidden")));
extern __typeof (strcmp) strcmp __attribute__ ((visibility ("hidden")));
extern __typeof (strcpy) strcpy __attribute__ ((visibility ("hidden")));
extern __typeof (strcspn) strcspn __attribute__ ((visibility ("hidden")));
extern __typeof (strlen) strlen __attribute__ ((visibility ("hidden")));
extern __typeof (strncmp) strncmp __attribute__ ((visibility ("hidden")));
extern __typeof (strncpy) strncpy __attribute__ ((visibility ("hidden")));
extern __typeof (strpbrk) strpbrk __attribute__ ((visibility ("hidden")));
extern __typeof (stpcpy) stpcpy __attribute__ ((visibility ("hidden")));
extern __typeof (strrchr) strrchr __attribute__ ((visibility ("hidden")));
extern __typeof (strspn) strspn __attribute__ ((visibility ("hidden")));
extern __typeof (strstr) strstr __attribute__ ((visibility ("hidden")));
extern __typeof (ffs) ffs __attribute__ ((visibility ("hidden")));
# 173 "../include/string.h"
extern __typeof (mempcpy) mempcpy __asm__ ("__mempcpy");
extern __typeof (stpcpy) stpcpy __asm__ ("__stpcpy");


extern void *__memcpy_chk (void *__restrict __dest,
      const void *__restrict __src, size_t __len,
      size_t __destlen) __attribute__ ((__nothrow__ ));
extern void *__memmove_chk (void *__dest, const void *__src, size_t __len,
       size_t __destlen) __attribute__ ((__nothrow__ ));
extern void *__mempcpy_chk (void *__restrict __dest,
       const void *__restrict __src, size_t __len,
       size_t __destlen) __attribute__ ((__nothrow__ ));
extern void *__memset_chk (void *__dest, int __ch, size_t __len,
      size_t __destlen) __attribute__ ((__nothrow__ ));
extern char *__strcpy_chk (char *__restrict __dest,
      const char *__restrict __src,
      size_t __destlen) __attribute__ ((__nothrow__ ));
extern char *__stpcpy_chk (char *__restrict __dest,
      const char *__restrict __src,
      size_t __destlen) __attribute__ ((__nothrow__ ));
extern char *__strncpy_chk (char *__restrict __dest,
       const char *__restrict __src,
       size_t __len, size_t __destlen) __attribute__ ((__nothrow__ ));
extern char *__strcat_chk (char *__restrict __dest,
      const char *__restrict __src,
      size_t __destlen) __attribute__ ((__nothrow__ ));
extern char *__strncat_chk (char *__restrict __dest,
       const char *__restrict __src,
       size_t __len, size_t __destlen) __attribute__ ((__nothrow__ ));
# 35 "plural.y" 2
# 1 "../include/plural-exp.h" 1

# 1 "../intl/plural-exp.h" 1
# 30 "../intl/plural-exp.h"
enum expression_operator
{

  var,
  num,

  lnot,

  mult,
  divide,
  module,
  plus,
  minus,
  less_than,
  greater_than,
  less_or_equal,
  greater_or_equal,
  equal,
  not_equal,
  land,
  lor,

  qmop
};



struct expression
{
  int nargs;
  enum expression_operator operation;
  union
  {
    unsigned long int num;
    struct expression *args[3];
  } val;
};



struct parse_args
{
  const char *cp;
  struct expression *res;
};
# 104 "../intl/plural-exp.h"
extern void __gettext_free_exp (struct expression *exp) ;
extern int __gettextparse (struct parse_args *arg);
extern const struct expression __gettext_germanic_plural ;
extern void __gettext_extract_plural (const char *nullentry,
           const struct expression **pluralp,
           unsigned long int *npluralsp)
     ;
# 3 "../include/plural-exp.h" 2


extern __typeof (__gettextparse) __gettextparse ;
# 36 "plural.y" 2
# 116 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
# 145 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
  enum yytokentype
  {
    EQUOP2 = 258,
    CMPOP2 = 259,
    ADDOP2 = 260,
    MULOP2 = 261,
    NUMBER = 262
  };
# 164 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
union YYSTYPE
{
# 49 "plural.y"

  unsigned long int num;
  enum expression_operator op;
  struct expression *exp;
# 173 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
};

typedef union YYSTYPE YYSTYPE;






int __gettextparse (struct parse_args *arg);
# 55 "plural.y"


static int __gettextlex (YYSTYPE *lval, struct parse_args *arg);
static void __gettexterror (struct parse_args *arg, const char *str);



static struct expression *
new_exp (int nargs, enum expression_operator op,
  struct expression * const *args)
{
  int i;
  struct expression *newp;


  for (i = nargs - 1; i >= 0; i--)
    if (args[i] == 
# 71 "plural.y" 3 4
                  ((void *)0)
# 71 "plural.y"
                      )
      goto fail;


  newp = (struct expression *) malloc (sizeof (*newp));
  if (newp != 
# 76 "plural.y" 3 4
             ((void *)0)
# 76 "plural.y"
                 )
    {
      newp->nargs = nargs;
      newp->operation = op;
      for (i = nargs - 1; i >= 0; i--)
 newp->val.args[i] = args[i];
      return newp;
    }

 fail:
  for (i = nargs - 1; i >= 0; i--)
    __gettext_free_exp (args[i]);

  return 
# 89 "plural.y" 3 4
        ((void *)0)
# 89 "plural.y"
            ;
}

static inline struct expression *
new_exp_0 (enum expression_operator op)
{
  return new_exp (0, op, 
# 95 "plural.y" 3 4
                        ((void *)0)
# 95 "plural.y"
                            );
}

static inline struct expression *
new_exp_1 (enum expression_operator op, struct expression *right)
{
  struct expression *args[1];

  args[0] = right;
  return new_exp (1, op, args);
}

static struct expression *
new_exp_2 (enum expression_operator op, struct expression *left,
    struct expression *right)
{
  struct expression *args[2];

  args[0] = left;
  args[1] = right;
  return new_exp (2, op, args);
}

static inline struct expression *
new_exp_3 (enum expression_operator op, struct expression *bexp,
    struct expression *tbranch, struct expression *fbranch)
{
  struct expression *args[3];

  args[0] = bexp;
  args[1] = tbranch;
  args[2] = fbranch;
  return new_exp (3, op, args);
}
# 265 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
# 273 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
typedef unsigned char yytype_uint8;





typedef signed char yytype_int8;





typedef unsigned short int yytype_uint16;





typedef short int yytype_int16;
# 448 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
union yyalloc
{
  yytype_int16 yyss_alloc;
  YYSTYPE yyvs_alloc;
};
# 527 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
static const yytype_uint8 yytranslate[] =
{
       0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 10, 2, 2, 2, 2, 5, 2,
      14, 15, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 12, 2,
       2, 2, 2, 3, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
      13, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 4, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 1, 2, 6, 7,
       8, 9, 11
};
# 600 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
static const yytype_int8 yypact[] =
{
      -9, -9, -10, -10, -9, 8, 36, -10, 13, -10,
      -9, -9, -9, -9, -9, -9, -9, -10, 26, 41,
      45, 18, -2, 14, -10, -9, 36
};




static const yytype_uint8 yydefact[] =
{
       0, 0, 12, 11, 0, 0, 2, 10, 0, 1,
       0, 0, 0, 0, 0, 0, 0, 13, 0, 4,
       5, 6, 7, 8, 9, 0, 3
};


static const yytype_int8 yypgoto[] =
{
     -10, -10, -1
};


static const yytype_int8 yydefgoto[] =
{
      -1, 5, 6
};




static const yytype_uint8 yytable[] =
{
       7, 1, 2, 8, 3, 4, 15, 16, 9, 18,
      19, 20, 21, 22, 23, 24, 10, 11, 12, 13,
      14, 15, 16, 16, 26, 14, 15, 16, 17, 10,
      11, 12, 13, 14, 15, 16, 0, 0, 25, 10,
      11, 12, 13, 14, 15, 16, 12, 13, 14, 15,
      16, 13, 14, 15, 16
};

static const yytype_int8 yycheck[] =
{
       1, 10, 11, 4, 13, 14, 8, 9, 0, 10,
      11, 12, 13, 14, 15, 16, 3, 4, 5, 6,
       7, 8, 9, 9, 25, 7, 8, 9, 15, 3,
       4, 5, 6, 7, 8, 9, -1, -1, 12, 3,
       4, 5, 6, 7, 8, 9, 5, 6, 7, 8,
       9, 6, 7, 8, 9
};



static const yytype_uint8 yystos[] =
{
       0, 10, 11, 13, 14, 17, 18, 18, 18, 0,
       3, 4, 5, 6, 7, 8, 9, 15, 18, 18,
      18, 18, 18, 18, 18, 12, 18
};


static const yytype_uint8 yyr1[] =
{
       0, 16, 17, 18, 18, 18, 18, 18, 18, 18,
      18, 18, 18, 18
};


static const yytype_uint8 yyr2[] =
{
       0, 2, 1, 5, 3, 3, 3, 3, 3, 3,
       2, 1, 1, 3
};
# 1085 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
static void
yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, struct parse_args *arg)
{
  ((void) (yyvaluep));
  ((void) (arg));
  if (!yymsg)
    yymsg = "Deleting";
  ;

 
# 1094 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
#pragma GCC diagnostic push
# 1094 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
 
# 1094 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
#pragma GCC diagnostic ignored "-Wuninitialized"
# 1094 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
 
# 1094 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
# 1094 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
 
  ((void) (yytype));
 
# 1096 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
#pragma GCC diagnostic pop
# 1096 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
 
}
# 1106 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
int
__gettextparse (struct parse_args *arg)
{

int yychar;






YYSTYPE yylval ;


    int __gettextnerrs;

    int yystate;

    int yyerrstatus;
# 1134 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
    yytype_int16 yyssa[200];
    yytype_int16 *yyss;
    yytype_int16 *yyssp;


    YYSTYPE yyvsa[200];
    YYSTYPE *yyvs;
    YYSTYPE *yyvsp;

    long unsigned int yystacksize;

  int yyn;
  int yyresult;

  int yytoken = 0;


  YYSTYPE yyval;
# 1164 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
  int yylen = 0;

  yyssp = yyss = yyssa;
  yyvsp = yyvs = yyvsa;
  yystacksize = 200;

  ;

  yystate = 0;
  yyerrstatus = 0;
  __gettextnerrs = 0;
  yychar = (-2);
  goto yysetstate;




 yynewstate:


  yyssp++;

 yysetstate:
  *yyssp = yystate;

  if (yyss + yystacksize - 1 <= yyssp)
    {

      long unsigned int yysize = yyssp - yyss + 1;
# 1219 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
      if (10000 <= yystacksize)
        goto yyexhaustedlab;
      yystacksize *= 2;
      if (10000 < yystacksize)
        yystacksize = 10000;

      {
        yytype_int16 *yyss1 = yyss;
        union yyalloc *yyptr =
          (union yyalloc *) malloc (((yystacksize) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) + (sizeof (union yyalloc) - 1)));
        if (! yyptr)
          goto yyexhaustedlab;
        do { long unsigned int yynewbytes; __builtin_memcpy (&yyptr->yyss_alloc, yyss, (yysize) * sizeof (*(yyss))); yyss = &yyptr->yyss_alloc; yynewbytes = yystacksize * sizeof (*yyss) + (sizeof (union yyalloc) - 1); yyptr += yynewbytes / sizeof (*yyptr); } while (0);
        do { long unsigned int yynewbytes; __builtin_memcpy (&yyptr->yyvs_alloc, yyvs, (yysize) * sizeof (*(yyvs))); yyvs = &yyptr->yyvs_alloc; yynewbytes = yystacksize * sizeof (*yyvs) + (sizeof (union yyalloc) - 1); yyptr += yynewbytes / sizeof (*yyptr); } while (0);

        if (yyss1 != yyssa)
          free (yyss1);
      }



      yyssp = yyss + yysize - 1;
      yyvsp = yyvs + yysize - 1;

     
                                                   ;

      if (yyss + yystacksize - 1 <= yyssp)
        goto yyabortlab;
    }

  ;

  if (yystate == 9)
    goto yyacceptlab;

  goto yybackup;




yybackup:





  yyn = yypact[yystate];
  if ((!!((yyn) == (-10))))
    goto yydefault;




  if (yychar == (-2))
    {
      ;
      yychar = __gettextlex (&yylval, arg);
    }

  if (yychar <= 0)
    {
      yychar = yytoken = 0;
      ;
    }
  else
    {
      yytoken = ((unsigned int) (yychar) <= 262 ? yytranslate[yychar] : 2);
      ;
    }



  yyn += yytoken;
  if (yyn < 0 || 54 < yyn || yycheck[yyn] != yytoken)
    goto yydefault;
  yyn = yytable[yyn];
  if (yyn <= 0)
    {
      if (0)
        goto yyerrlab;
      yyn = -yyn;
      goto yyreduce;
    }



  if (yyerrstatus)
    yyerrstatus--;


  ;


  yychar = (-2);

  yystate = yyn;
 
# 1316 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
#pragma GCC diagnostic push
# 1316 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
 
# 1316 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
#pragma GCC diagnostic ignored "-Wuninitialized"
# 1316 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
 
# 1316 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
# 1316 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
 
  *++yyvsp = yylval;
 
# 1318 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
#pragma GCC diagnostic pop
# 1318 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
 

  goto yynewstate;





yydefault:
  yyn = yydefact[yystate];
  if (yyn == 0)
    goto yyerrlab;
  goto yyreduce;





yyreduce:

  yylen = yyr2[yyn];
# 1348 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
  yyval = yyvsp[1-yylen];


  ;
  switch (yyn)
    {
        case 2:
# 153 "plural.y"
    {
     if ((yyvsp[0].exp) == 
# 154 "plural.y" 3 4
                          ((void *)0)
# 154 "plural.y"
                              )
       goto yyabortlab;
     arg->res = (yyvsp[0].exp);
   }
# 1362 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
    break;

  case 3:
# 161 "plural.y"
    {
     (yyval.exp) = new_exp_3 (qmop, (yyvsp[-4].exp), (yyvsp[-2].exp), (yyvsp[0].exp));
   }
# 1370 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
    break;

  case 4:
# 165 "plural.y"
    {
     (yyval.exp) = new_exp_2 (lor, (yyvsp[-2].exp), (yyvsp[0].exp));
   }
# 1378 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
    break;

  case 5:
# 169 "plural.y"
    {
     (yyval.exp) = new_exp_2 (land, (yyvsp[-2].exp), (yyvsp[0].exp));
   }
# 1386 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
    break;

  case 6:
# 173 "plural.y"
    {
     (yyval.exp) = new_exp_2 ((yyvsp[-1].op), (yyvsp[-2].exp), (yyvsp[0].exp));
   }
# 1394 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
    break;

  case 7:
# 177 "plural.y"
    {
     (yyval.exp) = new_exp_2 ((yyvsp[-1].op), (yyvsp[-2].exp), (yyvsp[0].exp));
   }
# 1402 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
    break;

  case 8:
# 181 "plural.y"
    {
     (yyval.exp) = new_exp_2 ((yyvsp[-1].op), (yyvsp[-2].exp), (yyvsp[0].exp));
   }
# 1410 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
    break;

  case 9:
# 185 "plural.y"
    {
     (yyval.exp) = new_exp_2 ((yyvsp[-1].op), (yyvsp[-2].exp), (yyvsp[0].exp));
   }
# 1418 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
    break;

  case 10:
# 189 "plural.y"
    {
     (yyval.exp) = new_exp_1 (lnot, (yyvsp[0].exp));
   }
# 1426 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
    break;

  case 11:
# 193 "plural.y"
    {
     (yyval.exp) = new_exp_0 (var);
   }
# 1434 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
    break;

  case 12:
# 197 "plural.y"
    {
     if (((yyval.exp) = new_exp_0 (num)) != 
# 198 "plural.y" 3 4
                                           ((void *)0)
# 198 "plural.y"
                                               )
       (yyval.exp)->val.num = (yyvsp[0].num);
   }
# 1443 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
    break;

  case 13:
# 202 "plural.y"
    {
     (yyval.exp) = (yyvsp[-1].exp);
   }
# 1451 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
    break;
# 1455 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
      default: break;
    }
# 1468 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
  ;

  (yyvsp -= (yylen), yyssp -= (yylen));
  yylen = 0;
  ;

  *++yyvsp = yyval;





  yyn = yyr1[yyn];

  yystate = yypgoto[yyn - 16] + *yyssp;
  if (0 <= yystate && yystate <= 54 && yycheck[yystate] == *yyssp)
    yystate = yytable[yystate];
  else
    yystate = yydefgoto[yyn - 16];

  goto yynewstate;





yyerrlab:


  yytoken = yychar == (-2) ? (-2) : ((unsigned int) (yychar) <= 262 ? yytranslate[yychar] : 2);


  if (!yyerrstatus)
    {
      ++__gettextnerrs;

      __gettexterror (arg, "syntax error");
# 1537 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
    }



  if (yyerrstatus == 3)
    {



      if (yychar <= 0)
        {

          if (yychar == 0)
            goto yyabortlab;
        }
      else
        {
          yydestruct ("Error: discarding",
                      yytoken, &yylval, arg);
          yychar = (-2);
        }
    }



  goto yyerrlab1;





yyerrorlab:




  if ( 0)
     goto yyerrorlab;



  (yyvsp -= (yylen), yyssp -= (yylen));
  yylen = 0;
  ;
  yystate = *yyssp;
  goto yyerrlab1;





yyerrlab1:
  yyerrstatus = 3;

  for (;;)
    {
      yyn = yypact[yystate];
      if (!(!!((yyn) == (-10))))
        {
          yyn += 1;
          if (0 <= yyn && yyn <= 54 && yycheck[yyn] == 1)
            {
              yyn = yytable[yyn];
              if (0 < yyn)
                break;
            }
        }


      if (yyssp == yyss)
        goto yyabortlab;


      yydestruct ("Error: popping",
                  yystos[yystate], yyvsp, arg);
      (yyvsp -= (1), yyssp -= (1));
      yystate = *yyssp;
      ;
    }

 
# 1617 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
#pragma GCC diagnostic push
# 1617 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
 
# 1617 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
#pragma GCC diagnostic ignored "-Wuninitialized"
# 1617 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
 
# 1617 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
# 1617 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
 
  *++yyvsp = yylval;
 
# 1619 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
#pragma GCC diagnostic pop
# 1619 "/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c"
 



  ;

  yystate = yyn;
  goto yynewstate;





yyacceptlab:
  yyresult = 0;
  goto yyreturn;




yyabortlab:
  yyresult = 1;
  goto yyreturn;





yyexhaustedlab:
  __gettexterror (arg, "memory exhausted");
  yyresult = 2;



yyreturn:
  if (yychar != (-2))
    {


      yytoken = ((unsigned int) (yychar) <= 262 ? yytranslate[yychar] : 2);
      yydestruct ("Cleanup: discarding lookahead",
                  yytoken, &yylval, arg);
    }


  (yyvsp -= (yylen), yyssp -= (yylen));
  ;
  while (yyssp != yyss)
    {
      yydestruct ("Cleanup: popping",
                  yystos[*yyssp], yyvsp, arg);
      (yyvsp -= (1), yyssp -= (1));
    }

  if (yyss != yyssa)
    free (yyss);





  return yyresult;
}
# 207 "plural.y"


void
__gettext_free_exp (struct expression *exp)
{
  if (exp == 
# 212 "plural.y" 3 4
            ((void *)0)
# 212 "plural.y"
                )
    return;


  switch (exp->nargs)
    {
    case 3:
      __gettext_free_exp (exp->val.args[2]);

    case 2:
      __gettext_free_exp (exp->val.args[1]);

    case 1:
      __gettext_free_exp (exp->val.args[0]);

    default:
      break;
    }

  free (exp);
}


static int
__gettextlex (YYSTYPE *lval, struct parse_args *arg)
{
  const char *exp = arg->cp;
  int result;

  while (1)
    {
      if (exp[0] == '\0')
 {
   arg->cp = exp;
   return 0;
 }

      if (exp[0] != ' ' && exp[0] != '\t')
 break;

      ++exp;
    }

  result = *exp++;
  switch (result)
    {
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
      {
 unsigned long int n = result - '0';
 while (exp[0] >= '0' && exp[0] <= '9')
   {
     n *= 10;
     n += exp[0] - '0';
     ++exp;
   }
 lval->num = n;
 result = 262;
      }
      break;

    case '=':
      if (exp[0] == '=')
 {
   ++exp;
   lval->op = equal;
   result = 258;
 }
      else
 result = 256;
      break;

    case '!':
      if (exp[0] == '=')
 {
   ++exp;
   lval->op = not_equal;
   result = 258;
 }
      break;

    case '&':
    case '|':
      if (exp[0] == result)
 ++exp;
      else
 result = 256;
      break;

    case '<':
      if (exp[0] == '=')
 {
   ++exp;
   lval->op = less_or_equal;
 }
      else
 lval->op = less_than;
      result = 259;
      break;

    case '>':
      if (exp[0] == '=')
 {
   ++exp;
   lval->op = greater_or_equal;
 }
      else
 lval->op = greater_than;
      result = 259;
      break;

    case '*':
      lval->op = mult;
      result = 261;
      break;

    case '/':
      lval->op = divide;
      result = 261;
      break;

    case '%':
      lval->op = module;
      result = 261;
      break;

    case '+':
      lval->op = plus;
      result = 260;
      break;

    case '-':
      lval->op = minus;
      result = 260;
      break;

    case 'n':
    case '?':
    case ':':
    case '(':
    case ')':

      break;

    case ';':
    case '\n':
    case '\0':

      --exp;
      result = 0;
      break;

    default:
      result = 256;



      break;
    }

  arg->cp = exp;

  return result;
}


static void
__gettexterror (struct parse_args *arg, const char *str)
{

}

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-15 10:29                     ` James Greenhalgh
@ 2018-08-15 15:04                       ` Richard Biener
  2018-08-15 15:51                       ` Martin Sebor
  1 sibling, 0 replies; 45+ messages in thread
From: Richard Biener @ 2018-08-15 15:04 UTC (permalink / raw)
  To: gcc-patches, James Greenhalgh, Martin Sebor
  Cc: Jason Merrill, Gcc Patch List, Joseph Myers, nd

On August 15, 2018 12:28:55 PM GMT+02:00, James Greenhalgh <James.Greenhalgh@arm.com> wrote:
>On Tue, Aug 14, 2018 at 09:34:08PM -0500, Martin Sebor wrote:
>> On 08/14/2018 09:24 AM, Martin Sebor wrote:
>> > On 08/14/2018 09:08 AM, Martin Sebor wrote:
>> >> On 08/14/2018 07:27 AM, James Greenhalgh wrote:
>> >>> On Wed, Aug 08, 2018 at 07:17:07PM -0500, Martin Sebor wrote:
>> >>>> On 08/08/2018 05:08 AM, Jason Merrill wrote:
>> >>>>> On Wed, Aug 8, 2018 at 9:04 AM, Martin Sebor <msebor@gmail.com>
>wrote:
>> >>>>>> On 08/07/2018 02:57 AM, Jason Merrill wrote:
>> >>>>>>>
>> >>>>>>> On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor
><msebor@gmail.com>
>> >>>>>>> wrote:
>> >>>>>>>>
>> >>>>>>>> On 07/31/2018 07:38 AM, Jason Merrill wrote:
>> >>>
>> >>> <snip>
>> >>>
>> >>>> Done in the attached patch.  I've also avoided dealing with
>> >>>> zero-length arrays and added tests to make sure their size
>> >>>> stays is regardless of the form of their initializer and
>> >>>> the appropriate warnings are issued.
>> >>>>
>> >>>> Using build_string() rather than build_string_literal() needed
>> >>>> a tweak in digest_init_r().  It didn't break anything but since
>> >>>> the array type may not have a domain yet, neither will the
>> >>>> string.  It looks like that may get adjusted later on but I've
>> >>>> temporarily guarded the code with #if 1.  If the change is
>> >>>> fine I'll remove the #if before committing.
>> >>>>
>> >>>> This initial patch only handles narrow character initializers
>> >>>> (i.e., those with TYPE_STRING_FLAG set).  Once this gets some
>> >>>> exposure I'd like to extend it to other character types,
>> >>>> including wchar_t.
>> >>>
>> >>> Hi Martin,
>> >>>
>> >>> This causes issues for the AArch64 tests (full list below).
>> >>>
>> >>> I see an error message on the following construct:
>> >>>
>> >>>   void foo (void)
>> >>>   {
>> >>>     __Poly8_t x[4] = { 1, 2, 3, 4 };
>> >>>   }
>> >>>
>> >>>   init.c:3:20: error: array of inappropriate type initialized
>from
>> >>> string constant
>> >>>   3 |   __Poly8_t x[4] = { 1, 2, 3, 4 };
>> >>>     |
>> >>>
>> >>> __Poly8_t is a type we define in our backend, through a
>convoluted
>> >>> set of
>> >>> functions, which operates a lot like an unsigned, QI mode type.
>> >>
>> >> I see the error with my aarch64 cross-compiler .  The new code
>> >> that does the conversion of array initializers to STRING_CSTs
>> >> looks for the TYPE_STRING_FLAG() to be set on the type of
>> >> the array elements.  Perhaps __Poly8_t should not have the flag
>> >> set?  (If it needs it then I think we'd have to only consider
>> >> named character types.)
>> >
>> > The change below gets rid of the compilation error.  I don't
>> > know if it's appropriate for the aarch64 back end:
>> >
>> > Index: gcc/config/aarch64/aarch64-builtins.c
>> > ===================================================================
>> > --- gcc/config/aarch64/aarch64-builtins.c    (revision 263537)
>> > +++ gcc/config/aarch64/aarch64-builtins.c    (working copy)
>> > @@ -643,6 +643,7 @@ aarch64_init_simd_builtin_types (void)
>> >    /* Poly types are a world of their own.  */
>> >    aarch64_simd_types[Poly8_t].eltype =
>aarch64_simd_types[Poly8_t].itype =
>> >      build_distinct_type_copy (unsigned_intQI_type_node);
>> > +  TYPE_STRING_FLAG (aarch64_simd_types[Poly8_t].eltype) = false;
>> >    aarch64_simd_types[Poly16_t].eltype =
>> > aarch64_simd_types[Poly16_t].itype =
>> >      build_distinct_type_copy (unsigned_intHI_type_node);
>> >    aarch64_simd_types[Poly64_t].eltype =
>> > aarch64_simd_types[Poly64_t].itype =
>
>This fix seems correct to me, the poly types are not strings. Looking
>at
>other uses of TYPE_STRING_FLAG this change doesn't seem like it would
>have
>impact on parsing or code generation.
>
>OK for trunk.
>
>> >>> A second set of tests fail due to changed inlining behaviour for
>> >>> functions
>> >>> with char array initialization:
>> >>>
>> >>>   gcc.target/aarch64/vset_lane_1.c
>> >>>   gcc.target/aarch64/vneg_s.c
>> >>>   gcc.target/aarch64/vclz.c
>> >>
>> >> I'm not sure what's going on here.  The tests are very big and
>> >> take forever to compile with an aarch64 cross-compiler, and I'm
>> >> not sure what to look for.  Can you provide a smaller test case
>> >> that shows the issue?
>> 
>> I wonder if these changes might be due to the same problem:
>> the tests define and initialize arrays of the Int8x16_t type
>> which is initialized to intQI_type_node, i.e., the signed
>> form of Poly8_t.  Does the conversion to STRING_CST cause
>> a performance degradation or is it just that the tests end
>> up with equivalent but slightly different assembly?
>
>These tests aren't looking at performance, just expecting to see
>certain
>instructions emitted. The only change is that now the int8x16_t forms
>are
>inlined (so the scan-assembler-times fails with two matches, one
>expected,
>one in the inlined function body copy).
>
>The difference seems to be in the initialization cost of the input data
>set.
>
>Before your patch:
>
>  int8_tD.3359 test_set0D.21541[8];
>  int8_tD.3359 answ_set0D.21542[8];
>
>      test_set0D.21541[0] = 0;
>      test_set0D.21541[1] = 1;
>      test_set0D.21541[2] = -1;
>      test_set0D.21541[3] = 10;
>      test_set0D.21541[4] = -10;
>      test_set0D.21541[5] = 0;
>      test_set0D.21541[6] = 127;
>      test_set0D.21541[7] = -128;
>      answ_set0D.21542[0] = 0;
>      answ_set0D.21542[1] = -1;
>      answ_set0D.21542[2] = 1;
>      answ_set0D.21542[3] = -10;
>      answ_set0D.21542[4] = 10;
>      answ_set0D.21542[5] = 0;
>      answ_set0D.21542[6] = -127;
>      answ_set0D.21542[7] = -128;
>
>After your patch:
>
>  int8_tD.3357 test_set0D.21539[8];
>  int8_tD.3357 answ_set0D.21540[8];
>
>      test_set0D.21539 = "";
>      answ_set0D.21540 = "";

Can we fix printing of string literals to include non-printable chars please? The above looks like wrong-code though it probably isn't. When Martin L. proposed a similar patch I was suggesting to restrict conversion to initializes with only printable characters. 

>I think that is probably what you expected to happen; but the impact on
>inlining might not have been.

It's more the effect of changed gimplification that shows, the inlining is a 2nd order effect. 

Richard. 

 Probably, we want to just change these
>tests
>to explicitly disable inlining. The tests appear to execute correctly.
>
>The print in the dump file is a bit unusual; presumably the impact of
>having
>non-printing characters in my initializer list - but less helpful
>output for
>it.
>
>Off topic; these tests are quick to copmpile on my cross and native
>compilers. Do you have additional checking enabled?
>
>Thanks,
>James
>
>> 
>> The tests also use int8_t and uint8_t for the expected results.
>> Those are typedefs for signed and unsigned char, respectively.
>> Is the conversion to strings for those fine?
>> 
>> Martin

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-15 10:29                     ` James Greenhalgh
  2018-08-15 15:04                       ` Richard Biener
@ 2018-08-15 15:51                       ` Martin Sebor
  2018-08-17 17:19                         ` [PATCH] Fix poly types after PR tree-optimization/71625 strlen optimization Szabolcs Nagy
  1 sibling, 1 reply; 45+ messages in thread
From: Martin Sebor @ 2018-08-15 15:51 UTC (permalink / raw)
  To: James Greenhalgh; +Cc: Jason Merrill, Gcc Patch List, Joseph Myers, nd

On 08/15/2018 04:28 AM, James Greenhalgh wrote:
> On Tue, Aug 14, 2018 at 09:34:08PM -0500, Martin Sebor wrote:
>> On 08/14/2018 09:24 AM, Martin Sebor wrote:
>>> On 08/14/2018 09:08 AM, Martin Sebor wrote:
>>>> On 08/14/2018 07:27 AM, James Greenhalgh wrote:
>>>>> On Wed, Aug 08, 2018 at 07:17:07PM -0500, Martin Sebor wrote:
>>>>>> On 08/08/2018 05:08 AM, Jason Merrill wrote:
>>>>>>> On Wed, Aug 8, 2018 at 9:04 AM, Martin Sebor <msebor@gmail.com> wrote:
>>>>>>>> On 08/07/2018 02:57 AM, Jason Merrill wrote:
>>>>>>>>>
>>>>>>>>> On Wed, Aug 1, 2018 at 12:49 AM, Martin Sebor <msebor@gmail.com>
>>>>>>>>> wrote:
>>>>>>>>>>
>>>>>>>>>> On 07/31/2018 07:38 AM, Jason Merrill wrote:
>>>>>
>>>>> <snip>
>>>>>
>>>>>> Done in the attached patch.  I've also avoided dealing with
>>>>>> zero-length arrays and added tests to make sure their size
>>>>>> stays is regardless of the form of their initializer and
>>>>>> the appropriate warnings are issued.
>>>>>>
>>>>>> Using build_string() rather than build_string_literal() needed
>>>>>> a tweak in digest_init_r().  It didn't break anything but since
>>>>>> the array type may not have a domain yet, neither will the
>>>>>> string.  It looks like that may get adjusted later on but I've
>>>>>> temporarily guarded the code with #if 1.  If the change is
>>>>>> fine I'll remove the #if before committing.
>>>>>>
>>>>>> This initial patch only handles narrow character initializers
>>>>>> (i.e., those with TYPE_STRING_FLAG set).  Once this gets some
>>>>>> exposure I'd like to extend it to other character types,
>>>>>> including wchar_t.
>>>>>
>>>>> Hi Martin,
>>>>>
>>>>> This causes issues for the AArch64 tests (full list below).
>>>>>
>>>>> I see an error message on the following construct:
>>>>>
>>>>>   void foo (void)
>>>>>   {
>>>>>     __Poly8_t x[4] = { 1, 2, 3, 4 };
>>>>>   }
>>>>>
>>>>>   init.c:3:20: error: array of inappropriate type initialized from
>>>>> string constant
>>>>>   3 |   __Poly8_t x[4] = { 1, 2, 3, 4 };
>>>>>     |
>>>>>
>>>>> __Poly8_t is a type we define in our backend, through a convoluted
>>>>> set of
>>>>> functions, which operates a lot like an unsigned, QI mode type.
>>>>
>>>> I see the error with my aarch64 cross-compiler .  The new code
>>>> that does the conversion of array initializers to STRING_CSTs
>>>> looks for the TYPE_STRING_FLAG() to be set on the type of
>>>> the array elements.  Perhaps __Poly8_t should not have the flag
>>>> set?  (If it needs it then I think we'd have to only consider
>>>> named character types.)
>>>
>>> The change below gets rid of the compilation error.  I don't
>>> know if it's appropriate for the aarch64 back end:
>>>
>>> Index: gcc/config/aarch64/aarch64-builtins.c
>>> ===================================================================
>>> --- gcc/config/aarch64/aarch64-builtins.c    (revision 263537)
>>> +++ gcc/config/aarch64/aarch64-builtins.c    (working copy)
>>> @@ -643,6 +643,7 @@ aarch64_init_simd_builtin_types (void)
>>>    /* Poly types are a world of their own.  */
>>>    aarch64_simd_types[Poly8_t].eltype = aarch64_simd_types[Poly8_t].itype =
>>>      build_distinct_type_copy (unsigned_intQI_type_node);
>>> +  TYPE_STRING_FLAG (aarch64_simd_types[Poly8_t].eltype) = false;
>>>    aarch64_simd_types[Poly16_t].eltype =
>>> aarch64_simd_types[Poly16_t].itype =
>>>      build_distinct_type_copy (unsigned_intHI_type_node);
>>>    aarch64_simd_types[Poly64_t].eltype =
>>> aarch64_simd_types[Poly64_t].itype =
>
> This fix seems correct to me, the poly types are not strings. Looking at
> other uses of TYPE_STRING_FLAG this change doesn't seem like it would have
> impact on parsing or code generation.
>
> OK for trunk.

I committed this in r263561.

>>>>> A second set of tests fail due to changed inlining behaviour for
>>>>> functions
>>>>> with char array initialization:
>>>>>
>>>>>   gcc.target/aarch64/vset_lane_1.c
>>>>>   gcc.target/aarch64/vneg_s.c
>>>>>   gcc.target/aarch64/vclz.c
>>>>
>>>> I'm not sure what's going on here.  The tests are very big and
>>>> take forever to compile with an aarch64 cross-compiler, and I'm
>>>> not sure what to look for.  Can you provide a smaller test case
>>>> that shows the issue?
>>
>> I wonder if these changes might be due to the same problem:
>> the tests define and initialize arrays of the Int8x16_t type
>> which is initialized to intQI_type_node, i.e., the signed
>> form of Poly8_t.  Does the conversion to STRING_CST cause
>> a performance degradation or is it just that the tests end
>> up with equivalent but slightly different assembly?
>
> These tests aren't looking at performance, just expecting to see certain
> instructions emitted. The only change is that now the int8x16_t forms are
> inlined (so the scan-assembler-times fails with two matches, one expected,
> one in the inlined function body copy).
>
> The difference seems to be in the initialization cost of the input data set.
>
> Before your patch:
>
>   int8_tD.3359 test_set0D.21541[8];
>   int8_tD.3359 answ_set0D.21542[8];
>
>       test_set0D.21541[0] = 0;
>       test_set0D.21541[1] = 1;
>       test_set0D.21541[2] = -1;
>       test_set0D.21541[3] = 10;
>       test_set0D.21541[4] = -10;
>       test_set0D.21541[5] = 0;
>       test_set0D.21541[6] = 127;
>       test_set0D.21541[7] = -128;
>       answ_set0D.21542[0] = 0;
>       answ_set0D.21542[1] = -1;
>       answ_set0D.21542[2] = 1;
>       answ_set0D.21542[3] = -10;
>       answ_set0D.21542[4] = 10;
>       answ_set0D.21542[5] = 0;
>       answ_set0D.21542[6] = -127;
>       answ_set0D.21542[7] = -128;
>
> After your patch:
>
>   int8_tD.3357 test_set0D.21539[8];
>   int8_tD.3357 answ_set0D.21540[8];
>
>       test_set0D.21539 = "";
>       answ_set0D.21540 = "";
>
> I think that is probably what you expected to happen; but the impact on
> inlining might not have been. Probably, we want to just change these tests
> to explicitly disable inlining. The tests appear to execute correctly.
>
> The print in the dump file is a bit unusual; presumably the impact of having
> non-printing characters in my initializer list - but less helpful output for
> it.

I agree it's less than helpful.  It's not the result of this
change.  The output is the same for string literals.  E.g., for
this:

   void f (void*, ...);

   void g (void)
   {
     char a[] = { 0, 1, 2, 3 };
     char b[] = "\000\001\002\003";
     f (a, b);
   }

we get the following on trunk:

   <bb 2> [local count: 1073741825]:
   a = "";
   b = "";
   f (&a, &b);

and the following with GCC 8:

   MEM[(char[4] *)&a] = 50462976;
   b = "";
   f (&a, &b);

I'll see if I can quickly tweak things to include all characters
in the output.

> Off topic; these tests are quick to copmpile on my cross and native
> compilers. Do you have additional checking enabled?

Yes, I did have --enable-checking=all set that I forgot about.
With it, gcc.target/aarch64/advsimd-intrinsics/vmax.c takes
2m 21sec to compile without optimization.  The
gcc.target/aarch64/vclz.c test takes 1m 45sec at -O3.

Removing --enable-checking=all reduced the compile times for
the two tests to just over a second.

Martin

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-15 12:07                   ` Joseph Myers
@ 2018-08-15 21:02                     ` Martin Sebor
  2018-08-15 21:14                       ` Jeff Law
  2018-08-15 21:34                       ` Jeff Law
  0 siblings, 2 replies; 45+ messages in thread
From: Martin Sebor @ 2018-08-15 21:02 UTC (permalink / raw)
  To: Joseph Myers; +Cc: James Greenhalgh, Jason Merrill, Gcc Patch List, nd

[-- Attachment #1: Type: text/plain, Size: 3705 bytes --]

On 08/15/2018 06:07 AM, Joseph Myers wrote:
> On Tue, 14 Aug 2018, Martin Sebor wrote:
>
>>> This is with Bison 3.0.4, should the version used to produce intl/plural.c
>>> prove relevant.
>>
>> Can you send me the translation unit and the options it was compiled
>> with that triggered the errors?
>
> I've attached plural.i.  The error is a static link error linking sln, but
> maybe comparing results of compiling plural.i before and after the changes
> may be enlightening (unless it's actually a difference in code elsewhere
> in glibc causing a link error reported in plural.o).
>
> Compiled with:
>
> alpha-glibc-linux-gnu-gcc
> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c
> -c -std=gnu11 -fgnu89-inline  -O2 -Wall -Werror -Wundef -Wwrite-strings
> -fmerge-all-constants -fno-stack-protector -frounding-math -g
> -Wstrict-prototypes -Wold-style-definition -fno-math-errno
> -mlong-double-128 -mieee -mfp-rounding-mode=d     -ftls-model=initial-exec
> -I../include
> -I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl
> -I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu
> -I../sysdeps/unix/sysv/linux/alpha/alpha
> -I../sysdeps/unix/sysv/linux/alpha/fpu  -I../sysdeps/alpha/fpu
> -I../sysdeps/unix/sysv/linux/alpha  -I../sysdeps/alpha/nptl
> -I../sysdeps/unix/sysv/linux/wordsize-64  -I../sysdeps/ieee754/ldbl-64-128
> -I../sysdeps/ieee754/ldbl-opt  -I../sysdeps/unix/sysv/linux/include
> -I../sysdeps/unix/sysv/linux  -I../sysdeps/nptl  -I../sysdeps/pthread
> -I../sysdeps/gnu  -I../sysdeps/unix/inet  -I../sysdeps/unix/sysv
> -I../sysdeps/unix/alpha  -I../sysdeps/unix  -I../sysdeps/posix
> -I../sysdeps/alpha  -I../sysdeps/wordsize-64
> -I../sysdeps/ieee754/ldbl-128  -I../sysdeps/ieee754/dbl-64/wordsize-64
> -I../sysdeps/ieee754/dbl-64  -I../sysdeps/ieee754/flt-32
> -I../sysdeps/ieee754  -I../sysdeps/generic  -I.. -I../libio -I.
> -D_LIBC_REENTRANT -include
> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/libc-modules.h
> -DMODULE_NAME=libc -include ../include/libc-symbols.h
> -DTOP_NAMESPACE=glibc -D'LOCALEDIR="/usr/share/locale"'
> -D'LOCALE_ALIAS_PATH="/usr/share/locale"' -o
> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o
> -MD -MP -MF
> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o.dt
> -MT
> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o
>

Thanks.  I don't see anything obviously wrong but I don't know
much about Alpha assembly.  Attached are the two .s files, with
(plural-new.s) and without (plural-old.s) the array-to-string
transformation.

There are also only a handful of transformed arrays in the file
and they all look reasonable to me (see the attachment named
plural-array-to-string.txt).  The only arrays in the .sdata
section are yydefgoto and yypgoto, both before and after.
They are each just 3 bytes in size.

There is one unusual difference in the loads of one of them in
the assembly emitted by GCC for __gettextparse.

Before:

	ldah $22,yypgoto($29)				!gprelhigh
	...
	lda $2,yypgoto($22)				!gprellow

After:

	ldah $2,yypgoto+2305843009213693936($29)	!gprelhigh
	...
	lda $2,yypgoto+2305843009213693936($2)		!gprellow

I don't know if it's significant -- the lda instruction uses
just the least significant 16 bits of the constant displacement,
shifted left by 16.  I don't see any obviously bogus constants
in the disassembly produced by objdump.

I'll need some help from someone who knows more about Alpha
to understand what's going on.

Martin

[-- Attachment #2: plural-old.s --]
[-- Type: text/plain, Size: 29233 bytes --]


plural-old.o:     file format elf64-alpha


Disassembly of section .text:

0000000000000000 <__gettext_free_exp>:
   0:	00 00 bb 27 	ldah	gp,0(t12)
   4:	00 00 bd 23 	lda	gp,0(gp)
   8:	f0 ff de 23 	lda	sp,-16(sp)
   c:	08 00 3e b5 	stq	s0,8(sp)
  10:	09 04 f0 47 	mov	a0,s0
  14:	00 00 5e b7 	stq	ra,0(sp)
  18:	11 00 00 e6 	beq	a0,60 <__gettext_free_exp+0x60>
  1c:	00 00 30 a0 	ldl	t0,0(a0)
  20:	a2 5d 20 40 	cmple	t0,0x2,t1
  24:	12 00 40 e4 	beq	t1,70 <__gettext_free_exp+0x70>
  28:	a2 55 20 40 	cmpeq	t0,0x2,t1
  2c:	17 00 40 f4 	bne	t1,8c <__gettext_free_exp+0x8c>
  30:	a1 35 20 40 	cmpeq	t0,0x1,t0
  34:	05 00 20 e4 	beq	t0,4c <__gettext_free_exp+0x4c>
  38:	08 00 09 a6 	ldq	a0,8(s0)
  3c:	00 00 7d a7 	ldq	t12,0(gp)
  40:	00 40 5b 6b 	jsr	ra,(t12),44 <__gettext_free_exp+0x44>
  44:	00 00 ba 27 	ldah	gp,0(ra)
  48:	00 00 bd 23 	lda	gp,0(gp)
  4c:	10 04 e9 47 	mov	s0,a0
  50:	00 00 7d a7 	ldq	t12,0(gp)
  54:	00 40 5b 6b 	jsr	ra,(t12),58 <__gettext_free_exp+0x58>
  58:	00 00 ba 27 	ldah	gp,0(ra)
  5c:	00 00 bd 23 	lda	gp,0(gp)
  60:	00 00 5e a7 	ldq	ra,0(sp)
  64:	08 00 3e a5 	ldq	s0,8(sp)
  68:	10 00 de 23 	lda	sp,16(sp)
  6c:	01 80 fa 6b 	ret
  70:	a1 75 20 40 	cmpeq	t0,0x3,t0
  74:	f5 ff 3f e4 	beq	t0,4c <__gettext_free_exp+0x4c>
  78:	18 00 10 a6 	ldq	a0,24(a0)
  7c:	00 00 7d a7 	ldq	t12,0(gp)
  80:	00 40 5b 6b 	jsr	ra,(t12),84 <__gettext_free_exp+0x84>
  84:	00 00 ba 27 	ldah	gp,0(ra)
  88:	00 00 bd 23 	lda	gp,0(gp)
  8c:	10 00 09 a6 	ldq	a0,16(s0)
  90:	00 00 7d a7 	ldq	t12,0(gp)
  94:	00 40 5b 6b 	jsr	ra,(t12),98 <__gettext_free_exp+0x98>
  98:	00 00 ba 27 	ldah	gp,0(ra)
  9c:	00 00 bd 23 	lda	gp,0(gp)
  a0:	e5 ff ff c3 	br	38 <__gettext_free_exp+0x38>
  a4:	00 00 fe 2f 	unop	
  a8:	1f 04 ff 47 	nop	
  ac:	00 00 fe 2f 	unop	

00000000000000b0 <new_exp>:
  b0:	00 00 bb 27 	ldah	gp,0(t12)
  b4:	00 00 bd 23 	lda	gp,0(gp)
  b8:	d0 ff de 23 	lda	sp,-48(sp)
  bc:	08 00 3e b5 	stq	s0,8(sp)
  c0:	29 31 00 42 	subl	a0,0x1,s0
  c4:	10 00 5e b5 	stq	s1,16(sp)
  c8:	01 00 29 20 	lda	t0,1(s0)
  cc:	18 00 7e b5 	stq	s2,24(sp)
  d0:	0a 04 f2 47 	mov	a2,s1
  d4:	20 00 9e b5 	stq	s3,32(sp)
  d8:	0b 04 f0 47 	mov	a0,s2
  dc:	00 00 5e b7 	stq	ra,0(sp)
  e0:	0c 04 f1 47 	mov	a1,s3
  e4:	35 00 20 e4 	beq	t0,1bc <new_exp+0x10c>
  e8:	01 04 e9 47 	mov	s0,t0
  ec:	01 00 e0 c3 	br	f4 <new_exp+0x44>
  f0:	1b 00 40 e4 	beq	t1,160 <new_exp+0xb0>
  f4:	43 06 2a 40 	s8addq	t0,s1,t2
  f8:	ff ff 21 20 	lda	t0,-1(t0)
  fc:	02 00 e1 43 	sextl	t0,t1
 100:	00 00 63 a4 	ldq	t2,0(t2)
 104:	01 00 42 20 	lda	t1,1(t1)
 108:	f9 ff 7f f4 	bne	t2,f0 <new_exp+0x40>
 10c:	00 00 fe 2f 	unop	
 110:	41 06 2a 41 	s8addq	s0,s1,t0
 114:	ff ff 29 21 	lda	s0,-1(s0)
 118:	00 00 01 a6 	ldq	a0,0(t0)
 11c:	00 00 7d a7 	ldq	t12,0(gp)
 120:	00 40 5b 6b 	jsr	ra,(t12),124 <new_exp+0x74>
 124:	00 00 ba 27 	ldah	gp,0(ra)
 128:	00 00 bd 23 	lda	gp,0(gp)
 12c:	01 00 e9 43 	sextl	s0,t0
 130:	01 00 21 20 	lda	t0,1(t0)
 134:	f6 ff 3f f4 	bne	t0,110 <new_exp+0x60>
 138:	00 00 5e a7 	ldq	ra,0(sp)
 13c:	08 00 3e a5 	ldq	s0,8(sp)
 140:	10 00 5e a5 	ldq	s1,16(sp)
 144:	18 00 7e a5 	ldq	s2,24(sp)
 148:	00 04 ff 47 	clr	v0
 14c:	20 00 9e a5 	ldq	s3,32(sp)
 150:	30 00 de 23 	lda	sp,48(sp)
 154:	01 80 fa 6b 	ret
 158:	1f 04 ff 47 	nop	
 15c:	00 00 fe 2f 	unop	
 160:	20 00 1f 22 	lda	a0,32
 164:	00 00 7d a7 	ldq	t12,0(gp)
 168:	00 40 5b 6b 	jsr	ra,(t12),16c <new_exp+0xbc>
 16c:	00 00 ba 27 	ldah	gp,0(ra)
 170:	00 00 bd 23 	lda	gp,0(gp)
 174:	e6 ff 1f e4 	beq	v0,110 <new_exp+0x60>
 178:	00 00 60 b1 	stl	s2,0(v0)
 17c:	04 00 80 b1 	stl	s3,4(v0)
 180:	41 06 2a 41 	s8addq	s0,s1,t0
 184:	42 06 20 41 	s8addq	s0,v0,t1
 188:	ff ff 29 21 	lda	s0,-1(s0)
 18c:	00 00 61 a4 	ldq	t2,0(t0)
 190:	01 00 e9 43 	sextl	s0,t0
 194:	01 00 21 20 	lda	t0,1(t0)
 198:	08 00 62 b4 	stq	t2,8(t1)
 19c:	f8 ff 3f f4 	bne	t0,180 <new_exp+0xd0>
 1a0:	00 00 5e a7 	ldq	ra,0(sp)
 1a4:	08 00 3e a5 	ldq	s0,8(sp)
 1a8:	10 00 5e a5 	ldq	s1,16(sp)
 1ac:	18 00 7e a5 	ldq	s2,24(sp)
 1b0:	20 00 9e a5 	ldq	s3,32(sp)
 1b4:	30 00 de 23 	lda	sp,48(sp)
 1b8:	01 80 fa 6b 	ret
 1bc:	20 00 1f 22 	lda	a0,32
 1c0:	00 00 7d a7 	ldq	t12,0(gp)
 1c4:	00 40 5b 6b 	jsr	ra,(t12),1c8 <new_exp+0x118>
 1c8:	00 00 ba 27 	ldah	gp,0(ra)
 1cc:	00 00 bd 23 	lda	gp,0(gp)
 1d0:	d9 ff 1f e4 	beq	v0,138 <new_exp+0x88>
 1d4:	04 00 80 b1 	stl	s3,4(v0)
 1d8:	00 00 5e a7 	ldq	ra,0(sp)
 1dc:	08 00 3e a5 	ldq	s0,8(sp)
 1e0:	10 00 5e a5 	ldq	s1,16(sp)
 1e4:	18 00 7e a5 	ldq	s2,24(sp)
 1e8:	20 00 9e a5 	ldq	s3,32(sp)
 1ec:	00 00 e0 b3 	stl	zero,0(v0)
 1f0:	30 00 de 23 	lda	sp,48(sp)
 1f4:	01 80 fa 6b 	ret
 1f8:	1f 04 ff 47 	nop	
 1fc:	00 00 fe 2f 	unop	

0000000000000200 <__gettextparse>:
 200:	00 00 bb 27 	ldah	gp,0(t12)
 204:	00 00 bd 23 	lda	gp,0(gp)
 208:	90 f7 de 23 	lda	sp,-2160(sp)
 20c:	00 00 9d 24 	ldah	t3,0(gp)
 210:	80 06 3e a0 	ldl	t0,1664(sp)
 214:	08 00 3e b5 	stq	s0,8(sp)
 218:	80 06 3e 21 	lda	s0,1664(sp)
 21c:	10 00 5e b5 	stq	s1,16(sp)
 220:	40 00 5e 21 	lda	s1,64(sp)
 224:	21 96 3f 48 	zapnot	t0,0xfc,t0
 228:	20 00 9e b5 	stq	s3,32(sp)
 22c:	00 00 9d 25 	ldah	s3,0(gp)
 230:	18 00 7e b5 	stq	s2,24(sp)
 234:	28 00 be b5 	stq	s4,40(sp)
 238:	fe ff bf 20 	lda	t4,-2
 23c:	38 00 fe b5 	stq	fp,56(sp)
 240:	c8 00 7f 21 	lda	s2,200
 244:	80 06 3e b0 	stl	t0,1664(sp)
 248:	0f 04 ea 47 	mov	s1,fp
 24c:	01 04 ff 47 	clr	t0
 250:	00 00 5e b7 	stq	ra,0(sp)
 254:	0d 04 e9 47 	mov	s0,s4
 258:	30 00 de b5 	stq	s5,48(sp)
 25c:	00 00 84 20 	lda	t3,0(t3)
 260:	40 08 1e b6 	stq	a0,2112(sp)
 264:	00 00 8c 21 	lda	s3,0(s3)
 268:	38 08 fe b7 	stq	zero,2104(sp)
 26c:	30 08 3e b5 	stq	s0,2096(sp)
 270:	02 04 81 40 	addq	t3,t0,t1
 274:	01 00 c2 20 	lda	t5,1(t1)
 278:	00 00 e2 2c 	ldq_u	t6,0(t1)
 27c:	47 0f e6 48 	extqh	t6,t5,t6
 280:	87 17 e7 48 	sra	t6,0x38,t6
 284:	0a 00 47 20 	lda	t1,10(t6)
 288:	1d 00 40 e4 	beq	t1,300 <__gettextparse+0x100>
 28c:	02 00 45 20 	lda	t1,2(t4)
 290:	17 01 40 e4 	beq	t1,6f0 <__gettextparse+0x4f0>
 294:	86 00 a0 ec 	ble	t4,4b0 <__gettextparse+0x2b0>
 298:	00 00 5d 24 	ldah	t1,0(gp)
 29c:	00 00 42 20 	lda	t1,0(t1)
 2a0:	02 04 a2 40 	addq	t4,t1,t1
 2a4:	00 00 02 2d 	ldq_u	t7,0(t1)
 2a8:	c8 00 02 49 	extbl	t7,t1,t7
 2ac:	07 00 e8 40 	addl	t6,t7,t6
 2b0:	26 f6 e1 48 	zapnot	t6,0xf,t5
 2b4:	a6 d7 c6 40 	cmpule	t5,0x36,t5
 2b8:	11 00 c0 e4 	beq	t5,300 <__gettextparse+0x100>
 2bc:	06 04 ec 40 	addq	t6,s3,t5
 2c0:	01 00 c6 22 	lda	t8,1(t5)
 2c4:	00 00 46 2c 	ldq_u	t1,0(t5)
 2c8:	42 0f 56 48 	extqh	t1,t8,t1
 2cc:	82 17 47 48 	sra	t1,0x38,t1
 2d0:	a2 05 48 40 	cmpeq	t1,t7,t1
 2d4:	0a 00 40 e4 	beq	t1,300 <__gettextparse+0x100>
 2d8:	00 00 3d 24 	ldah	t0,0(gp)
 2dc:	00 00 21 20 	lda	t0,0(t0)
 2e0:	07 04 e1 40 	addq	t6,t0,t6
 2e4:	00 00 27 2c 	ldq_u	t0,0(t6)
 2e8:	c1 00 27 48 	extbl	t0,t6,t0
 2ec:	20 01 20 f4 	bne	t0,770 <__gettextparse+0x570>
 2f0:	08 04 ea 47 	mov	s1,t7
 2f4:	08 00 0a a4 	ldq	v0,8(s1)
 2f8:	f0 ff ff 20 	lda	t6,-16
 2fc:	8d 00 e0 c3 	br	534 <__gettextparse+0x334>
 300:	00 00 5d 24 	ldah	t1,0(gp)
 304:	00 00 42 20 	lda	t1,0(t1)
 308:	02 04 22 40 	addq	t0,t1,t1
 30c:	00 00 c2 2c 	ldq_u	t5,0(t1)
 310:	c2 00 c2 48 	extbl	t5,t1,t1
 314:	08 00 e2 43 	sextl	t1,t7
 318:	45 00 40 f4 	bne	t1,430 <__gettextparse+0x230>
 31c:	38 08 5e a4 	ldq	t1,2104(sp)
 320:	ae 75 40 40 	cmpeq	t1,0x3,s5
 324:	16 00 c0 e5 	beq	s5,380 <__gettextparse+0x180>
 328:	1d 01 a0 fc 	bgt	t4,7a0 <__gettextparse+0x5a0>
 32c:	14 00 a0 f4 	bne	t4,380 <__gettextparse+0x180>
 330:	09 04 ed 47 	mov	s4,s0
 334:	01 00 5f 21 	lda	s1,1
 338:	27 00 e0 c3 	br	3d8 <__gettextparse+0x1d8>
 33c:	00 00 fe 2f 	unop	
 340:	00 00 5d 24 	ldah	t1,0(gp)
 344:	00 00 42 20 	lda	t1,0(t1)
 348:	01 04 22 40 	addq	t0,t1,t0
 34c:	00 00 41 2c 	ldq_u	t1,0(t0)
 350:	c1 00 41 48 	extbl	t1,t0,t0
 354:	9d 01 20 f4 	bne	t0,9cc <__gettextparse+0x7cc>
 358:	1f 04 ff 47 	nop	
 35c:	00 00 fe 2f 	unop	
 360:	a1 05 2d 41 	cmpeq	s0,s4,t0
 364:	1b 00 20 f4 	bne	t0,3d4 <__gettextparse+0x1d4>
 368:	fe ff 29 21 	lda	s0,-2(s0)
 36c:	02 00 49 20 	lda	t1,2(s0)
 370:	f8 ff 4a 21 	lda	s1,-8(s1)
 374:	00 00 29 2c 	ldq_u	t0,0(s0)
 378:	41 0f 22 48 	extqh	t0,t1,t0
 37c:	81 17 26 48 	sra	t0,0x30,t0
 380:	01 04 81 40 	addq	t3,t0,t0
 384:	01 00 41 20 	lda	t1,1(t0)
 388:	00 00 21 2c 	ldq_u	t0,0(t0)
 38c:	41 0f 22 48 	extqh	t0,t1,t0
 390:	81 17 27 48 	sra	t0,0x38,t0
 394:	0a 00 41 20 	lda	t1,10(t0)
 398:	f1 ff 5f e4 	beq	t1,360 <__gettextparse+0x160>
 39c:	01 30 20 40 	addl	t0,0x1,t0
 3a0:	22 f6 21 48 	zapnot	t0,0xf,t1
 3a4:	01 00 e1 43 	sextl	t0,t0
 3a8:	a2 d7 46 40 	cmpule	t1,0x36,t1
 3ac:	ec ff 5f e4 	beq	t1,360 <__gettextparse+0x160>
 3b0:	06 04 2c 40 	addq	t0,s3,t5
 3b4:	01 00 e6 20 	lda	t6,1(t5)
 3b8:	00 00 46 2c 	ldq_u	t1,0(t5)
 3bc:	42 0f 47 48 	extqh	t1,t6,t1
 3c0:	82 17 47 48 	sra	t1,0x38,t1
 3c4:	a2 35 40 40 	cmpeq	t1,0x1,t1
 3c8:	dd ff 5f f4 	bne	t1,340 <__gettextparse+0x140>
 3cc:	a1 05 2d 41 	cmpeq	s0,s4,t0
 3d0:	e5 ff 3f e4 	beq	t0,368 <__gettextparse+0x168>
 3d4:	01 00 5f 21 	lda	s1,1
 3d8:	30 08 7e a4 	ldq	t2,2096(sp)
 3dc:	a1 05 23 41 	cmpeq	s0,t2,t0
 3e0:	05 00 20 f4 	bne	t0,3f8 <__gettextparse+0x1f8>
 3e4:	10 04 e9 47 	mov	s0,a0
 3e8:	00 00 7d a7 	ldq	t12,0(gp)
 3ec:	00 40 5b 6b 	jsr	ra,(t12),3f0 <__gettextparse+0x1f0>
 3f0:	00 00 ba 27 	ldah	gp,0(ra)
 3f4:	00 00 bd 23 	lda	gp,0(gp)
 3f8:	00 04 ea 47 	mov	s1,v0
 3fc:	00 00 5e a7 	ldq	ra,0(sp)
 400:	08 00 3e a5 	ldq	s0,8(sp)
 404:	10 00 5e a5 	ldq	s1,16(sp)
 408:	18 00 7e a5 	ldq	s2,24(sp)
 40c:	20 00 9e a5 	ldq	s3,32(sp)
 410:	28 00 be a5 	ldq	s4,40(sp)
 414:	30 00 de a5 	ldq	s5,48(sp)
 418:	38 00 fe a5 	ldq	fp,56(sp)
 41c:	70 08 de 23 	lda	sp,2160(sp)
 420:	01 80 fa 6b 	ret
 424:	00 00 fe 2f 	unop	
 428:	1f 04 ff 47 	nop	
 42c:	00 00 fe 2f 	unop	
 430:	00 00 3d 24 	ldah	t0,0(gp)
 434:	00 00 21 20 	lda	t0,0(t0)
 438:	01 04 01 41 	addq	t7,t0,t0
 43c:	a7 b7 41 40 	cmpule	t1,0xd,t6
 440:	00 00 c1 2c 	ldq_u	t5,0(t0)
 444:	c1 00 c1 48 	extbl	t5,t0,t0
 448:	01 00 df 20 	lda	t5,1
 44c:	26 01 c1 40 	subl	t5,t0,t5
 450:	46 06 ca 40 	s8addq	t5,s1,t5
 454:	00 00 06 a4 	ldq	v0,0(t5)
 458:	19 00 e0 f4 	bne	t6,4c0 <__gettextparse+0x2c0>
 45c:	00 00 5d 24 	ldah	t1,0(gp)
 460:	00 00 42 20 	lda	t1,0(t1)
 464:	02 04 02 41 	addq	t7,t1,t1
 468:	00 00 dd 26 	ldah	t8,0(gp)
 46c:	48 16 20 40 	s8addq	t0,0,t7
 470:	00 00 e2 2c 	ldq_u	t6,0(t1)
 474:	01 04 21 40 	addq	t0,t0,t0
 478:	29 05 21 41 	subq	s0,t0,s0
 47c:	c2 00 e2 48 	extbl	t6,t1,t1
 480:	28 05 48 41 	subq	s1,t7,t7
 484:	27 11 42 40 	subl	t1,0x10,t6
 488:	00 00 56 20 	lda	t1,0(t8)
 48c:	02 04 e2 40 	addq	t6,t1,t1
 490:	01 00 c2 20 	lda	t5,1(t1)
 494:	00 00 22 2c 	ldq_u	t0,0(t1)
 498:	41 0f 26 48 	extqh	t0,t5,t0
 49c:	81 17 27 48 	sra	t0,0x38,t0
 4a0:	24 00 e0 c3 	br	534 <__gettextparse+0x334>
 4a4:	00 00 fe 2f 	unop	
 4a8:	1f 04 ff 47 	nop	
 4ac:	00 00 fe 2f 	unop	
 4b0:	08 04 ff 47 	clr	t7
 4b4:	05 04 ff 47 	clr	t4
 4b8:	7d ff ff c3 	br	2b0 <__gettextparse+0xb0>
 4bc:	00 00 fe 2f 	unop	
 4c0:	00 00 dd 24 	ldah	t5,0(gp)
 4c4:	00 00 c6 20 	lda	t5,0(t5)
 4c8:	42 04 46 40 	s4addq	t1,t5,t1
 4cc:	00 00 42 a0 	ldl	t1,0(t1)
 4d0:	02 04 a2 43 	addq	gp,t1,t1
 4d4:	00 00 e2 6b 	jmp	(t1)
 4d8:	1f 04 ff 47 	nop	
 4dc:	00 00 fe 2f 	unop	
 4e0:	10 08 5e 22 	lda	a2,2064(sp)
 4e4:	f8 ff 2a a2 	ldl	a1,-8(s1)
 4e8:	00 00 4a a4 	ldq	t1,0(s1)
 4ec:	f0 ff 2a a4 	ldq	t0,-16(s1)
 4f0:	10 08 3e b4 	stq	t0,2064(sp)
 4f4:	02 00 1f 22 	lda	a0,2
 4f8:	ff ff 3f 20 	lda	t0,-1
 4fc:	68 08 9e b4 	stq	t3,2152(sp)
 500:	58 08 3e b4 	stq	t0,2136(sp)
 504:	fa ff 29 21 	lda	s0,-6(s0)
 508:	60 08 be b4 	stq	t4,2144(sp)
 50c:	18 08 5e b4 	stq	t1,2072(sp)
 510:	00 00 7d a7 	ldq	t12,0(gp)
 514:	00 40 5b 6b 	jsr	ra,(t12),518 <__gettextparse+0x318>
 518:	00 00 ba 27 	ldah	gp,0(ra)
 51c:	00 00 bd 23 	lda	gp,0(gp)
 520:	e8 ff 0a 21 	lda	t7,-24(s1)
 524:	58 08 3e a4 	ldq	t0,2136(sp)
 528:	02 00 ff 20 	lda	t6,2
 52c:	68 08 9e a4 	ldq	t3,2152(sp)
 530:	60 08 be a4 	ldq	t4,2144(sp)
 534:	08 00 08 b4 	stq	v0,8(t7)
 538:	02 00 49 20 	lda	t1,2(s0)
 53c:	08 00 48 21 	lda	s1,8(t7)
 540:	00 00 c9 2c 	ldq_u	t5,0(s0)
 544:	46 0f c2 48 	extqh	t5,t1,t5
 548:	86 17 c6 48 	sra	t5,0x30,t5
 54c:	01 00 c1 40 	addl	t5,t0,t0
 550:	28 f6 21 48 	zapnot	t0,0xf,t7
 554:	01 00 e1 43 	sextl	t0,t0
 558:	a8 d7 06 41 	cmpule	t7,0x36,t7
 55c:	07 00 00 e5 	beq	t7,57c <__gettextparse+0x37c>
 560:	16 04 2c 40 	addq	t0,s3,t8
 564:	01 00 f6 22 	lda	t9,1(t8)
 568:	00 00 16 2d 	ldq_u	t7,0(t8)
 56c:	48 0f 17 49 	extqh	t7,t9,t7
 570:	88 17 07 49 	sra	t7,0x38,t7
 574:	a6 05 06 41 	cmpeq	t7,t5,t5
 578:	8d 00 c0 f4 	bne	t5,7b0 <__gettextparse+0x5b0>
 57c:	00 00 dd 24 	ldah	t5,0(gp)
 580:	00 00 c6 20 	lda	t5,0(t5)
 584:	06 04 e6 40 	addq	t6,t5,t5
 588:	01 00 e6 20 	lda	t6,1(t5)
 58c:	00 00 26 2c 	ldq_u	t0,0(t5)
 590:	41 0f 27 48 	extqh	t0,t6,t0
 594:	81 17 27 48 	sra	t0,0x38,t0
 598:	16 04 6b 41 	addq	s2,s2,t8
 59c:	02 00 09 2d 	ldq_u	t7,2(s0)
 5a0:	67 03 22 48 	inswl	t0,t1,t6
 5a4:	fe ff d6 20 	lda	t5,-2(t8)
 5a8:	48 02 02 49 	mskwl	t7,t1,t7
 5ac:	06 04 a6 41 	addq	s4,t5,t5
 5b0:	07 04 e8 44 	or	t6,t7,t6
 5b4:	02 00 e9 3c 	stq_u	t6,2(s0)
 5b8:	a6 03 46 40 	cmpult	t1,t5,t5
 5bc:	09 04 e2 47 	mov	t1,s0
 5c0:	44 00 c0 f4 	bne	t5,6d4 <__gettextparse+0x4d4>
 5c4:	2a 05 4d 40 	subq	t1,s4,s1
 5c8:	8a 37 40 49 	sra	s1,0x1,s1
 5cc:	0f 27 df 20 	lda	t5,9999
 5d0:	ab 07 66 41 	cmpule	s2,t5,s2
 5d4:	01 00 4a 21 	lda	s1,1(s1)
 5d8:	b2 01 60 e5 	beq	s2,ca4 <__gettextparse+0xaa4>
 5dc:	10 27 5f 20 	lda	t1,10000
 5e0:	00 00 7d a7 	ldq	t12,0(gp)
 5e4:	ab 03 c2 42 	cmpult	t8,t1,s2
 5e8:	58 08 3e b4 	stq	t0,2136(sp)
 5ec:	68 08 9e b4 	stq	t3,2152(sp)
 5f0:	c2 04 76 45 	cmovne	s2,t8,t1
 5f4:	60 08 be b4 	stq	t4,2144(sp)
 5f8:	50 04 42 40 	s4addq	t1,t1,a0
 5fc:	10 04 10 42 	addq	a0,a0,a0
 600:	07 00 10 22 	lda	a0,7(a0)
 604:	0b 04 e2 47 	mov	t1,s2
 608:	00 40 5b 6b 	jsr	ra,(t12),60c <__gettextparse+0x40c>
 60c:	00 00 ba 27 	ldah	gp,0(ra)
 610:	00 00 bd 23 	lda	gp,0(gp)
 614:	0e 04 e0 47 	mov	v0,s5
 618:	a2 01 00 e4 	beq	v0,ca4 <__gettextparse+0xaa4>
 61c:	09 04 4a 41 	addq	s1,s1,s0
 620:	00 00 7d a7 	ldq	t12,0(gp)
 624:	12 04 e9 47 	mov	s0,a2
 628:	11 04 ed 47 	mov	s4,a1
 62c:	10 04 e0 47 	mov	v0,a0
 630:	00 40 5b 6b 	jsr	ra,(t12),634 <__gettextparse+0x434>
 634:	00 00 ba 27 	ldah	gp,0(ra)
 638:	4a 16 40 41 	s8addq	s1,0,s1
 63c:	06 04 6b 41 	addq	s2,s2,t5
 640:	00 00 bd 23 	lda	gp,0(gp)
 644:	06 04 c6 41 	addq	s5,t5,t5
 648:	11 04 ef 47 	mov	fp,a1
 64c:	00 00 7d a7 	ldq	t12,0(gp)
 650:	10 04 e6 47 	mov	t5,a0
 654:	12 04 ea 47 	mov	s1,a2
 658:	00 40 5b 6b 	jsr	ra,(t12),65c <__gettextparse+0x45c>
 65c:	00 00 ba 27 	ldah	gp,0(ra)
 660:	0f 04 6b 41 	addq	s2,s2,fp
 664:	30 08 5e a4 	ldq	t1,2096(sp)
 668:	00 00 bd 23 	lda	gp,0(gp)
 66c:	58 08 3e a4 	ldq	t0,2136(sp)
 670:	06 04 e0 47 	mov	v0,t5
 674:	68 08 9e a4 	ldq	t3,2152(sp)
 678:	a7 05 a2 41 	cmpeq	s4,t1,t6
 67c:	60 08 be a4 	ldq	t4,2144(sp)
 680:	0a 00 e0 f4 	bne	t6,6ac <__gettextparse+0x4ac>
 684:	10 04 ed 47 	mov	s4,a0
 688:	00 00 7d a7 	ldq	t12,0(gp)
 68c:	50 08 1e b4 	stq	v0,2128(sp)
 690:	00 40 5b 6b 	jsr	ra,(t12),694 <__gettextparse+0x494>
 694:	00 00 ba 27 	ldah	gp,0(ra)
 698:	50 08 de a4 	ldq	t5,2128(sp)
 69c:	00 00 bd 23 	lda	gp,0(gp)
 6a0:	60 08 be a4 	ldq	t4,2144(sp)
 6a4:	68 08 9e a4 	ldq	t3,2152(sp)
 6a8:	58 08 3e a4 	ldq	t0,2136(sp)
 6ac:	fe ff 29 21 	lda	s0,-2(s0)
 6b0:	fe ff ef 21 	lda	fp,-2(fp)
 6b4:	09 04 c9 41 	addq	s5,s0,s0
 6b8:	0f 04 cf 41 	addq	s5,fp,fp
 6bc:	f8 ff 4a 21 	lda	s1,-8(s1)
 6c0:	af 03 2f 41 	cmpult	s0,fp,fp
 6c4:	0a 04 ca 40 	addq	t5,s1,s1
 6c8:	79 01 e0 e5 	beq	fp,cb0 <__gettextparse+0xab0>
 6cc:	0f 04 e6 47 	mov	t5,fp
 6d0:	0d 04 ee 47 	mov	s5,s4
 6d4:	a2 35 21 40 	cmpeq	t0,0x9,t1
 6d8:	e5 fe 5f e4 	beq	t1,270 <__gettextparse+0x70>
 6dc:	09 04 ed 47 	mov	s4,s0
 6e0:	0a 04 ff 47 	clr	s1
 6e4:	3c ff ff c3 	br	3d8 <__gettextparse+0x1d8>
 6e8:	1f 04 ff 47 	nop	
 6ec:	00 00 fe 2f 	unop	
 6f0:	40 08 7e a4 	ldq	t2,2112(sp)
 6f4:	00 00 c3 a6 	ldq	t8,0(t2)
 6f8:	01 00 16 21 	lda	t7,1(t8)
 6fc:	00 00 56 2c 	ldq_u	t1,0(t8)
 700:	42 0f 48 48 	extqh	t1,t7,t1
 704:	82 17 47 48 	sra	t1,0x38,t1
 708:	08 00 40 f4 	bne	t1,72c <__gettextparse+0x52c>
 70c:	2e 00 e0 c3 	br	7c8 <__gettextparse+0x5c8>
 710:	02 00 b6 20 	lda	t4,2(t8)
 714:	00 00 48 2c 	ldq_u	t1,0(t7)
 718:	16 04 e8 47 	mov	t7,t8
 71c:	42 0f 45 48 	extqh	t1,t4,t1
 720:	82 17 47 48 	sra	t1,0x38,t1
 724:	2a 00 40 e4 	beq	t1,7d0 <__gettextparse+0x5d0>
 728:	01 00 08 21 	lda	t7,1(t7)
 72c:	a6 15 44 40 	cmpeq	t1,0x20,t5
 730:	a5 35 41 40 	cmpeq	t1,0x9,t4
 734:	a6 15 c0 40 	cmpeq	t5,0,t5
 738:	a5 15 a0 40 	cmpeq	t4,0,t4
 73c:	17 04 e8 47 	mov	t7,t9
 740:	05 00 c5 44 	and	t5,t4,t4
 744:	f2 ff bf e4 	beq	t4,710 <__gettextparse+0x510>
 748:	06 f0 5f 44 	and	t1,0xff,t5
 74c:	a6 97 cf 40 	cmpule	t5,0x7c,t5
 750:	05 00 e2 43 	sextl	t1,t4
 754:	97 00 c0 f4 	bne	t5,9b4 <__gettextparse+0x7b4>
 758:	40 08 be a4 	ldq	t4,2112(sp)
 75c:	00 00 05 b5 	stq	t7,0(t4)
 760:	01 00 1f 21 	lda	t7,1
 764:	00 01 bf 20 	lda	t4,256
 768:	d0 fe ff c3 	br	2ac <__gettextparse+0xac>
 76c:	00 00 fe 2f 	unop	
 770:	38 08 7e a4 	ldq	t2,2104(sp)
 774:	08 00 4a 21 	lda	s1,8(s1)
 778:	48 08 be a4 	ldq	t4,2120(sp)
 77c:	22 31 60 40 	subl	t2,0x1,t1
 780:	00 00 aa b4 	stq	t4,0(s1)
 784:	c3 04 62 44 	cmovne	t2,t1,t2
 788:	fe ff bf 20 	lda	t4,-2
 78c:	38 08 7e b4 	stq	t2,2104(sp)
 790:	02 00 49 20 	lda	t1,2(s0)
 794:	80 ff ff c3 	br	598 <__gettextparse+0x398>
 798:	1f 04 ff 47 	nop	
 79c:	00 00 fe 2f 	unop	
 7a0:	fe ff bf 20 	lda	t4,-2
 7a4:	f6 fe ff c3 	br	380 <__gettextparse+0x180>
 7a8:	1f 04 ff 47 	nop	
 7ac:	00 00 fe 2f 	unop	
 7b0:	00 00 7d 24 	ldah	t2,0(gp)
 7b4:	00 00 63 20 	lda	t2,0(t2)
 7b8:	01 04 23 40 	addq	t0,t2,t0
 7bc:	00 00 c1 2c 	ldq_u	t5,0(t0)
 7c0:	c1 00 c1 48 	extbl	t5,t0,t0
 7c4:	74 ff ff c3 	br	598 <__gettextparse+0x398>
 7c8:	17 04 f6 47 	mov	t8,t9
 7cc:	00 00 fe 2f 	unop	
 7d0:	08 04 ff 47 	clr	t7
 7d4:	40 08 be a4 	ldq	t4,2112(sp)
 7d8:	00 00 e5 b6 	stq	t9,0(t4)
 7dc:	05 04 ff 47 	clr	t4
 7e0:	b3 fe ff c3 	br	2b0 <__gettextparse+0xb0>
 7e4:	00 00 fe 2f 	unop	
 7e8:	1f 04 ff 47 	nop	
 7ec:	00 00 fe 2f 	unop	
 7f0:	10 08 5e 22 	lda	a2,2064(sp)
 7f4:	00 00 2a a4 	ldq	t0,0(s1)
 7f8:	02 00 3f 22 	lda	a1,2
 7fc:	68 08 9e b4 	stq	t3,2152(sp)
 800:	01 00 1f 22 	lda	a0,1
 804:	60 08 be b4 	stq	t4,2144(sp)
 808:	10 08 3e b4 	stq	t0,2064(sp)
 80c:	ff ff 3f 20 	lda	t0,-1
 810:	58 08 3e b4 	stq	t0,2136(sp)
 814:	fc ff 29 21 	lda	s0,-4(s0)
 818:	00 00 7d a7 	ldq	t12,0(gp)
 81c:	00 40 5b 6b 	jsr	ra,(t12),820 <__gettextparse+0x620>
 820:	00 00 ba 27 	ldah	gp,0(ra)
 824:	00 00 bd 23 	lda	gp,0(gp)
 828:	f0 ff 0a 21 	lda	t7,-16(s1)
 82c:	58 08 3e a4 	ldq	t0,2136(sp)
 830:	02 00 ff 20 	lda	t6,2
 834:	68 08 9e a4 	ldq	t3,2152(sp)
 838:	60 08 be a4 	ldq	t4,2144(sp)
 83c:	3d ff ff c3 	br	534 <__gettextparse+0x334>
 840:	12 04 ff 47 	clr	a2
 844:	68 08 9e b4 	stq	t3,2152(sp)
 848:	11 04 ff 47 	clr	a1
 84c:	60 08 be b4 	stq	t4,2144(sp)
 850:	10 04 ff 47 	clr	a0
 854:	00 00 7d a7 	ldq	t12,0(gp)
 858:	00 40 5b 6b 	jsr	ra,(t12),85c <__gettextparse+0x65c>
 85c:	00 00 ba 27 	ldah	gp,0(ra)
 860:	00 00 bd 23 	lda	gp,0(gp)
 864:	fe ff 29 21 	lda	s0,-2(s0)
 868:	f8 ff 0a 21 	lda	t7,-8(s1)
 86c:	68 08 9e a4 	ldq	t3,2152(sp)
 870:	ff ff 3f 20 	lda	t0,-1
 874:	60 08 be a4 	ldq	t4,2144(sp)
 878:	02 00 ff 20 	lda	t6,2
 87c:	2d ff ff c3 	br	534 <__gettextparse+0x334>
 880:	12 04 ff 47 	clr	a2
 884:	68 08 9e b4 	stq	t3,2152(sp)
 888:	01 00 3f 22 	lda	a1,1
 88c:	60 08 be b4 	stq	t4,2144(sp)
 890:	10 04 ff 47 	clr	a0
 894:	00 00 7d a7 	ldq	t12,0(gp)
 898:	00 40 5b 6b 	jsr	ra,(t12),89c <__gettextparse+0x69c>
 89c:	00 00 ba 27 	ldah	gp,0(ra)
 8a0:	00 00 bd 23 	lda	gp,0(gp)
 8a4:	fe ff 29 21 	lda	s0,-2(s0)
 8a8:	f8 ff 0a 21 	lda	t7,-8(s1)
 8ac:	68 08 9e a4 	ldq	t3,2152(sp)
 8b0:	ff ff 3f 20 	lda	t0,-1
 8b4:	60 08 be a4 	ldq	t4,2144(sp)
 8b8:	02 00 ff 20 	lda	t6,2
 8bc:	1d ff 1f e4 	beq	v0,534 <__gettextparse+0x334>
 8c0:	00 00 4a a4 	ldq	t1,0(s1)
 8c4:	08 00 40 b4 	stq	t1,8(v0)
 8c8:	1a ff ff c3 	br	534 <__gettextparse+0x334>
 8cc:	00 00 fe 2f 	unop	
 8d0:	e8 ff 0a 21 	lda	t7,-24(s1)
 8d4:	f8 ff 0a a4 	ldq	v0,-8(s1)
 8d8:	fa ff 29 21 	lda	s0,-6(s0)
 8dc:	ff ff 3f 20 	lda	t0,-1
 8e0:	02 00 ff 20 	lda	t6,2
 8e4:	13 ff ff c3 	br	534 <__gettextparse+0x334>
 8e8:	1f 04 ff 47 	nop	
 8ec:	00 00 fe 2f 	unop	
 8f0:	10 08 5e 22 	lda	a2,2064(sp)
 8f4:	00 00 4a a4 	ldq	t1,0(s1)
 8f8:	0e 00 3f 22 	lda	a1,14
 8fc:	f0 ff 2a a4 	ldq	t0,-16(s1)
 900:	fb fe ff c3 	br	4f0 <__gettextparse+0x2f0>
 904:	00 00 fe 2f 	unop	
 908:	1f 04 ff 47 	nop	
 90c:	00 00 fe 2f 	unop	
 910:	10 08 5e 22 	lda	a2,2064(sp)
 914:	00 00 4a a4 	ldq	t1,0(s1)
 918:	0f 00 3f 22 	lda	a1,15
 91c:	f0 ff 2a a4 	ldq	t0,-16(s1)
 920:	f3 fe ff c3 	br	4f0 <__gettextparse+0x2f0>
 924:	00 00 fe 2f 	unop	
 928:	1f 04 ff 47 	nop	
 92c:	00 00 fe 2f 	unop	
 930:	e0 ff 2a a4 	ldq	t0,-32(s1)
 934:	f0 ff ca a4 	ldq	t5,-16(s1)
 938:	10 08 5e 22 	lda	a2,2064(sp)
 93c:	00 00 4a a4 	ldq	t1,0(s1)
 940:	10 08 3e b4 	stq	t0,2064(sp)
 944:	10 00 3f 22 	lda	a1,16
 948:	ff ff 3f 20 	lda	t0,-1
 94c:	68 08 9e b4 	stq	t3,2152(sp)
 950:	03 00 1f 22 	lda	a0,3
 954:	58 08 3e b4 	stq	t0,2136(sp)
 958:	60 08 be b4 	stq	t4,2144(sp)
 95c:	f6 ff 29 21 	lda	s0,-10(s0)
 960:	18 08 de b4 	stq	t5,2072(sp)
 964:	20 08 5e b4 	stq	t1,2080(sp)
 968:	00 00 7d a7 	ldq	t12,0(gp)
 96c:	00 40 5b 6b 	jsr	ra,(t12),970 <__gettextparse+0x770>
 970:	00 00 ba 27 	ldah	gp,0(ra)
 974:	00 00 bd 23 	lda	gp,0(gp)
 978:	d8 ff 0a 21 	lda	t7,-40(s1)
 97c:	58 08 3e a4 	ldq	t0,2136(sp)
 980:	02 00 ff 20 	lda	t6,2
 984:	68 08 9e a4 	ldq	t3,2152(sp)
 988:	60 08 be a4 	ldq	t4,2144(sp)
 98c:	e9 fe ff c3 	br	534 <__gettextparse+0x334>
 990:	00 00 2a a4 	ldq	t0,0(s1)
 994:	66 fe 3f e4 	beq	t0,330 <__gettextparse+0x130>
 998:	f8 ff 0a 21 	lda	t7,-8(s1)
 99c:	40 08 7e a4 	ldq	t2,2112(sp)
 9a0:	fe ff 29 21 	lda	s0,-2(s0)
 9a4:	01 00 ff 20 	lda	t6,1
 9a8:	08 00 23 b4 	stq	t0,8(t2)
 9ac:	f6 ff 3f 20 	lda	t0,-10
 9b0:	e0 fe ff c3 	br	534 <__gettextparse+0x334>
 9b4:	00 00 dd 24 	ldah	t5,0(gp)
 9b8:	00 00 c6 20 	lda	t5,0(t5)
 9bc:	46 04 46 40 	s4addq	t1,t5,t5
 9c0:	00 00 c6 a0 	ldl	t5,0(t5)
 9c4:	06 04 a6 43 	addq	gp,t5,t5
 9c8:	00 00 e6 6b 	jmp	(t5)
 9cc:	03 00 5f 20 	lda	t1,3
 9d0:	48 08 7e a4 	ldq	t2,2120(sp)
 9d4:	38 08 5e b4 	stq	t1,2104(sp)
 9d8:	08 00 4a 21 	lda	s1,8(s1)
 9dc:	02 00 49 20 	lda	t1,2(s0)
 9e0:	00 00 6a b4 	stq	t2,0(s1)
 9e4:	ec fe ff c3 	br	598 <__gettextparse+0x398>
 9e8:	1f 04 ff 47 	nop	
 9ec:	00 00 fe 2f 	unop	
 9f0:	40 08 7e a4 	ldq	t2,2112(sp)
 9f4:	00 00 e3 b6 	stq	t9,0(t2)
 9f8:	26 fe ff c3 	br	294 <__gettextparse+0x94>
 9fc:	00 00 fe 2f 	unop	
 a00:	02 00 b6 20 	lda	t4,2(t8)
 a04:	01 00 56 2c 	ldq_u	t1,1(t8)
 a08:	42 0f 45 48 	extqh	t1,t4,t1
 a0c:	82 17 47 48 	sra	t1,0x38,t1
 a10:	a2 b5 47 40 	cmpeq	t1,0x3d,t1
 a14:	b2 00 40 f4 	bne	t1,ce0 <__gettextparse+0xae0>
 a18:	48 08 be a4 	ldq	t4,2120(sp)
 a1c:	40 08 7e a4 	ldq	t2,2112(sp)
 a20:	22 16 be 48 	zapnot	t4,0xf0,t1
 a24:	00 00 03 b5 	stq	t7,0(t2)
 a28:	03 01 bf 20 	lda	t4,259
 a2c:	02 34 41 44 	or	t1,0x9,t1
 a30:	48 08 5e b4 	stq	t1,2120(sp)
 a34:	07 00 1f 21 	lda	t7,7
 a38:	1c fe ff c3 	br	2ac <__gettextparse+0xac>
 a3c:	00 00 fe 2f 	unop	
 a40:	48 08 be a4 	ldq	t4,2120(sp)
 a44:	40 08 7e a4 	ldq	t2,2112(sp)
 a48:	22 16 be 48 	zapnot	t4,0xf0,t1
 a4c:	00 00 03 b5 	stq	t7,0(t2)
 a50:	05 01 bf 20 	lda	t4,261
 a54:	02 74 40 44 	or	t1,0x3,t1
 a58:	48 08 5e b4 	stq	t1,2120(sp)
 a5c:	09 00 1f 21 	lda	t7,9
 a60:	12 fe ff c3 	br	2ac <__gettextparse+0xac>
 a64:	00 00 fe 2f 	unop	
 a68:	1f 04 ff 47 	nop	
 a6c:	00 00 fe 2f 	unop	
 a70:	48 08 be a4 	ldq	t4,2120(sp)
 a74:	40 08 7e a4 	ldq	t2,2112(sp)
 a78:	22 16 be 48 	zapnot	t4,0xf0,t1
 a7c:	00 00 03 b5 	stq	t7,0(t2)
 a80:	04 01 bf 20 	lda	t4,260
 a84:	02 f4 40 44 	or	t1,0x7,t1
 a88:	48 08 5e b4 	stq	t1,2120(sp)
 a8c:	08 00 1f 21 	lda	t7,8
 a90:	06 fe ff c3 	br	2ac <__gettextparse+0xac>
 a94:	00 00 fe 2f 	unop	
 a98:	1f 04 ff 47 	nop	
 a9c:	00 00 fe 2f 	unop	
 aa0:	48 08 be a4 	ldq	t4,2120(sp)
 aa4:	40 08 7e a4 	ldq	t2,2112(sp)
 aa8:	22 16 be 48 	zapnot	t4,0xf0,t1
 aac:	00 00 03 b5 	stq	t7,0(t2)
 ab0:	04 01 bf 20 	lda	t4,260
 ab4:	02 d4 40 44 	or	t1,0x6,t1
 ab8:	48 08 5e b4 	stq	t1,2120(sp)
 abc:	08 00 1f 21 	lda	t7,8
 ac0:	fa fd ff c3 	br	2ac <__gettextparse+0xac>
 ac4:	00 00 fe 2f 	unop	
 ac8:	1f 04 ff 47 	nop	
 acc:	00 00 fe 2f 	unop	
 ad0:	02 00 f6 22 	lda	t9,2(t8)
 ad4:	01 00 d6 2c 	ldq_u	t5,1(t8)
 ad8:	46 0f d7 48 	extqh	t5,t9,t5
 adc:	86 17 c7 48 	sra	t5,0x38,t5
 ae0:	a2 05 c2 40 	cmpeq	t5,t1,t1
 ae4:	c2 ff 5f f4 	bne	t1,9f0 <__gettextparse+0x7f0>
 ae8:	00 01 bf 20 	lda	t4,256
 aec:	40 08 7e a4 	ldq	t2,2112(sp)
 af0:	00 00 03 b5 	stq	t7,0(t2)
 af4:	01 00 1f 21 	lda	t7,1
 af8:	ec fd ff c3 	br	2ac <__gettextparse+0xac>
 afc:	00 00 fe 2f 	unop	
 b00:	48 08 be a4 	ldq	t4,2120(sp)
 b04:	40 08 7e a4 	ldq	t2,2112(sp)
 b08:	22 16 be 48 	zapnot	t4,0xf0,t1
 b0c:	00 00 03 b5 	stq	t7,0(t2)
 b10:	05 01 bf 20 	lda	t4,261
 b14:	02 b4 40 44 	or	t1,0x5,t1
 b18:	48 08 5e b4 	stq	t1,2120(sp)
 b1c:	09 00 1f 21 	lda	t7,9
 b20:	e2 fd ff c3 	br	2ac <__gettextparse+0xac>
 b24:	00 00 fe 2f 	unop	
 b28:	1f 04 ff 47 	nop	
 b2c:	00 00 fe 2f 	unop	
 b30:	02 00 b6 20 	lda	t4,2(t8)
 b34:	01 00 56 2c 	ldq_u	t1,1(t8)
 b38:	42 0f 45 48 	extqh	t1,t4,t1
 b3c:	82 17 47 48 	sra	t1,0x38,t1
 b40:	a2 b5 47 40 	cmpeq	t1,0x3d,t1
 b44:	6f 00 40 f4 	bne	t1,d04 <__gettextparse+0xb04>
 b48:	21 00 bf 20 	lda	t4,33
 b4c:	40 08 5e a4 	ldq	t1,2112(sp)
 b50:	00 00 02 b5 	stq	t7,0(t1)
 b54:	0a 00 1f 21 	lda	t7,10
 b58:	d4 fd ff c3 	br	2ac <__gettextparse+0xac>
 b5c:	00 00 fe 2f 	unop	
 b60:	08 04 ff 47 	clr	t7
 b64:	40 08 5e a4 	ldq	t1,2112(sp)
 b68:	05 04 ff 47 	clr	t4
 b6c:	00 00 c2 b6 	stq	t8,0(t1)
 b70:	cf fd ff c3 	br	2b0 <__gettextparse+0xb0>
 b74:	00 00 fe 2f 	unop	
 b78:	1f 04 ff 47 	nop	
 b7c:	00 00 fe 2f 	unop	
 b80:	02 00 b6 20 	lda	t4,2(t8)
 b84:	01 00 56 2c 	ldq_u	t1,1(t8)
 b88:	42 0f 45 48 	extqh	t1,t4,t1
 b8c:	82 17 47 48 	sra	t1,0x38,t1
 b90:	a2 b5 47 40 	cmpeq	t1,0x3d,t1
 b94:	f0 fe 5f e4 	beq	t1,758 <__gettextparse+0x558>
 b98:	06 00 1f 21 	lda	t7,6
 b9c:	48 08 7e a4 	ldq	t2,2120(sp)
 ba0:	22 16 7e 48 	zapnot	t2,0xf0,t1
 ba4:	40 08 7e a4 	ldq	t2,2112(sp)
 ba8:	02 94 41 44 	or	t1,0xc,t1
 bac:	48 08 5e b4 	stq	t1,2120(sp)
 bb0:	00 00 a3 b4 	stq	t4,0(t2)
 bb4:	02 01 bf 20 	lda	t4,258
 bb8:	bc fd ff c3 	br	2ac <__gettextparse+0xac>
 bbc:	00 00 fe 2f 	unop	
 bc0:	02 00 b6 20 	lda	t4,2(t8)
 bc4:	01 00 56 2c 	ldq_u	t1,1(t8)
 bc8:	42 0f 45 48 	extqh	t1,t4,t1
 bcc:	82 17 47 48 	sra	t1,0x38,t1
 bd0:	a2 b5 47 40 	cmpeq	t1,0x3d,t1
 bd4:	39 00 40 f4 	bne	t1,cbc <__gettextparse+0xabc>
 bd8:	48 08 be a4 	ldq	t4,2120(sp)
 bdc:	40 08 7e a4 	ldq	t2,2112(sp)
 be0:	22 16 be 48 	zapnot	t4,0xf0,t1
 be4:	00 00 03 b5 	stq	t7,0(t2)
 be8:	03 01 bf 20 	lda	t4,259
 bec:	02 14 41 44 	or	t1,0x8,t1
 bf0:	48 08 5e b4 	stq	t1,2120(sp)
 bf4:	07 00 1f 21 	lda	t7,7
 bf8:	ac fd ff c3 	br	2ac <__gettextparse+0xac>
 bfc:	00 00 fe 2f 	unop	
 c00:	02 00 d6 20 	lda	t5,2(t8)
 c04:	01 00 56 2c 	ldq_u	t1,1(t8)
 c08:	25 11 a6 40 	subl	t4,0x30,t4
 c0c:	42 0f 46 48 	extqh	t1,t5,t1
 c10:	82 17 47 48 	sra	t1,0x38,t1
 c14:	22 11 46 40 	subl	t1,0x30,t1
 c18:	06 f0 5f 44 	and	t1,0xff,t5
 c1c:	a6 37 c1 40 	cmpule	t5,0x9,t5
 c20:	0e 00 c0 e4 	beq	t5,c5c <__gettextparse+0xa5c>
 c24:	01 00 08 21 	lda	t7,1(t7)
 c28:	17 04 e8 47 	mov	t7,t9
 c2c:	01 00 08 21 	lda	t7,1(t7)
 c30:	45 04 a5 40 	s4addq	t4,t4,t4
 c34:	00 00 d7 2c 	ldq_u	t5,0(t9)
 c38:	02 00 e2 43 	sextl	t1,t1
 c3c:	05 04 a5 40 	addq	t4,t4,t4
 c40:	46 0f c8 48 	extqh	t5,t7,t5
 c44:	05 04 45 40 	addq	t1,t4,t4
 c48:	82 17 c7 48 	sra	t5,0x38,t1
 c4c:	22 11 46 40 	subl	t1,0x30,t1
 c50:	06 f0 5f 44 	and	t1,0xff,t5
 c54:	a6 37 c1 40 	cmpule	t5,0x9,t5
 c58:	f3 ff df f4 	bne	t5,c28 <__gettextparse+0xa28>
 c5c:	40 08 5e a4 	ldq	t1,2112(sp)
 c60:	48 08 be b4 	stq	t4,2120(sp)
 c64:	0b 00 1f 21 	lda	t7,11
 c68:	06 01 bf 20 	lda	t4,262
 c6c:	00 00 e2 b6 	stq	t9,0(t1)
 c70:	8e fd ff c3 	br	2ac <__gettextparse+0xac>
 c74:	00 00 fe 2f 	unop	
 c78:	1f 04 ff 47 	nop	
 c7c:	00 00 fe 2f 	unop	
 c80:	48 08 be a4 	ldq	t4,2120(sp)
 c84:	40 08 7e a4 	ldq	t2,2112(sp)
 c88:	22 16 be 48 	zapnot	t4,0xf0,t1
 c8c:	00 00 03 b5 	stq	t7,0(t2)
 c90:	05 01 bf 20 	lda	t4,261
 c94:	02 94 40 44 	or	t1,0x4,t1
 c98:	48 08 5e b4 	stq	t1,2120(sp)
 c9c:	09 00 1f 21 	lda	t7,9
 ca0:	82 fd ff c3 	br	2ac <__gettextparse+0xac>
 ca4:	09 04 ed 47 	mov	s4,s0
 ca8:	02 00 5f 21 	lda	s1,2
 cac:	ca fd ff c3 	br	3d8 <__gettextparse+0x1d8>
 cb0:	09 04 ee 47 	mov	s5,s0
 cb4:	01 00 5f 21 	lda	s1,1
 cb8:	ca fd ff c3 	br	3e4 <__gettextparse+0x1e4>
 cbc:	07 00 1f 21 	lda	t7,7
 cc0:	48 08 7e a4 	ldq	t2,2120(sp)
 cc4:	22 16 7e 48 	zapnot	t2,0xf0,t1
 cc8:	40 08 7e a4 	ldq	t2,2112(sp)
 ccc:	02 54 41 44 	or	t1,0xa,t1
 cd0:	48 08 5e b4 	stq	t1,2120(sp)
 cd4:	00 00 a3 b4 	stq	t4,0(t2)
 cd8:	03 01 bf 20 	lda	t4,259
 cdc:	73 fd ff c3 	br	2ac <__gettextparse+0xac>
 ce0:	07 00 1f 21 	lda	t7,7
 ce4:	48 08 7e a4 	ldq	t2,2120(sp)
 ce8:	22 16 7e 48 	zapnot	t2,0xf0,t1
 cec:	40 08 7e a4 	ldq	t2,2112(sp)
 cf0:	02 74 41 44 	or	t1,0xb,t1
 cf4:	48 08 5e b4 	stq	t1,2120(sp)
 cf8:	00 00 a3 b4 	stq	t4,0(t2)
 cfc:	03 01 bf 20 	lda	t4,259
 d00:	6a fd ff c3 	br	2ac <__gettextparse+0xac>
 d04:	06 00 1f 21 	lda	t7,6
 d08:	48 08 7e a4 	ldq	t2,2120(sp)
 d0c:	22 16 7e 48 	zapnot	t2,0xf0,t1
 d10:	40 08 7e a4 	ldq	t2,2112(sp)
 d14:	02 b4 41 44 	or	t1,0xd,t1
 d18:	48 08 5e b4 	stq	t1,2120(sp)
 d1c:	00 00 a3 b4 	stq	t4,0(t2)
 d20:	02 01 bf 20 	lda	t4,258
 d24:	61 fd ff c3 	br	2ac <__gettextparse+0xac>
 d28:	1f 04 ff 47 	nop	
 d2c:	00 00 fe 2f 	unop	

[-- Attachment #3: plural-new.s --]
[-- Type: text/plain, Size: 29023 bytes --]


plural-new.o:     file format elf64-alpha


Disassembly of section .text:

0000000000000000 <__gettext_free_exp>:
   0:	00 00 bb 27 	ldah	gp,0(t12)
   4:	00 00 bd 23 	lda	gp,0(gp)
   8:	f0 ff de 23 	lda	sp,-16(sp)
   c:	08 00 3e b5 	stq	s0,8(sp)
  10:	09 04 f0 47 	mov	a0,s0
  14:	00 00 5e b7 	stq	ra,0(sp)
  18:	11 00 00 e6 	beq	a0,60 <__gettext_free_exp+0x60>
  1c:	00 00 30 a0 	ldl	t0,0(a0)
  20:	a2 5d 20 40 	cmple	t0,0x2,t1
  24:	12 00 40 e4 	beq	t1,70 <__gettext_free_exp+0x70>
  28:	a2 55 20 40 	cmpeq	t0,0x2,t1
  2c:	17 00 40 f4 	bne	t1,8c <__gettext_free_exp+0x8c>
  30:	a1 35 20 40 	cmpeq	t0,0x1,t0
  34:	05 00 20 e4 	beq	t0,4c <__gettext_free_exp+0x4c>
  38:	08 00 09 a6 	ldq	a0,8(s0)
  3c:	00 00 7d a7 	ldq	t12,0(gp)
  40:	00 40 5b 6b 	jsr	ra,(t12),44 <__gettext_free_exp+0x44>
  44:	00 00 ba 27 	ldah	gp,0(ra)
  48:	00 00 bd 23 	lda	gp,0(gp)
  4c:	10 04 e9 47 	mov	s0,a0
  50:	00 00 7d a7 	ldq	t12,0(gp)
  54:	00 40 5b 6b 	jsr	ra,(t12),58 <__gettext_free_exp+0x58>
  58:	00 00 ba 27 	ldah	gp,0(ra)
  5c:	00 00 bd 23 	lda	gp,0(gp)
  60:	00 00 5e a7 	ldq	ra,0(sp)
  64:	08 00 3e a5 	ldq	s0,8(sp)
  68:	10 00 de 23 	lda	sp,16(sp)
  6c:	01 80 fa 6b 	ret
  70:	a1 75 20 40 	cmpeq	t0,0x3,t0
  74:	f5 ff 3f e4 	beq	t0,4c <__gettext_free_exp+0x4c>
  78:	18 00 10 a6 	ldq	a0,24(a0)
  7c:	00 00 7d a7 	ldq	t12,0(gp)
  80:	00 40 5b 6b 	jsr	ra,(t12),84 <__gettext_free_exp+0x84>
  84:	00 00 ba 27 	ldah	gp,0(ra)
  88:	00 00 bd 23 	lda	gp,0(gp)
  8c:	10 00 09 a6 	ldq	a0,16(s0)
  90:	00 00 7d a7 	ldq	t12,0(gp)
  94:	00 40 5b 6b 	jsr	ra,(t12),98 <__gettext_free_exp+0x98>
  98:	00 00 ba 27 	ldah	gp,0(ra)
  9c:	00 00 bd 23 	lda	gp,0(gp)
  a0:	e5 ff ff c3 	br	38 <__gettext_free_exp+0x38>
  a4:	00 00 fe 2f 	unop	
  a8:	1f 04 ff 47 	nop	
  ac:	00 00 fe 2f 	unop	

00000000000000b0 <new_exp>:
  b0:	00 00 bb 27 	ldah	gp,0(t12)
  b4:	00 00 bd 23 	lda	gp,0(gp)
  b8:	d0 ff de 23 	lda	sp,-48(sp)
  bc:	08 00 3e b5 	stq	s0,8(sp)
  c0:	29 31 00 42 	subl	a0,0x1,s0
  c4:	10 00 5e b5 	stq	s1,16(sp)
  c8:	01 00 29 20 	lda	t0,1(s0)
  cc:	18 00 7e b5 	stq	s2,24(sp)
  d0:	0a 04 f2 47 	mov	a2,s1
  d4:	20 00 9e b5 	stq	s3,32(sp)
  d8:	0b 04 f0 47 	mov	a0,s2
  dc:	00 00 5e b7 	stq	ra,0(sp)
  e0:	0c 04 f1 47 	mov	a1,s3
  e4:	35 00 20 e4 	beq	t0,1bc <new_exp+0x10c>
  e8:	01 04 e9 47 	mov	s0,t0
  ec:	01 00 e0 c3 	br	f4 <new_exp+0x44>
  f0:	1b 00 40 e4 	beq	t1,160 <new_exp+0xb0>
  f4:	43 06 2a 40 	s8addq	t0,s1,t2
  f8:	ff ff 21 20 	lda	t0,-1(t0)
  fc:	02 00 e1 43 	sextl	t0,t1
 100:	00 00 63 a4 	ldq	t2,0(t2)
 104:	01 00 42 20 	lda	t1,1(t1)
 108:	f9 ff 7f f4 	bne	t2,f0 <new_exp+0x40>
 10c:	00 00 fe 2f 	unop	
 110:	41 06 2a 41 	s8addq	s0,s1,t0
 114:	ff ff 29 21 	lda	s0,-1(s0)
 118:	00 00 01 a6 	ldq	a0,0(t0)
 11c:	00 00 7d a7 	ldq	t12,0(gp)
 120:	00 40 5b 6b 	jsr	ra,(t12),124 <new_exp+0x74>
 124:	00 00 ba 27 	ldah	gp,0(ra)
 128:	00 00 bd 23 	lda	gp,0(gp)
 12c:	01 00 e9 43 	sextl	s0,t0
 130:	01 00 21 20 	lda	t0,1(t0)
 134:	f6 ff 3f f4 	bne	t0,110 <new_exp+0x60>
 138:	00 00 5e a7 	ldq	ra,0(sp)
 13c:	08 00 3e a5 	ldq	s0,8(sp)
 140:	10 00 5e a5 	ldq	s1,16(sp)
 144:	18 00 7e a5 	ldq	s2,24(sp)
 148:	00 04 ff 47 	clr	v0
 14c:	20 00 9e a5 	ldq	s3,32(sp)
 150:	30 00 de 23 	lda	sp,48(sp)
 154:	01 80 fa 6b 	ret
 158:	1f 04 ff 47 	nop	
 15c:	00 00 fe 2f 	unop	
 160:	20 00 1f 22 	lda	a0,32
 164:	00 00 7d a7 	ldq	t12,0(gp)
 168:	00 40 5b 6b 	jsr	ra,(t12),16c <new_exp+0xbc>
 16c:	00 00 ba 27 	ldah	gp,0(ra)
 170:	00 00 bd 23 	lda	gp,0(gp)
 174:	e6 ff 1f e4 	beq	v0,110 <new_exp+0x60>
 178:	00 00 60 b1 	stl	s2,0(v0)
 17c:	04 00 80 b1 	stl	s3,4(v0)
 180:	41 06 2a 41 	s8addq	s0,s1,t0
 184:	42 06 20 41 	s8addq	s0,v0,t1
 188:	ff ff 29 21 	lda	s0,-1(s0)
 18c:	00 00 61 a4 	ldq	t2,0(t0)
 190:	01 00 e9 43 	sextl	s0,t0
 194:	01 00 21 20 	lda	t0,1(t0)
 198:	08 00 62 b4 	stq	t2,8(t1)
 19c:	f8 ff 3f f4 	bne	t0,180 <new_exp+0xd0>
 1a0:	00 00 5e a7 	ldq	ra,0(sp)
 1a4:	08 00 3e a5 	ldq	s0,8(sp)
 1a8:	10 00 5e a5 	ldq	s1,16(sp)
 1ac:	18 00 7e a5 	ldq	s2,24(sp)
 1b0:	20 00 9e a5 	ldq	s3,32(sp)
 1b4:	30 00 de 23 	lda	sp,48(sp)
 1b8:	01 80 fa 6b 	ret
 1bc:	20 00 1f 22 	lda	a0,32
 1c0:	00 00 7d a7 	ldq	t12,0(gp)
 1c4:	00 40 5b 6b 	jsr	ra,(t12),1c8 <new_exp+0x118>
 1c8:	00 00 ba 27 	ldah	gp,0(ra)
 1cc:	00 00 bd 23 	lda	gp,0(gp)
 1d0:	d9 ff 1f e4 	beq	v0,138 <new_exp+0x88>
 1d4:	04 00 80 b1 	stl	s3,4(v0)
 1d8:	00 00 5e a7 	ldq	ra,0(sp)
 1dc:	08 00 3e a5 	ldq	s0,8(sp)
 1e0:	10 00 5e a5 	ldq	s1,16(sp)
 1e4:	18 00 7e a5 	ldq	s2,24(sp)
 1e8:	20 00 9e a5 	ldq	s3,32(sp)
 1ec:	00 00 e0 b3 	stl	zero,0(v0)
 1f0:	30 00 de 23 	lda	sp,48(sp)
 1f4:	01 80 fa 6b 	ret
 1f8:	1f 04 ff 47 	nop	
 1fc:	00 00 fe 2f 	unop	

0000000000000200 <__gettextparse>:
 200:	00 00 bb 27 	ldah	gp,0(t12)
 204:	00 00 bd 23 	lda	gp,0(gp)
 208:	90 f7 de 23 	lda	sp,-2160(sp)
 20c:	00 00 9d 24 	ldah	t3,0(gp)
 210:	80 06 3e a0 	ldl	t0,1664(sp)
 214:	08 00 3e b5 	stq	s0,8(sp)
 218:	00 00 5d 24 	ldah	t1,0(gp)
 21c:	80 06 3e 21 	lda	s0,1664(sp)
 220:	10 00 5e b5 	stq	s1,16(sp)
 224:	21 96 3f 48 	zapnot	t0,0xfc,t0
 228:	18 00 7e b5 	stq	s2,24(sp)
 22c:	40 00 5e 21 	lda	s1,64(sp)
 230:	20 00 9e b5 	stq	s3,32(sp)
 234:	28 00 be b5 	stq	s4,40(sp)
 238:	00 00 42 20 	lda	t1,0(t1)
 23c:	30 00 de b5 	stq	s5,48(sp)
 240:	fe ff bf 20 	lda	t4,-2
 244:	80 06 3e b0 	stl	t0,1664(sp)
 248:	c8 00 7f 21 	lda	s2,200
 24c:	01 04 ff 47 	clr	t0
 250:	00 00 5e b7 	stq	ra,0(sp)
 254:	0e 04 ea 47 	mov	s1,s5
 258:	38 00 fe b5 	stq	fp,56(sp)
 25c:	0d 04 e9 47 	mov	s0,s4
 260:	40 08 1e b6 	stq	a0,2112(sp)
 264:	00 00 84 21 	lda	s3,0(t3)
 268:	38 08 fe b7 	stq	zero,2104(sp)
 26c:	01 00 42 20 	lda	t1,1(t1)
 270:	30 08 3e b5 	stq	s0,2096(sp)
 274:	48 08 5e b4 	stq	t1,2120(sp)
 278:	02 04 81 41 	addq	s3,t0,t1
 27c:	01 00 c2 20 	lda	t5,1(t1)
 280:	00 00 e2 2c 	ldq_u	t6,0(t1)
 284:	47 0f e6 48 	extqh	t6,t5,t6
 288:	87 17 e7 48 	sra	t6,0x38,t6
 28c:	0a 00 47 20 	lda	t1,10(t6)
 290:	27 00 40 e4 	beq	t1,330 <__gettextparse+0x130>
 294:	02 00 45 20 	lda	t1,2(t4)
 298:	21 01 40 e4 	beq	t1,720 <__gettextparse+0x520>
 29c:	94 00 a0 ec 	ble	t4,4f0 <__gettextparse+0x2f0>
 2a0:	00 00 5d 24 	ldah	t1,0(gp)
 2a4:	00 00 42 20 	lda	t1,0(t1)
 2a8:	02 04 a2 40 	addq	t4,t1,t1
 2ac:	00 00 02 2d 	ldq_u	t7,0(t1)
 2b0:	c8 00 02 49 	extbl	t7,t1,t7
 2b4:	07 00 e8 40 	addl	t6,t7,t6
 2b8:	26 f6 e1 48 	zapnot	t6,0xf,t5
 2bc:	a6 d7 c6 40 	cmpule	t5,0x36,t5
 2c0:	1b 00 c0 e4 	beq	t5,330 <__gettextparse+0x130>
 2c4:	00 00 dd 24 	ldah	t5,0(gp)
 2c8:	00 00 c6 20 	lda	t5,0(t5)
 2cc:	06 04 e6 40 	addq	t6,t5,t5
 2d0:	01 00 c6 22 	lda	t8,1(t5)
 2d4:	00 00 46 2c 	ldq_u	t1,0(t5)
 2d8:	42 0f 56 48 	extqh	t1,t8,t1
 2dc:	82 17 47 48 	sra	t1,0x38,t1
 2e0:	a2 05 48 40 	cmpeq	t1,t7,t1
 2e4:	12 00 40 e4 	beq	t1,330 <__gettextparse+0x130>
 2e8:	00 00 3d 24 	ldah	t0,0(gp)
 2ec:	00 00 21 20 	lda	t0,0(t0)
 2f0:	07 04 e1 40 	addq	t6,t0,t6
 2f4:	00 00 27 2c 	ldq_u	t0,0(t6)
 2f8:	c1 00 27 48 	extbl	t0,t6,t0
 2fc:	28 01 20 f4 	bne	t0,7a0 <__gettextparse+0x5a0>
 300:	00 00 5d 24 	ldah	t1,0(gp)
 304:	48 08 7e a4 	ldq	t2,2120(sp)
 308:	00 00 42 20 	lda	t1,0(t1)
 30c:	08 00 0a a4 	ldq	v0,8(s1)
 310:	08 04 ea 47 	mov	s1,t7
 314:	f0 ff ff 20 	lda	t6,-16
 318:	00 00 22 2c 	ldq_u	t0,0(t1)
 31c:	41 0f 23 48 	extqh	t0,t2,t0
 320:	81 17 27 48 	sra	t0,0x38,t0
 324:	8f 00 e0 c3 	br	564 <__gettextparse+0x364>
 328:	1f 04 ff 47 	nop	
 32c:	00 00 fe 2f 	unop	
 330:	00 00 5d 24 	ldah	t1,0(gp)
 334:	00 00 42 20 	lda	t1,0(t1)
 338:	02 04 22 40 	addq	t0,t1,t1
 33c:	00 00 c2 2c 	ldq_u	t5,0(t1)
 340:	c2 00 c2 48 	extbl	t5,t1,t1
 344:	08 00 e2 43 	sextl	t1,t7
 348:	35 00 40 f4 	bne	t1,420 <__gettextparse+0x220>
 34c:	38 08 9e a4 	ldq	t3,2104(sp)
 350:	a2 75 80 40 	cmpeq	t3,0x3,t1
 354:	02 00 40 e4 	beq	t1,360 <__gettextparse+0x160>
 358:	1d 01 a0 fc 	bgt	t4,7d0 <__gettextparse+0x5d0>
 35c:	4d 02 a0 e4 	beq	t4,c94 <__gettextparse+0xa94>
 360:	00 00 dd 24 	ldah	t5,0(gp)
 364:	00 00 fd 24 	ldah	t6,0(gp)
 368:	00 00 c6 20 	lda	t5,0(t5)
 36c:	00 00 e7 20 	lda	t6,0(t6)
 370:	0b 00 e0 c3 	br	3a0 <__gettextparse+0x1a0>
 374:	00 00 fe 2f 	unop	
 378:	1f 04 ff 47 	nop	
 37c:	00 00 fe 2f 	unop	
 380:	a1 05 2d 41 	cmpeq	s0,s4,t0
 384:	46 00 20 f4 	bne	t0,4a0 <__gettextparse+0x2a0>
 388:	fe ff 29 21 	lda	s0,-2(s0)
 38c:	02 00 49 20 	lda	t1,2(s0)
 390:	f8 ff 4a 21 	lda	s1,-8(s1)
 394:	00 00 29 2c 	ldq_u	t0,0(s0)
 398:	41 0f 22 48 	extqh	t0,t1,t0
 39c:	81 17 26 48 	sra	t0,0x30,t0
 3a0:	01 04 81 41 	addq	s3,t0,t0
 3a4:	01 00 41 20 	lda	t1,1(t0)
 3a8:	00 00 21 2c 	ldq_u	t0,0(t0)
 3ac:	41 0f 22 48 	extqh	t0,t1,t0
 3b0:	81 17 27 48 	sra	t0,0x38,t0
 3b4:	0a 00 41 20 	lda	t1,10(t0)
 3b8:	f1 ff 5f e4 	beq	t1,380 <__gettextparse+0x180>
 3bc:	01 30 20 40 	addl	t0,0x1,t0
 3c0:	22 f6 21 48 	zapnot	t0,0xf,t1
 3c4:	01 00 e1 43 	sextl	t0,t0
 3c8:	a2 d7 46 40 	cmpule	t1,0x36,t1
 3cc:	ec ff 5f e4 	beq	t1,380 <__gettextparse+0x180>
 3d0:	08 04 26 40 	addq	t0,t5,t7
 3d4:	01 00 c8 22 	lda	t8,1(t7)
 3d8:	00 00 48 2c 	ldq_u	t1,0(t7)
 3dc:	42 0f 56 48 	extqh	t1,t8,t1
 3e0:	82 17 47 48 	sra	t1,0x38,t1
 3e4:	a2 35 40 40 	cmpeq	t1,0x1,t1
 3e8:	e5 ff 5f e4 	beq	t1,380 <__gettextparse+0x180>
 3ec:	01 04 27 40 	addq	t0,t6,t0
 3f0:	00 00 41 2c 	ldq_u	t1,0(t0)
 3f4:	c1 00 41 48 	extbl	t1,t0,t0
 3f8:	e1 ff 3f e4 	beq	t0,380 <__gettextparse+0x180>
 3fc:	03 00 9f 20 	lda	t3,3
 400:	50 08 7e a4 	ldq	t2,2128(sp)
 404:	38 08 9e b4 	stq	t3,2104(sp)
 408:	08 00 4a 21 	lda	s1,8(s1)
 40c:	02 00 49 20 	lda	t1,2(s0)
 410:	00 00 6a b4 	stq	t2,0(s1)
 414:	6e 00 e0 c3 	br	5d0 <__gettextparse+0x3d0>
 418:	1f 04 ff 47 	nop	
 41c:	00 00 fe 2f 	unop	
 420:	00 00 3d 24 	ldah	t0,0(gp)
 424:	00 00 21 20 	lda	t0,0(t0)
 428:	01 04 01 41 	addq	t7,t0,t0
 42c:	a7 b7 41 40 	cmpule	t1,0xd,t6
 430:	00 00 c1 2c 	ldq_u	t5,0(t0)
 434:	c1 00 c1 48 	extbl	t5,t0,t0
 438:	01 00 df 20 	lda	t5,1
 43c:	26 01 c1 40 	subl	t5,t0,t5
 440:	46 06 ca 40 	s8addq	t5,s1,t5
 444:	00 00 06 a4 	ldq	v0,0(t5)
 448:	2d 00 e0 f4 	bne	t6,500 <__gettextparse+0x300>
 44c:	00 00 5d 24 	ldah	t1,0(gp)
 450:	00 00 42 20 	lda	t1,0(t1)
 454:	02 04 02 41 	addq	t7,t1,t1
 458:	00 00 9d 24 	ldah	t3,0(gp)
 45c:	48 16 20 40 	s8addq	t0,0,t7
 460:	00 00 e2 2c 	ldq_u	t6,0(t1)
 464:	01 04 21 40 	addq	t0,t0,t0
 468:	00 00 84 20 	lda	t3,0(t3)
 46c:	c2 00 e2 48 	extbl	t6,t1,t1
 470:	29 05 21 41 	subq	s0,t0,s0
 474:	27 11 42 40 	subl	t1,0x10,t6
 478:	01 04 e4 40 	addq	t6,t3,t0
 47c:	01 00 41 20 	lda	t1,1(t0)
 480:	28 05 48 41 	subq	s1,t7,t7
 484:	00 00 21 2c 	ldq_u	t0,0(t0)
 488:	41 0f 22 48 	extqh	t0,t1,t0
 48c:	81 17 27 48 	sra	t0,0x38,t0
 490:	34 00 e0 c3 	br	564 <__gettextparse+0x364>
 494:	00 00 fe 2f 	unop	
 498:	1f 04 ff 47 	nop	
 49c:	00 00 fe 2f 	unop	
 4a0:	01 00 5f 21 	lda	s1,1
 4a4:	30 08 3e a4 	ldq	t0,2096(sp)
 4a8:	ad 05 21 41 	cmpeq	s0,t0,s4
 4ac:	05 00 a0 f5 	bne	s4,4c4 <__gettextparse+0x2c4>
 4b0:	10 04 e9 47 	mov	s0,a0
 4b4:	00 00 7d a7 	ldq	t12,0(gp)
 4b8:	00 40 5b 6b 	jsr	ra,(t12),4bc <__gettextparse+0x2bc>
 4bc:	00 00 ba 27 	ldah	gp,0(ra)
 4c0:	00 00 bd 23 	lda	gp,0(gp)
 4c4:	00 04 ea 47 	mov	s1,v0
 4c8:	00 00 5e a7 	ldq	ra,0(sp)
 4cc:	08 00 3e a5 	ldq	s0,8(sp)
 4d0:	10 00 5e a5 	ldq	s1,16(sp)
 4d4:	18 00 7e a5 	ldq	s2,24(sp)
 4d8:	20 00 9e a5 	ldq	s3,32(sp)
 4dc:	28 00 be a5 	ldq	s4,40(sp)
 4e0:	30 00 de a5 	ldq	s5,48(sp)
 4e4:	38 00 fe a5 	ldq	fp,56(sp)
 4e8:	70 08 de 23 	lda	sp,2160(sp)
 4ec:	01 80 fa 6b 	ret
 4f0:	08 04 ff 47 	clr	t7
 4f4:	05 04 ff 47 	clr	t4
 4f8:	6f ff ff c3 	br	2b8 <__gettextparse+0xb8>
 4fc:	00 00 fe 2f 	unop	
 500:	00 00 dd 24 	ldah	t5,0(gp)
 504:	00 00 c6 20 	lda	t5,0(t5)
 508:	42 04 46 40 	s4addq	t1,t5,t1
 50c:	00 00 42 a0 	ldl	t1,0(t1)
 510:	02 04 a2 43 	addq	gp,t1,t1
 514:	00 00 e2 6b 	jmp	(t1)
 518:	1f 04 ff 47 	nop	
 51c:	00 00 fe 2f 	unop	
 520:	10 08 5e 22 	lda	a2,2064(sp)
 524:	f8 ff 2a a2 	ldl	a1,-8(s1)
 528:	00 00 4a a4 	ldq	t1,0(s1)
 52c:	f0 ff 2a a4 	ldq	t0,-16(s1)
 530:	02 00 1f 22 	lda	a0,2
 534:	10 08 3e b4 	stq	t0,2064(sp)
 538:	68 08 be b4 	stq	t4,2152(sp)
 53c:	fa ff 29 21 	lda	s0,-6(s0)
 540:	18 08 5e b4 	stq	t1,2072(sp)
 544:	00 00 7d a7 	ldq	t12,0(gp)
 548:	00 40 5b 6b 	jsr	ra,(t12),54c <__gettextparse+0x34c>
 54c:	00 00 ba 27 	ldah	gp,0(ra)
 550:	00 00 bd 23 	lda	gp,0(gp)
 554:	e8 ff 0a 21 	lda	t7,-24(s1)
 558:	68 08 be a4 	ldq	t4,2152(sp)
 55c:	ff ff 3f 20 	lda	t0,-1
 560:	02 00 ff 20 	lda	t6,2
 564:	08 00 08 b4 	stq	v0,8(t7)
 568:	02 00 49 20 	lda	t1,2(s0)
 56c:	08 00 48 21 	lda	s1,8(t7)
 570:	00 00 c9 2c 	ldq_u	t5,0(s0)
 574:	46 0f c2 48 	extqh	t5,t1,t5
 578:	86 17 c6 48 	sra	t5,0x30,t5
 57c:	01 00 c1 40 	addl	t5,t0,t0
 580:	28 f6 21 48 	zapnot	t0,0xf,t7
 584:	01 00 e1 43 	sextl	t0,t0
 588:	a8 d7 06 41 	cmpule	t7,0x36,t7
 58c:	09 00 00 e5 	beq	t7,5b4 <__gettextparse+0x3b4>
 590:	00 00 dd 26 	ldah	t8,0(gp)
 594:	00 00 d6 22 	lda	t8,0(t8)
 598:	16 04 36 40 	addq	t0,t8,t8
 59c:	01 00 f6 22 	lda	t9,1(t8)
 5a0:	00 00 16 2d 	ldq_u	t7,0(t8)
 5a4:	48 0f 17 49 	extqh	t7,t9,t7
 5a8:	88 17 07 49 	sra	t7,0x38,t7
 5ac:	a6 05 06 41 	cmpeq	t7,t5,t5
 5b0:	8b 00 c0 f4 	bne	t5,7e0 <__gettextparse+0x5e0>
 5b4:	00 00 dd 24 	ldah	t5,0(gp)
 5b8:	00 00 c6 20 	lda	t5,0(t5)
 5bc:	06 04 e6 40 	addq	t6,t5,t5
 5c0:	01 00 e6 20 	lda	t6,1(t5)
 5c4:	00 00 26 2c 	ldq_u	t0,0(t5)
 5c8:	41 0f 27 48 	extqh	t0,t6,t0
 5cc:	81 17 27 48 	sra	t0,0x38,t0
 5d0:	16 04 6b 41 	addq	s2,s2,t8
 5d4:	02 00 09 2d 	ldq_u	t7,2(s0)
 5d8:	67 03 22 48 	inswl	t0,t1,t6
 5dc:	fe ff d6 20 	lda	t5,-2(t8)
 5e0:	48 02 02 49 	mskwl	t7,t1,t7
 5e4:	06 04 a6 41 	addq	s4,t5,t5
 5e8:	07 04 e8 44 	or	t6,t7,t6
 5ec:	02 00 e9 3c 	stq_u	t6,2(s0)
 5f0:	a6 03 46 40 	cmpult	t1,t5,t5
 5f4:	09 04 e2 47 	mov	t1,s0
 5f8:	41 00 c0 f4 	bne	t5,700 <__gettextparse+0x500>
 5fc:	2a 05 4d 40 	subq	t1,s4,s1
 600:	8a 37 40 49 	sra	s1,0x1,s1
 604:	0f 27 df 20 	lda	t5,9999
 608:	ab 07 66 41 	cmpule	s2,t5,s2
 60c:	01 00 4a 21 	lda	s1,1(s1)
 610:	a3 01 60 e5 	beq	s2,ca0 <__gettextparse+0xaa0>
 614:	10 27 5f 20 	lda	t1,10000
 618:	00 00 7d a7 	ldq	t12,0(gp)
 61c:	ab 03 c2 42 	cmpult	t8,t1,s2
 620:	60 08 3e b4 	stq	t0,2144(sp)
 624:	68 08 be b4 	stq	t4,2152(sp)
 628:	c2 04 76 45 	cmovne	s2,t8,t1
 62c:	50 04 42 40 	s4addq	t1,t1,a0
 630:	10 04 10 42 	addq	a0,a0,a0
 634:	07 00 10 22 	lda	a0,7(a0)
 638:	0b 04 e2 47 	mov	t1,s2
 63c:	00 40 5b 6b 	jsr	ra,(t12),640 <__gettextparse+0x440>
 640:	00 00 ba 27 	ldah	gp,0(ra)
 644:	00 00 bd 23 	lda	gp,0(gp)
 648:	0f 04 e0 47 	mov	v0,fp
 64c:	94 01 00 e4 	beq	v0,ca0 <__gettextparse+0xaa0>
 650:	09 04 4a 41 	addq	s1,s1,s0
 654:	00 00 7d a7 	ldq	t12,0(gp)
 658:	12 04 e9 47 	mov	s0,a2
 65c:	11 04 ed 47 	mov	s4,a1
 660:	10 04 e0 47 	mov	v0,a0
 664:	00 40 5b 6b 	jsr	ra,(t12),668 <__gettextparse+0x468>
 668:	00 00 ba 27 	ldah	gp,0(ra)
 66c:	4a 16 40 41 	s8addq	s1,0,s1
 670:	06 04 6b 41 	addq	s2,s2,t5
 674:	00 00 bd 23 	lda	gp,0(gp)
 678:	06 04 e6 41 	addq	fp,t5,t5
 67c:	11 04 ee 47 	mov	s5,a1
 680:	00 00 7d a7 	ldq	t12,0(gp)
 684:	10 04 e6 47 	mov	t5,a0
 688:	12 04 ea 47 	mov	s1,a2
 68c:	00 40 5b 6b 	jsr	ra,(t12),690 <__gettextparse+0x490>
 690:	00 00 ba 27 	ldah	gp,0(ra)
 694:	0e 04 6b 41 	addq	s2,s2,s5
 698:	30 08 7e a4 	ldq	t2,2096(sp)
 69c:	00 00 bd 23 	lda	gp,0(gp)
 6a0:	60 08 3e a4 	ldq	t0,2144(sp)
 6a4:	06 04 e0 47 	mov	v0,t5
 6a8:	68 08 be a4 	ldq	t4,2152(sp)
 6ac:	a7 05 a3 41 	cmpeq	s4,t2,t6
 6b0:	09 00 e0 f4 	bne	t6,6d8 <__gettextparse+0x4d8>
 6b4:	10 04 ed 47 	mov	s4,a0
 6b8:	00 00 7d a7 	ldq	t12,0(gp)
 6bc:	58 08 1e b4 	stq	v0,2136(sp)
 6c0:	00 40 5b 6b 	jsr	ra,(t12),6c4 <__gettextparse+0x4c4>
 6c4:	00 00 ba 27 	ldah	gp,0(ra)
 6c8:	58 08 de a4 	ldq	t5,2136(sp)
 6cc:	00 00 bd 23 	lda	gp,0(gp)
 6d0:	68 08 be a4 	ldq	t4,2152(sp)
 6d4:	60 08 3e a4 	ldq	t0,2144(sp)
 6d8:	fe ff 29 21 	lda	s0,-2(s0)
 6dc:	fe ff ce 21 	lda	s5,-2(s5)
 6e0:	09 04 e9 41 	addq	fp,s0,s0
 6e4:	0e 04 ee 41 	addq	fp,s5,s5
 6e8:	f8 ff 4a 21 	lda	s1,-8(s1)
 6ec:	ae 03 2e 41 	cmpult	s0,s5,s5
 6f0:	0a 04 ca 40 	addq	t5,s1,s1
 6f4:	6d 01 c0 e5 	beq	s5,cac <__gettextparse+0xaac>
 6f8:	0e 04 e6 47 	mov	t5,s5
 6fc:	0d 04 ef 47 	mov	fp,s4
 700:	a2 35 21 40 	cmpeq	t0,0x9,t1
 704:	dc fe 5f e4 	beq	t1,278 <__gettextparse+0x78>
 708:	09 04 ed 47 	mov	s4,s0
 70c:	0a 04 ff 47 	clr	s1
 710:	64 ff ff c3 	br	4a4 <__gettextparse+0x2a4>
 714:	00 00 fe 2f 	unop	
 718:	1f 04 ff 47 	nop	
 71c:	00 00 fe 2f 	unop	
 720:	40 08 9e a4 	ldq	t3,2112(sp)
 724:	00 00 c4 a6 	ldq	t8,0(t3)
 728:	01 00 16 21 	lda	t7,1(t8)
 72c:	00 00 56 2c 	ldq_u	t1,0(t8)
 730:	42 0f 48 48 	extqh	t1,t7,t1
 734:	82 17 47 48 	sra	t1,0x38,t1
 738:	08 00 40 f4 	bne	t1,75c <__gettextparse+0x55c>
 73c:	2e 00 e0 c3 	br	7f8 <__gettextparse+0x5f8>
 740:	02 00 b6 20 	lda	t4,2(t8)
 744:	00 00 48 2c 	ldq_u	t1,0(t7)
 748:	16 04 e8 47 	mov	t7,t8
 74c:	42 0f 45 48 	extqh	t1,t4,t1
 750:	82 17 47 48 	sra	t1,0x38,t1
 754:	2a 00 40 e4 	beq	t1,800 <__gettextparse+0x600>
 758:	01 00 08 21 	lda	t7,1(t7)
 75c:	a6 15 44 40 	cmpeq	t1,0x20,t5
 760:	a5 35 41 40 	cmpeq	t1,0x9,t4
 764:	a6 15 c0 40 	cmpeq	t5,0,t5
 768:	a5 15 a0 40 	cmpeq	t4,0,t4
 76c:	17 04 e8 47 	mov	t7,t9
 770:	05 00 c5 44 	and	t5,t4,t4
 774:	f2 ff bf e4 	beq	t4,740 <__gettextparse+0x540>
 778:	06 f0 5f 44 	and	t1,0xff,t5
 77c:	a6 97 cf 40 	cmpule	t5,0x7c,t5
 780:	05 00 e2 43 	sextl	t1,t4
 784:	8f 00 c0 f4 	bne	t5,9c4 <__gettextparse+0x7c4>
 788:	00 01 bf 20 	lda	t4,256
 78c:	40 08 9e a4 	ldq	t3,2112(sp)
 790:	00 00 04 b5 	stq	t7,0(t3)
 794:	01 00 1f 21 	lda	t7,1
 798:	c6 fe ff c3 	br	2b4 <__gettextparse+0xb4>
 79c:	00 00 fe 2f 	unop	
 7a0:	38 08 9e a4 	ldq	t3,2104(sp)
 7a4:	08 00 4a 21 	lda	s1,8(s1)
 7a8:	50 08 7e a4 	ldq	t2,2128(sp)
 7ac:	fe ff bf 20 	lda	t4,-2
 7b0:	22 31 80 40 	subl	t3,0x1,t1
 7b4:	c4 04 82 44 	cmovne	t3,t1,t3
 7b8:	00 00 6a b4 	stq	t2,0(s1)
 7bc:	38 08 9e b4 	stq	t3,2104(sp)
 7c0:	02 00 49 20 	lda	t1,2(s0)
 7c4:	82 ff ff c3 	br	5d0 <__gettextparse+0x3d0>
 7c8:	1f 04 ff 47 	nop	
 7cc:	00 00 fe 2f 	unop	
 7d0:	fe ff bf 20 	lda	t4,-2
 7d4:	e2 fe ff c3 	br	360 <__gettextparse+0x160>
 7d8:	1f 04 ff 47 	nop	
 7dc:	00 00 fe 2f 	unop	
 7e0:	00 00 dd 24 	ldah	t5,0(gp)
 7e4:	00 00 c6 20 	lda	t5,0(t5)
 7e8:	01 04 26 40 	addq	t0,t5,t0
 7ec:	00 00 c1 2c 	ldq_u	t5,0(t0)
 7f0:	c1 00 c1 48 	extbl	t5,t0,t0
 7f4:	76 ff ff c3 	br	5d0 <__gettextparse+0x3d0>
 7f8:	17 04 f6 47 	mov	t8,t9
 7fc:	00 00 fe 2f 	unop	
 800:	08 04 ff 47 	clr	t7
 804:	40 08 5e a4 	ldq	t1,2112(sp)
 808:	05 04 ff 47 	clr	t4
 80c:	00 00 e2 b6 	stq	t9,0(t1)
 810:	a9 fe ff c3 	br	2b8 <__gettextparse+0xb8>
 814:	00 00 fe 2f 	unop	
 818:	1f 04 ff 47 	nop	
 81c:	00 00 fe 2f 	unop	
 820:	10 08 5e 22 	lda	a2,2064(sp)
 824:	00 00 2a a4 	ldq	t0,0(s1)
 828:	02 00 3f 22 	lda	a1,2
 82c:	68 08 be b4 	stq	t4,2152(sp)
 830:	01 00 1f 22 	lda	a0,1
 834:	10 08 3e b4 	stq	t0,2064(sp)
 838:	fc ff 29 21 	lda	s0,-4(s0)
 83c:	00 00 7d a7 	ldq	t12,0(gp)
 840:	00 40 5b 6b 	jsr	ra,(t12),844 <__gettextparse+0x644>
 844:	00 00 ba 27 	ldah	gp,0(ra)
 848:	00 00 bd 23 	lda	gp,0(gp)
 84c:	f0 ff 0a 21 	lda	t7,-16(s1)
 850:	68 08 be a4 	ldq	t4,2152(sp)
 854:	ff ff 3f 20 	lda	t0,-1
 858:	02 00 ff 20 	lda	t6,2
 85c:	41 ff ff c3 	br	564 <__gettextparse+0x364>
 860:	12 04 ff 47 	clr	a2
 864:	68 08 be b4 	stq	t4,2152(sp)
 868:	11 04 ff 47 	clr	a1
 86c:	10 04 ff 47 	clr	a0
 870:	00 00 7d a7 	ldq	t12,0(gp)
 874:	00 40 5b 6b 	jsr	ra,(t12),878 <__gettextparse+0x678>
 878:	00 00 ba 27 	ldah	gp,0(ra)
 87c:	00 00 bd 23 	lda	gp,0(gp)
 880:	fe ff 29 21 	lda	s0,-2(s0)
 884:	f8 ff 0a 21 	lda	t7,-8(s1)
 888:	68 08 be a4 	ldq	t4,2152(sp)
 88c:	ff ff 3f 20 	lda	t0,-1
 890:	02 00 ff 20 	lda	t6,2
 894:	33 ff ff c3 	br	564 <__gettextparse+0x364>
 898:	1f 04 ff 47 	nop	
 89c:	00 00 fe 2f 	unop	
 8a0:	12 04 ff 47 	clr	a2
 8a4:	68 08 be b4 	stq	t4,2152(sp)
 8a8:	01 00 3f 22 	lda	a1,1
 8ac:	10 04 ff 47 	clr	a0
 8b0:	00 00 7d a7 	ldq	t12,0(gp)
 8b4:	00 40 5b 6b 	jsr	ra,(t12),8b8 <__gettextparse+0x6b8>
 8b8:	00 00 ba 27 	ldah	gp,0(ra)
 8bc:	00 00 bd 23 	lda	gp,0(gp)
 8c0:	fe ff 29 21 	lda	s0,-2(s0)
 8c4:	f8 ff 0a 21 	lda	t7,-8(s1)
 8c8:	68 08 be a4 	ldq	t4,2152(sp)
 8cc:	ff ff 3f 20 	lda	t0,-1
 8d0:	02 00 ff 20 	lda	t6,2
 8d4:	23 ff 1f e4 	beq	v0,564 <__gettextparse+0x364>
 8d8:	00 00 4a a4 	ldq	t1,0(s1)
 8dc:	08 00 40 b4 	stq	t1,8(v0)
 8e0:	20 ff ff c3 	br	564 <__gettextparse+0x364>
 8e4:	00 00 fe 2f 	unop	
 8e8:	1f 04 ff 47 	nop	
 8ec:	00 00 fe 2f 	unop	
 8f0:	e8 ff 0a 21 	lda	t7,-24(s1)
 8f4:	f8 ff 0a a4 	ldq	v0,-8(s1)
 8f8:	fa ff 29 21 	lda	s0,-6(s0)
 8fc:	ff ff 3f 20 	lda	t0,-1
 900:	02 00 ff 20 	lda	t6,2
 904:	17 ff ff c3 	br	564 <__gettextparse+0x364>
 908:	1f 04 ff 47 	nop	
 90c:	00 00 fe 2f 	unop	
 910:	10 08 5e 22 	lda	a2,2064(sp)
 914:	00 00 4a a4 	ldq	t1,0(s1)
 918:	0e 00 3f 22 	lda	a1,14
 91c:	f0 ff 2a a4 	ldq	t0,-16(s1)
 920:	03 ff ff c3 	br	530 <__gettextparse+0x330>
 924:	00 00 fe 2f 	unop	
 928:	1f 04 ff 47 	nop	
 92c:	00 00 fe 2f 	unop	
 930:	10 08 5e 22 	lda	a2,2064(sp)
 934:	00 00 4a a4 	ldq	t1,0(s1)
 938:	0f 00 3f 22 	lda	a1,15
 93c:	f0 ff 2a a4 	ldq	t0,-16(s1)
 940:	fb fe ff c3 	br	530 <__gettextparse+0x330>
 944:	00 00 fe 2f 	unop	
 948:	1f 04 ff 47 	nop	
 94c:	00 00 fe 2f 	unop	
 950:	e0 ff 2a a4 	ldq	t0,-32(s1)
 954:	f0 ff ca a4 	ldq	t5,-16(s1)
 958:	10 08 5e 22 	lda	a2,2064(sp)
 95c:	00 00 4a a4 	ldq	t1,0(s1)
 960:	10 00 3f 22 	lda	a1,16
 964:	10 08 3e b4 	stq	t0,2064(sp)
 968:	03 00 1f 22 	lda	a0,3
 96c:	68 08 be b4 	stq	t4,2152(sp)
 970:	18 08 de b4 	stq	t5,2072(sp)
 974:	f6 ff 29 21 	lda	s0,-10(s0)
 978:	20 08 5e b4 	stq	t1,2080(sp)
 97c:	00 00 7d a7 	ldq	t12,0(gp)
 980:	00 40 5b 6b 	jsr	ra,(t12),984 <__gettextparse+0x784>
 984:	00 00 ba 27 	ldah	gp,0(ra)
 988:	00 00 bd 23 	lda	gp,0(gp)
 98c:	d8 ff 0a 21 	lda	t7,-40(s1)
 990:	68 08 be a4 	ldq	t4,2152(sp)
 994:	ff ff 3f 20 	lda	t0,-1
 998:	02 00 ff 20 	lda	t6,2
 99c:	f1 fe ff c3 	br	564 <__gettextparse+0x364>
 9a0:	00 00 2a a4 	ldq	t0,0(s1)
 9a4:	bb 00 20 e4 	beq	t0,c94 <__gettextparse+0xa94>
 9a8:	f8 ff 0a 21 	lda	t7,-8(s1)
 9ac:	40 08 5e a4 	ldq	t1,2112(sp)
 9b0:	fe ff 29 21 	lda	s0,-2(s0)
 9b4:	01 00 ff 20 	lda	t6,1
 9b8:	08 00 22 b4 	stq	t0,8(t1)
 9bc:	f6 ff 3f 20 	lda	t0,-10
 9c0:	e8 fe ff c3 	br	564 <__gettextparse+0x364>
 9c4:	00 00 dd 24 	ldah	t5,0(gp)
 9c8:	00 00 c6 20 	lda	t5,0(t5)
 9cc:	46 04 46 40 	s4addq	t1,t5,t5
 9d0:	00 00 c6 a0 	ldl	t5,0(t5)
 9d4:	06 04 a6 43 	addq	gp,t5,t5
 9d8:	00 00 e6 6b 	jmp	(t5)
 9dc:	00 00 fe 2f 	unop	
 9e0:	40 08 7e a4 	ldq	t2,2112(sp)
 9e4:	00 00 e3 b6 	stq	t9,0(t2)
 9e8:	2c fe ff c3 	br	29c <__gettextparse+0x9c>
 9ec:	00 00 fe 2f 	unop	
 9f0:	02 00 b6 20 	lda	t4,2(t8)
 9f4:	01 00 56 2c 	ldq_u	t1,1(t8)
 9f8:	50 08 9e a4 	ldq	t3,2128(sp)
 9fc:	42 0f 45 48 	extqh	t1,t4,t1
 a00:	82 17 47 48 	sra	t1,0x38,t1
 a04:	a2 b5 47 40 	cmpeq	t1,0x3d,t1
 a08:	b3 00 40 f4 	bne	t1,cd8 <__gettextparse+0xad8>
 a0c:	22 16 9e 48 	zapnot	t3,0xf0,t1
 a10:	40 08 7e a4 	ldq	t2,2112(sp)
 a14:	03 01 bf 20 	lda	t4,259
 a18:	02 34 41 44 	or	t1,0x9,t1
 a1c:	50 08 5e b4 	stq	t1,2128(sp)
 a20:	00 00 03 b5 	stq	t7,0(t2)
 a24:	07 00 1f 21 	lda	t7,7
 a28:	22 fe ff c3 	br	2b4 <__gettextparse+0xb4>
 a2c:	00 00 fe 2f 	unop	
 a30:	50 08 9e a4 	ldq	t3,2128(sp)
 a34:	05 01 bf 20 	lda	t4,261
 a38:	40 08 7e a4 	ldq	t2,2112(sp)
 a3c:	22 16 9e 48 	zapnot	t3,0xf0,t1
 a40:	00 00 03 b5 	stq	t7,0(t2)
 a44:	09 00 1f 21 	lda	t7,9
 a48:	02 74 40 44 	or	t1,0x3,t1
 a4c:	50 08 5e b4 	stq	t1,2128(sp)
 a50:	18 fe ff c3 	br	2b4 <__gettextparse+0xb4>
 a54:	00 00 fe 2f 	unop	
 a58:	1f 04 ff 47 	nop	
 a5c:	00 00 fe 2f 	unop	
 a60:	50 08 9e a4 	ldq	t3,2128(sp)
 a64:	04 01 bf 20 	lda	t4,260
 a68:	40 08 7e a4 	ldq	t2,2112(sp)
 a6c:	22 16 9e 48 	zapnot	t3,0xf0,t1
 a70:	00 00 03 b5 	stq	t7,0(t2)
 a74:	08 00 1f 21 	lda	t7,8
 a78:	02 f4 40 44 	or	t1,0x7,t1
 a7c:	50 08 5e b4 	stq	t1,2128(sp)
 a80:	0c fe ff c3 	br	2b4 <__gettextparse+0xb4>
 a84:	00 00 fe 2f 	unop	
 a88:	1f 04 ff 47 	nop	
 a8c:	00 00 fe 2f 	unop	
 a90:	50 08 9e a4 	ldq	t3,2128(sp)
 a94:	04 01 bf 20 	lda	t4,260
 a98:	40 08 7e a4 	ldq	t2,2112(sp)
 a9c:	22 16 9e 48 	zapnot	t3,0xf0,t1
 aa0:	00 00 03 b5 	stq	t7,0(t2)
 aa4:	08 00 1f 21 	lda	t7,8
 aa8:	02 d4 40 44 	or	t1,0x6,t1
 aac:	50 08 5e b4 	stq	t1,2128(sp)
 ab0:	00 fe ff c3 	br	2b4 <__gettextparse+0xb4>
 ab4:	00 00 fe 2f 	unop	
 ab8:	1f 04 ff 47 	nop	
 abc:	00 00 fe 2f 	unop	
 ac0:	02 00 f6 22 	lda	t9,2(t8)
 ac4:	01 00 d6 2c 	ldq_u	t5,1(t8)
 ac8:	46 0f d7 48 	extqh	t5,t9,t5
 acc:	86 17 c7 48 	sra	t5,0x38,t5
 ad0:	a2 05 c2 40 	cmpeq	t5,t1,t1
 ad4:	c2 ff 5f f4 	bne	t1,9e0 <__gettextparse+0x7e0>
 ad8:	00 01 bf 20 	lda	t4,256
 adc:	40 08 7e a4 	ldq	t2,2112(sp)
 ae0:	00 00 03 b5 	stq	t7,0(t2)
 ae4:	01 00 1f 21 	lda	t7,1
 ae8:	f2 fd ff c3 	br	2b4 <__gettextparse+0xb4>
 aec:	00 00 fe 2f 	unop	
 af0:	50 08 9e a4 	ldq	t3,2128(sp)
 af4:	05 01 bf 20 	lda	t4,261
 af8:	40 08 7e a4 	ldq	t2,2112(sp)
 afc:	22 16 9e 48 	zapnot	t3,0xf0,t1
 b00:	00 00 03 b5 	stq	t7,0(t2)
 b04:	09 00 1f 21 	lda	t7,9
 b08:	02 b4 40 44 	or	t1,0x5,t1
 b0c:	50 08 5e b4 	stq	t1,2128(sp)
 b10:	e8 fd ff c3 	br	2b4 <__gettextparse+0xb4>
 b14:	00 00 fe 2f 	unop	
 b18:	1f 04 ff 47 	nop	
 b1c:	00 00 fe 2f 	unop	
 b20:	02 00 b6 20 	lda	t4,2(t8)
 b24:	01 00 56 2c 	ldq_u	t1,1(t8)
 b28:	42 0f 45 48 	extqh	t1,t4,t1
 b2c:	82 17 47 48 	sra	t1,0x38,t1
 b30:	a2 b5 47 40 	cmpeq	t1,0x3d,t1
 b34:	70 00 40 f4 	bne	t1,cf8 <__gettextparse+0xaf8>
 b38:	21 00 bf 20 	lda	t4,33
 b3c:	40 08 5e a4 	ldq	t1,2112(sp)
 b40:	00 00 02 b5 	stq	t7,0(t1)
 b44:	0a 00 1f 21 	lda	t7,10
 b48:	da fd ff c3 	br	2b4 <__gettextparse+0xb4>
 b4c:	00 00 fe 2f 	unop	
 b50:	08 04 ff 47 	clr	t7
 b54:	40 08 5e a4 	ldq	t1,2112(sp)
 b58:	05 04 ff 47 	clr	t4
 b5c:	00 00 c2 b6 	stq	t8,0(t1)
 b60:	d5 fd ff c3 	br	2b8 <__gettextparse+0xb8>
 b64:	00 00 fe 2f 	unop	
 b68:	1f 04 ff 47 	nop	
 b6c:	00 00 fe 2f 	unop	
 b70:	02 00 b6 20 	lda	t4,2(t8)
 b74:	01 00 56 2c 	ldq_u	t1,1(t8)
 b78:	42 0f 45 48 	extqh	t1,t4,t1
 b7c:	82 17 47 48 	sra	t1,0x38,t1
 b80:	a2 b5 47 40 	cmpeq	t1,0x3d,t1
 b84:	00 ff 5f e4 	beq	t1,788 <__gettextparse+0x588>
 b88:	50 08 9e a4 	ldq	t3,2128(sp)
 b8c:	06 00 1f 21 	lda	t7,6
 b90:	40 08 7e a4 	ldq	t2,2112(sp)
 b94:	22 16 9e 48 	zapnot	t3,0xf0,t1
 b98:	00 00 a3 b4 	stq	t4,0(t2)
 b9c:	02 01 bf 20 	lda	t4,258
 ba0:	02 94 41 44 	or	t1,0xc,t1
 ba4:	50 08 5e b4 	stq	t1,2128(sp)
 ba8:	c2 fd ff c3 	br	2b4 <__gettextparse+0xb4>
 bac:	00 00 fe 2f 	unop	
 bb0:	02 00 b6 20 	lda	t4,2(t8)
 bb4:	01 00 56 2c 	ldq_u	t1,1(t8)
 bb8:	50 08 9e a4 	ldq	t3,2128(sp)
 bbc:	42 0f 45 48 	extqh	t1,t4,t1
 bc0:	82 17 47 48 	sra	t1,0x38,t1
 bc4:	a2 b5 47 40 	cmpeq	t1,0x3d,t1
 bc8:	3b 00 40 f4 	bne	t1,cb8 <__gettextparse+0xab8>
 bcc:	22 16 9e 48 	zapnot	t3,0xf0,t1
 bd0:	40 08 7e a4 	ldq	t2,2112(sp)
 bd4:	03 01 bf 20 	lda	t4,259
 bd8:	02 14 41 44 	or	t1,0x8,t1
 bdc:	50 08 5e b4 	stq	t1,2128(sp)
 be0:	00 00 03 b5 	stq	t7,0(t2)
 be4:	07 00 1f 21 	lda	t7,7
 be8:	b2 fd ff c3 	br	2b4 <__gettextparse+0xb4>
 bec:	00 00 fe 2f 	unop	
 bf0:	02 00 d6 20 	lda	t5,2(t8)
 bf4:	01 00 56 2c 	ldq_u	t1,1(t8)
 bf8:	25 11 a6 40 	subl	t4,0x30,t4
 bfc:	42 0f 46 48 	extqh	t1,t5,t1
 c00:	82 17 47 48 	sra	t1,0x38,t1
 c04:	22 11 46 40 	subl	t1,0x30,t1
 c08:	06 f0 5f 44 	and	t1,0xff,t5
 c0c:	a6 37 c1 40 	cmpule	t5,0x9,t5
 c10:	0e 00 c0 e4 	beq	t5,c4c <__gettextparse+0xa4c>
 c14:	01 00 08 21 	lda	t7,1(t7)
 c18:	17 04 e8 47 	mov	t7,t9
 c1c:	01 00 08 21 	lda	t7,1(t7)
 c20:	45 04 a5 40 	s4addq	t4,t4,t4
 c24:	00 00 d7 2c 	ldq_u	t5,0(t9)
 c28:	02 00 e2 43 	sextl	t1,t1
 c2c:	05 04 a5 40 	addq	t4,t4,t4
 c30:	46 0f c8 48 	extqh	t5,t7,t5
 c34:	05 04 45 40 	addq	t1,t4,t4
 c38:	82 17 c7 48 	sra	t5,0x38,t1
 c3c:	22 11 46 40 	subl	t1,0x30,t1
 c40:	06 f0 5f 44 	and	t1,0xff,t5
 c44:	a6 37 c1 40 	cmpule	t5,0x9,t5
 c48:	f3 ff df f4 	bne	t5,c18 <__gettextparse+0xa18>
 c4c:	40 08 7e a4 	ldq	t2,2112(sp)
 c50:	50 08 be b4 	stq	t4,2128(sp)
 c54:	0b 00 1f 21 	lda	t7,11
 c58:	06 01 bf 20 	lda	t4,262
 c5c:	00 00 e3 b6 	stq	t9,0(t2)
 c60:	94 fd ff c3 	br	2b4 <__gettextparse+0xb4>
 c64:	00 00 fe 2f 	unop	
 c68:	1f 04 ff 47 	nop	
 c6c:	00 00 fe 2f 	unop	
 c70:	50 08 9e a4 	ldq	t3,2128(sp)
 c74:	05 01 bf 20 	lda	t4,261
 c78:	40 08 7e a4 	ldq	t2,2112(sp)
 c7c:	22 16 9e 48 	zapnot	t3,0xf0,t1
 c80:	00 00 03 b5 	stq	t7,0(t2)
 c84:	09 00 1f 21 	lda	t7,9
 c88:	02 94 40 44 	or	t1,0x4,t1
 c8c:	50 08 5e b4 	stq	t1,2128(sp)
 c90:	88 fd ff c3 	br	2b4 <__gettextparse+0xb4>
 c94:	09 04 ed 47 	mov	s4,s0
 c98:	01 00 5f 21 	lda	s1,1
 c9c:	01 fe ff c3 	br	4a4 <__gettextparse+0x2a4>
 ca0:	09 04 ed 47 	mov	s4,s0
 ca4:	02 00 5f 21 	lda	s1,2
 ca8:	fe fd ff c3 	br	4a4 <__gettextparse+0x2a4>
 cac:	09 04 ef 47 	mov	fp,s0
 cb0:	01 00 5f 21 	lda	s1,1
 cb4:	fe fd ff c3 	br	4b0 <__gettextparse+0x2b0>
 cb8:	22 16 9e 48 	zapnot	t3,0xf0,t1
 cbc:	40 08 7e a4 	ldq	t2,2112(sp)
 cc0:	07 00 1f 21 	lda	t7,7
 cc4:	02 54 41 44 	or	t1,0xa,t1
 cc8:	50 08 5e b4 	stq	t1,2128(sp)
 ccc:	00 00 a3 b4 	stq	t4,0(t2)
 cd0:	03 01 bf 20 	lda	t4,259
 cd4:	77 fd ff c3 	br	2b4 <__gettextparse+0xb4>
 cd8:	22 16 9e 48 	zapnot	t3,0xf0,t1
 cdc:	40 08 7e a4 	ldq	t2,2112(sp)
 ce0:	07 00 1f 21 	lda	t7,7
 ce4:	02 74 41 44 	or	t1,0xb,t1
 ce8:	50 08 5e b4 	stq	t1,2128(sp)
 cec:	00 00 a3 b4 	stq	t4,0(t2)
 cf0:	03 01 bf 20 	lda	t4,259
 cf4:	6f fd ff c3 	br	2b4 <__gettextparse+0xb4>
 cf8:	50 08 9e a4 	ldq	t3,2128(sp)
 cfc:	06 00 1f 21 	lda	t7,6
 d00:	40 08 7e a4 	ldq	t2,2112(sp)
 d04:	22 16 9e 48 	zapnot	t3,0xf0,t1
 d08:	00 00 a3 b4 	stq	t4,0(t2)
 d0c:	02 01 bf 20 	lda	t4,258
 d10:	02 b4 41 44 	or	t1,0xd,t1
 d14:	50 08 5e b4 	stq	t1,2128(sp)
 d18:	66 fd ff c3 	br	2b4 <__gettextparse+0xb4>
 d1c:	00 00 fe 2f 	unop	

[-- Attachment #4: plural-array-to-string.txt --]
[-- Type: text/plain, Size: 3316 bytes --]

/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:527:1: note: yytranslate = "\000\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\012\002\002\002\002\005\002\016\017\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\014\002\002\002\002\003\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\015\002\002\002\002\002\002\002\002\002\002\002\002\002\004\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\002\001\002\006\007\010\011"
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:600:1: note: yypact = "\37777777767\37777777767\37777777766\37777777766\37777777767\010$\37777777766\015\37777777766\37777777767\37777777767\37777777767\37777777767\37777777767\37777777767\37777777767\37777777766\032)-\022\37777777776\016\37777777766\37777777767"
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:610:1: note: yydefact = "\000\000\014\013\000\000\002\012\000\001\000\000\000\000\000\000\000\015\000\004\005\006\007\010\011\000"
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:618:1: note: yypgoto = "\37777777766\37777777766"
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:624:1: note: yydefgoto = "\37777777777\005"
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:632:1: note: yytable = "\007\001\002\010\003\004\017\020\011\022\023\024\025\026\027\030\012\013\014\015\016\017\020\020\032\016\017\020\021\012\013\014\015\016\017\020\000\000\031\012\013\014\015\016\017\020\014\015\016\017\020\015\016\017"
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:642:1: note: yycheck = "\001\012\013\004\015\016\010\011\000\012\013\014\015\016\017\020\003\004\005\006\007\010\011\011\031\007\010\011\017\003\004\005\006\007\010\011\37777777777\37777777777\014\003\004\005\006\007\010\011\005\006\007\010\011\006\007\010"
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:654:1: note: yystos = "\000\012\013\015\016\021\022\022\022\000\003\004\005\006\007\010\011\017\022\022\022\022\022\022\022\014"
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:662:1: note: yyr1 = "\000\020\021\022\022\022\022\022\022\022\022\022\022"
/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c:669:1: note: yyr2 = "\000\002\001\005\003\003\003\003\003\003\002\001\001"

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-15 21:02                     ` Martin Sebor
@ 2018-08-15 21:14                       ` Jeff Law
  2018-08-15 21:34                       ` Jeff Law
  1 sibling, 0 replies; 45+ messages in thread
From: Jeff Law @ 2018-08-15 21:14 UTC (permalink / raw)
  To: Martin Sebor, Joseph Myers
  Cc: James Greenhalgh, Jason Merrill, Gcc Patch List, nd

On 08/15/2018 03:02 PM, Martin Sebor wrote:
> On 08/15/2018 06:07 AM, Joseph Myers wrote:
>> On Tue, 14 Aug 2018, Martin Sebor wrote:
>>
>>>> This is with Bison 3.0.4, should the version used to produce
>>>> intl/plural.c
>>>> prove relevant.
>>>
>>> Can you send me the translation unit and the options it was compiled
>>> with that triggered the errors?
>>
>> I've attached plural.i.  The error is a static link error linking sln,
>> but
>> maybe comparing results of compiling plural.i before and after the
>> changes
>> may be enlightening (unless it's actually a difference in code elsewhere
>> in glibc causing a link error reported in plural.o).
>>
>> Compiled with:
>>
>> alpha-glibc-linux-gnu-gcc
>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c
>>
>> -c -std=gnu11 -fgnu89-inline  -O2 -Wall -Werror -Wundef -Wwrite-strings
>> -fmerge-all-constants -fno-stack-protector -frounding-math -g
>> -Wstrict-prototypes -Wold-style-definition -fno-math-errno
>> -mlong-double-128 -mieee -mfp-rounding-mode=d    
>> -ftls-model=initial-exec
>> -I../include
>> -I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl
>>
>> -I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu
>>
>> -I../sysdeps/unix/sysv/linux/alpha/alpha
>> -I../sysdeps/unix/sysv/linux/alpha/fpu  -I../sysdeps/alpha/fpu
>> -I../sysdeps/unix/sysv/linux/alpha  -I../sysdeps/alpha/nptl
>> -I../sysdeps/unix/sysv/linux/wordsize-64 
>> -I../sysdeps/ieee754/ldbl-64-128
>> -I../sysdeps/ieee754/ldbl-opt  -I../sysdeps/unix/sysv/linux/include
>> -I../sysdeps/unix/sysv/linux  -I../sysdeps/nptl  -I../sysdeps/pthread
>> -I../sysdeps/gnu  -I../sysdeps/unix/inet  -I../sysdeps/unix/sysv
>> -I../sysdeps/unix/alpha  -I../sysdeps/unix  -I../sysdeps/posix
>> -I../sysdeps/alpha  -I../sysdeps/wordsize-64
>> -I../sysdeps/ieee754/ldbl-128  -I../sysdeps/ieee754/dbl-64/wordsize-64
>> -I../sysdeps/ieee754/dbl-64  -I../sysdeps/ieee754/flt-32
>> -I../sysdeps/ieee754  -I../sysdeps/generic  -I.. -I../libio -I.
>> -D_LIBC_REENTRANT -include
>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/libc-modules.h
>>
>> -DMODULE_NAME=libc -include ../include/libc-symbols.h
>> -DTOP_NAMESPACE=glibc -D'LOCALEDIR="/usr/share/locale"'
>> -D'LOCALE_ALIAS_PATH="/usr/share/locale"' -o
>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o
>>
>> -MD -MP -MF
>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o.dt
>>
>> -MT
>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o
>>
>>
> 
> Thanks.  I don't see anything obviously wrong but I don't know
> much about Alpha assembly.  Attached are the two .s files, with
> (plural-new.s) and without (plural-old.s) the array-to-string
> transformation.
> 
> There are also only a handful of transformed arrays in the file
> and they all look reasonable to me (see the attachment named
> plural-array-to-string.txt).  The only arrays in the .sdata
> section are yydefgoto and yypgoto, both before and after.
> They are each just 3 bytes in size.
> 
> There is one unusual difference in the loads of one of them in
> the assembly emitted by GCC for __gettextparse.
> 
> Before:
> 
>     ldah $22,yypgoto($29)                !gprelhigh
>     ...
>     lda $2,yypgoto($22)                !gprellow
> 
> After:
> 
>     ldah $2,yypgoto+2305843009213693936($29)    !gprelhigh
>     ...
>     lda $2,yypgoto+2305843009213693936($2)        !gprellow
> 
> I don't know if it's significant -- the lda instruction uses
> just the least significant 16 bits of the constant displacement,
> shifted left by 16.  I don't see any obviously bogus constants
> in the disassembly produced by objdump.
> 
> I'll need some help from someone who knows more about Alpha
> to understand what's going on.
I wonder if the change to how we set up the initializers is ultimately
changing the section those go into and ultimately causing an overflow of
the .sdata section.

Jeff
> 
> Martin

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-15 21:02                     ` Martin Sebor
  2018-08-15 21:14                       ` Jeff Law
@ 2018-08-15 21:34                       ` Jeff Law
  2018-08-16 15:23                         ` Martin Sebor
  1 sibling, 1 reply; 45+ messages in thread
From: Jeff Law @ 2018-08-15 21:34 UTC (permalink / raw)
  To: Martin Sebor, Joseph Myers
  Cc: James Greenhalgh, Jason Merrill, Gcc Patch List, nd

On 08/15/2018 03:02 PM, Martin Sebor wrote:
> On 08/15/2018 06:07 AM, Joseph Myers wrote:
>> On Tue, 14 Aug 2018, Martin Sebor wrote:
>>
>>>> This is with Bison 3.0.4, should the version used to produce
>>>> intl/plural.c
>>>> prove relevant.
>>>
>>> Can you send me the translation unit and the options it was compiled
>>> with that triggered the errors?
>>
>> I've attached plural.i.  The error is a static link error linking sln,
>> but
>> maybe comparing results of compiling plural.i before and after the
>> changes
>> may be enlightening (unless it's actually a difference in code elsewhere
>> in glibc causing a link error reported in plural.o).
>>
>> Compiled with:
>>
>> alpha-glibc-linux-gnu-gcc
>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c
>>
>> -c -std=gnu11 -fgnu89-inline  -O2 -Wall -Werror -Wundef -Wwrite-strings
>> -fmerge-all-constants -fno-stack-protector -frounding-math -g
>> -Wstrict-prototypes -Wold-style-definition -fno-math-errno
>> -mlong-double-128 -mieee -mfp-rounding-mode=d    
>> -ftls-model=initial-exec
>> -I../include
>> -I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl
>>
>> -I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu
>>
>> -I../sysdeps/unix/sysv/linux/alpha/alpha
>> -I../sysdeps/unix/sysv/linux/alpha/fpu  -I../sysdeps/alpha/fpu
>> -I../sysdeps/unix/sysv/linux/alpha  -I../sysdeps/alpha/nptl
>> -I../sysdeps/unix/sysv/linux/wordsize-64 
>> -I../sysdeps/ieee754/ldbl-64-128
>> -I../sysdeps/ieee754/ldbl-opt  -I../sysdeps/unix/sysv/linux/include
>> -I../sysdeps/unix/sysv/linux  -I../sysdeps/nptl  -I../sysdeps/pthread
>> -I../sysdeps/gnu  -I../sysdeps/unix/inet  -I../sysdeps/unix/sysv
>> -I../sysdeps/unix/alpha  -I../sysdeps/unix  -I../sysdeps/posix
>> -I../sysdeps/alpha  -I../sysdeps/wordsize-64
>> -I../sysdeps/ieee754/ldbl-128  -I../sysdeps/ieee754/dbl-64/wordsize-64
>> -I../sysdeps/ieee754/dbl-64  -I../sysdeps/ieee754/flt-32
>> -I../sysdeps/ieee754  -I../sysdeps/generic  -I.. -I../libio -I.
>> -D_LIBC_REENTRANT -include
>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/libc-modules.h
>>
>> -DMODULE_NAME=libc -include ../include/libc-symbols.h
>> -DTOP_NAMESPACE=glibc -D'LOCALEDIR="/usr/share/locale"'
>> -D'LOCALE_ALIAS_PATH="/usr/share/locale"' -o
>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o
>>
>> -MD -MP -MF
>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o.dt
>>
>> -MT
>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o
>>
>>
> 
> Thanks.  I don't see anything obviously wrong but I don't know
> much about Alpha assembly.  Attached are the two .s files, with
> (plural-new.s) and without (plural-old.s) the array-to-string
> transformation.
I'd focus on these  insns which correspond to the error from the linker:

They're in plural.o within the fucntion gettextparse


        ldah $2,yypgoto+2305843009213693936($29)                !gprelhigh

Something certainly doesn't look right...

At the .o level this turns into:
218:   00 00 5d 24     ldah    t1,0(gp)
                        218: GPRELHIGH  .sdata+0x1ffffffffffffff3


300:   00 00 5d 24     ldah    t1,0(gp)
                        300: GPRELHIGH  .sdata+0x1ffffffffffffff3

It's not really a matter of what the instruction does, but a matter of
the relocation.  You'd have to look at the definition of GPRELHIGH which
you can find in BFD.


Jeff

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-15 21:34                       ` Jeff Law
@ 2018-08-16 15:23                         ` Martin Sebor
  2018-08-16 15:32                           ` Jeff Law
  0 siblings, 1 reply; 45+ messages in thread
From: Martin Sebor @ 2018-08-16 15:23 UTC (permalink / raw)
  To: Jeff Law, Joseph Myers
  Cc: James Greenhalgh, Jason Merrill, Gcc Patch List, nd

On 08/15/2018 03:34 PM, Jeff Law wrote:
> On 08/15/2018 03:02 PM, Martin Sebor wrote:
>> On 08/15/2018 06:07 AM, Joseph Myers wrote:
>>> On Tue, 14 Aug 2018, Martin Sebor wrote:
>>>
>>>>> This is with Bison 3.0.4, should the version used to produce
>>>>> intl/plural.c
>>>>> prove relevant.
>>>>
>>>> Can you send me the translation unit and the options it was compiled
>>>> with that triggered the errors?
>>>
>>> I've attached plural.i.  The error is a static link error linking sln,
>>> but
>>> maybe comparing results of compiling plural.i before and after the
>>> changes
>>> may be enlightening (unless it's actually a difference in code elsewhere
>>> in glibc causing a link error reported in plural.o).
>>>
>>> Compiled with:
>>>
>>> alpha-glibc-linux-gnu-gcc
>>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c
>>>
>>> -c -std=gnu11 -fgnu89-inline  -O2 -Wall -Werror -Wundef -Wwrite-strings
>>> -fmerge-all-constants -fno-stack-protector -frounding-math -g
>>> -Wstrict-prototypes -Wold-style-definition -fno-math-errno
>>> -mlong-double-128 -mieee -mfp-rounding-mode=d
>>> -ftls-model=initial-exec
>>> -I../include
>>> -I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl
>>>
>>> -I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu
>>>
>>> -I../sysdeps/unix/sysv/linux/alpha/alpha
>>> -I../sysdeps/unix/sysv/linux/alpha/fpu  -I../sysdeps/alpha/fpu
>>> -I../sysdeps/unix/sysv/linux/alpha  -I../sysdeps/alpha/nptl
>>> -I../sysdeps/unix/sysv/linux/wordsize-64
>>> -I../sysdeps/ieee754/ldbl-64-128
>>> -I../sysdeps/ieee754/ldbl-opt  -I../sysdeps/unix/sysv/linux/include
>>> -I../sysdeps/unix/sysv/linux  -I../sysdeps/nptl  -I../sysdeps/pthread
>>> -I../sysdeps/gnu  -I../sysdeps/unix/inet  -I../sysdeps/unix/sysv
>>> -I../sysdeps/unix/alpha  -I../sysdeps/unix  -I../sysdeps/posix
>>> -I../sysdeps/alpha  -I../sysdeps/wordsize-64
>>> -I../sysdeps/ieee754/ldbl-128  -I../sysdeps/ieee754/dbl-64/wordsize-64
>>> -I../sysdeps/ieee754/dbl-64  -I../sysdeps/ieee754/flt-32
>>> -I../sysdeps/ieee754  -I../sysdeps/generic  -I.. -I../libio -I.
>>> -D_LIBC_REENTRANT -include
>>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/libc-modules.h
>>>
>>> -DMODULE_NAME=libc -include ../include/libc-symbols.h
>>> -DTOP_NAMESPACE=glibc -D'LOCALEDIR="/usr/share/locale"'
>>> -D'LOCALE_ALIAS_PATH="/usr/share/locale"' -o
>>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o
>>>
>>> -MD -MP -MF
>>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o.dt
>>>
>>> -MT
>>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o
>>>
>>>
>>
>> Thanks.  I don't see anything obviously wrong but I don't know
>> much about Alpha assembly.  Attached are the two .s files, with
>> (plural-new.s) and without (plural-old.s) the array-to-string
>> transformation.
> I'd focus on these  insns which correspond to the error from the linker:
>
> They're in plural.o within the fucntion gettextparse
>
>
>         ldah $2,yypgoto+2305843009213693936($29)                !gprelhigh
>
> Something certainly doesn't look right...

Thanks.  I also get the same exact same assembly with both
forms of initializers for the two constant arrays, i.e.,

   static const yytype_int8 yypgoto[3] = "\366\366\377";
   static const yytype_int8 yydefgoto[3] = "\377\005\006";

and

   static const yytype_int8 yypgoto[] = { -10, -10, -1 };
   static const yytype_int8 yydefgoto[] = { -1, 5, 6 };

They end up in the .sdata section either way (the former
both with and without the GCC change as might be expected):

         .section        .sdata,"aws"
         .type   yydefgoto, @object
         .size   yydefgoto, 3
   yydefgoto:
         .ascii  "\377\005\006"
         .type   yypgoto, @object
         .size   yypgoto, 3
   yypgoto:
         .ascii  "\366\366\377"
         .section        .rodata

and also before the GCC change:

         .section        .sdata,"aws"
         .type   yydefgoto, @object
         .size   yydefgoto, 3
   yydefgoto:
         .byte   -1
         .byte   5
         .byte   6
         .type   yypgoto, @object
         .size   yypgoto, 3
   yypgoto:
         .byte   -10
         .byte   -10
         .byte   -1

> At the .o level this turns into:
> 218:   00 00 5d 24     ldah    t1,0(gp)
>                         218: GPRELHIGH  .sdata+0x1ffffffffffffff3
>
>
> 300:   00 00 5d 24     ldah    t1,0(gp)
>                         300: GPRELHIGH  .sdata+0x1ffffffffffffff3
>
> It's not really a matter of what the instruction does, but a matter of
> the relocation.  You'd have to look at the definition of GPRELHIGH which
> you can find in BFD.

The definitions match the assembly with both kinds of
initializers, and with the string literal also with GCC before
the change:

   0000000000000218 GPRELHIGH         .sdata+0x1ffffffffffffff3
   0000000000000238 GPRELLOW          .sdata+0x1ffffffffffffff3
   0000000000000300 GPRELHIGH         .sdata+0x1ffffffffffffff3
   0000000000000308 GPRELLOW          .sdata+0x1ffffffffffffff3
   0000000000000458 GPRELHIGH         .sdata+0x0000000000000003
   0000000000000468 GPRELLOW          .sdata+0x0000000000000003

vs the array form before the GCC change:

   0000000000000468 GPRELHIGH         .sdata+0x0000000000000003
   0000000000000488 GPRELLOW          .sdata+0x0000000000000003
   000000000000057c GPRELHIGH         .sdata
   0000000000000580 GPRELLOW          .sdata

So it seems as though using the string literal as an initializer
tickles a latent bug in GCC and the question is where.

Martin

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-16 15:23                         ` Martin Sebor
@ 2018-08-16 15:32                           ` Jeff Law
  0 siblings, 0 replies; 45+ messages in thread
From: Jeff Law @ 2018-08-16 15:32 UTC (permalink / raw)
  To: Martin Sebor, Joseph Myers
  Cc: James Greenhalgh, Jason Merrill, Gcc Patch List, nd

On 08/16/2018 09:23 AM, Martin Sebor wrote:
> On 08/15/2018 03:34 PM, Jeff Law wrote:
>> On 08/15/2018 03:02 PM, Martin Sebor wrote:
>>> On 08/15/2018 06:07 AM, Joseph Myers wrote:
>>>> On Tue, 14 Aug 2018, Martin Sebor wrote:
>>>>
>>>>>> This is with Bison 3.0.4, should the version used to produce
>>>>>> intl/plural.c
>>>>>> prove relevant.
>>>>>
>>>>> Can you send me the translation unit and the options it was compiled
>>>>> with that triggered the errors?
>>>>
>>>> I've attached plural.i.  The error is a static link error linking sln,
>>>> but
>>>> maybe comparing results of compiling plural.i before and after the
>>>> changes
>>>> may be enlightening (unless it's actually a difference in code
>>>> elsewhere
>>>> in glibc causing a link error reported in plural.o).
>>>>
>>>> Compiled with:
>>>>
>>>> alpha-glibc-linux-gnu-gcc
>>>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.c
>>>>
>>>>
>>>> -c -std=gnu11 -fgnu89-inline  -O2 -Wall -Werror -Wundef -Wwrite-strings
>>>> -fmerge-all-constants -fno-stack-protector -frounding-math -g
>>>> -Wstrict-prototypes -Wold-style-definition -fno-math-errno
>>>> -mlong-double-128 -mieee -mfp-rounding-mode=d
>>>> -ftls-model=initial-exec
>>>> -I../include
>>>> -I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl
>>>>
>>>>
>>>> -I/scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu
>>>>
>>>>
>>>> -I../sysdeps/unix/sysv/linux/alpha/alpha
>>>> -I../sysdeps/unix/sysv/linux/alpha/fpu  -I../sysdeps/alpha/fpu
>>>> -I../sysdeps/unix/sysv/linux/alpha  -I../sysdeps/alpha/nptl
>>>> -I../sysdeps/unix/sysv/linux/wordsize-64
>>>> -I../sysdeps/ieee754/ldbl-64-128
>>>> -I../sysdeps/ieee754/ldbl-opt  -I../sysdeps/unix/sysv/linux/include
>>>> -I../sysdeps/unix/sysv/linux  -I../sysdeps/nptl  -I../sysdeps/pthread
>>>> -I../sysdeps/gnu  -I../sysdeps/unix/inet  -I../sysdeps/unix/sysv
>>>> -I../sysdeps/unix/alpha  -I../sysdeps/unix  -I../sysdeps/posix
>>>> -I../sysdeps/alpha  -I../sysdeps/wordsize-64
>>>> -I../sysdeps/ieee754/ldbl-128  -I../sysdeps/ieee754/dbl-64/wordsize-64
>>>> -I../sysdeps/ieee754/dbl-64  -I../sysdeps/ieee754/flt-32
>>>> -I../sysdeps/ieee754  -I../sysdeps/generic  -I.. -I../libio -I.
>>>> -D_LIBC_REENTRANT -include
>>>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/libc-modules.h
>>>>
>>>>
>>>> -DMODULE_NAME=libc -include ../include/libc-symbols.h
>>>> -DTOP_NAMESPACE=glibc -D'LOCALEDIR="/usr/share/locale"'
>>>> -D'LOCALE_ALIAS_PATH="/usr/share/locale"' -o
>>>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o
>>>>
>>>>
>>>> -MD -MP -MF
>>>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o.dt
>>>>
>>>>
>>>> -MT
>>>> /scratch/jmyers/glibc/many9/build/compilers/alpha-linux-gnu/glibc/alpha-linux-gnu/intl/plural.o
>>>>
>>>>
>>>>
>>>
>>> Thanks.  I don't see anything obviously wrong but I don't know
>>> much about Alpha assembly.  Attached are the two .s files, with
>>> (plural-new.s) and without (plural-old.s) the array-to-string
>>> transformation.
>> I'd focus on these  insns which correspond to the error from the linker:
>>
>> They're in plural.o within the fucntion gettextparse
>>
>>
>>         ldah $2,yypgoto+2305843009213693936($29)               
>> !gprelhigh
>>
>> Something certainly doesn't look right...
> 
> Thanks.  I also get the same exact same assembly with both
> forms of initializers for the two constant arrays, i.e.,
> 
>   static const yytype_int8 yypgoto[3] = "\366\366\377";
>   static const yytype_int8 yydefgoto[3] = "\377\005\006";
> 
> and
> 
>   static const yytype_int8 yypgoto[] = { -10, -10, -1 };
>   static const yytype_int8 yydefgoto[] = { -1, 5, 6 };
> 
> They end up in the .sdata section either way (the former
> both with and without the GCC change as might be expected):
> 
>         .section        .sdata,"aws"
>         .type   yydefgoto, @object
>         .size   yydefgoto, 3
>   yydefgoto:
>         .ascii  "\377\005\006"
>         .type   yypgoto, @object
>         .size   yypgoto, 3
>   yypgoto:
>         .ascii  "\366\366\377"
>         .section        .rodata
> 
> and also before the GCC change:
> 
>         .section        .sdata,"aws"
>         .type   yydefgoto, @object
>         .size   yydefgoto, 3
>   yydefgoto:
>         .byte   -1
>         .byte   5
>         .byte   6
>         .type   yypgoto, @object
>         .size   yypgoto, 3
>   yypgoto:
>         .byte   -10
>         .byte   -10
>         .byte   -1
> 
>> At the .o level this turns into:
>> 218:   00 00 5d 24     ldah    t1,0(gp)
>>                         218: GPRELHIGH  .sdata+0x1ffffffffffffff3
>>
>>
>> 300:   00 00 5d 24     ldah    t1,0(gp)
>>                         300: GPRELHIGH  .sdata+0x1ffffffffffffff3
>>
>> It's not really a matter of what the instruction does, but a matter of
>> the relocation.  You'd have to look at the definition of GPRELHIGH which
>> you can find in BFD.
> 
> The definitions match the assembly with both kinds of
> initializers, and with the string literal also with GCC before
> the change:
> 
>   0000000000000218 GPRELHIGH         .sdata+0x1ffffffffffffff3
>   0000000000000238 GPRELLOW          .sdata+0x1ffffffffffffff3
>   0000000000000300 GPRELHIGH         .sdata+0x1ffffffffffffff3
>   0000000000000308 GPRELLOW          .sdata+0x1ffffffffffffff3
>   0000000000000458 GPRELHIGH         .sdata+0x0000000000000003
>   0000000000000468 GPRELLOW          .sdata+0x0000000000000003
> 
> vs the array form before the GCC change:
> 
>   0000000000000468 GPRELHIGH         .sdata+0x0000000000000003
>   0000000000000488 GPRELLOW          .sdata+0x0000000000000003
>   000000000000057c GPRELHIGH         .sdata
>   0000000000000580 GPRELLOW          .sdata
> 
> So it seems as though using the string literal as an initializer
> tickles a latent bug in GCC and the question is where.
I'd start working backwards from alpha_print_operand_address using a
cross compiler.  I'd also get a -dap dump and look at the actual address
in the insn that's emitting the offending ldah instructions.

Jeff

^ permalink raw reply	[flat|nested] 45+ messages in thread

* [PATCH] Fix poly types after PR tree-optimization/71625 strlen optimization
  2018-08-15 15:51                       ` Martin Sebor
@ 2018-08-17 17:19                         ` Szabolcs Nagy
  2018-08-17 17:22                           ` Kyrill Tkachov
  0 siblings, 1 reply; 45+ messages in thread
From: Szabolcs Nagy @ 2018-08-17 17:19 UTC (permalink / raw)
  To: Martin Sebor, James Greenhalgh
  Cc: nd, Jason Merrill, Gcc Patch List, Joseph Myers, Kyrylo Tkachov

[-- Attachment #1: Type: text/plain, Size: 1584 bytes --]

On 15/08/18 16:51, Martin Sebor wrote:
> On 08/15/2018 04:28 AM, James Greenhalgh wrote:
>> On Tue, Aug 14, 2018 at 09:34:08PM -0500, Martin Sebor wrote:
>>> On 08/14/2018 09:24 AM, Martin Sebor wrote:
>>>> On 08/14/2018 09:08 AM, Martin Sebor wrote:
>>>> --- gcc/config/aarch64/aarch64-builtins.c    (revision 263537)
>>>> +++ gcc/config/aarch64/aarch64-builtins.c    (working copy)
>>>> @@ -643,6 +643,7 @@ aarch64_init_simd_builtin_types (void)
>>>>    /* Poly types are a world of their own.  */
>>>>    aarch64_simd_types[Poly8_t].eltype = aarch64_simd_types[Poly8_t].itype =
>>>>      build_distinct_type_copy (unsigned_intQI_type_node);
>>>> +  TYPE_STRING_FLAG (aarch64_simd_types[Poly8_t].eltype) = false;
>>>>    aarch64_simd_types[Poly16_t].eltype =
>>>> aarch64_simd_types[Poly16_t].itype =
>>>>      build_distinct_type_copy (unsigned_intHI_type_node);
>>>>    aarch64_simd_types[Poly64_t].eltype =
>>>> aarch64_simd_types[Poly64_t].itype =
>>
>> This fix seems correct to me, the poly types are not strings. Looking at
>> other uses of TYPE_STRING_FLAG this change doesn't seem like it would have
>> impact on parsing or code generation.
>>
>> OK for trunk.
> 
> I committed this in r263561.
> 

happens on arm too.

Same as r263561, but for arm: avoid compilation errors caused by poly
initializers getting treated as string literals.

Tested on arm-none-linux-gnueabihf.

gcc/ChangeLog:
2018-08-17  Szabolcs Nagy  <szabolcs.nagy@arm.com>

	* config/arm/arm-builtins.c (arm_init_simd_builtin_types): Clear
	polyNxK_t element's TYPE_STRING_FLAG.

[-- Attachment #2: poly.diff --]
[-- Type: text/x-patch, Size: 728 bytes --]

diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c
index 183a7b907f6..563ca51dcd0 100644
--- a/gcc/config/arm/arm-builtins.c
+++ b/gcc/config/arm/arm-builtins.c
@@ -927,6 +927,11 @@ arm_init_simd_builtin_types (void)
   (*lang_hooks.types.register_builtin_type) (arm_simd_polyTI_type_node,
 					     "__builtin_neon_poly128");
 
+  /* Prevent front-ends from transforming poly vectors into string
+     literals.  */
+  TYPE_STRING_FLAG (arm_simd_polyQI_type_node) = false;
+  TYPE_STRING_FLAG (arm_simd_polyHI_type_node) = false;
+
   /* Init all the element types built by the front-end.  */
   arm_simd_types[Int8x8_t].eltype = intQI_type_node;
   arm_simd_types[Int8x16_t].eltype = intQI_type_node;

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] Fix poly types after PR tree-optimization/71625 strlen optimization
  2018-08-17 17:19                         ` [PATCH] Fix poly types after PR tree-optimization/71625 strlen optimization Szabolcs Nagy
@ 2018-08-17 17:22                           ` Kyrill Tkachov
  0 siblings, 0 replies; 45+ messages in thread
From: Kyrill Tkachov @ 2018-08-17 17:22 UTC (permalink / raw)
  To: Szabolcs Nagy, Martin Sebor, James Greenhalgh
  Cc: nd, Jason Merrill, Gcc Patch List, Joseph Myers

Hi Szabolcs,

On 17/08/18 18:18, Szabolcs Nagy wrote:
> On 15/08/18 16:51, Martin Sebor wrote:
> > On 08/15/2018 04:28 AM, James Greenhalgh wrote:
> >> On Tue, Aug 14, 2018 at 09:34:08PM -0500, Martin Sebor wrote:
> >>> On 08/14/2018 09:24 AM, Martin Sebor wrote:
> >>>> On 08/14/2018 09:08 AM, Martin Sebor wrote:
> >>>> --- gcc/config/aarch64/aarch64-builtins.c    (revision 263537)
> >>>> +++ gcc/config/aarch64/aarch64-builtins.c    (working copy)
> >>>> @@ -643,6 +643,7 @@ aarch64_init_simd_builtin_types (void)
> >>>>    /* Poly types are a world of their own. */
> >>>>    aarch64_simd_types[Poly8_t].eltype = aarch64_simd_types[Poly8_t].itype =
> >>>>      build_distinct_type_copy (unsigned_intQI_type_node);
> >>>> +  TYPE_STRING_FLAG (aarch64_simd_types[Poly8_t].eltype) = false;
> >>>>    aarch64_simd_types[Poly16_t].eltype =
> >>>> aarch64_simd_types[Poly16_t].itype =
> >>>>      build_distinct_type_copy (unsigned_intHI_type_node);
> >>>>    aarch64_simd_types[Poly64_t].eltype =
> >>>> aarch64_simd_types[Poly64_t].itype =
> >>
> >> This fix seems correct to me, the poly types are not strings. Looking at
> >> other uses of TYPE_STRING_FLAG this change doesn't seem like it would have
> >> impact on parsing or code generation.
> >>
> >> OK for trunk.
> >
> > I committed this in r263561.
> >
>
> happens on arm too.
>
> Same as r263561, but for arm: avoid compilation errors caused by poly
> initializers getting treated as string literals.
>
> Tested on arm-none-linux-gnueabihf.
>
> gcc/ChangeLog:
> 2018-08-17  Szabolcs Nagy  <szabolcs.nagy@arm.com>
>
>         * config/arm/arm-builtins.c (arm_init_simd_builtin_types): Clear
>         polyNxK_t element's TYPE_STRING_FLAG.


diff --git a/gcc/config/arm/arm-builtins.c b/gcc/config/arm/arm-builtins.c
index 183a7b907f6..563ca51dcd0 100644
--- a/gcc/config/arm/arm-builtins.c
+++ b/gcc/config/arm/arm-builtins.c
@@ -927,6 +927,11 @@ arm_init_simd_builtin_types (void)
    (*lang_hooks.types.register_builtin_type) (arm_simd_polyTI_type_node,
  					     "__builtin_neon_poly128");
  
+  /* Prevent front-ends from transforming poly vectors into string
+     literals.  */
+  TYPE_STRING_FLAG (arm_simd_polyQI_type_node) = false;
+  TYPE_STRING_FLAG (arm_simd_polyHI_type_node) = false;
+
    /* Init all the element types built by the front-end.  */
    arm_simd_types[Int8x8_t].eltype = intQI_type_node;
    arm_simd_types[Int8x16_t].eltype = intQI_type_node;

Ok.
Thanks,
Kyrill

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-18 16:46       ` Richard Sandiford
@ 2018-08-18 17:09         ` Bernd Edlinger
  0 siblings, 0 replies; 45+ messages in thread
From: Bernd Edlinger @ 2018-08-18 17:09 UTC (permalink / raw)
  To: Jeff Law, Martin Sebor, Joseph S. Myers, James Greenhalgh,
	Jason Merrill, GCC Patches, nd, richard.sandiford

[-- Attachment #1: Type: text/plain, Size: 6446 bytes --]

On 08/18/18 18:46, Richard Sandiford wrote:
> Bernd Edlinger <bernd.edlinger@hotmail.de> writes:
>> On 08/18/18 12:40, Richard Sandiford wrote:
>>> Bernd Edlinger <bernd.edlinger@hotmail.de> writes:
>>>> Hi everybody,
>>>>
>>>> On 08/16/18 08:36, Bernd Edlinger wrote:
>>>>> Jeff Law wrote:
>>>>>> I wonder if the change to how we set up the initializers is ultimately
>>>>>> changing the section those go into and ultimately causing an overflow of
>>>>>> the .sdata section.
>>>>>
>>>>>
>>>>> Yes, that is definitely the case.
>>>>> Due to the -fmerge-all-constants option used
>>>>> named arrays with brace initializer look like string initializers
>>>>> and can go into the merge section if there are no embedded nul chars.
>>>>> But the string constants can now be huge.
>>>>>
>>>>> See my other patch about string merging:
>>>>> [PATCH] Handle not explicitly zero terminated strings in merge sections
>>>>> https://gcc.gnu.org/ml/gcc-patches/2018-08/msg00481.html
>>>>>
>>>>>
>>>>> Can this section overflow?
>>>>>
>>>>
>>>>
>>>> could someone try out if this (untested) patch fixes the issue?
>>>>
>>>>
>>>> Thanks,
>>>> Bernd.
>>>>
>>>>
>>>> 2018-08-18  Bernd Edlinger  <bernd.edlinger@hotmail.de>
>>>>
>>>> 	* expmed.c (simple_mem_bitfield_p): Do shift right signed.
>>>> 	* config/alpha/alpha.h (CONSTANT_ADDRESS_P): Avoid signed
>>>> 	integer overflow.
>>>>
>>>> Index: gcc/config/alpha/alpha.h
>>>> ===================================================================
>>>> --- gcc/config/alpha/alpha.h	(revision 263611)
>>>> +++ gcc/config/alpha/alpha.h	(working copy)
>>>> @@ -678,7 +678,7 @@ enum reg_class {
>>>>    
>>>>    #define CONSTANT_ADDRESS_P(X)   \
>>>>      (CONST_INT_P (X)		\
>>>> -   && (unsigned HOST_WIDE_INT) (INTVAL (X) + 0x8000) < 0x10000)
>>>> +   && (UINTVAL (X) + 0x8000) < 0x10000)
>>>>    
>>>>    /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
>>>>       and check its validity for a certain class.
>>>> Index: gcc/expmed.c
>>>> ===================================================================
>>>> --- gcc/expmed.c	(revision 263611)
>>>> +++ gcc/expmed.c	(working copy)
>>>> @@ -579,8 +579,12 @@ static bool
>>>>    simple_mem_bitfield_p (rtx op0, poly_uint64 bitsize, poly_uint64 bitnum,
>>>>    		       machine_mode mode, poly_uint64 *bytenum)
>>>>    {
>>>> +  poly_int64 ibit = bitnum;
>>>> +  poly_int64 ibyte;
>>>> +  if (!multiple_p (ibit, BITS_PER_UNIT, &ibyte))
>>>> +    return false;
>>>> +  *bytenum = ibyte;
>>>>      return (MEM_P (op0)
>>>> -	  && multiple_p (bitnum, BITS_PER_UNIT, bytenum)
>>>>    	  && known_eq (bitsize, GET_MODE_BITSIZE (mode))
>>>>    	  && (!targetm.slow_unaligned_access (mode, MEM_ALIGN (op0))
>>>>    	      || (multiple_p (bitnum, GET_MODE_ALIGNMENT (mode))
>>>
>>> Do we have a genuinely negative bit offset here?  Seems like the callers
>>> would need to be updated if so, since the code is consistent in treating
>>> the offset as unsigned.
>>>
>>
>> Aehm, yes.
>>
>> The test case plural.i contains this:
>>
>> static const yytype_int8 yypgoto[] =
>> {
>>        -10, -10, -1
>> };
>>
>> static const yytype_uint8 yyr1[] =
>> {
>>          0, 16, 17, 18, 18, 18, 18, 18, 18, 18,
>>         18, 18, 18, 18
>> };
>>
>>     yyn = yyr1[yyn];
>>
>>     yystate = yypgoto[yyn - 16] + *yyssp;
>>
>>
>> There will probably a reason why yyn can never be 0
>> in yyn = yyr1[yyn]; but it is not really obvious.
>>
>> In plural.i.228t.optimized we have:
>>
>>    pretmp_400 = yypgoto[-16];
>>     _385 = (int) pretmp_400;
>>     goto <bb 69>; [100.00%]
> 
> Ah, ok.
> 
> [...]
> 
>> (gdb) frame 26
>> #26 0x000000000082f828 in expand_expr_real_1 (exp=<optimized out>, target=<optimized out>,
>>       tmode=<optimized out>, modifier=EXPAND_NORMAL, alt_rtl=0x0, inner_reference_p=<optimized out>)
>>       at ../../gcc-trunk/gcc/expr.c:10801
>> 10801					     ext_mode, ext_mode, reversep, alt_rtl);
>> (gdb) list
>> 10796		      reversep = TYPE_REVERSE_STORAGE_ORDER (type);
>> 10797	
>> 10798		    op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp,
>> 10799					     (modifier == EXPAND_STACK_PARM
>> 10800					      ? NULL_RTX : target),
>> 10801					     ext_mode, ext_mode, reversep, alt_rtl);
>> 10802	
>> 10803		    /* If the result has a record type and the mode of OP0 is an
>> 10804		       integral mode then, if BITSIZE is narrower than this mode
>> 10805		       and this is for big-endian data, we must put the field
>> (gdb) p bitpos
>> $1 = {<poly_int_pod<1u, long>> = {coeffs = {-128}}, <No data fields>}
> 
> The get_inner_reference->store_field path in expand_assignment has:
> 
>        /* Make sure bitpos is not negative, it can wreak havoc later.  */
>        if (maybe_lt (bitpos, 0))
> 	{
> 	  gcc_assert (offset == NULL_TREE);
> 	  offset = size_int (bits_to_bytes_round_down (bitpos));
> 	  bitpos = num_trailing_bits (bitpos);
> 	}
> 
> So maybe this is what havoc looks like.
> 
> It's not my area, but I think we should be doing something similar for
> the get_inner_reference->expand_bit_field path in expand_expr_real_1.
> Haven't checked whether the offset == NULL_TREE assert would be
> guaranteed there though.
> 

Yes, I come to the same conclusion.

The offset==NULL assertion reflects the logic around the "wreak havoc" comment
in get_inner_reference, so that is guaranteed to hold, at least immediately
after get_inner_reference returns.


>> $5 = {<poly_int_pod<1u, unsigned long>> = {coeffs = {0x1ffffffffffffff0}}, <No data fields>}
>>
>> The byte offset is completely wrong now, due to the bitnum was
>> initially a negative integer and got converted to unsigned.  At the
>> moment when that is converted to byte offsets it is done wrong.  I
>> think it is too much to change everything to signed arithmetics, but
>> at least when converting a bit pos to a byte pos, it should be done in
>> signed arithmetics.
> 
> But then we'd mishandle a real 1ULL << 63 bitpos (say).  Realise it's
> unlikely in real code, but it'd still probably be possible to construct
> a variant of the original test case in which the bias was
> +0x1000000000000000 rather than -16.
> 

Yes, I see, thanks.
Additionally I think we need some assertions, when signed bit quantities
are passed to store_bit_field and expand_bit_field.


Thanks
Bernd.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch-expr.diff --]
[-- Type: text/x-patch; name="patch-expr.diff", Size: 1952 bytes --]

2018-08-19  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	* expr.c (expand_assignment): Assert that bitpos is positive.
	(store_field): Likewise
	(expand_expr_real_1): Make sure that bitpos is positive.

Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(Revision 263644)
+++ gcc/expr.c	(Arbeitskopie)
@@ -5270,6 +5270,7 @@ expand_assignment (tree to, tree from, bool nontem
 		MEM_VOLATILE_P (to_rtx) = 1;
 	    }
 
+	  gcc_assert (known_ge (bitpos, 0));
 	  if (optimize_bitfield_assignment_op (bitsize, bitpos,
 					       bitregion_start, bitregion_end,
 					       mode1, to_rtx, to, from,
@@ -7046,6 +7047,7 @@ store_field (rtx target, poly_int64 bitsize, poly_
 	}
 
       /* Store the value in the bitfield.  */
+      gcc_assert (known_ge (bitpos, 0));
       store_bit_field (target, bitsize, bitpos,
 		       bitregion_start, bitregion_end,
 		       mode, temp, reverse);
@@ -10545,6 +10547,14 @@ expand_expr_real_1 (tree exp, rtx target, machine_
 	mode2
 	  = CONSTANT_P (op0) ? TYPE_MODE (TREE_TYPE (tem)) : GET_MODE (op0);
 
+	/* Make sure bitpos is not negative, it can wreak havoc later.  */
+	if (maybe_lt (bitpos, 0))
+	  {
+	    gcc_assert (offset == NULL_TREE);
+	    offset = size_int (bits_to_bytes_round_down (bitpos));
+	    bitpos = num_trailing_bits (bitpos);
+	  }
+
 	/* If we have either an offset, a BLKmode result, or a reference
 	   outside the underlying object, we must force it to memory.
 	   Such a case can occur in Ada if we have unchecked conversion
@@ -10795,6 +10805,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_
 		&& GET_MODE_CLASS (ext_mode) == MODE_INT)
 	      reversep = TYPE_REVERSE_STORAGE_ORDER (type);
 
+	    gcc_assert (known_ge (bitpos, 0));
 	    op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp,
 				     (modifier == EXPAND_STACK_PARM
 				      ? NULL_RTX : target),

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-18 14:25     ` Bernd Edlinger
@ 2018-08-18 16:46       ` Richard Sandiford
  2018-08-18 17:09         ` Bernd Edlinger
  0 siblings, 1 reply; 45+ messages in thread
From: Richard Sandiford @ 2018-08-18 16:46 UTC (permalink / raw)
  To: Bernd Edlinger
  Cc: Jeff Law, Martin Sebor, Joseph S. Myers, James Greenhalgh,
	Jason Merrill, GCC Patches, nd

Bernd Edlinger <bernd.edlinger@hotmail.de> writes:
> On 08/18/18 12:40, Richard Sandiford wrote:
>> Bernd Edlinger <bernd.edlinger@hotmail.de> writes:
>>> Hi everybody,
>>>
>>> On 08/16/18 08:36, Bernd Edlinger wrote:
>>>> Jeff Law wrote:
>>>>> I wonder if the change to how we set up the initializers is ultimately
>>>>> changing the section those go into and ultimately causing an overflow of
>>>>> the .sdata section.
>>>>
>>>>
>>>> Yes, that is definitely the case.
>>>> Due to the -fmerge-all-constants option used
>>>> named arrays with brace initializer look like string initializers
>>>> and can go into the merge section if there are no embedded nul chars.
>>>> But the string constants can now be huge.
>>>>
>>>> See my other patch about string merging:
>>>> [PATCH] Handle not explicitly zero terminated strings in merge sections
>>>> https://gcc.gnu.org/ml/gcc-patches/2018-08/msg00481.html
>>>>
>>>>
>>>> Can this section overflow?
>>>>
>>>
>>>
>>> could someone try out if this (untested) patch fixes the issue?
>>>
>>>
>>> Thanks,
>>> Bernd.
>>>
>>>
>>> 2018-08-18  Bernd Edlinger  <bernd.edlinger@hotmail.de>
>>>
>>> 	* expmed.c (simple_mem_bitfield_p): Do shift right signed.
>>> 	* config/alpha/alpha.h (CONSTANT_ADDRESS_P): Avoid signed
>>> 	integer overflow.
>>>
>>> Index: gcc/config/alpha/alpha.h
>>> ===================================================================
>>> --- gcc/config/alpha/alpha.h	(revision 263611)
>>> +++ gcc/config/alpha/alpha.h	(working copy)
>>> @@ -678,7 +678,7 @@ enum reg_class {
>>>   
>>>   #define CONSTANT_ADDRESS_P(X)   \
>>>     (CONST_INT_P (X)		\
>>> -   && (unsigned HOST_WIDE_INT) (INTVAL (X) + 0x8000) < 0x10000)
>>> +   && (UINTVAL (X) + 0x8000) < 0x10000)
>>>   
>>>   /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
>>>      and check its validity for a certain class.
>>> Index: gcc/expmed.c
>>> ===================================================================
>>> --- gcc/expmed.c	(revision 263611)
>>> +++ gcc/expmed.c	(working copy)
>>> @@ -579,8 +579,12 @@ static bool
>>>   simple_mem_bitfield_p (rtx op0, poly_uint64 bitsize, poly_uint64 bitnum,
>>>   		       machine_mode mode, poly_uint64 *bytenum)
>>>   {
>>> +  poly_int64 ibit = bitnum;
>>> +  poly_int64 ibyte;
>>> +  if (!multiple_p (ibit, BITS_PER_UNIT, &ibyte))
>>> +    return false;
>>> +  *bytenum = ibyte;
>>>     return (MEM_P (op0)
>>> -	  && multiple_p (bitnum, BITS_PER_UNIT, bytenum)
>>>   	  && known_eq (bitsize, GET_MODE_BITSIZE (mode))
>>>   	  && (!targetm.slow_unaligned_access (mode, MEM_ALIGN (op0))
>>>   	      || (multiple_p (bitnum, GET_MODE_ALIGNMENT (mode))
>> 
>> Do we have a genuinely negative bit offset here?  Seems like the callers
>> would need to be updated if so, since the code is consistent in treating
>> the offset as unsigned.
>> 
>
> Aehm, yes.
>
> The test case plural.i contains this:
>
> static const yytype_int8 yypgoto[] =
> {
>       -10, -10, -1
> };
>
> static const yytype_uint8 yyr1[] =
> {
>         0, 16, 17, 18, 18, 18, 18, 18, 18, 18,
>        18, 18, 18, 18
> };
>
>    yyn = yyr1[yyn];
>
>    yystate = yypgoto[yyn - 16] + *yyssp;
>
>
> There will probably a reason why yyn can never be 0
> in yyn = yyr1[yyn]; but it is not really obvious.
>
> In plural.i.228t.optimized we have:
>
>   pretmp_400 = yypgoto[-16];
>    _385 = (int) pretmp_400;
>    goto <bb 69>; [100.00%]

Ah, ok.

[...]

> (gdb) frame 26
> #26 0x000000000082f828 in expand_expr_real_1 (exp=<optimized out>, target=<optimized out>,
>      tmode=<optimized out>, modifier=EXPAND_NORMAL, alt_rtl=0x0, inner_reference_p=<optimized out>)
>      at ../../gcc-trunk/gcc/expr.c:10801
> 10801					     ext_mode, ext_mode, reversep, alt_rtl);
> (gdb) list
> 10796		      reversep = TYPE_REVERSE_STORAGE_ORDER (type);
> 10797	
> 10798		    op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp,
> 10799					     (modifier == EXPAND_STACK_PARM
> 10800					      ? NULL_RTX : target),
> 10801					     ext_mode, ext_mode, reversep, alt_rtl);
> 10802	
> 10803		    /* If the result has a record type and the mode of OP0 is an
> 10804		       integral mode then, if BITSIZE is narrower than this mode
> 10805		       and this is for big-endian data, we must put the field
> (gdb) p bitpos
> $1 = {<poly_int_pod<1u, long>> = {coeffs = {-128}}, <No data fields>}

The get_inner_reference->store_field path in expand_assignment has:

      /* Make sure bitpos is not negative, it can wreak havoc later.  */
      if (maybe_lt (bitpos, 0))
	{
	  gcc_assert (offset == NULL_TREE);
	  offset = size_int (bits_to_bytes_round_down (bitpos));
	  bitpos = num_trailing_bits (bitpos);
	}

So maybe this is what havoc looks like.

It's not my area, but I think we should be doing something similar for
the get_inner_reference->expand_bit_field path in expand_expr_real_1.
Haven't checked whether the offset == NULL_TREE assert would be
guaranteed there though.

> $5 = {<poly_int_pod<1u, unsigned long>> = {coeffs = {0x1ffffffffffffff0}}, <No data fields>}
>
> The byte offset is completely wrong now, due to the bitnum was
> initially a negative integer and got converted to unsigned.  At the
> moment when that is converted to byte offsets it is done wrong.  I
> think it is too much to change everything to signed arithmetics, but
> at least when converting a bit pos to a byte pos, it should be done in
> signed arithmetics.

But then we'd mishandle a real 1ULL << 63 bitpos (say).  Realise it's
unlikely in real code, but it'd still probably be possible to construct
a variant of the original test case in which the bias was
+0x1000000000000000 rather than -16.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-18 10:40   ` Richard Sandiford
@ 2018-08-18 14:25     ` Bernd Edlinger
  2018-08-18 16:46       ` Richard Sandiford
  0 siblings, 1 reply; 45+ messages in thread
From: Bernd Edlinger @ 2018-08-18 14:25 UTC (permalink / raw)
  To: Jeff Law, Martin Sebor, Joseph S. Myers, James Greenhalgh,
	Jason Merrill, GCC Patches, nd, richard.sandiford

On 08/18/18 12:40, Richard Sandiford wrote:
> Bernd Edlinger <bernd.edlinger@hotmail.de> writes:
>> Hi everybody,
>>
>> On 08/16/18 08:36, Bernd Edlinger wrote:
>>> Jeff Law wrote:
>>>> I wonder if the change to how we set up the initializers is ultimately
>>>> changing the section those go into and ultimately causing an overflow of
>>>> the .sdata section.
>>>
>>>
>>> Yes, that is definitely the case.
>>> Due to the -fmerge-all-constants option used
>>> named arrays with brace initializer look like string initializers
>>> and can go into the merge section if there are no embedded nul chars.
>>> But the string constants can now be huge.
>>>
>>> See my other patch about string merging:
>>> [PATCH] Handle not explicitly zero terminated strings in merge sections
>>> https://gcc.gnu.org/ml/gcc-patches/2018-08/msg00481.html
>>>
>>>
>>> Can this section overflow?
>>>
>>
>>
>> could someone try out if this (untested) patch fixes the issue?
>>
>>
>> Thanks,
>> Bernd.
>>
>>
>> 2018-08-18  Bernd Edlinger  <bernd.edlinger@hotmail.de>
>>
>> 	* expmed.c (simple_mem_bitfield_p): Do shift right signed.
>> 	* config/alpha/alpha.h (CONSTANT_ADDRESS_P): Avoid signed
>> 	integer overflow.
>>
>> Index: gcc/config/alpha/alpha.h
>> ===================================================================
>> --- gcc/config/alpha/alpha.h	(revision 263611)
>> +++ gcc/config/alpha/alpha.h	(working copy)
>> @@ -678,7 +678,7 @@ enum reg_class {
>>   
>>   #define CONSTANT_ADDRESS_P(X)   \
>>     (CONST_INT_P (X)		\
>> -   && (unsigned HOST_WIDE_INT) (INTVAL (X) + 0x8000) < 0x10000)
>> +   && (UINTVAL (X) + 0x8000) < 0x10000)
>>   
>>   /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
>>      and check its validity for a certain class.
>> Index: gcc/expmed.c
>> ===================================================================
>> --- gcc/expmed.c	(revision 263611)
>> +++ gcc/expmed.c	(working copy)
>> @@ -579,8 +579,12 @@ static bool
>>   simple_mem_bitfield_p (rtx op0, poly_uint64 bitsize, poly_uint64 bitnum,
>>   		       machine_mode mode, poly_uint64 *bytenum)
>>   {
>> +  poly_int64 ibit = bitnum;
>> +  poly_int64 ibyte;
>> +  if (!multiple_p (ibit, BITS_PER_UNIT, &ibyte))
>> +    return false;
>> +  *bytenum = ibyte;
>>     return (MEM_P (op0)
>> -	  && multiple_p (bitnum, BITS_PER_UNIT, bytenum)
>>   	  && known_eq (bitsize, GET_MODE_BITSIZE (mode))
>>   	  && (!targetm.slow_unaligned_access (mode, MEM_ALIGN (op0))
>>   	      || (multiple_p (bitnum, GET_MODE_ALIGNMENT (mode))
> 
> Do we have a genuinely negative bit offset here?  Seems like the callers
> would need to be updated if so, since the code is consistent in treating
> the offset as unsigned.
> 

Aehm, yes.

The test case plural.i contains this:

static const yytype_int8 yypgoto[] =
{
      -10, -10, -1
};

static const yytype_uint8 yyr1[] =
{
        0, 16, 17, 18, 18, 18, 18, 18, 18, 18,
       18, 18, 18, 18
};

   yyn = yyr1[yyn];

   yystate = yypgoto[yyn - 16] + *yyssp;


There will probably a reason why yyn can never be 0
in yyn = yyr1[yyn]; but it is not really obvious.

In plural.i.228t.optimized we have:

  pretmp_400 = yypgoto[-16];
   _385 = (int) pretmp_400;
   goto <bb 69>; [100.00%]

which is expanded to:

(insn 927 926 928 59 (set (reg/f:DI 369)
         (symbol_ref:DI ("yypgoto") [flags 0x6] <var_decl 0x7f76af1d1c60 yypgoto>)) -1
      (nil))
(insn 928 927 929 59 (set (reg:DI 372)
         (const_int 1 [0x1])) -1
      (nil))
(insn 929 928 930 59 (set (reg:DI 371)
         (ashift:DI (reg:DI 372)
             (const_int 61 [0x3d]))) -1
      (expr_list:REG_EQUAL (const_int 2305843009213693952 [0x2000000000000000])
         (nil)))
(insn 930 929 931 59 (set (reg/f:DI 370)
         (plus:DI (reg/f:DI 369)
             (reg:DI 371))) -1
      (nil))
(insn 931 930 932 59 (set (reg:DI 375)
         (plus:DI (reg/f:DI 370)
             (const_int 1 [0x1]))) -1
      (nil))
(insn 932 931 933 59 (set (reg:DI 376)
         (mem/u/c:DI (and:DI (plus:DI (reg/f:DI 370)
                     (const_int -16 [0xfffffffffffffff0]))
                 (const_int -8 [0xfffffffffffffff8])) [0  S8 A64])) -1
      (nil))
(insn 933 932 934 59 (set (reg:DI 377)
         (ashift:DI (reg:DI 376)
             (minus:DI (const_int 64 [0x40])
                 (ashift:DI (and:DI (reg:DI 375)
                         (const_int 7 [0x7]))
                     (const_int 3 [0x3]))))) -1
      (nil))
(insn 934 933 935 59 (set (reg:DI 374)
         (ashiftrt:DI (reg:DI 377)
             (const_int 56 [0x38]))) -1
      (nil))


Certainly there is also a target bug, because

(define_insn "*movdi"
   [(set (match_operand:DI 0 "nonimmediate_operand"
                                 "=r,r,r,r,r,r,r,r, m, *f,*f, Q, r,*f")
         (match_operand:DI 1 "input_operand"
                                 "rJ,K,L,T,s,n,s,m,rJ,*fJ, Q,*f,*f, r"))]
   "register_operand (operands[0], DImode)
    || reg_or_0_operand (operands[1], DImode)"
   "@
    mov %r1,%0
    lda %0,%1($31)
    ldah %0,%h1($31)
    #
    #
    #
    lda %0,%1
    ldq%A1 %0,%1
    stq%A0 %r1,%0
    fmov %R1,%0
    ldt %0,%1
    stt %R1,%0
    ftoit %1,%0
    itoft %1,%0"

overload 7 of 14, has constraint op0 = r, op1 = s.
and assembles to lda %0,%1 so s matches symbol_ref+any_integer
I think even without the bug in the expansion, that could
happen if I write
volatile x = 0; if (x) { char *y = &yypgoto[0x20000000000000]; }

I think there should be a splitter for large offsets that gets enabled
after reload and splits the mov r,s+x into mov r,s; add r,x or something
appropriate.

So let's see, how does insn 929 get expanded?

Index: emit-rtl.c
===================================================================
--- emit-rtl.c	(Revision 263644)
+++ emit-rtl.c	(Arbeitskopie)
@@ -4023,6 +4023,8 @@
    insn = as_a <rtx_insn *> (rtx_alloc (INSN));
  
    INSN_UID (insn) = cur_insn_uid++;
+  if (INSN_UID (insn) == 929)
+    asm ("int3");
    PATTERN (insn) = pattern;
    INSN_CODE (insn) = -1;
    REG_NOTES (insn) = NULL;

gdb --args ../gcc-build-alpha-linux-gnu/gcc/cc1 -fpreprocessed plural.i -quiet -dumpbase plural.i -mlong-double-128 -mieee "-mfp-rounding-mode=d" -auxbase plural -g -O2 -Wall -Werror -Wundef -Wwrite-strings -Wstrict-prototypes -Wold-style-definition "-std=gnu11" -fgnu89-inline -fmerge-all-constants -fno-stack-protector -frounding-math -fno-math-errno "-ftls-model=initial-exec" -o plural.s

#0  make_insn_raw (pattern=pattern@entry=0x7ffff6e60c30) at ../../gcc-trunk/gcc/emit-rtl.c:4031
#1  0x00000000007fde49 in emit_insn (x=x@entry=0x7ffff6e60c30) at ../../gcc-trunk/gcc/emit-rtl.c:5108
#2  0x0000000000a92623 in expand_binop_directly (icode=CODE_FOR_ashldi3, mode=mode@entry=E_DImode,
     binoptab=binoptab@entry=ashl_optab, op0=op0@entry=0x7ffff6e60be8, op1=op1@entry=0x7ffff6ecf860,
     target=target@entry=0x7ffff6e60bd0, unsignedp=unsignedp@entry=0,
     methods=methods@entry=OPTAB_WIDEN, last=last@entry=0x7ffff6e618c0)
     at ../../gcc-trunk/gcc/optabs.c:1114
#3  0x0000000000a8fe62 in expand_binop (mode=mode@entry=E_DImode, binoptab=<optimized out>,
     binoptab@entry=ashl_optab, op0=op0@entry=0x7ffff6e60be8, op1=<optimized out>,
     target=target@entry=0x7ffff6e60bd0, unsignedp=unsignedp@entry=0, methods=methods@entry=OPTAB_WIDEN)
     at ../../gcc-trunk/gcc/optabs.c:1186
#4  0x0000000000f1421b in alpha_emit_set_const_1 (target=target@entry=0x7ffff6e60bd0,
     mode=mode@entry=E_DImode, c=c@entry=2305843009213693952, n=n@entry=2,
     no_output=no_output@entry=false) at ../../gcc-trunk/gcc/config/alpha/alpha.c:1925
#5  0x0000000000f147a0 in alpha_emit_set_const (target=0x7ffff6e60bd0, mode=E_DImode,
     c=2305843009213693952, n=3, no_output=<optimized out>)
     at ../../gcc-trunk/gcc/config/alpha/alpha.c:2048
#6  0x0000000000f1545a in alpha_split_const_mov (mode=mode@entry=E_DImode,
     operands=operands@entry=0x7fffffffc7b0) at ../../gcc-trunk/gcc/config/alpha/alpha.c:2214
#7  0x0000000000f15536 in alpha_expand_mov (mode=mode@entry=E_DImode,
     operands=operands@entry=0x7fffffffc7b0) at ../../gcc-trunk/gcc/config/alpha/alpha.c:2263
#8  0x00000000010f0f67 in gen_movdi (operand0=0x7ffff6e60bd0, operand1=0x7ffff6da8580)
     at ../../gcc-trunk/gcc/config/alpha/alpha.md:4062
#9  0x0000000000833893 in operator() (a1=0x7ffff6da8580, a0=0x7ffff6e60bd0, this=<optimized out>)
     at ../../gcc-trunk/gcc/recog.h:301
#10 emit_move_insn_1 (x=x@entry=0x7ffff6e60bd0, y=y@entry=0x7ffff6da8580)
     at ../../gcc-trunk/gcc/expr.c:3694
#11 0x0000000000833b86 in emit_move_insn (x=x@entry=0x7ffff6e60bd0, y=y@entry=0x7ffff6da8580)
     at ../../gcc-trunk/gcc/expr.c:3790
#12 0x0000000000810aa0 in copy_to_mode_reg (mode=mode@entry=E_DImode, x=0x7ffff6da8580)
     at ../../gcc-trunk/gcc/explow.c:632
#13 0x0000000000a8b69a in maybe_legitimize_operand (op=0x7fffffffca40, opno=<optimized out>,
     icode=CODE_FOR_adddi3) at ../../gcc-trunk/gcc/optabs.c:7168
#14 maybe_legitimize_operands (icode=icode@entry=CODE_FOR_adddi3, opno=opno@entry=0,
     nops=nops@entry=3, ops=ops@entry=0x7fffffffca10) at ../../gcc-trunk/gcc/optabs.c:7292
#15 0x0000000000a8bcde in maybe_gen_insn (icode=icode@entry=CODE_FOR_adddi3, nops=nops@entry=3,
     ops=ops@entry=0x7fffffffca10) at ../../gcc-trunk/gcc/optabs.c:7311
#16 0x0000000000a925ff in expand_binop_directly (icode=CODE_FOR_adddi3, mode=mode@entry=E_DImode,
     binoptab=binoptab@entry=add_optab, op0=op0@entry=0x7ffff6e60b40, op1=op1@entry=0x7ffff6da8580,
     target=target@entry=0x0, unsignedp=unsignedp@entry=1, methods=methods@entry=OPTAB_LIB_WIDEN,
     last=last@entry=0x7ffff6e61880) at ../../gcc-trunk/gcc/optabs.c:1098
#17 0x0000000000a8fe62 in expand_binop (mode=mode@entry=E_DImode, binoptab=<optimized out>,
     op0=op0@entry=0x7ffff6e60b40, op1=<optimized out>, target=target@entry=0x0,
     unsignedp=unsignedp@entry=1, methods=OPTAB_LIB_WIDEN) at ../../gcc-trunk/gcc/optabs.c:1186
#18 0x0000000000a923e3 in expand_simple_binop (mode=mode@entry=E_DImode, code=code@entry=PLUS,
     op0=op0@entry=0x7ffff6e60b40, op1=<optimized out>, target=target@entry=0x0,
     unsignedp=unsignedp@entry=1, methods=<optimized out>, methods@entry=OPTAB_LIB_WIDEN)
     at ../../gcc-trunk/gcc/optabs.c:917
#19 0x0000000000f12d6f in alpha_legitimize_address_1 (x=0x7ffff6e60b40, x@entry=0x7ffff6e60ba0,
     scratch=scratch@entry=0x0, mode=<optimized out>) at ../../gcc-trunk/gcc/config/alpha/alpha.c:1159
#20 0x0000000000f133cb in alpha_legitimize_address (x=0x7ffff6e60ba0, oldx=<optimized out>,
     mode=<optimized out>) at ../../gcc-trunk/gcc/config/alpha/alpha.c:1177
#21 0x0000000000810922 in memory_address_addr_space (mode=E_QImode, x=0x7ffff6e60ba0,
     as=<optimized out>) at ../../gcc-trunk/gcc/explow.c:450
#22 0x00000000007f689d in change_address_1 (memref=memref@entry=0x7ffff6e60b88,
     mode=mode@entry=E_QImode, addr=addr@entry=0x7ffff6e60ba0, validate=validate@entry=1,
     inplace=inplace@entry=false) at ../../gcc-trunk/gcc/emit-rtl.c:2288
#23 0x00000000007fab5c in adjust_address_1 (memref=memref@entry=0x7ffff6e60b88,
     mode=mode@entry=E_QImode, offset=..., validate=validate@entry=1,
     adjust_address=adjust_address@entry=1, adjust_object=adjust_object@entry=1, size=...,
     size@entry=...) at ../../gcc-trunk/gcc/emit-rtl.c:2420
#24 0x000000000081942a in extract_bit_field_1 (str_rtx=str_rtx@entry=0x7ffff6e60b88,
     bitsize=bitsize@entry=..., bitnum=..., bitnum@entry=..., unsignedp=unsignedp@entry=0,
     target=target@entry=0x0, mode=mode@entry=E_QImode, tmode=<optimized out>, tmode@entry=E_QImode,
     reverse=reverse@entry=false, fallback_p=fallback_p@entry=true, alt_rtl=alt_rtl@entry=0x0)
     at ../../gcc-trunk/gcc/expmed.c:1805
#25 0x000000000081a063 in extract_bit_field (str_rtx=0x7ffff6e60b88, bitsize=..., bitnum=...,
     unsignedp=0, target=target@entry=0x0, mode=mode@entry=E_QImode, tmode=tmode@entry=E_QImode,
     reverse=false, alt_rtl=alt_rtl@entry=0x0) at ../../gcc-trunk/gcc/expmed.c:2097
#26 0x000000000082f828 in expand_expr_real_1 (exp=<optimized out>, target=<optimized out>,
     tmode=<optimized out>, modifier=EXPAND_NORMAL, alt_rtl=0x0, inner_reference_p=<optimized out>)
     at ../../gcc-trunk/gcc/expr.c:10801
#27 0x000000000083047a in expand_expr_real_1 (exp=0x7ffff6df8f30, target=<optimized out>,
     tmode=E_SImode, modifier=EXPAND_NORMAL, alt_rtl=0x0, inner_reference_p=<optimized out>)
     at ../../gcc-trunk/gcc/expr.c:9861
#28 0x000000000083d9de in expand_expr (modifier=EXPAND_NORMAL, mode=E_SImode, target=0x0,
     exp=0x7ffff6df8f30) at ../../gcc-trunk/gcc/expr.h:279
#29 expand_expr_real_2 (ops=ops@entry=0x7fffffffd8a0, target=<optimized out>, tmode=E_SImode,
     modifier=modifier@entry=EXPAND_NORMAL) at ../../gcc-trunk/gcc/expr.c:8455
#30 0x000000000070ba16 in expand_gimple_stmt_1 (stmt=stmt@entry=0x7ffff6e0eb40)
     at ../../gcc-trunk/gcc/cfgexpand.c:3674
#31 0x000000000070d4ad in expand_gimple_stmt (stmt=stmt@entry=0x7ffff6e0eb40)
     at ../../gcc-trunk/gcc/cfgexpand.c:3734
#32 0x000000000070dbbe in expand_gimple_basic_block (bb=0x7ffff6deb478,
     disable_tail_calls=disable_tail_calls@entry=false) at ../../gcc-trunk/gcc/cfgexpand.c:5770
#33 0x0000000000713597 in (anonymous namespace)::pass_expand::execute (this=<optimized out>,
     fun=0x7ffff70ab4d0) at ../../gcc-trunk/gcc/cfgexpand.c:6373
#34 0x0000000000ab4e25 in execute_one_pass (pass=pass@entry=0x1b28700)
     at ../../gcc-trunk/gcc/passes.c:2446
#35 0x0000000000ab5738 in execute_pass_list_1 (pass=0x1b28700) at ../../gcc-trunk/gcc/passes.c:2535
#36 0x0000000000ab5795 in execute_pass_list (fn=0x7ffff70ab4d0, pass=<optimized out>)
     at ../../gcc-trunk/gcc/passes.c:2546
#37 0x000000000074efe8 in cgraph_node::expand (this=0x7ffff6cfb840)
     at ../../gcc-trunk/gcc/cgraphunit.c:2116
#38 0x00000000007508a1 in expand_all_functions () at ../../gcc-trunk/gcc/cgraphunit.c:2254
#39 symbol_table::compile (this=this@entry=0x7ffff6ecc000) at ../../gcc-trunk/gcc/cgraphunit.c:2605
#40 0x0000000000752c75 in symbol_table::finalize_compilation_unit (this=0x7ffff6ecc000)
     at ../../gcc-trunk/gcc/cgraphunit.c:2698
#41 0x0000000000b97d6d in compile_file () at ../../gcc-trunk/gcc/toplev.c:480
#42 0x000000000059cb5e in do_compile () at ../../gcc-trunk/gcc/toplev.c:2165
#43 toplev::main (this=this@entry=0x7fffffffdce0, argc=argc@entry=28, argv=argv@entry=0x7fffffffdde8)
     at ../../gcc-trunk/gcc/toplev.c:2300
#44 0x000000000059ecb7 in main (argc=28, argv=0x7fffffffdde8) at ../../gcc-trunk/gcc/main.c:39

(gdb) frame 26
#26 0x000000000082f828 in expand_expr_real_1 (exp=<optimized out>, target=<optimized out>,
     tmode=<optimized out>, modifier=EXPAND_NORMAL, alt_rtl=0x0, inner_reference_p=<optimized out>)
     at ../../gcc-trunk/gcc/expr.c:10801
10801					     ext_mode, ext_mode, reversep, alt_rtl);
(gdb) list
10796		      reversep = TYPE_REVERSE_STORAGE_ORDER (type);
10797	
10798		    op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp,
10799					     (modifier == EXPAND_STACK_PARM
10800					      ? NULL_RTX : target),
10801					     ext_mode, ext_mode, reversep, alt_rtl);
10802	
10803		    /* If the result has a record type and the mode of OP0 is an
10804		       integral mode then, if BITSIZE is narrower than this mode
10805		       and this is for big-endian data, we must put the field
(gdb) p bitpos
$1 = {<poly_int_pod<1u, long>> = {coeffs = {-128}}, <No data fields>}
(gdb) frame 25
#25 0x000000000081a063 in extract_bit_field (str_rtx=0x7ffff6e60b88, bitsize=..., bitnum=...,
     unsignedp=0, target=target@entry=0x0, mode=mode@entry=E_QImode, tmode=tmode@entry=E_QImode,
     reverse=false, alt_rtl=alt_rtl@entry=0x0) at ../../gcc-trunk/gcc/expmed.c:2097
2097				      target, mode, tmode, reverse, true, alt_rtl);
(gdb) list
2092	      return extract_bit_field_1 (str_rtx, ibitsize, ibitnum, unsignedp,
2093					  target, mode, tmode, reverse, true, alt_rtl);
2094	    }
2095	
2096	  return extract_bit_field_1 (str_rtx, bitsize, bitnum, unsignedp,
2097				      target, mode, tmode, reverse, true, alt_rtl);
2098	}
2099	^L
2100	/* Use shifts and boolean operations to extract a field of BITSIZE bits
2101	   from bit BITNUM of OP0.  If OP0_MODE is defined, it is the mode of OP0,
(gdb) p/x bitnum
$3 = {<poly_int_pod<1u, unsigned long>> = {coeffs = {0xffffffffffffff80}}, <No data fields>}
(gdb) frame 24
#24 0x000000000081942a in extract_bit_field_1 (str_rtx=str_rtx@entry=0x7ffff6e60b88,
     bitsize=bitsize@entry=..., bitnum=..., bitnum@entry=..., unsignedp=unsignedp@entry=0,
     target=target@entry=0x0, mode=mode@entry=E_QImode, tmode=<optimized out>, tmode@entry=E_QImode,
     reverse=reverse@entry=false, fallback_p=fallback_p@entry=true, alt_rtl=alt_rtl@entry=0x0)
     at ../../gcc-trunk/gcc/expmed.c:1805
1805	      op0 = adjust_bitfield_address (op0, mode1, bytenum);
(gdb) list
1800	  /* Extraction of a full MODE1 value can be done with a load as long as
1801	     the field is on a byte boundary and is sufficiently aligned.  */
1802	  poly_uint64 bytenum;
1803	  if (simple_mem_bitfield_p (op0, bitsize, bitnum, mode1, &bytenum))
1804	    {
1805	      op0 = adjust_bitfield_address (op0, mode1, bytenum);
1806	      if (reverse)
1807		op0 = flip_storage_order (mode1, op0);
1808	      return convert_extracted_bit_field (op0, mode, tmode, unsignedp);
1809	    }
(gdb) p/x bytenum
$5 = {<poly_int_pod<1u, unsigned long>> = {coeffs = {0x1ffffffffffffff0}}, <No data fields>}

The byte offset is completely wrong now, due to the bitnum was initially a negative integer
and got converted to unsigned.  At the moment when that is converted to byte offsets it is
done wrong.  I think it is too much to change everything to signed arithmetics,
but at least when converting a bit pos to a byte pos, it should be done in signed arithmetics.

So yes, I think a negative offset can happen.  And it must be handled correctly.


Thanks
Bernd.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-17 22:26 ` Bernd Edlinger
  2018-08-18  4:13   ` Jeff Law
@ 2018-08-18 10:40   ` Richard Sandiford
  2018-08-18 14:25     ` Bernd Edlinger
  1 sibling, 1 reply; 45+ messages in thread
From: Richard Sandiford @ 2018-08-18 10:40 UTC (permalink / raw)
  To: Bernd Edlinger
  Cc: Jeff Law, Martin Sebor, Joseph S. Myers, James Greenhalgh,
	Jason Merrill, GCC Patches, nd

Bernd Edlinger <bernd.edlinger@hotmail.de> writes:
> Hi everybody,
>
> On 08/16/18 08:36, Bernd Edlinger wrote:
>> Jeff Law wrote:
>>> I wonder if the change to how we set up the initializers is ultimately
>>> changing the section those go into and ultimately causing an overflow of
>>> the .sdata section.
>> 
>> 
>> Yes, that is definitely the case.
>> Due to the -fmerge-all-constants option used
>> named arrays with brace initializer look like string initializers
>> and can go into the merge section if there are no embedded nul chars.
>> But the string constants can now be huge.
>> 
>> See my other patch about string merging:
>> [PATCH] Handle not explicitly zero terminated strings in merge sections
>> https://gcc.gnu.org/ml/gcc-patches/2018-08/msg00481.html
>> 
>> 
>> Can this section overflow?
>> 
>
>
> could someone try out if this (untested) patch fixes the issue?
>
>
> Thanks,
> Bernd.
>
>
> 2018-08-18  Bernd Edlinger  <bernd.edlinger@hotmail.de>
>
> 	* expmed.c (simple_mem_bitfield_p): Do shift right signed.
> 	* config/alpha/alpha.h (CONSTANT_ADDRESS_P): Avoid signed
> 	integer overflow.
>
> Index: gcc/config/alpha/alpha.h
> ===================================================================
> --- gcc/config/alpha/alpha.h	(revision 263611)
> +++ gcc/config/alpha/alpha.h	(working copy)
> @@ -678,7 +678,7 @@ enum reg_class {
>  
>  #define CONSTANT_ADDRESS_P(X)   \
>    (CONST_INT_P (X)		\
> -   && (unsigned HOST_WIDE_INT) (INTVAL (X) + 0x8000) < 0x10000)
> +   && (UINTVAL (X) + 0x8000) < 0x10000)
>  
>  /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
>     and check its validity for a certain class.
> Index: gcc/expmed.c
> ===================================================================
> --- gcc/expmed.c	(revision 263611)
> +++ gcc/expmed.c	(working copy)
> @@ -579,8 +579,12 @@ static bool
>  simple_mem_bitfield_p (rtx op0, poly_uint64 bitsize, poly_uint64 bitnum,
>  		       machine_mode mode, poly_uint64 *bytenum)
>  {
> +  poly_int64 ibit = bitnum;
> +  poly_int64 ibyte;
> +  if (!multiple_p (ibit, BITS_PER_UNIT, &ibyte))
> +    return false;
> +  *bytenum = ibyte;
>    return (MEM_P (op0)
> -	  && multiple_p (bitnum, BITS_PER_UNIT, bytenum)
>  	  && known_eq (bitsize, GET_MODE_BITSIZE (mode))
>  	  && (!targetm.slow_unaligned_access (mode, MEM_ALIGN (op0))
>  	      || (multiple_p (bitnum, GET_MODE_ALIGNMENT (mode))

Do we have a genuinely negative bit offset here?  Seems like the callers
would need to be updated if so, since the code is consistent in treating
the offset as unsigned.

Thanks,
Richard

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-17 22:26 ` Bernd Edlinger
@ 2018-08-18  4:13   ` Jeff Law
  2018-08-18 10:40   ` Richard Sandiford
  1 sibling, 0 replies; 45+ messages in thread
From: Jeff Law @ 2018-08-18  4:13 UTC (permalink / raw)
  To: Bernd Edlinger, Martin Sebor, Joseph S. Myers
  Cc: James Greenhalgh, Jason Merrill, GCC Patches, nd

On 08/17/2018 04:26 PM, Bernd Edlinger wrote:
> Hi everybody,
> 
> On 08/16/18 08:36, Bernd Edlinger wrote:
>> Jeff Law wrote:
>>> I wonder if the change to how we set up the initializers is ultimately
>>> changing the section those go into and ultimately causing an overflow of
>>> the .sdata section.
>>
>>
>> Yes, that is definitely the case.
>> Due to the -fmerge-all-constants option used
>> named arrays with brace initializer look like string initializers
>> and can go into the merge section if there are no embedded nul chars.
>> But the string constants can now be huge.
>>
>> See my other patch about string merging:
>> [PATCH] Handle not explicitly zero terminated strings in merge sections
>> https://gcc.gnu.org/ml/gcc-patches/2018-08/msg00481.html
>>
>>
>> Can this section overflow?
>>
> 
> 
> could someone try out if this (untested) patch fixes the issue?
It seems to in my limited testing.

jeff

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-16  6:37 Bernd Edlinger
@ 2018-08-17 22:26 ` Bernd Edlinger
  2018-08-18  4:13   ` Jeff Law
  2018-08-18 10:40   ` Richard Sandiford
  0 siblings, 2 replies; 45+ messages in thread
From: Bernd Edlinger @ 2018-08-17 22:26 UTC (permalink / raw)
  To: Jeff Law, Martin Sebor, Joseph S. Myers
  Cc: James Greenhalgh, Jason Merrill, GCC Patches, nd

[-- Attachment #1: Type: text/plain, Size: 853 bytes --]

Hi everybody,

On 08/16/18 08:36, Bernd Edlinger wrote:
> Jeff Law wrote:
>> I wonder if the change to how we set up the initializers is ultimately
>> changing the section those go into and ultimately causing an overflow of
>> the .sdata section.
> 
> 
> Yes, that is definitely the case.
> Due to the -fmerge-all-constants option used
> named arrays with brace initializer look like string initializers
> and can go into the merge section if there are no embedded nul chars.
> But the string constants can now be huge.
> 
> See my other patch about string merging:
> [PATCH] Handle not explicitly zero terminated strings in merge sections
> https://gcc.gnu.org/ml/gcc-patches/2018-08/msg00481.html
> 
> 
> Can this section overflow?
> 


could someone try out if this (untested) patch fixes the issue?


Thanks,
Bernd.



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: patch-alpha.diff --]
[-- Type: text/x-patch; name="patch-alpha.diff", Size: 1444 bytes --]

2018-08-18  Bernd Edlinger  <bernd.edlinger@hotmail.de>

	* expmed.c (simple_mem_bitfield_p): Do shift right signed.
	* config/alpha/alpha.h (CONSTANT_ADDRESS_P): Avoid signed
	integer overflow.

Index: gcc/config/alpha/alpha.h
===================================================================
--- gcc/config/alpha/alpha.h	(revision 263611)
+++ gcc/config/alpha/alpha.h	(working copy)
@@ -678,7 +678,7 @@ enum reg_class {
 
 #define CONSTANT_ADDRESS_P(X)   \
   (CONST_INT_P (X)		\
-   && (unsigned HOST_WIDE_INT) (INTVAL (X) + 0x8000) < 0x10000)
+   && (UINTVAL (X) + 0x8000) < 0x10000)
 
 /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
    and check its validity for a certain class.
Index: gcc/expmed.c
===================================================================
--- gcc/expmed.c	(revision 263611)
+++ gcc/expmed.c	(working copy)
@@ -579,8 +579,12 @@ static bool
 simple_mem_bitfield_p (rtx op0, poly_uint64 bitsize, poly_uint64 bitnum,
 		       machine_mode mode, poly_uint64 *bytenum)
 {
+  poly_int64 ibit = bitnum;
+  poly_int64 ibyte;
+  if (!multiple_p (ibit, BITS_PER_UNIT, &ibyte))
+    return false;
+  *bytenum = ibyte;
   return (MEM_P (op0)
-	  && multiple_p (bitnum, BITS_PER_UNIT, bytenum)
 	  && known_eq (bitsize, GET_MODE_BITSIZE (mode))
 	  && (!targetm.slow_unaligned_access (mode, MEM_ALIGN (op0))
 	      || (multiple_p (bitnum, GET_MODE_ALIGNMENT (mode))

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
@ 2018-08-16  6:37 Bernd Edlinger
  2018-08-17 22:26 ` Bernd Edlinger
  0 siblings, 1 reply; 45+ messages in thread
From: Bernd Edlinger @ 2018-08-16  6:37 UTC (permalink / raw)
  To: Jeff Law, Martin Sebor, Joseph S. Myers
  Cc: James Greenhalgh, Jason Merrill, GCC Patches, nd

Jeff Law wrote:
> I wonder if the change to how we set up the initializers is ultimately
> changing the section those go into and ultimately causing an overflow of
> the .sdata section.


Yes, that is definitely the case.
Due to the -fmerge-all-constants option used
named arrays with brace initializer look like string initializers
and can go into the merge section if there are no embedded nul chars.
But the string constants can now be huge.

See my other patch about string merging:
[PATCH] Handle not explicitly zero terminated strings in merge sections
https://gcc.gnu.org/ml/gcc-patches/2018-08/msg00481.html


Can this section overflow?


Bernd.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-09  0:23       ` Martin Sebor
@ 2018-08-09 10:47         ` Joseph Myers
  0 siblings, 0 replies; 45+ messages in thread
From: Joseph Myers @ 2018-08-09 10:47 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Jason Merrill, Bernd Edlinger, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1275 bytes --]

On Thu, 9 Aug 2018, Martin Sebor wrote:

> But for a declaration at file scope and without an initializer,
> GCC warns that the array is assumed to have one element, but
> then gives an error when sizeof is applied to it:

That's how tentative definitions (C17 6.9.2) work.  There's an implicit 
initializer of { 0 }, but only at the end of the translation unit, so the 
type is incomplete until then and sizeof cannot be applied to it.

> even though the array does have a size of 1.  (I guess that's
> because of the [] syntax but the warning sure makes the sizeof
> error surprising.)  Auto declarations of arrays with no bound
> and with no intializer are rejected with an error:
> 
>   char a[];   // error: array size missing in ‘a’

Tentative definitions only exist at file scope (and in standard C they 
can't have an incomplete type if they have internal linkage).  See 6.7#7, 
"If an identifier for an object is declared with no linkage, the type for 
the object shall be complete by the end of its declarator, or by the end 
of its init-declarator if it has an initializer; in the case of function 
parameters (including in prototypes), it is the adjusted type (see 
6.7.6.3) that is required to be complete."

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-08 20:48     ` Joseph Myers
@ 2018-08-09  0:23       ` Martin Sebor
  2018-08-09 10:47         ` Joseph Myers
  0 siblings, 1 reply; 45+ messages in thread
From: Martin Sebor @ 2018-08-09  0:23 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Jason Merrill, Bernd Edlinger, gcc-patches

On 08/08/2018 02:48 PM, Joseph Myers wrote:
> On Wed, 8 Aug 2018, Martin Sebor wrote:
>
>> Jason/Joseph, is this meant to be accepted?  It's rejected with
>> a hard error with -Wpedantic but I don't see any tests for it:
>>
>> warning: ISO C forbids empty initializer braces [-Wpedantic]
>>    const char x[] = { };
>>                     ^
>> error: zero or negative size array ‘b’
>>    const char x[] = { };
>>               ^
>>
>> I'll avoid handling it but I'm not sure I should add a test case
>> for it if it's accepted by mistake (and if I should open a bug
>> to reject it instead).
>
> It's a perfectly ordinary combination of two GNU extensions (zero-size
> arrays, and empty initializer braces), so yes, it should be accepted, and
> have size 0 (but -pedantic should produce a pedwarn, not a hard error).

Okay, let me fix that separately.

As an aside, while adding tests for the zero-size array, I found
the handling of these extensions less than intuitive.

The empty braced initializer makes the array complete and gives
it a zero size.  I suppose that makes sense.

But for a declaration at file scope and without an initializer,
GCC warns that the array is assumed to have one element, but
then gives an error when sizeof is applied to it:

   const char a[];   // warning: array ‘a’ assumed to have one element
   const int n = sizeof a;   // error: invalid application of ‘sizeof’ 
to incomplete type ‘const char[]’

even though the array does have a size of 1.  (I guess that's
because of the [] syntax but the warning sure makes the sizeof
error surprising.)  Auto declarations of arrays with no bound
and with no intializer are rejected with an error:

   char a[];   // error: array size missing in ‘a’

I'm sure there's some explanation for this too but that doesn't
make it intuitive to work with.

It would be nice to say something about how this works and maybe
even why in the manual.  The documentation for zero-length arrays
doesn't describe these kinds of extensions or the subtle nuances
(it only talks about the [0] form where the zero is explicit, or
flexible array members).  Without tests it's hard to tell what's
meant to be valid and what could be accepted by accident.  With
the patch accepted tests will exist, but unless it's discussed
somewhere I missed I'll put together a patch to update the docs.

Martin

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-08 19:50   ` Martin Sebor
  2018-08-08 20:35     ` Bernd Edlinger
@ 2018-08-08 20:48     ` Joseph Myers
  2018-08-09  0:23       ` Martin Sebor
  1 sibling, 1 reply; 45+ messages in thread
From: Joseph Myers @ 2018-08-08 20:48 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Jason Merrill, Bernd Edlinger, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 809 bytes --]

On Wed, 8 Aug 2018, Martin Sebor wrote:

> Jason/Joseph, is this meant to be accepted?  It's rejected with
> a hard error with -Wpedantic but I don't see any tests for it:
> 
> warning: ISO C forbids empty initializer braces [-Wpedantic]
>    const char x[] = { };
>                     ^
> error: zero or negative size array ‘b’
>    const char x[] = { };
>               ^
> 
> I'll avoid handling it but I'm not sure I should add a test case
> for it if it's accepted by mistake (and if I should open a bug
> to reject it instead).

It's a perfectly ordinary combination of two GNU extensions (zero-size 
arrays, and empty initializer braces), so yes, it should be accepted, and 
have size 0 (but -pedantic should produce a pedwarn, not a hard error).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-08 19:50   ` Martin Sebor
@ 2018-08-08 20:35     ` Bernd Edlinger
  2018-08-08 20:48     ` Joseph Myers
  1 sibling, 0 replies; 45+ messages in thread
From: Bernd Edlinger @ 2018-08-08 20:35 UTC (permalink / raw)
  To: Martin Sebor, Jason Merrill; +Cc: gcc-patches, Joseph Myers

On 08/08/18 21:50, Martin Sebor wrote:
>> Sorry, again, but could it be possible that this test case changed
>> with your patch?
>>
>> $ cat w.c
>> const char  x[] = {  };
>> int main()
>> {
>>    __builtin_printf("%ld\n", sizeof(x));
>>    return 0;
>> }
>> $ gcc w.c
>> $ ./a.out
>> 1
>>
>> without your patch
>> $ ./a.out
>> 0
>>
> 
> Jason/Joseph, is this meant to be accepted?  It's rejected with
> a hard error with -Wpedantic but I don't see any tests for it:
> 
> warning: ISO C forbids empty initializer braces [-Wpedantic]
>     const char x[] = { };
>                      ^
> error: zero or negative size array ‘b’
>     const char x[] = { };
>                ^
> 
> I'll avoid handling it but I'm not sure I should add a test case
> for it if it's accepted by mistake (and if I should open a bug
> to reject it instead).
> 
> The comment above complete_array_type() in c-common.c and
> the code kind of suggest it's on purpose but the odd failure
> mode (hard error with -Wpedantic, silence otherwise) and
> the absence of tests make me wonder.
> 

This is also a bit odd:
$ cat w.cc
$ g++ w.cc
w.cc:1:26: error: initializer-string for array of chars is too long [-fpermissive]
  char   x[3] = { 1,2,3,4  };
$ cat w1.cc
char   x[3] = { 1,2,3,4,5  };
int main()
{
   __builtin_printf("%ld\n", sizeof(x));
   return 0;
}
$ g++ w.cc
w1.cc:1:28: error: too many initializers for 'char [3]'
  char   x[3] = { 1,2,3,4,5  };

This suggests, that it might be better to fold the initializer at where
my C/C++ FE patch shortens the string constants?

It would have the advantage, that the array size is already known there.
And it would avoid changing the array size accidentally, because the
decl is already laid out?

What do you think?


Bernd.

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-08 18:34 ` Bernd Edlinger
@ 2018-08-08 19:50   ` Martin Sebor
  2018-08-08 20:35     ` Bernd Edlinger
  2018-08-08 20:48     ` Joseph Myers
  0 siblings, 2 replies; 45+ messages in thread
From: Martin Sebor @ 2018-08-08 19:50 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Bernd Edlinger, gcc-patches, Joseph Myers

> Sorry, again, but could it be possible that this test case changed
> with your patch?
>
> $ cat w.c
> const char  x[] = {  };
> int main()
> {
>    __builtin_printf("%ld\n", sizeof(x));
>    return 0;
> }
> $ gcc w.c
> $ ./a.out
> 1
>
> without your patch
> $ ./a.out
> 0
>

Jason/Joseph, is this meant to be accepted?  It's rejected with
a hard error with -Wpedantic but I don't see any tests for it:

warning: ISO C forbids empty initializer braces [-Wpedantic]
    const char x[] = { };
                     ^
error: zero or negative size array ‘b’
    const char x[] = { };
               ^

I'll avoid handling it but I'm not sure I should add a test case
for it if it's accepted by mistake (and if I should open a bug
to reject it instead).

The comment above complete_array_type() in c-common.c and
the code kind of suggest it's on purpose but the odd failure
mode (hard error with -Wpedantic, silence otherwise) and
the absence of tests make me wonder.

Martin

^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
  2018-08-08 17:33 Bernd Edlinger
@ 2018-08-08 18:34 ` Bernd Edlinger
  2018-08-08 19:50   ` Martin Sebor
  0 siblings, 1 reply; 45+ messages in thread
From: Bernd Edlinger @ 2018-08-08 18:34 UTC (permalink / raw)
  To: Martin Sebor, Jason Merrill; +Cc: gcc-patches, Joseph Myers

On 08/08/18 19:33, Bernd Edlinger wrote:
> Hi Martin,
> 
> sorry, I hope you forgive me, when I add a few comments to your patch.
> 
>> +  unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (ctor);
>> +  tree eltype = TREE_TYPE (type);
> ...
>> +      /* Bail if the CTOR has a block of more than 256 embedded nuls
>> +        due to implicitly initialized elements.  */
>> +      unsigned nelts = (idx - str.length ()) + 1;
>> +      if (nelts > 256)
>> +       return NULL_TREE;
> 
> nelts shadows previous nelts.
> 
>> +  if (!nelts || str.length () < i)
> 
> I don't understand when is str.length () < i ?
> 
>> +    /* Append a nul for the empty initializer { } and for the last
>> +       explicit initializer in the loop above that is a nul.  */
>> +    str.safe_push (0);
>> +
>> +  /* Build a string literal but return the embedded STRING_CST.  */
>> +  tree res = build_string_literal (str.length (), str.begin ());
>> +  res = TREE_OPERAND (TREE_OPERAND (res, 0), 0);
>> +  return res;
>> +}
> 
> 
> res has a different type than the object you initialize.
> I think you should use:
> 
> tree res = build_string (str.length (), str.begin ());
> TREE_TYPE (res) = type;
> return res;
> 

Sorry, again, but could it be possible that this test case changed
with your patch?

$ cat w.c
const char  x[] = {  };
int main()
{
   __builtin_printf("%ld\n", sizeof(x));
   return 0;
}
$ gcc w.c
$ ./a.out
1

without your patch
$ ./a.out
0


Bernd.


^ permalink raw reply	[flat|nested] 45+ messages in thread

* Re: [PATCH] convert braced initializers to strings (PR 71625)
@ 2018-08-08 17:33 Bernd Edlinger
  2018-08-08 18:34 ` Bernd Edlinger
  0 siblings, 1 reply; 45+ messages in thread
From: Bernd Edlinger @ 2018-08-08 17:33 UTC (permalink / raw)
  To: Martin Sebor, Jason Merrill; +Cc: gcc-patches, Joseph Myers

Hi Martin,

sorry, I hope you forgive me, when I add a few comments to your patch.

> +  unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (ctor);
> +  tree eltype = TREE_TYPE (type);
...
> +      /* Bail if the CTOR has a block of more than 256 embedded nuls
> +        due to implicitly initialized elements.  */
> +      unsigned nelts = (idx - str.length ()) + 1;
> +      if (nelts > 256)
> +       return NULL_TREE;

nelts shadows previous nelts.

> +  if (!nelts || str.length () < i)

I don't understand when is str.length () < i ?

> +    /* Append a nul for the empty initializer { } and for the last
> +       explicit initializer in the loop above that is a nul.  */
> +    str.safe_push (0);
> +
> +  /* Build a string literal but return the embedded STRING_CST.  */
> +  tree res = build_string_literal (str.length (), str.begin ());
> +  res = TREE_OPERAND (TREE_OPERAND (res, 0), 0);
> +  return res;
> +}


res has a different type than the object you initialize.
I think you should use:

tree res = build_string (str.length (), str.begin ());
TREE_TYPE (res) = type;
return res;


Bernd.

^ permalink raw reply	[flat|nested] 45+ messages in thread

end of thread, other threads:[~2018-08-18 17:09 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-30 23:51 [PATCH] convert braced initializers to strings (PR 71625) Martin Sebor
2018-07-31 13:39 ` Jason Merrill
2018-07-31 14:49   ` Martin Sebor
2018-08-07  8:58     ` Jason Merrill
2018-08-07 23:04       ` Martin Sebor
2018-08-08 11:09         ` Jason Merrill
2018-08-09  0:17           ` Martin Sebor
2018-08-09 22:07             ` Joseph Myers
2018-08-13 10:36             ` Jason Merrill
2018-08-14 13:27             ` James Greenhalgh
2018-08-14 15:08               ` Martin Sebor
2018-08-14 15:24                 ` Martin Sebor
2018-08-15  2:34                   ` Martin Sebor
2018-08-15 10:29                     ` James Greenhalgh
2018-08-15 15:04                       ` Richard Biener
2018-08-15 15:51                       ` Martin Sebor
2018-08-17 17:19                         ` [PATCH] Fix poly types after PR tree-optimization/71625 strlen optimization Szabolcs Nagy
2018-08-17 17:22                           ` Kyrill Tkachov
2018-08-14 21:14               ` [PATCH] convert braced initializers to strings (PR 71625) Joseph Myers
2018-08-14 22:18                 ` Martin Sebor
2018-08-15 12:07                   ` Joseph Myers
2018-08-15 21:02                     ` Martin Sebor
2018-08-15 21:14                       ` Jeff Law
2018-08-15 21:34                       ` Jeff Law
2018-08-16 15:23                         ` Martin Sebor
2018-08-16 15:32                           ` Jeff Law
2018-08-06 16:41 ` Martin Sebor
2018-08-06 17:04   ` Joseph Myers
2018-08-07  2:02     ` Martin Sebor
2018-08-07 11:31       ` Joseph Myers
2018-08-07 23:05         ` Martin Sebor
2018-08-08 17:33 Bernd Edlinger
2018-08-08 18:34 ` Bernd Edlinger
2018-08-08 19:50   ` Martin Sebor
2018-08-08 20:35     ` Bernd Edlinger
2018-08-08 20:48     ` Joseph Myers
2018-08-09  0:23       ` Martin Sebor
2018-08-09 10:47         ` Joseph Myers
2018-08-16  6:37 Bernd Edlinger
2018-08-17 22:26 ` Bernd Edlinger
2018-08-18  4:13   ` Jeff Law
2018-08-18 10:40   ` Richard Sandiford
2018-08-18 14:25     ` Bernd Edlinger
2018-08-18 16:46       ` Richard Sandiford
2018-08-18 17:09         ` Bernd Edlinger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).