This fixes a bug in the NVPTX backend where taking the address of a function renamed by the backend (e.g. 'call' or 'malloc') would wrongly use the original name. Now all decl renaming is handled up front via TARGET_MANGLE_DECL_ASSEMBLER_NAME hook, which becomes the only caller of nvptx_name_replacement.
En passant, it also fixes one instance where handling of star prefix on user-supplied DECL_ASSEMBLER_NAME was missing. gcc/ * config/nvptx/nvptx.c (nvptx_name_replacement): Return NULL if no replacement needed. (nvptx_mangle_decl_assembler_name): New. (write_fn_proto): Do not call nvptx_name_replacement. (write_fn_proto_from_insn): Ditto. (nvptx_output_call_insn): Ditto. (TARGET_MANGLE_DECL_ASSEMBLER_NAME): Define. gcc/testsuite/ * gcc.target/nvptx/rename-call.c: New test. * gcc.target/nvptx/rename-call-2.c: New test. * gcc.target/nvptx/asm-name.c: New test. --- Hello, This is an NVPTX bug fix that I'm going to apply to gomp-nvptx branch, but it's a generally useful fix. OK for trunk? Now or when stage1 opens? Thanks. Alexander gcc/config/nvptx/nvptx.c | 26 ++++++++++++++++---------- gcc/testsuite/gcc.target/nvptx/asm-name.c | 14 ++++++++++++++ gcc/testsuite/gcc.target/nvptx/rename-call-2.c | 12 ++++++++++++ gcc/testsuite/gcc.target/nvptx/rename-call.c | 16 ++++++++++++++++ 4 files changed, 58 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/gcc.target/nvptx/asm-name.c create mode 100644 gcc/testsuite/gcc.target/nvptx/rename-call-2.c create mode 100644 gcc/testsuite/gcc.target/nvptx/rename-call.c diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c index 1fc25e5..0c55976 100644 --- a/gcc/config/nvptx/nvptx.c +++ b/gcc/config/nvptx/nvptx.c @@ -273,7 +273,16 @@ nvptx_name_replacement (const char *name) for (size_t i = 0; i < ARRAY_SIZE (replacements) / 2; i++) if (!strcmp (name, replacements[2 * i])) return replacements[2 * i + 1]; - return name; + return NULL; +} + +/* Implement TARGET_MANGLE_DECL_ASSEMBLER_NAME. */ + +static tree +nvptx_mangle_decl_assembler_name (tree ARG_UNUSED (decl), tree id) +{ + const char *name = nvptx_name_replacement (IDENTIFIER_POINTER (id)); + return name ? get_identifier (name) : id; } /* If MODE should be treated as two registers of an inner mode, return @@ -735,13 +744,8 @@ write_fn_proto (std::stringstream &s, bool is_defn, if (is_defn) /* Emit a declaration. The PTX assembler gets upset without it. */ name = write_fn_proto (s, false, name, decl); - else - { - /* Avoid repeating the name replacement. */ - name = nvptx_name_replacement (name); - if (name[0] == '*') - name++; - } + else if (name[0] == '*') + name++; write_fn_marker (s, is_defn, TREE_PUBLIC (decl), name); @@ -822,7 +826,8 @@ write_fn_proto_from_insn (std::stringstream &s, const char *name, } else { - name = nvptx_name_replacement (name); + if (name[0] == '*') + name++; write_fn_marker (s, false, true, name); s << "\t.extern .func "; } @@ -1976,7 +1981,6 @@ nvptx_output_call_insn (rtx_insn *insn, rtx result, rtx callee) if (decl) { const char *name = get_fnname_from_decl (decl); - name = nvptx_name_replacement (name); assemble_name (asm_out_file, name); } else @@ -5124,6 +5128,8 @@ nvptx_goacc_reduction (gcall *call) #undef TARGET_NO_REGISTER_ALLOCATION #define TARGET_NO_REGISTER_ALLOCATION true +#undef TARGET_MANGLE_DECL_ASSEMBLER_NAME +#define TARGET_MANGLE_DECL_ASSEMBLER_NAME nvptx_mangle_decl_assembler_name #undef TARGET_ENCODE_SECTION_INFO #define TARGET_ENCODE_SECTION_INFO nvptx_encode_section_info #undef TARGET_RECORD_OFFLOAD_SYMBOL diff --git a/gcc/testsuite/gcc.target/nvptx/asm-name.c b/gcc/testsuite/gcc.target/nvptx/asm-name.c new file mode 100644 index 0000000..db52fff --- /dev/null +++ b/gcc/testsuite/gcc.target/nvptx/asm-name.c @@ -0,0 +1,14 @@ +/* { dg-options "-std=gnu99" } */ +/* { dg-do assemble } */ + +void foo(void) asm("bar"); +void foo_np() asm("baz"); + +void *p1 = foo; +void *p2 = foo_np; + +void *r1() { return foo; } +void *r2() { return foo_np; } + +void f1() { foo(); } +void f2() { foo_np(); } diff --git a/gcc/testsuite/gcc.target/nvptx/rename-call-2.c b/gcc/testsuite/gcc.target/nvptx/rename-call-2.c new file mode 100644 index 0000000..230c680 --- /dev/null +++ b/gcc/testsuite/gcc.target/nvptx/rename-call-2.c @@ -0,0 +1,12 @@ +/* { dg-options "-std=gnu99" } */ +/* { dg-do assemble } */ + +/* Like rename-call.c, but using old-style prototype. */ + +void call(); + +void *p = call; + +void *r() { return call; } + +void f() { call(); } diff --git a/gcc/testsuite/gcc.target/nvptx/rename-call.c b/gcc/testsuite/gcc.target/nvptx/rename-call.c new file mode 100644 index 0000000..d5685a7 --- /dev/null +++ b/gcc/testsuite/gcc.target/nvptx/rename-call.c @@ -0,0 +1,16 @@ +/* { dg-options "-std=gnu99" } */ +/* { dg-do assemble } */ + +/* Due to a bug in ptxas, calling a function named 'call' results in a "syntax + error" diagnostic. To work around that, nvptx backend renames it to + '__nvptx_call', but it used to do that inconsistently, and taking the address + of the function used the original name. Check that it consistently works in + different contexts. */ + +void call(void); + +void *p = call; + +void *r() { return call; } + +void f() { call(); } -- 1.8.3.1