1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 04:02:41 +01:00

[ORC] Remove OrcV1 APIs.

This removes all legacy layers, legacy utilities, the old Orc C bindings,
OrcMCJITReplacement, and OrcMCJITReplacement regression tests.

ExecutionEngine and MCJIT are not affected by this change.
This commit is contained in:
Lang Hames 2020-09-07 21:21:28 -07:00
parent 159c8567b3
commit 2d8b3a7239
128 changed files with 26 additions and 8550 deletions

View File

@ -1,169 +0,0 @@
/*===----------- llvm-c/OrcBindings.h - Orc Lib C Iface ---------*- C++ -*-===*\
|* *|
|* Part of the LLVM Project, under the Apache License v2.0 with LLVM *|
|* Exceptions. *|
|* See https://llvm.org/LICENSE.txt for license information. *|
|* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception *|
|* *|
|*===----------------------------------------------------------------------===*|
|* *|
|* This header declares the C interface to libLLVMOrcJIT.a, which implements *|
|* JIT compilation of LLVM IR. *|
|* *|
|* Many exotic languages can interoperate with C code but have a harder time *|
|* with C++ due to name mangling. So in addition to C, this interface enables *|
|* tools written in such languages. *|
|* *|
|* Note: This interface is experimental. It is *NOT* stable, and may be *|
|* changed without warning. *|
|* *|
\*===----------------------------------------------------------------------===*/
#ifndef LLVM_C_ORCBINDINGS_H
#define LLVM_C_ORCBINDINGS_H
#include "llvm-c/Error.h"
#include "llvm-c/ExternC.h"
#include "llvm-c/Object.h"
#include "llvm-c/TargetMachine.h"
LLVM_C_EXTERN_C_BEGIN
typedef struct LLVMOrcOpaqueJITStack *LLVMOrcJITStackRef;
typedef uint64_t LLVMOrcModuleHandle;
typedef uint64_t LLVMOrcTargetAddress;
typedef uint64_t (*LLVMOrcSymbolResolverFn)(const char *Name, void *LookupCtx);
typedef uint64_t (*LLVMOrcLazyCompileCallbackFn)(LLVMOrcJITStackRef JITStack,
void *CallbackCtx);
/**
* Create an ORC JIT stack.
*
* The client owns the resulting stack, and must call OrcDisposeInstance(...)
* to destroy it and free its memory. The JIT stack will take ownership of the
* TargetMachine, which will be destroyed when the stack is destroyed. The
* client should not attempt to dispose of the Target Machine, or it will result
* in a double-free.
*/
LLVMOrcJITStackRef LLVMOrcCreateInstance(LLVMTargetMachineRef TM);
/**
* Get the error message for the most recent error (if any).
*
* This message is owned by the ORC JIT Stack and will be freed when the stack
* is disposed of by LLVMOrcDisposeInstance.
*/
const char *LLVMOrcGetErrorMsg(LLVMOrcJITStackRef JITStack);
/**
* Mangle the given symbol.
* Memory will be allocated for MangledSymbol to hold the result. The client
*/
void LLVMOrcGetMangledSymbol(LLVMOrcJITStackRef JITStack, char **MangledSymbol,
const char *Symbol);
/**
* Dispose of a mangled symbol.
*/
void LLVMOrcDisposeMangledSymbol(char *MangledSymbol);
/**
* Create a lazy compile callback.
*/
LLVMErrorRef LLVMOrcCreateLazyCompileCallback(
LLVMOrcJITStackRef JITStack, LLVMOrcTargetAddress *RetAddr,
LLVMOrcLazyCompileCallbackFn Callback, void *CallbackCtx);
/**
* Create a named indirect call stub.
*/
LLVMErrorRef LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack,
const char *StubName,
LLVMOrcTargetAddress InitAddr);
/**
* Set the pointer for the given indirect stub.
*/
LLVMErrorRef LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack,
const char *StubName,
LLVMOrcTargetAddress NewAddr);
/**
* Add module to be eagerly compiled.
*/
LLVMErrorRef LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle,
LLVMModuleRef Mod,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx);
/**
* Add module to be lazily compiled one function at a time.
*/
LLVMErrorRef LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle,
LLVMModuleRef Mod,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx);
/**
* Add an object file.
*
* This method takes ownership of the given memory buffer and attempts to add
* it to the JIT as an object file.
* Clients should *not* dispose of the 'Obj' argument: the JIT will manage it
* from this call onwards.
*/
LLVMErrorRef LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle,
LLVMMemoryBufferRef Obj,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx);
/**
* Remove a module set from the JIT.
*
* This works for all modules that can be added via OrcAdd*, including object
* files.
*/
LLVMErrorRef LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle H);
/**
* Get symbol address from JIT instance.
*/
LLVMErrorRef LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack,
LLVMOrcTargetAddress *RetAddr,
const char *SymbolName);
/**
* Get symbol address from JIT instance, searching only the specified
* handle.
*/
LLVMErrorRef LLVMOrcGetSymbolAddressIn(LLVMOrcJITStackRef JITStack,
LLVMOrcTargetAddress *RetAddr,
LLVMOrcModuleHandle H,
const char *SymbolName);
/**
* Dispose of an ORC JIT stack.
*/
LLVMErrorRef LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack);
/**
* Register a JIT Event Listener.
*
* A NULL listener is ignored.
*/
void LLVMOrcRegisterJITEventListener(LLVMOrcJITStackRef JITStack, LLVMJITEventListenerRef L);
/**
* Unegister a JIT Event Listener.
*
* A NULL listener is ignored.
*/
void LLVMOrcUnregisterJITEventListener(LLVMOrcJITStackRef JITStack, LLVMJITEventListenerRef L);
LLVM_C_EXTERN_C_END
#endif /* LLVM_C_ORCBINDINGS_H */

View File

@ -142,11 +142,6 @@ protected:
std::shared_ptr<LegacyJITSymbolResolver> SR,
std::unique_ptr<TargetMachine> TM);
static ExecutionEngine *(*OrcMCJITReplacementCtor)(
std::string *ErrorStr, std::shared_ptr<MCJITMemoryManager> MM,
std::shared_ptr<LegacyJITSymbolResolver> SR,
std::unique_ptr<TargetMachine> TM);
static ExecutionEngine *(*InterpCtor)(std::unique_ptr<Module> M,
std::string *ErrorStr);
@ -552,7 +547,6 @@ private:
std::string MCPU;
SmallVector<std::string, 4> MAttrs;
bool VerifyModules;
bool UseOrcMCJITReplacement;
bool EmulatedTLS = true;
public:
@ -648,17 +642,6 @@ public:
return *this;
}
// Use OrcMCJITReplacement instead of MCJIT. Off by default.
LLVM_ATTRIBUTE_DEPRECATED(
inline void setUseOrcMCJITReplacement(bool UseOrcMCJITReplacement),
"ORCv1 utilities (including OrcMCJITReplacement) are deprecated. Please "
"use ORCv2/LLJIT instead (see docs/ORCv2.rst)");
void setUseOrcMCJITReplacement(ORCv1DeprecationAcknowledgement,
bool UseOrcMCJITReplacement) {
this->UseOrcMCJITReplacement = UseOrcMCJITReplacement;
}
void setEmulatedTLS(bool EmulatedTLS) {
this->EmulatedTLS = EmulatedTLS;
}
@ -679,10 +662,6 @@ public:
ExecutionEngine *create(TargetMachine *TM);
};
void EngineBuilder::setUseOrcMCJITReplacement(bool UseOrcMCJITReplacement) {
this->UseOrcMCJITReplacement = UseOrcMCJITReplacement;
}
// Create wrappers for C Binding types (see CBindingWrapping.h).
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ExecutionEngine, LLVMExecutionEngineRef)

View File

@ -20,10 +20,8 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
#include "llvm/ExecutionEngine/Orc/Layer.h"
#include "llvm/ExecutionEngine/Orc/LazyReexports.h"
#include "llvm/ExecutionEngine/Orc/Legacy.h"
#include "llvm/ExecutionEngine/Orc/OrcError.h"
#include "llvm/ExecutionEngine/Orc/Speculation.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
@ -136,635 +134,6 @@ private:
ImplSymbolMap *AliaseeImpls = nullptr;
};
/// Compile-on-demand layer.
///
/// When a module is added to this layer a stub is created for each of its
/// function definitions. The stubs and other global values are immediately
/// added to the layer below. When a stub is called it triggers the extraction
/// of the function body from the original module. The extracted body is then
/// compiled and executed.
template <typename BaseLayerT,
typename CompileCallbackMgrT = JITCompileCallbackManager,
typename IndirectStubsMgrT = IndirectStubsManager>
class LegacyCompileOnDemandLayer {
private:
template <typename MaterializerFtor>
class LambdaMaterializer final : public ValueMaterializer {
public:
LambdaMaterializer(MaterializerFtor M) : M(std::move(M)) {}
Value *materialize(Value *V) final { return M(V); }
private:
MaterializerFtor M;
};
template <typename MaterializerFtor>
LambdaMaterializer<MaterializerFtor>
createLambdaMaterializer(MaterializerFtor M) {
return LambdaMaterializer<MaterializerFtor>(std::move(M));
}
// Provide type-erasure for the Modules and MemoryManagers.
template <typename ResourceT>
class ResourceOwner {
public:
ResourceOwner() = default;
ResourceOwner(const ResourceOwner &) = delete;
ResourceOwner &operator=(const ResourceOwner &) = delete;
virtual ~ResourceOwner() = default;
virtual ResourceT& getResource() const = 0;
};
template <typename ResourceT, typename ResourcePtrT>
class ResourceOwnerImpl : public ResourceOwner<ResourceT> {
public:
ResourceOwnerImpl(ResourcePtrT ResourcePtr)
: ResourcePtr(std::move(ResourcePtr)) {}
ResourceT& getResource() const override { return *ResourcePtr; }
private:
ResourcePtrT ResourcePtr;
};
template <typename ResourceT, typename ResourcePtrT>
std::unique_ptr<ResourceOwner<ResourceT>>
wrapOwnership(ResourcePtrT ResourcePtr) {
using RO = ResourceOwnerImpl<ResourceT, ResourcePtrT>;
return std::make_unique<RO>(std::move(ResourcePtr));
}
struct LogicalDylib {
struct SourceModuleEntry {
std::unique_ptr<Module> SourceMod;
std::set<Function*> StubsToClone;
};
using SourceModulesList = std::vector<SourceModuleEntry>;
using SourceModuleHandle = typename SourceModulesList::size_type;
LogicalDylib() = default;
LogicalDylib(VModuleKey K, std::shared_ptr<SymbolResolver> BackingResolver,
std::unique_ptr<IndirectStubsMgrT> StubsMgr)
: K(std::move(K)), BackingResolver(std::move(BackingResolver)),
StubsMgr(std::move(StubsMgr)) {}
SourceModuleHandle addSourceModule(std::unique_ptr<Module> M) {
SourceModuleHandle H = SourceModules.size();
SourceModules.push_back(SourceModuleEntry());
SourceModules.back().SourceMod = std::move(M);
return H;
}
Module& getSourceModule(SourceModuleHandle H) {
return *SourceModules[H].SourceMod;
}
std::set<Function*>& getStubsToClone(SourceModuleHandle H) {
return SourceModules[H].StubsToClone;
}
JITSymbol findSymbol(BaseLayerT &BaseLayer, const std::string &Name,
bool ExportedSymbolsOnly) {
if (auto Sym = StubsMgr->findStub(Name, ExportedSymbolsOnly))
return Sym;
for (auto BLK : BaseLayerVModuleKeys)
if (auto Sym = BaseLayer.findSymbolIn(BLK, Name, ExportedSymbolsOnly))
return Sym;
else if (auto Err = Sym.takeError())
return std::move(Err);
return nullptr;
}
Error removeModulesFromBaseLayer(BaseLayerT &BaseLayer) {
for (auto &BLK : BaseLayerVModuleKeys)
if (auto Err = BaseLayer.removeModule(BLK))
return Err;
return Error::success();
}
VModuleKey K;
std::shared_ptr<SymbolResolver> BackingResolver;
std::unique_ptr<IndirectStubsMgrT> StubsMgr;
SymbolLinkagePromoter PromoteSymbols;
SourceModulesList SourceModules;
std::vector<VModuleKey> BaseLayerVModuleKeys;
};
public:
/// Module partitioning functor.
using PartitioningFtor = std::function<std::set<Function*>(Function&)>;
/// Builder for IndirectStubsManagers.
using IndirectStubsManagerBuilderT =
std::function<std::unique_ptr<IndirectStubsMgrT>()>;
using SymbolResolverGetter =
std::function<std::shared_ptr<SymbolResolver>(VModuleKey K)>;
using SymbolResolverSetter =
std::function<void(VModuleKey K, std::shared_ptr<SymbolResolver> R)>;
/// Construct a compile-on-demand layer instance.
LLVM_ATTRIBUTE_DEPRECATED(
LegacyCompileOnDemandLayer(
ExecutionSession &ES, BaseLayerT &BaseLayer,
SymbolResolverGetter GetSymbolResolver,
SymbolResolverSetter SetSymbolResolver, PartitioningFtor Partition,
CompileCallbackMgrT &CallbackMgr,
IndirectStubsManagerBuilderT CreateIndirectStubsManager,
bool CloneStubsIntoPartitions = true),
"ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please "
"use "
"the ORCv2 LegacyCompileOnDemandLayer instead");
/// Legacy layer constructor with deprecation acknowledgement.
LegacyCompileOnDemandLayer(
ORCv1DeprecationAcknowledgement, ExecutionSession &ES,
BaseLayerT &BaseLayer, SymbolResolverGetter GetSymbolResolver,
SymbolResolverSetter SetSymbolResolver, PartitioningFtor Partition,
CompileCallbackMgrT &CallbackMgr,
IndirectStubsManagerBuilderT CreateIndirectStubsManager,
bool CloneStubsIntoPartitions = true)
: ES(ES), BaseLayer(BaseLayer),
GetSymbolResolver(std::move(GetSymbolResolver)),
SetSymbolResolver(std::move(SetSymbolResolver)),
Partition(std::move(Partition)), CompileCallbackMgr(CallbackMgr),
CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)),
CloneStubsIntoPartitions(CloneStubsIntoPartitions) {}
~LegacyCompileOnDemandLayer() {
// FIXME: Report error on log.
while (!LogicalDylibs.empty())
consumeError(removeModule(LogicalDylibs.begin()->first));
}
/// Add a module to the compile-on-demand layer.
Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
assert(!LogicalDylibs.count(K) && "VModuleKey K already in use");
auto I = LogicalDylibs.insert(
LogicalDylibs.end(),
std::make_pair(K, LogicalDylib(K, GetSymbolResolver(K),
CreateIndirectStubsManager())));
return addLogicalModule(I->second, std::move(M));
}
/// Add extra modules to an existing logical module.
Error addExtraModule(VModuleKey K, std::unique_ptr<Module> M) {
return addLogicalModule(LogicalDylibs[K], std::move(M));
}
/// Remove the module represented by the given key.
///
/// This will remove all modules in the layers below that were derived from
/// the module represented by K.
Error removeModule(VModuleKey K) {
auto I = LogicalDylibs.find(K);
assert(I != LogicalDylibs.end() && "VModuleKey K not valid here");
auto Err = I->second.removeModulesFromBaseLayer(BaseLayer);
LogicalDylibs.erase(I);
return Err;
}
/// Search for the given named symbol.
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it exists.
JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
for (auto &KV : LogicalDylibs) {
if (auto Sym = KV.second.StubsMgr->findStub(Name, ExportedSymbolsOnly))
return Sym;
if (auto Sym =
findSymbolIn(KV.first, std::string(Name), ExportedSymbolsOnly))
return Sym;
else if (auto Err = Sym.takeError())
return std::move(Err);
}
return BaseLayer.findSymbol(std::string(Name), ExportedSymbolsOnly);
}
/// Get the address of a symbol provided by this layer, or some layer
/// below this one.
JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
bool ExportedSymbolsOnly) {
assert(LogicalDylibs.count(K) && "VModuleKey K is not valid here");
return LogicalDylibs[K].findSymbol(BaseLayer, Name, ExportedSymbolsOnly);
}
/// Update the stub for the given function to point at FnBodyAddr.
/// This can be used to support re-optimization.
/// @return true if the function exists and the stub is updated, false
/// otherwise.
//
// FIXME: We should track and free associated resources (unused compile
// callbacks, uncompiled IR, and no-longer-needed/reachable function
// implementations).
Error updatePointer(std::string FuncName, JITTargetAddress FnBodyAddr) {
//Find out which logical dylib contains our symbol
auto LDI = LogicalDylibs.begin();
for (auto LDE = LogicalDylibs.end(); LDI != LDE; ++LDI) {
if (auto LMResources =
LDI->getLogicalModuleResourcesForSymbol(FuncName, false)) {
Module &SrcM = LMResources->SourceModule->getResource();
std::string CalledFnName = mangle(FuncName, SrcM.getDataLayout());
if (auto Err = LMResources->StubsMgr->updatePointer(CalledFnName,
FnBodyAddr))
return Err;
return Error::success();
}
}
return make_error<JITSymbolNotFound>(FuncName);
}
private:
Error addLogicalModule(LogicalDylib &LD, std::unique_ptr<Module> SrcMPtr) {
// Rename anonymous globals and promote linkage to ensure that everything
// will resolve properly after we partition SrcM.
LD.PromoteSymbols(*SrcMPtr);
// Create a logical module handle for SrcM within the logical dylib.
Module &SrcM = *SrcMPtr;
auto LMId = LD.addSourceModule(std::move(SrcMPtr));
// Create stub functions.
const DataLayout &DL = SrcM.getDataLayout();
typename IndirectStubsMgrT::StubInitsMap StubInits;
for (auto &F : SrcM) {
// Skip declarations.
if (F.isDeclaration())
continue;
// Skip weak functions for which we already have definitions.
auto MangledName = mangle(F.getName(), DL);
if (F.hasWeakLinkage() || F.hasLinkOnceLinkage()) {
if (auto Sym = LD.findSymbol(BaseLayer, MangledName, false))
continue;
else if (auto Err = Sym.takeError())
return Err;
}
// Record all functions defined by this module.
if (CloneStubsIntoPartitions)
LD.getStubsToClone(LMId).insert(&F);
// Create a callback, associate it with the stub for the function,
// and set the compile action to compile the partition containing the
// function.
auto CompileAction = [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;
}
};
if (auto CCAddr =
CompileCallbackMgr.getCompileCallback(std::move(CompileAction)))
StubInits[MangledName] =
std::make_pair(*CCAddr, JITSymbolFlags::fromGlobalValue(F));
else
return CCAddr.takeError();
}
if (auto Err = LD.StubsMgr->createStubs(StubInits))
return Err;
// If this module doesn't contain any globals, aliases, or module flags then
// we can bail out early and avoid the overhead of creating and managing an
// empty globals module.
if (SrcM.global_empty() && SrcM.alias_empty() &&
!SrcM.getModuleFlagsMetadata())
return Error::success();
// Create the GlobalValues module.
auto GVsM = std::make_unique<Module>((SrcM.getName() + ".globals").str(),
SrcM.getContext());
GVsM->setDataLayout(DL);
ValueToValueMapTy VMap;
// Clone global variable decls.
for (auto &GV : SrcM.globals())
if (!GV.isDeclaration() && !VMap.count(&GV))
cloneGlobalVariableDecl(*GVsM, GV, &VMap);
// And the aliases.
for (auto &A : SrcM.aliases())
if (!VMap.count(&A))
cloneGlobalAliasDecl(*GVsM, A, VMap);
// Clone the module flags.
cloneModuleFlagsMetadata(*GVsM, SrcM, VMap);
// Now we need to clone the GV and alias initializers.
// Initializers may refer to functions declared (but not defined) in this
// module. Build a materializer to clone decls on demand.
auto Materializer = createLambdaMaterializer(
[&LD, &GVsM](Value *V) -> Value* {
if (auto *F = dyn_cast<Function>(V)) {
// Decls in the original module just get cloned.
if (F->isDeclaration())
return cloneFunctionDecl(*GVsM, *F);
// Definitions in the original module (which we have emitted stubs
// for at this point) get turned into a constant alias to the stub
// instead.
const DataLayout &DL = GVsM->getDataLayout();
std::string FName = mangle(F->getName(), DL);
unsigned PtrBitWidth = DL.getPointerTypeSizeInBits(F->getType());
JITTargetAddress StubAddr =
LD.StubsMgr->findStub(FName, false).getAddress();
ConstantInt *StubAddrCI =
ConstantInt::get(GVsM->getContext(), APInt(PtrBitWidth, StubAddr));
Constant *Init = ConstantExpr::getCast(Instruction::IntToPtr,
StubAddrCI, F->getType());
return GlobalAlias::create(F->getFunctionType(),
F->getType()->getAddressSpace(),
F->getLinkage(), F->getName(),
Init, GVsM.get());
}
// else....
return nullptr;
});
// Clone the global variable initializers.
for (auto &GV : SrcM.globals())
if (!GV.isDeclaration())
moveGlobalVariableInitializer(GV, VMap, &Materializer);
// Clone the global alias initializers.
for (auto &A : SrcM.aliases()) {
auto *NewA = cast<GlobalAlias>(VMap[&A]);
assert(NewA && "Alias not cloned?");
Value *Init = MapValue(A.getAliasee(), VMap, RF_None, nullptr,
&Materializer);
NewA->setAliasee(cast<Constant>(Init));
}
// Build a resolver for the globals module and add it to the base layer.
auto LegacyLookup = [this, &LD](StringRef Name) -> JITSymbol {
if (auto Sym = LD.StubsMgr->findStub(Name, false))
return Sym;
if (auto Sym = LD.findSymbol(BaseLayer, std::string(Name), false))
return Sym;
else if (auto Err = Sym.takeError())
return std::move(Err);
return nullptr;
};
auto GVsResolver = createSymbolResolver(
[&LD, LegacyLookup](const SymbolNameSet &Symbols) {
auto RS = getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup);
if (!RS) {
logAllUnhandledErrors(
RS.takeError(), errs(),
"CODLayer/GVsResolver responsibility set lookup failed: ");
return SymbolNameSet();
}
if (RS->size() == Symbols.size())
return *RS;
SymbolNameSet NotFoundViaLegacyLookup;
for (auto &S : Symbols)
if (!RS->count(S))
NotFoundViaLegacyLookup.insert(S);
auto RS2 =
LD.BackingResolver->getResponsibilitySet(NotFoundViaLegacyLookup);
for (auto &S : RS2)
(*RS).insert(S);
return *RS;
},
[this, &LD,
LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Query,
SymbolNameSet Symbols) {
auto NotFoundViaLegacyLookup =
lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
return LD.BackingResolver->lookup(Query, NotFoundViaLegacyLookup);
});
SetSymbolResolver(LD.K, std::move(GVsResolver));
if (auto Err = BaseLayer.addModule(LD.K, std::move(GVsM)))
return Err;
LD.BaseLayerVModuleKeys.push_back(LD.K);
return Error::success();
}
static std::string mangle(StringRef Name, const DataLayout &DL) {
std::string MangledName;
{
raw_string_ostream MangledNameStream(MangledName);
Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
}
return MangledName;
}
Expected<JITTargetAddress>
extractAndCompile(LogicalDylib &LD,
typename LogicalDylib::SourceModuleHandle LMId,
Function &F) {
Module &SrcM = LD.getSourceModule(LMId);
// If F is a declaration we must already have compiled it.
if (F.isDeclaration())
return 0;
// Grab the name of the function being called here.
std::string CalledFnName = mangle(F.getName(), SrcM.getDataLayout());
JITTargetAddress CalledAddr = 0;
auto Part = Partition(F);
if (auto PartKeyOrErr = emitPartition(LD, LMId, Part)) {
auto &PartKey = *PartKeyOrErr;
for (auto *SubF : Part) {
std::string FnName = mangle(SubF->getName(), SrcM.getDataLayout());
if (auto FnBodySym = BaseLayer.findSymbolIn(PartKey, FnName, false)) {
if (auto FnBodyAddrOrErr = FnBodySym.getAddress()) {
JITTargetAddress FnBodyAddr = *FnBodyAddrOrErr;
// 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;
} else
return FnBodyAddrOrErr.takeError();
} else if (auto Err = FnBodySym.takeError())
return std::move(Err);
else
llvm_unreachable("Function not emitted for partition");
}
LD.BaseLayerVModuleKeys.push_back(PartKey);
} else
return PartKeyOrErr.takeError();
return CalledAddr;
}
template <typename PartitionT>
Expected<VModuleKey>
emitPartition(LogicalDylib &LD,
typename LogicalDylib::SourceModuleHandle LMId,
const PartitionT &Part) {
Module &SrcM = LD.getSourceModule(LMId);
// Create the module.
std::string NewName(SrcM.getName());
for (auto *F : Part) {
NewName += ".";
NewName += F->getName();
}
auto M = std::make_unique<Module>(NewName, SrcM.getContext());
M->setDataLayout(SrcM.getDataLayout());
ValueToValueMapTy VMap;
auto Materializer = createLambdaMaterializer([&LD, &LMId,
&M](Value *V) -> Value * {
if (auto *GV = dyn_cast<GlobalVariable>(V))
return cloneGlobalVariableDecl(*M, *GV);
if (auto *F = dyn_cast<Function>(V)) {
// Check whether we want to clone an available_externally definition.
if (!LD.getStubsToClone(LMId).count(F))
return cloneFunctionDecl(*M, *F);
// Ok - we want an inlinable stub. For that to work we need a decl
// for the stub pointer.
auto *StubPtr = createImplPointer(*F->getType(), *M,
F->getName() + "$stub_ptr", nullptr);
auto *ClonedF = cloneFunctionDecl(*M, *F);
makeStub(*ClonedF, *StubPtr);
ClonedF->setLinkage(GlobalValue::AvailableExternallyLinkage);
ClonedF->addFnAttr(Attribute::AlwaysInline);
return ClonedF;
}
if (auto *A = dyn_cast<GlobalAlias>(V)) {
auto *Ty = A->getValueType();
if (Ty->isFunctionTy())
return Function::Create(cast<FunctionType>(Ty),
GlobalValue::ExternalLinkage, A->getName(),
M.get());
return new GlobalVariable(*M, Ty, false, GlobalValue::ExternalLinkage,
nullptr, A->getName(), nullptr,
GlobalValue::NotThreadLocal,
A->getType()->getAddressSpace());
}
return nullptr;
});
// Create decls in the new module.
for (auto *F : Part)
cloneFunctionDecl(*M, *F, &VMap);
// Move the function bodies.
for (auto *F : Part)
moveFunctionBody(*F, VMap, &Materializer);
auto K = ES.allocateVModule();
auto LegacyLookup = [this, &LD](StringRef Name) -> JITSymbol {
return LD.findSymbol(BaseLayer, std::string(Name), false);
};
// Create memory manager and symbol resolver.
auto Resolver = createSymbolResolver(
[&LD, LegacyLookup](const SymbolNameSet &Symbols) {
auto RS = getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup);
if (!RS) {
logAllUnhandledErrors(
RS.takeError(), errs(),
"CODLayer/SubResolver responsibility set lookup failed: ");
return SymbolNameSet();
}
if (RS->size() == Symbols.size())
return *RS;
SymbolNameSet NotFoundViaLegacyLookup;
for (auto &S : Symbols)
if (!RS->count(S))
NotFoundViaLegacyLookup.insert(S);
auto RS2 =
LD.BackingResolver->getResponsibilitySet(NotFoundViaLegacyLookup);
for (auto &S : RS2)
(*RS).insert(S);
return *RS;
},
[this, &LD, LegacyLookup](std::shared_ptr<AsynchronousSymbolQuery> Q,
SymbolNameSet Symbols) {
auto NotFoundViaLegacyLookup =
lookupWithLegacyFn(ES, *Q, Symbols, LegacyLookup);
return LD.BackingResolver->lookup(Q,
std::move(NotFoundViaLegacyLookup));
});
SetSymbolResolver(K, std::move(Resolver));
if (auto Err = BaseLayer.addModule(std::move(K), std::move(M)))
return std::move(Err);
return K;
}
ExecutionSession &ES;
BaseLayerT &BaseLayer;
SymbolResolverGetter GetSymbolResolver;
SymbolResolverSetter SetSymbolResolver;
PartitioningFtor Partition;
CompileCallbackMgrT &CompileCallbackMgr;
IndirectStubsManagerBuilderT CreateIndirectStubsManager;
std::map<VModuleKey, LogicalDylib> LogicalDylibs;
bool CloneStubsIntoPartitions;
};
template <typename BaseLayerT, typename CompileCallbackMgrT,
typename IndirectStubsMgrT>
LegacyCompileOnDemandLayer<BaseLayerT, CompileCallbackMgrT, IndirectStubsMgrT>::
LegacyCompileOnDemandLayer(
ExecutionSession &ES, BaseLayerT &BaseLayer,
SymbolResolverGetter GetSymbolResolver,
SymbolResolverSetter SetSymbolResolver, PartitioningFtor Partition,
CompileCallbackMgrT &CallbackMgr,
IndirectStubsManagerBuilderT CreateIndirectStubsManager,
bool CloneStubsIntoPartitions)
: ES(ES), BaseLayer(BaseLayer),
GetSymbolResolver(std::move(GetSymbolResolver)),
SetSymbolResolver(std::move(SetSymbolResolver)),
Partition(std::move(Partition)), CompileCallbackMgr(CallbackMgr),
CreateIndirectStubsManager(std::move(CreateIndirectStubsManager)),
CloneStubsIntoPartitions(CloneStubsIntoPartitions) {}
} // end namespace orc
} // end namespace llvm

