aboutsummaryrefslogtreecommitdiff
path: root/backend/lib/CodeGen
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-04 05:34:15 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-04 05:34:15 +0800
commit183e2354e9fdd107be420cbb185c1d239434aa48 (patch)
treece5c42cb6e9790072d5dcf00d1d55cb7f6573ddc /backend/lib/CodeGen
parent67d6231fba98e776c0f442e5b6908e279c35e346 (diff)
downloadrcc-project-183e2354e9fdd107be420cbb185c1d239434aa48.tar.gz
rcc-project-183e2354e9fdd107be420cbb185c1d239434aa48.tar.xz
[MIR] Add machine instruction parser and printer
Parse MachineFunction bodies in two passes and serialize the same MachineIR model in complete or readable form. Extend instruction attachments and memory operands required by the fixed LLVM MIR grammar, and cover deterministic parse-print round trips.
Diffstat (limited to 'backend/lib/CodeGen')
-rw-r--r--backend/lib/CodeGen/MachineFunctionCloner.cpp39
-rw-r--r--backend/lib/CodeGen/MachineInstr.cpp69
-rw-r--r--backend/lib/CodeGen/MachineMemOperand.cpp55
-rw-r--r--backend/lib/CodeGen/MachineVerifier.cpp38
4 files changed, 200 insertions, 1 deletions
diff --git a/backend/lib/CodeGen/MachineFunctionCloner.cpp b/backend/lib/CodeGen/MachineFunctionCloner.cpp
index 7dcf5e2..9342c5a 100644
--- a/backend/lib/CodeGen/MachineFunctionCloner.cpp
+++ b/backend/lib/CodeGen/MachineFunctionCloner.cpp
@@ -414,6 +414,45 @@ cloneMemOperand(const MachineMemOperand &SourceOperand, CloneState &State) {
if (!DebugNumberResult)
return std::unexpected(DebugNumberResult.error());
}
+ if (SourceInstruction->preInstrSymbol()) {
+ auto SymbolResult =
+ NewInstruction->setPreInstrSymbol(std::string(*SourceInstruction->preInstrSymbol()));
+ if (!SymbolResult)
+ return std::unexpected(SymbolResult.error());
+ }
+ if (SourceInstruction->postInstrSymbol()) {
+ auto SymbolResult =
+ NewInstruction->setPostInstrSymbol(std::string(*SourceInstruction->postInstrSymbol()));
+ if (!SymbolResult)
+ return std::unexpected(SymbolResult.error());
+ }
+ if (SourceInstruction->heapAllocMarker()) {
+ auto MarkerResult =
+ NewInstruction->setHeapAllocMarker(*SourceInstruction->heapAllocMarker());
+ if (!MarkerResult)
+ return std::unexpected(MarkerResult.error());
+ }
+ if (SourceInstruction->pcSections()) {
+ auto SectionsResult = NewInstruction->setPCSections(*SourceInstruction->pcSections());
+ if (!SectionsResult)
+ return std::unexpected(SectionsResult.error());
+ }
+ if (SourceInstruction->mmra()) {
+ auto MMRAResult = NewInstruction->setMMRA(*SourceInstruction->mmra());
+ if (!MMRAResult)
+ return std::unexpected(MMRAResult.error());
+ }
+ if (SourceInstruction->cfiType()) {
+ auto TypeResult = NewInstruction->setCFIType(*SourceInstruction->cfiType());
+ if (!TypeResult)
+ return std::unexpected(TypeResult.error());
+ }
+ if (SourceInstruction->deactivationSymbol()) {
+ auto SymbolResult = NewInstruction->setDeactivationSymbol(
+ std::string(*SourceInstruction->deactivationSymbol()));
+ if (!SymbolResult)
+ return std::unexpected(SymbolResult.error());
+ }
auto AppendResult = DestinationBlock->appendInstruction(*NewInstruction);
if (!AppendResult)
diff --git a/backend/lib/CodeGen/MachineInstr.cpp b/backend/lib/CodeGen/MachineInstr.cpp
index a8fe9b5..7597651 100644
--- a/backend/lib/CodeGen/MachineInstr.cpp
+++ b/backend/lib/CodeGen/MachineInstr.cpp
@@ -12,6 +12,8 @@
#include <functional>
#include <limits>
#include <optional>
+#include <string>
+#include <string_view>
#include <utility>
namespace rcc {
@@ -157,6 +159,73 @@ Expected<void> MachineInstr::setDebugLocation(MachineDebugLocation NewLocation)
return {};
}
+std::optional<std::string_view> MachineInstr::preInstrSymbol() const noexcept {
+ if (!PreInstrSymbol)
+ return std::nullopt;
+ return *PreInstrSymbol;
+}
+
+Expected<void> MachineInstr::setPreInstrSymbol(std::string Symbol) {
+ if (Symbol.empty())
+ return makeUnexpected(ErrorCode::InvalidArgument, "pre-instruction symbol cannot be empty");
+ PreInstrSymbol = std::move(Symbol);
+ return {};
+}
+
+std::optional<std::string_view> MachineInstr::postInstrSymbol() const noexcept {
+ if (!PostInstrSymbol)
+ return std::nullopt;
+ return *PostInstrSymbol;
+}
+
+Expected<void> MachineInstr::setPostInstrSymbol(std::string Symbol) {
+ if (Symbol.empty())
+ return makeUnexpected(ErrorCode::InvalidArgument, "post-instruction symbol cannot be empty");
+ PostInstrSymbol = std::move(Symbol);
+ return {};
+}
+
+Expected<void> MachineInstr::setHeapAllocMarker(MachineMetadataReference Marker) {
+ if (!Marker.isValid())
+ return makeUnexpected(ErrorCode::InvalidArgument, "heap-allocation marker must be valid");
+ HeapAllocMarker = Marker;
+ return {};
+}
+
+Expected<void> MachineInstr::setPCSections(MachineMetadataReference Sections) {
+ if (!Sections.isValid())
+ return makeUnexpected(ErrorCode::InvalidArgument, "PC sections metadata must be valid");
+ PCSections = Sections;
+ return {};
+}
+
+Expected<void> MachineInstr::setMMRA(MachineMetadataReference Metadata) {
+ if (!Metadata.isValid())
+ return makeUnexpected(ErrorCode::InvalidArgument, "MMRA metadata must be valid");
+ MMRA = Metadata;
+ return {};
+}
+
+Expected<void> MachineInstr::setCFIType(std::uint64_t Type) {
+ if (Type == 0 || Type > std::numeric_limits<std::uint32_t>::max())
+ return makeUnexpected(ErrorCode::InvalidArgument, "CFI type must fit in nonzero uint32");
+ CFIType = static_cast<std::uint32_t>(Type);
+ return {};
+}
+
+std::optional<std::string_view> MachineInstr::deactivationSymbol() const noexcept {
+ if (!DeactivationSymbol)
+ return std::nullopt;
+ return *DeactivationSymbol;
+}
+
+Expected<void> MachineInstr::setDeactivationSymbol(std::string Symbol) {
+ if (Symbol.empty())
+ return makeUnexpected(ErrorCode::InvalidArgument, "deactivation symbol cannot be empty");
+ DeactivationSymbol = std::move(Symbol);
+ return {};
+}
+
Expected<void> MachineInstr::addMemOperand(const MachineMemOperand &MemOperand) {
if (!OwnerFunction->ownsMemOperand(MemOperand)) {
return makeUnexpected(ErrorCode::InvalidArgument,
diff --git a/backend/lib/CodeGen/MachineMemOperand.cpp b/backend/lib/CodeGen/MachineMemOperand.cpp
index 451dbdb..95e7237 100644
--- a/backend/lib/CodeGen/MachineMemOperand.cpp
+++ b/backend/lib/CodeGen/MachineMemOperand.cpp
@@ -2,6 +2,9 @@
#include "rcc/CodeGen/MachineMemOperand.h"
+#include <algorithm>
+#include <array>
+#include <ranges>
#include <utility>
namespace rcc {
@@ -160,6 +163,38 @@ MemoryBase MemoryBase::externalSymbol(std::string Name) {
return MemoryBase(Kind::ExternalSymbol, std::move(Name));
}
+MemoryBase MemoryBase::irValue(std::string Name) {
+ return MemoryBase(Kind::IRValue, std::move(Name));
+}
+
+MemoryBase MemoryBase::stack() {
+ return MemoryBase(Kind::Stack, std::monostate{});
+}
+
+MemoryBase MemoryBase::got() {
+ return MemoryBase(Kind::GOT, std::monostate{});
+}
+
+MemoryBase MemoryBase::constantPoolPseudo() {
+ return MemoryBase(Kind::ConstantPoolPseudo, std::monostate{});
+}
+
+MemoryBase MemoryBase::jumpTablePseudo() {
+ return MemoryBase(Kind::JumpTablePseudo, std::monostate{});
+}
+
+MemoryBase MemoryBase::callEntryGlobal(std::string Name) {
+ return MemoryBase(Kind::CallEntryGlobal, std::move(Name));
+}
+
+MemoryBase MemoryBase::callEntryExternal(std::string Name) {
+ return MemoryBase(Kind::CallEntryExternal, std::move(Name));
+}
+
+MemoryBase MemoryBase::custom(std::string Name) {
+ return MemoryBase(Kind::Custom, std::move(Name));
+}
+
std::optional<FrameIndex> MemoryBase::frameIndex() const noexcept {
if (BaseKind != Kind::FrameIndex)
return std::nullopt;
@@ -179,8 +214,11 @@ std::optional<JumpTableIndex> MemoryBase::jumpTableIndex() const noexcept {
}
std::optional<std::string_view> MemoryBase::symbolName() const noexcept {
- if (BaseKind != Kind::GlobalSymbol && BaseKind != Kind::ExternalSymbol)
+ if (BaseKind != Kind::GlobalSymbol && BaseKind != Kind::ExternalSymbol &&
+ BaseKind != Kind::IRValue && BaseKind != Kind::CallEntryGlobal &&
+ BaseKind != Kind::CallEntryExternal && BaseKind != Kind::Custom) {
return std::nullopt;
+ }
return std::get<std::string>(Value);
}
@@ -195,6 +233,10 @@ Expected<MachineMemOperand> MachineMemOperand::create(MachineMemOperandDesc Desc
return makeUnexpected(ErrorCode::InvalidArgument,
"machine memory operand address space must fit in 24 bits");
}
+ if (Description.BaseAlign && Description.BaseAlign->bytes() < Description.Align.bytes()) {
+ return makeUnexpected(ErrorCode::InvalidArgument,
+ "machine memory operand base alignment cannot be smaller than alignment");
+ }
if (Description.Accesses.has(MemoryAccessFlag::Invariant) && (!IsLoad || IsStore)) {
return makeUnexpected(ErrorCode::InvalidArgument,
"invariant memory operands must be load-only");
@@ -208,6 +250,17 @@ Expected<MachineMemOperand> MachineMemOperand::create(MachineMemOperandDesc Desc
if (SymbolName && SymbolName->empty()) {
return makeUnexpected(ErrorCode::InvalidArgument, "memory base symbol name cannot be empty");
}
+ const std::array MetadataReferences{
+ Description.TBAA, Description.AliasScope,
+ Description.NoAlias, Description.NoAliasAddressSpace,
+ Description.RangeMetadata,
+ };
+ if (std::ranges::any_of(MetadataReferences, [](const auto &Reference) {
+ return Reference.has_value() && !Reference->isValid();
+ })) {
+ return makeUnexpected(ErrorCode::InvalidArgument,
+ "machine memory operand contains an invalid metadata reference");
+ }
return MachineMemOperand(std::move(Description));
}
diff --git a/backend/lib/CodeGen/MachineVerifier.cpp b/backend/lib/CodeGen/MachineVerifier.cpp
index fd027fe..3ebe683 100644
--- a/backend/lib/CodeGen/MachineVerifier.cpp
+++ b/backend/lib/CodeGen/MachineVerifier.cpp
@@ -12,11 +12,13 @@
#include "rcc/CodeGen/MachineRegisterInfo.h"
#include <algorithm>
+#include <array>
#include <cstddef>
#include <cstdint>
#include <optional>
#include <ranges>
#include <string>
+#include <string_view>
#include <unordered_map>
#include <unordered_set>
#include <utility>
@@ -306,6 +308,29 @@ private:
if (!DebugLocationResult)
return failWith("instruction debug location", DebugLocationResult.error());
}
+ const auto VerifyAttachment = [this](const std::optional<MachineMetadataReference> &Reference,
+ std::string_view Name) -> Expected<void> {
+ if (!Reference)
+ return {};
+ auto Verification = verifyMachineMetadataReference(*Reference, Function.metadata());
+ if (!Verification)
+ return failWith(Name, Verification.error());
+ return {};
+ };
+ if (auto Verification =
+ VerifyAttachment(Instruction.heapAllocMarker(), "instruction heap-allocation marker");
+ !Verification) {
+ return Verification;
+ }
+ if (auto Verification =
+ VerifyAttachment(Instruction.pcSections(), "instruction PC sections metadata");
+ !Verification) {
+ return Verification;
+ }
+ if (auto Verification = VerifyAttachment(Instruction.mmra(), "instruction MMRA metadata");
+ !Verification) {
+ return Verification;
+ }
if (Instruction.origin() && Instruction.origin()->value() == 0)
return fail("instruction has an invalid origin ID");
@@ -364,6 +389,19 @@ private:
if (MemOperand == nullptr || !RegisteredMemOperands.contains(MemOperand)) {
return fail("instruction references a foreign or null MMO");
}
+ const MachineMemOperandDesc &Description = MemOperand->description();
+ const std::array MetadataReferences{
+ Description.TBAA, Description.AliasScope,
+ Description.NoAlias, Description.NoAliasAddressSpace,
+ Description.RangeMetadata,
+ };
+ for (const auto &Reference : MetadataReferences) {
+ if (!Reference)
+ continue;
+ auto Verification = verifyMachineMetadataReference(*Reference, Function.metadata());
+ if (!Verification)
+ return failWith("machine memory operand metadata", Verification.error());
+ }
}
return {};
}