Index: llvm/lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -10203,6 +10203,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 did 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) Index: llvm/test/CodeGen/RISCV/nest-register.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/RISCV/nest-register.ll @@ -0,0 +1,79 @@ +; 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=riscv32 -mattr=+m -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV32IM %s +; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV64I %s +; RUN: llc -mtriple=riscv64 -mattr=+m -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV64IM %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 +; +; RV32IM-LABEL: nest_receiver: +; RV32IM: # %bb.0: +; RV32IM-NEXT: mv a0, t2 +; RV32IM-NEXT: ret +; +; RV64I-LABEL: nest_receiver: +; RV64I: # %bb.0: +; RV64I-NEXT: mv a0, t2 +; RV64I-NEXT: ret +; +; RV64IM-LABEL: nest_receiver: +; RV64IM: # %bb.0: +; RV64IM-NEXT: mv a0, t2 +; RV64IM-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 +; +; RV32IM-LABEL: nest_caller: +; RV32IM: # %bb.0: +; RV32IM-NEXT: addi sp, sp, -16 +; RV32IM-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; RV32IM-NEXT: mv t2, a0 +; RV32IM-NEXT: call nest_receiver@plt +; RV32IM-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; RV32IM-NEXT: addi sp, sp, 16 +; RV32IM-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 +; +; RV64IM-LABEL: nest_caller: +; RV64IM: # %bb.0: +; RV64IM-NEXT: addi sp, sp, -16 +; RV64IM-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; RV64IM-NEXT: mv t2, a0 +; RV64IM-NEXT: call nest_receiver@plt +; RV64IM-NEXT: ld ra, 8(sp) # 8-byte Folded Reload +; RV64IM-NEXT: addi sp, sp, 16 +; RV64IM-NEXT: ret + %result = call i8* @nest_receiver(i8* nest %arg) + ret i8* %result +}