[llvm] f4f6c63 - [RISCV] Add support for static chain

via llvm-commits llvm-commits at lists.llvm.org
Wed Nov 9 00:10:40 PST 2022


Author: melonedo
Date: 2022-11-09T16:10:32+08:00
New Revision: f4f6c63f0df7465b3f4e64e1637405e641f19dc2

URL: https://github.com/llvm/llvm-project/commit/f4f6c63f0df7465b3f4e64e1637405e641f19dc2
DIFF: https://github.com/llvm/llvm-project/commit/f4f6c63f0df7465b3f4e64e1637405e641f19dc2.diff

LOG: [RISCV] Add support for static chain

The static chain parameter is a special parameter that is not passed in the usual argument registers or stack space. For example, in x64 System V ABI it is always passed in R10. Although the ABI of RISCV does not assign a register for this purpose, GCC had support for it on RISC-V a long time ago, and it is exposed via `__builtin_call_with_static_chain` intrinsic, and assign t2 for static chain parameters. This patch also chose t2 for compatibility.

In LLVM, static chain parameters are handled by the `nest` attribute of an argument to a function ([D6332](https://reviews.llvm.org/D6332)), so tests are added to ensure `nest` arguments are handled correctly.

Reviewed By: kito-cheng, MaskRay

Differential Revision: https://reviews.llvm.org/D129106

Added: 
    llvm/test/CodeGen/RISCV/ghccc-nest.ll
    llvm/test/CodeGen/RISCV/nest-register.ll

Modified: 
    llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index a7f77325b605..b08461587fd7 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -11078,6 +11078,15 @@ static bool CC_RISCV(const DataLayout &DL, RISCVABI::ABI ABI, unsigned ValNo,
   assert(XLen == 32 || XLen == 64);
   MVT XLenVT = XLen == 32 ? MVT::i32 : MVT::i64;
 
+  // Static chain parameter must not be passed in normal argument registers,
+  // so we assign t2 for it as done in GCC's __builtin_call_with_static_chain
+  if (ArgFlags.isNest()) {
+    if (unsigned Reg = State.AllocateReg(RISCV::X7)) {
+      State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
+      return false;
+    }
+  }
+
   // Any return value split in to more than two values can't be returned
   // directly. Vectors are returned via the available vector registers.
   if (!LocVT.isVector() && IsRet && ValNo > 1)
@@ -11618,6 +11627,11 @@ static bool CC_RISCV_GHC(unsigned ValNo, MVT ValVT, MVT LocVT,
                          CCValAssign::LocInfo LocInfo,
                          ISD::ArgFlagsTy ArgFlags, CCState &State) {
 
+  if (ArgFlags.isNest()) {
+    report_fatal_error(
+        "Attribute 'nest' is not supported in GHC calling convention");
+  }
+
   if (LocVT == MVT::i32 || LocVT == MVT::i64) {
     // Pass in STG registers: Base, Sp, Hp, R1, R2, R3, R4, R5, R6, R7, SpLim
     //                        s1    s2  s3  s4  s5  s6  s7  s8  s9  s10 s11

diff  --git a/llvm/test/CodeGen/RISCV/ghccc-nest.ll b/llvm/test/CodeGen/RISCV/ghccc-nest.ll
new file mode 100644
index 000000000000..c8ed3895a0a5
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/ghccc-nest.ll
@@ -0,0 +1,13 @@
+; RUN: not --crash llc -mtriple=riscv64 -mattr=+f,+d -verify-machineinstrs -filetype=null < %s 2>&1 | FileCheck %s
+; RUN: not --crash llc -mtriple=riscv32 -mattr=+f,+d -verify-machineinstrs -filetype=null < %s 2>&1 | FileCheck %s
+
+define ghccc ptr @nest_receiver(ptr nest %arg) nounwind {
+  ret ptr %arg
+}
+
+define ghccc ptr @nest_caller(ptr %arg) nounwind {
+  %result = call ghccc ptr @nest_receiver(ptr nest %arg)
+  ret ptr %result
+}
+
+; CHECK: LLVM ERROR: Attribute 'nest' is not supported in GHC calling convention

diff  --git a/llvm/test/CodeGen/RISCV/nest-register.ll b/llvm/test/CodeGen/RISCV/nest-register.ll
new file mode 100644
index 000000000000..97704ebae4cb
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/nest-register.ll
@@ -0,0 +1,47 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefix=RV32I %s
+; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
+; RUN:   | FileCheck -check-prefix=RV64I %s
+
+; Tests that the 'nest' parameter attribute causes the relevant parameter to be
+; passed in the right register.
+
+define ptr @nest_receiver(ptr nest %arg) nounwind {
+; RV32I-LABEL: nest_receiver:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    mv a0, t2
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: nest_receiver:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    mv a0, t2
+; RV64I-NEXT:    ret
+;
+  ret ptr %arg
+}
+
+define ptr @nest_caller(ptr %arg) nounwind {
+; RV32I-LABEL: nest_caller:
+; RV32I:       # %bb.0:
+; RV32I-NEXT:    addi sp, sp, -16
+; RV32I-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT:    mv t2, a0
+; RV32I-NEXT:    call nest_receiver at plt
+; RV32I-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT:    addi sp, sp, 16
+; RV32I-NEXT:    ret
+;
+; RV64I-LABEL: nest_caller:
+; RV64I:       # %bb.0:
+; RV64I-NEXT:    addi sp, sp, -16
+; RV64I-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT:    mv t2, a0
+; RV64I-NEXT:    call nest_receiver at plt
+; RV64I-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT:    addi sp, sp, 16
+; RV64I-NEXT:    ret
+;
+  %result = call ptr @nest_receiver(ptr nest %arg)
+  ret ptr %result
+}


        


More information about the llvm-commits mailing list