llvm.org GIT mirror llvm / 23ffb3e
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@201826 91177308-0d34-0410-b5e6-96231b3b80d8 Filip Pizlo 5 years ago
5 changed file(s) with 95 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
457457 //===------------------------ Stackmap Intrinsics -------------------------===//
458458 //
459459 def int_experimental_stackmap : Intrinsic<[],
460 [llvm_i64_ty, llvm_i32_ty, llvm_vararg_ty]>;
460 [llvm_i64_ty, llvm_i32_ty, llvm_vararg_ty],
461 [Throws]>;
461462 def int_experimental_patchpoint_void : Intrinsic<[],
462463 [llvm_i64_ty, llvm_i32_ty,
463464 llvm_ptr_ty, llvm_i32_ty,
11 Analysis
22 Core
33 ExecutionEngine
4 IPO
45 JIT
56 MCJIT
67 ScalarOpts
1717 #include "llvm-c/ExecutionEngine.h"
1818 #include "llvm-c/Target.h"
1919 #include "llvm-c/Transforms/Scalar.h"
20 #include "llvm-c/Transforms/PassManagerBuilder.h"
2021 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
2122 #include "llvm/Support/Host.h"
2223 #include "gtest/gtest.h"
2526 using namespace llvm;
2627
2728 static bool didCallAllocateCodeSection;
29 static bool didAllocateCompactUnwindSection;
2830
2931 static uint8_t *roundTripAllocateCodeSection(void *object, uintptr_t size,
3032 unsigned alignment,
4042 unsigned sectionID,
4143 const char *sectionName,
4244 LLVMBool isReadOnly) {
45 if (!strcmp(sectionName, "__compact_unwind"))
46 didAllocateCompactUnwindSection = true;
4347 return static_cast(object)->allocateDataSection(
4448 size, alignment, sectionID, sectionName, isReadOnly);
4549 }
134138
135139 virtual void SetUp() {
136140 didCallAllocateCodeSection = false;
141 didAllocateCompactUnwindSection = false;
137142 Module = 0;
138143 Function = 0;
139144 Engine = 0;
159164 LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry");
160165 LLVMBuilderRef builder = LLVMCreateBuilder();
161166 LLVMPositionBuilderAtEnd(builder, entry);
167 LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0));
168
169 LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
170 LLVMDisposeMessage(Error);
171
172 LLVMDisposeBuilder(builder);
173 }
174
175 void buildFunctionThatUsesStackmap() {
176 Module = LLVMModuleCreateWithName("simple_module");
177
178 LLVMSetTarget(Module, HostTriple.c_str());
179
180 LLVMTypeRef stackmapParamTypes[] = { LLVMInt64Type(), LLVMInt32Type() };
181 LLVMValueRef stackmap = LLVMAddFunction(
182 Module, "llvm.experimental.stackmap",
183 LLVMFunctionType(LLVMVoidType(), stackmapParamTypes, 2, 1));
184 LLVMSetLinkage(stackmap, LLVMExternalLinkage);
185
186 Function = LLVMAddFunction(
187 Module, "simple_function", LLVMFunctionType(LLVMInt32Type(), 0, 0, 0));
188
189 LLVMBasicBlockRef entry = LLVMAppendBasicBlock(Function, "entry");
190 LLVMBuilderRef builder = LLVMCreateBuilder();
191 LLVMPositionBuilderAtEnd(builder, entry);
192 LLVMValueRef stackmapArgs[] = {
193 LLVMConstInt(LLVMInt64Type(), 0, 0), LLVMConstInt(LLVMInt32Type(), 5, 0),
194 LLVMConstInt(LLVMInt32Type(), 42, 0)
195 };
196 LLVMBuildCall(builder, stackmap, stackmapArgs, 3, "");
162197 LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 42, 0));
163198
164199 LLVMVerifyModule(Module, LLVMAbortProcessAction, &Error);
245280 LLVMAddInstructionCombiningPass(pass);
246281 LLVMRunPassManager(pass, Module);
247282 LLVMDisposePassManager(pass);
283 }
284
285 void buildAndRunOptPasses() {
286 LLVMPassManagerBuilderRef passBuilder;
287
288 passBuilder = LLVMPassManagerBuilderCreate();
289 LLVMPassManagerBuilderSetOptLevel(passBuilder, 2);
290 LLVMPassManagerBuilderSetSizeLevel(passBuilder, 0);
291
292 LLVMPassManagerRef functionPasses =
293 LLVMCreateFunctionPassManagerForModule(Module);
294 LLVMPassManagerRef modulePasses =
295 LLVMCreatePassManager();
296
297 LLVMAddTargetData(LLVMGetExecutionEngineTargetData(Engine), modulePasses);
298
299 LLVMPassManagerBuilderPopulateFunctionPassManager(passBuilder,
300 functionPasses);
301 LLVMPassManagerBuilderPopulateModulePassManager(passBuilder, modulePasses);
302
303 LLVMPassManagerBuilderDispose(passBuilder);
304
305 LLVMInitializeFunctionPassManager(functionPasses);
306 for (LLVMValueRef value = LLVMGetFirstFunction(Module);
307 value; value = LLVMGetNextFunction(value))
308 LLVMRunFunctionPassManager(functionPasses, value);
309 LLVMFinalizeFunctionPassManager(functionPasses);
310
311 LLVMRunPassManager(modulePasses, Module);
312
313 LLVMDisposePassManager(functionPasses);
314 LLVMDisposePassManager(modulePasses);
248315 }
249316
250317 LLVMModuleRef Module;
292359 EXPECT_TRUE(didCallAllocateCodeSection);
293360 }
294361
362 TEST_F(MCJITCAPITest, stackmap_creates_compact_unwind_on_darwin) {
363 SKIP_UNSUPPORTED_PLATFORM;
364
365 buildFunctionThatUsesStackmap();
366 buildMCJITOptions();
367 useRoundTripSectionMemoryManager();
368 buildMCJITEngine();
369 buildAndRunOptPasses();
370
371 union {
372 void *raw;
373 int (*usable)();
374 } functionPointer;
375 functionPointer.raw = LLVMGetPointerToGlobal(Engine, Function);
376
377 EXPECT_EQ(42, functionPointer.usable());
378 EXPECT_TRUE(didCallAllocateCodeSection);
379
380 EXPECT_TRUE(
381 Triple(HostTriple).getOS() != Triple::Darwin ||
382 didAllocateCompactUnwindSection);
383 }
384
295385 TEST_F(MCJITCAPITest, reserve_allocation_space) {
296386 SKIP_UNSUPPORTED_PLATFORM;
297387
88
99 LEVEL = ../../..
1010 TESTNAME = MCJIT
11 LINK_COMPONENTS := core jit mcjit native support
11 LINK_COMPONENTS := core ipo jit mcjit native support
1212
1313 include $(LEVEL)/Makefile.config
1414 include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
665665 OS << " }\n";
666666 } else {
667667 OS << " return AttributeSet();\n";
668 OS << " }\n";
668669 }
669670 }
670671