[PowerPC] Materialize more constants with CR-field set in late peephole
[llvm-core.git] / lib / Support / Windows / DynamicLibrary.inc
blob1d47f0848a6dfac5e0b295b5fa344264dcd1a81a
1 //===- Win32/DynamicLibrary.cpp - Win32 DL Implementation -------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file provides the Win32 specific implementation of DynamicLibrary.
12 //===----------------------------------------------------------------------===//
14 #include "WindowsSupport.h"
15 #include "llvm/Support/ConvertUTF.h"
16 #include "llvm/Support/raw_ostream.h"
18 #include <psapi.h>
20 //===----------------------------------------------------------------------===//
21 //=== WARNING: Implementation here must contain only Win32 specific code
22 //===          and must not be UNIX code.
23 //===----------------------------------------------------------------------===//
26 DynamicLibrary::HandleSet::~HandleSet() {
27   for (void *Handle : llvm::reverse(Handles))
28     FreeLibrary(HMODULE(Handle));
30   // 'Process' should not be released on Windows.
31   assert((!Process || Process==this) && "Bad Handle");
32   // llvm_shutdown called, Return to default
33   DynamicLibrary::SearchOrder = DynamicLibrary::SO_Linker;
36 void *DynamicLibrary::HandleSet::DLOpen(const char *File, std::string *Err) {
37   // Create the instance and return it to be the *Process* handle
38   // simillar to dlopen(NULL, RTLD_LAZY|RTLD_GLOBAL)
39   if (!File)
40     return &(*OpenedHandles);
42   SmallVector<wchar_t, MAX_PATH> FileUnicode;
43   if (std::error_code ec = windows::UTF8ToUTF16(File, FileUnicode)) {
44     SetLastError(ec.value());
45     MakeErrMsg(Err, std::string(File) + ": Can't convert to UTF-16");
46     return &DynamicLibrary::Invalid;
47   }
49   HMODULE Handle = LoadLibraryW(FileUnicode.data());
50   if (Handle == NULL) {
51     MakeErrMsg(Err, std::string(File) + ": Can't open");
52     return &DynamicLibrary::Invalid;
53   }
55   return reinterpret_cast<void*>(Handle);
58 static DynamicLibrary::HandleSet *IsOpenedHandlesInstance(void *Handle) {
59   if (!OpenedHandles.isConstructed())
60     return nullptr;
61   DynamicLibrary::HandleSet &Inst = *OpenedHandles;
62   return Handle == &Inst ? &Inst : nullptr;
65 void DynamicLibrary::HandleSet::DLClose(void *Handle) {
66   if (HandleSet* HS = IsOpenedHandlesInstance(Handle))
67     HS->Process = nullptr; // Just drop the *Process* handle.
68   else
69     FreeLibrary((HMODULE)Handle);
72 static bool GetProcessModules(HANDLE H, DWORD &Bytes, HMODULE *Data = nullptr) {
73   // EnumProcessModules will fail on Windows 64 while some versions of
74   // MingW-32 don't have EnumProcessModulesEx.
75   if (
76 #ifdef _WIN64
77       !EnumProcessModulesEx(H, Data, Bytes, &Bytes, LIST_MODULES_64BIT)
78 #else
79       !EnumProcessModules(H, Data, Bytes, &Bytes)
80 #endif
81      ) {
82     std::string Err;
83     if (MakeErrMsg(&Err, "EnumProcessModules failure"))
84       llvm::errs() << Err << "\n";
85     return false;
86   }
87   return true;
90 void *DynamicLibrary::HandleSet::DLSym(void *Handle, const char *Symbol) {
91   HandleSet* HS = IsOpenedHandlesInstance(Handle);
92   if (!HS)
93     return (void *)uintptr_t(GetProcAddress((HMODULE)Handle, Symbol));
95   // Could have done a dlclose on the *Process* handle
96   if (!HS->Process)
97     return nullptr;
99   // Trials indicate EnumProcessModulesEx is consistantly faster than using
100   // EnumerateLoadedModules64 or CreateToolhelp32Snapshot.
101   //
102   // | Handles | DbgHelp.dll | CreateSnapshot | EnumProcessModulesEx
103   // |=========|=============|========================================
104   // | 37      | 0.0000585 * | 0.0003031      | 0.0000152
105   // | 1020    | 0.0026310 * | 0.0121598      | 0.0002683
106   // | 2084    | 0.0149418 * | 0.0369936      | 0.0005610
107   //
108   // * Not including the load time of Dbghelp.dll (~.005 sec)
109   //
110   // There's still a case to somehow cache the result of EnumProcessModulesEx
111   // across invocations, but the complication of doing that properly...
112   // Possibly using LdrRegisterDllNotification to invalidate the cache?
114   DWORD Bytes = 0;
115   HMODULE Self = HMODULE(GetCurrentProcess());
116   if (!GetProcessModules(Self, Bytes))
117     return nullptr;
119   // Get the most recent list in case any modules added/removed between calls
120   // to EnumProcessModulesEx that gets the amount of, then copies the HMODULES.
121   // MSDN is pretty clear that if the module list changes during the call to
122   // EnumProcessModulesEx the results should not be used.
123   std::vector<HMODULE> Handles;
124   do {
125     assert(Bytes && ((Bytes % sizeof(HMODULE)) == 0) &&
126            "Should have at least one module and be aligned");
127     Handles.resize(Bytes / sizeof(HMODULE));
128     if (!GetProcessModules(Self, Bytes, Handles.data()))
129       return nullptr;
130   } while (Bytes != (Handles.size() * sizeof(HMODULE)));
132   // Try EXE first, mirroring what dlsym(dlopen(NULL)) does.
133   if (FARPROC Ptr = GetProcAddress(HMODULE(Handles.front()), Symbol))
134     return (void *) uintptr_t(Ptr);
136   if (Handles.size() > 1) {
137     // This is different behaviour than what Posix dlsym(dlopen(NULL)) does.
138     // Doing that here is causing real problems for the JIT where msvc.dll
139     // and ucrt.dll can define the same symbols. The runtime linker will choose
140     // symbols from ucrt.dll first, but iterating NOT in reverse here would
141     // mean that the msvc.dll versions would be returned.
143     for (auto I = Handles.rbegin(), E = Handles.rend()-1; I != E; ++I) {
144       if (FARPROC Ptr = GetProcAddress(HMODULE(*I), Symbol))
145         return (void *) uintptr_t(Ptr);
146     }
147   }
148   return nullptr;
152 // Stack probing routines are in the support library (e.g. libgcc), but we don't
153 // have dynamic linking on windows. Provide a hook.
154 #define EXPLICIT_SYMBOL(SYM)                    \
155   extern "C" { extern void *SYM; }
156 #define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) EXPLICIT_SYMBOL(SYMTO)
158 #ifdef _M_IX86
159 // Win32 on x86 implements certain single-precision math functions as macros.
160 // These functions are not exported by the DLL, but will still be needed
161 // for symbol-resolution by the JIT loader. Therefore, this Support libray
162 // provides helper functions with the same implementation.
164 #define INLINE_DEF_SYMBOL1(TYP, SYM)                                           \
165   extern "C" TYP inline_##SYM(TYP _X) { return SYM(_X); }
166 #define INLINE_DEF_SYMBOL2(TYP, SYM)                                           \
167   extern "C" TYP inline_##SYM(TYP _X, TYP _Y) { return SYM(_X, _Y); }
168 #endif
170 #include "explicit_symbols.inc"
172 #undef EXPLICIT_SYMBOL
173 #undef EXPLICIT_SYMBOL2
174 #undef INLINE_DEF_SYMBOL1
175 #undef INLINE_DEF_SYMBOL2
177 static void *DoSearch(const char *SymbolName) {
179 #define EXPLICIT_SYMBOL(SYM)                                                   \
180   if (!strcmp(SymbolName, #SYM))                                               \
181     return (void *)&SYM;
182 #define EXPLICIT_SYMBOL2(SYMFROM, SYMTO)                                       \
183   if (!strcmp(SymbolName, #SYMFROM))                                           \
184     return (void *)&SYMTO;
186 #ifdef _M_IX86
187 #define INLINE_DEF_SYMBOL1(TYP, SYM)                                           \
188   if (!strcmp(SymbolName, #SYM))                                               \
189     return (void *)&inline_##SYM;
190 #define INLINE_DEF_SYMBOL2(TYP, SYM) INLINE_DEF_SYMBOL1(TYP, SYM)
191 #endif
193   {
194 #include "explicit_symbols.inc"
195   }
197 #undef EXPLICIT_SYMBOL
198 #undef EXPLICIT_SYMBOL2
199 #undef INLINE_DEF_SYMBOL1
200 #undef INLINE_DEF_SYMBOL2
202   return nullptr;