diff options
author | Filip Pizlo <fpizlo@apple.com> | 2014-02-20 23:57:31 +0000 |
---|---|---|
committer | Filip Pizlo <fpizlo@apple.com> | 2014-02-20 23:57:31 +0000 |
commit | c95bd8d88f660d39ff7ffaed4a78b7f2622b5641 (patch) | |
tree | 6db156315a894e9404d8ee8d49290640663a5ac5 /llvm/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp | |
parent | 71966c99a55f42135a871bccd0c6f4a90af7af4a (diff) | |
download | bcm5719-llvm-c95bd8d88f660d39ff7ffaed4a78b7f2622b5641.tar.gz bcm5719-llvm-c95bd8d88f660d39ff7ffaed4a78b7f2622b5641.zip |
Stackmaps are used for OSR exits, which is a custom kind of unwinding. Hence, they
should not be marked nounwind.
Marking them nounwind caused crashes in the WebKit FTL JIT, because if we enable
sufficient optimizations, LLVM starts eliding compact_unwind sections (or any unwind
data for that matter), making deoptimization via stackmaps impossible.
This changes the stackmap intrinsic to be may-throw, adds a test for exactly the
sympton that WebKit saw, and fixes TableGen to handle un-attributed intrinsics.
Thanks to atrick and philipreames for reviewing this.
llvm-svn: 201826
Diffstat (limited to 'llvm/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp')
-rw-r--r-- | llvm/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/llvm/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp b/llvm/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp index a56d9c7b9c0..7a7d178623d 100644 --- a/llvm/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp +++ b/llvm/unittests/ExecutionEngine/MCJIT/MCJITCAPITest.cpp @@ -18,6 +18,7 @@ #include "llvm-c/ExecutionEngine.h" #include "llvm-c/Target.h" #include "llvm-c/Transforms/Scalar.h" +#include "llvm-c/Transforms/PassManagerBuilder.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include "llvm/Support/Host.h" #include "gtest/gtest.h" @@ -26,6 +27,7 @@ using namespace llvm; static bool didCallAllocateCodeSection; +static bool didAllocateCompactUnwindSection; static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size, unsigned alignment, @@ -41,6 +43,8 @@ static uint8_t *roundTripAllocateDataSection(void *object, uintptr_t size, unsigned sectionID, const char *sectionName, LLVMBool isReadOnly) { + if (!strcmp(sectionName, "__compact_unwind")) + didAllocateCompactUnwindSection = true; return static_cast<SectionMemoryManager*>(object)->allocateDataSection( size, alignment, sectionID, sectionName, isReadOnly); } @@ -135,6 +139,7 @@ protected: virtual void SetUp() { didCallAllocateCodeSection = false; + didAllocateCompactUnwindSection = false; Module = 0; Function = 0; Engine = 0; @@ -168,6 +173,36 @@ protected: LLVMDisposeBuilder(builder); } + void buildFunctionThatUsesStackmap() { + Module = LLVMModuleCreateWithName("simple_module"); + + LLVMSetTarget(Module, HostTriple.c_str()); + + LLVMTypeRef stackmapParamTypes[] = { LLVMInt64Type(), LLVMInt32Type() }; + LLVMValueRef stackmap = LLVMAddFunction( + Module, "llvm.experimental.stackmap", + LLVMFunctionType(LLVMVoidType(), stackmapParamTypes, 2, 1)); + LLVMSetLinkage(stackmap, LLVMExternalLinkage); + + Function = LLVMAddFunction( + Module, "simple_function", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0)); + + LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry"); + LLVMBuilderRef builder = LLVMCreateBuilder(); + LLVMPositionBuilderAtEnd(builder, entry); + LLVMValueRef stackmapArgs[] = { + LLVMConstInt(LLVMInt64Type(), 0, 0), LLVMConstInt(LLVMInt32Type(), 5, 0), + LLVMConstInt(LLVMInt32Type(), 42, 0) + }; + LLVMBuildCall(builder, stackmap, stackmapArgs, 3, ""); + LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0)); + + LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error); + LLVMDisposeMessage(Error); + + LLVMDisposeBuilder(builder); + } + void buildModuleWithCodeAndData() { Module = LLVMModuleCreateWithName("simple_module"); @@ -248,6 +283,38 @@ protected: LLVMDisposePassManager(pass); } + void buildAndRunOptPasses() { + LLVMPassManagerBuilderRef passBuilder; + + passBuilder = LLVMPassManagerBuilderCreate(); + LLVMPassManagerBuilderSetOptLevel(passBuilder, 2); + LLVMPassManagerBuilderSetSizeLevel(passBuilder, 0); + + LLVMPassManagerRef functionPasses = + LLVMCreateFunctionPassManagerForModule(Module); + LLVMPassManagerRef modulePasses = + LLVMCreatePassManager(); + + LLVMAddTargetData(LLVMGetExecutionEngineTargetData(Engine), modulePasses); + + LLVMPassManagerBuilderPopulateFunctionPassManager(passBuilder, + functionPasses); + LLVMPassManagerBuilderPopulateModulePassManager(passBuilder, modulePasses); + + LLVMPassManagerBuilderDispose(passBuilder); + + LLVMInitializeFunctionPassManager(functionPasses); + for (LLVMValueRef value = LLVMGetFirstFunction(Module); + value; value = LLVMGetNextFunction(value)) + LLVMRunFunctionPassManager(functionPasses, value); + LLVMFinalizeFunctionPassManager(functionPasses); + + LLVMRunPassManager(modulePasses, Module); + + LLVMDisposePassManager(functionPasses); + LLVMDisposePassManager(modulePasses); + } + LLVMModuleRef Module; LLVMValueRef Function; LLVMValueRef Function2; @@ -293,6 +360,29 @@ TEST_F(MCJITCAPITest, custom_memory_manager) { EXPECT_TRUE(didCallAllocateCodeSection); } +TEST_F(MCJITCAPITest, stackmap_creates_compact_unwind_on_darwin) { + SKIP_UNSUPPORTED_PLATFORM; + + buildFunctionThatUsesStackmap(); + buildMCJITOptions(); + useRoundTripSectionMemoryManager(); + buildMCJITEngine(); + buildAndRunOptPasses(); + + union { + void *raw; + int (*usable)(); + } functionPointer; + functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function); + + EXPECT_EQ(42, functionPointer.usable()); + EXPECT_TRUE(didCallAllocateCodeSection); + + EXPECT_TRUE( + Triple(HostTriple).getOS() != Triple::Darwin || + didAllocateCompactUnwindSection); +} + TEST_F(MCJITCAPITest, reserve_allocation_space) { SKIP_UNSUPPORTED_PLATFORM; |