[llvm] 6428857 - [ORC] Introduce lookupAndRecordAddrs utility.
Lang Hames via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 19 22:15:38 PDT 2021
Author: Lang Hames
Date: 2021-08-20T15:12:19+10:00
New Revision: 642885710e20acf3cc0d815009e62b8a39693bc0
URL: https://github.com/llvm/llvm-project/commit/642885710e20acf3cc0d815009e62b8a39693bc0
DIFF: https://github.com/llvm/llvm-project/commit/642885710e20acf3cc0d815009e62b8a39693bc0.diff
LOG: [ORC] Introduce lookupAndRecordAddrs utility.
Accepts a vector of (SymbolStringPtr, ExecutorAddress*) pairs, looks up all the
symbols, then writes their address to each of the corresponding
ExecutorAddresses.
This idiom (looking up and recording addresses into a specific set of variables)
is used in MachOPlatform and the (temporarily reverted) ELFNixPlatform, and is
likely to be used in other places in the near future, so wrapping it in a
utility function should save us some boilerplate.
Added:
llvm/include/llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h
llvm/lib/ExecutionEngine/Orc/LookupAndRecordAddrs.cpp
llvm/unittests/ExecutionEngine/Orc/LookupAndRecordAddrsTest.cpp
Modified:
llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
Removed:
################################################################################
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h b/llvm/include/llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h
new file mode 100644
index 0000000000000..c100005afc1e1
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h
@@ -0,0 +1,69 @@
+//===-- LookupAndRecordAddrs.h - Symbol lookup support utility --*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Record the addresses of a set of symbols into ExecutorAddress objects.
+//
+// This can be used to avoid repeated lookup (via ExecutionSession::lookup) of
+// the given symbols.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_LOOKUPANDRECORDADDRS_H
+#define LLVM_EXECUTIONENGINE_ORC_LOOKUPANDRECORDADDRS_H
+
+#include "llvm/ADT/FunctionExtras.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
+
+#include <vector>
+
+namespace llvm {
+namespace orc {
+
+/// Record addresses of the given symbols in the given ExecutorAddresses.
+///
+/// Useful for making permanent records of symbol addreses to call or
+/// access in the executor (e.g. runtime support functions in Platform
+/// subclasses).
+///
+/// By default the symbols are looked up using
+/// SymbolLookupFlags::RequiredSymbol, and an error will be generated if any of
+/// the requested symbols are not defined.
+///
+/// If SymbolLookupFlags::WeaklyReferencedSymbol is used then any missing
+/// symbols will have their corresponding address objects set to zero, and
+/// this function will never generate an error (the caller will need to check
+/// addresses before using them).
+///
+/// Asynchronous version.
+void lookupAndRecordAddrs(
+ unique_function<void(Error)> OnRecorded, ExecutionSession &ES, LookupKind K,
+ const JITDylibSearchOrder &SearchOrder,
+ std::vector<std::pair<SymbolStringPtr, ExecutorAddress *>> Pairs,
+ SymbolLookupFlags LookupFlags = SymbolLookupFlags::RequiredSymbol);
+
+/// Record addresses of the given symbols in the given ExecutorAddresses.
+///
+/// Blocking version.
+Error lookupAndRecordAddrs(
+ ExecutionSession &ES, LookupKind K, const JITDylibSearchOrder &SearchOrder,
+ std::vector<std::pair<SymbolStringPtr, ExecutorAddress *>> Pairs,
+ SymbolLookupFlags LookupFlags = SymbolLookupFlags::RequiredSymbol);
+
+/// Record addresses of given symbols in the given ExecutorAddresses.
+///
+/// ExecutorProcessControl lookup version. Lookups are always implicitly
+/// weak.
+Error lookupAndRecordAddrs(
+ ExecutorProcessControl &EPC, tpctypes::DylibHandle H,
+ std::vector<std::pair<SymbolStringPtr, ExecutorAddress *>> Pairs);
+
+} // End namespace orc
+} // End namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_LOOKUPANDRECORDADDRS_H
diff --git a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
index edf9b3ff9b394..6dc12dac7daf1 100644
--- a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
@@ -15,6 +15,7 @@ add_llvm_component_library(LLVMOrcJIT
JITTargetMachineBuilder.cpp
LazyReexports.cpp
Layer.cpp
+ LookupAndRecordAddrs.cpp
LLJIT.cpp
MachOPlatform.cpp
Mangling.cpp
diff --git a/llvm/lib/ExecutionEngine/Orc/LookupAndRecordAddrs.cpp b/llvm/lib/ExecutionEngine/Orc/LookupAndRecordAddrs.cpp
new file mode 100644
index 0000000000000..35b469692f80d
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/LookupAndRecordAddrs.cpp
@@ -0,0 +1,82 @@
+//===------- LookupAndRecordAddrs.h - Symbol lookup support utility -------===//
+//
+// 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/LookupAndRecordAddrs.h"
+
+#include <future>
+
+namespace llvm {
+namespace orc {
+
+void lookupAndRecordAddrs(
+ unique_function<void(Error)> OnRecorded, ExecutionSession &ES, LookupKind K,
+ const JITDylibSearchOrder &SearchOrder,
+ std::vector<std::pair<SymbolStringPtr, ExecutorAddress *>> Pairs,
+ SymbolLookupFlags LookupFlags) {
+
+ SymbolLookupSet Symbols;
+ for (auto &KV : Pairs)
+ Symbols.add(KV.first, LookupFlags);
+
+ ES.lookup(
+ K, SearchOrder, Symbols, SymbolState::Ready,
+ [Pairs = std::move(Pairs),
+ OnRec = std::move(OnRecorded)](Expected<SymbolMap> Result) mutable {
+ if (!Result)
+ return OnRec(Result.takeError());
+ for (auto &KV : Pairs) {
+ auto I = Result->find(KV.first);
+ KV.second->setValue((I != Result->end()) ? I->second.getAddress()
+ : 0);
+ }
+ OnRec(Error::success());
+ },
+ NoDependenciesToRegister);
+}
+
+Error lookupAndRecordAddrs(
+ ExecutionSession &ES, LookupKind K, const JITDylibSearchOrder &SearchOrder,
+ std::vector<std::pair<SymbolStringPtr, ExecutorAddress *>> Pairs,
+ SymbolLookupFlags LookupFlags) {
+
+ std::promise<MSVCPError> ResultP;
+ auto ResultF = ResultP.get_future();
+ lookupAndRecordAddrs([&](Error Err) { ResultP.set_value(std::move(Err)); },
+ ES, K, SearchOrder, Pairs, LookupFlags);
+ return ResultF.get();
+}
+
+Error lookupAndRecordAddrs(
+ ExecutorProcessControl &EPC, tpctypes::DylibHandle H,
+ std::vector<std::pair<SymbolStringPtr, ExecutorAddress *>> Pairs,
+ SymbolLookupFlags LookupFlags) {
+
+ SymbolLookupSet Symbols;
+ for (auto &KV : Pairs)
+ Symbols.add(KV.first, LookupFlags);
+
+ ExecutorProcessControl::LookupRequest LR(H, Symbols);
+ auto Result = EPC.lookupSymbols(LR);
+ if (!Result)
+ return Result.takeError();
+
+ if (Result->size() != 1)
+ return make_error<StringError>("Error in lookup result",
+ inconvertibleErrorCode());
+ if (Result->front().size() != Pairs.size())
+ return make_error<StringError>("Error in lookup result elements",
+ inconvertibleErrorCode());
+
+ for (unsigned I = 0; I != Pairs.size(); ++I)
+ Pairs[I].second->setValue(Result->front()[I]);
+
+ return Error::success();
+}
+
+} // End namespace orc.
+} // End namespace llvm.
diff --git a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
index 23086d3bfb32b..e04fe1f19212c 100644
--- a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
@@ -12,6 +12,7 @@
#include "llvm/ExecutionEngine/JITLink/x86_64.h"
#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/Debug.h"
@@ -496,31 +497,17 @@ void MachOPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
Error MachOPlatform::bootstrapMachORuntime(JITDylib &PlatformJD) {
- std::pair<const char *, ExecutorAddress *> Symbols[] = {
- {"___orc_rt_macho_platform_bootstrap", &orc_rt_macho_platform_bootstrap},
- {"___orc_rt_macho_platform_shutdown", &orc_rt_macho_platform_shutdown},
- {"___orc_rt_macho_register_object_sections",
- &orc_rt_macho_register_object_sections},
- {"___orc_rt_macho_create_pthread_key", &orc_rt_macho_create_pthread_key}};
-
- SymbolLookupSet RuntimeSymbols;
- std::vector<std::pair<SymbolStringPtr, ExecutorAddress *>> AddrsToRecord;
- for (const auto &KV : Symbols) {
- auto Name = ES.intern(KV.first);
- RuntimeSymbols.add(Name);
- AddrsToRecord.push_back({std::move(Name), KV.second});
- }
-
- auto RuntimeSymbolAddrs = ES.lookup(
- {{&PlatformJD, JITDylibLookupFlags::MatchAllSymbols}}, RuntimeSymbols);
- if (!RuntimeSymbolAddrs)
- return RuntimeSymbolAddrs.takeError();
-
- for (const auto &KV : AddrsToRecord) {
- auto &Name = KV.first;
- assert(RuntimeSymbolAddrs->count(Name) && "Missing runtime symbol?");
- KV.second->setValue((*RuntimeSymbolAddrs)[Name].getAddress());
- }
+ if (auto Err = lookupAndRecordAddrs(
+ ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
+ {{ES.intern("___orc_rt_macho_platform_bootstrap"),
+ &orc_rt_macho_platform_bootstrap},
+ {ES.intern("___orc_rt_macho_platform_shutdown"),
+ &orc_rt_macho_platform_shutdown},
+ {ES.intern("___orc_rt_macho_register_object_sections"),
+ &orc_rt_macho_register_object_sections},
+ {ES.intern("___orc_rt_macho_create_pthread_key"),
+ &orc_rt_macho_create_pthread_key}}))
+ return Err;
if (auto Err =
ES.callSPSWrapper<void()>(orc_rt_macho_platform_bootstrap.getValue()))
diff --git a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
index 5c2a7879dcd3f..8f7097af7a8cc 100644
--- a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
+++ b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
@@ -20,6 +20,7 @@ add_llvm_unittest(OrcJITTests
IndirectionUtilsTest.cpp
JITTargetMachineBuilderTest.cpp
LazyCallThroughAndReexportsTest.cpp
+ LookupAndRecordAddrsTest.cpp
ObjectLinkingLayerTest.cpp
OrcCAPITest.cpp
OrcTestCommon.cpp
diff --git a/llvm/unittests/ExecutionEngine/Orc/LookupAndRecordAddrsTest.cpp b/llvm/unittests/ExecutionEngine/Orc/LookupAndRecordAddrsTest.cpp
new file mode 100644
index 0000000000000..aff356149f667
--- /dev/null
+++ b/llvm/unittests/ExecutionEngine/Orc/LookupAndRecordAddrsTest.cpp
@@ -0,0 +1,108 @@
+//===- LookupAndRecordAddrsTest.cpp - Unit tests for LookupAndRecordAddrs -===//
+//
+// 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 "OrcTestCommon.h"
+
+#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
+#include "llvm/Support/MSVCErrorWorkarounds.h"
+#include "llvm/Testing/Support/Error.h"
+
+#include <future>
+
+using namespace llvm;
+using namespace llvm::orc;
+
+class LookupAndRecordAddrsTest : public CoreAPIsBasedStandardTest {};
+
+namespace {
+
+TEST_F(LookupAndRecordAddrsTest, AsyncRequiredSuccess) {
+ cantFail(JD.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarSym}})));
+
+ ExecutorAddress FooAddress, BarAddress;
+ std::promise<MSVCPError> ErrP;
+
+ lookupAndRecordAddrs([&](Error Err) { ErrP.set_value(std::move(Err)); }, ES,
+ LookupKind::Static, makeJITDylibSearchOrder(&JD),
+ {{Foo, &FooAddress}, {Bar, &BarAddress}});
+
+ Error Err = ErrP.get_future().get();
+
+ EXPECT_THAT_ERROR(std::move(Err), Succeeded());
+ EXPECT_EQ(FooAddress.getValue(), FooAddr);
+ EXPECT_EQ(BarAddress.getValue(), BarAddr);
+}
+
+TEST_F(LookupAndRecordAddrsTest, AsyncRequiredFailure) {
+ ExecutorAddress FooAddress, BarAddress;
+ std::promise<MSVCPError> ErrP;
+
+ lookupAndRecordAddrs([&](Error Err) { ErrP.set_value(std::move(Err)); }, ES,
+ LookupKind::Static, makeJITDylibSearchOrder(&JD),
+ {{Foo, &FooAddress}, {Bar, &BarAddress}});
+
+ Error Err = ErrP.get_future().get();
+
+ EXPECT_THAT_ERROR(std::move(Err), Failed());
+}
+
+TEST_F(LookupAndRecordAddrsTest, AsyncWeakReference) {
+ cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
+
+ ExecutorAddress FooAddress, BarAddress;
+ std::promise<MSVCPError> ErrP;
+
+ lookupAndRecordAddrs([&](Error Err) { ErrP.set_value(std::move(Err)); }, ES,
+ LookupKind::Static, makeJITDylibSearchOrder(&JD),
+ {{Foo, &FooAddress}, {Bar, &BarAddress}},
+ SymbolLookupFlags::WeaklyReferencedSymbol);
+
+ Error Err = ErrP.get_future().get();
+
+ EXPECT_THAT_ERROR(std::move(Err), Succeeded());
+ EXPECT_EQ(FooAddress.getValue(), FooAddr);
+ EXPECT_EQ(BarAddress.getValue(), 0U);
+}
+
+TEST_F(LookupAndRecordAddrsTest, BlockingRequiredSuccess) {
+ cantFail(JD.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarSym}})));
+
+ ExecutorAddress FooAddress, BarAddress;
+ auto Err =
+ lookupAndRecordAddrs(ES, LookupKind::Static, makeJITDylibSearchOrder(&JD),
+ {{Foo, &FooAddress}, {Bar, &BarAddress}});
+
+ EXPECT_THAT_ERROR(std::move(Err), Succeeded());
+ EXPECT_EQ(FooAddress.getValue(), FooAddr);
+ EXPECT_EQ(BarAddress.getValue(), BarAddr);
+}
+
+TEST_F(LookupAndRecordAddrsTest, BlockingRequiredFailure) {
+ ExecutorAddress FooAddress, BarAddress;
+ auto Err =
+ lookupAndRecordAddrs(ES, LookupKind::Static, makeJITDylibSearchOrder(&JD),
+ {{Foo, &FooAddress}, {Bar, &BarAddress}});
+
+ EXPECT_THAT_ERROR(std::move(Err), Failed());
+}
+
+TEST_F(LookupAndRecordAddrsTest, BlockingWeakReference) {
+ cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
+
+ ExecutorAddress FooAddress, BarAddress;
+ auto Err =
+ lookupAndRecordAddrs(ES, LookupKind::Static, makeJITDylibSearchOrder(&JD),
+ {{Foo, &FooAddress}, {Bar, &BarAddress}},
+ SymbolLookupFlags::WeaklyReferencedSymbol);
+
+ EXPECT_THAT_ERROR(std::move(Err), Succeeded());
+ EXPECT_EQ(FooAddress.getValue(), FooAddr);
+ EXPECT_EQ(BarAddress.getValue(), 0U);
+}
+
+} // namespace
More information about the llvm-commits
mailing list