MI thunks generate RTL as if reload were complete and emit it directly
without running register allocation.  Creating a pseudo while
materializing an invalid sibcall address therefore triggers the
gen_reg_rtx assertion.

Use STATIC_CHAIN_REGNUM for this post-reload thunk path.  It is available
as a temporary in MI thunks and belongs to SIBCALL_REGS.  Keep using a
pseudo for sibcalls expanded before register allocation.

        PR target/126449

gcc/ChangeLog:

        * config/riscv/riscv.cc (riscv_legitimize_call_address): Use
        STATIC_CHAIN_REGNUM when a sibcall address is materialized in
        post-reload thunk code.

gcc/testsuite/ChangeLog:

        * g++.target/riscv/pr126449.C: New test.

Reported-by: Michal Jireš <[email protected]>
Signed-off-by: Jin Ma <[email protected]>
---
 gcc/config/riscv/riscv.cc                 | 17 ++++++++++++++---
 gcc/testsuite/g++.target/riscv/pr126449.C | 23 +++++++++++++++++++++++
 2 files changed, 37 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/g++.target/riscv/pr126449.C

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index a401c0c7c93..d813f03b549 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -8110,9 +8110,20 @@ riscv_legitimize_call_address (rtx addr, bool sibcall_p)
 {
   if (!call_insn_operand (addr, VOIDmode))
     {
-      rtx reg = sibcall_p
-               ? gen_reg_rtx (Pmode)
-               : RISCV_CALL_ADDRESS_TEMP (Pmode);
+      rtx reg;
+      if (sibcall_p && can_create_pseudo_p ())
+       reg = gen_reg_rtx (Pmode);
+      else if (sibcall_p)
+       {
+         /* MI thunks are expanded as post-reload code and cannot create
+            pseudos.  STATIC_CHAIN_REGNUM is available as a temporary there
+            and is suitable for an indirect sibling call.  */
+         gcc_assert (riscv_in_thunk_func
+                     && SIBCALL_REG_P (STATIC_CHAIN_REGNUM));
+         reg = gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM);
+       }
+      else
+       reg = RISCV_CALL_ADDRESS_TEMP (Pmode);
       riscv_emit_move (reg, addr);
 
       if (is_zicfilp_p ())
diff --git a/gcc/testsuite/g++.target/riscv/pr126449.C 
b/gcc/testsuite/g++.target/riscv/pr126449.C
new file mode 100644
index 00000000000..f5f4c90b3eb
--- /dev/null
+++ b/gcc/testsuite/g++.target/riscv/pr126449.C
@@ -0,0 +1,23 @@
+/* PR target/126449 */
+/* { dg-do compile { target { rv64 } } } */
+/* { dg-options "-mcmodel=large -fno-pie" } */
+
+struct AddIn
+{
+  virtual ~AddIn ();
+};
+
+struct Base
+{
+  virtual ~Base ();
+};
+
+struct Deriv : Base, AddIn
+{
+};
+
+int
+main ()
+{
+  Deriv deriv;
+}
-- 
2.52.0

Reply via email to