From da8bc76b4bf7d1a7b025d6c8ef5809551467dcc7 Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Sun, 9 Aug 2026 13:23:48 +0800 Subject: [CodeGen] Implement RV64GC frame lowering --- .../lib/Target/RISCV/RISCVRegisterAllocation.cpp | 84 ++++++++++++++++++++++ 1 file changed, 84 insertions(+) (limited to 'backend/lib/Target/RISCV/RISCVRegisterAllocation.cpp') diff --git a/backend/lib/Target/RISCV/RISCVRegisterAllocation.cpp b/backend/lib/Target/RISCV/RISCVRegisterAllocation.cpp index e437e18..81fc6dc 100644 --- a/backend/lib/Target/RISCV/RISCVRegisterAllocation.cpp +++ b/backend/lib/Target/RISCV/RISCVRegisterAllocation.cpp @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later #include "rcc/CodeGen/InstructionDescriptor.h" +#include "rcc/CodeGen/MachineBasicBlock.h" #include "rcc/CodeGen/MachineFunction.h" #include "rcc/CodeGen/MachineIRBuilder.h" #include "rcc/CodeGen/MachineInstr.h" @@ -13,6 +14,7 @@ #include #include +#include #include #include #include @@ -35,6 +37,20 @@ struct SpillForm final { return RegisterClassID::fromValue(static_cast(Value)); } +[[nodiscard]] std::optional immediateValue(const MachineOperand &Operand) noexcept { + if (const auto *Immediate = Operand.getIf()) + return *Immediate; + const auto *Integer = Operand.getIf(); + if (Integer == nullptr || Integer->Value.bitWidth() == 0 || Integer->Value.bitWidth() > 64) { + return std::nullopt; + } + std::uint64_t Raw = Integer->Value.words().empty() ? 0 : Integer->Value.words().front(); + const std::uint32_t Width = Integer->Value.bitWidth(); + if (Width < 64 && (Raw & (std::uint64_t{1} << (Width - 1U))) != 0) + Raw |= ~std::uint64_t{0} << Width; + return std::bit_cast(Raw); +} + [[nodiscard]] constexpr std::optional spillForm(RegisterClassID Class) noexcept { if (Class == registerClassID(RegisterClass::GPR) || Class == registerClassID(RegisterClass::GPRC) || @@ -102,6 +118,74 @@ createStackMemoryOperand(MachineIRBuilder &Builder, FrameIndex StackSlot, Memory class RISCVRegisterAllocationInfo final : public TargetRegisterAllocationInfo { public: + [[nodiscard]] bool + isReservedForFunction(const MachineFunction &Function, PhysicalRegister Reg, + const TargetDescription &Target) const noexcept override { + std::uint64_t RequiredAlignment = 16; + RequiredAlignment = std::max( + RequiredAlignment, Function.frameInfo().state().MaxAlignment.value_or(Alignment{}).bytes()); + for (const StackObject &Object : Function.frameInfo().objects()) { + if (!Object.isTombstone() && !Object.description()->IsDead) { + RequiredAlignment = std::max(RequiredAlignment, 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; + const auto Requested = immediateValue(*Instruction->operandAt(1)); + if (Requested && *Requested > 0 && + std::has_single_bit(static_cast(*Requested))) { + RequiredAlignment = std::max(RequiredAlignment, static_cast(*Requested)); + } + } + } + const bool RequiresRealignment = RequiredAlignment > 16; + if (Reg.number() == static_cast(PhysicalRegisterID::X9)) + return RequiresRealignment; + if (Reg.number() != static_cast(PhysicalRegisterID::X8)) + return false; + const MachineFrameState &State = Function.frameInfo().state(); + bool HasCalls = State.HasCalls; + for (const MachineBasicBlock *Block = Function.firstBlock(); Block != nullptr && !HasCalls; + Block = Block->next()) { + for (const MachineInstr *Instruction = Block->firstInstruction(); Instruction != nullptr; + Instruction = Instruction->next()) { + const InstructionDescriptor *Descriptor = + Target.instructionDescriptor(Instruction->opcode()); + if (Descriptor != nullptr && Descriptor->Flags.has(InstructionFlag::Call)) { + HasCalls = true; + break; + } + } + } + const bool HasVariableObject = + std::ranges::any_of(Function.frameInfo().objects(), [](const StackObject &Object) { + return !Object.isTombstone() && !Object.description()->IsDead && Object.isVariableSized(); + }); + if (State.IsFrameAddressTaken || State.HasOpaqueSPAdjustment || HasVariableObject || + RequiresRealignment) + return true; + switch (State.FramePointerPolicy) { + case MachineFramePointerPolicy::All: + case MachineFramePointerPolicy::Reserved: + return true; + case MachineFramePointerPolicy::NonLeaf: + case MachineFramePointerPolicy::NonLeafNoReserve: + return HasCalls; + case MachineFramePointerPolicy::None: + case MachineFramePointerPolicy::Count: + return false; + } + return false; + } + [[nodiscard]] Expected validateSpillReload(RegisterClassID Class, const TargetDescription &Target) const override { const RegisterClassDesc *Description = Target.registers().registerClass(Class); -- cgit v1.2.3