Browse Source

Merge pull request #2143 from tex3d/dxc-opts3

Add -Qembed_debug, don't embed debug info by default
Tex Riddell 6 years ago
parent
commit
e97d1b1c77

+ 8 - 0
include/dxc/Support/HLSLOptions.h

@@ -150,6 +150,7 @@ public:
   bool DisplayIncludeProcess = false; // OPT__vi
   bool RecompileFromBinary = false; // OPT _Recompile (Recompiling the DXBC binary file not .hlsl file)
   bool StripDebug = false; // OPT Qstrip_debug
+  bool EmbedDebug = false; // OPT Qembed_debug
   bool StripRootSignature = false; // OPT_Qstrip_rootsignature
   bool StripPrivate = false; // OPT_Qstrip_priv
   bool StripReflection = false; // OPT_Qstrip_reflect
@@ -167,6 +168,13 @@ public:
   bool IsRootSignatureProfile();
   bool IsLibraryProfile();
 
+  // Helpers to clarify interpretation of flags for behavior in implementation
+  bool IsDebugInfoEnabled();    // Zi
+  bool EmbedDebugInfo();        // Qembed_debug
+  bool EmbedPDBName();          // Zi or Fd
+  bool DebugFileIsDirectory();  // Fd ends in '\\'
+  llvm::StringRef GetPDBName(); // Fd name
+
   // SPIRV Change Starts
 #ifdef ENABLE_SPIRV_CODEGEN
   bool GenSPIRV;                    // OPT_spirv

+ 5 - 1
include/dxc/Support/HLSLOptions.td

@@ -330,7 +330,9 @@ def Fc : JoinedOrSeparate<["-", "/"], "Fc">, MetaVarName<"<file>">, HelpText<"Ou
 //def Fx : JoinedOrSeparate<["-", "/"], "Fx">, MetaVarName<"<file>">, HelpText<"Output assembly code and hex listing file">;
 def Fh : JoinedOrSeparate<["-", "/"], "Fh">, MetaVarName<"<file>">, HelpText<"Output header file containing object code">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
 def Fe : JoinedOrSeparate<["-", "/"], "Fe">, MetaVarName<"<file>">, HelpText<"Output warnings and errors to the given file">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
-def Fd : JoinedOrSeparate<["-", "/"], "Fd">, MetaVarName<"<file>">, HelpText<"Write debug information to the given file or directory; trail \\ to auto-generate and imply Qstrip_priv">, Flags<[CoreOption, DriverOption]>, Group<hlslcomp_Group>;
+def Fd : JoinedOrSeparate<["-", "/"], "Fd">, MetaVarName<"<file>">,
+  HelpText<"Write debug information to the given file, or automatically named file in directory when ending in '\\'">,
+  Flags<[CoreOption, DriverOption]>, Group<hlslcomp_Group>;
 def Vn : JoinedOrSeparate<["-", "/"], "Vn">, MetaVarName<"<name>">, HelpText<"Use <name> as variable name in header file">, Flags<[DriverOption]>, Group<hlslcomp_Group>;
 def Cc : Flag<["-", "/"], "Cc">, HelpText<"Output color coded assembly listings">, Group<hlslcomp_Group>, Flags<[DriverOption]>;
 def Ni : Flag<["-", "/"], "Ni">, HelpText<"Output instruction numbers in assembly listings">, Group<hlslcomp_Group>, Flags<[DriverOption]>;
@@ -349,6 +351,8 @@ def Qstrip_reflect : Flag<["-", "/"], "Qstrip_reflect">, Flags<[CoreOption]>, Gr
   HelpText<"Strip reflection data from shader bytecode  (must be used with /Fo <file>)">;
 def Qstrip_debug : Flag<["-", "/"], "Qstrip_debug">, Flags<[CoreOption]>, Group<hlslutil_Group>,
   HelpText<"Strip debug information from 4_0+ shader bytecode  (must be used with /Fo <file>)">;
+def Qembed_debug : Flag<["-", "/"], "Qembed_debug">, Flags<[CoreOption]>, Group<hlslutil_Group>,
+  HelpText<"Embed PDB in shader container (must be used with /Zi)">;
 def Qstrip_priv : Flag<["-", "/"], "Qstrip_priv">, Flags<[DriverOption]>, Group<hlslutil_Group>,
   HelpText<"Strip private data from shader bytecode  (must be used with /Fo <file>)">;
 

+ 37 - 5
lib/DxcSupport/HLSLOptions.cpp

@@ -12,6 +12,7 @@
 #include "llvm/Option/OptTable.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Path.h"
 #include "dxc/Support/Global.h"
 #include "dxc/Support/WinIncludes.h"
 #include "dxc/Support/HLSLOptions.h"
@@ -144,6 +145,28 @@ bool DxcOpts::IsLibraryProfile() {
   return TargetProfile.startswith("lib_");
 }
 
