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/Support/TargetSelect.h"
31
#include "llvm/Type.h"
39
Function *makeReturnGlobal(std::string Name, GlobalVariable *G, Module *M) {
40
std::vector<Type*> params;
41
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
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()) {
67
virtual void *getPointerToNamedFunction(const std::string &Name,
68
bool AbortOnFailure = true) {
69
return Base->getPointerToNamedFunction(Name, AbortOnFailure);
72
virtual void setMemoryWritable() { Base->setMemoryWritable(); }
73
virtual void setMemoryExecutable() { Base->setMemoryExecutable(); }
74
virtual void setPoisonMemory(bool poison) { Base->setPoisonMemory(poison); }
75
virtual void AllocateGOT() { Base->AllocateGOT(); }
76
virtual uint8_t *getGOTBase() const { return Base->getGOTBase(); }
77
struct StartFunctionBodyCall {
78
StartFunctionBodyCall(uint8_t *Result, const Function *F,
79
uintptr_t ActualSize, uintptr_t ActualSizeResult)
80
: Result(Result), F(F), F_dump(DumpFunction(F)),
81
ActualSize(ActualSize), ActualSizeResult(ActualSizeResult) {}
86
uintptr_t ActualSizeResult;
88
std::vector<StartFunctionBodyCall> startFunctionBodyCalls;
89
virtual uint8_t *startFunctionBody(const Function *F,
90
uintptr_t &ActualSize) {
91
uintptr_t InitialActualSize = ActualSize;
92
uint8_t *Result = Base->startFunctionBody(F, ActualSize);
93
startFunctionBodyCalls.push_back(
94
StartFunctionBodyCall(Result, F, InitialActualSize, ActualSize));
98
virtual uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize,
101
return Base->allocateStub(F, StubSize, Alignment);
103
struct EndFunctionBodyCall {
104
EndFunctionBodyCall(const Function *F, uint8_t *FunctionStart,
105
uint8_t *FunctionEnd)
106
: F(F), F_dump(DumpFunction(F)),
107
FunctionStart(FunctionStart), FunctionEnd(FunctionEnd) {}
110
uint8_t *FunctionStart;
111
uint8_t *FunctionEnd;
113
std::vector<EndFunctionBodyCall> endFunctionBodyCalls;
114
virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart,
115
uint8_t *FunctionEnd) {
116
endFunctionBodyCalls.push_back(
117
EndFunctionBodyCall(F, FunctionStart, FunctionEnd));
118
Base->endFunctionBody(F, FunctionStart, FunctionEnd);
120
virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
121
unsigned SectionID) {
122
return Base->allocateDataSection(Size, Alignment, SectionID);
124
virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
125
unsigned SectionID) {
126
return Base->allocateCodeSection(Size, Alignment, SectionID);
128
virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
129
return Base->allocateSpace(Size, Alignment);
131
virtual uint8_t *allocateGlobal(uintptr_t Size, unsigned Alignment) {
132
return Base->allocateGlobal(Size, Alignment);
134
struct DeallocateFunctionBodyCall {
135
DeallocateFunctionBodyCall(const void *Body) : Body(Body) {}
138
std::vector<DeallocateFunctionBodyCall> deallocateFunctionBodyCalls;
139
virtual void deallocateFunctionBody(void *Body) {
140
deallocateFunctionBodyCalls.push_back(DeallocateFunctionBodyCall(Body));
141
Base->deallocateFunctionBody(Body);
143
struct DeallocateExceptionTableCall {
144
DeallocateExceptionTableCall(const void *ET) : ET(ET) {}
147
std::vector<DeallocateExceptionTableCall> deallocateExceptionTableCalls;
148
virtual void deallocateExceptionTable(void *ET) {
149
deallocateExceptionTableCalls.push_back(DeallocateExceptionTableCall(ET));
150
Base->deallocateExceptionTable(ET);
152
struct StartExceptionTableCall {
153
StartExceptionTableCall(uint8_t *Result, const Function *F,
154
uintptr_t ActualSize, uintptr_t ActualSizeResult)
155
: Result(Result), F(F), F_dump(DumpFunction(F)),
156
ActualSize(ActualSize), ActualSizeResult(ActualSizeResult) {}
160
uintptr_t ActualSize;
161
uintptr_t ActualSizeResult;
163
std::vector<StartExceptionTableCall> startExceptionTableCalls;
164
virtual uint8_t* startExceptionTable(const Function* F,
165
uintptr_t &ActualSize) {
166
uintptr_t InitialActualSize = ActualSize;
167
uint8_t *Result = Base->startExceptionTable(F, ActualSize);
168
startExceptionTableCalls.push_back(
169
StartExceptionTableCall(Result, F, InitialActualSize, ActualSize));
172
struct EndExceptionTableCall {
173
EndExceptionTableCall(const Function *F, uint8_t *TableStart,
174
uint8_t *TableEnd, uint8_t* FrameRegister)
175
: F(F), F_dump(DumpFunction(F)),
176
TableStart(TableStart), TableEnd(TableEnd),
177
FrameRegister(FrameRegister) {}
182
uint8_t *FrameRegister;
184
std::vector<EndExceptionTableCall> endExceptionTableCalls;
185
virtual void endExceptionTable(const Function *F, uint8_t *TableStart,
186
uint8_t *TableEnd, uint8_t* FrameRegister) {
187
endExceptionTableCalls.push_back(
188
EndExceptionTableCall(F, TableStart, TableEnd, FrameRegister));
189
return Base->endExceptionTable(F, TableStart, TableEnd, FrameRegister);
193
bool LoadAssemblyInto(Module *M, const char *assembly) {
196
NULL != ParseAssemblyString(assembly, M, Error, M->getContext());
198
raw_string_ostream os(errMsg);
200
EXPECT_TRUE(success) << os.str();
204
class JITTest : public testing::Test {
206
virtual void SetUp() {
207
M = new Module("<main>", Context);
208
RJMM = new RecordingJITMemoryManager;
209
RJMM->setPoisonMemory(true);
211
TheJIT.reset(EngineBuilder(M).setEngineKind(EngineKind::JIT)
212
.setJITMemoryManager(RJMM)
213
.setErrorStr(&Error).create());
214
ASSERT_TRUE(TheJIT.get() != NULL) << Error;
217
void LoadAssembly(const char *assembly) {
218
LoadAssemblyInto(M, assembly);
222
Module *M; // Owned by ExecutionEngine.
223
RecordingJITMemoryManager *RJMM;
224
OwningPtr<ExecutionEngine> TheJIT;
227
// Regression test for a bug. The JIT used to allocate globals inside the same
228
// memory block used for the function, and when the function code was freed,
229
// the global was left in the same place. This test allocates a function
230
// that uses and global, deallocates it, and then makes sure that the global
231
// stays alive after that.
232
TEST(JIT, GlobalInFunction) {
234
Module *M = new Module("<main>", context);
236
JITMemoryManager *MemMgr = JITMemoryManager::CreateDefaultMemManager();
237
// Tell the memory manager to poison freed memory so that accessing freed
238
// memory is more easily tested.
239
MemMgr->setPoisonMemory(true);
241
OwningPtr<ExecutionEngine> JIT(EngineBuilder(M)
242
.setEngineKind(EngineKind::JIT)
244
.setJITMemoryManager(MemMgr)
245
// The next line enables the fix:
246
.setAllocateGVsWithCode(false)
248
ASSERT_EQ(Error, "");
250
// Create a global variable.
251
Type *GTy = Type::getInt32Ty(context);
252
GlobalVariable *G = new GlobalVariable(
255
false, // Not constant.
256
GlobalValue::InternalLinkage,
257
Constant::getNullValue(GTy),
260
// Make a function that points to a global.
261
Function *F1 = makeReturnGlobal("F1", G, M);
263
// Get the pointer to the native code to force it to JIT the function and
264
// allocate space for the global.
266
reinterpret_cast<void(*)()>((intptr_t)JIT->getPointerToFunction(F1));
268
// Since F1 was codegen'd, a pointer to G should be available.
269
int32_t *GPtr = (int32_t*)JIT->getPointerToGlobalIfAvailable(G);
270
ASSERT_NE((int32_t*)NULL, GPtr);
273
// F1() should increment G.
277
// Make a second function identical to the first, referring to the same
279
Function *F2 = makeReturnGlobal("F2", G, M);
281
reinterpret_cast<void(*)()>((intptr_t)JIT->getPointerToFunction(F2));
283
// F2() should increment G.
288
JIT->freeMachineCodeForFunction(F1);
290
// F2() should *still* increment G.
295
int PlusOne(int arg) {
299
// ARM tests disabled pending fix for PR10783.
300
#if !defined(__arm__)
301
TEST_F(JITTest, FarCallToKnownFunction) {
302
// x86-64 can only make direct calls to functions within 32 bits of
303
// the current PC. To call anything farther away, we have to load
304
// the address into a register and call through the register. The
305
// current JIT does this by allocating a stub for any far call.
306
// There was a bug in which the JIT tried to emit a direct call when
307
// the target was already in the JIT's global mappings and lazy
308
// compilation was disabled.
310
Function *KnownFunction = Function::Create(
311
TypeBuilder<int(int), false>::get(Context),
312
GlobalValue::ExternalLinkage, "known", M);
313
TheJIT->addGlobalMapping(KnownFunction, (void*)(intptr_t)PlusOne);
315
// int test() { return known(7); }
316
Function *TestFunction = Function::Create(
317
TypeBuilder<int(), false>::get(Context),
318
GlobalValue::ExternalLinkage, "test", M);
319
BasicBlock *Entry = BasicBlock::Create(Context, "entry", TestFunction);
320
IRBuilder<> Builder(Entry);
321
Value *result = Builder.CreateCall(
323
ConstantInt::get(TypeBuilder<int, false>::get(Context), 7));
324
Builder.CreateRet(result);
326
TheJIT->DisableLazyCompilation(true);
327
int (*TestFunctionPtr)() = reinterpret_cast<int(*)()>(
328
(intptr_t)TheJIT->getPointerToFunction(TestFunction));
329
// This used to crash in trying to call PlusOne().
330
EXPECT_EQ(8, TestFunctionPtr());
333
// Test a function C which calls A and B which call each other.
334
TEST_F(JITTest, NonLazyCompilationStillNeedsStubs) {
335
TheJIT->DisableLazyCompilation(true);
337
FunctionType *Func1Ty =
338
cast<FunctionType>(TypeBuilder<void(void), false>::get(Context));
339
std::vector<Type*> arg_types;
340
arg_types.push_back(Type::getInt1Ty(Context));
341
FunctionType *FuncTy = FunctionType::get(
342
Type::getVoidTy(Context), arg_types, false);
343
Function *Func1 = Function::Create(Func1Ty, Function::ExternalLinkage,
345
Function *Func2 = Function::Create(FuncTy, Function::InternalLinkage,
347
Function *Func3 = Function::Create(FuncTy, Function::InternalLinkage,
349
BasicBlock *Block1 = BasicBlock::Create(Context, "block1", Func1);
350
BasicBlock *Block2 = BasicBlock::Create(Context, "block2", Func2);
351
BasicBlock *True2 = BasicBlock::Create(Context, "cond_true", Func2);
352
BasicBlock *False2 = BasicBlock::Create(Context, "cond_false", Func2);
353
BasicBlock *Block3 = BasicBlock::Create(Context, "block3", Func3);
354
BasicBlock *True3 = BasicBlock::Create(Context, "cond_true", Func3);
355
BasicBlock *False3 = BasicBlock::Create(Context, "cond_false", Func3);
357
// Make Func1 call Func2(0) and Func3(0).
358
IRBuilder<> Builder(Block1);
359
Builder.CreateCall(Func2, ConstantInt::getTrue(Context));
360
Builder.CreateCall(Func3, ConstantInt::getTrue(Context));
361
Builder.CreateRetVoid();
363
// void Func2(bool b) { if (b) { Func3(false); return; } return; }
364
Builder.SetInsertPoint(Block2);
365
Builder.CreateCondBr(Func2->arg_begin(), True2, False2);
366
Builder.SetInsertPoint(True2);
367
Builder.CreateCall(Func3, ConstantInt::getFalse(Context));
368
Builder.CreateRetVoid();
369
Builder.SetInsertPoint(False2);
370
Builder.CreateRetVoid();
372
// void Func3(bool b) { if (b) { Func2(false); return; } return; }
373
Builder.SetInsertPoint(Block3);
374
Builder.CreateCondBr(Func3->arg_begin(), True3, False3);
375
Builder.SetInsertPoint(True3);
376
Builder.CreateCall(Func2, ConstantInt::getFalse(Context));
377
Builder.CreateRetVoid();
378
Builder.SetInsertPoint(False3);
379
Builder.CreateRetVoid();
381
// Compile the function to native code
383
reinterpret_cast<void(*)()>((intptr_t)TheJIT->getPointerToFunction(Func1));
388
// Regression test for PR5162. This used to trigger an AssertingVH inside the
389
// JIT's Function to stub mapping.
390
TEST_F(JITTest, NonLazyLeaksNoStubs) {
391
TheJIT->DisableLazyCompilation(true);
393
// Create two functions with a single basic block each.
394
FunctionType *FuncTy =
395
cast<FunctionType>(TypeBuilder<int(), false>::get(Context));
396
Function *Func1 = Function::Create(FuncTy, Function::ExternalLinkage,
398
Function *Func2 = Function::Create(FuncTy, Function::InternalLinkage,
400
BasicBlock *Block1 = BasicBlock::Create(Context, "block1", Func1);
401
BasicBlock *Block2 = BasicBlock::Create(Context, "block2", Func2);
403
// The first function calls the second and returns the result
404
IRBuilder<> Builder(Block1);
405
Value *Result = Builder.CreateCall(Func2);
406
Builder.CreateRet(Result);
408
// The second function just returns a constant
409
Builder.SetInsertPoint(Block2);
410
Builder.CreateRet(ConstantInt::get(TypeBuilder<int, false>::get(Context),42));
412
// Compile the function to native code
413
(void)TheJIT->getPointerToFunction(Func1);
415
// Free the JIT state for the functions
416
TheJIT->freeMachineCodeForFunction(Func1);
417
TheJIT->freeMachineCodeForFunction(Func2);
419
// Delete the first function (and show that is has no users)
420
EXPECT_EQ(Func1->getNumUses(), 0u);
421
Func1->eraseFromParent();
423
// Delete the second function (and show that it has no users - it had one,
424
// func1 but that's gone now)
425
EXPECT_EQ(Func2->getNumUses(), 0u);
426
Func2->eraseFromParent();
429
TEST_F(JITTest, ModuleDeletion) {
430
TheJIT->DisableLazyCompilation(false);
431
LoadAssembly("define void @main() { "
432
" call i32 @computeVal() "
436
"define internal i32 @computeVal() { "
439
Function *func = M->getFunction("main");
440
TheJIT->getPointerToFunction(func);
441
TheJIT->removeModule(M);
444
SmallPtrSet<const void*, 2> FunctionsDeallocated;
445
for (unsigned i = 0, e = RJMM->deallocateFunctionBodyCalls.size();
447
FunctionsDeallocated.insert(RJMM->deallocateFunctionBodyCalls[i].Body);
449
for (unsigned i = 0, e = RJMM->startFunctionBodyCalls.size(); i != e; ++i) {
450
EXPECT_TRUE(FunctionsDeallocated.count(
451
RJMM->startFunctionBodyCalls[i].Result))
452
<< "Function leaked: \n" << RJMM->startFunctionBodyCalls[i].F_dump;
454
EXPECT_EQ(RJMM->startFunctionBodyCalls.size(),
455
RJMM->deallocateFunctionBodyCalls.size());
457
SmallPtrSet<const void*, 2> ExceptionTablesDeallocated;
458
unsigned NumTablesDeallocated = 0;
459
for (unsigned i = 0, e = RJMM->deallocateExceptionTableCalls.size();
461
ExceptionTablesDeallocated.insert(
462
RJMM->deallocateExceptionTableCalls[i].ET);
463
if (RJMM->deallocateExceptionTableCalls[i].ET != NULL) {
464
// If JITEmitDebugInfo is off, we'll "deallocate" NULL, which doesn't
465
// appear in startExceptionTableCalls.
466
NumTablesDeallocated++;
469
for (unsigned i = 0, e = RJMM->startExceptionTableCalls.size(); i != e; ++i) {
470
EXPECT_TRUE(ExceptionTablesDeallocated.count(
471
RJMM->startExceptionTableCalls[i].Result))
472
<< "Function's exception table leaked: \n"
473
<< RJMM->startExceptionTableCalls[i].F_dump;
475
EXPECT_EQ(RJMM->startExceptionTableCalls.size(),
476
NumTablesDeallocated);
478
#endif // !defined(__arm__)
480
// ARM and PPC still emit stubs for calls since the target may be too far away
481
// to call directly. This #if can probably be removed when
482
// http://llvm.org/PR5201 is fixed.
483
#if !defined(__arm__) && !defined(__powerpc__) && !defined(__ppc__)
484
typedef int (*FooPtr) ();
486
TEST_F(JITTest, NoStubs) {
487
LoadAssembly("define void @bar() {"
492
"define i32 @foo() {"
498
"define i32 @main() {"
500
"%0 = call i32 @foo()"
504
Function *foo = M->getFunction("foo");
505
uintptr_t tmp = (uintptr_t)(TheJIT->getPointerToFunction(foo));
506
FooPtr ptr = (FooPtr)(tmp);
510
// We should now allocate no more stubs, we have the code to foo
511
// and the existing stub for bar.
512
int stubsBefore = RJMM->stubsAllocated;
513
Function *func = M->getFunction("main");
514
TheJIT->getPointerToFunction(func);
516
Function *bar = M->getFunction("bar");
517
TheJIT->getPointerToFunction(bar);
519
ASSERT_EQ(stubsBefore, RJMM->stubsAllocated);
521
#endif // !ARM && !PPC
523
TEST_F(JITTest, FunctionPointersOutliveTheirCreator) {
524
TheJIT->DisableLazyCompilation(true);
525
LoadAssembly("define i8()* @get_foo_addr() { "
529
"define i8 @foo() { "
532
Function *F_get_foo_addr = M->getFunction("get_foo_addr");
534
typedef char(*fooT)();
535
fooT (*get_foo_addr)() = reinterpret_cast<fooT(*)()>(
536
(intptr_t)TheJIT->getPointerToFunction(F_get_foo_addr));
537
fooT foo_addr = get_foo_addr();
539
// Now free get_foo_addr. This should not free the machine code for foo or
540
// any call stub returned as foo's canonical address.
541
TheJIT->freeMachineCodeForFunction(F_get_foo_addr);
543
// Check by calling the reported address of foo.
544
EXPECT_EQ(42, foo_addr());
546
// The reported address should also be the same as the result of a subsequent
547
// getPointerToFunction(foo).
549
// Fails until PR5126 is fixed:
550
Function *F_foo = M->getFunction("foo");
551
fooT foo = reinterpret_cast<fooT>(
552
(intptr_t)TheJIT->getPointerToFunction(F_foo));
553
EXPECT_EQ((intptr_t)foo, (intptr_t)foo_addr);
557
// ARM doesn't have an implementation of replaceMachineCodeForFunction(), so
558
// recompileAndRelinkFunction doesn't work.
559
#if !defined(__arm__)
560
TEST_F(JITTest, FunctionIsRecompiledAndRelinked) {
561
Function *F = Function::Create(TypeBuilder<int(void), false>::get(Context),
562
GlobalValue::ExternalLinkage, "test", M);
563
BasicBlock *Entry = BasicBlock::Create(Context, "entry", F);
564
IRBuilder<> Builder(Entry);
565
Value *Val = ConstantInt::get(TypeBuilder<int, false>::get(Context), 1);
566
Builder.CreateRet(Val);
568
TheJIT->DisableLazyCompilation(true);
569
// Compile the function once, and make sure it works.
570
int (*OrigFPtr)() = reinterpret_cast<int(*)()>(
571
(intptr_t)TheJIT->recompileAndRelinkFunction(F));
572
EXPECT_EQ(1, OrigFPtr());
574
// Now change the function to return a different value.
575
Entry->eraseFromParent();
576
BasicBlock *NewEntry = BasicBlock::Create(Context, "new_entry", F);
577
Builder.SetInsertPoint(NewEntry);
578
Val = ConstantInt::get(TypeBuilder<int, false>::get(Context), 2);
579
Builder.CreateRet(Val);
580
// Recompile it, which should produce a new function pointer _and_ update the
582
int (*NewFPtr)() = reinterpret_cast<int(*)()>(
583
(intptr_t)TheJIT->recompileAndRelinkFunction(F));
585
EXPECT_EQ(2, NewFPtr())
586
<< "The new pointer should call the new version of the function";
587
EXPECT_EQ(2, OrigFPtr())
588
<< "The old pointer's target should now jump to the new version";
590
#endif // !defined(__arm__)
592
} // anonymous namespace
593
// This variable is intentionally defined differently in the statically-compiled
594
// program from the IR input to the JIT to assert that the JIT doesn't use its
596
extern "C" int32_t JITTest_AvailableExternallyGlobal;
597
int32_t JITTest_AvailableExternallyGlobal = 42;
600
TEST_F(JITTest, AvailableExternallyGlobalIsntEmitted) {
601
TheJIT->DisableLazyCompilation(true);
602
LoadAssembly("@JITTest_AvailableExternallyGlobal = "
603
" available_externally global i32 7 "
605
"define i32 @loader() { "
606
" %result = load i32* @JITTest_AvailableExternallyGlobal "
609
Function *loaderIR = M->getFunction("loader");
611
int32_t (*loader)() = reinterpret_cast<int32_t(*)()>(
612
(intptr_t)TheJIT->getPointerToFunction(loaderIR));
613
EXPECT_EQ(42, loader()) << "func should return 42 from the external global,"
614
<< " not 7 from the IR version.";
617
} // anonymous namespace
618
// This function is intentionally defined differently in the statically-compiled
619
// program from the IR input to the JIT to assert that the JIT doesn't use its
621
extern "C" int32_t JITTest_AvailableExternallyFunction() {
626
// ARM tests disabled pending fix for PR10783.
627
#if !defined(__arm__)
628
TEST_F(JITTest, AvailableExternallyFunctionIsntCompiled) {
629
TheJIT->DisableLazyCompilation(true);
630
LoadAssembly("define available_externally i32 "
631
" @JITTest_AvailableExternallyFunction() { "
635
"define i32 @func() { "
636
" %result = tail call i32 "
637
" @JITTest_AvailableExternallyFunction() "
640
Function *funcIR = M->getFunction("func");
642
int32_t (*func)() = reinterpret_cast<int32_t(*)()>(
643
(intptr_t)TheJIT->getPointerToFunction(funcIR));
644
EXPECT_EQ(42, func()) << "func should return 42 from the static version,"
645
<< " not 7 from the IR version.";
648
TEST_F(JITTest, EscapedLazyStubStillCallable) {
649
TheJIT->DisableLazyCompilation(false);
650
LoadAssembly("define internal i32 @stubbed() { "
654
"define i32()* @get_stub() { "
655
" ret i32()* @stubbed "
657
typedef int32_t(*StubTy)();
659
// Call get_stub() to get the address of @stubbed without actually JITting it.
660
Function *get_stubIR = M->getFunction("get_stub");
661
StubTy (*get_stub)() = reinterpret_cast<StubTy(*)()>(
662
(intptr_t)TheJIT->getPointerToFunction(get_stubIR));
663
StubTy stubbed = get_stub();
664
// Now get_stubIR is the only reference to stubbed's stub.
665
get_stubIR->eraseFromParent();
666
// Now there are no references inside the JIT, but we've got a pointer outside
667
// it. The stub should be callable and return the right value.
668
EXPECT_EQ(42, stubbed());
671
// Converts the LLVM assembly to bitcode and returns it in a std::string. An
672
// empty string indicates an error.
673
std::string AssembleToBitcode(LLVMContext &Context, const char *Assembly) {
674
Module TempModule("TempModule", Context);
675
if (!LoadAssemblyInto(&TempModule, Assembly)) {
680
raw_string_ostream OS(Result);
681
WriteBitcodeToFile(&TempModule, OS);
686
// Returns a newly-created ExecutionEngine that reads the bitcode in 'Bitcode'
687
// lazily. The associated Module (owned by the ExecutionEngine) is returned in
688
// M. Both will be NULL on an error. Bitcode must live at least as long as the
690
ExecutionEngine *getJITFromBitcode(
691
LLVMContext &Context, const std::string &Bitcode, Module *&M) {
692
// c_str() is null-terminated like MemoryBuffer::getMemBuffer requires.
693
MemoryBuffer *BitcodeBuffer =
694
MemoryBuffer::getMemBuffer(Bitcode, "Bitcode for test");
696
M = getLazyBitcodeModule(BitcodeBuffer, Context, &errMsg);
698
ADD_FAILURE() << errMsg;
699
delete BitcodeBuffer;
702
ExecutionEngine *TheJIT = EngineBuilder(M)
703
.setEngineKind(EngineKind::JIT)
704
.setErrorStr(&errMsg)
706
if (TheJIT == NULL) {
707
ADD_FAILURE() << errMsg;
715
TEST(LazyLoadedJITTest, MaterializableAvailableExternallyFunctionIsntCompiled) {
717
const std::string Bitcode =
718
AssembleToBitcode(Context,
719
"define available_externally i32 "
720
" @JITTest_AvailableExternallyFunction() { "
724
"define i32 @func() { "
725
" %result = tail call i32 "
726
" @JITTest_AvailableExternallyFunction() "
729
ASSERT_FALSE(Bitcode.empty()) << "Assembling failed";
731
OwningPtr<ExecutionEngine> TheJIT(getJITFromBitcode(Context, Bitcode, M));
732
ASSERT_TRUE(TheJIT.get()) << "Failed to create JIT.";
733
TheJIT->DisableLazyCompilation(true);
735
Function *funcIR = M->getFunction("func");
736
Function *availableFunctionIR =
737
M->getFunction("JITTest_AvailableExternallyFunction");
739
// Double-check that the available_externally function is still unmaterialized
740
// when getPointerToFunction needs to find out if it's available_externally.
741
EXPECT_TRUE(availableFunctionIR->isMaterializable());
743
int32_t (*func)() = reinterpret_cast<int32_t(*)()>(
744
(intptr_t)TheJIT->getPointerToFunction(funcIR));
745
EXPECT_EQ(42, func()) << "func should return 42 from the static version,"
746
<< " not 7 from the IR version.";
749
TEST(LazyLoadedJITTest, EagerCompiledRecursionThroughGhost) {
751
const std::string Bitcode =
752
AssembleToBitcode(Context,
753
"define i32 @recur1(i32 %a) { "
754
" %zero = icmp eq i32 %a, 0 "
755
" br i1 %zero, label %done, label %notdone "
759
" %am1 = sub i32 %a, 1 "
760
" %result = call i32 @recur2(i32 %am1) "
764
"define i32 @recur2(i32 %b) { "
765
" %result = call i32 @recur1(i32 %b) "
768
ASSERT_FALSE(Bitcode.empty()) << "Assembling failed";
770
OwningPtr<ExecutionEngine> TheJIT(getJITFromBitcode(Context, Bitcode, M));
771
ASSERT_TRUE(TheJIT.get()) << "Failed to create JIT.";
772
TheJIT->DisableLazyCompilation(true);
774
Function *recur1IR = M->getFunction("recur1");
775
Function *recur2IR = M->getFunction("recur2");
776
EXPECT_TRUE(recur1IR->isMaterializable());
777
EXPECT_TRUE(recur2IR->isMaterializable());
779
int32_t (*recur1)(int32_t) = reinterpret_cast<int32_t(*)(int32_t)>(
780
(intptr_t)TheJIT->getPointerToFunction(recur1IR));
781
EXPECT_EQ(3, recur1(4));
783
#endif // !defined(__arm__)
785
// This code is copied from JITEventListenerTest, but it only runs once for all
786
// the tests in this directory. Everything seems fine, but that's strange
788
class JITEnvironment : public testing::Environment {
789
virtual void SetUp() {
790
// Required to create a JIT.
791
InitializeNativeTarget();
794
testing::Environment* const jit_env =
795
testing::AddGlobalTestEnvironment(new JITEnvironment);