Make ExecutionEngine owning a DataLayout

Summary:
This change is part of a series of commits dedicated to have a single
DataLayout during compilation by using always the one owned by the
module.

The ExecutionEngine will act as an exception and will be unsafe to
be reused across context. We don't enforce this rule but undefined
behavior can occurs if the user tries to do it.

Reviewers: lhames

Subscribers: echristo, llvm-commits, rafael, yaron.keren

Differential Revision: http://reviews.llvm.org/D11110

From: Mehdi Amini <mehdi.amini@apple.com>
llvm-svn: 242387
This commit is contained in:
Mehdi Amini 2015-07-16 06:17:14 +00:00
parent bd7287ebe5
commit f2643f41b4
9 changed files with 61 additions and 55 deletions

View File

@ -104,7 +104,12 @@ class ExecutionEngine {
ExecutionEngineState EEState; ExecutionEngineState EEState;
/// The target data for the platform for which execution is being performed. /// The target data for the platform for which execution is being performed.
const DataLayout *DL; ///
/// Note: the DataLayout is LLVMContext specific because it has an
/// internal cache based on type pointers. It makes unsafe to reuse the
/// ExecutionEngine across context, we don't enforce this rule but undefined
/// behavior can occurs if the user tries to do it.
const DataLayout DL;
/// Whether lazy JIT compilation is enabled. /// Whether lazy JIT compilation is enabled.
bool CompilingLazily; bool CompilingLazily;
@ -126,8 +131,6 @@ protected:
/// optimize for the case where there is only one module. /// optimize for the case where there is only one module.
SmallVector<std::unique_ptr<Module>, 1> Modules; SmallVector<std::unique_ptr<Module>, 1> Modules;
void setDataLayout(const DataLayout *Val) { DL = Val; }
/// getMemoryforGV - Allocate memory for a global variable. /// getMemoryforGV - Allocate memory for a global variable.
virtual char *getMemoryForGV(const GlobalVariable *GV); virtual char *getMemoryForGV(const GlobalVariable *GV);
@ -194,7 +197,7 @@ public:
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
const DataLayout *getDataLayout() const { return DL; } const DataLayout &getDataLayout() const { return DL; }
/// removeModule - Remove a Module from the list of modules. Returns true if /// removeModule - Remove a Module from the list of modules. Returns true if
/// M is found. /// M is found.
@ -478,8 +481,8 @@ public:
} }
protected: protected:
ExecutionEngine() {} ExecutionEngine(const DataLayout DL) : DL(std::move(DL)){};
explicit ExecutionEngine(std::unique_ptr<Module> M); explicit ExecutionEngine(const DataLayout DL, std::unique_ptr<Module> M);
void emitGlobals(); void emitGlobals();

View File

