@@ -1692,6 +1692,29 @@ nvptx_assemble_decl_end (void)
fprintf (asm_out_file, ";\n");
}
+/* Return a type suitable to output initializers for TYPE. */
+static const_tree
+nvptx_ptx_type_for_output (const_tree type)
+{
+ /* Avoid picking a larger type than the underlying type. */
+ if (TREE_CODE (type) == ARRAY_TYPE
+ || TREE_CODE (type) == COMPLEX_TYPE)
+ type = TREE_TYPE (type);
+ int sz = int_size_in_bytes (type);
+ if (sz < 0)
+ return char_type_node;
+ /* Size of the output type must divide that of original type. Initializers
+ with pointers to objects need a pointer-sized type. These requirements
+ may be contradictory for packed structs, but giving priority to first at
+ least allows to output some initializers correctly. Here we pick largest
+ suitable integer type without deeper inspection. */
+ return (sz % 8 || !TARGET_ABI64
+ ? (sz % 4
+ ? (sz % 2 ? char_type_node : short_integer_type_node)
+ : integer_type_node)
+ : long_integer_type_node);
+}
+
/* Start a declaration of a variable of TYPE with NAME to
FILE. IS_PUBLIC says whether this will be externally visible.
Here we just write the linker hint and decide on the chunk size
@@ -1705,15 +1728,7 @@ init_output_initializer (FILE *file, const char *name, const_tree type,
assemble_name_raw (file, name);
fputc ('\n', file);
- if (TREE_CODE (type) == ARRAY_TYPE)
- type = TREE_TYPE (type);
- int sz = int_size_in_bytes (type);
- if ((TREE_CODE (type) != INTEGER_TYPE
- && TREE_CODE (type) != ENUMERAL_TYPE
- && TREE_CODE (type) != REAL_TYPE)
- || sz < 0
- || sz > HOST_BITS_PER_WIDE_INT)
- type = ptr_type_node;
+ type = nvptx_ptx_type_for_output (type);
decl_chunk_size = int_size_in_bytes (type);
decl_chunk_mode = int_mode_for_mode (TYPE_MODE (type));
decl_offset = 0;