diff --git a/include/dxc/DXIL/DxilModule.h b/include/dxc/DXIL/DxilModule.h index 3f1ba12f86..baab38f671 100644 --- a/include/dxc/DXIL/DxilModule.h +++ b/include/dxc/DXIL/DxilModule.h @@ -205,6 +205,7 @@ class DxilModule { void ResetEntryPropsMap(DxilEntryPropsMap &&PropMap); bool StripReflection(); + bool StripNamesSensitiveToDebug(); void StripDebugRelatedCode(); void RemoveUnusedTypeAnnotations(); diff --git a/include/dxc/HLSL/DxilGenerationPass.h b/include/dxc/HLSL/DxilGenerationPass.h index 7348bbd4d6..a3b49c6c6d 100644 --- a/include/dxc/HLSL/DxilGenerationPass.h +++ b/include/dxc/HLSL/DxilGenerationPass.h @@ -82,6 +82,7 @@ FunctionPass *createMatrixBitcastLowerPass(); ModulePass *createDxilCleanupAddrSpaceCastPass(); ModulePass *createDxilRenameResourcesPass(); ModulePass *createDxilScalarizeVectorIntrinsicsPass(); +ModulePass *createDxilStripDebugSensitiveInfoPass(); void initializeDxilLowerCreateHandleForLibPass(llvm::PassRegistry &); void initializeDxilAllocateResourcesForLibPass(llvm::PassRegistry &); @@ -117,6 +118,7 @@ void initializeMatrixBitcastLowerPassPass(llvm::PassRegistry &); void initializeDxilCleanupAddrSpaceCastPass(llvm::PassRegistry &); void initializeDxilRenameResourcesPass(llvm::PassRegistry &); void initializeDxilScalarizeVectorIntrinsicsPass(llvm::PassRegistry &); +void initializeDxilStripDebugSensitiveInfoPass(llvm::PassRegistry &); ModulePass *createDxilValidateWaveSensitivityPass(); void initializeDxilValidateWaveSensitivityPass(llvm::PassRegistry &); diff --git a/include/dxc/HLSL/DxilLinker.h b/include/dxc/HLSL/DxilLinker.h index c7eae51574..c0ab38fbe5 100644 --- a/include/dxc/HLSL/DxilLinker.h +++ b/include/dxc/HLSL/DxilLinker.h @@ -42,6 +42,7 @@ class DxilLinker { void SetValidatorVersion(unsigned valMajor, unsigned valMinor) { m_valMajor = valMajor, m_valMinor = valMinor; } + void SetStripDebug(bool StripDebug) { m_StripDebug = StripDebug; } virtual bool HasLibNameRegistered(llvm::StringRef name) = 0; virtual bool RegisterLib(llvm::StringRef name, std::unique_ptr pModule, @@ -56,9 +57,11 @@ class DxilLinker { protected: DxilLinker(llvm::LLVMContext &Ctx, unsigned valMajor, unsigned valMinor) - : m_ctx(Ctx), m_valMajor(valMajor), m_valMinor(valMinor) {} + : m_ctx(Ctx), m_valMajor(valMajor), m_valMinor(valMinor), + m_StripDebug(false) {} llvm::LLVMContext &m_ctx; unsigned m_valMajor, m_valMinor; + bool m_StripDebug; }; } // namespace hlsl diff --git a/include/llvm/Transforms/IPO/PassManagerBuilder.h b/include/llvm/Transforms/IPO/PassManagerBuilder.h index 2f342d9412..09622aac4f 100644 --- a/include/llvm/Transforms/IPO/PassManagerBuilder.h +++ b/include/llvm/Transforms/IPO/PassManagerBuilder.h @@ -140,6 +140,7 @@ class PassManagerBuilder { bool HLSLEnableDebugNops = false; // HLSL Change bool HLSLEarlyInlining = true; // HLSL Change bool HLSLNoSink = false; // HLSL Change + bool StripDebug = false; void addHLSLPasses(legacy::PassManagerBase &MPM); // HLSL Change private: diff --git a/lib/DXIL/DxilModule.cpp b/lib/DXIL/DxilModule.cpp index f4abdd15aa..70b46b3bb4 100644 --- a/lib/DXIL/DxilModule.cpp +++ b/lib/DXIL/DxilModule.cpp @@ -31,6 +31,7 @@ #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/TypeFinder.h" #include "llvm/Support/raw_ostream.h" #include @@ -1826,6 +1827,56 @@ bool DxilModule::StripReflection() { return bChanged; } +bool DxilModule::StripNamesSensitiveToDebug() { + bool changed = false; + + if (!GetShaderModel()->IsLib()) { + // Strip struct names + unsigned nextStructId = 0; + TypeFinder StructTypes; + StructTypes.run(*m_pModule, true); + for (StructType *STy : StructTypes) { + if (!STy->hasName()) + continue; + + StringRef Name = STy->getName(); + if (Name.startswith("dx.")) + continue; + + STy->setName((Twine("dx.strip.struct.") + Twine(nextStructId++)).str()); + changed = true; + } + + // Strip entry function name + if (m_pEntryFunc) { + SetEntryFunctionName("dx.strip.entry."); + m_pEntryFunc->setName("dx.strip.entry."); + changed = true; + } + + // Strip groupshared variable names + unsigned nextGroupSharedId = 0; + for (GlobalVariable &globalVar : m_pModule->globals()) { + if (globalVar.getType()->getPointerAddressSpace() == + DXIL::kTGSMAddrSpace && + globalVar.hasName()) { + StringRef Name = globalVar.getName(); + if (Name.startswith("dx.") || Name.startswith("llvm.")) + continue; + globalVar.setName( + (Twine("dx.strip.tgsm.") + Twine(nextGroupSharedId++)).str()); + changed = true; + } + } + + // ReEmit meta. + if (changed) + ReEmitDxilResources(); + } + + return changed; +} + static void RemoveTypesFromSet(Type *Ty, SetVector &typeSet) { if (Ty->isPointerTy()) diff --git a/lib/HLSL/CMakeLists.txt b/lib/HLSL/CMakeLists.txt index 7677e8be41..2734c5aeb6 100644 --- a/lib/HLSL/CMakeLists.txt +++ b/lib/HLSL/CMakeLists.txt @@ -27,6 +27,7 @@ add_llvm_library(LLVMHLSL DxilRenameResourcesPass.cpp DxilScalarizeVectorIntrinsics.cpp DxilSimpleGVNHoist.cpp + DxilStripDebugSensitiveInfo.cpp DxilSignatureValidation.cpp DxilTargetLowering.cpp DxilTargetTransformInfo.cpp diff --git a/lib/HLSL/DxilLinker.cpp b/lib/HLSL/DxilLinker.cpp index ea10b23a4c..b7687b45ad 100644 --- a/lib/HLSL/DxilLinker.cpp +++ b/lib/HLSL/DxilLinker.cpp @@ -349,9 +349,9 @@ namespace { // Create module from link defines. struct DxilLinkJob { DxilLinkJob(LLVMContext &Ctx, dxilutil::ExportMap &exportMap, - unsigned valMajor, unsigned valMinor) + unsigned valMajor, unsigned valMinor, bool StripDebug) : m_ctx(Ctx), m_exportMap(exportMap), m_valMajor(valMajor), - m_valMinor(valMinor) {} + m_valMinor(valMinor), m_StripDebug(StripDebug) {} std::unique_ptr Link(std::pair &entryLinkPair, const ShaderModel *pSM); @@ -394,6 +394,7 @@ struct DxilLinkJob { LLVMContext &m_ctx; dxilutil::ExportMap &m_exportMap; unsigned m_valMajor, m_valMinor; + bool m_StripDebug; }; } // namespace @@ -1296,6 +1297,9 @@ void DxilLinkJob::RunPreparePass(Module &M) { PM.add(createDxilEmitMetadataPass()); PM.add(createDxilFinalizePreservesPass()); + if (m_StripDebug) + PM.add(createDxilStripDebugSensitiveInfoPass()); + PM.run(M); } @@ -1488,7 +1492,7 @@ DxilLinkerImpl::Link(StringRef entry, StringRef profile, return nullptr; } - DxilLinkJob linkJob(m_ctx, exportMap, m_valMajor, m_valMinor); + DxilLinkJob linkJob(m_ctx, exportMap, m_valMajor, m_valMinor, m_StripDebug); SetVector libSet; SetVector addedFunctionSet; diff --git a/lib/HLSL/DxilStripDebugSensitiveInfo.cpp b/lib/HLSL/DxilStripDebugSensitiveInfo.cpp new file mode 100644 index 0000000000..66bd85389a --- /dev/null +++ b/lib/HLSL/DxilStripDebugSensitiveInfo.cpp @@ -0,0 +1,47 @@ +/////////////////////////////////////////////////////////////////////////////// +// // +// DxilStripDebugSensitiveInfo.cpp // +// Copyright (C) Microsoft Corporation. All rights reserved. // +// This file is distributed under the University of Illinois Open Source // +// License. See LICENSE.TXT for details. // +// // +// Pass to strip debug-sensitive information from DXIL modules. // +// // +/////////////////////////////////////////////////////////////////////////////// + +#include "dxc/DXIL/DxilModule.h" +#include "dxc/HLSL/DxilGenerationPass.h" +#include "llvm/IR/Module.h" +#include "llvm/Pass.h" + +using namespace llvm; +using namespace hlsl; + +namespace { + +class DxilStripDebugSensitiveInfo : public ModulePass { +public: + static char ID; + explicit DxilStripDebugSensitiveInfo() : ModulePass(ID) {} + + StringRef getPassName() const override { + return "DXIL Strip Debug-Sensitive Information"; + } + + bool runOnModule(Module &M) override { + if (!M.HasDxilModule()) + return false; + return M.GetOrCreateDxilModule().StripNamesSensitiveToDebug(); + } +}; + +char DxilStripDebugSensitiveInfo::ID = 0; + +} // namespace + +ModulePass *llvm::createDxilStripDebugSensitiveInfoPass() { + return new DxilStripDebugSensitiveInfo(); +} + +INITIALIZE_PASS(DxilStripDebugSensitiveInfo, "hlsl-dxil-strip-debug-info", + "HLSL DXIL Strip Debug-Sensitive Information", false, false) diff --git a/lib/Transforms/IPO/PassManagerBuilder.cpp b/lib/Transforms/IPO/PassManagerBuilder.cpp index 46dc5508b9..b3509adfd8 100644 --- a/lib/Transforms/IPO/PassManagerBuilder.cpp +++ b/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -132,6 +132,7 @@ PassManagerBuilder::PassManagerBuilder() { VerifyOutput = false; MergeFunctions = false; PrepareForLTO = false; + StripDebug = false; } PassManagerBuilder::~PassManagerBuilder() { @@ -393,6 +394,8 @@ void PassManagerBuilder::populateModulePassManager( MPM.add(createDxilDeleteRedundantDebugValuesPass()); MPM.add(createNoPausePassesPass()); MPM.add(createDxilEmitMetadataPass()); + if (StripDebug) + MPM.add(createDxilStripDebugSensitiveInfoPass()); } // HLSL Change Ends. return; @@ -712,6 +715,8 @@ void PassManagerBuilder::populateModulePassManager( MPM.add(createNoPausePassesPass()); MPM.add(createDxilValidateWaveSensitivityPass()); MPM.add(createDxilEmitMetadataPass()); + if (StripDebug) + MPM.add(createDxilStripDebugSensitiveInfoPass()); } // HLSL Change Ends. addExtensionsToPM(EP_OptimizerLast, MPM); diff --git a/tools/clang/include/clang/Frontend/CodeGenOptions.h b/tools/clang/include/clang/Frontend/CodeGenOptions.h index 859cba53da..adfbcc1ed9 100644 --- a/tools/clang/include/clang/Frontend/CodeGenOptions.h +++ b/tools/clang/include/clang/Frontend/CodeGenOptions.h @@ -170,6 +170,8 @@ class CodeGenOptions : public CodeGenOptionsBase { /// Name of the profile file to use as input for -fprofile-instr-use std::string InstrProfileInput; + bool StripDebug = false; + /// A list of file names passed with -fcuda-include-gpubinary options to /// forward to CUDA runtime back-end for incorporating them into host-side /// object file. diff --git a/tools/clang/lib/CodeGen/BackendUtil.cpp b/tools/clang/lib/CodeGen/BackendUtil.cpp index 52d77bf115..01aff6b808 100644 --- a/tools/clang/lib/CodeGen/BackendUtil.cpp +++ b/tools/clang/lib/CodeGen/BackendUtil.cpp @@ -361,6 +361,7 @@ void EmitAssemblyHelper::CreatePasses() { OptToggles.IsEnabled(hlsl::options::TOGGLE_PARTIAL_LIFETIME_MARKERS); PMBuilder.HLSLEnableAggressiveReassociation = OptToggles.IsEnabled( hlsl::options::TOGGLE_ENABLE_AGGRESSIVE_REASSOCIATION); + PMBuilder.StripDebug = CodeGenOpts.StripDebug; // HLSL Change - end PMBuilder.DisableUnitAtATime = !CodeGenOpts.UnitAtATime; diff --git a/tools/clang/tools/dxcompiler/dxclinker.cpp b/tools/clang/tools/dxcompiler/dxclinker.cpp index f5427ccc08..16748faf22 100644 --- a/tools/clang/tools/dxcompiler/dxclinker.cpp +++ b/tools/clang/tools/dxcompiler/dxclinker.cpp @@ -306,6 +306,7 @@ HRESULT STDMETHODCALLTYPE DxcLinker::Link( dxcutil::GetValidatorVersion(&valMajor, &valMinor); } m_pLinker->SetValidatorVersion(valMajor, valMinor); + m_pLinker->SetStripDebug(opts.StripDebug); // Root signature-only container validation is only supported on 1.5 and // above. @@ -415,6 +416,7 @@ HRESULT STDMETHODCALLTYPE DxcLinker::Link( SerializeFlags, pOutputStream, 0, opts.DebugFile, &Diag, &ShaderHashContent, pReflectionStream, pRootSigStream, nullptr, nullptr); + if (needsValidation) { valHR = dxcutil::ValidateAndAssembleToContainer(inputs); } else { diff --git a/tools/clang/tools/dxcompiler/dxcompilerobj.cpp b/tools/clang/tools/dxcompiler/dxcompilerobj.cpp index 230047b4a8..b81e544aac 100644 --- a/tools/clang/tools/dxcompiler/dxcompilerobj.cpp +++ b/tools/clang/tools/dxcompiler/dxcompilerobj.cpp @@ -1608,6 +1608,7 @@ class DxcCompiler : public IDxcCompiler3, Opts.EnableLifetimeMarkers; compiler.getCodeGenOpts().HLSLEnablePayloadAccessQualifiers = Opts.EnablePayloadQualifiers; + compiler.getCodeGenOpts().StripDebug = Opts.StripDebug; // Translate signature packing options if (Opts.PackPrefixStable) diff --git a/tools/clang/unittests/HLSL/DxilContainerTest.cpp b/tools/clang/unittests/HLSL/DxilContainerTest.cpp index 5869923802..89b4c889a2 100644 --- a/tools/clang/unittests/HLSL/DxilContainerTest.cpp +++ b/tools/clang/unittests/HLSL/DxilContainerTest.cpp @@ -118,8 +118,11 @@ class DxilContainerTest : public ::testing::Test { TEST_METHOD(DxilContainerUnitTest) TEST_METHOD(DxilContainerCompilerVersionTest) TEST_METHOD(ContainerBuilder_AddPrivateForceLast) - TEST_METHOD(ReflectionMatchesDXBC_CheckIn) + TEST_METHOD(StripReflectionRemovesStructNames) + TEST_METHOD(StripReflectionRemovesEntryFunctionName) + TEST_METHOD(StripReflectionRemovesGroupsharedNames) + TEST_METHOD(StripReflectionLibraryDoesNotStripNames) BEGIN_TEST_METHOD(ReflectionMatchesDXBC_Full) TEST_METHOD_PROPERTY(L"Priority", L"1") END_TEST_METHOD() @@ -607,12 +610,14 @@ class DxilContainerTest : public ::testing::Test { } std::string DisassembleProgram(LPCSTR program, LPCWSTR entryPoint, - LPCWSTR target) { + LPCWSTR target, LPCWSTR *pArguments = nullptr, + UINT32 argCount = 0) { CComPtr pCompiler; CComPtr pProgram; CComPtr pDisassembly; - CompileToProgram(program, entryPoint, target, nullptr, 0, &pProgram); + CompileToProgram(program, entryPoint, target, pArguments, argCount, + &pProgram); VERIFY_SUCCEEDED(CreateCompiler(&pCompiler)); VERIFY_SUCCEEDED(pCompiler->Disassemble(pProgram, &pDisassembly)); return BlobToUtf8(pDisassembly); @@ -893,54 +898,54 @@ TEST_F(DxilContainerTest, CompileWhenOKThenIncludesSignatures) { std::string s = DisassembleProgram(program, L"VSMain", L"vs_6_0"); // NOTE: this will change when proper packing is done, and when // 'always-reads' is accurately implemented. - const char - expected_1_4[] = ";\n" - "; Input signature:\n" - ";\n" - "; Name Index Mask Register " - "SysValue Format Used\n" - "; -------------------- ----- ------ -------- " - "-------- ------- ------\n" - "; POSITION 0 xyzw 0 " - "NONE float \n" // should read 'xyzw' in Used - "; COLOR 0 xyzw 1 " - "NONE float \n" // should read '1' in register - ";\n" - ";\n" - "; Output signature:\n" - ";\n" - "; Name Index Mask Register " - "SysValue Format Used\n" - "; -------------------- ----- ------ -------- " - "-------- ------- ------\n" - "; SV_Position 0 xyzw 0 " - "POS float xyzw\n" // could read SV_POSITION - "; COLOR 0 xyzw 1 " - "NONE float xyzw\n"; // should read '1' in register - const char - expected[] = ";\n" - "; Input signature:\n" - ";\n" - "; Name Index Mask Register SysValue " - "Format Used\n" - "; -------------------- ----- ------ -------- -------- " - "------- ------\n" - "; POSITION 0 xyzw 0 NONE " - "float xyzw\n" // should read 'xyzw' in Used - "; COLOR 0 xyzw 1 NONE " - "float xyzw\n" // should read '1' in register - ";\n" - ";\n" - "; Output signature:\n" - ";\n" - "; Name Index Mask Register SysValue " - "Format Used\n" - "; -------------------- ----- ------ -------- -------- " - "------- ------\n" - "; SV_Position 0 xyzw 0 POS " - "float xyzw\n" // could read SV_POSITION - "; COLOR 0 xyzw 1 NONE " - "float xyzw\n"; // should read '1' in register + const char expected_1_4[] = + ";\n" + "; Input signature:\n" + ";\n" + "; Name Index Mask Register " + "SysValue Format Used\n" + "; -------------------- ----- ------ -------- " + "-------- ------- ------\n" + "; POSITION 0 xyzw 0 " + "NONE float \n" // should read 'xyzw' in Used + "; COLOR 0 xyzw 1 " + "NONE float \n" // should read '1' in register + ";\n" + ";\n" + "; Output signature:\n" + ";\n" + "; Name Index Mask Register " + "SysValue Format Used\n" + "; -------------------- ----- ------ -------- " + "-------- ------- ------\n" + "; SV_Position 0 xyzw 0 " + "POS float xyzw\n" // could read SV_POSITION + "; COLOR 0 xyzw 1 " + "NONE float xyzw\n"; // should read '1' in register + const char expected[] = + ";\n" + "; Input signature:\n" + ";\n" + "; Name Index Mask Register SysValue " + "Format Used\n" + "; -------------------- ----- ------ -------- -------- " + "------- ------\n" + "; POSITION 0 xyzw 0 NONE " + "float xyzw\n" // should read 'xyzw' in Used + "; COLOR 0 xyzw 1 NONE " + "float xyzw\n" // should read '1' in register + ";\n" + ";\n" + "; Output signature:\n" + ";\n" + "; Name Index Mask Register SysValue " + "Format Used\n" + "; -------------------- ----- ------ -------- -------- " + "------- ------\n" + "; SV_Position 0 xyzw 0 POS " + "float xyzw\n" // could read SV_POSITION + "; COLOR 0 xyzw 1 NONE " + "float xyzw\n"; // should read '1' in register if (hlsl::DXIL::CompareVersions(m_ver.m_ValMajor, m_ver.m_ValMinor, 1, 5) < 0) { std::string start(s.c_str(), strlen(expected_1_4)); @@ -955,52 +960,50 @@ TEST_F(DxilContainerTest, CompileWhenOKThenIncludesSignatures) { std::string s = DisassembleProgram(program, L"PSMain", L"ps_6_0"); // NOTE: this will change when proper packing is done, and when // 'always-reads' is accurately implemented. - const char - expected_1_4[] = - ";\n" - "; Input signature:\n" - ";\n" - "; Name Index Mask Register SysValue Format " - "Used\n" - "; -------------------- ----- ------ -------- -------- ------- " - "------\n" - "; SV_Position 0 xyzw 0 POS float " - " \n" // could read SV_POSITION - "; COLOR 0 xyzw 1 NONE float " - " \n" // should read '1' in register, xyzw in Used - ";\n" - ";\n" - "; Output signature:\n" - ";\n" - "; Name Index Mask Register SysValue Format " - "Used\n" - "; -------------------- ----- ------ -------- -------- ------- " - "------\n" - "; SV_Target 0 xyzw 0 TARGET float " - "xyzw\n"; // could read SV_TARGET - const char - expected[] = - ";\n" - "; Input signature:\n" - ";\n" - "; Name Index Mask Register SysValue Format " - "Used\n" - "; -------------------- ----- ------ -------- -------- ------- " - "------\n" - "; SV_Position 0 xyzw 0 POS float " - " \n" // could read SV_POSITION - "; COLOR 0 xyzw 1 NONE float " - "xyzw\n" // should read '1' in register, xyzw in Used - ";\n" - ";\n" - "; Output signature:\n" - ";\n" - "; Name Index Mask Register SysValue Format " - "Used\n" - "; -------------------- ----- ------ -------- -------- ------- " - "------\n" - "; SV_Target 0 xyzw 0 TARGET float " - "xyzw\n"; // could read SV_TARGET + const char expected_1_4[] = + ";\n" + "; Input signature:\n" + ";\n" + "; Name Index Mask Register SysValue Format " + "Used\n" + "; -------------------- ----- ------ -------- -------- ------- " + "------\n" + "; SV_Position 0 xyzw 0 POS float " + " \n" // could read SV_POSITION + "; COLOR 0 xyzw 1 NONE float " + " \n" // should read '1' in register, xyzw in Used + ";\n" + ";\n" + "; Output signature:\n" + ";\n" + "; Name Index Mask Register SysValue Format " + "Used\n" + "; -------------------- ----- ------ -------- -------- ------- " + "------\n" + "; SV_Target 0 xyzw 0 TARGET float " + "xyzw\n"; // could read SV_TARGET + const char expected[] = + ";\n" + "; Input signature:\n" + ";\n" + "; Name Index Mask Register SysValue Format " + "Used\n" + "; -------------------- ----- ------ -------- -------- ------- " + "------\n" + "; SV_Position 0 xyzw 0 POS float " + " \n" // could read SV_POSITION + "; COLOR 0 xyzw 1 NONE float " + "xyzw\n" // should read '1' in register, xyzw in Used + ";\n" + ";\n" + "; Output signature:\n" + ";\n" + "; Name Index Mask Register SysValue Format " + "Used\n" + "; -------------------- ----- ------ -------- -------- ------- " + "------\n" + "; SV_Target 0 xyzw 0 TARGET float " + "xyzw\n"; // could read SV_TARGET if (hlsl::DXIL::CompareVersions(m_ver.m_ValMajor, m_ver.m_ValMinor, 1, 5) < 0) { std::string start(s.c_str(), strlen(expected_1_4)); @@ -3081,3 +3084,86 @@ TEST_F(DxilContainerTest, DxilContainerUnitTest) { hlsl::GetDxilProgramHeader(&header, hlsl::DxilFourCC::DFCC_DXIL)); VERIFY_IS_NULL(hlsl::GetDxilPartByType(&header, hlsl::DxilFourCC::DFCC_DXIL)); } + +TEST_F(DxilContainerTest, StripReflectionRemovesStructNames) { + const char *Code = R"( + struct MyCustomStruct { + float4 position; + float4 color; + }; + + MyCustomStruct main() : SV_Target { + MyCustomStruct s; + s.position = float4(0, 0, 0, 1); + s.color = float4(1, 1, 1, 1); + return s; + } + )"; + + LPCWSTR StripDebug = L"-Qstrip_debug"; + + std::string disassembly = + DisassembleProgram(Code, L"main", L"ps_6_0", &StripDebug, 1); + + VERIFY_IS_TRUE(disassembly.find("MyCustomStruct") == std::string::npos); +} + +TEST_F(DxilContainerTest, StripReflectionRemovesEntryFunctionName) { + const char *Code = R"( + float4 MyCustomEntryPoint() : SV_Target { + return float4(1, 0, 0, 1); + } + )"; + + LPCWSTR StripDebug = L"-Qstrip_debug"; + + std::string disassembly = DisassembleProgram(Code, L"MyCustomEntryPoint", + L"ps_6_0", &StripDebug, 1); + + VERIFY_IS_TRUE(disassembly.find("MyCustomEntryPoint") == std::string::npos); + VERIFY_IS_TRUE(disassembly.find("dx.strip.entry.") != std::string::npos); +} + +TEST_F(DxilContainerTest, StripReflectionRemovesGroupsharedNames) { + const char *Code = R"( + groupshared float mySharedData[256]; + groupshared int mySharedCounter; + + [numthreads(8, 8, 1)] + void CSMain(uint3 dispatchThreadID : SV_DispatchThreadID) { + mySharedData[dispatchThreadID.x] = 1.0f; + mySharedCounter = 42; + } + )"; + + LPCWSTR StripDebug = L"-Qstrip_debug"; + + std::string disassembly = + DisassembleProgram(Code, L"CSMain", L"cs_6_0", &StripDebug, 1); + + VERIFY_IS_TRUE(disassembly.find("mySharedData") == std::string::npos); + VERIFY_IS_TRUE(disassembly.find("mySharedCounter") == std::string::npos); + VERIFY_IS_TRUE(disassembly.find("dx.strip.tgsm.") != std::string::npos); +} + +TEST_F(DxilContainerTest, StripReflectionLibraryDoesNotStripNames) { + const char *Code = R"( + struct MyLibStruct { + float val; + }; + + [shader("raygeneration")] + void MyRayGenEntry() { + MyLibStruct s; + s.val = 1.0f; + } + )"; + + LPCWSTR StripDebug = L"-Qstrip_debug"; + + std::string disassembly = + DisassembleProgram(Code, L"", L"lib_6_3", &StripDebug, 1); + + VERIFY_IS_TRUE(disassembly.find("MyLibStruct") != std::string::npos || + disassembly.find("dx.strip.struct.") == std::string::npos); +}