Skip to content

Commit 6428857

Browse files
committed
[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.
1 parent 1cd3d19 commit 6428857

File tree

6 files changed

+273
-25
lines changed

6 files changed

+273
-25
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
//===-- LookupAndRecordAddrs.h - Symbol lookup support utility --*- C++ -*-===//
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+
// Record the addresses of a set of symbols into ExecutorAddress objects.
10+
//
11+
// This can be used to avoid repeated lookup (via ExecutionSession::lookup) of
12+
// the given symbols.
13+
//
14+
//===----------------------------------------------------------------------===//
15+
16+
#ifndef LLVM_EXECUTIONENGINE_ORC_LOOKUPANDRECORDADDRS_H
17+
#define LLVM_EXECUTIONENGINE_ORC_LOOKUPANDRECORDADDRS_H
18+
19+
#include "llvm/ADT/FunctionExtras.h"
20+
#include "llvm/ExecutionEngine/Orc/Core.h"
21+
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
22+
23+
#include <vector>
24+
25+
namespace llvm {
26+
namespace orc {
27+
28+
/// Record addresses of the given symbols in the given ExecutorAddresses.
29+
///
30+
/// Useful for making permanent records of symbol addreses to call or
31+
/// access in the executor (e.g. runtime support functions in Platform
32+
/// subclasses).
33+
///
34+
/// By default the symbols are looked up using
35+
/// SymbolLookupFlags::RequiredSymbol, and an error will be generated if any of
36+
/// the requested symbols are not defined.
37+
///
38+
/// If SymbolLookupFlags::WeaklyReferencedSymbol is used then any missing
39+
/// symbols will have their corresponding address objects set to zero, and
40+
/// this function will never generate an error (the caller will need to check
41+
/// addresses before using them).
42+
///
43+
/// Asynchronous version.
44+
void lookupAndRecordAddrs(
45+
unique_function<void(Error)> OnRecorded, ExecutionSession &ES, LookupKind K,
46+
const JITDylibSearchOrder &SearchOrder,
47+
std::vector<std::pair<SymbolStringPtr, ExecutorAddress *>> Pairs,
48+
SymbolLookupFlags LookupFlags = SymbolLookupFlags::RequiredSymbol);
49+
50+
/// Record addresses of the given symbols in the given ExecutorAddresses.
51+
///
52+
/// Blocking version.
53+
Error lookupAndRecordAddrs(
54+
ExecutionSession &ES, LookupKind K, const JITDylibSearchOrder &SearchOrder,
55+
std::vector<std::pair<SymbolStringPtr, ExecutorAddress *>> Pairs,
56+
SymbolLookupFlags LookupFlags = SymbolLookupFlags::RequiredSymbol);
57+
58+
/// Record addresses of given symbols in the given ExecutorAddresses.
59+
///
60+
/// ExecutorProcessControl lookup version. Lookups are always implicitly
61+
/// weak.
62+
Error lookupAndRecordAddrs(
63+
ExecutorProcessControl &EPC, tpctypes::DylibHandle H,
64+
std::vector<std::pair<SymbolStringPtr, ExecutorAddress *>> Pairs);
65+
66+
} // End namespace orc
67+
} // End namespace llvm
68+
69+
#endif // LLVM_EXECUTIONENGINE_ORC_LOOKUPANDRECORDADDRS_H

llvm/lib/ExecutionEngine/Orc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ add_llvm_component_library(LLVMOrcJIT
1515
JITTargetMachineBuilder.cpp
1616
LazyReexports.cpp
1717
Layer.cpp
18+
LookupAndRecordAddrs.cpp
1819
LLJIT.cpp
1920
MachOPlatform.cpp
2021
Mangling.cpp
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//===------- LookupAndRecordAddrs.h - Symbol lookup support utility -------===//
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/LookupAndRecordAddrs.h"
10+
11+
#include <future>
12+
13+
namespace llvm {
14+
namespace orc {
15+
16+
void lookupAndRecordAddrs(
17+
unique_function<void(Error)> OnRecorded, ExecutionSession &ES, LookupKind K,
18+
const JITDylibSearchOrder &SearchOrder,
19+
std::vector<std::pair<SymbolStringPtr, ExecutorAddress *>> Pairs,
20+
SymbolLookupFlags LookupFlags) {
21+
22+
SymbolLookupSet Symbols;
23+
for (auto &KV : Pairs)
24+
Symbols.add(KV.first, LookupFlags);
25+
26+
ES.lookup(
27+
K, SearchOrder, Symbols, SymbolState::Ready,
28+
[Pairs = std::move(Pairs),
29+
OnRec = std::move(OnRecorded)](Expected<SymbolMap> Result) mutable {
30+
if (!Result)
31+
return OnRec(Result.takeError());
32+
for (auto &KV : Pairs) {
33+
auto I = Result->find(KV.first);
34+
KV.second->setValue((I != Result->end()) ? I->second.getAddress()
35+
: 0);
36+
}
37+
OnRec(Error::success());
38+
},
39+
NoDependenciesToRegister);
40+
}
41+
42+
Error lookupAndRecordAddrs(
43+
ExecutionSession &ES, LookupKind K, const JITDylibSearchOrder &SearchOrder,
44+
std::vector<std::pair<SymbolStringPtr, ExecutorAddress *>> Pairs,
45+
SymbolLookupFlags LookupFlags) {
46+
47+
std::promise<MSVCPError> ResultP;
48+
auto ResultF = ResultP.get_future();
49+
lookupAndRecordAddrs([&](Error Err) { ResultP.set_value(std::move(Err)); },
50+
ES, K, SearchOrder, Pairs, LookupFlags);
51+
return ResultF.get();
52+
}
53+
54+
Error lookupAndRecordAddrs(
55+
ExecutorProcessControl &EPC, tpctypes::DylibHandle H,
56+
std::vector<std::pair<SymbolStringPtr, ExecutorAddress *>> Pairs,
57+
SymbolLookupFlags LookupFlags) {
58+
59+
SymbolLookupSet Symbols;
60+
for (auto &KV : Pairs)
61+
Symbols.add(KV.first, LookupFlags);
62+
63+
ExecutorProcessControl::LookupRequest LR(H, Symbols);
64+
auto Result = EPC.lookupSymbols(LR);
65+
if (!Result)
66+
return Result.takeError();
67+
68+
if (Result->size() != 1)
69+
return make_error<StringError>("Error in lookup result",
70+
inconvertibleErrorCode());
71+
if (Result->front().size() != Pairs.size())
72+
return make_error<StringError>("Error in lookup result elements",
73+
inconvertibleErrorCode());
74+
75+
for (unsigned I = 0; I != Pairs.size(); ++I)
76+
Pairs[I].second->setValue(Result->front()[I]);
77+
78+
return Error::success();
79+
}
80+
81+
} // End namespace orc.
82+
} // End namespace llvm.

llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "llvm/ExecutionEngine/JITLink/x86_64.h"
1313
#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
1414
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
15+
#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
1516
#include "llvm/Support/BinaryByteStream.h"
1617
#include "llvm/Support/Debug.h"
1718

@@ -496,31 +497,17 @@ void MachOPlatform::rt_lookupSymbol(SendSymbolAddressFn SendResult,
496497

497498
Error MachOPlatform::bootstrapMachORuntime(JITDylib &PlatformJD) {
498499

499-
std::pair<const char *, ExecutorAddress *> Symbols[] = {
500-
{"___orc_rt_macho_platform_bootstrap", &orc_rt_macho_platform_bootstrap},
501-
{"___orc_rt_macho_platform_shutdown", &orc_rt_macho_platform_shutdown},
502-
{"___orc_rt_macho_register_object_sections",
503-
&orc_rt_macho_register_object_sections},
504-
{"___orc_rt_macho_create_pthread_key", &orc_rt_macho_create_pthread_key}};
505-
506-
SymbolLookupSet RuntimeSymbols;
507-
std::vector<std::pair<SymbolStringPtr, ExecutorAddress *>> AddrsToRecord;
508-
for (const auto &KV : Symbols) {
509-
auto Name = ES.intern(KV.first);
510-
RuntimeSymbols.add(Name);
511-
AddrsToRecord.push_back({std::move(Name), KV.second});
512-
}
513-
514-
auto RuntimeSymbolAddrs = ES.lookup(
515-
{{&PlatformJD, JITDylibLookupFlags::MatchAllSymbols}}, RuntimeSymbols);
516-
if (!RuntimeSymbolAddrs)
517-
return RuntimeSymbolAddrs.takeError();
518-
519-
for (const auto &KV : AddrsToRecord) {
520-
auto &Name = KV.first;
521-
assert(RuntimeSymbolAddrs->count(Name) && "Missing runtime symbol?");
522-
KV.second->setValue((*RuntimeSymbolAddrs)[Name].getAddress());
523-
}
500+
if (auto Err = lookupAndRecordAddrs(
501+
ES, LookupKind::Static, makeJITDylibSearchOrder(&PlatformJD),
502+
{{ES.intern("___orc_rt_macho_platform_bootstrap"),
503+
&orc_rt_macho_platform_bootstrap},
504+
{ES.intern("___orc_rt_macho_platform_shutdown"),
505+
&orc_rt_macho_platform_shutdown},
506+
{ES.intern("___orc_rt_macho_register_object_sections"),
507+
&orc_rt_macho_register_object_sections},
508+
{ES.intern("___orc_rt_macho_create_pthread_key"),
509+
&orc_rt_macho_create_pthread_key}}))
510+
return Err;
524511

525512
if (auto Err =
526513
ES.callSPSWrapper<void()>(orc_rt_macho_platform_bootstrap.getValue()))

llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ add_llvm_unittest(OrcJITTests
2020
IndirectionUtilsTest.cpp
2121
JITTargetMachineBuilderTest.cpp
2222
LazyCallThroughAndReexportsTest.cpp
23+
LookupAndRecordAddrsTest.cpp
2324
ObjectLinkingLayerTest.cpp
2425
OrcCAPITest.cpp
2526
OrcTestCommon.cpp
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
//===- LookupAndRecordAddrsTest.cpp - Unit tests for LookupAndRecordAddrs -===//
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 "OrcTestCommon.h"
10+
11+
#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
12+
#include "llvm/Support/MSVCErrorWorkarounds.h"
13+
#include "llvm/Testing/Support/Error.h"
14+
15+
#include <future>
16+
17+
using namespace llvm;
18+
using namespace llvm::orc;
19+
20+
class LookupAndRecordAddrsTest : public CoreAPIsBasedStandardTest {};
21+
22+
namespace {
23+
24+
TEST_F(LookupAndRecordAddrsTest, AsyncRequiredSuccess) {
25+
cantFail(JD.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarSym}})));
26+
27+
ExecutorAddress FooAddress, BarAddress;
28+
std::promise<MSVCPError> ErrP;
29+
30+
lookupAndRecordAddrs([&](Error Err) { ErrP.set_value(std::move(Err)); }, ES,
31+
LookupKind::Static, makeJITDylibSearchOrder(&JD),
32+
{{Foo, &FooAddress}, {Bar, &BarAddress}});
33+
34+
Error Err = ErrP.get_future().get();
35+
36+
EXPECT_THAT_ERROR(std::move(Err), Succeeded());
37+
EXPECT_EQ(FooAddress.getValue(), FooAddr);
38+
EXPECT_EQ(BarAddress.getValue(), BarAddr);
39+
}
40+
41+
TEST_F(LookupAndRecordAddrsTest, AsyncRequiredFailure) {
42+
ExecutorAddress FooAddress, BarAddress;
43+
std::promise<MSVCPError> ErrP;
44+
45+
lookupAndRecordAddrs([&](Error Err) { ErrP.set_value(std::move(Err)); }, ES,
46+
LookupKind::Static, makeJITDylibSearchOrder(&JD),
47+
{{Foo, &FooAddress}, {Bar, &BarAddress}});
48+
49+
Error Err = ErrP.get_future().get();
50+
51+
EXPECT_THAT_ERROR(std::move(Err), Failed());
52+
}
53+
54+
TEST_F(LookupAndRecordAddrsTest, AsyncWeakReference) {
55+
cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
56+
57+
ExecutorAddress FooAddress, BarAddress;
58+
std::promise<MSVCPError> ErrP;
59+
60+
lookupAndRecordAddrs([&](Error Err) { ErrP.set_value(std::move(Err)); }, ES,
61+
LookupKind::Static, makeJITDylibSearchOrder(&JD),
62+
{{Foo, &FooAddress}, {Bar, &BarAddress}},
63+
SymbolLookupFlags::WeaklyReferencedSymbol);
64+
65+
Error Err = ErrP.get_future().get();
66+
67+
EXPECT_THAT_ERROR(std::move(Err), Succeeded());
68+
EXPECT_EQ(FooAddress.getValue(), FooAddr);
69+
EXPECT_EQ(BarAddress.getValue(), 0U);
70+
}
71+
72+
TEST_F(LookupAndRecordAddrsTest, BlockingRequiredSuccess) {
73+
cantFail(JD.define(absoluteSymbols({{Foo, FooSym}, {Bar, BarSym}})));
74+
75+
ExecutorAddress FooAddress, BarAddress;
76+
auto Err =
77+
lookupAndRecordAddrs(ES, LookupKind::Static, makeJITDylibSearchOrder(&JD),
78+
{{Foo, &FooAddress}, {Bar, &BarAddress}});
79+
80+
EXPECT_THAT_ERROR(std::move(Err), Succeeded());
81+
EXPECT_EQ(FooAddress.getValue(), FooAddr);
82+
EXPECT_EQ(BarAddress.getValue(), BarAddr);
83+
}
84+
85+
TEST_F(LookupAndRecordAddrsTest, BlockingRequiredFailure) {
86+
ExecutorAddress FooAddress, BarAddress;
87+
auto Err =
88+
lookupAndRecordAddrs(ES, LookupKind::Static, makeJITDylibSearchOrder(&JD),
89+
{{Foo, &FooAddress}, {Bar, &BarAddress}});
90+
91+
EXPECT_THAT_ERROR(std::move(Err), Failed());
92+
}
93+
94+
TEST_F(LookupAndRecordAddrsTest, BlockingWeakReference) {
95+
cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
96+
97+
ExecutorAddress FooAddress, BarAddress;
98+
auto Err =
99+
lookupAndRecordAddrs(ES, LookupKind::Static, makeJITDylibSearchOrder(&JD),
100+
{{Foo, &FooAddress}, {Bar, &BarAddress}},
101+
SymbolLookupFlags::WeaklyReferencedSymbol);
102+
103+
EXPECT_THAT_ERROR(std::move(Err), Succeeded());
104+
EXPECT_EQ(FooAddress.getValue(), FooAddr);
105+
EXPECT_EQ(BarAddress.getValue(), 0U);
106+
}
107+
108+
} // namespace

0 commit comments

Comments
 (0)