aboutsummaryrefslogtreecommitdiff
path: root/backend/include/rcc/MIR
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-07 01:27:41 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-07 01:27:41 +0800
commit76d89700953ddd81cf31ab8f260eddf67e93aa85 (patch)
treec96a453164154b2d1559cea36910df52103f0f19 /backend/include/rcc/MIR
parent183e2354e9fdd107be420cbb185c1d239434aa48 (diff)
downloadrcc-project-76d89700953ddd81cf31ab8f260eddf67e93aa85.tar.gz
rcc-project-76d89700953ddd81cf31ab8f260eddf67e93aa85.tar.xz
[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.
Diffstat (limited to 'backend/include/rcc/MIR')
-rw-r--r--backend/include/rcc/MIR/EmbeddedIR.h39
-rw-r--r--backend/include/rcc/MIR/LLVMConstantSyntax.h52
-rw-r--r--backend/include/rcc/MIR/MIDebugSyntax.h17
-rw-r--r--backend/include/rcc/MIR/MIParser.h12
-rw-r--r--backend/include/rcc/MIR/MIRDocument.h143
5 files changed, 260 insertions, 3 deletions
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<const EmbeddedIRReference> 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<EmbeddedIRReference> Blocks;
std::vector<EmbeddedIRReference> Allocas;
+ std::vector<EmbeddedIRReference> Values;
std::unordered_map<std::string, std::size_t, StringHash, std::equal_to<>> BlockNameToIndex;
std::unordered_map<std::string, std::size_t, StringHash, std::equal_to<>> AllocaNameToIndex;
+ std::unordered_map<std::string, std::size_t, StringHash, std::equal_to<>> ValueNameToIndex;
friend class EmbeddedIRIndexer;
};
@@ -101,13 +122,19 @@ public:
return GlobalObjects;
}
- [[nodiscard]] std::span<const EmbeddedIRReference> metadataDefinitions() const noexcept {
+ [[nodiscard]] std::span<const EmbeddedIRMetadataDefinition>
+ metadataDefinitions() const noexcept {
return MetadataDefinitions;
}
+ [[nodiscard]] std::span<const EmbeddedIRTypeDefinition> 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<TextRange> DataLayoutRange;
std::vector<EmbeddedIRFunction> Functions;
std::vector<EmbeddedIRReference> GlobalObjects;
- std::vector<EmbeddedIRReference> MetadataDefinitions;
+ std::vector<EmbeddedIRMetadataDefinition> MetadataDefinitions;
+ std::vector<EmbeddedIRTypeDefinition> TypeDefinitions;
std::unordered_map<std::string, std::size_t, StringHash, std::equal_to<>> FunctionNameToIndex;
std::unordered_map<std::string, std::size_t, StringHash, std::equal_to<>> GlobalNameToIndex;
std::unordered_map<std::string, std::size_t, StringHash, std::equal_to<>> MetadataNameToIndex;
+ std::unordered_map<std::string, std::size_t, StringHash, std::equal_to<>> TypeNameToIndex;
friend class EmbeddedIRIndexer;
};
@@ -159,6 +188,10 @@ public:
return Diagnostics;
}
+ [[nodiscard]] std::optional<EmbeddedIRReferenceIndex> 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 <cstddef>
+#include <cstdint>
+#include <span>
+#include <string>
+#include <string_view>
+
+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<const LLVMNamedTypeDefinition> 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<GenericConstantData>
+parseLLVMConstant(std::string_view Text, LLVMConstantSyntaxOptions Options = {});
+
+[[nodiscard]] Expected<GenericConstantType> parseLLVMType(std::string_view Text,
+ LLVMConstantSyntaxOptions Options = {});
+
+[[nodiscard]] Expected<std::string> printLLVMConstant(const GenericConstantData &Constant);
+
+[[nodiscard]] Expected<std::uint64_t>
+llvmConstantStorageSize(const GenericConstantType &Type, LLVMConstantSyntaxOptions Options = {});
+
+[[nodiscard]] Expected<Alignment>
+llvmConstantPreferredAlignment(const GenericConstantType &Type,
+ LLVMConstantSyntaxOptions Options = {});
+
+[[nodiscard]] Expected<std::uint32_t> 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 <cstdint>
+#include <optional>
+#include <string_view>
+
+namespace rcc::mir {
+
+[[nodiscard]] std::optional<std::uint64_t>
+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 <cstddef>
#include <cstdint>
+#include <functional>
#include <memory>
#include <optional>
#include <span>
#include <string>
+#include <string_view>
#include <vector>
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<MIVirtualRegisterSlot> VirtualRegisters;
std::vector<MIFrameObjectSlot> StackObjects;
std::vector<MIFrameObjectSlot> FixedStackObjects;
std::vector<MIConstantPoolSlot> ConstantPoolItems;
std::vector<MIJumpTableSlot> JumpTables;
std::vector<MIMetadataSlot> Metadata;
std::vector<MISyncScopeSlot> SyncScopes;
+ std::function<Expected<SyncScopeID>(std::string_view)> InternSyncScope;
+ std::function<Expected<std::uint32_t>(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 <cstdint>
+#include <optional>
+#include <span>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace rcc {
+
+class TargetDescription;
+
+namespace mir {
+
+struct MIRFunctionDocumentInfo final {
+ MachineFunctionStableID Function;
+ std::optional<bool> NoPHIs;
+ std::optional<bool> IsSSA;
+ std::optional<bool> NoVRegs;
+ std::optional<bool> 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<const MIRFunctionDocumentInfo> functionDocumentInfo() const noexcept {
+ return FunctionInfo;
+ }
+
+ [[nodiscard]] std::span<const MISyncScopeSlot> syncScopes() const noexcept {
+ return SyncScopes;
+ }
+
+private:
+ CompilationUnit Unit;
+ std::optional<EmbeddedIRReferenceIndex> EmbeddedIR;
+ std::vector<MIRFunctionDocumentInfo> FunctionInfo;
+ std::vector<MISyncScopeSlot> 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<const TextDiagnostic> diagnostics() const noexcept {
+ return Diagnostics;
+ }
+
+private:
+ MIRDocumentParseResult(std::string SourceName, std::string SourceText)
+ : Source(std::move(SourceName), std::move(SourceText)) {}
+
+ TextSource Source;
+ std::optional<MIRDocument> Document;
+ std::vector<TextDiagnostic> 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<std::string> printMIRDocument(const MIRDocument &Document,
+ const TargetDescription &Target,
+ MIRDocumentPrinterOptions Options = {});
+
+} // namespace mir
+} // namespace rcc
+
+#endif // RCC_MIR_MIRDOCUMENT_H