blob: deb5dc3dad124a1dc081edbaae70d622f7203f51 [file] [edit]
///////////////////////////////////////////////////////////////////////////////
// //
// DxilDiaTable.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 "dia2.h"
#include "dxc/Support/Global.h"
#include "dxc/Support/microcom.h"
#include "DxilDia.h"
namespace dxil_dia {
class Session;
namespace Table {
enum class Kind {
Symbols,
SourceFiles,
LineNumbers,
Sections,
SegmentMap,
InjectedSource,
FrameData,
InputAssemblyFile
};
static constexpr Kind FirstKind = Kind::Symbols;
static constexpr Kind LastKind = Kind::InputAssemblyFile;
HRESULT Create(
/* [in] */ Session *pSession,
/* [in] */ Kind kind,
/* [out] */ IDiaTable **ppTable);
} // namespace Table
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",
L"SourceFiles",
L"LineNumbers",
L"Sections",
L"SegmentMap",
L"InjectedSource",
L"FrameData",
L"InputAssemblyFiles"
};
DXC_MICROCOM_TM_REF_FIELDS()
CComPtr<Session> m_pSession;
unsigned m_next;
unsigned m_count;
Table::Kind m_kind;
public:
DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL()
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) {
return DoBasicQueryInterface<IDiaTable, T, IEnumUnknown>(this, iid, ppvObject);
}
TableBase(IMalloc *pMalloc, Session *pSession, Table::Kind kind) {
m_pMalloc = pMalloc;
m_pSession = pSession;
m_kind = kind;
m_next = 0;
m_count = 0;
}
// IEnumUnknown implementation.
STDMETHODIMP Next(
_In_ ULONG celt,
_Out_writes_to_(celt, *pceltFetched) IUnknown **rgelt,
_Out_opt_ ULONG *pceltFetched) override {
DxcThreadMalloc TM(m_pMalloc);
ULONG fetched = 0;
while (fetched < celt && m_next < m_count) {
HRESULT hr = Item(m_next, &rgelt[fetched]);
if (FAILED(hr)) {
return hr; // TODO: this leaks prior tables.
}
++m_next, ++fetched;
}
if (pceltFetched != nullptr)
*pceltFetched = fetched;
return (fetched == celt) ? S_OK : S_FALSE;
}
STDMETHODIMP Skip(ULONG celt) override {
if (celt + m_next <= m_count) {
m_next += celt;
return S_OK;
}
return S_FALSE;
}
STDMETHODIMP Reset(void) override {
m_next = 0;
return S_OK;
}
STDMETHODIMP Clone(IEnumUnknown **ppenum) override {
return ENotImpl();
}
// IDiaTable implementation.
STDMETHODIMP get__NewEnum(IUnknown **pRetVal) override {
return ENotImpl();
}
STDMETHODIMP get_name(BSTR *pRetVal) override {
*pRetVal = SysAllocString(TableNames[(unsigned)m_kind]);
return (*pRetVal) ? S_OK : E_OUTOFMEMORY;
}
STDMETHODIMP get_Count(_Out_ LONG *pRetVal) override {
*pRetVal = m_count;
return S_OK;
}
STDMETHODIMP Item(DWORD index, _COM_Outptr_ IUnknown **table) override {
if (index >= m_count)
return E_INVALIDARG;
return GetItem(index, (TItem **)table);
}
// T implementation (partial).
STDMETHODIMP Clone(_COM_Outptr_ T **ppenum) override {
*ppenum = nullptr;
return ENotImpl();
}
STDMETHODIMP Next(
/* [in] */ ULONG celt,
/* [out] */ TItem **rgelt,
/* [out] */ ULONG *pceltFetched) override {
DxcThreadMalloc TM(m_pMalloc);
ULONG fetched = 0;
while (fetched < celt && m_next < m_count) {
HRESULT hr = GetItem(m_next, &rgelt[fetched]);
if (FAILED(hr)) {
return hr; // TODO: this leaks prior items.
}
++m_next, ++fetched;
}
if (pceltFetched != nullptr)
*pceltFetched = fetched;
return (fetched == celt) ? S_OK : S_FALSE;
}
STDMETHODIMP Item(
/* [in] */ DWORD index,
/* [retval][out] */ TItem **ppItem) override {
DxcThreadMalloc TM(m_pMalloc);
if (index >= m_count)
return E_INVALIDARG;
return GetItem(index, ppItem);
}
virtual HRESULT GetItem(DWORD index, TItem **ppItem) = 0;
};
} // namespace impl
} // namespace dxil_dia