summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/Support/Windows
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Support/Windows')
-rw-r--r--contrib/llvm/lib/Support/Windows/DynamicLibrary.inc220
-rw-r--r--contrib/llvm/lib/Support/Windows/Host.inc14
-rw-r--r--contrib/llvm/lib/Support/Windows/Mutex.inc11
-rw-r--r--contrib/llvm/lib/Support/Windows/Path.inc306
-rw-r--r--contrib/llvm/lib/Support/Windows/Process.inc1
-rw-r--r--contrib/llvm/lib/Support/Windows/Program.inc1
-rw-r--r--contrib/llvm/lib/Support/Windows/RWMutex.inc13
-rw-r--r--contrib/llvm/lib/Support/Windows/Signals.inc2
-rw-r--r--contrib/llvm/lib/Support/Windows/ThreadLocal.inc11
-rw-r--r--contrib/llvm/lib/Support/Windows/Threading.inc109
-rw-r--r--contrib/llvm/lib/Support/Windows/WindowsSupport.h4
11 files changed, 528 insertions, 164 deletions
diff --git a/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc b/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc
index 0506894..083ea90 100644
--- a/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc
+++ b/contrib/llvm/lib/Support/Windows/DynamicLibrary.inc
@@ -12,92 +12,142 @@
//===----------------------------------------------------------------------===//
#include "WindowsSupport.h"
+#include "llvm/Support/raw_ostream.h"
-#ifdef __MINGW32__
- #include <imagehlp.h>
-#else
- #include <dbghelp.h>
-#endif
-
-#ifdef _MSC_VER
- #include <ntverp.h>
-#endif
-
-namespace llvm {
-using namespace sys;
+#include <psapi.h>
//===----------------------------------------------------------------------===//
//=== WARNING: Implementation here must contain only Win32 specific code
//=== and must not be UNIX code.
//===----------------------------------------------------------------------===//
-typedef BOOL (WINAPI *fpEnumerateLoadedModules)(HANDLE,PENUMLOADED_MODULES_CALLBACK64,PVOID);
-static fpEnumerateLoadedModules fEnumerateLoadedModules;
-static DenseSet<HMODULE> *OpenedHandles;
-static bool loadDebugHelp(void) {
- HMODULE hLib = ::LoadLibraryW(L"Dbghelp.dll");
- if (hLib) {
- fEnumerateLoadedModules = (fpEnumerateLoadedModules)
- ::GetProcAddress(hLib, "EnumerateLoadedModules64");
- }
- return fEnumerateLoadedModules != 0;
-}
+DynamicLibrary::HandleSet::~HandleSet() {
+ for (void *Handle : llvm::reverse(Handles))
+ FreeLibrary(HMODULE(Handle));
-static BOOL CALLBACK
-ELM_Callback(PCSTR ModuleName, DWORD64 ModuleBase,
- ULONG ModuleSize, PVOID UserContext) {
- OpenedHandles->insert((HMODULE)ModuleBase);
- return TRUE;
+ // 'Process' should not be released on Windows.
+ assert((!Process || Process==this) && "Bad Handle");
+ // llvm_shutdown called, Return to default
+ DynamicLibrary::SearchOrder = DynamicLibrary::SO_Linker;
}
-DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
- std::string *errMsg) {
- SmartScopedLock<true> lock(*SymbolsMutex);
+void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
+ // Create the instance and return it to be the *Process* handle
+ // simillar to dlopen(NULL, RTLD_LAZY|RTLD_GLOBAL)
+ if (!File)
+ return &(*OpenedHandles);
- if (!filename) {
- // When no file is specified, enumerate all DLLs and EXEs in the process.
- if (OpenedHandles == 0)
- OpenedHandles = new DenseSet<HMODULE>();
-
- if (!fEnumerateLoadedModules) {
- if (!loadDebugHelp()) {
- assert(false && "These APIs should always be available");
- return DynamicLibrary();
- }
- }
-
- fEnumerateLoadedModules(GetCurrentProcess(), ELM_Callback, 0);
- // Dummy library that represents "search all handles".
- // This is mostly to ensure that the return value still shows up as "valid".
- return DynamicLibrary(&OpenedHandles);
- }
-
- SmallVector<wchar_t, MAX_PATH> filenameUnicode;
- if (std::error_code ec = windows::UTF8ToUTF16(filename, filenameUnicode)) {
+ SmallVector<wchar_t, MAX_PATH> FileUnicode;
+ if (std::error_code ec = windows::UTF8ToUTF16(File, FileUnicode)) {
SetLastError(ec.value());
- MakeErrMsg(errMsg, std::string(filename) + ": Can't convert to UTF-16");
- return DynamicLibrary();
+ MakeErrMsg(Err, std::string(File) + ": Can't convert to UTF-16");
+ return &DynamicLibrary::Invalid;
}
-
- HMODULE a_handle = LoadLibraryW(filenameUnicode.data());
- if (a_handle == 0) {
- MakeErrMsg(errMsg, std::string(filename) + ": Can't open");
- return DynamicLibrary();
+ HMODULE Handle = LoadLibraryW(FileUnicode.data());
+ if (Handle == NULL) {
+ MakeErrMsg(Err, std::string(File) + ": Can't open");
+ return &DynamicLibrary::Invalid;
}
- if (OpenedHandles == 0)
- OpenedHandles = new DenseSet<HMODULE>();
+ return reinterpret_cast<void*>(Handle);
+}
+
+static DynamicLibrary::HandleSet *IsOpenedHandlesInstance(void *Handle) {
+ if (!OpenedHandles.isConstructed())
+ return nullptr;
+ DynamicLibrary::HandleSet &Inst = *OpenedHandles;
+ return Handle == &Inst ? &Inst : nullptr;
+}
+
+void DynamicLibrary::HandleSet::DLClose(void *Handle) {
+ if (HandleSet* HS = IsOpenedHandlesInstance(Handle))
+ HS->Process = nullptr; // Just drop the *Process* handle.
+ else
+ FreeLibrary((HMODULE)Handle);
+}
- // If we've already loaded this library, FreeLibrary() the handle in order to
- // keep the internal refcount at +1.
- if (!OpenedHandles->insert(a_handle).second)
- FreeLibrary(a_handle);
+static bool GetProcessModules(HANDLE H, DWORD &Bytes, HMODULE *Data = nullptr) {
+ // EnumProcessModules will fail on Windows 64 while some versions of
+ // MingW-32 don't have EnumProcessModulesEx.
+ if (
+#ifdef _WIN64
+ !EnumProcessModulesEx(H, Data, Bytes, &Bytes, LIST_MODULES_64BIT)
+#else
+ !EnumProcessModules(H, Data, Bytes, &Bytes)
+#endif
+ ) {
+ std::string Err;
+ if (MakeErrMsg(&Err, "EnumProcessModules failure"))
+ llvm::errs() << Err << "\n";
+ return false;
+ }
+ return true;
+}
- return DynamicLibrary(a_handle);
+void *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) {
+ HandleSet* HS = IsOpenedHandlesInstance(Handle);
+ if (!HS)
+ return (void *)uintptr_t(GetProcAddress((HMODULE)Handle, Symbol));
+
+ // Could have done a dlclose on the *Process* handle
+ if (!HS->Process)
+ return nullptr;
+
+ // Trials indicate EnumProcessModulesEx is consistantly faster than using
+ // EnumerateLoadedModules64 or CreateToolhelp32Snapshot.
+ //
+ // | Handles | DbgHelp.dll | CreateSnapshot | EnumProcessModulesEx
+ // |=========|=============|========================================
+ // | 37 | 0.0000585 * | 0.0003031 | 0.0000152
+ // | 1020 | 0.0026310 * | 0.0121598 | 0.0002683
+ // | 2084 | 0.0149418 * | 0.0369936 | 0.0005610
+ //
+ // * Not including the load time of Dbghelp.dll (~.005 sec)
+ //
+ // There's still a case to somehow cache the result of EnumProcessModulesEx
+ // across invocations, but the complication of doing that properly...
+ // Possibly using LdrRegisterDllNotification to invalidate the cache?
+
+ DWORD Bytes = 0;
+ HMODULE Self = HMODULE(GetCurrentProcess());
+ if (!GetProcessModules(Self, Bytes))
+ return nullptr;
+
+ // Get the most recent list in case any modules added/removed between calls
+ // to EnumProcessModulesEx that gets the amount of, then copies the HMODULES.
+ // MSDN is pretty clear that if the module list changes during the call to
+ // EnumProcessModulesEx the results should not be used.
+ std::vector<HMODULE> Handles;
+ do {
+ assert(Bytes && ((Bytes % sizeof(HMODULE)) == 0) &&
+ "Should have at least one module and be aligned");
+ Handles.resize(Bytes / sizeof(HMODULE));
+ if (!GetProcessModules(Self, Bytes, Handles.data()))
+ return nullptr;
+ } while (Bytes != (Handles.size() * sizeof(HMODULE)));
+
+ // Try EXE first, mirroring what dlsym(dlopen(NULL)) does.
+ if (FARPROC Ptr = GetProcAddress(HMODULE(Handles.front()), Symbol))
+ return (void *) uintptr_t(Ptr);
+
+ if (Handles.size() > 1) {
+ // This is different behaviour than what Posix dlsym(dlopen(NULL)) does.
+ // Doing that here is causing real problems for the JIT where msvc.dll
+ // and ucrt.dll can define the same symbols. The runtime linker will choose
+ // symbols from ucrt.dll first, but iterating NOT in reverse here would
+ // mean that the msvc.dll versions would be returned.
+
+ for (auto I = Handles.rbegin(), E = Handles.rend()-1; I != E; ++I) {
+ if (FARPROC Ptr = GetProcAddress(HMODULE(*I), Symbol))
+ return (void *) uintptr_t(Ptr);
+ }
+ }
+ return nullptr;
}
+
// Stack probing routines are in the support library (e.g. libgcc), but we don't
// have dynamic linking on windows. Provide a hook.
#define EXPLICIT_SYMBOL(SYM) \
@@ -123,38 +173,18 @@ DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename,
#undef INLINE_DEF_SYMBOL1
#undef INLINE_DEF_SYMBOL2
-void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) {
- SmartScopedLock<true> Lock(*SymbolsMutex);
-
- // First check symbols added via AddSymbol().
- if (ExplicitSymbols.isConstructed()) {
- StringMap<void *>::iterator i = ExplicitSymbols->find(symbolName);
-
- if (i != ExplicitSymbols->end())
- return i->second;
- }
-
- // Now search the libraries.
- if (OpenedHandles) {
- for (DenseSet<HMODULE>::iterator I = OpenedHandles->begin(),
- E = OpenedHandles->end(); I != E; ++I) {
- FARPROC ptr = GetProcAddress((HMODULE)*I, symbolName);
- if (ptr) {
- return (void *)(intptr_t)ptr;
- }
- }
- }
+static void *DoSearch(const char *SymbolName) {
#define EXPLICIT_SYMBOL(SYM) \
- if (!strcmp(symbolName, #SYM)) \
+ if (!strcmp(SymbolName, #SYM)) \
return (void *)&SYM;
#define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) \
- if (!strcmp(symbolName, #SYMFROM)) \
+ if (!strcmp(SymbolName, #SYMFROM)) \
return (void *)&SYMTO;
#ifdef _M_IX86
#define INLINE_DEF_SYMBOL1(TYP, SYM) \
- if (!strcmp(symbolName, #SYM)) \
+ if (!strcmp(SymbolName, #SYM)) \
return (void *)&inline_##SYM;
#define INLINE_DEF_SYMBOL2(TYP, SYM) INLINE_DEF_SYMBOL1(TYP, SYM)
#endif
@@ -168,15 +198,5 @@ void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) {
#undef INLINE_DEF_SYMBOL1
#undef INLINE_DEF_SYMBOL2
- return 0;
-}
-
-void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) {
- if (!isValid())
- return NULL;
- if (Data == &OpenedHandles)
- return SearchForAddressOfSymbol(symbolName);
- return (void *)(intptr_t)GetProcAddress((HMODULE)Data, symbolName);
-}
-
+ return nullptr;
}
diff --git a/contrib/llvm/lib/Support/Windows/Host.inc b/contrib/llvm/lib/Support/Windows/Host.inc
index fe89fe0..90a6fb3 100644
--- a/contrib/llvm/lib/Support/Windows/Host.inc
+++ b/contrib/llvm/lib/Support/Windows/Host.inc
@@ -17,6 +17,18 @@
using namespace llvm;
+static std::string updateTripleOSVersion(std::string Triple) {
+ return Triple;
+}
+
std::string sys::getDefaultTargetTriple() {
- return Triple::normalize(LLVM_DEFAULT_TARGET_TRIPLE);
+ const char *Triple = LLVM_DEFAULT_TARGET_TRIPLE;
+
+ // Override the default target with an environment variable named by LLVM_TARGET_TRIPLE_ENV.
+#if defined(LLVM_TARGET_TRIPLE_ENV)
+ if (const char *EnvTriple = std::getenv(LLVM_TARGET_TRIPLE_ENV))
+ Triple = EnvTriple;
+#endif
+
+ return Triple::normalize(Triple);
}
diff --git a/contrib/llvm/lib/Support/Windows/Mutex.inc b/contrib/llvm/lib/Support/Windows/Mutex.inc
index ab79d07..0af145e 100644
--- a/contrib/llvm/lib/Support/Windows/Mutex.inc
+++ b/contrib/llvm/lib/Support/Windows/Mutex.inc
@@ -20,15 +20,14 @@
#include "llvm/Support/Mutex.h"
namespace llvm {
-using namespace sys;
-MutexImpl::MutexImpl(bool /*recursive*/)
+sys::MutexImpl::MutexImpl(bool /*recursive*/)
{
data_ = new CRITICAL_SECTION;
InitializeCriticalSection((LPCRITICAL_SECTION)data_);
}
-MutexImpl::~MutexImpl()
+sys::MutexImpl::~MutexImpl()
{
DeleteCriticalSection((LPCRITICAL_SECTION)data_);
delete (LPCRITICAL_SECTION)data_;
@@ -36,21 +35,21 @@ MutexImpl::~MutexImpl()
}
bool
-MutexImpl::acquire()
+sys::MutexImpl::acquire()
{
EnterCriticalSection((LPCRITICAL_SECTION)data_);
return true;
}
bool
-MutexImpl::release()
+sys::MutexImpl::release()
{
LeaveCriticalSection((LPCRITICAL_SECTION)data_);
return true;
}
bool
-MutexImpl::tryacquire()
+sys::MutexImpl::tryacquire()
{
return TryEnterCriticalSection((LPCRITICAL_SECTION)data_);
}
diff --git a/contrib/llvm/lib/Support/Windows/Path.inc b/contrib/llvm/lib/Support/Windows/Path.inc
index 27b250b..b00d390 100644
--- a/contrib/llvm/lib/Support/Windows/Path.inc
+++ b/contrib/llvm/lib/Support/Windows/Path.inc
@@ -26,6 +26,7 @@
// These two headers must be included last, and make sure shlobj is required
// after Windows.h to make sure it picks up our definition of _WIN32_WINNT
#include "WindowsSupport.h"
+#include <shellapi.h>
#include <shlobj.h>
#undef max
@@ -178,6 +179,10 @@ TimePoint<> file_status::getLastModificationTime() const {
return toTimePoint(Time);
}
+uint32_t file_status::getLinkCount() const {
+ return NumLinks;
+}
+
std::error_code current_path(SmallVectorImpl<char> &result) {
SmallVector<wchar_t, MAX_PATH> cur_path;
DWORD len = MAX_PATH;
@@ -200,6 +205,18 @@ std::error_code current_path(SmallVectorImpl<char> &result) {
return UTF16ToUTF8(cur_path.begin(), cur_path.size(), result);
}
+std::error_code set_current_path(const Twine &path) {
+ // Convert to utf-16.
+ SmallVector<wchar_t, 128> wide_path;
+ if (std::error_code ec = widenPath(path, wide_path))
+ return ec;
+
+ if (!::SetCurrentDirectoryW(wide_path.begin()))
+ return mapWindowsError(::GetLastError());
+
+ return std::error_code();
+}
+
std::error_code create_directory(const Twine &path, bool IgnoreExisting,
perms Perms) {
SmallVector<wchar_t, 128> path_utf16;
@@ -265,6 +282,80 @@ std::error_code remove(const Twine &path, bool IgnoreNonExisting) {
return std::error_code();
}
+static std::error_code is_local_internal(SmallVectorImpl<wchar_t> &Path,
+ bool &Result) {
+ SmallVector<wchar_t, 128> VolumePath;
+ size_t Len = 128;
+ while (true) {
+ VolumePath.resize(Len);
+ BOOL Success =
+ ::GetVolumePathNameW(Path.data(), VolumePath.data(), VolumePath.size());
+
+ if (Success)
+ break;
+
+ DWORD Err = ::GetLastError();
+ if (Err != ERROR_INSUFFICIENT_BUFFER)
+ return mapWindowsError(Err);
+
+ Len *= 2;
+ }
+ // If the output buffer has exactly enough space for the path name, but not
+ // the null terminator, it will leave the output unterminated. Push a null
+ // terminator onto the end to ensure that this never happens.
+ VolumePath.push_back(L'\0');
+ VolumePath.set_size(wcslen(VolumePath.data()));
+ const wchar_t *P = VolumePath.data();
+
+ UINT Type = ::GetDriveTypeW(P);
+ switch (Type) {
+ case DRIVE_FIXED:
+ Result = true;
+ return std::error_code();
+ case DRIVE_REMOTE:
+ case DRIVE_CDROM:
+ case DRIVE_RAMDISK:
+ case DRIVE_REMOVABLE:
+ Result = false;
+ return std::error_code();
+ default:
+ return make_error_code(errc::no_such_file_or_directory);
+ }
+ llvm_unreachable("Unreachable!");
+}
+
+std::error_code is_local(const Twine &path, bool &result) {
+ if (!llvm::sys::fs::exists(path) || !llvm::sys::path::has_root_path(path))
+ return make_error_code(errc::no_such_file_or_directory);
+
+ SmallString<128> Storage;
+ StringRef P = path.toStringRef(Storage);
+
+ // Convert to utf-16.
+ SmallVector<wchar_t, 128> WidePath;
+ if (std::error_code ec = widenPath(P, WidePath))
+ return ec;
+ return is_local_internal(WidePath, result);
+}
+
+std::error_code is_local(int FD, bool &Result) {
+ SmallVector<wchar_t, 128> FinalPath;
+ HANDLE Handle = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
+
+ size_t Len = 128;
+ do {
+ FinalPath.reserve(Len);
+ Len = ::GetFinalPathNameByHandleW(Handle, FinalPath.data(),
+ FinalPath.capacity() - 1, VOLUME_NAME_NT);
+ if (Len == 0)
+ return mapWindowsError(::GetLastError());
+ } while (Len > FinalPath.capacity());
+
+ FinalPath.set_size(Len);
+
+ return is_local_internal(FinalPath, Result);
+}
+
std::error_code rename(const Twine &from, const Twine &to) {
// Convert to utf-16.
SmallVector<wchar_t, 128> wide_from;
@@ -443,13 +534,16 @@ static std::error_code getStatus(HANDLE FileHandle, file_status &Result) {
file_type Type = (Info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
? file_type::directory_file
: file_type::regular_file;
- Result =
- file_status(Type, Info.ftLastAccessTime.dwHighDateTime,
- Info.ftLastAccessTime.dwLowDateTime,
- Info.ftLastWriteTime.dwHighDateTime,
- Info.ftLastWriteTime.dwLowDateTime,
- Info.dwVolumeSerialNumber, Info.nFileSizeHigh,
- Info.nFileSizeLow, Info.nFileIndexHigh, Info.nFileIndexLow);
+ perms Permissions = (Info.dwFileAttributes & FILE_ATTRIBUTE_READONLY)
+ ? (all_read | all_exe)
+ : all_all;
+ Result = file_status(
+ Type, Permissions, Info.nNumberOfLinks,
+ Info.ftLastAccessTime.dwHighDateTime,
+ Info.ftLastAccessTime.dwLowDateTime,
+ Info.ftLastWriteTime.dwHighDateTime, Info.ftLastWriteTime.dwLowDateTime,
+ Info.dwVolumeSerialNumber, Info.nFileSizeHigh, Info.nFileSizeLow,
+ Info.nFileIndexHigh, Info.nFileIndexLow);
return std::error_code();
}
@@ -465,7 +559,7 @@ handle_status_error:
return mapWindowsError(LastError);
}
-std::error_code status(const Twine &path, file_status &result) {
+std::error_code status(const Twine &path, file_status &result, bool Follow) {
SmallString<128> path_storage;
SmallVector<wchar_t, 128> path_utf16;
@@ -482,28 +576,19 @@ std::error_code status(const Twine &path, file_status &result) {
if (attr == INVALID_FILE_ATTRIBUTES)
return getStatus(INVALID_HANDLE_VALUE, result);
+ DWORD Flags = FILE_FLAG_BACKUP_SEMANTICS;
// Handle reparse points.
- if (attr & FILE_ATTRIBUTE_REPARSE_POINT) {
- ScopedFileHandle h(
- ::CreateFileW(path_utf16.begin(),
- 0, // Attributes only.
- FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL,
- OPEN_EXISTING,
- FILE_FLAG_BACKUP_SEMANTICS,
- 0));
- if (!h)
- return getStatus(INVALID_HANDLE_VALUE, result);
- }
+ if (!Follow && (attr & FILE_ATTRIBUTE_REPARSE_POINT))
+ Flags |= FILE_FLAG_OPEN_REPARSE_POINT;
ScopedFileHandle h(
::CreateFileW(path_utf16.begin(), 0, // Attributes only.
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
- NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0));
- if (!h)
- return getStatus(INVALID_HANDLE_VALUE, result);
+ NULL, OPEN_EXISTING, Flags, 0));
+ if (!h)
+ return getStatus(INVALID_HANDLE_VALUE, result);
- return getStatus(h, result);
+ return getStatus(h, result);
}
std::error_code status(int FD, file_status &Result) {
@@ -511,6 +596,37 @@ std::error_code status(int FD, file_status &Result) {
return getStatus(FileHandle, Result);
}
+std::error_code setPermissions(const Twine &Path, perms Permissions) {
+ SmallVector<wchar_t, 128> PathUTF16;
+ if (std::error_code EC = widenPath(Path, PathUTF16))
+ return EC;
+
+ DWORD Attributes = ::GetFileAttributesW(PathUTF16.begin());
+ if (Attributes == INVALID_FILE_ATTRIBUTES)
+ return mapWindowsError(GetLastError());
+
+ // There are many Windows file attributes that are not to do with the file
+ // permissions (e.g. FILE_ATTRIBUTE_HIDDEN). We need to be careful to preserve
+ // them.
+ if (Permissions & all_write) {
+ Attributes &= ~FILE_ATTRIBUTE_READONLY;
+ if (Attributes == 0)
+ // FILE_ATTRIBUTE_NORMAL indicates no other attributes are set.
+ Attributes |= FILE_ATTRIBUTE_NORMAL;
+ }
+ else {
+ Attributes |= FILE_ATTRIBUTE_READONLY;
+ // FILE_ATTRIBUTE_NORMAL is not compatible with any other attributes, so
+ // remove it, if it is present.
+ Attributes &= ~FILE_ATTRIBUTE_NORMAL;
+ }
+
+ if (!::SetFileAttributesW(PathUTF16.begin(), Attributes))
+ return mapWindowsError(GetLastError());
+
+ return std::error_code();
+}
+
std::error_code setLastModificationAndAccessTime(int FD, TimePoint<> Time) {
FILETIME FT = toFILETIME(Time);
HANDLE FileHandle = reinterpret_cast<HANDLE>(_get_osfhandle(FD));
@@ -616,7 +732,8 @@ int mapped_file_region::alignment() {
}
std::error_code detail::directory_iterator_construct(detail::DirIterState &it,
- StringRef path){
+ StringRef path,
+ bool follow_symlinks) {
SmallVector<wchar_t, 128> path_utf16;
if (std::error_code ec = widenPath(path, path_utf16))
@@ -661,7 +778,7 @@ std::error_code detail::directory_iterator_construct(detail::DirIterState &it,
it.IterationHandle = intptr_t(FindHandle.take());
SmallString<128> directory_entry_path(path);
path::append(directory_entry_path, directory_entry_name_utf8);
- it.CurrentEntry = directory_entry(directory_entry_path);
+ it.CurrentEntry = directory_entry(directory_entry_path, follow_symlinks);
return std::error_code();
}
@@ -701,6 +818,52 @@ std::error_code detail::directory_iterator_increment(detail::DirIterState &it) {
return std::error_code();
}
+static std::error_code realPathFromHandle(HANDLE H,
+ SmallVectorImpl<char> &RealPath) {
+ RealPath.clear();
+ llvm::SmallVector<wchar_t, MAX_PATH> Buffer;
+ DWORD CountChars = ::GetFinalPathNameByHandleW(
+ H, Buffer.begin(), Buffer.capacity() - 1, FILE_NAME_NORMALIZED);
+ if (CountChars > Buffer.capacity()) {
+ // The buffer wasn't big enough, try again. In this case the return value
+ // *does* indicate the size of the null terminator.
+ Buffer.reserve(CountChars);
+ CountChars = ::GetFinalPathNameByHandleW(
+ H, Buffer.data(), Buffer.capacity() - 1, FILE_NAME_NORMALIZED);
+ }
+ if (CountChars == 0)
+ return mapWindowsError(GetLastError());
+
+ const wchar_t *Data = Buffer.data();
+ if (CountChars >= 4) {
+ if (0 == ::memcmp(Data, L"\\\\?\\", 8)) {
+ CountChars -= 4;
+ Data += 4;
+ }
+ }
+
+ // Convert the result from UTF-16 to UTF-8.
+ return UTF16ToUTF8(Data, CountChars, RealPath);
+}
+
+static std::error_code directoryRealPath(const Twine &Name,
+ SmallVectorImpl<char> &RealPath) {
+ SmallVector<wchar_t, 128> PathUTF16;
+
+ if (std::error_code EC = widenPath(Name, PathUTF16))
+ return EC;
+
+ HANDLE H =
+ ::CreateFileW(PathUTF16.begin(), GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+ if (H == INVALID_HANDLE_VALUE)
+ return mapWindowsError(GetLastError());
+ std::error_code EC = realPathFromHandle(H, RealPath);
+ ::CloseHandle(H);
+ return EC;
+}
+
std::error_code openFileForRead(const Twine &Name, int &ResultFD,
SmallVectorImpl<char> *RealPath) {
SmallVector<wchar_t, 128> PathUTF16;
@@ -732,20 +895,8 @@ std::error_code openFileForRead(const Twine &Name, int &ResultFD,
}
// Fetch the real name of the file, if the user asked
- if (RealPath) {
- RealPath->clear();
- wchar_t RealPathUTF16[MAX_PATH];
- DWORD CountChars =
- ::GetFinalPathNameByHandleW(H, RealPathUTF16, MAX_PATH,
- FILE_NAME_NORMALIZED);
- if (CountChars > 0 && CountChars < MAX_PATH) {
- // Convert the result from UTF-16 to UTF-8.
- SmallString<MAX_PATH> RealPathUTF8;
- if (!UTF16ToUTF8(RealPathUTF16, CountChars, RealPathUTF8))
- RealPath->append(RealPathUTF8.data(),
- RealPathUTF8.data() + strlen(RealPathUTF8.data()));
- }
- }
+ if (RealPath)
+ realPathFromHandle(H, *RealPath);
ResultFD = FD;
return std::error_code();
@@ -843,6 +994,81 @@ std::error_code getPathFromOpenFD(int FD, SmallVectorImpl<char> &ResultPath) {
return windows::UTF16ToUTF8(TempPath.data(), CharCount, ResultPath);
}
+
+std::error_code remove_directories(const Twine &path, bool IgnoreErrors) {
+ // Convert to utf-16.
+ SmallVector<wchar_t, 128> Path16;
+ std::error_code EC = widenPath(path, Path16);
+ if (EC && !IgnoreErrors)
+ return EC;
+
+ // SHFileOperation() accepts a list of paths, and so must be double null-
+ // terminated to indicate the end of the list. The buffer is already null
+ // terminated, but since that null character is not considered part of the
+ // vector's size, pushing another one will just consume that byte. So we
+ // need to push 2 null terminators.
+ Path16.push_back(0);
+ Path16.push_back(0);
+
+ SHFILEOPSTRUCTW shfos = {};
+ shfos.wFunc = FO_DELETE;
+ shfos.pFrom = Path16.data();
+ shfos.fFlags = FOF_NO_UI;
+
+ int result = ::SHFileOperationW(&shfos);
+ if (result != 0 && !IgnoreErrors)
+ return mapWindowsError(result);
+ return std::error_code();
+}
+
+static void expandTildeExpr(SmallVectorImpl<char> &Path) {
+ // Path does not begin with a tilde expression.
+ if (Path.empty() || Path[0] != '~')
+ return;
+
+ StringRef PathStr(Path.begin(), Path.size());
+ PathStr = PathStr.drop_front();
+ StringRef Expr = PathStr.take_until([](char c) { return path::is_separator(c); });
+
+ if (!Expr.empty()) {
+ // This is probably a ~username/ expression. Don't support this on Windows.
+ return;
+ }
+
+ SmallString<128> HomeDir;
+ if (!path::home_directory(HomeDir)) {
+ // For some reason we couldn't get the home directory. Just exit.
+ return;
+ }
+
+ // Overwrite the first character and insert the rest.
+ Path[0] = HomeDir[0];
+ Path.insert(Path.begin() + 1, HomeDir.begin() + 1, HomeDir.end());
+}
+
+std::error_code real_path(const Twine &path, SmallVectorImpl<char> &dest,
+ bool expand_tilde) {
+ dest.clear();
+ if (path.isTriviallyEmpty())
+ return std::error_code();
+
+ if (expand_tilde) {
+ SmallString<128> Storage;
+ path.toVector(Storage);
+ expandTildeExpr(Storage);
+ return real_path(Storage, dest, false);
+ }
+
+ if (is_directory(path))
+ return directoryRealPath(path, dest);
+
+ int fd;
+ if (std::error_code EC = llvm::sys::fs::openFileForRead(path, fd, &dest))
+ return EC;
+ ::close(fd);
+ return std::error_code();
+}
+
} // end namespace fs
namespace path {
diff --git a/contrib/llvm/lib/Support/Windows/Process.inc b/contrib/llvm/lib/Support/Windows/Process.inc
index 8d646b3..18aef61 100644
--- a/contrib/llvm/lib/Support/Windows/Process.inc
+++ b/contrib/llvm/lib/Support/Windows/Process.inc
@@ -47,7 +47,6 @@
#endif
using namespace llvm;
-using namespace sys;
// This function retrieves the page size using GetNativeSystemInfo() and is
// present solely so it can be called once to initialize the self_process member
diff --git a/contrib/llvm/lib/Support/Windows/Program.inc b/contrib/llvm/lib/Support/Windows/Program.inc
index 78fc538..721167d 100644
--- a/contrib/llvm/lib/Support/Windows/Program.inc
+++ b/contrib/llvm/lib/Support/Windows/Program.inc
@@ -29,7 +29,6 @@
//===----------------------------------------------------------------------===//
namespace llvm {
-using namespace sys;
ProcessInfo::ProcessInfo() : ProcessHandle(0), Pid(0), ReturnCode(0) {}
diff --git a/contrib/llvm/lib/Support/Windows/RWMutex.inc b/contrib/llvm/lib/Support/Windows/RWMutex.inc
index 2d1d25f..ac60c2f 100644
--- a/contrib/llvm/lib/Support/Windows/RWMutex.inc
+++ b/contrib/llvm/lib/Support/Windows/RWMutex.inc
@@ -19,7 +19,6 @@
#include "WindowsSupport.h"
namespace llvm {
-using namespace sys;
// Windows has slim read-writer lock support on Vista and higher, so we
// will attempt to load the APIs. If they exist, we will use them, and
@@ -73,7 +72,7 @@ static bool loadSRW() {
return sHasSRW;
}
-RWMutexImpl::RWMutexImpl() {
+sys::RWMutexImpl::RWMutexImpl() {
if (loadSRW()) {
data_ = calloc(1, sizeof(SRWLOCK));
fpInitializeSRWLock(static_cast<PSRWLOCK>(data_));
@@ -83,14 +82,14 @@ RWMutexImpl::RWMutexImpl() {
}
}
-RWMutexImpl::~RWMutexImpl() {
+sys::RWMutexImpl::~RWMutexImpl() {
if (!sHasSRW)
DeleteCriticalSection(static_cast<LPCRITICAL_SECTION>(data_));
// Nothing to do in the case of slim reader/writers except free the memory.
free(data_);
}
-bool RWMutexImpl::reader_acquire() {
+bool sys::RWMutexImpl::reader_acquire() {
if (sHasSRW) {
fpAcquireSRWLockShared(static_cast<PSRWLOCK>(data_));
} else {
@@ -99,7 +98,7 @@ bool RWMutexImpl::reader_acquire() {
return true;
}
-bool RWMutexImpl::reader_release() {
+bool sys::RWMutexImpl::reader_release() {
if (sHasSRW) {
fpReleaseSRWLockShared(static_cast<PSRWLOCK>(data_));
} else {
@@ -108,7 +107,7 @@ bool RWMutexImpl::reader_release() {
return true;
}
-bool RWMutexImpl::writer_acquire() {
+bool sys::RWMutexImpl::writer_acquire() {
if (sHasSRW) {
fpAcquireSRWLockExclusive(static_cast<PSRWLOCK>(data_));
} else {
@@ -117,7 +116,7 @@ bool RWMutexImpl::writer_acquire() {
return true;
}
-bool RWMutexImpl::writer_release() {
+bool sys::RWMutexImpl::writer_release() {
if (sHasSRW) {
fpReleaseSRWLockExclusive(static_cast<PSRWLOCK>(data_));
} else {
diff --git a/contrib/llvm/lib/Support/Windows/Signals.inc b/contrib/llvm/lib/Support/Windows/Signals.inc
index f739421..1ef5188 100644
--- a/contrib/llvm/lib/Support/Windows/Signals.inc
+++ b/contrib/llvm/lib/Support/Windows/Signals.inc
@@ -776,7 +776,7 @@ static LONG WINAPI LLVMUnhandledExceptionFilter(LPEXCEPTION_POINTERS ep) {
// the nasty sorts of crashes that aren't 100% reproducible from a set of
// inputs (or in the event that the user is unable or unwilling to provide a
// reproducible case).
- if (!llvm::Process::AreCoreFilesPrevented()) {
+ if (!llvm::sys::Process::AreCoreFilesPrevented()) {
MINIDUMP_EXCEPTION_INFORMATION ExceptionInfo;
ExceptionInfo.ThreadId = ::GetCurrentThreadId();
ExceptionInfo.ExceptionPointers = ep;
diff --git a/contrib/llvm/lib/Support/Windows/ThreadLocal.inc b/contrib/llvm/lib/Support/Windows/ThreadLocal.inc
index b9cb8ff..8be1c3e 100644
--- a/contrib/llvm/lib/Support/Windows/ThreadLocal.inc
+++ b/contrib/llvm/lib/Support/Windows/ThreadLocal.inc
@@ -20,33 +20,32 @@
#include "llvm/Support/ThreadLocal.h"
namespace llvm {
-using namespace sys;
-ThreadLocalImpl::ThreadLocalImpl() : data() {
+sys::ThreadLocalImpl::ThreadLocalImpl() : data() {
static_assert(sizeof(DWORD) <= sizeof(data), "size too big");
DWORD* tls = reinterpret_cast<DWORD*>(&data);
*tls = TlsAlloc();
assert(*tls != TLS_OUT_OF_INDEXES);
}
-ThreadLocalImpl::~ThreadLocalImpl() {
+sys::ThreadLocalImpl::~ThreadLocalImpl() {
DWORD* tls = reinterpret_cast<DWORD*>(&data);
TlsFree(*tls);
}
-void *ThreadLocalImpl::getInstance() {
+void *sys::ThreadLocalImpl::getInstance() {
DWORD* tls = reinterpret_cast<DWORD*>(&data);
return TlsGetValue(*tls);
}
-void ThreadLocalImpl::setInstance(const void* d){
+void sys::ThreadLocalImpl::setInstance(const void* d){
DWORD* tls = reinterpret_cast<DWORD*>(&data);
int errorcode = TlsSetValue(*tls, const_cast<void*>(d));
assert(errorcode != 0);
(void)errorcode;
}
-void ThreadLocalImpl::removeInstance() {
+void sys::ThreadLocalImpl::removeInstance() {
setInstance(0);
}
diff --git a/contrib/llvm/lib/Support/Windows/Threading.inc b/contrib/llvm/lib/Support/Windows/Threading.inc
new file mode 100644
index 0000000..decb488
--- /dev/null
+++ b/contrib/llvm/lib/Support/Windows/Threading.inc
@@ -0,0 +1,109 @@
+//===- Windows/Threading.inc - Win32 Threading Implementation - -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides the Win32 specific implementation of Threading functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
+
+#include "Windows/WindowsSupport.h"
+#include <process.h>
+
+// Windows will at times define MemoryFence.
+#ifdef MemoryFence
+#undef MemoryFence
+#endif
+
+namespace {
+ struct ThreadInfo {
+ void(*func)(void*);
+ void *param;
+ };
+}
+
+static unsigned __stdcall ThreadCallback(void *param) {
+ struct ThreadInfo *info = reinterpret_cast<struct ThreadInfo *>(param);
+ info->func(info->param);
+
+ return 0;
+}
+
+void llvm::llvm_execute_on_thread(void(*Fn)(void*), void *UserData,
+ unsigned RequestedStackSize) {
+ struct ThreadInfo param = { Fn, UserData };
+
+ HANDLE hThread = (HANDLE)::_beginthreadex(NULL,
+ RequestedStackSize, ThreadCallback,
+ &param, 0, NULL);
+
+ if (hThread) {
+ // We actually don't care whether the wait succeeds or fails, in
+ // the same way we don't care whether the pthread_join call succeeds
+ // or fails. There's not much we could do if this were to fail. But
+ // on success, this call will wait until the thread finishes executing
+ // before returning.
+ (void)::WaitForSingleObject(hThread, INFINITE);
+ ::CloseHandle(hThread);
+ }
+}
+
+uint64_t llvm::get_threadid() {
+ return uint64_t(::GetCurrentThreadId());
+}
+
+uint32_t llvm::get_max_thread_name_length() { return 0; }
+
+#if defined(_MSC_VER)
+static void SetThreadName(DWORD Id, LPCSTR Name) {
+ constexpr DWORD MS_VC_EXCEPTION = 0x406D1388;
+
+#pragma pack(push, 8)
+ struct THREADNAME_INFO {
+ DWORD dwType; // Must be 0x1000.
+ LPCSTR szName; // Pointer to thread name
+ DWORD dwThreadId; // Thread ID (-1 == current thread)
+ DWORD dwFlags; // Reserved. Do not use.
+ };
+#pragma pack(pop)
+
+ THREADNAME_INFO info;
+ info.dwType = 0x1000;
+ info.szName = Name;
+ info.dwThreadId = Id;
+ info.dwFlags = 0;
+
+ __try {
+ ::RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR),
+ (ULONG_PTR *)&info);
+ }
+ __except (EXCEPTION_EXECUTE_HANDLER) {
+ }
+}
+#endif
+
+void llvm::set_thread_name(const Twine &Name) {
+#if defined(_MSC_VER)
+ // Make sure the input is null terminated.
+ SmallString<64> Storage;
+ StringRef NameStr = Name.toNullTerminatedStringRef(Storage);
+ SetThreadName(::GetCurrentThreadId(), NameStr.data());
+#endif
+}
+
+void llvm::get_thread_name(SmallVectorImpl<char> &Name) {
+ // "Name" is not an inherent property of a thread on Windows. In fact, when
+ // you "set" the name, you are only firing a one-time message to a debugger
+ // which it interprets as a program setting its threads' name. We may be
+ // able to get fancy by creating a TLS entry when someone calls
+ // set_thread_name so that subsequent calls to get_thread_name return this
+ // value.
+ Name.clear();
+}
diff --git a/contrib/llvm/lib/Support/Windows/WindowsSupport.h b/contrib/llvm/lib/Support/Windows/WindowsSupport.h
index c358b99..d4599dc 100644
--- a/contrib/llvm/lib/Support/Windows/WindowsSupport.h
+++ b/contrib/llvm/lib/Support/Windows/WindowsSupport.h
@@ -45,7 +45,9 @@
#include <string>
#include <system_error>
#include <windows.h>
-#include <wincrypt.h> // Must be included after windows.h
+
+// Must be included after windows.h
+#include <wincrypt.h>
/// Determines if the program is running on Windows 8 or newer. This
/// reimplements one of the helpers in the Windows 8.1 SDK, which are intended
OpenPOWER on IntegriCloud