2015-12-04 Nathan Sidwell gcc/ * config/nvptx/nvptx.c (nvptx_assemble_decl_begin): New, replacing ... (init_output_initializer): ... this. (nvptx_output_aligned_decl, nvptx_asm_declare_constant_name, nvptx_declare_object_name, nvptx_assemble_undefined_decl): Use nvptx_assemble_decl_begin. gcc/testsuite/ * gcc.target/nvptx/ary-init.c: New. Index: config/nvptx/nvptx.c =================================================================== --- config/nvptx/nvptx.c (revision 231267) +++ config/nvptx/nvptx.c (working copy) @@ -1628,6 +1628,50 @@ nvptx_output_ascii (FILE *, const char * nvptx_assemble_value (str[i], 1); } +/* 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. + The caller has already emitted any indentation and linkage + specifier. It is responsible for any initializer, terminating ; + and newline. SIZE is in bytes, ALIGN is in bits -- confusingly + this is the opposite way round that PTX wants them! */ + +static void +nvptx_assemble_decl_begin (FILE *file, const char *name, const char *section, + const_tree type, HOST_WIDE_INT size, unsigned align) +{ + while (TREE_CODE (type) == ARRAY_TYPE) + type = TREE_TYPE (type); + + if (!INTEGRAL_TYPE_P (type) && !SCALAR_FLOAT_TYPE_P (type)) + type = ptr_type_node; + unsigned elt_size = int_size_in_bytes (type); + if (elt_size > UNITS_PER_WORD) + { + type = ptr_type_node; + elt_size = int_size_in_bytes (type); + } + + decl_chunk_size = elt_size; + decl_chunk_mode = int_mode_for_mode (TYPE_MODE (type)); + decl_offset = 0; + init_part = 0; + + object_size = size; + object_finished = !size; + + fprintf (file, "%s .align %d .u%d ", + section, align / BITS_PER_UNIT, + elt_size * BITS_PER_UNIT); + assemble_name (file, name); + + if (size) + /* We make everything an array, to simplify any initialization + emission. */ + fprintf (file, "[" HOST_WIDE_INT_PRINT_DEC "]", + (size + elt_size - 1) / elt_size); +} + /* Called when the initializer for a decl has been completely output through combinations of the three functions above. */ @@ -1644,33 +1688,6 @@ nvptx_assemble_decl_end (void) fprintf (asm_out_file, ";\n"); } -/* 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 - to use. */ - -static void -init_output_initializer (FILE *file, const char *name, const_tree type, - bool is_public) -{ - write_var_marker (file, true, is_public, name); - - 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; - decl_chunk_size = int_size_in_bytes (type); - decl_chunk_mode = int_mode_for_mode (TYPE_MODE (type)); - decl_offset = 0; - init_part = 0; - object_finished = false; -} - /* Output an uninitialized common or file-scope variable. */ void @@ -1681,13 +1698,10 @@ nvptx_output_aligned_decl (FILE *file, c /* If this is public, it is common. The nearest thing we have to common is weak. */ - fprintf (file, "\t%s%s .align %d .b8 ", - TREE_PUBLIC (decl) ? ".weak " : "", - section_for_decl (decl), - align / BITS_PER_UNIT); - assemble_name (file, name); - if (size > 0) - fprintf (file, "[" HOST_WIDE_INT_PRINT_DEC"]", size); + fprintf (file, "\t%s", TREE_PUBLIC (decl) ? ".weak " : ""); + + nvptx_assemble_decl_begin (file, name, section_for_decl (decl), + TREE_TYPE (decl), size, align); fprintf (file, ";\n"); } @@ -1697,17 +1711,15 @@ nvptx_output_aligned_decl (FILE *file, c static void nvptx_asm_declare_constant_name (FILE *file, const char *name, - const_tree exp, HOST_WIDE_INT size) + const_tree exp, HOST_WIDE_INT obj_size) { + write_var_marker (file, true, false, name); + + fprintf (file, "\t"); + tree type = TREE_TYPE (exp); - init_output_initializer (file, name, type, false); - fprintf (file, "\t.const .align %d .u%d ", - TYPE_ALIGN (TREE_TYPE (exp)) / BITS_PER_UNIT, - decl_chunk_size * BITS_PER_UNIT); - assemble_name (file, name); - fprintf (file, "[" HOST_WIDE_INT_PRINT_DEC "]", - (size + decl_chunk_size - 1) / decl_chunk_size); - object_size = size; + nvptx_assemble_decl_begin (file, name, ".const", type, obj_size, + TYPE_ALIGN (type)); } /* Implement the ASM_DECLARE_OBJECT_NAME macro. Used to start writing @@ -1716,24 +1728,15 @@ nvptx_asm_declare_constant_name (FILE *f void nvptx_declare_object_name (FILE *file, const char *name, const_tree decl) { - tree type = TREE_TYPE (decl); + write_var_marker (file, true, TREE_PUBLIC (decl), name); - init_output_initializer (file, name, type, TREE_PUBLIC (decl)); - fprintf (file, "\t%s%s .align %d .u%d ", - !TREE_PUBLIC (decl) ? "" - : DECL_WEAK (decl) ? ".weak " : ".visible ", - section_for_decl (decl), - DECL_ALIGN (decl) / BITS_PER_UNIT, - decl_chunk_size * BITS_PER_UNIT); - assemble_name (file, name); + fprintf (file, "\t%s", (!TREE_PUBLIC (decl) ? "" + : DECL_WEAK (decl) ? ".weak " : ".visible ")); - unsigned HOST_WIDE_INT size = tree_to_uhwi (DECL_SIZE_UNIT (decl)); - if (size > 0) - fprintf (file, "[" HOST_WIDE_INT_PRINT_DEC "]", - (size + decl_chunk_size - 1) / decl_chunk_size); - else - object_finished = true; - object_size = size; + tree type = TREE_TYPE (decl); + HOST_WIDE_INT obj_size = tree_to_shwi (DECL_SIZE_UNIT (decl)); + nvptx_assemble_decl_begin (file, name, section_for_decl (decl), + type, obj_size, DECL_ALIGN (decl)); } /* Implement TARGET_ASM_GLOBALIZE_LABEL by doing nothing. */ @@ -1751,12 +1754,11 @@ nvptx_assemble_undefined_decl (FILE *fil { write_var_marker (file, false, TREE_PUBLIC (decl), name); - fprintf (file, "\t.extern %s .b8 ", section_for_decl (decl)); - assemble_name_raw (file, name); - - HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (decl)); - if (size > 0) - fprintf (file, "[" HOST_WIDE_INT_PRINT_DEC"]", size); + fprintf (file, "\t.extern "); + 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)); fprintf (file, ";\n"); } Index: testsuite/gcc.target/nvptx/ary-init.c =================================================================== --- testsuite/gcc.target/nvptx/ary-init.c (revision 0) +++ testsuite/gcc.target/nvptx/ary-init.c (working copy) @@ -0,0 +1,21 @@ +/* { dg-additional-options "-Wno-long-long" } */ + +char ca1[2] = {'a', 'b'}; +short sa1[2] = { 1, 2 }; +int ia1[2] = { 3, 4 }; +long long la1[2] = { 5, 6 }; + +char ca2[2][2] = {'A', 'B', 'C', 'D'}; +short sa2[2][2] = { 7, 8, 9, 10 }; +int ia2[2][2] = { 11, 12, 13, 14 }; +long long la2[2][2] = { 15, 16, 17, 18 }; + +/* dg-final { scan-assembler " .align 8 .u64 la1\\\[2\\\] = { 5, 6 };" } } */ +/* dg-final { scan-assembler " .align 4 .u32 ia1\\\[2\\\] = { 3, 4 };" } } */ +/* dg-final { scan-assembler " .align 2 .u16 sa1\\\[2\\\] = { 1, 2 };" } } */ +/* dg-final { scan-assembler " .align 1 .u8 ca1\\\[2\\\] = { 97, 98 };" } } */ + +/* dg-final { scan-assembler " .align 8 .u64 la2\\\[4\\\] = { 15, 16, 17, 18 };" } } */ +/* dg-final { scan-assembler " .align 4 .u32 ia2\\\[4\\\] = { 11, 12, 13, 14 };" } } */ +/* dg-final { scan-assembler " .align 2 .u16 sa2\\\[4\\\] = { 7, 8, 9, 10 };" } } */ +/* dg-final { scan-assembler " .align 1 .u8 ca2\\\[4\\\] = { 65, 66, 67, 68 };" } } */