2018-06-19 02:01:43 +08:00
|
|
|
//===----- CompileOnDemandLayer.cpp - Lazily emit IR on first call --------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// 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
|
2018-06-19 02:01:43 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
|
2020-02-23 01:49:55 +08:00
|
|
|
|
|
|
|
#include "llvm/ADT/Hashing.h"
|
[ORC] Add generic initializer/deinitializer support.
Initializers and deinitializers are used to implement C++ static constructors
and destructors, runtime registration for some languages (e.g. with the
Objective-C runtime for Objective-C/C++ code) and other tasks that would
typically be performed when a shared-object/dylib is loaded or unloaded by a
statically compiled program.
MCJIT and ORC have historically provided limited support for discovering and
running initializers/deinitializers by scanning the llvm.global_ctors and
llvm.global_dtors variables and recording the functions to be run. This approach
suffers from several drawbacks: (1) It only works for IR inputs, not for object
files (including cached JIT'd objects). (2) It only works for initializers
described by llvm.global_ctors and llvm.global_dtors, however not all
initializers are described in this way (Objective-C, for example, describes
initializers via specially named metadata sections). (3) To make the
initializer/deinitializer functions described by llvm.global_ctors and
llvm.global_dtors searchable they must be promoted to extern linkage, polluting
the JIT symbol table (extra care must be taken to ensure this promotion does
not result in symbol name clashes).
This patch introduces several interdependent changes to ORCv2 to support the
construction of new initialization schemes, and includes an implementation of a
backwards-compatible llvm.global_ctor/llvm.global_dtor scanning scheme, and a
MachO specific scheme that handles Objective-C runtime registration (if the
Objective-C runtime is available) enabling execution of LLVM IR compiled from
Objective-C and Swift.
The major changes included in this patch are:
(1) The MaterializationUnit and MaterializationResponsibility classes are
extended to describe an optional "initializer" symbol for the module (see the
getInitializerSymbol method on each class). The presence or absence of this
symbol indicates whether the module contains any initializers or
deinitializers. The initializer symbol otherwise behaves like any other:
searching for it triggers materialization.
(2) A new Platform interface is introduced in llvm/ExecutionEngine/Orc/Core.h
which provides the following callback interface:
- Error setupJITDylib(JITDylib &JD): Can be used to install standard symbols
in JITDylibs upon creation. E.g. __dso_handle.
- Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU): Generally
used to record initializer symbols.
- Error notifyRemoving(JITDylib &JD, VModuleKey K): Used to notify a platform
that a module is being removed.
Platform implementations can use these callbacks to track outstanding
initializers and implement a platform-specific approach for executing them. For
example, the MachOPlatform installs a plugin in the JIT linker to scan for both
__mod_inits sections (for C++ static constructors) and ObjC metadata sections.
If discovered, these are processed in the usual platform order: Objective-C
registration is carried out first, then static initializers are executed,
ensuring that calls to Objective-C from static initializers will be safe.
This patch updates LLJIT to use the new scheme for initialization. Two
LLJIT::PlatformSupport classes are implemented: A GenericIR platform and a MachO
platform. The GenericIR platform implements a modified version of the previous
llvm.global-ctor scraping scheme to provide support for Windows and
Linux. LLJIT's MachO platform uses the MachOPlatform class to provide MachO
specific initialization as described above.
Reviewers: sgraenitz, dblaikie
Subscribers: mgorny, hiraditya, mgrang, ributzka, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D74300
2019-12-16 18:50:40 +08:00
|
|
|
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
|
2018-06-19 02:01:43 +08:00
|
|
|
#include "llvm/IR/Mangler.h"
|
|
|
|
#include "llvm/IR/Module.h"
|
2020-02-23 01:49:55 +08:00
|
|
|
#include "llvm/Support/FormatVariadic.h"
|
2018-06-19 02:01:43 +08:00
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
using namespace llvm::orc;
|
|
|
|
|
2018-09-30 07:49:57 +08:00
|
|
|
static ThreadSafeModule extractSubModule(ThreadSafeModule &TSM,
|
|
|
|
StringRef Suffix,
|
|
|
|
GVPredicate ShouldExtract) {
|
2018-06-27 05:35:48 +08:00
|
|
|
|
2018-09-30 07:49:57 +08:00
|
|
|
auto DeleteExtractedDefs = [](GlobalValue &GV) {
|
|
|
|
// Bump the linkage: this global will be provided by the external module.
|
|
|
|
GV.setLinkage(GlobalValue::ExternalLinkage);
|
2018-06-19 02:01:43 +08:00
|
|
|
|
2018-09-30 07:49:57 +08:00
|
|
|
// Delete the definition in the source module.
|
2018-09-26 09:24:12 +08:00
|
|
|
if (isa<Function>(GV)) {
|
|
|
|
auto &F = cast<Function>(GV);
|
|
|
|
F.deleteBody();
|
|
|
|
F.setPersonalityFn(nullptr);
|
|
|
|
} else if (isa<GlobalVariable>(GV)) {
|
|
|
|
cast<GlobalVariable>(GV).setInitializer(nullptr);
|
2018-09-30 07:49:57 +08:00
|
|
|
} else if (isa<GlobalAlias>(GV)) {
|
|
|
|
// We need to turn deleted aliases into function or variable decls based
|
|
|
|
// on the type of their aliasee.
|
|
|
|
auto &A = cast<GlobalAlias>(GV);
|
|
|
|
Constant *Aliasee = A.getAliasee();
|
|
|
|
assert(A.hasName() && "Anonymous alias?");
|
|
|
|
assert(Aliasee->hasName() && "Anonymous aliasee");
|
2020-01-29 03:23:46 +08:00
|
|
|
std::string AliasName = std::string(A.getName());
|
2018-09-30 07:49:57 +08:00
|
|
|
|
|
|
|
if (isa<Function>(Aliasee)) {
|
|
|
|
auto *F = cloneFunctionDecl(*A.getParent(), *cast<Function>(Aliasee));
|
|
|
|
A.replaceAllUsesWith(F);
|
|
|
|
A.eraseFromParent();
|
|
|
|
F->setName(AliasName);
|
|
|
|
} else if (isa<GlobalVariable>(Aliasee)) {
|
|
|
|
auto *G = cloneGlobalVariableDecl(*A.getParent(),
|
|
|
|
*cast<GlobalVariable>(Aliasee));
|
|
|
|
A.replaceAllUsesWith(G);
|
|
|
|
A.eraseFromParent();
|
|
|
|
G->setName(AliasName);
|
|
|
|
} else
|
|
|
|
llvm_unreachable("Alias to unsupported type");
|
2018-09-26 09:24:12 +08:00
|
|
|
} else
|
|
|
|
llvm_unreachable("Unsupported global type");
|
|
|
|
};
|
2018-06-19 02:01:43 +08:00
|
|
|
|
2019-08-02 23:21:37 +08:00
|
|
|
auto NewTSM = cloneToNewContext(TSM, ShouldExtract, DeleteExtractedDefs);
|
|
|
|
NewTSM.withModuleDo([&](Module &M) {
|
|
|
|
M.setModuleIdentifier((M.getModuleIdentifier() + Suffix).str());
|
|
|
|
});
|
2018-06-19 02:01:43 +08:00
|
|
|
|
2019-08-02 23:21:37 +08:00
|
|
|
return NewTSM;
|
2018-07-06 03:01:27 +08:00
|
|
|
}
|
2018-06-19 02:01:43 +08:00
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
namespace orc {
|
|
|
|
|
2018-09-30 07:49:57 +08:00
|
|
|
class PartitioningIRMaterializationUnit : public IRMaterializationUnit {
|
2018-06-19 02:01:43 +08:00
|
|
|
public:
|
2020-01-22 08:28:30 +08:00
|
|
|
PartitioningIRMaterializationUnit(ExecutionSession &ES,
|
[ORC] Add generic initializer/deinitializer support.
Initializers and deinitializers are used to implement C++ static constructors
and destructors, runtime registration for some languages (e.g. with the
Objective-C runtime for Objective-C/C++ code) and other tasks that would
typically be performed when a shared-object/dylib is loaded or unloaded by a
statically compiled program.
MCJIT and ORC have historically provided limited support for discovering and
running initializers/deinitializers by scanning the llvm.global_ctors and
llvm.global_dtors variables and recording the functions to be run. This approach
suffers from several drawbacks: (1) It only works for IR inputs, not for object
files (including cached JIT'd objects). (2) It only works for initializers
described by llvm.global_ctors and llvm.global_dtors, however not all
initializers are described in this way (Objective-C, for example, describes
initializers via specially named metadata sections). (3) To make the
initializer/deinitializer functions described by llvm.global_ctors and
llvm.global_dtors searchable they must be promoted to extern linkage, polluting
the JIT symbol table (extra care must be taken to ensure this promotion does
not result in symbol name clashes).
This patch introduces several interdependent changes to ORCv2 to support the
construction of new initialization schemes, and includes an implementation of a
backwards-compatible llvm.global_ctor/llvm.global_dtor scanning scheme, and a
MachO specific scheme that handles Objective-C runtime registration (if the
Objective-C runtime is available) enabling execution of LLVM IR compiled from
Objective-C and Swift.
The major changes included in this patch are:
(1) The MaterializationUnit and MaterializationResponsibility classes are
extended to describe an optional "initializer" symbol for the module (see the
getInitializerSymbol method on each class). The presence or absence of this
symbol indicates whether the module contains any initializers or
deinitializers. The initializer symbol otherwise behaves like any other:
searching for it triggers materialization.
(2) A new Platform interface is introduced in llvm/ExecutionEngine/Orc/Core.h
which provides the following callback interface:
- Error setupJITDylib(JITDylib &JD): Can be used to install standard symbols
in JITDylibs upon creation. E.g. __dso_handle.
- Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU): Generally
used to record initializer symbols.
- Error notifyRemoving(JITDylib &JD, VModuleKey K): Used to notify a platform
that a module is being removed.
Platform implementations can use these callbacks to track outstanding
initializers and implement a platform-specific approach for executing them. For
example, the MachOPlatform installs a plugin in the JIT linker to scan for both
__mod_inits sections (for C++ static constructors) and ObjC metadata sections.
If discovered, these are processed in the usual platform order: Objective-C
registration is carried out first, then static initializers are executed,
ensuring that calls to Objective-C from static initializers will be safe.
This patch updates LLJIT to use the new scheme for initialization. Two
LLJIT::PlatformSupport classes are implemented: A GenericIR platform and a MachO
platform. The GenericIR platform implements a modified version of the previous
llvm.global-ctor scraping scheme to provide support for Windows and
Linux. LLJIT's MachO platform uses the MachOPlatform class to provide MachO
specific initialization as described above.
Reviewers: sgraenitz, dblaikie
Subscribers: mgorny, hiraditya, mgrang, ributzka, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D74300
2019-12-16 18:50:40 +08:00
|
|
|
const IRSymbolMapper::ManglingOptions &MO,
|
2020-01-22 08:28:30 +08:00
|
|
|
ThreadSafeModule TSM, VModuleKey K,
|
|
|
|
CompileOnDemandLayer &Parent)
|
|
|
|
: IRMaterializationUnit(ES, MO, std::move(TSM), std::move(K)),
|
2018-10-17 04:13:06 +08:00
|
|
|
Parent(Parent) {}
|
2018-07-21 02:31:50 +08:00
|
|
|
|
2018-09-30 07:49:57 +08:00
|
|
|
PartitioningIRMaterializationUnit(
|
[ORC] Add generic initializer/deinitializer support.
Initializers and deinitializers are used to implement C++ static constructors
and destructors, runtime registration for some languages (e.g. with the
Objective-C runtime for Objective-C/C++ code) and other tasks that would
typically be performed when a shared-object/dylib is loaded or unloaded by a
statically compiled program.
MCJIT and ORC have historically provided limited support for discovering and
running initializers/deinitializers by scanning the llvm.global_ctors and
llvm.global_dtors variables and recording the functions to be run. This approach
suffers from several drawbacks: (1) It only works for IR inputs, not for object
files (including cached JIT'd objects). (2) It only works for initializers
described by llvm.global_ctors and llvm.global_dtors, however not all
initializers are described in this way (Objective-C, for example, describes
initializers via specially named metadata sections). (3) To make the
initializer/deinitializer functions described by llvm.global_ctors and
llvm.global_dtors searchable they must be promoted to extern linkage, polluting
the JIT symbol table (extra care must be taken to ensure this promotion does
not result in symbol name clashes).
This patch introduces several interdependent changes to ORCv2 to support the
construction of new initialization schemes, and includes an implementation of a
backwards-compatible llvm.global_ctor/llvm.global_dtor scanning scheme, and a
MachO specific scheme that handles Objective-C runtime registration (if the
Objective-C runtime is available) enabling execution of LLVM IR compiled from
Objective-C and Swift.
The major changes included in this patch are:
(1) The MaterializationUnit and MaterializationResponsibility classes are
extended to describe an optional "initializer" symbol for the module (see the
getInitializerSymbol method on each class). The presence or absence of this
symbol indicates whether the module contains any initializers or
deinitializers. The initializer symbol otherwise behaves like any other:
searching for it triggers materialization.
(2) A new Platform interface is introduced in llvm/ExecutionEngine/Orc/Core.h
which provides the following callback interface:
- Error setupJITDylib(JITDylib &JD): Can be used to install standard symbols
in JITDylibs upon creation. E.g. __dso_handle.
- Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU): Generally
used to record initializer symbols.
- Error notifyRemoving(JITDylib &JD, VModuleKey K): Used to notify a platform
that a module is being removed.
Platform implementations can use these callbacks to track outstanding
initializers and implement a platform-specific approach for executing them. For
example, the MachOPlatform installs a plugin in the JIT linker to scan for both
__mod_inits sections (for C++ static constructors) and ObjC metadata sections.
If discovered, these are processed in the usual platform order: Objective-C
registration is carried out first, then static initializers are executed,
ensuring that calls to Objective-C from static initializers will be safe.
This patch updates LLJIT to use the new scheme for initialization. Two
LLJIT::PlatformSupport classes are implemented: A GenericIR platform and a MachO
platform. The GenericIR platform implements a modified version of the previous
llvm.global-ctor scraping scheme to provide support for Windows and
Linux. LLJIT's MachO platform uses the MachOPlatform class to provide MachO
specific initialization as described above.
Reviewers: sgraenitz, dblaikie
Subscribers: mgorny, hiraditya, mgrang, ributzka, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D74300
2019-12-16 18:50:40 +08:00
|
|
|
ThreadSafeModule TSM, VModuleKey K, SymbolFlagsMap SymbolFlags,
|
|
|
|
SymbolStringPtr InitSymbol, SymbolNameToDefinitionMap SymbolToDefinition,
|
2018-10-16 06:56:10 +08:00
|
|
|
CompileOnDemandLayer &Parent)
|
2018-10-17 04:13:06 +08:00
|
|
|
: IRMaterializationUnit(std::move(TSM), std::move(K),
|
[ORC] Add generic initializer/deinitializer support.
Initializers and deinitializers are used to implement C++ static constructors
and destructors, runtime registration for some languages (e.g. with the
Objective-C runtime for Objective-C/C++ code) and other tasks that would
typically be performed when a shared-object/dylib is loaded or unloaded by a
statically compiled program.
MCJIT and ORC have historically provided limited support for discovering and
running initializers/deinitializers by scanning the llvm.global_ctors and
llvm.global_dtors variables and recording the functions to be run. This approach
suffers from several drawbacks: (1) It only works for IR inputs, not for object
files (including cached JIT'd objects). (2) It only works for initializers
described by llvm.global_ctors and llvm.global_dtors, however not all
initializers are described in this way (Objective-C, for example, describes
initializers via specially named metadata sections). (3) To make the
initializer/deinitializer functions described by llvm.global_ctors and
llvm.global_dtors searchable they must be promoted to extern linkage, polluting
the JIT symbol table (extra care must be taken to ensure this promotion does
not result in symbol name clashes).
This patch introduces several interdependent changes to ORCv2 to support the
construction of new initialization schemes, and includes an implementation of a
backwards-compatible llvm.global_ctor/llvm.global_dtor scanning scheme, and a
MachO specific scheme that handles Objective-C runtime registration (if the
Objective-C runtime is available) enabling execution of LLVM IR compiled from
Objective-C and Swift.
The major changes included in this patch are:
(1) The MaterializationUnit and MaterializationResponsibility classes are
extended to describe an optional "initializer" symbol for the module (see the
getInitializerSymbol method on each class). The presence or absence of this
symbol indicates whether the module contains any initializers or
deinitializers. The initializer symbol otherwise behaves like any other:
searching for it triggers materialization.
(2) A new Platform interface is introduced in llvm/ExecutionEngine/Orc/Core.h
which provides the following callback interface:
- Error setupJITDylib(JITDylib &JD): Can be used to install standard symbols
in JITDylibs upon creation. E.g. __dso_handle.
- Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU): Generally
used to record initializer symbols.
- Error notifyRemoving(JITDylib &JD, VModuleKey K): Used to notify a platform
that a module is being removed.
Platform implementations can use these callbacks to track outstanding
initializers and implement a platform-specific approach for executing them. For
example, the MachOPlatform installs a plugin in the JIT linker to scan for both
__mod_inits sections (for C++ static constructors) and ObjC metadata sections.
If discovered, these are processed in the usual platform order: Objective-C
registration is carried out first, then static initializers are executed,
ensuring that calls to Objective-C from static initializers will be safe.
This patch updates LLJIT to use the new scheme for initialization. Two
LLJIT::PlatformSupport classes are implemented: A GenericIR platform and a MachO
platform. The GenericIR platform implements a modified version of the previous
llvm.global-ctor scraping scheme to provide support for Windows and
Linux. LLJIT's MachO platform uses the MachOPlatform class to provide MachO
specific initialization as described above.
Reviewers: sgraenitz, dblaikie
Subscribers: mgorny, hiraditya, mgrang, ributzka, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D74300
2019-12-16 18:50:40 +08:00
|
|
|
std::move(SymbolFlags), std::move(InitSymbol),
|
2018-06-19 02:01:43 +08:00
|
|
|
std::move(SymbolToDefinition)),
|
2018-07-21 02:31:50 +08:00
|
|
|
Parent(Parent) {}
|
2018-06-19 02:01:43 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
void materialize(MaterializationResponsibility R) override {
|
2018-09-30 07:49:57 +08:00
|
|
|
Parent.emitPartition(std::move(R), std::move(TSM),
|
|
|
|
std::move(SymbolToDefinition));
|
2018-06-19 02:01:43 +08:00
|
|
|
}
|
|
|
|
|
2018-10-07 07:02:06 +08:00
|
|
|
void discard(const JITDylib &V, const SymbolStringPtr &Name) override {
|
2018-06-19 02:01:43 +08:00
|
|
|
// All original symbols were materialized by the CODLayer and should be
|
|
|
|
// final. The function bodies provided by M should never be overridden.
|
|
|
|
llvm_unreachable("Discard should never be called on an "
|
|
|
|
"ExtractingIRMaterializationUnit");
|
|
|
|
}
|
|
|
|
|
2018-07-06 03:01:27 +08:00
|
|
|
mutable std::mutex SourceModuleMutex;
|
2018-10-16 06:56:10 +08:00
|
|
|
CompileOnDemandLayer &Parent;
|
2018-06-19 02:01:43 +08:00
|
|
|
};
|
|
|
|
|
2018-10-16 06:56:10 +08:00
|
|
|
Optional<CompileOnDemandLayer::GlobalValueSet>
|
|
|
|
CompileOnDemandLayer::compileRequested(GlobalValueSet Requested) {
|
2020-02-10 23:06:45 +08:00
|
|
|
return std::move(Requested);
|
2018-09-30 07:49:57 +08:00
|
|
|
}
|
|
|
|
|
2018-10-16 06:56:10 +08:00
|
|
|
Optional<CompileOnDemandLayer::GlobalValueSet>
|
|
|
|
CompileOnDemandLayer::compileWholeModule(GlobalValueSet Requested) {
|
2018-09-30 07:49:57 +08:00
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
2018-10-16 06:56:10 +08:00
|
|
|
CompileOnDemandLayer::CompileOnDemandLayer(
|
2018-09-26 13:08:29 +08:00
|
|
|
ExecutionSession &ES, IRLayer &BaseLayer, LazyCallThroughManager &LCTMgr,
|
2018-09-26 09:24:12 +08:00
|
|
|
IndirectStubsManagerBuilder BuildIndirectStubsManager)
|
2020-01-22 08:28:30 +08:00
|
|
|
: IRLayer(ES, BaseLayer.getManglingOptions()), BaseLayer(BaseLayer),
|
|
|
|
LCTMgr(LCTMgr),
|
2018-09-26 09:24:12 +08:00
|
|
|
BuildIndirectStubsManager(std::move(BuildIndirectStubsManager)) {}
|
2018-06-19 02:01:43 +08:00
|
|
|
|
2018-10-16 06:56:10 +08:00
|
|
|
void CompileOnDemandLayer::setPartitionFunction(PartitionFunction Partition) {
|
2018-09-30 07:49:57 +08:00
|
|
|
this->Partition = std::move(Partition);
|
2018-06-19 02:01:43 +08:00
|
|
|
}
|
|
|
|
|
2019-08-03 22:42:13 +08:00
|
|
|
void CompileOnDemandLayer::setImplMap(ImplSymbolMap *Imp) {
|
|
|
|
this->AliaseeImpls = Imp;
|
|
|
|
}
|
2018-10-17 04:13:06 +08:00
|
|
|
void CompileOnDemandLayer::emit(MaterializationResponsibility R,
|
|
|
|
ThreadSafeModule TSM) {
|
2019-08-02 23:21:37 +08:00
|
|
|
assert(TSM && "Null module");
|
2018-09-30 07:49:57 +08:00
|
|
|
|
2018-06-19 02:01:43 +08:00
|
|
|
auto &ES = getExecutionSession();
|
|
|
|
|
2019-08-02 23:21:37 +08:00
|
|
|
// Sort the callables and non-callables, build re-exports and lodge the
|
2018-09-30 07:49:57 +08:00
|
|
|
// actual module with the implementation dylib.
|
|
|
|
auto &PDR = getPerDylibResources(R.getTargetJITDylib());
|
2018-06-19 02:01:43 +08:00
|
|
|
|
2018-09-30 07:49:57 +08:00
|
|
|
SymbolAliasMap NonCallables;
|
|
|
|
SymbolAliasMap Callables;
|
2019-08-02 23:21:37 +08:00
|
|
|
TSM.withModuleDo([&](Module &M) {
|
|
|
|
// First, do some cleanup on the module:
|
|
|
|
cleanUpModule(M);
|
|
|
|
});
|
2018-06-19 02:01:43 +08:00
|
|
|
|
2020-01-22 08:28:30 +08:00
|
|
|
for (auto &KV : R.getSymbols()) {
|
|
|
|
auto &Name = KV.first;
|
|
|
|
auto &Flags = KV.second;
|
|
|
|
if (Flags.isCallable())
|
|
|
|
Callables[Name] = SymbolAliasMapEntry(Name, Flags);
|
|
|
|
else
|
|
|
|
NonCallables[Name] = SymbolAliasMapEntry(Name, Flags);
|
|
|
|
}
|
|
|
|
|
2018-09-30 07:49:57 +08:00
|
|
|
// Create a partitioning materialization unit and lodge it with the
|
|
|
|
// implementation dylib.
|
|
|
|
if (auto Err = PDR.getImplDylib().define(
|
2019-08-15 23:54:37 +08:00
|
|
|
std::make_unique<PartitioningIRMaterializationUnit>(
|
2020-01-22 08:28:30 +08:00
|
|
|
ES, *getManglingOptions(), std::move(TSM), R.getVModuleKey(),
|
|
|
|
*this))) {
|
2018-06-19 02:01:43 +08:00
|
|
|
ES.reportError(std::move(Err));
|
|
|
|
R.failMaterialization();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-03-19 11:09:11 +08:00
|
|
|
if (!NonCallables.empty())
|
|
|
|
R.replace(reexports(PDR.getImplDylib(), std::move(NonCallables),
|
|
|
|
JITDylibLookupFlags::MatchAllSymbols));
|
|
|
|
if (!Callables.empty())
|
|
|
|
R.replace(lazyReexports(LCTMgr, PDR.getISManager(), PDR.getImplDylib(),
|
|
|
|
std::move(Callables), AliaseeImpls));
|
2018-06-19 02:01:43 +08:00
|
|
|
}
|
|
|
|
|
2018-10-16 06:56:10 +08:00
|
|
|
CompileOnDemandLayer::PerDylibResources &
|
|
|
|
CompileOnDemandLayer::getPerDylibResources(JITDylib &TargetD) {
|
2018-09-26 13:08:29 +08:00
|
|
|
auto I = DylibResources.find(&TargetD);
|
|
|
|
if (I == DylibResources.end()) {
|
2019-12-05 14:45:38 +08:00
|
|
|
auto &ImplD =
|
[ORC] Add generic initializer/deinitializer support.
Initializers and deinitializers are used to implement C++ static constructors
and destructors, runtime registration for some languages (e.g. with the
Objective-C runtime for Objective-C/C++ code) and other tasks that would
typically be performed when a shared-object/dylib is loaded or unloaded by a
statically compiled program.
MCJIT and ORC have historically provided limited support for discovering and
running initializers/deinitializers by scanning the llvm.global_ctors and
llvm.global_dtors variables and recording the functions to be run. This approach
suffers from several drawbacks: (1) It only works for IR inputs, not for object
files (including cached JIT'd objects). (2) It only works for initializers
described by llvm.global_ctors and llvm.global_dtors, however not all
initializers are described in this way (Objective-C, for example, describes
initializers via specially named metadata sections). (3) To make the
initializer/deinitializer functions described by llvm.global_ctors and
llvm.global_dtors searchable they must be promoted to extern linkage, polluting
the JIT symbol table (extra care must be taken to ensure this promotion does
not result in symbol name clashes).
This patch introduces several interdependent changes to ORCv2 to support the
construction of new initialization schemes, and includes an implementation of a
backwards-compatible llvm.global_ctor/llvm.global_dtor scanning scheme, and a
MachO specific scheme that handles Objective-C runtime registration (if the
Objective-C runtime is available) enabling execution of LLVM IR compiled from
Objective-C and Swift.
The major changes included in this patch are:
(1) The MaterializationUnit and MaterializationResponsibility classes are
extended to describe an optional "initializer" symbol for the module (see the
getInitializerSymbol method on each class). The presence or absence of this
symbol indicates whether the module contains any initializers or
deinitializers. The initializer symbol otherwise behaves like any other:
searching for it triggers materialization.
(2) A new Platform interface is introduced in llvm/ExecutionEngine/Orc/Core.h
which provides the following callback interface:
- Error setupJITDylib(JITDylib &JD): Can be used to install standard symbols
in JITDylibs upon creation. E.g. __dso_handle.
- Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU): Generally
used to record initializer symbols.
- Error notifyRemoving(JITDylib &JD, VModuleKey K): Used to notify a platform
that a module is being removed.
Platform implementations can use these callbacks to track outstanding
initializers and implement a platform-specific approach for executing them. For
example, the MachOPlatform installs a plugin in the JIT linker to scan for both
__mod_inits sections (for C++ static constructors) and ObjC metadata sections.
If discovered, these are processed in the usual platform order: Objective-C
registration is carried out first, then static initializers are executed,
ensuring that calls to Objective-C from static initializers will be safe.
This patch updates LLJIT to use the new scheme for initialization. Two
LLJIT::PlatformSupport classes are implemented: A GenericIR platform and a MachO
platform. The GenericIR platform implements a modified version of the previous
llvm.global-ctor scraping scheme to provide support for Windows and
Linux. LLJIT's MachO platform uses the MachOPlatform class to provide MachO
specific initialization as described above.
Reviewers: sgraenitz, dblaikie
Subscribers: mgorny, hiraditya, mgrang, ributzka, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D74300
2019-12-16 18:50:40 +08:00
|
|
|
getExecutionSession().createBareJITDylib(TargetD.getName() + ".impl");
|
|
|
|
JITDylibSearchOrder NewSearchOrder;
|
2019-11-26 13:57:27 +08:00
|
|
|
TargetD.withSearchOrderDo(
|
|
|
|
[&](const JITDylibSearchOrder &TargetSearchOrder) {
|
[ORC] Add generic initializer/deinitializer support.
Initializers and deinitializers are used to implement C++ static constructors
and destructors, runtime registration for some languages (e.g. with the
Objective-C runtime for Objective-C/C++ code) and other tasks that would
typically be performed when a shared-object/dylib is loaded or unloaded by a
statically compiled program.
MCJIT and ORC have historically provided limited support for discovering and
running initializers/deinitializers by scanning the llvm.global_ctors and
llvm.global_dtors variables and recording the functions to be run. This approach
suffers from several drawbacks: (1) It only works for IR inputs, not for object
files (including cached JIT'd objects). (2) It only works for initializers
described by llvm.global_ctors and llvm.global_dtors, however not all
initializers are described in this way (Objective-C, for example, describes
initializers via specially named metadata sections). (3) To make the
initializer/deinitializer functions described by llvm.global_ctors and
llvm.global_dtors searchable they must be promoted to extern linkage, polluting
the JIT symbol table (extra care must be taken to ensure this promotion does
not result in symbol name clashes).
This patch introduces several interdependent changes to ORCv2 to support the
construction of new initialization schemes, and includes an implementation of a
backwards-compatible llvm.global_ctor/llvm.global_dtor scanning scheme, and a
MachO specific scheme that handles Objective-C runtime registration (if the
Objective-C runtime is available) enabling execution of LLVM IR compiled from
Objective-C and Swift.
The major changes included in this patch are:
(1) The MaterializationUnit and MaterializationResponsibility classes are
extended to describe an optional "initializer" symbol for the module (see the
getInitializerSymbol method on each class). The presence or absence of this
symbol indicates whether the module contains any initializers or
deinitializers. The initializer symbol otherwise behaves like any other:
searching for it triggers materialization.
(2) A new Platform interface is introduced in llvm/ExecutionEngine/Orc/Core.h
which provides the following callback interface:
- Error setupJITDylib(JITDylib &JD): Can be used to install standard symbols
in JITDylibs upon creation. E.g. __dso_handle.
- Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU): Generally
used to record initializer symbols.
- Error notifyRemoving(JITDylib &JD, VModuleKey K): Used to notify a platform
that a module is being removed.
Platform implementations can use these callbacks to track outstanding
initializers and implement a platform-specific approach for executing them. For
example, the MachOPlatform installs a plugin in the JIT linker to scan for both
__mod_inits sections (for C++ static constructors) and ObjC metadata sections.
If discovered, these are processed in the usual platform order: Objective-C
registration is carried out first, then static initializers are executed,
ensuring that calls to Objective-C from static initializers will be safe.
This patch updates LLJIT to use the new scheme for initialization. Two
LLJIT::PlatformSupport classes are implemented: A GenericIR platform and a MachO
platform. The GenericIR platform implements a modified version of the previous
llvm.global-ctor scraping scheme to provide support for Windows and
Linux. LLJIT's MachO platform uses the MachOPlatform class to provide MachO
specific initialization as described above.
Reviewers: sgraenitz, dblaikie
Subscribers: mgorny, hiraditya, mgrang, ributzka, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D74300
2019-12-16 18:50:40 +08:00
|
|
|
NewSearchOrder = TargetSearchOrder;
|
2019-11-26 13:57:27 +08:00
|
|
|
});
|
[ORC] Add generic initializer/deinitializer support.
Initializers and deinitializers are used to implement C++ static constructors
and destructors, runtime registration for some languages (e.g. with the
Objective-C runtime for Objective-C/C++ code) and other tasks that would
typically be performed when a shared-object/dylib is loaded or unloaded by a
statically compiled program.
MCJIT and ORC have historically provided limited support for discovering and
running initializers/deinitializers by scanning the llvm.global_ctors and
llvm.global_dtors variables and recording the functions to be run. This approach
suffers from several drawbacks: (1) It only works for IR inputs, not for object
files (including cached JIT'd objects). (2) It only works for initializers
described by llvm.global_ctors and llvm.global_dtors, however not all
initializers are described in this way (Objective-C, for example, describes
initializers via specially named metadata sections). (3) To make the
initializer/deinitializer functions described by llvm.global_ctors and
llvm.global_dtors searchable they must be promoted to extern linkage, polluting
the JIT symbol table (extra care must be taken to ensure this promotion does
not result in symbol name clashes).
This patch introduces several interdependent changes to ORCv2 to support the
construction of new initialization schemes, and includes an implementation of a
backwards-compatible llvm.global_ctor/llvm.global_dtor scanning scheme, and a
MachO specific scheme that handles Objective-C runtime registration (if the
Objective-C runtime is available) enabling execution of LLVM IR compiled from
Objective-C and Swift.
The major changes included in this patch are:
(1) The MaterializationUnit and MaterializationResponsibility classes are
extended to describe an optional "initializer" symbol for the module (see the
getInitializerSymbol method on each class). The presence or absence of this
symbol indicates whether the module contains any initializers or
deinitializers. The initializer symbol otherwise behaves like any other:
searching for it triggers materialization.
(2) A new Platform interface is introduced in llvm/ExecutionEngine/Orc/Core.h
which provides the following callback interface:
- Error setupJITDylib(JITDylib &JD): Can be used to install standard symbols
in JITDylibs upon creation. E.g. __dso_handle.
- Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU): Generally
used to record initializer symbols.
- Error notifyRemoving(JITDylib &JD, VModuleKey K): Used to notify a platform
that a module is being removed.
Platform implementations can use these callbacks to track outstanding
initializers and implement a platform-specific approach for executing them. For
example, the MachOPlatform installs a plugin in the JIT linker to scan for both
__mod_inits sections (for C++ static constructors) and ObjC metadata sections.
If discovered, these are processed in the usual platform order: Objective-C
registration is carried out first, then static initializers are executed,
ensuring that calls to Objective-C from static initializers will be safe.
This patch updates LLJIT to use the new scheme for initialization. Two
LLJIT::PlatformSupport classes are implemented: A GenericIR platform and a MachO
platform. The GenericIR platform implements a modified version of the previous
llvm.global-ctor scraping scheme to provide support for Windows and
Linux. LLJIT's MachO platform uses the MachOPlatform class to provide MachO
specific initialization as described above.
Reviewers: sgraenitz, dblaikie
Subscribers: mgorny, hiraditya, mgrang, ributzka, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D74300
2019-12-16 18:50:40 +08:00
|
|
|
|
|
|
|
assert(
|
|
|
|
!NewSearchOrder.empty() && NewSearchOrder.front().first == &TargetD &&
|
|
|
|
NewSearchOrder.front().second == JITDylibLookupFlags::MatchAllSymbols &&
|
|
|
|
"TargetD must be at the front of its own search order and match "
|
|
|
|
"non-exported symbol");
|
|
|
|
NewSearchOrder.insert(std::next(NewSearchOrder.begin()),
|
|
|
|
{&ImplD, JITDylibLookupFlags::MatchAllSymbols});
|
|
|
|
ImplD.setSearchOrder(NewSearchOrder, false);
|
|
|
|
TargetD.setSearchOrder(std::move(NewSearchOrder), false);
|
|
|
|
|
2018-09-26 13:08:29 +08:00
|
|
|
PerDylibResources PDR(ImplD, BuildIndirectStubsManager());
|
|
|
|
I = DylibResources.insert(std::make_pair(&TargetD, std::move(PDR))).first;
|
|
|
|
}
|
|
|
|
|
|
|
|
return I->second;
|
2018-06-19 02:01:43 +08:00
|
|
|
}
|
|
|
|
|
2018-10-16 06:56:10 +08:00
|
|
|
void CompileOnDemandLayer::cleanUpModule(Module &M) {
|
2018-09-30 07:49:57 +08:00
|
|
|
for (auto &F : M.functions()) {
|
|
|
|
if (F.isDeclaration())
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (F.hasAvailableExternallyLinkage()) {
|
|
|
|
F.deleteBody();
|
|
|
|
F.setPersonalityFn(nullptr);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-16 06:56:10 +08:00
|
|
|
void CompileOnDemandLayer::expandPartition(GlobalValueSet &Partition) {
|
2018-09-30 07:49:57 +08:00
|
|
|
// Expands the partition to ensure the following rules hold:
|
|
|
|
// (1) If any alias is in the partition, its aliasee is also in the partition.
|
|
|
|
// (2) If any aliasee is in the partition, its aliases are also in the
|
|
|
|
// partiton.
|
|
|
|
// (3) If any global variable is in the partition then all global variables
|
|
|
|
// are in the partition.
|
|
|
|
assert(!Partition.empty() && "Unexpected empty partition");
|
|
|
|
|
|
|
|
const Module &M = *(*Partition.begin())->getParent();
|
|
|
|
bool ContainsGlobalVariables = false;
|
|
|
|
std::vector<const GlobalValue *> GVsToAdd;
|
|
|
|
|
|
|
|
for (auto *GV : Partition)
|
|
|
|
if (isa<GlobalAlias>(GV))
|
|
|
|
GVsToAdd.push_back(
|
|
|
|
cast<GlobalValue>(cast<GlobalAlias>(GV)->getAliasee()));
|
|
|
|
else if (isa<GlobalVariable>(GV))
|
|
|
|
ContainsGlobalVariables = true;
|
|
|
|
|
|
|
|
for (auto &A : M.aliases())
|
|
|
|
if (Partition.count(cast<GlobalValue>(A.getAliasee())))
|
|
|
|
GVsToAdd.push_back(&A);
|
|
|
|
|
|
|
|
if (ContainsGlobalVariables)
|
|
|
|
for (auto &G : M.globals())
|
|
|
|
GVsToAdd.push_back(&G);
|
|
|
|
|
|
|
|
for (auto *GV : GVsToAdd)
|
|
|
|
Partition.insert(GV);
|
|
|
|
}
|
|
|
|
|
2018-10-16 06:56:10 +08:00
|
|
|
void CompileOnDemandLayer::emitPartition(
|
2018-09-30 07:49:57 +08:00
|
|
|
MaterializationResponsibility R, ThreadSafeModule TSM,
|
|
|
|
IRMaterializationUnit::SymbolNameToDefinitionMap Defs) {
|
|
|
|
|
|
|
|
// FIXME: Need a 'notify lazy-extracting/emitting' callback to tie the
|
|
|
|
// extracted module key, extracted module, and source module key
|
|
|
|
// together. This could be used, for example, to provide a specific
|
|
|
|
// memory manager instance to the linking layer.
|
|
|
|
|
|
|
|
auto &ES = getExecutionSession();
|
|
|
|
GlobalValueSet RequestedGVs;
|
|
|
|
for (auto &Name : R.getRequestedSymbols()) {
|
[ORC] Add generic initializer/deinitializer support.
Initializers and deinitializers are used to implement C++ static constructors
and destructors, runtime registration for some languages (e.g. with the
Objective-C runtime for Objective-C/C++ code) and other tasks that would
typically be performed when a shared-object/dylib is loaded or unloaded by a
statically compiled program.
MCJIT and ORC have historically provided limited support for discovering and
running initializers/deinitializers by scanning the llvm.global_ctors and
llvm.global_dtors variables and recording the functions to be run. This approach
suffers from several drawbacks: (1) It only works for IR inputs, not for object
files (including cached JIT'd objects). (2) It only works for initializers
described by llvm.global_ctors and llvm.global_dtors, however not all
initializers are described in this way (Objective-C, for example, describes
initializers via specially named metadata sections). (3) To make the
initializer/deinitializer functions described by llvm.global_ctors and
llvm.global_dtors searchable they must be promoted to extern linkage, polluting
the JIT symbol table (extra care must be taken to ensure this promotion does
not result in symbol name clashes).
This patch introduces several interdependent changes to ORCv2 to support the
construction of new initialization schemes, and includes an implementation of a
backwards-compatible llvm.global_ctor/llvm.global_dtor scanning scheme, and a
MachO specific scheme that handles Objective-C runtime registration (if the
Objective-C runtime is available) enabling execution of LLVM IR compiled from
Objective-C and Swift.
The major changes included in this patch are:
(1) The MaterializationUnit and MaterializationResponsibility classes are
extended to describe an optional "initializer" symbol for the module (see the
getInitializerSymbol method on each class). The presence or absence of this
symbol indicates whether the module contains any initializers or
deinitializers. The initializer symbol otherwise behaves like any other:
searching for it triggers materialization.
(2) A new Platform interface is introduced in llvm/ExecutionEngine/Orc/Core.h
which provides the following callback interface:
- Error setupJITDylib(JITDylib &JD): Can be used to install standard symbols
in JITDylibs upon creation. E.g. __dso_handle.
- Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU): Generally
used to record initializer symbols.
- Error notifyRemoving(JITDylib &JD, VModuleKey K): Used to notify a platform
that a module is being removed.
Platform implementations can use these callbacks to track outstanding
initializers and implement a platform-specific approach for executing them. For
example, the MachOPlatform installs a plugin in the JIT linker to scan for both
__mod_inits sections (for C++ static constructors) and ObjC metadata sections.
If discovered, these are processed in the usual platform order: Objective-C
registration is carried out first, then static initializers are executed,
ensuring that calls to Objective-C from static initializers will be safe.
This patch updates LLJIT to use the new scheme for initialization. Two
LLJIT::PlatformSupport classes are implemented: A GenericIR platform and a MachO
platform. The GenericIR platform implements a modified version of the previous
llvm.global-ctor scraping scheme to provide support for Windows and
Linux. LLJIT's MachO platform uses the MachOPlatform class to provide MachO
specific initialization as described above.
Reviewers: sgraenitz, dblaikie
Subscribers: mgorny, hiraditya, mgrang, ributzka, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D74300
2019-12-16 18:50:40 +08:00
|
|
|
if (Name == R.getInitializerSymbol())
|
|
|
|
TSM.withModuleDo([&](Module &M) {
|
|
|
|
for (auto &GV : getStaticInitGVs(M))
|
|
|
|
RequestedGVs.insert(&GV);
|
|
|
|
});
|
|
|
|
else {
|
|
|
|
assert(Defs.count(Name) && "No definition for symbol");
|
|
|
|
RequestedGVs.insert(Defs[Name]);
|
|
|
|
}
|
2018-09-30 07:49:57 +08:00
|
|
|
}
|
|
|
|
|
2019-08-02 23:21:37 +08:00
|
|
|
/// Perform partitioning with the context lock held, since the partition
|
|
|
|
/// function is allowed to access the globals to compute the partition.
|
|
|
|
auto GVsToExtract =
|
|
|
|
TSM.withModuleDo([&](Module &M) { return Partition(RequestedGVs); });
|
2018-09-30 07:49:57 +08:00
|
|
|
|
|
|
|
// Take a 'None' partition to mean the whole module (as opposed to an empty
|
|
|
|
// partition, which means "materialize nothing"). Emit the whole module
|
|
|
|
// unmodified to the base layer.
|
|
|
|
if (GVsToExtract == None) {
|
|
|
|
Defs.clear();
|
2018-10-17 04:13:06 +08:00
|
|
|
BaseLayer.emit(std::move(R), std::move(TSM));
|
2018-09-30 07:49:57 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the partition is empty, return the whole module to the symbol table.
|
|
|
|
if (GVsToExtract->empty()) {
|
2019-08-15 23:54:37 +08:00
|
|
|
R.replace(std::make_unique<PartitioningIRMaterializationUnit>(
|
[ORC] Add generic initializer/deinitializer support.
Initializers and deinitializers are used to implement C++ static constructors
and destructors, runtime registration for some languages (e.g. with the
Objective-C runtime for Objective-C/C++ code) and other tasks that would
typically be performed when a shared-object/dylib is loaded or unloaded by a
statically compiled program.
MCJIT and ORC have historically provided limited support for discovering and
running initializers/deinitializers by scanning the llvm.global_ctors and
llvm.global_dtors variables and recording the functions to be run. This approach
suffers from several drawbacks: (1) It only works for IR inputs, not for object
files (including cached JIT'd objects). (2) It only works for initializers
described by llvm.global_ctors and llvm.global_dtors, however not all
initializers are described in this way (Objective-C, for example, describes
initializers via specially named metadata sections). (3) To make the
initializer/deinitializer functions described by llvm.global_ctors and
llvm.global_dtors searchable they must be promoted to extern linkage, polluting
the JIT symbol table (extra care must be taken to ensure this promotion does
not result in symbol name clashes).
This patch introduces several interdependent changes to ORCv2 to support the
construction of new initialization schemes, and includes an implementation of a
backwards-compatible llvm.global_ctor/llvm.global_dtor scanning scheme, and a
MachO specific scheme that handles Objective-C runtime registration (if the
Objective-C runtime is available) enabling execution of LLVM IR compiled from
Objective-C and Swift.
The major changes included in this patch are:
(1) The MaterializationUnit and MaterializationResponsibility classes are
extended to describe an optional "initializer" symbol for the module (see the
getInitializerSymbol method on each class). The presence or absence of this
symbol indicates whether the module contains any initializers or
deinitializers. The initializer symbol otherwise behaves like any other:
searching for it triggers materialization.
(2) A new Platform interface is introduced in llvm/ExecutionEngine/Orc/Core.h
which provides the following callback interface:
- Error setupJITDylib(JITDylib &JD): Can be used to install standard symbols
in JITDylibs upon creation. E.g. __dso_handle.
- Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU): Generally
used to record initializer symbols.
- Error notifyRemoving(JITDylib &JD, VModuleKey K): Used to notify a platform
that a module is being removed.
Platform implementations can use these callbacks to track outstanding
initializers and implement a platform-specific approach for executing them. For
example, the MachOPlatform installs a plugin in the JIT linker to scan for both
__mod_inits sections (for C++ static constructors) and ObjC metadata sections.
If discovered, these are processed in the usual platform order: Objective-C
registration is carried out first, then static initializers are executed,
ensuring that calls to Objective-C from static initializers will be safe.
This patch updates LLJIT to use the new scheme for initialization. Two
LLJIT::PlatformSupport classes are implemented: A GenericIR platform and a MachO
platform. The GenericIR platform implements a modified version of the previous
llvm.global-ctor scraping scheme to provide support for Windows and
Linux. LLJIT's MachO platform uses the MachOPlatform class to provide MachO
specific initialization as described above.
Reviewers: sgraenitz, dblaikie
Subscribers: mgorny, hiraditya, mgrang, ributzka, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D74300
2019-12-16 18:50:40 +08:00
|
|
|
std::move(TSM), R.getVModuleKey(), R.getSymbols(),
|
|
|
|
R.getInitializerSymbol(), std::move(Defs), *this));
|
2018-09-30 07:49:57 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-10-10 04:44:32 +08:00
|
|
|
// Ok -- we actually need to partition the symbols. Promote the symbol
|
2019-08-02 23:21:37 +08:00
|
|
|
// linkages/names, expand the partition to include any required symbols
|
|
|
|
// (i.e. symbols that can't be separated from our partition), and
|
|
|
|
// then extract the partition.
|
|
|
|
//
|
|
|
|
// FIXME: We apply this promotion once per partitioning. It's safe, but
|
|
|
|
// overkill.
|
|
|
|
auto ExtractedTSM =
|
|
|
|
TSM.withModuleDo([&](Module &M) -> Expected<ThreadSafeModule> {
|
|
|
|
auto PromotedGlobals = PromoteSymbols(M);
|
|
|
|
if (!PromotedGlobals.empty()) {
|
2020-02-23 01:49:55 +08:00
|
|
|
|
2019-08-02 23:21:37 +08:00
|
|
|
MangleAndInterner Mangle(ES, M.getDataLayout());
|
|
|
|
SymbolFlagsMap SymbolFlags;
|
2020-02-23 01:49:55 +08:00
|
|
|
IRSymbolMapper::add(ES, *getManglingOptions(),
|
|
|
|
PromotedGlobals, SymbolFlags);
|
|
|
|
|
2019-08-02 23:21:37 +08:00
|
|
|
if (auto Err = R.defineMaterializing(SymbolFlags))
|
2020-02-10 23:06:45 +08:00
|
|
|
return std::move(Err);
|
2019-08-02 23:21:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
expandPartition(*GVsToExtract);
|
|
|
|
|
2020-02-23 01:49:55 +08:00
|
|
|
// Submodule name is given by hashing the names of the globals.
|
|
|
|
std::string SubModuleName;
|
|
|
|
{
|
|
|
|
std::vector<const GlobalValue*> HashGVs;
|
|
|
|
HashGVs.reserve(GVsToExtract->size());
|
|
|
|
for (auto *GV : *GVsToExtract)
|
|
|
|
HashGVs.push_back(GV);
|
|
|
|
llvm::sort(HashGVs, [](const GlobalValue *LHS, const GlobalValue *RHS) {
|
|
|
|
return LHS->getName() < RHS->getName();
|
|
|
|
});
|
|
|
|
hash_code HC(0);
|
|
|
|
for (auto *GV : HashGVs) {
|
|
|
|
assert(GV->hasName() && "All GVs to extract should be named by now");
|
|
|
|
auto GVName = GV->getName();
|
|
|
|
HC = hash_combine(HC, hash_combine_range(GVName.begin(), GVName.end()));
|
|
|
|
}
|
|
|
|
raw_string_ostream(SubModuleName)
|
|
|
|
<< ".submodule."
|
|
|
|
<< formatv(sizeof(size_t) == 8 ? "{0:x16}" : "{0:x8}",
|
|
|
|
static_cast<size_t>(HC))
|
|
|
|
<< ".ll";
|
|
|
|
}
|
|
|
|
|
2019-08-02 23:21:37 +08:00
|
|
|
// Extract the requested partiton (plus any necessary aliases) and
|
|
|
|
// put the rest back into the impl dylib.
|
|
|
|
auto ShouldExtract = [&](const GlobalValue &GV) -> bool {
|
|
|
|
return GVsToExtract->count(&GV);
|
|
|
|
};
|
|
|
|
|
2020-02-23 01:49:55 +08:00
|
|
|
return extractSubModule(TSM, SubModuleName , ShouldExtract);
|
2019-08-02 23:21:37 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
if (!ExtractedTSM) {
|
|
|
|
ES.reportError(ExtractedTSM.takeError());
|
|
|
|
R.failMaterialization();
|
|
|
|
return;
|
2018-10-10 04:44:32 +08:00
|
|
|
}
|
|
|
|
|
2019-08-15 23:54:37 +08:00
|
|
|
R.replace(std::make_unique<PartitioningIRMaterializationUnit>(
|
2020-01-22 08:28:30 +08:00
|
|
|
ES, *getManglingOptions(), std::move(TSM), R.getVModuleKey(), *this));
|
2019-08-02 23:21:37 +08:00
|
|
|
BaseLayer.emit(std::move(R), std::move(*ExtractedTSM));
|
2018-06-19 02:01:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
} // end namespace orc
|
|
|
|
} // end namespace llvm
|