@ -61,8 +61,8 @@ ExecutionEngine *(*ExecutionEngine::InterpCtor)(std::unique_ptr<Module> M,
void JITEventListener::anchor() {} void JITEventListener::anchor() {}
ExecutionEngine::ExecutionEngine(std::unique_ptr<Module> M) ExecutionEngine::ExecutionEngine(const DataLayout DL, std::unique_ptr<Module> M)
: LazyFunctionCreator(nullptr) { : DL(std::move(DL)), LazyFunctionCreator(nullptr) {
CompilingLazily = false; CompilingLazily = false;
GVCompilationDisabled = false; GVCompilationDisabled = false;
SymbolSearchingDisabled = false; SymbolSearchingDisabled = false;
@ -115,7 +115,7 @@ public:
} // anonymous namespace } // anonymous namespace
char *ExecutionEngine::getMemoryForGV(const GlobalVariable *GV) { char *ExecutionEngine::getMemoryForGV(const GlobalVariable *GV) {
return GVMemoryBlock::Create(GV, *getDataLayout()); return GVMemoryBlock::Create(GV, getDataLayout());
} }
void ExecutionEngine::addObjectFile(std::unique_ptr<object::ObjectFile> O) { void ExecutionEngine::addObjectFile(std::unique_ptr<object::ObjectFile> O) {
@ -326,7 +326,7 @@ void *ArgvArray::reset(LLVMContext &C, ExecutionEngine *EE,
const std::vector<std::string> &InputArgv) { const std::vector<std::string> &InputArgv) {
Values.clear(); // Free the old contents. Values.clear(); // Free the old contents.
Values.reserve(InputArgv.size()); Values.reserve(InputArgv.size());
unsigned PtrSize = EE->getDataLayout()->getPointerSize(); unsigned PtrSize = EE->getDataLayout().getPointerSize();
Array = make_unique<char[]>((InputArgv.size()+1)*PtrSize); Array = make_unique<char[]>((InputArgv.size()+1)*PtrSize);
DEBUG(dbgs() << "JIT: ARGV = " << (void*)Array.get() << "\n"); DEBUG(dbgs() << "JIT: ARGV = " << (void*)Array.get() << "\n");
@ -401,7 +401,7 @@ void ExecutionEngine::runStaticConstructorsDestructors(bool isDtors) {
#ifndef NDEBUG #ifndef NDEBUG
/// isTargetNullPtr - Return whether the target pointer stored at Loc is null. /// isTargetNullPtr - Return whether the target pointer stored at Loc is null.
static bool isTargetNullPtr(ExecutionEngine *EE, void *Loc) { static bool isTargetNullPtr(ExecutionEngine *EE, void *Loc) {
unsigned PtrSize = EE->getDataLayout()->getPointerSize(); unsigned PtrSize = EE->getDataLayout().getPointerSize();
for (unsigned i = 0; i < PtrSize; ++i) for (unsigned i = 0; i < PtrSize; ++i)
if (*(i + (uint8_t*)Loc)) if (*(i + (uint8_t*)Loc))
return false; return false;
@ -634,8 +634,8 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
case Instruction::GetElementPtr: { case Instruction::GetElementPtr: {
// Compute the index // Compute the index
GenericValue Result = getConstantValue(Op0); GenericValue Result = getConstantValue(Op0);
APInt Offset(DL->getPointerSizeInBits(), 0); APInt Offset(DL.getPointerSizeInBits(), 0);
cast<GEPOperator>(CE)->accumulateConstantOffset(*DL, Offset); cast<GEPOperator>(CE)->accumulateConstantOffset(DL, Offset);
char* tmp = (char*) Result.PointerVal; char* tmp = (char*) Result.PointerVal;
Result = PTOGV(tmp + Offset.getSExtValue()); Result = PTOGV(tmp + Offset.getSExtValue());
@ -722,16 +722,16 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
} }
case Instruction::PtrToInt: { case Instruction::PtrToInt: {
GenericValue GV = getConstantValue(Op0); GenericValue GV = getConstantValue(Op0);
uint32_t PtrWidth = DL->getTypeSizeInBits(Op0->getType()); uint32_t PtrWidth = DL.getTypeSizeInBits(Op0->getType());
assert(PtrWidth <= 64 && "Bad pointer width"); assert(PtrWidth <= 64 && "Bad pointer width");
GV.IntVal = APInt(PtrWidth, uintptr_t(GV.PointerVal)); GV.IntVal = APInt(PtrWidth, uintptr_t(GV.PointerVal));
uint32_t IntWidth = DL->getTypeSizeInBits(CE->getType()); uint32_t IntWidth = DL.getTypeSizeInBits(CE->getType());
GV.IntVal = GV.IntVal.zextOrTrunc(IntWidth); GV.IntVal = GV.IntVal.zextOrTrunc(IntWidth);
return GV; return GV;
} }
case Instruction::IntToPtr: { case Instruction::IntToPtr: {
GenericValue GV = getConstantValue(Op0); GenericValue GV = getConstantValue(Op0);
uint32_t PtrWidth = DL->getTypeSizeInBits(CE->getType()); uint32_t PtrWidth = DL.getTypeSizeInBits(CE->getType());
GV.IntVal = GV.IntVal.zextOrTrunc(PtrWidth); GV.IntVal = GV.IntVal.zextOrTrunc(PtrWidth);
assert(GV.IntVal.getBitWidth() <= 64 && "Bad pointer width"); assert(GV.IntVal.getBitWidth() <= 64 && "Bad pointer width");
GV.PointerVal = PointerTy(uintptr_t(GV.IntVal.getZExtValue())); GV.PointerVal = PointerTy(uintptr_t(GV.IntVal.getZExtValue()));
@ -1033,7 +1033,7 @@ static void StoreIntToMemory(const APInt &IntVal, uint8_t *Dst,
void ExecutionEngine::StoreValueToMemory(const GenericValue &Val, void ExecutionEngine::StoreValueToMemory(const GenericValue &Val,
GenericValue *Ptr, Type *Ty) { GenericValue *Ptr, Type *Ty) {
const unsigned StoreBytes = getDataLayout()->getTypeStoreSize(Ty); const unsigned StoreBytes = getDataLayout().getTypeStoreSize(Ty);
switch (Ty->getTypeID()) { switch (Ty->getTypeID()) {
default: default:
@ -1073,7 +1073,7 @@ void ExecutionEngine::StoreValueToMemory(const GenericValue &Val,
break; break;
} }
if (sys::IsLittleEndianHost != getDataLayout()->isLittleEndian()) if (sys::IsLittleEndianHost != getDataLayout().isLittleEndian())
// Host and target are different endian - reverse the stored bytes. // Host and target are different endian - reverse the stored bytes.
std::reverse((uint8_t*)Ptr, StoreBytes + (uint8_t*)Ptr); std::reverse((uint8_t*)Ptr, StoreBytes + (uint8_t*)Ptr);
} }
@ -1110,7 +1110,7 @@ static void LoadIntFromMemory(APInt &IntVal, uint8_t *Src, unsigned LoadBytes) {
void ExecutionEngine::LoadValueFromMemory(GenericValue &Result, void ExecutionEngine::LoadValueFromMemory(GenericValue &Result,
GenericValue *Ptr, GenericValue *Ptr,
Type *Ty) { Type *Ty) {
const unsigned LoadBytes = getDataLayout()->getTypeStoreSize(Ty); const unsigned LoadBytes = getDataLayout().getTypeStoreSize(Ty);
switch (Ty->getTypeID()) { switch (Ty->getTypeID()) {
case Type::IntegerTyID: case Type::IntegerTyID:
@ -1176,20 +1176,20 @@ void ExecutionEngine::InitializeMemory(const Constant *Init, void *Addr) {
if (const ConstantVector *CP = dyn_cast<ConstantVector>(Init)) { if (const ConstantVector *CP = dyn_cast<ConstantVector>(Init)) {
unsigned ElementSize = unsigned ElementSize =
getDataLayout()->getTypeAllocSize(CP->getType()->getElementType()); getDataLayout().getTypeAllocSize(CP->getType()->getElementType());
for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i)
InitializeMemory(CP->getOperand(i), (char*)Addr+i*ElementSize); InitializeMemory(CP->getOperand(i), (char*)Addr+i*ElementSize);
return; return;
} }
if (isa<ConstantAggregateZero>(Init)) { if (isa<ConstantAggregateZero>(Init)) {
memset(Addr, 0, (size_t)getDataLayout()->getTypeAllocSize(Init->getType())); memset(Addr, 0, (size_t)getDataLayout().getTypeAllocSize(Init->getType()));
return; return;
} }
if (const ConstantArray *CPA = dyn_cast<ConstantArray>(Init)) { if (const ConstantArray *CPA = dyn_cast<ConstantArray>(Init)) {
unsigned ElementSize = unsigned ElementSize =
getDataLayout()->getTypeAllocSize(CPA->getType()->getElementType()); getDataLayout().getTypeAllocSize(CPA->getType()->getElementType());
for (unsigned i = 0, e = CPA->getNumOperands(); i != e; ++i) for (unsigned i = 0, e = CPA->getNumOperands(); i != e; ++i)
InitializeMemory(CPA->getOperand(i), (char*)Addr+i*ElementSize); InitializeMemory(CPA->getOperand(i), (char*)Addr+i*ElementSize);
return; return;
@ -1197,7 +1197,7 @@ void ExecutionEngine::InitializeMemory(const Constant *Init, void *Addr) {
if (const ConstantStruct *CPS = dyn_cast<ConstantStruct>(Init)) { if (const ConstantStruct *CPS = dyn_cast<ConstantStruct>(Init)) {
const StructLayout *SL = const StructLayout *SL =
getDataLayout()->getStructLayout(cast<StructType>(CPS->getType())); getDataLayout().getStructLayout(cast<StructType>(CPS->getType()));
for (unsigned i = 0, e = CPS->getNumOperands(); i != e; ++i) for (unsigned i = 0, e = CPS->getNumOperands(); i != e; ++i)
InitializeMemory(CPS->getOperand(i), (char*)Addr+SL->getElementOffset(i)); InitializeMemory(CPS->getOperand(i), (char*)Addr+SL->getElementOffset(i));
return; return;
@ -1342,7 +1342,7 @@ void ExecutionEngine::EmitGlobalVariable(const GlobalVariable *GV) {
InitializeMemory(GV->getInitializer(), GA); InitializeMemory(GV->getInitializer(), GA);
Type *ElTy = GV->getType()->getElementType(); Type *ElTy = GV->getType()->getElementType();
size_t GVSize = (size_t)getDataLayout()->getTypeAllocSize(ElTy); size_t GVSize = (size_t)getDataLayout().getTypeAllocSize(ElTy);
NumInitBytes += (unsigned)GVSize; NumInitBytes += (unsigned)GVSize;
++NumGlobals; ++NumGlobals;
} }

View File

@ -318,7 +318,7 @@ void *LLVMRecompileAndRelinkFunction(LLVMExecutionEngineRef EE,
} }
LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE) { LLVMTargetDataRef LLVMGetExecutionEngineTargetData(LLVMExecutionEngineRef EE) {
return wrap(unwrap(EE)->getDataLayout()); return wrap(&unwrap(EE)->getDataLayout());
} }
LLVMTargetMachineRef LLVMTargetMachineRef

View File

@ -968,7 +968,7 @@ void Interpreter::visitAllocaInst(AllocaInst &I) {
unsigned NumElements = unsigned NumElements =
getOperandValue(I.getOperand(0), SF).IntVal.getZExtValue(); getOperandValue(I.getOperand(0), SF).IntVal.getZExtValue();
unsigned TypeSize = (size_t)TD.getTypeAllocSize(Ty); unsigned TypeSize = (size_t)getDataLayout().getTypeAllocSize(Ty);
// Avoid malloc-ing zero bytes, use max()... // Avoid malloc-ing zero bytes, use max()...
unsigned MemToAlloc = std::max(1U, NumElements * TypeSize); unsigned MemToAlloc = std::max(1U, NumElements * TypeSize);
@ -1000,7 +1000,7 @@ GenericValue Interpreter::executeGEPOperation(Value *Ptr, gep_type_iterator I,
for (; I != E; ++I) { for (; I != E; ++I) {
if (StructType *STy = dyn_cast<StructType>(*I)) { if (StructType *STy = dyn_cast<StructType>(*I)) {
const StructLayout *SLO = TD.getStructLayout(STy); const StructLayout *SLO = getDataLayout().getStructLayout(STy);
const ConstantInt *CPU = cast<ConstantInt>(I.getOperand()); const ConstantInt *CPU = cast<ConstantInt>(I.getOperand());
unsigned Index = unsigned(CPU->getZExtValue()); unsigned Index = unsigned(CPU->getZExtValue());
@ -1020,7 +1020,7 @@ GenericValue Interpreter::executeGEPOperation(Value *Ptr, gep_type_iterator I,
assert(BitWidth == 64 && "Invalid index type for getelementptr"); assert(BitWidth == 64 && "Invalid index type for getelementptr");
Idx = (int64_t)IdxGV.IntVal.getZExtValue(); Idx = (int64_t)IdxGV.IntVal.getZExtValue();
} }
Total += TD.getTypeAllocSize(ST->getElementType())*Idx; Total += getDataLayout().getTypeAllocSize(ST->getElementType()) * Idx;
} }
} }
@ -1477,7 +1477,7 @@ GenericValue Interpreter::executeIntToPtrInst(Value *SrcVal, Type *DstTy,
GenericValue Dest, Src = getOperandValue(SrcVal, SF); GenericValue Dest, Src = getOperandValue(SrcVal, SF);
assert(DstTy->isPointerTy() && "Invalid PtrToInt instruction"); assert(DstTy->isPointerTy() && "Invalid PtrToInt instruction");
uint32_t PtrSize = TD.getPointerSizeInBits(); uint32_t PtrSize = getDataLayout().getPointerSizeInBits();
if (PtrSize != Src.IntVal.getBitWidth()) if (PtrSize != Src.IntVal.getBitWidth())
Src.IntVal = Src.IntVal.zextOrTrunc(PtrSize); Src.IntVal = Src.IntVal.zextOrTrunc(PtrSize);
@ -1497,7 +1497,7 @@ GenericValue Interpreter::executeBitCastInst(Value *SrcVal, Type *DstTy,
(DstTy->getTypeID() == Type::VectorTyID)) { (DstTy->getTypeID() == Type::VectorTyID)) {
// vector src bitcast to vector dst or vector src bitcast to scalar dst or // vector src bitcast to vector dst or vector src bitcast to scalar dst or
// scalar src bitcast to vector dst // scalar src bitcast to vector dst
bool isLittleEndian = TD.isLittleEndian(); bool isLittleEndian = getDataLayout().isLittleEndian();
GenericValue TempDst, TempSrc, SrcVec; GenericValue TempDst, TempSrc, SrcVec;
const Type *SrcElemTy; const Type *SrcElemTy;
const Type *DstElemTy; const Type *DstElemTy;

View File

@ -368,7 +368,7 @@ static GenericValue lle_X_sprintf(FunctionType *FT,
case 'x': case 'X': case 'x': case 'X':
if (HowLong >= 1) { if (HowLong >= 1) {
if (HowLong == 1 && if (HowLong == 1 &&
TheInterpreter->getDataLayout()->getPointerSizeInBits() == 64 && TheInterpreter->getDataLayout().getPointerSizeInBits() == 64 &&
sizeof(long) < sizeof(int64_t)) { sizeof(long) < sizeof(int64_t)) {
// Make sure we use %lld with a 64 bit argument because we might be // Make sure we use %lld with a 64 bit argument because we might be
// compiling LLI on a 32 bit compiler. // compiling LLI on a 32 bit compiler.

View File

@ -49,16 +49,15 @@ ExecutionEngine *Interpreter::create(std::unique_ptr<Module> M,
// Interpreter ctor - Initialize stuff // Interpreter ctor - Initialize stuff
// //
Interpreter::Interpreter(std::unique_ptr<Module> M) Interpreter::Interpreter(std::unique_ptr<Module> M)
: ExecutionEngine(std::move(M)), TD(Modules.back().get()) { : ExecutionEngine(M->getDataLayout(), std::move(M)) {
memset(&ExitValue.Untyped, 0, sizeof(ExitValue.Untyped)); memset(&ExitValue.Untyped, 0, sizeof(ExitValue.Untyped));
setDataLayout(&TD);
// Initialize the "backend" // Initialize the "backend"
initializeExecutionEngine(); initializeExecutionEngine();
initializeExternalFunctions(); initializeExternalFunctions();
emitGlobals(); emitGlobals();
IL = new IntrinsicLowering(TD); IL = new IntrinsicLowering(getDataLayout());
} }
Interpreter::~Interpreter() { Interpreter::~Interpreter() {

View File

@ -95,7 +95,6 @@ struct ExecutionContext {
// //
class Interpreter : public ExecutionEngine, public InstVisitor<Interpreter> { class Interpreter : public ExecutionEngine, public InstVisitor<Interpreter> {
GenericValue ExitValue; // The return value of the called function GenericValue ExitValue; // The return value of the called function
DataLayout TD;
IntrinsicLowering *IL; IntrinsicLowering *IL;
// The runtime stack of executing code. The top of the stack is the current // The runtime stack of executing code. The top of the stack is the current

View File

@ -65,12 +65,13 @@ MCJIT::createJIT(std::unique_ptr<Module> M,
std::move(Resolver)); std::move(Resolver));
} }
MCJIT::MCJIT(std::unique_ptr<Module> M, std::unique_ptr<TargetMachine> tm, MCJIT::MCJIT(std::unique_ptr<Module> M, std::unique_ptr<TargetMachine> TM,
std::shared_ptr<MCJITMemoryManager> MemMgr, std::shared_ptr<MCJITMemoryManager> MemMgr,
std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver) std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver)
: ExecutionEngine(std::move(M)), TM(std::move(tm)), Ctx(nullptr), : ExecutionEngine(*TM->getDataLayout(), std::move(M)), TM(std::move(TM)),
MemMgr(std::move(MemMgr)), Resolver(*this, std::move(Resolver)), Ctx(nullptr), MemMgr(std::move(MemMgr)),
Dyld(*this->MemMgr, this->Resolver), ObjCache(nullptr) { Resolver(*this, std::move(Resolver)), Dyld(*this->MemMgr, this->Resolver),
ObjCache(nullptr) {
// FIXME: We are managing our modules, so we do not want the base class // FIXME: We are managing our modules, so we do not want the base class
// ExecutionEngine to manage them as well. To avoid double destruction // ExecutionEngine to manage them as well. To avoid double destruction
// of the first (and only) module added in ExecutionEngine constructor // of the first (and only) module added in ExecutionEngine constructor
@ -85,7 +86,6 @@ MCJIT::MCJIT(std::unique_ptr<Module> M, std::unique_ptr<TargetMachine> tm,
Modules.clear(); Modules.clear();
OwnedModules.addModule(std::move(First)); OwnedModules.addModule(std::move(First));
setDataLayout(TM->getDataLayout());
RegisterJITEventListener(JITEventListener::createGDBRegistrationListener()); RegisterJITEventListener(JITEventListener::createGDBRegistrationListener());
} }
@ -193,7 +193,11 @@ void MCJIT::generateCodeForModule(Module *M) {
if (ObjCache) if (ObjCache)
ObjectToLoad = ObjCache->getObject(M); ObjectToLoad = ObjCache->getObject(M);
M->setDataLayout(*TM->getDataLayout()); if (M->getDataLayout().isDefault()) {
M->setDataLayout(getDataLayout());
} else {
assert(M->getDataLayout() == getDataLayout() && "DataLayout Mismatch");
}
// If the cache did not contain a suitable object, compile the object // If the cache did not contain a suitable object, compile the object
if (!ObjectToLoad) { if (!ObjectToLoad) {
@ -265,7 +269,7 @@ void MCJIT::finalizeModule(Module *M) {
RuntimeDyld::SymbolInfo MCJIT::findExistingSymbol(const std::string &Name) { RuntimeDyld::SymbolInfo MCJIT::findExistingSymbol(const std::string &Name) {
SmallString<128> FullName; SmallString<128> FullName;
Mangler::getNameWithPrefix(FullName, Name, *TM->getDataLayout()); Mangler::getNameWithPrefix(FullName, Name, getDataLayout());
return Dyld.getSymbol(FullName); return Dyld.getSymbol(FullName);
} }

View File

@ -137,25 +137,26 @@ public:
} }
OrcMCJITReplacement( OrcMCJITReplacement(
std::shared_ptr<MCJITMemoryManager> MemMgr, std::shared_ptr<MCJITMemoryManager> MemMgr,
std::shared_ptr<RuntimeDyld::SymbolResolver> ClientResolver, std::shared_ptr<RuntimeDyld::SymbolResolver> ClientResolver,
std::unique_ptr<TargetMachine> TM) std::unique_ptr<TargetMachine> TM)
: TM(std::move(TM)), MemMgr(*this, std::move(MemMgr)), : ExecutionEngine(*TM->getDataLayout()), TM(std::move(TM)),
Resolver(*this), ClientResolver(std::move(ClientResolver)), MemMgr(*this, std::move(MemMgr)), Resolver(*this),
NotifyObjectLoaded(*this), NotifyFinalized(*this), ClientResolver(std::move(ClientResolver)), NotifyObjectLoaded(*this),
NotifyFinalized(*this),
ObjectLayer(NotifyObjectLoaded, NotifyFinalized), ObjectLayer(NotifyObjectLoaded, NotifyFinalized),
CompileLayer(ObjectLayer, SimpleCompiler(*this->TM)), CompileLayer(ObjectLayer, SimpleCompiler(*this->TM)),
LazyEmitLayer(CompileLayer) { LazyEmitLayer(CompileLayer) {}
setDataLayout(this->TM->getDataLayout());
}
void addModule(std::unique_ptr<Module> M) override { void addModule(std::unique_ptr<Module> M) override {
// If this module doesn't have a DataLayout attached then attach the // If this module doesn't have a DataLayout attached then attach the
// default. // default.
if (M->getDataLayout().isDefault()) if (M->getDataLayout().isDefault()) {
M->setDataLayout(*getDataLayout()); M->setDataLayout(getDataLayout());
} else {
assert(M->getDataLayout() == getDataLayout() && "DataLayout Mismatch");
}
Modules.push_back(std::move(M)); Modules.push_back(std::move(M));
std::vector<Module *> Ms; std::vector<Module *> Ms;
Ms.push_back(&*Modules.back()); Ms.push_back(&*Modules.back());
@ -310,7 +311,7 @@ private:
std::string MangledName; std::string MangledName;
{ {
raw_string_ostream MangledNameStream(MangledName); raw_string_ostream MangledNameStream(MangledName);
Mang.getNameWithPrefix(MangledNameStream, Name, *TM->getDataLayout()); Mang.getNameWithPrefix(MangledNameStream, Name, getDataLayout());
} }
return MangledName; return MangledName;
} }