forked from FEX-Emu/FEX
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHost.cpp
More file actions
115 lines (89 loc) · 4.94 KB
/
Host.cpp
File metadata and controls
115 lines (89 loc) · 4.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/*
$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)