koffi 2.15.1 → 2.16.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/koffi/darwin_arm64/koffi.node +0 -0
- package/build/koffi/darwin_x64/koffi.node +0 -0
- package/build/koffi/freebsd_arm64/koffi.node +0 -0
- package/build/koffi/freebsd_ia32/koffi.node +0 -0
- package/build/koffi/freebsd_x64/koffi.node +0 -0
- package/build/koffi/linux_arm64/koffi.node +0 -0
- package/build/koffi/linux_armhf/koffi.node +0 -0
- package/build/koffi/linux_ia32/koffi.node +0 -0
- package/build/koffi/linux_loong64/koffi.node +0 -0
- package/build/koffi/linux_riscv64d/koffi.node +0 -0
- package/build/koffi/linux_x64/koffi.node +0 -0
- package/build/koffi/musl_arm64/koffi.node +0 -0
- package/build/koffi/musl_x64/koffi.node +0 -0
- package/build/koffi/openbsd_ia32/koffi.node +0 -0
- package/build/koffi/openbsd_x64/koffi.node +0 -0
- package/build/koffi/win32_arm64/koffi.node +0 -0
- package/build/koffi/win32_ia32/koffi.node +0 -0
- package/build/koffi/win32_x64/koffi.node +0 -0
- package/index.d.ts +11 -9
- package/index.js +8 -8
- package/indirect.js +8 -8
- package/package.json +1 -1
- package/src/koffi/src/abi_arm32.cc +222 -219
- package/src/koffi/src/abi_arm32_asm.S +1 -29
- package/src/koffi/src/abi_arm64.cc +257 -235
- package/src/koffi/src/abi_arm64_asm.S +1 -32
- package/src/koffi/src/abi_arm64_asm.asm +1 -23
- package/src/koffi/src/abi_loong64_asm.S +1 -25
- package/src/koffi/src/abi_riscv64.cc +220 -217
- package/src/koffi/src/abi_riscv64_asm.S +1 -25
- package/src/koffi/src/abi_x64_sysv.cc +196 -192
- package/src/koffi/src/abi_x64_sysv_asm.S +1 -31
- package/src/koffi/src/abi_x64_win.cc +188 -172
- package/src/koffi/src/abi_x64_win_asm.S +1 -19
- package/src/koffi/src/abi_x64_win_asm.asm +1 -21
- package/src/koffi/src/abi_x86.cc +224 -189
- package/src/koffi/src/abi_x86_asm.S +6 -25
- package/src/koffi/src/abi_x86_asm.asm +9 -22
- package/src/koffi/src/call.cc +246 -428
- package/src/koffi/src/call.hh +9 -8
- package/src/koffi/src/ffi.cc +140 -87
- package/src/koffi/src/ffi.hh +12 -58
- package/src/koffi/src/primitives.inc +39 -0
- package/src/koffi/src/trampolines/armasm.inc +0 -32770
- package/src/koffi/src/trampolines/gnu.inc +0 -24578
- package/src/koffi/src/trampolines/masm32.inc +0 -32770
- package/src/koffi/src/trampolines/masm64.inc +0 -32770
- package/src/koffi/src/trampolines/prototypes.inc +16385 -16385
- package/src/koffi/src/util.cc +149 -107
- package/src/koffi/src/util.hh +76 -40
package/src/koffi/src/abi_x86.cc
CHANGED
|
@@ -22,7 +22,7 @@ struct BackRegisters {
|
|
|
22
22
|
double d;
|
|
23
23
|
float f;
|
|
24
24
|
} x87;
|
|
25
|
-
|
|
25
|
+
int ret_type;
|
|
26
26
|
int ret_pop;
|
|
27
27
|
};
|
|
28
28
|
|
|
@@ -37,8 +37,6 @@ extern "C" napi_value CallSwitchStack(Napi::Function *func, size_t argc, napi_va
|
|
|
37
37
|
uint8_t *old_sp, Span<uint8_t> *new_stack,
|
|
38
38
|
napi_value (*call)(Napi::Function *func, size_t argc, napi_value *argv));
|
|
39
39
|
|
|
40
|
-
#include "trampolines/prototypes.inc"
|
|
41
|
-
|
|
42
40
|
bool AnalyseFunction(Napi::Env env, InstanceData *instance, FunctionInfo *func)
|
|
43
41
|
{
|
|
44
42
|
if (!func->lib && func->convention != CallConvention::Cdecl &&
|
|
@@ -113,11 +111,10 @@ bool AnalyseFunction(Napi::Env env, InstanceData *instance, FunctionInfo *func)
|
|
|
113
111
|
|
|
114
112
|
bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
115
113
|
{
|
|
116
|
-
uint32_t *args_ptr =
|
|
114
|
+
uint32_t *args_ptr = AllocStack<uint32_t>(func->args_size);
|
|
117
115
|
uint32_t *fast_ptr = nullptr;
|
|
118
116
|
|
|
119
|
-
|
|
120
|
-
if (!AllocStack(func->args_size, 16, &args_ptr)) [[unlikely]]
|
|
117
|
+
if (!args_ptr) [[unlikely]]
|
|
121
118
|
return false;
|
|
122
119
|
if (func->fast) {
|
|
123
120
|
fast_ptr = args_ptr;
|
|
@@ -128,162 +125,224 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
128
125
|
*((func->ret.fast ? fast_ptr : args_ptr)++) = (uint32_t)return_ptr;
|
|
129
126
|
}
|
|
130
127
|
|
|
128
|
+
Size i = -1;
|
|
129
|
+
|
|
130
|
+
#if defined(__GNUC__) || defined(__clang__)
|
|
131
|
+
static const void *const DispatchTable[] = {
|
|
132
|
+
#define PRIMITIVE(Name) && Name,
|
|
133
|
+
#include "primitives.inc"
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
#define LOOP
|
|
137
|
+
#define CASE(Primitive) \
|
|
138
|
+
do { \
|
|
139
|
+
PrimitiveKind next = func->primitives[++i]; \
|
|
140
|
+
goto *DispatchTable[(int)next]; \
|
|
141
|
+
} while (false); \
|
|
142
|
+
Primitive:
|
|
143
|
+
#define OR(Primitive) \
|
|
144
|
+
Primitive:
|
|
145
|
+
#else
|
|
146
|
+
#define LOOP \
|
|
147
|
+
while (++i < func->parameters.len) \
|
|
148
|
+
switch (func->primitives[i])
|
|
149
|
+
#define CASE(Primitive) \
|
|
150
|
+
break; \
|
|
151
|
+
case PrimitiveKind::Primitive:
|
|
152
|
+
#define OR(Primitive) \
|
|
153
|
+
case PrimitiveKind::Primitive:
|
|
154
|
+
#endif
|
|
155
|
+
|
|
131
156
|
#define PUSH_INTEGER_32(CType) \
|
|
132
157
|
do { \
|
|
133
|
-
|
|
158
|
+
const ParameterInfo ¶m = func->parameters[i]; \
|
|
159
|
+
Napi::Value value = info[param.offset]; \
|
|
160
|
+
\
|
|
161
|
+
CType v; \
|
|
162
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
134
163
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
135
164
|
return false; \
|
|
136
165
|
} \
|
|
137
166
|
\
|
|
138
|
-
CType v = GetNumber<CType>(value); \
|
|
139
167
|
*((param.fast ? fast_ptr : args_ptr)++) = (uint32_t)v; \
|
|
140
168
|
} while (false)
|
|
141
169
|
#define PUSH_INTEGER_32_SWAP(CType) \
|
|
142
170
|
do { \
|
|
143
|
-
|
|
171
|
+
const ParameterInfo ¶m = func->parameters[i]; \
|
|
172
|
+
Napi::Value value = info[param.offset]; \
|
|
173
|
+
\
|
|
174
|
+
CType v; \
|
|
175
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
144
176
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
145
177
|
return false; \
|
|
146
178
|
} \
|
|
147
179
|
\
|
|
148
|
-
CType v = GetNumber<CType>(value); \
|
|
149
180
|
*((param.fast ? fast_ptr : args_ptr)++) = (uint32_t)ReverseBytes(v); \
|
|
150
181
|
} while (false)
|
|
151
182
|
#define PUSH_INTEGER_64(CType) \
|
|
152
183
|
do { \
|
|
153
|
-
|
|
184
|
+
const ParameterInfo ¶m = func->parameters[i]; \
|
|
185
|
+
Napi::Value value = info[param.offset]; \
|
|
186
|
+
\
|
|
187
|
+
CType v; \
|
|
188
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
154
189
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
155
190
|
return false; \
|
|
156
191
|
} \
|
|
157
192
|
\
|
|
158
|
-
CType v = GetNumber<CType>(value); \
|
|
159
|
-
\
|
|
160
193
|
*(uint64_t *)args_ptr = (uint64_t)v; \
|
|
161
194
|
args_ptr += 2; \
|
|
162
195
|
} while (false)
|
|
163
196
|
#define PUSH_INTEGER_64_SWAP(CType) \
|
|
164
197
|
do { \
|
|
165
|
-
|
|
198
|
+
const ParameterInfo ¶m = func->parameters[i]; \
|
|
199
|
+
Napi::Value value = info[param.offset]; \
|
|
200
|
+
\
|
|
201
|
+
CType v; \
|
|
202
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
166
203
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
167
204
|
return false; \
|
|
168
205
|
} \
|
|
169
206
|
\
|
|
170
|
-
CType v = GetNumber<CType>(value); \
|
|
171
|
-
\
|
|
172
207
|
*(uint64_t *)args_ptr = (uint64_t)ReverseBytes(v); \
|
|
173
208
|
args_ptr += 2; \
|
|
174
209
|
} while (false)
|
|
175
210
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
const ParameterInfo ¶m = func->parameters[i];
|
|
179
|
-
K_ASSERT(param.directions >= 1 && param.directions <= 3);
|
|
211
|
+
LOOP {
|
|
212
|
+
CASE(Void) { K_UNREACHABLE(); };
|
|
180
213
|
|
|
181
|
-
|
|
214
|
+
CASE(Bool) {
|
|
215
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
216
|
+
Napi::Value value = info[param.offset];
|
|
182
217
|
|
|
183
|
-
|
|
184
|
-
|
|
218
|
+
bool b;
|
|
219
|
+
if (napi_get_value_bool(env, value, &b) != napi_ok) [[unlikely]] {
|
|
220
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
185
223
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
224
|
+
*(bool *)((param.fast ? fast_ptr : args_ptr)++) = b;
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
CASE(Int8) { PUSH_INTEGER_32(int8_t); };
|
|
228
|
+
CASE(UInt8) { PUSH_INTEGER_32(uint8_t); };
|
|
229
|
+
CASE(Int16) { PUSH_INTEGER_32(int16_t); };
|
|
230
|
+
CASE(Int16S) { PUSH_INTEGER_32_SWAP(int16_t); };
|
|
231
|
+
CASE(UInt16) { PUSH_INTEGER_32(uint16_t); };
|
|
232
|
+
CASE(UInt16S) { PUSH_INTEGER_32_SWAP(uint16_t); };
|
|
233
|
+
CASE(Int32) { PUSH_INTEGER_32(int32_t); };
|
|
234
|
+
CASE(Int32S) { PUSH_INTEGER_32_SWAP(int32_t); };
|
|
235
|
+
CASE(UInt32) { PUSH_INTEGER_32(uint32_t); };
|
|
236
|
+
CASE(UInt32S) { PUSH_INTEGER_32_SWAP(uint32_t); };
|
|
237
|
+
CASE(Int64) { PUSH_INTEGER_64(int64_t); };
|
|
238
|
+
CASE(Int64S) { PUSH_INTEGER_64_SWAP(int64_t); };
|
|
239
|
+
CASE(UInt64) { PUSH_INTEGER_64(uint64_t); };
|
|
240
|
+
CASE(UInt64S) { PUSH_INTEGER_64_SWAP(uint64_t); };
|
|
241
|
+
|
|
242
|
+
CASE(String) {
|
|
243
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
244
|
+
Napi::Value value = info[param.offset];
|
|
191
245
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
case PrimitiveKind::Int8: { PUSH_INTEGER_32(int8_t); } break;
|
|
196
|
-
case PrimitiveKind::UInt8: { PUSH_INTEGER_32(uint8_t); } break;
|
|
197
|
-
case PrimitiveKind::Int16: { PUSH_INTEGER_32(int16_t); } break;
|
|
198
|
-
case PrimitiveKind::Int16S: { PUSH_INTEGER_32_SWAP(int16_t); } break;
|
|
199
|
-
case PrimitiveKind::UInt16: { PUSH_INTEGER_32(uint16_t); } break;
|
|
200
|
-
case PrimitiveKind::UInt16S: { PUSH_INTEGER_32_SWAP(uint16_t); } break;
|
|
201
|
-
case PrimitiveKind::Int32: { PUSH_INTEGER_32(int32_t); } break;
|
|
202
|
-
case PrimitiveKind::Int32S: { PUSH_INTEGER_32_SWAP(int32_t); } break;
|
|
203
|
-
case PrimitiveKind::UInt32: { PUSH_INTEGER_32(uint32_t); } break;
|
|
204
|
-
case PrimitiveKind::UInt32S: { PUSH_INTEGER_32_SWAP(uint32_t); } break;
|
|
205
|
-
case PrimitiveKind::Int64: { PUSH_INTEGER_64(int64_t); } break;
|
|
206
|
-
case PrimitiveKind::Int64S: { PUSH_INTEGER_64_SWAP(int64_t); } break;
|
|
207
|
-
case PrimitiveKind::UInt64: { PUSH_INTEGER_64(uint64_t); } break;
|
|
208
|
-
case PrimitiveKind::UInt64S: { PUSH_INTEGER_64_SWAP(uint64_t); } break;
|
|
209
|
-
case PrimitiveKind::String: {
|
|
210
|
-
const char *str;
|
|
211
|
-
if (!PushString(value, param.directions, &str)) [[unlikely]]
|
|
212
|
-
return false;
|
|
246
|
+
const char *str;
|
|
247
|
+
if (!PushString(value, param.directions, &str)) [[unlikely]]
|
|
248
|
+
return false;
|
|
213
249
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
return false;
|
|
250
|
+
*(const char **)((param.fast ? fast_ptr : args_ptr)++) = str;
|
|
251
|
+
};
|
|
252
|
+
CASE(String16) {
|
|
253
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
254
|
+
Napi::Value value = info[param.offset];
|
|
220
255
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
const char32_t *str32;
|
|
225
|
-
if (!PushString32(value, param.directions, &str32)) [[unlikely]]
|
|
226
|
-
return false;
|
|
256
|
+
const char16_t *str16;
|
|
257
|
+
if (!PushString16(value, param.directions, &str16)) [[unlikely]]
|
|
258
|
+
return false;
|
|
227
259
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
return false;
|
|
260
|
+
*(const char16_t **)((param.fast ? fast_ptr : args_ptr)++) = str16;
|
|
261
|
+
};
|
|
262
|
+
CASE(String32) {
|
|
263
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
264
|
+
Napi::Value value = info[param.offset];
|
|
234
265
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
case PrimitiveKind::Union: {
|
|
239
|
-
if (!IsObject(value)) [[unlikely]] {
|
|
240
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
|
|
241
|
-
return false;
|
|
242
|
-
}
|
|
266
|
+
const char32_t *str32;
|
|
267
|
+
if (!PushString32(value, param.directions, &str32)) [[unlikely]]
|
|
268
|
+
return false;
|
|
243
269
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
if (param.fast) {
|
|
247
|
-
uint8_t *ptr = (uint8_t *)(fast_ptr++);
|
|
248
|
-
if (!PushObject(obj, param.type, ptr))
|
|
249
|
-
return false;
|
|
250
|
-
} else {
|
|
251
|
-
uint8_t *ptr = (uint8_t *)args_ptr;
|
|
252
|
-
if (!PushObject(obj, param.type, ptr))
|
|
253
|
-
return false;
|
|
254
|
-
args_ptr = (uint32_t *)AlignUp(ptr + param.type->size, 4);
|
|
255
|
-
}
|
|
256
|
-
} break;
|
|
257
|
-
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
258
|
-
case PrimitiveKind::Float32: {
|
|
259
|
-
if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
|
|
260
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
261
|
-
return false;
|
|
262
|
-
}
|
|
270
|
+
*(const char32_t **)((param.fast ? fast_ptr : args_ptr)++) = str32;
|
|
271
|
+
};
|
|
263
272
|
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
case PrimitiveKind::Float64: {
|
|
268
|
-
if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
|
|
269
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
270
|
-
return false;
|
|
271
|
-
}
|
|
273
|
+
CASE(Pointer) {
|
|
274
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
275
|
+
Napi::Value value = info[param.offset];
|
|
272
276
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
277
|
+
void *ptr;
|
|
278
|
+
if (!PushPointer(value, param.type, param.directions, &ptr)) [[unlikely]]
|
|
279
|
+
return false;
|
|
280
|
+
|
|
281
|
+
*(void **)((param.fast ? fast_ptr : args_ptr)++) = ptr;
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
CASE(Record) OR(Union) {
|
|
285
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
286
|
+
Napi::Value value = info[param.offset];
|
|
287
|
+
|
|
288
|
+
if (!IsObject(value)) [[unlikely]] {
|
|
289
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
|
|
290
|
+
return false;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
Napi::Object obj = value.As<Napi::Object>();
|
|
294
|
+
|
|
295
|
+
if (param.fast) {
|
|
296
|
+
uint8_t *ptr = (uint8_t *)(fast_ptr++);
|
|
297
|
+
if (!PushObject(obj, param.type, ptr))
|
|
280
298
|
return false;
|
|
299
|
+
} else {
|
|
300
|
+
uint8_t *ptr = (uint8_t *)args_ptr;
|
|
301
|
+
if (!PushObject(obj, param.type, ptr))
|
|
302
|
+
return false;
|
|
303
|
+
args_ptr = (uint32_t *)AlignUp(ptr + param.type->size, 4);
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
CASE(Array) { K_UNREACHABLE(); };
|
|
281
307
|
|
|
282
|
-
|
|
283
|
-
|
|
308
|
+
CASE(Float32) {
|
|
309
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
310
|
+
Napi::Value value = info[param.offset];
|
|
284
311
|
|
|
285
|
-
|
|
286
|
-
|
|
312
|
+
float f;
|
|
313
|
+
if (!TryNumber(value, &f)) [[unlikely]] {
|
|
314
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
315
|
+
return false;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
*(float *)((param.fast ? fast_ptr : args_ptr)++) = f;
|
|
319
|
+
};
|
|
320
|
+
CASE(Float64) {
|
|
321
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
322
|
+
Napi::Value value = info[param.offset];
|
|
323
|
+
|
|
324
|
+
double d;
|
|
325
|
+
if (!TryNumber(value, &d)) [[unlikely]] {
|
|
326
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
327
|
+
return false;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
*(double *)args_ptr = d;
|
|
331
|
+
args_ptr += 2;
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
CASE(Callback) {
|
|
335
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
336
|
+
Napi::Value value = info[param.offset];
|
|
337
|
+
|
|
338
|
+
void *ptr;
|
|
339
|
+
if (!PushCallback(value, param.type, &ptr)) [[unlikely]]
|
|
340
|
+
return false;
|
|
341
|
+
|
|
342
|
+
*(void **)((param.fast ? fast_ptr : args_ptr)++) = ptr;
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
CASE(Prototype) { /* End loop */ };
|
|
287
346
|
}
|
|
288
347
|
|
|
289
348
|
#undef PUSH_INTEGER_64_SWAP
|
|
@@ -291,6 +350,10 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
291
350
|
#undef PUSH_INTEGER_32_SWAP
|
|
292
351
|
#undef PUSH_INTEGER_32
|
|
293
352
|
|
|
353
|
+
#undef OR
|
|
354
|
+
#undef CASE
|
|
355
|
+
#undef LOOP
|
|
356
|
+
|
|
294
357
|
new_sp = mem->stack.end();
|
|
295
358
|
|
|
296
359
|
return true;
|
|
@@ -416,17 +479,8 @@ Napi::Value CallData::Complete(const FunctionInfo *func)
|
|
|
416
479
|
case PrimitiveKind::String: return result.ptr ? Napi::String::New(env, (const char *)result.ptr) : env.Null();
|
|
417
480
|
case PrimitiveKind::String16: return result.ptr ? Napi::String::New(env, (const char16_t *)result.ptr) : env.Null();
|
|
418
481
|
case PrimitiveKind::String32: return result.ptr ? MakeStringFromUTF32(env, (const char32_t *)result.ptr) : env.Null();
|
|
419
|
-
case PrimitiveKind::Pointer:
|
|
420
|
-
case PrimitiveKind::Callback:
|
|
421
|
-
if (result.ptr) {
|
|
422
|
-
Napi::External<void> external = Napi::External<void>::New(env, result.ptr);
|
|
423
|
-
SetValueTag(external, func->ret.type->ref.marker);
|
|
424
|
-
|
|
425
|
-
return external;
|
|
426
|
-
} else {
|
|
427
|
-
return env.Null();
|
|
428
|
-
}
|
|
429
|
-
} break;
|
|
482
|
+
case PrimitiveKind::Pointer: return result.ptr ? WrapPointer(env, func->ret.type->ref.type, result.ptr) : env.Null();
|
|
483
|
+
case PrimitiveKind::Callback: return result.ptr ? WrapCallback(env, func->ret.type->ref.type, result.ptr) : env.Null();
|
|
430
484
|
case PrimitiveKind::Record:
|
|
431
485
|
case PrimitiveKind::Union: {
|
|
432
486
|
const uint8_t *ptr = return_ptr ? (const uint8_t *)return_ptr
|
|
@@ -491,7 +545,7 @@ void CallData::Relay(Size idx, uint8_t *, uint8_t *caller_sp, bool switch_stack,
|
|
|
491
545
|
K_DEFER_N(err_guard) {
|
|
492
546
|
int pop = out_reg->ret_pop;
|
|
493
547
|
memset(out_reg, 0, K_SIZE(*out_reg));
|
|
494
|
-
out_reg->
|
|
548
|
+
out_reg->ret_type = 0;
|
|
495
549
|
out_reg->ret_pop = pop;
|
|
496
550
|
};
|
|
497
551
|
|
|
@@ -636,18 +690,21 @@ void CallData::Relay(Size idx, uint8_t *, uint8_t *caller_sp, bool switch_stack,
|
|
|
636
690
|
Napi::Value arg = str32 ? MakeStringFromUTF32(env, str32) : env.Null();
|
|
637
691
|
arguments.Append(arg);
|
|
638
692
|
} break;
|
|
639
|
-
case PrimitiveKind::Pointer:
|
|
640
|
-
case PrimitiveKind::Callback: {
|
|
693
|
+
case PrimitiveKind::Pointer: {
|
|
641
694
|
void *ptr2 = *(void **)(args_ptr++);
|
|
642
695
|
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
SetValueTag(external, param.type->ref.marker);
|
|
696
|
+
Napi::Value p = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
|
|
697
|
+
arguments.Append(p);
|
|
646
698
|
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
arguments.Append(env.Null());
|
|
699
|
+
if (param.type->dispose) {
|
|
700
|
+
param.type->dispose(env, param.type, ptr2);
|
|
650
701
|
}
|
|
702
|
+
} break;
|
|
703
|
+
case PrimitiveKind::Callback: {
|
|
704
|
+
void *ptr2 = *(void **)(args_ptr++);
|
|
705
|
+
|
|
706
|
+
Napi::Value p = ptr2 ? WrapCallback(env, param.type->ref.type, ptr2) : env.Null();
|
|
707
|
+
arguments.Append(p);
|
|
651
708
|
|
|
652
709
|
if (param.type->dispose) {
|
|
653
710
|
param.type->dispose(env, param.type, ptr2);
|
|
@@ -700,59 +757,62 @@ void CallData::Relay(Size idx, uint8_t *, uint8_t *caller_sp, bool switch_stack,
|
|
|
700
757
|
|
|
701
758
|
#define RETURN_INTEGER_32(CType) \
|
|
702
759
|
do { \
|
|
703
|
-
|
|
760
|
+
CType v; \
|
|
761
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
704
762
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
705
763
|
return; \
|
|
706
764
|
} \
|
|
707
765
|
\
|
|
708
|
-
CType v = GetNumber<CType>(value); \
|
|
709
766
|
out_reg->eax = (uint32_t)v; \
|
|
767
|
+
out_reg->ret_type = 0; \
|
|
710
768
|
} while (false)
|
|
711
769
|
#define RETURN_INTEGER_32_SWAP(CType) \
|
|
712
770
|
do { \
|
|
713
|
-
|
|
771
|
+
CType v; \
|
|
772
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
714
773
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
715
774
|
return; \
|
|
716
775
|
} \
|
|
717
776
|
\
|
|
718
|
-
CType v = GetNumber<CType>(value); \
|
|
719
777
|
out_reg->eax = (uint32_t)ReverseBytes(v); \
|
|
778
|
+
out_reg->ret_type = 0; \
|
|
720
779
|
} while (false)
|
|
721
780
|
#define RETURN_INTEGER_64(CType) \
|
|
722
781
|
do { \
|
|
723
|
-
|
|
782
|
+
CType v; \
|
|
783
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
724
784
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
725
785
|
return; \
|
|
726
786
|
} \
|
|
727
787
|
\
|
|
728
|
-
CType v = GetNumber<CType>(value); \
|
|
729
|
-
\
|
|
730
788
|
out_reg->eax = (uint32_t)((uint64_t)v >> 32); \
|
|
731
789
|
out_reg->edx = (uint32_t)((uint64_t)v & 0xFFFFFFFFu); \
|
|
790
|
+
out_reg->ret_type = 0; \
|
|
732
791
|
} while (false)
|
|
733
792
|
#define RETURN_INTEGER_64_SWAP(CType) \
|
|
734
793
|
do { \
|
|
735
|
-
|
|
794
|
+
CType v; \
|
|
795
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
736
796
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
737
797
|
return; \
|
|
738
798
|
} \
|
|
739
799
|
\
|
|
740
|
-
CType v = ReverseBytes(GetNumber<CType>(value)); \
|
|
741
|
-
\
|
|
742
800
|
out_reg->eax = (uint32_t)((uint64_t)v >> 32); \
|
|
743
801
|
out_reg->edx = (uint32_t)((uint64_t)v & 0xFFFFFFFFu); \
|
|
802
|
+
out_reg->ret_type = 0; \
|
|
744
803
|
} while (false)
|
|
745
804
|
|
|
746
805
|
switch (type->primitive) {
|
|
747
|
-
case PrimitiveKind::Void: {} break;
|
|
806
|
+
case PrimitiveKind::Void: { out_reg->ret_type = 0; } break;
|
|
748
807
|
case PrimitiveKind::Bool: {
|
|
749
|
-
|
|
808
|
+
bool b;
|
|
809
|
+
if (napi_get_value_bool(env, value, &b) != napi_ok) [[unlikely]] {
|
|
750
810
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
|
|
751
811
|
return;
|
|
752
812
|
}
|
|
753
813
|
|
|
754
|
-
bool b = value.As<Napi::Boolean>();
|
|
755
814
|
out_reg->eax = (uint32_t)b;
|
|
815
|
+
out_reg->ret_type = 0;
|
|
756
816
|
} break;
|
|
757
817
|
case PrimitiveKind::Int8: { RETURN_INTEGER_32(int8_t); } break;
|
|
758
818
|
case PrimitiveKind::UInt8: { RETURN_INTEGER_32(uint8_t); } break;
|
|
@@ -774,6 +834,7 @@ void CallData::Relay(Size idx, uint8_t *, uint8_t *caller_sp, bool switch_stack,
|
|
|
774
834
|
return;
|
|
775
835
|
|
|
776
836
|
out_reg->eax = (uint32_t)str;
|
|
837
|
+
out_reg->ret_type = 0;
|
|
777
838
|
} break;
|
|
778
839
|
case PrimitiveKind::String16: {
|
|
779
840
|
const char16_t *str16;
|
|
@@ -781,6 +842,7 @@ void CallData::Relay(Size idx, uint8_t *, uint8_t *caller_sp, bool switch_stack,
|
|
|
781
842
|
return;
|
|
782
843
|
|
|
783
844
|
out_reg->eax = (uint32_t)str16;
|
|
845
|
+
out_reg->ret_type = 0;
|
|
784
846
|
} break;
|
|
785
847
|
case PrimitiveKind::String32: {
|
|
786
848
|
const char32_t *str32;
|
|
@@ -788,28 +850,15 @@ void CallData::Relay(Size idx, uint8_t *, uint8_t *caller_sp, bool switch_stack,
|
|
|
788
850
|
return;
|
|
789
851
|
|
|
790
852
|
out_reg->eax = (uint32_t)str32;
|
|
853
|
+
out_reg->ret_type = 0;
|
|
791
854
|
} break;
|
|
792
855
|
case PrimitiveKind::Pointer: {
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
if (CheckValueTag(value, type->ref.marker)) {
|
|
796
|
-
ptr = value.As<Napi::External<uint8_t>>().Data();
|
|
797
|
-
} else if (IsObject(value) && (type->ref.type->primitive == PrimitiveKind::Record ||
|
|
798
|
-
type->ref.type->primitive == PrimitiveKind::Union)) {
|
|
799
|
-
Napi::Object obj = value.As<Napi::Object>();
|
|
800
|
-
|
|
801
|
-
ptr = AllocHeap(type->ref.type->size, 16);
|
|
802
|
-
|
|
803
|
-
if (!PushObject(obj, type->ref.type, ptr))
|
|
804
|
-
return;
|
|
805
|
-
} else if (IsNullOrUndefined(value)) {
|
|
806
|
-
ptr = nullptr;
|
|
807
|
-
} else {
|
|
808
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
|
|
856
|
+
void *ptr;
|
|
857
|
+
if (!PushPointer(value, type, 1, &ptr)) [[unlikely]]
|
|
809
858
|
return;
|
|
810
|
-
}
|
|
811
859
|
|
|
812
860
|
out_reg->eax = (uint32_t)ptr;
|
|
861
|
+
out_reg->ret_type = 0;
|
|
813
862
|
} break;
|
|
814
863
|
case PrimitiveKind::Record:
|
|
815
864
|
case PrimitiveKind::Union: {
|
|
@@ -827,45 +876,37 @@ void CallData::Relay(Size idx, uint8_t *, uint8_t *caller_sp, bool switch_stack,
|
|
|
827
876
|
} else {
|
|
828
877
|
PushObject(obj, type, (uint8_t *)&out_reg->eax);
|
|
829
878
|
}
|
|
879
|
+
|
|
880
|
+
out_reg->ret_type = 0;
|
|
830
881
|
} break;
|
|
831
882
|
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
832
883
|
case PrimitiveKind::Float32: {
|
|
833
|
-
|
|
884
|
+
float f;
|
|
885
|
+
if (!TryNumber(value, &f)) [[unlikely]] {
|
|
834
886
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
835
887
|
return;
|
|
836
888
|
}
|
|
837
889
|
|
|
838
|
-
out_reg->x87.f =
|
|
839
|
-
out_reg->
|
|
890
|
+
out_reg->x87.f = f;
|
|
891
|
+
out_reg->ret_type = 1;
|
|
840
892
|
} break;
|
|
841
893
|
case PrimitiveKind::Float64: {
|
|
842
|
-
|
|
894
|
+
double d;
|
|
895
|
+
if (!TryNumber(value, &d)) [[unlikely]] {
|
|
843
896
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
844
897
|
return;
|
|
845
898
|
}
|
|
846
899
|
|
|
847
|
-
out_reg->x87.d =
|
|
848
|
-
out_reg->
|
|
900
|
+
out_reg->x87.d = d;
|
|
901
|
+
out_reg->ret_type = 2;
|
|
849
902
|
} break;
|
|
850
903
|
case PrimitiveKind::Callback: {
|
|
851
904
|
void *ptr;
|
|
852
|
-
|
|
853
|
-
if (value.IsFunction()) {
|
|
854
|
-
Napi::Function func2 = value.As<Napi::Function>();
|
|
855
|
-
|
|
856
|
-
ptr = ReserveTrampoline(type->ref.proto, func2);
|
|
857
|
-
if (!ptr) [[unlikely]]
|
|
858
|
-
return;
|
|
859
|
-
} else if (CheckValueTag(value, type->ref.marker)) {
|
|
860
|
-
ptr = value.As<Napi::External<void>>().Data();
|
|
861
|
-
} else if (IsNullOrUndefined(value)) {
|
|
862
|
-
ptr = nullptr;
|
|
863
|
-
} else {
|
|
864
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
|
|
905
|
+
if (!PushCallback(value, type, &ptr)) [[unlikely]]
|
|
865
906
|
return;
|
|
866
|
-
}
|
|
867
907
|
|
|
868
908
|
out_reg->eax = (uint32_t)ptr;
|
|
909
|
+
out_reg->ret_type = 0;
|
|
869
910
|
} break;
|
|
870
911
|
|
|
871
912
|
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
@@ -879,12 +920,6 @@ void CallData::Relay(Size idx, uint8_t *, uint8_t *caller_sp, bool switch_stack,
|
|
|
879
920
|
err_guard.Disable();
|
|
880
921
|
}
|
|
881
922
|
|
|
882
|
-
void *GetTrampoline(int16_t idx, const FunctionInfo *proto)
|
|
883
|
-
{
|
|
884
|
-
bool x87 = IsFloat(proto->ret.type);
|
|
885
|
-
return Trampolines[idx][x87];
|
|
886
|
-
}
|
|
887
|
-
|
|
888
923
|
}
|
|
889
924
|
|
|
890
925
|
#endif
|
|
@@ -90,6 +90,7 @@ ForwardCallRD:
|
|
|
90
90
|
# Depending on ABI, call convention and return value size, we need to issue ret <something>. Since ret
|
|
91
91
|
# only takes an immediate value, and I prefer not to branch, the return address is moved instead according
|
|
92
92
|
# to BackRegisters::ret_pop before ret is issued.
|
|
93
|
+
# We need to branch at the end to avoid x87 stack imbalance.
|
|
93
94
|
.macro trampoline id
|
|
94
95
|
.cfi_startproc
|
|
95
96
|
.cfi_def_cfa esp, 4
|
|
@@ -108,36 +109,16 @@ ForwardCallRD:
|
|
|
108
109
|
movl 44(%esp), %edx
|
|
109
110
|
movl 36(%esp), %ecx
|
|
110
111
|
movl %edx, 44(%esp, %ecx)
|
|
112
|
+
cmpl $1, 32(%esp)
|
|
113
|
+
je 1f
|
|
114
|
+
cmpl $2, 32(%esp)
|
|
115
|
+
je 2f
|
|
116
|
+
0:
|
|
111
117
|
movl 16(%esp), %eax
|
|
112
118
|
movl 20(%esp), %edx
|
|
113
119
|
leal 44(%esp, %ecx), %esp
|
|
114
120
|
.cfi_def_cfa esp, 4
|
|
115
121
|
ret
|
|
116
|
-
.cfi_endproc
|
|
117
|
-
.endm
|
|
118
|
-
|
|
119
|
-
# This version also loads the x87 stack with the result, if need be.
|
|
120
|
-
# We have to branch to avoid x87 stack imbalance.
|
|
121
|
-
.macro trampoline_vec id
|
|
122
|
-
.cfi_startproc
|
|
123
|
-
.cfi_def_cfa esp, 4
|
|
124
|
-
ENDBR32
|
|
125
|
-
sub $44, %esp
|
|
126
|
-
.cfi_def_cfa esp, 48
|
|
127
|
-
movl $\id, 0(%esp)
|
|
128
|
-
movl %esp, 4(%esp)
|
|
129
|
-
leal 48(%esp), %eax
|
|
130
|
-
movl %eax, 8(%esp)
|
|
131
|
-
leal 16(%esp), %eax
|
|
132
|
-
movl %eax, 12(%esp)
|
|
133
|
-
call GetEIP
|
|
134
|
-
addl $_GLOBAL_OFFSET_TABLE_, %ecx
|
|
135
|
-
call *RelayCallback@GOT(%ecx)
|
|
136
|
-
movl 44(%esp), %edx
|
|
137
|
-
movl 36(%esp), %ecx
|
|
138
|
-
movl %edx, 44(%esp, %ecx, 4)
|
|
139
|
-
cmpb $0, 32(%esp)
|
|
140
|
-
jne 2f
|
|
141
122
|
1:
|
|
142
123
|
flds 24(%esp)
|
|
143
124
|
leal 44(%esp, %ecx), %esp
|