diff --git a/lib/Support/Windows/DynamicLibrary.inc b/lib/Support/Windows/DynamicLibrary.inc index 241f95d55a9..79d5f79afa9 100644 --- a/lib/Support/Windows/DynamicLibrary.inc +++ b/lib/Support/Windows/DynamicLibrary.inc @@ -94,10 +94,24 @@ DynamicLibrary DynamicLibrary::getPermanentLibrary(const char *filename, extern "C" { extern void *SYM; } #define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) EXPLICIT_SYMBOL(SYMTO) +#ifdef _M_IX86 +// Win32 on x86 implements certain single-precision math functions as macros. +// These functions are not exported by the DLL, but will still be needed +// for symbol-resolution by the JIT loader. Therefore, this Support libray +// provides helper functions with the same implementation. + +#define INLINE_DEF_SYMBOL1(TYP, SYM) \ + extern "C" TYP inline_##SYM(TYP _X) { return SYM(_X); } +#define INLINE_DEF_SYMBOL2(TYP, SYM) \ + extern "C" TYP inline_##SYM(TYP _X, TYP _Y) { return SYM(_X, _Y); } +#endif + #include "explicit_symbols.inc" #undef EXPLICIT_SYMBOL #undef EXPLICIT_SYMBOL2 +#undef INLINE_DEF_SYMBOL1 +#undef INLINE_DEF_SYMBOL2 void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) { SmartScopedLock Lock(*SymbolsMutex); @@ -121,22 +135,32 @@ void* DynamicLibrary::SearchForAddressOfSymbol(const char* symbolName) { } } - #define EXPLICIT_SYMBOL(SYM) \ - if (!strcmp(symbolName, #SYM)) return (void*)&SYM; - #define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) \ - if (!strcmp(symbolName, #SYMFROM)) return (void*)&SYMTO; +#define EXPLICIT_SYMBOL(SYM) \ + if (!strcmp(symbolName, #SYM)) \ + return (void *)&SYM; +#define EXPLICIT_SYMBOL2(SYMFROM, SYMTO) \ + if (!strcmp(symbolName, #SYMFROM)) \ + return (void *)&SYMTO; + +#ifdef _M_IX86 +#define INLINE_DEF_SYMBOL1(TYP, SYM) \ + if (!strcmp(symbolName, #SYM)) \ + return (void *)&inline_##SYM; +#define INLINE_DEF_SYMBOL2(TYP, SYM) INLINE_DEF_SYMBOL1(TYP, SYM) +#endif { - #include "explicit_symbols.inc" +#include "explicit_symbols.inc" } - #undef EXPLICIT_SYMBOL - #undef EXPLICIT_SYMBOL2 +#undef EXPLICIT_SYMBOL +#undef EXPLICIT_SYMBOL2 +#undef INLINE_DEF_SYMBOL1 +#undef INLINE_DEF_SYMBOL2 return 0; } - void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { if (!isValid()) return NULL; @@ -145,5 +169,4 @@ void *DynamicLibrary::getAddressOfSymbol(const char *symbolName) { return (void *)(intptr_t)GetProcAddress((HMODULE)Data, symbolName); } - } diff --git a/lib/Support/Windows/explicit_symbols.inc b/lib/Support/Windows/explicit_symbols.inc index 379645d2ff6..5f3818919d2 100644 --- a/lib/Support/Windows/explicit_symbols.inc +++ b/lib/Support/Windows/explicit_symbols.inc @@ -63,4 +63,32 @@ /* msvcrt */ #if defined(_MSC_VER) EXPLICIT_SYMBOL2(alloca, _alloca_probe) + +#ifdef _M_IX86 +#define INLINE_DEF_FLOAT_SYMBOL(SYM, ARGC) INLINE_DEF_SYMBOL##ARGC(float, SYM) + INLINE_DEF_FLOAT_SYMBOL(acosf, 1) + INLINE_DEF_FLOAT_SYMBOL(asinf, 1) + INLINE_DEF_FLOAT_SYMBOL(atanf, 1) + INLINE_DEF_FLOAT_SYMBOL(atan2f, 2) + INLINE_DEF_FLOAT_SYMBOL(ceilf, 1) +#if (_MSC_VER==1800) + INLINE_DEF_FLOAT_SYMBOL(copysignf, 2) +#endif + INLINE_DEF_FLOAT_SYMBOL(cosf, 1) + INLINE_DEF_FLOAT_SYMBOL(coshf, 1) + INLINE_DEF_FLOAT_SYMBOL(expf, 1) + INLINE_DEF_FLOAT_SYMBOL(floorf, 1) + INLINE_DEF_FLOAT_SYMBOL(fminf, 2) + INLINE_DEF_FLOAT_SYMBOL(fmaxf, 2) + INLINE_DEF_FLOAT_SYMBOL(fmodf, 2) + INLINE_DEF_FLOAT_SYMBOL(logf, 1) + INLINE_DEF_FLOAT_SYMBOL(powf, 2) + INLINE_DEF_FLOAT_SYMBOL(sinf, 1) + INLINE_DEF_FLOAT_SYMBOL(sinhf, 1) + INLINE_DEF_FLOAT_SYMBOL(sqrtf, 1) + INLINE_DEF_FLOAT_SYMBOL(tanf, 1) + INLINE_DEF_FLOAT_SYMBOL(tanhf, 1) +#undef INLINE_DEF_FLOAT_SYMBOL +#endif + #endif diff --git a/test/ExecutionEngine/frem.ll b/test/ExecutionEngine/frem.ll new file mode 100644 index 00000000000..7e0b6060f6f --- /dev/null +++ b/test/ExecutionEngine/frem.ll @@ -0,0 +1,20 @@ +; LLI.exe used to crash on Windows\X86 when certain single precession +; floating point intrinsics (defined as macros) are used. +; This unit test guards against the failure. +; +; RUN: %lli %s | FileCheck %s + +@flt = internal global float 12.0e+0 +@str = internal constant [18 x i8] c"Double value: %f\0A\00" + +declare i32 @printf(i8* nocapture, ...) nounwind + +define i32 @main() { + %flt = load float* @flt + %float2 = frem float %flt, 5.0 + %double1 = fpext float %float2 to double + call i32 (i8*, ...)* @printf(i8* getelementptr ([18 x i8]* @str, i32 0, i64 0), double %double1) + ret i32 0 +} + +; CHECK: Double value: 2.0