+bool DxcOpts::IsDebugInfoEnabled() {
+  return DebugInfo;
+}
+
+bool DxcOpts::EmbedDebugInfo() {
+  return EmbedDebug;
+}
+
+bool DxcOpts::EmbedPDBName() {
+  return IsDebugInfoEnabled() || !DebugFile.empty();
+}
+
+bool DxcOpts::DebugFileIsDirectory() {
+  return !DebugFile.empty() && llvm::sys::path::is_separator(DebugFile[DebugFile.size() - 1]);
+}
+
+llvm::StringRef DxcOpts::GetPDBName() {
+  if (!DebugFileIsDirectory())
+    return DebugFile;
+  return llvm::StringRef();
+}
+
 MainArgs::MainArgs(int argc, const wchar_t **argv, int skipArgCount) {
   if (argc > skipArgCount) {
     Utf8StringVector.reserve(argc - skipArgCount);
@@ -411,10 +434,10 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
   opts.OutputObject = Args.getLastArgValue(OPT_Fo);
   opts.OutputHeader = Args.getLastArgValue(OPT_Fh);
   opts.OutputWarningsFile = Args.getLastArgValue(OPT_Fe);
-  opts.UseColor = Args.hasFlag(OPT_Cc, OPT_INVALID);
-  opts.UseInstructionNumbers = Args.hasFlag(OPT_Ni, OPT_INVALID);
-  opts.UseInstructionByteOffsets = Args.hasFlag(OPT_No, OPT_INVALID);
-  opts.UseHexLiterals = Args.hasFlag(OPT_Lx, OPT_INVALID);
+  opts.UseColor = Args.hasFlag(OPT_Cc, OPT_INVALID, false);
+  opts.UseInstructionNumbers = Args.hasFlag(OPT_Ni, OPT_INVALID, false);
+  opts.UseInstructionByteOffsets = Args.hasFlag(OPT_No, OPT_INVALID, false);
+  opts.UseHexLiterals = Args.hasFlag(OPT_Lx, OPT_INVALID, false);
   opts.Preprocess = Args.getLastArgValue(OPT_P);
   opts.AstDump = Args.hasFlag(OPT_ast_dump, OPT_INVALID, false);
   opts.CodeGenHighLevel = Args.hasFlag(OPT_fcgl, OPT_INVALID, false);
@@ -533,6 +556,7 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
   opts.PreferFlowControl = Args.hasFlag(OPT_Gfp, OPT_INVALID, false);
   opts.RecompileFromBinary = Args.hasFlag(OPT_recompile, OPT_INVALID, false);
   opts.StripDebug = Args.hasFlag(OPT_Qstrip_debug, OPT_INVALID, false);
+  opts.EmbedDebug = Args.hasFlag(OPT_Qembed_debug, OPT_INVALID, false);
   opts.StripRootSignature = Args.hasFlag(OPT_Qstrip_rootsignature, OPT_INVALID, false);
   opts.StripPrivate = Args.hasFlag(OPT_Qstrip_priv, OPT_INVALID, false);
   opts.StripReflection = Args.hasFlag(OPT_Qstrip_reflect, OPT_INVALID, false);
@@ -609,8 +633,16 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
     return 1;
   }
 
+  if (opts.EmbedDebug && !opts.DebugInfo) {
+    errors << "Must enable debug info with /Zi for /Qembed_debug";
+    return 1;
+  }
+
   if (!opts.DebugNameForBinary && !opts.DebugNameForSource) {
-    opts.DebugNameForSource = true;
+    if (opts.DebugInfo)
+      opts.DebugNameForSource = true;
+    else
+      opts.DebugNameForBinary = true;
   }
   else if (opts.DebugNameForBinary && opts.DebugNameForSource) {
     errors << "Cannot specify both /Zss and /Zsb";

+ 42 - 57
lib/DxilContainer/DxilContainerAssembler.cpp

@@ -1567,10 +1567,6 @@ void hlsl::SerializeDxilContainerForModule(DxilModule *pModule,
   CComPtr<AbstractMemoryStream> pProgramStream = pInputProgramStream;
   bool bModuleStripped = false;
   bool bHasDebugInfo = HasDebugInfo(*pModule->GetModule());
-  const uint32_t DebugInfoNameHashLen = 32;   // 32 chars of MD5
-  const uint32_t DebugInfoNameSuffix = 4;     // '.lld'
-  const uint32_t DebugInfoNameNullAndPad = 4; // '\0\0\0\0'
-  CComPtr<AbstractMemoryStream> pHashStream;
   if (bHasDebugInfo) {
     uint32_t debugInUInt32, debugPaddingBytes;
     GetPaddedProgramPartSize(pInputProgramStream, debugInUInt32, debugPaddingBytes);
@@ -1583,6 +1579,10 @@ void hlsl::SerializeDxilContainerForModule(DxilModule *pModule,
     llvm::StripDebugInfo(*pModule->GetModule());
     pModule->StripDebugRelatedCode();
     bModuleStripped = true;
+  } else {
+    // If no debug info, clear DebugNameDependOnSource
+    // (it's default, and this scenario can happen)
+    Flags &= ~SerializeDxilFlags::DebugNameDependOnSource;
   }
 
   if (Flags & SerializeDxilFlags::StripReflectionFromDxilPart) {
@@ -1598,65 +1598,50 @@ void hlsl::SerializeDxilContainerForModule(DxilModule *pModule,
     WriteBitcodeToFile(pModule->GetModule(), outStream, true);
   }
 
-  if (bHasDebugInfo && (Flags & SerializeDxilFlags::IncludeDebugNamePart)) {
-    // If the debug name should be specific to the sources, base the name on the
-    // debug bitcode, which will include the source references, line numbers,
-    // etc. Otherwise, do it exclusively on the target shader bitcode.
-
-    pHashStream = (int)(Flags & SerializeDxilFlags::DebugNameDependOnSource)
+  // Serialize debug name if requested.
+  CComPtr<AbstractMemoryStream> pHashStream;
+  std::string DebugNameStr; // Used if constructing name based on hash
+  if (Flags & SerializeDxilFlags::IncludeDebugNamePart) {
+    if (DebugName.empty()) {
+      // If the debug name should be specific to the sources, base the name on the debug
+      // bitcode, which will include the source references, line numbers, etc. Otherwise,
+      // do it exclusively on the target shader bitcode.
+      pHashStream = (int)(Flags & SerializeDxilFlags::DebugNameDependOnSource)
                       ? CComPtr<AbstractMemoryStream>(pModuleBitcode)
                       : CComPtr<AbstractMemoryStream>(pProgramStream);
 
-    // Use user specified debug name if a) it's given and b) it's not a path
-    bool UseDebugName =
-        DebugName.size() && !DebugName.endswith(llvm::StringRef("\\"));
-
-    // Calculate the length of the name
-    const uint32_t NameLen = UseDebugName
-                                 ? DebugName.size()
-                                 : DebugInfoNameHashLen + DebugInfoNameSuffix;
+      ArrayRef<uint8_t> Data((uint8_t *)pHashStream->GetPtr(), pHashStream->GetPtrSize());
+      llvm::MD5 md5;
+      llvm::MD5::MD5Result md5Result;
+      SmallString<32> Hash;
+      md5.update(Data);
+      md5.final(md5Result);
+      md5.stringifyResult(md5Result, Hash);
+      DebugNameStr += Hash;
+      DebugNameStr += ".lld";
+      DebugName = DebugNameStr;
+    }
 
     // Calculate the size of the blob part.
-    const uint32_t DebugInfoContentLen =
-        sizeof(DxilShaderDebugName) + NameLen + DebugInfoNameNullAndPad;
+    const uint32_t DebugInfoContentLen = PSVALIGN4(
+        sizeof(DxilShaderDebugName) + DebugName.size() + 1); // 1 for null
+
+    writer.AddPart(DFCC_ShaderDebugName, DebugInfoContentLen,
+      [DebugName]
+      (AbstractMemoryStream *pStream)
+    {
+      DxilShaderDebugName NameContent;
+      NameContent.Flags = 0;
+      NameContent.NameLength = DebugName.size();
+      IFT(WriteStreamValue(pStream, NameContent));
 
-    writer.AddPart(
-        DFCC_ShaderDebugName, DebugInfoContentLen,
-        [DebugInfoNameSuffix, DebugInfoNameHashLen, UseDebugName, DebugName,
-         pHashStream](AbstractMemoryStream *pStream) {
-          DxilShaderDebugName NameContent;
-          NameContent.Flags = 0;
-
-          if (UseDebugName) {
-            NameContent.NameLength = DebugName.size();
-            IFT(WriteStreamValue(pStream, NameContent));
-
-            ULONG cbWritten;
-            IFT(pStream->Write(DebugName.begin(), DebugName.size(),
-                               &cbWritten));
-            const char Pad[] = {'\0', '\0', '\0', '\0'};
-            IFT(pStream->Write(Pad, _countof(Pad), &cbWritten));
-          } else {
-            NameContent.NameLength = DebugInfoNameHashLen + DebugInfoNameSuffix;
-            IFT(WriteStreamValue(pStream, NameContent));
-
-            ArrayRef<uint8_t> Data((uint8_t *)pHashStream->GetPtr(),
-                                   pHashStream->GetPtrSize());
-            llvm::MD5 md5;
-            llvm::MD5::MD5Result md5Result;
-            SmallString<32> Hash;
-            md5.update(Data);
-            md5.final(md5Result);
-            md5.stringifyResult(md5Result, Hash);
-
-            ULONG cbWritten;
-            IFT(pStream->Write(Hash.data(), Hash.size(), &cbWritten));
-            const char SuffixAndPad[] = {'.',  'l',  'l',  'd',
-                                         '\0', '\0', '\0', '\0'};
-            IFT(pStream->Write(SuffixAndPad, _countof(SuffixAndPad),
-                               &cbWritten));
-          }
-        });
+      ULONG cbWritten;
+      IFT(pStream->Write(DebugName.begin(), DebugName.size(), &cbWritten));
+      const char Pad[] = { '\0','\0','\0','\0' };
+      // Always writes at least one null to align size
+      unsigned padLen = (4 - ((sizeof(DxilShaderDebugName) + cbWritten) & 0x3));
+      IFT(pStream->Write(Pad, padLen, &cbWritten));
+    });
   }
 
   // Compute padded bitcode size.

+ 49 - 20
tools/clang/tools/dxc/dxclib/dxc.cpp

@@ -150,7 +150,10 @@ public:
   }
 
   int  Compile();
-  void Recompile(IDxcBlob *pSource, IDxcLibrary *pLibrary, IDxcCompiler *pCompiler, std::vector<LPCWSTR> &args, IDxcOperationResult **pCompileResult);
+  void Recompile(IDxcBlob *pSource, IDxcLibrary *pLibrary,
+                 IDxcCompiler *pCompiler, std::vector<LPCWSTR> &args,
+                 std::wstring &outputPDBPath, CComPtr<IDxcBlob> &pDebugBlob,
+                 IDxcOperationResult **pCompileResult);
   int DumpBinary();
   void Preprocess();
   void GetCompilerVersionInfo(llvm::raw_string_ostream &OS);
@@ -223,13 +226,12 @@ int DxcContext::ActOnBlob(IDxcBlob *pBlob, IDxcBlob *pDebugBlob, LPCWSTR pDebugB
       "found in the shader, please use the "
       "/Zi switch to generate debug "
       "information compiling this shader.");
-
     if (pDebugBlob != nullptr) {
       IFTBOOLMSG(pDebugBlobName && *pDebugBlobName, E_INVALIDARG,
         "/Fd was specified but no debug name was produced");
       WriteBlobToFile(pDebugBlob, pDebugBlobName);
-    }
-    else {
+    } else {
+      // Note: This is for load from binary case
       WritePartToFile(pBlob, hlsl::DFCC_ShaderDebugInfoDXIL, m_Opts.DebugFile);
     }
   }
@@ -542,7 +544,11 @@ public:
   }
 };
 
-void DxcContext::Recompile(IDxcBlob *pSource, IDxcLibrary *pLibrary, IDxcCompiler *pCompiler, std::vector<LPCWSTR> &args, IDxcOperationResult **ppCompileResult) {
+void DxcContext::Recompile(IDxcBlob *pSource, IDxcLibrary *pLibrary,
+                           IDxcCompiler *pCompiler, std::vector<LPCWSTR> &args,
+                           std::wstring &outputPDBPath,
+                           CComPtr<IDxcBlob> &pDebugBlob,
+                           IDxcOperationResult **ppCompileResult) {
 // Recompile currently only supported on Windows
 #ifdef _WIN32
   CComPtr<IDxcBlob> pTargetBlob;
@@ -689,11 +695,28 @@ void DxcContext::Recompile(IDxcBlob *pSource, IDxcLibrary *pLibrary, IDxcCompile
   }
 
   CComPtr<IDxcOperationResult> pResult;
-  IFT(pCompiler->Compile(pCompileSource, pMainFileName,
-    StringRefUtf16(EntryPoint),
-    StringRefUtf16(TargetProfile), ConcatArgs.data(),
-    ConcatArgs.size(), ConcatDefines.data(),
-    ConcatDefines.size(), pIncludeHandler, &pResult));
+
+  if (!m_Opts.DebugFile.empty()) {
+    CComPtr<IDxcCompiler2> pCompiler2;
+    CComHeapPtr<WCHAR> pDebugName;
+    Unicode::UTF8ToUTF16String(m_Opts.DebugFile.str().c_str(), &outputPDBPath);
+    IFT(pCompiler->QueryInterface(&pCompiler2));
+    IFT(pCompiler2->CompileWithDebug(
+        pCompileSource, pMainFileName, StringRefUtf16(EntryPoint),
+        StringRefUtf16(TargetProfile), ConcatArgs.data(), ConcatArgs.size(),
+        ConcatDefines.data(), ConcatDefines.size(), pIncludeHandler, &pResult,
+        &pDebugName, &pDebugBlob));
+    if (pDebugName.m_pData && m_Opts.DebugFileIsDirectory()) {
+      outputPDBPath += pDebugName.m_pData;
+    }
+  } else {
+    IFT(pCompiler->Compile(pCompileSource, pMainFileName,
+      StringRefUtf16(EntryPoint),
+      StringRefUtf16(TargetProfile), ConcatArgs.data(),
+      ConcatArgs.size(), ConcatDefines.data(),
+      ConcatDefines.size(), pIncludeHandler, &pResult));
+  }
+
   *ppCompileResult = pResult.Detach();
 #else
   assert(false && "Recompile is currently only supported on Windows.");
@@ -705,7 +728,7 @@ int DxcContext::Compile() {
   CComPtr<IDxcCompiler> pCompiler;
   CComPtr<IDxcOperationResult> pCompileResult;
   CComPtr<IDxcBlob> pDebugBlob;
-  std::wstring debugName;
+  std::wstring outputPDBPath;
   {
     CComPtr<IDxcBlobEncoding> pSource;
 
@@ -727,9 +750,9 @@ int DxcContext::Compile() {
     IFTARG(pSource->GetBufferSize() >= 4);
 
     if (m_Opts.RecompileFromBinary) {
-      Recompile(pSource, pLibrary, pCompiler, args, &pCompileResult);
-    }
-    else {
+      Recompile(pSource, pLibrary, pCompiler, args, outputPDBPath, pDebugBlob,
+                &pCompileResult);
+    } else {
       CComPtr<IDxcIncludeHandler> pIncludeHandler;
       IFT(pLibrary->CreateIncludeHandler(&pIncludeHandler));
 
@@ -744,10 +767,10 @@ int DxcContext::Compile() {
         }
       }
 
-      if (!m_Opts.DebugFile.empty() && m_Opts.DebugFile.endswith(llvm::StringRef("\\"))) {
-        args.push_back(L"/Qstrip_debug"); // implied
+      if (!m_Opts.DebugFile.empty()) {
         CComPtr<IDxcCompiler2> pCompiler2;
         CComHeapPtr<WCHAR> pDebugName;
+        Unicode::UTF8ToUTF16String(m_Opts.DebugFile.str().c_str(), &outputPDBPath);
         IFT(pCompiler.QueryInterface(&pCompiler2));
         IFT(pCompiler2->CompileWithDebug(
             pSource, StringRefUtf16(m_Opts.InputFile),
@@ -755,9 +778,8 @@ int DxcContext::Compile() {
             args.data(), args.size(), m_Opts.Defines.data(),
             m_Opts.Defines.size(), pIncludeHandler, &pCompileResult,
             &pDebugName, &pDebugBlob));
-        if (pDebugName.m_pData) {
-          Unicode::UTF8ToUTF16String(m_Opts.DebugFile.str().c_str(), &debugName);
-          debugName += pDebugName.m_pData;
+        if (pDebugName.m_pData && m_Opts.DebugFileIsDirectory()) {
+          outputPDBPath += pDebugName.m_pData;
         }
       } else {
         IFT(pCompiler->Compile(pSource, StringRefUtf16(m_Opts.InputFile),
@@ -767,6 +789,13 @@ int DxcContext::Compile() {
           m_Opts.Defines.size(), pIncludeHandler, &pCompileResult));
       }
     }
+
+    // When compiling we don't embed debug info if options don't ask for it.
+    // If user specified /Qstrip_debug, remove from m_Opts now so we don't
+    // try to modify the container to strip debug info that isn't there.
+    if (!m_Opts.EmbedDebugInfo()) {
+      m_Opts.StripDebug = false;
+    }
   }
 
   if (!m_Opts.OutputWarningsFile.empty()) {
@@ -786,7 +815,7 @@ int DxcContext::Compile() {
     pCompiler.Release();
     pCompileResult.Release();
     if (pProgram.p != nullptr) {
-      ActOnBlob(pProgram.p, pDebugBlob, debugName.c_str());
+      ActOnBlob(pProgram.p, pDebugBlob, outputPDBPath.c_str());
     }
   }
   return status;

+ 17 - 3
tools/clang/tools/dxcompiler/dxcassembler.cpp

@@ -32,6 +32,17 @@ using namespace hlsl;
 // This declaration is used for the locally-linked validator.
 HRESULT CreateDxcValidator(_In_ REFIID riid, _Out_ LPVOID *ppv);
 
+static bool HasDebugInfo(const Module &M) {
+  for (Module::const_named_metadata_iterator NMI = M.named_metadata_begin(),
+                                             NME = M.named_metadata_end();
+       NMI != NME; ++NMI) {
+    if (NMI->getName().startswith("llvm.dbg.")) {
+      return true;
+    }
+  }
+  return false;
+}
+
 class DxcAssembler : public IDxcAssembler {
 private:
   DXC_MICROCOM_TM_REF_FIELDS()      
@@ -130,9 +141,12 @@ HRESULT STDMETHODCALLTYPE DxcAssembler::AssembleToContainer(
     outStream.flush();
 
     CComPtr<IDxcBlob> pResultBlob;
-    static constexpr hlsl::SerializeDxilFlags flags = static_cast<hlsl::SerializeDxilFlags>(
-        static_cast<uint32_t>(SerializeDxilFlags::IncludeDebugNamePart) |
-        static_cast<uint32_t>(SerializeDxilFlags::IncludeDebugInfoPart));
+    hlsl::SerializeDxilFlags flags = hlsl::SerializeDxilFlags::None;
+    if (HasDebugInfo(*M)) {
+      flags |= SerializeDxilFlags::IncludeDebugInfoPart;
+      flags |= SerializeDxilFlags::IncludeDebugNamePart;
+      flags |= SerializeDxilFlags::DebugNameDependOnSource;
+    }
     dxcutil::AssembleToContainer(std::move(M), pResultBlob,
                                          TM.p, flags,
                                          pOutputStream);

+ 14 - 9
tools/clang/tools/dxcompiler/dxcompilerobj.cpp

@@ -573,12 +573,17 @@ public:
         outStream.flush();
 
         SerializeDxilFlags SerializeFlags = SerializeDxilFlags::None;
-        if (opts.DebugInfo) {
-          SerializeFlags = SerializeDxilFlags::IncludeDebugNamePart;
-          // Unless we want to strip it right away, include it in the container.
-          if (!opts.StripDebug || ppDebugBlob == nullptr) {
-            SerializeFlags |= SerializeDxilFlags::IncludeDebugInfoPart;
-          }
+        if (opts.EmbedPDBName()) {
+          SerializeFlags |= SerializeDxilFlags::IncludeDebugNamePart;
+        }
+        // If -Qembed_debug specified, embed the debug info.
+        // Or, if there is no output pointer for the debug blob (such as when called by Compile()),
+        // embed the debug info and emit a note.
+        if (opts.EmbedDebugInfo()) {
+          SerializeFlags |= SerializeDxilFlags::IncludeDebugInfoPart;
+        } else if (opts.DebugInfo && !ppDebugBlob) {
+          w << "warning: no output provided for debug - embedding PDB in shader container.  Use -Qembed_debug to silence this warning.\n";
+          SerializeFlags |= SerializeDxilFlags::IncludeDebugInfoPart;
         }
         if (opts.DebugNameForSource) {
           SerializeFlags |= SerializeDxilFlags::DebugNameDependOnSource;
@@ -595,7 +600,7 @@ public:
           if (needsValidation) {
             valHR = dxcutil::ValidateAndAssembleToContainer(
                 action.takeModule(), pOutputBlob, m_pMalloc, SerializeFlags,
-                pOutputStream, opts.DebugInfo, opts.DebugFile, compiler.getDiagnostics());
+                pOutputStream, opts.IsDebugInfoEnabled(), opts.GetPDBName(), compiler.getDiagnostics());
           } else {
             dxcutil::AssembleToContainer(action.takeModule(),
                                                  pOutputBlob, m_pMalloc,
@@ -638,7 +643,7 @@ public:
       HRESULT status;
       DXVERIFY_NOMSG(SUCCEEDED((*ppResult)->GetStatus(&status)));
       if (SUCCEEDED(status)) {
-        if (opts.DebugInfo && ppDebugBlob) {
+        if (opts.IsDebugInfoEnabled() && ppDebugBlob) {
           DXVERIFY_NOMSG(SUCCEEDED(pOutputStream.QueryInterface(ppDebugBlob)));
         }
         if (ppDebugBlobName) {
@@ -854,7 +859,7 @@ public:
 
     compiler.getFrontendOpts().Inputs.push_back(FrontendInputFile(pMainFile, IK_HLSL));
     // Setup debug information.
-    if (Opts.DebugInfo) {
+    if (Opts.IsDebugInfoEnabled()) {
       CodeGenOptions &CGOpts = compiler.getCodeGenOpts();
       CGOpts.setDebugInfo(CodeGenOptions::FullDebugInfo);
       CGOpts.DebugColumnInfo = 1;

+ 2 - 0
tools/clang/tools/libclang/CMakeLists.txt

@@ -184,6 +184,8 @@ if(ENABLE_SHARED)
 endif()
 endif() # HLSL Change
 
+add_dependencies(libclang TablegenHLSLOptions)  # HLSL Change
+
 # HLSL Change Starts
 # add_clang_library(${LIBCLANG_STATIC_TARGET_NAME} STATIC ${SOURCES})
 # target_link_libraries(${LIBCLANG_STATIC_TARGET_NAME} ${LIBS})

+ 7 - 4
tools/clang/unittests/HLSL/CompilerTest.cpp

@@ -830,7 +830,7 @@ public:
 
     VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
     CreateBlobFromText(hlsl, &pSource);
-    LPCWSTR args[] = { L"/Zi" };
+    LPCWSTR args[] = { L"/Zi", L"/Qembed_debug" };
     VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
       L"ps_6_0", args, _countof(args), nullptr, 0, nullptr, &pResult));
     VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
@@ -1255,7 +1255,7 @@ TEST_F(CompilerTest, CompileWhenDebugWorksThenStripDebug) {
                      "  return local;\r\n"
                      "}",
                      &pSource);
-  LPCWSTR args[] = {L"/Zi"};
+  LPCWSTR args[] = {L"/Zi", L"/Qembed_debug"};
 
   VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
                                       L"ps_6_0", args, _countof(args), nullptr,
@@ -1352,7 +1352,7 @@ TEST_F(CompilerTest, CompileThenAddCustomDebugName) {
     "}",
     &pSource);
 
-  LPCWSTR args[] = { L"/Zi", L"/Zss" };
+  LPCWSTR args[] = { L"/Zi", L"/Qembed_debug", L"/Zss" };
 
   VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"source.hlsl", L"main",
     L"ps_6_0", args, _countof(args), nullptr, 0,
@@ -2266,8 +2266,11 @@ static void CompileTestAndLoadDia(dxc::DxcDllSupport &dllSupport, IDiaDataSource
   CComPtr<IDxcLibrary> pLib;
   CComPtr<IDxcContainerReflection> pReflection;
   UINT32 index;
+  std::vector<LPCWSTR> args;
+  args.push_back(L"/Zi");
+  args.push_back(L"/Qembed_debug");
 
-  VerifyCompileOK(dllSupport, EmptyCompute, L"cs_6_0", L"/Zi", &pContainer);
+  VerifyCompileOK(dllSupport, EmptyCompute, L"cs_6_0", args, &pContainer);
   VERIFY_SUCCEEDED(dllSupport.CreateInstance(CLSID_DxcLibrary, &pLib));
   VERIFY_SUCCEEDED(dllSupport.CreateInstance(CLSID_DxcContainerReflection, &pReflection));
   VERIFY_SUCCEEDED(pReflection->Load(pContainer));

+ 5 - 4
tools/clang/unittests/HLSL/DxilContainerTest.cpp

@@ -522,9 +522,9 @@ bool DxilContainerTest::InitSupport() {
 TEST_F(DxilContainerTest, CompileWhenDebugSourceThenSourceMatters) {
   char program1[] = "float4 main() : SV_Target { return 0; }";
   char program2[] = "  float4 main() : SV_Target { return 0; }  ";
-  LPCWSTR Zi[] = { L"/Zi" };
-  LPCWSTR ZiZss[] = { L"/Zi", L"/Zss" };
-  LPCWSTR ZiZsb[] = { L"/Zi", L"/Zsb" };
+  LPCWSTR Zi[] = { L"/Zi", L"/Qembed_debug" };
+  LPCWSTR ZiZss[] = { L"/Zi", L"/Qembed_debug", L"/Zss" };
+  LPCWSTR ZiZsb[] = { L"/Zi", L"/Qembed_debug", L"/Zsb" };
   
   // No debug info, no debug name...
   std::string noName = CompileToDebugName(program1, L"main", L"ps_6_0", nullptr, 0);
@@ -1497,11 +1497,12 @@ TEST_F(DxilContainerTest, DxilContainerUnitTest) {
   CComPtr<IDxcOperationResult> pResult;
   std::vector<LPCWSTR> arguments;
   arguments.emplace_back(L"/Zi");
+  arguments.emplace_back(L"/Qembed_debug");
   
   VERIFY_SUCCEEDED(CreateCompiler(&pCompiler));
   CreateBlobFromText("float4 main() : SV_Target { return 0; }", &pSource);
   // Test DxilContainer with ShaderDebugInfoDXIL
-  VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", L"main", L"ps_6_0", arguments.data(), 1, nullptr, 0, nullptr, &pResult));
+  VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", L"main", L"ps_6_0", arguments.data(), arguments.size(), nullptr, 0, nullptr, &pResult));
   VERIFY_SUCCEEDED(pResult->GetResult(&pProgram));
   
   const hlsl::DxilContainerHeader *pHeader = static_cast<const hlsl::DxilContainerHeader *> (pProgram->GetBufferPointer());

+ 31 - 34
tools/clang/unittests/HLSL/LinkerTest.cpp

@@ -71,8 +71,8 @@ public:
         m_dllSupport.CreateInstance(CLSID_DxcLinker, pResultLinker));
   }
 
-  void CompileLib(LPCWSTR filename, IDxcBlob **pResultBlob, LPCWSTR *pArguments,
-                  UINT32 argCount) {
+  void CompileLib(LPCWSTR filename, IDxcBlob **pResultBlob,
+                  llvm::ArrayRef<LPCWSTR> pArguments = {}) {
     std::wstring fullPath = hlsl_test::GetPathToHlslDataFile(filename);
     CComPtr<IDxcBlobEncoding> pSource;
     CComPtr<IDxcLibrary> pLibrary;
@@ -89,15 +89,12 @@ public:
     VERIFY_SUCCEEDED(
         m_dllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler));
     VERIFY_SUCCEEDED(pCompiler->Compile(pSource, L"hlsl.hlsl", L"", shWide,
-                                        pArguments, argCount, nullptr, 0,
+                                        const_cast<LPCWSTR*>(pArguments.data()), pArguments.size(),
+                                        nullptr, 0,
                                         nullptr, &pResult));
     VERIFY_SUCCEEDED(pResult->GetResult(pResultBlob));
   }
 
-  void CompileLib(LPCWSTR filename, IDxcBlob **pResourceBlob) {
-    CompileLib(filename, pResourceBlob, nullptr, 0);
-  }
-
   void RegisterDxcModule(LPCWSTR pLibName, IDxcBlob *pBlob,
                          IDxcLinker *pLinker) {
     VERIFY_SUCCEEDED(pLinker->RegisterLibrary(pLibName, pBlob));
@@ -170,10 +167,10 @@ TEST_F(LinkerTest, RunLinkAllProfiles) {
   CreateLinker(&pLinker);
 
   LPCWSTR libName = L"entry";
-  LPCWSTR option[] = { L"-Zi" };
+  LPCWSTR option[] = { L"-Zi", L"-Qembed_debug" };
 
   CComPtr<IDxcBlob> pEntryLib;
-  CompileLib(L"..\\CodeGenHLSL\\lib_entries2.hlsl", &pEntryLib, option, 1);
+  CompileLib(L"..\\CodeGenHLSL\\lib_entries2.hlsl", &pEntryLib, option);
   RegisterDxcModule(libName, pEntryLib, pLinker);
 
   Link(L"vs_main", L"vs_6_0", pLinker, {libName}, {},{});
@@ -379,15 +376,15 @@ TEST_F(LinkerTest, RunLinkResRet) {
 }
 
 TEST_F(LinkerTest, RunLinkToLib) {
-  LPCWSTR option[] = {L"-Zi"};
+  LPCWSTR option[] = {L"-Zi", L"-Qembed_debug"};
 
   CComPtr<IDxcBlob> pEntryLib;
   CompileLib(L"..\\CodeGenHLSL\\linker\\lib_mat_entry2.hlsl",
-             &pEntryLib, option, 1);
+             &pEntryLib, option);
   CComPtr<IDxcBlob> pLib;
   CompileLib(
       L"..\\CodeGenHLSL\\linker\\lib_mat_cast2.hlsl",
-      &pLib, option, 1);
+      &pLib, option);
 
   CComPtr<IDxcLinker> pLinker;
   CreateLinker(&pLinker);
@@ -398,7 +395,7 @@ TEST_F(LinkerTest, RunLinkToLib) {
   LPCWSTR libName2 = L"test";
   RegisterDxcModule(libName2, pLib, pLinker);
 
-  Link(L"", L"lib_6_3", pLinker, {libName, libName2}, {"!llvm.dbg.cu"}, {});
+  Link(L"", L"lib_6_3", pLinker, {libName, libName2}, {"!llvm.dbg.cu"}, {}, option);
 }
 
 TEST_F(LinkerTest, RunLinkToLibExport) {
@@ -444,14 +441,14 @@ TEST_F(LinkerTest, RunLinkFailSelectRes) {
 }
 
 TEST_F(LinkerTest, RunLinkToLibWithUnresolvedFunctions) {
-  LPCWSTR option[] = { L"-Zi" };
+  LPCWSTR option[] = { L"-Zi", L"-Qembed_debug" };
 
   CComPtr<IDxcBlob> pLib1;
   CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func1.hlsl",
-             &pLib1, option, 1);
+             &pLib1, option);
   CComPtr<IDxcBlob> pLib2;
   CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func2.hlsl",
-             &pLib2, option, 1);
+             &pLib2, option);
 
   CComPtr<IDxcLinker> pLinker;
   CreateLinker(&pLinker);
@@ -474,14 +471,14 @@ TEST_F(LinkerTest, RunLinkToLibWithUnresolvedFunctions) {
 }
 
 TEST_F(LinkerTest, RunLinkToLibWithUnresolvedFunctionsExports) {
-  LPCWSTR option[] = { L"-Zi" };
+  LPCWSTR option[] = { L"-Zi", L"-Qembed_debug" };
 
   CComPtr<IDxcBlob> pLib1;
   CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func1.hlsl",
-    &pLib1, option, 1);
+    &pLib1, option);
   CComPtr<IDxcBlob> pLib2;
   CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func2.hlsl",
-    &pLib2, option, 1);
+    &pLib2, option);
 
   CComPtr<IDxcLinker> pLinker;
   CreateLinker(&pLinker);
@@ -509,14 +506,14 @@ TEST_F(LinkerTest, RunLinkToLibWithUnresolvedFunctionsExports) {
 }
 
 TEST_F(LinkerTest, RunLinkToLibWithExportNamesSwapped) {
-  LPCWSTR option[] = { L"-Zi" };
+  LPCWSTR option[] = { L"-Zi", L"-Qembed_debug" };
 
   CComPtr<IDxcBlob> pLib1;
   CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func1.hlsl",
-    &pLib1, option, 1);
+    &pLib1, option);
   CComPtr<IDxcBlob> pLib2;
   CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func2.hlsl",
-    &pLib2, option, 1);
+    &pLib2, option);
 
   CComPtr<IDxcLinker> pLinker;
   CreateLinker(&pLinker);
@@ -541,14 +538,14 @@ TEST_F(LinkerTest, RunLinkToLibWithExportNamesSwapped) {
 }
 
 TEST_F(LinkerTest, RunLinkToLibWithExportCollision) {
-  LPCWSTR option[] = { L"-Zi" };
+  LPCWSTR option[] = { L"-Zi", L"-Qembed_debug" };
 
   CComPtr<IDxcBlob> pLib1;
   CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func1.hlsl",
-    &pLib1, option, 1);
+    &pLib1, option);
   CComPtr<IDxcBlob> pLib2;
   CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func2.hlsl",
-    &pLib2, option, 1);
+    &pLib2, option);
 
   CComPtr<IDxcLinker> pLinker;
   CreateLinker(&pLinker);
@@ -566,14 +563,14 @@ TEST_F(LinkerTest, RunLinkToLibWithExportCollision) {
 }
 
 TEST_F(LinkerTest, RunLinkToLibWithUnusedExport) {
-  LPCWSTR option[] = { L"-Zi" };
+  LPCWSTR option[] = { L"-Zi", L"-Qembed_debug" };
 
   CComPtr<IDxcBlob> pLib1;
   CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func1.hlsl",
-    &pLib1, option, 1);
+    &pLib1, option);
   CComPtr<IDxcBlob> pLib2;
   CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func2.hlsl",
-    &pLib2, option, 1);
+    &pLib2, option);
 
   CComPtr<IDxcLinker> pLinker;
   CreateLinker(&pLinker);
@@ -591,14 +588,14 @@ TEST_F(LinkerTest, RunLinkToLibWithUnusedExport) {
 }
 
 TEST_F(LinkerTest, RunLinkToLibWithNoExports) {
-  LPCWSTR option[] = { L"-Zi" };
+  LPCWSTR option[] = { L"-Zi", L"-Qembed_debug" };
 
   CComPtr<IDxcBlob> pLib1;
   CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func1.hlsl",
-    &pLib1, option, 1);
+    &pLib1, option);
   CComPtr<IDxcBlob> pLib2;
   CompileLib(L"..\\CodeGenHLSL\\linker\\lib_unresolved_func2.hlsl",
-    &pLib2, option, 1);
+    &pLib2, option);
 
   CComPtr<IDxcLinker> pLinker;
   CreateLinker(&pLinker);
@@ -616,14 +613,14 @@ TEST_F(LinkerTest, RunLinkToLibWithNoExports) {
 }
 
 TEST_F(LinkerTest, RunLinkWithPotentialIntrinsicNameCollisions) {
-  LPCWSTR option[] = { L"-Zi" };
+  LPCWSTR option[] = { L"-Zi", L"-Qembed_debug" };
 
   CComPtr<IDxcBlob> pLib1;
   CompileLib(L"..\\CodeGenHLSL\\linker\\createHandle_multi.hlsl",
-    &pLib1, option, 1);
+    &pLib1, option);
   CComPtr<IDxcBlob> pLib2;
   CompileLib(L"..\\CodeGenHLSL\\linker\\createHandle_multi2.hlsl",
-    &pLib2, option, 1);
+    &pLib2, option);
 
   CComPtr<IDxcLinker> pLinker;
   CreateLinker(&pLinker);

+ 114 - 12
utils/hct/hcttestcmds.cmd

@@ -29,16 +29,34 @@ if %errorlevel% neq 0 (
   exit /b 1
 )
 
-dxc.exe /T ps_6_0 "%testfiles%\smoke.hlsl" /Zi /Fd smoke.hlsl.d 1>nul
+rem /Fd implies /Qstrip_debug
+dxc.exe /T ps_6_0 "%testfiles%\smoke.hlsl" /Zi /Fd smoke.hlsl.d /Fo smoke.hlsl.Fd.dxo 1>nul
 if %errorlevel% neq 0 (
-  echo Failed - %CD%\dxc.exe /T ps_6_0 "%testfiles%\smoke.hlsl" /Zi /Fd %CD%\smoke.hlsl.d
+  echo Failed - %CD%\dxc.exe /T ps_6_0 "%testfiles%\smoke.hlsl" /Fd %CD%\smoke.hlsl.d
   call :cleanup 2>nul
   exit /b 1
 )
-
-dxc.exe /T ps_6_0 "%testfiles%\smoke.hlsl" /Zi /Fd %CD%\ /Fo smoke.hlsl.strip 1>nul
+dxc.exe -dumpbin smoke.hlsl.Fd.dxo | findstr "shader debug name: smoke.hlsl.d" 1>nul
 if %errorlevel% neq 0 (
-  echo Failed - %CD%\dxc.exe /T ps_6_0 "%testfiles%\smoke.hlsl" /Zi /Fd %CD%\
+  echo Failed to find shader debug name.
+  call :cleanup 2>nul
+  exit /b 1
+)
+dxc.exe -dumpbin smoke.hlsl.Fd.dxo | findstr "DICompileUnit" 1>nul
+if %errorlevel% equ 0 (
+  echo Found DICompileUnit after implied strip.
+  call :cleanup 2>nul
+  exit /b 1
+)
+rem del .lld file if exists
+dir %CD%\*.lld 1>nul
+if %errorlevel% equ 0 (
+  del %CD%\*.lld
+)
+rem /Fd implies /Qstrip_debug ; path with \ produces auto hash-named .lld file
+dxc.exe /T ps_6_0 "%testfiles%\smoke.hlsl" /Zi /Fd .\ /Fo smoke.hlsl.strip 1>nul
+if %errorlevel% neq 0 (
+  echo Failed - %CD%\dxc.exe /T ps_6_0 "%testfiles%\smoke.hlsl" /Fd %CD%\
   call :cleanup 2>nul
   exit /b 1
 )
@@ -49,8 +67,8 @@ if %errorlevel% neq 0 (
   call :cleanup 2>nul
   exit /b 1
 )
-rem /Fd with trailing backslash implies /Qstrip_debug
-dxc.exe -dumpbin smoke.hlsl.strip | findstr "shader debug name" 1>nul
+rem auto debug name is hex digest + .lld
+dxc.exe -dumpbin smoke.hlsl.strip | findstr -r -c:"shader debug name: [0-9a-f]*.lld" 1>nul
 if %errorlevel% neq 0 (
   echo Failed to find shader debug name.
   call :cleanup 2>nul
@@ -63,6 +81,80 @@ if %errorlevel% equ 0 (
   exit /b 1
 )
 
+rem Embed debug info
+rem first delete .lld file if exists
+dir %CD%\*.lld 1>nul
+if %errorlevel% equ 0 (
+  del %CD%\*.lld
+)
+dxc.exe /T ps_6_0 "%testfiles%\smoke.hlsl" /Zi /Qembed_debug /Fo smoke.hlsl.embedpdb 1>nul
+if %errorlevel% neq 0 (
+  echo Failed - %CD%\dxc.exe /T ps_6_0 "%testfiles%\smoke.hlsl" /Zi /Qembed_debug
+  call :cleanup 2>nul
+  exit /b 1
+)
+rem .lld file should NOT be produced
+dir %CD%\*.lld 1>nul
+if %errorlevel% equ 0 (
+  echo Found unexpected .lld file at %CD%
+  call :cleanup 2>nul
+  exit /b 1
+)
+rem should have auto debug name, which is hex digest + .lld
+dxc.exe -dumpbin smoke.hlsl.embedpdb | findstr -r -c:"shader debug name: [0-9a-f]*.lld" 1>nul
+if %errorlevel% neq 0 (
+  echo Failed to find shader debug name.
+  call :cleanup 2>nul
+  exit /b 1
+)
+dxc.exe -dumpbin smoke.hlsl.embedpdb | findstr "DICompileUnit" 1>nul
+if %errorlevel% neq 0 (
+  echo Did not find DICompileUnit when /Zi /Qembed_debug is used to embed debug info.
+  call :cleanup 2>nul
+  exit /b 1
+)
+
+del smoke.hlsl.embedpdb
+rem Auto-embed debug info when no debug output, and expect warning signifying that this is the case.
+rem first delete .lld file if exists
+dir %CD%\*.lld 1>nul
+if %errorlevel% equ 0 (
+  del %CD%\*.lld
+)
+dxc.exe /T ps_6_0 "%testfiles%\smoke.hlsl" /Zi /Fo smoke.hlsl.embedpdb /Fe smoke.err.embedpdb 1>nul
+if %errorlevel% neq 0 (
+  echo Failed - %CD%\dxc.exe /T ps_6_0 "%testfiles%\smoke.hlsl" /Zi
+  call :cleanup 2>nul
+  exit /b 1
+)
+rem Search for warning:
+findstr -c:"warning: no output provided for debug - embedding PDB in shader container.  Use -Qembed_debug to silence this warning." smoke.err.embedpdb
+if %errorlevel% neq 0 (
+  echo Did not find warning about embedding debug info without -Qembed_debug.
+  call :cleanup 2>nul
+  exit /b 1
+)
+rem .lld file should NOT be produced
+dir %CD%\*.lld 1>nul
+if %errorlevel% equ 0 (
+  echo Found unexpected .lld file at %CD%
+  call :cleanup 2>nul
+  exit /b 1
+)
+rem should have auto debug name, which is hex digest + .lld
+dxc.exe -dumpbin smoke.hlsl.embedpdb | findstr -r -c:"shader debug name: [0-9a-f]*.lld" 1>nul
+if %errorlevel% neq 0 (
+  echo Failed to find shader debug name.
+  call :cleanup 2>nul
+  exit /b 1
+)
+dxc.exe -dumpbin smoke.hlsl.embedpdb | findstr "DICompileUnit" 1>nul
+if %errorlevel% neq 0 (
+  echo Did not find DICompileUnit when /Zi /Qembed_debug is used to embed debug info.
+  call :cleanup 2>nul
+  exit /b 1
+)
+
 dxc.exe /T ps_6_0 "%testfiles%\smoke.hlsl" /Fe smoke.hlsl.e 1>nul
 if %errorlevel% neq 0 (
   echo Failed - %CD%\dxc.exe /T ps_6_0 "%testfiles%\smoke.hlsl" /Fe %CD%\smoke.hlsl.e
@@ -185,14 +277,14 @@ if %errorlevel% equ 0 (
   exit /b 1
 )
 
-dxc.exe /T ps_6_0 "%testfiles%\smoke.hlsl" /Zi /Fo smoke.cso 1> nul
+dxc.exe /T ps_6_0 "%testfiles%\smoke.hlsl" /Zi /Qembed_debug /Fo smoke.cso 1> nul
 if %errorlevel% neq 0 (
   echo Failed to compile to binary object from %CD%\smoke.hlsl
   call :cleanup 2>nul
   exit /b 1
 )
 
-dxc.exe /T ps_6_0 "%testfiles%\smoke.hlsl" /Zi /Fo smoke.cso /Cc /Ni /No /Lx 1> nul
+dxc.exe /T ps_6_0 "%testfiles%\smoke.hlsl" /Zi /Qembed_debug /Fo smoke.cso /Cc /Ni /No /Lx 1> nul
 if %errorlevel% neq 0 (
   echo Failed to compile to binary object from "%testfiles%\smoke.hlsl" with disassembly options
   call :cleanup 2>nul
@@ -220,7 +312,7 @@ if %errorlevel% neq 0 (
   exit /b 1
 )
 
-dxc.exe "%testfiles%\smoke.hlsl" /D "semantic = SV_Position" /T vs_6_0 /Zi /DDX12 /Fo smoke.cso 1> nul
+dxc.exe "%testfiles%\smoke.hlsl" /D "semantic = SV_Position" /T vs_6_0 /Zi /Qembed_debug /DDX12 /Fo smoke.cso 1> nul
 if %errorlevel% neq 0 (
   echo Failed to compile "%testfiles%\smoke.hlsl" with command line defines
   call :cleanup 2>nul
@@ -340,7 +432,7 @@ if %errorlevel% equ 0 (
   exit /b 1
 )
 
-dxc.exe "%testfiles%\TextVS.hlsl" /Tvs_6_0 /Zi /Fo TextVS.cso 1>nul
+dxc.exe "%testfiles%\TextVS.hlsl" /Tvs_6_0 /Zi /Qembed_debug /Fo TextVS.cso 1>nul
 if %errorlevel% neq 0 (
   echo failed to compile "%testfiles%\TextVS.hlsl"
   call :cleanup 2>nul
@@ -639,7 +731,12 @@ call :cleanup
 exit /b 0
 
 :cleanup
-del %CD%\*.lld
+exit /b 0
+rem del .lld file if exists
+dir %CD%\*.lld 1>nul
+if %errorlevel% equ 0 (
+  del %CD%\*.lld
+)
 del %CD%\NonUniform.cso
 del %CD%\NonUniformNoRootSig.cso
 del %CD%\NonUniformRootSig.cso
@@ -660,9 +757,12 @@ del %CD%\smoke.cso.plain.bc
 del %CD%\smoke.hl.txt
 del %CD%\smoke.hlsl.c
 del %CD%\smoke.hlsl.d
+del %CD%\smoke.hlsl.Fd.dxo
 del %CD%\smoke.hlsl.e
 del %CD%\smoke.hlsl.h
 del %CD%\smoke.hlsl.strip
+del %CD%\smoke.hlsl.embedpdb
+del %CD%\smoke.err.embedpdb
 del %CD%\smoke.ll
 del %CD%\smoke.opt.ll
 del %CD%\smoke.opt.prn.txt
@@ -679,6 +779,8 @@ del %CD%\test-global-rs.hlsl
 del %CD%\test-local-rs.hlsl
 del %CD%\test-global-rs.cso
 del %CD%\test-local-rs.cso
+del %CD%\smoke.no.warning.txt
+del %CD%\smoke.warning.txt
 
 exit /b 0