diff options
| author | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-11 20:08:36 +0800 |
|---|---|---|
| committer | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-11 20:08:36 +0800 |
| commit | 551f0b3fcd6f797ed6dca90f39123b0359396dcb (patch) | |
| tree | ccef579ebdf4f1df9bf2b5f08062b66c216b19bd /backend/unittests/Target/RISCVCallLoweringTest.cpp | |
| parent | 8b797159e6c8fe1294fd2d26de3bd0992c61ea24 (diff) | |
| download | rcc-project-551f0b3fcd6f797ed6dca90f39123b0359396dcb.tar.gz rcc-project-551f0b3fcd6f797ed6dca90f39123b0359396dcb.tar.xz | |
[RISCV] Match LLVM call-frame pseudo semantics
Diffstat (limited to 'backend/unittests/Target/RISCVCallLoweringTest.cpp')
| -rw-r--r-- | backend/unittests/Target/RISCVCallLoweringTest.cpp | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/backend/unittests/Target/RISCVCallLoweringTest.cpp b/backend/unittests/Target/RISCVCallLoweringTest.cpp index d3685ae..1eaf146 100644 --- a/backend/unittests/Target/RISCVCallLoweringTest.cpp +++ b/backend/unittests/Target/RISCVCallLoweringTest.cpp @@ -483,6 +483,8 @@ void testOrdinaryAndIndirectEmission(TestContext &Context) { return; const auto Instructions = instructions(*Block); + rcc::MachineInstr *FrameDown = Instructions.empty() ? nullptr : Instructions.front(); + rcc::MachineInstr *FrameUp = Instructions.size() > 3 ? Instructions[3] : nullptr; rcc::MachineInstr *Call = findInstruction(*Block, rcc::riscv::InstructionOpcode::PseudoCALL); Context.expect(Instructions.size() == 5 && Instructions.front()->opcode() == @@ -497,6 +499,39 @@ void testOrdinaryAndIndirectEmission(TestContext &Context) { Call->operandAt(2)->kind() == rcc::MachineOperand::Kind::RegisterMask, "ordinary emission must materialize canonical full-value copies, call-frame, " "target, ID, and RegMask"); + const rcc::Register StackPointer = + rcc::Register::fromPhysical(physical(rcc::riscv::PhysicalRegisterID::X2)); + const auto HasStackPointerEffects = [StackPointer](const rcc::MachineInstr *Instruction) { + bool HasDef = false; + bool HasUse = false; + if (Instruction == nullptr) + return false; + for (const rcc::MachineOperand &Operand : Instruction->operands()) { + if (!Operand.isRegister() || !Operand.isImplicit() || + Operand.registerValue() != StackPointer) { + continue; + } + HasDef |= Operand.isDef(); + HasUse |= Operand.isUse(); + } + return HasDef && HasUse; + }; + const auto ImmediateAt = [](const rcc::MachineInstr *Instruction, std::size_t Index) { + const rcc::MachineOperand *Operand = + Instruction == nullptr ? nullptr : Instruction->operandAt(Index); + return Operand == nullptr ? nullptr : Operand->getIf<std::int64_t>(); + }; + const auto *DownAmount = ImmediateAt(FrameDown, 0); + const auto *DownPrepared = ImmediateAt(FrameDown, 1); + const auto *UpAmount = ImmediateAt(FrameUp, 0); + const auto *UpPrepared = ImmediateAt(FrameUp, 1); + Context.expect( + DownAmount != nullptr && *DownAmount == 0 && DownPrepared != nullptr && *DownPrepared == 0 && + UpAmount != nullptr && *UpAmount == 0 && UpPrepared != nullptr && *UpPrepared == 0 && + HasStackPointerEffects(FrameDown) && HasStackPointerEffects(FrameUp) && + !FrameDown->flags().has(rcc::MachineInstrFlag::FrameSetup) && + !FrameUp->flags().has(rcc::MachineInstrFlag::FrameDestroy), + "call-frame pseudos must use LLVM amount/prepared-byte operands and implicit SP effects"); bool HasArgumentUse = false; bool HasResultDef = false; for (const rcc::MachineOperand &Operand : Call->operands()) { |
