diff options
author | Jeffrey Yasskin <jyasskin@google.com> | 2009-12-22 23:18:18 +0000 |
---|---|---|
committer | Jeffrey Yasskin <jyasskin@google.com> | 2009-12-22 23:18:18 +0000 |
commit | e41845445955688408a20c35850442fbcffb69f3 (patch) | |
tree | cc1b23da37c2a4bbc99761558490360044203fe1 | |
parent | d210c4a75a6da94bfb5154d87ed4e3a97755636d (diff) | |
download | external_llvm-e41845445955688408a20c35850442fbcffb69f3.zip external_llvm-e41845445955688408a20c35850442fbcffb69f3.tar.gz external_llvm-e41845445955688408a20c35850442fbcffb69f3.tar.bz2 |
Fix a crash in JIT::recompileAndRelinkFunction(). It doesn't pass the MCI
argument to runJITOnFunction(), which caused a null pointer dereference at
every call.
Patch by Gianluca Guida!
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@91939 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/ExecutionEngine/JIT/JIT.cpp | 6 | ||||
-rw-r--r-- | unittests/ExecutionEngine/JIT/JITTest.cpp | 31 |
2 files changed, 35 insertions, 2 deletions
diff --git a/lib/ExecutionEngine/JIT/JIT.cpp b/lib/ExecutionEngine/JIT/JIT.cpp index 9b5a176..ebc2567 100644 --- a/lib/ExecutionEngine/JIT/JIT.cpp +++ b/lib/ExecutionEngine/JIT/JIT.cpp @@ -611,11 +611,13 @@ void JIT::runJITOnFunction(Function *F, MachineCodeInfo *MCI) { } }; MCIListener MCIL(MCI); - RegisterJITEventListener(&MCIL); + if (MCI) + RegisterJITEventListener(&MCIL); runJITOnFunctionUnlocked(F, locked); - UnregisterJITEventListener(&MCIL); + if (MCI) + UnregisterJITEventListener(&MCIL); } void JIT::runJITOnFunctionUnlocked(Function *F, const MutexGuard &locked) { diff --git a/unittests/ExecutionEngine/JIT/JITTest.cpp b/unittests/ExecutionEngine/JIT/JITTest.cpp index da4dfc4..c6c26c7 100644 --- a/unittests/ExecutionEngine/JIT/JITTest.cpp +++ b/unittests/ExecutionEngine/JIT/JITTest.cpp @@ -534,6 +534,37 @@ TEST_F(JITTest, FunctionPointersOutliveTheirCreator) { #endif } +TEST_F(JITTest, FunctionIsRecompiledAndRelinked) { + Function *F = Function::Create(TypeBuilder<int(void), false>::get(Context), + GlobalValue::ExternalLinkage, "test", M); + BasicBlock *Entry = BasicBlock::Create(Context, "entry", F); + IRBuilder<> Builder(Entry); + Value *Val = ConstantInt::get(TypeBuilder<int, false>::get(Context), 1); + Builder.CreateRet(Val); + + TheJIT->DisableLazyCompilation(true); + // Compile the function once, and make sure it works. + int (*OrigFPtr)() = reinterpret_cast<int(*)()>( + (intptr_t)TheJIT->recompileAndRelinkFunction(F)); + EXPECT_EQ(1, OrigFPtr()); + + // Now change the function to return a different value. + Entry->eraseFromParent(); + BasicBlock *NewEntry = BasicBlock::Create(Context, "new_entry", F); + Builder.SetInsertPoint(NewEntry); + Val = ConstantInt::get(TypeBuilder<int, false>::get(Context), 2); + Builder.CreateRet(Val); + // Recompile it, which should produce a new function pointer _and_ update the + // old one. + int (*NewFPtr)() = reinterpret_cast<int(*)()>( + (intptr_t)TheJIT->recompileAndRelinkFunction(F)); + + EXPECT_EQ(2, NewFPtr()) + << "The new pointer should call the new version of the function"; + EXPECT_EQ(2, OrigFPtr()) + << "The old pointer's target should now jump to the new version"; +} + } // anonymous namespace // This variable is intentionally defined differently in the statically-compiled // program from the IR input to the JIT to assert that the JIT doesn't use its |