Implements DIA Interfaces for HLSL variable-value mapping. (#2050)

This commit is contained in:
John Porto 2019-03-19 11:46:10 -07:00 коммит произвёл GitHub
Родитель 68204b3bfe
Коммит d432a02f77
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
20 изменённых файлов: 2933 добавлений и 217 удалений

Просмотреть файл

@ -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;