From 379ff50dcc7ccf977379aee68fa9d10f69065d23 Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Sun, 9 Aug 2026 18:31:49 +0800 Subject: [MC] Implement RV64GC assembly emission --- backend/lib/AsmPrinter/MachineMCContext.cpp | 153 ++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 backend/lib/AsmPrinter/MachineMCContext.cpp (limited to 'backend/lib/AsmPrinter/MachineMCContext.cpp') diff --git a/backend/lib/AsmPrinter/MachineMCContext.cpp b/backend/lib/AsmPrinter/MachineMCContext.cpp new file mode 100644 index 0000000..163e228 --- /dev/null +++ b/backend/lib/AsmPrinter/MachineMCContext.cpp @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "rcc/CodeGen/MachineMCContext.h" + +#include "rcc/CodeGen/CompilationUnit.h" +#include "rcc/CodeGen/GlobalObject.h" +#include "rcc/CodeGen/MachineBasicBlock.h" +#include "rcc/CodeGen/MachineConstantPool.h" +#include "rcc/CodeGen/MachineFunction.h" +#include "rcc/CodeGen/MachineJumpTableInfo.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace rcc { + +std::size_t MachineMCContext::FunctionIndexHash::operator()(FunctionIndexKey Key) const noexcept { + const std::size_t FunctionHash = std::hash{}(Key.Function); + const std::size_t IndexHash = std::hash{}(Key.Index); + return FunctionHash ^ (IndexHash + 0x9e3779b9U + (FunctionHash << 6U) + (FunctionHash >> 2U)); +} + +Expected MachineMCContext::initialize(const CompilationUnit &Unit) { + auto Verification = Unit.verify(); + if (!Verification) + return std::unexpected(Verification.error()); + for (std::size_t Index = 0; Index < Unit.globalObjectCount(); ++Index) { + const GlobalObjectDesc *Object = Unit.globalObjectAt(Index); + if (Object == nullptr) + return makeUnexpected(ErrorCode::InternalError, "compilation unit contains a null global"); + auto Symbol = Context->getOrCreateSymbol(Object->Symbol, mc::MCSymbolKind::Object); + if (!Symbol) + return std::unexpected(Symbol.error()); + GlobalSymbols.emplace(Object, std::move(*Symbol)); + } + for (std::size_t Index = 0; Index < Unit.functionCount(); ++Index) { + const MachineFunction *Function = Unit.functionAt(Index); + if (Function == nullptr) + return makeUnexpected(ErrorCode::InternalError, "compilation unit contains a null function"); + auto Initialized = initializeFunction(*Function); + if (!Initialized) + return std::unexpected(Initialized.error()); + } + return {}; +} + +Expected MachineMCContext::initializeFunction(const MachineFunction &Function) { + if (FunctionSymbols.contains(&Function)) + return {}; + + auto FunctionSymbol = + Context->getOrCreateSymbol(std::string(Function.name()), mc::MCSymbolKind::Function); + if (!FunctionSymbol) + return std::unexpected(FunctionSymbol.error()); + FunctionSymbols.emplace(&Function, *FunctionSymbol); + + for (const MachineBasicBlock *Block = Function.firstBlock(); Block != nullptr; + Block = Block->next()) { + const std::optional DenseNumber = Block->denseNumber(); + if (!Block->isLinked() || !DenseNumber) { + return makeUnexpected(ErrorCode::AssemblyLoweringFailed, + "MC symbol initialization requires linked and numbered blocks"); + } + const std::string Name = + ".LBB" + std::to_string(Function.stableID().value()) + "_" + std::to_string(*DenseNumber); + auto Symbol = Context->getOrCreateSymbol(Name, mc::MCSymbolKind::BasicBlock); + if (!Symbol) + return std::unexpected(Symbol.error()); + BlockSymbols.emplace(Block, *Symbol); + } + + for (const MachineConstantPoolEntry &Entry : Function.constantPool().entries()) { + if (Entry.isTombstone()) + continue; + const std::string Name = ".LCPI" + std::to_string(Function.stableID().value()) + "_" + + std::to_string(Entry.index().value()); + auto Symbol = Context->getOrCreateSymbol(Name, mc::MCSymbolKind::ConstantPool); + if (!Symbol) + return std::unexpected(Symbol.error()); + ConstantPoolSymbols.emplace( + FunctionIndexKey{.Function = &Function, .Index = Entry.index().value()}, *Symbol); + } + + for (const MachineJumpTableEntry &Entry : Function.jumpTableInfo().tables()) { + if (Entry.isTombstone() || Entry.isPending()) + continue; + const std::string Name = ".LJTI" + std::to_string(Function.stableID().value()) + "_" + + std::to_string(Entry.index().value()); + auto Symbol = Context->getOrCreateSymbol(Name, mc::MCSymbolKind::JumpTable); + if (!Symbol) + return std::unexpected(Symbol.error()); + JumpTableSymbols.emplace( + FunctionIndexKey{.Function = &Function, .Index = Entry.index().value()}, *Symbol); + } + return {}; +} + +mc::MCSymbolRef MachineMCContext::functionSymbol(const MachineFunction &Function) const noexcept { + const auto Position = FunctionSymbols.find(&Function); + return Position == FunctionSymbols.end() ? mc::MCSymbolRef{} : Position->second; +} + +mc::MCSymbolRef MachineMCContext::globalSymbol(const GlobalObjectDesc &Object) const noexcept { + const auto Position = GlobalSymbols.find(&Object); + return Position == GlobalSymbols.end() ? mc::MCSymbolRef{} : Position->second; +} + +mc::MCSymbolRef MachineMCContext::blockSymbol(const MachineBasicBlock &Block) const noexcept { + const auto Position = BlockSymbols.find(&Block); + return Position == BlockSymbols.end() ? mc::MCSymbolRef{} : Position->second; +} + +mc::MCSymbolRef MachineMCContext::constantPoolSymbol(const MachineFunction &Function, + ConstantPoolIndex Index) const noexcept { + const auto Position = + ConstantPoolSymbols.find(FunctionIndexKey{.Function = &Function, .Index = Index.value()}); + return Position == ConstantPoolSymbols.end() ? mc::MCSymbolRef{} : Position->second; +} + +mc::MCSymbolRef MachineMCContext::jumpTableSymbol(const MachineFunction &Function, + JumpTableIndex Index) const noexcept { + const auto Position = + JumpTableSymbols.find(FunctionIndexKey{.Function = &Function, .Index = Index.value()}); + return Position == JumpTableSymbols.end() ? mc::MCSymbolRef{} : Position->second; +} + +Expected MachineMCContext::symbol(std::string Name, mc::MCSymbolKind Kind) { + return Context->getOrCreateSymbol(std::move(Name), Kind); +} + +Expected MachineMCContext::blockAddressSymbol(std::string_view FunctionName, + std::string_view BlockName) const { + for (const auto &[Block, Symbol] : BlockSymbols) { + if (Block == nullptr || Block->function().name() != FunctionName) + continue; + const auto IRName = Block->attributes().irBlockName(); + const auto MachineName = Block->attributes().name(); + const bool NumericMatch = + Block->denseNumber() && std::to_string(*Block->denseNumber()) == BlockName; + if ((IRName && *IRName == BlockName) || (MachineName && *MachineName == BlockName) || + NumericMatch) + return Symbol; + } + return makeUnexpected(ErrorCode::AssemblyLoweringFailed, + "block-address operand does not resolve to an emitted block symbol"); +} + +} // namespace rcc -- cgit v1.2.3