Implements DIA Interfaces for HLSL variable-value mapping. (#2050)
This commit is contained in:
Родитель
68204b3bfe
Коммит
d432a02f77
|
@ -43,6 +43,7 @@ static constexpr char MDName[] = "pix-alloca-reg";
|
|||
static constexpr uint32_t ID = 1;
|
||||
|
||||
void AddMD(llvm::LLVMContext &Ctx, llvm::AllocaInst *pAlloca, std::uint32_t RegNum, std::uint32_t Count);
|
||||
bool FromInst(llvm::AllocaInst *pAlloca, std::uint32_t *pRegBase, std::uint32_t *pRegSize);
|
||||
} // namespace PixAllocaReg
|
||||
|
||||
namespace PixAllocaRegWrite {
|
|
@ -24,9 +24,9 @@ add_subdirectory(DxcSupport) # HLSL Change
|
|||
add_subdirectory(HLSL) # HLSL Change
|
||||
add_subdirectory(DXIL) # HLSL Change
|
||||
add_subdirectory(DxilContainer) # HLSL Change
|
||||
add_subdirectory(DxilPIXPasses) # HLSL Change
|
||||
if(WIN32) # HLSL Change
|
||||
add_subdirectory(DxilDia) # HLSL Change
|
||||
endif(WIN32) # HLSL Change
|
||||
add_subdirectory(DxilPIXPasses) # HLSL Change
|
||||
add_subdirectory(DxilRootSignature) # HLSL Change
|
||||
add_subdirectory(DxrFallback) # HLSL Change
|
||||
|
|
|
@ -10,6 +10,7 @@ add_llvm_library(LLVMDxilDia
|
|||
DxilDiaDataSource.cpp
|
||||
DxilDiaEnumTables.cpp
|
||||
DxilDiaSession.cpp
|
||||
DxilDiaSymbolManager.cpp
|
||||
DxilDiaTable.cpp
|
||||
DxilDiaTableFrameData.cpp
|
||||
DxilDiaTableInjectedSources.cpp
|
||||
|
@ -28,3 +29,5 @@ if (WIN32)
|
|||
target_link_libraries(LLVMDxilDia PRIVATE ${LIBRARIES} ${DIASDK_LIBRARIES})
|
||||
include_directories(AFTER ${LLVM_INCLUDE_DIR}/dxc/Tracing ${DIASDK_INCLUDE_DIRS})
|
||||
endif (WIN32)
|
||||
|
||||
add_dependencies(LLVMDxilDia LLVMDxilPIXPasses intrinsics_gen)
|
||||
|
|
|
@ -11,18 +11,24 @@
|
|||
|
||||
#include "DxilDiaSession.h"
|
||||
|
||||
#include "dxc/DxilPIXPasses/DxilPIXPasses.h"
|
||||
#include "dxc/DxilPIXPasses/DxilPIXVirtualRegisters.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/InstIterator.h"
|
||||
#include "llvm/IR/Instruction.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/Metadata.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/LegacyPassManager.h"
|
||||
#include "llvm/PassRegistry.h"
|
||||
|
||||
#include "DxilDia.h"
|
||||
#include "DxilDiaEnumTables.h"
|
||||
#include "DxilDiaTable.h"
|
||||
#include "DxilDiaTableInjectedSources.h"
|
||||
#include "DxilDiaTableLineNumbers.h"
|
||||
#include "DxilDiaTableSourceFiles.h"
|
||||
#include "DxilDiaTableSymbols.h"
|
||||
|
||||
void dxil_dia::Session::Init(
|
||||
std::shared_ptr<llvm::LLVMContext> context,
|
||||
|
@ -34,6 +40,11 @@ void dxil_dia::Session::Init(
|
|||
m_finder = finder;
|
||||
m_dxilModule = std::make_unique<hlsl::DxilModule>(module.get());
|
||||
|
||||
llvm::legacy::PassManager PM;
|
||||
llvm::initializeDxilAnnotateWithVirtualRegisterPass(*llvm::PassRegistry::getPassRegistry());
|
||||
PM.add(llvm::createDxilAnnotateWithVirtualRegisterPass());
|
||||
PM.run(*m_module);
|
||||
|
||||
// Extract HLSL metadata.
|
||||
m_dxilModule->LoadDxilMetadata();
|
||||
|
||||
|
@ -59,30 +70,35 @@ void dxil_dia::Session::Init(
|
|||
m_arguments = m_module->getNamedMetadata("llvm.dbg.args");
|
||||
|
||||
// Build up a linear list of instructions. The index will be used as the
|
||||
// RVA. Debug instructions are ommitted from this enumeration.
|
||||
for (const llvm::Function &fn : m_module->functions()) {
|
||||
for (llvm::const_inst_iterator it = inst_begin(fn), end = inst_end(fn); it != end; ++it) {
|
||||
const llvm::Instruction &i = *it;
|
||||
if (const auto *call = llvm::dyn_cast<const llvm::CallInst>(&i)) {
|
||||
const llvm::Function *pFn = call->getCalledFunction();
|
||||
if (pFn && pFn->getName().startswith("llvm.dbg.")) {
|
||||
continue;
|
||||
}
|
||||
// RVA.
|
||||
for (llvm::Function &fn : m_module->functions()) {
|
||||
for (llvm::inst_iterator it = inst_begin(fn), end = inst_end(fn); it != end; ++it) {
|
||||
llvm::Instruction &i = *it;
|
||||
RVA rva;
|
||||
if (!pix_dxil::PixDxilInstNum::FromInst(&i, &rva)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
m_rvaMap.insert({ &i, static_cast<RVA>(m_instructions.size()) });
|
||||
m_instructions.push_back(&i);
|
||||
if (i.getDebugLoc()) {
|
||||
m_rvaMap.insert({ &i, rva });
|
||||
m_instructions.insert({ rva, &i});
|
||||
if (llvm::DebugLoc DL = i.getDebugLoc()) {
|
||||
auto result = m_lineToInfoMap.emplace(DL.getLine(), LineInfo(DL.getCol(), rva, rva + 1));
|
||||
if (!result.second) {
|
||||
result.first->second.StartCol = std::min(result.first->second.StartCol, DL.getCol());
|
||||
result.first->second.Last = rva + 1;
|
||||
}
|
||||
m_instructionLines.push_back(&i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sanity check to make sure rva map is same as instruction index.
|
||||
for (size_t i = 0, e = m_instructions.size(); i < e; ++i) {
|
||||
DXASSERT(m_rvaMap.find(m_instructions[i]) != m_rvaMap.end(), "instruction not mapped to rva");
|
||||
DXASSERT(m_rvaMap[m_instructions[i]] == i, "instruction mapped to wrong rva");
|
||||
for (auto It = m_instructions.begin(); It != m_instructions.end(); ++It) {
|
||||
DXASSERT(m_rvaMap.find(It->second) != m_rvaMap.end(), "instruction not mapped to rva");
|
||||
DXASSERT(m_rvaMap[It->second] == It->first, "instruction mapped to wrong rva");
|
||||
}
|
||||
|
||||
// Initialize symbols
|
||||
m_symsMgr.Init(this);
|
||||
}
|
||||
|
||||
HRESULT dxil_dia::Session::getSourceFileIdByName(
|
||||
|
@ -109,6 +125,21 @@ STDMETHODIMP dxil_dia::Session::get_loadAddress(
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Session::get_globalScope(
|
||||
/* [retval][out] */ IDiaSymbol **pRetVal) {
|
||||
DxcThreadMalloc TM(m_pMalloc);
|
||||
|
||||
if (pRetVal == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*pRetVal = nullptr;
|
||||
|
||||
Symbol *ret;
|
||||
IFR(m_symsMgr.GetGlobalScope(&ret));
|
||||
*pRetVal = ret;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Session::getEnumTables(
|
||||
/* [out] */ _COM_Outptr_ IDiaEnumTables **ppEnumTables) {
|
||||
if (!m_pEnumTables) {
|
||||
|
@ -136,6 +167,57 @@ STDMETHODIMP dxil_dia::Session::findFileById(
|
|||
return pElt->QueryInterface(ppResult);
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Session::findFile(
|
||||
/* [in] */ IDiaSymbol *pCompiland,
|
||||
/* [in] */ LPCOLESTR name,
|
||||
/* [in] */ DWORD compareFlags,
|
||||
/* [out] */ IDiaEnumSourceFiles **ppResult) {
|
||||
if (!m_pEnumTables) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
// TODO: properly support compareFlags.
|
||||
auto namecmp = &_wcsicmp;
|
||||
if (compareFlags & nsCaseSensitive) {
|
||||
namecmp = &wcscmp;
|
||||
}
|
||||
|
||||
DxcThreadMalloc TM(m_pMalloc);
|
||||
CComPtr<IDiaTable> pTable;
|
||||
VARIANT vtIndex;
|
||||
vtIndex.vt = VT_UI4;
|
||||
vtIndex.uintVal = (int)Table::Kind::SourceFiles;
|
||||
IFR(m_pEnumTables->Item(vtIndex, &pTable));
|
||||
|
||||
CComPtr<IDiaEnumSourceFiles> pSourceTable;
|
||||
IFR(pTable->QueryInterface(&pSourceTable));
|
||||
HRESULT hr;
|
||||
CComPtr<IDiaSourceFile> src;
|
||||
ULONG cnt;
|
||||
std::vector<CComPtr<IDiaSourceFile>> sources;
|
||||
|
||||
pSourceTable->Reset();
|
||||
while (SUCCEEDED(hr = pSourceTable->Next(1, &src, &cnt)) && hr == S_OK && cnt == 1) {
|
||||
CComBSTR currName;
|
||||
IFR(src->get_fileName(&currName));
|
||||
if (namecmp(name, currName) == 0) {
|
||||
sources.emplace_back(src);
|
||||
}
|
||||
src.Release();
|
||||
}
|
||||
|
||||
*ppResult = CreateOnMalloc<SourceFilesTable>(
|
||||
GetMallocNoRef(),
|
||||
this,
|
||||
std::move(sources));
|
||||
|
||||
if (*ppResult == nullptr) {
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
(*ppResult)->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
namespace dxil_dia {
|
||||
static HRESULT DxcDiaFindLineNumbersByRVA(
|
||||
Session *pSession,
|
||||
|
@ -147,15 +229,16 @@ static HRESULT DxcDiaFindLineNumbersByRVA(
|
|||
return E_POINTER;
|
||||
|
||||
std::vector<const llvm::Instruction*> instructions;
|
||||
const std::vector<const llvm::Instruction*> &allInstructions = pSession->InstructionsRef();
|
||||
auto &allInstructions = pSession->InstructionsRef();
|
||||
|
||||
// Gather the list of insructions that map to the given rva range.
|
||||
for (DWORD i = rva; i < rva + length; ++i) {
|
||||
if (i >= allInstructions.size())
|
||||
auto It = allInstructions.find(i);
|
||||
if (It == allInstructions.end())
|
||||
return E_INVALIDARG;
|
||||
|
||||
// Only include the instruction if it has debug info for line mappings.
|
||||
const llvm::Instruction *inst = allInstructions[i];
|
||||
const llvm::Instruction *inst = It->second;
|
||||
if (inst->getDebugLoc())
|
||||
instructions.push_back(inst);
|
||||
}
|
||||
|
@ -187,6 +270,80 @@ STDMETHODIMP dxil_dia::Session::findLinesByRVA(
|
|||
return DxcDiaFindLineNumbersByRVA(this, rva, length, ppResult);
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Session::findInlineeLinesByAddr(
|
||||
/* [in] */ IDiaSymbol *parent,
|
||||
/* [in] */ DWORD isect,
|
||||
/* [in] */ DWORD offset,
|
||||
/* [in] */ DWORD length,
|
||||
/* [out] */ IDiaEnumLineNumbers **ppResult) {
|
||||
DxcThreadMalloc TM(m_pMalloc);
|
||||
return DxcDiaFindLineNumbersByRVA(this, offset, length, ppResult);
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Session::findLinesByLinenum(
|
||||
/* [in] */ IDiaSymbol *compiland,
|
||||
/* [in] */ IDiaSourceFile *file,
|
||||
/* [in] */ DWORD linenum,
|
||||
/* [in] */ DWORD column,
|
||||
/* [out] */ IDiaEnumLineNumbers **ppResult) {
|
||||
if (!m_pEnumTables) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*ppResult = nullptr;
|
||||
|
||||
DxcThreadMalloc TM(m_pMalloc);
|
||||
CComPtr<IDiaTable> pTable;
|
||||
VARIANT vtIndex;
|
||||
vtIndex.vt = VT_UI4;
|
||||
vtIndex.uintVal = (int)Table::Kind::LineNumbers;
|
||||
IFR(m_pEnumTables->Item(vtIndex, &pTable));
|
||||
|
||||
CComPtr<IDiaEnumLineNumbers> pLineTable;
|
||||
IFR(pTable->QueryInterface(&pLineTable));
|
||||
HRESULT hr;
|
||||
CComPtr<IDiaLineNumber> line;
|
||||
ULONG cnt;
|
||||
std::vector<const llvm::Instruction *> lines;
|
||||
|
||||
std::function<bool(DWORD, DWORD)>column_matches = [column](DWORD colStart, DWORD colEnd) -> bool {
|
||||
return true;
|
||||
};
|
||||
|
||||
if (column != 0) {
|
||||
column_matches = [column](DWORD colStart, DWORD colEnd) -> bool {
|
||||
return colStart < column && column < colEnd;
|
||||
};
|
||||
}
|
||||
|
||||
pLineTable->Reset();
|
||||
while (SUCCEEDED(hr = pLineTable->Next(1, &line, &cnt)) && hr == S_OK && cnt == 1) {
|
||||
CComPtr<IDiaSourceFile> f;
|
||||
DWORD ln, lnEnd, cn, cnEnd;
|
||||
IFR(line->get_lineNumber(&ln));
|
||||
IFR(line->get_lineNumberEnd(&lnEnd));
|
||||
IFR(line->get_columnNumber(&cn));
|
||||
IFR(line->get_columnNumberEnd(&cnEnd));
|
||||
IFR(line->get_sourceFile(&f));
|
||||
|
||||
if (file == f && (ln <= linenum && linenum <= lnEnd) && column_matches(cn, cnEnd)) {
|
||||
lines.emplace_back(reinterpret_cast<LineNumber*>(line.p)->Inst());
|
||||
}
|
||||
line.Release();
|
||||
}
|
||||
|
||||
HRESULT result = lines.empty() ? S_FALSE : S_OK;
|
||||
*ppResult = CreateOnMalloc<LineNumbersTable>(
|
||||
GetMallocNoRef(),
|
||||
this,
|
||||
std::move(lines));
|
||||
|
||||
if (*ppResult == nullptr) {
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
(*ppResult)->AddRef();
|
||||
return result;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Session::findInjectedSource(
|
||||
/* [in] */ LPCOLESTR srcFile,
|
||||
/* [out] */ IDiaEnumInjectedSources **ppResult) {
|
||||
|
@ -203,3 +360,29 @@ STDMETHODIMP dxil_dia::Session::findInjectedSource(
|
|||
}
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
static constexpr DWORD kD3DCodeSection = 1;
|
||||
STDMETHODIMP dxil_dia::Session::findInlineFramesByAddr(
|
||||
/* [in] */ IDiaSymbol *parent,
|
||||
/* [in] */ DWORD isect,
|
||||
/* [in] */ DWORD offset,
|
||||
/* [out] */ IDiaEnumSymbols **ppResult) {
|
||||
if (parent != nullptr || isect != kD3DCodeSection || ppResult == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*ppResult = nullptr;
|
||||
|
||||
DxcThreadMalloc TM(m_pMalloc);
|
||||
auto &allInstructions = InstructionsRef();
|
||||
auto It = allInstructions.find(offset);
|
||||
if (It == allInstructions.end()) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
SymbolChildrenEnumerator *ChildrenEnum;
|
||||
IFR(hr = m_symsMgr.DbgScopeOf(It->second, &ChildrenEnum));
|
||||
|
||||
*ppResult = ChildrenEnum;
|
||||
return hr;
|
||||
}
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "dxc/Support/WinIncludes.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
@ -25,12 +26,25 @@
|
|||
#include "dxc/Support/microcom.h"
|
||||
|
||||
#include "DxilDia.h"
|
||||
#include "DxilDiaSymbolManager.h"
|
||||
|
||||
namespace dxil_dia {
|
||||
|
||||
class Session : public IDiaSession {
|
||||
public:
|
||||
using RVA = unsigned;
|
||||
using RVAMap = std::map<RVA, const llvm::Instruction *>;
|
||||
|
||||
struct LineInfo {
|
||||
LineInfo(std::uint32_t start_col, RVA first, RVA last)
|
||||
: StartCol(start_col),
|
||||
First(first),
|
||||
Last(last) {}
|
||||
|
||||
std::uint32_t StartCol = 0;
|
||||
RVA First = 0;
|
||||
RVA Last = 0;
|
||||
};
|
||||
using LineToInfoMap = std::unordered_map<std::uint32_t, LineInfo>;
|
||||
|
||||
DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL()
|
||||
DXC_MICROCOM_TM_CTOR(Session)
|
||||
|
@ -48,9 +62,11 @@ public:
|
|||
hlsl::DxilModule &DxilModuleRef() { return *m_dxilModule.get(); }
|
||||
llvm::Module &ModuleRef() { return *m_module.get(); }
|
||||
llvm::DebugInfoFinder &InfoRef() { return *m_finder.get(); }
|
||||
std::vector<const llvm::Instruction *> &InstructionsRef() { return m_instructions; }
|
||||
std::vector<const llvm::Instruction *> &InstructionLinesRef() { return m_instructionLines; }
|
||||
std::unordered_map<const llvm::Instruction *, RVA> &RvaMapRef() { return m_rvaMap; }
|
||||
const SymbolManager &SymMgr() const { return m_symsMgr; }
|
||||
const RVAMap &InstructionsRef() const { return m_instructions; }
|
||||
const std::vector<const llvm::Instruction *> &InstructionLinesRef() const { return m_instructionLines; }
|
||||
const std::unordered_map<const llvm::Instruction *, RVA> &RvaMapRef() const { return m_rvaMap; }
|
||||
const LineToInfoMap &LineToColumnStartMapRef() const { return m_lineToInfoMap; }
|
||||
|
||||
HRESULT getSourceFileIdByName(llvm::StringRef fileName, DWORD *pRetVal);
|
||||
|
||||
|
@ -65,7 +81,7 @@ public:
|
|||
/* [in] */ ULONGLONG NewVal) override { return ENotImpl(); }
|
||||
|
||||
STDMETHODIMP get_globalScope(
|
||||
/* [retval][out] */ IDiaSymbol **pRetVal) override { return ENotImpl(); }
|
||||
/* [retval][out] */ IDiaSymbol **pRetVal) override;
|
||||
|
||||
STDMETHODIMP getEnumTables(
|
||||
_COM_Outptr_ IDiaEnumTables **ppEnumTables) override;
|
||||
|
@ -75,21 +91,21 @@ public:
|
|||
|
||||
STDMETHODIMP findChildren(
|
||||
/* [in] */ IDiaSymbol *parent,
|
||||
/* [in] */ enum SymTagEnum symtag,
|
||||
/* [in] */ enum SymTagEnum symtag,
|
||||
/* [in] */ LPCOLESTR name,
|
||||
/* [in] */ DWORD compareFlags,
|
||||
/* [out] */ IDiaEnumSymbols **ppResult) override { return ENotImpl(); }
|
||||
|
||||
STDMETHODIMP findChildrenEx(
|
||||
/* [in] */ IDiaSymbol *parent,
|
||||
/* [in] */ enum SymTagEnum symtag,
|
||||
/* [in] */ enum SymTagEnum symtag,
|
||||
/* [in] */ LPCOLESTR name,
|
||||
/* [in] */ DWORD compareFlags,
|
||||
/* [out] */ IDiaEnumSymbols **ppResult) override { return ENotImpl(); }
|
||||
|
||||
STDMETHODIMP findChildrenExByAddr(
|
||||
/* [in] */ IDiaSymbol *parent,
|
||||
/* [in] */ enum SymTagEnum symtag,
|
||||
/* [in] */ enum SymTagEnum symtag,
|
||||
/* [in] */ LPCOLESTR name,
|
||||
/* [in] */ DWORD compareFlags,
|
||||
/* [in] */ DWORD isect,
|
||||
|
@ -98,7 +114,7 @@ public:
|
|||
|
||||
STDMETHODIMP findChildrenExByVA(
|
||||
/* [in] */ IDiaSymbol *parent,
|
||||
/* [in] */ enum SymTagEnum symtag,
|
||||
/* [in] */ enum SymTagEnum symtag,
|
||||
/* [in] */ LPCOLESTR name,
|
||||
/* [in] */ DWORD compareFlags,
|
||||
/* [in] */ ULONGLONG va,
|
||||
|
@ -106,7 +122,7 @@ public:
|
|||
|
||||
STDMETHODIMP findChildrenExByRVA(
|
||||
/* [in] */ IDiaSymbol *parent,
|
||||
/* [in] */ enum SymTagEnum symtag,
|
||||
/* [in] */ enum SymTagEnum symtag,
|
||||
/* [in] */ LPCOLESTR name,
|
||||
/* [in] */ DWORD compareFlags,
|
||||
/* [in] */ DWORD rva,
|
||||
|
@ -115,7 +131,7 @@ public:
|
|||
STDMETHODIMP findSymbolByAddr(
|
||||
/* [in] */ DWORD isect,
|
||||
/* [in] */ DWORD offset,
|
||||
/* [in] */ enum SymTagEnum symtag,
|
||||
/* [in] */ enum SymTagEnum symtag,
|
||||
/* [out] */ IDiaSymbol **ppSymbol) override { return ENotImpl(); }
|
||||
|
||||
STDMETHODIMP findSymbolByRVA(
|
||||
|
@ -157,7 +173,7 @@ public:
|
|||
/* [in] */ IDiaSymbol *pCompiland,
|
||||
/* [in] */ LPCOLESTR name,
|
||||
/* [in] */ DWORD compareFlags,
|
||||
/* [out] */ IDiaEnumSourceFiles **ppResult) override { return ENotImpl(); }
|
||||
/* [out] */ IDiaEnumSourceFiles **ppResult) override;
|
||||
|
||||
STDMETHODIMP findFileById(
|
||||
/* [in] */ DWORD uniqueId,
|
||||
|
@ -189,7 +205,7 @@ public:
|
|||
/* [in] */ IDiaSourceFile *file,
|
||||
/* [in] */ DWORD linenum,
|
||||
/* [in] */ DWORD column,
|
||||
/* [out] */ IDiaEnumLineNumbers **ppResult) override { return ENotImpl(); }
|
||||
/* [out] */ IDiaEnumLineNumbers **ppResult) override;
|
||||
|
||||
STDMETHODIMP findInjectedSource(
|
||||
/* [in] */ LPCOLESTR srcFile,
|
||||
|
@ -202,7 +218,7 @@ public:
|
|||
/* [in] */ IDiaSymbol *parent,
|
||||
/* [in] */ DWORD isect,
|
||||
/* [in] */ DWORD offset,
|
||||
/* [out] */ IDiaEnumSymbols **ppResult) override { return ENotImpl(); }
|
||||
/* [out] */ IDiaEnumSymbols **ppResult) override;
|
||||
|
||||
STDMETHODIMP findInlineFramesByRVA(
|
||||
/* [in] */ IDiaSymbol *parent,
|
||||
|
@ -223,7 +239,7 @@ public:
|
|||
/* [in] */ DWORD isect,
|
||||
/* [in] */ DWORD offset,
|
||||
/* [in] */ DWORD length,
|
||||
/* [out] */ IDiaEnumLineNumbers **ppResult) override { return ENotImpl(); }
|
||||
/* [out] */ IDiaEnumLineNumbers **ppResult) override;
|
||||
|
||||
STDMETHODIMP findInlineeLinesByRVA(
|
||||
/* [in] */ IDiaSymbol *parent,
|
||||
|
@ -369,9 +385,11 @@ private:
|
|||
llvm::NamedMDNode *m_defines;
|
||||
llvm::NamedMDNode *m_mainFileName;
|
||||
llvm::NamedMDNode *m_arguments;
|
||||
std::vector<const llvm::Instruction *> m_instructions;
|
||||
RVAMap m_instructions;
|
||||
std::vector<const llvm::Instruction *> m_instructionLines; // Instructions with line info.
|
||||
std::unordered_map<const llvm::Instruction *, RVA> m_rvaMap; // Map instruction to its RVA.
|
||||
LineToInfoMap m_lineToInfoMap;
|
||||
SymbolManager m_symsMgr;
|
||||
|
||||
private:
|
||||
CComPtr<IDiaEnumTables> m_pEnumTables;
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,84 @@
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// DxilDiaSymbolsManager.h //
|
||||
// Copyright (C) Microsoft Corporation. All rights reserved. //
|
||||
// This file is distributed under the University of Illinois Open Source //
|
||||
// License. See LICENSE.TXT for details. //
|
||||
// //
|
||||
// DIA API implementation for DXIL modules. //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
#pragma once
|
||||
|
||||
#include "dxc/Support/WinIncludes.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/ADT/PointerUnion.h"
|
||||
|
||||
namespace llvm {
|
||||
class DIDerivedType;
|
||||
class DILocalVariable;
|
||||
class DIScope;
|
||||
class DITemplateTypeParameter;
|
||||
class DIType;
|
||||
class Instruction;
|
||||
} // namespace llvm
|
||||
|
||||
namespace dxil_dia {
|
||||
class Session;
|
||||
class Symbol;
|
||||
class SymbolChildrenEnumerator;
|
||||
|
||||
class SymbolManager {
|
||||
public:
|
||||
struct LiveRange {
|
||||
unsigned Start;
|
||||
unsigned Length;
|
||||
};
|
||||
|
||||
using CreateSymbolFn = std::function<HRESULT(Session *pSession, Symbol **)>;
|
||||
using ScopeToIDMap = llvm::DenseMap<llvm::DIScope *, DWORD>;
|
||||
using IDToLiveRangeMap = std::unordered_map<DWORD, LiveRange>;
|
||||
using ParentToChildrenMap = std::unordered_multimap<DWORD, DWORD>;
|
||||
|
||||
|
||||
SymbolManager();
|
||||
~SymbolManager();
|
||||
|
||||
void Init(Session *pSes);
|
||||
|
||||
size_t NumSymbols() const { return m_symbolCtors.size(); }
|
||||
HRESULT GetSymbolByID(size_t id, Symbol **ppSym) const;
|
||||
HRESULT GetLiveRangeOf(Symbol *pSym, LiveRange *LR) const;
|
||||
HRESULT GetGlobalScope(Symbol **ppSym) const;
|
||||
HRESULT ChildrenOf(Symbol *pSym, std::vector<CComPtr<Symbol>> *pChildren) const;
|
||||
HRESULT DbgScopeOf(const llvm::Instruction *instr, SymbolChildrenEnumerator **ppRet) const;
|
||||
|
||||
private:
|
||||
HRESULT ChildrenOf(DWORD ID, std::vector<CComPtr<Symbol>> *pChildren) const;
|
||||
|
||||
// Not a CComPtr, and not AddRef'd - m_pSession is the owner of this.
|
||||
Session *m_pSession = nullptr;
|
||||
|
||||
// Vector of all symbols in the DXIL module.
|
||||
std::vector<CreateSymbolFn> m_symbolCtors;
|
||||
|
||||
// Mapping from scope to its ID.
|
||||
ScopeToIDMap m_scopeToID;
|
||||
|
||||
// Mapping from symbol ID to live range. Globals are live [0, end),
|
||||
// locals, [first dbg.declare, end of scope)
|
||||
// TODO: the live range information assumes structured dxil - which should hold
|
||||
// for non-optimized code - so we need something more robust. For now, this is
|
||||
// good enough.
|
||||
IDToLiveRangeMap m_symbolToLiveRange;
|
||||
|
||||
ParentToChildrenMap m_parentToChildren;
|
||||
};
|
||||
} // namespace dxil_dia
|
|
@ -25,22 +25,23 @@ HRESULT dxil_dia::Table::Create(
|
|||
/* [in] */ Session *pSession,
|
||||
/* [in] */ Table::Kind kind,
|
||||
/* [out] */ IDiaTable **ppTable) {
|
||||
*ppTable = nullptr;
|
||||
IMalloc *pMalloc = pSession->GetMallocNoRef();
|
||||
switch (kind) {
|
||||
case Table::Kind::Symbols: *ppTable = CreateOnMalloc<SymbolsTable>(pMalloc, pSession); break;
|
||||
case Table::Kind::SourceFiles: *ppTable = CreateOnMalloc<SourceFilesTable>(pMalloc, pSession); break;
|
||||
case Table::Kind::LineNumbers: *ppTable = CreateOnMalloc<LineNumbersTable>(pMalloc, pSession); break;
|
||||
case Table::Kind::Sections: *ppTable = CreateOnMalloc<SectionsTable>(pMalloc, pSession); break;
|
||||
case Table::Kind::SegmentMap: *ppTable = CreateOnMalloc<SegmentMapTable>(pMalloc, pSession); break;
|
||||
case Table::Kind::InjectedSource: *ppTable = CreateOnMalloc<InjectedSourcesTable>(pMalloc, pSession); break;
|
||||
case Table::Kind::FrameData: *ppTable = CreateOnMalloc<FrameDataTable>(pMalloc, pSession); break;
|
||||
case Table::Kind::InputAssemblyFile: *ppTable = CreateOnMalloc<InputAssemblyFilesTable>(pMalloc, pSession); break;
|
||||
default: return E_FAIL;
|
||||
}
|
||||
if (*ppTable == nullptr)
|
||||
return E_OUTOFMEMORY;
|
||||
(*ppTable)->AddRef();
|
||||
return S_OK;
|
||||
return E_NOTIMPL;
|
||||
try {
|
||||
*ppTable = nullptr;
|
||||
IMalloc *pMalloc = pSession->GetMallocNoRef();
|
||||
switch (kind) {
|
||||
case Table::Kind::Symbols: *ppTable = CreateOnMalloc<SymbolsTable>(pMalloc, pSession); break;
|
||||
case Table::Kind::SourceFiles: *ppTable = CreateOnMalloc<SourceFilesTable>(pMalloc, pSession); break;
|
||||
case Table::Kind::LineNumbers: *ppTable = CreateOnMalloc<LineNumbersTable>(pMalloc, pSession); break;
|
||||
case Table::Kind::Sections: *ppTable = CreateOnMalloc<SectionsTable>(pMalloc, pSession); break;
|
||||
case Table::Kind::SegmentMap: *ppTable = CreateOnMalloc<SegmentMapTable>(pMalloc, pSession); break;
|
||||
case Table::Kind::InjectedSource: *ppTable = CreateOnMalloc<InjectedSourcesTable>(pMalloc, pSession); break;
|
||||
case Table::Kind::FrameData: *ppTable = CreateOnMalloc<FrameDataTable>(pMalloc, pSession); break;
|
||||
case Table::Kind::InputAssemblyFile: *ppTable = CreateOnMalloc<InputAssemblyFilesTable>(pMalloc, pSession); break;
|
||||
default: return E_FAIL;
|
||||
}
|
||||
if (*ppTable == nullptr)
|
||||
return E_OUTOFMEMORY;
|
||||
(*ppTable)->AddRef();
|
||||
return S_OK;
|
||||
} CATCH_CPP_RETURN_HRESULT();
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "dia2.h"
|
||||
|
||||
#include "dxc/Support/Global.h"
|
||||
#include "dxc/Support/microcom.h"
|
||||
|
||||
#include "DxilDia.h"
|
||||
|
@ -47,6 +48,19 @@ namespace impl {
|
|||
|
||||
template<typename T, typename TItem>
|
||||
class TableBase : public IDiaTable, public T {
|
||||
public:
|
||||
// COM Interfaces do not have virtual destructors; they instead rely on
|
||||
// AddRef/Release matching calls for managing object lifetimes. This
|
||||
// template is inherited by the implementing table types (which is fine),
|
||||
// and it also provides the base implementation of the COM's memory
|
||||
// management callbacks (which is not fine: once a table goes out of scope
|
||||
// a method in this class will invoke the object's destructor -- which, being
|
||||
// non-virtual, will be this class' instead of the derived table's.) Therefore,
|
||||
// we introduce a virtual destructor.
|
||||
virtual ~TableBase() {
|
||||
DXASSERT(m_dwRef == 0, "deleting COM table with active references");
|
||||
}
|
||||
|
||||
protected:
|
||||
static constexpr LPCWSTR TableNames[] = {
|
||||
L"Symbols",
|
||||
|
@ -64,6 +78,7 @@ protected:
|
|||
unsigned m_next;
|
||||
unsigned m_count;
|
||||
Table::Kind m_kind;
|
||||
|
||||
public:
|
||||
DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL()
|
||||
|
||||
|
|
|
@ -64,9 +64,61 @@ STDMETHODIMP dxil_dia::LineNumber::get_columnNumberEnd(
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::LineNumber::get_addressOffset(
|
||||
/* [retval][out] */ DWORD *pRetVal) {
|
||||
return get_relativeVirtualAddress(pRetVal);
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::LineNumber::get_relativeVirtualAddress(
|
||||
/* [retval][out] */ DWORD *pRetVal) {
|
||||
*pRetVal = m_pSession->RvaMapRef()[m_inst];
|
||||
if (pRetVal == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*pRetVal = 0;
|
||||
|
||||
const auto &rvaMap = m_pSession->RvaMapRef();
|
||||
auto it = rvaMap.find(m_inst);
|
||||
if (it == rvaMap.end()) {
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
*pRetVal = it->second;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::LineNumber::get_length(
|
||||
/* [retval][out] */ DWORD *pRetVal) {
|
||||
if (pRetVal == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*pRetVal = 1;
|
||||
|
||||
if (llvm::DebugLoc DL = m_inst->getDebugLoc()) {
|
||||
const auto &LineToColumn = m_pSession->LineToColumnStartMapRef();
|
||||
auto it = LineToColumn.find(DL.getLine());
|
||||
if (it != LineToColumn.end()) {
|
||||
*pRetVal = it->second.Last - it->second.First;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::LineNumber::get_statement(
|
||||
/* [retval][out] */ BOOL *pRetVal) {
|
||||
if (pRetVal == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*pRetVal = FALSE;
|
||||
|
||||
if (llvm::DebugLoc DL = m_inst->getDebugLoc()) {
|
||||
const auto &LineToColumn = m_pSession->LineToColumnStartMapRef();
|
||||
auto it = LineToColumn.find(DL.getLine());
|
||||
if (it != LineToColumn.end()) {
|
||||
*pRetVal = it->second.StartCol == DL.getCol();
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,8 @@ public:
|
|||
|
||||
const llvm::DebugLoc &DL() const;
|
||||
|
||||
const llvm::Instruction *Inst() const { return m_inst; }
|
||||
|
||||
STDMETHODIMP get_compiland(
|
||||
/* [retval][out] */ IDiaSymbol **pRetVal) override { return ENotImpl(); }
|
||||
|
||||
|
@ -70,7 +72,7 @@ public:
|
|||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
|
||||
STDMETHODIMP get_addressOffset(
|
||||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
/* [retval][out] */ DWORD *pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_relativeVirtualAddress(
|
||||
/* [retval][out] */ DWORD *pRetVal) override;
|
||||
|
@ -79,13 +81,13 @@ public:
|
|||
/* [retval][out] */ ULONGLONG *pRetVal) override { return ENotImpl(); }
|
||||
|
||||
STDMETHODIMP get_length(
|
||||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
/* [retval][out] */ DWORD *pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_sourceFileId(
|
||||
/* [retval][out] */ DWORD *pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_statement(
|
||||
/* [retval][out] */ BOOL *pRetVal) override { return ENotImpl(); }
|
||||
/* [retval][out] */ BOOL *pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_compilandId(
|
||||
/* [retval][out] */ DWORD *pRetVal) override;
|
||||
|
|
|
@ -44,14 +44,23 @@ dxil_dia::SourceFilesTable::SourceFilesTable(
|
|||
m_items.assign(m_count, nullptr);
|
||||
}
|
||||
|
||||
HRESULT dxil_dia::SourceFilesTable::GetItem(DWORD index, IDiaSourceFile **ppItem) {
|
||||
if (!m_items[index]) {
|
||||
m_items[index] = CreateOnMalloc<SourceFile>(m_pMalloc, m_pSession, index);
|
||||
if (m_items[index] == nullptr)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
m_items[index].p->AddRef();
|
||||
*ppItem = m_items[index];
|
||||
(*ppItem)->AddRef();
|
||||
return S_OK;
|
||||
dxil_dia::SourceFilesTable::SourceFilesTable(
|
||||
IMalloc *pMalloc,
|
||||
Session *pSession,
|
||||
std::vector<CComPtr<IDiaSourceFile>> &&items)
|
||||
: impl::TableBase<IDiaEnumSourceFiles, IDiaSourceFile>(pMalloc, pSession, Table::Kind::SourceFiles),
|
||||
m_items(std::move(items)) {
|
||||
m_count = m_items.size();
|
||||
}
|
||||
|
||||
HRESULT dxil_dia::SourceFilesTable::GetItem(DWORD index, IDiaSourceFile **ppItem) {
|
||||
if (!m_items[index]) {
|
||||
m_items[index] = CreateOnMalloc<SourceFile>(m_pMalloc, m_pSession, index);
|
||||
if (m_items[index] == nullptr)
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
m_items[index].p->AddRef();
|
||||
*ppItem = m_items[index];
|
||||
(*ppItem)->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -69,6 +69,8 @@ public:
|
|||
class SourceFilesTable : public impl::TableBase<IDiaEnumSourceFiles, IDiaSourceFile> {
|
||||
public:
|
||||
SourceFilesTable(IMalloc *pMalloc, Session *pSession);
|
||||
SourceFilesTable(IMalloc *pMalloc, Session *pSession,
|
||||
std::vector<CComPtr<IDiaSourceFile>> &&items);
|
||||
|
||||
HRESULT GetItem(DWORD index, IDiaSourceFile **ppItem) override;
|
||||
|
||||
|
|
|
@ -14,28 +14,30 @@
|
|||
#include <comdef.h>
|
||||
|
||||
#include "dxc/Support/Unicode.h"
|
||||
#include "llvm/ADT/DenseSet.h"
|
||||
#include "llvm/IR/DebugInfo.h"
|
||||
#include "llvm/IR/DebugInfoMetadata.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/IR/Metadata.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Support/raw_os_ostream.h"
|
||||
|
||||
#include "DxilDiaSession.h"
|
||||
|
||||
HRESULT dxil_dia::Symbol::Create(IMalloc *pMalloc, Session *pSession, DWORD index, DWORD symTag, Symbol **pSymbol) {
|
||||
*pSymbol = Alloc(pMalloc);
|
||||
if (*pSymbol == nullptr) return E_OUTOFMEMORY;
|
||||
(*pSymbol)->AddRef();
|
||||
(*pSymbol)->Init(pSession, index, symTag);
|
||||
return S_OK;
|
||||
}
|
||||
dxil_dia::Symbol::~Symbol() = default;
|
||||
|
||||
void dxil_dia::Symbol::Init(Session *pSession, DWORD index, DWORD symTag) {
|
||||
void dxil_dia::Symbol::Init(Session *pSession, DWORD ID, DWORD symTag) {
|
||||
DXASSERT_ARGS(m_pSession == nullptr, "Double init on symbol %d", ID);
|
||||
m_pSession = pSession;
|
||||
m_index = index;
|
||||
m_ID = ID;
|
||||
m_symTag = symTag;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_symIndexId(
|
||||
/* [retval][out] */ DWORD *pRetVal) {
|
||||
*pRetVal = m_index;
|
||||
*pRetVal = m_ID;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
@ -47,119 +49,377 @@ STDMETHODIMP dxil_dia::Symbol::get_symTag(
|
|||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_name(
|
||||
/* [retval][out] */ BSTR *pRetVal) {
|
||||
DxcThreadMalloc TM(m_pSession->GetMallocNoRef());
|
||||
if (pRetVal == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*pRetVal = nullptr;
|
||||
if (!m_hasName) {
|
||||
return S_FALSE;
|
||||
}
|
||||
return m_name.CopyTo(pRetVal);
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_lexicalParent(
|
||||
/* [retval][out] */ IDiaSymbol **pRetVal) {
|
||||
if (pRetVal == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*pRetVal = nullptr;
|
||||
|
||||
DWORD dwParentID = this->m_lexicalParent;
|
||||
if (dwParentID == 0) {
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
Symbol *pParent;
|
||||
IFR(m_pSession->SymMgr().GetSymbolByID(dwParentID, &pParent));
|
||||
|
||||
*pRetVal = pParent;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_type(
|
||||
/* [retval][out] */ IDiaSymbol **pRetVal) {
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_dataKind(
|
||||
/* [retval][out] */ DWORD *pRetVal) {
|
||||
if (pRetVal == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*pRetVal = 0;
|
||||
if (!m_hasDataKind) {
|
||||
return S_FALSE;
|
||||
}
|
||||
*pRetVal = m_dataKind;
|
||||
return m_dataKind ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_locationType(
|
||||
/* [retval][out] */ DWORD *pRetVal) {
|
||||
if (pRetVal == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*pRetVal = LocIsNull;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_sourceFileName(
|
||||
/* [retval][out] */ BSTR *pRetVal) {
|
||||
if (pRetVal == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*pRetVal = nullptr;
|
||||
if (!m_hasSourceFileName) {
|
||||
return S_FALSE;
|
||||
}
|
||||
*pRetVal = m_sourceFileName.Copy();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_value(
|
||||
/* [retval][out] */ VARIANT *pRetVal) {
|
||||
if (pRetVal == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
ZeroMemory(pRetVal, sizeof(*pRetVal));
|
||||
if (!m_hasValue) {
|
||||
return S_FALSE;
|
||||
}
|
||||
return VariantCopy(pRetVal, &m_value);
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_baseType(
|
||||
/* [retval][out] */ DWORD *pRetVal) {
|
||||
if (pRetVal != nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*pRetVal = btNoType;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_count(
|
||||
/* [retval][out] */ DWORD *pRetVal) {
|
||||
if (pRetVal == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*pRetVal = 0;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_offset(
|
||||
/* [retval][out] */ LONG *pRetVal) {
|
||||
if (pRetVal != nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*pRetVal = 0;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_length(
|
||||
/* [retval][out] */ ULONGLONG *pRetVal) {
|
||||
if (pRetVal != nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*pRetVal = 0;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_lexicalParentId(
|
||||
/* [retval][out] */ DWORD *pRetVal) {
|
||||
if (pRetVal == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*pRetVal = 0;
|
||||
if (!m_hasLexicalParent) {
|
||||
return S_FALSE;
|
||||
}
|
||||
*pRetVal = m_lexicalParent;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void dxil_dia::SymbolChildrenEnumerator::Init(std::vector<CComPtr<Symbol>> &&syms) {
|
||||
std::swap(syms, m_symbols);
|
||||
m_pos = m_symbols.begin();
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE dxil_dia::SymbolChildrenEnumerator::get_Count(
|
||||
/* [retval][out] */ LONG *pRetVal) {
|
||||
if (pRetVal == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*pRetVal = m_symbols.size();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE dxil_dia::SymbolChildrenEnumerator::Item(
|
||||
/* [in] */ DWORD index,
|
||||
/* [retval][out] */ IDiaSymbol **symbol) {
|
||||
if (symbol == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*symbol = nullptr;
|
||||
|
||||
if (index < 0 || index > m_symbols.size()) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*symbol = m_symbols[index];
|
||||
(*symbol)->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE dxil_dia::SymbolChildrenEnumerator::Reset(void) {
|
||||
m_pos = m_symbols.begin();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT STDMETHODCALLTYPE dxil_dia::SymbolChildrenEnumerator::Next(
|
||||
/* [in] */ ULONG celt,
|
||||
/* [out] */ IDiaSymbol **rgelt,
|
||||
/* [out] */ ULONG *pceltFetched) {
|
||||
DxcThreadMalloc TM(m_pMalloc);
|
||||
if (rgelt == nullptr || pceltFetched == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*pceltFetched = 0;
|
||||
ZeroMemory(rgelt, sizeof(*rgelt) * celt);
|
||||
|
||||
for (; *pceltFetched < celt && m_pos != m_symbols.end(); ++m_pos, ++rgelt, ++(*pceltFetched)) {
|
||||
*rgelt = *m_pos;
|
||||
(*rgelt)->AddRef();
|
||||
}
|
||||
|
||||
return (*pceltFetched == celt) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::findChildren(
|
||||
/* [in] */ enum SymTagEnum symtag,
|
||||
/* [in] */ LPCOLESTR name,
|
||||
/* [in] */ DWORD compareFlags,
|
||||
/* [out] */ IDiaEnumSymbols **ppResult) {
|
||||
return findChildrenEx(symtag, name, compareFlags, ppResult);;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::findChildrenEx(
|
||||
/* [in] */ enum SymTagEnum symtag,
|
||||
/* [in] */ LPCOLESTR name,
|
||||
/* [in] */ DWORD compareFlags,
|
||||
/* [out] */ IDiaEnumSymbols **ppResult) {
|
||||
DxcThreadMalloc TM(m_pMalloc);
|
||||
if (ppResult == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*ppResult = nullptr;
|
||||
|
||||
CComPtr<SymbolChildrenEnumerator> ret = SymbolChildrenEnumerator::Alloc(m_pMalloc);
|
||||
if (!ret) {
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
std::vector<CComPtr<Symbol>> children;
|
||||
IFR(GetChildren(&children));
|
||||
|
||||
if (symtag != nsNone) {
|
||||
std::vector<CComPtr<Symbol>> tmp;
|
||||
tmp.reserve(children.size());
|
||||
for (const auto & c : children) {
|
||||
if (c->m_symTag == symtag) {
|
||||
tmp.emplace_back(c);
|
||||
}
|
||||
}
|
||||
std::swap(tmp, children);
|
||||
}
|
||||
|
||||
if (name != nullptr && compareFlags != nsNone) {
|
||||
std::vector<CComPtr<Symbol>> tmp;
|
||||
tmp.reserve(children.size());
|
||||
for (const auto & c : children) {
|
||||
CComBSTR cName;
|
||||
IFR(c->get_name(&cName));
|
||||
if (compareFlags == nsfCaseInsensitive && StrCmpW(cName, name) != 0) {
|
||||
continue;
|
||||
} else if (compareFlags == nsfCaseSensitive && StrCmpIW(cName, name) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c->m_symTag == symtag) {
|
||||
tmp.emplace_back(c);
|
||||
}
|
||||
}
|
||||
std::swap(tmp, children);
|
||||
}
|
||||
|
||||
ret->Init(std::move(children));
|
||||
|
||||
*ppResult = ret.Detach();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_isAggregated(
|
||||
/* [retval][out] */ BOOL *pRetVal) {
|
||||
if (pRetVal == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*pRetVal = false;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_registerType(
|
||||
/* [retval][out] */ DWORD *pRetVal) {
|
||||
if (pRetVal == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*pRetVal = 0;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_sizeInUdt(
|
||||
/* [retval][out] */ DWORD *pRetVal) {
|
||||
if (pRetVal == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*pRetVal = 0;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_liveRangeStartAddressOffset(
|
||||
/* [retval][out] */ DWORD *pRetVal) {
|
||||
if (pRetVal == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*pRetVal = 0;
|
||||
|
||||
SymbolManager::LiveRange LR;
|
||||
IFR(m_pSession->SymMgr().GetLiveRangeOf(this, &LR));
|
||||
*pRetVal = LR.Start;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_liveRangeLength(
|
||||
/* [retval][out] */ ULONGLONG *pRetVal) {
|
||||
if (pRetVal == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*pRetVal = 0;
|
||||
|
||||
SymbolManager::LiveRange LR;
|
||||
IFR(m_pSession->SymMgr().GetLiveRangeOf(this, &LR));
|
||||
*pRetVal = LR.Length;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_offsetInUdt(
|
||||
/* [retval][out] */ DWORD *pRetVal) {
|
||||
if (pRetVal == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*pRetVal = 0;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_numericProperties(
|
||||
/* [in] */ DWORD cnt,
|
||||
/* [out] */ DWORD *pcnt,
|
||||
/* [size_is][out] */ DWORD *pProperties) {
|
||||
if (pcnt == nullptr || pProperties == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
ZeroMemory(pProperties, sizeof(*pProperties) * cnt);
|
||||
*pcnt = 0;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_numberOfRegisterIndices(
|
||||
/* [retval][out] */ DWORD *pRetVal) {
|
||||
if (pRetVal == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
*pRetVal = 0;
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
STDMETHODIMP dxil_dia::Symbol::get_isHLSLData(
|
||||
/* [retval][out] */ BOOL *pRetVal) {
|
||||
if (pRetVal == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*pRetVal = false;
|
||||
if (!m_hasIsHLSLData) {
|
||||
return S_FALSE;
|
||||
}
|
||||
*pRetVal = m_isHLSLData;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
dxil_dia::SymbolsTable::SymbolsTable(IMalloc *pMalloc, Session *pSession)
|
||||
: impl::TableBase<IDiaEnumSymbols, IDiaSymbol>(pMalloc, pSession, Table::Kind::Symbols) {
|
||||
// The count is as follows:
|
||||
// One symbol for the program.
|
||||
// One Compiland per compilation unit.
|
||||
// One CompilandDetails per compilation unit.
|
||||
// Three CompilandEnv per Compliands: hlslFlags, hlslTarget, hlslEntry, hlslDefines, hlslArguments.
|
||||
// One Function/Data for each global.
|
||||
// One symbol for each type.
|
||||
const size_t SymbolsPerCU = 1 + 1 + 5;
|
||||
m_count = 1 + pSession->InfoRef().compile_unit_count() * SymbolsPerCU;
|
||||
m_count = pSession->SymMgr().NumSymbols();
|
||||
}
|
||||
|
||||
HRESULT dxil_dia::SymbolsTable::GetItem(DWORD index, IDiaSymbol **ppItem) {
|
||||
DxcThreadMalloc TM(m_pMalloc);
|
||||
|
||||
// Ids are one-based, so adjust the index.
|
||||
++index;
|
||||
|
||||
// Program symbol.
|
||||
CComPtr<Symbol> item;
|
||||
if (index == HlslProgramId) {
|
||||
IFR(Symbol::Create(m_pMalloc, m_pSession, index, SymTagExe, &item));
|
||||
item->SetName(L"HLSL");
|
||||
} else if (index == HlslCompilandId) {
|
||||
IFR(Symbol::Create(m_pMalloc, m_pSession, index, SymTagCompiland, &item));
|
||||
item->SetName(L"main");
|
||||
item->SetLexicalParent(HlslProgramId);
|
||||
if (m_pSession->MainFileName()) {
|
||||
llvm::StringRef strRef = llvm::dyn_cast<llvm::MDString>(m_pSession->MainFileName()->getOperand(0)->getOperand(0))->getString();
|
||||
std::string str(strRef.begin(), strRef.size()); // To make sure str is null terminated
|
||||
item->SetSourceFileName(_bstr_t(Unicode::UTF8ToUTF16StringOrThrow(str.data()).c_str()));
|
||||
}
|
||||
} else if (index == HlslCompilandDetailsId) {
|
||||
IFR(Symbol::Create(m_pMalloc, m_pSession, index, SymTagCompilandDetails, &item));
|
||||
item->SetLexicalParent(HlslCompilandId);
|
||||
// TODO: complete the rest of the compiland details
|
||||
// platform: 256, language: 16, frontEndMajor: 6, frontEndMinor: 3, value: 0, hasDebugInfo: 1, compilerName: comiler string goes here
|
||||
} else if (index == HlslCompilandEnvFlagsId) {
|
||||
IFR(Symbol::Create(m_pMalloc, m_pSession, index, SymTagCompilandEnv, &item));
|
||||
item->SetLexicalParent(HlslCompilandId);
|
||||
item->SetName(L"hlslFlags");
|
||||
item->SetValue(m_pSession->DxilModuleRef().GetGlobalFlags());
|
||||
} else if (index == HlslCompilandEnvTargetId) {
|
||||
IFR(Symbol::Create(m_pMalloc, m_pSession, index, SymTagCompilandEnv, &item));
|
||||
item->SetLexicalParent(HlslCompilandId);
|
||||
item->SetName(L"hlslTarget");
|
||||
item->SetValue(m_pSession->DxilModuleRef().GetShaderModel()->GetName());
|
||||
} else if (index == HlslCompilandEnvEntryId) {
|
||||
IFR(Symbol::Create(m_pMalloc, m_pSession, index, SymTagCompilandEnv, &item));
|
||||
item->SetLexicalParent(HlslCompilandId);
|
||||
item->SetName(L"hlslEntry");
|
||||
item->SetValue(m_pSession->DxilModuleRef().GetEntryFunctionName().c_str());
|
||||
} else if (index == HlslCompilandEnvDefinesId) {
|
||||
IFR(Symbol::Create(m_pMalloc, m_pSession, index, SymTagCompilandEnv, &item));
|
||||
item->SetLexicalParent(HlslCompilandId);
|
||||
item->SetName(L"hlslDefines");
|
||||
llvm::MDNode *definesNode = m_pSession->Defines()->getOperand(0);
|
||||
// Construct a double null terminated string for defines with L"\0" as a delimiter
|
||||
CComBSTR pBSTR;
|
||||
for (llvm::MDNode::op_iterator it = definesNode->op_begin(); it != definesNode->op_end(); ++it) {
|
||||
llvm::StringRef strRef = llvm::dyn_cast<llvm::MDString>(*it)->getString();
|
||||
std::string str(strRef.begin(), strRef.size());
|
||||
CA2W cv(str.c_str());
|
||||
pBSTR.Append(cv);
|
||||
pBSTR.Append(L"\0", 1);
|
||||
}
|
||||
pBSTR.Append(L"\0", 1);
|
||||
VARIANT Variant;
|
||||
Variant.bstrVal = pBSTR;
|
||||
Variant.vt = VARENUM::VT_BSTR;
|
||||
item->SetValue(&Variant);
|
||||
} else if (index == HlslCompilandEnvArgumentsId) {
|
||||
IFR(Symbol::Create(m_pMalloc, m_pSession, index, SymTagCompilandEnv, &item));
|
||||
item->SetLexicalParent(HlslCompilandId);
|
||||
item->SetName(L"hlslArguments");
|
||||
auto Arguments = m_pSession->Arguments()->getOperand(0);
|
||||
auto NumArguments = Arguments->getNumOperands();
|
||||
std::string args;
|
||||
for (unsigned i = 0; i < NumArguments; ++i) {
|
||||
llvm::StringRef strRef = llvm::dyn_cast<llvm::MDString>(Arguments->getOperand(i))->getString();
|
||||
if (!args.empty())
|
||||
args.push_back(' ');
|
||||
args = args + strRef.str();
|
||||
}
|
||||
item->SetValue(args.c_str());
|
||||
if (ppItem == nullptr) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
*ppItem = nullptr;
|
||||
|
||||
// TODO: add support for global data and functions as well as types.
|
||||
Symbol *ret = nullptr;
|
||||
const DWORD dwSymID = index + 1;
|
||||
IFR(m_pSession->SymMgr().GetSymbolByID(dwSymID, &ret));
|
||||
|
||||
*ppItem = item.Detach();
|
||||
return (*ppItem == nullptr) ? E_FAIL : S_OK;
|
||||
*ppItem = ret;
|
||||
return S_OK;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include "dxc/Support/WinIncludes.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "dia2.h"
|
||||
|
||||
#include "dxc/Support/Global.h"
|
||||
|
@ -26,32 +28,50 @@ class Session;
|
|||
|
||||
class Symbol : public IDiaSymbol {
|
||||
DXC_MICROCOM_TM_REF_FIELDS()
|
||||
|
||||
protected:
|
||||
DXC_MICROCOM_TM_CTOR_ONLY(Symbol)
|
||||
|
||||
CComPtr<Session> m_pSession;
|
||||
DWORD m_index;
|
||||
|
||||
private:
|
||||
DWORD m_ID;
|
||||
DWORD m_symTag;
|
||||
bool m_hasLexicalParent = false;
|
||||
DWORD m_lexicalParent = 0;
|
||||
bool m_hasIsHLSLData = false;
|
||||
bool m_isHLSLData = false;
|
||||
bool m_hasDataKind = false;
|
||||
DWORD m_dataKind = 0;
|
||||
bool m_hasSourceFileName = false;
|
||||
CComBSTR m_sourceFileName;
|
||||
bool m_hasName = false;
|
||||
CComBSTR m_name;
|
||||
bool m_hasValue = false;
|
||||
CComVariant m_value;
|
||||
|
||||
public:
|
||||
virtual ~Symbol();
|
||||
DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL()
|
||||
DXC_MICROCOM_TM_CTOR(Symbol)
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) {
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) final {
|
||||
return DoBasicQueryInterface<IDiaSymbol>(this, iid, ppvObject);
|
||||
}
|
||||
|
||||
static HRESULT Create(IMalloc *pMalloc, Session *pSession, DWORD index, DWORD symTag, Symbol **pSymbol);
|
||||
|
||||
void Init(Session *pSession, DWORD index, DWORD symTag);
|
||||
|
||||
void SetDataKind(DWORD value) { m_dataKind = value; }
|
||||
void SetLexicalParent(DWORD value) { m_lexicalParent = value; }
|
||||
void SetName(LPCWSTR value) { m_name = value; }
|
||||
void SetValue(LPCSTR value) { m_value = value; }
|
||||
void SetValue(VARIANT *pValue) { m_value.Copy(pValue); }
|
||||
void SetValue(unsigned value) { m_value = value; }
|
||||
void SetSourceFileName(BSTR value) { m_sourceFileName = value; }
|
||||
DWORD GetID() const { return m_ID; }
|
||||
|
||||
void SetDataKind(DWORD value) { m_hasDataKind = true; m_dataKind = value; }
|
||||
void SetLexicalParent(DWORD value) { m_hasLexicalParent = true; m_lexicalParent = value; }
|
||||
bool HasName() const { return m_hasName; }
|
||||
void SetName(LPCWSTR value) { m_hasName = true; m_name = value; }
|
||||
void SetValue(LPCSTR value) { m_hasValue = true; m_value = value; }
|
||||
void SetValue(VARIANT *pValue) { m_hasValue = true; m_value.Copy(pValue); }
|
||||
void SetValue(unsigned value) { m_hasValue = true; m_value = value; }
|
||||
void SetSourceFileName(BSTR value) { m_hasSourceFileName = true; m_sourceFileName = value; }
|
||||
void SetIsHLSLData(bool value) { m_hasIsHLSLData = true; m_isHLSLData = value; }
|
||||
|
||||
virtual HRESULT GetChildren(std::vector<CComPtr<Symbol>> *children) = 0;
|
||||
|
||||
#pragma region IDiaSymbol implementation.
|
||||
STDMETHODIMP get_symIndexId(
|
||||
|
@ -64,19 +84,19 @@ public:
|
|||
/* [retval][out] */ BSTR *pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_lexicalParent(
|
||||
/* [retval][out] */ IDiaSymbol **pRetVal) override { return ENotImpl(); }
|
||||
/* [retval][out] */ IDiaSymbol **pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_classParent(
|
||||
/* [retval][out] */ IDiaSymbol **pRetVal) override { return ENotImpl(); }
|
||||
|
||||
STDMETHODIMP get_type(
|
||||
/* [retval][out] */ IDiaSymbol **pRetVal) override { return ENotImpl(); }
|
||||
/* [retval][out] */ IDiaSymbol **pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_dataKind(
|
||||
/* [retval][out] */ DWORD *pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_locationType(
|
||||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
/* [retval][out] */ DWORD *pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_addressSection(
|
||||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
|
@ -94,10 +114,10 @@ public:
|
|||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
|
||||
STDMETHODIMP get_offset(
|
||||
/* [retval][out] */ LONG *pRetVal) override { return ENotImpl(); }
|
||||
/* [retval][out] */ LONG *pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_length(
|
||||
/* [retval][out] */ ULONGLONG *pRetVal) override { return ENotImpl(); }
|
||||
/* [retval][out] */ ULONGLONG *pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_slot(
|
||||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
|
@ -175,7 +195,7 @@ public:
|
|||
/* [retval][out] */ VARIANT *pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_baseType(
|
||||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
/* [retval][out] */ DWORD *pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_token(
|
||||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
|
@ -193,7 +213,7 @@ public:
|
|||
/* [retval][out] */ BOOL *pRetVal) override { return ENotImpl(); }
|
||||
|
||||
STDMETHODIMP get_count(
|
||||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
/* [retval][out] */ DWORD *pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_bitPosition(
|
||||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
|
@ -238,7 +258,7 @@ public:
|
|||
/* [retval][out] */ IDiaSymbol **pRetVal) override { return ENotImpl(); }
|
||||
|
||||
STDMETHODIMP get_lexicalParentId(
|
||||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
/* [retval][out] */ DWORD *pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_classParentId(
|
||||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
|
@ -306,13 +326,13 @@ public:
|
|||
/* [in] */ enum SymTagEnum symtag,
|
||||
/* [in] */ LPCOLESTR name,
|
||||
/* [in] */ DWORD compareFlags,
|
||||
/* [out] */ IDiaEnumSymbols **ppResult) override { return ENotImpl(); }
|
||||
/* [out] */ IDiaEnumSymbols **ppResult) override;
|
||||
|
||||
STDMETHODIMP findChildrenEx(
|
||||
/* [in] */ enum SymTagEnum symtag,
|
||||
/* [in] */ LPCOLESTR name,
|
||||
/* [in] */ DWORD compareFlags,
|
||||
/* [out] */ IDiaEnumSymbols **ppResult) override { return ENotImpl(); }
|
||||
/* [out] */ IDiaEnumSymbols **ppResult) override;
|
||||
|
||||
STDMETHODIMP findChildrenExByAddr(
|
||||
/* [in] */ enum SymTagEnum symtag,
|
||||
|
@ -441,7 +461,7 @@ public:
|
|||
/* [retval][out] */ BOOL *pRetVal) override { return ENotImpl(); }
|
||||
|
||||
STDMETHODIMP get_isAggregated(
|
||||
/* [retval][out] */ BOOL *pRetVal) override { return ENotImpl(); }
|
||||
/* [retval][out] */ BOOL *pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_isSplitted(
|
||||
/* [retval][out] */ BOOL *pRetVal) override { return ENotImpl(); }
|
||||
|
@ -522,7 +542,7 @@ public:
|
|||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
|
||||
STDMETHODIMP get_liveRangeStartAddressOffset(
|
||||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
/* [retval][out] */ DWORD *pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_liveRangeStartRelativeVirtualAddress(
|
||||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
|
@ -531,10 +551,10 @@ public:
|
|||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
|
||||
STDMETHODIMP get_liveRangeLength(
|
||||
/* [retval][out] */ ULONGLONG *pRetVal) override { return ENotImpl(); }
|
||||
/* [retval][out] */ ULONGLONG *pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_offsetInUdt(
|
||||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
/* [retval][out] */ DWORD *pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_paramBasePointerRegisterId(
|
||||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
|
@ -560,7 +580,7 @@ public:
|
|||
STDMETHODIMP get_numericProperties(
|
||||
/* [in] */ DWORD cnt,
|
||||
/* [out] */ DWORD *pcnt,
|
||||
/* [size_is][out] */ DWORD *pProperties) override { return ENotImpl(); }
|
||||
/* [size_is][out] */ DWORD *pProperties) override;
|
||||
|
||||
STDMETHODIMP get_modifierValues(
|
||||
/* [in] */ DWORD cnt,
|
||||
|
@ -577,7 +597,7 @@ public:
|
|||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
|
||||
STDMETHODIMP get_registerType(
|
||||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
/* [retval][out] */ DWORD *pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_baseDataSlot(
|
||||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
|
@ -595,7 +615,7 @@ public:
|
|||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
|
||||
STDMETHODIMP get_sizeInUdt(
|
||||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
/* [retval][out] */ DWORD *pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_memorySpaceKind(
|
||||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
|
@ -613,10 +633,10 @@ public:
|
|||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
|
||||
STDMETHODIMP get_numberOfRegisterIndices(
|
||||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
/* [retval][out] */ DWORD *pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_isHLSLData(
|
||||
/* [retval][out] */ BOOL *pRetVal) override { return ENotImpl(); }
|
||||
/* [retval][out] */ BOOL *pRetVal) override;
|
||||
|
||||
STDMETHODIMP get_isPointerToDataMember(
|
||||
/* [retval][out] */ BOOL *pRetVal) override { return ENotImpl(); }
|
||||
|
@ -808,7 +828,48 @@ public:
|
|||
STDMETHODIMP get_bindSlot(
|
||||
/* [retval][out] */ DWORD *pRetVal) override { return ENotImpl(); }
|
||||
|
||||
#pragma endregion IDiaSymbol implementation.
|
||||
#pragma endregion
|
||||
};
|
||||
|
||||
class SymbolChildrenEnumerator : public IDiaEnumSymbols {
|
||||
public:
|
||||
DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL()
|
||||
DXC_MICROCOM_TM_CTOR(SymbolChildrenEnumerator)
|
||||
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) {
|
||||
return DoBasicQueryInterface<IDiaEnumSymbols>(this, iid, ppvObject);
|
||||
}
|
||||
|
||||
void Init(std::vector<CComPtr<Symbol>> &&syms);
|
||||
|
||||
#pragma region IDiaEnumSymbols implementation
|
||||
/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get__NewEnum(
|
||||
/* [retval][out] */ IUnknown **pRetVal) override { return ENotImpl(); }
|
||||
|
||||
/* [id][helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Count(
|
||||
/* [retval][out] */ LONG *pRetVal) override;
|
||||
|
||||
/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Item(
|
||||
/* [in] */ DWORD index,
|
||||
/* [retval][out] */ IDiaSymbol **symbol) override;
|
||||
|
||||
HRESULT STDMETHODCALLTYPE Next(
|
||||
/* [in] */ ULONG celt,
|
||||
/* [out] */ IDiaSymbol **rgelt,
|
||||
/* [out] */ ULONG *pceltFetched) override;
|
||||
|
||||
HRESULT STDMETHODCALLTYPE Skip(
|
||||
/* [in] */ ULONG celt) override { return ENotImpl(); }
|
||||
|
||||
HRESULT STDMETHODCALLTYPE Reset(void) override;
|
||||
|
||||
HRESULT STDMETHODCALLTYPE Clone(
|
||||
/* [out] */ IDiaEnumSymbols **ppenum) override { return ENotImpl(); }
|
||||
#pragma endregion
|
||||
|
||||
private:
|
||||
DXC_MICROCOM_TM_REF_FIELDS()
|
||||
std::vector<CComPtr<Symbol>> m_symbols;
|
||||
std::vector<CComPtr<Symbol>>::iterator m_pos;
|
||||
};
|
||||
|
||||
class SymbolsTable : public impl::TableBase<IDiaEnumSymbols, IDiaSymbol> {
|
||||
|
|
|
@ -13,4 +13,4 @@
|
|||
type = Library
|
||||
name = DxilDia
|
||||
parent = Libraries
|
||||
required_libraries = Core DxcSupport Support
|
||||
required_libraries = Core DxilPIXPasses DxcSupport Support
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "dxc/DxilPIXPasses/DxilPIXPasses.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "dxc/DXIL/DxilModule.h"
|
||||
#include "dxc/DxilPIXPasses/DxilPIXPasses.h"
|
||||
#include "dxc/DxilPIXPasses/DxilPIXVirtualRegisters.h"
|
||||
#include "dxc/Support/Global.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
@ -30,8 +30,6 @@
|
|||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include "DxilPIXVirtualRegisters.h"
|
||||
|
||||
#define DEBUG_TYPE "dxil-annotate-with-virtual-regs"
|
||||
|
||||
namespace {
|
||||
|
@ -70,12 +68,26 @@ bool DxilAnnotateWithVirtualRegister::runOnModule(llvm::Module &M) {
|
|||
}
|
||||
|
||||
if (OSOverride != nullptr) {
|
||||
*OSOverride << "\nBegin - dxil values to virtual register mapping\n";
|
||||
*OSOverride << "\nBegin - instruction ID to line\n";
|
||||
}
|
||||
|
||||
std::uint32_t InstNum = 0;
|
||||
for (llvm::Instruction &I : llvm::inst_range(m_DM->GetEntryFunction())) {
|
||||
pix_dxil::PixDxilInstNum::AddMD(M.getContext(), &I, ++InstNum);
|
||||
if (OSOverride != nullptr) {
|
||||
*OSOverride << InstNum << ' ';
|
||||
I.print(*OSOverride);
|
||||
*OSOverride << "\n";
|
||||
}
|
||||
pix_dxil::PixDxilInstNum::AddMD(M.getContext(), &I, InstNum++);
|
||||
}
|
||||
|
||||
if (OSOverride != nullptr) {
|
||||
*OSOverride << "\nEnd - instruction ID to line\n";
|
||||
}
|
||||
|
||||
|
||||
if (OSOverride != nullptr) {
|
||||
*OSOverride << "\nBegin - dxil values to virtual register mapping\n";
|
||||
}
|
||||
|
||||
for (llvm::Instruction &I : llvm::inst_range(m_DM->GetEntryFunction())) {
|
||||
|
@ -165,7 +177,10 @@ bool DxilAnnotateWithVirtualRegister::IsAllocaRegisterWrite(llvm::Value *V, llvm
|
|||
|
||||
void DxilAnnotateWithVirtualRegister::AnnotateAlloca(llvm::AllocaInst *pAlloca) {
|
||||
llvm::Type *pAllocaTy = pAlloca->getType()->getElementType();
|
||||
if (pAllocaTy->isFloatTy() || pAllocaTy->isIntegerTy()) {
|
||||
if (pAllocaTy->isFloatTy() ||
|
||||
pAllocaTy->isIntegerTy() ||
|
||||
pAllocaTy->isHalfTy() ||
|
||||
pAllocaTy->isIntegerTy(16)) {
|
||||
AssignNewAllocaRegister(pAlloca, 1);
|
||||
} else if (auto *AT = llvm::dyn_cast<llvm::ArrayType>(pAllocaTy)) {
|
||||
AssignNewAllocaRegister(pAlloca, AT->getNumElements());
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "dxc/DXIL/DxilModule.h"
|
||||
#include "dxc/DXIL/DxilOperations.h"
|
||||
#include "dxc/DxilPIXPasses/DxilPIXPasses.h"
|
||||
#include "dxc/DxilPIXPasses/DxilPIXVirtualRegisters.h"
|
||||
#include "dxc/DXIL/DxilUtil.h"
|
||||
|
||||
#include "llvm/IR/Module.h"
|
||||
|
@ -21,8 +22,6 @@
|
|||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
|
||||
#include "DxilPIXVirtualRegisters.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace hlsl;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "DxilPIXVirtualRegisters.h"
|
||||
#include "dxc/DxilPIXPasses/DxilPIXVirtualRegisters.h"
|
||||
|
||||
#include "dxc/Support/Global.h"
|
||||
#include "llvm/IR/Constant.h"
|
||||
|
@ -123,6 +123,18 @@ void pix_dxil::PixAllocaReg::AddMD(llvm::LLVMContext &Ctx, llvm::AllocaInst *pAl
|
|||
llvm::ConstantAsMetadata::get(B.getInt32(Count)) }));
|
||||
}
|
||||
|
||||
bool pix_dxil::PixAllocaReg::FromInst(llvm::AllocaInst *pAlloca, std::uint32_t *pRegBase, std::uint32_t *pRegSize) {
|
||||
*pRegBase = 0;
|
||||
*pRegSize = 0;
|
||||
|
||||
auto *mdNodes = pAlloca->getMetadata(MDName);
|
||||
if (mdNodes == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ParsePixAllocaReg(mdNodes, pRegBase, pRegSize);
|
||||
}
|
||||
|
||||
namespace pix_dxil {
|
||||
namespace PixAllocaRegWrite {
|
||||
static constexpr uint32_t IndexIsConst = 1;
|
||||
|
|
|
@ -981,7 +981,7 @@ TEST_F(CompilerTest, CompileWhenDebugThenDIPresent) {
|
|||
//WEX::Logging::Log::Comment(GetDebugInfoAsText(pDiaSource).c_str());
|
||||
|
||||
// Very basic tests - we have basic symbols, line numbers, and files with sources.
|
||||
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, lexicalParent: id=2, value: ps_6_0"));
|
||||
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"));
|
||||
std::wstring diaFileContent = GetDebugFileContent(pDiaSource).c_str();
|
||||
|
@ -1013,28 +1013,40 @@ TEST_F(CompilerTest, CompileDebugLines) {
|
|||
" return z;\r\n"
|
||||
"}", &pDiaSource));
|
||||
|
||||
const int numExpectedRVAs = 6;
|
||||
static constexpr uint32_t numExpectedRVAs = 10;
|
||||
|
||||
auto verifyLines = [=](const std::vector<LineNumber> lines) {
|
||||
VERIFY_ARE_EQUAL(lines.size(), numExpectedRVAs);
|
||||
// 0: loadInput
|
||||
VERIFY_ARE_EQUAL(lines[0].rva, 0);
|
||||
VERIFY_ARE_EQUAL(lines[0].line, 1);
|
||||
// 1: abs
|
||||
// 1: dbg.value
|
||||
VERIFY_ARE_EQUAL(lines[1].rva, 1);
|
||||
VERIFY_ARE_EQUAL(lines[1].line, 2);
|
||||
// 2: sin
|
||||
VERIFY_ARE_EQUAL(lines[1].line, 1);
|
||||
// 2: abs
|
||||
VERIFY_ARE_EQUAL(lines[2].rva, 2);
|
||||
VERIFY_ARE_EQUAL(lines[2].line, 3);
|
||||
// 3: add
|
||||
VERIFY_ARE_EQUAL(lines[2].line, 2);
|
||||
// 3: dbg.value
|
||||
VERIFY_ARE_EQUAL(lines[3].rva, 3);
|
||||
VERIFY_ARE_EQUAL(lines[3].line, 4);
|
||||
// 4: storeOutput
|
||||
VERIFY_ARE_EQUAL(lines[3].line, 2);
|
||||
// 4: sin
|
||||
VERIFY_ARE_EQUAL(lines[4].rva, 4);
|
||||
VERIFY_ARE_EQUAL(lines[4].line, 5);
|
||||
// 5: ret
|
||||
VERIFY_ARE_EQUAL(lines[4].line, 3);
|
||||
// 5: dbg.value
|
||||
VERIFY_ARE_EQUAL(lines[5].rva, 5);
|
||||
VERIFY_ARE_EQUAL(lines[5].line, 5);
|
||||
VERIFY_ARE_EQUAL(lines[5].line, 3);
|
||||
// 6: fadd
|
||||
VERIFY_ARE_EQUAL(lines[6].rva, 6);
|
||||
VERIFY_ARE_EQUAL(lines[6].line, 4);
|
||||
// 7: dbg.value
|
||||
VERIFY_ARE_EQUAL(lines[7].rva, 7);
|
||||
VERIFY_ARE_EQUAL(lines[7].line, 4);
|
||||
// 8: storeOutput
|
||||
VERIFY_ARE_EQUAL(lines[8].rva, 8);
|
||||
VERIFY_ARE_EQUAL(lines[8].line, 5);
|
||||
// 9: ret
|
||||
VERIFY_ARE_EQUAL(lines[9].rva, 9);
|
||||
VERIFY_ARE_EQUAL(lines[9].line, 5);
|
||||
};
|
||||
|
||||
CComPtr<IDiaSession> pSession;
|
||||
|
|
Загрузка…
Ссылка в новой задаче