mirror of
https://github.com/FEX-Emu/FEX.git
synced 2026-10-06 21:00:17 +02:00
116 lines
4.9 KiB
C++
116 lines
4.9 KiB
C++
/*
|
|
$info$
|
|
tags: thunklibs|fex_thunk_test
|
|
$end_info$
|
|
*/
|
|
|
|
#include <dlfcn.h>
|
|
|
|
#include <unordered_map>
|
|
|
|
#include "common/Host.h"
|
|
|
|
#include "api.h"
|
|
|
|
#include "thunkgen_host_libfex_thunk_test.inl"
|
|
|
|
static uint32_t fexfn_impl_libfex_thunk_test_QueryOffsetOf(guest_layout<ReorderingType*> data, int index) {
|
|
if (index == 0) {
|
|
return offsetof(guest_layout<ReorderingType>::type, a);
|
|
} else {
|
|
return offsetof(guest_layout<ReorderingType>::type, b);
|
|
}
|
|
}
|
|
|
|
void fex_custom_repack_entry(host_layout<CustomRepackedType>& to, const guest_layout<CustomRepackedType>& from) {
|
|
to.data.custom_repack_invoked = 1;
|
|
}
|
|
|
|
bool fex_custom_repack_exit(guest_layout<CustomRepackedType>& to, const host_layout<CustomRepackedType>& from) {
|
|
return false;
|
|
}
|
|
|
|
template<StructType TypeIndex, typename Type>
|
|
static const TestBaseStruct* convert(const TestBaseStruct* source) {
|
|
// Using malloc here since no easily available type information is available at the time of destruction.
|
|
auto guest_next = reinterpret_cast<guest_layout<Type>*>((void*)source);
|
|
auto child_mem = (char*)aligned_alloc(alignof(host_layout<Type>), sizeof(host_layout<Type>));
|
|
auto child = new (child_mem) host_layout<Type> {*guest_next};
|
|
|
|
fex_custom_repack_entry(*child, *reinterpret_cast<guest_layout<Type>*>((void*)(source)));
|
|
|
|
return (const TestBaseStruct*)child;
|
|
}
|
|
|
|
template<StructType TypeIndex, typename Type>
|
|
static void convert_to_guest(void* into, const TestBaseStruct* from) {
|
|
auto typed_into = (guest_layout<Type>*)into;
|
|
auto oldNext = typed_into->data.Next;
|
|
*typed_into = to_guest(to_host_layout(*(Type*)from));
|
|
typed_into->data.Next = oldNext;
|
|
|
|
fex_custom_repack_exit(*typed_into, to_host_layout(*(Type*)from));
|
|
}
|
|
|
|
template<StructType TypeIndex, typename Type>
|
|
inline constexpr std::pair<StructType, std::pair<const TestBaseStruct* (*)(const TestBaseStruct*), void (*)(void*, const TestBaseStruct*)>> converters = {
|
|
TypeIndex,
|
|
{convert<TypeIndex, Type>, convert_to_guest<TypeIndex, Type>}};
|
|
|
|
static std::unordered_map<StructType, std::pair<const TestBaseStruct* (*)(const TestBaseStruct*), void (*)(void*, const TestBaseStruct*)>> next_handlers {
|
|
converters<StructType::Struct1, TestStruct1>,
|
|
converters<StructType::Struct2, TestStruct2>,
|
|
};
|
|
|
|
static void default_fex_custom_repack_entry(TestBaseStruct& into, const guest_layout<TestBaseStruct>* from) {
|
|
if (!from->data.Next.get_pointer()) {
|
|
into.Next = nullptr;
|
|
return;
|
|
}
|
|
auto typed_source = reinterpret_cast<const guest_layout<TestBaseStruct>*>(from->data.Next.get_pointer());
|
|
|
|
auto next_handler = next_handlers.at(StructType {typed_source->data.Type.data});
|
|
|
|
into.Next = (TestBaseStruct*)next_handler.first((const TestBaseStruct*)typed_source);
|
|
}
|
|
|
|
static void default_fex_custom_repack_reverse(guest_layout<TestBaseStruct>& into, const TestBaseStruct* from) {
|
|
auto NextHost = from->Next;
|
|
if (!NextHost) {
|
|
return;
|
|
}
|
|
|
|
auto next_handler = next_handlers.at(static_cast<StructType>(into.data.Next.get_pointer()->data.Type.data));
|
|
next_handler.second((void*)into.data.Next.get_pointer(), from->Next);
|
|
|
|
free((void*)NextHost);
|
|
}
|
|
|
|
#define CREATE_INFO_DEFAULT_CUSTOM_REPACK(name) \
|
|
void fex_custom_repack_entry(host_layout<name>& into, const guest_layout<name>& from) { \
|
|
default_fex_custom_repack_entry(*(TestBaseStruct*)&into.data, reinterpret_cast<const guest_layout<TestBaseStruct>*>(&from)); \
|
|
} \
|
|
\
|
|
bool fex_custom_repack_exit(guest_layout<name>& into, const host_layout<name>& from) { \
|
|
auto prev_next = into.data.Next; \
|
|
default_fex_custom_repack_reverse(*reinterpret_cast<guest_layout<TestBaseStruct>*>(&into), \
|
|
&reinterpret_cast<const TestBaseStruct&>(from.data)); \
|
|
into = to_guest(from); \
|
|
into.data.Next = prev_next; \
|
|
return true; \
|
|
}
|
|
|
|
CREATE_INFO_DEFAULT_CUSTOM_REPACK(TestStruct1)
|
|
CREATE_INFO_DEFAULT_CUSTOM_REPACK(TestStruct2)
|
|
|
|
void fex_custom_repack_entry(host_layout<TestBaseStruct>&, const guest_layout<TestBaseStruct>&) {
|
|
std::abort();
|
|
}
|
|
|
|
bool fex_custom_repack_exit(guest_layout<TestBaseStruct>&, const host_layout<TestBaseStruct>&) {
|
|
std::abort();
|
|
return false;
|
|
}
|
|
|
|
EXPORTS(libfex_thunk_test)
|