]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / llvm / lib / ExecutionEngine / Orc / LazyReexports.cpp
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/LazyReexports.h"
10
11 #include "llvm/ADT/Triple.h"
12 #include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
13
14 #define DEBUG_TYPE "orc"
15
16 namespace llvm {
17 namespace orc {
18
19 void LazyCallThroughManager::NotifyResolvedFunction::anchor() {}
20
21 LazyCallThroughManager::LazyCallThroughManager(
22     ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr,
23     std::unique_ptr<TrampolinePool> TP)
24     : ES(ES), ErrorHandlerAddr(ErrorHandlerAddr), TP(std::move(TP)) {}
25
26 Expected<JITTargetAddress> LazyCallThroughManager::getCallThroughTrampoline(
27     JITDylib &SourceJD, SymbolStringPtr SymbolName,
28     std::shared_ptr<NotifyResolvedFunction> NotifyResolved) {
29   std::lock_guard<std::mutex> Lock(LCTMMutex);
30   auto Trampoline = TP->getTrampoline();
31
32   if (!Trampoline)
33     return Trampoline.takeError();
34
35   Reexports[*Trampoline] = std::make_pair(&SourceJD, std::move(SymbolName));
36   Notifiers[*Trampoline] = std::move(NotifyResolved);
37   return *Trampoline;
38 }
39
40 JITTargetAddress
41 LazyCallThroughManager::callThroughToSymbol(JITTargetAddress TrampolineAddr) {
42   JITDylib *SourceJD = nullptr;
43   SymbolStringPtr SymbolName;
44
45   {
46     std::lock_guard<std::mutex> Lock(LCTMMutex);
47     auto I = Reexports.find(TrampolineAddr);
48     if (I == Reexports.end())
49       return ErrorHandlerAddr;
50     SourceJD = I->second.first;
51     SymbolName = I->second.second;
52   }
53
54   auto LookupResult = ES.lookup(
55       makeJITDylibSearchOrder(SourceJD, JITDylibLookupFlags::MatchAllSymbols),
56       SymbolName);
57
58   if (!LookupResult) {
59     ES.reportError(LookupResult.takeError());
60     return ErrorHandlerAddr;
61   }
62
63   auto ResolvedAddr = LookupResult->getAddress();
64
65   std::shared_ptr<NotifyResolvedFunction> NotifyResolved = nullptr;
66   {
67     std::lock_guard<std::mutex> Lock(LCTMMutex);
68     auto I = Notifiers.find(TrampolineAddr);
69     if (I != Notifiers.end()) {
70       NotifyResolved = I->second;
71       Notifiers.erase(I);
72     }
73   }
74
75   if (NotifyResolved) {
76     if (auto Err = (*NotifyResolved)(*SourceJD, SymbolName, ResolvedAddr)) {
77       ES.reportError(std::move(Err));
78       return ErrorHandlerAddr;
79     }
80   }
81
82   return ResolvedAddr;
83 }
84
85 Expected<std::unique_ptr<LazyCallThroughManager>>
86 createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
87                                   JITTargetAddress ErrorHandlerAddr) {
88   switch (T.getArch()) {
89   default:
90     return make_error<StringError>(
91         std::string("No callback manager available for ") + T.str(),
92         inconvertibleErrorCode());
93
94   case Triple::aarch64:
95   case Triple::aarch64_32:
96     return LocalLazyCallThroughManager::Create<OrcAArch64>(ES,
97                                                            ErrorHandlerAddr);
98
99   case Triple::x86:
100     return LocalLazyCallThroughManager::Create<OrcI386>(ES, ErrorHandlerAddr);
101
102   case Triple::mips:
103     return LocalLazyCallThroughManager::Create<OrcMips32Be>(ES,
104                                                             ErrorHandlerAddr);
105
106   case Triple::mipsel:
107     return LocalLazyCallThroughManager::Create<OrcMips32Le>(ES,
108                                                             ErrorHandlerAddr);
109
110   case Triple::mips64:
111   case Triple::mips64el:
112     return LocalLazyCallThroughManager::Create<OrcMips64>(ES, ErrorHandlerAddr);
113
114   case Triple::x86_64:
115     if (T.getOS() == Triple::OSType::Win32)
116       return LocalLazyCallThroughManager::Create<OrcX86_64_Win32>(
117           ES, ErrorHandlerAddr);
118     else
119       return LocalLazyCallThroughManager::Create<OrcX86_64_SysV>(
120           ES, ErrorHandlerAddr);
121   }
122 }
123
124 LazyReexportsMaterializationUnit::LazyReexportsMaterializationUnit(
125     LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager,
126     JITDylib &SourceJD, SymbolAliasMap CallableAliases, ImplSymbolMap *SrcJDLoc,
127     VModuleKey K)
128     : MaterializationUnit(extractFlags(CallableAliases), std::move(K)),
129       LCTManager(LCTManager), ISManager(ISManager), SourceJD(SourceJD),
130       CallableAliases(std::move(CallableAliases)),
131       NotifyResolved(LazyCallThroughManager::createNotifyResolvedFunction(
132           [&ISManager](JITDylib &JD, const SymbolStringPtr &SymbolName,
133                        JITTargetAddress ResolvedAddr) {
134             return ISManager.updatePointer(*SymbolName, ResolvedAddr);
135           })),
136       AliaseeTable(SrcJDLoc) {}
137
138 StringRef LazyReexportsMaterializationUnit::getName() const {
139   return "<Lazy Reexports>";
140 }
141
142 void LazyReexportsMaterializationUnit::materialize(
143     MaterializationResponsibility R) {
144   auto RequestedSymbols = R.getRequestedSymbols();
145
146   SymbolAliasMap RequestedAliases;
147   for (auto &RequestedSymbol : RequestedSymbols) {
148     auto I = CallableAliases.find(RequestedSymbol);
149     assert(I != CallableAliases.end() && "Symbol not found in alias map?");
150     RequestedAliases[I->first] = std::move(I->second);
151     CallableAliases.erase(I);
152   }
153
154   if (!CallableAliases.empty())
155     R.replace(lazyReexports(LCTManager, ISManager, SourceJD,
156                             std::move(CallableAliases), AliaseeTable));
157
158   IndirectStubsManager::StubInitsMap StubInits;
159   for (auto &Alias : RequestedAliases) {
160
161     auto CallThroughTrampoline = LCTManager.getCallThroughTrampoline(
162         SourceJD, Alias.second.Aliasee, NotifyResolved);
163
164     if (!CallThroughTrampoline) {
165       SourceJD.getExecutionSession().reportError(
166           CallThroughTrampoline.takeError());
167       R.failMaterialization();
168       return;
169     }
170
171     StubInits[*Alias.first] =
172         std::make_pair(*CallThroughTrampoline, Alias.second.AliasFlags);
173   }
174
175   if (AliaseeTable != nullptr && !RequestedAliases.empty())
176     AliaseeTable->trackImpls(RequestedAliases, &SourceJD);
177
178   if (auto Err = ISManager.createStubs(StubInits)) {
179     SourceJD.getExecutionSession().reportError(std::move(Err));
180     R.failMaterialization();
181     return;
182   }
183
184   SymbolMap Stubs;
185   for (auto &Alias : RequestedAliases)
186     Stubs[Alias.first] = ISManager.findStub(*Alias.first, false);
187
188   // No registered dependencies, so these calls cannot fail.
189   cantFail(R.notifyResolved(Stubs));
190   cantFail(R.notifyEmitted());
191 }
192
193 void LazyReexportsMaterializationUnit::discard(const JITDylib &JD,
194                                                const SymbolStringPtr &Name) {
195   assert(CallableAliases.count(Name) &&
196          "Symbol not covered by this MaterializationUnit");
197   CallableAliases.erase(Name);
198 }
199
200 SymbolFlagsMap
201 LazyReexportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
202   SymbolFlagsMap SymbolFlags;
203   for (auto &KV : Aliases) {
204     assert(KV.second.AliasFlags.isCallable() &&
205            "Lazy re-exports must be callable symbols");
206     SymbolFlags[KV.first] = KV.second.AliasFlags;
207   }
208   return SymbolFlags;
209 }
210
211 } // End namespace orc.
212 } // End namespace llvm.