//===-- ExecutionEngine.cpp - Common Implementation shared by EEs ---------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the common interface used by the various execution engine
// subclasses.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "jit"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/ModuleProvider.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Config/alloca.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MutexGuard.h"
#include "llvm/System/DynamicLibrary.h"
#include "llvm/System/Host.h"
#include "llvm/Target/TargetData.h"
#include <cmath>
#include <cstring>
using namespace llvm;
STATISTIC(NumInitBytes, "Number of bytes of global vars initialized");
STATISTIC(NumGlobals , "Number of global vars initialized");
ExecutionEngine::EECtorFn ExecutionEngine::JITCtor = 0;
ExecutionEngine::EECtorFn ExecutionEngine::InterpCtor = 0;
ExecutionEngine::EERegisterFn ExecutionEngine::ExceptionTableRegister = 0;
ExecutionEngine::ExecutionEngine(ModuleProvider *P) : LazyFunctionCreator(0) {
LazyCompilationDisabled = false;
GVCompilationDisabled = false;
SymbolSearchingDisabled = false;
DlsymStubsEnabled = false;
Modules.push_back(P);
assert(P && "ModuleProvider is null?");
}
ExecutionEngine::~ExecutionEngine() {
clearAllGlobalMappings();
for (unsigned i = 0, e = Modules.size(); i != e; ++i)
delete Modules[i];
}
char* ExecutionEngine::getMemoryForGV(const GlobalVariable* GV) {
const Type *ElTy = GV->getType()->getElementType();
size_t GVSize = (size_t)getTargetData()->getTypePaddedSize(ElTy);
return new char[GVSize];
}
/// removeModuleProvider - Remove a ModuleProvider from the list of modules.
/// Relases the Module from the ModuleProvider, materializing it in the
/// process, and returns the materialized Module.
Module* ExecutionEngine::removeModuleProvider(ModuleProvider *P,
std::string *ErrInfo) {
for(SmallVector<ModuleProvider *, 1>::iterator I = Modules.begin(),
E = Modules.end(); I != E; ++I) {
ModuleProvider *MP = *I;
if (MP == P) {
Modules.erase(I);
clearGlobalMappingsFromModule(MP->getModule());
return MP->releaseModule(ErrInfo);
}
}
return NULL;
}
/// deleteModuleProvider - Remove a ModuleProvider from the list of modules,
/// and deletes the ModuleProvider and owned Module. Avoids materializing
/// the underlying module.
void ExecutionEngine::deleteModuleProvider(ModuleProvider *P,
std::string *ErrInfo) {
for(SmallVector<ModuleProvider *, 1>::iterator I = Modules.begin(),
E = Modules.end(); I != E; ++I) {
ModuleProvider *MP = *I;
if (MP == P) {
Modules.erase(I);
clearGlobalMappingsFromModule(MP->getModule());
delete MP;
return;
}
}
}
/// FindFunctionNamed - Search all of the active modules to find the one that
/// defines FnName. This is very slow operation and shouldn't be used for
/// general code.
Function *ExecutionEngine::FindFunctionNamed(const char *FnName) {
for (unsigned i = 0, e = Modules.size(); i != e; ++i) {
if (Function *F = Modules[i]->getModule()->getFunction(FnName))
return F;
}
return 0;
}
/// addGlobalMapping - Tell the execution engine that the specified global is
/// at the specified location. This is used internally as functions are JIT'd
/// and as global variables are laid out in memory. It can and should also be
/// used by clients of the EE that want to have an LLVM global overlay
/// existing data in memory.
void ExecutionEngine::addGlobalMapping(const GlobalValue *GV, void *Addr) {
MutexGuard locked(lock);
DOUT << "JIT: Map \'" << GV->getNameStart() << "\' to [" << Addr << "]\n";
void *&CurVal = state.getGlobalAddressMap(locked)[GV];
assert((CurVal == 0 || Addr == 0) && "GlobalMapping already established!");
CurVal = Addr;
// If we are using the reverse mapping, add it too
if (!state.getGlobalAddressReverseMap(locked).empty()) {
const GlobalValue *&V = state