[nvptx,PR85296] Fix handling of extern var with flexible array member

Message ID af913e3e-d55c-fb26-94f0-8f6ec6e4e201@mentor.com
State New
Headers show
Series
  • [nvptx,PR85296] Fix handling of extern var with flexible array member
Related show

Commit Message

Tom de Vries April 12, 2018, 7:30 a.m.
Hi,

for the recently added test-case pr85244-1.c, we run into the following 
failure with the standalone nvptx toolchain:
...
spawn nvptx-none-run ./pr85244-1.exe
error   : Size doesn't match for 'val' in 'input file 2 at offset 3047', 
first specified in 'input file 1 at offset 1805'
nvptx-run: cuLinkAddData failed: unknown error (CUDA_ERROR_UNKNOWN, 999)
...


The linking problem happens because while in pr85244-2.s we have an 
array of size 3:
...
   .visible .const .align 8 .u64 val[3] = { 0, 180388626432, 1337 };
...

in pr85244-1.s we have an array of size 2:
...
         .extern .const .align 8 .u64 val[2]; 

...


The ptx declarations correspond to this source bit in pr85244-1.c:
...
struct s {
  long a;
  int b;
  int tab[];
};

extern const struct s val;
...

and this one in pr85244-2.c (omitting type decl):
...
const struct s val = { 0, 0, { 42, 1337 } };
...

Because ptx has no structs, structs are declared as arrays of a certain 
base type, in this case u64.

In pr85244-2.c we calculate the size of the array, and based on the 
initializer we arrive at a size of 3.

In pr85244-1.c we calculate the size of the array, and based on the type 
we arrive at at size of 2.


The patch fixes this by declaring extern structs which have a flexible 
array member as an array without given dimension.

Build and tested on nvptx.

Committed to stage4 trunk.

Thanks,
- Tom

Patch

[nvptx] Fix handling of extern var with flexible array member

2018-04-12  Tom de Vries  <tom@codesourcery.com>

	PR target/85296
	* config/nvptx/nvptx.c (flexible_array_member_type_p): New function.
	(nvptx_assemble_decl_begin): Add undefined param.  Declare undefined
	array with flexible array member as array without given dimension.
	(nvptx_assemble_undefined_decl): Set nvptx_assemble_decl_begin call
	argument for undefined param to true.

---
 gcc/config/nvptx/nvptx.c | 35 +++++++++++++++++++++++++++++++++--
 1 file changed, 33 insertions(+), 2 deletions(-)

diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c
index a9a3053..131b495 100644
--- a/gcc/config/nvptx/nvptx.c
+++ b/gcc/config/nvptx/nvptx.c
@@ -2021,6 +2021,30 @@  nvptx_output_ascii (FILE *, const char *str, unsigned HOST_WIDE_INT size)
     nvptx_assemble_value (str[i], 1);
 }
 
+/* Return true if TYPE is a record type where the last field is an array without
+   given dimension.  */
+
+static bool
+flexible_array_member_type_p (const_tree type)
+{
+  if (TREE_CODE (type) != RECORD_TYPE)
+    return false;
+
+  const_tree last_field = NULL_TREE;
+  for (const_tree f = TYPE_FIELDS (type); f; f = TREE_CHAIN (f))
+    last_field = f;
+
+  if (!last_field)
+    return false;
+
+  const_tree last_field_type = TREE_TYPE (last_field);
+  if (TREE_CODE (last_field_type) != ARRAY_TYPE)
+    return false;
+
+  return (! TYPE_DOMAIN (last_field_type)
+	  || ! TYPE_MAX_VALUE (TYPE_DOMAIN (last_field_type)));
+}
+
 /* Emit a PTX variable decl and prepare for emission of its
    initializer.  NAME is the symbol name and SETION the PTX data
    area. The type is TYPE, object size SIZE and alignment is ALIGN.
@@ -2031,11 +2055,18 @@  nvptx_output_ascii (FILE *, const char *str, unsigned HOST_WIDE_INT size)
 
 static void
 nvptx_assemble_decl_begin (FILE *file, const char *name, const char *section,
-			   const_tree type, HOST_WIDE_INT size, unsigned align)
+			   const_tree type, HOST_WIDE_INT size, unsigned align,
+			   bool undefined = false)
 {
   bool atype = (TREE_CODE (type) == ARRAY_TYPE)
     && (TYPE_DOMAIN (type) == NULL_TREE);
 
+  if (undefined && flexible_array_member_type_p (type))
+    {
+      size = 0;
+      atype = true;
+    }
+
   while (TREE_CODE (type) == ARRAY_TYPE)
     type = TREE_TYPE (type);
 
@@ -2172,7 +2203,7 @@  nvptx_assemble_undefined_decl (FILE *file, const char *name, const_tree decl)
   tree size = DECL_SIZE_UNIT (decl);
   nvptx_assemble_decl_begin (file, name, section_for_decl (decl),
 			     TREE_TYPE (decl), size ? tree_to_shwi (size) : 0,
-			     DECL_ALIGN (decl));
+			     DECL_ALIGN (decl), true);
   nvptx_assemble_decl_end ();
 }