1 | //===---------- LazyReexports.cpp - Utilities for lazy reexports ----------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "llvm/ExecutionEngine/Orc/LazyObjectLinkingLayer.h" |
10 | |
11 | #include "llvm/ExecutionEngine/Orc/LazyReexports.h" |
12 | #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" |
13 | #include "llvm/ExecutionEngine/Orc/RedirectionManager.h" |
14 | |
15 | using namespace llvm; |
16 | using namespace llvm::jitlink; |
17 | |
18 | namespace { |
19 | |
20 | constexpr StringRef FnBodySuffix = "$orc_fnbody" ; |
21 | |
22 | } // anonymous namespace |
23 | |
24 | namespace llvm::orc { |
25 | |
26 | class LazyObjectLinkingLayer::RenamerPlugin |
27 | : public ObjectLinkingLayer::Plugin { |
28 | public: |
29 | void modifyPassConfig(MaterializationResponsibility &MR, |
30 | jitlink::LinkGraph &LG, |
31 | jitlink::PassConfiguration &Config) override { |
32 | // We need to insert this before the mark-live pass to ensure that we don't |
33 | // delete the bodies (their names won't match the responsibility set until |
34 | // after this pass completes. |
35 | Config.PrePrunePasses.insert( |
36 | position: Config.PrePrunePasses.begin(), |
37 | x: [&MR](LinkGraph &G) { return renameFunctionBodies(G, MR); }); |
38 | } |
39 | |
40 | Error notifyFailed(MaterializationResponsibility &MR) override { |
41 | return Error::success(); |
42 | } |
43 | |
44 | Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override { |
45 | return Error::success(); |
46 | } |
47 | |
48 | void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey, |
49 | ResourceKey SrcKey) override {} |
50 | |
51 | private: |
52 | static Error renameFunctionBodies(LinkGraph &G, |
53 | MaterializationResponsibility &MR) { |
54 | DenseMap<StringRef, NonOwningSymbolStringPtr> SymsToRename; |
55 | for (auto &[Name, Flags] : MR.getSymbols()) |
56 | if ((*Name).ends_with(Suffix: FnBodySuffix)) |
57 | SymsToRename[(*Name).drop_back(N: FnBodySuffix.size())] = |
58 | NonOwningSymbolStringPtr(Name); |
59 | |
60 | for (auto *Sym : G.defined_symbols()) { |
61 | if (!Sym->hasName()) |
62 | continue; |
63 | auto I = SymsToRename.find(Val: *Sym->getName()); |
64 | if (I == SymsToRename.end()) |
65 | continue; |
66 | Sym->setName(G.intern(SymbolName: G.allocateName(Source: *I->second))); |
67 | } |
68 | |
69 | return Error::success(); |
70 | } |
71 | }; |
72 | |
73 | LazyObjectLinkingLayer::LazyObjectLinkingLayer(ObjectLinkingLayer &BaseLayer, |
74 | LazyReexportsManager &LRMgr) |
75 | : ObjectLayer(BaseLayer.getExecutionSession()), BaseLayer(BaseLayer), |
76 | LRMgr(LRMgr) { |
77 | BaseLayer.addPlugin(P: std::make_unique<RenamerPlugin>()); |
78 | } |
79 | |
80 | Error LazyObjectLinkingLayer::add(ResourceTrackerSP RT, |
81 | std::unique_ptr<MemoryBuffer> O, |
82 | MaterializationUnit::Interface I) { |
83 | |
84 | // Object files with initializer symbols can't be lazy. |
85 | if (I.InitSymbol) |
86 | return BaseLayer.add(RT: std::move(RT), O: std::move(O), I: std::move(I)); |
87 | |
88 | auto &ES = getExecutionSession(); |
89 | SymbolAliasMap LazySymbols; |
90 | for (auto &[Name, Flags] : I.SymbolFlags) |
91 | if (Flags.isCallable()) |
92 | LazySymbols[Name] = {ES.intern(SymName: (*Name + FnBodySuffix).str()), Flags}; |
93 | |
94 | for (auto &[Name, AI] : LazySymbols) { |
95 | I.SymbolFlags.erase(Val: Name); |
96 | I.SymbolFlags[AI.Aliasee] = AI.AliasFlags; |
97 | } |
98 | |
99 | if (auto Err = BaseLayer.add(RT, O: std::move(O), I: std::move(I))) |
100 | return Err; |
101 | |
102 | auto &JD = RT->getJITDylib(); |
103 | return JD.define(MU: lazyReexports(LRM&: LRMgr, Reexports: std::move(LazySymbols)), RT: std::move(RT)); |
104 | } |
105 | |
106 | void LazyObjectLinkingLayer::emit( |
107 | std::unique_ptr<MaterializationResponsibility> MR, |
108 | std::unique_ptr<MemoryBuffer> Obj) { |
109 | return BaseLayer.emit(R: std::move(MR), O: std::move(Obj)); |
110 | } |
111 | |
112 | } // namespace llvm::orc |
113 | |