From 36c4344ddf1866005c62910166ca077bf2e8f62e Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Wed, 26 Aug 2026 17:38:21 +0800 Subject: [CodeGen] Implement RISC-V finalize-isel --- backend/lib/CodeGen/CMakeLists.txt | 2 + backend/lib/CodeGen/FinalizeISel.cpp | 101 +++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 backend/lib/CodeGen/FinalizeISel.cpp (limited to 'backend/lib/CodeGen') diff --git a/backend/lib/CodeGen/CMakeLists.txt b/backend/lib/CodeGen/CMakeLists.txt index 795fb40..a7a0586 100644 --- a/backend/lib/CodeGen/CMakeLists.txt +++ b/backend/lib/CodeGen/CMakeLists.txt @@ -8,6 +8,7 @@ set( GlobalObject.cpp GenericOpcodes.cpp FrameIndexElimination.cpp + FinalizeISel.cpp InstructionDescriptor.cpp LowLevelType.cpp MachineBasicBlockAttributes.cpp @@ -100,6 +101,7 @@ set( "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/GlobalObject.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/GenericOpcodes.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/FrameIndexElimination.h" + "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/FinalizeISel.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/InstructionDescriptor.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/InlineAsm.h" "${RCC_BACKEND_SOURCE_DIR}/include/rcc/CodeGen/LowLevelType.h" diff --git a/backend/lib/CodeGen/FinalizeISel.cpp b/backend/lib/CodeGen/FinalizeISel.cpp new file mode 100644 index 0000000..9b5c11f --- /dev/null +++ b/backend/lib/CodeGen/FinalizeISel.cpp @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rcc/CodeGen/FinalizeISel.h" + +#include "rcc/CodeGen/InstructionDescriptor.h" +#include "rcc/CodeGen/MachineBasicBlock.h" +#include "rcc/CodeGen/MachineFrameInfo.h" +#include "rcc/CodeGen/MachineFunction.h" +#include "rcc/CodeGen/MachineInstr.h" +#include "rcc/CodeGen/TargetDescription.h" + +#include + +namespace rcc { +namespace { + +[[nodiscard]] const MachinePassContract &finalizeISelContract() { + static const MachinePassContract Contract = [] { + MachinePassContract Value{ + .Name = "finalize-isel", + .Requires = {}, + .Sets = {}, + .Clears = {}, + .RequiredAnalyses = {}, + .VerificationStage = PipelineStage::Selected, + }; + Value.ThreadSafety = PassThreadSafety::ThreadSafe; + Value.DeclaredChanges = {MachinePassChange::Instructions, MachinePassChange::Operands, + MachinePassChange::CFG, MachinePassChange::BlockLayout, + MachinePassChange::Frame}; + return Value; + }(); + return Contract; +} + +} // namespace + +const MachinePassContract &FinalizeISelPass::contract() const noexcept { + return finalizeISelContract(); +} + +Expected FinalizeISelPass::run(MachineFunction &Function, + const TargetDescription &Target, + MachineFunctionAnalysisManager &) { + MachinePassResult Result; + MachineBasicBlock *Block = Function.firstBlock(); + while (Block != nullptr) { + MachineInstr *Instruction = Block->firstInstruction(); + while (Instruction != nullptr) { + MachineInstr *Next = Instruction->next(); + const InstructionDescriptor *Descriptor = Target.instructionDescriptor(Instruction->opcode()); + if (Descriptor == nullptr) { + return makeUnexpected(ErrorCode::VerificationError, + "finalize-isel encountered an unknown opcode"); + } + + if (Instruction->flags().has(MachineInstrFlag::FrameSetup) || + Instruction->flags().has(MachineInstrFlag::FrameDestroy)) { + MachineFrameState State = Function.frameInfo().state(); + if (!State.AdjustsStack) { + State.AdjustsStack = true; + auto Updated = Function.frameInfo().setState(std::move(State)); + if (!Updated) + return std::unexpected(Updated.error()); + Result.Changes.add(MachinePassChange::Frame); + } + } + + if (!Descriptor->Flags.has(InstructionFlag::UsesCustomInserter)) { + Instruction = Next; + continue; + } + + auto Expanded = Info->emitInstrWithCustomInserter(*Instruction, *Block, Function, Target); + if (!Expanded) + return std::unexpected(Expanded.error()); + if (*Expanded == nullptr || &(*Expanded)->function() != &Function) { + return makeUnexpected(ErrorCode::InternalError, + "custom inserter returned an invalid basic block"); + } + + Result.Changes.add(MachinePassChange::Instructions); + Result.Changes.add(MachinePassChange::Operands); + if (*Expanded != Block) { + Result.Changes.add(MachinePassChange::CFG); + Result.Changes.add(MachinePassChange::BlockLayout); + Block = *Expanded; + Instruction = Block->firstInstruction(); + } else { + Instruction = Next; + } + } + Block = Block->next(); + } + + Result.Changed = !Result.Changes.empty(); + Result.Preserved = Result.Changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); + return Result; +} + +} // namespace rcc -- cgit v1.2.3