#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
-#include "llvm/ModuleProvider.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/Debug.h"
STATISTIC(NumInitBytes, "Number of bytes of global vars initialized");
STATISTIC(NumGlobals , "Number of global vars initialized");
-ExecutionEngine *(*ExecutionEngine::JITCtor)(ModuleProvider *MP,
- std::string *ErrorStr,
- JITMemoryManager *JMM,
- CodeGenOpt::Level OptLevel,
- bool GVsWithCode,
- CodeModel::Model CMM) = 0;
-ExecutionEngine *(*ExecutionEngine::InterpCtor)(ModuleProvider *MP,
+ExecutionEngine *(*ExecutionEngine::JITCtor)(
+ Module *M,
+ std::string *ErrorStr,
+ JITMemoryManager *JMM,
+ CodeGenOpt::Level OptLevel,
+ bool GVsWithCode,
+ CodeModel::Model CMM,
+ StringRef MArch,
+ StringRef MCPU,
+ const SmallVectorImpl<std::string>& MAttrs) = 0;
+ExecutionEngine *(*ExecutionEngine::InterpCtor)(Module *M,
std::string *ErrorStr) = 0;
-ExecutionEngine::EERegisterFn ExecutionEngine::ExceptionTableRegister = 0;
-
-ExecutionEngine::ExecutionEngine(ModuleProvider *P)
+ExecutionEngine::ExecutionEngine(Module *M)
: EEState(*this),
- LazyFunctionCreator(0) {
+ LazyFunctionCreator(0),
+ ExceptionTableRegister(0),
+ ExceptionTableDeregister(0) {
CompilingLazily = false;
GVCompilationDisabled = false;
SymbolSearchingDisabled = false;
- Modules.push_back(P);
- assert(P && "ModuleProvider is null?");
+ Modules.push_back(M);
+ assert(M && "Module is null?");
}
ExecutionEngine::~ExecutionEngine() {
delete Modules[i];
}
-char* ExecutionEngine::getMemoryForGV(const GlobalVariable* GV) {
- const Type *ElTy = GV->getType()->getElementType();
- size_t GVSize = (size_t)getTargetData()->getTypeAllocSize(ElTy);
- return new char[GVSize];
+void ExecutionEngine::DeregisterAllTables() {
+ if (ExceptionTableDeregister) {
+ std::vector<void*>::iterator it = AllExceptionTables.begin();
+ std::vector<void*>::iterator ite = AllExceptionTables.end();
+ for (; it != ite; ++it)
+ ExceptionTableDeregister(*it);
+ AllExceptionTables.clear();
+ }
}
-/// 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);
- }
+namespace {
+// This class automatically deletes the memory block when the GlobalVariable is
+// destroyed.
+class GVMemoryBlock : public CallbackVH {
+ GVMemoryBlock(const GlobalVariable *GV)
+ : CallbackVH(const_cast<GlobalVariable*>(GV)) {}
+
+public:
+ // Returns the address the GlobalVariable should be written into. The
+ // GVMemoryBlock object prefixes that.
+ static char *Create(const GlobalVariable *GV, const TargetData& TD) {
+ const Type *ElTy = GV->getType()->getElementType();
+ size_t GVSize = (size_t)TD.getTypeAllocSize(ElTy);
+ void *RawMemory = ::operator new(
+ TargetData::RoundUpAlignment(sizeof(GVMemoryBlock),
+ TD.getPreferredAlignment(GV))
+ + GVSize);
+ new(RawMemory) GVMemoryBlock(GV);
+ return static_cast<char*>(RawMemory) + sizeof(GVMemoryBlock);
}
- return NULL;
+
+ virtual void deleted() {
+ // We allocated with operator new and with some extra memory hanging off the
+ // end, so don't just delete this. I'm not sure if this is actually
+ // required.
+ this->~GVMemoryBlock();
+ ::operator delete(this);
+ }
+};
+} // anonymous namespace
+
+char* ExecutionEngine::getMemoryForGV(const GlobalVariable* GV) {
+ return GVMemoryBlock::Create(GV, *getTargetData());
}
-/// 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) {
+/// removeModule - Remove a Module from the list of modules.
+bool ExecutionEngine::removeModule(Module *M) {
+ for(SmallVector<Module *, 1>::iterator I = Modules.begin(),
+ E = Modules.end(); I != E; ++I) {
+ Module *Found = *I;
+ if (Found == M) {
Modules.erase(I);
- clearGlobalMappingsFromModule(MP->getModule());
- delete MP;
- return;
+ clearGlobalMappingsFromModule(M);
+ return true;
}
}
+ return false;
}
/// FindFunctionNamed - Search all of the active modules to find the one that
/// 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))
+ if (Function *F = Modules[i]->getFunction(FnName))
return F;
}
return 0;
return I != EEState.getGlobalAddressReverseMap(locked).end() ? I->second : 0;
}
-// CreateArgv - Turn a vector of strings into a nice argv style array of
-// pointers to null terminated strings.
-//
-static void *CreateArgv(LLVMContext &C, ExecutionEngine *EE,
- const std::vector<std::string> &InputArgv) {
+namespace {
+class ArgvArray {
+ char *Array;
+ std::vector<char*> Values;
+public:
+ ArgvArray() : Array(NULL) {}
+ ~ArgvArray() { clear(); }
+ void clear() {
+ delete[] Array;
+ Array = NULL;
+ for (size_t I = 0, E = Values.size(); I != E; ++I) {
+ delete[] Values[I];
+ }
+ Values.clear();
+ }
+ /// Turn a vector of strings into a nice argv style array of pointers to null
+ /// terminated strings.
+ void *reset(LLVMContext &C, ExecutionEngine *EE,
+ const std::vector<std::string> &InputArgv);
+};
+} // anonymous namespace
+void *ArgvArray::reset(LLVMContext &C, ExecutionEngine *EE,
+ const std::vector<std::string> &InputArgv) {
+ clear(); // Free the old contents.
unsigned PtrSize = EE->getTargetData()->getPointerSize();
- char *Result = new char[(InputArgv.size()+1)*PtrSize];
+ Array = new char[(InputArgv.size()+1)*PtrSize];
- DEBUG(dbgs() << "JIT: ARGV = " << (void*)Result << "\n");
+ DEBUG(dbgs() << "JIT: ARGV = " << (void*)Array << "\n");
const Type *SBytePtr = Type::getInt8PtrTy(C);
for (unsigned i = 0; i != InputArgv.size(); ++i) {
unsigned Size = InputArgv[i].size()+1;
char *Dest = new char[Size];
+ Values.push_back(Dest);
DEBUG(dbgs() << "JIT: ARGV[" << i << "] = " << (void*)Dest << "\n");
std::copy(InputArgv[i].begin(), InputArgv[i].end(), Dest);
Dest[Size-1] = 0;
- // Endian safe: Result[i] = (PointerTy)Dest;
- EE->StoreValueToMemory(PTOGV(Dest), (GenericValue*)(Result+i*PtrSize),
+ // Endian safe: Array[i] = (PointerTy)Dest;
+ EE->StoreValueToMemory(PTOGV(Dest), (GenericValue*)(Array+i*PtrSize),
SBytePtr);
}
// Null terminate it
EE->StoreValueToMemory(PTOGV(0),
- (GenericValue*)(Result+InputArgv.size()*PtrSize),
+ (GenericValue*)(Array+InputArgv.size()*PtrSize),
SBytePtr);
- return Result;
+ return Array;
}
void ExecutionEngine::runStaticConstructorsDestructors(bool isDtors) {
// Execute global ctors/dtors for each module in the program.
for (unsigned m = 0, e = Modules.size(); m != e; ++m)
- runStaticConstructorsDestructors(Modules[m]->getModule(), isDtors);
+ runStaticConstructorsDestructors(Modules[m], isDtors);
}
#ifndef NDEBUG
switch (NumArgs) {
case 3:
if (FTy->getParamType(2) != PPInt8Ty) {
- llvm_report_error("Invalid type for third argument of main() supplied");
+ report_fatal_error("Invalid type for third argument of main() supplied");
}
// FALLS THROUGH
case 2:
if (FTy->getParamType(1) != PPInt8Ty) {
- llvm_report_error("Invalid type for second argument of main() supplied");
+ report_fatal_error("Invalid type for second argument of main() supplied");
}
// FALLS THROUGH
case 1:
- if (!FTy->getParamType(0)->isInteger(32)) {
- llvm_report_error("Invalid type for first argument of main() supplied");
+ if (!FTy->getParamType(0)->isIntegerTy(32)) {
+ report_fatal_error("Invalid type for first argument of main() supplied");
}
// FALLS THROUGH
case 0:
- if (!isa<IntegerType>(FTy->getReturnType()) &&
+ if (!FTy->getReturnType()->isIntegerTy() &&
!FTy->getReturnType()->isVoidTy()) {
- llvm_report_error("Invalid return type of main() supplied");
+ report_fatal_error("Invalid return type of main() supplied");
}
break;
default:
- llvm_report_error("Invalid number of arguments of main() supplied");
+ report_fatal_error("Invalid number of arguments of main() supplied");
}
+ ArgvArray CArgv;
+ ArgvArray CEnv;
if (NumArgs) {
GVArgs.push_back(GVArgc); // Arg #0 = argc.
if (NumArgs > 1) {
// Arg #1 = argv.
- GVArgs.push_back(PTOGV(CreateArgv(Fn->getContext(), this, argv)));
+ GVArgs.push_back(PTOGV(CArgv.reset(Fn->getContext(), this, argv)));
assert(!isTargetNullPtr(this, GVTOP(GVArgs[1])) &&
"argv[0] was null after CreateArgv");
if (NumArgs > 2) {
for (unsigned i = 0; envp[i]; ++i)
EnvVars.push_back(envp[i]);
// Arg #2 = envp.
- GVArgs.push_back(PTOGV(CreateArgv(Fn->getContext(), this, EnvVars)));
+ GVArgs.push_back(PTOGV(CEnv.reset(Fn->getContext(), this, EnvVars)));
}
}
}
/// Interpreter or there's an error. If even an Interpreter cannot be created,
/// NULL is returned.
///
-ExecutionEngine *ExecutionEngine::create(ModuleProvider *MP,
+ExecutionEngine *ExecutionEngine::create(Module *M,
bool ForceInterpreter,
std::string *ErrorStr,
CodeGenOpt::Level OptLevel,
bool GVsWithCode) {
- return EngineBuilder(MP)
+ return EngineBuilder(M)
.setEngineKind(ForceInterpreter
? EngineKind::Interpreter
: EngineKind::JIT)
.create();
}
-ExecutionEngine *ExecutionEngine::create(Module *M) {
- return EngineBuilder(M).create();
-}
-
-/// EngineBuilder - Overloaded constructor that automatically creates an
-/// ExistingModuleProvider for an existing module.
-EngineBuilder::EngineBuilder(Module *m) : MP(new ExistingModuleProvider(m)) {
- InitEngine();
-}
-
ExecutionEngine *EngineBuilder::create() {
// Make sure we can resolve symbols in the program as well. The zero arg
// to the function tells DynamicLibrary to load the program, not a library.
if (WhichEngine & EngineKind::JIT) {
if (ExecutionEngine::JITCtor) {
ExecutionEngine *EE =
- ExecutionEngine::JITCtor(MP, ErrorStr, JMM, OptLevel,
- AllocateGVsWithCode, CMModel);
+ ExecutionEngine::JITCtor(M, ErrorStr, JMM, OptLevel,
+ AllocateGVsWithCode, CMModel,
+ MArch, MCPU, MAttrs);
if (EE) return EE;
}
}
// an interpreter instead.
if (WhichEngine & EngineKind::Interpreter) {
if (ExecutionEngine::InterpCtor)
- return ExecutionEngine::InterpCtor(MP, ErrorStr);
+ return ExecutionEngine::InterpCtor(M, ErrorStr);
if (ErrorStr)
*ErrorStr = "Interpreter has not been linked in.";
return 0;
switch (Op0->getType()->getTypeID()) {
default: llvm_unreachable("Invalid bitcast operand");
case Type::IntegerTyID:
- assert(DestTy->isFloatingPoint() && "invalid bitcast");
+ assert(DestTy->isFloatingPointTy() && "invalid bitcast");
if (DestTy->isFloatTy())
GV.FloatVal = GV.IntVal.bitsToFloat();
else if (DestTy->isDoubleTy())
GV.DoubleVal = GV.IntVal.bitsToDouble();
break;
case Type::FloatTyID:
- assert(DestTy->isInteger(32) && "Invalid bitcast");
+ assert(DestTy->isIntegerTy(32) && "Invalid bitcast");
GV.IntVal.floatToBits(GV.FloatVal);
break;
case Type::DoubleTyID:
- assert(DestTy->isInteger(64) && "Invalid bitcast");
+ assert(DestTy->isIntegerTy(64) && "Invalid bitcast");
GV.IntVal.doubleToBits(GV.DoubleVal);
break;
case Type::PointerTyID:
- assert(isa<PointerType>(DestTy) && "Invalid bitcast");
+ assert(DestTy->isPointerTy() && "Invalid bitcast");
break; // getConstantValue(Op0) above already converted it
}
return GV;
case Instruction::FDiv:
GV.FloatVal = LHS.FloatVal / RHS.FloatVal; break;
case Instruction::FRem:
- GV.FloatVal = ::fmodf(LHS.FloatVal,RHS.FloatVal); break;
+ GV.FloatVal = std::fmod(LHS.FloatVal,RHS.FloatVal); break;
}
break;
case Type::DoubleTyID:
case Instruction::FDiv:
GV.DoubleVal = LHS.DoubleVal / RHS.DoubleVal; break;
case Instruction::FRem:
- GV.DoubleVal = ::fmod(LHS.DoubleVal,RHS.DoubleVal); break;
+ GV.DoubleVal = std::fmod(LHS.DoubleVal,RHS.DoubleVal); break;
}
break;
case Type::X86_FP80TyID:
std::string msg;
raw_string_ostream Msg(msg);
Msg << "ConstantExpr not handled: " << *CE;
- llvm_report_error(Msg.str());
+ report_fatal_error(Msg.str());
}
GenericValue Result;
std::string msg;
raw_string_ostream Msg(msg);
Msg << "ERROR: Constant unimplemented for type: " << *C->getType();
- llvm_report_error(Msg.str());
+ report_fatal_error(Msg.str());
}
return Result;
}
std::string msg;
raw_string_ostream Msg(msg);
Msg << "Cannot load value of type " << *Ty << "!";
- llvm_report_error(Msg.str());
+ report_fatal_error(Msg.str());
}
}
if (Modules.size() != 1) {
for (unsigned m = 0, e = Modules.size(); m != e; ++m) {
- Module &M = *Modules[m]->getModule();
+ Module &M = *Modules[m];
for (Module::const_global_iterator I = M.global_begin(),
E = M.global_end(); I != E; ++I) {
const GlobalValue *GV = I;
std::vector<const GlobalValue*> NonCanonicalGlobals;
for (unsigned m = 0, e = Modules.size(); m != e; ++m) {
- Module &M = *Modules[m]->getModule();
+ Module &M = *Modules[m];
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
// In the multi-module case, see what this global maps to.
sys::DynamicLibrary::SearchForAddressOfSymbol(I->getName()))
addGlobalMapping(I, SymAddr);
else {
- llvm_report_error("Could not resolve external global address: "
+ report_fatal_error("Could not resolve external global address: "
+I->getName());
}
}