Files
clang-p2996/llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp
Lang Hames 2f8c6f9362 [ORC] Rename MaterializationResponsibility resolve and emit methods to
notifyResolved/notifyEmitted.

The 'notify' prefix better describes what these methods do: they update the JIT
symbol states and notify any pending queries that the 'resolved' and 'emitted'
states have been reached (rather than actually performing the resolution or
emission themselves). Since new states are going to be introduced in the near
future (to track symbol registration/initialization) it's worth changing the
convention pre-emptively to avoid further confusion.

llvm-svn: 363322
2019-06-13 20:11:23 +00:00

205 lines
6.6 KiB
C++

//===---------- LazyReexports.cpp - Utilities for lazy reexports ----------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/LazyReexports.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
#define DEBUG_TYPE "orc"
namespace llvm {
namespace orc {
void LazyCallThroughManager::NotifyResolvedFunction::anchor() {}
LazyCallThroughManager::LazyCallThroughManager(
ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr,
std::unique_ptr<TrampolinePool> TP)
: ES(ES), ErrorHandlerAddr(ErrorHandlerAddr), TP(std::move(TP)) {}
Expected<JITTargetAddress> LazyCallThroughManager::getCallThroughTrampoline(
JITDylib &SourceJD, SymbolStringPtr SymbolName,
std::shared_ptr<NotifyResolvedFunction> NotifyResolved) {
std::lock_guard<std::mutex> Lock(LCTMMutex);
auto Trampoline = TP->getTrampoline();
if (!Trampoline)
return Trampoline.takeError();
Reexports[*Trampoline] = std::make_pair(&SourceJD, std::move(SymbolName));
Notifiers[*Trampoline] = std::move(NotifyResolved);
return *Trampoline;
}
JITTargetAddress
LazyCallThroughManager::callThroughToSymbol(JITTargetAddress TrampolineAddr) {
JITDylib *SourceJD = nullptr;
SymbolStringPtr SymbolName;
{
std::lock_guard<std::mutex> Lock(LCTMMutex);
auto I = Reexports.find(TrampolineAddr);
if (I == Reexports.end())
return ErrorHandlerAddr;
SourceJD = I->second.first;
SymbolName = I->second.second;
}
auto LookupResult =
ES.lookup(JITDylibSearchList({{SourceJD, true}}), SymbolName);
if (!LookupResult) {
ES.reportError(LookupResult.takeError());
return ErrorHandlerAddr;
}
auto ResolvedAddr = LookupResult->getAddress();
std::shared_ptr<NotifyResolvedFunction> NotifyResolved = nullptr;
{
std::lock_guard<std::mutex> Lock(LCTMMutex);
auto I = Notifiers.find(TrampolineAddr);
if (I != Notifiers.end()) {
NotifyResolved = I->second;
Notifiers.erase(I);
}
}
if (NotifyResolved) {
if (auto Err = (*NotifyResolved)(*SourceJD, SymbolName, ResolvedAddr)) {
ES.reportError(std::move(Err));
return ErrorHandlerAddr;
}
}
return ResolvedAddr;
}
Expected<std::unique_ptr<LazyCallThroughManager>>
createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
JITTargetAddress ErrorHandlerAddr) {
switch (T.getArch()) {
default:
return make_error<StringError>(
std::string("No callback manager available for ") + T.str(),
inconvertibleErrorCode());
case Triple::aarch64:
return LocalLazyCallThroughManager::Create<OrcAArch64>(ES,
ErrorHandlerAddr);
case Triple::x86:
return LocalLazyCallThroughManager::Create<OrcI386>(ES, ErrorHandlerAddr);
case Triple::mips:
return LocalLazyCallThroughManager::Create<OrcMips32Be>(ES,
ErrorHandlerAddr);
case Triple::mipsel:
return LocalLazyCallThroughManager::Create<OrcMips32Le>(ES,
ErrorHandlerAddr);
case Triple::mips64:
case Triple::mips64el:
return LocalLazyCallThroughManager::Create<OrcMips64>(ES, ErrorHandlerAddr);
case Triple::x86_64:
if (T.getOS() == Triple::OSType::Win32)
return LocalLazyCallThroughManager::Create<OrcX86_64_Win32>(
ES, ErrorHandlerAddr);
else
return LocalLazyCallThroughManager::Create<OrcX86_64_SysV>(
ES, ErrorHandlerAddr);
}
}
LazyReexportsMaterializationUnit::LazyReexportsMaterializationUnit(
LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager,
JITDylib &SourceJD, SymbolAliasMap CallableAliases, VModuleKey K)
: MaterializationUnit(extractFlags(CallableAliases), std::move(K)),
LCTManager(LCTManager), ISManager(ISManager), SourceJD(SourceJD),
CallableAliases(std::move(CallableAliases)),
NotifyResolved(LazyCallThroughManager::createNotifyResolvedFunction(
[&ISManager](JITDylib &JD, const SymbolStringPtr &SymbolName,
JITTargetAddress ResolvedAddr) {
return ISManager.updatePointer(*SymbolName, ResolvedAddr);
})) {}
StringRef LazyReexportsMaterializationUnit::getName() const {
return "<Lazy Reexports>";
}
void LazyReexportsMaterializationUnit::materialize(
MaterializationResponsibility R) {
auto RequestedSymbols = R.getRequestedSymbols();
SymbolAliasMap RequestedAliases;
for (auto &RequestedSymbol : RequestedSymbols) {
auto I = CallableAliases.find(RequestedSymbol);
assert(I != CallableAliases.end() && "Symbol not found in alias map?");
RequestedAliases[I->first] = std::move(I->second);
CallableAliases.erase(I);
}
if (!CallableAliases.empty())
R.replace(lazyReexports(LCTManager, ISManager, SourceJD,
std::move(CallableAliases)));
IndirectStubsManager::StubInitsMap StubInits;
for (auto &Alias : RequestedAliases) {
auto CallThroughTrampoline = LCTManager.getCallThroughTrampoline(
SourceJD, Alias.second.Aliasee, NotifyResolved);
if (!CallThroughTrampoline) {
SourceJD.getExecutionSession().reportError(
CallThroughTrampoline.takeError());
R.failMaterialization();
return;
}
StubInits[*Alias.first] =
std::make_pair(*CallThroughTrampoline, Alias.second.AliasFlags);
}
if (auto Err = ISManager.createStubs(StubInits)) {
SourceJD.getExecutionSession().reportError(std::move(Err));
R.failMaterialization();
return;
}
SymbolMap Stubs;
for (auto &Alias : RequestedAliases)
Stubs[Alias.first] = ISManager.findStub(*Alias.first, false);
R.notifyResolved(Stubs);
R.notifyEmitted();
}
void LazyReexportsMaterializationUnit::discard(const JITDylib &JD,
const SymbolStringPtr &Name) {
assert(CallableAliases.count(Name) &&
"Symbol not covered by this MaterializationUnit");
CallableAliases.erase(Name);
}
SymbolFlagsMap
LazyReexportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
SymbolFlagsMap SymbolFlags;
for (auto &KV : Aliases) {
assert(KV.second.AliasFlags.isCallable() &&
"Lazy re-exports must be callable symbols");
SymbolFlags[KV.first] = KV.second.AliasFlags;
}
return SymbolFlags;
}
} // End namespace orc.
} // End namespace llvm.