Files
FEX-Emu--FEX/ThunkLibs/libfex_thunk_test/Host.cpp
T

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)