View File

@ -759,8 +759,6 @@ private:
void dropSymbol(const SymbolStringPtr &Name);
bool canStillFail();
void handleFailed(Error Err);
void detach();
@ -912,17 +910,6 @@ public:
/// Dump current JITDylib state to OS.
void dump(raw_ostream &OS);
/// FIXME: Remove this when we remove the old ORC layers.
/// Search the given JITDylibs in order for the symbols in Symbols. Results
/// (once they become available) will be returned via the given Query.
///
/// If any symbol is not found then the unresolved symbols will be returned,
/// and the query will not be applied. The Query is not failed and can be
/// re-used in a subsequent lookup once the symbols have been added, or
/// manually failed.
Expected<SymbolNameSet>
legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names);
/// Returns the given JITDylibs and all of their transitive dependencies in
/// DFS order (based on linkage relationships). Each JITDylib will appear
/// only once.
@ -1039,10 +1026,6 @@ private:
LookupKind K, JITDylibLookupFlags JDLookupFlags,
SymbolLookupSet &Unresolved);
bool lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
SymbolLookupSet &Unresolved);
void detachQueryHelper(AsynchronousSymbolQuery &Q,
const SymbolNameSet &QuerySymbols);
@ -1198,18 +1181,6 @@ public:
return *this;
}
void legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err);
using LegacyAsyncLookupFunction = std::function<SymbolNameSet(
std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Names)>;
/// A legacy lookup function for JITSymbolResolverAdapter.
/// Do not use -- this will be removed soon.
Expected<SymbolMap>
legacyLookup(LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names,
SymbolState RequiredState,
RegisterDependenciesFunction RegisterDependencies);
/// Search the given JITDylib list for the given symbols.
///
/// SearchOrder lists the JITDylibs to search. For each dylib, the associated

View File

@ -152,56 +152,6 @@ inline iterator_range<StaticInitGVIterator> getStaticInitGVs(Module &M) {
return make_range(StaticInitGVIterator(M), StaticInitGVIterator());
}
/// Convenience class for recording constructor/destructor names for
/// later execution.
template <typename JITLayerT>
class LegacyCtorDtorRunner {
public:
/// Construct a CtorDtorRunner for the given range using the given
/// name mangling function.
LLVM_ATTRIBUTE_DEPRECATED(
LegacyCtorDtorRunner(std::vector<std::string> CtorDtorNames,
VModuleKey K),
"ORCv1 utilities (utilities with the 'Legacy' prefix) are deprecated. "
"Please use the ORCv2 CtorDtorRunner utility instead");
LegacyCtorDtorRunner(ORCv1DeprecationAcknowledgement,
std::vector<std::string> CtorDtorNames, VModuleKey K)
: CtorDtorNames(std::move(CtorDtorNames)), K(K) {}
/// Run the recorded constructors/destructors through the given JIT
/// layer.
Error runViaLayer(JITLayerT &JITLayer) const {
using CtorDtorTy = void (*)();
for (const auto &CtorDtorName : CtorDtorNames) {
if (auto CtorDtorSym = JITLayer.findSymbolIn(K, CtorDtorName, false)) {
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:
std::vector<std::string> CtorDtorNames;
orc::VModuleKey K;
};
template <typename JITLayerT>
LegacyCtorDtorRunner<JITLayerT>::LegacyCtorDtorRunner(
std::vector<std::string> CtorDtorNames, VModuleKey K)
: CtorDtorNames(std::move(CtorDtorNames)), K(K) {}
class CtorDtorRunner {
public:
CtorDtorRunner(JITDylib &JD) : JD(JD) {}
@ -250,45 +200,6 @@ protected:
void *DSOHandle);
};
class LegacyLocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase {
public:
/// Create a runtime-overrides class.
template <typename MangleFtorT>
LLVM_ATTRIBUTE_DEPRECATED(
LegacyLocalCXXRuntimeOverrides(const MangleFtorT &Mangle),
"ORCv1 utilities (utilities with the 'Legacy' prefix) are deprecated. "
"Please use the ORCv2 LocalCXXRuntimeOverrides utility instead");
template <typename MangleFtorT>
LegacyLocalCXXRuntimeOverrides(ORCv1DeprecationAcknowledgement,
const MangleFtorT &Mangle) {
addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride));
addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride));
}
/// Search overrided symbols.
JITEvaluatedSymbol searchOverrides(const std::string &Name) {
auto I = CXXRuntimeOverrides.find(Name);
if (I != CXXRuntimeOverrides.end())
return JITEvaluatedSymbol(I->second, JITSymbolFlags::Exported);
return nullptr;
}
private:
void addOverride(const std::string &Name, JITTargetAddress Addr) {
CXXRuntimeOverrides.insert(std::make_pair(Name, Addr));
}
StringMap<JITTargetAddress> CXXRuntimeOverrides;
};
template <typename MangleFtorT>
LegacyLocalCXXRuntimeOverrides::LegacyLocalCXXRuntimeOverrides(
const MangleFtorT &Mangle) {
addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride));
addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride));
}
class LocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase {
public:
Error enable(JITDylib &JD, MangleAndInterner &Mangler);

View File

@ -1,110 +0,0 @@
//===- GlobalMappingLayer.h - Run all IR through a functor ------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Convenience layer for injecting symbols that will appear in calls to
// findSymbol.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_EXECUTIONENGINE_ORC_GLOBALMAPPINGLAYER_H
#define LLVM_EXECUTIONENGINE_ORC_GLOBALMAPPINGLAYER_H
#include "llvm/ExecutionEngine/JITSymbol.h"
#include <map>
#include <memory>
#include <string>
namespace llvm {
class Module;
namespace orc {
/// Global mapping layer.
///
/// This layer overrides the findSymbol method to first search a local symbol
/// table that the client can define. It can be used to inject new symbol
/// mappings into the JIT. Beware, however: symbols within a single IR module or
/// object file will still resolve locally (via RuntimeDyld's symbol table) -
/// such internal references cannot be overriden via this layer.
template <typename BaseLayerT>
class GlobalMappingLayer {
public:
/// Handle to an added module.
using ModuleHandleT = typename BaseLayerT::ModuleHandleT;
/// Construct an GlobalMappingLayer with the given BaseLayer
GlobalMappingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
/// Add the given module to the JIT.
/// @return A handle for the added modules.
Expected<ModuleHandleT>
addModule(std::shared_ptr<Module> M,
std::shared_ptr<JITSymbolResolver> Resolver) {
return BaseLayer.addModule(std::move(M), std::move(Resolver));
}
/// Remove the module set associated with the handle H.
Error removeModule(ModuleHandleT H) { return BaseLayer.removeModule(H); }
/// Manually set the address to return for the given symbol.
void setGlobalMapping(const std::string &Name, JITTargetAddress Addr) {
SymbolTable[Name] = Addr;
}
/// Remove the given symbol from the global mapping.
void eraseGlobalMapping(const std::string &Name) {
SymbolTable.erase(Name);
}
/// Search for the given named symbol.
///
/// This method will first search the local symbol table, returning
/// any symbol found there. If the symbol is not found in the local
/// table then this call will be passed through to the base layer.
///
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it exists.
JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
auto I = SymbolTable.find(Name);
if (I != SymbolTable.end())
return JITSymbol(I->second, JITSymbolFlags::Exported);
return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
}
/// Get the address of the given symbol in the context of the of the
/// module represented by the handle H. This call is forwarded to the
/// base layer's implementation.
/// @param H The handle for the module to search in.
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it is found in the
/// given module.
JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
bool ExportedSymbolsOnly) {
return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly);
}
/// Immediately emit and finalize the module set represented by the
/// given handle.
/// @param H Handle for module set to emit/finalize.
Error emitAndFinalize(ModuleHandleT H) {
return BaseLayer.emitAndFinalize(H);
}
private:
BaseLayerT &BaseLayer;
std::map<std::string, JITTargetAddress> SymbolTable;
};
} // end namespace orc
} // end namespace llvm
#endif // LLVM_EXECUTIONENGINE_ORC_GLOBALMAPPINGLAYER_H

View File

@ -66,99 +66,6 @@ private:
NotifyCompiledFunction NotifyCompiled = NotifyCompiledFunction();
};
/// Eager IR compiling layer.
///
/// This layer immediately compiles each IR module added via addModule to an
/// object file and adds this module file to the layer below, which must
/// implement the object layer concept.
template <typename BaseLayerT, typename CompileFtor>
class LegacyIRCompileLayer {
public:
/// Callback type for notifications when modules are compiled.
using NotifyCompiledCallback =
std::function<void(VModuleKey K, std::unique_ptr<Module>)>;
/// Construct an LegacyIRCompileLayer with the given BaseLayer, which must
/// implement the ObjectLayer concept.
LLVM_ATTRIBUTE_DEPRECATED(
LegacyIRCompileLayer(
BaseLayerT &BaseLayer, CompileFtor Compile,
NotifyCompiledCallback NotifyCompiled = NotifyCompiledCallback()),
"ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please "
"use "
"the ORCv2 IRCompileLayer instead");
/// Legacy layer constructor with deprecation acknowledgement.
LegacyIRCompileLayer(
ORCv1DeprecationAcknowledgement, BaseLayerT &BaseLayer,
CompileFtor Compile,
NotifyCompiledCallback NotifyCompiled = NotifyCompiledCallback())
: BaseLayer(BaseLayer), Compile(std::move(Compile)),
NotifyCompiled(std::move(NotifyCompiled)) {}
/// Get a reference to the compiler functor.
CompileFtor& getCompiler() { return Compile; }
/// (Re)set the NotifyCompiled callback.
void setNotifyCompiled(NotifyCompiledCallback NotifyCompiled) {
this->NotifyCompiled = std::move(NotifyCompiled);
}
/// Compile the module, and add the resulting object to the base layer
/// along with the given memory manager and symbol resolver.
Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
auto Obj = Compile(*M);
if (!Obj)
return Obj.takeError();
if (auto Err = BaseLayer.addObject(std::move(K), std::move(*Obj)))
return Err;
if (NotifyCompiled)
NotifyCompiled(std::move(K), std::move(M));
return Error::success();
}
/// Remove the module associated with the VModuleKey K.
Error removeModule(VModuleKey K) { return BaseLayer.removeObject(K); }
/// Search for the given named symbol.
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it exists.
JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
}
/// Get the address of the given symbol in compiled module represented
/// by the handle H. This call is forwarded to the base layer's
/// implementation.
/// @param K The VModuleKey for the module to search in.
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it is found in the
/// given module.
JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
bool ExportedSymbolsOnly) {
return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly);
}
/// Immediately emit and finalize the module represented by the given
/// handle.
/// @param K The VModuleKey for the module to emit/finalize.
Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); }
private:
BaseLayerT &BaseLayer;
CompileFtor Compile;
NotifyCompiledCallback NotifyCompiled;
};
template <typename BaseLayerT, typename CompileFtor>
LegacyIRCompileLayer<BaseLayerT, CompileFtor>::LegacyIRCompileLayer(
BaseLayerT &BaseLayer, CompileFtor Compile,
NotifyCompiledCallback NotifyCompiled)
: BaseLayer(BaseLayer), Compile(std::move(Compile)),
NotifyCompiled(std::move(NotifyCompiled)) {}
} // end namespace orc
} // end namespace llvm

View File

@ -51,80 +51,6 @@ private:
TransformFunction Transform;
};
/// IR mutating layer.
///
/// This layer applies a user supplied transform to each module that is added,
/// then adds the transformed module to the layer below.
template <typename BaseLayerT, typename TransformFtor>
class LegacyIRTransformLayer {
public:
/// Construct an LegacyIRTransformLayer with the given BaseLayer
LLVM_ATTRIBUTE_DEPRECATED(
LegacyIRTransformLayer(BaseLayerT &BaseLayer,
TransformFtor Transform = TransformFtor()),
"ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please "
"use "
"the ORCv2 IRTransformLayer instead");
/// Legacy layer constructor with deprecation acknowledgement.
LegacyIRTransformLayer(ORCv1DeprecationAcknowledgement, BaseLayerT &BaseLayer,
TransformFtor Transform = TransformFtor())
: BaseLayer(BaseLayer), Transform(std::move(Transform)) {}
/// Apply the transform functor to the module, then add the module to
/// the layer below, along with the memory manager and symbol resolver.
///
/// @return A handle for the added modules.
Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
return BaseLayer.addModule(std::move(K), Transform(std::move(M)));
}
/// Remove the module associated with the VModuleKey K.
Error removeModule(VModuleKey K) { return BaseLayer.removeModule(K); }
/// Search for the given named symbol.
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it exists.
JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
}
/// Get the address of the given symbol in the context of the module
/// represented by the VModuleKey K. This call is forwarded to the base
/// layer's implementation.
/// @param K The VModuleKey for the module to search in.
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it is found in the
/// given module.
JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
bool ExportedSymbolsOnly) {
return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly);
}
/// Immediately emit and finalize the module represented by the given
/// VModuleKey.
/// @param K The VModuleKey for the module to emit/finalize.
Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); }
/// Access the transform functor directly.
TransformFtor& getTransform() { return Transform; }
/// Access the mumate functor directly.
const TransformFtor& getTransform() const { return Transform; }
private:
BaseLayerT &BaseLayer;
TransformFtor Transform;
};
template <typename BaseLayerT, typename TransformFtor>
LegacyIRTransformLayer<BaseLayerT, TransformFtor>::LegacyIRTransformLayer(
BaseLayerT &BaseLayer, TransformFtor Transform)
: BaseLayer(BaseLayer), Transform(std::move(Transform)) {}
} // end namespace orc
} // end namespace llvm

View File

@ -1,84 +0,0 @@
//===- LambdaResolverMM - Redirect symbol lookup via a functor --*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Defines a RuntimeDyld::SymbolResolver subclass that uses a user-supplied
// functor for symbol resolution.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H
#define LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H
#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/OrcV1Deprecation.h"
#include <memory>
namespace llvm {
namespace orc {
template <typename DylibLookupFtorT, typename ExternalLookupFtorT>
class LambdaResolver : public LegacyJITSymbolResolver {
public:
LLVM_ATTRIBUTE_DEPRECATED(
LambdaResolver(DylibLookupFtorT DylibLookupFtor,
ExternalLookupFtorT ExternalLookupFtor),
"ORCv1 utilities (including resolvers) are deprecated and will be "
"removed "
"in the next release. Please use ORCv2 (see docs/ORCv2.rst)");
LambdaResolver(ORCv1DeprecationAcknowledgement,
DylibLookupFtorT DylibLookupFtor,
ExternalLookupFtorT ExternalLookupFtor)
: DylibLookupFtor(DylibLookupFtor),
ExternalLookupFtor(ExternalLookupFtor) {}
JITSymbol findSymbolInLogicalDylib(const std::string &Name) final {
return DylibLookupFtor(Name);
}
JITSymbol findSymbol(const std::string &Name) final {
return ExternalLookupFtor(Name);
}
private:
DylibLookupFtorT DylibLookupFtor;
ExternalLookupFtorT ExternalLookupFtor;
};
template <typename DylibLookupFtorT, typename ExternalLookupFtorT>
LambdaResolver<DylibLookupFtorT, ExternalLookupFtorT>::LambdaResolver(
DylibLookupFtorT DylibLookupFtor, ExternalLookupFtorT ExternalLookupFtor)
: DylibLookupFtor(DylibLookupFtor), ExternalLookupFtor(ExternalLookupFtor) {
}
template <typename DylibLookupFtorT,
typename ExternalLookupFtorT>
std::shared_ptr<LambdaResolver<DylibLookupFtorT, ExternalLookupFtorT>>
createLambdaResolver(DylibLookupFtorT DylibLookupFtor,
ExternalLookupFtorT ExternalLookupFtor) {
using LR = LambdaResolver<DylibLookupFtorT, ExternalLookupFtorT>;
return std::make_unique<LR>(std::move(DylibLookupFtor),
std::move(ExternalLookupFtor));
}
template <typename DylibLookupFtorT, typename ExternalLookupFtorT>
std::shared_ptr<LambdaResolver<DylibLookupFtorT, ExternalLookupFtorT>>
createLambdaResolver(ORCv1DeprecationAcknowledgement,
DylibLookupFtorT DylibLookupFtor,
ExternalLookupFtorT ExternalLookupFtor) {
using LR = LambdaResolver<DylibLookupFtorT, ExternalLookupFtorT>;
return std::make_unique<LR>(AcknowledgeORCv1Deprecation,
std::move(DylibLookupFtor),
std::move(ExternalLookupFtor));
}
} // end namespace orc
} // end namespace llvm
#endif // LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H

View File

@ -1,267 +0,0 @@
//===- LazyEmittingLayer.h - Lazily emit IR to lower JIT layers -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Contains the definition for a lazy-emitting layer for the JIT.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
#define LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <list>
#include <memory>
#include <string>
namespace llvm {
namespace orc {
/// Lazy-emitting IR layer.
///
/// This layer accepts LLVM IR Modules (via addModule) but does not
/// immediately emit them the layer below. Instead, emission to the base layer
/// is deferred until the first time the client requests the address (via
/// JITSymbol::getAddress) for a symbol contained in this layer.
template <typename BaseLayerT> class LazyEmittingLayer {
private:
class EmissionDeferredModule {
public:
EmissionDeferredModule(VModuleKey K, std::unique_ptr<Module> M)
: K(std::move(K)), M(std::move(M)) {}
JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) {
switch (EmitState) {
case NotEmitted:
if (auto GV = searchGVs(Name, ExportedSymbolsOnly)) {
JITSymbolFlags Flags = JITSymbolFlags::fromGlobalValue(*GV);
auto GetAddress = [this, ExportedSymbolsOnly, Name = Name.str(),
&B]() -> Expected<JITTargetAddress> {
if (this->EmitState == Emitting)
return 0;
else if (this->EmitState == NotEmitted) {
this->EmitState = Emitting;
if (auto Err = this->emitToBaseLayer(B))
return std::move(Err);
this->EmitState = Emitted;
}
if (auto Sym = B.findSymbolIn(K, Name, 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
return nullptr;
case Emitting:
// Calling "emit" can trigger a recursive call to 'find' (e.g. to check
// for pre-existing definitions of common-symbol), but any symbol in
// this module would already have been found internally (in the
// RuntimeDyld that did the lookup), so just return a nullptr here.
return nullptr;
case Emitted:
return B.findSymbolIn(K, std::string(Name), ExportedSymbolsOnly);
}
llvm_unreachable("Invalid emit-state.");
}
Error removeModuleFromBaseLayer(BaseLayerT& BaseLayer) {
return EmitState != NotEmitted ? BaseLayer.removeModule(K)
: Error::success();
}
void emitAndFinalize(BaseLayerT &BaseLayer) {
assert(EmitState != Emitting &&
"Cannot emitAndFinalize while already emitting");
if (EmitState == NotEmitted) {
EmitState = Emitting;
emitToBaseLayer(BaseLayer);
EmitState = Emitted;
}
BaseLayer.emitAndFinalize(K);
}
private:
const GlobalValue* searchGVs(StringRef Name,
bool ExportedSymbolsOnly) const {
// FIXME: We could clean all this up if we had a way to reliably demangle
// names: We could just demangle name and search, rather than
// mangling everything else.
// If we have already built the mangled name set then just search it.
if (MangledSymbols) {
auto VI = MangledSymbols->find(Name);
if (VI == MangledSymbols->end())
return nullptr;
auto GV = VI->second;
if (!ExportedSymbolsOnly || GV->hasDefaultVisibility())
return GV;
return nullptr;
}
// If we haven't built the mangled name set yet, try to build it. As an
// optimization this will leave MangledNames set to nullptr if we find
// Name in the process of building the set.
return buildMangledSymbols(Name, ExportedSymbolsOnly);
}
Error 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();
return BaseLayer.addModule(std::move(K), std::move(M));
}
// If the mangled name of the given GlobalValue matches the given search
// name (and its visibility conforms to the ExportedSymbolsOnly flag) then
// return the symbol. Otherwise, add the mangled name to the Names map and
// return nullptr.
const GlobalValue* addGlobalValue(StringMap<const GlobalValue*> &Names,
const GlobalValue &GV,
const Mangler &Mang, StringRef SearchName,
bool ExportedSymbolsOnly) const {
// Modules don't "provide" decls or common symbols.
if (GV.isDeclaration() || GV.hasCommonLinkage())
return nullptr;
// Mangle the GV name.
std::string MangledName;
{
raw_string_ostream MangledNameStream(MangledName);
Mang.getNameWithPrefix(MangledNameStream, &GV, false);
}
// Check whether this is the name we were searching for, and if it is then
// bail out early.
if (MangledName == SearchName)
if (!ExportedSymbolsOnly || GV.hasDefaultVisibility())
return &GV;
// Otherwise add this to the map for later.
Names[MangledName] = &GV;
return nullptr;
}
// Build the MangledSymbols map. Bails out early (with MangledSymbols left set
// to nullptr) if the given SearchName is found while building the map.
const GlobalValue* buildMangledSymbols(StringRef SearchName,
bool ExportedSymbolsOnly) const {
assert(!MangledSymbols && "Mangled symbols map already exists?");
auto Symbols = std::make_unique<StringMap<const GlobalValue*>>();
Mangler Mang;
for (const auto &GO : M->global_objects())
if (auto GV = addGlobalValue(*Symbols, GO, Mang, SearchName,
ExportedSymbolsOnly))
return GV;
MangledSymbols = std::move(Symbols);
return nullptr;
}
enum { NotEmitted, Emitting, Emitted } EmitState = NotEmitted;
VModuleKey K;
std::unique_ptr<Module> M;
mutable std::unique_ptr<StringMap<const GlobalValue*>> MangledSymbols;
};
BaseLayerT &BaseLayer;
std::map<VModuleKey, std::unique_ptr<EmissionDeferredModule>> ModuleMap;
public:
/// Construct a lazy emitting layer.
LLVM_ATTRIBUTE_DEPRECATED(
LazyEmittingLayer(BaseLayerT &BaseLayer),
"ORCv1 layers (including LazyEmittingLayer) are deprecated. Please use "
"ORCv2, where lazy emission is the default");
/// Construct a lazy emitting layer.
LazyEmittingLayer(ORCv1DeprecationAcknowledgement, BaseLayerT &BaseLayer)
: BaseLayer(BaseLayer) {}
/// Add the given module to the lazy emitting layer.
Error addModule(VModuleKey K, std::unique_ptr<Module> M) {
assert(!ModuleMap.count(K) && "VModuleKey K already in use");
ModuleMap[K] =
std::make_unique<EmissionDeferredModule>(std::move(K), std::move(M));
return Error::success();
}
/// Remove the module represented by the given handle.
///
/// This method will free the memory associated with the given module, both
/// in this layer, and the base layer.
Error removeModule(VModuleKey K) {
auto I = ModuleMap.find(K);
assert(I != ModuleMap.end() && "VModuleKey K not valid here");
auto EDM = std::move(I.second);
ModuleMap.erase(I);
return EDM->removeModuleFromBaseLayer(BaseLayer);
}
/// Search for the given named symbol.
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it exists.
JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
// Look for the symbol among existing definitions.
if (auto Symbol = BaseLayer.findSymbol(Name, ExportedSymbolsOnly))
return Symbol;
// If not found then search the deferred modules. If any of these contain a
// definition of 'Name' then they will return a JITSymbol that will emit
// the corresponding module when the symbol address is requested.
for (auto &KV : ModuleMap)
if (auto Symbol = KV.second->find(Name, ExportedSymbolsOnly, BaseLayer))
return Symbol;
// If no definition found anywhere return a null symbol.
return nullptr;
}
/// Get the address of the given symbol in the context of the of
/// compiled modules represented by the key K.
JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
bool ExportedSymbolsOnly) {
assert(ModuleMap.count(K) && "VModuleKey K not valid here");
return ModuleMap[K]->find(Name, ExportedSymbolsOnly, BaseLayer);
}
/// Immediately emit and finalize the module represented by the given
/// key.
Error emitAndFinalize(VModuleKey K) {
assert(ModuleMap.count(K) && "VModuleKey K not valid here");
return ModuleMap[K]->emitAndFinalize(BaseLayer);
}
};
template <typename BaseLayerT>
LazyEmittingLayer<BaseLayerT>::LazyEmittingLayer(BaseLayerT &BaseLayer)
: BaseLayer(BaseLayer) {}
} // end namespace orc
} // end namespace llvm
#endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H

View File

