-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy paththunk.c
More file actions
172 lines (154 loc) · 4.74 KB
/
Copy paththunk.c
File metadata and controls
172 lines (154 loc) · 4.74 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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#include <stdlib.h>
#include "thunk.h"
#include "util.h"
#include "wa.h"
#include "wa_result.h"
/*
Outbound Thunks (calling imported functions)
*/
result_t thunk_out(Module* m, uint32_t fidx) {
int p;
Block* func = &m->functions[fidx];
Type* type = func->type;
if (should_trace()) {
wa_warn(" >>> thunk_out 0x%x(%d) %s.%s(", func->fidx, func->fidx,
func->import_module, func->import_field);
for (p = type->param_count - 1; p >= 0; p--) {
wa_warn("%s%s", value_repr(&m->stack[m->sp - p]), p ? " " : "");
}
wa_warn("), %d results\n", type->result_count);
wa_debug(" mask: 0x%llx\n", type->mask);
}
if (!func->func_ptr) {
char* msg = calloc(1024 + strlen(func->import_field), 1);
sprintf(msg, "No thunk for %s\n", func->import_field);
return res_new_err(msg);
}
switch (type->mask) {
case 0x800:
THUNK_OUT_0(m, func, 0);
break;
case 0x8001:
THUNK_OUT_1(m, func, 0, i);
break;
case 0x80011:
THUNK_OUT_2(m, func, 0, i, i);
break;
case 0x8001111:
THUNK_OUT_4(m, func, 0, i, i, i, i);
break;
case 0x810:
THUNK_OUT_0(m, func, i);
break;
case 0x8101:
THUNK_OUT_1(m, func, i, i);
break;
case 0x81011:
THUNK_OUT_2(m, func, i, i, i);
break;
case 0x810111:
THUNK_OUT_3(m, func, i, i, i, i);
break;
case 0x8101111:
THUNK_OUT_4(m, func, i, i, i, i, i);
break;
case 0x81011111:
THUNK_OUT_5(m, func, i, i, i, i, i, i);
break;
case 0x8003:
THUNK_OUT_1(m, func, 0, f);
break;
case 0x80033:
THUNK_OUT_2(m, func, 0, f, f);
break;
case 0x800333:
THUNK_OUT_3(m, func, 0, f, f, f);
break;
case 0x8003333:
THUNK_OUT_4(m, func, 0, f, f, f, f);
break;
case 0x8303:
THUNK_OUT_1(m, func, f, f);
break;
case 0x8004:
THUNK_OUT_1(m, func, 0, F);
break;
case 0x80044:
THUNK_OUT_2(m, func, 0, F, F);
break;
case 0x800444:
THUNK_OUT_3(m, func, 0, F, F, F);
break;
case 0x8004444:
THUNK_OUT_4(m, func, 0, F, F, F, F);
break;
case 0x800444444:
THUNK_OUT_6(m, func, 0, F, F, F, F, F, F);
break;
case 0x8103:
THUNK_OUT_1(m, func, i, f);
break;
case 0x8404:
THUNK_OUT_1(m, func, F, F);
break;
default:
FATAL("unsupported thunk_out mask 0x%llx\n", type->mask);
}
wa_trace(" <<< thunk_out 0x%x(%d) %s.%s = %s\n", func->fidx, func->fidx,
func->import_module, func->import_field,
type->result_count > 0 ? value_repr(&m->stack[m->sp]) : "_");
return res_new_ok();
}
/*
Inbound Thunks (external calls into exported functions)
*/
/* TODO: global state, clean up somehow
This global is used by setup_thunk_in since signal handlers don't have
a way to pass arguments when they are setup.
*/
Module* _wa_current_module_;
THUNK_IN_FN_0(m, 0)
THUNK_IN_FN_2(m, 0, i, i)
THUNK_IN_FN_1(m, 0, F)
THUNK_IN_FN_1(m, i, i)
THUNK_IN_FN_2(m, i, i, i)
/* Push arguments
return function pointer to thunk_in_* function
*/
void (*setup_thunk_in(uint32_t fidx))(void) {
uint32_t p;
void (*f)(void) = NULL;
Module* m = _wa_current_module_; /* TODO: global state, clean up somehow */
Block* func = &m->functions[fidx];
Type* type = func->type;
/* Make space on the stack*/
m->sp += type->param_count;
wa_trace(
" {{}} setup_thunk_in '%s', mask: 0x%lluxx, ARGS FOR '>>' ARE BOGUS\n",
func->export_name, type->mask);
/* Do normal function call setup. The fp will point to the start of stack
elements that were just added above*/
setup_call(m, fidx);
/* Set the type of the unset stack elements */
for (p = 0; p < type->param_count; p++) {
m->stack[m->fp + p].value_type = type->params[p];
}
/* Return the thunk_in function */
switch (type->mask) {
case 0x800:
f = (void (*)(void))thunk_in_0_0;
break;
case 0x8101:
f = (void (*)(void))thunk_in_i_i;
break;
case 0x80011:
f = (void (*)(void))thunk_in_0_ii;
break;
default:
FATAL("unsupported thunk_in mask 0x%llx\n", type->mask);
}
return f;
}
void init_thunk_in(Module* m) {
_wa_current_module_ = m; /* TODO: global state, clean up somehow*/
}