1 //===- JITTest.cpp - Unit tests for the JIT -------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "gtest/gtest.h"
11 #include "llvm/ADT/OwningPtr.h"
12 #include "llvm/ADT/SmallPtrSet.h"
13 #include "llvm/Assembly/Parser.h"
14 #include "llvm/BasicBlock.h"
15 #include "llvm/Bitcode/ReaderWriter.h"
16 #include "llvm/Constant.h"
17 #include "llvm/Constants.h"
18 #include "llvm/DerivedTypes.h"
19 #include "llvm/ExecutionEngine/JIT.h"
20 #include "llvm/ExecutionEngine/JITMemoryManager.h"
21 #include "llvm/Function.h"
22 #include "llvm/GlobalValue.h"
23 #include "llvm/GlobalVariable.h"
24 #include "llvm/LLVMContext.h"
25 #include "llvm/Module.h"
26 #include "llvm/Support/IRBuilder.h"
27 #include "llvm/Support/MemoryBuffer.h"
28 #include "llvm/Support/SourceMgr.h"
29 #include "llvm/Support/TypeBuilder.h"
30 #include "llvm/Target/TargetSelect.h"
31 #include "llvm/Type.h"
39 Function
*makeReturnGlobal(std::string Name
, GlobalVariable
*G
, Module
*M
) {
40 std::vector
<const Type
*> params
;
41 const FunctionType
*FTy
= FunctionType::get(G
->getType()->getElementType(),
43 Function
*F
= Function::Create(FTy
, GlobalValue::ExternalLinkage
, Name
, M
);
44 BasicBlock
*Entry
= BasicBlock::Create(M
->getContext(), "entry", F
);
45 IRBuilder
<> builder(Entry
);
46 Value
*Load
= builder
.CreateLoad(G
);
47 const Type
*GTy
= G
->getType()->getElementType();
48 Value
*Add
= builder
.CreateAdd(Load
, ConstantInt::get(GTy
, 1LL));
49 builder
.CreateStore(Add
, G
);
50 builder
.CreateRet(Add
);
54 std::string
DumpFunction(const Function
*F
) {
56 raw_string_ostream(Result
) << "" << *F
;
60 class RecordingJITMemoryManager
: public JITMemoryManager
{
61 const OwningPtr
<JITMemoryManager
> Base
;
63 RecordingJITMemoryManager()
64 : Base(JITMemoryManager::CreateDefaultMemManager()) {
68 virtual void setMemoryWritable() { Base
->setMemoryWritable(); }
69 virtual void setMemoryExecutable() { Base
->setMemoryExecutable(); }
70 virtual void setPoisonMemory(bool poison
) { Base
->setPoisonMemory(poison
); }
71 virtual void AllocateGOT() { Base
->AllocateGOT(); }
72 virtual uint8_t *getGOTBase() const { return Base
->getGOTBase(); }
73 struct StartFunctionBodyCall
{
74 StartFunctionBodyCall(uint8_t *Result
, const Function
*F
,
75 uintptr_t ActualSize
, uintptr_t ActualSizeResult
)
76 : Result(Result
), F(F
), F_dump(DumpFunction(F
)),
77 ActualSize(ActualSize
), ActualSizeResult(ActualSizeResult
) {}
82 uintptr_t ActualSizeResult
;
84 std::vector
<StartFunctionBodyCall
> startFunctionBodyCalls
;
85 virtual uint8_t *startFunctionBody(const Function
*F
,
86 uintptr_t &ActualSize
) {
87 uintptr_t InitialActualSize
= ActualSize
;
88 uint8_t *Result
= Base
->startFunctionBody(F
, ActualSize
);
89 startFunctionBodyCalls
.push_back(
90 StartFunctionBodyCall(Result
, F
, InitialActualSize
, ActualSize
));
94 virtual uint8_t *allocateStub(const GlobalValue
* F
, unsigned StubSize
,
97 return Base
->allocateStub(F
, StubSize
, Alignment
);
99 struct EndFunctionBodyCall
{
100 EndFunctionBodyCall(const Function
*F
, uint8_t *FunctionStart
,
101 uint8_t *FunctionEnd
)
102 : F(F
), F_dump(DumpFunction(F
)),
103 FunctionStart(FunctionStart
), FunctionEnd(FunctionEnd
) {}
106 uint8_t *FunctionStart
;
107 uint8_t *FunctionEnd
;
109 std::vector
<EndFunctionBodyCall
> endFunctionBodyCalls
;
110 virtual void endFunctionBody(const Function
*F
, uint8_t *FunctionStart
,
111 uint8_t *FunctionEnd
) {
112 endFunctionBodyCalls
.push_back(
113 EndFunctionBodyCall(F
, FunctionStart
, FunctionEnd
));
114 Base
->endFunctionBody(F
, FunctionStart
, FunctionEnd
);
116 virtual uint8_t *allocateSpace(intptr_t Size
, unsigned Alignment
) {
117 return Base
->allocateSpace(Size
, Alignment
);
119 virtual uint8_t *allocateGlobal(uintptr_t Size
, unsigned Alignment
) {
120 return Base
->allocateGlobal(Size
, Alignment
);
122 struct DeallocateFunctionBodyCall
{
123 DeallocateFunctionBodyCall(const void *Body
) : Body(Body
) {}
126 std::vector
<DeallocateFunctionBodyCall
> deallocateFunctionBodyCalls
;
127 virtual void deallocateFunctionBody(void *Body
) {
128 deallocateFunctionBodyCalls
.push_back(DeallocateFunctionBodyCall(Body
));
129 Base
->deallocateFunctionBody(Body
);
131 struct DeallocateExceptionTableCall
{
132 DeallocateExceptionTableCall(const void *ET
) : ET(ET
) {}
135 std::vector
<DeallocateExceptionTableCall
> deallocateExceptionTableCalls
;
136 virtual void deallocateExceptionTable(void *ET
) {
137 deallocateExceptionTableCalls
.push_back(DeallocateExceptionTableCall(ET
));
138 Base
->deallocateExceptionTable(ET
);
140 struct StartExceptionTableCall
{
141 StartExceptionTableCall(uint8_t *Result
, const Function
*F
,
142 uintptr_t ActualSize
, uintptr_t ActualSizeResult
)
143 : Result(Result
), F(F
), F_dump(DumpFunction(F
)),
144 ActualSize(ActualSize
), ActualSizeResult(ActualSizeResult
) {}
148 uintptr_t ActualSize
;
149 uintptr_t ActualSizeResult
;
151 std::vector
<StartExceptionTableCall
> startExceptionTableCalls
;
152 virtual uint8_t* startExceptionTable(const Function
* F
,
153 uintptr_t &ActualSize
) {
154 uintptr_t InitialActualSize
= ActualSize
;
155 uint8_t *Result
= Base
->startExceptionTable(F
, ActualSize
);
156 startExceptionTableCalls
.push_back(
157 StartExceptionTableCall(Result
, F
, InitialActualSize
, ActualSize
));
160 struct EndExceptionTableCall
{
161 EndExceptionTableCall(const Function
*F
, uint8_t *TableStart
,
162 uint8_t *TableEnd
, uint8_t* FrameRegister
)
163 : F(F
), F_dump(DumpFunction(F
)),
164 TableStart(TableStart
), TableEnd(TableEnd
),
165 FrameRegister(FrameRegister
) {}
170 uint8_t *FrameRegister
;
172 std::vector
<EndExceptionTableCall
> endExceptionTableCalls
;
173 virtual void endExceptionTable(const Function
*F
, uint8_t *TableStart
,
174 uint8_t *TableEnd
, uint8_t* FrameRegister
) {
175 endExceptionTableCalls
.push_back(
176 EndExceptionTableCall(F
, TableStart
, TableEnd
, FrameRegister
));
177 return Base
->endExceptionTable(F
, TableStart
, TableEnd
, FrameRegister
);
181 bool LoadAssemblyInto(Module
*M
, const char *assembly
) {
184 NULL
!= ParseAssemblyString(assembly
, M
, Error
, M
->getContext());
186 raw_string_ostream
os(errMsg
);
188 EXPECT_TRUE(success
) << os
.str();
192 class JITTest
: public testing::Test
{
194 virtual void SetUp() {
195 M
= new Module("<main>", Context
);
196 RJMM
= new RecordingJITMemoryManager
;
197 RJMM
->setPoisonMemory(true);
199 TheJIT
.reset(EngineBuilder(M
).setEngineKind(EngineKind::JIT
)
200 .setJITMemoryManager(RJMM
)
201 .setErrorStr(&Error
).create());
202 ASSERT_TRUE(TheJIT
.get() != NULL
) << Error
;
205 void LoadAssembly(const char *assembly
) {
206 LoadAssemblyInto(M
, assembly
);
210 Module
*M
; // Owned by ExecutionEngine.
211 RecordingJITMemoryManager
*RJMM
;
212 OwningPtr
<ExecutionEngine
> TheJIT
;
215 // Regression test for a bug. The JIT used to allocate globals inside the same
216 // memory block used for the function, and when the function code was freed,
217 // the global was left in the same place. This test allocates a function
218 // that uses and global, deallocates it, and then makes sure that the global
219 // stays alive after that.
220 TEST(JIT
, GlobalInFunction
) {
222 Module
*M
= new Module("<main>", context
);
224 JITMemoryManager
*MemMgr
= JITMemoryManager::CreateDefaultMemManager();
225 // Tell the memory manager to poison freed memory so that accessing freed
226 // memory is more easily tested.
227 MemMgr
->setPoisonMemory(true);
229 OwningPtr
<ExecutionEngine
> JIT(EngineBuilder(M
)
230 .setEngineKind(EngineKind::JIT
)
232 .setJITMemoryManager(MemMgr
)
233 // The next line enables the fix:
234 .setAllocateGVsWithCode(false)
236 ASSERT_EQ(Error
, "");
238 // Create a global variable.
239 const Type
*GTy
= Type::getInt32Ty(context
);
240 GlobalVariable
*G
= new GlobalVariable(
243 false, // Not constant.
244 GlobalValue::InternalLinkage
,
245 Constant::getNullValue(GTy
),
248 // Make a function that points to a global.
249 Function
*F1
= makeReturnGlobal("F1", G
, M
);
251 // Get the pointer to the native code to force it to JIT the function and
252 // allocate space for the global.
254 reinterpret_cast<void(*)()>((intptr_t)JIT
->getPointerToFunction(F1
));
256 // Since F1 was codegen'd, a pointer to G should be available.
257 int32_t *GPtr
= (int32_t*)JIT
->getPointerToGlobalIfAvailable(G
);
258 ASSERT_NE((int32_t*)NULL
, GPtr
);
261 // F1() should increment G.
265 // Make a second function identical to the first, referring to the same
267 Function
*F2
= makeReturnGlobal("F2", G
, M
);
269 reinterpret_cast<void(*)()>((intptr_t)JIT
->getPointerToFunction(F2
));
271 // F2() should increment G.
276 JIT
->freeMachineCodeForFunction(F1
);
278 // F2() should *still* increment G.
283 int PlusOne(int arg
) {
287 TEST_F(JITTest
, FarCallToKnownFunction
) {
288 // x86-64 can only make direct calls to functions within 32 bits of
289 // the current PC. To call anything farther away, we have to load
290 // the address into a register and call through the register. The
291 // current JIT does this by allocating a stub for any far call.
292 // There was a bug in which the JIT tried to emit a direct call when
293 // the target was already in the JIT's global mappings and lazy
294 // compilation was disabled.
296 Function
*KnownFunction
= Function::Create(
297 TypeBuilder
<int(int), false>::get(Context
),
298 GlobalValue::ExternalLinkage
, "known", M
);
299 TheJIT
->addGlobalMapping(KnownFunction
, (void*)(intptr_t)PlusOne
);
301 // int test() { return known(7); }
302 Function
*TestFunction
= Function::Create(
303 TypeBuilder
<int(), false>::get(Context
),
304 GlobalValue::ExternalLinkage
, "test", M
);
305 BasicBlock
*Entry
= BasicBlock::Create(Context
, "entry", TestFunction
);
306 IRBuilder
<> Builder(Entry
);
307 Value
*result
= Builder
.CreateCall(
309 ConstantInt::get(TypeBuilder
<int, false>::get(Context
), 7));
310 Builder
.CreateRet(result
);
312 TheJIT
->DisableLazyCompilation(true);
313 int (*TestFunctionPtr
)() = reinterpret_cast<int(*)()>(
314 (intptr_t)TheJIT
->getPointerToFunction(TestFunction
));
315 // This used to crash in trying to call PlusOne().
316 EXPECT_EQ(8, TestFunctionPtr());
319 // Test a function C which calls A and B which call each other.
320 TEST_F(JITTest
, NonLazyCompilationStillNeedsStubs
) {
321 TheJIT
->DisableLazyCompilation(true);
323 const FunctionType
*Func1Ty
=
324 cast
<FunctionType
>(TypeBuilder
<void(void), false>::get(Context
));
325 std::vector
<const Type
*> arg_types
;
326 arg_types
.push_back(Type::getInt1Ty(Context
));
327 const FunctionType
*FuncTy
= FunctionType::get(
328 Type::getVoidTy(Context
), arg_types
, false);
329 Function
*Func1
= Function::Create(Func1Ty
, Function::ExternalLinkage
,
331 Function
*Func2
= Function::Create(FuncTy
, Function::InternalLinkage
,
333 Function
*Func3
= Function::Create(FuncTy
, Function::InternalLinkage
,
335 BasicBlock
*Block1
= BasicBlock::Create(Context
, "block1", Func1
);
336 BasicBlock
*Block2
= BasicBlock::Create(Context
, "block2", Func2
);
337 BasicBlock
*True2
= BasicBlock::Create(Context
, "cond_true", Func2
);
338 BasicBlock
*False2
= BasicBlock::Create(Context
, "cond_false", Func2
);
339 BasicBlock
*Block3
= BasicBlock::Create(Context
, "block3", Func3
);
340 BasicBlock
*True3
= BasicBlock::Create(Context
, "cond_true", Func3
);
341 BasicBlock
*False3
= BasicBlock::Create(Context
, "cond_false", Func3
);
343 // Make Func1 call Func2(0) and Func3(0).
344 IRBuilder
<> Builder(Block1
);
345 Builder
.CreateCall(Func2
, ConstantInt::getTrue(Context
));
346 Builder
.CreateCall(Func3
, ConstantInt::getTrue(Context
));
347 Builder
.CreateRetVoid();
349 // void Func2(bool b) { if (b) { Func3(false); return; } return; }
350 Builder
.SetInsertPoint(Block2
);
351 Builder
.CreateCondBr(Func2
->arg_begin(), True2
, False2
);
352 Builder
.SetInsertPoint(True2
);
353 Builder
.CreateCall(Func3
, ConstantInt::getFalse(Context
));
354 Builder
.CreateRetVoid();
355 Builder
.SetInsertPoint(False2
);
356 Builder
.CreateRetVoid();
358 // void Func3(bool b) { if (b) { Func2(false); return; } return; }
359 Builder
.SetInsertPoint(Block3
);
360 Builder
.CreateCondBr(Func3
->arg_begin(), True3
, False3
);
361 Builder
.SetInsertPoint(True3
);
362 Builder
.CreateCall(Func2
, ConstantInt::getFalse(Context
));
363 Builder
.CreateRetVoid();
364 Builder
.SetInsertPoint(False3
);
365 Builder
.CreateRetVoid();
367 // Compile the function to native code
369 reinterpret_cast<void(*)()>((intptr_t)TheJIT
->getPointerToFunction(Func1
));
374 // Regression test for PR5162. This used to trigger an AssertingVH inside the
375 // JIT's Function to stub mapping.
376 TEST_F(JITTest
, NonLazyLeaksNoStubs
) {
377 TheJIT
->DisableLazyCompilation(true);
379 // Create two functions with a single basic block each.
380 const FunctionType
*FuncTy
=
381 cast
<FunctionType
>(TypeBuilder
<int(), false>::get(Context
));
382 Function
*Func1
= Function::Create(FuncTy
, Function::ExternalLinkage
,
384 Function
*Func2
= Function::Create(FuncTy
, Function::InternalLinkage
,
386 BasicBlock
*Block1
= BasicBlock::Create(Context
, "block1", Func1
);
387 BasicBlock
*Block2
= BasicBlock::Create(Context
, "block2", Func2
);
389 // The first function calls the second and returns the result
390 IRBuilder
<> Builder(Block1
);
391 Value
*Result
= Builder
.CreateCall(Func2
);
392 Builder
.CreateRet(Result
);
394 // The second function just returns a constant
395 Builder
.SetInsertPoint(Block2
);
396 Builder
.CreateRet(ConstantInt::get(TypeBuilder
<int, false>::get(Context
),42));
398 // Compile the function to native code
399 (void)TheJIT
->getPointerToFunction(Func1
);
401 // Free the JIT state for the functions
402 TheJIT
->freeMachineCodeForFunction(Func1
);
403 TheJIT
->freeMachineCodeForFunction(Func2
);
405 // Delete the first function (and show that is has no users)
406 EXPECT_EQ(Func1
->getNumUses(), 0u);
407 Func1
->eraseFromParent();
409 // Delete the second function (and show that it has no users - it had one,
410 // func1 but that's gone now)
411 EXPECT_EQ(Func2
->getNumUses(), 0u);
412 Func2
->eraseFromParent();
415 TEST_F(JITTest
, ModuleDeletion
) {
416 TheJIT
->DisableLazyCompilation(false);
417 LoadAssembly("define void @main() { "
418 " call i32 @computeVal() "
422 "define internal i32 @computeVal() { "
425 Function
*func
= M
->getFunction("main");
426 TheJIT
->getPointerToFunction(func
);
427 TheJIT
->removeModule(M
);
430 SmallPtrSet
<const void*, 2> FunctionsDeallocated
;
431 for (unsigned i
= 0, e
= RJMM
->deallocateFunctionBodyCalls
.size();
433 FunctionsDeallocated
.insert(RJMM
->deallocateFunctionBodyCalls
[i
].Body
);
435 for (unsigned i
= 0, e
= RJMM
->startFunctionBodyCalls
.size(); i
!= e
; ++i
) {
436 EXPECT_TRUE(FunctionsDeallocated
.count(
437 RJMM
->startFunctionBodyCalls
[i
].Result
))
438 << "Function leaked: \n" << RJMM
->startFunctionBodyCalls
[i
].F_dump
;
440 EXPECT_EQ(RJMM
->startFunctionBodyCalls
.size(),
441 RJMM
->deallocateFunctionBodyCalls
.size());
443 SmallPtrSet
<const void*, 2> ExceptionTablesDeallocated
;
444 unsigned NumTablesDeallocated
= 0;
445 for (unsigned i
= 0, e
= RJMM
->deallocateExceptionTableCalls
.size();
447 ExceptionTablesDeallocated
.insert(
448 RJMM
->deallocateExceptionTableCalls
[i
].ET
);
449 if (RJMM
->deallocateExceptionTableCalls
[i
].ET
!= NULL
) {
450 // If JITEmitDebugInfo is off, we'll "deallocate" NULL, which doesn't
451 // appear in startExceptionTableCalls.
452 NumTablesDeallocated
++;
455 for (unsigned i
= 0, e
= RJMM
->startExceptionTableCalls
.size(); i
!= e
; ++i
) {
456 EXPECT_TRUE(ExceptionTablesDeallocated
.count(
457 RJMM
->startExceptionTableCalls
[i
].Result
))
458 << "Function's exception table leaked: \n"
459 << RJMM
->startExceptionTableCalls
[i
].F_dump
;
461 EXPECT_EQ(RJMM
->startExceptionTableCalls
.size(),
462 NumTablesDeallocated
);
465 // ARM and PPC still emit stubs for calls since the target may be too far away
466 // to call directly. This #if can probably be removed when
467 // http://llvm.org/PR5201 is fixed.
468 #if !defined(__arm__) && !defined(__powerpc__) && !defined(__ppc__)
469 typedef int (*FooPtr
) ();
471 TEST_F(JITTest
, NoStubs
) {
472 LoadAssembly("define void @bar() {"
477 "define i32 @foo() {"
483 "define i32 @main() {"
485 "%0 = call i32 @foo()"
489 Function
*foo
= M
->getFunction("foo");
490 uintptr_t tmp
= (uintptr_t)(TheJIT
->getPointerToFunction(foo
));
491 FooPtr ptr
= (FooPtr
)(tmp
);
495 // We should now allocate no more stubs, we have the code to foo
496 // and the existing stub for bar.
497 int stubsBefore
= RJMM
->stubsAllocated
;
498 Function
*func
= M
->getFunction("main");
499 TheJIT
->getPointerToFunction(func
);
501 Function
*bar
= M
->getFunction("bar");
502 TheJIT
->getPointerToFunction(bar
);
504 ASSERT_EQ(stubsBefore
, RJMM
->stubsAllocated
);
506 #endif // !ARM && !PPC
508 TEST_F(JITTest
, FunctionPointersOutliveTheirCreator
) {
509 TheJIT
->DisableLazyCompilation(true);
510 LoadAssembly("define i8()* @get_foo_addr() { "
514 "define i8 @foo() { "
517 Function
*F_get_foo_addr
= M
->getFunction("get_foo_addr");
519 typedef char(*fooT
)();
520 fooT (*get_foo_addr
)() = reinterpret_cast<fooT(*)()>(
521 (intptr_t)TheJIT
->getPointerToFunction(F_get_foo_addr
));
522 fooT foo_addr
= get_foo_addr();
524 // Now free get_foo_addr. This should not free the machine code for foo or
525 // any call stub returned as foo's canonical address.
526 TheJIT
->freeMachineCodeForFunction(F_get_foo_addr
);
528 // Check by calling the reported address of foo.
529 EXPECT_EQ(42, foo_addr());
531 // The reported address should also be the same as the result of a subsequent
532 // getPointerToFunction(foo).
534 // Fails until PR5126 is fixed:
535 Function
*F_foo
= M
->getFunction("foo");
536 fooT foo
= reinterpret_cast<fooT
>(
537 (intptr_t)TheJIT
->getPointerToFunction(F_foo
));
538 EXPECT_EQ((intptr_t)foo
, (intptr_t)foo_addr
);
542 // ARM doesn't have an implementation of replaceMachineCodeForFunction(), so
543 // recompileAndRelinkFunction doesn't work.
544 #if !defined(__arm__)
545 TEST_F(JITTest
, FunctionIsRecompiledAndRelinked
) {
546 Function
*F
= Function::Create(TypeBuilder
<int(void), false>::get(Context
),
547 GlobalValue::ExternalLinkage
, "test", M
);
548 BasicBlock
*Entry
= BasicBlock::Create(Context
, "entry", F
);
549 IRBuilder
<> Builder(Entry
);
550 Value
*Val
= ConstantInt::get(TypeBuilder
<int, false>::get(Context
), 1);
551 Builder
.CreateRet(Val
);
553 TheJIT
->DisableLazyCompilation(true);
554 // Compile the function once, and make sure it works.
555 int (*OrigFPtr
)() = reinterpret_cast<int(*)()>(
556 (intptr_t)TheJIT
->recompileAndRelinkFunction(F
));
557 EXPECT_EQ(1, OrigFPtr());
559 // Now change the function to return a different value.
560 Entry
->eraseFromParent();
561 BasicBlock
*NewEntry
= BasicBlock::Create(Context
, "new_entry", F
);
562 Builder
.SetInsertPoint(NewEntry
);
563 Val
= ConstantInt::get(TypeBuilder
<int, false>::get(Context
), 2);
564 Builder
.CreateRet(Val
);
565 // Recompile it, which should produce a new function pointer _and_ update the
567 int (*NewFPtr
)() = reinterpret_cast<int(*)()>(
568 (intptr_t)TheJIT
->recompileAndRelinkFunction(F
));
570 EXPECT_EQ(2, NewFPtr())
571 << "The new pointer should call the new version of the function";
572 EXPECT_EQ(2, OrigFPtr())
573 << "The old pointer's target should now jump to the new version";
575 #endif // !defined(__arm__)
577 } // anonymous namespace
578 // This variable is intentionally defined differently in the statically-compiled
579 // program from the IR input to the JIT to assert that the JIT doesn't use its
581 extern "C" int32_t JITTest_AvailableExternallyGlobal
;
582 int32_t JITTest_AvailableExternallyGlobal
= 42;
585 TEST_F(JITTest
, AvailableExternallyGlobalIsntEmitted
) {
586 TheJIT
->DisableLazyCompilation(true);
587 LoadAssembly("@JITTest_AvailableExternallyGlobal = "
588 " available_externally global i32 7 "
590 "define i32 @loader() { "
591 " %result = load i32* @JITTest_AvailableExternallyGlobal "
594 Function
*loaderIR
= M
->getFunction("loader");
596 int32_t (*loader
)() = reinterpret_cast<int32_t(*)()>(
597 (intptr_t)TheJIT
->getPointerToFunction(loaderIR
));
598 EXPECT_EQ(42, loader()) << "func should return 42 from the external global,"
599 << " not 7 from the IR version.";
602 } // anonymous namespace
603 // This function is intentionally defined differently in the statically-compiled
604 // program from the IR input to the JIT to assert that the JIT doesn't use its
606 extern "C" int32_t JITTest_AvailableExternallyFunction() {
611 TEST_F(JITTest
, AvailableExternallyFunctionIsntCompiled
) {
612 TheJIT
->DisableLazyCompilation(true);
613 LoadAssembly("define available_externally i32 "
614 " @JITTest_AvailableExternallyFunction() { "
618 "define i32 @func() { "
619 " %result = tail call i32 "
620 " @JITTest_AvailableExternallyFunction() "
623 Function
*funcIR
= M
->getFunction("func");
625 int32_t (*func
)() = reinterpret_cast<int32_t(*)()>(
626 (intptr_t)TheJIT
->getPointerToFunction(funcIR
));
627 EXPECT_EQ(42, func()) << "func should return 42 from the static version,"
628 << " not 7 from the IR version.";
631 TEST_F(JITTest
, EscapedLazyStubStillCallable
) {
632 TheJIT
->DisableLazyCompilation(false);
633 LoadAssembly("define internal i32 @stubbed() { "
637 "define i32()* @get_stub() { "
638 " ret i32()* @stubbed "
640 typedef int32_t(*StubTy
)();
642 // Call get_stub() to get the address of @stubbed without actually JITting it.
643 Function
*get_stubIR
= M
->getFunction("get_stub");
644 StubTy (*get_stub
)() = reinterpret_cast<StubTy(*)()>(
645 (intptr_t)TheJIT
->getPointerToFunction(get_stubIR
));
646 StubTy stubbed
= get_stub();
647 // Now get_stubIR is the only reference to stubbed's stub.
648 get_stubIR
->eraseFromParent();
649 // Now there are no references inside the JIT, but we've got a pointer outside
650 // it. The stub should be callable and return the right value.
651 EXPECT_EQ(42, stubbed());
654 // Converts the LLVM assembly to bitcode and returns it in a std::string. An
655 // empty string indicates an error.
656 std::string
AssembleToBitcode(LLVMContext
&Context
, const char *Assembly
) {
657 Module
TempModule("TempModule", Context
);
658 if (!LoadAssemblyInto(&TempModule
, Assembly
)) {
663 raw_string_ostream
OS(Result
);
664 WriteBitcodeToFile(&TempModule
, OS
);
669 // Returns a newly-created ExecutionEngine that reads the bitcode in 'Bitcode'
670 // lazily. The associated Module (owned by the ExecutionEngine) is returned in
671 // M. Both will be NULL on an error. Bitcode must live at least as long as the
673 ExecutionEngine
*getJITFromBitcode(
674 LLVMContext
&Context
, const std::string
&Bitcode
, Module
*&M
) {
675 // c_str() is null-terminated like MemoryBuffer::getMemBuffer requires.
676 MemoryBuffer
*BitcodeBuffer
=
677 MemoryBuffer::getMemBuffer(Bitcode
, "Bitcode for test");
679 M
= getLazyBitcodeModule(BitcodeBuffer
, Context
, &errMsg
);
681 ADD_FAILURE() << errMsg
;
682 delete BitcodeBuffer
;
685 ExecutionEngine
*TheJIT
= EngineBuilder(M
)
686 .setEngineKind(EngineKind::JIT
)
687 .setErrorStr(&errMsg
)
689 if (TheJIT
== NULL
) {
690 ADD_FAILURE() << errMsg
;
698 TEST(LazyLoadedJITTest
, MaterializableAvailableExternallyFunctionIsntCompiled
) {
700 const std::string Bitcode
=
701 AssembleToBitcode(Context
,
702 "define available_externally i32 "
703 " @JITTest_AvailableExternallyFunction() { "
707 "define i32 @func() { "
708 " %result = tail call i32 "
709 " @JITTest_AvailableExternallyFunction() "
712 ASSERT_FALSE(Bitcode
.empty()) << "Assembling failed";
714 OwningPtr
<ExecutionEngine
> TheJIT(getJITFromBitcode(Context
, Bitcode
, M
));
715 ASSERT_TRUE(TheJIT
.get()) << "Failed to create JIT.";
716 TheJIT
->DisableLazyCompilation(true);
718 Function
*funcIR
= M
->getFunction("func");
719 Function
*availableFunctionIR
=
720 M
->getFunction("JITTest_AvailableExternallyFunction");
722 // Double-check that the available_externally function is still unmaterialized
723 // when getPointerToFunction needs to find out if it's available_externally.
724 EXPECT_TRUE(availableFunctionIR
->isMaterializable());
726 int32_t (*func
)() = reinterpret_cast<int32_t(*)()>(
727 (intptr_t)TheJIT
->getPointerToFunction(funcIR
));
728 EXPECT_EQ(42, func()) << "func should return 42 from the static version,"
729 << " not 7 from the IR version.";
732 TEST(LazyLoadedJITTest
, EagerCompiledRecursionThroughGhost
) {
734 const std::string Bitcode
=
735 AssembleToBitcode(Context
,
736 "define i32 @recur1(i32 %a) { "
737 " %zero = icmp eq i32 %a, 0 "
738 " br i1 %zero, label %done, label %notdone "
742 " %am1 = sub i32 %a, 1 "
743 " %result = call i32 @recur2(i32 %am1) "
747 "define i32 @recur2(i32 %b) { "
748 " %result = call i32 @recur1(i32 %b) "
751 ASSERT_FALSE(Bitcode
.empty()) << "Assembling failed";
753 OwningPtr
<ExecutionEngine
> TheJIT(getJITFromBitcode(Context
, Bitcode
, M
));
754 ASSERT_TRUE(TheJIT
.get()) << "Failed to create JIT.";
755 TheJIT
->DisableLazyCompilation(true);
757 Function
*recur1IR
= M
->getFunction("recur1");
758 Function
*recur2IR
= M
->getFunction("recur2");
759 EXPECT_TRUE(recur1IR
->isMaterializable());
760 EXPECT_TRUE(recur2IR
->isMaterializable());
762 int32_t (*recur1
)(int32_t) = reinterpret_cast<int32_t(*)(int32_t)>(
763 (intptr_t)TheJIT
->getPointerToFunction(recur1IR
));
764 EXPECT_EQ(3, recur1(4));
767 // This code is copied from JITEventListenerTest, but it only runs once for all
768 // the tests in this directory. Everything seems fine, but that's strange
770 class JITEnvironment
: public testing::Environment
{
771 virtual void SetUp() {
772 // Required to create a JIT.
773 InitializeNativeTarget();
776 testing::Environment
* const jit_env
=
777 testing::AddGlobalTestEnvironment(new JITEnvironment
);