@ -1,211 +0,0 @@
//===--- Legacy.h -- Adapters for ExecutionEngine API interop ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Contains core ORC APIs.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_EXECUTIONENGINE_ORC_LEGACY_H
#define LLVM_EXECUTIONENGINE_ORC_LEGACY_H
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
namespace llvm {
namespace orc {
/// SymbolResolver is a composable interface for looking up symbol flags
/// and addresses using the AsynchronousSymbolQuery type. It will
/// eventually replace the LegacyJITSymbolResolver interface as the
/// stardard ORC symbol resolver type.
///
/// FIXME: SymbolResolvers should go away and be replaced with VSOs with
/// defenition generators.
class SymbolResolver {
public:
virtual ~SymbolResolver() = default;
/// Returns the subset of the given symbols that the caller is responsible for
/// materializing.
virtual SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) = 0;
/// For each symbol in Symbols that can be found, assigns that symbols
/// value in Query. Returns the set of symbols that could not be found.
virtual SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
SymbolNameSet Symbols) = 0;
private:
virtual void anchor();
};
/// Implements SymbolResolver with a pair of supplied function objects
/// for convenience. See createSymbolResolver.
template <typename GetResponsibilitySetFn, typename LookupFn>
class LambdaSymbolResolver final : public SymbolResolver {
public:
template <typename GetResponsibilitySetFnRef, typename LookupFnRef>
LambdaSymbolResolver(GetResponsibilitySetFnRef &&GetResponsibilitySet,
LookupFnRef &&Lookup)
: GetResponsibilitySet(
std::forward<GetResponsibilitySetFnRef>(GetResponsibilitySet)),
Lookup(std::forward<LookupFnRef>(Lookup)) {}
SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final {
return GetResponsibilitySet(Symbols);
}
SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
SymbolNameSet Symbols) final {
return Lookup(std::move(Query), std::move(Symbols));
}
private:
GetResponsibilitySetFn GetResponsibilitySet;
LookupFn Lookup;
};
/// Creates a SymbolResolver implementation from the pair of supplied
/// function objects.
template <typename GetResponsibilitySetFn, typename LookupFn>
std::unique_ptr<LambdaSymbolResolver<
std::remove_cv_t<std::remove_reference_t<GetResponsibilitySetFn>>,
std::remove_cv_t<std::remove_reference_t<LookupFn>>>>
createSymbolResolver(GetResponsibilitySetFn &&GetResponsibilitySet,
LookupFn &&Lookup) {
using LambdaSymbolResolverImpl = LambdaSymbolResolver<
std::remove_cv_t<std::remove_reference_t<GetResponsibilitySetFn>>,
std::remove_cv_t<std::remove_reference_t<LookupFn>>>;
return std::make_unique<LambdaSymbolResolverImpl>(
std::forward<GetResponsibilitySetFn>(GetResponsibilitySet),
std::forward<LookupFn>(Lookup));
}
/// Legacy adapter. Remove once we kill off the old ORC layers.
class JITSymbolResolverAdapter : public JITSymbolResolver {
public:
JITSymbolResolverAdapter(ExecutionSession &ES, SymbolResolver &R,
MaterializationResponsibility *MR);
Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) override;
void lookup(const LookupSet &Symbols, OnResolvedFunction OnResolved) override;
private:
ExecutionSession &ES;
std::set<SymbolStringPtr> ResolvedStrings;
SymbolResolver &R;
MaterializationResponsibility *MR;
};
/// Use the given legacy-style FindSymbol function (i.e. a function that takes
/// a const std::string& or StringRef and returns a JITSymbol) to get the
/// subset of symbols that the caller is responsible for materializing. If any
/// JITSymbol returned by FindSymbol is in an error state the function returns
/// immediately with that error.
///
/// Useful for implementing getResponsibilitySet bodies that query legacy
/// resolvers.
template <typename FindSymbolFn>
Expected<SymbolNameSet>
getResponsibilitySetWithLegacyFn(const SymbolNameSet &Symbols,
FindSymbolFn FindSymbol) {
SymbolNameSet Result;
for (auto &S : Symbols) {
if (JITSymbol Sym = FindSymbol(*S)) {
if (!Sym.getFlags().isStrong())
Result.insert(S);
} else if (auto Err = Sym.takeError())
return std::move(Err);
}
return Result;
}
/// Use the given legacy-style FindSymbol function (i.e. a function that
/// takes a const std::string& or StringRef and returns a JITSymbol) to
/// find the address and flags for each symbol in Symbols and store the
/// result in Query. If any JITSymbol returned by FindSymbol is in an
/// error then Query.notifyFailed(...) is called with that error and the
/// function returns immediately. On success, returns the set of symbols
/// not found.
///
/// Useful for implementing lookup bodies that query legacy resolvers.
template <typename FindSymbolFn>
SymbolNameSet
lookupWithLegacyFn(ExecutionSession &ES, AsynchronousSymbolQuery &Query,
const SymbolNameSet &Symbols, FindSymbolFn FindSymbol) {
SymbolNameSet SymbolsNotFound;
bool NewSymbolsResolved = false;
for (auto &S : Symbols) {
if (JITSymbol Sym = FindSymbol(*S)) {
if (auto Addr = Sym.getAddress()) {
Query.notifySymbolMetRequiredState(
S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
NewSymbolsResolved = true;
} else {
ES.legacyFailQuery(Query, Addr.takeError());
return SymbolNameSet();
}
} else if (auto Err = Sym.takeError()) {
ES.legacyFailQuery(Query, std::move(Err));
return SymbolNameSet();
} else
SymbolsNotFound.insert(S);
}
if (NewSymbolsResolved && Query.isComplete())
Query.handleComplete();
return SymbolsNotFound;
}
/// An ORC SymbolResolver implementation that uses a legacy
/// findSymbol-like function to perform lookup;
template <typename LegacyLookupFn>
class LegacyLookupFnResolver final : public SymbolResolver {
public:
using ErrorReporter = std::function<void(Error)>;
LegacyLookupFnResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
ErrorReporter ReportError)
: ES(ES), LegacyLookup(std::move(LegacyLookup)),
ReportError(std::move(ReportError)) {}
SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final {
if (auto ResponsibilitySet =
getResponsibilitySetWithLegacyFn(Symbols, LegacyLookup))
return std::move(*ResponsibilitySet);
else {
ReportError(ResponsibilitySet.takeError());
return SymbolNameSet();
}
}
SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
SymbolNameSet Symbols) final {
return lookupWithLegacyFn(ES, *Query, Symbols, LegacyLookup);
}
private:
ExecutionSession &ES;
LegacyLookupFn LegacyLookup;
ErrorReporter ReportError;
};
template <typename LegacyLookupFn>
std::shared_ptr<LegacyLookupFnResolver<LegacyLookupFn>>
createLegacyLookupResolver(ExecutionSession &ES, LegacyLookupFn LegacyLookup,
std::function<void(Error)> ErrorReporter) {
return std::make_shared<LegacyLookupFnResolver<LegacyLookupFn>>(
ES, std::move(LegacyLookup), std::move(ErrorReporter));
}
} // End namespace orc
} // End namespace llvm
#endif // LLVM_EXECUTIONENGINE_ORC_LEGACY_H

View File

@ -1,43 +0,0 @@
//===------ NullResolver.h - Reject symbol lookup requests ------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Defines a RuntimeDyld::SymbolResolver subclass that rejects all symbol
// resolution requests, for clients that have no cross-object fixups.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H
#define LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H
#include "llvm/ExecutionEngine/Orc/Legacy.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
namespace llvm {
namespace orc {
class NullResolver : public SymbolResolver {
public:
SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) final;
SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
SymbolNameSet Symbols) final;
};
/// SymbolResolver impliementation that rejects all resolution requests.
/// Useful for clients that have no cross-object fixups.
class NullLegacyResolver : public LegacyJITSymbolResolver {
public:
JITSymbol findSymbol(const std::string &Name) final;
JITSymbol findSymbolInLogicalDylib(const std::string &Name) final;
};
} // End namespace orc.
} // End namespace llvm.
#endif // LLVM_EXECUTIONENGINE_ORC_NULLRESOLVER_H

View File

@ -43,88 +43,6 @@ private:
TransformFunction Transform;
};
/// Object mutating layer.
///
/// This layer accepts sets of ObjectFiles (via addObject). It
/// immediately applies the user supplied functor to each object, then adds
/// the set of transformed objects to the layer below.
template <typename BaseLayerT, typename TransformFtor>
class LegacyObjectTransformLayer {
public:
/// Construct an ObjectTransformLayer with the given BaseLayer
LLVM_ATTRIBUTE_DEPRECATED(
LegacyObjectTransformLayer(BaseLayerT &BaseLayer,
TransformFtor Transform = TransformFtor()),
"ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please "
"use "
"the ORCv2 ObjectTransformLayer instead");
/// Legacy layer constructor with deprecation acknowledgement.
LegacyObjectTransformLayer(ORCv1DeprecationAcknowledgement,
BaseLayerT &BaseLayer,
TransformFtor Transform = TransformFtor())
: BaseLayer(BaseLayer), Transform(std::move(Transform)) {}
/// Apply the transform functor to each object in the object set, then
/// add the resulting set of objects to the base layer, along with the
/// memory manager and symbol resolver.
///
/// @return A handle for the added objects.
template <typename ObjectPtr> Error addObject(VModuleKey K, ObjectPtr Obj) {
return BaseLayer.addObject(std::move(K), Transform(std::move(Obj)));
}
/// Remove the object set associated with the VModuleKey K.
Error removeObject(VModuleKey K) { return BaseLayer.removeObject(K); }
/// Search for the given named symbol.
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it exists.
JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
}
/// Get the address of the given symbol in the context of the set of
/// objects represented by the VModuleKey K. This call is forwarded to
/// the base layer's implementation.
/// @param K The VModuleKey associated with the object set to search in.
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it is found in the
/// given object set.
JITSymbol findSymbolIn(VModuleKey K, const std::string &Name,
bool ExportedSymbolsOnly) {
return BaseLayer.findSymbolIn(K, Name, ExportedSymbolsOnly);
}
/// Immediately emit and finalize the object set represented by the
/// given VModuleKey K.
Error emitAndFinalize(VModuleKey K) { return BaseLayer.emitAndFinalize(K); }
/// Map section addresses for the objects associated with the
/// VModuleKey K.
void mapSectionAddress(VModuleKey K, const void *LocalAddress,
JITTargetAddress TargetAddr) {
BaseLayer.mapSectionAddress(K, LocalAddress, TargetAddr);
}
/// Access the transform functor directly.
TransformFtor &getTransform() { return Transform; }
/// Access the mumate functor directly.
const TransformFtor &getTransform() const { return Transform; }
private:
BaseLayerT &BaseLayer;
TransformFtor Transform;
};
template <typename BaseLayerT, typename TransformFtor>
LegacyObjectTransformLayer<BaseLayerT, TransformFtor>::
LegacyObjectTransformLayer(BaseLayerT &BaseLayer, TransformFtor Transform)
: BaseLayer(BaseLayer), Transform(std::move(Transform)) {}
} // end namespace orc
} // end namespace llvm

View File

@ -20,7 +20,6 @@
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/Layer.h"
#include "llvm/ExecutionEngine/Orc/Legacy.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Error.h"
@ -148,356 +147,6 @@ private:
LoadedObjInfos;
};
class LegacyRTDyldObjectLinkingLayerBase {
public:
using ObjectPtr = std::unique_ptr<MemoryBuffer>;
protected:
/// Holds an object to be allocated/linked as a unit in the JIT.
///
/// An instance of this class will be created for each object added
/// via JITObjectLayer::addObject. Deleting the instance (via
/// removeObject) frees its memory, removing all symbol definitions that
/// had been provided by this instance. Higher level layers are responsible
/// for taking any action required to handle the missing symbols.
class LinkedObject {
public:
LinkedObject() = default;
LinkedObject(const LinkedObject&) = delete;
void operator=(const LinkedObject&) = delete;
virtual ~LinkedObject() = default;
virtual Error finalize() = 0;
virtual JITSymbol::GetAddressFtor
getSymbolMaterializer(std::string Name) = 0;
virtual void mapSectionAddress(const void *LocalAddress,
JITTargetAddress TargetAddr) const = 0;
JITSymbol getSymbol(StringRef Name, bool ExportedSymbolsOnly) {
auto SymEntry = SymbolTable.find(Name);
if (SymEntry == SymbolTable.end())
return nullptr;
if (!SymEntry->second.getFlags().isExported() && ExportedSymbolsOnly)
return nullptr;
if (!Finalized)
return JITSymbol(getSymbolMaterializer(std::string(Name)),
SymEntry->second.getFlags());
return JITSymbol(SymEntry->second);
}
protected:
StringMap<JITEvaluatedSymbol> SymbolTable;
bool Finalized = false;
};
};
/// Bare bones object linking layer.
///
/// This class is intended to be used as the base layer for a JIT. It allows
/// object files to be loaded into memory, linked, and the addresses of their
/// symbols queried. All objects added to this layer can see each other's
/// symbols.
class LegacyRTDyldObjectLinkingLayer : public LegacyRTDyldObjectLinkingLayerBase {
public:
using LegacyRTDyldObjectLinkingLayerBase::ObjectPtr;
/// Functor for receiving object-loaded notifications.
using NotifyLoadedFtor =
std::function<void(VModuleKey, const object::ObjectFile &Obj,
const RuntimeDyld::LoadedObjectInfo &)>;
/// Functor for receiving finalization notifications.
using NotifyFinalizedFtor =
std::function<void(VModuleKey, const object::ObjectFile &Obj,
const RuntimeDyld::LoadedObjectInfo &)>;
/// Functor for receiving deallocation notifications.
using NotifyFreedFtor = std::function<void(VModuleKey, const object::ObjectFile &Obj)>;
private:
using OwnedObject = object::OwningBinary<object::ObjectFile>;
template <typename MemoryManagerPtrT>
class ConcreteLinkedObject : public LinkedObject {
public:
ConcreteLinkedObject(LegacyRTDyldObjectLinkingLayer &Parent, VModuleKey K,
OwnedObject Obj, MemoryManagerPtrT MemMgr,
std::shared_ptr<SymbolResolver> Resolver,
bool ProcessAllSections)
: K(std::move(K)),
Parent(Parent),
MemMgr(std::move(MemMgr)),
PFC(std::make_unique<PreFinalizeContents>(
std::move(Obj), std::move(Resolver),
ProcessAllSections)) {
buildInitialSymbolTable(PFC->Obj);
}
~ConcreteLinkedObject() override {
if (this->Parent.NotifyFreed && ObjForNotify.getBinary())
this->Parent.NotifyFreed(K, *ObjForNotify.getBinary());
MemMgr->deregisterEHFrames();
}
Error finalize() override {
assert(PFC && "mapSectionAddress called on finalized LinkedObject");
JITSymbolResolverAdapter ResolverAdapter(Parent.ES, *PFC->Resolver,
nullptr);
PFC->RTDyld = std::make_unique<RuntimeDyld>(*MemMgr, ResolverAdapter);
PFC->RTDyld->setProcessAllSections(PFC->ProcessAllSections);
Finalized = true;
std::unique_ptr<RuntimeDyld::LoadedObjectInfo> Info =
PFC->RTDyld->loadObject(*PFC->Obj.getBinary());
// Copy the symbol table out of the RuntimeDyld instance.
{
auto SymTab = PFC->RTDyld->getSymbolTable();
for (auto &KV : SymTab)
SymbolTable[KV.first] = KV.second;
}
if (Parent.NotifyLoaded)
Parent.NotifyLoaded(K, *PFC->Obj.getBinary(), *Info);
PFC->RTDyld->finalizeWithMemoryManagerLocking();
if (PFC->RTDyld->hasError())
return make_error<StringError>(PFC->RTDyld->getErrorString(),
inconvertibleErrorCode());
if (Parent.NotifyFinalized)
Parent.NotifyFinalized(K, *PFC->Obj.getBinary(), *Info);
// Release resources.
if (this->Parent.NotifyFreed)
ObjForNotify = std::move(PFC->Obj); // needed for callback
PFC = nullptr;
return Error::success();
}
JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override {
return [this, Name]() -> Expected<JITTargetAddress> {
// The symbol may be materialized between the creation of this lambda
// and its execution, so we need to double check.
if (!this->Finalized)
if (auto Err = this->finalize())
return std::move(Err);
return this->getSymbol(Name, false).getAddress();
};
}
void mapSectionAddress(const void *LocalAddress,
JITTargetAddress TargetAddr) const override {
assert(PFC && "mapSectionAddress called on finalized LinkedObject");
assert(PFC->RTDyld && "mapSectionAddress called on raw LinkedObject");
PFC->RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
}
private:
void buildInitialSymbolTable(const OwnedObject &Obj) {
for (auto &Symbol : Obj.getBinary()->symbols()) {
if (Expected<uint32_t> SymbolFlagsOrErr = Symbol.getFlags()) {
if (*SymbolFlagsOrErr & object::SymbolRef::SF_Undefined)
continue;
} else {
// FIXME: Raise an error for bad symbols.
consumeError(SymbolFlagsOrErr.takeError());
continue;
}
Expected<StringRef> SymbolName = Symbol.getName();
// FIXME: Raise an error for bad symbols.
if (!SymbolName) {
consumeError(SymbolName.takeError());
continue;
}
// FIXME: Raise an error for bad symbols.
auto Flags = JITSymbolFlags::fromObjectSymbol(Symbol);
if (!Flags) {
consumeError(Flags.takeError());
continue;
}
SymbolTable.insert(
std::make_pair(*SymbolName, JITEvaluatedSymbol(0, *Flags)));
}
}
// Contains the information needed prior to finalization: the object files,
// memory manager, resolver, and flags needed for RuntimeDyld.
struct PreFinalizeContents {
PreFinalizeContents(OwnedObject Obj,
std::shared_ptr<SymbolResolver> Resolver,
bool ProcessAllSections)
: Obj(std::move(Obj)),
Resolver(std::move(Resolver)),
ProcessAllSections(ProcessAllSections) {}
OwnedObject Obj;
std::shared_ptr<SymbolResolver> Resolver;
bool ProcessAllSections;
std::unique_ptr<RuntimeDyld> RTDyld;
};
VModuleKey K;
LegacyRTDyldObjectLinkingLayer &Parent;
MemoryManagerPtrT MemMgr;
OwnedObject ObjForNotify;
std::unique_ptr<PreFinalizeContents> PFC;
};
template <typename MemoryManagerPtrT>
std::unique_ptr<ConcreteLinkedObject<MemoryManagerPtrT>>
createLinkedObject(LegacyRTDyldObjectLinkingLayer &Parent, VModuleKey K,
OwnedObject Obj, MemoryManagerPtrT MemMgr,
std::shared_ptr<SymbolResolver> Resolver,
bool ProcessAllSections) {
using LOS = ConcreteLinkedObject<MemoryManagerPtrT>;
return std::make_unique<LOS>(Parent, std::move(K), std::move(Obj),
std::move(MemMgr), std::move(Resolver),
ProcessAllSections);
}
public:
struct Resources {
std::shared_ptr<RuntimeDyld::MemoryManager> MemMgr;
std::shared_ptr<SymbolResolver> Resolver;
};
using ResourcesGetter = std::function<Resources(VModuleKey)>;
/// Construct an ObjectLinkingLayer with the given NotifyLoaded,
/// and NotifyFinalized functors.
LLVM_ATTRIBUTE_DEPRECATED(
LegacyRTDyldObjectLinkingLayer(
ExecutionSession &ES, ResourcesGetter GetResources,
NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor(),
NotifyFreedFtor NotifyFreed = NotifyFreedFtor()),
"ORCv1 layers (layers with the 'Legacy' prefix) are deprecated. Please "
"use "
"ORCv2 (see docs/ORCv2.rst)");
// Legacy layer constructor with deprecation acknowledgement.
LegacyRTDyldObjectLinkingLayer(
ORCv1DeprecationAcknowledgement, ExecutionSession &ES,
ResourcesGetter GetResources,
NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor(),
NotifyFreedFtor NotifyFreed = NotifyFreedFtor())
: ES(ES), GetResources(std::move(GetResources)),
NotifyLoaded(std::move(NotifyLoaded)),
NotifyFinalized(std::move(NotifyFinalized)),
NotifyFreed(std::move(NotifyFreed)), ProcessAllSections(false) {}
/// Set the 'ProcessAllSections' flag.
///
/// If set to true, all sections in each object file will be allocated using
/// the memory manager, rather than just the sections required for execution.
///
/// This is kludgy, and may be removed in the future.
void setProcessAllSections(bool ProcessAllSections) {
this->ProcessAllSections = ProcessAllSections;
}
/// Add an object to the JIT.
Error addObject(VModuleKey K, ObjectPtr ObjBuffer) {
auto Obj =
object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef());
if (!Obj)
return Obj.takeError();
assert(!LinkedObjects.count(K) && "VModuleKey already in use");
auto R = GetResources(K);
LinkedObjects[K] = createLinkedObject(
*this, K, OwnedObject(std::move(*Obj), std::move(ObjBuffer)),
std::move(R.MemMgr), std::move(R.Resolver), ProcessAllSections);
return Error::success();
}
/// Remove the object associated with VModuleKey K.
///
/// All memory allocated for the object will be freed, and the sections and
/// symbols it provided will no longer be available. No attempt is made to
/// re-emit the missing symbols, and any use of these symbols (directly or
/// 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.
Error removeObject(VModuleKey K) {
assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
// How do we invalidate the symbols in H?
LinkedObjects.erase(K);
return Error::success();
}
/// Search for the given named symbol.
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it exists.
JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
for (auto &KV : LinkedObjects)
if (auto Sym = KV.second->getSymbol(Name, ExportedSymbolsOnly))
return Sym;
else if (auto Err = Sym.takeError())
return std::move(Err);
return nullptr;
}
/// Search for the given named symbol in the context of the loaded
/// object represented by the VModuleKey K.
/// @param K The VModuleKey for the object to search in.
/// @param Name The name of the symbol to search for.
/// @param ExportedSymbolsOnly If true, search only for exported symbols.
/// @return A handle for the given named symbol, if it is found in the
/// given object.
JITSymbol findSymbolIn(VModuleKey K, StringRef Name,
bool ExportedSymbolsOnly) {
assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
return LinkedObjects[K]->getSymbol(Name, ExportedSymbolsOnly);
}
/// Map section addresses for the object associated with the
/// VModuleKey K.
void mapSectionAddress(VModuleKey K, const void *LocalAddress,
JITTargetAddress TargetAddr) {
assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
LinkedObjects[K]->mapSectionAddress(LocalAddress, TargetAddr);
}
/// Immediately emit and finalize the object represented by the given
/// VModuleKey.
/// @param K VModuleKey for object to emit/finalize.
Error emitAndFinalize(VModuleKey K) {
assert(LinkedObjects.count(K) && "VModuleKey not associated with object");
return LinkedObjects[K]->finalize();
}
private:
ExecutionSession &ES;
ResourcesGetter GetResources;
NotifyLoadedFtor NotifyLoaded;
NotifyFinalizedFtor NotifyFinalized;
NotifyFreedFtor NotifyFreed;
// NB! `LinkedObjects` needs to be destroyed before `NotifyFreed` because
// `~ConcreteLinkedObject` calls `NotifyFreed`
std::map<VModuleKey, std::unique_ptr<LinkedObject>> LinkedObjects;
bool ProcessAllSections = false;
};
} // end namespace orc
} // end namespace llvm

View File

