From a8a9d7d926202450645deae872d4d9dc11d63215 Mon Sep 17 00:00:00 2001 From: Richard-Qin-X Date: Sun, 2 Aug 2026 03:37:46 +0800 Subject: [CodeGen] Model machine debug metadata Replace marker-based metadata operands with scoped references and inline DIExpression values. Add structured DILocation chains, instruction debug attachments, stack variable records, and entry values with unified verification, builder support, and deterministic cloning. --- .../CodeGen/MachineFunctionRecordsTest.cpp | 79 +++++++++++++++++----- 1 file changed, 61 insertions(+), 18 deletions(-) (limited to 'backend/unittests/CodeGen/MachineFunctionRecordsTest.cpp') diff --git a/backend/unittests/CodeGen/MachineFunctionRecordsTest.cpp b/backend/unittests/CodeGen/MachineFunctionRecordsTest.cpp index 4f41b39..8ca6bf3 100644 --- a/backend/unittests/CodeGen/MachineFunctionRecordsTest.cpp +++ b/backend/unittests/CodeGen/MachineFunctionRecordsTest.cpp @@ -5,6 +5,7 @@ #include "Target/TestTarget.h" #include "rcc/CodeGen/InstructionDescriptor.h" #include "rcc/CodeGen/MachineBasicBlock.h" +#include "rcc/CodeGen/MachineDebugInfo.h" #include "rcc/CodeGen/MachineFunction.h" #include "rcc/CodeGen/MachineFunctionCloner.h" #include "rcc/CodeGen/MachineInstr.h" @@ -14,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -120,6 +122,8 @@ void testValueValidation(TestContext &Context) { .Flags = 0, }), "a called-global record must require a nonempty callee"); + Context.expect(!Records.addEntryValue({}), + "an entry-value record must require a physical register and debug metadata"); const rcc::MachinePrefetchTarget Target{ .Block = {.BaseID = 7, .CloneID = 3}, @@ -135,6 +139,9 @@ void testVerifierAndClone(TestContext &Context) { auto Function = createFunction(Context, 1, "records"); if (!Target || Function == nullptr) return; + Context.expect( + Function->metadata().addNode({.Slot = 0, .IsDistinct = false, .Elements = {}}).has_value(), + "function record metadata setup must succeed"); rcc::MachineBasicBlock *Block = appendBlock(Context, *Function); if (Block == nullptr) @@ -175,6 +182,22 @@ void testVerifierAndClone(TestContext &Context) { }) .has_value(), "structured prefetch target information must be stored"); + auto EntryLocation = + rcc::MachineDebugLocation::reference(rcc::MachineMetadataReference::embeddedIR(12)); + Context.expect(EntryLocation.has_value(), "entry-value debug location must be representable"); + if (!EntryLocation) + return; + const rcc::MachineEntryValueInfo EntryValue{ + .Reg = G0, + .DebugInfo = + { + .Variable = rcc::MachineMetadataReference::embeddedIR(10), + .Expression = rcc::MachineMetadataValue::expression(rcc::MachineDIExpression{}), + .Location = *EntryLocation, + }, + }; + Context.expect(Function->records().addEntryValue(EntryValue).has_value(), + "structured entry-value debug information must be stored"); Context.expect(rcc::MachineVerifier::verify(*Function, *Target).has_value(), "well-formed function records must pass unified verification"); @@ -190,24 +213,25 @@ void testVerifierAndClone(TestContext &Context) { const auto InstructionID = Clone->InstructionStableIDs.find(Call->stableID()); const rcc::MachineFunctionRecords &ClonedRecords = Clone->ClonedFunction->records(); - Context.expect(InstructionID != Clone->InstructionStableIDs.end() && - ClonedRecords.hasCalleeSavedRegisters() && - ClonedRecords.calleeSavedRegisters().size() == 2 && - ClonedRecords.callSites().size() == 1 && - ClonedRecords.callSites()[0].CallInstruction == InstructionID->second && - ClonedRecords.callSites()[0].ForwardedArguments.size() == 2 && - ClonedRecords.callSites()[0].ForwardedArguments[1].ArgumentNumber == 0 && - ClonedRecords.callSites()[0].CalleeTypeIDs == - std::vector({0x11, 0x22}) && - ClonedRecords.calledGlobals().size() == 1 && - ClonedRecords.calledGlobals()[0].CallInstruction == InstructionID->second && - ClonedRecords.calledGlobals()[0].Callee == "callee" && - ClonedRecords.calledGlobals()[0].Flags == 5 && - ClonedRecords.prefetchTargets().size() == 1 && - ClonedRecords.prefetchTargets()[0].Block == - rcc::MachineBasicBlockProfileID{.BaseID = 19, .CloneID = 2} && - ClonedRecords.prefetchTargets()[0].CallsiteIndex == 8, - "deep clone must preserve records and remap instruction StableIDs"); + Context.expect( + InstructionID != Clone->InstructionStableIDs.end() && + ClonedRecords.hasCalleeSavedRegisters() && + ClonedRecords.calleeSavedRegisters().size() == 2 && + ClonedRecords.callSites().size() == 1 && + ClonedRecords.callSites()[0].CallInstruction == InstructionID->second && + ClonedRecords.callSites()[0].ForwardedArguments.size() == 2 && + ClonedRecords.callSites()[0].ForwardedArguments[1].ArgumentNumber == 0 && + ClonedRecords.callSites()[0].CalleeTypeIDs == std::vector({0x11, 0x22}) && + ClonedRecords.calledGlobals().size() == 1 && + ClonedRecords.calledGlobals()[0].CallInstruction == InstructionID->second && + ClonedRecords.calledGlobals()[0].Callee == "callee" && + ClonedRecords.calledGlobals()[0].Flags == 5 && + ClonedRecords.prefetchTargets().size() == 1 && + ClonedRecords.prefetchTargets()[0].Block == + rcc::MachineBasicBlockProfileID{.BaseID = 19, .CloneID = 2} && + ClonedRecords.prefetchTargets()[0].CallsiteIndex == 8 && + ClonedRecords.entryValues().size() == 1 && ClonedRecords.entryValues()[0] == EntryValue, + "deep clone must preserve records and remap instruction StableIDs"); } void testCrossReferenceFailures(TestContext &Context) { @@ -306,6 +330,25 @@ void testCrossReferenceFailures(TestContext &Context) { Context.expect(!rcc::MachineVerifier::verify(*Function, *Target), "linked block bb_id values must be unique"); } + + { + auto Function = createFunction(Context, 13, "entry-value-register"); + if (Function == nullptr) + return; + Context.expect(Function->records() + .addEntryValue({ + .Reg = phys(999), + .DebugInfo = + { + .Variable = rcc::MachineMetadataReference::embeddedIR(1), + .Expression = std::nullopt, + .Location = std::nullopt, + }, + }) + .has_value() && + !rcc::MachineVerifier::verify(*Function, *Target), + "entry-value records must reject target-unknown physical registers"); + } } } // namespace -- cgit v1.2.3