Parcourir la source

Support findInjectedSource (#573)

* Support findInjectedSource and set correct count for DxcDiaTableInjectedSource.
Xiang Li il y a 8 ans
Parent
commit
eab2c2ff0f

+ 39 - 3
tools/clang/tools/dxcompiler/dxcdia.cpp

@@ -379,8 +379,8 @@ public:
     /* [out] */ IDiaEnumLineNumbers **ppResult) { return E_NOTIMPL; }
     /* [out] */ IDiaEnumLineNumbers **ppResult) { return E_NOTIMPL; }
 
 
   __override STDMETHODIMP findInjectedSource(
   __override STDMETHODIMP findInjectedSource(
-    /* [in] */ LPCOLESTR srcFile,
-    /* [out] */ IDiaEnumInjectedSources **ppResult) { return E_NOTIMPL; }
+      /* [in] */ LPCOLESTR srcFile,
+      /* [out] */ IDiaEnumInjectedSources **ppResult);
 
 
   __override STDMETHODIMP getEnumDebugStreams(
   __override STDMETHODIMP getEnumDebugStreams(
     /* [out] */ IDiaEnumDebugStreams **ppEnumDebugStreams) { return E_NOTIMPL; }
     /* [out] */ IDiaEnumDebugStreams **ppEnumDebugStreams) { return E_NOTIMPL; }
@@ -1975,6 +1975,7 @@ public:
       }
       }
       return S_OK;
       return S_OK;
     }
     }
+
     cbData = std::min((DWORD)Content().size(), cbData);
     cbData = std::min((DWORD)Content().size(), cbData);
     memcpy(pbData, Content().begin(), cbData);
     memcpy(pbData, Content().begin(), cbData);
     if (pcbData) {
     if (pcbData) {
@@ -1994,12 +1995,30 @@ public:
   }
   }
 
 
   __override HRESULT GetItem(DWORD index, IDiaInjectedSource **ppItem) {
   __override HRESULT GetItem(DWORD index, IDiaInjectedSource **ppItem) {
-    *ppItem = CreateOnMalloc<DxcDiaInjectedSource>(m_pMalloc, m_pSession, index);
+    if (index >= m_count)
+      return E_INVALIDARG;
+    unsigned itemIndex = index;
+    if (m_count == m_indexList.size())
+      itemIndex = m_indexList[index];
+    *ppItem = CreateOnMalloc<DxcDiaInjectedSource>(m_pMalloc, m_pSession, itemIndex);
     if (*ppItem == nullptr)
     if (*ppItem == nullptr)
       return E_OUTOFMEMORY;
       return E_OUTOFMEMORY;
     (*ppItem)->AddRef();
     (*ppItem)->AddRef();
     return S_OK;
     return S_OK;
   }
   }
+  void Init(StringRef filename) {
+    for (unsigned i = 0; i < m_pSession->Contents()->getNumOperands(); ++i) {
+      StringRef fn =
+          dyn_cast<MDString>(m_pSession->Contents()->getOperand(i)->getOperand(0))
+              ->getString();
+      if (fn.equals(filename)) {
+        m_indexList.emplace_back(i);
+      }
+    }
+    m_count = m_indexList.size();
+  }
+private:
+  std::vector<unsigned> m_indexList;
 };
 };
 
 
 class DxcDiaTableFrameData : public DxcDiaTableBase<IDiaEnumFrameData, IDiaFrameData> {
 class DxcDiaTableFrameData : public DxcDiaTableBase<IDiaEnumFrameData, IDiaFrameData> {
@@ -2025,6 +2044,23 @@ public:
   // HLSL is not based on IL, so no data to return.
   // HLSL is not based on IL, so no data to return.
 };
 };
 
 
+__override STDMETHODIMP DxcDiaSession::findInjectedSource(
+    /* [in] */ LPCOLESTR srcFile,
+    /* [out] */ IDiaEnumInjectedSources **ppResult) {
+  if (Contents() != nullptr) {
+    CW2A pUtf8FileName(srcFile);
+    DxcThreadMalloc TM(m_pMalloc);
+    IDiaTable *pTable;
+    IFT(CreateDxcDiaTable(this, DiaTableKind::InjectedSource, &pTable));
+    DxcDiaTableInjectedSource *pInjectedSource =
+        dynamic_cast<DxcDiaTableInjectedSource *>(pTable);
+    pInjectedSource->Init(pUtf8FileName.m_psz);
+    *ppResult = pInjectedSource;
+    return S_OK;
+  }
+  return S_FALSE;
+}
+
 static
 static
 HRESULT CreateDxcDiaTable(DxcDiaSession *pSession, DiaTableKind kind, IDiaTable **ppTable) {
 HRESULT CreateDxcDiaTable(DxcDiaSession *pSession, DiaTableKind kind, IDiaTable **ppTable) {
   *ppTable = nullptr;
   *ppTable = nullptr;

+ 78 - 2
tools/clang/unittests/HLSL/CompilerTest.cpp

@@ -1285,7 +1285,82 @@ public:
 
 
     return o.str();
     return o.str();
   }
   }