@ -1,564 +0,0 @@
//===------ RemoteObjectLayer.h - Forwards objs to a remote -----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Forwards objects to a remote object layer via RPC.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H
#define LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H
#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
#include "llvm/ExecutionEngine/Orc/OrcRemoteTargetRPCAPI.h"
#include "llvm/Object/ObjectFile.h"
#include <map>
namespace llvm {
namespace orc {
/// RPC API needed by RemoteObjectClientLayer and RemoteObjectServerLayer.
class RemoteObjectLayerAPI {
public:
using ObjHandleT = remote::ResourceIdMgr::ResourceId;
protected:
using RemoteSymbolId = remote::ResourceIdMgr::ResourceId;
using RemoteSymbol = std::pair<RemoteSymbolId, JITSymbolFlags>;
public:
using BadSymbolHandleError = remote::ResourceNotFound<RemoteSymbolId>;
using BadObjectHandleError = remote::ResourceNotFound<ObjHandleT>;
protected:
static const ObjHandleT InvalidObjectHandleId = 0;
static const RemoteSymbolId NullSymbolId = 0;
class AddObject
: public rpc::Function<AddObject, Expected<ObjHandleT>(std::string)> {
public:
static const char *getName() { return "AddObject"; }
};
class RemoveObject
: public rpc::Function<RemoveObject, Error(ObjHandleT)> {
public:
static const char *getName() { return "RemoveObject"; }
};
class FindSymbol
: public rpc::Function<FindSymbol, Expected<RemoteSymbol>(std::string,
bool)> {
public:
static const char *getName() { return "FindSymbol"; }
};
class FindSymbolIn
: public rpc::Function<FindSymbolIn,
Expected<RemoteSymbol>(ObjHandleT, std::string,
bool)> {
public:
static const char *getName() { return "FindSymbolIn"; }
};
class EmitAndFinalize
: public rpc::Function<EmitAndFinalize,
Error(ObjHandleT)> {
public:
static const char *getName() { return "EmitAndFinalize"; }
};
class Lookup
: public rpc::Function<Lookup,
Expected<RemoteSymbol>(ObjHandleT, std::string)> {
public:
static const char *getName() { return "Lookup"; }
};
class LookupInLogicalDylib
: public rpc::Function<LookupInLogicalDylib,
Expected<RemoteSymbol>(ObjHandleT, std::string)> {
public:
static const char *getName() { return "LookupInLogicalDylib"; }
};
class ReleaseRemoteSymbol
: public rpc::Function<ReleaseRemoteSymbol, Error(RemoteSymbolId)> {
public:
static const char *getName() { return "ReleaseRemoteSymbol"; }
};
class MaterializeRemoteSymbol
: public rpc::Function<MaterializeRemoteSymbol,
Expected<JITTargetAddress>(RemoteSymbolId)> {
public:
static const char *getName() { return "MaterializeRemoteSymbol"; }
};
};
/// Base class containing common utilities for RemoteObjectClientLayer and
/// RemoteObjectServerLayer.
template <typename RPCEndpoint>
class RemoteObjectLayer : public RemoteObjectLayerAPI {
public:
RemoteObjectLayer(RPCEndpoint &Remote,
std::function<void(Error)> ReportError)
: Remote(Remote), ReportError(std::move(ReportError)),
SymbolIdMgr(NullSymbolId + 1) {
using ThisT = RemoteObjectLayer<RPCEndpoint>;
Remote.template addHandler<ReleaseRemoteSymbol>(
*this, &ThisT::handleReleaseRemoteSymbol);
Remote.template addHandler<MaterializeRemoteSymbol>(
*this, &ThisT::handleMaterializeRemoteSymbol);
}
protected:
/// This class is used as the symbol materializer for JITSymbols returned by
/// RemoteObjectLayerClient/RemoteObjectLayerServer -- the materializer knows
/// how to call back to the other RPC endpoint to get the address when
/// requested.
class RemoteSymbolMaterializer {
public:
/// Construct a RemoteSymbolMaterializer for the given RemoteObjectLayer
/// with the given Id.
RemoteSymbolMaterializer(RemoteObjectLayer &C,
RemoteSymbolId Id)
: C(C), Id(Id) {}
RemoteSymbolMaterializer(RemoteSymbolMaterializer &&Other)
: C(Other.C), Id(Other.Id) {
Other.Id = 0;
}
RemoteSymbolMaterializer &operator=(RemoteSymbolMaterializer &&) = delete;
/// Release the remote symbol.
~RemoteSymbolMaterializer() {
if (Id)
C.releaseRemoteSymbol(Id);
}
/// Materialize the symbol on the remote and get its address.
Expected<JITTargetAddress> materialize() {
auto Addr = C.materializeRemoteSymbol(Id);
Id = 0;
return Addr;
}
private:
RemoteObjectLayer &C;
RemoteSymbolId Id;
};
/// Convenience function for getting a null remote symbol value.
RemoteSymbol nullRemoteSymbol() {
return RemoteSymbol(0, JITSymbolFlags());
}
/// Creates a StringError that contains a copy of Err's log message, then
/// sends that StringError to ReportError.
///
/// This allows us to locally log error messages for errors that will actually
/// be delivered to the remote.
Error teeLog(Error Err) {
return handleErrors(std::move(Err),
[this](std::unique_ptr<ErrorInfoBase> EIB) {
ReportError(make_error<StringError>(
EIB->message(),
EIB->convertToErrorCode()));
return Error(std::move(EIB));
});
}
Error badRemoteSymbolIdError(RemoteSymbolId Id) {
return make_error<BadSymbolHandleError>(Id, "Remote JIT Symbol");
}
Error badObjectHandleError(ObjHandleT H) {
return make_error<RemoteObjectLayerAPI::BadObjectHandleError>(
H, "Bad object handle");
}
/// Create a RemoteSymbol wrapping the given JITSymbol.
Expected<RemoteSymbol> jitSymbolToRemote(JITSymbol Sym) {
if (Sym) {
auto Id = SymbolIdMgr.getNext();
auto Flags = Sym.getFlags();
assert(!InUseSymbols.count(Id) && "Symbol id already in use");
InUseSymbols.insert(std::make_pair(Id, std::move(Sym)));
return RemoteSymbol(Id, Flags);
} else if (auto Err = Sym.takeError())
return teeLog(std::move(Err));
// else...
return nullRemoteSymbol();
}
/// Convert an Expected<RemoteSymbol> to a JITSymbol.
JITSymbol remoteToJITSymbol(Expected<RemoteSymbol> RemoteSymOrErr) {
if (RemoteSymOrErr) {
auto &RemoteSym = *RemoteSymOrErr;
if (RemoteSym == nullRemoteSymbol())
return nullptr;
// else...
RemoteSymbolMaterializer RSM(*this, RemoteSym.first);
auto Sym = JITSymbol(
[RSM = std::move(RSM)]() mutable { return RSM.materialize(); },
RemoteSym.second);
return Sym;
} else
return RemoteSymOrErr.takeError();
}
RPCEndpoint &Remote;
std::function<void(Error)> ReportError;
private:
/// Notify the remote to release the given JITSymbol.
void releaseRemoteSymbol(RemoteSymbolId Id) {
if (auto Err = Remote.template callB<ReleaseRemoteSymbol>(Id))
ReportError(std::move(Err));
}
/// Notify the remote to materialize the JITSymbol with the given Id and
/// return its address.
Expected<JITTargetAddress> materializeRemoteSymbol(RemoteSymbolId Id) {
return Remote.template callB<MaterializeRemoteSymbol>(Id);
}
/// Release the JITSymbol with the given Id.
Error handleReleaseRemoteSymbol(RemoteSymbolId Id) {
auto SI = InUseSymbols.find(Id);
if (SI != InUseSymbols.end()) {
InUseSymbols.erase(SI);
return Error::success();
} else
return teeLog(badRemoteSymbolIdError(Id));
}
/// Run the materializer for the JITSymbol with the given Id and return its
/// address.
Expected<JITTargetAddress> handleMaterializeRemoteSymbol(RemoteSymbolId Id) {
auto SI = InUseSymbols.find(Id);
if (SI != InUseSymbols.end()) {
auto AddrOrErr = SI->second.getAddress();
InUseSymbols.erase(SI);
SymbolIdMgr.release(Id);
if (AddrOrErr)
return *AddrOrErr;
else
return teeLog(AddrOrErr.takeError());
} else {
return teeLog(badRemoteSymbolIdError(Id));
}
}
remote::ResourceIdMgr SymbolIdMgr;
std::map<RemoteSymbolId, JITSymbol> InUseSymbols;
};
/// RemoteObjectClientLayer forwards the ORC Object Layer API over an RPC
/// connection.
///
/// This class can be used as the base layer of a JIT stack on the client and
/// will forward operations to a corresponding RemoteObjectServerLayer on the
/// server (which can be composed on top of a "real" object layer like
/// RTDyldObjectLinkingLayer to actually carry out the operations).
///
/// Sending relocatable objects to the server (rather than fully relocated
/// bits) allows JIT'd code to be cached on the server side and re-used in
/// subsequent JIT sessions.
template <typename RPCEndpoint>
class RemoteObjectClientLayer : public RemoteObjectLayer<RPCEndpoint> {
private:
using AddObject = RemoteObjectLayerAPI::AddObject;
using RemoveObject = RemoteObjectLayerAPI::RemoveObject;
using FindSymbol = RemoteObjectLayerAPI::FindSymbol;
using FindSymbolIn = RemoteObjectLayerAPI::FindSymbolIn;
using EmitAndFinalize = RemoteObjectLayerAPI::EmitAndFinalize;
using Lookup = RemoteObjectLayerAPI::Lookup;
using LookupInLogicalDylib = RemoteObjectLayerAPI::LookupInLogicalDylib;
using RemoteObjectLayer<RPCEndpoint>::teeLog;
using RemoteObjectLayer<RPCEndpoint>::badObjectHandleError;
using RemoteObjectLayer<RPCEndpoint>::remoteToJITSymbol;
public:
using ObjHandleT = RemoteObjectLayerAPI::ObjHandleT;
using RemoteSymbol = RemoteObjectLayerAPI::RemoteSymbol;
using ObjectPtr = std::unique_ptr<MemoryBuffer>;
/// Create a RemoteObjectClientLayer that communicates with a
/// RemoteObjectServerLayer instance via the given RPCEndpoint.
///
/// The ReportError functor can be used locally log errors that are intended
/// to be sent sent
LLVM_ATTRIBUTE_DEPRECATED(
RemoteObjectClientLayer(RPCEndpoint &Remote,
std::function<void(Error)> ReportError),
"ORCv1 layers (including RemoteObjectClientLayer) are deprecated. Please "
"use "
"ORCv2 (see docs/ORCv2.rst)");
RemoteObjectClientLayer(ORCv1DeprecationAcknowledgement, RPCEndpoint &Remote,
std::function<void(Error)> ReportError)
: RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)) {
using ThisT = RemoteObjectClientLayer<RPCEndpoint>;
Remote.template addHandler<Lookup>(*this, &ThisT::lookup);
Remote.template addHandler<LookupInLogicalDylib>(
*this, &ThisT::lookupInLogicalDylib);
}
/// Add an object to the JIT.
///
/// @return A handle that can be used to refer to the loaded object (for
/// symbol searching, finalization, freeing memory, etc.).
Expected<ObjHandleT>
addObject(ObjectPtr ObjBuffer,
std::shared_ptr<LegacyJITSymbolResolver> Resolver) {
if (auto HandleOrErr =
this->Remote.template callB<AddObject>(ObjBuffer->getBuffer())) {
auto &Handle = *HandleOrErr;
// FIXME: Return an error for this:
assert(!Resolvers.count(Handle) && "Handle already in use?");
Resolvers[Handle] = std::move(Resolver);
return Handle;
} else
return HandleOrErr.takeError();
}
/// Remove the given object from the JIT.
Error removeObject(ObjHandleT H) {
return this->Remote.template callB<RemoveObject>(H);
}
/// Search for the given named symbol.
JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
return remoteToJITSymbol(
this->Remote.template callB<FindSymbol>(Name,
ExportedSymbolsOnly));
}
/// Search for the given named symbol within the given context.
JITSymbol findSymbolIn(ObjHandleT H, StringRef Name, bool ExportedSymbolsOnly) {
return remoteToJITSymbol(
this->Remote.template callB<FindSymbolIn>(H, Name,
ExportedSymbolsOnly));
}
/// Immediately emit and finalize the object with the given handle.
Error emitAndFinalize(ObjHandleT H) {
return this->Remote.template callB<EmitAndFinalize>(H);
}
private:
Expected<RemoteSymbol> lookup(ObjHandleT H, const std::string &Name) {
auto RI = Resolvers.find(H);
if (RI != Resolvers.end()) {
return this->jitSymbolToRemote(RI->second->findSymbol(Name));
} else
return teeLog(badObjectHandleError(H));
}
Expected<RemoteSymbol> lookupInLogicalDylib(ObjHandleT H,
const std::string &Name) {
auto RI = Resolvers.find(H);
if (RI != Resolvers.end())
return this->jitSymbolToRemote(
RI->second->findSymbolInLogicalDylib(Name));
else
return teeLog(badObjectHandleError(H));
}
std::map<remote::ResourceIdMgr::ResourceId,
std::shared_ptr<LegacyJITSymbolResolver>>
Resolvers;
};
/// RemoteObjectServerLayer acts as a server and handling RPC calls for the
/// object layer API from the given RPC connection.
///
/// This class can be composed on top of a 'real' object layer (e.g.
/// RTDyldObjectLinkingLayer) to do the actual work of relocating objects
/// and making them executable.
template <typename BaseLayerT, typename RPCEndpoint>
class RemoteObjectServerLayer : public RemoteObjectLayer<RPCEndpoint> {
private:
using ObjHandleT = RemoteObjectLayerAPI::ObjHandleT;
using RemoteSymbol = RemoteObjectLayerAPI::RemoteSymbol;
using AddObject = RemoteObjectLayerAPI::AddObject;
using RemoveObject = RemoteObjectLayerAPI::RemoveObject;
using FindSymbol = RemoteObjectLayerAPI::FindSymbol;
using FindSymbolIn = RemoteObjectLayerAPI::FindSymbolIn;
using EmitAndFinalize = RemoteObjectLayerAPI::EmitAndFinalize;
using Lookup = RemoteObjectLayerAPI::Lookup;
using LookupInLogicalDylib = RemoteObjectLayerAPI::LookupInLogicalDylib;
using RemoteObjectLayer<RPCEndpoint>::teeLog;
using RemoteObjectLayer<RPCEndpoint>::badObjectHandleError;
using RemoteObjectLayer<RPCEndpoint>::remoteToJITSymbol;
public:
/// Create a RemoteObjectServerLayer with the given base layer (which must be
/// an object layer), RPC endpoint, and error reporter function.
LLVM_ATTRIBUTE_DEPRECATED(
RemoteObjectServerLayer(BaseLayerT &BaseLayer, RPCEndpoint &Remote,
std::function<void(Error)> ReportError),
"ORCv1 layers (including RemoteObjectServerLayer) are deprecated. Please "
"use "
"ORCv2 (see docs/ORCv2.rst)");
RemoteObjectServerLayer(ORCv1DeprecationAcknowledgement,
BaseLayerT &BaseLayer, RPCEndpoint &Remote,
std::function<void(Error)> ReportError)
: RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)),
BaseLayer(BaseLayer), HandleIdMgr(1) {
using ThisT = RemoteObjectServerLayer<BaseLayerT, RPCEndpoint>;
Remote.template addHandler<AddObject>(*this, &ThisT::addObject);
Remote.template addHandler<RemoveObject>(*this, &ThisT::removeObject);
Remote.template addHandler<FindSymbol>(*this, &ThisT::findSymbol);
Remote.template addHandler<FindSymbolIn>(*this, &ThisT::findSymbolIn);
Remote.template addHandler<EmitAndFinalize>(*this, &ThisT::emitAndFinalize);
}
private:
class StringMemoryBuffer : public MemoryBuffer {
public:
StringMemoryBuffer(std::string Buffer)
: Buffer(std::move(Buffer)) {
init(this->Buffer.data(), this->Buffer.data() + this->Buffer.size(),
false);
}
BufferKind getBufferKind() const override { return MemoryBuffer_Malloc; }
private:
std::string Buffer;
};
JITSymbol lookup(ObjHandleT Id, const std::string &Name) {
return remoteToJITSymbol(
this->Remote.template callB<Lookup>(Id, Name));
}
JITSymbol lookupInLogicalDylib(ObjHandleT Id, const std::string &Name) {
return remoteToJITSymbol(
this->Remote.template callB<LookupInLogicalDylib>(Id, Name));
}
Expected<ObjHandleT> addObject(std::string ObjBuffer) {
auto Buffer = std::make_unique<StringMemoryBuffer>(std::move(ObjBuffer));
auto Id = HandleIdMgr.getNext();
assert(!BaseLayerHandles.count(Id) && "Id already in use?");
auto Resolver = createLambdaResolver(
AcknowledgeORCv1Deprecation,
[this, Id](const std::string &Name) { return lookup(Id, Name); },
[this, Id](const std::string &Name) {
return lookupInLogicalDylib(Id, Name);
});
if (auto HandleOrErr =
BaseLayer.addObject(std::move(Buffer), std::move(Resolver))) {
BaseLayerHandles[Id] = std::move(*HandleOrErr);
return Id;
} else
return teeLog(HandleOrErr.takeError());
}
Error removeObject(ObjHandleT H) {
auto HI = BaseLayerHandles.find(H);
if (HI != BaseLayerHandles.end()) {
if (auto Err = BaseLayer.removeObject(HI->second))
return teeLog(std::move(Err));
return Error::success();
} else
return teeLog(badObjectHandleError(H));
}
Expected<RemoteSymbol> findSymbol(const std::string &Name,
bool ExportedSymbolsOnly) {
if (auto Sym = BaseLayer.findSymbol(Name, ExportedSymbolsOnly))
return this->jitSymbolToRemote(std::move(Sym));
else if (auto Err = Sym.takeError())
return teeLog(std::move(Err));
return this->nullRemoteSymbol();
}
Expected<RemoteSymbol> findSymbolIn(ObjHandleT H, const std::string &Name,
bool ExportedSymbolsOnly) {
auto HI = BaseLayerHandles.find(H);
if (HI != BaseLayerHandles.end()) {
if (auto Sym = BaseLayer.findSymbolIn(HI->second, Name, ExportedSymbolsOnly))
return this->jitSymbolToRemote(std::move(Sym));
else if (auto Err = Sym.takeError())
return teeLog(std::move(Err));
return this->nullRemoteSymbol();
} else
return teeLog(badObjectHandleError(H));
}
Error emitAndFinalize(ObjHandleT H) {
auto HI = BaseLayerHandles.find(H);
if (HI != BaseLayerHandles.end()) {
if (auto Err = BaseLayer.emitAndFinalize(HI->second))
return teeLog(std::move(Err));
return Error::success();
} else
return teeLog(badObjectHandleError(H));
}
BaseLayerT &BaseLayer;
remote::ResourceIdMgr HandleIdMgr;
std::map<ObjHandleT, typename BaseLayerT::ObjHandleT> BaseLayerHandles;
};
template <typename RPCEndpoint>
RemoteObjectClientLayer<RPCEndpoint>::RemoteObjectClientLayer(
RPCEndpoint &Remote, std::function<void(Error)> ReportError)
: RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)) {
using ThisT = RemoteObjectClientLayer<RPCEndpoint>;
Remote.template addHandler<Lookup>(*this, &ThisT::lookup);
Remote.template addHandler<LookupInLogicalDylib>(
*this, &ThisT::lookupInLogicalDylib);
}
template <typename BaseLayerT, typename RPCEndpoint>
RemoteObjectServerLayer<BaseLayerT, RPCEndpoint>::RemoteObjectServerLayer(
BaseLayerT &BaseLayer, RPCEndpoint &Remote,
std::function<void(Error)> ReportError)
: RemoteObjectLayer<RPCEndpoint>(Remote, std::move(ReportError)),
BaseLayer(BaseLayer), HandleIdMgr(1) {
using ThisT = RemoteObjectServerLayer<BaseLayerT, RPCEndpoint>;
Remote.template addHandler<AddObject>(*this, &ThisT::addObject);
Remote.template addHandler<RemoveObject>(*this, &ThisT::removeObject);
Remote.template addHandler<FindSymbol>(*this, &ThisT::findSymbol);
Remote.template addHandler<FindSymbolIn>(*this, &ThisT::findSymbolIn);
Remote.template addHandler<EmitAndFinalize>(*this, &ThisT::emitAndFinalize);
}
} // end namespace orc
} // end namespace llvm
#endif // LLVM_EXECUTIONENGINE_ORC_REMOTEOBJECTLAYER_H

View File

@ -53,11 +53,6 @@ ExecutionEngine *(*ExecutionEngine::MCJITCtor)(
std::shared_ptr<LegacyJITSymbolResolver> Resolver,
std::unique_ptr<TargetMachine> TM) = nullptr;
ExecutionEngine *(*ExecutionEngine::OrcMCJITReplacementCtor)(
std::string *ErrorStr, std::shared_ptr<MCJITMemoryManager> MemMgr,
std::shared_ptr<LegacyJITSymbolResolver> Resolver,
std::unique_ptr<TargetMachine> TM) = nullptr;
ExecutionEngine *(*ExecutionEngine::InterpCtor)(std::unique_ptr<Module> M,
std::string *ErrorStr) =nullptr;
@ -476,8 +471,7 @@ EngineBuilder::EngineBuilder() : EngineBuilder(nullptr) {}
EngineBuilder::EngineBuilder(std::unique_ptr<Module> M)
: M(std::move(M)), WhichEngine(EngineKind::Either), ErrorStr(nullptr),
OptLevel(CodeGenOpt::Default), MemMgr(nullptr), Resolver(nullptr),
UseOrcMCJITReplacement(false) {
OptLevel(CodeGenOpt::Default), MemMgr(nullptr), Resolver(nullptr) {
// IR module verification is enabled by default in debug builds, and disabled
// by default in release builds.
#ifndef NDEBUG
@ -540,12 +534,7 @@ ExecutionEngine *EngineBuilder::create(TargetMachine *TM) {
}
ExecutionEngine *EE = nullptr;
if (ExecutionEngine::OrcMCJITReplacementCtor && UseOrcMCJITReplacement) {
EE = ExecutionEngine::OrcMCJITReplacementCtor(ErrorStr, std::move(MemMgr),
std::move(Resolver),
std::move(TheTM));
EE->addModule(std::move(M));
} else if (ExecutionEngine::MCJITCtor)
if (ExecutionEngine::MCJITCtor)
EE = ExecutionEngine::MCJITCtor(std::move(M), ErrorStr, std::move(MemMgr),
std::move(Resolver), std::move(TheTM));

View File

@ -9,18 +9,14 @@ add_llvm_component_library(LLVMOrcJIT
IRTransformLayer.cpp
JITTargetMachineBuilder.cpp
LazyReexports.cpp
Legacy.cpp
Layer.cpp
LLJIT.cpp
MachOPlatform.cpp
Mangling.cpp
NullResolver.cpp
ObjectLinkingLayer.cpp
ObjectTransformLayer.cpp
OrcABISupport.cpp
OrcCBindings.cpp
OrcV2CBindings.cpp
OrcMCJITReplacement.cpp
RTDyldObjectLinkingLayer.cpp
Speculation.cpp
SpeculateAnalyses.cpp

View File

@ -137,8 +137,6 @@ void AsynchronousSymbolQuery::handleComplete() {
TmpNotifyComplete(std::move(ResolvedSymbols));
}
bool AsynchronousSymbolQuery::canStillFail() { return !!NotifyComplete; }
void AsynchronousSymbolQuery::handleFailed(Error Err) {
assert(QueryRegistrations.empty() && ResolvedSymbols.empty() &&
OutstandingSymbolsCount == 0 &&
@ -1406,132 +1404,6 @@ Error JITDylib::lodgeQueryImpl(MaterializationUnitList &MUs,
});
}
Expected<SymbolNameSet>
JITDylib::legacyLookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
SymbolNameSet Names) {
assert(Q && "Query can not be null");
ES.runOutstandingMUs();
bool QueryComplete = false;
std::vector<std::unique_ptr<MaterializationUnit>> MUs;
SymbolLookupSet Unresolved(Names);
auto Err = ES.runSessionLocked([&, this]() -> Error {
QueryComplete = lookupImpl(Q, MUs, Unresolved);
// Run any definition generators.
for (auto &DG : DefGenerators) {
// Bail out early if we have resolved everything.
if (Unresolved.empty())
break;
assert(!QueryComplete && "query complete but unresolved symbols remain?");
if (auto Err = DG->tryToGenerate(LookupKind::Static, *this,
JITDylibLookupFlags::MatchAllSymbols,
Unresolved))
return Err;
if (!Unresolved.empty())
QueryComplete = lookupImpl(Q, MUs, Unresolved);
}
return Error::success();
});
if (Err)
return std::move(Err);
assert((MUs.empty() || !QueryComplete) &&
"If action flags are set, there should be no work to do (so no MUs)");
if (QueryComplete)
Q->handleComplete();
// FIXME: Swap back to the old code below once RuntimeDyld works with
// callbacks from asynchronous queries.
// Add MUs to the OutstandingMUs list.
{
std::lock_guard<std::recursive_mutex> Lock(ES.OutstandingMUsMutex);
auto ThisJD = shared_from_this();
for (auto &MU : MUs) {
auto MR = MU->createMaterializationResponsibility(ThisJD);
ES.OutstandingMUs.push_back(make_pair(std::move(MU), std::move(MR)));
}
}
ES.runOutstandingMUs();
// Dispatch any required MaterializationUnits for materialization.
// for (auto &MU : MUs)
// ES.dispatchMaterialization(*this, std::move(MU));
SymbolNameSet RemainingSymbols;
for (auto &KV : Unresolved)
RemainingSymbols.insert(KV.first);
return RemainingSymbols;
}
bool JITDylib::lookupImpl(
std::shared_ptr<AsynchronousSymbolQuery> &Q,
std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
SymbolLookupSet &Unresolved) {
bool QueryComplete = false;
std::vector<SymbolStringPtr> ToRemove;
Unresolved.forEachWithRemoval(
[&](const SymbolStringPtr &Name, SymbolLookupFlags Flags) -> bool {
// Search for the name in Symbols. Skip without removing if not found.
auto SymI = Symbols.find(Name);
if (SymI == Symbols.end())
return false;
// If the symbol is already in the required state then notify the query
// and remove.
if (SymI->second.getState() >= Q->getRequiredState()) {
Q->notifySymbolMetRequiredState(Name, SymI->second.getSymbol());
if (Q->isComplete())
QueryComplete = true;
return true;
}
// If the symbol is lazy, get the MaterialiaztionUnit for it.
if (SymI->second.hasMaterializerAttached()) {
assert(SymI->second.getAddress() == 0 &&
"Lazy symbol should not have a resolved address");
auto UMII = UnmaterializedInfos.find(Name);
assert(UMII != UnmaterializedInfos.end() &&
"Lazy symbol should have UnmaterializedInfo");
auto MU = std::move(UMII->second->MU);
assert(MU != nullptr && "Materializer should not be null");
// Kick all symbols associated with this MaterializationUnit into
// materializing state.
for (auto &KV : MU->getSymbols()) {
auto SymK = Symbols.find(KV.first);
assert(SymK != Symbols.end() && "Missing symbol table entry");
SymK->second.setState(SymbolState::Materializing);
SymK->second.setMaterializerAttached(false);
UnmaterializedInfos.erase(KV.first);
}
// Add MU to the list of MaterializationUnits to be materialized.
MUs.push_back(std::move(MU));
}
// Add the query to the PendingQueries list.
assert(SymI->second.getState() != SymbolState::NeverSearched &&
SymI->second.getState() != SymbolState::Ready &&
"By this line the symbol should be materializing");
auto &MI = MaterializingInfos[Name];
MI.addQuery(Q);
Q->addQueryDependence(*this, Name);
return true;
});
return QueryComplete;
}
void JITDylib::dump(raw_ostream &OS) {
ES.runSessionLocked([&, this]() {
OS << "JITDylib \"" << JITDylibName << "\" (ES: "
@ -1804,88 +1676,6 @@ Expected<JITDylib &> ExecutionSession::createJITDylib(std::string Name) {
return JD;
}
void ExecutionSession::legacyFailQuery(AsynchronousSymbolQuery &Q, Error Err) {
assert(!!Err && "Error should be in failure state");
bool SendErrorToQuery;
runSessionLocked([&]() {
Q.detach();
SendErrorToQuery = Q.canStillFail();
});
if (SendErrorToQuery)
Q.handleFailed(std::move(Err));
else
reportError(std::move(Err));
}
Expected<SymbolMap> ExecutionSession::legacyLookup(
LegacyAsyncLookupFunction AsyncLookup, SymbolNameSet Names,
SymbolState RequiredState,
RegisterDependenciesFunction RegisterDependencies) {
#if LLVM_ENABLE_THREADS
// In the threaded case we use promises to return the results.
std::promise<SymbolMap> PromisedResult;
Error ResolutionError = Error::success();
auto NotifyComplete = [&](Expected<SymbolMap> R) {
if (R)
PromisedResult.set_value(std::move(*R));
else {
ErrorAsOutParameter _(&ResolutionError);
ResolutionError = R.takeError();
PromisedResult.set_value(SymbolMap());
}
};
#else
SymbolMap Result;
Error ResolutionError = Error::success();
auto NotifyComplete = [&](Expected<SymbolMap> R) {
ErrorAsOutParameter _(&ResolutionError);
if (R)
Result = std::move(*R);
else
ResolutionError = R.takeError();
};
#endif
auto Query = std::make_shared<AsynchronousSymbolQuery>(
SymbolLookupSet(Names), RequiredState, std::move(NotifyComplete));
// FIXME: This should be run session locked along with the registration code
// and error reporting below.
SymbolNameSet UnresolvedSymbols = AsyncLookup(Query, std::move(Names));
// If the query was lodged successfully then register the dependencies,
// otherwise fail it with an error.
if (UnresolvedSymbols.empty())
RegisterDependencies(Query->QueryRegistrations);
else {
bool DeliverError = runSessionLocked([&]() {
Query->detach();
return Query->canStillFail();
});
auto Err = make_error<SymbolsNotFound>(std::move(UnresolvedSymbols));
if (DeliverError)
Query->handleFailed(std::move(Err));
else
reportError(std::move(Err));
}
#if LLVM_ENABLE_THREADS
auto ResultFuture = PromisedResult.get_future();
auto Result = ResultFuture.get();
if (ResolutionError)
return std::move(ResolutionError);
return std::move(Result);
#else
if (ResolutionError)
return std::move(ResolutionError);
return Result;
#endif
}
std::vector<std::shared_ptr<JITDylib>>
JITDylib::getDFSLinkOrder(ArrayRef<std::shared_ptr<JITDylib>> JDs) {
if (JDs.empty())

View File

@ -1,68 +0,0 @@
//===------- Legacy.cpp - Adapters for ExecutionEngine API interop --------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/Legacy.h"
namespace llvm {
namespace orc {
void SymbolResolver::anchor() {}
JITSymbolResolverAdapter::JITSymbolResolverAdapter(
ExecutionSession &ES, SymbolResolver &R, MaterializationResponsibility *MR)
: ES(ES), R(R), MR(MR) {}
void JITSymbolResolverAdapter::lookup(const LookupSet &Symbols,
OnResolvedFunction OnResolved) {
SymbolNameSet InternedSymbols;
for (auto &S : Symbols)
InternedSymbols.insert(ES.intern(S));
auto OnResolvedWithUnwrap = [OnResolved = std::move(OnResolved)](
Expected<SymbolMap> InternedResult) mutable {
if (!InternedResult) {
OnResolved(InternedResult.takeError());
return;
}
LookupResult Result;
for (auto &KV : *InternedResult)
Result[*KV.first] = std::move(KV.second);
OnResolved(Result);
};
auto Q = std::make_shared<AsynchronousSymbolQuery>(
SymbolLookupSet(InternedSymbols), SymbolState::Resolved,
std::move(OnResolvedWithUnwrap));
auto Unresolved = R.lookup(Q, InternedSymbols);
if (Unresolved.empty()) {
if (MR)
MR->addDependenciesForAll(Q->QueryRegistrations);
} else
ES.legacyFailQuery(*Q, make_error<SymbolsNotFound>(std::move(Unresolved)));
}
Expected<JITSymbolResolverAdapter::LookupSet>
JITSymbolResolverAdapter::getResponsibilitySet(const LookupSet &Symbols) {
SymbolNameSet InternedSymbols;
for (auto &S : Symbols)
InternedSymbols.insert(ES.intern(S));
auto InternedResult = R.getResponsibilitySet(InternedSymbols);
LookupSet Result;
for (auto &S : InternedResult) {
ResolvedStrings.insert(S);
Result.insert(*S);
}
return Result;
}
} // End namespace orc.
} // End namespace llvm.

View File

@ -1,37 +0,0 @@
//===---------- NullResolver.cpp - Reject symbol lookup requests ----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/NullResolver.h"
#include "llvm/Support/ErrorHandling.h"
namespace llvm {
namespace orc {
SymbolNameSet NullResolver::getResponsibilitySet(const SymbolNameSet &Symbols) {
return Symbols;
}
SymbolNameSet
NullResolver::lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
SymbolNameSet Symbols) {
assert(Symbols.empty() && "Null resolver: Symbols must be empty");
return Symbols;
}
JITSymbol NullLegacyResolver::findSymbol(const std::string &Name) {
llvm_unreachable("Unexpected cross-object symbol reference");
}
JITSymbol
NullLegacyResolver::findSymbolInLogicalDylib(const std::string &Name) {
llvm_unreachable("Unexpected cross-object symbol reference");
}
} // End namespace orc.
} // End namespace llvm.

View File

@ -1,158 +0,0 @@
//===----------- OrcCBindings.cpp - C bindings for the Orc APIs -----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "OrcCBindingsStack.h"
#include "llvm-c/OrcBindings.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
using namespace llvm;
LLVMOrcJITStackRef LLVMOrcCreateInstance(LLVMTargetMachineRef TM) {
TargetMachine *TM2(unwrap(TM));
Triple T(TM2->getTargetTriple());
auto IndirectStubsMgrBuilder =
orc::createLocalIndirectStubsManagerBuilder(T);
OrcCBindingsStack *JITStack =
new OrcCBindingsStack(*TM2, std::move(IndirectStubsMgrBuilder));
return wrap(JITStack);
}
const char *LLVMOrcGetErrorMsg(LLVMOrcJITStackRef JITStack) {
OrcCBindingsStack &J = *unwrap(JITStack);
return J.getErrorMessage().c_str();
}
void LLVMOrcGetMangledSymbol(LLVMOrcJITStackRef JITStack, char **MangledName,
const char *SymbolName) {
OrcCBindingsStack &J = *unwrap(JITStack);
std::string Mangled = J.mangle(SymbolName);
*MangledName = new char[Mangled.size() + 1];
strcpy(*MangledName, Mangled.c_str());
}
void LLVMOrcDisposeMangledSymbol(char *MangledName) { delete[] MangledName; }
LLVMErrorRef LLVMOrcCreateLazyCompileCallback(
LLVMOrcJITStackRef JITStack, LLVMOrcTargetAddress *RetAddr,
LLVMOrcLazyCompileCallbackFn Callback, void *CallbackCtx) {
OrcCBindingsStack &J = *unwrap(JITStack);
if (auto Addr = J.createLazyCompileCallback(Callback, CallbackCtx)) {
*RetAddr = *Addr;
return LLVMErrorSuccess;
} else
return wrap(Addr.takeError());
}
LLVMErrorRef LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack,
const char *StubName,
LLVMOrcTargetAddress InitAddr) {
OrcCBindingsStack &J = *unwrap(JITStack);
return wrap(J.createIndirectStub(StubName, InitAddr));
}
LLVMErrorRef LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack,
const char *StubName,
LLVMOrcTargetAddress NewAddr) {
OrcCBindingsStack &J = *unwrap(JITStack);
return wrap(J.setIndirectStubPointer(StubName, NewAddr));
}
LLVMErrorRef LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle,
LLVMModuleRef Mod,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx) {
OrcCBindingsStack &J = *unwrap(JITStack);
std::unique_ptr<Module> M(unwrap(Mod));
if (auto Handle =
J.addIRModuleEager(std::move(M), SymbolResolver, SymbolResolverCtx)) {
*RetHandle = *Handle;
return LLVMErrorSuccess;
} else
return wrap(Handle.takeError());
}
LLVMErrorRef LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle,
LLVMModuleRef Mod,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx) {
OrcCBindingsStack &J = *unwrap(JITStack);
std::unique_ptr<Module> M(unwrap(Mod));
if (auto Handle =
J.addIRModuleLazy(std::move(M), SymbolResolver, SymbolResolverCtx)) {
*RetHandle = *Handle;
return LLVMErrorSuccess;
} else
return wrap(Handle.takeError());
}
LLVMErrorRef LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle *RetHandle,
LLVMMemoryBufferRef Obj,
LLVMOrcSymbolResolverFn SymbolResolver,
void *SymbolResolverCtx) {
OrcCBindingsStack &J = *unwrap(JITStack);
std::unique_ptr<MemoryBuffer> O(unwrap(Obj));
if (auto Handle =
J.addObject(std::move(O), SymbolResolver, SymbolResolverCtx)) {
*RetHandle = *Handle;
return LLVMErrorSuccess;
} else
return wrap(Handle.takeError());
}
LLVMErrorRef LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack,
LLVMOrcModuleHandle H) {
OrcCBindingsStack &J = *unwrap(JITStack);
return wrap(J.removeModule(H));
}
LLVMErrorRef LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack,
LLVMOrcTargetAddress *RetAddr,
const char *SymbolName) {
OrcCBindingsStack &J = *unwrap(JITStack);
if (auto Addr = J.findSymbolAddress(SymbolName, true)) {
*RetAddr = *Addr;
return LLVMErrorSuccess;
} else
return wrap(Addr.takeError());
}
LLVMErrorRef LLVMOrcGetSymbolAddressIn(LLVMOrcJITStackRef JITStack,
LLVMOrcTargetAddress *RetAddr,
LLVMOrcModuleHandle H,
const char *SymbolName) {
OrcCBindingsStack &J = *unwrap(JITStack);
if (auto Addr = J.findSymbolAddressIn(H, SymbolName, true)) {
*RetAddr = *Addr;
return LLVMErrorSuccess;
} else
return wrap(Addr.takeError());
}
LLVMErrorRef LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack) {
auto *J = unwrap(JITStack);
auto Err = J->shutdown();
delete J;
return wrap(std::move(Err));
}
void LLVMOrcRegisterJITEventListener(LLVMOrcJITStackRef JITStack, LLVMJITEventListenerRef L)
{
unwrap(JITStack)->RegisterJITEventListener(unwrap(L));
}
void LLVMOrcUnregisterJITEventListener(LLVMOrcJITStackRef JITStack, LLVMJITEventListenerRef L)
{
unwrap(JITStack)->UnregisterJITEventListener(unwrap(L));
}

