diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -10602,6 +10602,15 @@ 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) @@ -11127,6 +11136,11 @@ 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 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/ghccc-nest.ll @@ -0,0 +1,15 @@ +; Check that no nest arguments are not passed in GHC calling convention +; +; RUN: not --crash llc -mtriple=riscv64 -mattr=+f,+d -verify-machineinstrs < %s 2>&1 | FileCheck %s +; RUN: not --crash llc -mtriple=riscv32 -mattr=+f,+d -verify-machineinstrs < %s 2>&1 | FileCheck %s + +define ghccc i8* @nest_receiver(i8* nest %arg) nounwind { + ret i8* %arg +} + +define ghccc i8* @nest_caller(i8* %arg) nounwind { + %result = call ghccc i8* @nest_receiver(i8* nest %arg) + ret i8* %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 --- /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 i8* @nest_receiver(i8* 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 i8* %arg +} + +define i8* @nest_caller(i8* %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@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@plt +; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret +; + %result = call i8* @nest_receiver(i8* nest %arg) + ret i8* %result +}