[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