From 551f0b3fcd6f797ed6dca90f39123b0359396dcb Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Tue, 11 Aug 2026 20:08:36 +0800 Subject: [RISCV] Match LLVM call-frame pseudo semantics --- backend/lib/Target/RISCV/RISCVFrameLowering.cpp | 46 +++++++++---------------- 1 file changed, 17 insertions(+), 29 deletions(-) (limited to 'backend/lib/Target/RISCV/RISCVFrameLowering.cpp') diff --git a/backend/lib/Target/RISCV/RISCVFrameLowering.cpp b/backend/lib/Target/RISCV/RISCVFrameLowering.cpp index e47a9c8..4ba5540 100644 --- a/backend/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/backend/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -102,29 +102,33 @@ constexpr std::uint8_t DwarfOpBaseRegisterExtended = 0x92U; struct CallFrameRequirement final { std::int64_t Amount = 0; - std::int64_t Alignment = 0; + std::int64_t PreparedBytes = 0; std::int64_t AlignedAmount = 0; }; [[nodiscard]] Expected callFrameRequirement(const MachineInstr &Instruction) { - if (Instruction.operandCount() != 2) { + if (Instruction.operandCount() < 2) { return makeUnexpected(ErrorCode::VerificationError, - "RISC-V call-frame pseudo requires exactly amount and alignment"); + "RISC-V call-frame pseudo requires amount and prepared-byte operands"); + } + for (std::size_t Index = 2; Index < Instruction.operandCount(); ++Index) { + const MachineOperand *Operand = Instruction.operandAt(Index); + if (Operand == nullptr || !Operand->isRegister() || !Operand->isImplicit()) { + return makeUnexpected(ErrorCode::VerificationError, + "RISC-V call-frame pseudo has an unexpected explicit operand"); + } } auto Amount = immediateValue(*Instruction.operandAt(0)); - auto RequestedAlignment = immediateValue(*Instruction.operandAt(1)); - if (!Amount || !RequestedAlignment || *Amount < 0 || *RequestedAlignment <= 0 || - !std::has_single_bit(static_cast(*RequestedAlignment))) { + auto PreparedBytes = immediateValue(*Instruction.operandAt(1)); + if (!Amount || !PreparedBytes || *Amount < 0 || *PreparedBytes < 0) { return makeUnexpected(ErrorCode::VerificationError, - "RISC-V call-frame amount or alignment is invalid"); + "RISC-V call-frame amount or prepared-byte count is invalid"); } - const std::uint64_t Alignment = - std::max(StackAlignmentBytes, static_cast(*RequestedAlignment)); - auto Aligned = alignTo(static_cast(*Amount), Alignment); + auto Aligned = alignTo(static_cast(*Amount), StackAlignmentBytes); if (!Aligned || *Aligned > static_cast(std::numeric_limits::max())) { return makeUnexpected(ErrorCode::FrameLayoutFailed, "RISC-V call-frame amount is too large"); } - return CallFrameRequirement{*Amount, *RequestedAlignment, static_cast(*Aligned)}; + return CallFrameRequirement{*Amount, *PreparedBytes, static_cast(*Aligned)}; } [[nodiscard]] Expected callFrameAmount(const MachineInstr &Instruction) { @@ -148,23 +152,6 @@ struct CallFrameRequirement final { if (!Object.isTombstone() && !Object.description()->IsDead) Result = std::max(Result, Object.description()->Align.bytes()); } - for (const MachineBasicBlock *Block = Function.firstBlock(); Block != nullptr; - Block = Block->next()) { - for (const MachineInstr *Instruction = Block->firstInstruction(); Instruction != nullptr; - Instruction = Instruction->next()) { - if (Instruction->opcode() != targetOpcode(InstructionOpcode::ADJCALLSTACKDOWN) && - Instruction->opcode() != targetOpcode(InstructionOpcode::ADJCALLSTACKUP)) { - continue; - } - if (Instruction->operandCount() < 2) - continue; - auto Requested = immediateValue(*Instruction->operandAt(1)); - if (Requested && *Requested > 0 && - std::has_single_bit(static_cast(*Requested))) { - Result = std::max(Result, static_cast(*Requested)); - } - } - } return Result; } @@ -314,7 +301,8 @@ struct CallFrameRequirement final { return makeUnexpected(ErrorCode::VerificationError, "RISC-V call-frame destroy has no matching setup"); } - if (Active->Amount != Requirement->Amount || Active->Alignment != Requirement->Alignment) { + if (Active->Amount != Requirement->Amount || + Active->PreparedBytes != Requirement->PreparedBytes) { return makeUnexpected(ErrorCode::VerificationError, "RISC-V call-frame setup and destroy requirements differ"); } -- cgit v1.2.3