/* $info$ tags: thunklibs|fex_thunk_test $end_info$ */ #include #include #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 data, int index) { if (index == 0) { return offsetof(guest_layout::type, a); } else { return offsetof(guest_layout::type, b); } } void fex_custom_repack_entry(host_layout& to, const guest_layout& from) { to.data.custom_repack_invoked = 1; } bool fex_custom_repack_exit(guest_layout& to, const host_layout& from) { return false; } template 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*>((void*)source); auto child_mem = (char*)aligned_alloc(alignof(host_layout), sizeof(host_layout)); auto child = new (child_mem) host_layout {*guest_next}; fex_custom_repack_entry(*child, *reinterpret_cast*>((void*)(source))); return (const TestBaseStruct*)child; } template static void convert_to_guest(void* into, const TestBaseStruct* from) { auto typed_into = (guest_layout*)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 inline constexpr std::pair> converters = { TypeIndex, {convert, convert_to_guest}}; static std::unordered_map> next_handlers { converters, converters, }; static void default_fex_custom_repack_entry(TestBaseStruct& into, const guest_layout* from) { if (!from->data.Next.get_pointer()) { into.Next = nullptr; return; } auto typed_source = reinterpret_cast*>(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& into, const TestBaseStruct* from) { auto NextHost = from->Next; if (!NextHost) { return; } auto next_handler = next_handlers.at(static_cast(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& into, const guest_layout& from) { \ default_fex_custom_repack_entry(*(TestBaseStruct*)&into.data, reinterpret_cast*>(&from)); \ } \ \ bool fex_custom_repack_exit(guest_layout& into, const host_layout& from) { \ auto prev_next = into.data.Next; \ default_fex_custom_repack_reverse(*reinterpret_cast*>(&into), \ &reinterpret_cast(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&, const guest_layout&) { std::abort(); } bool fex_custom_repack_exit(guest_layout&, const host_layout&) { std::abort(); return false; } EXPORTS(libfex_thunk_test)