plugify 1.2.8
Loading...
Searching...
No Matches
call.hpp
1#pragma once
2
3#include <array>
4#include <bit>
5#include <concepts>
6#include <cstddef>
7#include <cstdint>
8#include <cstring>
9#include <memory>
10#include <span>
11#include <stdexcept>
12#include <type_traits>
13
14#include "plugify/global.h"
15#include "plugify/mem_addr.hpp"
16#include "plugify/method.hpp"
17#include "plugify/property.hpp"
18#include "plugify/signarure.hpp"
19#include "plugify/value_type.hpp"
20#include "plg/inplace_vector.hpp"
21
22namespace plugify {
23 class Return;
24
35 class PLUGIFY_API JitCall {
36 public:
41
46 JitCall(const JitCall& other) = delete;
47
52 JitCall(JitCall&& other) noexcept;
53
58
59 enum class WaitType { None, Breakpoint, Wait_Keypress };
60
61
62 using CallingFunc = void (*)(const uint64_t* params, const Return*); // Return can be null
63
68 using HiddenParam = bool (*)(ValueType);
69
78 MemAddr GetJitFunc(const Signature& sig, MemAddr target, WaitType waitType, bool hidden);
79
89 const Method& method,
90 MemAddr target,
91 WaitType waitType = WaitType::None,
92 HiddenParam hidden = &ValueUtils::IsHiddenParam
93 );
94
100 MemAddr GetFunction() const noexcept;
101
109 MemAddr GetTargetFunc() const noexcept;
110
115 std::string_view GetError() noexcept;
116
123 JitCall& operator=(const JitCall& other) = delete;
124
132 JitCall& operator=(JitCall&& other) noexcept;
133
134 PLUGIFY_ACCESS : struct Impl;
135 PLUGIFY_NO_DLL_EXPORT_WARNING(std::unique_ptr<Impl> _impl;)
136 };
137
138 // Concept for types that can be stored in parameter slots
139 template <typename T>
140 concept ParameterType = std::is_trivially_copyable_v<T>
141 && (std::is_arithmetic_v<T> || std::is_pointer_v<T> || std::is_enum_v<T>);
142
143 // Concept for types that fit in a single slot
144 template <typename T>
145 concept SingleSlotType = ParameterType<T> && sizeof(T) <= sizeof(uint64_t);
146
147 // Concept for types that need multiple slots
148 template <typename T>
149 concept MultiSlotType = ParameterType<T> && sizeof(T) > sizeof(uint64_t);
150
158 public:
159 using SlotType = uint64_t;
160 static constexpr size_t SlotSize = sizeof(SlotType);
161
166 explicit Parameters(size_t slotCount) {
167 _storage.reserve(slotCount);
168 }
169
176 template <SingleSlotType T>
177 Parameters& Add(T value) {
178 SlotType& slot = _storage.emplace_back();
179 std::memcpy(&slot, &value, sizeof(T));
180 return *this;
181 }
182
189 template <MultiSlotType T>
190 Parameters& AddLarge(const T& value) {
191 constexpr size_t slotsNeeded = (sizeof(T) + SlotSize - 1) / SlotSize;
192 size_t oldSize = _storage.size();
193 _storage.resize(oldSize + slotsNeeded);
194 std::memcpy(&_storage[oldSize], &value, sizeof(T));
195 return *this;
196 }
197
204 template <typename... Args>
205 requires(ParameterType<Args> && ...)
206 Parameters& AddMultiple(Args... args) {
207 (Add(args), ...);
208 return *this;
209 }
210
218 template <SingleSlotType T>
219 Parameters& SetAt(size_t index, T value) {
220 SlotType& slot = _storage.at(index);
221 slot = {};
222 std::memcpy(&slot, &value, sizeof(T));
223 return *this;
224 }
225
230 [[nodiscard]] const SlotType* Get() const noexcept {
231 return _storage.data();
232 }
233
238 [[nodiscard]] std::span<const SlotType> GetSpan() const noexcept {
239 return { _storage.data(), _storage.size() };
240 }
241
246 [[nodiscard]] size_t GetUsedSlots() const noexcept {
247 return _storage.size();
248 }
249
254 [[nodiscard]] size_t GetCapacity() const noexcept {
255 return _storage.capacity();
256 }
257
261 void Reset() noexcept {
262 _storage.clear();
263 }
264
270 [[nodiscard]] bool HasSpace(size_t slotsNeeded = 1) const noexcept {
271 return _storage.size() + slotsNeeded < _storage.capacity();
272 }
273
274 private:
276 };
277
284 class Return {
285 public:
286 using SlotType = uint64_t;
287 static constexpr size_t MaxSize = 2 * sizeof(SlotType);
288
294 template <typename T, typename... Args>
295 requires(sizeof(T) <= MaxSize && std::is_trivially_destructible_v<T>)
296 void Construct(Args&&... args) noexcept(noexcept(T(std::forward<Args>(args)...))) {
297 std::construct_at(reinterpret_cast<T*>(_storage.data()), std::forward<Args>(args)...);
298 }
299
305 template <typename T>
306 requires(sizeof(T) <= MaxSize && std::is_trivially_copyable_v<T>)
307 void Set(T value) noexcept {
308 _storage = {};
309 std::memcpy(_storage.data(), &value, sizeof(T));
310 }
311
317 template <typename T>
318 requires(sizeof(T) <= MaxSize && std::is_trivially_copyable_v<T>)
319 [[nodiscard]] T Get() const noexcept {
320 T result;
321 std::memcpy(&result, _storage.data(), sizeof(T));
322 return result;
323 }
324
328 void Clear() noexcept {
329 _storage = {};
330 }
331
332 private:
333 alignas(alignof(std::max_align_t))
334 std::array<std::byte, MaxSize> _storage{};
335 };
336} // namespace plugify
Class encapsulates architecture-, OS- and compiler-specific function call semantics in a virtual "bin...
Definition call.hpp:35
JitCall(const JitCall &other)=delete
Copy constructor.
JitCall(JitCall &&other) noexcept
Move constructor.
MemAddr GetJitFunc(const Method &method, MemAddr target, WaitType waitType=WaitType::None, HiddenParam hidden=&ValueUtils::IsHiddenParam)
Get a dynamically created function based on the method reference.
MemAddr GetFunction() const noexcept
Get a dynamically created function.
bool(*)(ValueType) HiddenParam
HiddenParam is a predicate function pointer to determine if a ValueType should be passed as a hidden ...
Definition call.hpp:68
MemAddr GetJitFunc(const Signature &sig, MemAddr target, WaitType waitType, bool hidden)
Get a dynamically created function based on the raw signature.
~JitCall()
Destructor.
JitCall()
Constructor.
A wrapper class for memory addresses, providing utility functions for pointer manipulation.
Definition mem_addr.hpp:12
Builder for function parameters to be passed to JIT code.
Definition call.hpp:157
std::span< const SlotType > GetSpan() const noexcept
Get a span view of the parameters.
Definition call.hpp:238
Parameters & SetAt(size_t index, T value)
Set argument at specific position (overwrites if exists).
Definition call.hpp:219
bool HasSpace(size_t slotsNeeded=1) const noexcept
Check if there's room for more arguments.
Definition call.hpp:270
size_t GetCapacity() const noexcept
Get the total capacity.
Definition call.hpp:254
const SlotType * Get() const noexcept
Get pointer to the parameter data.
Definition call.hpp:230
Parameters & AddLarge(const T &value)
Add a large argument that spans multiple slots.
Definition call.hpp:190
void Reset() noexcept
Reset the builder to reuse it.
Definition call.hpp:261
Parameters & Add(T value)
Add an argument at the next available position.
Definition call.hpp:177
Parameters(size_t slotCount)
Constructor.
Definition call.hpp:166
size_t GetUsedSlots() const noexcept
Get the number of slots used.
Definition call.hpp:246
Wrapper for function return values.
Definition call.hpp:284
void Clear() noexcept
Clear the return value storage.
Definition call.hpp:328
T Get() const noexcept
Get the return value.
Definition call.hpp:319
void Set(T value) noexcept
Set the return value.
Definition call.hpp:307
Replacement for asmjit::FuncSignature using ValueType.
Definition signarure.hpp:44