29 if (isa<Function>(GV)) {
30 auto &
F = cast<Function>(GV);
32 F.setPersonalityFn(
nullptr);
33 }
else if (isa<GlobalVariable>(GV)) {
34 cast<GlobalVariable>(GV).setInitializer(
nullptr);
35 }
else if (isa<GlobalAlias>(GV)) {
38 auto &
A = cast<GlobalAlias>(GV);
40 assert(
A.hasName() &&
"Anonymous alias?");
42 std::string AliasName = std::string(
A.getName());
44 if (isa<Function>(Aliasee)) {
46 A.replaceAllUsesWith(
F);
48 F->setName(AliasName);
49 }
else if (isa<GlobalVariable>(Aliasee)) {
51 *cast<GlobalVariable>(Aliasee));
52 A.replaceAllUsesWith(
G);
54 G->setName(AliasName);
62 NewTSM.withModuleDo([&](
Module &M) {
63 M.setModuleIdentifier((M.getModuleIdentifier() + Suffix).str());
89 void materialize(std::unique_ptr<MaterializationResponsibility> R)
override {
90 Parent.emitPartition(std::move(R), std::move(
TSM),
98 "ExtractingIRMaterializationUnit");
101 mutable std::mutex SourceModuleMutex;
105std::optional<CompileOnDemandLayer::GlobalValueSet>
107 return std::move(Requested);
110std::optional<CompileOnDemandLayer::GlobalValueSet>
118 :
IRLayer(ES, BaseLayer.getManglingOptions()), BaseLayer(BaseLayer),
120 BuildIndirectStubsManager(
std::
move(BuildIndirectStubsManager)) {}
123 this->Partition = std::move(Partition);
127 this->AliaseeImpls = Imp;
131 assert(TSM &&
"Null module");
137 auto &PDR = getPerDylibResources(R->getTargetJITDylib());
146 for (
auto &KV : R->getSymbols()) {
147 auto &
Name = KV.first;
148 auto &Flags = KV.second;
149 if (Flags.isCallable())
157 if (
auto Err = PDR.getImplDylib().define(
158 std::make_unique<PartitioningIRMaterializationUnit>(
160 ES.reportError(std::move(Err));
161 R->failMaterialization();
165 if (!NonCallables.
empty())
167 R->replace(
reexports(PDR.getImplDylib(), std::move(NonCallables),
170 R->failMaterialization();
173 if (!Callables.
empty()) {
174 if (
auto Err = R->replace(
175 lazyReexports(LCTMgr, PDR.getISManager(), PDR.getImplDylib(),
176 std::move(Callables), AliaseeImpls))) {
178 R->failMaterialization();
184CompileOnDemandLayer::PerDylibResources &
185CompileOnDemandLayer::getPerDylibResources(
JITDylib &TargetD) {
186 std::lock_guard<std::mutex> Lock(CODLayerMutex);
188 auto I = DylibResources.find(&TargetD);
189 if (
I == DylibResources.end()) {
194 NewLinkOrder = TargetLinkOrder;
197 assert(!NewLinkOrder.empty() && NewLinkOrder.front().first == &TargetD &&
198 NewLinkOrder.front().second ==
200 "TargetD must be at the front of its own search order and match "
201 "non-exported symbol");
202 NewLinkOrder.insert(std::next(NewLinkOrder.begin()),
203 {&ImplD, JITDylibLookupFlags::MatchAllSymbols});
204 ImplD.setLinkOrder(NewLinkOrder,
false);
207 PerDylibResources PDR(ImplD, BuildIndirectStubsManager());
208 I = DylibResources.insert(std::make_pair(&TargetD, std::move(PDR))).first;
214void CompileOnDemandLayer::cleanUpModule(
Module &M) {
215 for (
auto &
F :
M.functions()) {
216 if (
F.isDeclaration())
219 if (
F.hasAvailableExternallyLinkage()) {
221 F.setPersonalityFn(
nullptr);
227void CompileOnDemandLayer::expandPartition(GlobalValueSet &Partition) {
234 assert(!Partition.empty() &&
"Unexpected empty partition");
237 bool ContainsGlobalVariables =
false;
238 std::vector<const GlobalValue *> GVsToAdd;
240 for (
const auto *GV : Partition)
241 if (isa<GlobalAlias>(GV))
243 cast<GlobalValue>(cast<GlobalAlias>(GV)->getAliasee()));
244 else if (isa<GlobalVariable>(GV))
245 ContainsGlobalVariables =
true;
247 for (
auto &
A :
M.aliases())
248 if (Partition.count(cast<GlobalValue>(
A.getAliasee())))
249 GVsToAdd.push_back(&
A);
251 if (ContainsGlobalVariables)
252 for (
auto &
G :
M.globals())
253 GVsToAdd.push_back(&
G);
255 for (
const auto *GV : GVsToAdd)
259void CompileOnDemandLayer::emitPartition(
270 for (
auto &
Name :
R->getRequestedSymbols()) {
271 if (
Name ==
R->getInitializerSymbol())
274 RequestedGVs.insert(&GV);
277 assert(Defs.count(
Name) &&
"No definition for symbol");
278 RequestedGVs.insert(Defs[
Name]);
290 if (GVsToExtract == std::nullopt) {
292 BaseLayer.
emit(std::move(R), std::move(TSM));
297 if (GVsToExtract->empty()) {
299 R->replace(std::make_unique<PartitioningIRMaterializationUnit>(
302 R->getInitializerSymbol()),
303 std::move(Defs), *
this))) {
305 R->failMaterialization();
320 auto PromotedGlobals = PromoteSymbols(M);
321 if (!PromotedGlobals.empty()) {
326 PromotedGlobals, SymbolFlags);
328 if (
auto Err =
R->defineMaterializing(SymbolFlags))
329 return std::move(Err);
332 expandPartition(*GVsToExtract);
335 std::string SubModuleName;
337 std::vector<const GlobalValue*> HashGVs;
338 HashGVs.reserve(GVsToExtract->size());
339 for (
const auto *GV : *GVsToExtract)
340 HashGVs.push_back(GV);
345 for (
const auto *GV : HashGVs) {
346 assert(GV->hasName() &&
"All GVs to extract should be named by now");
347 auto GVName = GV->getName();
352 <<
formatv(
sizeof(
size_t) == 8 ?
"{0:x16}" :
"{0:x8}",
353 static_cast<size_t>(HC))
359 auto ShouldExtract = [&](
const GlobalValue &GV) ->
bool {
360 return GVsToExtract->count(&GV);
367 ES.reportError(ExtractedTSM.takeError());
368 R->failMaterialization();
372 if (
auto Err =
R->replace(std::make_unique<PartitioningIRMaterializationUnit>(
374 ES.reportError(std::move(Err));
375 R->failMaterialization();
378 BaseLayer.
emit(std::move(R), std::move(*ExtractedTSM));
static const Function * getParent(const Value *V)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static ThreadSafeModule extractSubModule(ThreadSafeModule &TSM, StringRef Suffix, GVPredicate ShouldExtract)
Module.h This file contains the declarations for the Module class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This is an important base class in LLVM.
Tagged union holding either a T or a Error.
Function::iterator insert(Function::iterator Position, BasicBlock *BB)
Insert BB in the basic block list at Position.
@ ExternalLinkage
Externally visible function.
A Module instance is used to store all the information related to an LLVM module.
StringRef - Represent a constant reference to a string, i.e.
StringRef getName() const
Return a constant reference to the value's name.
An opaque object representing a hash code.
const std::string & getName() const
Get the name for this JITLinkDylib.
CompileOnDemandLayer(ExecutionSession &ES, IRLayer &BaseLayer, LazyCallThroughManager &LCTMgr, IndirectStubsManagerBuilder BuildIndirectStubsManager)
Construct a CompileOnDemandLayer.
std::function< std::unique_ptr< IndirectStubsManager >()> IndirectStubsManagerBuilder
Builder for IndirectStubsManagers.
static std::optional< GlobalValueSet > compileWholeModule(GlobalValueSet Requested)
Off-the-shelf partitioning which compiles whole modules whenever any symbol in them is requested.
void emit(std::unique_ptr< MaterializationResponsibility > R, ThreadSafeModule TSM) override
Emits the given module.
std::set< const GlobalValue * > GlobalValueSet
void setImplMap(ImplSymbolMap *Imp)
Sets the ImplSymbolMap.
static std::optional< GlobalValueSet > compileRequested(GlobalValueSet Requested)
Off-the-shelf partitioning which compiles all requested symbols (usually a single function at a time)...
std::function< std::optional< GlobalValueSet >(GlobalValueSet Requested)> PartitionFunction
Partitioning function.
void setPartitionFunction(PartitionFunction Partition)
Sets the partition function.
An ExecutionSession represents a running JIT program.
void reportError(Error Err)
Report a error for this execution session.
JITDylib & createBareJITDylib(std::string Name)
Add a new bare JITDylib to this ExecutionSession.
Interface for layers that accept LLVM IR.
virtual void emit(std::unique_ptr< MaterializationResponsibility > R, ThreadSafeModule TSM)=0
Emit should materialize the given IR.
ExecutionSession & getExecutionSession()
Returns the ExecutionSession for this layer.
const IRSymbolMapper::ManglingOptions *& getManglingOptions() const
Get the mangling options for this layer.
IRMaterializationUnit is a convenient base class for MaterializationUnits wrapping LLVM IR.
SymbolNameToDefinitionMap SymbolToDefinition
std::map< SymbolStringPtr, GlobalValue * > SymbolNameToDefinitionMap
static void add(ExecutionSession &ES, const ManglingOptions &MO, ArrayRef< GlobalValue * > GVs, SymbolFlagsMap &SymbolFlags, SymbolNameToDefinitionMap *SymbolToDefinition=nullptr)
Add mangled symbols for the given GlobalValues to SymbolFlags.
Represents a JIT'd dynamic library.
auto withLinkOrderDo(Func &&F) -> decltype(F(std::declval< const JITDylibSearchOrder & >()))
Do something with the link order (run under the session lock).
void setLinkOrder(JITDylibSearchOrder NewSearchOrder, bool LinkAgainstThisJITDylibFirst=true)
Set the link order to be used when fixing up definitions in JITDylib.
Manages a set of 'lazy call-through' trampolines.
Mangles symbol names then uniques them in the context of an ExecutionSession.
PartitioningIRMaterializationUnit(ExecutionSession &ES, const IRSymbolMapper::ManglingOptions &MO, ThreadSafeModule TSM, CompileOnDemandLayer &Parent)
PartitioningIRMaterializationUnit(ThreadSafeModule TSM, Interface I, SymbolNameToDefinitionMap SymbolToDefinition, CompileOnDemandLayer &Parent)
Pointer to a pooled string representing a symbol name.
An LLVM Module together with a shared ThreadSafeContext.
decltype(auto) withModuleDo(Func &&F)
Locks the associated ThreadSafeContext and calls the given function on the contained Module.
A raw_ostream that writes to an std::string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::vector< std::pair< JITDylib *, JITDylibLookupFlags > > JITDylibSearchOrder
A list of (JITDylib*, JITDylibLookupFlags) pairs to be used as a search order during symbol lookup.
iterator_range< StaticInitGVIterator > getStaticInitGVs(Module &M)
Create an iterator range over the GlobalValues that contribute to static initialization.
std::function< bool(const GlobalValue &)> GVPredicate
std::unique_ptr< ReExportsMaterializationUnit > reexports(JITDylib &SourceJD, SymbolAliasMap Aliases, JITDylibLookupFlags SourceJDLookupFlags=JITDylibLookupFlags::MatchExportedSymbolsOnly)
Create a materialization unit for re-exporting symbols from another JITDylib with alternative names/f...
GlobalVariable * cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV, ValueToValueMapTy *VMap=nullptr)
Clone a global variable declaration into a new module.
Function * cloneFunctionDecl(Module &Dst, const Function &F, ValueToValueMapTy *VMap=nullptr)
Clone a function declaration into a new module.
std::unique_ptr< LazyReexportsMaterializationUnit > lazyReexports(LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager, JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc=nullptr)
Define lazy-reexports based on the given SymbolAliasMap.
ThreadSafeModule cloneToNewContext(const ThreadSafeModule &TSMW, GVPredicate ShouldCloneDef=GVPredicate(), GVModifier UpdateClonedDefSource=GVModifier())
Clones the given module on to a new context.
This is an optimization pass for GlobalISel generic memory operations.
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< Ts >(Vals))...))>
void sort(IteratorTy Start, IteratorTy End)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
hash_code hash_combine_range(InputIteratorT first, InputIteratorT last)
Compute a hash_code for a sequence of values.
Implement std::hash so that hash_code can be used in STL containers.