From 76d89700953ddd81cf31ab8f260eddf67e93aa85 Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Fri, 7 Aug 2026 01:27:41 +0800 Subject: [MIR] Complete document parsing and printing Implement the single LLVM-compatible MIR document path with structured\nembedded-IR references, YAML mappings, constants, and deterministic printing.\n\nKeep pointer LLT widths DataLayout-derived, reject layout-dependent output\nwhen embedded IR is omitted, and record the fixed-baseline compatibility\ncontract and regression coverage. --- backend/include/rcc/MIR/EmbeddedIR.h | 39 +++++++- backend/include/rcc/MIR/LLVMConstantSyntax.h | 52 ++++++++++ backend/include/rcc/MIR/MIDebugSyntax.h | 17 ++++ backend/include/rcc/MIR/MIParser.h | 12 +++ backend/include/rcc/MIR/MIRDocument.h | 143 +++++++++++++++++++++++++++ 5 files changed, 260 insertions(+), 3 deletions(-) create mode 100644 backend/include/rcc/MIR/LLVMConstantSyntax.h create mode 100644 backend/include/rcc/MIR/MIDebugSyntax.h create mode 100644 backend/include/rcc/MIR/MIRDocument.h (limited to 'backend/include/rcc/MIR') diff --git a/backend/include/rcc/MIR/EmbeddedIR.h b/backend/include/rcc/MIR/EmbeddedIR.h index 8e9e0f6..50567de 100644 --- a/backend/include/rcc/MIR/EmbeddedIR.h +++ b/backend/include/rcc/MIR/EmbeddedIR.h @@ -24,6 +24,20 @@ struct EmbeddedIRReference final { TextRange Range; }; +struct EmbeddedIRMetadataDefinition final { + std::string Name; + TextRange Range; + std::string DynamicType; +}; + +struct EmbeddedIRTypeDefinition final { + std::string Name; + TextRange Range; + std::string Definition; + TextRange DefinitionRange; + bool NumericName = false; +}; + class EmbeddedIRFunction final { public: [[nodiscard]] std::string_view name() const noexcept { @@ -46,8 +60,13 @@ public: return Allocas; } + [[nodiscard]] std::span values() const noexcept { + return Values; + } + [[nodiscard]] const EmbeddedIRReference *block(std::string_view QueryName) const noexcept; [[nodiscard]] const EmbeddedIRReference *alloca(std::string_view QueryName) const noexcept; + [[nodiscard]] const EmbeddedIRReference *value(std::string_view QueryName) const noexcept; private: struct StringHash final { @@ -63,8 +82,10 @@ private: bool IsDefinition = false; std::vector Blocks; std::vector Allocas; + std::vector Values; std::unordered_map> BlockNameToIndex; std::unordered_map> AllocaNameToIndex; + std::unordered_map> ValueNameToIndex; friend class EmbeddedIRIndexer; }; @@ -101,13 +122,19 @@ public: return GlobalObjects; } - [[nodiscard]] std::span metadataDefinitions() const noexcept { + [[nodiscard]] std::span + metadataDefinitions() const noexcept { return MetadataDefinitions; } + [[nodiscard]] std::span typeDefinitions() const noexcept { + return TypeDefinitions; + } + [[nodiscard]] const EmbeddedIRFunction *function(std::string_view Name) const noexcept; [[nodiscard]] const EmbeddedIRReference *globalObject(std::string_view Name) const noexcept; - [[nodiscard]] const EmbeddedIRReference *metadata(std::string_view Name) const noexcept; + [[nodiscard]] const EmbeddedIRMetadataDefinition *metadata(std::string_view Name) const noexcept; + [[nodiscard]] const EmbeddedIRTypeDefinition *typeDefinition(std::string_view Name) const noexcept; [[nodiscard]] bool hasGlobalValue(std::string_view Name) const noexcept { return function(Name) != nullptr || globalObject(Name) != nullptr; } @@ -131,10 +158,12 @@ private: std::optional DataLayoutRange; std::vector Functions; std::vector GlobalObjects; - std::vector MetadataDefinitions; + std::vector MetadataDefinitions; + std::vector TypeDefinitions; std::unordered_map> FunctionNameToIndex; std::unordered_map> GlobalNameToIndex; std::unordered_map> MetadataNameToIndex; + std::unordered_map> TypeNameToIndex; friend class EmbeddedIRIndexer; }; @@ -159,6 +188,10 @@ public: return Diagnostics; } + [[nodiscard]] std::optional takeIndex() && { + return std::move(Index); + } + private: EmbeddedIRIndexResult() = default; diff --git a/backend/include/rcc/MIR/LLVMConstantSyntax.h b/backend/include/rcc/MIR/LLVMConstantSyntax.h new file mode 100644 index 0000000..9d7a7d4 --- /dev/null +++ b/backend/include/rcc/MIR/LLVMConstantSyntax.h @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef RCC_MIR_LLVMCONSTANTSYNTAX_H +#define RCC_MIR_LLVMCONSTANTSYNTAX_H + +#include "rcc/CodeGen/GenericConstant.h" +#include "rcc/Support/Error.h" + +#include +#include +#include +#include +#include + +namespace rcc::mir { + +struct LLVMNamedTypeDefinition final { + std::string_view Name; + std::string_view Definition; + bool NumericName = false; +}; + +struct LLVMConstantSyntaxOptions final { + std::uint32_t DefaultPointerSizeInBits = 0; + std::string_view DataLayout; + std::span NamedTypes; + std::size_t MaximumDepth = 1024; + std::size_t MaximumNodes = std::size_t{1} << 24U; + std::size_t MaximumTokenLength = std::size_t{1} << 24U; +}; + +[[nodiscard]] Expected +parseLLVMConstant(std::string_view Text, LLVMConstantSyntaxOptions Options = {}); + +[[nodiscard]] Expected parseLLVMType(std::string_view Text, + LLVMConstantSyntaxOptions Options = {}); + +[[nodiscard]] Expected printLLVMConstant(const GenericConstantData &Constant); + +[[nodiscard]] Expected +llvmConstantStorageSize(const GenericConstantType &Type, LLVMConstantSyntaxOptions Options = {}); + +[[nodiscard]] Expected +llvmConstantPreferredAlignment(const GenericConstantType &Type, + LLVMConstantSyntaxOptions Options = {}); + +[[nodiscard]] Expected llvmPointerSizeInBits(std::uint32_t AddressSpace, + LLVMConstantSyntaxOptions Options = {}); + +} // namespace rcc::mir + +#endif // RCC_MIR_LLVMCONSTANTSYNTAX_H diff --git a/backend/include/rcc/MIR/MIDebugSyntax.h b/backend/include/rcc/MIR/MIDebugSyntax.h new file mode 100644 index 0000000..a8427dc --- /dev/null +++ b/backend/include/rcc/MIR/MIDebugSyntax.h @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef RCC_MIR_MIDEBUGSYNTAX_H +#define RCC_MIR_MIDEBUGSYNTAX_H + +#include +#include +#include + +namespace rcc::mir { + +[[nodiscard]] std::optional +parseDIExpressionOpcodeName(std::string_view Name) noexcept; + +} // namespace rcc::mir + +#endif // RCC_MIR_MIDEBUGSYNTAX_H diff --git a/backend/include/rcc/MIR/MIParser.h b/backend/include/rcc/MIR/MIParser.h index 978e928..116a97f 100644 --- a/backend/include/rcc/MIR/MIParser.h +++ b/backend/include/rcc/MIR/MIParser.h @@ -5,15 +5,18 @@ #include "rcc/CodeGen/MachineIRTypes.h" #include "rcc/CodeGen/MachineMetadata.h" +#include "rcc/CodeGen/Register.h" #include "rcc/Support/Error.h" #include "rcc/Support/TextDiagnostic.h" #include #include +#include #include #include #include #include +#include #include namespace rcc { @@ -23,6 +26,11 @@ class TargetDescription; namespace mir { +struct MIVirtualRegisterSlot final { + std::uint32_t TextID = 0; + Register Reg; +}; + struct MIFrameObjectSlot final { std::uint32_t TextID = 0; FrameIndex Index; @@ -50,12 +58,15 @@ struct MISyncScopeSlot final { }; struct MIParserContext final { + std::vector VirtualRegisters; std::vector StackObjects; std::vector FixedStackObjects; std::vector ConstantPoolItems; std::vector JumpTables; std::vector Metadata; std::vector SyncScopes; + std::function(std::string_view)> InternSyncScope; + std::function(std::uint32_t)> PointerSizeInBits; std::uint32_t DefaultPointerSizeInBits = 0; }; @@ -66,6 +77,7 @@ struct MIParserOptions final { std::size_t MaximumInstructions = std::size_t{1} << 24U; std::size_t MaximumOperandsPerInstruction = std::size_t{1} << 20U; std::size_t MaximumMemoryOperandsPerInstruction = std::size_t{1} << 20U; + bool VerifyAfterParse = true; }; class MIParser final { diff --git a/backend/include/rcc/MIR/MIRDocument.h b/backend/include/rcc/MIR/MIRDocument.h new file mode 100644 index 0000000..7980ca1 --- /dev/null +++ b/backend/include/rcc/MIR/MIRDocument.h @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef RCC_MIR_MIRDOCUMENT_H +#define RCC_MIR_MIRDOCUMENT_H + +#include "rcc/CodeGen/CompilationUnit.h" +#include "rcc/CodeGen/StableID.h" +#include "rcc/MIR/EmbeddedIR.h" +#include "rcc/MIR/MIParser.h" +#include "rcc/MIR/MIPrinter.h" +#include "rcc/Support/TextDiagnostic.h" +#include "rcc/Support/YAML.h" + +#include +#include +#include +#include +#include +#include + +namespace rcc { + +class TargetDescription; + +namespace mir { + +struct MIRFunctionDocumentInfo final { + MachineFunctionStableID Function; + std::optional NoPHIs; + std::optional IsSSA; + std::optional NoVRegs; + std::optional HasFakeUses; + + friend bool operator==(const MIRFunctionDocumentInfo &Left, + const MIRFunctionDocumentInfo &Right) = default; +}; + +class MIRDocument final { +public: + MIRDocument(); + explicit MIRDocument(CompilationUnit Unit); + MIRDocument(const MIRDocument &) = delete; + MIRDocument &operator=(const MIRDocument &) = delete; + MIRDocument(MIRDocument &&) noexcept; + MIRDocument &operator=(MIRDocument &&) noexcept; + ~MIRDocument(); + + [[nodiscard]] CompilationUnit &unit() noexcept { + return Unit; + } + + [[nodiscard]] const CompilationUnit &unit() const noexcept { + return Unit; + } + + [[nodiscard]] const EmbeddedIRReferenceIndex *embeddedIR() const noexcept { + return EmbeddedIR ? &*EmbeddedIR : nullptr; + } + + [[nodiscard]] std::span functionDocumentInfo() const noexcept { + return FunctionInfo; + } + + [[nodiscard]] std::span syncScopes() const noexcept { + return SyncScopes; + } + +private: + CompilationUnit Unit; + std::optional EmbeddedIR; + std::vector FunctionInfo; + std::vector SyncScopes; + + friend class MIRDocumentParser; +}; + +struct MIRDocumentParserOptions final { + yaml::ParseOptions YAML; + MIParserOptions MachineInstructions; + std::string DataLayout; + std::uint32_t DefaultPointerSizeInBits = 0; + bool VerifyMachineFunctions = true; +}; + +class MIRDocumentParseResult final { +public: + MIRDocumentParseResult(const MIRDocumentParseResult &) = delete; + MIRDocumentParseResult &operator=(const MIRDocumentParseResult &) = delete; + MIRDocumentParseResult(MIRDocumentParseResult &&) noexcept; + MIRDocumentParseResult &operator=(MIRDocumentParseResult &&) noexcept; + ~MIRDocumentParseResult(); + + [[nodiscard]] bool succeeded() const noexcept { + return Document.has_value() && Diagnostics.empty(); + } + + [[nodiscard]] MIRDocument *document() noexcept { + return Document ? &*Document : nullptr; + } + + [[nodiscard]] const MIRDocument *document() const noexcept { + return Document ? &*Document : nullptr; + } + + [[nodiscard]] const TextSource &source() const noexcept { + return Source; + } + + [[nodiscard]] std::span diagnostics() const noexcept { + return Diagnostics; + } + +private: + MIRDocumentParseResult(std::string SourceName, std::string SourceText) + : Source(std::move(SourceName), std::move(SourceText)) {} + + TextSource Source; + std::optional Document; + std::vector Diagnostics; + + friend class MIRDocumentParser; +}; + +[[nodiscard]] MIRDocumentParseResult parseMIRDocument(const TargetDescription &Target, + std::string SourceName, + std::string SourceText, + MIRDocumentParserOptions Options = {}); + +struct MIRDocumentPrinterOptions final { + MIPrintMode Mode = MIPrintMode::Complete; + bool EmitEmbeddedIR = true; + std::string DataLayout; + std::uint32_t DefaultPointerSizeInBits = 0; +}; + +[[nodiscard]] Expected printMIRDocument(const MIRDocument &Document, + const TargetDescription &Target, + MIRDocumentPrinterOptions Options = {}); + +} // namespace mir +} // namespace rcc + +#endif // RCC_MIR_MIRDOCUMENT_H -- cgit v1.2.3