3 #if defined(SKSE_SUPPORT_XBYAK)
15 using deleter_type = std::function<void(
void* a_mem, std::size_t a_size)>;
32 if (
this != std::addressof(a_rhs)) {
33 move_from(std::move(a_rhs));
38 void create(std::size_t a_size) {
return create(a_size,
nullptr); }
39 void create(std::size_t a_size,
void* a_module);
43 auto trampoline =
static_cast<std::byte*
>(a_trampoline);
45 constexpr
auto INT3 =
static_cast<int>(0xCC);
46 std::memset(trampoline,
INT3, a_size);
51 _deleter = std::move(a_deleter);
59 [[nodiscard]]
void*
allocate(std::size_t a_size)
61 auto result = do_allocate(a_size);
66 #ifdef SKSE_SUPPORT_XBYAK
67 [[nodiscard]]
void*
allocate(Xbyak::CodeGenerator& a_code);
73 return static_cast<T*
>(
allocate(
sizeof(T)));
76 [[nodiscard]] constexpr std::size_t
empty() const noexcept {
return _capacity == 0; }
77 [[nodiscard]] constexpr std::size_t
capacity() const noexcept {
return _capacity; }
78 [[nodiscard]] constexpr std::size_t
allocated_size() const noexcept {
return _size; }
79 [[nodiscard]] constexpr std::size_t
free_size() const noexcept {
return _capacity - _size; }
81 template <std::
size_t N>
82 std::uintptr_t
write_branch(std::uintptr_t a_src, std::uintptr_t a_dst)
84 std::uint8_t data = 0;
85 if constexpr (N == 5) {
89 }
else if constexpr (N == 6) {
94 static_assert(
false && N,
"invalid branch size");
97 return write_branch<N>(a_src, a_dst, data);
100 template <std::
size_t N,
class F>
103 return write_branch<N>(a_src, stl::unrestricted_cast<std::uintptr_t>(a_dst));
106 template <std::
size_t N>
107 std::uintptr_t
write_call(std::uintptr_t a_src, std::uintptr_t a_dst)
109 std::uint8_t data = 0;
110 if constexpr (N == 5) {
114 }
else if constexpr (N == 6) {
119 static_assert(
false && N,
"invalid call size");
122 return write_branch<N>(a_src, a_dst, data);
125 template <std::
size_t N,
class F>
128 return write_call<N>(a_src, stl::unrestricted_cast<std::uintptr_t>(a_dst));
132 [[nodiscard]]
void* do_create(std::size_t a_size, std::uintptr_t a_address);
133 [[nodiscard]]
void* do_allocate(std::size_t a_size);
135 void write_5branch(std::uintptr_t a_src, std::uintptr_t a_dst, std::uint8_t a_opcode);
136 void write_6branch(std::uintptr_t a_src, std::uintptr_t a_dst, std::uint8_t a_modrm);
138 template <std::
size_t N>
139 [[nodiscard]] std::uintptr_t
write_branch(std::uintptr_t a_src, std::uintptr_t a_dst, std::uint8_t a_data)
141 const auto disp =
reinterpret_cast<std::int32_t*
>(a_src + N - 4);
142 const auto nextOp = a_src + N;
143 const auto func = nextOp + *disp;
145 if constexpr (N == 5) {
146 write_5branch(a_src, a_dst, a_data);
147 }
else if constexpr (N == 6) {
148 write_6branch(a_src, a_dst, a_data);
150 static_assert(
false && N,
"invalid branch size");
158 _5branches = std::move(a_rhs._5branches);
159 _6branches = std::move(a_rhs._6branches);
160 _name = std::move(a_rhs._name);
162 _deleter = std::move(a_rhs._deleter);
165 a_rhs._data =
nullptr;
167 _capacity = a_rhs._capacity;
174 void log_stats()
const;
176 [[nodiscard]]
bool in_range(std::ptrdiff_t a_disp)
const
181 return min <= a_disp && a_disp <=
max;
186 if (_data && _deleter) {
187 _deleter(_data, _capacity);
197 std::map<std::uintptr_t, std::byte*> _5branches;
198 std::map<std::uintptr_t, std::byte*> _6branches;
201 std::byte* _data{
nullptr };
202 std::size_t _capacity{ 0 };
203 std::size_t _size{ 0 };
Definition: Trampoline.h:13
std::uintptr_t write_call(std::uintptr_t a_src, std::uintptr_t a_dst)
Definition: Trampoline.h:107
constexpr std::size_t allocated_size() const noexcept
Definition: Trampoline.h:78
std::function< void(void *a_mem, std::size_t a_size)> deleter_type
Definition: Trampoline.h:15
T * allocate()
Definition: Trampoline.h:71
void * allocate(std::size_t a_size)
Definition: Trampoline.h:59
~Trampoline()
Definition: Trampoline.h:26
std::uintptr_t write_branch(std::uintptr_t a_src, std::uintptr_t a_dst)
Definition: Trampoline.h:82
Trampoline(std::string_view a_name)
Definition: Trampoline.h:22
Trampoline(const Trampoline &)=delete
void set_trampoline(void *a_trampoline, std::size_t a_size, deleter_type a_deleter={})
Definition: Trampoline.h:41
Trampoline(Trampoline &&a_rhs) noexcept
Definition: Trampoline.h:20
std::uintptr_t write_branch(std::uintptr_t a_src, F a_dst)
Definition: Trampoline.h:101
void create(std::size_t a_size)
Definition: Trampoline.h:38
Trampoline & operator=(Trampoline &&a_rhs) noexcept
Definition: Trampoline.h:30
constexpr std::size_t capacity() const noexcept
Definition: Trampoline.h:77
std::uintptr_t write_call(std::uintptr_t a_src, F a_dst)
Definition: Trampoline.h:126
constexpr std::size_t empty() const noexcept
Definition: Trampoline.h:76
constexpr std::size_t free_size() const noexcept
Definition: Trampoline.h:79
void create(std::size_t a_size, void *a_module)
Trampoline & operator=(const Trampoline &)=delete
constexpr std::uint8_t INT3
Definition: Relocation.h:172
NiColor min(const NiColor &a_lhs, const NiColor &a_rhs)
Definition: ColorUtil.h:63
NiColor max(const NiColor &a_lhs, const NiColor &a_rhs)
Definition: ColorUtil.h:71
string(const CharT(&)[N]) -> string< CharT, N - 1 >
Trampoline & GetTrampoline()