View File

@ -1,534 +0,0 @@
//===- OrcCBindingsStack.h - Orc JIT stack for C bindings -----*- C++ -*---===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
#define LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
#include "llvm-c/OrcBindings.h"
#include "llvm-c/TargetMachine.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include <algorithm>
#include <cstdint>
#include <functional>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
namespace llvm {
class OrcCBindingsStack;
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcCBindingsStack, LLVMOrcJITStackRef)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
namespace detail {
// FIXME: Kill this off once the Layer concept becomes an interface.
class GenericLayer {
public:
virtual ~GenericLayer() = default;
virtual JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
bool ExportedSymbolsOnly) = 0;
virtual Error removeModule(orc::VModuleKey K) = 0;
};
template <typename LayerT> class GenericLayerImpl : public GenericLayer {
public:
GenericLayerImpl(LayerT &Layer) : Layer(Layer) {}
JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
bool ExportedSymbolsOnly) override {
return Layer.findSymbolIn(K, Name, ExportedSymbolsOnly);
}
Error removeModule(orc::VModuleKey K) override {
return Layer.removeModule(K);
}
private:
LayerT &Layer;
};
template <>
class GenericLayerImpl<orc::LegacyRTDyldObjectLinkingLayer> : public GenericLayer {
private:
using LayerT = orc::LegacyRTDyldObjectLinkingLayer;
public:
GenericLayerImpl(LayerT &Layer) : Layer(Layer) {}
JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
bool ExportedSymbolsOnly) override {
return Layer.findSymbolIn(K, Name, ExportedSymbolsOnly);
}
Error removeModule(orc::VModuleKey K) override {
return Layer.removeObject(K);
}
private:
LayerT &Layer;
};
template <typename LayerT>
std::unique_ptr<GenericLayerImpl<LayerT>> createGenericLayer(LayerT &Layer) {
return std::make_unique<GenericLayerImpl<LayerT>>(Layer);
}
} // end namespace detail
class OrcCBindingsStack {
public:
using CompileCallbackMgr = orc::JITCompileCallbackManager;
using ObjLayerT = orc::LegacyRTDyldObjectLinkingLayer;
using CompileLayerT = orc::LegacyIRCompileLayer<ObjLayerT, orc::SimpleCompiler>;
using CODLayerT =
orc::LegacyCompileOnDemandLayer<CompileLayerT, CompileCallbackMgr>;
using CallbackManagerBuilder =
std::function<std::unique_ptr<CompileCallbackMgr>()>;
using IndirectStubsManagerBuilder = CODLayerT::IndirectStubsManagerBuilderT;
private:
using OwningObject = object::OwningBinary<object::ObjectFile>;
class CBindingsResolver : public orc::SymbolResolver {
public:
CBindingsResolver(OrcCBindingsStack &Stack,
LLVMOrcSymbolResolverFn ExternalResolver,
void *ExternalResolverCtx)
: Stack(Stack), ExternalResolver(std::move(ExternalResolver)),
ExternalResolverCtx(std::move(ExternalResolverCtx)) {}
orc::SymbolNameSet
getResponsibilitySet(const orc::SymbolNameSet &Symbols) override {
orc::SymbolNameSet Result;
for (auto &S : Symbols) {
if (auto Sym = findSymbol(std::string(*S))) {
if (!Sym.getFlags().isStrong())
Result.insert(S);
} else if (auto Err = Sym.takeError()) {
Stack.reportError(std::move(Err));
return orc::SymbolNameSet();
}
}
return Result;
}
orc::SymbolNameSet
lookup(std::shared_ptr<orc::AsynchronousSymbolQuery> Query,
orc::SymbolNameSet Symbols) override {
orc::SymbolNameSet UnresolvedSymbols;
for (auto &S : Symbols) {
if (auto Sym = findSymbol(std::string(*S))) {
if (auto Addr = Sym.getAddress()) {
Query->notifySymbolMetRequiredState(
S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
} else {
Stack.ES.legacyFailQuery(*Query, Addr.takeError());
return orc::SymbolNameSet();
}
} else if (auto Err = Sym.takeError()) {
Stack.ES.legacyFailQuery(*Query, std::move(Err));
return orc::SymbolNameSet();
} else
UnresolvedSymbols.insert(S);
}
if (Query->isComplete())
Query->handleComplete();
return UnresolvedSymbols;
}
private:
JITSymbol findSymbol(const std::string &Name) {
// Search order:
// 1. JIT'd symbols.
// 2. Runtime overrides.
// 3. External resolver (if present).
if (Stack.CODLayer) {
if (auto Sym = Stack.CODLayer->findSymbol(Name, true))
return Sym;
else if (auto Err = Sym.takeError())
return Sym.takeError();
} else {
if (auto Sym = Stack.CompileLayer.findSymbol(Name, true))
return Sym;
else if (auto Err = Sym.takeError())
return Sym.takeError();
}
if (auto Sym = Stack.CXXRuntimeOverrides.searchOverrides(Name))
return Sym;
if (ExternalResolver)
return JITSymbol(ExternalResolver(Name.c_str(), ExternalResolverCtx),
JITSymbolFlags::Exported);
return JITSymbol(nullptr);
}
OrcCBindingsStack &Stack;
LLVMOrcSymbolResolverFn ExternalResolver;
void *ExternalResolverCtx = nullptr;
};
public:
OrcCBindingsStack(TargetMachine &TM,
IndirectStubsManagerBuilder IndirectStubsMgrBuilder)
: CCMgr(createCompileCallbackManager(TM, ES)), DL(TM.createDataLayout()),
IndirectStubsMgr(IndirectStubsMgrBuilder()),
ObjectLayer(
AcknowledgeORCv1Deprecation, ES,
[this](orc::VModuleKey K) {
auto ResolverI = Resolvers.find(K);
assert(ResolverI != Resolvers.end() &&
"No resolver for module K");
auto Resolver = std::move(ResolverI->second);
Resolvers.erase(ResolverI);
return ObjLayerT::Resources{
std::make_shared<SectionMemoryManager>(), Resolver};
},
nullptr,
[this](orc::VModuleKey K, const object::ObjectFile &Obj,
const RuntimeDyld::LoadedObjectInfo &LoadedObjInfo) {
this->notifyFinalized(K, Obj, LoadedObjInfo);
},
[this](orc::VModuleKey K, const object::ObjectFile &Obj) {
this->notifyFreed(K, Obj);
}),
CompileLayer(AcknowledgeORCv1Deprecation, ObjectLayer,
orc::SimpleCompiler(TM)),
CODLayer(createCODLayer(ES, CompileLayer, CCMgr.get(),
std::move(IndirectStubsMgrBuilder), Resolvers)),
CXXRuntimeOverrides(
AcknowledgeORCv1Deprecation,
[this](const std::string &S) { return mangle(S); }) {}
Error shutdown() {
// Run any destructors registered with __cxa_atexit.
CXXRuntimeOverrides.runDestructors();
// Run any IR destructors.
for (auto &DtorRunner : IRStaticDestructorRunners)
if (auto Err = DtorRunner.runViaLayer(*this))
return Err;
return Error::success();
}
std::string mangle(StringRef Name) {
std::string MangledName;
{
raw_string_ostream MangledNameStream(MangledName);
Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
}
return MangledName;
}
template <typename PtrTy>
static PtrTy fromTargetAddress(JITTargetAddress Addr) {
return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
}
Expected<JITTargetAddress>
createLazyCompileCallback(LLVMOrcLazyCompileCallbackFn Callback,
void *CallbackCtx) {
auto WrappedCallback = [=]() -> JITTargetAddress {
return Callback(wrap(this), CallbackCtx);
};
return CCMgr->getCompileCallback(std::move(WrappedCallback));
}
Error createIndirectStub(StringRef StubName, JITTargetAddress Addr) {
return IndirectStubsMgr->createStub(StubName, Addr,
JITSymbolFlags::Exported);
}
Error setIndirectStubPointer(StringRef Name, JITTargetAddress Addr) {
return IndirectStubsMgr->updatePointer(Name, Addr);
}
template <typename LayerT>
Expected<orc::VModuleKey>
addIRModule(LayerT &Layer, std::unique_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);
// Record the static constructors and destructors. We have to do this before
// we hand over ownership of the module to the JIT.
std::vector<std::string> CtorNames, DtorNames;
for (auto Ctor : orc::getConstructors(*M))
CtorNames.push_back(mangle(Ctor.Func->getName()));
for (auto Dtor : orc::getDestructors(*M))
DtorNames.push_back(mangle(Dtor.Func->getName()));
// Add the module to the JIT.
auto K = ES.allocateVModule();
Resolvers[K] = std::make_shared<CBindingsResolver>(*this, ExternalResolver,
ExternalResolverCtx);
if (auto Err = Layer.addModule(K, std::move(M)))
return std::move(Err);
KeyLayers[K] = detail::createGenericLayer(Layer);
// Run the static constructors, and save the static destructor runner for
// execution when the JIT is torn down.
orc::LegacyCtorDtorRunner<OrcCBindingsStack> CtorRunner(
AcknowledgeORCv1Deprecation, std::move(CtorNames), K);
if (auto Err = CtorRunner.runViaLayer(*this))
return std::move(Err);
IRStaticDestructorRunners.emplace_back(AcknowledgeORCv1Deprecation,
std::move(DtorNames), K);
return K;
}
Expected<orc::VModuleKey>
addIRModuleEager(std::unique_ptr<Module> M,
LLVMOrcSymbolResolverFn ExternalResolver,
void *ExternalResolverCtx) {
return addIRModule(CompileLayer, std::move(M),
std::make_unique<SectionMemoryManager>(),
std::move(ExternalResolver), ExternalResolverCtx);
}
Expected<orc::VModuleKey>
addIRModuleLazy(std::unique_ptr<Module> M,
LLVMOrcSymbolResolverFn ExternalResolver,
void *ExternalResolverCtx) {
if (!CODLayer)
return make_error<StringError>("Can not add lazy module: No compile "
"callback manager available",
inconvertibleErrorCode());
return addIRModule(*CODLayer, std::move(M),
std::make_unique<SectionMemoryManager>(),
std::move(ExternalResolver), ExternalResolverCtx);
}
Error removeModule(orc::VModuleKey K) {
// FIXME: Should error release the module key?
if (auto Err = KeyLayers[K]->removeModule(K))
return Err;
ES.releaseVModule(K);
KeyLayers.erase(K);
return Error::success();
}
Expected<orc::VModuleKey> addObject(std::unique_ptr<MemoryBuffer> ObjBuffer,
LLVMOrcSymbolResolverFn ExternalResolver,
void *ExternalResolverCtx) {
if (auto Obj = object::ObjectFile::createObjectFile(
ObjBuffer->getMemBufferRef())) {
auto K = ES.allocateVModule();
Resolvers[K] = std::make_shared<CBindingsResolver>(
*this, ExternalResolver, ExternalResolverCtx);
if (auto Err = ObjectLayer.addObject(K, std::move(ObjBuffer)))
return std::move(Err);
KeyLayers[K] = detail::createGenericLayer(ObjectLayer);
return K;
} else
return Obj.takeError();
}
JITSymbol findSymbol(const std::string &Name,
bool ExportedSymbolsOnly) {
if (auto Sym = IndirectStubsMgr->findStub(Name, ExportedSymbolsOnly))
return Sym;
if (CODLayer)
return CODLayer->findSymbol(mangle(Name), ExportedSymbolsOnly);
return CompileLayer.findSymbol(mangle(Name), ExportedSymbolsOnly);
}
JITSymbol findSymbolIn(orc::VModuleKey K, const std::string &Name,
bool ExportedSymbolsOnly) {
assert(KeyLayers.count(K) && "looking up symbol in unknown module");
return KeyLayers[K]->findSymbolIn(K, mangle(Name), ExportedSymbolsOnly);
}
Expected<JITTargetAddress> findSymbolAddress(const std::string &Name,
bool ExportedSymbolsOnly) {
if (auto Sym = findSymbol(Name, ExportedSymbolsOnly)) {
// Successful lookup, non-null symbol:
if (auto AddrOrErr = Sym.getAddress())
return *AddrOrErr;
else
return AddrOrErr.takeError();
} else if (auto Err = Sym.takeError()) {
// Lookup failure - report error.
return std::move(Err);
}
// No symbol not found. Return 0.
return 0;
}
Expected<JITTargetAddress> findSymbolAddressIn(orc::VModuleKey K,
const std::string &Name,
bool ExportedSymbolsOnly) {
if (auto Sym = findSymbolIn(K, Name, ExportedSymbolsOnly)) {
// Successful lookup, non-null symbol:
if (auto AddrOrErr = Sym.getAddress())
return *AddrOrErr;
else
return AddrOrErr.takeError();
} else if (auto Err = Sym.takeError()) {
// Lookup failure - report error.
return std::move(Err);
}
// Symbol not found. Return 0.
return 0;
}
const std::string &getErrorMessage() const { return ErrMsg; }
void RegisterJITEventListener(JITEventListener *L) {
if (!L)
return;
EventListeners.push_back(L);
}
void UnregisterJITEventListener(JITEventListener *L) {
if (!L)
return;
auto I = find(reverse(EventListeners), L);
if (I != EventListeners.rend()) {
std::swap(*I, EventListeners.back());
EventListeners.pop_back();
}
}
private:
using ResolverMap =
std::map<orc::VModuleKey, std::shared_ptr<orc::SymbolResolver>>;
static std::unique_ptr<CompileCallbackMgr>
createCompileCallbackManager(TargetMachine &TM, orc::ExecutionSession &ES) {
auto CCMgr = createLocalCompileCallbackManager(TM.getTargetTriple(), ES, 0);
if (!CCMgr) {
// FIXME: It would be good if we could report this somewhere, but we do
// have an instance yet.
logAllUnhandledErrors(CCMgr.takeError(), errs(), "ORC error: ");
return nullptr;
}
return std::move(*CCMgr);
}
static std::unique_ptr<CODLayerT>
createCODLayer(orc::ExecutionSession &ES, CompileLayerT &CompileLayer,
CompileCallbackMgr *CCMgr,
IndirectStubsManagerBuilder IndirectStubsMgrBuilder,
ResolverMap &Resolvers) {
// If there is no compile callback manager available we can not create a
// compile on demand layer.
if (!CCMgr)
return nullptr;
return std::make_unique<CODLayerT>(
AcknowledgeORCv1Deprecation, ES, CompileLayer,
[&Resolvers](orc::VModuleKey K) {
auto ResolverI = Resolvers.find(K);
assert(ResolverI != Resolvers.end() && "No resolver for module K");
return ResolverI->second;
},
[&Resolvers](orc::VModuleKey K,
std::shared_ptr<orc::SymbolResolver> Resolver) {
assert(!Resolvers.count(K) && "Resolver already present");
Resolvers[K] = std::move(Resolver);
},
[](Function &F) { return std::set<Function *>({&F}); }, *CCMgr,
std::move(IndirectStubsMgrBuilder), false);
}
void reportError(Error Err) {
// FIXME: Report errors on the execution session.
logAllUnhandledErrors(std::move(Err), errs(), "ORC error: ");
};
void notifyFinalized(orc::VModuleKey K,
const object::ObjectFile &Obj,
const RuntimeDyld::LoadedObjectInfo &LoadedObjInfo) {
uint64_t Key = static_cast<uint64_t>(
reinterpret_cast<uintptr_t>(Obj.getData().data()));
for (auto &Listener : EventListeners)
Listener->notifyObjectLoaded(Key, Obj, LoadedObjInfo);
}
void notifyFreed(orc::VModuleKey K, const object::ObjectFile &Obj) {
uint64_t Key = static_cast<uint64_t>(
reinterpret_cast<uintptr_t>(Obj.getData().data()));
for (auto &Listener : EventListeners)
Listener->notifyFreeingObject(Key);
}
orc::ExecutionSession ES;
std::unique_ptr<CompileCallbackMgr> CCMgr;
std::vector<JITEventListener *> EventListeners;
DataLayout DL;
SectionMemoryManager CCMgrMemMgr;
std::unique_ptr<orc::IndirectStubsManager> IndirectStubsMgr;
ObjLayerT ObjectLayer;
CompileLayerT CompileLayer;
std::unique_ptr<CODLayerT> CODLayer;
std::map<orc::VModuleKey, std::unique_ptr<detail::GenericLayer>> KeyLayers;
orc::LegacyLocalCXXRuntimeOverrides CXXRuntimeOverrides;
std::vector<orc::LegacyCtorDtorRunner<OrcCBindingsStack>> IRStaticDestructorRunners;
std::string ErrMsg;
ResolverMap Resolvers;
};
} // end namespace llvm
#endif // LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H

View File

@ -1,138 +0,0 @@
//===-------- OrcMCJITReplacement.cpp - Orc-based MCJIT replacement -------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "OrcMCJITReplacement.h"
#include "llvm/ExecutionEngine/GenericValue.h"
namespace {
static struct RegisterJIT {
RegisterJIT() { llvm::orc::OrcMCJITReplacement::Register(); }
} JITRegistrator;
}
extern "C" void LLVMLinkInOrcMCJITReplacement() {}
namespace llvm {
namespace orc {
GenericValue
OrcMCJITReplacement::runFunction(Function *F,
ArrayRef<GenericValue> ArgValues) {
assert(F && "Function *F was null at entry to run()");
void *FPtr = getPointerToFunction(F);
assert(FPtr && "Pointer to fn's code was null after getPointerToFunction");
FunctionType *FTy = F->getFunctionType();
Type *RetTy = FTy->getReturnType();
assert((FTy->getNumParams() == ArgValues.size() ||
(FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) &&
"Wrong number of arguments passed into function!");
assert(FTy->getNumParams() == ArgValues.size() &&
"This doesn't support passing arguments through varargs (yet)!");
// Handle some common cases first. These cases correspond to common `main'
// prototypes.
if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) {
switch (ArgValues.size()) {
case 3:
if (FTy->getParamType(0)->isIntegerTy(32) &&
FTy->getParamType(1)->isPointerTy() &&
FTy->getParamType(2)->isPointerTy()) {
int (*PF)(int, char **, const char **) =
(int (*)(int, char **, const char **))(intptr_t)FPtr;
// Call the function.
GenericValue rv;
rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
(char **)GVTOP(ArgValues[1]),
(const char **)GVTOP(ArgValues[2])));
return rv;
}
break;
case 2:
if (FTy->getParamType(0)->isIntegerTy(32) &&
FTy->getParamType(1)->isPointerTy()) {
int (*PF)(int, char **) = (int (*)(int, char **))(intptr_t)FPtr;
// Call the function.
GenericValue rv;
rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
(char **)GVTOP(ArgValues[1])));
return rv;
}
break;
case 1:
if (FTy->getNumParams() == 1 && FTy->getParamType(0)->isIntegerTy(32)) {
GenericValue rv;
int (*PF)(int) = (int (*)(int))(intptr_t)FPtr;
rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue()));
return rv;
}
break;
}
}
// Handle cases where no arguments are passed first.
if (ArgValues.empty()) {
GenericValue rv;
switch (RetTy->getTypeID()) {
default:
llvm_unreachable("Unknown return type for function call!");
case Type::IntegerTyID: {
unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth();
if (BitWidth == 1)
rv.IntVal = APInt(BitWidth, ((bool (*)())(intptr_t)FPtr)());
else if (BitWidth <= 8)
rv.IntVal = APInt(BitWidth, ((char (*)())(intptr_t)FPtr)());
else if (BitWidth <= 16)
rv.IntVal = APInt(BitWidth, ((short (*)())(intptr_t)FPtr)());
else if (BitWidth <= 32)
rv.IntVal = APInt(BitWidth, ((int (*)())(intptr_t)FPtr)());
else if (BitWidth <= 64)
rv.IntVal = APInt(BitWidth, ((int64_t (*)())(intptr_t)FPtr)());
else
llvm_unreachable("Integer types > 64 bits not supported");
return rv;
}
case Type::VoidTyID:
rv.IntVal = APInt(32, ((int (*)())(intptr_t)FPtr)());
return rv;
case Type::FloatTyID:
rv.FloatVal = ((float (*)())(intptr_t)FPtr)();
return rv;
case Type::DoubleTyID:
rv.DoubleVal = ((double (*)())(intptr_t)FPtr)();
return rv;
case Type::X86_FP80TyID:
case Type::FP128TyID:
case Type::PPC_FP128TyID:
llvm_unreachable("long double not supported yet");
case Type::PointerTyID:
return PTOGV(((void *(*)())(intptr_t)FPtr)());
}
}
llvm_unreachable("Full-featured argument passing not supported yet!");
}
void OrcMCJITReplacement::runStaticConstructorsDestructors(bool isDtors) {
auto &CtorDtorsMap = isDtors ? UnexecutedDestructors : UnexecutedConstructors;
for (auto &KV : CtorDtorsMap)
cantFail(LegacyCtorDtorRunner<LazyEmitLayerT>(
AcknowledgeORCv1Deprecation, std::move(KV.second), KV.first)
.runViaLayer(LazyEmitLayer));
CtorDtorsMap.clear();
}
} // End namespace orc.
} // End namespace llvm.

View File

