diff --git a/include/dxc/Test/HlslTestUtils.h b/include/dxc/Test/HlslTestUtils.h index 666feb9dcd..b1903b9c08 100644 --- a/include/dxc/Test/HlslTestUtils.h +++ b/include/dxc/Test/HlslTestUtils.h @@ -115,6 +115,7 @@ using namespace std; #endif // VERIFY_ARE_EQUAL static constexpr char whitespaceChars[] = " \t\r\n"; +static constexpr wchar_t wideWhitespaceChars[] = L" \t\r\n"; inline std::string strltrim(const std::string &value) { size_t first = value.find_first_not_of(whitespaceChars); @@ -157,6 +158,25 @@ strtok(const std::string &value, const char *delimiters = whitespaceChars) { return tokens; } +inline std::vector +strtok(const std::wstring &value, + const wchar_t *delimiters = wideWhitespaceChars) { + size_t searchOffset = 0; + std::vector tokens; + while (searchOffset != value.size()) { + size_t tokenStartIndex = value.find_first_not_of(delimiters, searchOffset); + if (tokenStartIndex == std::string::npos) + break; + size_t tokenEndIndex = value.find_first_of(delimiters, tokenStartIndex); + if (tokenEndIndex == std::string::npos) + tokenEndIndex = value.size(); + tokens.emplace_back( + value.substr(tokenStartIndex, tokenEndIndex - tokenStartIndex)); + searchOffset = tokenEndIndex; + } + return tokens; +} + // strreplace will replace all instances of lookFors with replacements at the // same index. Will log an error if the string is not found, unless the first // character is ? marking it optional. diff --git a/include/dxc/WinAdapter.h b/include/dxc/WinAdapter.h index fe4cb14ffa..b2eb35b61c 100644 --- a/include/dxc/WinAdapter.h +++ b/include/dxc/WinAdapter.h @@ -1015,6 +1015,11 @@ class CComBSTR { m_str = NULL; return s; } + + void Empty() throw() { + SysFreeString(m_str); + m_str = NULL; + } }; //===--------- Convert argv to wchar ----------------===// diff --git a/lib/DxilDia/DxcPixLiveVariables.cpp b/lib/DxilDia/DxcPixLiveVariables.cpp index 9c1bc38c90..725c2078c0 100644 --- a/lib/DxilDia/DxcPixLiveVariables.cpp +++ b/lib/DxilDia/DxcPixLiveVariables.cpp @@ -49,12 +49,19 @@ class UniqueScopeForInlinedFunctions { // is at file-level scope, it will return nullptr. if (auto Namespace = llvm::dyn_cast(FunctionScope)) { if (auto *ContainingScope = Namespace->getScope()) { - FunctionScope = ContainingScope; + if (FunctionScope == InlinedAtScope) + InlinedAtScope = FunctionScope = ContainingScope; + else + FunctionScope = ContainingScope; return; } } const llvm::DITypeIdentifierMap EmptyMap; - FunctionScope = FunctionScope->getScope().resolve(EmptyMap); + if (FunctionScope == InlinedAtScope) + InlinedAtScope = FunctionScope = + FunctionScope->getScope().resolve(EmptyMap); + else + FunctionScope = FunctionScope->getScope().resolve(EmptyMap); } static UniqueScopeForInlinedFunctions Create(llvm::DebugLoc const &DbgLoc, diff --git a/tools/clang/unittests/HLSL/PixDiaTest.cpp b/tools/clang/unittests/HLSL/PixDiaTest.cpp index e288df6a33..dede2386df 100644 --- a/tools/clang/unittests/HLSL/PixDiaTest.cpp +++ b/tools/clang/unittests/HLSL/PixDiaTest.cpp @@ -14,7 +14,6 @@ #include "dxc/DxilContainer/DxilContainer.h" #include "dxc/Support/WinIncludes.h" -#include "dxc/dxcapi.h" #include "dxc/Test/DxcTestUtils.h" #include "dxc/Test/HLSLTestData.h" @@ -177,8 +176,14 @@ class PixDiaTest { TEST_METHOD(DxcPixDxilDebugInfo_UnnamedField) TEST_METHOD(DxcPixDxilDebugInfo_SubProgramsInNamespaces) TEST_METHOD(DxcPixDxilDebugInfo_SubPrograms) - TEST_METHOD(DxcPixDxilDebugInfo_InlinedFunctions_TwiceInlinedFunctions) - TEST_METHOD(DxcPixDxilDebugInfo_InlinedFunctions_CalledTwiceInSameCaller) + TEST_METHOD( + DxcPixDxilDebugInfo_VariableScopes_InlinedFunctions_TwiceInlinedFunctions) + TEST_METHOD( + DxcPixDxilDebugInfo_VariableScopes_InlinedFunctions_CalledTwiceInSameCaller) + TEST_METHOD(DxcPixDxilDebugInfo_VariableScopes_ForScopes) + TEST_METHOD(DxcPixDxilDebugInfo_VariableScopes_ScopeBraces) + TEST_METHOD(DxcPixDxilDebugInfo_VariableScopes_Function) + TEST_METHOD(DxcPixDxilDebugInfo_VariableScopes_Member) dxc::DxcDllSupport m_dllSupport; VersionSupportInfo m_ver; @@ -638,7 +643,8 @@ class PixDiaTest { const char *hlsl, const wchar_t *profile, const char *lineAtWhichToExamineVariables, std::vector const &ExpectedVariables); - CComPtr + + DebuggerInterfaces CompileAndCreateDxcDebug(const char *hlsl, const wchar_t *profile, IDxcIncludeHandler *includer = nullptr); @@ -769,7 +775,7 @@ void PixDiaTest::CompileAndRunAnnotationAndGetDebugPart( *ppDebugPart = GetDebugPart(dllSupport, pNewContainer).Detach(); } -CComPtr +DebuggerInterfaces PixDiaTest::CompileAndCreateDxcDebug(const char *hlsl, const wchar_t *profile, IDxcIncludeHandler *includer) { @@ -783,9 +789,10 @@ PixDiaTest::CompileAndCreateDxcDebug(const char *hlsl, const wchar_t *profile, CComPtr Factory; VERIFY_SUCCEEDED(session->QueryInterface(IID_PPV_ARGS(&Factory))); - CComPtr dxilDebugger; - VERIFY_SUCCEEDED(Factory->NewDxcPixDxilDebugInfo(&dxilDebugger)); - return dxilDebugger; + DebuggerInterfaces ret; + VERIFY_SUCCEEDED(Factory->NewDxcPixDxilDebugInfo(&ret.debugInfo)); + VERIFY_SUCCEEDED(Factory->NewDxcPixCompilationInfo(&ret.compilationInfo)); + return ret; } CComPtr @@ -845,7 +852,7 @@ void PixDiaTest::TestGlobalStaticCase( const char *lineAtWhichToExamineVariables, std::vector const &ExpectedVariables) { - auto dxilDebugger = CompileAndCreateDxcDebug(hlsl, profile); + auto dxilDebugger = CompileAndCreateDxcDebug(hlsl, profile).debugInfo; auto liveVariables = GetLiveVariablesAt(hlsl, lineAtWhichToExamineVariables, dxilDebugger); @@ -2239,7 +2246,7 @@ void main() } )"; - auto dxilDebugger = CompileAndCreateDxcDebug(hlsl, L"cs_6_6"); + auto dxilDebugger = CompileAndCreateDxcDebug(hlsl, L"cs_6_6").debugInfo; auto liveVariables = GetLiveVariablesAt(hlsl, "InterestingLine", dxilDebugger); @@ -2300,7 +2307,7 @@ void main() } )"; - auto dxilDebugger = CompileAndCreateDxcDebug(hlsl, L"cs_6_6"); + auto dxilDebugger = CompileAndCreateDxcDebug(hlsl, L"cs_6_6").debugInfo; auto liveVariables = GetLiveVariablesAt(hlsl, "InterestingLine", dxilDebugger); @@ -2358,7 +2365,7 @@ void main() } )"; - auto dxilDebugger = CompileAndCreateDxcDebug(hlsl, L"cs_6_6"); + auto dxilDebugger = CompileAndCreateDxcDebug(hlsl, L"cs_6_6").debugInfo; auto liveVariables = GetLiveVariablesAt(hlsl, "InterestingLine", dxilDebugger); @@ -2418,7 +2425,7 @@ void main() } )"; - auto dxilDebugger = CompileAndCreateDxcDebug(hlsl, L"cs_6_6"); + auto dxilDebugger = CompileAndCreateDxcDebug(hlsl, L"cs_6_6").debugInfo; auto liveVariables = GetLiveVariablesAt(hlsl, "InterestingLine", dxilDebugger); @@ -2451,7 +2458,7 @@ void PixDiaTest::TestUnnamedTypeCase(const char *hlsl, const wchar_t *expectedTypeName) { if (m_ver.SkipDxilVersion(1, 2)) return; - auto dxilDebugger = CompileAndCreateDxcDebug(hlsl, L"cs_6_0"); + auto dxilDebugger = CompileAndCreateDxcDebug(hlsl, L"cs_6_0").debugInfo; auto liveVariables = GetLiveVariablesAt(hlsl, "InterestingLine", dxilDebugger); DWORD count; @@ -2562,7 +2569,7 @@ void main() if (m_ver.SkipDxilVersion(1, 2)) return; - auto dxilDebugger = CompileAndCreateDxcDebug(hlsl, L"cs_6_0"); + auto dxilDebugger = CompileAndCreateDxcDebug(hlsl, L"cs_6_0").debugInfo; auto liveVariables = GetLiveVariablesAt(hlsl, "InterestingLine", dxilDebugger); DWORD count; @@ -2656,7 +2663,7 @@ float4 fn2( float3 f3, float d, bool sanitize = true ) )"}}); auto dxilDebugger = - CompileAndCreateDxcDebug(hlsl, L"cs_6_0", pIncludeHandler); + CompileAndCreateDxcDebug(hlsl, L"cs_6_0", pIncludeHandler).debugInfo; struct SourceLocations { CComBSTR Filename; @@ -2780,7 +2787,7 @@ static DWORD AdvanceUntilFunctionEntered(IDxcPixDxilDebugInfo *dxilDebugger, static DWORD GetRegisterNumberForVariable(IDxcPixDxilDebugInfo *dxilDebugger, DWORD instructionOffset, wchar_t const *variableName, - wchar_t const *memberName) { + wchar_t const *memberName = nullptr) { CComPtr DxcPixDxilLiveVariables; if (SUCCEEDED(dxilDebugger->GetLiveVariablesAt(instructionOffset, &DxcPixDxilLiveVariables))) { @@ -2795,12 +2802,14 @@ static DWORD GetRegisterNumberForVariable(IDxcPixDxilDebugInfo *dxilDebugger, if (Name == variableName) { CComPtr DxcPixDxilStorage; VERIFY_SUCCEEDED(DxcPixVariable->GetStorage(&DxcPixDxilStorage)); - CComPtr DxcPixDxilMemberStorage; - VERIFY_SUCCEEDED(DxcPixDxilStorage->AccessField( - memberName, &DxcPixDxilMemberStorage)); + if (memberName != nullptr) { + CComPtr DxcPixDxilMemberStorage; + VERIFY_SUCCEEDED(DxcPixDxilStorage->AccessField( + memberName, &DxcPixDxilMemberStorage)); + DxcPixDxilStorage = DxcPixDxilMemberStorage; + } DWORD RegisterNumber = 42; - VERIFY_SUCCEEDED( - DxcPixDxilMemberStorage->GetRegisterNumber(&RegisterNumber)); + VERIFY_SUCCEEDED(DxcPixDxilStorage->GetRegisterNumber(&RegisterNumber)); return RegisterNumber; } } @@ -2809,7 +2818,37 @@ static DWORD GetRegisterNumberForVariable(IDxcPixDxilDebugInfo *dxilDebugger, return -1; } -TEST_F(PixDiaTest, DxcPixDxilDebugInfo_InlinedFunctions_TwiceInlinedFunctions) { +static void +CheckVariableExistsAtThisInstruction(IDxcPixDxilDebugInfo *dxilDebugger, + DWORD instructionOffset, + wchar_t const *variableName) { + // It's sufficient to know that there _is_ a register number the var: + (void)GetRegisterNumberForVariable(dxilDebugger, instructionOffset, + variableName); +} + +static void +CheckVariableDoesNOTExistsAtThisInstruction(IDxcPixDxilDebugInfo *dxilDebugger, + DWORD instructionOffset, + wchar_t const *variableName) { + CComPtr DxcPixDxilLiveVariables; + VERIFY_SUCCEEDED(dxilDebugger->GetLiveVariablesAt(instructionOffset, + &DxcPixDxilLiveVariables)); + DWORD count = 42; + VERIFY_SUCCEEDED(DxcPixDxilLiveVariables->GetCount(&count)); + for (DWORD i = 0; i < count; ++i) { + CComPtr DxcPixVariable; + VERIFY_SUCCEEDED( + DxcPixDxilLiveVariables->GetVariableByIndex(i, &DxcPixVariable)); + CComBSTR Name; + VERIFY_SUCCEEDED(DxcPixVariable->GetName(&Name)); + VERIFY_ARE_NOT_EQUAL(Name, variableName); + } +} + +TEST_F( + PixDiaTest, + DxcPixDxilDebugInfo_VariableScopes_InlinedFunctions_TwiceInlinedFunctions) { if (m_ver.SkipDxilVersion(1, 6)) return; @@ -2880,7 +2919,7 @@ float4 DeeperInlinedFunction(in BuiltInTriangleIntersectionAttributes attr, int )"}}); auto dxilDebugger = - CompileAndCreateDxcDebug(hlsl, L"lib_6_6", pIncludeHandler); + CompileAndCreateDxcDebug(hlsl, L"lib_6_6", pIncludeHandler).debugInfo; // Case: same functions called from two different top-level callers DWORD instructionOffset = @@ -2923,8 +2962,9 @@ float4 DeeperInlinedFunction(in BuiltInTriangleIntersectionAttributes attr, int ColorRegisterNumberWhenCalledFromOuterForDeeper); } -TEST_F(PixDiaTest, - DxcPixDxilDebugInfo_InlinedFunctions_CalledTwiceInSameCaller) { +TEST_F( + PixDiaTest, + DxcPixDxilDebugInfo_VariableScopes_InlinedFunctions_CalledTwiceInSameCaller) { if (m_ver.SkipDxilVersion(1, 6)) return; @@ -2953,7 +2993,7 @@ void ClosestHitShader3(inout RayPayload payload, in BuiltInTriangleIntersectionA } )"; - auto dxilDebugger = CompileAndCreateDxcDebug(hlsl, L"lib_6_6"); + auto dxilDebugger = CompileAndCreateDxcDebug(hlsl, L"lib_6_6").debugInfo; // Case: same function called from two places in same top-level function. // In this case, we expect the storage for the variable to be in the same @@ -2976,4 +3016,192 @@ void ClosestHitShader3(inout RayPayload payload, in BuiltInTriangleIntersectionA VERIFY_ARE_EQUAL(callsite0, callsite1); } +TEST_F(PixDiaTest, DxcPixDxilDebugInfo_VariableScopes_ForScopes) { + if (m_ver.SkipDxilVersion(1, 6)) + return; + + const char *hlsl = + R"(/*01*/RWStructuredBuffer intRWUAV: register(u0); +/*02*/[shader("compute")] +/*03*/[numthreads(1,1,1)] +/*04*/void CSMain() +/*05*/{ +/*06*/ int zero = intRWUAV.Load(0); +/*07*/ int two = zero * 2; // debug-loc(CheckVariableExistsHere) +/*08*/ int three = zero * 3; +/*09*/ for(int i =0; i < two; ++ i) +/*10*/ { +/*11*/ int one = intRWUAV.Load(i); +/*12*/ three += one; // debug-loc(Stop inside loop) +/*13*/ } +/*14*/ intRWUAV[0] = three; // debug-loc(Stop here) +/*15*/} +)"; + + auto debugInterfaces = CompileAndCreateDxcDebug(hlsl, L"lib_6_6"); + auto dxilDebugger = debugInterfaces.debugInfo; + auto Labels = GatherDebugLocLabelsFromDxcUtils(debugInterfaces); + + // Case: same function called from two places in same top-level function. + // In this case, we expect the storage for the variable to be in the same + // place for both "instances" of the function: as a thread proceeds through + // the caller, it will write new values into the variable's storage during + // the second or subsequent invocations of the inlined function. + DWORD instructionOffset = + AdvanceUntilFunctionEntered(dxilDebugger, 0, L"CSMain"); + + instructionOffset = + Labels->FindInstructionOffsetForLabel(L"CheckVariableExistsHere"); + CheckVariableExistsAtThisInstruction(dxilDebugger, instructionOffset, + L"zero"); + + instructionOffset = + Labels->FindInstructionOffsetForLabel(L"Stop inside loop"); + CheckVariableExistsAtThisInstruction(dxilDebugger, instructionOffset, + L"zero"); + + instructionOffset = Labels->FindInstructionOffsetForLabel(L"Stop here"); + CheckVariableDoesNOTExistsAtThisInstruction(dxilDebugger, instructionOffset, + L"one"); +} + +TEST_F(PixDiaTest, DxcPixDxilDebugInfo_VariableScopes_ScopeBraces) { + if (m_ver.SkipDxilVersion(1, 6)) + return; + + const char *hlsl = + R"(/*01*/RWStructuredBuffer intRWUAV: register(u0); +/*02*/[shader("compute")] +/*03*/[numthreads(1,1,1)] +/*04*/void CSMain() +/*05*/{ +/*06*/ int zero = intRWUAV.Load(0); +/*07*/ int two = zero * 2; // debug-loc(CheckVariableExistsHere) +/*08*/ { +/*09*/ int one = intRWUAV.Load(1); +/*10*/ two += one; // debug-loc(Stop inside loop) +/*11*/ } +/*12*/ intRWUAV[0] = two; // debug-loc(Stop here) +/*13*/} +)"; + + auto debugInterfaces = CompileAndCreateDxcDebug(hlsl, L"lib_6_6"); + auto Labels = GatherDebugLocLabelsFromDxcUtils(debugInterfaces); + auto dxilDebugger = debugInterfaces.debugInfo; + + // Case: same function called from two places in same top-level function. + // In this case, we expect the storage for the variable to be in the same + // place for both "instances" of the function: as a thread proceeds through + // the caller, it will write new values into the variable's storage during + // the second or subsequent invocations of the inlined function. + DWORD instructionOffset = + AdvanceUntilFunctionEntered(dxilDebugger, 0, L"CSMain"); + + instructionOffset = + Labels->FindInstructionOffsetForLabel(L"CheckVariableExistsHere"); + CheckVariableExistsAtThisInstruction(dxilDebugger, instructionOffset, + L"zero"); + + instructionOffset = + Labels->FindInstructionOffsetForLabel(L"Stop inside loop"); + CheckVariableExistsAtThisInstruction(dxilDebugger, instructionOffset, + L"zero"); + + instructionOffset = Labels->FindInstructionOffsetForLabel(L"Stop here"); + CheckVariableDoesNOTExistsAtThisInstruction(dxilDebugger, instructionOffset, + L"one"); +} + +TEST_F(PixDiaTest, DxcPixDxilDebugInfo_VariableScopes_Function) { + if (m_ver.SkipDxilVersion(1, 6)) + return; + + const char *hlsl = + R"(/*01*/RWStructuredBuffer intRWUAV: register(u0); +/*02*/int Square(int i) { +/*03*/ int i2 = i * i; // debug-loc(Stop in subroutine) +/*04*/ return i2; +/*05*/} +/*06*/[shader("compute")] +/*07*/[numthreads(1,1,1)] +/*08*/void CSMain() +/*09*/{ +/*10*/ int zero = intRWUAV.Load(0); +/*11*/ int two = Square(zero); +/*12*/ intRWUAV[0] = two; // debug-loc(Stop here) +/*13*/} +)"; + + auto debugInterfaces = CompileAndCreateDxcDebug(hlsl, L"lib_6_6"); + auto Labels = GatherDebugLocLabelsFromDxcUtils(debugInterfaces); + auto dxilDebugger = debugInterfaces.debugInfo; + + // Case: same function called from two places in same top-level function. + // In this case, we expect the storage for the variable to be in the same + // place for both "instances" of the function: as a thread proceeds through + // the caller, it will write new values into the variable's storage during + // the second or subsequent invocations of the inlined function. + DWORD instructionOffset = + AdvanceUntilFunctionEntered(dxilDebugger, 0, L"CSMain"); + + instructionOffset = + Labels->FindInstructionOffsetForLabel(L"Stop in subroutine"); + CheckVariableDoesNOTExistsAtThisInstruction(dxilDebugger, instructionOffset, + L"zero"); + + instructionOffset = Labels->FindInstructionOffsetForLabel(L"Stop here"); + CheckVariableDoesNOTExistsAtThisInstruction(dxilDebugger, instructionOffset, + L"i2"); + CheckVariableExistsAtThisInstruction(dxilDebugger, instructionOffset, + L"zero"); +} + +TEST_F(PixDiaTest, DxcPixDxilDebugInfo_VariableScopes_Member) { + if (m_ver.SkipDxilVersion(1, 6)) + return; + + const char *hlsl = + R"(/*01*/RWStructuredBuffer intRWUAV: register(u0); +struct Struct { + int i; + int Getter() { + int q = i; + return q; //debug-loc(inside member fn) + } +}; +[shader("compute")] +[numthreads(1,1,1)] +void CSMain() +{ + Struct s; + s.i = intRWUAV.Load(0); + int j = s.Getter(); + intRWUAV[0] = j; // debug-loc(Stop here) +} +)"; + + auto debugInterfaces = CompileAndCreateDxcDebug(hlsl, L"lib_6_6"); + auto Labels = GatherDebugLocLabelsFromDxcUtils(debugInterfaces); + auto dxilDebugger = debugInterfaces.debugInfo; + + // Case: same function called from two places in same top-level function. + // In this case, we expect the storage for the variable to be in the same + // place for both "instances" of the function: as a thread proceeds through + // the caller, it will write new values into the variable's storage during + // the second or subsequent invocations of the inlined function. + DWORD instructionOffset = + AdvanceUntilFunctionEntered(dxilDebugger, 0, L"CSMain"); + + instructionOffset = + Labels->FindInstructionOffsetForLabel(L"inside member fn"); + CheckVariableDoesNOTExistsAtThisInstruction(dxilDebugger, instructionOffset, + L"s"); + CheckVariableExistsAtThisInstruction(dxilDebugger, instructionOffset, L"q"); + + instructionOffset = Labels->FindInstructionOffsetForLabel(L"Stop here"); + CheckVariableDoesNOTExistsAtThisInstruction(dxilDebugger, instructionOffset, + L"i"); + CheckVariableExistsAtThisInstruction(dxilDebugger, instructionOffset, L"j"); +} + #endif diff --git a/tools/clang/unittests/HLSL/PixTestUtils.cpp b/tools/clang/unittests/HLSL/PixTestUtils.cpp index a4a8033099..4d4a8f2bb7 100644 --- a/tools/clang/unittests/HLSL/PixTestUtils.cpp +++ b/tools/clang/unittests/HLSL/PixTestUtils.cpp @@ -274,6 +274,66 @@ PassOutput RunAnnotationPasses(dxc::DxcDllSupport &dllSupport, IDxcBlob *dxil, Tokenize(outputText.c_str(), "\n")}; } +class InstructionOffsetSeekerImpl : public InstructionOffsetSeeker { + + std::map m_labelToInstructionOffset; + +public: + InstructionOffsetSeekerImpl(DebuggerInterfaces &debuggerInterfaces) { + DWORD SourceFileOrdinal = 0; + CComBSTR fileName; + CComBSTR fileContent; + while (SUCCEEDED(debuggerInterfaces.compilationInfo->GetSourceFile( + SourceFileOrdinal, &fileName, &fileContent))) { + auto lines = strtok(std::wstring(fileContent), L"\n"); + for (size_t line = 0; line < lines.size(); ++line) { + const wchar_t DebugLocLabel[] = L"debug-loc("; + auto DebugLocPos = lines[line].find(DebugLocLabel); + if (DebugLocPos != std::wstring::npos) { + auto StartLabelPos = DebugLocPos + (_countof(DebugLocLabel) - 1); + auto CloseDebugLocPos = lines[line].find(L")", StartLabelPos); + if (CloseDebugLocPos == std::string::npos) { + VERIFY_ARE_NOT_EQUAL(CloseDebugLocPos, std::string::npos); + } + auto Label = lines[line].substr(StartLabelPos, + CloseDebugLocPos - StartLabelPos); + CComPtr InstructionOffsets; + if (FAILED((debuggerInterfaces.debugInfo + ->InstructionOffsetsFromSourceLocation( + fileName, line + 1, 0, &InstructionOffsets)))) { + VERIFY_FAIL(L"InstructionOffsetsFromSourceLocation failed"); + } + auto InstructionOffsetCount = InstructionOffsets->GetCount(); + if (InstructionOffsetCount == 0) { + VERIFY_FAIL(L"Instruction offset count was zero"); + } + if (m_labelToInstructionOffset.find(Label) != + m_labelToInstructionOffset.end()) { + VERIFY_FAIL(L"Duplicate label found!"); + } + // Just the last offset is sufficient: + m_labelToInstructionOffset[Label] = + InstructionOffsets->GetOffsetByIndex(InstructionOffsetCount - 1); + } + } + SourceFileOrdinal++; + fileName.Empty(); + fileContent.Empty(); + } + } + + virtual DWORD FindInstructionOffsetForLabel(const wchar_t *label) override { + VERIFY_ARE_NOT_EQUAL(m_labelToInstructionOffset.find(label), + m_labelToInstructionOffset.end()); + return m_labelToInstructionOffset[label]; + } +}; + +std::unique_ptr +GatherDebugLocLabelsFromDxcUtils(DebuggerInterfaces &debuggerInterfaces) { + return std::make_unique(debuggerInterfaces); +} + CComPtr GetDebugPart(dxc::DxcDllSupport &dllSupport, IDxcBlob *container) { diff --git a/tools/clang/unittests/HLSL/PixTestUtils.h b/tools/clang/unittests/HLSL/PixTestUtils.h index fd9ad9d736..8f7d0cdf45 100644 --- a/tools/clang/unittests/HLSL/PixTestUtils.h +++ b/tools/clang/unittests/HLSL/PixTestUtils.h @@ -12,8 +12,9 @@ #pragma once #include "dxc/Support/WinIncludes.h" -#include "dxc/dxcapi.h" +#include "dxc/dxcpix.h" +#include #include #include @@ -57,4 +58,19 @@ struct PassOutput { PassOutput RunAnnotationPasses(dxc::DxcDllSupport &dllSupport, IDxcBlob *dxil, int startingLineNumber = 0); + +struct DebuggerInterfaces { + CComPtr debugInfo; + CComPtr compilationInfo; +}; + +class InstructionOffsetSeeker { +public: + virtual ~InstructionOffsetSeeker() {} + virtual DWORD FindInstructionOffsetForLabel(const wchar_t *label) = 0; +}; + +std::unique_ptr +GatherDebugLocLabelsFromDxcUtils(DebuggerInterfaces &debuggerInterfaces); + } // namespace pix_test