From ffcb5745ab54e62e2e7e048ee082209a4ac19146 Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Wed, 18 Mar 2026 15:07:57 +1100 Subject: [PATCH] [orc-rt] Add BootstrapInfo: info for controller session bootstrap. (#187184) BootstrapInfo holds information needed to bootstrap the ExecutionSession in the controller. Future patches will update ControllerAccess to send the bootstrap information at controller-connection time. BootstrapInfo includes information about the executor process (via Session::processInfo), an initial set of symbols (replacing Session::controllerInterface()), and a simple key/value store. --- orc-rt/include/CMakeLists.txt | 1 + orc-rt/include/orc-rt/BootstrapInfo.h | 67 +++++++++++ orc-rt/include/orc-rt/Session.h | 5 - orc-rt/lib/executor/BootstrapInfo.cpp | 52 +++++++++ orc-rt/lib/executor/CMakeLists.txt | 1 + orc-rt/lib/executor/Session.cpp | 7 +- orc-rt/unittests/BootstrapInfoTest.cpp | 152 +++++++++++++++++++++++++ orc-rt/unittests/CMakeLists.txt | 1 + orc-rt/unittests/SessionTest.cpp | 35 ------ 9 files changed, 275 insertions(+), 46 deletions(-) create mode 100644 orc-rt/include/orc-rt/BootstrapInfo.h create mode 100644 orc-rt/lib/executor/BootstrapInfo.cpp create mode 100644 orc-rt/unittests/BootstrapInfoTest.cpp diff --git a/orc-rt/include/CMakeLists.txt b/orc-rt/include/CMakeLists.txt index ba87b42c3b11..0c3b6595fa3b 100644 --- a/orc-rt/include/CMakeLists.txt +++ b/orc-rt/include/CMakeLists.txt @@ -6,6 +6,7 @@ set(ORC_RT_HEADERS orc-rt-c/orc-rt.h orc-rt/AllocAction.h orc-rt/BitmaskEnum.h + orc-rt/BootstrapInfo.h orc-rt/Compiler.h orc-rt/SimpleSymbolTable.h orc-rt/Error.h diff --git a/orc-rt/include/orc-rt/BootstrapInfo.h b/orc-rt/include/orc-rt/BootstrapInfo.h new file mode 100644 index 000000000000..a26c439874c2 --- /dev/null +++ b/orc-rt/include/orc-rt/BootstrapInfo.h @@ -0,0 +1,67 @@ +//===- BootstrapInfo.h - Bootstrap syms & values for controller -*- 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 +// +//===----------------------------------------------------------------------===// +// +// BootstrapInfo API. +// +//===----------------------------------------------------------------------===// + +#ifndef ORC_RT_BOOTSTRAPINFO_H +#define ORC_RT_BOOTSTRAPINFO_H + +#include "orc-rt/Error.h" +#include "orc-rt/SimpleSymbolTable.h" +#include "orc-rt/move_only_function.h" +#include "orc-rt/sps-ci/AllSPSCI.h" +#include +#include +#include +#include + +namespace orc_rt { + +class ExecutorProcessInfo; +class Session; + +/// Holds initial values that will be used to bootstrap the controller's +/// ExecutorProcessControl object. +class BootstrapInfo { +public: + using ValueMap = std::unordered_map; + using InitialSymbolsBuilder = move_only_function; + using InitialValuesBuilder = move_only_function; + + /// Construct a BootstrapInfo object from the given Session, Symbols, and + /// Values. + BootstrapInfo(Session &S, SimpleSymbolTable Symbols = {}, + ValueMap Values = {}); + + /// Construct with a default initial symbols and values. + static Expected + CreateDefault(Session &S, + InitialSymbolsBuilder AddInitialSymbols = sps_ci::addAll, + InitialValuesBuilder AddInitialValues = {}); + + const Session &session() const noexcept { return S; } + + const ExecutorProcessInfo &processInfo() const noexcept; + + SimpleSymbolTable &symbols() noexcept { return Symbols; } + const SimpleSymbolTable &symbols() const noexcept { return Symbols; } + + ValueMap &values() noexcept { return Values; } + const ValueMap &values() const noexcept { return Values; } + +private: + Session &S; + SimpleSymbolTable Symbols; + ValueMap Values; +}; + +} // namespace orc_rt + +#endif // ORC_RT_BOOTSTRAPINFO_H diff --git a/orc-rt/include/orc-rt/Session.h b/orc-rt/include/orc-rt/Session.h index 932b0b4fe451..1c45eac01ac0 100644 --- a/orc-rt/include/orc-rt/Session.h +++ b/orc-rt/include/orc-rt/Session.h @@ -139,10 +139,6 @@ public: /// Report an error via the ErrorReporter function. void reportError(Error Err) { ReportError(std::move(Err)); } - /// Controller interface symbols map. - auto controllerInterface() { return LockedAccess(CI, M); } - auto controllerInterface() const { return LockedAccess(CI, M); } - /// Initiate session shutdown. /// /// Runs shutdown on registered resources in reverse order. @@ -216,7 +212,6 @@ private: mutable std::mutex M; std::vector> Services; - SimpleSymbolTable CI; std::unique_ptr SI; }; diff --git a/orc-rt/lib/executor/BootstrapInfo.cpp b/orc-rt/lib/executor/BootstrapInfo.cpp new file mode 100644 index 000000000000..a06f0b482df5 --- /dev/null +++ b/orc-rt/lib/executor/BootstrapInfo.cpp @@ -0,0 +1,52 @@ +//===- BootstrapInfo.cpp --------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Contains the implementation of APIs in the orc-rt/BootstrapInfo.h header. +// +//===----------------------------------------------------------------------===// + +#include "orc-rt/BootstrapInfo.h" + +#include "orc-rt/ExecutorProcessInfo.h" +#include "orc-rt/Session.h" + +namespace orc_rt { + +BootstrapInfo::BootstrapInfo(Session &S, SimpleSymbolTable Symbols, + ValueMap Values) + : S(S), Symbols(std::move(Symbols)), Values(std::move(Values)) {} + +Expected +BootstrapInfo::CreateDefault(Session &S, + InitialSymbolsBuilder AddInitialSymbols, + InitialValuesBuilder AddInitialValues) { + + SimpleSymbolTable InitialSymbols; + // Add session symbol. + std::pair SessionSymbol[] = { + {"orc_rt_Session_Instance", static_cast(&S)}}; + if (auto Err = InitialSymbols.addUnique(SessionSymbol)) + return std::move(Err); + + if (AddInitialSymbols) + if (auto Err = AddInitialSymbols(InitialSymbols)) + return std::move(Err); + + ValueMap InitialValues; + if (AddInitialValues) + if (auto Err = AddInitialValues(InitialValues)) + return std::move(Err); + + return BootstrapInfo(S, std::move(InitialSymbols), std::move(InitialValues)); +} + +const ExecutorProcessInfo &BootstrapInfo::processInfo() const noexcept { + return S.processInfo(); +} + +} // namespace orc_rt diff --git a/orc-rt/lib/executor/CMakeLists.txt b/orc-rt/lib/executor/CMakeLists.txt index 9d390a859221..eebf142e5d86 100644 --- a/orc-rt/lib/executor/CMakeLists.txt +++ b/orc-rt/lib/executor/CMakeLists.txt @@ -1,5 +1,6 @@ set(files AllocAction.cpp + BootstrapInfo.cpp SimpleSymbolTable.cpp Error.cpp ExecutorProcessInfo.cpp diff --git a/orc-rt/lib/executor/Session.cpp b/orc-rt/lib/executor/Session.cpp index 945c08e76bde..ef59565ea534 100644 --- a/orc-rt/lib/executor/Session.cpp +++ b/orc-rt/lib/executor/Session.cpp @@ -20,12 +20,7 @@ Session::Session(ExecutorProcessInfo EPI, std::unique_ptr Dispatcher, ErrorReporterFn ReportError) : EPI(std::move(EPI)), Dispatcher(std::move(Dispatcher)), - ReportError(std::move(ReportError)) { - std::pair InitialSymbols[] = { - {"orc_rt_SessionInstance", static_cast(this)}}; - - cantFail(CI.addUnique(InitialSymbols)); -} + ReportError(std::move(ReportError)) {} Session::~Session() { waitForShutdown(); } diff --git a/orc-rt/unittests/BootstrapInfoTest.cpp b/orc-rt/unittests/BootstrapInfoTest.cpp new file mode 100644 index 000000000000..67f497a49c8e --- /dev/null +++ b/orc-rt/unittests/BootstrapInfoTest.cpp @@ -0,0 +1,152 @@ +//===- BootstrapInfoTest.cpp ----------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Tests for orc-rt's BootstrapInfo.h APIs. +// +//===----------------------------------------------------------------------===// + +#include "orc-rt/BootstrapInfo.h" +#include "orc-rt/Session.h" +#include "orc-rt/TaskDispatcher.h" +#include "gtest/gtest.h" + +using namespace orc_rt; + +static ExecutorProcessInfo mockExecutorProcessInfo() noexcept { + return ExecutorProcessInfo("arm64-apple-darwin", 16384); +} + +class NoDispatcher : public TaskDispatcher { +public: + void dispatch(std::unique_ptr T) override { + assert(false && "strictly no dispatching!"); + } + void shutdown() override {} +}; + +static void noErrors(Error Err) { cantFail(std::move(Err)); } + +TEST(BootstrapInfoTest, ExplicitConstruction) { + Session S(mockExecutorProcessInfo(), std::make_unique(), + noErrors); + BootstrapInfo BI(S); + EXPECT_EQ(&BI.session(), &S); + EXPECT_TRUE(BI.symbols().empty()); + EXPECT_TRUE(BI.values().empty()); +} + +TEST(BootstrapInfoTest, ExplicitConstructionWithSymbolsAndValues) { + Session S(mockExecutorProcessInfo(), std::make_unique(), + noErrors); + int X = 0; + SimpleSymbolTable Symbols; + std::pair Syms[] = {{"orc_rt_X", &X}}; + cantFail(Symbols.addUnique(Syms)); + + BootstrapInfo::ValueMap Values; + Values["key"] = "value"; + + BootstrapInfo BI(S, std::move(Symbols), std::move(Values)); + EXPECT_EQ(BI.symbols().size(), 1U); + EXPECT_TRUE(BI.symbols().count("orc_rt_X")); + EXPECT_EQ(BI.symbols().at("orc_rt_X"), &X); + EXPECT_EQ(BI.values().size(), 1U); + EXPECT_EQ(BI.values().at("key"), "value"); +} + +TEST(BootstrapInfoTest, ProcessInfoDelegates) { + Session S(mockExecutorProcessInfo(), std::make_unique(), + noErrors); + BootstrapInfo BI(S); + EXPECT_EQ(&BI.processInfo(), &S.processInfo()); +} + +TEST(BootstrapInfoTest, CreateDefaultSucceeds) { + Session S(mockExecutorProcessInfo(), std::make_unique(), + noErrors); + auto BI = cantFail(BootstrapInfo::CreateDefault(S)); + EXPECT_EQ(&BI.session(), &S); +} + +TEST(BootstrapInfoTest, CreateDefaultContainsSessionSymbol) { + Session S(mockExecutorProcessInfo(), std::make_unique(), + noErrors); + auto BI = cantFail(BootstrapInfo::CreateDefault(S)); + ASSERT_TRUE(BI.symbols().count("orc_rt_Session_Instance")); + EXPECT_EQ(BI.symbols().at("orc_rt_Session_Instance"), + static_cast(&S)); +} + +TEST(BootstrapInfoTest, CreateDefaultContainsSPSCISymbols) { + Session S(mockExecutorProcessInfo(), std::make_unique(), + noErrors); + auto BI = cantFail(BootstrapInfo::CreateDefault(S)); + // The default addAll should have registered SPS CI symbols. + EXPECT_TRUE(BI.symbols().count( + "orc_rt_sps_ci_SimpleNativeMemoryMap_reserve_sps_wrapper")); +} + +TEST(BootstrapInfoTest, CreateDefaultWithNoSymbolsBuilder) { + Session S(mockExecutorProcessInfo(), std::make_unique(), + noErrors); + auto BI = cantFail(BootstrapInfo::CreateDefault(S, /*AddInitialSymbols=*/{}, + /*AddInitialValues=*/{})); + // Should still contain the session symbol (added unconditionally). + ASSERT_TRUE(BI.symbols().count("orc_rt_Session_Instance")); + // But no SPS CI symbols. + EXPECT_FALSE(BI.symbols().count( + "orc_rt_sps_ci_SimpleNativeMemoryMap_reserve_sps_wrapper")); +} + +TEST(BootstrapInfoTest, CreateDefaultWithCustomValuesBuilder) { + Session S(mockExecutorProcessInfo(), std::make_unique(), + noErrors); + auto BI = cantFail(BootstrapInfo::CreateDefault( + S, sps_ci::addAll, [](BootstrapInfo::ValueMap &Values) -> Error { + Values["test_key"] = "test_value"; + return Error::success(); + })); + EXPECT_EQ(BI.values().at("test_key"), "test_value"); +} + +TEST(BootstrapInfoTest, CreateDefaultSymbolsBuilderError) { + Session S(mockExecutorProcessInfo(), std::make_unique(), + noErrors); + auto BI = BootstrapInfo::CreateDefault(S, [](SimpleSymbolTable &) -> Error { + return make_error("symbols builder failed"); + }); + EXPECT_FALSE(!!BI); + auto ErrMsg = toString(BI.takeError()); + EXPECT_NE(ErrMsg.find("symbols builder failed"), std::string::npos); +} + +TEST(BootstrapInfoTest, CreateDefaultValuesBuilderError) { + Session S(mockExecutorProcessInfo(), std::make_unique(), + noErrors); + auto BI = BootstrapInfo::CreateDefault( + S, sps_ci::addAll, [](BootstrapInfo::ValueMap &) -> Error { + return make_error("values builder failed"); + }); + EXPECT_FALSE(!!BI); + auto ErrMsg = toString(BI.takeError()); + EXPECT_NE(ErrMsg.find("values builder failed"), std::string::npos); +} + +TEST(BootstrapInfoTest, MutableSymbolsAndValues) { + Session S(mockExecutorProcessInfo(), std::make_unique(), + noErrors); + BootstrapInfo BI(S); + + int X = 0; + std::pair Syms[] = {{"orc_rt_X", &X}}; + cantFail(BI.symbols().addUnique(Syms)); + BI.values()["key"] = "value"; + + EXPECT_EQ(BI.symbols().size(), 1U); + EXPECT_EQ(BI.values().size(), 1U); +} diff --git a/orc-rt/unittests/CMakeLists.txt b/orc-rt/unittests/CMakeLists.txt index 665b04d6a925..a749dc6adb27 100644 --- a/orc-rt/unittests/CMakeLists.txt +++ b/orc-rt/unittests/CMakeLists.txt @@ -14,6 +14,7 @@ endfunction() add_orc_rt_unittest(CoreTests AllocActionTest.cpp BitmaskEnumTest.cpp + BootstrapInfoTest.cpp CallableTraitsHelperTest.cpp SimpleSymbolTableTest.cpp EndianTest.cpp diff --git a/orc-rt/unittests/SessionTest.cpp b/orc-rt/unittests/SessionTest.cpp index 31a9da1c0308..5c10d9b4707d 100644 --- a/orc-rt/unittests/SessionTest.cpp +++ b/orc-rt/unittests/SessionTest.cpp @@ -398,41 +398,6 @@ TEST(SessionTest, CreateServiceAndUseRef) { CS.doMoreConfig(1); } -TEST(SessionTest, ControllerInterfaceContainsSessionByDefault) { - Session S(mockExecutorProcessInfo(), std::make_unique(), - noErrors); - ASSERT_TRUE(S.controllerInterface()->count("orc_rt_SessionInstance")); - EXPECT_EQ(S.controllerInterface()->at("orc_rt_SessionInstance"), - static_cast(&S)); -} - -TEST(SessionTest, ControllerInterfaceWithRef) { - Session S(mockExecutorProcessInfo(), std::make_unique(), - noErrors); - int X = 0, Y = 0; - S.controllerInterface().with_ref([&](SimpleSymbolTable &ST) { - std::pair Syms[] = { - {"orc_rt_A", static_cast(&X)}, - {"orc_rt_B", static_cast(&Y)}}; - cantFail(ST.addUnique(Syms)); - }); - - EXPECT_EQ(S.controllerInterface()->at("orc_rt_A"), &X); - EXPECT_EQ(S.controllerInterface()->at("orc_rt_B"), &Y); -} - -TEST(SessionTest, ControllerInterfaceConstAccess) { - Session S(mockExecutorProcessInfo(), std::make_unique(), - noErrors); - int X = 0; - std::pair Syms[] = {{"orc_rt_X", &X}}; - cantFail(S.controllerInterface()->addUnique(Syms)); - - const Session &CS = S; - ASSERT_TRUE(CS.controllerInterface()->count("orc_rt_X")); - EXPECT_EQ(CS.controllerInterface()->at("orc_rt_X"), &X); -} - TEST(ControllerAccessTest, Basics) { // Test that we can set the ControllerAccess implementation and still shut // down as expected.