From d62f022c92fcc3ebe2269273628943a0089683fd Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Thu, 13 Aug 2026 06:19:30 +0800 Subject: [CodeGen] Align MIR parser and printer ownership --- backend/lib/MIR/MIRDocumentParser.cpp | 398 ---------------------------------- 1 file changed, 398 deletions(-) delete mode 100644 backend/lib/MIR/MIRDocumentParser.cpp (limited to 'backend/lib/MIR/MIRDocumentParser.cpp') diff --git a/backend/lib/MIR/MIRDocumentParser.cpp b/backend/lib/MIR/MIRDocumentParser.cpp deleted file mode 100644 index 08627d5..0000000 --- a/backend/lib/MIR/MIRDocumentParser.cpp +++ /dev/null @@ -1,398 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later - -#include "MIRDocumentParser.h" - -#include "MIRDocumentReferenceValidation.h" -#include "MIRMetadataTextParser.h" -#include "MIRParserUtilities.h" -#include "rcc/CodeGen/MachineBasicBlock.h" -#include "rcc/CodeGen/MachineConstantPool.h" -#include "rcc/CodeGen/MachineFrameInfo.h" -#include "rcc/CodeGen/MachineFunction.h" -#include "rcc/CodeGen/MachineFunctionAttributes.h" -#include "rcc/CodeGen/MachineFunctionProperties.h" -#include "rcc/CodeGen/MachineFunctionRecords.h" -#include "rcc/CodeGen/MachineInstr.h" -#include "rcc/CodeGen/MachineJumpTableInfo.h" -#include "rcc/CodeGen/MachineMetadata.h" -#include "rcc/CodeGen/MachineRegisterInfo.h" -#include "rcc/CodeGen/MachineVerifier.h" -#include "rcc/CodeGen/TargetDescription.h" -#include "rcc/CodeGen/TargetMIRTextInfo.h" -#include "rcc/CodeGen/TargetRegisterInfo.h" -#include "rcc/MIR/LLVMConstantSyntax.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace rcc::mir { - -using parser_detail::parseBool; -using parser_detail::parsePrefixedID; -using parser_detail::parseSigned; -using parser_detail::parseUnsigned; -using parser_detail::parseUnsigned32; -using parser_detail::trim; - -bool MIRDocumentParser::fail(const TextRange &Range, std::string Message, std::string Category) { - if (Result.Diagnostics.empty()) { - Result.Diagnostics.push_back(TextDiagnostic{ - .Severity = DiagnosticSeverity::Error, - .Category = std::move(Category), - .Message = std::move(Message), - .SourceName = std::string(Result.Source.name()), - .Range = Range, - }); - } - return true; -} - -bool MIRDocumentParser::importError(const TextRange &Range, const Error &Failure, - std::string Category) { - return fail(Range, std::string(Failure.message()), std::move(Category)); -} - -const yaml::Node *MIRDocumentParser::mappingValue(const yaml::Node &Mapping, - std::string_view Key) const noexcept { - const auto Value = Mapping.mappingValue(Key); - return Value ? node(*Value) : nullptr; -} - -std::string_view MIRDocumentParser::effectiveDataLayout() const noexcept { - if (!Options.DataLayout.empty()) - return Options.DataLayout; - if (ActiveDocument != nullptr) { - if (const EmbeddedIRReferenceIndex *Embedded = ActiveDocument->embeddedIR()) { - if (const auto DataLayout = Embedded->dataLayout()) - return *DataLayout; - } - } - return {}; -} - -LLVMConstantSyntaxOptions MIRDocumentParser::pointerLayoutOptions() const noexcept { - return { - .DataLayout = effectiveDataLayout(), - .NamedTypes = {}, - }; -} - -bool MIRDocumentParser::requireKind(const yaml::Node &Node, yaml::NodeKind Kind, - std::string_view Description) { - if (Node.kind() == Kind) - return false; - return fail(Node.range(), std::string(Description) + " has the wrong YAML node kind"); -} - -bool MIRDocumentParser::validateKeys(const yaml::Node &Mapping, - std::span Keys, - std::string_view Description) { - for (const yaml::MappingEntry &Entry : Mapping.mapping()) { - if (std::ranges::find(Keys, Entry.Key) == Keys.end()) { - return fail(Entry.KeyRange, - "unknown " + std::string(Description) + " key '" + Entry.Key + "'"); - } - } - return false; -} - -bool MIRDocumentParser::scalar(const yaml::Node &Node, std::string_view &Value, - std::string_view Description) { - if (requireKind(Node, yaml::NodeKind::Scalar, Description)) - return true; - Value = Node.scalar(); - return false; -} - -bool MIRDocumentParser::boolean(const yaml::Node &Node, bool &Value) { - std::string_view Text; - if (scalar(Node, Text, "boolean") || !parseBool(Text, Value)) - return fail(Node.range(), "expected 'true' or 'false'"); - return false; -} - -bool MIRDocumentParser::unsignedValue(const yaml::Node &Node, std::uint64_t &Value, - std::string_view Description) { - std::string_view Text; - if (scalar(Node, Text, Description) || !parseUnsigned(Text, Value)) - return fail(Node.range(), "expected " + std::string(Description)); - return false; -} - -bool MIRDocumentParser::signedValue(const yaml::Node &Node, std::int64_t &Value, - std::string_view Description) { - std::string_view Text; - if (scalar(Node, Text, Description) || !parseSigned(Text, Value)) - return fail(Node.range(), "expected " + std::string(Description)); - return false; -} - -bool MIRDocumentParser::alignment(const yaml::Node &Node, Alignment &Value, bool AllowZero) { - std::uint64_t Bytes = 0; - if (unsignedValue(Node, Bytes, "an unsigned alignment")) - return true; - if (Bytes == 0 && AllowZero) { - Value = Alignment{}; - return false; - } - auto Parsed = Alignment::create(Bytes); - if (!Parsed) - return importError(Node.range(), Parsed.error()); - Value = *Parsed; - return false; -} - -bool MIRDocumentParser::physicalRegister(std::string_view Text, const TextRange &Range, - PhysicalRegister &Reg) { - Text = trim(Text); - if (!Text.starts_with('$') || Text.size() == 1) - return fail(Range, "physical register must use the '$name' MIR spelling"); - const PhysicalRegisterDesc *Description = Target.registers().physicalRegister(Text.substr(1)); - if (Description == nullptr) - return fail(Range, "unknown physical register '" + std::string(Text) + "'"); - Reg = Description->Reg; - return false; -} - -bool MIRDocumentParser::physicalRegister(const yaml::Node &Node, PhysicalRegister &Reg) { - std::string_view Text; - return scalar(Node, Text, "physical register") || physicalRegister(Text, Node.range(), Reg); -} - -bool MIRDocumentParser::virtualRegister(std::string_view Text, const TextRange &Range, - MachineFunction &Function, MIParserContext &Context, - Register &Reg) { - const auto ID = parsePrefixedID(Text, "%"); - if (!ID) - return fail(Range, "virtual register must use the '%N' MIR spelling"); - auto Found = - std::ranges::find_if(Context.VirtualRegisters, - [ID](const MIVirtualRegisterSlot &Slot) { return Slot.TextID == *ID; }); - if (Found == Context.VirtualRegisters.end()) { - auto Created = Function.registerInfo().createVirtualRegister(); - if (!Created) - return importError(Range, Created.error()); - Context.VirtualRegisters.push_back({*ID, *Created}); - Reg = *Created; - return false; - } - Reg = Found->Reg; - return false; -} - -MIRDocumentParseResult MIRDocumentParser::run() { - yaml::ParseResult YAMLResult = yaml::parse(std::string(Result.Source.name()), - std::string(Result.Source.text()), Options.YAML); - if (!YAMLResult.succeeded()) { - const auto Diagnostics = YAMLResult.diagnostics(); - Result.Diagnostics.assign(Diagnostics.begin(), Diagnostics.end()); - return std::move(Result); - } - Stream = YAMLResult.stream(); - if (Stream == nullptr || Stream->documents().empty()) { - static_cast(fail(Result.Source.range(0, 0), "MIR stream contains no YAML documents")); - return std::move(Result); - } - - MIRDocument Staging; - ActiveDocument = &Staging; - const auto IsEmptyDocument = [this](std::size_t Index) { - const yaml::Node *Root = node(Stream->documents()[Index].Root); - return Root != nullptr && Root->kind() == yaml::NodeKind::Null && - Root->range().Begin.Offset == Root->range().End.Offset; - }; - std::size_t FirstContent = 0; - while (FirstContent < Stream->documents().size() && IsEmptyDocument(FirstContent)) - ++FirstContent; - if (FirstContent == Stream->documents().size()) { - static_cast(fail(Stream->documents().front().Range, - "MIR stream must contain at least one machine function document")); - return std::move(Result); - } - - std::size_t FirstFunction = FirstContent; - const yaml::Node *FirstRoot = node(Stream->documents()[FirstContent].Root); - if (FirstRoot != nullptr && FirstRoot->kind() == yaml::NodeKind::Scalar) { - EmbeddedIRIndexResult Embedded = indexEmbeddedIR( - std::string(Result.Source.name()) + ":embedded-ir", std::string(FirstRoot->scalar())); - if (!Embedded.succeeded()) { - const auto Diagnostics = Embedded.diagnostics(); - if (Diagnostics.empty()) { - static_cast( - fail(FirstRoot->range(), "embedded LLVM IR indexing failed", "mir-embedded-ir")); - } else { - const TextDiagnostic &Diagnostic = Diagnostics.front(); - const TextRange Range = scalarDiagnosticRange(*FirstRoot, Diagnostic.Range); - static_cast(fail(Range, Diagnostic.Message, Diagnostic.Category)); - } - return std::move(Result); - } - Staging.EmbeddedIR = std::move(Embedded).takeIndex(); - FirstFunction = FirstContent + 1; - } - - if (!effectiveDataLayout().empty()) { - auto PointerSize = llvmPointerSizeInBits(0, pointerLayoutOptions()); - if (!PointerSize) { - static_cast(importError(Stream->documents()[FirstContent].Range, PointerSize.error(), - "mir-data-layout")); - return std::move(Result); - } - } - - bool SawFunction = false; - for (std::size_t Index = FirstFunction; Index < Stream->documents().size(); ++Index) { - if (IsEmptyDocument(Index)) - continue; - const yaml::Node *Root = node(Stream->documents()[Index].Root); - if (Root == nullptr || requireKind(*Root, yaml::NodeKind::Mapping, "machine function") || - parseFunction(*Root, Staging)) { - return std::move(Result); - } - SawFunction = true; - } - if (!SawFunction) { - static_cast(fail(Stream->documents()[FirstContent].Range, - "MIR stream must contain at least one machine function document")); - return std::move(Result); - } - - auto UnitResult = Staging.Unit.verify(); - if (!UnitResult) { - static_cast( - fail(Stream->documents().back().Range, "parsed compilation unit failed verification: " + - std::string(UnitResult.error().message()))); - return std::move(Result); - } - ActiveDocument = nullptr; - Result.Document = std::move(Staging); - return std::move(Result); -} - -bool MIRDocumentParser::parseFunction(const yaml::Node &Root, MIRDocument &Document) { - constexpr std::array Keys{ - std::string_view{"name"}, - std::string_view{"alignment"}, - std::string_view{"exposesReturnsTwice"}, - std::string_view{"legalized"}, - std::string_view{"regBankSelected"}, - std::string_view{"selected"}, - std::string_view{"failedISel"}, - std::string_view{"tracksRegLiveness"}, - std::string_view{"hasWinCFI"}, - std::string_view{"noPhis"}, - std::string_view{"isSSA"}, - std::string_view{"noVRegs"}, - std::string_view{"hasFakeUses"}, - std::string_view{"callsEHReturn"}, - std::string_view{"callsUnwindInit"}, - std::string_view{"hasEHContTarget"}, - std::string_view{"hasEHScopes"}, - std::string_view{"hasEHFunclets"}, - std::string_view{"isOutlined"}, - std::string_view{"debugInstrRef"}, - std::string_view{"failsVerification"}, - std::string_view{"tracksDebugUserValues"}, - std::string_view{"registers"}, - std::string_view{"liveins"}, - std::string_view{"calleeSavedRegisters"}, - std::string_view{"frameInfo"}, - std::string_view{"fixedStack"}, - std::string_view{"stack"}, - std::string_view{"entry_values"}, - std::string_view{"callSites"}, - std::string_view{"debugValueSubstitutions"}, - std::string_view{"constants"}, - std::string_view{"machineFunctionInfo"}, - std::string_view{"jumpTable"}, - std::string_view{"machineMetadataNodes"}, - std::string_view{"calledGlobals"}, - std::string_view{"prefetch-targets"}, - std::string_view{"body"}, - }; - const yaml::Node *NameNode = mappingValue(Root, "name"); - if (NameNode == nullptr) - return fail(Root.range(), "missing required key 'name'"); - if (validateKeys(Root, Keys, "machine function")) - return true; - std::string_view Name; - if (scalar(*NameNode, Name, "machine function name")) - return true; - - const EmbeddedIRFunction *IRFunction = nullptr; - if (Document.EmbeddedIR) { - if (Name.empty()) { - std::size_t AnonymousOrdinal = 0; - for (std::size_t Index = 0; Index < Document.Unit.functionCount(); ++Index) { - const MachineFunction *Existing = Document.Unit.functionAt(Index); - if (Existing != nullptr && Existing->name().empty()) - ++AnonymousOrdinal; - } - IRFunction = Document.EmbeddedIR->unnamedFunction(AnonymousOrdinal); - } else { - IRFunction = Document.EmbeddedIR->function(Name); - } - if (IRFunction == nullptr) - return fail(NameNode->range(), - "function '" + std::string(Name) + "' isn't defined in the provided LLVM IR"); - } - - if (!Name.empty() && Document.Unit.function(Name) != nullptr) - return fail(NameNode->range(), "redefinition of machine function '" + std::string(Name) + "'"); - - auto Created = Document.Unit.createMachineFunction(std::string(Name)); - if (!Created) - return importError(NameNode->range(), Created.error()); - MachineFunction &Function = **Created; - ActiveFunction = &Function; - - MIRFunctionDocumentInfo DocumentInfo{ - .Function = Function.stableID(), - .NoPHIs = std::nullopt, - .IsSSA = std::nullopt, - .NoVRegs = std::nullopt, - .HasFakeUses = std::nullopt, - }; - MIParserContext Context; - if (IRFunction != nullptr) { - Context.HasIRBlock = [IRFunction](std::string_view BlockName) { - return IRFunction->block(BlockName) != nullptr; - }; - } - - std::vector PendingJumpTables; - if (parseFunctionScalars(Root, Function, DocumentInfo) || - parseMetadata(Root, Function, Context) || parseRegisters(Root, Function, Context) || - parseStackObjects(Root, Function, Context) || parseConstants(Root, Function, Context) || - reserveJumpTables(Root, Function, Context, PendingJumpTables) || - parseBody(Root, Function, Context) || defineJumpTables(Function, PendingJumpTables) || - parseFrameState(Root, Function, Context) || - recomputeProperties(Root, Function, DocumentInfo) || parseTargetState(Root, Function) || - parseFunctionRecords(Root, Function) || validateDocumentReferences(Function)) { - return true; - } - - if (Options.VerifyMachineFunctions) { - auto Verified = MachineVerifier::verify(Function, Target); - if (!Verified) - return importError(Root.range(), Verified.error(), "mir-verifier"); - } - Document.FunctionInfo.push_back(DocumentInfo); - ActiveFunction = nullptr; - return false; -} - -} // namespace rcc::mir -- cgit v1.2.3