mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-27 13:40:43 +00:00
[ORC] Errorize the ORC APIs.
This patch updates the ORC layers and utilities to return and propagate llvm::Errors where appropriate. This is necessary to allow ORC to safely handle error cases in cross-process and remote JITing. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@307350 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d0585d352f
commit
a81793582b
@ -75,8 +75,8 @@ public:
|
||||
|
||||
// Add the set to the JIT with the resolver we created above and a newly
|
||||
// created SectionMemoryManager.
|
||||
return CompileLayer.addModule(std::move(M),
|
||||
std::move(Resolver));
|
||||
return cantFail(CompileLayer.addModule(std::move(M),
|
||||
std::move(Resolver)));
|
||||
}
|
||||
|
||||
JITSymbol findSymbol(const std::string Name) {
|
||||
@ -87,7 +87,7 @@ public:
|
||||
}
|
||||
|
||||
void removeModule(ModuleHandle H) {
|
||||
CompileLayer.removeModule(H);
|
||||
cantFail(CompileLayer.removeModule(H));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1150,7 +1150,7 @@ static void HandleTopLevelExpression() {
|
||||
|
||||
// Get the symbol's address and cast it to the right type (takes no
|
||||
// arguments, returns a double) so we can call it as a native function.
|
||||
double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress();
|
||||
double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress());
|
||||
fprintf(stderr, "Evaluated to %f\n", FP());
|
||||
|
||||
// Delete the anonymous expression module from the JIT.
|
||||
|
@ -88,8 +88,8 @@ public:
|
||||
|
||||
// Add the set to the JIT with the resolver we created above and a newly
|
||||
// created SectionMemoryManager.
|
||||
return OptimizeLayer.addModule(std::move(M),
|
||||
std::move(Resolver));
|
||||
return cantFail(OptimizeLayer.addModule(std::move(M),
|
||||
std::move(Resolver)));
|
||||
}
|
||||
|
||||
JITSymbol findSymbol(const std::string Name) {
|
||||
@ -100,7 +100,7 @@ public:
|
||||
}
|
||||
|
||||
void removeModule(ModuleHandle H) {
|
||||
OptimizeLayer.removeModule(H);
|
||||
cantFail(OptimizeLayer.removeModule(H));
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -1150,7 +1150,7 @@ static void HandleTopLevelExpression() {
|
||||
|
||||
// Get the symbol's address and cast it to the right type (takes no
|
||||
// arguments, returns a double) so we can call it as a native function.
|
||||
double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress();
|
||||
double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress());
|
||||
fprintf(stderr, "Evaluated to %f\n", FP());
|
||||
|
||||
// Delete the anonymous expression module from the JIT.
|
||||
|
@ -101,8 +101,7 @@ public:
|
||||
|
||||
// Add the set to the JIT with the resolver we created above and a newly
|
||||
// created SectionMemoryManager.
|
||||
return CODLayer.addModule(std::move(M),
|
||||
std::move(Resolver));
|
||||
return cantFail(CODLayer.addModule(std::move(M), std::move(Resolver)));
|
||||
}
|
||||
|
||||
JITSymbol findSymbol(const std::string Name) {
|
||||
@ -113,7 +112,7 @@ public:
|
||||
}
|
||||
|
||||
void removeModule(ModuleHandle H) {
|
||||
CODLayer.removeModule(H);
|
||||
cantFail(CODLayer.removeModule(H));
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -1150,7 +1150,7 @@ static void HandleTopLevelExpression() {
|
||||
|
||||
// Get the symbol's address and cast it to the right type (takes no
|
||||
// arguments, returns a double) so we can call it as a native function.
|
||||
double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress();
|
||||
double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress());
|
||||
fprintf(stderr, "Evaluated to %f\n", FP());
|
||||
|
||||
// Delete the anonymous expression module from the JIT.
|
||||
|
@ -128,8 +128,8 @@ public:
|
||||
|
||||
// Add the set to the JIT with the resolver we created above and a newly
|
||||
// created SectionMemoryManager.
|
||||
return OptimizeLayer.addModule(std::move(M),
|
||||
std::move(Resolver));
|
||||
return cantFail(OptimizeLayer.addModule(std::move(M),
|
||||
std::move(Resolver)));
|
||||
}
|
||||
|
||||
Error addFunctionAST(std::unique_ptr<FunctionAST> FnAST) {
|
||||
@ -175,7 +175,7 @@ public:
|
||||
addModule(std::move(M));
|
||||
auto Sym = findSymbol(SharedFnAST->getName() + "$impl");
|
||||
assert(Sym && "Couldn't find compiled function?");
|
||||
JITTargetAddress SymAddr = Sym.getAddress();
|
||||
JITTargetAddress SymAddr = cantFail(Sym.getAddress());
|
||||
if (auto Err =
|
||||
IndirectStubsMgr->updatePointer(mangle(SharedFnAST->getName()),
|
||||
SymAddr)) {
|
||||
@ -195,7 +195,7 @@ public:
|
||||
}
|
||||
|
||||
void removeModule(ModuleHandle H) {
|
||||
OptimizeLayer.removeModule(H);
|
||||
cantFail(OptimizeLayer.removeModule(H));
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -1153,7 +1153,7 @@ static void HandleTopLevelExpression() {
|
||||
|
||||
// Get the symbol's address and cast it to the right type (takes no
|
||||
// arguments, returns a double) so we can call it as a native function.
|
||||
double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress();
|
||||
double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress());
|
||||
fprintf(stderr, "Evaluated to %f\n", FP());
|
||||
|
||||
// Delete the anonymous expression module from the JIT.
|
||||
|
@ -157,8 +157,8 @@ public:
|
||||
|
||||
// Add the set to the JIT with the resolver we created above and a newly
|
||||
// created SectionMemoryManager.
|
||||
return OptimizeLayer.addModule(std::move(M),
|
||||
std::move(Resolver));
|
||||
return cantFail(OptimizeLayer.addModule(std::move(M),
|
||||
std::move(Resolver)));
|
||||
}
|
||||
|
||||
Error addFunctionAST(std::unique_ptr<FunctionAST> FnAST) {
|
||||
@ -204,7 +204,7 @@ public:
|
||||
addModule(std::move(M));
|
||||
auto Sym = findSymbol(SharedFnAST->getName() + "$impl");
|
||||
assert(Sym && "Couldn't find compiled function?");
|
||||
JITTargetAddress SymAddr = Sym.getAddress();
|
||||
JITTargetAddress SymAddr = cantFail(Sym.getAddress());
|
||||
if (auto Err =
|
||||
IndirectStubsMgr->updatePointer(mangle(SharedFnAST->getName()),
|
||||
SymAddr)) {
|
||||
@ -228,7 +228,7 @@ public:
|
||||
}
|
||||
|
||||
void removeModule(ModuleHandle H) {
|
||||
OptimizeLayer.removeModule(H);
|
||||
cantFail(OptimizeLayer.removeModule(H));
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -1177,7 +1177,7 @@ static void HandleTopLevelExpression() {
|
||||
|
||||
// Get the symbol's address and cast it to the right type (takes no
|
||||
// arguments, returns a double) so we can call it as a native function.
|
||||
ExitOnErr(TheJIT->executeRemoteExpr(ExprSymbol.getAddress()));
|
||||
ExitOnErr(TheJIT->executeRemoteExpr(cantFail(ExprSymbol.getAddress())));
|
||||
|
||||
// Delete the anonymous expression module from the JIT.
|
||||
TheJIT->removeModule(H);
|
||||
|
@ -611,7 +611,7 @@ static void HandleTopLevelExpression() {
|
||||
|
||||
// Get the symbol's address and cast it to the right type (takes no
|
||||
// arguments, returns a double) so we can call it as a native function.
|
||||
double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress();
|
||||
double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress());
|
||||
fprintf(stderr, "Evaluated to %f\n", FP());
|
||||
|
||||
// Delete the anonymous expression module from the JIT.
|
||||
|
@ -885,7 +885,7 @@ static void HandleTopLevelExpression() {
|
||||
|
||||
// Get the symbol's address and cast it to the right type (takes no
|
||||
// arguments, returns a double) so we can call it as a native function.
|
||||
double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress();
|
||||
double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress());
|
||||
fprintf(stderr, "Evaluated to %f\n", FP());
|
||||
|
||||
// Delete the anonymous expression module from the JIT.
|
||||
|
@ -1004,7 +1004,7 @@ static void HandleTopLevelExpression() {
|
||||
|
||||
// Get the symbol's address and cast it to the right type (takes no
|
||||
// arguments, returns a double) so we can call it as a native function.
|
||||
double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress();
|
||||
double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress());
|
||||
fprintf(stderr, "Evaluated to %f\n", FP());
|
||||
|
||||
// Delete the anonymous expression module from the JIT.
|
||||
|
@ -1173,7 +1173,7 @@ static void HandleTopLevelExpression() {
|
||||
|
||||
// Get the symbol's address and cast it to the right type (takes no
|
||||
// arguments, returns a double) so we can call it as a native function.
|
||||
double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress();
|
||||
double (*FP)() = (double (*)())(intptr_t)cantFail(ExprSymbol.getAddress());
|
||||
fprintf(stderr, "Evaluated to %f\n", FP());
|
||||
|
||||
// Delete the anonymous expression module from the JIT.
|
||||
|
@ -63,8 +63,8 @@ public:
|
||||
return JITSymbol(nullptr);
|
||||
},
|
||||
[](const std::string &S) { return nullptr; });
|
||||
auto H = CompileLayer.addModule(std::move(M),
|
||||
std::move(Resolver));
|
||||
auto H = cantFail(CompileLayer.addModule(std::move(M),
|
||||
std::move(Resolver)));
|
||||
|
||||
ModuleHandles.push_back(H);
|
||||
return H;
|
||||
@ -72,7 +72,7 @@ public:
|
||||
|
||||
void removeModule(ModuleHandleT H) {
|
||||
ModuleHandles.erase(find(ModuleHandles, H));
|
||||
CompileLayer.removeModule(H);
|
||||
cantFail(CompileLayer.removeModule(H));
|
||||
}
|
||||
|
||||
JITSymbol findSymbol(const std::string Name) {
|
||||
|
@ -113,8 +113,9 @@ void LLVMOrcDisposeMangledSymbol(char *MangledSymbol);
|
||||
/**
|
||||
* Create a lazy compile callback.
|
||||
*/
|
||||
LLVMOrcTargetAddress
|
||||
LLVMOrcErrorCode
|
||||
LLVMOrcCreateLazyCompileCallback(LLVMOrcJITStackRef JITStack,
|
||||
LLVMOrcTargetAddress *RetAddr,
|
||||
LLVMOrcLazyCompileCallbackFn Callback,
|
||||
void *CallbackCtx);
|
||||
|
||||
@ -135,8 +136,9 @@ LLVMOrcErrorCode LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack,
|
||||
/**
|
||||
* Add module to be eagerly compiled.
|
||||
*/
|
||||
LLVMOrcModuleHandle
|
||||
LLVMOrcErrorCode
|
||||
LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack,
|
||||
LLVMOrcModuleHandle *RetHandle,
|
||||
LLVMSharedModuleRef Mod,
|
||||
LLVMOrcSymbolResolverFn SymbolResolver,
|
||||
void *SymbolResolverCtx);
|
||||
@ -144,8 +146,9 @@ LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack,
|
||||
/**
|
||||
* Add module to be lazily compiled one function at a time.
|
||||
*/
|
||||
LLVMOrcModuleHandle
|
||||
LLVMOrcErrorCode
|
||||
LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack,
|
||||
LLVMOrcModuleHandle *RetHandle,
|
||||
LLVMSharedModuleRef Mod,
|
||||
LLVMOrcSymbolResolverFn SymbolResolver,
|
||||
void *SymbolResolverCtx);
|
||||
@ -153,10 +156,11 @@ LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack,
|
||||
/**
|
||||
* Add an object file.
|
||||
*/
|
||||
LLVMOrcModuleHandle LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack,
|
||||
LLVMSharedObjectBufferRef Obj,
|
||||
LLVMOrcSymbolResolverFn SymbolResolver,
|
||||
void *SymbolResolverCtx);
|
||||
LLVMOrcErrorCode LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack,
|
||||
LLVMOrcModuleHandle *RetHandle,
|
||||
LLVMSharedObjectBufferRef Obj,
|
||||
LLVMOrcSymbolResolverFn SymbolResolver,
|
||||
void *SymbolResolverCtx);
|
||||
|
||||
/**
|
||||
* Remove a module set from the JIT.
|
||||
@ -164,18 +168,20 @@ LLVMOrcModuleHandle LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack,
|
||||
* This works for all modules that can be added via OrcAdd*, including object
|
||||
* files.
|
||||
*/
|
||||
void LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack, LLVMOrcModuleHandle H);
|
||||
LLVMOrcErrorCode LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack,
|
||||
LLVMOrcModuleHandle H);
|
||||
|
||||
/**
|
||||
* Get symbol address from JIT instance.
|
||||
*/
|
||||
LLVMOrcTargetAddress LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack,
|
||||
const char *SymbolName);
|
||||
LLVMOrcErrorCode LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack,
|
||||
LLVMOrcTargetAddress *RetAddr,
|
||||
const char *SymbolName);
|
||||
|
||||
/**
|
||||
* Dispose of an ORC JIT stack.
|
||||
*/
|
||||
void LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack);
|
||||
LLVMOrcErrorCode LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "llvm/Support/Error.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class GlobalValue;
|
||||
@ -41,10 +43,11 @@ public:
|
||||
|
||||
enum FlagNames : UnderlyingType {
|
||||
None = 0,
|
||||
Weak = 1U << 0,
|
||||
Common = 1U << 1,
|
||||
Absolute = 1U << 2,
|
||||
Exported = 1U << 3
|
||||
HasError = 1U << 0,
|
||||
Weak = 1U << 1,
|
||||
Common = 1U << 2,
|
||||
Absolute = 1U << 3,
|
||||
Exported = 1U << 4
|
||||
};
|
||||
|
||||
/// @brief Default-construct a JITSymbolFlags instance.
|
||||
@ -53,6 +56,11 @@ public:
|
||||
/// @brief Construct a JITSymbolFlags instance from the given flags.
|
||||
JITSymbolFlags(FlagNames Flags) : Flags(Flags) {}
|
||||
|
||||
/// @brief Return true if there was an error retrieving this symbol.
|
||||
bool hasError() const {
|
||||
return (Flags & HasError) == HasError;
|
||||
}
|
||||
|
||||
/// @brief Returns true is the Weak flag is set.
|
||||
bool isWeak() const {
|
||||
return (Flags & Weak) == Weak;
|
||||
@ -113,11 +121,17 @@ private:
|
||||
/// @brief Represents a symbol in the JIT.
|
||||
class JITSymbol {
|
||||
public:
|
||||
using GetAddressFtor = std::function<JITTargetAddress()>;
|
||||
using GetAddressFtor = std::function<Expected<JITTargetAddress>()>;
|
||||
|
||||
/// @brief Create a 'null' symbol that represents failure to find a symbol
|
||||
/// definition.
|
||||
JITSymbol(std::nullptr_t) {}
|
||||
/// @brief Create a 'null' symbol, used to represent a "symbol not found"
|
||||
/// result from a successful (non-erroneous) lookup.
|
||||
JITSymbol(std::nullptr_t)
|
||||
: CachedAddr(0) {}
|
||||
|
||||
/// @brief Create a JITSymbol representing an error in the symbol lookup
|
||||
/// process (e.g. a network failure during a remote lookup).
|
||||
JITSymbol(Error Err)
|
||||
: Err(std::move(Err)), Flags(JITSymbolFlags::HasError) {}
|
||||
|
||||
/// @brief Create a symbol for a definition with a known address.
|
||||
JITSymbol(JITTargetAddress Addr, JITSymbolFlags Flags)
|
||||
@ -139,16 +153,57 @@ public:
|
||||
JITSymbol(GetAddressFtor GetAddress, JITSymbolFlags Flags)
|
||||
: GetAddress(std::move(GetAddress)), Flags(Flags) {}
|
||||
|
||||
JITSymbol(const JITSymbol&) = delete;
|
||||
JITSymbol& operator=(const JITSymbol&) = delete;
|
||||
|
||||
JITSymbol(JITSymbol &&Other)
|
||||
: GetAddress(std::move(Other.GetAddress)), Flags(std::move(Other.Flags)) {
|
||||
if (Flags.hasError())
|
||||
Err = std::move(Other.Err);
|
||||
else
|
||||
CachedAddr = std::move(Other.CachedAddr);
|
||||
}
|
||||
|
||||
JITSymbol& operator=(JITSymbol &&Other) {
|
||||
GetAddress = std::move(Other.GetAddress);
|
||||
Flags = std::move(Other.Flags);
|
||||
if (Flags.hasError())
|
||||
Err = std::move(Other.Err);
|
||||
else
|
||||
CachedAddr = std::move(Other.CachedAddr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~JITSymbol() {
|
||||
if (Flags.hasError())
|
||||
Err.~Error();
|
||||
else
|
||||
CachedAddr.~JITTargetAddress();
|
||||
}
|
||||
|
||||
/// @brief Returns true if the symbol exists, false otherwise.
|
||||
explicit operator bool() const { return CachedAddr || GetAddress; }
|
||||
explicit operator bool() const {
|
||||
return !Flags.hasError() && (CachedAddr || GetAddress);
|
||||
}
|
||||
|
||||
/// @brief Move the error field value out of this JITSymbol.
|
||||
Error takeError() {
|
||||
if (Flags.hasError())
|
||||
return std::move(Err);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
/// @brief Get the address of the symbol in the target address space. Returns
|
||||
/// '0' if the symbol does not exist.
|
||||
JITTargetAddress getAddress() {
|
||||
Expected<JITTargetAddress> getAddress() {
|
||||
assert(!Flags.hasError() && "getAddress called on error value");
|
||||
if (GetAddress) {
|
||||
CachedAddr = GetAddress();
|
||||
assert(CachedAddr && "Symbol could not be materialized.");
|
||||
GetAddress = nullptr;
|
||||
if (auto CachedAddrOrErr = GetAddress()) {
|
||||
GetAddress = nullptr;
|
||||
CachedAddr = *CachedAddrOrErr;
|
||||
assert(CachedAddr && "Symbol could not be materialized.");
|
||||
} else
|
||||
return CachedAddrOrErr.takeError();
|
||||
}
|
||||
return CachedAddr;
|
||||
}
|
||||
@ -157,7 +212,10 @@ public:
|
||||
|
||||
private:
|
||||
GetAddressFtor GetAddress;
|
||||
JITTargetAddress CachedAddr = 0;
|
||||
union {
|
||||
JITTargetAddress CachedAddr;
|
||||
Error Err;
|
||||
};
|
||||
JITSymbolFlags Flags;
|
||||
};
|
||||
|
||||
|
@ -176,12 +176,16 @@ private:
|
||||
for (auto BLH : BaseLayerHandles)
|
||||
if (auto Sym = BaseLayer.findSymbolIn(BLH, Name, ExportedSymbolsOnly))
|
||||
return Sym;
|
||||
else if (auto Err = Sym.takeError())
|
||||
return std::move(Err);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void removeModulesFromBaseLayer(BaseLayerT &BaseLayer) {
|
||||
Error removeModulesFromBaseLayer(BaseLayerT &BaseLayer) {
|
||||
for (auto &BLH : BaseLayerHandles)
|
||||
BaseLayer.removeModule(BLH);
|
||||
if (auto Err = BaseLayer.removeModule(BLH))
|
||||
return Err;
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
std::shared_ptr<JITSymbolResolver> ExternalSymbolResolver;
|
||||
@ -216,13 +220,15 @@ public:
|
||||
CloneStubsIntoPartitions(CloneStubsIntoPartitions) {}
|
||||
|
||||
~CompileOnDemandLayer() {
|
||||
// FIXME: Report error on log.
|
||||
while (!LogicalDylibs.empty())
|
||||
removeModule(LogicalDylibs.begin());
|
||||
consumeError(removeModule(LogicalDylibs.begin()));
|
||||
}
|
||||
|
||||
/// @brief Add a module to the compile-on-demand layer.
|
||||
ModuleHandleT addModule(std::shared_ptr<Module> M,
|
||||
std::shared_ptr<JITSymbolResolver> Resolver) {
|
||||
Expected<ModuleHandleT>
|
||||
addModule(std::shared_ptr<Module> M,
|
||||
std::shared_ptr<JITSymbolResolver> Resolver) {
|
||||
|
||||
LogicalDylibs.push_back(LogicalDylib());
|
||||
auto &LD = LogicalDylibs.back();
|
||||
@ -230,23 +236,25 @@ public:
|
||||
LD.StubsMgr = CreateIndirectStubsManager();
|
||||
|
||||
// Process each of the modules in this module set.
|
||||
addLogicalModule(LD, std::move(M));
|
||||
if (auto Err = addLogicalModule(LD, std::move(M)))
|
||||
return std::move(Err);
|
||||
|
||||
return std::prev(LogicalDylibs.end());
|
||||
}
|
||||
|
||||
/// @brief Add extra modules to an existing logical module.
|
||||
void addExtraModule(ModuleHandleT H, std::shared_ptr<Module> M) {
|
||||
addLogicalModule(*H, std::move(M));
|
||||
Error addExtraModule(ModuleHandleT H, std::shared_ptr<Module> M) {
|
||||
return addLogicalModule(*H, std::move(M));
|
||||
}
|
||||
|
||||
/// @brief Remove the module represented by the given handle.
|
||||
///
|
||||
/// This will remove all modules in the layers below that were derived from
|
||||
/// the module represented by H.
|
||||
void removeModule(ModuleHandleT H) {
|
||||
H->removeModulesFromBaseLayer(BaseLayer);
|
||||
Error removeModule(ModuleHandleT H) {
|
||||
auto Err = H->removeModulesFromBaseLayer(BaseLayer);
|
||||
LogicalDylibs.erase(H);
|
||||
return Err;
|
||||
}
|
||||
|
||||
/// @brief Search for the given named symbol.
|
||||
@ -260,6 +268,8 @@ public:
|
||||
return Sym;
|
||||
if (auto Sym = findSymbolIn(LDI, Name, ExportedSymbolsOnly))
|
||||
return Sym;
|
||||
else if (auto Err = Sym.takeError())
|
||||
return std::move(Err);
|
||||
}
|
||||
return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
|
||||
}
|
||||
@ -298,7 +308,7 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
void addLogicalModule(LogicalDylib &LD, std::shared_ptr<Module> SrcMPtr) {
|
||||
Error addLogicalModule(LogicalDylib &LD, std::shared_ptr<Module> SrcMPtr) {
|
||||
|
||||
// Rename all static functions / globals to $static.X :
|
||||
// This will unique the names across all modules in the logical dylib,
|
||||
@ -324,9 +334,12 @@ private:
|
||||
|
||||
// Skip weak functions for which we already have definitions.
|
||||
auto MangledName = mangle(F.getName(), DL);
|
||||
if (F.hasWeakLinkage() || F.hasLinkOnceLinkage())
|
||||
if (F.hasWeakLinkage() || F.hasLinkOnceLinkage()) {
|
||||
if (auto Sym = LD.findSymbol(BaseLayer, MangledName, false))
|
||||
continue;
|
||||
else if (auto Err = Sym.takeError())
|
||||
return std::move(Err);
|
||||
}
|
||||
|
||||
// Record all functions defined by this module.
|
||||
if (CloneStubsIntoPartitions)
|
||||
@ -339,9 +352,15 @@ private:
|
||||
StubInits[MangledName] =
|
||||
std::make_pair(CCInfo.getAddress(),
|
||||
JITSymbolFlags::fromGlobalValue(F));
|
||||
CCInfo.setCompileAction([this, &LD, LMId, &F]() {
|
||||
return this->extractAndCompile(LD, LMId, F);
|
||||
});
|
||||
CCInfo.setCompileAction([this, &LD, LMId, &F]() -> JITTargetAddress {
|
||||
if (auto FnImplAddrOrErr = this->extractAndCompile(LD, LMId, F))
|
||||
return *FnImplAddrOrErr;
|
||||
else {
|
||||
// FIXME: Report error, return to 'abort' or something similar.
|
||||
consumeError(FnImplAddrOrErr.takeError());
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
auto EC = LD.StubsMgr->createStubs(StubInits);
|
||||
@ -356,7 +375,7 @@ private:
|
||||
// empty globals module.
|
||||
if (SrcM.global_empty() && SrcM.alias_empty() &&
|
||||
!SrcM.getModuleFlagsMetadata())
|
||||
return;
|
||||
return Error::success();
|
||||
|
||||
// Create the GlobalValues module.
|
||||
auto GVsM = llvm::make_unique<Module>((SrcM.getName() + ".globals").str(),
|
||||
@ -382,8 +401,9 @@ private:
|
||||
|
||||
// Initializers may refer to functions declared (but not defined) in this
|
||||
// module. Build a materializer to clone decls on demand.
|
||||
Error MaterializerErrors = Error::success();
|
||||
auto Materializer = createLambdaMaterializer(
|
||||
[&LD, &GVsM](Value *V) -> Value* {
|
||||
[&LD, &GVsM, &MaterializerErrors](Value *V) -> Value* {
|
||||
if (auto *F = dyn_cast<Function>(V)) {
|
||||
// Decls in the original module just get cloned.
|
||||
if (F->isDeclaration())
|
||||
@ -394,13 +414,24 @@ private:
|
||||
// instead.
|
||||
const DataLayout &DL = GVsM->getDataLayout();
|
||||
std::string FName = mangle(F->getName(), DL);
|
||||
auto StubSym = LD.StubsMgr->findStub(FName, false);
|
||||
unsigned PtrBitWidth = DL.getPointerTypeSizeInBits(F->getType());
|
||||
ConstantInt *StubAddr =
|
||||
ConstantInt::get(GVsM->getContext(),
|
||||
APInt(PtrBitWidth, StubSym.getAddress()));
|
||||
JITTargetAddress StubAddr = 0;
|
||||
|
||||
// Get the address for the stub. If we encounter an error while
|
||||
// doing so, stash it in the MaterializerErrors variable and use a
|
||||
// null address as a placeholder.
|
||||
if (auto StubSym = LD.StubsMgr->findStub(FName, false)) {
|
||||
if (auto StubAddrOrErr = StubSym.getAddress())
|
||||
StubAddr = *StubAddrOrErr;
|
||||
else
|
||||
MaterializerErrors = joinErrors(std::move(MaterializerErrors),
|
||||
StubAddrOrErr.takeError());
|
||||
}
|
||||
|
||||
ConstantInt *StubAddrCI =
|
||||
ConstantInt::get(GVsM->getContext(), APInt(PtrBitWidth, StubAddr));
|
||||
Constant *Init = ConstantExpr::getCast(Instruction::IntToPtr,
|
||||
StubAddr, F->getType());
|
||||
StubAddrCI, F->getType());
|
||||
return GlobalAlias::create(F->getFunctionType(),
|
||||
F->getType()->getAddressSpace(),
|
||||
F->getLinkage(), F->getName(),
|
||||
@ -424,21 +455,31 @@ private:
|
||||
NewA->setAliasee(cast<Constant>(Init));
|
||||
}
|
||||
|
||||
if (MaterializerErrors)
|
||||
return MaterializerErrors;
|
||||
|
||||
// Build a resolver for the globals module and add it to the base layer.
|
||||
auto GVsResolver = createLambdaResolver(
|
||||
[this, &LD](const std::string &Name) {
|
||||
[this, &LD](const std::string &Name) -> JITSymbol {
|
||||
if (auto Sym = LD.StubsMgr->findStub(Name, false))
|
||||
return Sym;
|
||||
if (auto Sym = LD.findSymbol(BaseLayer, Name, false))
|
||||
return Sym;
|
||||
else if (auto Err = Sym.takeError())
|
||||
return std::move(Err);
|
||||
return LD.ExternalSymbolResolver->findSymbolInLogicalDylib(Name);
|
||||
},
|
||||
[&LD](const std::string &Name) {
|
||||
return LD.ExternalSymbolResolver->findSymbol(Name);
|
||||
});
|
||||
|
||||
auto GVsH = BaseLayer.addModule(std::move(GVsM), std::move(GVsResolver));
|
||||
LD.BaseLayerHandles.push_back(GVsH);
|
||||
if (auto GVsHOrErr =
|
||||
BaseLayer.addModule(std::move(GVsM), std::move(GVsResolver)))
|
||||
LD.BaseLayerHandles.push_back(*GVsHOrErr);
|
||||
else
|
||||
return GVsHOrErr.takeError();
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
static std::string mangle(StringRef Name, const DataLayout &DL) {
|
||||
@ -450,7 +491,7 @@ private:
|
||||
return MangledName;
|
||||
}
|
||||
|
||||
JITTargetAddress
|
||||
Expected<JITTargetAddress>
|
||||
extractAndCompile(LogicalDylib &LD,
|
||||
typename LogicalDylib::SourceModuleHandle LMId,
|
||||
Function &F) {
|
||||
@ -463,34 +504,42 @@ private:
|
||||
// Grab the name of the function being called here.
|
||||
std::string CalledFnName = mangle(F.getName(), SrcM.getDataLayout());
|
||||
|
||||
auto Part = Partition(F);
|
||||
auto PartH = emitPartition(LD, LMId, Part);
|
||||
|
||||
JITTargetAddress CalledAddr = 0;
|
||||
for (auto *SubF : Part) {
|
||||
std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout());
|
||||
auto FnBodySym = BaseLayer.findSymbolIn(PartH, FnName, false);
|
||||
assert(FnBodySym && "Couldn't find function body.");
|
||||
auto Part = Partition(F);
|
||||
if (auto PartHOrErr = emitPartition(LD, LMId, Part)) {
|
||||
auto &PartH = *PartHOrErr;
|
||||
for (auto *SubF : Part) {
|
||||
std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout());
|
||||
if (auto FnBodySym = BaseLayer.findSymbolIn(PartH, FnName, false)) {
|
||||
if (auto FnBodyAddrOrErr = FnBodySym.getAddress()) {
|
||||
JITTargetAddress FnBodyAddr = *FnBodyAddrOrErr;
|
||||
|
||||
JITTargetAddress FnBodyAddr = FnBodySym.getAddress();
|
||||
// If this is the function we're calling record the address so we can
|
||||
// return it from this function.
|
||||
if (SubF == &F)
|
||||
CalledAddr = FnBodyAddr;
|
||||
|
||||
// If this is the function we're calling record the address so we can
|
||||
// return it from this function.
|
||||
if (SubF == &F)
|
||||
CalledAddr = FnBodyAddr;
|
||||
// Update the function body pointer for the stub.
|
||||
if (auto EC = LD.StubsMgr->updatePointer(FnName, FnBodyAddr))
|
||||
return 0;
|
||||
|
||||
// Update the function body pointer for the stub.
|
||||
if (auto EC = LD.StubsMgr->updatePointer(FnName, FnBodyAddr))
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
return FnBodyAddrOrErr.takeError();
|
||||
} else if (auto Err = FnBodySym.takeError())
|
||||
return std::move(Err);
|
||||
else
|
||||
llvm_unreachable("Function not emitted for partition");
|
||||
}
|
||||
|
||||
LD.BaseLayerHandles.push_back(PartH);
|
||||
LD.BaseLayerHandles.push_back(PartH);
|
||||
} else
|
||||
return PartHOrErr.takeError();
|
||||
|
||||
return CalledAddr;
|
||||
}
|
||||
|
||||
template <typename PartitionT>
|
||||
BaseLayerModuleHandleT
|
||||
Expected<BaseLayerModuleHandleT>
|
||||
emitPartition(LogicalDylib &LD,
|
||||
typename LogicalDylib::SourceModuleHandle LMId,
|
||||
const PartitionT &Part) {
|
||||
@ -554,9 +603,11 @@ private:
|
||||
|
||||
// Create memory manager and symbol resolver.
|
||||
auto Resolver = createLambdaResolver(
|
||||
[this, &LD](const std::string &Name) {
|
||||
[this, &LD](const std::string &Name) -> JITSymbol {
|
||||
if (auto Sym = LD.findSymbol(BaseLayer, Name, false))
|
||||
return Sym;
|
||||
else if (auto Err = Sym.takeError())
|
||||
return std::move(Err);
|
||||
return LD.ExternalSymbolResolver->findSymbolInLogicalDylib(Name);
|
||||
},
|
||||
[&LD](const std::string &Name) {
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include "llvm/ADT/StringMap.h"
|
||||
#include "llvm/ADT/iterator_range.h"
|
||||
#include "llvm/ExecutionEngine/JITSymbol.h"
|
||||
#include "llvm/ExecutionEngine/RuntimeDyld.h"
|
||||
#include "llvm/ExecutionEngine/Orc/OrcError.h"
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
@ -99,19 +101,24 @@ public:
|
||||
|
||||
/// @brief Run the recorded constructors/destructors through the given JIT
|
||||
/// layer.
|
||||
bool runViaLayer(JITLayerT &JITLayer) const {
|
||||
Error runViaLayer(JITLayerT &JITLayer) const {
|
||||
using CtorDtorTy = void (*)();
|
||||
|
||||
bool Error = false;
|
||||
for (const auto &CtorDtorName : CtorDtorNames)
|
||||
if (auto CtorDtorSym = JITLayer.findSymbolIn(H, CtorDtorName, false)) {
|
||||
CtorDtorTy CtorDtor =
|
||||
reinterpret_cast<CtorDtorTy>(
|
||||
static_cast<uintptr_t>(CtorDtorSym.getAddress()));
|
||||
CtorDtor();
|
||||
} else
|
||||
Error = true;
|
||||
return !Error;
|
||||
if (auto AddrOrErr = CtorDtorSym.getAddress()) {
|
||||
CtorDtorTy CtorDtor =
|
||||
reinterpret_cast<CtorDtorTy>(static_cast<uintptr_t>(*AddrOrErr));
|
||||
CtorDtor();
|
||||
} else
|
||||
return AddrOrErr.takeError();
|
||||
} else {
|
||||
if (auto Err = CtorDtorSym.takeError())
|
||||
return Err;
|
||||
else
|
||||
return make_error<JITSymbolNotFound>(CtorDtorName);
|
||||
}
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -50,15 +50,18 @@ public:
|
||||
/// along with the given memory manager and symbol resolver.
|
||||
///
|
||||
/// @return A handle for the added module.
|
||||
ModuleHandleT addModule(std::shared_ptr<Module> M,
|
||||
std::shared_ptr<JITSymbolResolver> Resolver) {
|
||||
Expected<ModuleHandleT>
|
||||
addModule(std::shared_ptr<Module> M,
|
||||
std::shared_ptr<JITSymbolResolver> Resolver) {
|
||||
using CompileResult = decltype(Compile(*M));
|
||||
auto Obj = std::make_shared<CompileResult>(Compile(*M));
|
||||
return BaseLayer.addObject(std::move(Obj), std::move(Resolver));
|
||||
}
|
||||
|
||||
/// @brief Remove the module associated with the handle H.
|
||||
void removeModule(ModuleHandleT H) { BaseLayer.removeObject(H); }
|
||||
Error removeModule(ModuleHandleT H) {
|
||||
return BaseLayer.removeObject(H);
|
||||
}
|
||||
|
||||
/// @brief Search for the given named symbol.
|
||||
/// @param Name The name of the symbol to search for.
|
||||
@ -84,8 +87,8 @@ public:
|
||||
/// @brief Immediately emit and finalize the module represented by the given
|
||||
/// handle.
|
||||
/// @param H Handle for module to emit/finalize.
|
||||
void emitAndFinalize(ModuleHandleT H) {
|
||||
BaseLayer.emitAndFinalize(H);
|
||||
Error emitAndFinalize(ModuleHandleT H) {
|
||||
return BaseLayer.emitAndFinalize(H);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -42,13 +42,14 @@ public:
|
||||
/// the layer below, along with the memory manager and symbol resolver.
|
||||
///
|
||||
/// @return A handle for the added modules.
|
||||
ModuleHandleT addModule(std::shared_ptr<Module> M,
|
||||
std::shared_ptr<JITSymbolResolver> Resolver) {
|
||||
Expected<ModuleHandleT>
|
||||
addModule(std::shared_ptr<Module> M,
|
||||
std::shared_ptr<JITSymbolResolver> Resolver) {
|
||||
return BaseLayer.addModule(Transform(std::move(M)), std::move(Resolver));
|
||||
}
|
||||
|
||||
/// @brief Remove the module associated with the handle H.
|
||||
void removeModule(ModuleHandleT H) { BaseLayer.removeModule(H); }
|
||||
Error removeModule(ModuleHandleT H) { return BaseLayer.removeModule(H); }
|
||||
|
||||
/// @brief Search for the given named symbol.
|
||||
/// @param Name The name of the symbol to search for.
|
||||
@ -74,8 +75,8 @@ public:
|
||||
/// @brief Immediately emit and finalize the module represented by the given
|
||||
/// handle.
|
||||
/// @param H Handle for module to emit/finalize.
|
||||
void emitAndFinalize(ModuleHandleT H) {
|
||||
BaseLayer.emitAndFinalize(H);
|
||||
Error emitAndFinalize(ModuleHandleT H) {
|
||||
return BaseLayer.emitAndFinalize(H);
|
||||
}
|
||||
|
||||
/// @brief Access the transform functor directly.
|
||||
|
@ -60,16 +60,24 @@ private:
|
||||
std::string PName = Name;
|
||||
JITSymbolFlags Flags = JITSymbolFlags::fromGlobalValue(*GV);
|
||||
auto GetAddress =
|
||||
[this, ExportedSymbolsOnly, PName, &B]() -> JITTargetAddress {
|
||||
[this, ExportedSymbolsOnly, PName, &B]() -> Expected<JITTargetAddress> {
|
||||
if (this->EmitState == Emitting)
|
||||
return 0;
|
||||
else if (this->EmitState == NotEmitted) {
|
||||
this->EmitState = Emitting;
|
||||
Handle = this->emitToBaseLayer(B);
|
||||
if (auto HandleOrErr = this->emitToBaseLayer(B))
|
||||
Handle = std::move(*HandleOrErr);
|
||||
else
|
||||
return HandleOrErr.takeError();
|
||||
this->EmitState = Emitted;
|
||||
}
|
||||
auto Sym = B.findSymbolIn(Handle, PName, ExportedSymbolsOnly);
|
||||
return Sym.getAddress();
|
||||
if (auto Sym = B.findSymbolIn(Handle, PName, ExportedSymbolsOnly))
|
||||
return Sym.getAddress();
|
||||
else if (auto Err = Sym.takeError())
|
||||
return std::move(Err);
|
||||
else
|
||||
llvm_unreachable("Successful symbol lookup should return "
|
||||
"definition address here");
|
||||
};
|
||||
return JITSymbol(std::move(GetAddress), Flags);
|
||||
} else
|
||||
@ -127,7 +135,7 @@ private:
|
||||
return buildMangledSymbols(Name, ExportedSymbolsOnly);
|
||||
}
|
||||
|
||||
BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) {
|
||||
Expected<BaseLayerHandleT> emitToBaseLayer(BaseLayerT &BaseLayer) {
|
||||
// We don't need the mangled names set any more: Once we've emitted this
|
||||
// to the base layer we'll just look for symbols there.
|
||||
MangledSymbols.reset();
|
||||
@ -204,8 +212,9 @@ public:
|
||||
LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
|
||||
|
||||
/// @brief Add the given module to the lazy emitting layer.
|
||||
ModuleHandleT addModule(std::shared_ptr<Module> M,
|
||||
std::shared_ptr<JITSymbolResolver> Resolver) {
|
||||
Expected<ModuleHandleT>
|
||||
addModule(std::shared_ptr<Module> M,
|
||||
std::shared_ptr<JITSymbolResolver> Resolver) {
|
||||
return ModuleList.insert(
|
||||
ModuleList.end(),
|
||||
llvm::make_unique<EmissionDeferredModule>(std::move(M),
|
||||
@ -216,7 +225,7 @@ public:
|
||||
///
|
||||
/// This method will free the memory associated with the given module, both
|
||||
/// in this layer, and the base layer.
|
||||
void removeModule(ModuleHandleT H) {
|
||||
Error removeModule(ModuleHandleT H) {
|
||||
(*H)->removeModuleFromBaseLayer(BaseLayer);
|
||||
ModuleList.erase(H);
|
||||
}
|
||||
@ -251,8 +260,8 @@ public:
|
||||
/// @brief Immediately emit and finalize the module represented by the given
|
||||
/// handle.
|
||||
/// @param H Handle for module to emit/finalize.
|
||||
void emitAndFinalize(ModuleHandleT H) {
|
||||
(*H)->emitAndFinalize(BaseLayer);
|
||||
Error emitAndFinalize(ModuleHandleT H) {
|
||||
return (*H)->emitAndFinalize(BaseLayer);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -44,13 +44,13 @@ public:
|
||||
///
|
||||
/// @return A handle for the added objects.
|
||||
template <typename ObjectPtr>
|
||||
ObjHandleT addObject(ObjectPtr Obj,
|
||||
std::shared_ptr<JITSymbolResolver> Resolver) {
|
||||
Expected<ObjHandleT> addObject(ObjectPtr Obj,
|
||||
std::shared_ptr<JITSymbolResolver> Resolver) {
|
||||
return BaseLayer.addObject(Transform(std::move(Obj)), std::move(Resolver));
|
||||
}
|
||||
|
||||
/// @brief Remove the object set associated with the handle H.
|
||||
void removeObject(ObjHandleT H) { BaseLayer.removeObject(H); }
|
||||
Error removeObject(ObjHandleT H) { return BaseLayer.removeObject(H); }
|
||||
|
||||
/// @brief Search for the given named symbol.
|
||||
/// @param Name The name of the symbol to search for.
|
||||
@ -76,7 +76,9 @@ public:
|
||||
/// @brief Immediately emit and finalize the object set represented by the
|
||||
/// given handle.
|
||||
/// @param H Handle for object set to emit/finalize.
|
||||
void emitAndFinalize(ObjHandleT H) { BaseLayer.emitAndFinalize(H); }
|
||||
Error emitAndFinalize(ObjHandleT H) {
|
||||
return BaseLayer.emitAndFinalize(H);
|
||||
}
|
||||
|
||||
/// @brief Map section addresses for the objects associated with the handle H.
|
||||
void mapSectionAddress(ObjHandleT H, const void *LocalAddress,
|
||||
|
@ -22,7 +22,8 @@ namespace orc {
|
||||
|
||||
enum class OrcErrorCode : int {
|
||||
// RPC Errors
|
||||
RemoteAllocatorDoesNotExist = 1,
|
||||
JITSymbolNotFound = 1,
|
||||
RemoteAllocatorDoesNotExist,
|
||||
RemoteAllocatorIdAlreadyInUse,
|
||||
RemoteMProtectAddrUnrecognized,
|
||||
RemoteIndirectStubsOwnerDoesNotExist,
|
||||
@ -37,6 +38,18 @@ enum class OrcErrorCode : int {
|
||||
|
||||
std::error_code orcError(OrcErrorCode ErrCode);
|
||||
|
||||
class JITSymbolNotFound : public ErrorInfo<JITSymbolNotFound> {
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
JITSymbolNotFound(std::string SymbolName);
|
||||
std::error_code convertToErrorCode() const override;
|
||||
void log(raw_ostream &OS) const override;
|
||||
const std::string &getSymbolName() const;
|
||||
private:
|
||||
std::string SymbolName;
|
||||
};
|
||||
|
||||
} // End namespace orc.
|
||||
} // End namespace llvm.
|
||||
|
||||
|
@ -258,8 +258,8 @@ public:
|
||||
///
|
||||
/// @return A handle that can be used to refer to the loaded objects (for
|
||||
/// symbol searching, finalization, freeing memory, etc.).
|
||||
ObjHandleT addObject(ObjectPtr Obj,
|
||||
std::shared_ptr<JITSymbolResolver> Resolver) {
|
||||
Expected<ObjHandleT> addObject(ObjectPtr Obj,
|
||||
std::shared_ptr<JITSymbolResolver> Resolver) {
|
||||
auto Finalizer = [&](ObjHandleT H, RuntimeDyld &RTDyld,
|
||||
const ObjectPtr &ObjToLoad,
|
||||
std::function<void()> LOSHandleLoad) {
|
||||
@ -299,9 +299,10 @@ public:
|
||||
/// indirectly) will result in undefined behavior. If dependence tracking is
|
||||
/// required to detect or resolve such issues it should be added at a higher
|
||||
/// layer.
|
||||
void removeObject(ObjHandleT H) {
|
||||
Error removeObject(ObjHandleT H) {
|
||||
// How do we invalidate the symbols in H?
|
||||
LinkedObjList.erase(H);
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
/// @brief Search for the given named symbol.
|
||||
@ -338,8 +339,9 @@ public:
|
||||
/// @brief Immediately emit and finalize the object set represented by the
|
||||
/// given handle.
|
||||
/// @param H Handle for object set to emit/finalize.
|
||||
void emitAndFinalize(ObjHandleT H) {
|
||||
Error emitAndFinalize(ObjHandleT H) {
|
||||
(*H)->finalize();
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -317,7 +317,13 @@ uint64_t MCJIT::getSymbolAddress(const std::string &Name,
|
||||
raw_string_ostream MangledNameStream(MangledName);
|
||||
Mangler::getNameWithPrefix(MangledNameStream, Name, getDataLayout());
|
||||
}
|
||||
return findSymbol(MangledName, CheckFunctionsOnly).getAddress();
|
||||
if (auto Sym = findSymbol(MangledName, CheckFunctionsOnly)) {
|
||||
if (auto AddrOrErr = Sym.getAddress())
|
||||
return *AddrOrErr;
|
||||
else
|
||||
report_fatal_error(AddrOrErr.takeError());
|
||||
} else
|
||||
report_fatal_error(Sym.takeError());
|
||||
}
|
||||
|
||||
JITSymbol MCJIT::findSymbol(const std::string &Name,
|
||||
@ -599,11 +605,12 @@ GenericValue MCJIT::runFunction(Function *F, ArrayRef<GenericValue> ArgValues) {
|
||||
|
||||
void *MCJIT::getPointerToNamedFunction(StringRef Name, bool AbortOnFailure) {
|
||||
if (!isSymbolSearchingDisabled()) {
|
||||
void *ptr =
|
||||
reinterpret_cast<void*>(
|
||||
static_cast<uintptr_t>(Resolver.findSymbol(Name).getAddress()));
|
||||
if (ptr)
|
||||
return ptr;
|
||||
if (auto Sym = Resolver.findSymbol(Name)) {
|
||||
if (auto AddrOrErr = Sym.getAddress())
|
||||
return reinterpret_cast<void*>(
|
||||
static_cast<uintptr_t>(*AddrOrErr));
|
||||
} else if (auto Err = Sym.takeError())
|
||||
report_fatal_error(std::move(Err));
|
||||
}
|
||||
|
||||
/// If a LazyFunctionCreator is installed, use it to get/create the function.
|
||||
|
@ -60,12 +60,13 @@ void LLVMOrcGetMangledSymbol(LLVMOrcJITStackRef JITStack, char **MangledName,
|
||||
|
||||
void LLVMOrcDisposeMangledSymbol(char *MangledName) { delete[] MangledName; }
|
||||
|
||||
LLVMOrcTargetAddress
|
||||
LLVMOrcErrorCode
|
||||
LLVMOrcCreateLazyCompileCallback(LLVMOrcJITStackRef JITStack,
|
||||
LLVMOrcTargetAddress *RetAddr,
|
||||
LLVMOrcLazyCompileCallbackFn Callback,
|
||||
void *CallbackCtx) {
|
||||
OrcCBindingsStack &J = *unwrap(JITStack);
|
||||
return J.createLazyCompileCallback(Callback, CallbackCtx);
|
||||
return J.createLazyCompileCallback(*RetAddr, Callback, CallbackCtx);
|
||||
}
|
||||
|
||||
LLVMOrcErrorCode LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack,
|
||||
@ -82,38 +83,44 @@ LLVMOrcErrorCode LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack,
|
||||
return J.setIndirectStubPointer(StubName, NewAddr);
|
||||
}
|
||||
|
||||
LLVMOrcModuleHandle
|
||||
LLVMOrcErrorCode
|
||||
LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack,
|
||||
LLVMOrcModuleHandle *RetHandle,
|
||||
LLVMSharedModuleRef Mod,
|
||||
LLVMOrcSymbolResolverFn SymbolResolver,
|
||||
void *SymbolResolverCtx) {
|
||||
OrcCBindingsStack &J = *unwrap(JITStack);
|
||||
std::shared_ptr<Module> *M(unwrap(Mod));
|
||||
return J.addIRModuleEager(*M, SymbolResolver, SymbolResolverCtx);
|
||||
return J.addIRModuleEager(*RetHandle, *M, SymbolResolver, SymbolResolverCtx);
|
||||
}
|
||||
|
||||
LLVMOrcModuleHandle
|
||||
LLVMOrcErrorCode
|
||||
LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack,
|
||||
LLVMOrcModuleHandle *RetHandle,
|
||||
LLVMSharedModuleRef Mod,
|
||||
LLVMOrcSymbolResolverFn SymbolResolver,
|
||||
void *SymbolResolverCtx) {
|
||||
OrcCBindingsStack &J = *unwrap(JITStack);
|
||||
std::shared_ptr<Module> *M(unwrap(Mod));
|
||||
return J.addIRModuleLazy(*M, SymbolResolver, SymbolResolverCtx);
|
||||
return J.addIRModuleLazy(*RetHandle, *M, SymbolResolver, SymbolResolverCtx);
|
||||
}
|
||||
|
||||
void LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack, LLVMOrcModuleHandle H) {
|
||||
LLVMOrcErrorCode LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack,
|
||||
LLVMOrcModuleHandle H) {
|
||||
OrcCBindingsStack &J = *unwrap(JITStack);
|
||||
J.removeModule(H);
|
||||
return J.removeModule(H);
|
||||
}
|
||||
|
||||
LLVMOrcTargetAddress LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack,
|
||||
const char *SymbolName) {
|
||||
LLVMOrcErrorCode LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack,
|
||||
LLVMOrcTargetAddress *RetAddr,
|
||||
const char *SymbolName) {
|
||||
OrcCBindingsStack &J = *unwrap(JITStack);
|
||||
auto Sym = J.findSymbol(SymbolName, true);
|
||||
return Sym.getAddress();
|
||||
return J.findSymbolAddress(*RetAddr, SymbolName, true);
|
||||
}
|
||||
|
||||
void LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack) {
|
||||
delete unwrap(JITStack);
|
||||
LLVMOrcErrorCode LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack) {
|
||||
auto *J = unwrap(JITStack);
|
||||
auto Err = J->shutdown();
|
||||
delete J;
|
||||
return Err;
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ private:
|
||||
|
||||
virtual JITSymbol findSymbolIn(const std::string &Name,
|
||||
bool ExportedSymbolsOnly) = 0;
|
||||
virtual void removeModule() = 0;
|
||||
virtual Error removeModule() = 0;
|
||||
};
|
||||
|
||||
template <typename LayerT> class GenericHandleImpl : public GenericHandle {
|
||||
@ -83,7 +83,7 @@ private:
|
||||
return Layer.findSymbolIn(Handle, Name, ExportedSymbolsOnly);
|
||||
}
|
||||
|
||||
void removeModule() override { return Layer.removeModule(Handle); }
|
||||
Error removeModule() override { return Layer.removeModule(Handle); }
|
||||
|
||||
private:
|
||||
LayerT &Layer;
|
||||
@ -116,12 +116,14 @@ public:
|
||||
CXXRuntimeOverrides(
|
||||
[this](const std::string &S) { return mangle(S); }) {}
|
||||
|
||||
~OrcCBindingsStack() {
|
||||
LLVMOrcErrorCode shutdown() {
|
||||
// Run any destructors registered with __cxa_atexit.
|
||||
CXXRuntimeOverrides.runDestructors();
|
||||
// Run any IR destructors.
|
||||
for (auto &DtorRunner : IRStaticDestructorRunners)
|
||||
DtorRunner.runViaLayer(*this);
|
||||
if (auto Err = DtorRunner.runViaLayer(*this))
|
||||
return mapError(std::move(Err));
|
||||
return LLVMOrcErrSuccess;
|
||||
}
|
||||
|
||||
std::string mangle(StringRef Name) {
|
||||
@ -138,14 +140,17 @@ public:
|
||||
return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
|
||||
}
|
||||
|
||||
JITTargetAddress
|
||||
createLazyCompileCallback(LLVMOrcLazyCompileCallbackFn Callback,
|
||||
|
||||
LLVMOrcErrorCode
|
||||
createLazyCompileCallback(JITTargetAddress &RetAddr,
|
||||
LLVMOrcLazyCompileCallbackFn Callback,
|
||||
void *CallbackCtx) {
|
||||
auto CCInfo = CCMgr->getCompileCallback();
|
||||
CCInfo.setCompileAction([=]() -> JITTargetAddress {
|
||||
return Callback(wrap(this), CallbackCtx);
|
||||
});
|
||||
return CCInfo.getAddress();
|
||||
RetAddr = CCInfo.getAddress();
|
||||
return LLVMOrcErrSuccess;
|
||||
}
|
||||
|
||||
LLVMOrcErrorCode createIndirectStub(StringRef StubName,
|
||||
@ -164,7 +169,7 @@ public:
|
||||
void *ExternalResolverCtx) {
|
||||
return orc::createLambdaResolver(
|
||||
[this, ExternalResolver, ExternalResolverCtx](const std::string &Name)
|
||||
-> JITSymbol {
|
||||
-> JITSymbol {
|
||||
// Search order:
|
||||
// 1. JIT'd symbols.
|
||||
// 2. Runtime overrides.
|
||||
@ -172,6 +177,9 @@ public:
|
||||
|
||||
if (auto Sym = CODLayer.findSymbol(Name, true))
|
||||
return Sym;
|
||||
else if (auto Err = Sym.takeError())
|
||||
return Sym.takeError();
|
||||
|
||||
if (auto Sym = CXXRuntimeOverrides.searchOverrides(Name))
|
||||
return Sym;
|
||||
|
||||
@ -182,16 +190,19 @@ public:
|
||||
|
||||
return JITSymbol(nullptr);
|
||||
},
|
||||
[](const std::string &Name) {
|
||||
[](const std::string &Name) -> JITSymbol {
|
||||
return JITSymbol(nullptr);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename LayerT>
|
||||
ModuleHandleT addIRModule(LayerT &Layer, std::shared_ptr<Module> M,
|
||||
std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
|
||||
LLVMOrcSymbolResolverFn ExternalResolver,
|
||||
void *ExternalResolverCtx) {
|
||||
LLVMOrcErrorCode
|
||||
addIRModule(ModuleHandleT &RetHandle, LayerT &Layer,
|
||||
std::shared_ptr<Module> M,
|
||||
std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
|
||||
LLVMOrcSymbolResolverFn ExternalResolver,
|
||||
void *ExternalResolverCtx) {
|
||||
|
||||
// Attach a data-layout if one isn't already present.
|
||||
if (M->getDataLayout().isDefault())
|
||||
M->setDataLayout(DL);
|
||||
@ -208,42 +219,52 @@ public:
|
||||
auto Resolver = createResolver(ExternalResolver, ExternalResolverCtx);
|
||||
|
||||
// Add the module to the JIT.
|
||||
auto LH = Layer.addModule(std::move(M), std::move(Resolver));
|
||||
ModuleHandleT H = createHandle(Layer, LH);
|
||||
ModuleHandleT H;
|
||||
if (auto LHOrErr = Layer.addModule(std::move(M), std::move(Resolver)))
|
||||
H = createHandle(Layer, *LHOrErr);
|
||||
else
|
||||
return mapError(LHOrErr.takeError());
|
||||
|
||||
// Run the static constructors, and save the static destructor runner for
|
||||
// execution when the JIT is torn down.
|
||||
orc::CtorDtorRunner<OrcCBindingsStack> CtorRunner(std::move(CtorNames), H);
|
||||
CtorRunner.runViaLayer(*this);
|
||||
if (auto Err = CtorRunner.runViaLayer(*this))
|
||||
return mapError(std::move(Err));
|
||||
|
||||
IRStaticDestructorRunners.emplace_back(std::move(DtorNames), H);
|
||||
|
||||
return H;
|
||||
RetHandle = H;
|
||||
return LLVMOrcErrSuccess;
|
||||
}
|
||||
|
||||
ModuleHandleT addIRModuleEager(std::shared_ptr<Module> M,
|
||||
LLVMOrcSymbolResolverFn ExternalResolver,
|
||||
void *ExternalResolverCtx) {
|
||||
return addIRModule(CompileLayer, std::move(M),
|
||||
LLVMOrcErrorCode addIRModuleEager(ModuleHandleT &RetHandle,
|
||||
std::shared_ptr<Module> M,
|
||||
LLVMOrcSymbolResolverFn ExternalResolver,
|
||||
void *ExternalResolverCtx) {
|
||||
return addIRModule(RetHandle, CompileLayer, std::move(M),
|
||||
llvm::make_unique<SectionMemoryManager>(),
|
||||
std::move(ExternalResolver), ExternalResolverCtx);
|
||||
}
|
||||
|
||||
ModuleHandleT addIRModuleLazy(std::shared_ptr<Module> M,
|
||||
LLVMOrcSymbolResolverFn ExternalResolver,
|
||||
void *ExternalResolverCtx) {
|
||||
return addIRModule(CODLayer, std::move(M),
|
||||
LLVMOrcErrorCode addIRModuleLazy(ModuleHandleT &RetHandle,
|
||||
std::shared_ptr<Module> M,
|
||||
LLVMOrcSymbolResolverFn ExternalResolver,
|
||||
void *ExternalResolverCtx) {
|
||||
return addIRModule(RetHandle, CODLayer, std::move(M),
|
||||
llvm::make_unique<SectionMemoryManager>(),
|
||||
std::move(ExternalResolver), ExternalResolverCtx);
|
||||
}
|
||||
|
||||
void removeModule(ModuleHandleT H) {
|
||||
GenericHandles[H]->removeModule();
|
||||
LLVMOrcErrorCode removeModule(ModuleHandleT H) {
|
||||
if (auto Err = GenericHandles[H]->removeModule())
|
||||
return mapError(std::move(Err));
|
||||
GenericHandles[H] = nullptr;
|
||||
FreeHandleIndexes.push_back(H);
|
||||
return LLVMOrcErrSuccess;
|
||||
}
|
||||
|
||||
JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
|
||||
JITSymbol findSymbol(const std::string &Name,
|
||||
bool ExportedSymbolsOnly) {
|
||||
if (auto Sym = IndirectStubsMgr->findStub(Name, ExportedSymbolsOnly))
|
||||
return Sym;
|
||||
return CODLayer.findSymbol(mangle(Name), ExportedSymbolsOnly);
|
||||
@ -254,6 +275,26 @@ public:
|
||||
return GenericHandles[H]->findSymbolIn(Name, ExportedSymbolsOnly);
|
||||
}
|
||||
|
||||
LLVMOrcErrorCode findSymbolAddress(JITTargetAddress &RetAddr,
|
||||
const std::string &Name,
|
||||
bool ExportedSymbolsOnly) {
|
||||
RetAddr = 0;
|
||||
if (auto Sym = findSymbol(Name, ExportedSymbolsOnly)) {
|
||||
// Successful lookup, non-null symbol:
|
||||
if (auto AddrOrErr = Sym.getAddress()) {
|
||||
RetAddr = *AddrOrErr;
|
||||
return LLVMOrcErrSuccess;
|
||||
} else
|
||||
return mapError(AddrOrErr.takeError());
|
||||
} else if (auto Err = Sym.takeError()) {
|
||||
// Lookup failure - report error.
|
||||
return mapError(std::move(Err));
|
||||
}
|
||||
// Otherwise we had a successful lookup but got a null result. We already
|
||||
// set RetAddr to '0' above, so just return success.
|
||||
return LLVMOrcErrSuccess;
|
||||
}
|
||||
|
||||
const std::string &getErrorMessage() const { return ErrMsg; }
|
||||
|
||||
private:
|
||||
|
@ -45,6 +45,8 @@ public:
|
||||
return "Could not negotiate RPC function";
|
||||
case OrcErrorCode::RPCResponseAbandoned:
|
||||
return "RPC response abandoned";
|
||||
case OrcErrorCode::JITSymbolNotFound:
|
||||
return "JIT symbol not found";
|
||||
case OrcErrorCode::UnexpectedRPCCall:
|
||||
return "Unexpected RPC call";
|
||||
case OrcErrorCode::UnexpectedRPCResponse:
|
||||
@ -63,10 +65,29 @@ static ManagedStatic<OrcErrorCategory> OrcErrCat;
|
||||
namespace llvm {
|
||||
namespace orc {
|
||||
|
||||
char JITSymbolNotFound::ID = 0;
|
||||
|
||||
std::error_code orcError(OrcErrorCode ErrCode) {
|
||||
typedef std::underlying_type<OrcErrorCode>::type UT;
|
||||
return std::error_code(static_cast<UT>(ErrCode), *OrcErrCat);
|
||||
}
|
||||
|
||||
JITSymbolNotFound::JITSymbolNotFound(std::string SymbolName)
|
||||
: SymbolName(std::move(SymbolName)) {}
|
||||
|
||||
std::error_code JITSymbolNotFound::convertToErrorCode() const {
|
||||
typedef std::underlying_type<OrcErrorCode>::type UT;
|
||||
return std::error_code(static_cast<UT>(OrcErrorCode::JITSymbolNotFound),
|
||||
*OrcErrCat);
|
||||
}
|
||||
|
||||
void JITSymbolNotFound::log(raw_ostream &OS) const {
|
||||
OS << "Could not find symbol '" << SymbolName << "'";
|
||||
}
|
||||
|
||||
const std::string &JITSymbolNotFound::getSymbolName() const {
|
||||
return SymbolName;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -202,20 +202,20 @@ public:
|
||||
delete Mod;
|
||||
};
|
||||
LocalModules.push_back(std::shared_ptr<Module>(MPtr, std::move(Deleter)));
|
||||
LazyEmitLayer.addModule(LocalModules.back(), Resolver);
|
||||
cantFail(LazyEmitLayer.addModule(LocalModules.back(), Resolver));
|
||||
}
|
||||
|
||||
void addObjectFile(std::unique_ptr<object::ObjectFile> O) override {
|
||||
auto Obj =
|
||||
std::make_shared<object::OwningBinary<object::ObjectFile>>(std::move(O),
|
||||
nullptr);
|
||||
ObjectLayer.addObject(std::move(Obj), Resolver);
|
||||
cantFail(ObjectLayer.addObject(std::move(Obj), Resolver));
|
||||
}
|
||||
|
||||
void addObjectFile(object::OwningBinary<object::ObjectFile> O) override {
|
||||
auto Obj =
|
||||
std::make_shared<object::OwningBinary<object::ObjectFile>>(std::move(O));
|
||||
ObjectLayer.addObject(std::move(Obj), Resolver);
|
||||
cantFail(ObjectLayer.addObject(std::move(Obj), Resolver));
|
||||
}
|
||||
|
||||
void addArchive(object::OwningBinary<object::Archive> A) override {
|
||||
@ -234,7 +234,7 @@ public:
|
||||
}
|
||||
|
||||
uint64_t getSymbolAddress(StringRef Name) {
|
||||
return findSymbol(Name).getAddress();
|
||||
return cantFail(findSymbol(Name).getAddress());
|
||||
}
|
||||
|
||||
JITSymbol findSymbol(StringRef Name) {
|
||||
@ -323,7 +323,7 @@ private:
|
||||
auto Obj =
|
||||
std::make_shared<object::OwningBinary<object::ObjectFile>>(
|
||||
std::move(ChildObj), nullptr);
|
||||
ObjectLayer.addObject(std::move(Obj), Resolver);
|
||||
cantFail(ObjectLayer.addObject(std::move(Obj), Resolver));
|
||||
if (auto Sym = ObjectLayer.findSymbol(Name, true))
|
||||
return Sym;
|
||||
}
|
||||
|
@ -128,7 +128,10 @@ void RuntimeDyldImpl::resolveRelocations() {
|
||||
);
|
||||
|
||||
// First, resolve relocations associated with external symbols.
|
||||
resolveExternalSymbols();
|
||||
if (auto Err = resolveExternalSymbols()) {
|
||||
HasError = true;
|
||||
ErrorStr = toString(std::move(Err));
|
||||
}
|
||||
|
||||
// Iterate over all outstanding relocations
|
||||
for (auto it = Relocations.begin(), e = Relocations.end(); it != e; ++it) {
|
||||
@ -243,9 +246,11 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
|
||||
continue;
|
||||
// Then check the symbol resolver to see if there's a definition
|
||||
// elsewhere in this logical dylib.
|
||||
if (auto Sym = Resolver.findSymbolInLogicalDylib(Name))
|
||||
if (auto Sym = Resolver.findSymbolInLogicalDylib(Name)) {
|
||||
if (Sym.getFlags().isStrongDefinition())
|
||||
continue;
|
||||
} else if (auto Err = Sym.takeError())
|
||||
return std::move(Err);
|
||||
// else
|
||||
JITSymFlags &= ~JITSymbolFlags::Weak;
|
||||
}
|
||||
@ -953,7 +958,7 @@ void RuntimeDyldImpl::resolveRelocationList(const RelocationList &Relocs,
|
||||
}
|
||||
}
|
||||
|
||||
void RuntimeDyldImpl::resolveExternalSymbols() {
|
||||
Error RuntimeDyldImpl::resolveExternalSymbols() {
|
||||
while (!ExternalSymbolRelocations.empty()) {
|
||||
StringMap<RelocationList>::iterator i = ExternalSymbolRelocations.begin();
|
||||
|
||||
@ -971,10 +976,24 @@ void RuntimeDyldImpl::resolveExternalSymbols() {
|
||||
// This is an external symbol, try to get its address from the symbol
|
||||
// resolver.
|
||||
// First search for the symbol in this logical dylib.
|
||||
Addr = Resolver.findSymbolInLogicalDylib(Name.data()).getAddress();
|
||||
if (auto Sym = Resolver.findSymbolInLogicalDylib(Name.data())) {
|
||||
if (auto AddrOrErr = Sym.getAddress())
|
||||
Addr = *AddrOrErr;
|
||||
else
|
||||
return AddrOrErr.takeError();
|
||||
} else if (auto Err = Sym.takeError())
|
||||
return Err;
|
||||
|
||||
// If that fails, try searching for an external symbol.
|
||||
if (!Addr)
|
||||
Addr = Resolver.findSymbol(Name.data()).getAddress();
|
||||
if (!Addr) {
|
||||
if (auto Sym = Resolver.findSymbol(Name.data())) {
|
||||
if (auto AddrOrErr = Sym.getAddress())
|
||||
Addr = *AddrOrErr;
|
||||
else
|
||||
return AddrOrErr.takeError();
|
||||
} else if (auto Err = Sym.takeError())
|
||||
return Err;
|
||||
}
|
||||
// The call to getSymbolAddress may have caused additional modules to
|
||||
// be loaded, which may have added new entries to the
|
||||
// ExternalSymbolRelocations map. Consquently, we need to update our
|
||||
@ -1009,6 +1028,8 @@ void RuntimeDyldImpl::resolveExternalSymbols() {
|
||||
|
||||
ExternalSymbolRelocations.erase(i);
|
||||
}
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -742,7 +742,7 @@ uint64_t RuntimeDyldCheckerImpl::getSymbolLocalAddr(StringRef Symbol) const {
|
||||
uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const {
|
||||
if (auto InternalSymbol = getRTDyld().getSymbol(Symbol))
|
||||
return InternalSymbol.getAddress();
|
||||
return getRTDyld().Resolver.findSymbol(Symbol).getAddress();
|
||||
return cantFail(getRTDyld().Resolver.findSymbol(Symbol).getAddress());
|
||||
}
|
||||
|
||||
uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr,
|
||||
|
@ -417,7 +417,7 @@ protected:
|
||||
StubMap &Stubs) = 0;
|
||||
|
||||
/// \brief Resolve relocations to external symbols.
|
||||
void resolveExternalSymbols();
|
||||
Error resolveExternalSymbols();
|
||||
|
||||
// \brief Compute an upper bound of the memory that is required to load all
|
||||
// sections
|
||||
|
@ -148,18 +148,19 @@ int llvm::runOrcLazyJIT(std::vector<std::unique_ptr<Module>> Ms,
|
||||
|
||||
// Add the module, look up main and run it.
|
||||
for (auto &M : Ms)
|
||||
J.addModule(std::shared_ptr<Module>(std::move(M)));
|
||||
auto MainSym = J.findSymbol("main");
|
||||
cantFail(J.addModule(std::shared_ptr<Module>(std::move(M))));
|
||||
|
||||
if (!MainSym) {
|
||||
if (auto MainSym = J.findSymbol("main")) {
|
||||
typedef int (*MainFnPtr)(int, const char*[]);
|
||||
std::vector<const char *> ArgV;
|
||||
for (auto &Arg : Args)
|
||||
ArgV.push_back(Arg.c_str());
|
||||
auto Main = fromTargetAddress<MainFnPtr>(cantFail(MainSym.getAddress()));
|
||||
return Main(ArgV.size(), (const char**)ArgV.data());
|
||||
} else if (auto Err = MainSym.takeError())
|
||||
logAllUnhandledErrors(std::move(Err), llvm::errs(), "");
|
||||
else
|
||||
errs() << "Could not find main function.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
using MainFnPtr = int (*)(int, const char*[]);
|
||||
std::vector<const char *> ArgV;
|
||||
for (auto &Arg : Args)
|
||||
ArgV.push_back(Arg.c_str());
|
||||
auto Main = fromTargetAddress<MainFnPtr>(MainSym.getAddress());
|
||||
return Main(ArgV.size(), (const char**)ArgV.data());
|
||||
return 1;
|
||||
}
|
||||
|
@ -75,10 +75,14 @@ public:
|
||||
CXXRuntimeOverrides.runDestructors();
|
||||
// Run any IR destructors.
|
||||
for (auto &DtorRunner : IRStaticDestructorRunners)
|
||||
DtorRunner.runViaLayer(CODLayer);
|
||||
if (auto Err = DtorRunner.runViaLayer(CODLayer)) {
|
||||
// FIXME: OrcLazyJIT should probably take a "shutdownError" callback to
|
||||
// report these errors on.
|
||||
report_fatal_error(std::move(Err));
|
||||
}
|
||||
}
|
||||
|
||||
void addModule(std::shared_ptr<Module> M) {
|
||||
Error addModule(std::shared_ptr<Module> M) {
|
||||
if (M->getDataLayout().isDefault())
|
||||
M->setDataLayout(DL);
|
||||
|
||||
@ -125,19 +129,27 @@ public:
|
||||
);
|
||||
|
||||
// Add the module to the JIT.
|
||||
ModulesHandle =
|
||||
CODLayer.addModule(std::move(M), std::move(Resolver));
|
||||
if (auto ModulesHandleOrErr =
|
||||
CODLayer.addModule(std::move(M), std::move(Resolver)))
|
||||
ModulesHandle = std::move(*ModulesHandleOrErr);
|
||||
else
|
||||
return ModulesHandleOrErr.takeError();
|
||||
|
||||
} else
|
||||
CODLayer.addExtraModule(ModulesHandle, std::move(M));
|
||||
if (auto Err = CODLayer.addExtraModule(ModulesHandle, std::move(M)))
|
||||
return Err;
|
||||
|
||||
// Run the static constructors, and save the static destructor runner for
|
||||
// execution when the JIT is torn down.
|
||||
orc::CtorDtorRunner<CODLayerT> CtorRunner(std::move(CtorNames),
|
||||
ModulesHandle);
|
||||
CtorRunner.runViaLayer(CODLayer);
|
||||
if (auto Err = CtorRunner.runViaLayer(CODLayer))
|
||||
return Err;
|
||||
|
||||
IRStaticDestructorRunners.emplace_back(std::move(DtorNames),
|
||||
ModulesHandle);
|
||||
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
JITSymbol findSymbol(const std::string &Name) {
|
||||
|
@ -50,13 +50,14 @@ public:
|
||||
|
||||
TEST(CompileOnDemandLayerTest, FindSymbol) {
|
||||
auto MockBaseLayer = createMockBaseLayer<int>(
|
||||
DoNothingAndReturn<int>(0), DoNothingAndReturn<void>(),
|
||||
DoNothingAndReturn<int>(0),
|
||||
[](int Handle) { return Error::success(); },
|
||||
[](const std::string &Name, bool) {
|
||||
if (Name == "foo")
|
||||
return JITSymbol(1, JITSymbolFlags::Exported);
|
||||
return JITSymbol(nullptr);
|
||||
},
|
||||
DoNothingAndReturn<JITSymbol>(nullptr));
|
||||
ReturnNullJITSymbol());
|
||||
|
||||
typedef decltype(MockBaseLayer) MockBaseLayerT;
|
||||
DummyCallbackManager CallbackMgr;
|
||||
|
@ -37,13 +37,15 @@ TEST(GlobalMappingLayerTest, Empty) {
|
||||
|
||||
// Test fall-through for symbol in base layer.
|
||||
auto BarSym = L.findSymbol("bar", true);
|
||||
EXPECT_EQ(BarSym.getAddress(), static_cast<JITTargetAddress>(0x4567))
|
||||
EXPECT_EQ(cantFail(BarSym.getAddress()),
|
||||
static_cast<JITTargetAddress>(0x4567))
|
||||
<< "Symbol lookup fall-through failed.";
|
||||
|
||||
// Test setup of a global mapping.
|
||||
L.setGlobalMapping("foo", 0x0123);
|
||||
auto FooSym2 = L.findSymbol("foo", true);
|
||||
EXPECT_EQ(FooSym2.getAddress(), static_cast<JITTargetAddress>(0x0123))
|
||||
EXPECT_EQ(cantFail(FooSym2.getAddress()),
|
||||
static_cast<JITTargetAddress>(0x0123))
|
||||
<< "Symbol mapping setup failed.";
|
||||
|
||||
// Test removal of a global mapping.
|
||||
|
@ -27,7 +27,7 @@ struct MockBaseLayer {
|
||||
TEST(LazyEmittingLayerTest, Empty) {
|
||||
MockBaseLayer M;
|
||||
llvm::orc::LazyEmittingLayer<MockBaseLayer> L(M);
|
||||
L.addModule(std::unique_ptr<llvm::Module>(), nullptr);
|
||||
cantFail(L.addModule(std::unique_ptr<llvm::Module>(), nullptr));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -50,8 +50,9 @@ public:
|
||||
MockBaseLayer() : MockSymbol(nullptr) { resetExpectations(); }
|
||||
|
||||
template <typename ObjPtrT>
|
||||
ObjHandleT addObject(ObjPtrT Obj,
|
||||
std::shared_ptr<llvm::JITSymbolResolver> Resolver) {
|
||||
llvm::Expected<ObjHandleT>
|
||||
addObject(ObjPtrT Obj,
|
||||
std::shared_ptr<llvm::JITSymbolResolver> Resolver) {
|
||||
EXPECT_EQ(MockResolver, Resolver) << "Resolver should pass through";
|
||||
EXPECT_EQ(MockObject + 1, *Obj) << "Transform should be applied";
|
||||
LastCalled = "addObject";
|
||||
@ -73,10 +74,12 @@ public:
|
||||
resetExpectations();
|
||||
}
|
||||
|
||||
void removeObject(ObjHandleT H) {
|
||||
llvm::Error removeObject(ObjHandleT H) {
|
||||
EXPECT_EQ(MockObjHandle, H);
|
||||
LastCalled = "removeObject";
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
void expectRemoveObject(ObjHandleT H) { MockObjHandle = H; }
|
||||
void verifyRemoveObject() {
|
||||
EXPECT_EQ("removeObject", LastCalled);
|
||||
@ -89,7 +92,7 @@ public:
|
||||
EXPECT_EQ(MockBool, ExportedSymbolsOnly) << "Flag should pass through";
|
||||
LastCalled = "findSymbol";
|
||||
MockSymbol = llvm::JITSymbol(122, llvm::JITSymbolFlags::None);
|
||||
return MockSymbol;
|
||||
return llvm::JITSymbol(122, llvm::JITSymbolFlags::None);
|
||||
}
|
||||
void expectFindSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
|
||||
MockName = Name;
|
||||
@ -97,7 +100,8 @@ public:
|
||||
}
|
||||
void verifyFindSymbol(llvm::JITSymbol Returned) {
|
||||
EXPECT_EQ("findSymbol", LastCalled);
|
||||
EXPECT_EQ(MockSymbol.getAddress(), Returned.getAddress())
|
||||
EXPECT_EQ(cantFail(MockSymbol.getAddress()),
|
||||
cantFail(Returned.getAddress()))
|
||||
<< "Return should pass through";
|
||||
resetExpectations();
|
||||
}
|
||||
@ -109,7 +113,7 @@ public:
|
||||
EXPECT_EQ(MockBool, ExportedSymbolsOnly) << "Flag should pass through";
|
||||
LastCalled = "findSymbolIn";
|
||||
MockSymbol = llvm::JITSymbol(122, llvm::JITSymbolFlags::None);
|
||||
return MockSymbol;
|
||||
return llvm::JITSymbol(122, llvm::JITSymbolFlags::None);
|
||||
}
|
||||
void expectFindSymbolIn(ObjHandleT H, const std::string &Name,
|
||||
bool ExportedSymbolsOnly) {
|
||||
@ -119,16 +123,20 @@ public:
|
||||
}
|
||||
void verifyFindSymbolIn(llvm::JITSymbol Returned) {
|
||||
EXPECT_EQ("findSymbolIn", LastCalled);
|
||||
EXPECT_EQ(MockSymbol.getAddress(), Returned.getAddress())
|
||||
EXPECT_EQ(cantFail(MockSymbol.getAddress()),
|
||||
cantFail(Returned.getAddress()))
|
||||
<< "Return should pass through";
|
||||
resetExpectations();
|
||||
}
|
||||
|
||||
void emitAndFinalize(ObjHandleT H) {
|
||||
llvm::Error emitAndFinalize(ObjHandleT H) {
|
||||
EXPECT_EQ(MockObjHandle, H) << "Handle should pass through";
|
||||
LastCalled = "emitAndFinalize";
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
void expectEmitAndFinalize(ObjHandleT H) { MockObjHandle = H; }
|
||||
|
||||
void verifyEmitAndFinalize() {
|
||||
EXPECT_EQ("emitAndFinalize", LastCalled);
|
||||
resetExpectations();
|
||||
@ -201,38 +209,38 @@ TEST(ObjectTransformLayerTest, Main) {
|
||||
auto Obj1 = std::make_shared<MockObjectFile>(211);
|
||||
auto SR = std::make_shared<NullResolver>();
|
||||
M.expectAddObject(Obj1, SR);
|
||||
auto H = T1.addObject(std::move(Obj1), SR);
|
||||
auto H = cantFail(T1.addObject(std::move(Obj1), SR));
|
||||
M.verifyAddObject(H);
|
||||
|
||||
// Test addObjectSet with T2 (mutating)
|
||||
auto Obj2 = std::make_shared<MockObjectFile>(222);
|
||||
M.expectAddObject(Obj2, SR);
|
||||
H = T2.addObject(Obj2, SR);
|
||||
H = cantFail(T2.addObject(Obj2, SR));
|
||||
M.verifyAddObject(H);
|
||||
EXPECT_EQ(223, *Obj2) << "Expected mutation";
|
||||
|
||||
// Test removeObjectSet
|
||||
M.expectRemoveObject(H);
|
||||
T1.removeObject(H);
|
||||
cantFail(T1.removeObject(H));
|
||||
M.verifyRemoveObject();
|
||||
|
||||
// Test findSymbol
|
||||
std::string Name = "foo";
|
||||
bool ExportedOnly = true;
|
||||
M.expectFindSymbol(Name, ExportedOnly);
|
||||
llvm::JITSymbol Symbol = T2.findSymbol(Name, ExportedOnly);
|
||||
M.verifyFindSymbol(Symbol);
|
||||
llvm::JITSymbol Sym1 = T2.findSymbol(Name, ExportedOnly);
|
||||
M.verifyFindSymbol(std::move(Sym1));
|
||||
|
||||
// Test findSymbolIn
|
||||
Name = "bar";
|
||||
ExportedOnly = false;
|
||||
M.expectFindSymbolIn(H, Name, ExportedOnly);
|
||||
Symbol = T1.findSymbolIn(H, Name, ExportedOnly);
|
||||
M.verifyFindSymbolIn(Symbol);
|
||||
llvm::JITSymbol Sym2 = T1.findSymbolIn(H, Name, ExportedOnly);
|
||||
M.verifyFindSymbolIn(std::move(Sym2));
|
||||
|
||||
// Test emitAndFinalize
|
||||
M.expectEmitAndFinalize(H);
|
||||
T2.emitAndFinalize(H);
|
||||
cantFail(T2.emitAndFinalize(H));
|
||||
M.verifyEmitAndFinalize();
|
||||
|
||||
// Test mapSectionAddress
|
||||
@ -305,15 +313,15 @@ TEST(ObjectTransformLayerTest, Main) {
|
||||
// Make sure that the calls from IRCompileLayer to ObjectTransformLayer
|
||||
// compile.
|
||||
auto Resolver = std::make_shared<NullResolver>();
|
||||
CompileLayer.addModule(std::shared_ptr<llvm::Module>(), Resolver);
|
||||
cantFail(CompileLayer.addModule(std::shared_ptr<llvm::Module>(), Resolver));
|
||||
|
||||
// Make sure that the calls from ObjectTransformLayer to ObjectLinkingLayer
|
||||
// compile.
|
||||
decltype(TransformLayer)::ObjHandleT H2;
|
||||
TransformLayer.emitAndFinalize(H2);
|
||||
cantFail(TransformLayer.emitAndFinalize(H2));
|
||||
TransformLayer.findSymbolIn(H2, Name, false);
|
||||
TransformLayer.findSymbol(Name, true);
|
||||
TransformLayer.mapSectionAddress(H2, nullptr, 0);
|
||||
TransformLayer.removeObject(H2);
|
||||
cantFail(TransformLayer.removeObject(H2));
|
||||
}
|
||||
}
|
||||
|
@ -66,10 +66,11 @@ protected:
|
||||
auto *ET = CCtx->APIExecTest;
|
||||
CCtx->M = ET->createTestModule(ET->TM->getTargetTriple());
|
||||
LLVMSharedModuleRef SM = LLVMOrcMakeSharedModule(wrap(CCtx->M.release()));
|
||||
CCtx->H = LLVMOrcAddEagerlyCompiledIR(JITStack, SM, myResolver, nullptr);
|
||||
LLVMOrcAddEagerlyCompiledIR(JITStack, &CCtx->H, SM, myResolver, nullptr);
|
||||
LLVMOrcDisposeSharedModuleRef(SM);
|
||||
CCtx->Compiled = true;
|
||||
LLVMOrcTargetAddress MainAddr = LLVMOrcGetSymbolAddress(JITStack, "main");
|
||||
LLVMOrcTargetAddress MainAddr;
|
||||
LLVMOrcGetSymbolAddress(JITStack, &MainAddr, "main");
|
||||
LLVMOrcSetIndirectStubPointer(JITStack, "foo", MainAddr);
|
||||
return MainAddr;
|
||||
}
|
||||
@ -89,10 +90,12 @@ TEST_F(OrcCAPIExecutionTest, TestEagerIRCompilation) {
|
||||
LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
|
||||
|
||||
LLVMSharedModuleRef SM = LLVMOrcMakeSharedModule(wrap(M.release()));
|
||||
LLVMOrcModuleHandle H =
|
||||
LLVMOrcAddEagerlyCompiledIR(JIT, SM, myResolver, nullptr);
|
||||
LLVMOrcModuleHandle H;
|
||||
LLVMOrcAddEagerlyCompiledIR(JIT, &H, SM, myResolver, nullptr);
|
||||
LLVMOrcDisposeSharedModuleRef(SM);
|
||||
MainFnTy MainFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "main");
|
||||
LLVMOrcTargetAddress MainAddr;
|
||||
LLVMOrcGetSymbolAddress(JIT, &MainAddr, "main");
|
||||
MainFnTy MainFn = (MainFnTy)MainAddr;
|
||||
int Result = MainFn();
|
||||
EXPECT_EQ(Result, 42)
|
||||
<< "Eagerly JIT'd code did not return expected result";
|
||||
@ -115,10 +118,12 @@ TEST_F(OrcCAPIExecutionTest, TestLazyIRCompilation) {
|
||||
LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
|
||||
|
||||
LLVMSharedModuleRef SM = LLVMOrcMakeSharedModule(wrap(M.release()));
|
||||
LLVMOrcModuleHandle H =
|
||||
LLVMOrcAddLazilyCompiledIR(JIT, SM, myResolver, nullptr);
|
||||
LLVMOrcModuleHandle H;
|
||||
LLVMOrcAddLazilyCompiledIR(JIT, &H, SM, myResolver, nullptr);
|
||||
LLVMOrcDisposeSharedModuleRef(SM);
|
||||
MainFnTy MainFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "main");
|
||||
LLVMOrcTargetAddress MainAddr;
|
||||
LLVMOrcGetSymbolAddress(JIT, &MainAddr, "main");
|
||||
MainFnTy MainFn = (MainFnTy)MainAddr;
|
||||
int Result = MainFn();
|
||||
EXPECT_EQ(Result, 42)
|
||||
<< "Lazily JIT'd code did not return expected result";
|
||||
@ -140,11 +145,12 @@ TEST_F(OrcCAPIExecutionTest, TestDirectCallbacksAPI) {
|
||||
|
||||
CompileContext C;
|
||||
C.APIExecTest = this;
|
||||
LLVMOrcCreateIndirectStub(JIT, "foo",
|
||||
LLVMOrcCreateLazyCompileCallback(JIT,
|
||||
myCompileCallback,
|
||||
&C));
|
||||
MainFnTy FooFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "foo");
|
||||
LLVMOrcTargetAddress CCAddr;
|
||||
LLVMOrcCreateLazyCompileCallback(JIT, &CCAddr, myCompileCallback, &C);
|
||||
LLVMOrcCreateIndirectStub(JIT, "foo", CCAddr);
|
||||
LLVMOrcTargetAddress MainAddr;
|
||||
LLVMOrcGetSymbolAddress(JIT, &MainAddr, "foo");
|
||||
MainFnTy FooFn = (MainFnTy)MainAddr;
|
||||
int Result = FooFn();
|
||||
EXPECT_TRUE(C.Compiled)
|
||||
<< "Function wasn't lazily compiled";
|
||||
|
@ -119,19 +119,21 @@ public:
|
||||
RemoveModuleFtor &&RemoveModule,
|
||||
FindSymbolFtor &&FindSymbol,
|
||||
FindSymbolInFtor &&FindSymbolIn)
|
||||
: AddModule(AddModule), RemoveModule(RemoveModule),
|
||||
FindSymbol(FindSymbol), FindSymbolIn(FindSymbolIn)
|
||||
: AddModule(std::move(AddModule)),
|
||||
RemoveModule(std::move(RemoveModule)),
|
||||
FindSymbol(std::move(FindSymbol)),
|
||||
FindSymbolIn(std::move(FindSymbolIn))
|
||||
{}
|
||||
|
||||
template <typename ModuleT, typename MemoryManagerPtrT,
|
||||
typename SymbolResolverPtrT>
|
||||
ModuleHandleT addModule(ModuleT Ms, MemoryManagerPtrT MemMgr,
|
||||
SymbolResolverPtrT Resolver) {
|
||||
Expected<ModuleHandleT> addModule(ModuleT Ms, MemoryManagerPtrT MemMgr,
|
||||
SymbolResolverPtrT Resolver) {
|
||||
return AddModule(std::move(Ms), std::move(MemMgr), std::move(Resolver));
|
||||
}
|
||||
|
||||
void removeModule(ModuleHandleT H) {
|
||||
RemoveModule(H);
|
||||
Error removeModule(ModuleHandleT H) {
|
||||
return RemoveModule(H);
|
||||
}
|
||||
|
||||
JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
|
||||
@ -169,15 +171,24 @@ createMockBaseLayer(AddModuleFtor &&AddModule,
|
||||
std::forward<FindSymbolInFtor>(FindSymbolIn));
|
||||
}
|
||||
|
||||
|
||||
class ReturnNullJITSymbol {
|
||||
public:
|
||||
template <typename... Args>
|
||||
JITSymbol operator()(Args...) const {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ReturnT>
|
||||
class DoNothingAndReturn {
|
||||
public:
|
||||
DoNothingAndReturn(ReturnT Val) : Val(Val) {}
|
||||
DoNothingAndReturn(ReturnT Ret) : Ret(std::move(Ret)) {}
|
||||
|
||||
template <typename... Args>
|
||||
ReturnT operator()(Args...) const { return Val; }
|
||||
void operator()(Args...) const { return Ret; }
|
||||
private:
|
||||
ReturnT Val;
|
||||
ReturnT Ret;
|
||||
};
|
||||
|
||||
template <>
|
||||
|
@ -103,21 +103,21 @@ TEST(RTDyldObjectLinkingLayerTest, TestSetProcessAllSections) {
|
||||
|
||||
{
|
||||
// Test with ProcessAllSections = false (the default).
|
||||
auto H = ObjLayer.addObject(Obj, Resolver);
|
||||
ObjLayer.emitAndFinalize(H);
|
||||
auto H = cantFail(ObjLayer.addObject(Obj, Resolver));
|
||||
cantFail(ObjLayer.emitAndFinalize(H));
|
||||
EXPECT_EQ(DebugSectionSeen, false)
|
||||
<< "Unexpected debug info section";
|
||||
ObjLayer.removeObject(H);
|
||||
cantFail(ObjLayer.removeObject(H));
|
||||
}
|
||||
|
||||
{
|
||||
// Test with ProcessAllSections = true.
|
||||
ObjLayer.setProcessAllSections(true);
|
||||
auto H = ObjLayer.addObject(Obj, Resolver);
|
||||
ObjLayer.emitAndFinalize(H);
|
||||
auto H = cantFail(ObjLayer.addObject(Obj, Resolver));
|
||||
cantFail(ObjLayer.emitAndFinalize(H));
|
||||
EXPECT_EQ(DebugSectionSeen, true)
|
||||
<< "Expected debug info section not seen";
|
||||
ObjLayer.removeObject(H);
|
||||
cantFail(ObjLayer.removeObject(H));
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,10 +181,10 @@ TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoDuplicateFinalization) {
|
||||
return JITSymbol(nullptr);
|
||||
});
|
||||
|
||||
ObjLayer.addObject(std::move(Obj1), Resolver);
|
||||
auto H = ObjLayer.addObject(std::move(Obj2), Resolver);
|
||||
ObjLayer.emitAndFinalize(H);
|
||||
ObjLayer.removeObject(H);
|
||||
cantFail(ObjLayer.addObject(std::move(Obj1), Resolver));
|
||||
auto H = cantFail(ObjLayer.addObject(std::move(Obj2), Resolver));
|
||||
cantFail(ObjLayer.emitAndFinalize(H));
|
||||
cantFail(ObjLayer.removeObject(H));
|
||||
|
||||
// Finalization of module 2 should trigger finalization of module 1.
|
||||
// Verify that finalize on SMMW is only called once.
|
||||
@ -244,10 +244,10 @@ TEST_F(RTDyldObjectLinkingLayerExecutionTest, NoPrematureAllocation) {
|
||||
Compile(*MB2.getModule()));
|
||||
|
||||
auto NR = std::make_shared<NullResolver>();
|
||||
auto H = ObjLayer.addObject(std::move(Obj1), NR);
|
||||
ObjLayer.addObject(std::move(Obj2), NR);
|
||||
ObjLayer.emitAndFinalize(H);
|
||||
ObjLayer.removeObject(H);
|
||||
auto H = cantFail(ObjLayer.addObject(std::move(Obj1), NR));
|
||||
cantFail(ObjLayer.addObject(std::move(Obj2), NR));
|
||||
cantFail(ObjLayer.emitAndFinalize(H));
|
||||
cantFail(ObjLayer.removeObject(H));
|
||||
|
||||
// Only one call to needsToReserveAllocationSpace should have been made.
|
||||
EXPECT_EQ(MM->NeedsToReserveAllocationSpaceCount, 1)
|
||||
|
Loading…
Reference in New Issue
Block a user