diff --git a/include/dxc/Support/DxcLangExtensionsHelper.h b/include/dxc/Support/DxcLangExtensionsHelper.h index 4ca1c3689c..5e72487a2c 100644 --- a/include/dxc/Support/DxcLangExtensionsHelper.h +++ b/include/dxc/Support/DxcLangExtensionsHelper.h @@ -221,21 +221,27 @@ class DxcLangExtensionsHelper : public DxcLangExtensionsHelperApply { // Note that QueryInterface still needs to return the vtable. #define DXC_LANGEXTENSIONS_HELPER_IMPL(_helper_field_) \ __override HRESULT STDMETHODCALLTYPE RegisterIntrinsicTable(_In_ IDxcIntrinsicTable *pTable) { \ + DxcThreadMalloc TM(m_pMalloc); \ return (_helper_field_).RegisterIntrinsicTable(pTable); \ } \ __override HRESULT STDMETHODCALLTYPE RegisterSemanticDefine(LPCWSTR name) { \ + DxcThreadMalloc TM(m_pMalloc); \ return (_helper_field_).RegisterSemanticDefine(name); \ } \ __override HRESULT STDMETHODCALLTYPE RegisterSemanticDefineExclusion(LPCWSTR name) { \ + DxcThreadMalloc TM(m_pMalloc); \ return (_helper_field_).RegisterSemanticDefineExclusion(name); \ } \ __override HRESULT STDMETHODCALLTYPE RegisterDefine(LPCWSTR name) { \ + DxcThreadMalloc TM(m_pMalloc); \ return (_helper_field_).RegisterDefine(name); \ } \ __override HRESULT STDMETHODCALLTYPE SetSemanticDefineValidator(_In_ IDxcSemanticDefineValidator* pValidator) { \ + DxcThreadMalloc TM(m_pMalloc); \ return (_helper_field_).SetSemanticDefineValidator(pValidator); \ } \ __override HRESULT STDMETHODCALLTYPE SetSemanticDefineMetaDataName(LPCSTR name) { \ + DxcThreadMalloc TM(m_pMalloc); \ return (_helper_field_).SetSemanticDefineMetaDataName(name); \ } \ diff --git a/include/dxc/Support/FileIOHelper.h b/include/dxc/Support/FileIOHelper.h index 7f37bad5db..3620a1c735 100644 --- a/include/dxc/Support/FileIOHelper.h +++ b/include/dxc/Support/FileIOHelper.h @@ -17,6 +17,99 @@ struct IDxcBlobEncoding; namespace hlsl { +IMalloc *GetGlobalHeapMalloc() throw(); + +class CDxcThreadMallocAllocator { +public: + _Ret_maybenull_ _Post_writable_byte_size_(nBytes) _ATL_DECLSPEC_ALLOCATOR + static void *Reallocate(_In_ void *p, _In_ size_t nBytes) throw() { + return DxcGetThreadMallocNoRef()->Realloc(p, nBytes); + } + + _Ret_maybenull_ _Post_writable_byte_size_(nBytes) _ATL_DECLSPEC_ALLOCATOR + static void *Allocate(_In_ size_t nBytes) throw() { + return DxcGetThreadMallocNoRef()->Alloc(nBytes); + } + + static void Free(_In_ void *p) throw() { + return DxcGetThreadMallocNoRef()->Free(p); + } +}; + +// Like CComHeapPtr, but with CDxcThreadMallocAllocator. +template +class CDxcTMHeapPtr : + public CHeapPtr +{ +public: + CDxcTMHeapPtr() throw() + { + } + + explicit CDxcTMHeapPtr(_In_ T* pData) throw() : + CDxcTMHeapPtr(pData) + { + } +}; + +// Like CComHeapPtr, but with a stateful allocator. +template +class CDxcMallocHeapPtr +{ +private: + CComPtr m_pMalloc; +public: + T *m_pData; + + CDxcMallocHeapPtr(IMalloc *pMalloc) throw() + : m_pMalloc(pMalloc), m_pData(nullptr) {} + + ~CDxcMallocHeapPtr() { + if (m_pData) + m_pMalloc->Free(m_pData); + } + + operator T *() const throw() { return m_pData; } + + bool Allocate(_In_ SIZE_T ElementCount) throw() { + ATLASSERT(m_pData == NULL); + SIZE_T nBytes = ElementCount * sizeof(T); + m_pData = static_cast(m_pMalloc->Alloc(nBytes)); + if (m_pData == NULL) + return false; + return true; + } + + void AllocateBytes(_In_ SIZE_T ByteCount) throw() { + if (m_pData) + m_pMalloc->Free(m_pData); + m_pData = static_cast(m_pMalloc->Alloc(ByteCount)); + } + + // Attach to an existing pointer (takes ownership) + void Attach(_In_ T *pData) throw() { + m_pMalloc->Free(m_pData); + m_pData = pData; + } + + // Detach the pointer (releases ownership) + T *Detach() throw() { + T *pTemp = m_pData; + m_pData = NULL; + return pTemp; + } + + // Free the memory pointed to, and set the pointer to NULL + void Free() throw() { + m_pMalloc->Free(m_pData); + m_pData = NULL; + } +}; + +void ReadBinaryFile(_In_opt_ IMalloc *pMalloc, + _In_z_ LPCWSTR pFileName, + _Outptr_result_bytebuffer_(*pDataSize) void **ppData, + _Out_ DWORD *pDataSize); void ReadBinaryFile(_In_z_ LPCWSTR pFileName, _Outptr_result_bytebuffer_(*pDataSize) void **ppData, _Out_ DWORD *pDataSize); @@ -30,8 +123,13 @@ void WriteBinaryFile(_In_z_ LPCWSTR pFileName, UINT32 DxcCodePageFromBytes(_In_count_(byteLen) const char *bytes, size_t byteLen) throw(); +HRESULT +DxcCreateBlobFromFile(_In_opt_ IMalloc *pMalloc, LPCWSTR pFileName, + _In_opt_ UINT32 *pCodePage, + _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) throw(); + HRESULT DxcCreateBlobFromFile(LPCWSTR pFileName, _In_opt_ UINT32 *pCodePage, - _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) throw(); + _COM_Outptr_ IDxcBlobEncoding **ppBlobEncoding) throw(); // Given a blob, creates a subrange view. HRESULT DxcCreateBlobFromBlob(_In_ IDxcBlob *pBlob, UINT32 offset, @@ -49,7 +147,11 @@ DxcCreateBlobOnHeapCopy(_In_bytecount_(size) LPCVOID pData, UINT32 size, // Given a blob, creates a new instance with a specific code page set. HRESULT DxcCreateBlobWithEncodingSet(_In_ IDxcBlob *pBlob, UINT32 codePage, - _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) throw(); + _COM_Outptr_ IDxcBlobEncoding **ppBlobEncoding) throw(); +HRESULT +DxcCreateBlobWithEncodingSet( + _In_ IMalloc *pMalloc, _In_ IDxcBlob *pBlob, UINT32 codePage, + _COM_Outptr_ IDxcBlobEncoding **ppBlobEncoding) throw(); HRESULT DxcCreateBlobWithEncodingFromPinned( _In_bytecount_(size) LPCVOID pText, UINT32 size, UINT32 codePage, @@ -65,6 +167,7 @@ DxcCreateBlobWithEncodingOnHeap(_In_bytecount_(size) LPCVOID pText, UINT32 size, UINT32 codePage, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) throw(); +// Should rename this 'OnHeap' to be 'OnMalloc', change callers to pass arg. Using TLS. HRESULT DxcCreateBlobWithEncodingOnHeapCopy( _In_bytecount_(size) LPCVOID pText, UINT32 size, UINT32 codePage, @@ -75,6 +178,11 @@ DxcCreateBlobWithEncodingOnMalloc( _In_bytecount_(size) LPCVOID pText, IMalloc *pIMalloc, UINT32 size, UINT32 codePage, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) throw(); +HRESULT +DxcCreateBlobWithEncodingOnMallocCopy( + _In_ IMalloc *pIMalloc, _In_bytecount_(size) LPCVOID pText, UINT32 size, UINT32 codePage, + _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) throw(); + HRESULT DxcGetBlobAsUtf8(_In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) throw(); HRESULT @@ -82,8 +190,9 @@ DxcGetBlobAsUtf8NullTerm( _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobEncoding **ppBlobEncoding) throw(); -HRESULT DxcGetBlobAsUtf16(_In_ IDxcBlob *pBlob, - _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) throw(); +HRESULT +DxcGetBlobAsUtf16(_In_ IDxcBlob *pBlob, _In_ IMalloc *pMalloc, + _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) throw(); bool IsBlobNullOrEmpty(_In_opt_ IDxcBlob *pBlob) throw(); diff --git a/include/dxc/Support/Global.h b/include/dxc/Support/Global.h index a29d64ca07..e4a76b0077 100644 --- a/include/dxc/Support/Global.h +++ b/include/dxc/Support/Global.h @@ -5,7 +5,7 @@ // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // -// Provides important declarations global to all DX Compiler code. // +// Provides important declarations global to all DX Compiler code. // // // /////////////////////////////////////////////////////////////////////////////// @@ -25,6 +25,53 @@ typedef _Return_type_success_(return >= 0) long HRESULT; #include #include "dxc/Support/exception.h" +/////////////////////////////////////////////////////////////////////////////// +// Memory allocation support. +// +// This mechanism ties into the C++ new and delete operators. +// +// Other allocators may be used in specific situations, eg sub-allocators or +// the COM allocator for interop. This is the preferred allocator in general, +// however, as it eventually allows the library user to specify their own. +// + +struct IMalloc; + +// Used by DllMain to set up and tear down per-thread tracking. +HRESULT DxcInitThreadMalloc() throw(); +void DxcCleanupThreadMalloc() throw(); + +// Used by APIs entry points to set up per-thread/invocation allocator. +// Setting the IMalloc on the thread increases the reference count, +// clearing it decreases it. +void DxcClearThreadMalloc() throw(); +void DxcSetThreadMalloc(IMalloc *pMalloc) throw(); +void DxcSetThreadMallocOrDefault(IMalloc *pMalloc) throw(); + +// Swapping does not AddRef or Release new or prior. The pattern is to keep both alive, +// either in TLS, or on the stack to restore later. The returned value is the effective +// IMalloc also available in TLS. +IMalloc *DxcSwapThreadMalloc(IMalloc *pMalloc, IMalloc **ppPrior) throw(); +IMalloc *DxcSwapThreadMallocOrDefault(IMalloc *pMalloc, IMalloc **ppPrior) throw(); + +// Used to retrieve the current invocation's allocator or perform an alloc/free/realloc. +IMalloc *DxcGetThreadMallocNoRef() throw(); +_Ret_maybenull_ _Post_writable_byte_size_(nBytes) void *DxcThreadAlloc(size_t nBytes) throw(); +void DxcThreadFree(void *) throw(); + +struct DxcThreadMalloc { + DxcThreadMalloc(IMalloc *pMallocOrNull) throw() { + p = DxcSwapThreadMallocOrDefault(pMallocOrNull, &pPrior); + } + ~DxcThreadMalloc() { + DxcSwapThreadMalloc(pPrior, nullptr); + } + IMalloc *p; + IMalloc *pPrior; +}; + +/////////////////////////////////////////////////////////////////////////////// +// Error handling support. namespace std { class error_code; } void CheckLLVMErrorCode(const std::error_code &ec); diff --git a/include/dxc/Support/HLSLOptions.h b/include/dxc/Support/HLSLOptions.h index 416f4a27a4..7aaf31420f 100644 --- a/include/dxc/Support/HLSLOptions.h +++ b/include/dxc/Support/HLSLOptions.h @@ -52,6 +52,8 @@ enum ID { }; const llvm::opt::OptTable *getHlslOptTable(); +std::error_code initHlslOptTable(); +void cleanupHlslOptTable(); /////////////////////////////////////////////////////////////////////////////// // Helper classes to deal with options. diff --git a/include/dxc/Support/WinIncludes.h b/include/dxc/Support/WinIncludes.h index 59bb0c7bc6..91edbc7247 100644 --- a/include/dxc/Support/WinIncludes.h +++ b/include/dxc/Support/WinIncludes.h @@ -32,6 +32,7 @@ #include // atlbase.h needs to come before strsafe.h #include #include +#include /// Swap two ComPtr classes. template void swap(CComHeapPtr &a, CComHeapPtr &b) { diff --git a/include/dxc/Support/dxcapi.impl.h b/include/dxc/Support/dxcapi.impl.h index 8309388b89..6d3c4398e3 100644 --- a/include/dxc/Support/dxcapi.impl.h +++ b/include/dxc/Support/dxcapi.impl.h @@ -34,15 +34,18 @@ class raw_stream_ostream : public llvm::raw_ostream { class DxcOperationResult : public IDxcOperationResult { private: - DXC_MICROCOM_REF_FIELD(m_dwRef) + DXC_MICROCOM_TM_REF_FIELDS() - DxcOperationResult(_In_opt_ IDxcBlob *pResultBlob, - _In_opt_ IDxcBlobEncoding *pErrorBlob, HRESULT status) - : m_dwRef(0), m_status(status), m_result(pResultBlob), - m_errors(pErrorBlob) {} + void Init(_In_opt_ IDxcBlob *pResultBlob, + _In_opt_ IDxcBlobEncoding *pErrorBlob, HRESULT status) { + m_status = status; + m_result = pResultBlob; + m_errors = pErrorBlob; + } public: - DXC_MICROCOM_ADDREF_RELEASE_IMPL(m_dwRef) + DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL() + DXC_MICROCOM_TM_CTOR(DxcOperationResult) HRESULT m_status; CComPtr m_result; @@ -57,8 +60,9 @@ class DxcOperationResult : public IDxcOperationResult { HRESULT status, _COM_Outptr_ IDxcOperationResult **ppResult) { *ppResult = nullptr; - CComPtr result = new (std::nothrow) DxcOperationResult(pResultBlob, pErrorBlob, status); - if (result.p == nullptr) return E_OUTOFMEMORY; + CComPtr result = DxcOperationResult::Alloc(DxcGetThreadMallocNoRef()); + IFROOM(result.p); + result->Init(pResultBlob, pErrorBlob, status); *ppResult = result.Detach(); return S_OK; } diff --git a/include/dxc/Support/dxcapi.use.h b/include/dxc/Support/dxcapi.use.h index 1ce47cf287..43d225ccd4 100644 --- a/include/dxc/Support/dxcapi.use.h +++ b/include/dxc/Support/dxcapi.use.h @@ -21,6 +21,7 @@ class DxcDllSupport { protected: HMODULE m_dll; DxcCreateInstanceProc m_createFn; + DxcCreateInstance2Proc m_createFn2; HRESULT InitializeInternal(LPCWSTR dllName, LPCSTR fnName) { if (m_dll != nullptr) return S_OK; @@ -36,16 +37,28 @@ class DxcDllSupport { return hr; } + // Only basic functions used to avoid requiring additional headers. + m_createFn2 = nullptr; + char fnName2[128]; + size_t s = strlen(fnName); + if (s < sizeof(fnName2) - 2) { + memcpy(fnName2, fnName, s); + fnName2[s] = '2'; + fnName2[s + 1] = '\0'; + m_createFn2 = (DxcCreateInstance2Proc)GetProcAddress(m_dll, fnName2); + } + return S_OK; } public: - DxcDllSupport() : m_dll(nullptr), m_createFn(nullptr) { + DxcDllSupport() : m_dll(nullptr), m_createFn(nullptr), m_createFn2(nullptr) { } DxcDllSupport(DxcDllSupport&& other) { m_dll = other.m_dll; other.m_dll = nullptr; - m_createFn = other.m_createFn; other.m_dll = nullptr; + m_createFn = other.m_createFn; other.m_createFn = nullptr; + m_createFn2 = other.m_createFn2; other.m_createFn2 = nullptr; } ~DxcDllSupport() { @@ -72,6 +85,23 @@ class DxcDllSupport { return hr; } + template + HRESULT CreateInstance2(IMalloc *pMalloc, REFCLSID clsid, _Outptr_ TInterface** pResult) { + return CreateInstance2(pMalloc, clsid, __uuidof(TInterface), (IUnknown**)pResult); + } + + 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_createFn2 == nullptr) return E_FAIL; + HRESULT hr = m_createFn2(pMalloc, clsid, riid, (LPVOID*)pResult); + return hr; + } + + bool HasCreateWithMalloc() const { + return m_createFn2 != nullptr; + } + bool IsEnabled() const { return m_dll != nullptr; } @@ -79,6 +109,7 @@ class DxcDllSupport { void Cleanup() { if (m_dll != nullptr) { m_createFn = nullptr; + m_createFn2 = nullptr; FreeLibrary(m_dll); m_dll = nullptr; } diff --git a/include/dxc/Support/dxcfilesystem.h b/include/dxc/Support/dxcfilesystem.h index ccc5ba0c9b..137b6720ed 100644 --- a/include/dxc/Support/dxcfilesystem.h +++ b/include/dxc/Support/dxcfilesystem.h @@ -42,9 +42,8 @@ class DxcArgsFileSystem : public ::llvm::sys::fs::MSFileSystem { virtual HRESULT RegisterOutputStream(LPCWSTR pName, IStream *pStream) = 0; }; -HRESULT +DxcArgsFileSystem * CreateDxcArgsFileSystem(_In_ IDxcBlob *pSource, _In_ LPCWSTR pSourceName, - _In_opt_ IDxcIncludeHandler *pIncludeHandler, - _Outptr_ DxcArgsFileSystem **ppResult) throw(); + _In_opt_ IDxcIncludeHandler *pIncludeHandler); } // namespace dxcutil \ No newline at end of file diff --git a/include/dxc/Support/microcom.h b/include/dxc/Support/microcom.h index 22c22098b5..606aa56788 100644 --- a/include/dxc/Support/microcom.h +++ b/include/dxc/Support/microcom.h @@ -73,19 +73,49 @@ class CComInterfaceArray { } }; -#define DXC_MICROCOM_REF_FIELD(m_dwRef) volatile ULONG m_dwRef; - -#define DXC_MICROCOM_ADDREF_RELEASE_IMPL(m_dwRef) \ - bool HasSingleRef() { return 1 == m_dwRef; } \ - ULONG STDMETHODCALLTYPE AddRef() {\ +#define DXC_MICROCOM_REF_FIELD(m_dwRef) volatile ULONG m_dwRef = 0; +#define DXC_MICROCOM_ADDREF_IMPL(m_dwRef) \ + ULONG STDMETHODCALLTYPE AddRef() {\ return InterlockedIncrement(&m_dwRef); \ - } \ + } +#define DXC_MICROCOM_ADDREF_RELEASE_IMPL(m_dwRef) \ + DXC_MICROCOM_ADDREF_IMPL(m_dwRef) \ ULONG STDMETHODCALLTYPE Release() { \ ULONG result = InterlockedDecrement(&m_dwRef); \ if (result == 0) delete this; \ return result; \ } +template +inline T *CreateOnMalloc(IMalloc * pMalloc, Args&&... args) { + void *P = pMalloc->Alloc(sizeof(T)); \ + if (P) new (P)T(pMalloc, std::forward(args)...); \ + return (T *)P; \ +} + +// The "TM" version keep an IMalloc field that, if not null, indicate +// ownership of 'this' and of any allocations used during release. +#define DXC_MICROCOM_TM_REF_FIELDS() \ + volatile ULONG m_dwRef = 0;\ + CComPtr m_pMalloc; +#define DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL() \ + DXC_MICROCOM_ADDREF_IMPL(m_dwRef) \ + ULONG STDMETHODCALLTYPE Release() { \ + ULONG result = InterlockedDecrement(&m_dwRef); \ + if (result == 0) { \ + CComPtr pTmp(m_pMalloc); \ + DxcThreadMalloc M(pTmp); delete this; \ + } \ + return result; \ + } +#define DXC_MICROCOM_TM_CTOR(T) \ + T(IMalloc *pMalloc) : m_dwRef(0), m_pMalloc(pMalloc) { } \ + static T* Alloc(IMalloc *pMalloc) { \ + void *P = pMalloc->Alloc(sizeof(T)); \ + try { if (P) new (P)T(pMalloc); } catch (...) { operator delete(P); throw; } \ + return (T *)P; \ + } + /// /// Provides a QueryInterface implementation for a class that supports /// any number of interfaces in addition to IUnknown. diff --git a/include/dxc/dxcapi.h b/include/dxc/dxcapi.h index e000f0707c..70f93e834f 100644 --- a/include/dxc/dxcapi.h +++ b/include/dxc/dxcapi.h @@ -17,6 +17,7 @@ #define DXC_API_IMPORT __declspec(dllimport) #endif +struct IMalloc; struct IDxcIncludeHandler; /// @@ -42,6 +43,13 @@ typedef HRESULT (__stdcall *DxcCreateInstanceProc)( _Out_ LPVOID* ppv ); +typedef HRESULT(__stdcall *DxcCreateInstance2Proc)( + _In_ IMalloc *pMalloc, + _In_ REFCLSID rclsid, + _In_ REFIID riid, + _Out_ LPVOID* ppv + ); + /// /// Creates a single uninitialized object of the class associated with a specified CLSID. /// @@ -65,6 +73,13 @@ DXC_API_IMPORT HRESULT __stdcall DxcCreateInstance( _Out_ LPVOID* ppv ); +DXC_API_IMPORT HRESULT __stdcall DxcCreateInstance2( + _In_ IMalloc *pMalloc, + _In_ REFCLSID rclsid, + _In_ REFIID riid, + _Out_ LPVOID* ppv +); + // IDxcBlob is an alias of ID3D10Blob and ID3DBlob struct __declspec(uuid("8BA5FB08-5195-40e2-AC58-0D989C3A0102")) diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index 27f73157a2..ea9c4fde16 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -676,13 +676,16 @@ class DenseMap : public DenseMapBase, } bool allocateBuckets(unsigned Num) { - NumBuckets = Num; - if (NumBuckets == 0) { + // HLSL Change Starts - reorder statement to clean up properly on OOM + if (Num == 0) { + NumBuckets = 0; Buckets = nullptr; return false; } - Buckets = static_cast(operator new(sizeof(BucketT) * NumBuckets)); + Buckets = static_cast(operator new(sizeof(BucketT) * Num)); + NumBuckets = Num; + // HLSL Change Ends - reorder statement to clean up properly on OOM return true; } }; @@ -876,8 +879,8 @@ class SmallDenseMap // Now make this map use the large rep, and move all the entries back // into it. - Small = false; - new (getLargeRep()) LargeRep(allocateBuckets(AtLeast)); + new (getLargeRepForTransition()) LargeRep(allocateBuckets(AtLeast)); + Small = false; // HLSL Change - used to be prior to allocation this->moveFromOldBuckets(TmpBegin, TmpEnd); return; } @@ -953,6 +956,16 @@ class SmallDenseMap return const_cast( const_cast(this)->getLargeRep()); } + // HLSL Change Starts - avoid Small check, as we are in the process of transitioning + const LargeRep *getLargeRepForTransition() const { + // Note, same rule about aliasing as with getInlineBuckets. + return reinterpret_cast(storage.buffer); + } + LargeRep *getLargeRepForTransition() { + return const_cast( + const_cast(this)->getLargeRepForTransition()); + } + // HLSL Change Ends const BucketT *getBuckets() const { return Small ? getInlineBuckets() : getLargeRep()->Buckets; diff --git a/include/llvm/ADT/Statistic.h b/include/llvm/ADT/Statistic.h index d98abc375e..82901375be 100644 --- a/include/llvm/ADT/Statistic.h +++ b/include/llvm/ADT/Statistic.h @@ -52,7 +52,7 @@ class Statistic { // Allow use of this class as the value itself. operator unsigned() const { return Value; } -#if !defined(NDEBUG) || defined(LLVM_ENABLE_STATS) +#if (!defined(NDEBUG) || defined(LLVM_ENABLE_STATS)) && 0 // HLSL Change - always disable, shouldn't do process-wide alloc in compile const Statistic &operator=(unsigned Val) { Value = Val; return init(); diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h index 27126af091..c3355fa0ad 100644 --- a/include/llvm/Analysis/CallGraph.h +++ b/include/llvm/Analysis/CallGraph.h @@ -103,6 +103,7 @@ class CallGraph { /// functions that it calls. void addToCallGraph(Function *F); + void reset(); // HLSL Change public: CallGraph(Module &M); ~CallGraph(); diff --git a/include/llvm/Bitcode/BitstreamWriter.h b/include/llvm/Bitcode/BitstreamWriter.h index 9f23023a14..62d2049e7b 100644 --- a/include/llvm/Bitcode/BitstreamWriter.h +++ b/include/llvm/Bitcode/BitstreamWriter.h @@ -92,8 +92,10 @@ class BitstreamWriter { : Out(O), CurBit(0), CurValue(0), CurCodeSize(2) {} ~BitstreamWriter() { +#if 0 // HLSL Change - these are not true when recovering from OOM assert(CurBit == 0 && "Unflushed data remaining"); assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance"); +#endif } /// \brief Retrieve the current position in the stream, in bits. diff --git a/include/llvm/IR/LegacyPassManagers.h b/include/llvm/IR/LegacyPassManagers.h index d99cf22ee0..597b53a15d 100644 --- a/include/llvm/IR/LegacyPassManagers.h +++ b/include/llvm/IR/LegacyPassManagers.h @@ -143,7 +143,7 @@ class PassManagerPrettyStackEntry : public PrettyStackTraceEntry { /// suitable manager. class PMStack { public: - typedef std::vector::const_reverse_iterator iterator; + typedef llvm::SmallVector::const_reverse_iterator iterator; // HLSL Change - SmallVector rather than vector iterator begin() const { return S.rbegin(); } iterator end() const { return S.rend(); } @@ -155,7 +155,7 @@ class PMStack { void dump() const; private: - std::vector S; + llvm::SmallVector S; // HLSL Change - SmallVector rather than vector }; diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index 106c7567d9..552f596e7e 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -755,8 +755,9 @@ class MDNode : public Metadata { void operator delete(void *Mem); /// \brief Required by std, but never called. - void operator delete(void *, unsigned) { - llvm_unreachable("Constructor throws?"); + void operator delete(void *Mem, unsigned) { + //llvm_unreachable("Constructor throws?"); // HLSL Change - why, yes; yes it does (under OOM) + MDNode::operator delete(Mem); } /// \brief Required by std, but never called. @@ -903,7 +904,9 @@ class MDNode : public Metadata { /// \pre \a isTemporary(). void makeDistinct(); +public: // HLSL Change - make deleteAsSubclass accessible void deleteAsSubclass(); +private: MDNode *uniquify(); void eraseFromStore(); diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h index 13964eb06f..9165701033 100644 --- a/include/llvm/IR/User.h +++ b/include/llvm/IR/User.h @@ -77,9 +77,8 @@ class User : public Value { /// \brief Free memory allocated for User and Use objects. void operator delete(void *Usr); /// \brief Placement delete - required by std, but never called. - void operator delete(void*, unsigned) { - llvm_unreachable("Constructor throws?"); - } + void operator delete(void*, unsigned); + // llvm_unreachable("Constructor throws?"); - HLSL Change: it does on OOM /// \brief Placement delete - required by std, but never called. void operator delete(void*, unsigned, bool) { llvm_unreachable("Constructor throws?"); diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index 56cad07af9..db955337c1 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -169,7 +169,7 @@ class OptionCategory { }; // The general Option Category (used as default category). -extern OptionCategory GeneralCategory; +extern OptionCategory *GeneralCategory; // HLSL Change - GeneralCategory is now a pointer //===----------------------------------------------------------------------===// // Option Base class @@ -251,7 +251,7 @@ class Option { : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0), HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), Position(0), AdditionalVals(0), ArgStr(""), HelpStr(""), ValueStr(""), - Category(&GeneralCategory), FullyInitialized(false) {} + Category(GeneralCategory), FullyInitialized(false) {} // HLSL Change - not GeneralCategory inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; } diff --git a/include/llvm/Support/Mutex.h b/include/llvm/Support/Mutex.h index 0f4e61af44..34a083ad2b 100644 --- a/include/llvm/Support/Mutex.h +++ b/include/llvm/Support/Mutex.h @@ -71,7 +71,11 @@ namespace llvm /// @{ private: #if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0 +#if 0 // HLSL Change void* data_; ///< We don't know what the data will be +#else + char data_[40]; // C_ASSERT this is CRITICAL_SECTION-sized +#endif // HLSL Change #endif /// @} diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index bdc1040919..7229ef327c 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -91,6 +91,13 @@ class raw_ostream { /// tell - Return the current offset with the file. uint64_t tell() const { return current_pos() + GetNumBytesInBuffer(); } + // HLSL Change Starts - needed to clean up properly + virtual void close() { flush(); } + virtual bool has_error() const { return false; } + virtual void clear_error() { } + // HLSL Change Ends + + //===--------------------------------------------------------------------===// // Configuration Interface //===--------------------------------------------------------------------===// @@ -427,7 +434,7 @@ class raw_fd_ostream : public raw_pwrite_stream { /// output error has been encountered. /// This doesn't implicitly flush any pending output. Also, it doesn't /// guarantee to detect all errors unless the stream has been closed. - bool has_error() const { + bool has_error() const override { return Error; } @@ -440,7 +447,7 @@ class raw_fd_ostream : public raw_pwrite_stream { /// Unless explicitly silenced." /// - from The Zen of Python, by Tim Peters /// - void clear_error() { + void clear_error() override { Error = false; } }; diff --git a/lib/Analysis/DependenceAnalysis.cpp b/lib/Analysis/DependenceAnalysis.cpp index 8bb7b8ee5d..6f58f05565 100644 --- a/lib/Analysis/DependenceAnalysis.cpp +++ b/lib/Analysis/DependenceAnalysis.cpp @@ -107,9 +107,13 @@ STATISTIC(BanerjeeApplications, "Banerjee applications"); STATISTIC(BanerjeeIndependence, "Banerjee independence"); STATISTIC(BanerjeeSuccesses, "Banerjee successes"); +#if 0 // HLSL Change Starts - option pending static cl::opt Delinearize("da-delinearize", cl::init(false), cl::Hidden, cl::ZeroOrMore, cl::desc("Try to delinearize array references.")); +#else +static const bool Delinearize = false; +#endif // HLSL Change Ends //===----------------------------------------------------------------------===// // basics diff --git a/lib/Analysis/IPA/CallGraph.cpp b/lib/Analysis/IPA/CallGraph.cpp index 2d6437d881..8e92f1e5af 100644 --- a/lib/Analysis/IPA/CallGraph.cpp +++ b/lib/Analysis/IPA/CallGraph.cpp @@ -22,30 +22,46 @@ using namespace llvm; // CallGraph::CallGraph(Module &M) - : M(M), Root(nullptr), ExternalCallingNode(getOrInsertFunction(nullptr)), - CallsExternalNode(new CallGraphNode(nullptr)) { - // Add every function to the call graph. - for (Function &F : M) - addToCallGraph(&F); - - // If we didn't find a main function, use the external call graph node - if (!Root) - Root = ExternalCallingNode; + : M(M), Root(nullptr), ExternalCallingNode(nullptr), // HLSL Change - no allocation here + CallsExternalNode(nullptr) { + try { // HLSL change - guard and reset + ExternalCallingNode = getOrInsertFunction(nullptr); + CallsExternalNode = new CallGraphNode(nullptr); + // Add every function to the call graph. + for (Function &F : M) + addToCallGraph(&F); + + // If we didn't find a main function, use the external call graph node + if (!Root) + Root = ExternalCallingNode; + } catch (...) { + reset(); + throw; + } } -CallGraph::~CallGraph() { +// HLSL Change Starts +CallGraph::~CallGraph() { reset(); } +void CallGraph::reset() { + // This function cleans up the CallGraph, called from the destructor or + // an under-construction instance. +// HLSL Change Ends // CallsExternalNode is not in the function map, delete it explicitly. - CallsExternalNode->allReferencesDropped(); + if (CallsExternalNode) // HLSL Change - guard + CallsExternalNode->allReferencesDropped(); delete CallsExternalNode; + CallsExternalNode = nullptr; // Reset all node's use counts to zero before deleting them to prevent an // assertion from firing. #ifndef NDEBUG for (auto &I : FunctionMap) - I.second->allReferencesDropped(); + if (I.second) // HLSL Change - this guard needed when slot is alloc'ed but not populated + I.second->allReferencesDropped(); #endif for (auto &I : FunctionMap) delete I.second; + FunctionMap.clear(); } void CallGraph::addToCallGraph(Function *F) { diff --git a/lib/Analysis/IPA/CallGraphSCCPass.cpp b/lib/Analysis/IPA/CallGraphSCCPass.cpp index 07b389a2a1..95697e843b 100644 --- a/lib/Analysis/IPA/CallGraphSCCPass.cpp +++ b/lib/Analysis/IPA/CallGraphSCCPass.cpp @@ -31,8 +31,12 @@ using namespace llvm; #define DEBUG_TYPE "cgscc-passmgr" +#if 0 // HLSL Change Starts - option pending static cl::opt MaxIterations("max-cg-scc-iterations", cl::ReallyHidden, cl::init(4)); +#else +static const unsigned MaxIterations = 4; +#endif STATISTIC(MaxSCCIterations, "Maximum CGSCCPassMgr iterations on one SCC"); @@ -546,6 +550,7 @@ void CallGraphSCC::ReplaceNode(CallGraphNode *Old, CallGraphNode *New) { /// Assign pass manager to manage this pass. void CallGraphSCCPass::assignPassManager(PMStack &PMS, PassManagerType PreferredType) { + std::unique_ptr thisPtr(this); // HLSL Change // Find CGPassManager while (!PMS.empty() && PMS.top()->getPassManagerType() > PMT_CallGraphPassManager) @@ -577,6 +582,7 @@ void CallGraphSCCPass::assignPassManager(PMStack &PMS, PMS.push(CGP); } + thisPtr.release(); CGP->add(this); } diff --git a/lib/Analysis/LoopAccessAnalysis.cpp b/lib/Analysis/LoopAccessAnalysis.cpp index becbae4c5b..d6316dc75b 100644 --- a/lib/Analysis/LoopAccessAnalysis.cpp +++ b/lib/Analysis/LoopAccessAnalysis.cpp @@ -27,6 +27,7 @@ using namespace llvm; #define DEBUG_TYPE "loop-accesses" +#if 0 // HLSL Change Starts - option pending static cl::opt VectorizationFactor("force-vector-width", cl::Hidden, cl::desc("Sets the SIMD width. Zero is autoselect."), @@ -64,9 +65,17 @@ static cl::opt MaxInterestingDependence( cl::desc("Maximum number of interesting dependences collected by " "loop-access analysis (default = 100)"), cl::init(100)); +#else +unsigned VectorizerParams::VectorizationInterleave; +unsigned VectorizerParams::VectorizationFactor; +unsigned VectorizerParams::RuntimeMemoryCheckThreshold = 8; +static const unsigned MemoryCheckMergeThreshold = 100; +const unsigned VectorizerParams::MaxVectorWidth = 64; +static const unsigned MaxInterestingDependence = 100; +#endif // HLSL Change Ends bool VectorizerParams::isInterleaveForced() { - return ::VectorizationInterleave.getNumOccurrences() > 0; + return false; // HLSL Change - instead of return ::VectorizationInterleave.getNumOccurrences() > 0; } void LoopAccessReport::emitAnalysis(const LoopAccessReport &Message, diff --git a/lib/Analysis/LoopInfo.cpp b/lib/Analysis/LoopInfo.cpp index 6b6faf8a66..f9e5b47416 100644 --- a/lib/Analysis/LoopInfo.cpp +++ b/lib/Analysis/LoopInfo.cpp @@ -43,9 +43,12 @@ static bool VerifyLoopInfo = true; #else static bool VerifyLoopInfo = false; #endif +#if 0 // HLSL Change Starts - option pending static cl::opt VerifyLoopInfoX("verify-loop-info", cl::location(VerifyLoopInfo), cl::desc("Verify loop info (time consuming)")); +#else +#endif // HLSL Change Ends // Loop identifier metadata name. static const char *const LoopMDName = "llvm.loop"; diff --git a/lib/Analysis/LoopPass.cpp b/lib/Analysis/LoopPass.cpp index e9fcf02118..cb832da9b7 100644 --- a/lib/Analysis/LoopPass.cpp +++ b/lib/Analysis/LoopPass.cpp @@ -354,6 +354,7 @@ void LoopPass::preparePassManager(PMStack &PMS) { /// Assign pass manager to manage this pass. void LoopPass::assignPassManager(PMStack &PMS, PassManagerType PreferredType) { + std::unique_ptr thisPtr(this); // HLSL Change // Find LPPassManager while (!PMS.empty() && PMS.top()->getPassManagerType() > PMT_LoopPassManager) @@ -384,6 +385,7 @@ void LoopPass::assignPassManager(PMStack &PMS, PMS.push(LPPM); } + thisPtr.release(); // HLSL Change LPPM->add(this); } diff --git a/lib/Analysis/RegionPass.cpp b/lib/Analysis/RegionPass.cpp index 0d7a8c2da2..09a48ccc41 100644 --- a/lib/Analysis/RegionPass.cpp +++ b/lib/Analysis/RegionPass.cpp @@ -241,6 +241,7 @@ void RegionPass::preparePassManager(PMStack &PMS) { /// Assign pass manager to manage this pass. void RegionPass::assignPassManager(PMStack &PMS, PassManagerType PreferredType) { + std::unique_ptr thisPtr(this); // HLSL Change // Find RGPassManager while (!PMS.empty() && PMS.top()->getPassManagerType() > PMT_RegionPassManager) @@ -272,6 +273,7 @@ void RegionPass::assignPassManager(PMStack &PMS, PMS.push(RGPM); } + thisPtr.release(); // HLSL Change RGPM->add(this); } diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index 9c7c1754e3..ccf2be952d 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -102,6 +102,7 @@ STATISTIC(NumTripCountsNotComputed, STATISTIC(NumBruteForceTripCountsComputed, "Number of loops with trip counts computed by force"); +#if 0 // HLSL Change Starts - option pending static cl::opt MaxBruteForceIterations("scalar-evolution-max-iterations", cl::ReallyHidden, cl::desc("Maximum number of iterations SCEV will " @@ -113,6 +114,10 @@ MaxBruteForceIterations("scalar-evolution-max-iterations", cl::ReallyHidden, static cl::opt VerifySCEV("verify-scev", cl::desc("Verify ScalarEvolution's backedge taken counts (slow)")); +#else +static const unsigned MaxBruteForceIterations = 100; +static const bool VerifySCEV = false; +#endif // HLSL Change Ends INITIALIZE_PASS_BEGIN(ScalarEvolution, "scalar-evolution", "Scalar Evolution Analysis", false, true) diff --git a/lib/Analysis/ScopedNoAliasAA.cpp b/lib/Analysis/ScopedNoAliasAA.cpp index a5fca3e79b..21a905fab4 100644 --- a/lib/Analysis/ScopedNoAliasAA.cpp +++ b/lib/Analysis/ScopedNoAliasAA.cpp @@ -46,8 +46,12 @@ using namespace llvm; // A handy option for disabling scoped no-alias functionality. The same effect // can also be achieved by stripping the associated metadata tags from IR, but // this option is sometimes more convenient. +#if 0 // HLSL Change Starts - option pending static cl::opt EnableScopedNoAlias("enable-scoped-noalias", cl::init(true)); +#else +static const bool EnableScopedNoAlias = true; +#endif // HLSL Change Ends namespace { /// AliasScopeNode - This is a simple wrapper around an MDNode which provides diff --git a/lib/Analysis/TargetLibraryInfo.cpp b/lib/Analysis/TargetLibraryInfo.cpp index 27e380b325..e2bcd4a8c8 100644 --- a/lib/Analysis/TargetLibraryInfo.cpp +++ b/lib/Analysis/TargetLibraryInfo.cpp @@ -16,6 +16,7 @@ #include "llvm/Support/CommandLine.h" using namespace llvm; +#if 0 // HLSL Change Starts - option pending static cl::opt ClVectorLibrary( "vector-library", cl::Hidden, cl::desc("Vector functions library"), cl::init(TargetLibraryInfoImpl::NoLibrary), @@ -24,6 +25,9 @@ static cl::opt ClVectorLibrary( clEnumValN(TargetLibraryInfoImpl::Accelerate, "Accelerate", "Accelerate framework"), clEnumValEnd)); +#else +static const TargetLibraryInfoImpl::VectorLibrary ClVectorLibrary = TargetLibraryInfoImpl::NoLibrary; +#endif // HLSL Change Ends const char *const TargetLibraryInfoImpl::StandardNames[LibFunc::NumLibFuncs] = { #define TLI_DEFINE_STRING diff --git a/lib/Analysis/TypeBasedAliasAnalysis.cpp b/lib/Analysis/TypeBasedAliasAnalysis.cpp index 4e9c6f678e..310079b806 100644 --- a/lib/Analysis/TypeBasedAliasAnalysis.cpp +++ b/lib/Analysis/TypeBasedAliasAnalysis.cpp @@ -135,7 +135,11 @@ using namespace llvm; // A handy option for disabling TBAA functionality. The same effect can also be // achieved by stripping the !tbaa tags from IR, but this option is sometimes // more convenient. +#if 0 // HLSL Change Starts - option pending static cl::opt EnableTBAA("enable-tbaa", cl::init(true)); +#else +static const bool EnableTBAA = true; +#endif // HLSL Change Ends namespace { /// TBAANode - This is a simple wrapper around an MDNode which provides a diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index d1b973752e..ab08e3e7d9 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -41,6 +41,7 @@ using namespace llvm::PatternMatch; const unsigned MaxDepth = 6; +#if 0 // HLSL Change Starts - option pending /// Enable an experimental feature to leverage information about dominating /// conditions to compute known bits. The individual options below control how /// hard we search. The defaults are choosen to be fairly aggressive. If you @@ -52,7 +53,7 @@ static cl::opt EnableDomConditions("value-tracking-dom-conditions", // This is expensive, so we only do it for the top level query value. // (TODO: evaluate cost vs profit, consider higher thresholds) static cl::opt DomConditionsMaxDepth("dom-conditions-max-depth", - cl::Hidden, cl::init(1)); + cl::Hidden, cl::init(1)); /// How many dominating blocks should be scanned looking for dominating /// conditions? @@ -68,6 +69,13 @@ static cl::opt DomConditionsMaxUses("dom-conditions-max-uses", // If true, don't consider only compares whose only use is a branch. static cl::opt DomConditionsSingleCmpUse("dom-conditions-single-cmp-use", cl::Hidden, cl::init(false)); +#else +static const bool EnableDomConditions = false; +static const unsigned DomConditionsMaxDepth = 1; +static const unsigned DomConditionsMaxDomBlocks = 2000; +static const unsigned DomConditionsMaxUses = 2000; +static const bool DomConditionsSingleCmpUse = false; +#endif // HLSL Change Ends /// Returns the bitwidth of the given scalar or pointer type (if unknown returns /// 0). For vector types, returns the element type's bitwidth. diff --git a/lib/Analysis/regioninfo.cpp b/lib/Analysis/regioninfo.cpp index 8cd85348fd..ed3786b0ad 100644 --- a/lib/Analysis/regioninfo.cpp +++ b/lib/Analysis/regioninfo.cpp @@ -37,6 +37,7 @@ STATISTIC(numSimpleRegions, "The # of simple regions"); // Always verify if expensive checking is enabled. +#if 0 // HLSL Change Starts - option pending static cl::opt VerifyRegionInfoX( "verify-region-info", @@ -55,7 +56,8 @@ static cl::opt printStyleX("print-region-style", clEnumValN(Region::PrintRN, "rn", "print regions in detail with element_iterator"), clEnumValEnd)); - +#else +#endif // HLSL Change Ends //===----------------------------------------------------------------------===// // Region implementation diff --git a/lib/Bitcode/Writer/BitcodeWriter.cpp b/lib/Bitcode/Writer/BitcodeWriter.cpp index 0b5e6d4219..bb19ca0a20 100644 --- a/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -335,11 +335,11 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { uint64_t NumBits = VE.computeBitsRequiredForTypeIndicies(); // Abbrev for TYPE_CODE_POINTER. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_POINTER)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); Abbv->Add(BitCodeAbbrevOp(0)); // Addrspace = 0 - unsigned PtrAbbrev = Stream.EmitAbbrev(Abbv); + unsigned PtrAbbrev = Stream.EmitAbbrev(Abbv.get()); // Abbrev for TYPE_CODE_FUNCTION. Abbv = new BitCodeAbbrev(); @@ -348,7 +348,7 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); - unsigned FunctionAbbrev = Stream.EmitAbbrev(Abbv); + unsigned FunctionAbbrev = Stream.EmitAbbrev(Abbv.get()); // Abbrev for TYPE_CODE_STRUCT_ANON. Abbv = new BitCodeAbbrev(); @@ -357,14 +357,14 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); - unsigned StructAnonAbbrev = Stream.EmitAbbrev(Abbv); + unsigned StructAnonAbbrev = Stream.EmitAbbrev(Abbv.get()); // Abbrev for TYPE_CODE_STRUCT_NAME. Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_STRUCT_NAME)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); - unsigned StructNameAbbrev = Stream.EmitAbbrev(Abbv); + unsigned StructNameAbbrev = Stream.EmitAbbrev(Abbv.get()); // Abbrev for TYPE_CODE_STRUCT_NAMED. Abbv = new BitCodeAbbrev(); @@ -373,7 +373,7 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); - unsigned StructNamedAbbrev = Stream.EmitAbbrev(Abbv); + unsigned StructNamedAbbrev = Stream.EmitAbbrev(Abbv.get()); // Abbrev for TYPE_CODE_ARRAY. Abbv = new BitCodeAbbrev(); @@ -381,7 +381,7 @@ static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) { Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // size Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, NumBits)); - unsigned ArrayAbbrev = Stream.EmitAbbrev(Abbv); + unsigned ArrayAbbrev = Stream.EmitAbbrev(Abbv.get()); // Emit an entry count so the reader can reserve space. TypeVals.push_back(TypeList.size()); @@ -633,7 +633,7 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, unsigned SimpleGVarAbbrev = 0; if (!M->global_empty()) { // Add an abbrev for common globals with no visibility or thread localness. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::MODULE_CODE_GLOBALVAR)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, Log2_32_Ceil(MaxGlobalType+1))); @@ -655,7 +655,7 @@ static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE, Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, Log2_32_Ceil(SectionMap.size()+1))); // Don't bother emitting vis + thread local. - SimpleGVarAbbrev = Stream.EmitAbbrev(Abbv); + SimpleGVarAbbrev = Stream.EmitAbbrev(Abbv.get()); } // Emit the global variable information. @@ -1172,11 +1172,11 @@ static void WriteModuleMetadata(const Module *M, unsigned MDSAbbrev = 0; if (VE.hasMDString()) { // Abbrev for METADATA_STRING. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::METADATA_STRING)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); - MDSAbbrev = Stream.EmitAbbrev(Abbv); + MDSAbbrev = Stream.EmitAbbrev(Abbv.get()); } // Initialize MDNode abbreviations. @@ -1188,14 +1188,14 @@ static void WriteModuleMetadata(const Module *M, // // Assume the column is usually under 128, and always output the inlined-at // location (it's never more expensive than building an array size 1). - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::METADATA_LOCATION)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); - DILocationAbbrev = Stream.EmitAbbrev(Abbv); + DILocationAbbrev = Stream.EmitAbbrev(Abbv.get()); } if (VE.hasGenericDINode()) { @@ -1203,7 +1203,7 @@ static void WriteModuleMetadata(const Module *M, // // Assume the column is usually under 128, and always output the inlined-at // location (it's never more expensive than building an array size 1). - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::METADATA_GENERIC_DEBUG)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); @@ -1211,17 +1211,17 @@ static void WriteModuleMetadata(const Module *M, Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); - GenericDINodeAbbrev = Stream.EmitAbbrev(Abbv); + GenericDINodeAbbrev = Stream.EmitAbbrev(Abbv.get()); } unsigned NameAbbrev = 0; if (!M->named_metadata_empty()) { // Abbrev for METADATA_NAME. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::METADATA_NAME)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); - NameAbbrev = Stream.EmitAbbrev(Abbv); + NameAbbrev = Stream.EmitAbbrev(Abbv.get()); } SmallVector Record; @@ -1377,30 +1377,30 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal, // If this is a constant pool for the module, emit module-specific abbrevs. if (isGlobal) { // Abbrev for CST_CODE_AGGREGATE. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_AGGREGATE)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, Log2_32_Ceil(LastVal+1))); - AggregateAbbrev = Stream.EmitAbbrev(Abbv); + AggregateAbbrev = Stream.EmitAbbrev(Abbv.get()); // Abbrev for CST_CODE_STRING. Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_STRING)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); - String8Abbrev = Stream.EmitAbbrev(Abbv); + String8Abbrev = Stream.EmitAbbrev(Abbv.get()); // Abbrev for CST_CODE_CSTRING. Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CSTRING)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); - CString7Abbrev = Stream.EmitAbbrev(Abbv); + CString7Abbrev = Stream.EmitAbbrev(Abbv.get()); // Abbrev for CST_CODE_CSTRING. Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CSTRING)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); - CString6Abbrev = Stream.EmitAbbrev(Abbv); + CString6Abbrev = Stream.EmitAbbrev(Abbv.get()); } SmallVector Record; @@ -2181,70 +2181,70 @@ static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) { Stream.EnterBlockInfoBlock(2); { // 8-bit fixed-width VST_ENTRY/VST_BBENTRY strings. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, - Abbv) != VST_ENTRY_8_ABBREV) + Abbv.get()) != VST_ENTRY_8_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } { // 7-bit fixed width VST_ENTRY strings. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_ENTRY)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, - Abbv) != VST_ENTRY_7_ABBREV) + Abbv.get()) != VST_ENTRY_7_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } { // 6-bit char6 VST_ENTRY strings. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_ENTRY)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, - Abbv) != VST_ENTRY_6_ABBREV) + Abbv.get()) != VST_ENTRY_6_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } { // 6-bit char6 VST_BBENTRY strings. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_BBENTRY)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, - Abbv) != VST_BBENTRY_6_ABBREV) + Abbv.get()) != VST_BBENTRY_6_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } { // SETTYPE abbrev for CONSTANTS_BLOCK. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_SETTYPE)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, VE.computeBitsRequiredForTypeIndicies())); if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, - Abbv) != CONSTANTS_SETTYPE_ABBREV) + Abbv.get()) != CONSTANTS_SETTYPE_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } { // INTEGER abbrev for CONSTANTS_BLOCK. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_INTEGER)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, - Abbv) != CONSTANTS_INTEGER_ABBREV) + Abbv.get()) != CONSTANTS_INTEGER_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } { // CE_CAST abbrev for CONSTANTS_BLOCK. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CE_CAST)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // cast opc Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // typeid @@ -2252,21 +2252,21 @@ static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) { Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, - Abbv) != CONSTANTS_CE_CAST_Abbrev) + Abbv.get()) != CONSTANTS_CE_CAST_Abbrev) llvm_unreachable("Unexpected abbrev ordering!"); } { // NULL abbrev for CONSTANTS_BLOCK. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_NULL)); if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID, - Abbv) != CONSTANTS_NULL_Abbrev) + Abbv.get()) != CONSTANTS_NULL_Abbrev) llvm_unreachable("Unexpected abbrev ordering!"); } // FIXME: This should only use space for first class types! { // INST_LOAD abbrev for FUNCTION_BLOCK. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_LOAD)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Ptr Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // dest ty @@ -2274,73 +2274,73 @@ static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) { Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // Align Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // volatile if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, - Abbv) != FUNCTION_INST_LOAD_ABBREV) + Abbv.get()) != FUNCTION_INST_LOAD_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } { // INST_BINOP abbrev for FUNCTION_BLOCK. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_BINOP)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LHS Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // RHS Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, - Abbv) != FUNCTION_INST_BINOP_ABBREV) + Abbv.get()) != FUNCTION_INST_BINOP_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } { // INST_BINOP_FLAGS abbrev for FUNCTION_BLOCK. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_BINOP)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LHS Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // RHS Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); // flags if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, - Abbv) != FUNCTION_INST_BINOP_FLAGS_ABBREV) + Abbv.get()) != FUNCTION_INST_BINOP_FLAGS_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } { // INST_CAST abbrev for FUNCTION_BLOCK. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_CAST)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // OpVal Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // dest ty VE.computeBitsRequiredForTypeIndicies())); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, - Abbv) != FUNCTION_INST_CAST_ABBREV) + Abbv.get()) != FUNCTION_INST_CAST_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } { // INST_RET abbrev for FUNCTION_BLOCK. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_RET)); if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, - Abbv) != FUNCTION_INST_RET_VOID_ABBREV) + Abbv.get()) != FUNCTION_INST_RET_VOID_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } { // INST_RET abbrev for FUNCTION_BLOCK. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_RET)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ValID if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, - Abbv) != FUNCTION_INST_RET_VAL_ABBREV) + Abbv.get()) != FUNCTION_INST_RET_VAL_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } { // INST_UNREACHABLE abbrev for FUNCTION_BLOCK. - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_UNREACHABLE)); if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, - Abbv) != FUNCTION_INST_UNREACHABLE_ABBREV) + Abbv.get()) != FUNCTION_INST_UNREACHABLE_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } { - BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + IntrusiveRefCntPtr Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_GEP)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // dest ty Log2_32_Ceil(VE.getTypes().size() + 1))); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); - if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv) != + if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID, Abbv.get()) != FUNCTION_INST_GEP_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } diff --git a/lib/DxcSupport/CMakeLists.txt b/lib/DxcSupport/CMakeLists.txt index c11fa78be1..3c61f01ebc 100644 --- a/lib/DxcSupport/CMakeLists.txt +++ b/lib/DxcSupport/CMakeLists.txt @@ -2,6 +2,7 @@ # This file is distributed under the University of Illinois Open Source License. See LICENSE.TXT for details. add_llvm_library(LLVMDxcSupport dxcapi.use.cpp + dxcmem.cpp FileIOHelper.cpp Global.cpp HLSLOptions.cpp diff --git a/lib/DxcSupport/FileIOHelper.cpp b/lib/DxcSupport/FileIOHelper.cpp index 2e8aa2fa6f..83419b7527 100644 --- a/lib/DxcSupport/FileIOHelper.cpp +++ b/lib/DxcSupport/FileIOHelper.cpp @@ -5,7 +5,7 @@ // This file is distributed under the University of Illinois Open Source // // License. See LICENSE.TXT for details. // // // - +// TODO: consider including an empty blob singleton (possibly UTF-8/16 too). // // // /////////////////////////////////////////////////////////////////////////////// @@ -22,38 +22,109 @@ #define CP_UTF16 1200 +struct HeapMalloc : public IMalloc { +public: + ULONG STDMETHODCALLTYPE AddRef() { + return 1; + } + ULONG STDMETHODCALLTYPE Release() { + return 1; + } + STDMETHODIMP QueryInterface(REFIID iid, void** ppvObject) { + return DoBasicQueryInterface(this, iid, ppvObject); + } + virtual void *STDMETHODCALLTYPE Alloc( + /* [annotation][in] */ + _In_ SIZE_T cb) { + return HeapAlloc(GetProcessHeap(), 0, cb); + } + + virtual void *STDMETHODCALLTYPE Realloc( + /* [annotation][in] */ + _In_opt_ void *pv, + /* [annotation][in] */ + _In_ SIZE_T cb) + { + return HeapReAlloc(GetProcessHeap(), 0, pv, cb); + } + + virtual void STDMETHODCALLTYPE Free( + /* [annotation][in] */ + _In_opt_ void *pv) + { + HeapFree(GetProcessHeap(), 0, pv); + } + + + virtual SIZE_T STDMETHODCALLTYPE GetSize( + /* [annotation][in] */ + _In_opt_ _Post_writable_byte_size_(return) void *pv) + { + return HeapSize(GetProcessHeap(), 0, pv); + } + + virtual int STDMETHODCALLTYPE DidAlloc( + /* [annotation][in] */ + _In_opt_ void *pv) + { + return -1; // don't know + } + + + virtual void STDMETHODCALLTYPE HeapMinimize(void) + { + } +}; + +static HeapMalloc g_HeapMalloc; + namespace hlsl { +IMalloc *GetGlobalHeapMalloc() { + return &g_HeapMalloc; +} + _Use_decl_annotations_ -void ReadBinaryFile(LPCWSTR pFileName, void **ppData, DWORD *pDataSize) { - HANDLE hFile = CreateFileW(pFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); - if(hFile == INVALID_HANDLE_VALUE) { +void ReadBinaryFile(IMalloc *pMalloc, LPCWSTR pFileName, void **ppData, + DWORD *pDataSize) { + HANDLE hFile = CreateFileW(pFileName, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + if (hFile == INVALID_HANDLE_VALUE) { IFT(HRESULT_FROM_WIN32(GetLastError())); } + CHandle h(hFile); LARGE_INTEGER FileSize; - if(!GetFileSizeEx(hFile, &FileSize)) { + if (!GetFileSizeEx(hFile, &FileSize)) { IFT(HRESULT_FROM_WIN32(GetLastError())); } - if(FileSize.HighPart != 0) { + if (FileSize.HighPart != 0) { throw(hlsl::Exception(DXC_E_INPUT_FILE_TOO_LARGE, "input file is too large")); } - CComHeapPtr pData; - if (!pData.AllocateBytes(FileSize.LowPart)) { + + char *pData = (char *)pMalloc->Alloc(FileSize.LowPart); + if (!pData) { throw std::bad_alloc(); } DWORD BytesRead; - if(!ReadFile(hFile, pData.m_pData, FileSize.LowPart, &BytesRead, nullptr)) { - IFT(HRESULT_FROM_WIN32(GetLastError())); + if (!ReadFile(hFile, pData, FileSize.LowPart, &BytesRead, nullptr)) { + HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); + pMalloc->Free(pData); + throw ::hlsl::Exception(hr); } DXASSERT(FileSize.LowPart == BytesRead, "ReadFile operation failed"); - *ppData = pData.Detach(); + *ppData = pData; *pDataSize = FileSize.LowPart; } +_Use_decl_annotations_ +void ReadBinaryFile(LPCWSTR pFileName, void **ppData, DWORD *pDataSize) { + return ReadBinaryFile(GetGlobalHeapMalloc(), pFileName, ppData, pDataSize); +} + _Use_decl_annotations_ void WriteBinaryFile(LPCWSTR pFileName, const void *pData, DWORD DataSize) { HANDLE hFile = CreateFileW(pFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); @@ -103,18 +174,26 @@ UINT32 DxcCodePageFromBytes(const char *bytes, size_t byteLen) { class InternalDxcBlobEncoding : public IDxcBlobEncoding { private: - DXC_MICROCOM_REF_FIELD(m_dwRef) + DXC_MICROCOM_TM_REF_FIELDS() // an underlying m_pMalloc that owns this LPCVOID m_Buffer = nullptr; - IUnknown* m_Owner = nullptr; // IMalloc when MallocFree is true + IUnknown* m_Owner = nullptr; // IMalloc when MallocFree is true, owning the buffer SIZE_T m_BufferSize; - unsigned m_HeapFree : 1; unsigned m_EncodingKnown : 1; unsigned m_MallocFree : 1; UINT32 m_CodePage; public: - DXC_MICROCOM_ADDREF_RELEASE_IMPL(m_dwRef) - InternalDxcBlobEncoding() : m_dwRef(0) { + DXC_MICROCOM_ADDREF_IMPL(m_dwRef) + ULONG STDMETHODCALLTYPE Release() { + // Because blobs are also used by tests and utilities, we avoid using TLS. + ULONG result = InterlockedDecrement(&m_dwRef); + if (result == 0) { + CComPtr pTmp(m_pMalloc); + this->~InternalDxcBlobEncoding(); + pTmp->Free(this); + } + return result; } + DXC_MICROCOM_TM_CTOR(InternalDxcBlobEncoding) HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) { return DoBasicQueryInterface(this, iid, ppvObject); } @@ -126,33 +205,20 @@ class InternalDxcBlobEncoding : public IDxcBlobEncoding { if (m_Owner != nullptr) { m_Owner->Release(); } - if (m_HeapFree) { - CoTaskMemFree((LPVOID)m_Buffer); - } } static HRESULT CreateFromHeap(LPCVOID buffer, SIZE_T bufferSize, bool encodingKnown, UINT32 codePage, - _COM_Outptr_ InternalDxcBlobEncoding **pEncoding) { - *pEncoding = new (std::nothrow) InternalDxcBlobEncoding(); - if (*pEncoding == nullptr) { - return E_OUTOFMEMORY; - } - (*pEncoding)->m_Buffer = buffer; - (*pEncoding)->m_BufferSize = bufferSize; - (*pEncoding)->m_HeapFree = 1; - (*pEncoding)->m_EncodingKnown = encodingKnown; - (*pEncoding)->m_MallocFree = 0; - (*pEncoding)->m_CodePage = codePage; - (*pEncoding)->AddRef(); - return S_OK; + _COM_Outptr_ InternalDxcBlobEncoding **ppEncoding) { + return CreateFromMalloc(buffer, DxcGetThreadMallocNoRef(), bufferSize, + encodingKnown, codePage, ppEncoding); } static HRESULT - CreateFromBlob(_In_ IDxcBlob *pBlob, bool encodingKnown, UINT32 codePage, + CreateFromBlob(_In_ IDxcBlob *pBlob, _In_ IMalloc *pMalloc, bool encodingKnown, UINT32 codePage, _COM_Outptr_ InternalDxcBlobEncoding **pEncoding) { - *pEncoding = new (std::nothrow) InternalDxcBlobEncoding(); + *pEncoding = InternalDxcBlobEncoding::Alloc(pMalloc); if (*pEncoding == nullptr) { return E_OUTOFMEMORY; } @@ -160,25 +226,25 @@ class InternalDxcBlobEncoding : public IDxcBlobEncoding { (*pEncoding)->m_Owner = pBlob; (*pEncoding)->m_Buffer = pBlob->GetBufferPointer(); (*pEncoding)->m_BufferSize = pBlob->GetBufferSize(); - (*pEncoding)->m_HeapFree = 0; (*pEncoding)->m_EncodingKnown = encodingKnown; (*pEncoding)->m_MallocFree = 0; (*pEncoding)->m_CodePage = codePage; (*pEncoding)->AddRef(); return S_OK; } + static HRESULT CreateFromMalloc(LPCVOID buffer, IMalloc *pIMalloc, SIZE_T bufferSize, bool encodingKnown, UINT32 codePage, _COM_Outptr_ InternalDxcBlobEncoding **pEncoding) { - *pEncoding = new (std::nothrow) InternalDxcBlobEncoding(); + *pEncoding = InternalDxcBlobEncoding::Alloc(pIMalloc); if (*pEncoding == nullptr) { + *pEncoding = nullptr; return E_OUTOFMEMORY; } pIMalloc->AddRef(); (*pEncoding)->m_Owner = pIMalloc; (*pEncoding)->m_Buffer = buffer; (*pEncoding)->m_BufferSize = bufferSize; - (*pEncoding)->m_HeapFree = 0; (*pEncoding)->m_EncodingKnown = encodingKnown; (*pEncoding)->m_MallocFree = 1; (*pEncoding)->m_CodePage = codePage; @@ -207,12 +273,12 @@ class InternalDxcBlobEncoding : public IDxcBlobEncoding { // Relatively dangerous API. This means the buffer should be pinned for as // long as this object is alive. - void ClearFreeFlag() { m_HeapFree = 0; } + void ClearFreeFlag() { m_MallocFree = 0; } }; static HRESULT CodePageBufferToUtf16(UINT32 codePage, LPCVOID bufferPointer, SIZE_T bufferSize, - CComHeapPtr &utf16NewCopy, + CDxcMallocHeapPtr &utf16NewCopy, _Out_ UINT32 *pConvertedCharCount) { *pConvertedCharCount = 0; @@ -272,7 +338,7 @@ HRESULT DxcCreateBlobFromBlob( IFR(pBlobEncoding->GetEncoding(&encodingKnown, &codePage)); } CComPtr pCreated; - IFR(InternalDxcBlobEncoding::CreateFromBlob(pBlob, encodingKnown, codePage, + IFR(InternalDxcBlobEncoding::CreateFromBlob(pBlob, DxcGetThreadMallocNoRef(), encodingKnown, codePage, &pCreated)); pCreated->AdjustPtrAndSize(offset, length); *ppResult = pCreated.Detach(); @@ -317,17 +383,18 @@ DxcCreateBlobOnHeapCopy(_In_bytecount_(size) LPCVOID pData, UINT32 size, } _Use_decl_annotations_ -HRESULT DxcCreateBlobFromFile(LPCWSTR pFileName, UINT32 *pCodePage, - IDxcBlobEncoding **ppBlobEncoding) { +HRESULT +DxcCreateBlobFromFile(IMalloc *pMalloc, LPCWSTR pFileName, UINT32 *pCodePage, + IDxcBlobEncoding **ppBlobEncoding) throw() { if (pFileName == nullptr || ppBlobEncoding == nullptr) { return E_POINTER; } - CComHeapPtr pData; + LPVOID pData; DWORD dataSize; *ppBlobEncoding = nullptr; try { - ReadBinaryFile(pFileName, (void **)(&pData), &dataSize); + ReadBinaryFile(pMalloc, pFileName, &pData, &dataSize); } CATCH_CPP_RETURN_HRESULT(); @@ -335,30 +402,51 @@ HRESULT DxcCreateBlobFromFile(LPCWSTR pFileName, UINT32 *pCodePage, UINT32 codePage = (pCodePage != nullptr) ? *pCodePage : 0; InternalDxcBlobEncoding *internalEncoding; - HRESULT hr = InternalDxcBlobEncoding::CreateFromHeap( - pData, dataSize, known, codePage, &internalEncoding); + HRESULT hr = InternalDxcBlobEncoding::CreateFromMalloc( + pData, pMalloc, dataSize, known, codePage, &internalEncoding); if (SUCCEEDED(hr)) { *ppBlobEncoding = internalEncoding; - pData.Detach(); + } + else { + pMalloc->Free(pData); } return hr; } +_Use_decl_annotations_ +HRESULT DxcCreateBlobFromFile(LPCWSTR pFileName, UINT32 *pCodePage, + IDxcBlobEncoding **ppBlobEncoding) { + CComPtr pMalloc; + IFR(CoGetMalloc(1, &pMalloc)); + return DxcCreateBlobFromFile(pMalloc, pFileName, pCodePage, ppBlobEncoding); +} + _Use_decl_annotations_ HRESULT -DxcCreateBlobWithEncodingSet(IDxcBlob *pBlob, UINT32 codePage, - IDxcBlobEncoding **pBlobEncoding) { - *pBlobEncoding = nullptr; +DxcCreateBlobWithEncodingSet(IMalloc *pMalloc, IDxcBlob *pBlob, UINT32 codePage, + IDxcBlobEncoding **ppBlobEncoding) { + DXASSERT_NOMSG(pMalloc != nullptr); + DXASSERT_NOMSG(pBlob != nullptr); + DXASSERT_NOMSG(ppBlobEncoding != nullptr); + *ppBlobEncoding = nullptr; InternalDxcBlobEncoding *internalEncoding; - HRESULT hr = InternalDxcBlobEncoding::CreateFromBlob(pBlob, true, codePage, - &internalEncoding); + HRESULT hr = InternalDxcBlobEncoding::CreateFromBlob( + pBlob, pMalloc, true, codePage, &internalEncoding); if (SUCCEEDED(hr)) { - *pBlobEncoding = internalEncoding; + *ppBlobEncoding = internalEncoding; } return hr; } +_Use_decl_annotations_ +HRESULT +DxcCreateBlobWithEncodingSet(IDxcBlob *pBlob, UINT32 codePage, + IDxcBlobEncoding **ppBlobEncoding) { + return DxcCreateBlobWithEncodingSet(DxcGetThreadMallocNoRef(), pBlob, + codePage, ppBlobEncoding); +} + _Use_decl_annotations_ HRESULT DxcCreateBlobWithEncodingFromPinned(LPCVOID pText, UINT32 size, UINT32 codePage, @@ -426,8 +514,8 @@ DxcCreateBlobWithEncodingOnHeapCopy(LPCVOID pText, UINT32 size, UINT32 codePage, IDxcBlobEncoding **pBlobEncoding) { *pBlobEncoding = nullptr; - CComHeapPtr heapCopy; - if (!heapCopy.AllocateBytes(size)) { + CDxcMallocHeapPtr heapCopy(DxcGetThreadMallocNoRef()); + if (!heapCopy.Allocate(size)) { return E_OUTOFMEMORY; } memcpy(heapCopy.m_pData, pText, size); @@ -455,6 +543,23 @@ DxcCreateBlobWithEncodingOnMalloc(LPCVOID pText, IMalloc *pIMalloc, UINT32 size, return hr; } +_Use_decl_annotations_ +HRESULT +DxcCreateBlobWithEncodingOnMallocCopy(IMalloc *pIMalloc, LPCVOID pText, UINT32 size, UINT32 codePage, + IDxcBlobEncoding **ppBlobEncoding) { + *ppBlobEncoding = nullptr; + void *pData = pIMalloc->Alloc(size); + if (pData == nullptr) + return E_OUTOFMEMORY; + memcpy(pData, pText, size); + HRESULT hr = DxcCreateBlobWithEncodingOnMalloc(pData, pIMalloc, size, codePage, ppBlobEncoding); + if (FAILED(hr)) { + pIMalloc->Free(pData); + return hr; + } + return S_OK; +} + _Use_decl_annotations_ HRESULT DxcGetBlobAsUtf8(IDxcBlob *pBlob, IDxcBlobEncoding **pBlobEncoding) { @@ -488,7 +593,7 @@ HRESULT DxcGetBlobAsUtf8(IDxcBlob *pBlob, IDxcBlobEncoding **pBlobEncoding) { if (codePage == CP_UTF8) { // Reuse the underlying blob but create an object with the encoding known. InternalDxcBlobEncoding* internalEncoding; - hr = InternalDxcBlobEncoding::CreateFromBlob(pBlob, true, CP_UTF8, &internalEncoding); + hr = InternalDxcBlobEncoding::CreateFromBlob(pBlob, DxcGetThreadMallocNoRef(), true, CP_UTF8, &internalEncoding); if (SUCCEEDED(hr)) { *pBlobEncoding = internalEncoding; } @@ -499,7 +604,7 @@ HRESULT DxcGetBlobAsUtf8(IDxcBlob *pBlob, IDxcBlobEncoding **pBlobEncoding) { // Any UTF-16 output must be converted to UTF-16 first, then // back to the target code page. - CComHeapPtr utf16NewCopy; + CDxcMallocHeapPtr utf16NewCopy(DxcGetThreadMallocNoRef()); wchar_t* utf16Chars = nullptr; UINT32 utf16CharCount; if (codePage == CP_UTF16) { @@ -516,7 +621,7 @@ HRESULT DxcGetBlobAsUtf8(IDxcBlob *pBlob, IDxcBlobEncoding **pBlobEncoding) { } const UINT32 targetCodePage = CP_UTF8; - CComHeapPtr finalNewCopy; + CDxcTMHeapPtr finalNewCopy; int numToConvertFinal = WideCharToMultiByte( targetCodePage, 0, utf16Chars, utf16CharCount, finalNewCopy, 0, NULL, NULL); @@ -537,7 +642,8 @@ HRESULT DxcGetBlobAsUtf8(IDxcBlob *pBlob, IDxcBlobEncoding **pBlobEncoding) { ((LPSTR)finalNewCopy)[numActuallyConvertedFinal] = '\0'; InternalDxcBlobEncoding* internalEncoding; - hr = InternalDxcBlobEncoding::CreateFromHeap(finalNewCopy.m_pData, + hr = InternalDxcBlobEncoding::CreateFromMalloc(finalNewCopy.m_pData, + DxcGetThreadMallocNoRef(), numActuallyConvertedFinal, true, targetCodePage, &internalEncoding); if (SUCCEEDED(hr)) { *pBlobEncoding = internalEncoding; @@ -573,13 +679,14 @@ DxcGetBlobAsUtf8NullTerm(_In_ IDxcBlob *pBlob, } // We have a non-null-terminated UTF-8 stream. Copy to a new location. - CComHeapPtr pCopy; + CDxcTMHeapPtr pCopy; if (!pCopy.Allocate(blobSize + 1)) return E_OUTOFMEMORY; memcpy(pCopy.m_pData, pChars, blobSize); pCopy.m_pData[blobSize] = '\0'; - IFR(DxcCreateBlobWithEncodingOnHeap(pCopy.m_pData, blobSize + 1, CP_UTF8, - ppBlobEncoding)); + IFR(DxcCreateBlobWithEncodingOnMalloc( + pCopy.m_pData, DxcGetThreadMallocNoRef(), blobSize + 1, CP_UTF8, + ppBlobEncoding)); pCopy.Detach(); return S_OK; } @@ -593,7 +700,7 @@ DxcGetBlobAsUtf8NullTerm(_In_ IDxcBlob *pBlob, } _Use_decl_annotations_ -HRESULT DxcGetBlobAsUtf16(IDxcBlob *pBlob, IDxcBlobEncoding **pBlobEncoding) { +HRESULT DxcGetBlobAsUtf16(IDxcBlob *pBlob, IMalloc *pMalloc, IDxcBlobEncoding **pBlobEncoding) { *pBlobEncoding = nullptr; HRESULT hr; @@ -624,7 +731,7 @@ HRESULT DxcGetBlobAsUtf16(IDxcBlob *pBlob, IDxcBlobEncoding **pBlobEncoding) { // Reuse the underlying blob but create an object with the encoding known. if (codePage == CP_UTF16) { InternalDxcBlobEncoding* internalEncoding; - hr = InternalDxcBlobEncoding::CreateFromBlob(pBlob, true, CP_UTF16, &internalEncoding); + hr = InternalDxcBlobEncoding::CreateFromBlob(pBlob, pMalloc, true, CP_UTF16, &internalEncoding); if (SUCCEEDED(hr)) { *pBlobEncoding = internalEncoding; } @@ -632,7 +739,7 @@ HRESULT DxcGetBlobAsUtf16(IDxcBlob *pBlob, IDxcBlobEncoding **pBlobEncoding) { } // Convert and create a blob that owns the encoding. - CComHeapPtr utf16NewCopy; + CDxcMallocHeapPtr utf16NewCopy(pMalloc); UINT32 utf16CharCount; hr = CodePageBufferToUtf16(codePage, pBlob->GetBufferPointer(), blobLen, utf16NewCopy, &utf16CharCount); @@ -641,8 +748,9 @@ HRESULT DxcGetBlobAsUtf16(IDxcBlob *pBlob, IDxcBlobEncoding **pBlobEncoding) { } InternalDxcBlobEncoding* internalEncoding; - hr = InternalDxcBlobEncoding::CreateFromHeap(utf16NewCopy.m_pData, - utf16CharCount * sizeof(WCHAR), true, CP_UTF16, &internalEncoding); + hr = InternalDxcBlobEncoding::CreateFromMalloc( + utf16NewCopy.m_pData, pMalloc, + utf16CharCount * sizeof(WCHAR), true, CP_UTF16, &internalEncoding); if (SUCCEEDED(hr)) { *pBlobEncoding = internalEncoding; utf16NewCopy.Detach(); @@ -659,23 +767,31 @@ bool IsBlobNullOrEmpty(_In_opt_ IDxcBlob *pBlob) throw() { class MemoryStream : public AbstractMemoryStream, public IDxcBlob { private: - DXC_MICROCOM_REF_FIELD(m_dwRef) - CComPtr m_pMalloc; - LPBYTE m_pMemory; - ULONG m_offset; - ULONG m_size; - ULONG m_allocSize; + DXC_MICROCOM_TM_REF_FIELDS() + LPBYTE m_pMemory = nullptr; + ULONG m_offset = 0; + ULONG m_size = 0; + ULONG m_allocSize = 0; public: - DXC_MICROCOM_ADDREF_RELEASE_IMPL(m_dwRef) + DXC_MICROCOM_ADDREF_IMPL(m_dwRef) + ULONG STDMETHODCALLTYPE Release() { + // Because memory streams are also used by tests and utilities, + // we avoid using TLS. + ULONG result = InterlockedDecrement(&m_dwRef); \ + if (result == 0) { + CComPtr pTmp(m_pMalloc); + this->~MemoryStream(); + pTmp->Free(this); + } + return result; + } + + DXC_MICROCOM_TM_CTOR(MemoryStream) HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) { return DoBasicQueryInterface(this, iid, ppvObject); } - MemoryStream(_In_ IMalloc *pMalloc) - : m_dwRef(0), m_pMalloc(pMalloc), m_pMemory(nullptr), m_offset(0), - m_size(0), m_allocSize(0) {} - ~MemoryStream() { Reset(); } @@ -866,19 +982,22 @@ class MemoryStream : public AbstractMemoryStream, public IDxcBlob { class ReadOnlyBlobStream : public IStream { private: - DXC_MICROCOM_REF_FIELD(m_dwRef) + DXC_MICROCOM_TM_REF_FIELDS() CComPtr m_pSource; LPBYTE m_pMemory; ULONG m_offset; ULONG m_size; public: - DXC_MICROCOM_ADDREF_RELEASE_IMPL(m_dwRef) + DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL() + DXC_MICROCOM_TM_CTOR(ReadOnlyBlobStream) HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) { return DoBasicQueryInterface(this, iid, ppvObject); } - ReadOnlyBlobStream(IDxcBlob *pSource) : m_pSource(pSource), m_offset(0), m_dwRef(0) { + void Init(IDxcBlob *pSource) { + m_pSource = pSource; + m_offset = 0; m_size = m_pSource->GetBufferSize(); m_pMemory = (LPBYTE)m_pSource->GetBufferPointer(); } @@ -982,7 +1101,7 @@ HRESULT CreateMemoryStream(_In_ IMalloc *pMalloc, _COM_Outptr_ AbstractMemoryStr return E_POINTER; } - CComPtr stream = new (std::nothrow) MemoryStream(pMalloc); + CComPtr stream = MemoryStream::Alloc(pMalloc); *ppResult = stream.Detach(); return (*ppResult == nullptr) ? E_OUTOFMEMORY : S_OK; } @@ -992,7 +1111,10 @@ HRESULT CreateReadOnlyBlobStream(_In_ IDxcBlob *pSource, _COM_Outptr_ IStream** return E_POINTER; } - CComPtr stream = new (std::nothrow) ReadOnlyBlobStream(pSource); + CComPtr stream = ReadOnlyBlobStream::Alloc(DxcGetThreadMallocNoRef()); + if (stream.p) { + stream->Init(pSource); + } *ppResult = stream.Detach(); return (*ppResult == nullptr) ? E_OUTOFMEMORY : S_OK; } diff --git a/lib/DxcSupport/HLSLOptions.cpp b/lib/DxcSupport/HLSLOptions.cpp index 89a301aada..1aba9d6162 100644 --- a/lib/DxcSupport/HLSLOptions.cpp +++ b/lib/DxcSupport/HLSLOptions.cpp @@ -46,10 +46,23 @@ namespace { } -static HlslOptTable g_HlslOptTable; +static HlslOptTable *g_HlslOptTable; + +std::error_code hlsl::options::initHlslOptTable() { + DXASSERT(g_HlslOptTable == nullptr, "else double-init"); + g_HlslOptTable = new (std::nothrow) HlslOptTable(); + if (g_HlslOptTable == nullptr) + return std::error_code(E_OUTOFMEMORY, std::system_category()); + return std::error_code(); +} + +void hlsl::options::cleanupHlslOptTable() { + delete g_HlslOptTable; + g_HlslOptTable = nullptr; +} const OptTable * hlsl::options::getHlslOptTable() { - return &g_HlslOptTable; + return g_HlslOptTable; } void DxcDefines::push_back(llvm::StringRef value) { diff --git a/lib/DxcSupport/dxcmem.cpp b/lib/DxcSupport/dxcmem.cpp new file mode 100644 index 0000000000..bb97ed76e1 --- /dev/null +++ b/lib/DxcSupport/dxcmem.cpp @@ -0,0 +1,94 @@ +/////////////////////////////////////////////////////////////////////////////// +// // +// dxcmem.cpp // +// Copyright (C) Microsoft Corporation. All rights reserved. // +// This file is distributed under the University of Illinois Open Source // +// License. See LICENSE.TXT for details. // +// // +// Provides support for a thread-local allocator. // +// // +/////////////////////////////////////////////////////////////////////////////// + +#include "dxc/Support/Global.h" +#include + +#include "dxc/Support/WinIncludes.h" +#include + +static DWORD g_ThreadMallocTlsIndex; +static IMalloc *g_pDefaultMalloc; + +// Used by DllMain to set up and tear down per-thread tracking. +HRESULT DxcInitThreadMalloc() throw(); +void DxcCleanupThreadMalloc() throw(); + +// Used by APIs that are entry points to set up per-thread/invocation allocator. +void DxcSetThreadMalloc(IMalloc *pMalloc) throw(); +void DxcSetThreadMallocOrDefault(IMalloc *pMalloc) throw(); +void DxcClearThreadMalloc() throw(); + +// Used to retrieve the current invocation's allocator or perform an alloc/free/realloc. +IMalloc *DxcGetThreadMallocNoRef() throw(); +_Ret_maybenull_ _Post_writable_byte_size_(nBytes) void *DxcThreadAlloc(size_t nBytes) throw(); +void DxcThreadFree(void *) throw(); + +HRESULT DxcInitThreadMalloc() { + DXASSERT(g_ThreadMallocTlsIndex == 0, "else InitThreadMalloc already called"); + DXASSERT(g_pDefaultMalloc == nullptr, "else InitThreadMalloc already called"); + + // We capture the default malloc early to avoid potential failures later on. + HRESULT hrMalloc = CoGetMalloc(1, &g_pDefaultMalloc); + if (FAILED(hrMalloc)) return hrMalloc; + + g_ThreadMallocTlsIndex = TlsAlloc(); + if (g_ThreadMallocTlsIndex == TLS_OUT_OF_INDEXES) { + g_ThreadMallocTlsIndex = 0; + g_pDefaultMalloc->Release(); + g_pDefaultMalloc = nullptr; + return E_OUTOFMEMORY; + } + + return S_OK; +} + +void DxcCleanupThreadMalloc() { + if (g_ThreadMallocTlsIndex) { + TlsFree(g_ThreadMallocTlsIndex); + g_ThreadMallocTlsIndex = 0; + DXASSERT(g_pDefaultMalloc, "else DxcInitThreadMalloc didn't work/fail atomically"); + g_pDefaultMalloc->Release(); + g_pDefaultMalloc = nullptr; + } +} + +IMalloc *DxcGetThreadMallocNoRef() { + DXASSERT(g_ThreadMallocTlsIndex != 0, "else prior to DxcInitThreadMalloc or after DxcCleanupThreadMalloc"); + return reinterpret_cast(TlsGetValue(g_ThreadMallocTlsIndex)); +} +void DxcClearThreadMalloc() { + DXASSERT(g_ThreadMallocTlsIndex != 0, "else prior to DxcInitThreadMalloc or after DxcCleanupThreadMalloc"); + IMalloc *pMalloc = DxcGetThreadMallocNoRef(); + DXVERIFY_NOMSG(TlsSetValue(g_ThreadMallocTlsIndex, nullptr)); + pMalloc->Release(); +} +void DxcSetThreadMalloc(IMalloc *pMalloc) { + DXASSERT(g_ThreadMallocTlsIndex != 0, "else prior to DxcInitThreadMalloc or after DxcCleanupThreadMalloc"); + DXASSERT(DxcGetThreadMallocNoRef() == nullptr, "else nested allocation invoked"); + DXVERIFY_NOMSG(TlsSetValue(g_ThreadMallocTlsIndex, pMalloc)); + pMalloc->AddRef(); +} +void DxcSetThreadMallocOrDefault(IMalloc *pMalloc) { + DxcSetThreadMalloc(pMalloc ? pMalloc : g_pDefaultMalloc); +} +IMalloc *DxcSwapThreadMalloc(IMalloc *pMalloc, IMalloc **ppPrior) { + DXASSERT(g_ThreadMallocTlsIndex != 0, "else prior to DxcInitThreadMalloc or after DxcCleanupThreadMalloc"); + IMalloc *pPrior = DxcGetThreadMallocNoRef(); + if (ppPrior) { + *ppPrior = pPrior; + } + DXVERIFY_NOMSG(TlsSetValue(g_ThreadMallocTlsIndex, pMalloc)); + return pMalloc; +} +IMalloc *DxcSwapThreadMallocOrDefault(IMalloc *pMallocOrNull, IMalloc **ppPrior) { + return DxcSwapThreadMalloc(pMallocOrNull ? pMallocOrNull : g_pDefaultMalloc, ppPrior); +} diff --git a/lib/HLSL/DxcOptimizer.cpp b/lib/HLSL/DxcOptimizer.cpp index 28372077b6..8a3f9776cd 100644 --- a/lib/HLSL/DxcOptimizer.cpp +++ b/lib/HLSL/DxcOptimizer.cpp @@ -383,19 +383,19 @@ static HRESULT Utf8ToUtf16CoTaskMalloc(LPCSTR pValue, LPWSTR *ppResult) { class DxcOptimizerPass : public IDxcOptimizerPass { private: - DXC_MICROCOM_REF_FIELD(m_dwRef) + DXC_MICROCOM_TM_REF_FIELDS() LPCSTR m_pOptionName; LPCSTR m_pDescription; ArrayRef m_pArgNames; ArrayRef m_pArgDescriptions; public: - DXC_MICROCOM_ADDREF_RELEASE_IMPL(m_dwRef) + DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL() + DXC_MICROCOM_TM_CTOR(DxcOptimizerPass) HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) { return DoBasicQueryInterface(this, iid, ppvObject); } - DxcOptimizerPass() : m_dwRef(0) { } HRESULT Initialize(LPCSTR pOptionName, LPCSTR pDescription, ArrayRef pArgNames, ArrayRef pArgDescriptions) { DXASSERT(pArgNames.size() == pArgDescriptions.size(), "else lookup tables are out of alignment"); m_pOptionName = pOptionName; @@ -404,10 +404,10 @@ class DxcOptimizerPass : public IDxcOptimizerPass { m_pArgDescriptions = pArgDescriptions; return S_OK; } - static HRESULT Create(LPCSTR pOptionName, LPCSTR pDescription, ArrayRef pArgNames, ArrayRef pArgDescriptions, IDxcOptimizerPass **ppResult) { + static HRESULT Create(IMalloc *pMalloc, LPCSTR pOptionName, LPCSTR pDescription, ArrayRef pArgNames, ArrayRef pArgDescriptions, IDxcOptimizerPass **ppResult) { CComPtr result; *ppResult = nullptr; - result = new (std::nothrow)DxcOptimizerPass(); + result = DxcOptimizerPass::Alloc(pMalloc); IFROOM(result); IFR(result->Initialize(pOptionName, pDescription, pArgNames, pArgDescriptions)); *ppResult = result.Detach(); @@ -441,17 +441,17 @@ class DxcOptimizerPass : public IDxcOptimizerPass { class DxcOptimizer : public IDxcOptimizer { private: - DXC_MICROCOM_REF_FIELD(m_dwRef) + DXC_MICROCOM_TM_REF_FIELDS() PassRegistry *m_registry; std::vector m_passes; public: - DXC_MICROCOM_ADDREF_RELEASE_IMPL(m_dwRef) + DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL() + DXC_MICROCOM_TM_CTOR(DxcOptimizer) HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) { return DoBasicQueryInterface(this, iid, ppvObject); } - DxcOptimizer() : m_dwRef(0) { } HRESULT Initialize(); const PassInfo *getPassByID(llvm::AnalysisID PassID); const PassInfo *getPassByName(const char *pName); @@ -519,7 +519,8 @@ HRESULT STDMETHODCALLTYPE DxcOptimizer::GetAvailablePass( if (index >= m_passes.size()) return E_INVALIDARG; return DxcOptimizerPass::Create( - m_passes[index]->getPassArgument(), m_passes[index]->getPassName(), + m_pMalloc, m_passes[index]->getPassArgument(), + m_passes[index]->getPassName(), GetPassArgNames(m_passes[index]->getPassArgument()), GetPassArgDescriptions(m_passes[index]->getPassArgument()), ppResult); } @@ -535,6 +536,8 @@ HRESULT STDMETHODCALLTYPE DxcOptimizer::RunOptimizer( if (optionCount > 0 && ppOptions == nullptr) return E_POINTER; + DxcThreadMalloc TM(m_pMalloc); + // Setup input buffer. // The ir parsing requires the buffer to be null terminated. We deal with // both source and bitcode input, so the input buffer may not be null @@ -559,12 +562,10 @@ HRESULT STDMETHODCALLTYPE DxcOptimizer::RunOptimizer( legacy::PassManagerBase *pPassManager = &ModulePasses; try { - CComPtr pMalloc; CComPtr pOutputStream; CComPtr pOutputBlob; - IFT(CoGetMalloc(1, &pMalloc)); - IFT(CreateMemoryStream(pMalloc, &pOutputStream)); + IFT(CreateMemoryStream(m_pMalloc, &pOutputStream)); IFT(pOutputStream.QueryInterface(&pOutputBlob)); raw_stream_ostream outStream(pOutputStream.p); @@ -745,7 +746,7 @@ HRESULT STDMETHODCALLTYPE DxcOptimizer::RunOptimizer( } if (ppOutputModule != nullptr) { CComPtr pProgramStream; - IFT(CreateMemoryStream(pMalloc, &pProgramStream)); + IFT(CreateMemoryStream(m_pMalloc, &pProgramStream)); { raw_stream_ostream outStream(pProgramStream.p); WriteBitcodeToFile(M.get(), outStream, true); @@ -759,7 +760,7 @@ HRESULT STDMETHODCALLTYPE DxcOptimizer::RunOptimizer( } HRESULT CreateDxcOptimizer(_In_ REFIID riid, _Out_ LPVOID *ppv) { - CComPtr result = new (std::nothrow) DxcOptimizer(); + CComPtr result = DxcOptimizer::Alloc(DxcGetThreadMallocNoRef()); if (result == nullptr) { *ppv = nullptr; return E_OUTOFMEMORY; diff --git a/lib/HLSL/DxilContainerAssembler.cpp b/lib/HLSL/DxilContainerAssembler.cpp index aa3ab43339..2ae7fd4c6f 100644 --- a/lib/HLSL/DxilContainerAssembler.cpp +++ b/lib/HLSL/DxilContainerAssembler.cpp @@ -854,9 +854,7 @@ void hlsl::SerializeDxilContainerForModule(DxilModule *pModule, [&](AbstractMemoryStream *pStream) { rootSigWriter.write(pStream); }); pModule->StripRootSignatureFromMetadata(); pInputProgramStream.Release(); - CComPtr pMalloc; - IFT(CoGetMalloc(1, &pMalloc)); - IFT(CreateMemoryStream(pMalloc, &pInputProgramStream)); + IFT(CreateMemoryStream(DxcGetThreadMallocNoRef(), &pInputProgramStream)); raw_stream_ostream outStream(pInputProgramStream.p); WriteBitcodeToFile(pModule->GetModule(), outStream, true); } @@ -877,9 +875,7 @@ void hlsl::SerializeDxilContainerForModule(DxilModule *pModule, llvm::StripDebugInfo(*pModule->GetModule()); pModule->StripDebugRelatedCode(); - CComPtr pMalloc; - IFT(CoGetMalloc(1, &pMalloc)); - IFT(CreateMemoryStream(pMalloc, &pProgramStream)); + IFT(CreateMemoryStream(DxcGetThreadMallocNoRef(), &pProgramStream)); raw_stream_ostream outStream(pProgramStream.p); WriteBitcodeToFile(pModule->GetModule(), outStream, true); diff --git a/lib/HLSL/DxilContainerReflection.cpp b/lib/HLSL/DxilContainerReflection.cpp index 20976ea7ff..371f7cbb2b 100644 --- a/lib/HLSL/DxilContainerReflection.cpp +++ b/lib/HLSL/DxilContainerReflection.cpp @@ -46,18 +46,18 @@ using namespace hlsl; class DxilContainerReflection : public IDxcContainerReflection { private: - DXC_MICROCOM_REF_FIELD(m_dwRef) + DXC_MICROCOM_TM_REF_FIELDS() CComPtr m_container; - const DxilContainerHeader *m_pHeader; - uint32_t m_headerLen; + const DxilContainerHeader *m_pHeader = nullptr; + uint32_t m_headerLen = 0; bool IsLoaded() const { return m_pHeader != nullptr; } public: - DXC_MICROCOM_ADDREF_RELEASE_IMPL(m_dwRef) + DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL() + DXC_MICROCOM_TM_CTOR(DxilContainerReflection) HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) { return DoBasicQueryInterface(this, iid, ppvObject); } - DxilContainerReflection() : m_dwRef(0), m_pHeader(nullptr), m_headerLen(0) { } __override HRESULT STDMETHODCALLTYPE Load(_In_ IDxcBlob *pContainer); __override HRESULT STDMETHODCALLTYPE GetPartCount(_Out_ UINT32 *pResult); __override HRESULT STDMETHODCALLTYPE GetPartKind(UINT32 idx, _Out_ UINT32 *pResult); @@ -70,11 +70,11 @@ class CShaderReflectionConstantBuffer; class CShaderReflectionType; class DxilShaderReflection : public ID3D12ShaderReflection { private: - DXC_MICROCOM_REF_FIELD(m_dwRef) + DXC_MICROCOM_TM_REF_FIELDS() CComPtr m_pContainer; LLVMContext Context; std::unique_ptr m_pModule; // Must come after LLVMContext, otherwise unique_ptr will over-delete. - DxilModule *m_pDxilModule; + DxilModule *m_pDxilModule = nullptr; std::vector m_CBs; std::vector m_Resources; std::vector m_InputSignature; @@ -103,7 +103,8 @@ class DxilShaderReflection : public ID3D12ShaderReflection { api = DxilShaderReflection::PublicAPI::D3D11_47; return api; } - DXC_MICROCOM_ADDREF_RELEASE_IMPL(m_dwRef) + DXC_MICROCOM_TM_ADDREF_RELEASE_IMPL() + DXC_MICROCOM_TM_CTOR(DxilShaderReflection) HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject) { HRESULT hr = DoBasicQueryInterface(this, iid, ppvObject); if (hr == E_NOINTERFACE) { @@ -119,7 +120,6 @@ class DxilShaderReflection : public ID3D12ShaderReflection { return hr; } - DxilShaderReflection() : m_dwRef(0), m_pDxilModule(nullptr) { } HRESULT Load(IDxcBlob *pBlob, const DxilPartHeader *pPart); // ID3D12ShaderReflection @@ -216,6 +216,7 @@ HRESULT DxilContainerReflection::GetPartContent(UINT32 idx, _COM_Outptr_ IDxcBlo const char *pData = GetDxilPartData(pPart); uint32_t offset = (uint32_t)(pData - (char*)m_container->GetBufferPointer()); // Offset from the beginning. uint32_t length = pPart->PartSize; + DxcThreadMalloc TM(m_pMalloc); return DxcCreateBlobFromBlob(m_container, offset, length, ppResult); } @@ -241,8 +242,9 @@ HRESULT DxilContainerReflection::GetPartReflection(UINT32 idx, REFIID iid, void return E_NOTIMPL; } + DxcThreadMalloc TM(m_pMalloc); HRESULT hr = S_OK; - CComPtr pReflection = new (std::nothrow)DxilShaderReflection(); + CComPtr pReflection = DxilShaderReflection::Alloc(m_pMalloc); IFCOOM(pReflection.p); DxilShaderReflection::PublicAPI api = DxilShaderReflection::IIDToAPI(iid); pReflection->SetPublicAPI(api); @@ -254,8 +256,9 @@ HRESULT DxilContainerReflection::GetPartReflection(UINT32 idx, REFIID iid, void } void hlsl::CreateDxcContainerReflection(IDxcContainerReflection **ppResult) { - CComPtr pReflection = new DxilContainerReflection(); + CComPtr pReflection = DxilContainerReflection::Alloc(DxcGetThreadMallocNoRef()); *ppResult = pReflection.Detach(); + if (*ppResult == nullptr) throw std::bad_alloc(); } /////////////////////////////////////////////////////////////////////////////// diff --git a/lib/HLSL/DxilGenerationPass.cpp b/lib/HLSL/DxilGenerationPass.cpp index f98746b80b..769fa7c181 100644 --- a/lib/HLSL/DxilGenerationPass.cpp +++ b/lib/HLSL/DxilGenerationPass.cpp @@ -103,6 +103,8 @@ void InitResource(const DxilResource *pSource, DxilResource *pDest) { } void InitDxilModuleFromHLModule(HLModule &H, DxilModule &M, DxilEntrySignature *pSig, bool HasDebugInfo) { + std::unique_ptr pSigPtr(pSig); + // Subsystems. unsigned ValMajor, ValMinor; H.GetValidatorVersion(ValMajor, ValMinor); @@ -158,7 +160,7 @@ void InitDxilModuleFromHLModule(HLModule &H, DxilModule &M, DxilEntrySignature * } // Signatures. - M.ResetEntrySignature(pSig); + M.ResetEntrySignature(pSigPtr.release()); M.ResetRootSignature(H.ReleaseRootSignature()); // Shader properties. diff --git a/lib/HLSL/DxilRootSignature.cpp b/lib/HLSL/DxilRootSignature.cpp index efa7662079..88f4e8a705 100644 --- a/lib/HLSL/DxilRootSignature.cpp +++ b/lib/HLSL/DxilRootSignature.cpp @@ -95,7 +95,9 @@ void RootSignatureHandle::Deserialize() { void RootSignatureHandle::LoadSerialized(const uint8_t *pData, unsigned length) { DXASSERT_NOMSG(IsEmpty()); - IFT(DxcCreateBlobOnHeapCopy(pData, length, &m_pSerialized)); + IDxcBlobEncoding *pCreated; + IFT(DxcCreateBlobWithEncodingOnHeapCopy(pData, length, CP_UTF8, &pCreated)); + m_pSerialized = pCreated; } ////////////////////////////////////////////////////////////////////////////// @@ -1345,11 +1347,11 @@ void SerializeRootSignatureTemplate(_In_ const T_ROOT_SIGNATURE_DESC* pRootSigna memcpy(pSS, pRS->pStaticSamplers, StaticSamplerSize); // Create the result blob. - CComHeapPtr bytes; + CDxcMallocHeapPtr bytes(DxcGetThreadMallocNoRef()); CComPtr pBlob; unsigned cb = Serializer.GetSize(); DXASSERT_NOMSG((cb & 0x3) == 0); - IFTBOOL(bytes.AllocateBytes(cb), E_OUTOFMEMORY); + IFTBOOL(bytes.Allocate(cb), E_OUTOFMEMORY); IFT(Serializer.Compact(bytes.m_pData, cb)); IFT(DxcCreateBlobOnHeap(bytes.m_pData, cb, ppBlob)); bytes.Detach(); // Ownership transfered to ppBlob. diff --git a/lib/HLSL/DxilValidation.cpp b/lib/HLSL/DxilValidation.cpp index ab3b85d526..1a98a7a54d 100644 --- a/lib/HLSL/DxilValidation.cpp +++ b/lib/HLSL/DxilValidation.cpp @@ -4189,10 +4189,8 @@ static void VerifyBlobPartMatches(_In_ ValidationContext &ValCtx, return; } - CComPtr pMalloc; - IFT(CoGetMalloc(1, &pMalloc)); CComPtr pOutputStream; - IFT(CreateMemoryStream(pMalloc, &pOutputStream)); + IFT(CreateMemoryStream(DxcGetThreadMallocNoRef(), &pOutputStream)); pOutputStream->Reserve(Size); pWriter->write(pOutputStream); @@ -4504,10 +4502,8 @@ HRESULT ValidateDxilBitcode( if (!dxilModule.GetRootSignature().IsEmpty()) { unique_ptr pWriter(NewPSVWriter(dxilModule, 0)); DXASSERT_NOMSG(pWriter->size()); - CComPtr pMalloc; - IFT(CoGetMalloc(1, &pMalloc)); CComPtr pOutputStream; - IFT(CreateMemoryStream(pMalloc, &pOutputStream)); + IFT(CreateMemoryStream(DxcGetThreadMallocNoRef(), &pOutputStream)); pOutputStream->Reserve(pWriter->size()); pWriter->write(pOutputStream); const DxilVersionedRootSignatureDesc* pDesc = dxilModule.GetRootSignature().GetDesc(); diff --git a/lib/IR/DiagnosticInfo.cpp b/lib/IR/DiagnosticInfo.cpp index b8f77eda15..97305a5268 100644 --- a/lib/IR/DiagnosticInfo.cpp +++ b/lib/IR/DiagnosticInfo.cpp @@ -52,6 +52,8 @@ struct PassRemarksOpt { }; }; +#if 0 +// These should all be specific to a pipline, not global to the process. static PassRemarksOpt PassRemarksOptLoc; static PassRemarksOpt PassRemarksMissedOptLoc; static PassRemarksOpt PassRemarksAnalysisOptLoc; @@ -85,6 +87,21 @@ PassRemarksAnalysis( cl::Hidden, cl::location(PassRemarksAnalysisOptLoc), cl::ValueRequired, cl::ZeroOrMore); } +#else +struct PassRemarksOptNull { + Regex *Pattern = nullptr; + void operator=(const std::string &Val) { + } +}; +static PassRemarksOptNull PassRemarksOptLoc; +static PassRemarksOptNull PassRemarksMissedOptLoc; +static PassRemarksOptNull PassRemarksAnalysisOptLoc; + +static PassRemarksOptNull PassRemarks; +static PassRemarksOptNull PassRemarksMissed; +static PassRemarksOptNull PassRemarksAnalysis; +} +#endif int llvm::getNextAvailablePluginDiagnosticKind() { static std::atomic PluginKindID(DK_FirstPluginKind); diff --git a/lib/IR/Dominators.cpp b/lib/IR/Dominators.cpp index b6a8bbcbe5..d6930a7674 100644 --- a/lib/IR/Dominators.cpp +++ b/lib/IR/Dominators.cpp @@ -35,9 +35,11 @@ static bool VerifyDomInfo = true; #else static bool VerifyDomInfo = false; #endif +#if 0 // HLSL Change Starts - option pending static cl::opt VerifyDomInfoX("verify-dom-info", cl::location(VerifyDomInfo), cl::desc("Verify dominator info (time consuming)")); +#endif // HLSL Change Ends bool BasicBlockEdge::isSingleEdge() const { const TerminatorInst *TI = Start->getTerminator(); diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp index 75598b7b18..1407aeb556 100644 --- a/lib/IR/Function.cpp +++ b/lib/IR/Function.cpp @@ -383,26 +383,39 @@ static StringPool *GCNamePool; static ManagedStatic > GCLock; bool Function::hasGC() const { +#if 0 // HLSL Change sys::SmartScopedReader Reader(*GCLock); return GCNames && GCNames->count(this); +#else + return false; +#endif // HLSL Change Ends } const char *Function::getGC() const { +#if 0 // HLSL Change assert(hasGC() && "Function has no collector"); sys::SmartScopedReader Reader(*GCLock); return *(*GCNames)[this]; +#else + return nullptr; +#endif // HLSL Change Ends } void Function::setGC(const char *Str) { +#if 0 // HLSL Change Starts sys::SmartScopedWriter Writer(*GCLock); if (!GCNamePool) GCNamePool = new StringPool(); if (!GCNames) GCNames = new DenseMap(); (*GCNames)[this] = GCNamePool->intern(Str); +#else + assert(false && "GC not supported"); +#endif // HLSL Change Ends } void Function::clearGC() { +#if 0 // HLSL Change Starts sys::SmartScopedWriter Writer(*GCLock); if (GCNames) { GCNames->erase(this); @@ -415,6 +428,7 @@ void Function::clearGC() { } } } +#endif // HLSL Change Ends } /// copyAttributesFrom - copy all additional attributes (those not needed to diff --git a/lib/IR/LLVMContextImpl.cpp b/lib/IR/LLVMContextImpl.cpp index 1e2080770f..0ef4ff9154 100644 --- a/lib/IR/LLVMContextImpl.cpp +++ b/lib/IR/LLVMContextImpl.cpp @@ -85,9 +85,9 @@ LLVMContextImpl::~LLVMContextImpl() { // Also drop references that come from the Value bridges. for (auto &Pair : ValuesAsMetadata) - Pair.second->dropUsers(); + if (Pair.second) Pair.second->dropUsers(); // HLSL Change - if alloc failed, entry might not be populated for (auto &Pair : MetadataAsValues) - Pair.second->dropUse(); + if (Pair.second) Pair.second->dropUse(); // HLSL Change - if alloc failed, entry might not be populated // Destroy MDNodes. for (MDNode *I : DistinctMDNodes) diff --git a/lib/IR/LegacyPassManager.cpp b/lib/IR/LegacyPassManager.cpp index 638115dd84..e0638c7594 100644 --- a/lib/IR/LegacyPassManager.cpp +++ b/lib/IR/LegacyPassManager.cpp @@ -46,6 +46,7 @@ enum PassDebugLevel { }; } +#if 0 // HLSL Change Starts - option pending static cl::opt PassDebugging("debug-pass", cl::Hidden, cl::desc("Print PassManager debugging information"), @@ -56,12 +57,16 @@ PassDebugging("debug-pass", cl::Hidden, clEnumVal(Executions, "print pass name before it is executed"), clEnumVal(Details , "print pass details when it is executed"), clEnumValEnd)); +#else +static const PassDebugLevel PassDebugging = PassDebugLevel::Disabled; +#endif // HLSL Change Ends namespace { typedef llvm::cl::list PassOptionList; } +#if 0 // HLSL Change Starts - option pending // Print IR out before/after specified passes. static PassOptionList PrintBefore("print-before", @@ -81,6 +86,10 @@ static cl::opt PrintAfterAll("print-after-all", llvm::cl::desc("Print IR after each pass"), cl::init(false)); +#else +static const bool PrintBeforeAll = false; +static const bool PrintAfterAll = false; +#endif // HLSL Change Ends /// This is a helper to determine whether to print IR before or /// after a pass. @@ -99,13 +108,13 @@ static bool ShouldPrintBeforeOrAfterPass(const PassInfo *PI, /// This is a utility to check whether a pass should have IR dumped /// before it. static bool ShouldPrintBeforePass(const PassInfo *PI) { - return PrintBeforeAll || ShouldPrintBeforeOrAfterPass(PI, PrintBefore); + return false; // HLSL Change - return PrintBeforeAll || ShouldPrintBeforeOrAfterPass(PI, PrintBefore); } /// This is a utility to check whether a pass should have IR dumped /// after it. static bool ShouldPrintAfterPass(const PassInfo *PI) { - return PrintAfterAll || ShouldPrintBeforeOrAfterPass(PI, PrintAfter); + return false; // HLSL Change -PrintAfterAll || ShouldPrintBeforeOrAfterPass(PI, PrintAfter); } /// isPassDebuggingExecutionsOrMore - Return true if -debug-pass=Executions @@ -573,8 +582,10 @@ AnalysisUsage *PMTopLevelManager::findAnalysisUsage(Pass *P) { AnUsage = DMI->second; else { AnUsage = new AnalysisUsage(); + std::unique_ptr AnUsagePtr(AnUsage); // HLSL Change - unique_ptr until added P->getAnalysisUsage(*AnUsage); AnUsageMap[P] = AnUsage; + AnUsagePtr.release(); // HLSL Change } return AnUsage; } @@ -587,6 +598,8 @@ void PMTopLevelManager::schedulePass(Pass *P) { // TODO : Allocate function manager for this pass, other wise required set // may be inserted into previous function manager + std::unique_ptr PPtr(P); // take ownership locally until we pass it on + // Give pass a chance to prepare the stage. P->preparePassManager(activeStack); @@ -595,7 +608,7 @@ void PMTopLevelManager::schedulePass(Pass *P) { // available at this point. const PassInfo *PI = findAnalysisPassInfo(P->getPassID()); if (PI && PI->isAnalysis() && findAnalysisPass(P->getPassID())) { - delete P; + // delete P; // HLSL Change - let PPtr take care of this return; } @@ -658,9 +671,10 @@ void PMTopLevelManager::schedulePass(Pass *P) { // top level manager. Set up analysis resolver to connect them. PMDataManager *DM = getAsPMDataManager(); AnalysisResolver *AR = new AnalysisResolver(*DM); - P->setResolver(AR); + P->setResolver(AR); // HLSL Comment - P takes ownership of AR here DM->initializeAnalysisImpl(P); addImmutablePass(IP); + PPtr.release(); // HLSL Change DM->recordAvailableAnalysis(IP); return; } @@ -672,6 +686,7 @@ void PMTopLevelManager::schedulePass(Pass *P) { } // Add the requested pass to the best available pass manager. + PPtr.release(); // HLSL Change - assignPassManager takes ownership P->assignPassManager(activeStack, getTopLevelPassManagerType()); if (PI && !PI->isAnalysis() && ShouldPrintAfterPass(PI)) { @@ -971,10 +986,11 @@ void PMDataManager::freePass(Pass *P, StringRef Msg, /// Add pass P into the PassVector. Update /// AvailableAnalysis appropriately if ProcessAnalysis is true. void PMDataManager::add(Pass *P, bool ProcessAnalysis) { + std::unique_ptr PPtr(P); // HLSL Change - take ownership of P // This manager is going to manage pass P. Set up analysis resolver // to connect them. AnalysisResolver *AR = new AnalysisResolver(*this); - P->setResolver(AR); + P->setResolver(AR); // HLSL Note: setResolver takes onwership of AR // If a FunctionPass F is the last user of ModulePass info M // then the F's manager, not F, records itself as a last user of M. @@ -983,6 +999,7 @@ void PMDataManager::add(Pass *P, bool ProcessAnalysis) { if (!ProcessAnalysis) { // Add pass PassVector.push_back(P); + PPtr.release(); // HLSL Change return; } @@ -1044,6 +1061,7 @@ void PMDataManager::add(Pass *P, bool ProcessAnalysis) { // Add pass PassVector.push_back(P); + PPtr.release(); // HLSL Change } @@ -1370,7 +1388,11 @@ FunctionPassManager::FunctionPassManager(Module *m) : M(m) { // FPM is the top level manager. FPM->setTopLevelManager(FPM); - AnalysisResolver *AR = new AnalysisResolver(*FPM); + AnalysisResolver *AR = new (std::nothrow)AnalysisResolver(*FPM); // HLSL Change: nothrow and recover + if (!AR) { + delete FPM; + throw std::bad_alloc(); + } FPM->setResolver(AR); } @@ -1380,10 +1402,12 @@ FunctionPassManager::~FunctionPassManager() { void FunctionPassManager::add(Pass *P) { // HLSL Change Starts + std::unique_ptr PPtr(P); // take ownership of P, even on failure paths if (TrackPassOS) { P->dumpConfig(*TrackPassOS); (*TrackPassOS) << '\n'; } + PPtr.release(); // HLSL Change Ends FPM->add(P); } @@ -1726,10 +1750,12 @@ PassManager::~PassManager() { void PassManager::add(Pass *P) { // HLSL Change Starts + std::unique_ptr PPtr(P); // take ownership of P, even on failure paths if (TrackPassOS) { P->dumpConfig(*TrackPassOS); (*TrackPassOS) << '\n'; } + PPtr.release(); // HLSL Change Ends PM->add(P); } @@ -1744,9 +1770,11 @@ bool PassManager::run(Module &M) { // TimingInfo implementation bool llvm::TimePassesIsEnabled = false; +#if 0 // HLSL Change Starts - option pending static cl::opt EnableTiming("time-passes", cl::location(TimePassesIsEnabled), cl::desc("Time each pass, printing elapsed time for each on exit")); +#endif // createTheTimeInfo - This method either initializes the TheTimeInfo pointer to // a non-null value (if the -time-passes option is enabled) or it leaves it @@ -1836,6 +1864,7 @@ void ModulePass::assignPassManager(PMStack &PMS, /// in the PM Stack and add self into that manager. void FunctionPass::assignPassManager(PMStack &PMS, PassManagerType PreferredType) { + std::unique_ptr thisPtr(this); // HLSL Change // Find Function Pass Manager while (!PMS.empty()) { @@ -1870,6 +1899,7 @@ void FunctionPass::assignPassManager(PMStack &PMS, } // Assign FPP as the manager of this pass. + thisPtr.release(); FPP->add(this); } diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp index 1abcf0d18c..adefaa2cea 100644 --- a/lib/IR/Metadata.cpp +++ b/lib/IR/Metadata.cpp @@ -134,7 +134,7 @@ void ReplaceableMetadataImpl::addRef(void *Ref, OwnerTy Owner) { void ReplaceableMetadataImpl::dropRef(void *Ref) { bool WasErased = UseMap.erase(Ref); (void)WasErased; - assert(WasErased && "Expected to drop a reference"); + // assert(WasErased && "Expected to drop a reference"); // HLSL Change - not while cleaning up OOM } void ReplaceableMetadataImpl::moveRef(void *Ref, void *New, @@ -283,12 +283,12 @@ void ValueAsMetadata::handleDeletion(Value *V) { // Remove old entry from the map. ValueAsMetadata *MD = I->second; - assert(MD && "Expected valid metadata"); - assert(MD->getValue() == V && "Expected valid mapping"); + // assert(MD && "Expected valid metadata"); // HLSL Change - MD might be nullptr under OOM + // assert(MD->getValue() == V && "Expected valid mapping"); // HLSL Change - MD might be nullptr under OOM Store.erase(I); // Delete the metadata. - MD->replaceAllUsesWith(nullptr); + if (MD) MD->replaceAllUsesWith(nullptr); // HLSL Change - MD might be nullptr under OOM delete MD; } @@ -710,8 +710,16 @@ MDTuple *MDTuple::getImpl(LLVMContext &Context, ArrayRef MDs, assert(ShouldCreate && "Expected non-uniqued nodes to always be created"); } - return storeImpl(new (MDs.size()) MDTuple(Context, Storage, Hash, MDs), - Storage, Context.pImpl->MDTuples); + // HLSL Change - guard with try/catch + MDTuple *MDTuplePtr(new (MDs.size()) MDTuple(Context, Storage, Hash, MDs)); + MDTuple *Result; + try { + Result = storeImpl(MDTuplePtr, Storage, Context.pImpl->MDTuples); + } catch (...) { + MDTuplePtr->deleteAsSubclass(); + throw; + } + return Result; } void MDNode::deleteTemporary(MDNode *N) { diff --git a/lib/IR/Module.cpp b/lib/IR/Module.cpp index 20f7fdeb3d..6404657f2f 100644 --- a/lib/IR/Module.cpp +++ b/lib/IR/Module.cpp @@ -47,9 +47,12 @@ template class llvm::SymbolTableListTraits; Module::Module(StringRef MID, LLVMContext &C) : Context(C), Materializer(), ModuleID(MID), DL("") { - ValSymTab = new ValueSymbolTable(); - NamedMDSymTab = new StringMap(); + // HLSL Change - use unique_ptr to avoid leaks + std::unique_ptr ValSymTabPtr(new ValueSymbolTable()); + std::unique_ptr > NamedMDSymTabPtr(new StringMap()); Context.addModule(this); + ValSymTab = ValSymTabPtr.release(); + NamedMDSymTab = NamedMDSymTabPtr.release(); } Module::~Module() { diff --git a/lib/IR/User.cpp b/lib/IR/User.cpp index 522722d701..6c54cef3ee 100644 --- a/lib/IR/User.cpp +++ b/lib/IR/User.cpp @@ -136,6 +136,15 @@ void User::operator delete(void *Usr) { } } +// HLSL Change Starts +void User::operator delete(void *Usr, unsigned NumUserOperands) { + // Fun fact: during construction Obj->NumUserOperands is overwritten + Use *Storage = static_cast(Usr) - NumUserOperands; + Use::zap(Storage, Storage + NumUserOperands, /* Delete */ false); + ::operator delete(Storage); +} +// HLSL Change Ends + //===----------------------------------------------------------------------===// // Operator Class //===----------------------------------------------------------------------===// diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp index a4e34ef39e..cef4c9a169 100644 --- a/lib/IR/Value.cpp +++ b/lib/IR/Value.cpp @@ -181,8 +181,8 @@ void Value::setValueName(ValueName *VN) { return; } - HasName = true; Ctx.pImpl->ValueNames[this] = VN; + HasName = true; // HLSL Change - only set this to true after assignment } StringRef Value::getName() const { @@ -608,9 +608,9 @@ void ValueHandleBase::AddToUseList() { } void ValueHandleBase::RemoveFromUseList() { - assert(V && V->HasValueHandle && + assert(V && (std::current_exception() == nullptr || V->HasValueHandle) && // HLSL Change "Pointer doesn't have a use list!"); - + if (!V->HasValueHandle) return; // HLSL Change // Unlink this from its use list. ValueHandleBase **PrevPtr = getPrevPtr(); assert(*PrevPtr == this && "List invariant broken"); diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 2a0a4ff393..f0869d9045 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -78,7 +78,11 @@ #include using namespace llvm; +#if 0 // HLSL Change Starts - option pending static cl::opt VerifyDebugInfo("verify-debug-info", cl::init(true)); +#else +static const bool VerifyDebugInfo = true; +#endif // HLSL Change Ends namespace { struct VerifierSupport { diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp index c7d1d6ed08..2cad45b766 100644 --- a/lib/Support/CommandLine.cpp +++ b/lib/Support/CommandLine.cpp @@ -234,7 +234,7 @@ void Option::setArgStr(const char *S) { } // Initialise the general option category. -OptionCategory llvm::cl::GeneralCategory("General options"); +OptionCategory *llvm::cl::GeneralCategory; // HLSL Change - GeneralCategory is now a pointer void OptionCategory::registerCategory() { GlobalParser->registerCategory(this); @@ -817,7 +817,7 @@ void cl::ParseCommandLineOptions(int argc, const char *const *argv, void CommandLineParser::ParseCommandLineOptions(int argc, const char *const *argv, const char *Overview) { - assert(hasOptions() && "No options specified!"); + // assert(hasOptions() && "No options specified!"); // HLSL Change - it's valid to have no options for the DLL build // Expand response files. SmallVector newArgv(argv, argv + argc); @@ -1657,6 +1657,8 @@ static HelpPrinterWrapper WrappedNormalPrinter(UncategorizedNormalPrinter, static HelpPrinterWrapper WrappedHiddenPrinter(UncategorizedHiddenPrinter, CategorizedHiddenPrinter); +#if 0 // HLSL Change Starts + // Define a category for generic options that all tools should have. static cl::OptionCategory GenericCategory("Generic Options"); @@ -1713,6 +1715,13 @@ void HelpPrinterWrapper::operator=(bool Value) { } else UncategorizedPrinter = true; // Invoke uncategorized printer } +#else +static const bool PrintOptions = false; +static const bool PrintAllOptions = false; + +void HelpPrinterWrapper::operator=(bool Value) { +} +#endif // HLSL Change Ends // Print the value of each option. void cl::PrintOptionValues() { GlobalParser->printOptionValues(); } @@ -1795,10 +1804,14 @@ class VersionPrinter { // Define the --version option that prints out the LLVM version for the tool static VersionPrinter VersionPrinterInstance; +#if 0 // HLSL Change Starts static cl::opt> VersOp("version", cl::desc("Display the version of this program"), cl::location(VersionPrinterInstance), cl::ValueDisallowed, cl::cat(GenericCategory)); +#else +static const OptionCategory *GenericCategory; +#endif // HLSL Change Ends // Utility function for printing the help message. void cl::PrintHelpMessage(bool Hidden, bool Categorized) { @@ -1838,7 +1851,7 @@ StringMap