[llvm] r258185 - [Orc] Refactor ObjectLinkingLayer::addObjectSet to defer loading objects until
Lang Hames via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 19 13:06:38 PST 2016
Author: lhames
Date: Tue Jan 19 15:06:38 2016
New Revision: 258185
URL: http://llvm.org/viewvc/llvm-project?rev=258185&view=rev
Log:
[Orc] Refactor ObjectLinkingLayer::addObjectSet to defer loading objects until
they're needed.
Prior to this patch objects were loaded (via RuntimeDyld::loadObject) when they
were added to the ObjectLinkingLayer, but were not relocated and finalized until
a symbol address was requested. In the interim, another object could be loaded
and finalized with the same memory manager, causing relocation/finalization of
the first object to fail (as the first finalization call may have marked the
allocated memory for the first object read-only).
By deferring the loadObject call (and subsequent memory allocations) until an
object file is needed we can avoid prematurely finalizing memory.
Modified:
llvm/trunk/include/llvm/ExecutionEngine/JITSymbolFlags.h
llvm/trunk/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
llvm/trunk/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
llvm/trunk/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h
llvm/trunk/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp
Modified: llvm/trunk/include/llvm/ExecutionEngine/JITSymbolFlags.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/JITSymbolFlags.h?rev=258185&r1=258184&r2=258185&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/JITSymbolFlags.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/JITSymbolFlags.h Tue Jan 19 15:06:38 2016
@@ -15,6 +15,7 @@
#define LLVM_EXECUTIONENGINE_JITSYMBOLFLAGS_H
#include "llvm/IR/GlobalValue.h"
+#include "llvm/Object/SymbolicFile.h"
namespace llvm {
@@ -69,7 +70,16 @@ public:
if (!GV.hasLocalLinkage() && !GV.hasHiddenVisibility())
Flags |= JITSymbolFlags::Exported;
return Flags;
+ }
+ static JITSymbolFlags
+ flagsFromObjectSymbol(const object::BasicSymbolRef &Symbol) {
+ JITSymbolFlags Flags = JITSymbolFlags::None;
+ if (Symbol.getFlags() & object::BasicSymbolRef::SF_Weak)
+ Flags |= JITSymbolFlags::Weak;
+ if (Symbol.getFlags() & object::BasicSymbolRef::SF_Exported)
+ Flags |= JITSymbolFlags::Exported;
+ return Flags;
}
private:
Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h?rev=258185&r1=258184&r2=258185&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h Tue Jan 19 15:06:38 2016
@@ -37,9 +37,6 @@ public:
private:
typedef typename BaseLayerT::ObjSetHandleT ObjSetHandleT;
- typedef std::vector<std::unique_ptr<object::ObjectFile>> OwningObjectVec;
- typedef std::vector<std::unique_ptr<MemoryBuffer>> OwningBufferVec;
-
public:
/// @brief Handle to a set of compiled modules.
typedef ObjSetHandleT ModuleSetHandleT;
@@ -62,28 +59,29 @@ public:
ModuleSetHandleT addModuleSet(ModuleSetT Ms,
MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver) {
- OwningObjectVec Objects;
- OwningBufferVec Buffers;
+ std::vector<std::unique_ptr<object::OwningBinary<object::ObjectFile>>>
+ Objects;
for (const auto &M : Ms) {
- std::unique_ptr<object::ObjectFile> Object;
- std::unique_ptr<MemoryBuffer> Buffer;
+ auto Object =
+ llvm::make_unique<object::OwningBinary<object::ObjectFile>>();
if (ObjCache)
- std::tie(Object, Buffer) = tryToLoadFromObjectCache(*M).takeBinary();
+ *Object = tryToLoadFromObjectCache(*M);
- if (!Object) {
- std::tie(Object, Buffer) = Compile(*M).takeBinary();
+ if (!Object->getBinary()) {
+ *Object = Compile(*M);
if (ObjCache)
- ObjCache->notifyObjectCompiled(&*M, Buffer->getMemBufferRef());
+ ObjCache->notifyObjectCompiled(&*M,
+ Object->getBinary()->getMemoryBufferRef());
}
Objects.push_back(std::move(Object));
- Buffers.push_back(std::move(Buffer));
}
ModuleSetHandleT H =
- BaseLayer.addObjectSet(Objects, std::move(MemMgr), std::move(Resolver));
+ BaseLayer.addObjectSet(std::move(Objects), std::move(MemMgr),
+ std::move(Resolver));
return H;
}
Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h?rev=258185&r1=258184&r2=258185&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h Tue Jan 19 15:06:38 2016
@@ -26,7 +26,6 @@ namespace orc {
class ObjectLinkingLayerBase {
protected:
-
/// @brief Holds a set of objects to be allocated/linked as a unit in the JIT.
///
/// An instance of this class will be created for each set of objects added
@@ -38,38 +37,32 @@ protected:
LinkedObjectSet(const LinkedObjectSet&) = delete;
void operator=(const LinkedObjectSet&) = delete;
public:
- LinkedObjectSet(RuntimeDyld::MemoryManager &MemMgr,
- RuntimeDyld::SymbolResolver &Resolver,
- bool ProcessAllSections)
- : RTDyld(llvm::make_unique<RuntimeDyld>(MemMgr, Resolver)),
- State(Raw) {
- RTDyld->setProcessAllSections(ProcessAllSections);
- }
-
+ LinkedObjectSet() = default;
virtual ~LinkedObjectSet() {}
- std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
- addObject(const object::ObjectFile &Obj) {
- return RTDyld->loadObject(Obj);
- }
-
- RuntimeDyld::SymbolInfo getSymbol(StringRef Name) const {
- return RTDyld->getSymbol(Name);
- }
+ virtual void finalize() = 0;
- bool NeedsFinalization() const { return (State == Raw); }
+ virtual JITSymbol::GetAddressFtor
+ getSymbolMaterializer(std::string Name) = 0;
- virtual void Finalize() = 0;
+ virtual void mapSectionAddress(const void *LocalAddress,
+ TargetAddress TargetAddr) const = 0;
- void mapSectionAddress(const void *LocalAddress, TargetAddress TargetAddr) {
- assert((State != Finalized) &&
- "Attempting to remap sections for finalized objects.");
- RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
+ JITSymbol getSymbol(StringRef Name, bool ExportedSymbolsOnly) {
+ auto SymEntry = SymbolTable.find(Name);
+ if (SymEntry == SymbolTable.end())
+ return nullptr;
+ if (!SymEntry->second.isExported() && ExportedSymbolsOnly)
+ return nullptr;
+ if (!Finalized)
+ return JITSymbol(getSymbolMaterializer(Name),
+ SymEntry->second.getFlags());
+ return JITSymbol(SymEntry->second.getAddress(),
+ SymEntry->second.getFlags());
}
-
protected:
- std::unique_ptr<RuntimeDyld> RTDyld;
- enum { Raw, Finalizing, Finalized } State;
+ StringMap<RuntimeDyld::SymbolInfo> SymbolTable;
+ bool Finalized = false;
};
typedef std::list<std::unique_ptr<LinkedObjectSet>> LinkedObjectSetListT;
@@ -79,6 +72,7 @@ public:
typedef LinkedObjectSetListT::iterator ObjSetHandleT;
};
+
/// @brief Default (no-op) action to perform when loading objects.
class DoNothingOnNotifyLoaded {
public:
@@ -95,34 +89,124 @@ public:
/// symbols.
template <typename NotifyLoadedFtor = DoNothingOnNotifyLoaded>
class ObjectLinkingLayer : public ObjectLinkingLayerBase {
+public:
+
+ /// @brief Functor for receiving finalization notifications.
+ typedef std::function<void(ObjSetHandleT)> NotifyFinalizedFtor;
+
private:
- template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
+ template <typename ObjSetT, typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT, typename FinalizerFtor>
class ConcreteLinkedObjectSet : public LinkedObjectSet {
public:
- ConcreteLinkedObjectSet(MemoryManagerPtrT MemMgr,
+ ConcreteLinkedObjectSet(ObjSetT Objects, MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver,
+ FinalizerFtor Finalizer,
bool ProcessAllSections)
- : LinkedObjectSet(*MemMgr, *Resolver, ProcessAllSections),
- MemMgr(std::move(MemMgr)), Resolver(std::move(Resolver)) { }
+ : MemMgr(std::move(MemMgr)),
+ PFC(make_unique<PreFinalizeContents>(std::move(Objects),
+ std::move(Resolver),
+ std::move(Finalizer),
+ ProcessAllSections)) {
+ buildInitialSymbolTable(PFC->Objects);
+ }
+
+ void setHandle(ObjSetHandleT H) {
+ PFC->Handle = H;
+ }
+
+ void finalize() override {
+ assert(PFC && "mapSectionAddress called on finalized LinkedObjectSet");
+
+ RuntimeDyld RTDyld(*MemMgr, *PFC->Resolver);
+ RTDyld.setProcessAllSections(PFC->ProcessAllSections);
+ PFC->RTDyld = &RTDyld;
+
+ PFC->Finalizer(PFC->Handle, RTDyld, std::move(PFC->Objects),
+ [&]() {
+ updateSymbolTable(RTDyld);
+ Finalized = true;
+ });
+
+ // Release resources.
+ PFC = nullptr;
+ }
+
+ JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override {
+ return
+ [this, Name]() {
+ // The symbol may be materialized between the creation of this lambda
+ // and its execution, so we need to double check.
+ if (!Finalized)
+ finalize();
+ return getSymbol(Name, false).getAddress();
+ };
+ }
- void Finalize() override {
- State = Finalizing;
- RTDyld->finalizeWithMemoryManagerLocking();
- State = Finalized;
+ void mapSectionAddress(const void *LocalAddress,
+ TargetAddress TargetAddr) const override {
+ assert(PFC && "mapSectionAddress called on finalized LinkedObjectSet");
+ assert(PFC->RTDyld && "mapSectionAddress called on raw LinkedObjectSet");
+ PFC->RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
}
private:
+
+ void buildInitialSymbolTable(const ObjSetT &Objects) {
+ for (const auto &Obj : Objects)
+ for (auto &Symbol : getObject(*Obj).symbols()) {
+ if (Symbol.getFlags() & object::SymbolRef::SF_Undefined)
+ continue;
+ ErrorOr<StringRef> SymbolName = Symbol.getName();
+ // FIXME: Raise an error for bad symbols.
+ if (!SymbolName)
+ continue;
+ auto Flags = JITSymbol::flagsFromObjectSymbol(Symbol);
+ SymbolTable.insert(
+ std::make_pair(*SymbolName, RuntimeDyld::SymbolInfo(0, Flags)));
+ }
+ }
+
+ void updateSymbolTable(const RuntimeDyld &RTDyld) {
+ for (auto &SymEntry : SymbolTable)
+ SymEntry.second = RTDyld.getSymbol(SymEntry.first());
+ }
+
+ // Contains the information needed prior to finalization: the object files,
+ // memory manager, resolver, and flags needed for RuntimeDyld.
+ struct PreFinalizeContents {
+ PreFinalizeContents(ObjSetT Objects, SymbolResolverPtrT Resolver,
+ FinalizerFtor Finalizer, bool ProcessAllSections)
+ : Objects(std::move(Objects)), Resolver(std::move(Resolver)),
+ Finalizer(std::move(Finalizer)),
+ ProcessAllSections(ProcessAllSections) {}
+
+ ObjSetT Objects;
+ SymbolResolverPtrT Resolver;
+ FinalizerFtor Finalizer;
+ bool ProcessAllSections;
+ ObjSetHandleT Handle;
+ RuntimeDyld *RTDyld;
+ };
+
MemoryManagerPtrT MemMgr;
- SymbolResolverPtrT Resolver;
+ std::unique_ptr<PreFinalizeContents> PFC;
};
- template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
- std::unique_ptr<LinkedObjectSet>
- createLinkedObjectSet(MemoryManagerPtrT MemMgr, SymbolResolverPtrT Resolver,
+ template <typename ObjSetT, typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT, typename FinalizerFtor>
+ std::unique_ptr<
+ ConcreteLinkedObjectSet<ObjSetT, MemoryManagerPtrT,
+ SymbolResolverPtrT, FinalizerFtor>>
+ createLinkedObjectSet(ObjSetT Objects, MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver,
+ FinalizerFtor Finalizer,
bool ProcessAllSections) {
- typedef ConcreteLinkedObjectSet<MemoryManagerPtrT, SymbolResolverPtrT> LOS;
- return llvm::make_unique<LOS>(std::move(MemMgr), std::move(Resolver),
+ typedef ConcreteLinkedObjectSet<ObjSetT, MemoryManagerPtrT,
+ SymbolResolverPtrT, FinalizerFtor> LOS;
+ return llvm::make_unique<LOS>(std::move(Objects), std::move(MemMgr),
+ std::move(Resolver), std::move(Finalizer),
ProcessAllSections);
}
@@ -133,9 +217,6 @@ public:
typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
LoadedObjInfoList;
- /// @brief Functor for receiving finalization notifications.
- typedef std::function<void(ObjSetHandleT)> NotifyFinalizedFtor;
-
/// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
/// and NotifyFinalized functors.
ObjectLinkingLayer(
@@ -169,22 +250,39 @@ public:
template <typename ObjSetT,
typename MemoryManagerPtrT,
typename SymbolResolverPtrT>
- ObjSetHandleT addObjectSet(const ObjSetT &Objects,
+ ObjSetHandleT addObjectSet(ObjSetT Objects,
MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver) {
- ObjSetHandleT Handle =
- LinkedObjSetList.insert(
- LinkedObjSetList.end(),
- createLinkedObjectSet(std::move(MemMgr), std::move(Resolver),
- ProcessAllSections));
- LinkedObjectSet &LOS = **Handle;
- LoadedObjInfoList LoadedObjInfos;
-
- for (auto &Obj : Objects)
- LoadedObjInfos.push_back(LOS.addObject(*Obj));
-
- NotifyLoaded(Handle, Objects, LoadedObjInfos);
+ auto Finalizer = [&](ObjSetHandleT H, RuntimeDyld &RTDyld,
+ const ObjSetT &Objs,
+ std::function<void()> LOSHandleLoad) {
+ LoadedObjInfoList LoadedObjInfos;
+
+ for (auto &Obj : Objs)
+ LoadedObjInfos.push_back(RTDyld.loadObject(getObject(*Obj)));
+
+ LOSHandleLoad();
+
+ NotifyLoaded(H, Objs, LoadedObjInfos);
+
+ RTDyld.finalizeWithMemoryManagerLocking();
+
+ if (NotifyFinalized)
+ NotifyFinalized(H);
+ };
+
+ auto LOS =
+ createLinkedObjectSet(std::move(Objects), std::move(MemMgr),
+ std::move(Resolver), std::move(Finalizer),
+ ProcessAllSections);
+ // LOS is an owning-ptr. Keep a non-owning one so that we can set the handle
+ // below.
+ auto *LOSPtr = LOS.get();
+
+ ObjSetHandleT Handle = LinkedObjSetList.insert(LinkedObjSetList.end(),
+ std::move(LOS));
+ LOSPtr->setHandle(Handle);
return Handle;
}
@@ -224,33 +322,7 @@ public:
/// given object set.
JITSymbol findSymbolIn(ObjSetHandleT H, StringRef Name,
bool ExportedSymbolsOnly) {
- if (auto Sym = (*H)->getSymbol(Name)) {
- if (Sym.isExported() || !ExportedSymbolsOnly) {
- auto Addr = Sym.getAddress();
- auto Flags = Sym.getFlags();
- if (!(*H)->NeedsFinalization()) {
- // If this instance has already been finalized then we can just return
- // the address.
- return JITSymbol(Addr, Flags);
- } else {
- // If this instance needs finalization return a functor that will do
- // it. The functor still needs to double-check whether finalization is
- // required, in case someone else finalizes this set before the
- // functor is called.
- auto GetAddress =
- [this, Addr, H]() {
- if ((*H)->NeedsFinalization()) {
- (*H)->Finalize();
- if (NotifyFinalized)
- NotifyFinalized(H);
- }
- return Addr;
- };
- return JITSymbol(std::move(GetAddress), Flags);
- }
- }
- }
- return nullptr;
+ return (*H)->getSymbol(Name, ExportedSymbolsOnly);
}
/// @brief Map section addresses for the objects associated with the handle H.
@@ -263,12 +335,21 @@ public:
/// given handle.
/// @param H Handle for object set to emit/finalize.
void emitAndFinalize(ObjSetHandleT H) {
- (*H)->Finalize();
- if (NotifyFinalized)
- NotifyFinalized(H);
+ (*H)->finalize();
}
private:
+
+ static const object::ObjectFile& getObject(const object::ObjectFile &Obj) {
+ return Obj;
+ }
+
+ template <typename ObjT>
+ static const object::ObjectFile&
+ getObject(const object::OwningBinary<ObjT> &Obj) {
+ return *Obj.getBinary();
+ }
+
LinkedObjectSetListT LinkedObjSetList;
NotifyLoadedFtor NotifyLoaded;
NotifyFinalizedFtor NotifyFinalized;
Modified: llvm/trunk/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h?rev=258185&r1=258184&r2=258185&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h (original)
+++ llvm/trunk/lib/ExecutionEngine/Orc/OrcMCJITReplacement.h Tue Jan 19 15:06:38 2016
@@ -178,11 +178,10 @@ public:
}
void addObjectFile(object::OwningBinary<object::ObjectFile> O) override {
- std::unique_ptr<object::ObjectFile> Obj;
- std::unique_ptr<MemoryBuffer> Buf;
- std::tie(Obj, Buf) = O.takeBinary();
- std::vector<std::unique_ptr<object::ObjectFile>> Objs;
- Objs.push_back(std::move(Obj));
+ std::vector<std::unique_ptr<object::OwningBinary<object::ObjectFile>>> Objs;
+ Objs.push_back(
+ llvm::make_unique<object::OwningBinary<object::ObjectFile>>(
+ std::move(O)));
ObjectLayer.addObjectSet(std::move(Objs), &MemMgr, &Resolver);
}
@@ -284,12 +283,12 @@ private:
class NotifyObjectLoadedT {
public:
- typedef std::vector<std::unique_ptr<object::ObjectFile>> ObjListT;
typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
LoadedObjInfoListT;
NotifyObjectLoadedT(OrcMCJITReplacement &M) : M(M) {}
+ template <typename ObjListT>
void operator()(ObjectLinkingLayerBase::ObjSetHandleT H,
const ObjListT &Objects,
const LoadedObjInfoListT &Infos) const {
@@ -298,10 +297,21 @@ private:
assert(Objects.size() == Infos.size() &&
"Incorrect number of Infos for Objects.");
for (unsigned I = 0; I < Objects.size(); ++I)
- M.MemMgr.notifyObjectLoaded(&M, *Objects[I]);
+ M.MemMgr.notifyObjectLoaded(&M, getObject(*Objects[I]));
}
private:
+
+ static const object::ObjectFile& getObject(const object::ObjectFile &Obj) {
+ return Obj;
+ }
+
+ template <typename ObjT>
+ static const object::ObjectFile&
+ getObject(const object::OwningBinary<ObjT> &Obj) {
+ return *Obj.getBinary();
+ }
+
OrcMCJITReplacement &M;
};
Modified: llvm/trunk/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp?rev=258185&r1=258184&r2=258185&view=diff
==============================================================================
--- llvm/trunk/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp (original)
+++ llvm/trunk/unittests/ExecutionEngine/Orc/ObjectLinkingLayerTest.cpp Tue Jan 19 15:06:38 2016
@@ -12,6 +12,7 @@
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
+#include "llvm/ExecutionEngine/Orc/NullResolver.h"
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/LLVMContext.h"
@@ -29,6 +30,13 @@ class ObjectLinkingLayerExecutionTest :
class SectionMemoryManagerWrapper : public SectionMemoryManager {
public:
int FinalizationCount = 0;
+ int NeedsToReserveAllocationSpaceCount = 0;
+
+ bool needsToReserveAllocationSpace() override {
+ ++NeedsToReserveAllocationSpaceCount;
+ return SectionMemoryManager::needsToReserveAllocationSpace();
+ }
+
bool finalizeMemory(std::string *ErrMsg = 0) override {
++FinalizationCount;
return SectionMemoryManager::finalizeMemory(ErrMsg);
@@ -178,4 +186,68 @@ TEST_F(ObjectLinkingLayerExecutionTest,
<< "Extra call to finalize";
}
+TEST_F(ObjectLinkingLayerExecutionTest, NoPrematureAllocation) {
+
+ if (!TM)
+ return;
+
+ ObjectLinkingLayer<> ObjLayer;
+ SimpleCompiler Compile(*TM);
+
+ // Create a pair of unrelated modules:
+ //
+ // Module 1:
+ // int foo() { return 42; }
+ // Module 2:
+ // int bar() { return 7; }
+ //
+ // Both modules will share a memory manager. We want to verify that the
+ // second object is not loaded before the first one is finalized. To do this
+ // in a portable way, we abuse the
+ // RuntimeDyld::MemoryManager::needsToReserveAllocationSpace hook, which is
+ // called once per object before any sections are allocated.
+
+ ModuleBuilder MB1(getGlobalContext(), "", "dummy");
+ {
+ MB1.getModule()->setDataLayout(TM->createDataLayout());
+ Function *BarImpl = MB1.createFunctionDecl<int32_t(void)>("foo");
+ BasicBlock *BarEntry = BasicBlock::Create(getGlobalContext(), "entry",
+ BarImpl);
+ IRBuilder<> Builder(BarEntry);
+ IntegerType *Int32Ty = IntegerType::get(getGlobalContext(), 32);
+ Value *FourtyTwo = ConstantInt::getSigned(Int32Ty, 42);
+ Builder.CreateRet(FourtyTwo);
+ }
+
+ auto Obj1 = Compile(*MB1.getModule());
+ std::vector<object::ObjectFile*> Obj1Set;
+ Obj1Set.push_back(Obj1.getBinary());
+
+ ModuleBuilder MB2(getGlobalContext(), "", "dummy");
+ {
+ MB2.getModule()->setDataLayout(TM->createDataLayout());
+ Function *BarImpl = MB2.createFunctionDecl<int32_t(void)>("bar");
+ BasicBlock *BarEntry = BasicBlock::Create(getGlobalContext(), "entry",
+ BarImpl);
+ IRBuilder<> Builder(BarEntry);
+ IntegerType *Int32Ty = IntegerType::get(getGlobalContext(), 32);
+ Value *Seven = ConstantInt::getSigned(Int32Ty, 7);
+ Builder.CreateRet(Seven);
+ }
+ auto Obj2 = Compile(*MB2.getModule());
+ std::vector<object::ObjectFile*> Obj2Set;
+ Obj2Set.push_back(Obj2.getBinary());
+
+ SectionMemoryManagerWrapper SMMW;
+ NullResolver NR;
+ auto H = ObjLayer.addObjectSet(std::move(Obj1Set), &SMMW, &NR);
+ ObjLayer.addObjectSet(std::move(Obj2Set), &SMMW, &NR);
+ ObjLayer.emitAndFinalize(H);
+
+ // Only one call to needsToReserveAllocationSpace should have been made.
+ EXPECT_EQ(SMMW.NeedsToReserveAllocationSpaceCount, 1)
+ << "More than one call to needsToReserveAllocationSpace "
+ "(multiple unrelated objects loaded prior to finalization)";
+}
+
}
More information about the llvm-commits
mailing list