diff options
| author | Jay Kwak <82421531+jkwak-work@users.noreply.github.com> | 2025-08-28 10:45:07 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-08-28 17:45:07 +0000 |
| commit | c19e2e92ae8e713225262a17f39a438cd511d416 (patch) | |
| tree | 7c78e65d3c826c52b527c71500a72ecb18754254 /tools/slang-test | |
| parent | 3dc466487d489f09c835bdd872eb130cdc5784ea (diff) | |
Remove the embedded source to avoid self-matching in slang-test (#8305)
When `SIMPLE` type test is used with `-g[1-3]` option, the filecheck
pattern will most likely to match to the string itself on the embedded
source code rather than match to the emitted spirv-asm code.
This commit avoids the problem by removing the embedded source code.
This commit also provides an option to keep the embedded source code,
`-preserve-embedded-source`.
The source code removal is happening in two steps:
1. iterate all output lines and find SPIRV-ASM in the following pattern:
`%N = OpExtInst %void %M DebugSource %fileId %sourceId`. And then, store
the "%sourceId" value to identify which SPIRV instructions are for the
embedded source code.
2. iterate all output lines again to find the `%sourceId = OpString
"...."` and replace the whole string with the following string, ``` %1 =
OpString "// slang-test removed the embedded source // Use
`-preserve-embedded-source` to keep it explicitly " ```
This change revealed problems in the existing tests:
- tests/bugs/spirv-debug-info.slang : The expected text was missing and
it had to be added. The file also had Carrage-Return character on all
lines and the pre-commit git hook removed them.
- tests/spirv/debug-info.slang : the expected keyword DebugValue had to
change to DebugDeclare, because that's what we get with ToT.
- tests/spirv/debug-value-dynamic-index.slang : This test is currently
failing, and it will pass once DebugLocalVariable instruction missing
for parameter of the entry point function #7693 is resolved.
---------
Co-authored-by: slangbot <ellieh+slangbot@nvidia.com>
Diffstat (limited to 'tools/slang-test')
| -rw-r--r-- | tools/slang-test/slang-test-main.cpp | 107 |
1 files changed, 105 insertions, 2 deletions
diff --git a/tools/slang-test/slang-test-main.cpp b/tools/slang-test/slang-test-main.cpp index 3f707b5e5..6c0de13ec 100644 --- a/tools/slang-test/slang-test-main.cpp +++ b/tools/slang-test/slang-test-main.cpp @@ -54,6 +54,9 @@ SLANG_RHI_EXPORT_AGILITY_SDK using namespace Slang; +// Constants for slang-test specific options +static const char* kPreserveEmbeddedSourceOption = "-preserve-embedded-source"; + // Options for a particular test struct TestOptions { @@ -1531,7 +1534,94 @@ ToolReturnCode spawnAndWait( return getReturnCode(outExeRes); } -String getOutput(const ExecuteResult& exeRes) +// Remove embedded source code from SPIR-V assembly output to prevent filecheck from matching +// against embedded source instead of actual SPIR-V instructions +String removeEmbeddedSourceFromSPIRV(const String& spirvOutput) +{ + StringBuilder filteredOutput; + List<UnownedStringSlice> lines; + StringUtil::calcLines(spirvOutput.getUnownedSlice(), lines); + + if (spirvOutput.endsWith("\n")) + { + // The last empty line should be removed, + // because `StringUtil::calcLines()` turns "A\nB\n" into three lines; not two. + SLANG_ASSERT(lines[lines.getCount() - 1] == ""); + lines.setCount(lines.getCount() - 1); + } + + // First pass: Find OpString IDs that are referenced by DebugSource + List<String> sourceStringIds; + for (const auto& line : lines) + { + UnownedStringSlice trimmedLine = line.trim(); + + if (trimmedLine.indexOf(UnownedStringSlice(" DebugSource ")) == Index(-1)) + continue; + + // Extract the last parameter which is the source string ID + // Pattern: %4 = OpExtInst %void %2 DebugSource %5 %1 + List<UnownedStringSlice> tokens; + StringUtil::split(trimmedLine, ' ', tokens); + + // The last token should be the source string ID + UnownedStringSlice lastToken = tokens.getLast(); + if (lastToken.startsWith(UnownedStringSlice("%"))) + { + sourceStringIds.add(String(lastToken)); + } + } + + // Second pass: Process embedded source strings to replace content with informative message + bool insideSourceString = false; + for (const auto& line : lines) + { + UnownedStringSlice trimmedLine = line.trim(); + + if (!insideSourceString) + { + Index equalPos = trimmedLine.indexOf(UnownedStringSlice(" = OpString")); + if (equalPos != Index(-1) && trimmedLine.startsWith(UnownedStringSlice("%"))) + { + String currentStringId = String(trimmedLine.head(equalPos)); + if (sourceStringIds.contains(currentStringId)) + { + insideSourceString = true; + Index quotePos = line.indexOf('\"'); + if (quotePos != Index(-1)) + { + filteredOutput.append(String(line.head(quotePos + 1))); + filteredOutput.append("// slang-test removed the embedded source\n"); + filteredOutput.append("// Use `"); + filteredOutput.append(kPreserveEmbeddedSourceOption); + filteredOutput.append("` to keep it explicitly\n\"\n"); + } + continue; + } + } + } + + if (insideSourceString) + { + if (trimmedLine.endsWith("\"") && + (trimmedLine.getLength() < 2 || trimmedLine[trimmedLine.getLength() - 2] != '\\')) + { + insideSourceString = false; + } + + // skip the embedded source lines + continue; + } + + // Add this line to the filtered output + filteredOutput.append(line); + filteredOutput.append("\n"); + } + + return filteredOutput.produceString(); +} + +String getOutput(const ExecuteResult& exeRes, bool removeEmbeddedSource = false) { ExecuteResult::ResultCode resultCode = exeRes.resultCode; @@ -1539,6 +1629,12 @@ String getOutput(const ExecuteResult& exeRes) String standardError = exeRes.standardError; String debugLayer = exeRes.debugLayer; + // Apply embedded source removal to standard output if requested + if (removeEmbeddedSource) + { + standardOuptut = removeEmbeddedSourceFromSPIRV(standardOuptut); + } + // We construct a single output string that captures the results StringBuilder actualOutputBuilder; actualOutputBuilder.append("result code = "); @@ -2325,6 +2421,9 @@ TestResult runSimpleTest(TestContext* context, TestInput& input) for (auto arg : input.testOptions->args) { + // Filter out slang-test specific options that shouldn't be passed to slangc + if (arg == kPreserveEmbeddedSourceOption) + continue; cmdLine.addArg(arg); } @@ -2366,7 +2465,11 @@ TestResult runSimpleTest(TestContext* context, TestInput& input) exeRes = runExeRes; } - String actualOutput = getOutput(exeRes); + bool needToRemoveEmbeddedSource = + ((target == SLANG_SPIRV || target == SLANG_SPIRV_ASM) && + input.testOptions->args.indexOf(kPreserveEmbeddedSourceOption) == Index(-1)); + + String actualOutput = getOutput(exeRes, needToRemoveEmbeddedSource); return _validateOutput( context, |
