aboutsummaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
Diffstat (limited to 'backend')
-rw-r--r--backend/lib/MIR/MIRDocumentParser.cpp15
-rw-r--r--backend/lib/MIR/MIRDocumentParser.h3
-rw-r--r--backend/lib/MIR/MIRFunctionParser.cpp2
-rw-r--r--backend/unittests/MIR/MIRDocumentTest.cpp43
4 files changed, 57 insertions, 6 deletions
diff --git a/backend/lib/MIR/MIRDocumentParser.cpp b/backend/lib/MIR/MIRDocumentParser.cpp
index 954d0d8..9c4728a 100644
--- a/backend/lib/MIR/MIRDocumentParser.cpp
+++ b/backend/lib/MIR/MIRDocumentParser.cpp
@@ -172,15 +172,22 @@ bool MIRDocumentParser::physicalRegister(const yaml::Node &Node, PhysicalRegiste
}
bool MIRDocumentParser::virtualRegister(std::string_view Text, const TextRange &Range,
- const MIParserContext &Context, Register &Reg) {
+ MachineFunction &Function, MIParserContext &Context,
+ Register &Reg) {
const auto ID = parsePrefixedID(Text, "%");
if (!ID)
return fail(Range, "virtual register must use the '%N' MIR spelling");
- const auto Found =
+ auto Found =
std::ranges::find_if(Context.VirtualRegisters,
[ID](const MIVirtualRegisterSlot &Slot) { return Slot.TextID == *ID; });
- if (Found == Context.VirtualRegisters.end())
- return fail(Range, "reference to undefined virtual register '%" + std::to_string(*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;
}
diff --git a/backend/lib/MIR/MIRDocumentParser.h b/backend/lib/MIR/MIRDocumentParser.h
index 3fade39..4d1d1ea 100644
--- a/backend/lib/MIR/MIRDocumentParser.h
+++ b/backend/lib/MIR/MIRDocumentParser.h
@@ -70,7 +70,8 @@ private:
[[nodiscard]] bool physicalRegister(std::string_view Text, const TextRange &Range,
PhysicalRegister &Reg);
[[nodiscard]] bool virtualRegister(std::string_view Text, const TextRange &Range,
- const MIParserContext &Context, Register &Reg);
+ MachineFunction &Function, MIParserContext &Context,
+ Register &Reg);
[[nodiscard]] Expected<MachineMetadataReference>
resolveMetadataReference(const MachineFunction &Function, std::uint32_t Slot) const;
[[nodiscard]] bool parseVariableDebugInfo(const yaml::Node &Entry, MachineFunction &Function,
diff --git a/backend/lib/MIR/MIRFunctionParser.cpp b/backend/lib/MIR/MIRFunctionParser.cpp
index c8bba70..7e8821b 100644
--- a/backend/lib/MIR/MIRFunctionParser.cpp
+++ b/backend/lib/MIR/MIRFunctionParser.cpp
@@ -348,7 +348,7 @@ bool MIRDocumentParser::parseRegisters(const yaml::Node &Root, MachineFunction &
return true;
if (!trim(Text).empty()) {
Register Virtual;
- if (virtualRegister(Text, VirtualNode->range(), Context, Virtual))
+ if (virtualRegister(Text, VirtualNode->range(), Function, Context, Virtual))
return true;
Initial = Virtual;
}
diff --git a/backend/unittests/MIR/MIRDocumentTest.cpp b/backend/unittests/MIR/MIRDocumentTest.cpp
index 88f92bc..c655e64 100644
--- a/backend/unittests/MIR/MIRDocumentTest.cpp
+++ b/backend/unittests/MIR/MIRDocumentTest.cpp
@@ -949,6 +949,48 @@ body: |
printDiagnostics(Invalid);
}
+void testLiveInCreatesVirtualRegister(TestContext &Context) {
+ auto Target = createTarget();
+ Context.expect(Target.has_value(), "live-in virtual-register target must be valid");
+ if (!Target)
+ return;
+
+ constexpr std::string_view DocumentText = R"(---
+name: live_in_vreg
+liveins:
+ - { reg: '$g0', virtual-reg: '%0' }
+body: |
+ bb.0:
+ %0:gpr64 = TEST_COPY $g0
+)";
+ auto Parsed = rcc::mir::parseMIRDocument(*Target, "live-in-vreg.mir", std::string(DocumentText));
+ const rcc::MachineFunction *Function =
+ Parsed.succeeded() ? Parsed.document()->unit().function("live_in_vreg") : nullptr;
+ const auto Registers = Function != nullptr ? Function->registerInfo().virtualRegisters()
+ : std::span<const rcc::VirtualRegisterInfo>{};
+ const auto LiveIns = Function != nullptr ? Function->registerInfo().liveIns()
+ : std::span<const rcc::PhysicalRegisterLiveIn>{};
+ Context.expect(Parsed.succeeded() && Function != nullptr && Registers.size() == 1 &&
+ Registers.front().RegClass.has_value() && LiveIns.size() == 1 &&
+ LiveIns.front().InitialVirtualRegister.has_value(),
+ "a live-in must create a virtual register before the body constrains it");
+ if (!Parsed.succeeded()) {
+ printDiagnostics(Parsed);
+ return;
+ }
+
+ auto Printed = rcc::mir::printMIRDocument(*Parsed.document(), *Target);
+ Context.expect(Printed.has_value(),
+ "an implicitly created live-in virtual register must be printable");
+ if (!Printed)
+ return;
+ auto RoundTrip = rcc::mir::parseMIRDocument(*Target, "live-in-vreg-round-trip.mir", *Printed);
+ Context.expect(RoundTrip.succeeded(),
+ "an implicitly created live-in virtual register must round-trip");
+ if (!RoundTrip.succeeded())
+ printDiagnostics(RoundTrip);
+}
+
void testBodyDiagnosticLocation(TestContext &Context) {
auto Target = createTarget();
Context.expect(Target.has_value(), "body-diagnostic target must be valid");
@@ -1067,6 +1109,7 @@ int main() {
testFixedWidthDocumentFields(Context);
testAtomicFailure(Context);
testLLVMPropertySemantics(Context);
+ testLiveInCreatesVirtualRegister(Context);
testBodyDiagnosticLocation(Context);
testAnonymousFunctionsAndIRBlocks(Context);
return Context.result();