#define DEBUG_TYPE "jit"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
-
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Module.h"
-#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Statistic.h"
+#include "llvm/ExecutionEngine/GenericValue.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Operator.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Host.h"
#include "llvm/Support/MutexGuard.h"
+#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/ValueHandle.h"
#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/DynamicLibrary.h"
-#include "llvm/Support/Host.h"
-#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
#include <cmath>
#include <cstring>
Module *M,
std::string *ErrorStr,
JITMemoryManager *JMM,
- CodeGenOpt::Level OptLevel,
bool GVsWithCode,
TargetMachine *TM) = 0;
ExecutionEngine *(*ExecutionEngine::MCJITCtor)(
Module *M,
std::string *ErrorStr,
JITMemoryManager *JMM,
- CodeGenOpt::Level OptLevel,
bool GVsWithCode,
TargetMachine *TM) = 0;
ExecutionEngine *(*ExecutionEngine::InterpCtor)(Module *M,
public:
/// \brief Returns the address the GlobalVariable should be written into. The
/// GVMemoryBlock object prefixes that.
- static char *Create(const GlobalVariable *GV, const TargetData& TD) {
+ static char *Create(const GlobalVariable *GV, const DataLayout& TD) {
Type *ElTy = GV->getType()->getElementType();
size_t GVSize = (size_t)TD.getTypeAllocSize(ElTy);
void *RawMemory = ::operator new(
- TargetData::RoundUpAlignment(sizeof(GVMemoryBlock),
+ DataLayout::RoundUpAlignment(sizeof(GVMemoryBlock),
TD.getPreferredAlignment(GV))
+ GVSize);
new(RawMemory) GVMemoryBlock(GV);
} // anonymous namespace
char *ExecutionEngine::getMemoryForGV(const GlobalVariable *GV) {
- return GVMemoryBlock::Create(GV, *getTargetData());
+ return GVMemoryBlock::Create(GV, *getDataLayout());
}
bool ExecutionEngine::removeModule(Module *M) {
void *ArgvArray::reset(LLVMContext &C, ExecutionEngine *EE,
const std::vector<std::string> &InputArgv) {
clear(); // Free the old contents.
- unsigned PtrSize = EE->getTargetData()->getPointerSize();
+ unsigned PtrSize = EE->getDataLayout()->getPointerSize();
Array = new char[(InputArgv.size()+1)*PtrSize];
DEBUG(dbgs() << "JIT: ARGV = " << (void*)Array << "\n");
// Should be an array of '{ i32, void ()* }' structs. The first value is
// the init priority, which we ignore.
- if (isa<ConstantAggregateZero>(GV->getInitializer()))
+ ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
+ if (InitList == 0)
return;
- ConstantArray *InitList = cast<ConstantArray>(GV->getInitializer());
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
- if (isa<ConstantAggregateZero>(InitList->getOperand(i)))
- continue;
- ConstantStruct *CS = cast<ConstantStruct>(InitList->getOperand(i));
+ ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i));
+ if (CS == 0) continue;
Constant *FP = CS->getOperand(1);
if (FP->isNullValue())
#ifndef NDEBUG
/// isTargetNullPtr - Return whether the target pointer stored at Loc is null.
static bool isTargetNullPtr(ExecutionEngine *EE, void *Loc) {
- unsigned PtrSize = EE->getTargetData()->getPointerSize();
+ unsigned PtrSize = EE->getDataLayout()->getPointerSize();
for (unsigned i = 0; i < PtrSize; ++i)
if (*(i + (uint8_t*)Loc))
return false;
std::string *ErrorStr,
CodeGenOpt::Level OptLevel,
bool GVsWithCode) {
- return EngineBuilder(M)
+ EngineBuilder EB = EngineBuilder(M)
.setEngineKind(ForceInterpreter
? EngineKind::Interpreter
: EngineKind::JIT)
.setErrorStr(ErrorStr)
.setOptLevel(OptLevel)
- .setAllocateGVsWithCode(GVsWithCode)
- .create();
+ .setAllocateGVsWithCode(GVsWithCode);
+
+ return EB.create();
}
/// createJIT - This is the factory method for creating a JIT for the current
ExecutionEngine *ExecutionEngine::createJIT(Module *M,
std::string *ErrorStr,
JITMemoryManager *JMM,
- CodeGenOpt::Level OptLevel,
+ CodeGenOpt::Level OL,
bool GVsWithCode,
+ Reloc::Model RM,
CodeModel::Model CMM) {
if (ExecutionEngine::JITCtor == 0) {
if (ErrorStr)
// Use the defaults for extra parameters. Users can use EngineBuilder to
// set them.
- StringRef MArch = "";
- StringRef MCPU = "";
- SmallVector<std::string, 1> MAttrs;
-
- TargetMachine *TM =
- EngineBuilder::selectTarget(M, MArch, MCPU, MAttrs, ErrorStr);
+ EngineBuilder EB(M);
+ EB.setEngineKind(EngineKind::JIT);
+ EB.setErrorStr(ErrorStr);
+ EB.setRelocationModel(RM);
+ EB.setCodeModel(CMM);
+ EB.setAllocateGVsWithCode(GVsWithCode);
+ EB.setOptLevel(OL);
+ EB.setJITMemoryManager(JMM);
+
+ // TODO: permit custom TargetOptions here
+ TargetMachine *TM = EB.selectTarget();
if (!TM || (ErrorStr && ErrorStr->length() > 0)) return 0;
- TM->setCodeModel(CMM);
- return ExecutionEngine::JITCtor(M, ErrorStr, JMM, OptLevel, GVsWithCode, TM);
+ return ExecutionEngine::JITCtor(M, ErrorStr, JMM, GVsWithCode, TM);
}
-ExecutionEngine *EngineBuilder::create() {
+ExecutionEngine *EngineBuilder::create(TargetMachine *TM) {
+ OwningPtr<TargetMachine> TheTM(TM); // Take ownership.
+
// 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 (sys::DynamicLibrary::LoadLibraryPermanently(0, ErrorStr))
// Unless the interpreter was explicitly selected or the JIT is not linked,
// try making a JIT.
- if (WhichEngine & EngineKind::JIT) {
- if (TargetMachine *TM =
- EngineBuilder::selectTarget(M, MArch, MCPU, MAttrs, ErrorStr)) {
- TM->setCodeModel(CMModel);
-
- if (UseMCJIT && ExecutionEngine::MCJITCtor) {
- ExecutionEngine *EE =
- ExecutionEngine::MCJITCtor(M, ErrorStr, JMM, OptLevel,
- AllocateGVsWithCode, TM);
- if (EE) return EE;
- } else if (ExecutionEngine::JITCtor) {
- ExecutionEngine *EE =
- ExecutionEngine::JITCtor(M, ErrorStr, JMM, OptLevel,
- AllocateGVsWithCode, TM);
- if (EE) return EE;
- }
+ if ((WhichEngine & EngineKind::JIT) && TheTM) {
+ Triple TT(M->getTargetTriple());
+ if (!TM->getTarget().hasJIT()) {
+ errs() << "WARNING: This target JIT is not designed for the host"
+ << " you are running. If bad things happen, please choose"
+ << " a different -march switch.\n";
+ }
+
+ if (UseMCJIT && ExecutionEngine::MCJITCtor) {
+ ExecutionEngine *EE =
+ ExecutionEngine::MCJITCtor(M, ErrorStr, JMM,
+ AllocateGVsWithCode, TheTM.take());
+ if (EE) return EE;
+ } else if (ExecutionEngine::JITCtor) {
+ ExecutionEngine *EE =
+ ExecutionEngine::JITCtor(M, ErrorStr, JMM,
+ AllocateGVsWithCode, TheTM.take());
+ if (EE) return EE;
}
}
return 0;
}
- if ((WhichEngine & EngineKind::JIT) && ExecutionEngine::JITCtor == 0) {
+ if ((WhichEngine & EngineKind::JIT) && ExecutionEngine::JITCtor == 0 &&
+ ExecutionEngine::MCJITCtor == 0) {
if (ErrorStr)
*ErrorStr = "JIT has not been linked in.";
}
case Instruction::GetElementPtr: {
// Compute the index
GenericValue Result = getConstantValue(Op0);
- SmallVector<Value*, 8> Indices(CE->op_begin()+1, CE->op_end());
- uint64_t Offset =
- TD->getIndexedOffset(Op0->getType(), &Indices[0], Indices.size());
+ APInt Offset(TD->getPointerSizeInBits(), 0);
+ cast<GEPOperator>(CE)->accumulateConstantOffset(*TD, Offset);
char* tmp = (char*) Result.PointerVal;
- Result = PTOGV(tmp + Offset);
+ Result = PTOGV(tmp + Offset.getSExtValue());
return Result;
}
case Instruction::Trunc: {
else if (Op0->getType()->isDoubleTy())
GV.IntVal = APIntOps::RoundDoubleToAPInt(GV.DoubleVal, BitWidth);
else if (Op0->getType()->isX86_FP80Ty()) {
- APFloat apf = APFloat(GV.IntVal);
+ APFloat apf = APFloat(APFloat::x87DoubleExtended, GV.IntVal);
uint64_t v;
bool ignored;
(void)apf.convertToInteger(&v, BitWidth,
}
case Instruction::PtrToInt: {
GenericValue GV = getConstantValue(Op0);
- uint32_t PtrWidth = TD->getPointerSizeInBits();
+ uint32_t PtrWidth = TD->getTypeSizeInBits(Op0->getType());
+ assert(PtrWidth <= 64 && "Bad pointer width");
GV.IntVal = APInt(PtrWidth, uintptr_t(GV.PointerVal));
+ uint32_t IntWidth = TD->getTypeSizeInBits(CE->getType());
+ GV.IntVal = GV.IntVal.zextOrTrunc(IntWidth);
return GV;
}
case Instruction::IntToPtr: {
GenericValue GV = getConstantValue(Op0);
- uint32_t PtrWidth = TD->getPointerSizeInBits();
- if (PtrWidth != GV.IntVal.getBitWidth())
- GV.IntVal = GV.IntVal.zextOrTrunc(PtrWidth);
+ uint32_t PtrWidth = TD->getTypeSizeInBits(CE->getType());
+ GV.IntVal = GV.IntVal.zextOrTrunc(PtrWidth);
assert(GV.IntVal.getBitWidth() <= 64 && "Bad pointer width");
GV.PointerVal = PointerTy(uintptr_t(GV.IntVal.getZExtValue()));
return GV;
case Type::X86_FP80TyID:
case Type::PPC_FP128TyID:
case Type::FP128TyID: {
- APFloat apfLHS = APFloat(LHS.IntVal);
+ const fltSemantics &Sem = CE->getOperand(0)->getType()->getFltSemantics();
+ APFloat apfLHS = APFloat(Sem, LHS.IntVal);
switch (CE->getOpcode()) {
default: llvm_unreachable("Invalid long double opcode");
case Instruction::FAdd:
- apfLHS.add(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven);
+ apfLHS.add(APFloat(Sem, RHS.IntVal), APFloat::rmNearestTiesToEven);
GV.IntVal = apfLHS.bitcastToAPInt();
break;
case Instruction::FSub:
- apfLHS.subtract(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven);
+ apfLHS.subtract(APFloat(Sem, RHS.IntVal),
+ APFloat::rmNearestTiesToEven);
GV.IntVal = apfLHS.bitcastToAPInt();
break;
case Instruction::FMul:
- apfLHS.multiply(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven);
+ apfLHS.multiply(APFloat(Sem, RHS.IntVal),
+ APFloat::rmNearestTiesToEven);
GV.IntVal = apfLHS.bitcastToAPInt();
break;
case Instruction::FDiv:
- apfLHS.divide(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven);
+ apfLHS.divide(APFloat(Sem, RHS.IntVal),
+ APFloat::rmNearestTiesToEven);
GV.IntVal = apfLHS.bitcastToAPInt();
break;
case Instruction::FRem:
- apfLHS.mod(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven);
+ apfLHS.mod(APFloat(Sem, RHS.IntVal),
+ APFloat::rmNearestTiesToEven);
GV.IntVal = apfLHS.bitcastToAPInt();
break;
}
static void StoreIntToMemory(const APInt &IntVal, uint8_t *Dst,
unsigned StoreBytes) {
assert((IntVal.getBitWidth()+7)/8 >= StoreBytes && "Integer too small!");
- uint8_t *Src = (uint8_t *)IntVal.getRawData();
+ const uint8_t *Src = (const uint8_t *)IntVal.getRawData();
if (sys::isLittleEndianHost()) {
// Little-endian host - the source is ordered from LSB to MSB. Order the
void ExecutionEngine::StoreValueToMemory(const GenericValue &Val,
GenericValue *Ptr, Type *Ty) {
- const unsigned StoreBytes = getTargetData()->getTypeStoreSize(Ty);
+ const unsigned StoreBytes = getDataLayout()->getTypeStoreSize(Ty);
switch (Ty->getTypeID()) {
case Type::IntegerTyID:
dbgs() << "Cannot store value of type " << *Ty << "!\n";
}
- if (sys::isLittleEndianHost() != getTargetData()->isLittleEndian())
+ if (sys::isLittleEndianHost() != getDataLayout()->isLittleEndian())
// Host and target are different endian - reverse the stored bytes.
std::reverse((uint8_t*)Ptr, StoreBytes + (uint8_t*)Ptr);
}
/// from Src into IntVal, which is assumed to be wide enough and to hold zero.
static void LoadIntFromMemory(APInt &IntVal, uint8_t *Src, unsigned LoadBytes) {
assert((IntVal.getBitWidth()+7)/8 >= LoadBytes && "Integer too small!");
- uint8_t *Dst = (uint8_t *)IntVal.getRawData();
+ uint8_t *Dst = reinterpret_cast<uint8_t *>(
+ const_cast<uint64_t *>(IntVal.getRawData()));
if (sys::isLittleEndianHost())
// Little-endian host - the destination must be ordered from LSB to MSB.
void ExecutionEngine::LoadValueFromMemory(GenericValue &Result,
GenericValue *Ptr,
Type *Ty) {
- const unsigned LoadBytes = getTargetData()->getTypeStoreSize(Ty);
+ const unsigned LoadBytes = getDataLayout()->getTypeStoreSize(Ty);
switch (Ty->getTypeID()) {
case Type::IntegerTyID:
void ExecutionEngine::InitializeMemory(const Constant *Init, void *Addr) {
DEBUG(dbgs() << "JIT: Initializing " << Addr << " ");
DEBUG(Init->dump());
- if (isa<UndefValue>(Init)) {
+ if (isa<UndefValue>(Init))
return;
- } else if (const ConstantVector *CP = dyn_cast<ConstantVector>(Init)) {
+
+ if (const ConstantVector *CP = dyn_cast<ConstantVector>(Init)) {
unsigned ElementSize =
- getTargetData()->getTypeAllocSize(CP->getType()->getElementType());
+ getDataLayout()->getTypeAllocSize(CP->getType()->getElementType());
for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i)
InitializeMemory(CP->getOperand(i), (char*)Addr+i*ElementSize);
return;
- } else if (isa<ConstantAggregateZero>(Init)) {
- memset(Addr, 0, (size_t)getTargetData()->getTypeAllocSize(Init->getType()));
+ }
+
+ if (isa<ConstantAggregateZero>(Init)) {
+ memset(Addr, 0, (size_t)getDataLayout()->getTypeAllocSize(Init->getType()));
return;
- } else if (const ConstantArray *CPA = dyn_cast<ConstantArray>(Init)) {
+ }
+
+ if (const ConstantArray *CPA = dyn_cast<ConstantArray>(Init)) {
unsigned ElementSize =
- getTargetData()->getTypeAllocSize(CPA->getType()->getElementType());
+ getDataLayout()->getTypeAllocSize(CPA->getType()->getElementType());
for (unsigned i = 0, e = CPA->getNumOperands(); i != e; ++i)
InitializeMemory(CPA->getOperand(i), (char*)Addr+i*ElementSize);
return;
- } else if (const ConstantStruct *CPS = dyn_cast<ConstantStruct>(Init)) {
+ }
+
+ if (const ConstantStruct *CPS = dyn_cast<ConstantStruct>(Init)) {
const StructLayout *SL =
- getTargetData()->getStructLayout(cast<StructType>(CPS->getType()));
+ getDataLayout()->getStructLayout(cast<StructType>(CPS->getType()));
for (unsigned i = 0, e = CPS->getNumOperands(); i != e; ++i)
InitializeMemory(CPS->getOperand(i), (char*)Addr+SL->getElementOffset(i));
return;
- } else if (Init->getType()->isFirstClassType()) {
+ }
+
+ if (const ConstantDataSequential *CDS =
+ dyn_cast<ConstantDataSequential>(Init)) {
+ // CDS is already laid out in host memory order.
+ StringRef Data = CDS->getRawDataValues();
+ memcpy(Addr, Data.data(), Data.size());
+ return;
+ }
+
+ if (Init->getType()->isFirstClassType()) {
GenericValue Val = getConstantValue(Init);
StoreValueToMemory(Val, (GenericValue*)Addr, Init->getType());
return;
InitializeMemory(GV->getInitializer(), GA);
Type *ElTy = GV->getType()->getElementType();
- size_t GVSize = (size_t)getTargetData()->getTypeAllocSize(ElTy);
+ size_t GVSize = (size_t)getDataLayout()->getTypeAllocSize(ElTy);
NumInitBytes += (unsigned)GVSize;
++NumGlobals;
}
void ExecutionEngineState::AddressMapConfig::onRAUW(ExecutionEngineState *,
const GlobalValue *,
const GlobalValue *) {
- assert(false && "The ExecutionEngine doesn't know how to handle a"
- " RAUW on a value it has a global mapping for.");
+ llvm_unreachable("The ExecutionEngine doesn't know how to handle a"
+ " RAUW on a value it has a global mapping for.");
}