@ -1,502 +0,0 @@
//===- OrcMCJITReplacement.h - Orc based MCJIT replacement ------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Orc based MCJIT replacement.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H
#define LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/GenericValue.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h"
#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include <algorithm>
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
namespace llvm {
class ObjectCache;
namespace orc {
class OrcMCJITReplacement : public ExecutionEngine {
// OrcMCJITReplacement needs to do a little extra book-keeping to ensure that
// Orc's automatic finalization doesn't kick in earlier than MCJIT clients are
// expecting - see finalizeMemory.
class MCJITReplacementMemMgr : public MCJITMemoryManager {
public:
MCJITReplacementMemMgr(OrcMCJITReplacement &M,
std::shared_ptr<MCJITMemoryManager> ClientMM)
: M(M), ClientMM(std::move(ClientMM)) {}
uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID,
StringRef SectionName) override {
uint8_t *Addr =
ClientMM->allocateCodeSection(Size, Alignment, SectionID,
SectionName);
M.SectionsAllocatedSinceLastLoad.insert(Addr);
return Addr;
}
uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
unsigned SectionID, StringRef SectionName,
bool IsReadOnly) override {
uint8_t *Addr = ClientMM->allocateDataSection(Size, Alignment, SectionID,
SectionName, IsReadOnly);
M.SectionsAllocatedSinceLastLoad.insert(Addr);
return Addr;
}
void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
uintptr_t RODataSize, uint32_t RODataAlign,
uintptr_t RWDataSize,
uint32_t RWDataAlign) override {
return ClientMM->reserveAllocationSpace(CodeSize, CodeAlign,
RODataSize, RODataAlign,
RWDataSize, RWDataAlign);
}
bool needsToReserveAllocationSpace() override {
return ClientMM->needsToReserveAllocationSpace();
}
void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
size_t Size) override {
return ClientMM->registerEHFrames(Addr, LoadAddr, Size);
}
void deregisterEHFrames() override {
return ClientMM->deregisterEHFrames();
}
void notifyObjectLoaded(RuntimeDyld &RTDyld,
const object::ObjectFile &O) override {
return ClientMM->notifyObjectLoaded(RTDyld, O);
}
void notifyObjectLoaded(ExecutionEngine *EE,
const object::ObjectFile &O) override {
return ClientMM->notifyObjectLoaded(EE, O);
}
bool finalizeMemory(std::string *ErrMsg = nullptr) override {
// Each set of objects loaded will be finalized exactly once, but since
// symbol lookup during relocation may recursively trigger the
// loading/relocation of other modules, and since we're forwarding all
// finalizeMemory calls to a single underlying memory manager, we need to
// defer forwarding the call on until all necessary objects have been
// loaded. Otherwise, during the relocation of a leaf object, we will end
// up finalizing memory, causing a crash further up the stack when we
// attempt to apply relocations to finalized memory.
// To avoid finalizing too early, look at how many objects have been
// loaded but not yet finalized. This is a bit of a hack that relies on
// the fact that we're lazily emitting object files: The only way you can
// get more than one set of objects loaded but not yet finalized is if
// they were loaded during relocation of another set.
if (M.UnfinalizedSections.size() == 1)
return ClientMM->finalizeMemory(ErrMsg);
return false;
}
private:
OrcMCJITReplacement &M;
std::shared_ptr<MCJITMemoryManager> ClientMM;
};
class LinkingORCResolver : public orc::SymbolResolver {
public:
LinkingORCResolver(OrcMCJITReplacement &M) : M(M) {}
SymbolNameSet getResponsibilitySet(const SymbolNameSet &Symbols) override {
SymbolNameSet Result;
for (auto &S : Symbols) {
if (auto Sym = M.findMangledSymbol(*S)) {
if (!Sym.getFlags().isStrong())
Result.insert(S);
} else if (auto Err = Sym.takeError()) {
M.reportError(std::move(Err));
return SymbolNameSet();
} else {
if (auto Sym2 =
M.ClientResolver->findSymbolInLogicalDylib(std::string(*S))) {
if (!Sym2.getFlags().isStrong())
Result.insert(S);
} else if (auto Err = Sym2.takeError()) {
M.reportError(std::move(Err));
return SymbolNameSet();
} else
Result.insert(S);
}
}
return Result;
}
SymbolNameSet lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
SymbolNameSet Symbols) override {
SymbolNameSet UnresolvedSymbols;
bool NewSymbolsResolved = false;
for (auto &S : Symbols) {
if (auto Sym = M.findMangledSymbol(*S)) {
if (auto Addr = Sym.getAddress()) {
Query->notifySymbolMetRequiredState(
S, JITEvaluatedSymbol(*Addr, Sym.getFlags()));
NewSymbolsResolved = true;
} else {
M.ES.legacyFailQuery(*Query, Addr.takeError());
return SymbolNameSet();
}
} else if (auto Err = Sym.takeError()) {
M.ES.legacyFailQuery(*Query, std::move(Err));
return SymbolNameSet();
} else {
if (auto Sym2 = M.ClientResolver->findSymbol(std::string(*S))) {
if (auto Addr = Sym2.getAddress()) {
Query->notifySymbolMetRequiredState(
S, JITEvaluatedSymbol(*Addr, Sym2.getFlags()));
NewSymbolsResolved = true;
} else {
M.ES.legacyFailQuery(*Query, Addr.takeError());
return SymbolNameSet();
}
} else if (auto Err = Sym2.takeError()) {
M.ES.legacyFailQuery(*Query, std::move(Err));
return SymbolNameSet();
} else
UnresolvedSymbols.insert(S);
}
}
if (NewSymbolsResolved && Query->isComplete())
Query->handleComplete();
return UnresolvedSymbols;
}
private:
OrcMCJITReplacement &M;
};
private:
static ExecutionEngine *
createOrcMCJITReplacement(std::string *ErrorMsg,
std::shared_ptr<MCJITMemoryManager> MemMgr,
std::shared_ptr<LegacyJITSymbolResolver> Resolver,
std::unique_ptr<TargetMachine> TM) {
return new OrcMCJITReplacement(std::move(MemMgr), std::move(Resolver),
std::move(TM));
}
void reportError(Error Err) {
logAllUnhandledErrors(std::move(Err), errs(), "MCJIT error: ");
}
public:
OrcMCJITReplacement(std::shared_ptr<MCJITMemoryManager> MemMgr,
std::shared_ptr<LegacyJITSymbolResolver> ClientResolver,
std::unique_ptr<TargetMachine> TM)
: ExecutionEngine(TM->createDataLayout()), TM(std::move(TM)),
MemMgr(
std::make_shared<MCJITReplacementMemMgr>(*this, std::move(MemMgr))),
Resolver(std::make_shared<LinkingORCResolver>(*this)),
ClientResolver(std::move(ClientResolver)), NotifyObjectLoaded(*this),
NotifyFinalized(*this),
ObjectLayer(
AcknowledgeORCv1Deprecation, ES,
[this](VModuleKey K) {
return ObjectLayerT::Resources{this->MemMgr, this->Resolver};
},
NotifyObjectLoaded, NotifyFinalized),
CompileLayer(AcknowledgeORCv1Deprecation, ObjectLayer,
SimpleCompiler(*this->TM),
[this](VModuleKey K, std::unique_ptr<Module> M) {
Modules.push_back(std::move(M));
}),
LazyEmitLayer(AcknowledgeORCv1Deprecation, CompileLayer) {}
static void Register() {
OrcMCJITReplacementCtor = createOrcMCJITReplacement;
}
void addModule(std::unique_ptr<Module> M) override {
// If this module doesn't have a DataLayout attached then attach the
// default.
if (M->getDataLayout().isDefault()) {
M->setDataLayout(getDataLayout());
} else {
assert(M->getDataLayout() == getDataLayout() && "DataLayout Mismatch");
}
// Rename, bump linkage and record static constructors and destructors.
// We have to do this before we hand over ownership of the module to the
// JIT.
std::vector<std::string> CtorNames, DtorNames;
{
unsigned CtorId = 0, DtorId = 0;
for (auto Ctor : orc::getConstructors(*M)) {
std::string NewCtorName = ("__ORCstatic_ctor." + Twine(CtorId++)).str();
Ctor.Func->setName(NewCtorName);
Ctor.Func->setLinkage(GlobalValue::ExternalLinkage);
Ctor.Func->setVisibility(GlobalValue::HiddenVisibility);
CtorNames.push_back(mangle(NewCtorName));
}
for (auto Dtor : orc::getDestructors(*M)) {
std::string NewDtorName = ("__ORCstatic_dtor." + Twine(DtorId++)).str();
dbgs() << "Found dtor: " << NewDtorName << "\n";
Dtor.Func->setName(NewDtorName);
Dtor.Func->setLinkage(GlobalValue::ExternalLinkage);
Dtor.Func->setVisibility(GlobalValue::HiddenVisibility);
DtorNames.push_back(mangle(NewDtorName));
}
}
auto K = ES.allocateVModule();
UnexecutedConstructors[K] = std::move(CtorNames);
UnexecutedDestructors[K] = std::move(DtorNames);
cantFail(LazyEmitLayer.addModule(K, std::move(M)));
}
void addObjectFile(std::unique_ptr<object::ObjectFile> O) override {
cantFail(ObjectLayer.addObject(
ES.allocateVModule(), MemoryBuffer::getMemBufferCopy(O->getData())));
}
void addObjectFile(object::OwningBinary<object::ObjectFile> O) override {
std::unique_ptr<object::ObjectFile> Obj;
std::unique_ptr<MemoryBuffer> ObjBuffer;
std::tie(Obj, ObjBuffer) = O.takeBinary();
cantFail(ObjectLayer.addObject(ES.allocateVModule(), std::move(ObjBuffer)));
}
void addArchive(object::OwningBinary<object::Archive> A) override {
Archives.push_back(std::move(A));
}
bool removeModule(Module *M) override {
auto I = Modules.begin();
for (auto E = Modules.end(); I != E; ++I)
if (I->get() == M)
break;
if (I == Modules.end())
return false;
Modules.erase(I);
return true;
}
uint64_t getSymbolAddress(StringRef Name) {
return cantFail(findSymbol(Name).getAddress());
}
JITSymbol findSymbol(StringRef Name) {
return findMangledSymbol(mangle(Name));
}
void finalizeObject() override {
// This is deprecated - Aim to remove in ExecutionEngine.
// REMOVE IF POSSIBLE - Doesn't make sense for New JIT.
}
void mapSectionAddress(const void *LocalAddress,
uint64_t TargetAddress) override {
for (auto &P : UnfinalizedSections)
if (P.second.count(LocalAddress))
ObjectLayer.mapSectionAddress(P.first, LocalAddress, TargetAddress);
}
uint64_t getGlobalValueAddress(const std::string &Name) override {
return getSymbolAddress(Name);
}
uint64_t getFunctionAddress(const std::string &Name) override {
return getSymbolAddress(Name);
}
void *getPointerToFunction(Function *F) override {
uint64_t FAddr = getSymbolAddress(F->getName());
return reinterpret_cast<void *>(static_cast<uintptr_t>(FAddr));
}
void *getPointerToNamedFunction(StringRef Name,
bool AbortOnFailure = true) override {
uint64_t Addr = getSymbolAddress(Name);
if (!Addr && AbortOnFailure)
llvm_unreachable("Missing symbol!");
return reinterpret_cast<void *>(static_cast<uintptr_t>(Addr));
}
GenericValue runFunction(Function *F,
ArrayRef<GenericValue> ArgValues) override;
void setObjectCache(ObjectCache *NewCache) override {
CompileLayer.getCompiler().setObjectCache(NewCache);
}
void setProcessAllSections(bool ProcessAllSections) override {
ObjectLayer.setProcessAllSections(ProcessAllSections);
}
void runStaticConstructorsDestructors(bool isDtors) override;
private:
JITSymbol findMangledSymbol(StringRef Name) {
if (auto Sym = LazyEmitLayer.findSymbol(std::string(Name), false))
return Sym;
if (auto Sym = ClientResolver->findSymbol(std::string(Name)))
return Sym;
if (auto Sym = scanArchives(Name))
return Sym;
return nullptr;
}
JITSymbol scanArchives(StringRef Name) {
for (object::OwningBinary<object::Archive> &OB : Archives) {
object::Archive *A = OB.getBinary();
// Look for our symbols in each Archive
auto OptionalChildOrErr = A->findSym(Name);
if (!OptionalChildOrErr)
report_fatal_error(OptionalChildOrErr.takeError());
auto &OptionalChild = *OptionalChildOrErr;
if (OptionalChild) {
// FIXME: Support nested archives?
Expected<std::unique_ptr<object::Binary>> ChildBinOrErr =
OptionalChild->getAsBinary();
if (!ChildBinOrErr) {
// TODO: Actually report errors helpfully.
consumeError(ChildBinOrErr.takeError());
continue;
}
std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get();
if (ChildBin->isObject()) {
cantFail(ObjectLayer.addObject(
ES.allocateVModule(),
MemoryBuffer::getMemBufferCopy(ChildBin->getData())));
if (auto Sym = ObjectLayer.findSymbol(Name, true))
return Sym;
}
}
}
return nullptr;
}
class NotifyObjectLoadedT {
public:
using LoadedObjInfoListT =
std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>;
NotifyObjectLoadedT(OrcMCJITReplacement &M) : M(M) {}
void operator()(VModuleKey K, const object::ObjectFile &Obj,
const RuntimeDyld::LoadedObjectInfo &Info) const {
M.UnfinalizedSections[K] = std::move(M.SectionsAllocatedSinceLastLoad);
M.SectionsAllocatedSinceLastLoad = SectionAddrSet();
M.MemMgr->notifyObjectLoaded(&M, Obj);
}
private:
OrcMCJITReplacement &M;
};
class NotifyFinalizedT {
public:
NotifyFinalizedT(OrcMCJITReplacement &M) : M(M) {}
void operator()(VModuleKey K, const object::ObjectFile &Obj,
const RuntimeDyld::LoadedObjectInfo &Info) {
M.UnfinalizedSections.erase(K);
}
private:
OrcMCJITReplacement &M;
};
std::string mangle(StringRef Name) {
std::string MangledName;
{
raw_string_ostream MangledNameStream(MangledName);
Mang.getNameWithPrefix(MangledNameStream, Name, getDataLayout());
}
return MangledName;
}
using ObjectLayerT = LegacyRTDyldObjectLinkingLayer;
using CompileLayerT = LegacyIRCompileLayer<ObjectLayerT, orc::SimpleCompiler>;
using LazyEmitLayerT = LazyEmittingLayer<CompileLayerT>;
ExecutionSession ES;
std::unique_ptr<TargetMachine> TM;
std::shared_ptr<MCJITReplacementMemMgr> MemMgr;
std::shared_ptr<LinkingORCResolver> Resolver;
std::shared_ptr<LegacyJITSymbolResolver> ClientResolver;
Mangler Mang;
// IMPORTANT: ShouldDelete *must* come before LocalModules: The shared_ptr
// delete blocks in LocalModules refer to the ShouldDelete map, so
// LocalModules needs to be destructed before ShouldDelete.
std::map<Module*, bool> ShouldDelete;
NotifyObjectLoadedT NotifyObjectLoaded;
NotifyFinalizedT NotifyFinalized;
ObjectLayerT ObjectLayer;
CompileLayerT CompileLayer;
LazyEmitLayerT LazyEmitLayer;
std::map<VModuleKey, std::vector<std::string>> UnexecutedConstructors;
std::map<VModuleKey, std::vector<std::string>> UnexecutedDestructors;
// We need to store ObjLayerT::ObjSetHandles for each of the object sets
// that have been emitted but not yet finalized so that we can forward the
// mapSectionAddress calls appropriately.
using SectionAddrSet = std::set<const void *>;
SectionAddrSet SectionsAllocatedSinceLastLoad;
std::map<VModuleKey, SectionAddrSet> UnfinalizedSections;
std::vector<object::OwningBinary<object::Archive>> Archives;
};
} // end namespace orc
} // end namespace llvm
#endif // LLVM_LIB_EXECUTIONENGINE_ORC_MCJITREPLACEMENT_H

View File

@ -318,14 +318,5 @@ void RTDyldObjectLinkingLayer::onObjEmit(
NotifyEmitted(K, std::move(ObjBuffer));
}
LegacyRTDyldObjectLinkingLayer::LegacyRTDyldObjectLinkingLayer(
ExecutionSession &ES, ResourcesGetter GetResources,
NotifyLoadedFtor NotifyLoaded, NotifyFinalizedFtor NotifyFinalized,
NotifyFreedFtor NotifyFreed)
: ES(ES), GetResources(std::move(GetResources)),
NotifyLoaded(std::move(NotifyLoaded)),
NotifyFinalized(std::move(NotifyFinalized)),
NotifyFreed(std::move(NotifyFreed)), ProcessAllSections(false) {}
} // End namespace orc.
} // End namespace llvm.

View File

