Fix http://llvm.org/PR4822: allow module deletion after a function has been

compiled.

When functions are compiled, they accumulate references in the JITResolver's
stub maps. This patch removes those references when the functions are
destroyed.  It's illegal to destroy a Function when any thread may still try to
call its machine code.

This patch also updates r83987 to use ValueMap instead of explicit CallbackVHs
and fixes a couple "do stuff inside assert()" bugs from r84522.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84975 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Jeffrey Yasskin
2009-10-23 22:37:43 +00:00
parent 7b929dad59
commit 23e5fcfec4
5 changed files with 107 additions and 57 deletions

View File

@ -9,6 +9,7 @@
#include "gtest/gtest.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Assembly/Parser.h"
#include "llvm/BasicBlock.h"
#include "llvm/Constant.h"
#include "llvm/Constants.h"
@ -22,6 +23,7 @@
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/Support/IRBuilder.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TypeBuilder.h"
#include "llvm/Target/TargetSelect.h"
#include "llvm/Type.h"
@ -49,14 +51,25 @@ class JITTest : public testing::Test {
protected:
virtual void SetUp() {
M = new Module("<main>", Context);
MP = new ExistingModuleProvider(M);
std::string Error;
TheJIT.reset(EngineBuilder(M).setEngineKind(EngineKind::JIT)
TheJIT.reset(EngineBuilder(MP).setEngineKind(EngineKind::JIT)
.setErrorStr(&Error).create());
ASSERT_TRUE(TheJIT.get() != NULL) << Error;
}
void LoadAssembly(const char *assembly) {
SMDiagnostic Error;
bool success = NULL != ParseAssemblyString(assembly, M, Error, Context);
std::string errMsg;
raw_string_ostream os(errMsg);
Error.Print("", os);
ASSERT_TRUE(success) << os.str();
}
LLVMContext Context;
Module *M; // Owned by ExecutionEngine.
Module *M; // Owned by MP.
ModuleProvider *MP; // Owned by ExecutionEngine.
OwningPtr<ExecutionEngine> TheJIT;
};
@ -264,6 +277,20 @@ TEST_F(JITTest, NonLazyLeaksNoStubs) {
}
#endif
TEST_F(JITTest, ModuleDeletion) {
LoadAssembly("define void @main() { "
" call i32 @computeVal() "
" ret void "
"} "
" "
"define internal i32 @computeVal() { "
" ret i32 0 "
"} ");
Function *func = M->getFunction("main");
TheJIT->getPointerToFunction(func);
TheJIT->deleteModuleProvider(MP);
}
// This code is copied from JITEventListenerTest, but it only runs once for all
// the tests in this directory. Everything seems fine, but that's strange
// behavior.