[linux-port] Use cross-platform dynamic lib load (#1380)

LLVM includes a DynamicLibrary class that works on multiple platforms
Rather than ifdefing between dlopen for non-Windows and LoadLibraryW
on Windows, using this class allows us to abstract platform differences
while using the same code.

Changed DxilLibInitialize to attempt to initialize dxil.dll so the
smart mutex inside the dynamic library object uses the same IMalloc
as the other ManagedStatic objects so they can all be freed in order.
This commit is contained in:
Greg Roth 2018-06-26 15:33:14 -06:00 коммит произвёл Lei Zhang
Родитель 4aa0ac6c50
Коммит 3670c1372d
3 изменённых файлов: 32 добавлений и 21 удалений

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

@ -13,27 +13,27 @@
#define __DXCAPI_USE_H__
#include "dxc/dxcapi.h"
#include "llvm/Support/DynamicLibrary.h"
namespace dxc {
// Helper class to dynamically load the dxcompiler or a compatible libraries.
class DxcDllSupport {
protected:
HMODULE m_dll;
using DynamicLibrary = llvm::sys::DynamicLibrary;
DynamicLibrary m_dll;
DxcCreateInstanceProc m_createFn;
DxcCreateInstance2Proc m_createFn2;
HRESULT InitializeInternal(LPCWSTR dllName, LPCSTR fnName) {
if (m_dll != nullptr) return S_OK;
m_dll = LoadLibraryW(dllName);
if (m_dll == nullptr) return HRESULT_FROM_WIN32(GetLastError());
m_createFn = (DxcCreateInstanceProc)GetProcAddress(m_dll, fnName);
if (m_dll.isValid()) return S_OK;
m_dll = DynamicLibrary::getPermanentLibrary(CW2A(dllName));
if (!m_dll.isValid()) return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
m_createFn = (DxcCreateInstanceProc)m_dll.getAddressOfSymbol(fnName);
if (m_createFn == nullptr) {
HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
FreeLibrary(m_dll);
m_dll = nullptr;
m_dll = DynamicLibrary();
return hr;
}
@ -45,18 +45,18 @@ protected:
memcpy(fnName2, fnName, s);
fnName2[s] = '2';
fnName2[s + 1] = '\0';
m_createFn2 = (DxcCreateInstance2Proc)GetProcAddress(m_dll, fnName2);
m_createFn2 = (DxcCreateInstance2Proc)m_dll.getAddressOfSymbol(fnName2);
}
return S_OK;
}
public:
DxcDllSupport() : m_dll(nullptr), m_createFn(nullptr), m_createFn2(nullptr) {
DxcDllSupport() : m_dll(), m_createFn(nullptr), m_createFn2(nullptr) {
}
DxcDllSupport(DxcDllSupport&& other) {
m_dll = other.m_dll; other.m_dll = nullptr;
m_dll = other.m_dll; other.m_dll = DynamicLibrary();
m_createFn = other.m_createFn; other.m_createFn = nullptr;
m_createFn2 = other.m_createFn2; other.m_createFn2 = nullptr;
}
@ -66,7 +66,13 @@ public:
}
HRESULT Initialize() {
#ifdef _WIN32
return InitializeInternal(L"dxcompiler.dll", "DxcCreateInstance");
#elif __APPLE__
return InitializeInternal(L"libdxcompiler.dylib", "DxcCreateInstance");
#else
return InitializeInternal(L"libdxcompiler.so", "DxcCreateInstance");
#endif
}
HRESULT InitializeForDll(_In_z_ const wchar_t* dll, _In_z_ const char* entryPoint) {
@ -80,7 +86,7 @@ public:
HRESULT CreateInstance(REFCLSID clsid, REFIID riid, _Outptr_ IUnknown **pResult) {
if (pResult == nullptr) return E_POINTER;
if (m_dll == nullptr) return E_FAIL;
if (!m_dll.isValid()) return E_FAIL;
HRESULT hr = m_createFn(clsid, riid, (LPVOID*)pResult);
return hr;
}
@ -92,7 +98,7 @@ public:
HRESULT CreateInstance2(IMalloc *pMalloc, REFCLSID clsid, REFIID riid, _Outptr_ IUnknown **pResult) {
if (pResult == nullptr) return E_POINTER;
if (m_dll == nullptr) return E_FAIL;
if (!m_dll.isValid()) return E_FAIL;
if (m_createFn2 == nullptr) return E_FAIL;
HRESULT hr = m_createFn2(pMalloc, clsid, riid, (LPVOID*)pResult);
return hr;
@ -103,21 +109,20 @@ public:
}
bool IsEnabled() const {
return m_dll != nullptr;
return m_dll.isValid();
}
void Cleanup() {
if (m_dll != nullptr) {
if (m_dll.isValid()) {
m_createFn = nullptr;
m_createFn2 = nullptr;
FreeLibrary(m_dll);
m_dll = nullptr;
m_dll = DynamicLibrary();
}
}
HMODULE Detach() {
HMODULE module = m_dll;
m_dll = nullptr;
DynamicLibrary Detach() {
DynamicLibrary module = m_dll;
m_dll = DynamicLibrary();
return module;
}
};

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

@ -28,7 +28,7 @@ if( NOT MSVC )
endif( NOT MSVC )
# HLSL Change - add ignored sources
set(HLSL_IGNORE_SOURCES DynamicLibrary.cpp PluginLoader.cpp)
set(HLSL_IGNORE_SOURCES PluginLoader.cpp)
add_llvm_library(LLVMSupport
APFloat.cpp
@ -52,6 +52,7 @@ add_llvm_library(LLVMSupport
DeltaAlgorithm.cpp
DAGDeltaAlgorithm.cpp
Dwarf.cpp
DynamicLibrary.cpp
ErrorHandling.cpp
FileUtilities.cpp
FileOutputBuffer.cpp

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

@ -25,6 +25,11 @@ static llvm::sys::Mutex *cs = nullptr;
// This function is to prevent multiple attempts to load dxil.dll
HRESULT DxilLibInitialize() {
cs = new llvm::sys::Mutex;
#if LLVM_ON_WIN32
cs->lock();
g_DllLibResult = g_DllSupport.InitializeForDll(L"dxil.dll", "DxcCreateInstance");
cs->unlock();
#endif
return S_OK;
}