Functions which follow vector calling convention variant need be annotated by .variant_cc directive according the RISC-V Assembly Programmer's Manual and RISC-V ELF Specification[2].
[1] https://github.com/riscv-non-isa/riscv-asm-manual/blob/master/riscv-asm.md#pseudo-ops [2] https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#dynamic-linking gcc/ChangeLog: * config/riscv/riscv-protos.h (riscv_declare_function_name): Add protos. (riscv_asm_output_alias): Ditto. (riscv_asm_output_external): Ditto. * config/riscv/riscv.cc (riscv_asm_output_variant_cc): Output .variant_cc directive for vector function. (riscv_declare_function_name): Ditto. (riscv_asm_output_alias): Ditto. (riscv_asm_output_external): Ditto. * config/riscv/riscv.h (ASM_DECLARE_FUNCTION_NAME): Implement ASM_DECLARE_FUNCTION_NAME. (ASM_OUTPUT_DEF_FROM_DECLS): Implement ASM_OUTPUT_DEF_FROM_DECLS. (ASM_OUTPUT_EXTERNAL): Implement ASM_OUTPUT_EXTERNAL. gcc/testsuite/ChangeLog: * gcc.target/riscv/rvv/base/abi-call-variant_cc.c: New test. --- gcc/config/riscv/riscv-protos.h | 3 ++ gcc/config/riscv/riscv.cc | 48 +++++++++++++++++++ gcc/config/riscv/riscv.h | 15 ++++++ .../riscv/rvv/base/abi-call-variant_cc.c | 39 +++++++++++++++ 4 files changed, 105 insertions(+) create mode 100644 gcc/testsuite/gcc.target/riscv/rvv/base/abi-call-variant_cc.c diff --git a/gcc/config/riscv/riscv-protos.h b/gcc/config/riscv/riscv-protos.h index 4a67297173d..260ba2f9a49 100644 --- a/gcc/config/riscv/riscv-protos.h +++ b/gcc/config/riscv/riscv-protos.h @@ -101,6 +101,9 @@ extern bool riscv_split_64bit_move_p (rtx, rtx); extern void riscv_split_doubleword_move (rtx, rtx); extern const char *riscv_output_move (rtx, rtx); extern const char *riscv_output_return (); +extern void riscv_declare_function_name (FILE *, const char *, tree); +extern void riscv_asm_output_alias (FILE *, const tree, const tree); +extern void riscv_asm_output_external (FILE *, const tree, const char *); #ifdef RTX_CODE extern void riscv_expand_int_scc (rtx, enum rtx_code, rtx, rtx, bool *invert_ptr = 0); diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index 09c9e09e83a..83cf7a5da82 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -7013,6 +7013,54 @@ riscv_issue_rate (void) return tune_param->issue_rate; } +/* Output .variant_cc for function symbol which follows vector calling + convention. */ + +static void +riscv_asm_output_variant_cc (FILE *stream, const tree decl, const char *name) +{ + if (TREE_CODE (decl) == FUNCTION_DECL) + { + riscv_cc cc = (riscv_cc) fndecl_abi (decl).id (); + if (cc == RISCV_CC_V) + { + fprintf (stream, "\t.variant_cc\t"); + assemble_name (stream, name); + fprintf (stream, "\n"); + } + } +} + +/* Implement ASM_DECLARE_FUNCTION_NAME. */ + +void +riscv_declare_function_name (FILE *stream, const char *name, tree fndecl) +{ + riscv_asm_output_variant_cc (stream, fndecl, name); + ASM_OUTPUT_TYPE_DIRECTIVE (stream, name, "function"); + ASM_OUTPUT_LABEL (stream, name); +} + +/* Implement ASM_OUTPUT_DEF_FROM_DECLS. */ + +void +riscv_asm_output_alias (FILE *stream, const tree decl, const tree target) +{ + const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0); + const char *value = IDENTIFIER_POINTER (target); + riscv_asm_output_variant_cc (stream, decl, name); + ASM_OUTPUT_DEF (stream, name, value); +} + +/* Implement ASM_OUTPUT_EXTERNAL. */ + +void +riscv_asm_output_external (FILE *stream, tree decl, const char *name) +{ + default_elf_asm_output_external (stream, decl, name); + riscv_asm_output_variant_cc (stream, decl, name); +} + /* Auxiliary function to emit RISC-V ELF attribute. */ static void riscv_emit_attribute () diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h index b24b240dd75..1820593bab5 100644 --- a/gcc/config/riscv/riscv.h +++ b/gcc/config/riscv/riscv.h @@ -1021,6 +1021,21 @@ while (0) #define ASM_COMMENT_START "#" +/* Add output .variant_cc directive for specific function definition. */ +#undef ASM_DECLARE_FUNCTION_NAME +#define ASM_DECLARE_FUNCTION_NAME(STR, NAME, DECL) \ + riscv_declare_function_name (STR, NAME, DECL) + +/* Add output .variant_cc directive for specific alias definition. */ +#undef ASM_OUTPUT_DEF_FROM_DECLS +#define ASM_OUTPUT_DEF_FROM_DECLS(STR, DECL, TARGET) \ + riscv_asm_output_alias (STR, DECL, TARGET) + +/* Add output .variant_cc directive for specific extern function. */ +#undef ASM_OUTPUT_EXTERNAL +#define ASM_OUTPUT_EXTERNAL(STR, DECL, NAME) \ + riscv_asm_output_external (STR, DECL, NAME) + #undef SIZE_TYPE #define SIZE_TYPE (POINTER_SIZE == 64 ? "long unsigned int" : "unsigned int") diff --git a/gcc/testsuite/gcc.target/riscv/rvv/base/abi-call-variant_cc.c b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-call-variant_cc.c new file mode 100644 index 00000000000..4e45203f5b5 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/rvv/base/abi-call-variant_cc.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 --param=riscv-vector-abi -Wno-psabi" } */ + +#include "riscv_vector.h" + +void +f_undef1 (vint8m1_t a); +void +f_undef2 (vint8m1x8_t a); +void +f_undef3 (vbool1_t a); +vint8m1_t +f_undef4 (); + +void +bar_real (vint8m1_t a, vint8m1x8_t b, vbool1_t c) +{ + f_undef1 (a); + f_undef2 (b); + f_undef3 (c); +} + +__attribute__ ((alias ("bar_real"))) void +bar_alias (vint8m1_t a, vint8m1x8_t b, vbool1_t c); + +void +f_1 (vint8m1_t *a, vint8m1x8_t *b, vbool1_t *c) +{ + bar_alias (*a, *b, *c); + *a = f_undef4 (); +} + +/* { dg-final { scan-assembler-times {\.variant_cc\tbar_real} 1 } } */ +/* { dg-final { scan-assembler-times {\.variant_cc\tbar_alias} 1 } } */ +/* { dg-final { scan-assembler-times {\.variant_cc\tf_1} 0 } } */ +/* { dg-final { scan-assembler-times {\.variant_cc\tf_undef1} 1 } } */ +/* { dg-final { scan-assembler-times {\.variant_cc\tf_undef2} 1 } } */ +/* { dg-final { scan-assembler-times {\.variant_cc\tf_undef3} 1 } } */ +/* { dg-final { scan-assembler-times {\.variant_cc\tf_undef4} 1 } } */ -- 2.36.3