-  
+  std::wstring GetDebugFileContent(_In_ IDiaDataSource *pDataSource) {
+    CComPtr<IDiaSession> pSession;
+    CComPtr<IDiaTable> pTable;
+
+    CComPtr<IDiaTable> pSourcesTable;
+
+    CComPtr<IDiaEnumTables> pEnumTables;
+    std::wstringstream o;
+
+    VERIFY_SUCCEEDED(pDataSource->openSession(&pSession));
+    VERIFY_SUCCEEDED(pSession->getEnumTables(&pEnumTables));
+
+    ULONG fetched = 0;
+    while (pEnumTables->Next(1, &pTable, &fetched) == S_OK && fetched == 1) {
+      CComBSTR name;
+      IFT(pTable->get_name(&name));
+
+      if (wcscmp(name, L"SourceFiles") == 0) {
+        pSourcesTable = pTable.Detach();
+        continue;
+      }
+
+      pTable.Release();
+    }
+
+    if (!pSourcesTable) {
+      return L"cannot find source";
+    }
+
+    // Get source file contents.
+    // NOTE: "SourceFiles" has the root file first while "InjectedSources" is in
+    // alphabetical order.
+    //       It is important to keep the root file first for recompilation, so
+    //       iterate "SourceFiles" and look up the corresponding injected
+    //       source.
+    LONG count;
+    IFT(pSourcesTable->get_Count(&count));
+
+    CComPtr<IDiaSourceFile> pSourceFile;
+    CComBSTR pName;
+    CComPtr<IUnknown> pSymbolUnk;
+    CComPtr<IDiaEnumInjectedSources> pEnumInjectedSources;
+    CComPtr<IDiaInjectedSource> pInjectedSource;
+    std::wstring sourceText, sourceFilename;
+
+    while (SUCCEEDED(pSourcesTable->Next(1, &pSymbolUnk, &fetched)) &&
+           fetched == 1) {
+      sourceText = sourceFilename = L"";
+
+      IFT(pSymbolUnk->QueryInterface(&pSourceFile));
+      IFT(pSourceFile->get_fileName(&pName));
+
+      IFT(pSession->findInjectedSource(pName, &pEnumInjectedSources));
+
+      if (SUCCEEDED(pEnumInjectedSources->get_Count(&count)) && count == 1) {
+        IFT(pEnumInjectedSources->Item(0, &pInjectedSource));
+
+        DWORD cbData = 0;
+        std::string tempString;
+        CComBSTR bstr;
+        IFT(pInjectedSource->get_filename(&bstr));
+        IFT(pInjectedSource->get_source(0, &cbData, nullptr));
+
+        tempString.resize(cbData);
+        IFT(pInjectedSource->get_source(
+            cbData, &cbData, reinterpret_cast<BYTE *>(&tempString[0])));
+
+        CA2W tempWString(tempString.data());
+        o << tempWString.m_psz;
+      }
+      pSymbolUnk.Release();
+    }
+
+    return o.str();
+  }
+
   struct LineNumber { DWORD line; DWORD rva; };
   struct LineNumber { DWORD line; DWORD rva; };
   std::vector<LineNumber> ReadLineNumbers(IDiaEnumLineNumbers *pEnumLineNumbers) {
   std::vector<LineNumber> ReadLineNumbers(IDiaEnumLineNumbers *pEnumLineNumbers) {
     std::vector<LineNumber> lines;
     std::vector<LineNumber> lines;
@@ -1588,7 +1663,8 @@ TEST_F(CompilerTest, CompileWhenDebugThenDIPresent) {
   VERIFY_IS_NOT_NULL(wcsstr(diaDump.c_str(), L"symIndexId: 5, CompilandEnv, name: hlslTarget, value: ps_6_0"));
   VERIFY_IS_NOT_NULL(wcsstr(diaDump.c_str(), L"symIndexId: 5, CompilandEnv, name: hlslTarget, value: ps_6_0"));
   VERIFY_IS_NOT_NULL(wcsstr(diaDump.c_str(), L"lineNumber: 2"));
   VERIFY_IS_NOT_NULL(wcsstr(diaDump.c_str(), L"lineNumber: 2"));
   VERIFY_IS_NOT_NULL(wcsstr(diaDump.c_str(), L"length: 99, filename: source.hlsl"));
   VERIFY_IS_NOT_NULL(wcsstr(diaDump.c_str(), L"length: 99, filename: source.hlsl"));
-
+  std::wstring diaFileContent = GetDebugFileContent(pDiaSource).c_str();
+  VERIFY_IS_NOT_NULL(wcsstr(diaFileContent.c_str(), L"loat4 main(float4 pos : SV_Position) : SV_Target"));
 #if SUPPORT_FXC_PDB
 #if SUPPORT_FXC_PDB
   // Now, fake it by loading from a .pdb!
   // Now, fake it by loading from a .pdb!
   VERIFY_SUCCEEDED(CoInitializeEx(0, COINITBASE_MULTITHREADED));
   VERIFY_SUCCEEDED(CoInitializeEx(0, COINITBASE_MULTITHREADED));