@ -1,37 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
@.LC0 = internal global [10 x i8] c"argc: %d\0A\00" ; <[10 x i8]*> [#uses=1]
declare i32 @puts(i8*)
define void @getoptions(i32* %argc) {
bb0:
ret void
}
declare i32 @printf(i8*, ...)
define i32 @main(i32 %argc, i8** %argv) {
bb0:
call i32 (i8*, ...) @printf( i8* getelementptr ([10 x i8], [10 x i8]* @.LC0, i64 0, i64 0), i32 %argc ) ; <i32>:0 [#uses=0]
%cast224 = bitcast i8** %argv to i8* ; <i8*> [#uses=1]
%local = alloca i8* ; <i8**> [#uses=3]
store i8* %cast224, i8** %local
%cond226 = icmp sle i32 %argc, 0 ; <i1> [#uses=1]
br i1 %cond226, label %bb3, label %bb2
bb2: ; preds = %bb2, %bb0
%cann-indvar = phi i32 [ 0, %bb0 ], [ %add1-indvar, %bb2 ] ; <i32> [#uses=2]
%add1-indvar = add i32 %cann-indvar, 1 ; <i32> [#uses=2]
%cann-indvar-idxcast = sext i32 %cann-indvar to i64 ; <i64> [#uses=1]
%CT = bitcast i8** %local to i8*** ; <i8***> [#uses=1]
%reg115 = load i8**, i8*** %CT ; <i8**> [#uses=1]
%cast235 = getelementptr i8*, i8** %reg115, i64 %cann-indvar-idxcast ; <i8**> [#uses=1]
%reg117 = load i8*, i8** %cast235 ; <i8*> [#uses=1]
%reg236 = call i32 @puts( i8* %reg117 ) ; <i32> [#uses=0]
%cond239 = icmp slt i32 %add1-indvar, %argc ; <i1> [#uses=1]
br i1 %cond239, label %bb2, label %bb3
bb3: ; preds = %bb2, %bb0
%cast243 = bitcast i8** %local to i32* ; <i32*> [#uses=1]
call void @getoptions( i32* %cast243 )
ret i32 0
}

View File

@ -1,13 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
define i32 @foo(i32 %X, i32 %Y, double %A) {
%cond212 = fcmp une double %A, 1.000000e+00 ; <i1> [#uses=1]
%cast110 = zext i1 %cond212 to i32 ; <i32> [#uses=1]
ret i32 %cast110
}
define i32 @main() {
%reg212 = call i32 @foo( i32 0, i32 1, double 1.000000e+00 ) ; <i32> [#uses=1]
ret i32 %reg212
}

View File

@ -1,20 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
define i32 @main() {
call i32 @mylog( i32 4 ) ; <i32>:1 [#uses=0]
ret i32 0
}
define internal i32 @mylog(i32 %num) {
bb0:
br label %bb2
bb2: ; preds = %bb2, %bb0
%reg112 = phi i32 [ 10, %bb2 ], [ 1, %bb0 ] ; <i32> [#uses=1]
%cann-indvar = phi i32 [ %cann-indvar, %bb2 ], [ 0, %bb0 ] ; <i32> [#uses=1]
%reg114 = add i32 %reg112, 1 ; <i32> [#uses=2]
%cond222 = icmp slt i32 %reg114, %num ; <i1> [#uses=1]
br i1 %cond222, label %bb2, label %bb3
bb3: ; preds = %bb2
ret i32 %reg114
}

View File

@ -1,12 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
define i32 @main() {
; <label>:0
br label %Loop
Loop: ; preds = %Loop, %0
%X = phi i32 [ 0, %0 ], [ 1, %Loop ] ; <i32> [#uses=1]
br i1 true, label %Out, label %Loop
Out: ; preds = %Loop
ret i32 %X
}

View File

@ -1,11 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
; We were accidentally inverting the signedness of right shifts. Whoops.
define i32 @main() {
%X = ashr i32 -1, 16 ; <i32> [#uses=1]
%Y = ashr i32 %X, 16 ; <i32> [#uses=1]
%Z = add i32 %Y, 1 ; <i32> [#uses=1]
ret i32 %Z
}

View File

@ -1,10 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
define i32 @main() {
%X = fadd double 0.000000e+00, 1.000000e+00 ; <double> [#uses=1]
%Y = fsub double 0.000000e+00, 1.000000e+00 ; <double> [#uses=2]
%Z = fcmp oeq double %X, %Y ; <i1> [#uses=0]
fadd double %Y, 0.000000e+00 ; <double>:1 [#uses=0]
ret i32 0
}

View File

@ -1,17 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
define i32 @bar(i8* %X) {
; pointer should be 4 byte aligned!
%P = alloca double ; <double*> [#uses=1]
%R = ptrtoint double* %P to i32 ; <i32> [#uses=1]
%A = and i32 %R, 3 ; <i32> [#uses=1]
ret i32 %A
}
define i32 @main() {
%SP = alloca i8 ; <i8*> [#uses=1]
%X = add i32 0, 0 ; <i32> [#uses=1]
alloca i8, i32 %X ; <i8*>:1 [#uses=0]
call i32 @bar( i8* %SP ) ; <i32>:2 [#uses=1]
ret i32 %2
}

View File

@ -1,19 +0,0 @@
; This testcase should return with an exit code of 1.
;
; RUN: not %lli -jit-kind=orc-mcjit %s
@test = global i64 0 ; <i64*> [#uses=1]
define internal i64 @test.upgrd.1() {
%tmp.0 = load i64, i64* @test ; <i64> [#uses=1]
%tmp.1 = add i64 %tmp.0, 1 ; <i64> [#uses=1]
ret i64 %tmp.1
}
define i32 @main() {
%L = call i64 @test.upgrd.1( ) ; <i64> [#uses=1]
%I = trunc i64 %L to i32 ; <i32> [#uses=1]
ret i32 %I
}

View File

@ -1,11 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s test
declare i32 @puts(i8*)
define i32 @main(i32 %argc.1, i8** %argv.1) {
%tmp.5 = getelementptr i8*, i8** %argv.1, i64 1 ; <i8**> [#uses=1]
%tmp.6 = load i8*, i8** %tmp.5 ; <i8*> [#uses=1]
%tmp.0 = call i32 @puts( i8* %tmp.6 ) ; <i32> [#uses=0]
ret i32 0
}

View File

@ -1,13 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
define i32 @main() {
entry:
br label %endif
then: ; No predecessors!
br label %endif
endif: ; preds = %then, %entry
%x = phi i32 [ 4, %entry ], [ 27, %then ] ; <i32> [#uses=0]
%result = phi i32 [ 32, %then ], [ 0, %entry ] ; <i32> [#uses=0]
ret i32 0
}

View File

@ -1,17 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
; Testcase distilled from 256.bzip2.
define i32 @main() {
entry:
br label %loopentry.0
loopentry.0: ; preds = %loopentry.0, %entry
%h.0 = phi i32 [ %tmp.2, %loopentry.0 ], [ -1, %entry ] ; <i32> [#uses=1]
%tmp.2 = add i32 %h.0, 1 ; <i32> [#uses=3]
%tmp.4 = icmp ne i32 %tmp.2, 0 ; <i1> [#uses=1]
br i1 %tmp.4, label %loopentry.0, label %loopentry.1
loopentry.1: ; preds = %loopentry.0
%h.1 = phi i32 [ %tmp.2, %loopentry.0 ] ; <i32> [#uses=1]
ret i32 %h.1
}

View File

@ -1,15 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
; Testcase distilled from 256.bzip2.
define i32 @main() {
entry:
%X = add i32 1, -1 ; <i32> [#uses=3]
br label %Next
Next: ; preds = %entry
%A = phi i32 [ %X, %entry ] ; <i32> [#uses=0]
%B = phi i32 [ %X, %entry ] ; <i32> [#uses=0]
%C = phi i32 [ %X, %entry ] ; <i32> [#uses=1]
ret i32 %C
}

View File

@ -1,11 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
; This testcase failed to work because two variable sized allocas confused the
; local register allocator.
define i32 @main(i32 %X) {
%A = alloca i32, i32 %X ; <i32*> [#uses=0]
%B = alloca float, i32 %X ; <float*> [#uses=0]
ret i32 0
}

View File

@ -1,21 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
;
; Regression Test: EnvironmentTest.ll
;
; Description:
; This is a regression test that verifies that the JIT passes the
; environment to the main() function.
;
declare i32 @strlen(i8*)
define i32 @main(i32 %argc.1, i8** %argv.1, i8** %envp.1) {
%tmp.2 = load i8*, i8** %envp.1 ; <i8*> [#uses=1]
%tmp.3 = call i32 @strlen( i8* %tmp.2 ) ; <i32> [#uses=1]
%T = icmp eq i32 %tmp.3, 0 ; <i1> [#uses=1]
%R = zext i1 %T to i32 ; <i32> [#uses=1]
ret i32 %R
}

View File

@ -1,34 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
; This testcase exposes a bug in the local register allocator where it runs out
; of registers (due to too many overlapping live ranges), but then attempts to
; use the ESP register (which is not allocatable) to hold a value.
define i32 @main(i32 %A) {
; ESP gets used again...
%Ap2 = alloca i32, i32 %A ; <i32*> [#uses=11]
; Produce lots of overlapping live ranges
%B = add i32 %A, 1 ; <i32> [#uses=1]
%C = add i32 %A, 2 ; <i32> [#uses=1]
%D = add i32 %A, 3 ; <i32> [#uses=1]
%E = add i32 %A, 4 ; <i32> [#uses=1]
%F = add i32 %A, 5 ; <i32> [#uses=1]
%G = add i32 %A, 6 ; <i32> [#uses=1]
%H = add i32 %A, 7 ; <i32> [#uses=1]
%I = add i32 %A, 8 ; <i32> [#uses=1]
%J = add i32 %A, 9 ; <i32> [#uses=1]
%K = add i32 %A, 10 ; <i32> [#uses=1]
; Uses of all of the values
store i32 %A, i32* %Ap2
store i32 %B, i32* %Ap2
store i32 %C, i32* %Ap2
store i32 %D, i32* %Ap2
store i32 %E, i32* %Ap2
store i32 %F, i32* %Ap2
store i32 %G, i32* %Ap2
store i32 %H, i32* %Ap2
store i32 %I, i32* %Ap2
store i32 %J, i32* %Ap2
store i32 %K, i32* %Ap2
ret i32 0
}

View File

@ -1,23 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
@A = global i32 0 ; <i32*> [#uses=1]
define i32 @main() {
%Ret = call i32 @test( i1 true, i32 0 ) ; <i32> [#uses=1]
ret i32 %Ret
}
define i32 @test(i1 %c, i32 %A) {
br i1 %c, label %Taken1, label %NotTaken
Cont: ; preds = %Taken1, %NotTaken
%V = phi i32 [ 0, %NotTaken ], [ sub (i32 ptrtoint (i32* @A to i32), i32 1234), %Taken1 ] ; <i32> [#uses=0]
ret i32 0
NotTaken: ; preds = %0
br label %Cont
Taken1: ; preds = %0
%B = icmp eq i32 %A, 0 ; <i1> [#uses=1]
br i1 %B, label %Cont, label %ExitError
ExitError: ; preds = %Taken1
ret i32 12
}

View File

@ -1,22 +0,0 @@
; PR672
; RUN: %lli -jit-kind=orc-mcjit %s
; XFAIL: mcjit-ia32
define i32 @main() {
%f = bitcast i32 (i32, i32*, i32)* @check_tail to i32* ; <i32*> [#uses=1]
%res = tail call fastcc i32 @check_tail( i32 10, i32* %f, i32 10 ) ; <i32> [#uses=1]
ret i32 %res
}
define fastcc i32 @check_tail(i32 %x, i32* %f, i32 %g) {
%tmp1 = icmp sgt i32 %x, 0 ; <i1> [#uses=1]
br i1 %tmp1, label %if-then, label %if-else
if-then: ; preds = %0
%fun_ptr = bitcast i32* %f to i32 (i32, i32*, i32)* ; <i32 (i32, i32*, i32)*> [#uses=1]
%arg1 = add i32 %x, -1 ; <i32> [#uses=1]
%res = tail call fastcc i32 %fun_ptr( i32 %arg1, i32* %f, i32 %g ) ; <i32> [#uses=1]
ret i32 %res
if-else: ; preds = %0
ret i32 %x
}

View File

@ -1,19 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -force-interpreter %s
; PR1836
define i32 @main() {
entry:
%retval = alloca i32 ; <i32*> [#uses=2]
%tmp = alloca i32 ; <i32*> [#uses=2]
%x = alloca i75, align 16 ; <i75*> [#uses=1]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
store i75 999, i75* %x, align 16
store i32 0, i32* %tmp, align 4
%tmp1 = load i32, i32* %tmp, align 4 ; <i32> [#uses=1]
store i32 %tmp1, i32* %retval, align 4
br label %return
return: ; preds = %entry
%retval2 = load i32, i32* %retval ; <i32> [#uses=1]
ret i32 %retval2
}

View File

@ -1,60 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -force-interpreter=true %s | FileCheck %s
; CHECK: 1
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32"
target triple = "i686-pc-linux-gnu"
@.str = internal constant [10 x i8] c"MSB = %d\0A\00" ; <[10 x i8]*> [#uses=1]
define i65 @foo(i65 %x) {
entry:
%x_addr = alloca i65 ; <i65*> [#uses=2]
%retval = alloca i65 ; <i65*> [#uses=2]
%tmp = alloca i65 ; <i65*> [#uses=2]
%"alloca point" = bitcast i65 0 to i65 ; <i65> [#uses=0]
store i65 %x, i65* %x_addr
%tmp1 = load i65, i65* %x_addr, align 4 ; <i65> [#uses=1]
%tmp2 = ashr i65 %tmp1, 65 ; <i65> [#uses=1]
store i65 %tmp2, i65* %tmp, align 4
%tmp3 = load i65, i65* %tmp, align 4 ; <i65> [#uses=1]
store i65 %tmp3, i65* %retval, align 4
br label %return
return: ; preds = %entry
%retval4 = load i65, i65* %retval ; <i65> [#uses=1]
ret i65 %retval4
}
define i32 @main() {
entry:
%retval = alloca i32 ; <i32*> [#uses=1]
%iftmp.0 = alloca i32 ; <i32*> [#uses=3]
%"alloca point" = bitcast i32 0 to i32 ; <i32> [#uses=0]
%tmp = call i65 @foo( i65 -9 ) ; <i65> [#uses=1]
%tmp1 = lshr i65 %tmp, 64 ; <i65> [#uses=1]
%tmp2 = xor i65 %tmp1, 1 ; <i65> [#uses=1]
%tmp3 = and i65 %tmp2, 1 ; <i65> [#uses=1]
%tmp34 = trunc i65 %tmp3 to i8 ; <i8> [#uses=1]
%toBool = icmp ne i8 %tmp34, 0 ; <i1> [#uses=1]
br i1 %toBool, label %cond_true, label %cond_false
cond_true: ; preds = %entry
store i32 0, i32* %iftmp.0, align 4
br label %cond_next
cond_false: ; preds = %entry
store i32 1, i32* %iftmp.0, align 4
br label %cond_next
cond_next: ; preds = %cond_false, %cond_true
%tmp5 = getelementptr [10 x i8], [10 x i8]* @.str, i32 0, i32 0 ; <i8*> [#uses=1]
%tmp6 = load i32, i32* %iftmp.0, align 4 ; <i32> [#uses=1]
%tmp7 = call i32 (i8*, ...) @printf( i8* noalias %tmp5, i32 %tmp6 ) nounwind ; <i32> [#uses=0]
br label %return
return: ; preds = %cond_next
store i32 0, i32* %retval, align 4
%retval8 = load i32, i32* %retval ; <i32> [#uses=1]
ret i32 %retval8
}
declare i32 @printf(i8* noalias , ...) nounwind

View File

@ -1,25 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s
;
; Verify relocations to global symbols with addend work correctly.
;
; Compiled from this C code:
;
; int test[2] = { -1, 0 };
; int *p = &test[1];
;
; int main (void)
; {
; return *p;
; }
;
@test = global [2 x i32] [i32 -1, i32 0], align 4
@p = global i32* getelementptr inbounds ([2 x i32], [2 x i32]* @test, i64 0, i64 1), align 8
define i32 @main() {
entry:
%0 = load i32*, i32** @p, align 8
%1 = load i32, i32* %0, align 4
ret i32 %1
}

View File

@ -1,7 +0,0 @@
declare i32 @FA()
define i32 @FB() {
%r = call i32 @FA( ) ; <i32> [#uses=1]
ret i32 %r
}

View File

@ -1,7 +0,0 @@
declare i32 @FC()
define i32 @FB() {
%r = call i32 @FC( ) ; <i32> [#uses=1]
ret i32 %r
}

View File

@ -1,4 +0,0 @@
define i32 @FC() {
ret i32 0
}

View File

@ -1,30 +0,0 @@
declare i8* @__cxa_allocate_exception(i64)
declare void @__cxa_throw(i8*, i8*, i8*)
declare i32 @__gxx_personality_v0(...)
declare void @__cxa_end_catch()
declare i8* @__cxa_begin_catch(i8*)
@_ZTIi = external constant i8*
define void @throwException_B() {
%exception = tail call i8* @__cxa_allocate_exception(i64 4)
call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null)
unreachable
}
define i32 @FB() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
entry:
invoke void @throwException_B()
to label %try.cont unwind label %lpad
lpad:
%p = landingpad { i8*, i32 }
catch i8* bitcast (i8** @_ZTIi to i8*)
%e = extractvalue { i8*, i32 } %p, 0
call i8* @__cxa_begin_catch(i8* %e)
call void @__cxa_end_catch()
br label %try.cont
try.cont:
ret i32 0
}

View File

@ -1,9 +0,0 @@
define weak i32 @baz() #0 {
entry:
ret i32 0
}
define i8* @bar() {
entry:
ret i8* bitcast (i32 ()* @baz to i8*)
}

View File

@ -1,13 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -extra-module=%p/Inputs/cross-module-b.ll %s > /dev/null
declare i32 @FB()
define i32 @FA() {
ret i32 0
}
define i32 @main() {
%r = call i32 @FB( ) ; <i32> [#uses=1]
ret i32 %r
}

View File

@ -1,14 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -extra-module=%p/Inputs/cross-module-b.ll -relocation-model=pic -code-model=small %s > /dev/null
; XFAIL: mips-, mipsel-, i686, i386
declare i32 @FB()
define i32 @FA() {
ret i32 0
}
define i32 @main() {
%r = call i32 @FB( ) ; <i32> [#uses=1]
ret i32 %r
}

View File

@ -1,39 +0,0 @@
; REQUIRES: cxx-shared-library
; RUN: %lli -jit-kind=orc-mcjit -relocation-model=pic -code-model=large %s
; XFAIL: cygwin, windows-msvc, windows-gnu, mips-, mipsel-, i686, i386, aarch64, arm
declare i8* @__cxa_allocate_exception(i64)
declare void @__cxa_throw(i8*, i8*, i8*)
declare i32 @__gxx_personality_v0(...)
declare void @__cxa_end_catch()
declare i8* @__cxa_begin_catch(i8*)
@_ZTIi = external constant i8*
define void @throwException() {
%exception = tail call i8* @__cxa_allocate_exception(i64 4)
call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null)
unreachable
}
; Make an internal function so we exercise R_X86_64_GOTOFF64 relocations.
define internal dso_local void @use_gotoff() {
ret void
}
define i32 @main() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
entry:
call void @use_gotoff()
invoke void @throwException()
to label %try.cont unwind label %lpad
lpad:
%p = landingpad { i8*, i32 }
catch i8* bitcast (i8** @_ZTIi to i8*)
%e = extractvalue { i8*, i32 } %p, 0
call i8* @__cxa_begin_catch(i8* %e)
call void @__cxa_end_catch()
br label %try.cont
try.cont:
ret i32 0
}

View File

@ -1,33 +0,0 @@
; REQUIRES: cxx-shared-library
; RUN: %lli -jit-kind=orc-mcjit %s
; XFAIL: arm, cygwin, windows-msvc, windows-gnu
declare i8* @__cxa_allocate_exception(i64)
declare void @__cxa_throw(i8*, i8*, i8*)
declare i32 @__gxx_personality_v0(...)
declare void @__cxa_end_catch()
declare i8* @__cxa_begin_catch(i8*)
@_ZTIi = external constant i8*
define void @throwException() {
%exception = tail call i8* @__cxa_allocate_exception(i64 4)
call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null)
unreachable
}
define i32 @main() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
entry:
invoke void @throwException()
to label %try.cont unwind label %lpad
lpad:
%p = landingpad { i8*, i32 }
catch i8* bitcast (i8** @_ZTIi to i8*)
%e = extractvalue { i8*, i32 } %p, 0
call i8* @__cxa_begin_catch(i8* %e)
call void @__cxa_end_catch()
br label %try.cont
try.cont:
ret i32 0
}

View File

@ -1,21 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -force-interpreter=true %s | FileCheck %s
; CHECK: 40091eb8
define i32 @test(double %x) {
entry:
%x46.i = bitcast double %x to i64
%tmp343.i = lshr i64 %x46.i, 32
%tmp344.i = trunc i64 %tmp343.i to i32
ret i32 %tmp344.i
}
define i32 @main()
{
%res = call i32 @test(double 3.14)
%ptr = getelementptr [4 x i8], [4 x i8]* @format, i32 0, i32 0
call i32 (i8*,...) @printf(i8* %ptr, i32 %res)
ret i32 0
}
declare i32 @printf(i8*, ...)
@format = internal constant [4 x i8] c"%x\0A\00"

View File

@ -1,11 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
@.LC0 = internal global [12 x i8] c"Hello World\00" ; <[12 x i8]*> [#uses=1]
declare i32 @puts(i8*)
define i32 @main() {
%reg210 = call i32 @puts( i8* getelementptr ([12 x i8], [12 x i8]* @.LC0, i64 0, i64 0) ) ; <i32> [#uses=0]
ret i32 0
}

View File

@ -1,17 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
@X = global i32 7 ; <i32*> [#uses=0]
@msg = internal global [13 x i8] c"Hello World\0A\00" ; <[13 x i8]*> [#uses=1]
declare void @printf([13 x i8]*, ...)
define void @bar() {
call void ([13 x i8]*, ...) @printf( [13 x i8]* @msg )
ret void
}
define i32 @main() {
call void @bar( )
ret i32 0
}

View File

@ -1,27 +0,0 @@
root = config.root
targets = root.targets
if ('X86' in targets) | ('AArch64' in targets) | ('ARM' in targets) | \
('Mips' in targets) | ('PowerPC' in targets) | ('SystemZ' in targets):
config.unsupported = False
else:
config.unsupported = True
# FIXME: autoconf and cmake produce different arch names. We should normalize
# them before getting here.
if root.host_arch not in ['i386', 'x86', 'x86_64', 'AMD64',
'AArch64', 'ARM', 'Mips',
'PowerPC', 'ppc64', 'ppc64le', 'SystemZ']:
config.unsupported = True
if 'armv7' in root.host_arch:
config.unsupported = False
if 'i386-apple-darwin' in root.target_triple:
config.unsupported = True
if 'powerpc' in root.target_triple and not 'powerpc64' in root.target_triple:
config.unsupported = True
# ExecutionEngine tests are not expected to pass in a cross-compilation setup.
if 'native' not in config.available_features:
config.unsupported = True

View File

@ -1,24 +0,0 @@
; This first line will generate the .o files for the next run line
; RUN: rm -rf %t.cachedir %t.cachedir2 %t.cachedir3
; RUN: mkdir -p %t.cachedir %t.cachedir2 %t.cachedir3
; RUN: %lli -jit-kind=orc-mcjit -extra-module=%p/Inputs/multi-module-b.ll -extra-module=%p/Inputs/multi-module-c.ll -enable-cache-manager -object-cache-dir=%t.cachedir %s
; Collect generated objects.
; RUN: find %t.cachedir -type f -name 'multi-module-?.o' -exec mv -v '{}' %t.cachedir2 ';'
; This line tests MCJIT object loading
; RUN: %lli -jit-kind=orc-mcjit -extra-object=%t.cachedir2/multi-module-b.o -extra-object=%t.cachedir2/multi-module-c.o %s
; These lines put the object files into an archive
; RUN: llvm-ar r %t.cachedir3/load-object.a %t.cachedir2/multi-module-b.o
; RUN: llvm-ar r %t.cachedir3/load-object.a %t.cachedir2/multi-module-c.o
; This line test MCJIT archive loading
; RUN: %lli -jit-kind=orc-mcjit -extra-archive=%t.cachedir3/load-object.a %s
declare i32 @FB()
define i32 @main() {
%r = call i32 @FB( ) ; <i32> [#uses=1]
ret i32 %r
}

View File

@ -1,9 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -extra-module=%p/Inputs/multi-module-b.ll -extra-module=%p/Inputs/multi-module-c.ll %s > /dev/null
declare i32 @FB()
define i32 @main() {
%r = call i32 @FB( ) ; <i32> [#uses=1]
ret i32 %r
}

View File

@ -1,36 +0,0 @@
; REQUIRES: cxx-shared-library
; RUN: %lli -jit-kind=orc-mcjit -extra-module=%p/Inputs/multi-module-eh-b.ll %s
; XFAIL: arm, cygwin, windows-msvc, windows-gnu
declare i8* @__cxa_allocate_exception(i64)
declare void @__cxa_throw(i8*, i8*, i8*)
declare i32 @__gxx_personality_v0(...)
declare void @__cxa_end_catch()
declare i8* @__cxa_begin_catch(i8*)
@_ZTIi = external constant i8*
declare i32 @FB()
define void @throwException() {
%exception = tail call i8* @__cxa_allocate_exception(i64 4)
call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null)
unreachable
}
define i32 @main() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
entry:
invoke void @throwException()
to label %try.cont unwind label %lpad
lpad:
%p = landingpad { i8*, i32 }
catch i8* bitcast (i8** @_ZTIi to i8*)
%e = extractvalue { i8*, i32 } %p, 0
call i8* @__cxa_begin_catch(i8* %e)
call void @__cxa_end_catch()
br label %try.cont
try.cont:
%r = call i32 @FB( )
ret i32 %r
}

View File

@ -1,10 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -extra-module=%p/Inputs/multi-module-b.ll -extra-module=%p/Inputs/multi-module-c.ll -relocation-model=pic -code-model=small %s > /dev/null
; XFAIL: mips-, mipsel-, i686, i386
declare i32 @FB()
define i32 @main() {
%r = call i32 @FB( ) ; <i32> [#uses=1]
ret i32 %r
}

View File

@ -1,21 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
define i32 @foo(i32 %x, i32 %y, double %d) {
entry:
%d.int64 = bitcast double %d to i64
%d.top64 = lshr i64 %d.int64, 32
%d.top = trunc i64 %d.top64 to i32
%d.bottom = trunc i64 %d.int64 to i32
%topCorrect = icmp eq i32 %d.top, 3735928559
%bottomCorrect = icmp eq i32 %d.bottom, 4277009102
%right = and i1 %topCorrect, %bottomCorrect
%nRight = xor i1 %right, true
%retVal = zext i1 %nRight to i32
ret i32 %retVal
}
define i32 @main() {
entry:
%call = call i32 @foo(i32 0, i32 1, double 0xDEADBEEFFEEDFACE)
ret i32 %call
}

View File

@ -1,88 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -O0 -disable-lazy-compilation=false %s
; The intention of this test is to verify that symbols mapped to COMMON in ELF
; work as expected.
;
; Compiled from this C code:
;
; int zero_int;
; double zero_double;
; int zero_arr[10];
;
; int main()
; {
; zero_arr[zero_int + 5] = 40;
;
; if (zero_double < 1.1)
; zero_arr[zero_int + 2] = 70;
;
; for (int i = 1; i < 10; ++i) {
; zero_arr[i] = zero_arr[i - 1] + zero_arr[i];
; }
; return zero_arr[9] == 110 ? 0 : -1;
; }
@zero_int = common global i32 0, align 4
@zero_arr = common global [10 x i32] zeroinitializer, align 16
@zero_double = common global double 0.000000e+00, align 8
define i32 @main() nounwind {
entry:
%retval = alloca i32, align 4
%i = alloca i32, align 4
store i32 0, i32* %retval
%0 = load i32, i32* @zero_int, align 4
%add = add nsw i32 %0, 5
%idxprom = sext i32 %add to i64
%arrayidx = getelementptr inbounds [10 x i32], [10 x i32]* @zero_arr, i32 0, i64 %idxprom
store i32 40, i32* %arrayidx, align 4
%1 = load double, double* @zero_double, align 8
%cmp = fcmp olt double %1, 1.100000e+00
br i1 %cmp, label %if.then, label %if.end
if.then: ; preds = %entry
%2 = load i32, i32* @zero_int, align 4
%add1 = add nsw i32 %2, 2
%idxprom2 = sext i32 %add1 to i64
%arrayidx3 = getelementptr inbounds [10 x i32], [10 x i32]* @zero_arr, i32 0, i64 %idxprom2
store i32 70, i32* %arrayidx3, align 4
br label %if.end
if.end: ; preds = %if.then, %entry
store i32 1, i32* %i, align 4
br label %for.cond
for.cond: ; preds = %for.inc, %if.end
%3 = load i32, i32* %i, align 4
%cmp4 = icmp slt i32 %3, 10
br i1 %cmp4, label %for.body, label %for.end
for.body: ; preds = %for.cond
%4 = load i32, i32* %i, align 4
%sub = sub nsw i32 %4, 1
%idxprom5 = sext i32 %sub to i64
%arrayidx6 = getelementptr inbounds [10 x i32], [10 x i32]* @zero_arr, i32 0, i64 %idxprom5
%5 = load i32, i32* %arrayidx6, align 4
%6 = load i32, i32* %i, align 4
%idxprom7 = sext i32 %6 to i64
%arrayidx8 = getelementptr inbounds [10 x i32], [10 x i32]* @zero_arr, i32 0, i64 %idxprom7
%7 = load i32, i32* %arrayidx8, align 4
%add9 = add nsw i32 %5, %7
%8 = load i32, i32* %i, align 4
%idxprom10 = sext i32 %8 to i64
%arrayidx11 = getelementptr inbounds [10 x i32], [10 x i32]* @zero_arr, i32 0, i64 %idxprom10
store i32 %add9, i32* %arrayidx11, align 4
br label %for.inc
for.inc: ; preds = %for.body
%9 = load i32, i32* %i, align 4
%inc = add nsw i32 %9, 1
store i32 %inc, i32* %i, align 4
br label %for.cond
for.end: ; preds = %for.cond
%10 = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @zero_arr, i32 0, i64 9), align 4
%cmp12 = icmp eq i32 %10, 110
%cond = select i1 %cmp12, i32 0, i32 -1
ret i32 %cond
}

View File

@ -1,28 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s
; This test is intended to verify that a function weakly defined in
; JITted code, and strongly defined in the main executable, can be
; correctly resolved when called from elsewhere in JITted code.
; This test makes the assumption that the lli executable in compiled
; to export symbols (e.g. --export-dynamic), and that is actually does
; contain the symbol LLVMInitializeCodeGen. (Note that this function
; is not actually called by the test. The test simply verifes that
; the reference can be resolved without relocation errors.)
define linkonce_odr void @LLVMInitializeCodeGen() {
entry:
ret void
}
define void @test() {
entry:
call void @LLVMInitializeCodeGen()
ret void
}
define i32 @main() {
entry:
ret i32 0
}

View File

@ -1,7 +0,0 @@
declare i32 @FA()
define i32 @FB() nounwind {
%r = call i32 @FA( ) ; <i32> [#uses=1]
ret i32 %r
}

View File

@ -1,7 +0,0 @@
declare i32 @FC()
define i32 @FB() nounwind {
%r = call i32 @FC( ) ; <i32> [#uses=1]
ret i32 %r
}

View File

@ -1,4 +0,0 @@
define i32 @FC() nounwind {
ret i32 0
}

View File

@ -1,15 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -extra-module=%p/Inputs/cross-module-b.ll -disable-lazy-compilation=true -remote-mcjit -mcjit-remote-process=lli-child-target%exeext %s > /dev/null
; XFAIL: windows-gnu,windows-msvc
; UNSUPPORTED: powerpc64-unknown-linux-gnu
; Remove UNSUPPORTED for powerpc64-unknown-linux-gnu if problem caused by r266663 is fixed
declare i32 @FB()
define i32 @FA() nounwind {
ret i32 0
}
define i32 @main() nounwind {
%r = call i32 @FB( ) ; <i32> [#uses=1]
ret i32 %r
}

View File

@ -1,35 +0,0 @@
; REQUIRES: cxx-shared-library
; RUN: %lli -remote-mcjit -mcjit-remote-process=lli-child-target%exeext %s
; XFAIL: arm, cygwin, windows-msvc, windows-gnu
; UNSUPPORTED: powerpc64-unknown-linux-gnu
; Remove UNSUPPORTED for powerpc64-unknown-linux-gnu if problem caused by r266663 is fixed
declare i8* @__cxa_allocate_exception(i64)
declare void @__cxa_throw(i8*, i8*, i8*)
declare i32 @__gxx_personality_v0(...)
declare void @__cxa_end_catch()
declare i8* @__cxa_begin_catch(i8*)
@_ZTIi = external constant i8*
define void @throwException() {
%exception = tail call i8* @__cxa_allocate_exception(i64 4)
call void @__cxa_throw(i8* %exception, i8* bitcast (i8** @_ZTIi to i8*), i8* null)
unreachable
}
define i32 @main() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
entry:
invoke void @throwException()
to label %try.cont unwind label %lpad
lpad:
%p = landingpad { i8*, i32 }
catch i8* bitcast (i8** @_ZTIi to i8*)
%e = extractvalue { i8*, i32 } %p, 0
call i8* @__cxa_begin_catch(i8* %e)
call void @__cxa_end_catch()
br label %try.cont
try.cont:
ret i32 0
}

View File

@ -1,8 +0,0 @@
if 'armv4' in config.root.target_triple or \
'armv5' in config.root.target_triple:
config.unsupported = True
# This is temporary, until Remote MCJIT works on ARM
# See http://llvm.org/bugs/show_bug.cgi?id=18057
#if 'armv7' in config.root.target_triple:
# config.unsupported = True

View File

@ -1,12 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -extra-module=%p/Inputs/multi-module-b.ll -extra-module=%p/Inputs/multi-module-c.ll -disable-lazy-compilation=true -remote-mcjit -mcjit-remote-process=lli-child-target%exeext %s > /dev/null
; XFAIL: windows-gnu,windows-msvc
; UNSUPPORTED: powerpc64-unknown-linux-gnu
; Remove UNSUPPORTED for powerpc64-unknown-linux-gnu if problem caused by r266663 is fixed
declare i32 @FB()
define i32 @main() nounwind {
%r = call i32 @FB( ) ; <i32> [#uses=1]
ret i32 %r
}

View File

@ -1,13 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -remote-mcjit -mcjit-remote-process=lli-child-target%exeext %s > /dev/null
; XFAIL: windows-gnu,windows-msvc
; UNSUPPORTED: powerpc64-unknown-linux-gnu
; Remove UNSUPPORTED for powerpc64-unknown-linux-gnu if problem caused by r266663 is fixed
define i32 @bar() nounwind {
ret i32 0
}
define i32 @main() nounwind {
%r = call i32 @bar( ) ; <i32> [#uses=1]
ret i32 %r
}

View File

@ -1,38 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -remote-mcjit -disable-lazy-compilation=false -mcjit-remote-process=lli-child-target%exeext %s
; XFAIL: windows-gnu,windows-msvc
; UNSUPPORTED: powerpc64-unknown-linux-gnu
; Remove UNSUPPORTED for powerpc64-unknown-linux-gnu if problem caused by r266663 is fixed
define i32 @main() nounwind {
entry:
call void @lazily_compiled_address_is_consistent()
ret i32 0
}
; Test PR3043: @test should have the same address before and after
; it's JIT-compiled.
@funcPtr = common global i1 ()* null, align 4
@lcaic_failure = internal constant [46 x i8] c"@lazily_compiled_address_is_consistent failed\00"
define void @lazily_compiled_address_is_consistent() nounwind {
entry:
store i1 ()* @test, i1 ()** @funcPtr
%pass = tail call i1 @test() ; <i32> [#uses=1]
br i1 %pass, label %pass_block, label %fail_block
pass_block:
ret void
fail_block:
call i32 @puts(i8* getelementptr([46 x i8], [46 x i8]* @lcaic_failure, i32 0, i32 0))
call void @exit(i32 1)
unreachable
}
define i1 @test() nounwind {
entry:
%tmp = load i1 ()*, i1 ()** @funcPtr
%eq = icmp eq i1 ()* %tmp, @test
ret i1 %eq
}
declare i32 @puts(i8*) noreturn
declare void @exit(i32) noreturn

View File

@ -1,37 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -remote-mcjit -disable-lazy-compilation=false -relocation-model=pic -code-model=small %s
; XFAIL: *
; This function should fail until remote symbol resolution is supported.
define i32 @main() nounwind {
entry:
call void @lazily_compiled_address_is_consistent()
ret i32 0
}
; Test PR3043: @test should have the same address before and after
; it's JIT-compiled.
@funcPtr = common global i1 ()* null, align 4
@lcaic_failure = internal constant [46 x i8] c"@lazily_compiled_address_is_consistent failed\00"
define void @lazily_compiled_address_is_consistent() nounwind {
entry:
store i1 ()* @test, i1 ()** @funcPtr
%pass = tail call i1 @test() ; <i32> [#uses=1]
br i1 %pass, label %pass_block, label %fail_block
pass_block:
ret void
fail_block:
call i32 @puts(i8* getelementptr([46 x i8], [46 x i8]* @lcaic_failure, i32 0, i32 0))
call void @exit(i32 1)
unreachable
}
define i1 @test() nounwind {
entry:
%tmp = load i1 ()*, i1 ()** @funcPtr
%eq = icmp eq i1 ()* %tmp, @test
ret i1 %eq
}
declare i32 @puts(i8*) noreturn
declare void @exit(i32) noreturn

View File

@ -1,91 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -remote-mcjit -O0 -disable-lazy-compilation=false -mcjit-remote-process=lli-child-target%exeext %s
; XFAIL: windows-gnu,windows-msvc
; UNSUPPORTED: powerpc64-unknown-linux-gnu
; Remove UNSUPPORTED for powerpc64-unknown-linux-gnu if problem caused by r266663 is fixed
; The intention of this test is to verify that symbols mapped to COMMON in ELF
; work as expected.
;
; Compiled from this C code:
;
; int zero_int;
; double zero_double;
; int zero_arr[10];
;
; int main()
; {
; zero_arr[zero_int + 5] = 40;
;
; if (zero_double < 1.0)
; zero_arr[zero_int + 2] = 70;
;
; for (int i = 1; i < 10; ++i) {
; zero_arr[i] = zero_arr[i - 1] + zero_arr[i];
; }
; return zero_arr[9] == 110 ? 0 : -1;
; }
@zero_int = common global i32 0, align 4
@zero_arr = common global [10 x i32] zeroinitializer, align 16
@zero_double = common global double 0.000000e+00, align 8
define i32 @main() nounwind {
entry:
%retval = alloca i32, align 4
%i = alloca i32, align 4
store i32 0, i32* %retval
%0 = load i32, i32* @zero_int, align 4
%add = add nsw i32 %0, 5
%idxprom = sext i32 %add to i64
%arrayidx = getelementptr inbounds [10 x i32], [10 x i32]* @zero_arr, i32 0, i64 %idxprom
store i32 40, i32* %arrayidx, align 4
%1 = load double, double* @zero_double, align 8
%cmp = fcmp olt double %1, 1.000000e+00
br i1 %cmp, label %if.then, label %if.end
if.then: ; preds = %entry
%2 = load i32, i32* @zero_int, align 4
%add1 = add nsw i32 %2, 2
%idxprom2 = sext i32 %add1 to i64
%arrayidx3 = getelementptr inbounds [10 x i32], [10 x i32]* @zero_arr, i32 0, i64 %idxprom2
store i32 70, i32* %arrayidx3, align 4
br label %if.end
if.end: ; preds = %if.then, %entry
store i32 1, i32* %i, align 4
br label %for.cond
for.cond: ; preds = %for.inc, %if.end
%3 = load i32, i32* %i, align 4
%cmp4 = icmp slt i32 %3, 10
br i1 %cmp4, label %for.body, label %for.end
for.body: ; preds = %for.cond
%4 = load i32, i32* %i, align 4
%sub = sub nsw i32 %4, 1
%idxprom5 = sext i32 %sub to i64
%arrayidx6 = getelementptr inbounds [10 x i32], [10 x i32]* @zero_arr, i32 0, i64 %idxprom5
%5 = load i32, i32* %arrayidx6, align 4
%6 = load i32, i32* %i, align 4
%idxprom7 = sext i32 %6 to i64
%arrayidx8 = getelementptr inbounds [10 x i32], [10 x i32]* @zero_arr, i32 0, i64 %idxprom7
%7 = load i32, i32* %arrayidx8, align 4
%add9 = add nsw i32 %5, %7
%8 = load i32, i32* %i, align 4
%idxprom10 = sext i32 %8 to i64
%arrayidx11 = getelementptr inbounds [10 x i32], [10 x i32]* @zero_arr, i32 0, i64 %idxprom10
store i32 %add9, i32* %arrayidx11, align 4
br label %for.inc
for.inc: ; preds = %for.body
%9 = load i32, i32* %i, align 4
%inc = add nsw i32 %9, 1
store i32 %inc, i32* %i, align 4
br label %for.cond
for.end: ; preds = %for.cond
%10 = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @zero_arr, i32 0, i64 9), align 4
%cmp12 = icmp eq i32 %10, 110
%cond = select i1 %cmp12, i32 0, i32 -1
ret i32 %cond
}

View File

@ -1,18 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -remote-mcjit -O0 -mcjit-remote-process=lli-child-target%exeext %s
; XFAIL: windows-gnu,windows-msvc
; UNSUPPORTED: powerpc64-unknown-linux-gnu
; Remove UNSUPPORTED for powerpc64-unknown-linux-gnu if problem caused by r266663 is fixed
; Check that a variable is always aligned as specified.
@var = global i32 0, align 32
define i32 @main() nounwind {
%addr = ptrtoint i32* @var to i64
%mask = and i64 %addr, 31
%tst = icmp eq i64 %mask, 0
br i1 %tst, label %good, label %bad
good:
ret i32 0
bad:
ret i32 1
}

View File

@ -1,23 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -remote-mcjit -mcjit-remote-process=lli-child-target%exeext %s > /dev/null
; XFAIL: windows-gnu,windows-msvc
; UNSUPPORTED: powerpc64-unknown-linux-gnu
; Remove UNSUPPORTED for powerpc64-unknown-linux-gnu if problem caused by r266663 is fixed
define double @test(double* %DP, double %Arg) nounwind {
%D = load double, double* %DP ; <double> [#uses=1]
%V = fadd double %D, 1.000000e+00 ; <double> [#uses=2]
%W = fsub double %V, %V ; <double> [#uses=3]
%X = fmul double %W, %W ; <double> [#uses=2]
%Y = fdiv double %X, %X ; <double> [#uses=2]
%Q = fadd double %Y, %Arg ; <double> [#uses=1]
%R = bitcast double %Q to double ; <double> [#uses=1]
store double %Q, double* %DP
ret double %Y
}
define i32 @main() nounwind {
%X = alloca double ; <double*> [#uses=2]
store double 0.000000e+00, double* %X
call double @test( double* %X, double 2.000000e+00 ) ; <double>:1 [#uses=0]
ret i32 0
}

View File

@ -1,37 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -remote-mcjit -mcjit-remote-process=lli-child-target%exeext %s > /dev/null
; XFAIL: windows-gnu,windows-msvc
; UNSUPPORTED: powerpc64-unknown-linux-gnu
; Remove UNSUPPORTED for powerpc64-unknown-linux-gnu if problem caused by r266663 is fixed
@count = global i32 1, align 4
define i32 @main() nounwind {
entry:
%retval = alloca i32, align 4
%i = alloca i32, align 4
store i32 0, i32* %retval
store i32 0, i32* %i, align 4
br label %for.cond
for.cond: ; preds = %for.inc, %entry
%0 = load i32, i32* %i, align 4
%cmp = icmp slt i32 %0, 49
br i1 %cmp, label %for.body, label %for.end
for.body: ; preds = %for.cond
%1 = load i32, i32* @count, align 4
%inc = add nsw i32 %1, 1
store i32 %inc, i32* @count, align 4
br label %for.inc
for.inc: ; preds = %for.body
%2 = load i32, i32* %i, align 4
%inc1 = add nsw i32 %2, 1
store i32 %inc1, i32* %i, align 4
br label %for.cond
for.end: ; preds = %for.cond
%3 = load i32, i32* @count, align 4
%sub = sub nsw i32 %3, 50
ret i32 %sub
}

View File

@ -1,38 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -remote-mcjit -mcjit-remote-process=lli-child-target%exeext \
; RUN: -relocation-model=pic -code-model=small %s > /dev/null
; XFAIL: mips-, mipsel-, aarch64, arm, i686, i386, windows-gnu, windows-msvc
; UNSUPPORTED: powerpc64-unknown-linux-gnu
; Remove UNSUPPORTED for powerpc64-unknown-linux-gnu if problem caused by r266663 is fixed
@count = global i32 1, align 4
define i32 @main() nounwind uwtable {
entry:
%retval = alloca i32, align 4
%i = alloca i32, align 4
store i32 0, i32* %retval
store i32 0, i32* %i, align 4
br label %for.cond
for.cond: ; preds = %for.inc, %entry
%0 = load i32, i32* %i, align 4
%cmp = icmp slt i32 %0, 49
br i1 %cmp, label %for.body, label %for.end
for.body: ; preds = %for.cond
%1 = load i32, i32* @count, align 4
%inc = add nsw i32 %1, 1
store i32 %inc, i32* @count, align 4
br label %for.inc
for.inc: ; preds = %for.body
%2 = load i32, i32* %i, align 4
%inc1 = add nsw i32 %2, 1
store i32 %inc1, i32* %i, align 4
br label %for.cond
for.end: ; preds = %for.cond
%3 = load i32, i32* @count, align 4
%sub = sub nsw i32 %3, 50
ret i32 %sub
}

View File

@ -1,18 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -remote-mcjit -O0 -mcjit-remote-process=lli-child-target%exeext %s
; XFAIL: windows-gnu,windows-msvc
; UNSUPPORTED: powerpc64-unknown-linux-gnu
; Remove UNSUPPORTED for powerpc64-unknown-linux-gnu if problem caused by r266663 is fixed
@.str = private unnamed_addr constant [6 x i8] c"data1\00", align 1
@ptr = global i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i32 0, i32 0), align 4
@.str1 = private unnamed_addr constant [6 x i8] c"data2\00", align 1
@ptr2 = global i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str1, i32 0, i32 0), align 4
define i32 @main(i32 %argc, i8** nocapture %argv) nounwind readonly {
entry:
%0 = load i8*, i8** @ptr, align 4
%1 = load i8*, i8** @ptr2, align 4
%cmp = icmp eq i8* %0, %1
%. = zext i1 %cmp to i32
ret i32 %.
}

View File

@ -1,20 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -remote-mcjit -mcjit-remote-process=lli-child-target%exeext \
; RUN: -O0 -relocation-model=pic -code-model=small %s
; XFAIL: mips-, mipsel-, aarch64, arm, i686, i386, windows-gnu, windows-msvc
; UNSUPPORTED: powerpc64-unknown-linux-gnu
; Remove UNSUPPORTED for powerpc64-unknown-linux-gnu if problem caused by r266663 is fixed
@.str = private unnamed_addr constant [6 x i8] c"data1\00", align 1
@ptr = global i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str, i32 0, i32 0), align 4
@.str1 = private unnamed_addr constant [6 x i8] c"data2\00", align 1
@ptr2 = global i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str1, i32 0, i32 0), align 4
define i32 @main(i32 %argc, i8** nocapture %argv) nounwind readonly {
entry:
%0 = load i8*, i8** @ptr, align 4
%1 = load i8*, i8** @ptr2, align 4
%cmp = icmp eq i8* %0, %1
%. = zext i1 %cmp to i32
ret i32 %.
}

View File

@ -1,6 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
define i32 @main() {
ret i32 0
}

View File

@ -1,11 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
define i32 @bar() {
ret i32 0
}
define i32 @main() {
%r = call i32 @bar( ) ; <i32> [#uses=1]
ret i32 %r
}

View File

@ -1,36 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -disable-lazy-compilation=false -relocation-model=pic -code-model=small %s
; XFAIL: mips-, mipsel-, i686, i386, aarch64, arm
define i32 @main() nounwind {
entry:
call void @lazily_compiled_address_is_consistent()
ret i32 0
}
; Test PR3043: @test should have the same address before and after
; it's JIT-compiled.
@funcPtr = common global i1 ()* null, align 4
@lcaic_failure = internal constant [46 x i8] c"@lazily_compiled_address_is_consistent failed\00"
define void @lazily_compiled_address_is_consistent() nounwind {
entry:
store i1 ()* @test, i1 ()** @funcPtr
%pass = tail call i1 @test() ; <i32> [#uses=1]
br i1 %pass, label %pass_block, label %fail_block
pass_block:
ret void
fail_block:
call i32 @puts(i8* getelementptr([46 x i8], [46 x i8]* @lcaic_failure, i32 0, i32 0))
call void @exit(i32 1)
unreachable
}
define i1 @test() nounwind {
entry:
%tmp = load i1 ()*, i1 ()** @funcPtr
%eq = icmp eq i1 ()* %tmp, @test
ret i1 %eq
}
declare i32 @puts(i8*) noreturn
declare void @exit(i32) noreturn

View File

@ -1,35 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -disable-lazy-compilation=false %s
define i32 @main() nounwind {
entry:
call void @lazily_compiled_address_is_consistent()
ret i32 0
}
; Test PR3043: @test should have the same address before and after
; it's JIT-compiled.
@funcPtr = common global i1 ()* null, align 4
@lcaic_failure = internal constant [46 x i8] c"@lazily_compiled_address_is_consistent failed\00"
define void @lazily_compiled_address_is_consistent() nounwind {
entry:
store i1 ()* @test, i1 ()** @funcPtr
%pass = tail call i1 @test() ; <i32> [#uses=1]
br i1 %pass, label %pass_block, label %fail_block
pass_block:
ret void
fail_block:
call i32 @puts(i8* getelementptr([46 x i8], [46 x i8]* @lcaic_failure, i32 0, i32 0))
call void @exit(i32 1)
unreachable
}
define i1 @test() nounwind {
entry:
%tmp = load i1 ()*, i1 ()** @funcPtr
%eq = icmp eq i1 ()* %tmp, @test
ret i1 %eq
}
declare i32 @puts(i8*) noreturn
declare void @exit(i32) noreturn

View File

@ -1,34 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
define i32 @main() {
%A = add i8 0, 12 ; <i8> [#uses=1]
%B = sub i8 %A, 1 ; <i8> [#uses=2]
%C = mul i8 %B, %B ; <i8> [#uses=2]
%D = sdiv i8 %C, %C ; <i8> [#uses=2]
%E = srem i8 %D, %D ; <i8> [#uses=0]
%F = udiv i8 5, 6 ; <i8> [#uses=0]
%G = urem i8 6, 5 ; <i8> [#uses=0]
%A.upgrd.1 = add i16 0, 12 ; <i16> [#uses=1]
%B.upgrd.2 = sub i16 %A.upgrd.1, 1 ; <i16> [#uses=2]
%C.upgrd.3 = mul i16 %B.upgrd.2, %B.upgrd.2 ; <i16> [#uses=2]
%D.upgrd.4 = sdiv i16 %C.upgrd.3, %C.upgrd.3 ; <i16> [#uses=2]
%E.upgrd.5 = srem i16 %D.upgrd.4, %D.upgrd.4 ; <i16> [#uses=0]
%F.upgrd.6 = udiv i16 5, 6 ; <i16> [#uses=0]
%G.upgrd.7 = urem i32 6, 5 ; <i32> [#uses=0]
%A.upgrd.8 = add i32 0, 12 ; <i32> [#uses=1]
%B.upgrd.9 = sub i32 %A.upgrd.8, 1 ; <i32> [#uses=2]
%C.upgrd.10 = mul i32 %B.upgrd.9, %B.upgrd.9 ; <i32> [#uses=2]
%D.upgrd.11 = sdiv i32 %C.upgrd.10, %C.upgrd.10 ; <i32> [#uses=2]
%E.upgrd.12 = srem i32 %D.upgrd.11, %D.upgrd.11 ; <i32> [#uses=0]
%F.upgrd.13 = udiv i32 5, 6 ; <i32> [#uses=0]
%G1 = urem i32 6, 5 ; <i32> [#uses=0]
%A.upgrd.14 = add i64 0, 12 ; <i64> [#uses=1]
%B.upgrd.15 = sub i64 %A.upgrd.14, 1 ; <i64> [#uses=2]
%C.upgrd.16 = mul i64 %B.upgrd.15, %B.upgrd.15 ; <i64> [#uses=2]
%D.upgrd.17 = sdiv i64 %C.upgrd.16, %C.upgrd.16 ; <i64> [#uses=2]
%E.upgrd.18 = srem i64 %D.upgrd.17, %D.upgrd.17 ; <i64> [#uses=0]
%F.upgrd.19 = udiv i64 5, 6 ; <i64> [#uses=0]
%G.upgrd.20 = urem i64 6, 5 ; <i64> [#uses=0]
ret i32 0
}

View File

@ -1,12 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
; test unconditional branch
define i32 @main() {
br label %Test
Test: ; preds = %Test, %0
%X = icmp eq i32 0, 4 ; <i1> [#uses=1]
br i1 %X, label %Test, label %Label
Label: ; preds = %Test
ret i32 0
}

View File

@ -1,14 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
define i32 @_Z14func_exit_codev() nounwind uwtable {
entry:
ret i32 0
}
define i32 @main() nounwind uwtable {
entry:
%retval = alloca i32, align 4
store i32 0, i32* %retval
%call = call i32 @_Z14func_exit_codev()
ret i32 %call
}

View File

@ -1,21 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
declare void @exit(i32)
define i32 @test(i8 %C, i16 %S) {
%X = trunc i16 %S to i8 ; <i8> [#uses=1]
%Y = zext i8 %X to i32 ; <i32> [#uses=1]
ret i32 %Y
}
define void @FP(void (i32)* %F) {
%X = call i32 @test( i8 123, i16 1024 ) ; <i32> [#uses=1]
call void %F( i32 %X )
ret void
}
define i32 @main() {
call void @FP( void (i32)* @exit )
ret i32 1
}

View File

@ -1,109 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
define i32 @foo() {
ret i32 0
}
define i32 @main() {
icmp ne i1 true, false ; <i1>:1 [#uses=0]
zext i1 true to i8 ; <i8>:2 [#uses=0]
zext i1 true to i8 ; <i8>:3 [#uses=0]
zext i1 true to i16 ; <i16>:4 [#uses=0]
zext i1 true to i16 ; <i16>:5 [#uses=0]
zext i1 true to i32 ; <i32>:6 [#uses=0]
zext i1 true to i32 ; <i32>:7 [#uses=0]
zext i1 true to i64 ; <i64>:8 [#uses=0]
zext i1 true to i64 ; <i64>:9 [#uses=0]
uitofp i1 true to float ; <float>:10 [#uses=0]
uitofp i1 true to double ; <double>:11 [#uses=0]
icmp ne i8 0, 0 ; <i1>:12 [#uses=0]
icmp ne i8 1, 0 ; <i1>:13 [#uses=0]
bitcast i8 0 to i8 ; <i8>:14 [#uses=0]
bitcast i8 -1 to i8 ; <i8>:15 [#uses=0]
sext i8 4 to i16 ; <i16>:16 [#uses=0]
sext i8 4 to i16 ; <i16>:17 [#uses=0]
sext i8 4 to i64 ; <i64>:18 [#uses=0]
sext i8 4 to i64 ; <i64>:19 [#uses=0]
sitofp i8 4 to float ; <float>:20 [#uses=0]
sitofp i8 4 to double ; <double>:21 [#uses=0]
icmp ne i8 0, 0 ; <i1>:22 [#uses=0]
icmp ne i8 1, 0 ; <i1>:23 [#uses=0]
bitcast i8 0 to i8 ; <i8>:24 [#uses=0]
bitcast i8 1 to i8 ; <i8>:25 [#uses=0]
zext i8 4 to i16 ; <i16>:26 [#uses=0]
zext i8 4 to i16 ; <i16>:27 [#uses=0]
zext i8 4 to i64 ; <i64>:28 [#uses=0]
zext i8 4 to i64 ; <i64>:29 [#uses=0]
uitofp i8 0 to float ; <float>:30 [#uses=0]
uitofp i8 0 to double ; <double>:31 [#uses=0]
icmp ne i16 1, 0 ; <i1>:32 [#uses=0]
trunc i16 -1 to i8 ; <i8>:33 [#uses=0]
trunc i16 255 to i8 ; <i8>:34 [#uses=0]
bitcast i16 0 to i16 ; <i16>:35 [#uses=0]
bitcast i16 0 to i16 ; <i16>:36 [#uses=0]
sext i16 0 to i64 ; <i64>:37 [#uses=0]
sext i16 0 to i64 ; <i64>:38 [#uses=0]
sitofp i16 0 to float ; <float>:39 [#uses=0]
sitofp i16 0 to double ; <double>:40 [#uses=0]
icmp ne i16 1, 0 ; <i1>:41 [#uses=0]
trunc i16 1 to i8 ; <i8>:42 [#uses=0]
trunc i16 255 to i8 ; <i8>:43 [#uses=0]
bitcast i16 0 to i16 ; <i16>:44 [#uses=0]
bitcast i16 0 to i16 ; <i16>:45 [#uses=0]
zext i16 0 to i64 ; <i64>:46 [#uses=0]
zext i16 0 to i64 ; <i64>:47 [#uses=0]
uitofp i16 0 to float ; <float>:48 [#uses=0]
uitofp i16 0 to double ; <double>:49 [#uses=0]
icmp ne i32 6, 0 ; <i1>:50 [#uses=0]
trunc i32 -6 to i8 ; <i8>:51 [#uses=0]
trunc i32 6 to i8 ; <i8>:52 [#uses=0]
trunc i32 6 to i16 ; <i16>:53 [#uses=0]
bitcast i32 0 to i32 ; <i32>:54 [#uses=0]
sext i32 0 to i64 ; <i64>:55 [#uses=0]
sext i32 0 to i64 ; <i64>:56 [#uses=0]
sitofp i32 0 to float ; <float>:57 [#uses=0]
sitofp i32 0 to double ; <double>:58 [#uses=0]
icmp ne i32 6, 0 ; <i1>:59 [#uses=0]
trunc i32 7 to i8 ; <i8>:60 [#uses=0]
trunc i32 8 to i8 ; <i8>:61 [#uses=0]
trunc i32 9 to i16 ; <i16>:62 [#uses=0]
bitcast i32 10 to i32 ; <i32>:63 [#uses=0]
zext i32 0 to i64 ; <i64>:64 [#uses=0]
zext i32 0 to i64 ; <i64>:65 [#uses=0]
uitofp i32 0 to float ; <float>:66 [#uses=0]
uitofp i32 0 to double ; <double>:67 [#uses=0]
icmp ne i64 0, 0 ; <i1>:68 [#uses=0]
trunc i64 0 to i8 ; <i8>:69 [#uses=0]
trunc i64 0 to i8 ; <i8>:70 [#uses=0]
trunc i64 0 to i16 ; <i16>:71 [#uses=0]
trunc i64 0 to i16 ; <i16>:72 [#uses=0]
trunc i64 0 to i32 ; <i32>:73 [#uses=0]
trunc i64 0 to i32 ; <i32>:74 [#uses=0]
bitcast i64 0 to i64 ; <i64>:75 [#uses=0]
bitcast i64 0 to i64 ; <i64>:76 [#uses=0]
sitofp i64 0 to float ; <float>:77 [#uses=0]
sitofp i64 0 to double ; <double>:78 [#uses=0]
icmp ne i64 1, 0 ; <i1>:79 [#uses=0]
trunc i64 1 to i8 ; <i8>:80 [#uses=0]
trunc i64 1 to i8 ; <i8>:81 [#uses=0]
trunc i64 1 to i16 ; <i16>:82 [#uses=0]
trunc i64 1 to i16 ; <i16>:83 [#uses=0]
trunc i64 1 to i32 ; <i32>:84 [#uses=0]
trunc i64 1 to i32 ; <i32>:85 [#uses=0]
bitcast i64 1 to i64 ; <i64>:86 [#uses=0]
bitcast i64 1 to i64 ; <i64>:87 [#uses=0]
uitofp i64 1 to float ; <float>:88 [#uses=0]
uitofp i64 0 to double ; <double>:89 [#uses=0]
bitcast float 0.000000e+00 to float ; <float>:90 [#uses=0]
fpext float 0.000000e+00 to double ; <double>:91 [#uses=0]
fptosi double 0.000000e+00 to i8 ; <i8>:92 [#uses=0]
fptoui double 0.000000e+00 to i8 ; <i8>:93 [#uses=0]
fptosi double 0.000000e+00 to i16 ; <i16>:94 [#uses=0]
fptoui double 0.000000e+00 to i16 ; <i16>:95 [#uses=0]
fptosi double 0.000000e+00 to i32 ; <i32>:96 [#uses=0]
fptoui double 0.000000e+00 to i32 ; <i32>:97 [#uses=0]
fptosi double 0.000000e+00 to i64 ; <i64>:98 [#uses=0]
fptrunc double 0.000000e+00 to float ; <float>:99 [#uses=0]
bitcast double 0.000000e+00 to double ; <double>:100 [#uses=0]
ret i32 0
}

View File

@ -1,32 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -O0 %s
; This test checks that common symbols have been allocated addresses honouring
; the alignment requirement.
@CS1 = common global i32 0, align 16
@CS2 = common global i8 0, align 1
@CS3 = common global i32 0, align 16
define i32 @main() nounwind {
entry:
%retval = alloca i32, align 4
%ptr = alloca i32, align 4
store i32 0, i32* %retval
store i32 ptrtoint (i32* @CS3 to i32), i32* %ptr, align 4
%0 = load i32, i32* %ptr, align 4
%and = and i32 %0, 15
%tobool = icmp ne i32 %and, 0
br i1 %tobool, label %if.then, label %if.else
if.then: ; preds = %entry
store i32 1, i32* %retval
br label %return
if.else: ; preds = %entry
store i32 0, i32* %retval
br label %return
return: ; preds = %if.else, %if.then
%1 = load i32, i32* %retval
ret i32 %1
}

View File

@ -1,88 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -O0 -disable-lazy-compilation=false %s
; The intention of this test is to verify that symbols mapped to COMMON in ELF
; work as expected.
;
; Compiled from this C code:
;
; int zero_int;
; double zero_double;
; int zero_arr[10];
;
; int main()
; {
; zero_arr[zero_int + 5] = 40;
;
; if (zero_double < 1.0)
; zero_arr[zero_int + 2] = 70;
;
; for (int i = 1; i < 10; ++i) {
; zero_arr[i] = zero_arr[i - 1] + zero_arr[i];
; }
; return zero_arr[9] == 110 ? 0 : -1;
; }
@zero_int = common global i32 0, align 4
@zero_arr = common global [10 x i32] zeroinitializer, align 16
@zero_double = common global double 0.000000e+00, align 8
define i32 @main() nounwind {
entry:
%retval = alloca i32, align 4
%i = alloca i32, align 4
store i32 0, i32* %retval
%0 = load i32, i32* @zero_int, align 4
%add = add nsw i32 %0, 5
%idxprom = sext i32 %add to i64
%arrayidx = getelementptr inbounds [10 x i32], [10 x i32]* @zero_arr, i32 0, i64 %idxprom
store i32 40, i32* %arrayidx, align 4
%1 = load double, double* @zero_double, align 8
%cmp = fcmp olt double %1, 1.000000e+00
br i1 %cmp, label %if.then, label %if.end
if.then: ; preds = %entry
%2 = load i32, i32* @zero_int, align 4
%add1 = add nsw i32 %2, 2
%idxprom2 = sext i32 %add1 to i64
%arrayidx3 = getelementptr inbounds [10 x i32], [10 x i32]* @zero_arr, i32 0, i64 %idxprom2
store i32 70, i32* %arrayidx3, align 4
br label %if.end
if.end: ; preds = %if.then, %entry
store i32 1, i32* %i, align 4
br label %for.cond
for.cond: ; preds = %for.inc, %if.end
%3 = load i32, i32* %i, align 4
%cmp4 = icmp slt i32 %3, 10
br i1 %cmp4, label %for.body, label %for.end
for.body: ; preds = %for.cond
%4 = load i32, i32* %i, align 4
%sub = sub nsw i32 %4, 1
%idxprom5 = sext i32 %sub to i64
%arrayidx6 = getelementptr inbounds [10 x i32], [10 x i32]* @zero_arr, i32 0, i64 %idxprom5
%5 = load i32, i32* %arrayidx6, align 4
%6 = load i32, i32* %i, align 4
%idxprom7 = sext i32 %6 to i64
%arrayidx8 = getelementptr inbounds [10 x i32], [10 x i32]* @zero_arr, i32 0, i64 %idxprom7
%7 = load i32, i32* %arrayidx8, align 4
%add9 = add nsw i32 %5, %7
%8 = load i32, i32* %i, align 4
%idxprom10 = sext i32 %8 to i64
%arrayidx11 = getelementptr inbounds [10 x i32], [10 x i32]* @zero_arr, i32 0, i64 %idxprom10
store i32 %add9, i32* %arrayidx11, align 4
br label %for.inc
for.inc: ; preds = %for.body
%9 = load i32, i32* %i, align 4
%inc = add nsw i32 %9, 1
store i32 %inc, i32* %i, align 4
br label %for.cond
for.end: ; preds = %for.cond
%10 = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @zero_arr, i32 0, i64 9), align 4
%cmp12 = icmp eq i32 %10, 110
%cond = select i1 %cmp12, i32 0, i32 -1
ret i32 %cond
}

View File

@ -1,12 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
; This tests to make sure that we can evaluate weird constant expressions
@A = global i32 5 ; <i32*> [#uses=1]
@B = global i32 6 ; <i32*> [#uses=1]
define i32 @main() {
%A = or i1 false, icmp slt (i32* @A, i32* @B) ; <i1> [#uses=0]
ret i32 0
}

View File

@ -1,15 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -O0 %s
; Check that a variable is always aligned as specified.
@var = global i32 0, align 32
define i32 @main() {
%addr = ptrtoint i32* @var to i64
%mask = and i64 %addr, 31
%tst = icmp eq i64 %mask, 0
br i1 %tst, label %good, label %bad
good:
ret i32 0
bad:
ret i32 1
}

View File

@ -1,21 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
define double @test(double* %DP, double %Arg) {
%D = load double, double* %DP ; <double> [#uses=1]
%V = fadd double %D, 1.000000e+00 ; <double> [#uses=2]
%W = fsub double %V, %V ; <double> [#uses=3]
%X = fmul double %W, %W ; <double> [#uses=2]
%Y = fdiv double %X, %X ; <double> [#uses=2]
%Q = fadd double %Y, %Arg ; <double> [#uses=1]
%R = bitcast double %Q to double ; <double> [#uses=1]
store double %Q, double* %DP
ret double %Y
}
define i32 @main() {
%X = alloca double ; <double*> [#uses=2]
store double 0.000000e+00, double* %X
call double @test( double* %X, double 2.000000e+00 ) ; <double>:1 [#uses=0]
ret i32 0
}

View File

@ -1,23 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
define double @test(double* %DP, double %Arg) {
%D = load double, double* %DP ; <double> [#uses=1]
%V = fadd double %D, 1.000000e+00 ; <double> [#uses=2]
%W = fsub double %V, %V ; <double> [#uses=3]
%X = fmul double %W, %W ; <double> [#uses=2]
%Y = fdiv double %X, %X ; <double> [#uses=2]
%Z = frem double %Y, %Y ; <double> [#uses=3]
%Z1 = fdiv double %Z, %W ; <double> [#uses=0]
%Q = fadd double %Z, %Arg ; <double> [#uses=1]
%R = bitcast double %Q to double ; <double> [#uses=1]
store double %R, double* %DP
ret double %Z
}
define i32 @main() {
%X = alloca double ; <double*> [#uses=2]
store double 0.000000e+00, double* %X
call double @test( double* %X, double 2.000000e+00 ) ; <double>:1 [#uses=0]
ret i32 0
}

View File

@ -1,22 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
; XFAIL: darwin
@var = global i32 1, align 4
@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @ctor_func, i8* null }]
@llvm.global_dtors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @dtor_func, i8* null }]
define i32 @main() nounwind {
entry:
%0 = load i32, i32* @var, align 4
ret i32 %0
}
define internal void @ctor_func() section ".text.startup" {
entry:
store i32 0, i32* @var, align 4
ret void
}
define internal void @dtor_func() section ".text.startup" {
entry:
ret void
}

View File

@ -1,35 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit -relocation-model=pic -code-model=small %s > /dev/null
; XFAIL: mips-, mipsel-, aarch64, arm, i686, i386
@count = global i32 1, align 4
define i32 @main() nounwind uwtable {
entry:
%retval = alloca i32, align 4
%i = alloca i32, align 4
store i32 0, i32* %retval
store i32 0, i32* %i, align 4
br label %for.cond
for.cond: ; preds = %for.inc, %entry
%0 = load i32, i32* %i, align 4
%cmp = icmp slt i32 %0, 49
br i1 %cmp, label %for.body, label %for.end
for.body: ; preds = %for.cond
%1 = load i32, i32* @count, align 4
%inc = add nsw i32 %1, 1
store i32 %inc, i32* @count, align 4
br label %for.inc
for.inc: ; preds = %for.body
%2 = load i32, i32* %i, align 4
%inc1 = add nsw i32 %2, 1
store i32 %inc1, i32* %i, align 4
br label %for.cond
for.end: ; preds = %for.cond
%3 = load i32, i32* @count, align 4
%sub = sub nsw i32 %3, 50
ret i32 %sub
}

View File

@ -1,34 +0,0 @@
; RUN: %lli -jit-kind=orc-mcjit %s > /dev/null
@count = global i32 1, align 4
define i32 @main() nounwind uwtable {
entry:
%retval = alloca i32, align 4
%i = alloca i32, align 4
store i32 0, i32* %retval
store i32 0, i32* %i, align 4
br label %for.cond
for.cond: ; preds = %for.inc, %entry
%0 = load i32, i32* %i, align 4
%cmp = icmp slt i32 %0, 49
br i1 %cmp, label %for.body, label %for.end
for.body: ; preds = %for.cond
%1 = load i32, i32* @count, align 4
%inc = add nsw i32 %1, 1
store i32 %inc, i32* @count, align 4
br label %for.inc
for.inc: ; preds = %for.body
%2 = load i32, i32* %i, align 4
%inc1 = add nsw i32 %2, 1
store i32 %inc1, i32* %i, align 4
br label %for.cond
for.end: ; preds = %for.cond
%3 = load i32, i32* @count, align 4
%sub = sub nsw i32 %3, 50
ret i32 %sub
}

Some files were not shown because too many files have changed in this diff Show More