Jelajahi Sumber

[linux-port] FileSystem and IO. (#1374)

Some interactions with the FileSystem are not used by any API and are
therefore not implemented for Unix at the moment. We have put assertions in
place to make it easy to spot if any of those methods are ever used.
Ehsan 7 tahun lalu
induk
melakukan
f8f0bfcf0b

+ 4 - 0
include/dxc/Support/WinAdapter.h

@@ -41,6 +41,9 @@
 #define C_ASSERT(expr) static_assert((expr), "")
 #define ATLASSERT assert
 
+#define CoTaskMemAlloc malloc
+#define CoTaskMemFree free
+
 #define ARRAYSIZE(array) (sizeof(array) / sizeof(array[0]))
 
 #define _countof(a) (sizeof(a) / sizeof(*(a)))
@@ -101,6 +104,7 @@
 #define ERROR_FILE_NOT_FOUND ENOENT
 #define ERROR_IO_DEVICE EIO
 #define ERROR_INVALID_HANDLE EBADF
+#define ERROR_ARITHMETIC_OVERFLOW EOVERFLOW
 
 // Used by HRESULT <--> WIN32 error code conversion
 #define SEVERITY_ERROR 1

+ 1 - 0
include/dxc/Support/WinFunctions.h

@@ -22,6 +22,7 @@
 HRESULT StringCchPrintfA(char *dst, size_t dstSize, const char *format, ...);
 HRESULT UIntAdd(UINT uAugend, UINT uAddend, UINT *puResult);
 HRESULT IntToUInt(int in, UINT *out);
+HRESULT SizeTToInt(size_t in, INT *out);
 HRESULT UInt32Mult(UINT a, UINT b, UINT *out);
 int _stricmp(const char *str1, const char *str2);
 HRESULT CoGetMalloc(DWORD dwMemContext, IMalloc **ppMalloc);

+ 9 - 1
lib/DxcSupport/FileIOHelper.cpp

@@ -14,14 +14,19 @@
 #include "dxc/Support/microcom.h"
 #include "dxc/Support/Unicode.h"
 #include "dxc/Support/FileIOHelper.h"
+#include "dxc/Support/WinFunctions.h"
 #include "dxc/dxcapi.h"
 
 #include <algorithm>
 #include <memory>
+
+#ifdef _WIN32
 #include <intsafe.h>
+#endif
 
 #define CP_UTF16 1200
 
+#ifdef _WIN32
 struct HeapMalloc : public IMalloc {
 public:
   ULONG STDMETHODCALLTYPE AddRef() {
@@ -75,6 +80,9 @@ public:
   {
   }
 };
+#else
+typedef IMalloc HeapMalloc;
+#endif
 
 static HeapMalloc g_HeapMalloc;
 
@@ -311,9 +319,9 @@ static HRESULT CodePageBufferToUtf16(UINT32 codePage, LPCVOID bufferPointer,
   int numActuallyConvertedUTF16 =
       MultiByteToWideChar(codePage, MB_ERR_INVALID_CHARS, (LPCSTR)bufferPointer,
                           bufferSize, utf16NewCopy, buffSizeUTF16);
+
   if (numActuallyConvertedUTF16 == 0)
     return HRESULT_FROM_WIN32(GetLastError());
-
   ((LPWSTR)utf16NewCopy)[numActuallyConvertedUTF16] = L'\0';
   *pConvertedCharCount = numActuallyConvertedUTF16;
 

+ 15 - 3
lib/DxcSupport/WinFunctions.cpp

@@ -40,7 +40,7 @@ HRESULT UIntAdd(UINT uAugend, UINT uAddend, UINT *puResult) {
     hr = S_OK;
   } else {
     *puResult = 0xffffffff;
-    hr = (HRESULT)1L;
+    hr = ERROR_ARITHMETIC_OVERFLOW;
   }
   return hr;
 }
@@ -51,14 +51,26 @@ HRESULT IntToUInt(int in, UINT *out) {
     hr = S_OK;
   } else {
     *out = 0xffffffff;
-    hr = (HRESULT)1L;
+    hr = ERROR_ARITHMETIC_OVERFLOW;
+  }
+  return hr;
+}
+HRESULT SizeTToInt(size_t in, int *out) {
+  HRESULT hr;
+  if(in <= INT_MAX) {
+    *out = (int)in;
+    hr = S_OK;
+  }
+  else {
+    *out = 0xffffffff;
+    hr = ERROR_ARITHMETIC_OVERFLOW;
   }
   return hr;
 }
 HRESULT UInt32Mult(UINT a, UINT b, UINT *out) {
   uint64_t result = (uint64_t)a * (uint64_t)b;
   if (result > uint64_t(UINT_MAX))
-    return (HRESULT)1L;
+    return ERROR_ARITHMETIC_OVERFLOW;
 
   *out = (uint32_t)result;
   return S_OK;

+ 178 - 0
lib/MSSupport/MSFileSystemImpl.cpp

@@ -93,101 +93,178 @@ public:
 
 MSFileSystemForDisk::MSFileSystemForDisk()
 {
+  #ifdef _WIN32
   _defaultAttributes = GetConsoleOutputTextAttributes();
+  #endif
 }
 
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::FindNextFileW(HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData) throw()
 {
+  #ifdef _WIN32
   return ::FindNextFileW(hFindFile, lpFindFileData);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 
 _Use_decl_annotations_
 HANDLE MSFileSystemForDisk::FindFirstFileW(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData) throw()
 {
+  #ifdef _WIN32
   return ::FindFirstFileW(lpFileName, lpFindFileData);
+  #else
+  assert(false && "Not implemented for Unix");
+  return nullptr;
+  #endif
 }
 
 void MSFileSystemForDisk::FindClose(HANDLE findHandle) throw()
 {
+  #ifdef _WIN32
   ::FindClose(findHandle);
+  #else
+  assert(false && "Not implemented for Unix");
+  #endif
 }
 
 _Use_decl_annotations_
 HANDLE MSFileSystemForDisk::CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes) throw()
 {
+  #ifdef _WIN32
   return ::CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, nullptr, dwCreationDisposition, dwFlagsAndAttributes, nullptr);
+  #else
+  assert(false && "Not implemented for Unix");
+  return nullptr;
+  #endif
 }
 
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::SetFileTime(HANDLE hFile, _In_opt_ const FILETIME *lpCreationTime, _In_opt_ const FILETIME *lpLastAccessTime, _In_opt_ const FILETIME *lpLastWriteTime) throw()
 {
+  #ifdef _WIN32
   return ::SetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::GetFileInformationByHandle(HANDLE hFile, LPBY_HANDLE_FILE_INFORMATION lpFileInformation) throw()
 {
+  #ifdef _WIN32
   return ::GetFileInformationByHandle(hFile, lpFileInformation);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 
 _Use_decl_annotations_
 DWORD MSFileSystemForDisk::GetFileType(HANDLE hFile) throw()
 {
+  #ifdef _WIN32
   return ::GetFileType(hFile);
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::CreateHardLinkW(LPCWSTR lpFileName, LPCWSTR lpExistingFileName) throw()
 {
+  #ifdef _WIN32
   return ::CreateHardLinkW(lpFileName, lpExistingFileName, nullptr);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::MoveFileExW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlags) throw()
 {
+  #ifdef _WIN32
   return ::MoveFileExW(lpExistingFileName, lpNewFileName, dwFlags);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 
 _Use_decl_annotations_
 DWORD MSFileSystemForDisk::GetFileAttributesW(LPCWSTR lpFileName) throw()
 {
+  #ifdef _WIN32
   return ::GetFileAttributesW(lpFileName);
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::CloseHandle(HANDLE hObject) throw()
 {
+  #ifdef _WIN32
   return ::CloseHandle(hObject);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::DeleteFileW(LPCWSTR lpFileName) throw()
 {
+  #ifdef _WIN32
   return ::DeleteFileW(lpFileName);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::RemoveDirectoryW(LPCWSTR lpFileName) throw()
 {
+  #ifdef _WIN32
   return ::RemoveDirectoryW(lpFileName);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::CreateDirectoryW(LPCWSTR lpPathName) throw()
 {
+  #ifdef _WIN32
   return ::CreateDirectoryW(lpPathName, nullptr);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 
 _Use_decl_annotations_
 DWORD MSFileSystemForDisk::GetCurrentDirectoryW(DWORD nBufferLength,  LPWSTR lpBuffer) throw()
 {
+  #ifdef _WIN32
   return ::GetCurrentDirectoryW(nBufferLength, lpBuffer);
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 
 _Use_decl_annotations_
 DWORD MSFileSystemForDisk::GetMainModuleFileNameW(LPWSTR lpFilename, DWORD nSize) throw()
 {
+  #ifdef _WIN32
   // Add some code to ensure that the result is null terminated.
   if (nSize <= 1)
   {
@@ -199,14 +276,24 @@ DWORD MSFileSystemForDisk::GetMainModuleFileNameW(LPWSTR lpFilename, DWORD nSize
   if (result == 0) return result;
   lpFilename[result] = L'\0';
   return result;
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 
 _Use_decl_annotations_
 DWORD MSFileSystemForDisk::GetTempPathW(DWORD nBufferLength, LPWSTR lpBuffer) throw()
 {
+  #ifdef _WIN32
   return ::GetTempPathW(nBufferLength, lpBuffer);
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 
+#ifdef _WIN32
 namespace {
   typedef BOOLEAN(WINAPI *PtrCreateSymbolicLinkW)(
     /*__in*/ LPCWSTR lpSymlinkFileName,
@@ -217,103 +304,181 @@ namespace {
     PtrCreateSymbolicLinkW(::GetProcAddress(
     ::GetModuleHandleW(L"Kernel32.dll"), "CreateSymbolicLinkW"));
 }
+#endif
 
 _Use_decl_annotations_
 BOOLEAN MSFileSystemForDisk::CreateSymbolicLinkW(LPCWSTR lpSymlinkFileName, LPCWSTR lpTargetFileName, DWORD dwFlags) throw()
 {
+  #ifdef _WIN32
   return create_symbolic_link_api(lpSymlinkFileName, lpTargetFileName, dwFlags);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 
 bool MSFileSystemForDisk::SupportsCreateSymbolicLink() throw()
 {
+  #ifdef _WIN32
   return create_symbolic_link_api != nullptr;
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, _Out_opt_ LPDWORD lpNumberOfBytesRead) throw()
 {
+  #ifdef _WIN32
   return ::ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, nullptr);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 
 _Use_decl_annotations_
 HANDLE MSFileSystemForDisk::CreateFileMappingW(HANDLE hFile, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow) throw()
 {
+  #ifdef _WIN32
   return ::CreateFileMappingW(hFile, nullptr, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, nullptr);
+  #else
+  assert(false && "Not implemented for Unix");
+  return nullptr;
+  #endif
 }
 
 _Use_decl_annotations_
 LPVOID MSFileSystemForDisk::MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap) throw()
 {
+  #ifdef _WIN32
   return ::MapViewOfFile(hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap);
+  #else
+  assert(false && "Not implemented for Unix");
+  return nullptr;
+  #endif
 }
 
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::UnmapViewOfFile(LPCVOID lpBaseAddress) throw()
 {
+  #ifdef _WIN32
   return ::UnmapViewOfFile(lpBaseAddress);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 
 bool MSFileSystemForDisk::FileDescriptorIsDisplayed(int fd) throw()
 {
+  #ifdef _WIN32
   DWORD Mode;  // Unused
   return (GetConsoleMode((HANDLE)_get_osfhandle(fd), &Mode) != 0);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 
 unsigned MSFileSystemForDisk::GetColumnCount(DWORD nStdHandle) throw()
 {
+  #ifdef _WIN32
   unsigned Columns = 0;
   CONSOLE_SCREEN_BUFFER_INFO csbi;
   if (::GetConsoleScreenBufferInfo(GetStdHandle(nStdHandle), &csbi))
     Columns = csbi.dwSize.X;
   return Columns;
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 
 unsigned MSFileSystemForDisk::GetConsoleOutputTextAttributes() throw()
 {
+  #ifdef _WIN32
   CONSOLE_SCREEN_BUFFER_INFO csbi;
   if (::GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
     return csbi.wAttributes;
   return 0;
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 
 void MSFileSystemForDisk::SetConsoleOutputTextAttributes(unsigned attributes) throw()
 {
+  #ifdef _WIN32
   ::SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), attributes);
+  #else
+  assert(false && "Not implemented for Unix");
+  #endif
 }
 
 void MSFileSystemForDisk::ResetConsoleOutputTextAttributes() throw()
 {
+  #ifdef _WIN32
   ::SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), _defaultAttributes);
+  #else
+  assert(false && "Not implemented for Unix");
+  #endif
 }
 
 int MSFileSystemForDisk::open_osfhandle(intptr_t osfhandle, int flags) throw()
 {
+  #ifdef _WIN32
   return ::_open_osfhandle(osfhandle, flags);
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 
 intptr_t MSFileSystemForDisk::get_osfhandle(int fd) throw()
 {
+  #ifdef _WIN32
   return ::_get_osfhandle(fd);
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 
 int MSFileSystemForDisk::close(int fd) throw()
 {
+  #ifdef _WIN32
   return ::_close(fd);
+  #else
+  return ::close(fd);
+  #endif
 }
 
 long MSFileSystemForDisk::lseek(int fd, long offset, int origin) throw()
 {
+  #ifdef _WIN32
   return ::_lseek(fd, offset, origin);
+  #else
+  return ::lseek(fd, offset, origin);
+  #endif
 }
 
 int MSFileSystemForDisk::setmode(int fd, int mode) throw()
 {
+  #ifdef _WIN32
   return ::_setmode(fd, mode);
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 
 _Use_decl_annotations_
 errno_t MSFileSystemForDisk::resize_file(LPCWSTR path, uint64_t size) throw()
 {
+  #ifdef _WIN32
   int fd = ::_wopen(path, O_BINARY | _O_RDWR, S_IWRITE);
   if (fd == -1)
     return errno;
@@ -324,18 +489,31 @@ errno_t MSFileSystemForDisk::resize_file(LPCWSTR path, uint64_t size) throw()
 #endif
   ::_close(fd);
   return error;
+
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 
 _Use_decl_annotations_
 int MSFileSystemForDisk::Read(int fd, void* buffer, unsigned int count) throw()
 {
+  #ifdef _WIN32
   return ::_read(fd, buffer, count);
+  #else
+  return ::read(fd, buffer, count);
+  #endif
 }
 
 _Use_decl_annotations_
 int MSFileSystemForDisk::Write(int fd, const void* buffer, unsigned int count) throw()
 {
+  #ifdef _WIN32
   return ::_write(fd, buffer, count);
+  #else
+  return ::write(fd, buffer, count);
+  #endif
 }
 
 } // end namespace fs

+ 84 - 0
lib/Support/Unix/Path.inc

@@ -619,3 +619,87 @@ void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) {
 
 } // end namespace sys
 } // end namespace llvm
+
+
+// The following is implementation of MSFileSystem for Unix.
+// This will make usages of MSFileSystem throughout DirectXShaderCompiler
+// compatible with Unix.
+#include "llvm/Support/MSFileSystem.h"
+namespace llvm {
+namespace sys  {
+namespace fs {
+
+thread_local MSFileSystem* threadFS = nullptr;
+
+std::error_code SetupPerThreadFileSystem() throw() {
+  // This method is now a no-op since we are using thread_local.
+  return std::error_code();
+}
+void CleanupPerThreadFileSystem() throw() {
+  // This method is now a no-op since we are using thread_local.
+}
+
+MSFileSystem* GetCurrentThreadFileSystem() throw() {
+  return threadFS;
+}
+
+std::error_code SetCurrentThreadFileSystem(MSFileSystem* value) throw() {
+  // For now, disallow reentrancy in APIs (i.e., replace the current instance with another one).
+  if (value != nullptr) {
+    MSFileSystem* current = GetCurrentThreadFileSystem();
+    if (current != nullptr) {
+      return std::error_code(1131L, std::system_category());
+    }
+  }
+  threadFS = value;
+  return std::error_code();
+}
+
+int msf_read(int fd, void* buffer, unsigned int count) throw() {
+  MSFileSystem* fsr = GetCurrentThreadFileSystem();
+  if (fsr == nullptr) {
+    errno = EBADF;
+    return -1;
+  }
+  return fsr->Read(fd, buffer, count);
+}
+
+int msf_write(int fd, const void* buffer, unsigned int count) throw() {
+  MSFileSystem* fsr = GetCurrentThreadFileSystem();
+  if (fsr == nullptr) {
+    errno = EBADF;
+    return -1;
+  }
+  return fsr->Write(fd, buffer, count);
+}
+
+int msf_close(int fd) throw() {
+  MSFileSystem* fsr = GetCurrentThreadFileSystem();
+  if (fsr == nullptr) {
+    errno = EBADF;
+    return -1;
+  }
+  return fsr->close(fd);
+}
+
+long msf_lseek(int fd, long offset, int origin) {
+  MSFileSystem* fsr = GetCurrentThreadFileSystem();
+  if (fsr == nullptr) {
+    errno = EBADF;
+    return -1;
+  }
+  return fsr->lseek(fd, offset, origin);
+}
+
+int msf_setmode(int fd, int mode) throw() {
+  MSFileSystem* fsr = GetCurrentThreadFileSystem();
+  if (fsr == nullptr) {
+    errno = EBADF;
+    return -1;
+  }
+  return fsr->setmode(fd, mode);
+}
+
+}
+}
+}