]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / ExecutionEngine / Orc / LazyReexports.cpp
1 //===---------- LazyReexports.cpp - Utilities for lazy reexports ----------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "llvm/ExecutionEngine/Orc/LazyReexports.h"
11
12 #include "llvm/ADT/Triple.h"
13 #include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
14
15 #define DEBUG_TYPE "orc"
16
17 namespace llvm {
18 namespace orc {
19
20 void LazyCallThroughManager::NotifyResolvedFunction::anchor() {}
21
22 LazyCallThroughManager::LazyCallThroughManager(
23     ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr,
24     std::unique_ptr<TrampolinePool> TP)
25     : ES(ES), ErrorHandlerAddr(ErrorHandlerAddr), TP(std::move(TP)) {}
26
27 Expected<JITTargetAddress> LazyCallThroughManager::getCallThroughTrampoline(
28     JITDylib &SourceJD, SymbolStringPtr SymbolName,
29     std::shared_ptr<NotifyResolvedFunction> NotifyResolved) {
30   std::lock_guard<std::mutex> Lock(LCTMMutex);
31   auto Trampoline = TP->getTrampoline();
32
33   if (!Trampoline)
34     return Trampoline.takeError();
35
36   Reexports[*Trampoline] = std::make_pair(&SourceJD, std::move(SymbolName));
37   Notifiers[*Trampoline] = std::move(NotifyResolved);
38   return *Trampoline;
39 }
40
41 JITTargetAddress
42 LazyCallThroughManager::callThroughToSymbol(JITTargetAddress TrampolineAddr) {
43   JITDylib *SourceJD = nullptr;
44   SymbolStringPtr SymbolName;
45
46   {
47     std::lock_guard<std::mutex> Lock(LCTMMutex);
48     auto I = Reexports.find(TrampolineAddr);
49     if (I == Reexports.end())
50       return ErrorHandlerAddr;
51     SourceJD = I->second.first;
52     SymbolName = I->second.second;
53   }
54
55   auto LookupResult = ES.lookup(JITDylibSearchList({{SourceJD, true}}),
56                                 {SymbolName}, NoDependenciesToRegister, true);
57
58   if (!LookupResult) {
59     ES.reportError(LookupResult.takeError());
60     return ErrorHandlerAddr;
61   }
62
63   assert(LookupResult->size() == 1 && "Unexpected number of results");
64   assert(LookupResult->count(SymbolName) && "Unexpected result");
65
66   auto ResolvedAddr = LookupResult->begin()->second.getAddress();
67
68   std::shared_ptr<NotifyResolvedFunction> NotifyResolved = nullptr;
69   {
70     std::lock_guard<std::mutex> Lock(LCTMMutex);
71     auto I = Notifiers.find(TrampolineAddr);
72     if (I != Notifiers.end()) {
73       NotifyResolved = I->second;
74       Notifiers.erase(I);
75     }
76   }
77
78   if (NotifyResolved) {
79     if (auto Err = (*NotifyResolved)(*SourceJD, SymbolName, ResolvedAddr)) {
80       ES.reportError(std::move(Err));
81       return ErrorHandlerAddr;
82     }
83   }
84
85   return ResolvedAddr;
86 }
87
88 Expected<std::unique_ptr<LazyCallThroughManager>>
89 createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
90                                   JITTargetAddress ErrorHandlerAddr) {
91   switch (T.getArch()) {
92   default:
93     return make_error<StringError>(
94         std::string("No callback manager available for ") + T.str(),
95         inconvertibleErrorCode());
96
97   case Triple::aarch64:
98     return LocalLazyCallThroughManager::Create<OrcAArch64>(ES,
99                                                            ErrorHandlerAddr);
100
101   case Triple::x86:
102     return LocalLazyCallThroughManager::Create<OrcI386>(ES, ErrorHandlerAddr);
103
104   case Triple::mips:
105     return LocalLazyCallThroughManager::Create<OrcMips32Be>(ES,
106                                                             ErrorHandlerAddr);
107
108   case Triple::mipsel:
109     return LocalLazyCallThroughManager::Create<OrcMips32Le>(ES,
110                                                             ErrorHandlerAddr);
111
112   case Triple::mips64:
113   case Triple::mips64el:
114     return LocalLazyCallThroughManager::Create<OrcMips64>(ES, ErrorHandlerAddr);
115
116   case Triple::x86_64:
117     if (T.getOS() == Triple::OSType::Win32)
118       return LocalLazyCallThroughManager::Create<OrcX86_64_Win32>(
119           ES, ErrorHandlerAddr);
120     else
121       return LocalLazyCallThroughManager::Create<OrcX86_64_SysV>(
122           ES, ErrorHandlerAddr);
123   }
124 }
125
126 LazyReexportsMaterializationUnit::LazyReexportsMaterializationUnit(
127     LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager,
128     JITDylib &SourceJD, SymbolAliasMap CallableAliases, VModuleKey K)
129     : MaterializationUnit(extractFlags(CallableAliases), std::move(K)),
130       LCTManager(LCTManager), ISManager(ISManager), SourceJD(SourceJD),
131       CallableAliases(std::move(CallableAliases)),
132       NotifyResolved(LazyCallThroughManager::createNotifyResolvedFunction(
133           [&ISManager](JITDylib &JD, const SymbolStringPtr &SymbolName,
134                        JITTargetAddress ResolvedAddr) {
135             return ISManager.updatePointer(*SymbolName, ResolvedAddr);
136           })) {}
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)));
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 (auto Err = ISManager.createStubs(StubInits)) {
176     SourceJD.getExecutionSession().reportError(std::move(Err));
177     R.failMaterialization();
178     return;
179   }
180
181   SymbolMap Stubs;
182   for (auto &Alias : RequestedAliases)
183     Stubs[Alias.first] = ISManager.findStub(*Alias.first, false);
184
185   R.resolve(Stubs);
186   R.emit();
187 }
188
189 void LazyReexportsMaterializationUnit::discard(const JITDylib &JD,
190                                                const SymbolStringPtr &Name) {
191   assert(CallableAliases.count(Name) &&
192          "Symbol not covered by this MaterializationUnit");
193   CallableAliases.erase(Name);
194 }
195
196 SymbolFlagsMap
197 LazyReexportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
198   SymbolFlagsMap SymbolFlags;
199   for (auto &KV : Aliases) {
200     assert(KV.second.AliasFlags.isCallable() &&
201            "Lazy re-exports must be callable symbols");
202     SymbolFlags[KV.first] = KV.second.AliasFlags;
203   }
204   return SymbolFlags;
205 }
206
207 } // End namespace orc.
208 } // End namespace llvm.