Unload global values (global variables)

When executable code is generated from the llvm::Module the JIT stores the
GlobalValue, Address in a map. This map is used to 'lock' the GlobalValue, so
that it doesn't go out of sync. If we want to 'unload' it we first need to
update the global mapping so that the JIT/ExecutionEngine 'forgets' about the
mapping.
This commit is contained in:
Vassil Vassilev 2013-10-21 14:35:33 -05:00 committed by sftnight
parent f0152f8772
commit 0b3c13cd0d
3 changed files with 25 additions and 9 deletions

View File

@ -17,6 +17,7 @@
#include "clang/Sema/Scope.h"
#include "clang/Sema/Sema.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Module.h"
@ -36,6 +37,10 @@ namespace cling {
///
Sema* m_Sema;
///\brief The execution engine, either JIT or MCJIT, being recovered.
///
llvm::ExecutionEngine* m_EEngine;
///\brief The current transaction being reverted.
///
const Transaction* m_CurTransaction;
@ -55,7 +60,8 @@ namespace cling {
FileIDs m_FilesToUncache;
public:
DeclReverter(Sema* S, const Transaction* T): m_Sema(S), m_CurTransaction(T) {
DeclReverter(Sema* S, llvm::ExecutionEngine* EE, const Transaction* T)
: m_Sema(S), m_EEngine(EE), m_CurTransaction(T) {
m_Mangler.reset(m_Sema->getASTContext().createMangleContext());
}
~DeclReverter();
@ -258,7 +264,7 @@ namespace cling {
DeclContext* DC = ND->getDeclContext();
// If the decl was removed make sure that we fix the lookup
// If the decl was removed make sure that we fix the lookup
if (Successful) {
Scope* S = m_Sema->getScopeForContext(DC);
if (S)
@ -283,6 +289,9 @@ namespace cling {
llvm::GlobalValue* GV
= m_CurTransaction->getModule()->getNamedValue(mangledName);
// Remove the mapping from the JIT, otherwise it locks the GV and
// replaceAllUsesWith doesn't work
m_EEngine->updateGlobalMapping(GV, 0);
if (!GV->use_empty())
GV->replaceAllUsesWith(llvm::UndefValue::get(GV->getType()));
@ -512,14 +521,14 @@ namespace cling {
return false;
}
ASTNodeEraser::ASTNodeEraser(Sema* S) : m_Sema(S) {
}
ASTNodeEraser::ASTNodeEraser(Sema* S, llvm::ExecutionEngine* EE)
: m_Sema(S), m_EEngine(EE) { }
ASTNodeEraser::~ASTNodeEraser() {
}
bool ASTNodeEraser::RevertTransaction(const Transaction* T) {
DeclReverter DeclRev(m_Sema, T);
DeclReverter DeclRev(m_Sema, m_EEngine, T);
bool Successful = true;
for (Transaction::const_reverse_iterator I = T->rdecls_begin(),

View File

@ -1,12 +1,16 @@
//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// version: $Id: a88f59662c0204c76ab2204361d9f64b1e10fcfc $
// author: Vassil Vassilev <vvasilev@cern.ch>
//------------------------------------------------------------------------------
#ifndef CLING_AST_NODE_ERASER
#define CLING_AST_NODE_ERASER
namespace llvm {
class ExecutionEngine;
}
namespace clang {
class Sema;
}
@ -20,9 +24,10 @@ namespace cling {
class ASTNodeEraser {
private:
clang::Sema* m_Sema;
llvm::ExecutionEngine* m_EEngine;
public:
ASTNodeEraser(clang::Sema* S);
ASTNodeEraser(clang::Sema* S, llvm::ExecutionEngine* EE);
~ASTNodeEraser();
///\brief Rolls back given transaction from the AST.

View File

@ -448,7 +448,8 @@ namespace cling {
void IncrementalParser::rollbackTransaction(Transaction* T) const {
assert(T->getIssuedDiags() == Transaction::kErrors
&& "Rolling back with no errors");
ASTNodeEraser NodeEraser(&getCI()->getSema());
ASTNodeEraser NodeEraser(&getCI()->getSema(),
m_Interpreter->getExecutionEngine());
if (NodeEraser.RevertTransaction(T))
T->setState(Transaction::kRolledBack);
@ -620,7 +621,8 @@ namespace cling {
assert(T->getModule() &&
"Trying to uncodegen transaction taken in syntax only mode. ");
ASTNodeEraser NodeEraser(&getCI()->getSema());
ASTNodeEraser NodeEraser(&getCI()->getSema(),
m_Interpreter->getExecutionEngine());
NodeEraser.RevertTransaction(T);
InterpreterCallbacks* callbacks = m_Interpreter->getCallbacks();