2#ifndef CEL_RUNTIME_RAW_SEGMENT_HPP
3#define CEL_RUNTIME_RAW_SEGMENT_HPP
5#include <cel/runtime/detail/frame.hpp>
6#include <cel/runtime/detail/retirement.hpp>
14namespace cel::detail {
15struct instruction_storage;
35 detail::retirement_ptr<detail::instruction_storage> _storage;
36 friend struct detail::segment_access;
39 void* allocate_capture(std::size_t size, std::size_t alignment);
42 void append(
const void* capture,
43 void (*execute)(
const void*, frame&),
44 void (*destroy)(
const void*)
noexcept,
45 void (*retire)(
const void*, detail::retirement_queue&)
noexcept =
nullptr);
48 template <
class F,
class R,
class... Args>
50 std::array<value_type,
sizeof...(Args)> inputs;
51 std::array<value_type, std::is_void_v<R> ? 0 : 1>
55 static auto result_types() {
56 if constexpr (std::is_void_v<R>)
57 return std::array<value_type, 0>{};
59 return std::array{detail::concrete_adapter<R>::type()};
63 requires std::constructible_from<F, G&&>
explicit operation(G&& input) :
64 inputs{detail::concrete_adapter<Args>::type()...}, outputs(result_types()),
65 callback(std::forward<G>(input)) {}
68 template <std::size_t... I>
69 void invoke(frame& scope, std::index_sequence<I...>)
const {
71 scope.template acquire_operands<Args...>(inputs, std::index_sequence<I...>{});
72 scope.discard(
sizeof...(Args));
73 if constexpr (std::is_void_v<R>) {
74 std::apply([&](
auto&... args) { std::invoke(callback, scope, std::move(args)...); },
77 R result = std::apply(
78 [&](
auto&... args) -> R {
79 return std::invoke(callback, scope, std::move(args)...);
82 scope.push_result(outputs[0], result);
87 static void execute(
const void* capture, frame& scope) {
88 static_cast<const operation*
>(capture)->invoke(scope,
89 std::index_sequence_for<Args...>{});
92 static void destroy(
const void* capture)
noexcept {
93 std::destroy_at(
static_cast<const operation*
>(capture));
99 raw_segment() noexcept;
104 raw_segment(const raw_segment&) = delete;
106 raw_segment& operator=(const raw_segment&) = delete;
108 raw_segment(raw_segment&& other) noexcept;
111 raw_segment& operator=(raw_segment&& other) noexcept;
122 void execute(frame& scope) const;
136 template <class R, class... Args, class F>
137 void push_op(F&& callback) {
138 using capture_type = std::decay_t<F>;
139 static_assert(std::is_nothrow_destructible_v<capture_type>);
140 static_assert(std::is_invocable_r_v<R,
const capture_type&, frame&, Args...>);
141 using stored = operation<capture_type, R, Args...>;
142 auto* location =
static_cast<stored*
>(allocate_capture(
sizeof(stored),
alignof(stored)));
143 auto* capture = std::construct_at(location, std::forward<F>(callback));
145 append(capture, stored::execute, stored::destroy);
147 std::destroy_at(capture);
154 template <
class R,
class F>
155 void push_op0(F&& callback) {
156 push_op<R>(std::forward<F>(callback));
161 template <
class R,
class A,
class F>
162 void push_op1(F&& callback) {
163 push_op<R, A>(std::forward<F>(callback));
170 template <
class R,
class A,
class B,
class F>
171 void push_op2(F&& callback) {
172 push_op<R, A, B>(std::forward<F>(callback));
179 template <
class R,
class A,
class B,
class C,
class F>
180 void push_op3(F&& callback) {
181 push_op<R, A, B, C>(std::forward<F>(callback));