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
|
@@ -42,8 +42,6 @@ extern "C" napi_value CallSwitchStack(Napi::Function *func, size_t argc, napi_va
|
|
|
42
42
|
uint8_t *old_sp, Span<uint8_t> *new_stack,
|
|
43
43
|
napi_value (*call)(Napi::Function *func, size_t argc, napi_value *argv));
|
|
44
44
|
|
|
45
|
-
#include "trampolines/prototypes.inc"
|
|
46
|
-
|
|
47
45
|
static int IsHFA(const TypeInfo *type)
|
|
48
46
|
{
|
|
49
47
|
#if defined(__ARM_PCS_VFP)
|
|
@@ -201,54 +199,73 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
|
|
|
201
199
|
|
|
202
200
|
bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
203
201
|
{
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
uint32_t *vec_ptr =
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
// partially in GPR, partially in the stack.
|
|
212
|
-
if (!AllocStack(func->args_size, 16, &args_ptr)) [[unlikely]]
|
|
213
|
-
return false;
|
|
214
|
-
if (!AllocStack(4 * 4, 8, &gpr_ptr)) [[unlikely]]
|
|
215
|
-
return false;
|
|
216
|
-
if (!AllocStack(8 * 8, 8, &vec_ptr)) [[unlikely]]
|
|
202
|
+
// Unlike other call conventions, here we put the general-purpose registers before the stack, behind the vector ones).
|
|
203
|
+
// In the armv7hf calling convention, some arguments can end up partially in GPR, partially in the stack.
|
|
204
|
+
uint32_t *vec_ptr = AllocStack<uint32_t>(20 * 4 + func->args_size);
|
|
205
|
+
uint32_t *gpr_ptr = vec_ptr + 16;
|
|
206
|
+
uint32_t *args_ptr = vec_ptr + 20;
|
|
207
|
+
|
|
208
|
+
if (!vec_ptr) [[unlikely]]
|
|
217
209
|
return false;
|
|
218
210
|
if (func->ret.use_memory) {
|
|
219
211
|
return_ptr = AllocHeap(func->ret.type->size, 16);
|
|
220
212
|
*(uint8_t **)(gpr_ptr++) = return_ptr;
|
|
221
213
|
}
|
|
222
214
|
|
|
215
|
+
Size i = -1;
|
|
216
|
+
|
|
217
|
+
static const void *const DispatchTable[] = {
|
|
218
|
+
#define PRIMITIVE(Name) && Name,
|
|
219
|
+
#include "primitives.inc"
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
#define LOOP
|
|
223
|
+
#define CASE(Primitive) \
|
|
224
|
+
do { \
|
|
225
|
+
PrimitiveKind next = func->primitives[++i]; \
|
|
226
|
+
goto *DispatchTable[(int)next]; \
|
|
227
|
+
} while (false); \
|
|
228
|
+
Primitive:
|
|
229
|
+
#define OR(Primitive) \
|
|
230
|
+
Primitive:
|
|
231
|
+
|
|
223
232
|
#define PUSH_INTEGER_32(CType) \
|
|
224
233
|
do { \
|
|
225
|
-
|
|
234
|
+
const ParameterInfo ¶m = func->parameters[i]; \
|
|
235
|
+
Napi::Value value = info[param.offset]; \
|
|
236
|
+
\
|
|
237
|
+
CType v; \
|
|
238
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
226
239
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
227
240
|
return false; \
|
|
228
241
|
} \
|
|
229
242
|
\
|
|
230
|
-
CType v = GetNumber<CType>(value); \
|
|
231
243
|
*((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint32_t)v; \
|
|
232
244
|
} while (false)
|
|
233
245
|
#define PUSH_INTEGER_32_SWAP(CType) \
|
|
234
246
|
do { \
|
|
235
|
-
|
|
247
|
+
const ParameterInfo ¶m = func->parameters[i]; \
|
|
248
|
+
Napi::Value value = info[param.offset]; \
|
|
249
|
+
\
|
|
250
|
+
CType v; \
|
|
251
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
236
252
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
237
253
|
return false; \
|
|
238
254
|
} \
|
|
239
255
|
\
|
|
240
|
-
CType v = GetNumber<CType>(value); \
|
|
241
256
|
*((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint32_t)ReverseBytes(v); \
|
|
242
257
|
} while (false)
|
|
243
258
|
#define PUSH_INTEGER_64(CType) \
|
|
244
259
|
do { \
|
|
245
|
-
|
|
260
|
+
const ParameterInfo ¶m = func->parameters[i]; \
|
|
261
|
+
Napi::Value value = info[param.offset]; \
|
|
262
|
+
\
|
|
263
|
+
CType v; \
|
|
264
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
246
265
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
247
266
|
return false; \
|
|
248
267
|
} \
|
|
249
268
|
\
|
|
250
|
-
CType v = GetNumber<CType>(value); \
|
|
251
|
-
\
|
|
252
269
|
if (param.gpr_count) [[likely]] { \
|
|
253
270
|
gpr_ptr = AlignUp(gpr_ptr, 8); \
|
|
254
271
|
*(uint64_t *)gpr_ptr = (uint64_t)v; \
|
|
@@ -261,13 +278,15 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
261
278
|
} while (false)
|
|
262
279
|
#define PUSH_INTEGER_64_SWAP(CType) \
|
|
263
280
|
do { \
|
|
264
|
-
|
|
281
|
+
const ParameterInfo ¶m = func->parameters[i]; \
|
|
282
|
+
Napi::Value value = info[param.offset]; \
|
|
283
|
+
\
|
|
284
|
+
CType v; \
|
|
285
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
265
286
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
266
287
|
return false; \
|
|
267
288
|
} \
|
|
268
289
|
\
|
|
269
|
-
CType v = GetNumber<CType>(value); \
|
|
270
|
-
\
|
|
271
290
|
if (param.gpr_count) [[likely]] { \
|
|
272
291
|
gpr_ptr = AlignUp(gpr_ptr, 8); \
|
|
273
292
|
*(uint64_t *)gpr_ptr = (uint64_t)ReverseBytes(v); \
|
|
@@ -279,148 +298,170 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
279
298
|
} \
|
|
280
299
|
} while (false)
|
|
281
300
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
const ParameterInfo ¶m = func->parameters[i];
|
|
285
|
-
K_ASSERT(param.directions >= 1 && param.directions <= 3);
|
|
301
|
+
LOOP {
|
|
302
|
+
CASE(Void) { K_UNREACHABLE(); };
|
|
286
303
|
|
|
287
|
-
|
|
304
|
+
CASE(Bool) {
|
|
305
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
306
|
+
Napi::Value value = info[param.offset];
|
|
288
307
|
|
|
289
|
-
|
|
290
|
-
|
|
308
|
+
bool b;
|
|
309
|
+
if (napi_get_value_bool(env, value, &b) != napi_ok) [[unlikely]] {
|
|
310
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
|
|
311
|
+
return false;
|
|
312
|
+
}
|
|
291
313
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
314
|
+
*((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint32_t)b;
|
|
315
|
+
};
|
|
316
|
+
|
|
317
|
+
CASE(Int8) { PUSH_INTEGER_32(int8_t); };
|
|
318
|
+
CASE(UInt8) { PUSH_INTEGER_32(uint8_t); };
|
|
319
|
+
CASE(Int16) { PUSH_INTEGER_32(int16_t); };
|
|
320
|
+
CASE(Int16S) { PUSH_INTEGER_32_SWAP(int16_t); };
|
|
321
|
+
CASE(UInt16) { PUSH_INTEGER_32(uint16_t); };
|
|
322
|
+
CASE(UInt16S) { PUSH_INTEGER_32_SWAP(uint16_t); };
|
|
323
|
+
CASE(Int32) { PUSH_INTEGER_32(int32_t); };
|
|
324
|
+
CASE(Int32S) { PUSH_INTEGER_32_SWAP(int32_t); };
|
|
325
|
+
CASE(UInt32) { PUSH_INTEGER_32(uint32_t); };
|
|
326
|
+
CASE(UInt32S) { PUSH_INTEGER_32_SWAP(uint32_t); };
|
|
327
|
+
CASE(Int64) { PUSH_INTEGER_64(int64_t); };
|
|
328
|
+
CASE(Int64S) { PUSH_INTEGER_64_SWAP(int64_t); };
|
|
329
|
+
CASE(UInt64) { PUSH_INTEGER_64(uint64_t); };
|
|
330
|
+
CASE(UInt64S) { PUSH_INTEGER_64_SWAP(uint64_t); };
|
|
331
|
+
|
|
332
|
+
CASE(String) {
|
|
333
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
334
|
+
Napi::Value value = info[param.offset];
|
|
297
335
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
case PrimitiveKind::Int8: { PUSH_INTEGER_32(int8_t); } break;
|
|
302
|
-
case PrimitiveKind::UInt8: { PUSH_INTEGER_32(uint8_t); } break;
|
|
303
|
-
case PrimitiveKind::Int16: { PUSH_INTEGER_32(int16_t); } break;
|
|
304
|
-
case PrimitiveKind::Int16S: { PUSH_INTEGER_32_SWAP(int16_t); } break;
|
|
305
|
-
case PrimitiveKind::UInt16: { PUSH_INTEGER_32(uint16_t); } break;
|
|
306
|
-
case PrimitiveKind::UInt16S: { PUSH_INTEGER_32_SWAP(uint16_t); } break;
|
|
307
|
-
case PrimitiveKind::Int32: { PUSH_INTEGER_32(int32_t); } break;
|
|
308
|
-
case PrimitiveKind::Int32S: { PUSH_INTEGER_32_SWAP(int32_t); } break;
|
|
309
|
-
case PrimitiveKind::UInt32: { PUSH_INTEGER_32(uint32_t); } break;
|
|
310
|
-
case PrimitiveKind::UInt32S: { PUSH_INTEGER_32_SWAP(uint32_t); } break;
|
|
311
|
-
case PrimitiveKind::Int64: { PUSH_INTEGER_64(int64_t); } break;
|
|
312
|
-
case PrimitiveKind::Int64S: { PUSH_INTEGER_64_SWAP(int64_t); } break;
|
|
313
|
-
case PrimitiveKind::UInt64: { PUSH_INTEGER_64(uint64_t); } break;
|
|
314
|
-
case PrimitiveKind::UInt64S: { PUSH_INTEGER_64_SWAP(uint64_t); } break;
|
|
315
|
-
case PrimitiveKind::String: {
|
|
316
|
-
const char *str;
|
|
317
|
-
if (!PushString(value, param.directions, &str)) [[unlikely]]
|
|
318
|
-
return false;
|
|
336
|
+
const char *str;
|
|
337
|
+
if (!PushString(value, param.directions, &str)) [[unlikely]]
|
|
338
|
+
return false;
|
|
319
339
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
return false;
|
|
340
|
+
*(const char **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str;
|
|
341
|
+
};
|
|
342
|
+
CASE(String16) {
|
|
343
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
344
|
+
Napi::Value value = info[param.offset];
|
|
326
345
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
const char32_t *str32;
|
|
331
|
-
if (!PushString32(value, param.directions, &str32)) [[unlikely]]
|
|
332
|
-
return false;
|
|
346
|
+
const char16_t *str16;
|
|
347
|
+
if (!PushString16(value, param.directions, &str16)) [[unlikely]]
|
|
348
|
+
return false;
|
|
333
349
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
return false;
|
|
350
|
+
*(const char16_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str16;
|
|
351
|
+
};
|
|
352
|
+
CASE(String32) {
|
|
353
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
354
|
+
Napi::Value value = info[param.offset];
|
|
340
355
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
case PrimitiveKind::Union: {
|
|
345
|
-
if (!IsObject(value)) [[unlikely]] {
|
|
346
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
|
|
347
|
-
return false;
|
|
348
|
-
}
|
|
356
|
+
const char32_t *str32;
|
|
357
|
+
if (!PushString32(value, param.directions, &str32)) [[unlikely]]
|
|
358
|
+
return false;
|
|
349
359
|
|
|
350
|
-
|
|
360
|
+
*(const char32_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str32;
|
|
361
|
+
};
|
|
351
362
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
vec_ptr += param.vec_count;
|
|
356
|
-
} else if (param.gpr_count) {
|
|
357
|
-
K_ASSERT(param.type->align <= 8);
|
|
363
|
+
CASE(Pointer) {
|
|
364
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
365
|
+
Napi::Value value = info[param.offset];
|
|
358
366
|
|
|
359
|
-
|
|
360
|
-
|
|
367
|
+
void *ptr;
|
|
368
|
+
if (!PushPointer(value, param.type, param.directions, &ptr)) [[unlikely]]
|
|
369
|
+
return false;
|
|
361
370
|
|
|
362
|
-
|
|
363
|
-
|
|
371
|
+
*(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
|
|
372
|
+
};
|
|
364
373
|
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
int16_t align = (param.type->align <= 4) ? 4 : 8;
|
|
369
|
-
args_ptr = AlignUp(args_ptr, align);
|
|
374
|
+
CASE(Record) OR(Union) {
|
|
375
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
376
|
+
Napi::Value value = info[param.offset];
|
|
370
377
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
378
|
+
if (!IsObject(value)) [[unlikely]] {
|
|
379
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
|
|
380
|
+
return false;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
Napi::Object obj = value.As<Napi::Object>();
|
|
384
|
+
|
|
385
|
+
if (param.vec_count) {
|
|
386
|
+
if (!PushObject(obj, param.type, (uint8_t *)vec_ptr))
|
|
380
387
|
return false;
|
|
381
|
-
|
|
388
|
+
vec_ptr += param.vec_count;
|
|
389
|
+
} else if (param.gpr_count) {
|
|
390
|
+
K_ASSERT(param.type->align <= 8);
|
|
382
391
|
|
|
383
|
-
|
|
392
|
+
int16_t align = (param.type->align <= 4) ? 4 : 8;
|
|
393
|
+
gpr_ptr = AlignUp(gpr_ptr, align);
|
|
384
394
|
|
|
385
|
-
if (param.
|
|
386
|
-
*(float *)(vec_ptr++) = f;
|
|
387
|
-
} else if (param.gpr_count) {
|
|
388
|
-
*(float *)(gpr_ptr++) = f;
|
|
389
|
-
} else {
|
|
390
|
-
*(float *)(args_ptr++) = f;
|
|
391
|
-
}
|
|
392
|
-
} break;
|
|
393
|
-
case PrimitiveKind::Float64: {
|
|
394
|
-
if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
|
|
395
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
395
|
+
if (!PushObject(obj, param.type, (uint8_t *)gpr_ptr))
|
|
396
396
|
return false;
|
|
397
|
-
}
|
|
398
397
|
|
|
399
|
-
|
|
398
|
+
gpr_ptr += param.gpr_count;
|
|
399
|
+
args_ptr += (param.type->size - param.gpr_count * 4 + 3) / 4;
|
|
400
|
+
} else if (param.type->size) {
|
|
401
|
+
int16_t align = (param.type->align <= 4) ? 4 : 8;
|
|
402
|
+
args_ptr = AlignUp(args_ptr, align);
|
|
400
403
|
|
|
401
|
-
if (param.
|
|
402
|
-
*(double *)vec_ptr = d;
|
|
403
|
-
vec_ptr += 2;
|
|
404
|
-
} else if (param.gpr_count) {
|
|
405
|
-
gpr_ptr = AlignUp(gpr_ptr, 8);
|
|
406
|
-
*(double *)gpr_ptr = d;
|
|
407
|
-
gpr_ptr += 2;
|
|
408
|
-
} else {
|
|
409
|
-
args_ptr = AlignUp(args_ptr, 8);
|
|
410
|
-
*(double *)args_ptr = d;
|
|
411
|
-
args_ptr += 2;
|
|
412
|
-
}
|
|
413
|
-
} break;
|
|
414
|
-
case PrimitiveKind::Callback: {
|
|
415
|
-
void *ptr;
|
|
416
|
-
if (!PushCallback(value, param.type, &ptr)) [[unlikely]]
|
|
404
|
+
if (!PushObject(obj, param.type, (uint8_t *)args_ptr))
|
|
417
405
|
return false;
|
|
406
|
+
args_ptr += (param.type->size + 3) / 4;
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
CASE(Array) { K_UNREACHABLE(); };
|
|
418
410
|
|
|
419
|
-
|
|
420
|
-
|
|
411
|
+
CASE(Float32) {
|
|
412
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
413
|
+
Napi::Value value = info[param.offset];
|
|
421
414
|
|
|
422
|
-
|
|
423
|
-
|
|
415
|
+
float f;
|
|
416
|
+
if (!TryNumber(value, &f)) [[unlikely]] {
|
|
417
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
418
|
+
return false;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
if (param.vec_count) [[likely]] {
|
|
422
|
+
*(float *)(vec_ptr++) = f;
|
|
423
|
+
} else if (param.gpr_count) {
|
|
424
|
+
*(float *)(gpr_ptr++) = f;
|
|
425
|
+
} else {
|
|
426
|
+
*(float *)(args_ptr++) = f;
|
|
427
|
+
}
|
|
428
|
+
};
|
|
429
|
+
CASE(Float64) {
|
|
430
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
431
|
+
Napi::Value value = info[param.offset];
|
|
432
|
+
|
|
433
|
+
double d;
|
|
434
|
+
if (!TryNumber(value, &d)) [[unlikely]] {
|
|
435
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
if (param.vec_count) [[likely]] {
|
|
440
|
+
*(double *)vec_ptr = d;
|
|
441
|
+
vec_ptr += 2;
|
|
442
|
+
} else if (param.gpr_count) {
|
|
443
|
+
gpr_ptr = AlignUp(gpr_ptr, 8);
|
|
444
|
+
*(double *)gpr_ptr = d;
|
|
445
|
+
gpr_ptr += 2;
|
|
446
|
+
} else {
|
|
447
|
+
args_ptr = AlignUp(args_ptr, 8);
|
|
448
|
+
*(double *)args_ptr = d;
|
|
449
|
+
args_ptr += 2;
|
|
450
|
+
}
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
CASE(Callback) {
|
|
454
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
455
|
+
Napi::Value value = info[param.offset];
|
|
456
|
+
|
|
457
|
+
void *ptr;
|
|
458
|
+
if (!PushCallback(value, param.type, &ptr)) [[unlikely]]
|
|
459
|
+
return false;
|
|
460
|
+
|
|
461
|
+
*(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
CASE(Prototype) { /* End loop */ };
|
|
424
465
|
}
|
|
425
466
|
|
|
426
467
|
#undef PUSH_INTEGER_64_SWAP
|
|
@@ -428,6 +469,10 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
428
469
|
#undef PUSH_INTEGER_32_SWAP
|
|
429
470
|
#undef PUSH_INTEGER_32
|
|
430
471
|
|
|
472
|
+
#undef OR
|
|
473
|
+
#undef CASE
|
|
474
|
+
#undef LOOP
|
|
475
|
+
|
|
431
476
|
new_sp = mem->stack.end();
|
|
432
477
|
|
|
433
478
|
return true;
|
|
@@ -514,17 +559,8 @@ Napi::Value CallData::Complete(const FunctionInfo *func)
|
|
|
514
559
|
case PrimitiveKind::String: return result.ptr ? Napi::String::New(env, (const char *)result.ptr) : env.Null();
|
|
515
560
|
case PrimitiveKind::String16: return result.ptr ? Napi::String::New(env, (const char16_t *)result.ptr) : env.Null();
|
|
516
561
|
case PrimitiveKind::String32: return result.ptr ? MakeStringFromUTF32(env, (const char32_t *)result.ptr) : env.Null();
|
|
517
|
-
case PrimitiveKind::Pointer:
|
|
518
|
-
case PrimitiveKind::Callback:
|
|
519
|
-
if (result.ptr) {
|
|
520
|
-
Napi::External<void> external = Napi::External<void>::New(env, result.ptr);
|
|
521
|
-
SetValueTag(external, func->ret.type->ref.marker);
|
|
522
|
-
|
|
523
|
-
return external;
|
|
524
|
-
} else {
|
|
525
|
-
return env.Null();
|
|
526
|
-
}
|
|
527
|
-
} break;
|
|
562
|
+
case PrimitiveKind::Pointer: return result.ptr ? WrapPointer(env, func->ret.type->ref.type, result.ptr) : env.Null();
|
|
563
|
+
case PrimitiveKind::Callback: return result.ptr ? WrapCallback(env, func->ret.type->ref.type, result.ptr) : env.Null();
|
|
528
564
|
case PrimitiveKind::Record:
|
|
529
565
|
case PrimitiveKind::Union: {
|
|
530
566
|
const uint8_t *ptr = return_ptr ? (const uint8_t *)return_ptr
|
|
@@ -711,18 +747,21 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
711
747
|
Napi::Value arg = str32 ? MakeStringFromUTF32(env, str32) : env.Null();
|
|
712
748
|
arguments.Append(arg);
|
|
713
749
|
} break;
|
|
714
|
-
case PrimitiveKind::Pointer:
|
|
715
|
-
case PrimitiveKind::Callback: {
|
|
750
|
+
case PrimitiveKind::Pointer: {
|
|
716
751
|
void *ptr2 = *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++);
|
|
717
752
|
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
SetValueTag(external, param.type->ref.marker);
|
|
753
|
+
Napi::Value p = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
|
|
754
|
+
arguments.Append(p);
|
|
721
755
|
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
arguments.Append(env.Null());
|
|
756
|
+
if (param.type->dispose) {
|
|
757
|
+
param.type->dispose(env, param.type, ptr2);
|
|
725
758
|
}
|
|
759
|
+
} break;
|
|
760
|
+
case PrimitiveKind::Callback: {
|
|
761
|
+
void *ptr2 = *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++);
|
|
762
|
+
|
|
763
|
+
Napi::Value p = ptr2 ? WrapCallback(env, param.type->ref.type, ptr2) : env.Null();
|
|
764
|
+
arguments.Append(p);
|
|
726
765
|
|
|
727
766
|
if (param.type->dispose) {
|
|
728
767
|
param.type->dispose(env, param.type, ptr2);
|
|
@@ -825,45 +864,43 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
825
864
|
|
|
826
865
|
#define RETURN_INTEGER_32(CType) \
|
|
827
866
|
do { \
|
|
828
|
-
|
|
867
|
+
CType v; \
|
|
868
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
829
869
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for return value, expected number", GetValueType(instance, value)); \
|
|
830
870
|
return; \
|
|
831
871
|
} \
|
|
832
872
|
\
|
|
833
|
-
CType v = GetNumber<CType>(value); \
|
|
834
873
|
out_reg->r0 = (uint32_t)v; \
|
|
835
874
|
} while (false)
|
|
836
875
|
#define RETURN_INTEGER_32_SWAP(CType) \
|
|
837
876
|
do { \
|
|
838
|
-
|
|
839
|
-
|
|
877
|
+
CType v; \
|
|
878
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
879
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for return value, expected number", GetValueType(instance, value)); \
|
|
840
880
|
return; \
|
|
841
881
|
} \
|
|
842
882
|
\
|
|
843
|
-
CType v = GetNumber<CType>(value); \
|
|
844
883
|
out_reg->r0 = (uint32_t)ReverseBytes(v); \
|
|
845
884
|
} while (false)
|
|
846
885
|
#define RETURN_INTEGER_64(CType) \
|
|
847
886
|
do { \
|
|
848
|
-
|
|
849
|
-
|
|
887
|
+
CType v; \
|
|
888
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
889
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for return value, expected number", GetValueType(instance, value)); \
|
|
850
890
|
return; \
|
|
851
891
|
} \
|
|
852
892
|
\
|
|
853
|
-
CType v = GetNumber<CType>(value); \
|
|
854
|
-
\
|
|
855
893
|
out_reg->r0 = (uint32_t)((uint64_t)v >> 32); \
|
|
856
894
|
out_reg->r1 = (uint32_t)((uint64_t)v & 0xFFFFFFFFu); \
|
|
857
895
|
} while (false)
|
|
858
896
|
#define RETURN_INTEGER_64_SWAP(CType) \
|
|
859
897
|
do { \
|
|
860
|
-
|
|
861
|
-
|
|
898
|
+
CType v; \
|
|
899
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
900
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for return value, expected number", GetValueType(instance, value)); \
|
|
862
901
|
return; \
|
|
863
902
|
} \
|
|
864
903
|
\
|
|
865
|
-
CType v = ReverseBytes(GetNumber<CType>(value)); \
|
|
866
|
-
\
|
|
867
904
|
out_reg->r0 = (uint32_t)((uint64_t)v >> 32); \
|
|
868
905
|
out_reg->r1 = (uint32_t)((uint64_t)v & 0xFFFFFFFFu); \
|
|
869
906
|
} while (false)
|
|
@@ -872,12 +909,12 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
872
909
|
switch (type->primitive) {
|
|
873
910
|
case PrimitiveKind::Void: {} break;
|
|
874
911
|
case PrimitiveKind::Bool: {
|
|
875
|
-
|
|
912
|
+
bool b;
|
|
913
|
+
if (napi_get_value_bool(env, value, &b) != napi_ok) [[unlikely]] {
|
|
876
914
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
|
|
877
915
|
return;
|
|
878
916
|
}
|
|
879
917
|
|
|
880
|
-
bool b = value.As<Napi::Boolean>();
|
|
881
918
|
out_reg->r0 = (uint32_t)b;
|
|
882
919
|
} break;
|
|
883
920
|
case PrimitiveKind::Int8: { RETURN_INTEGER_32(int8_t); } break;
|
|
@@ -916,24 +953,9 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
916
953
|
out_reg->r0 = (uint32_t)str32;
|
|
917
954
|
} break;
|
|
918
955
|
case PrimitiveKind::Pointer: {
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
if (CheckValueTag(value, type->ref.marker)) {
|
|
922
|
-
ptr = value.As<Napi::External<uint8_t>>().Data();
|
|
923
|
-
} else if (IsObject(value) && (type->ref.type->primitive == PrimitiveKind::Record ||
|
|
924
|
-
type->ref.type->primitive == PrimitiveKind::Union)) {
|
|
925
|
-
Napi::Object obj = value.As<Napi::Object>();
|
|
926
|
-
|
|
927
|
-
ptr = AllocHeap(type->ref.type->size, 16);
|
|
928
|
-
|
|
929
|
-
if (!PushObject(obj, type->ref.type, ptr))
|
|
930
|
-
return;
|
|
931
|
-
} else if (IsNullOrUndefined(value)) {
|
|
932
|
-
ptr = nullptr;
|
|
933
|
-
} else {
|
|
934
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
|
|
956
|
+
void *ptr;
|
|
957
|
+
if (!PushPointer(value, type, 1, &ptr)) [[unlikely]]
|
|
935
958
|
return;
|
|
936
|
-
}
|
|
937
959
|
|
|
938
960
|
out_reg->r0 = (uint32_t)ptr;
|
|
939
961
|
} break;
|
|
@@ -958,12 +980,12 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
958
980
|
} break;
|
|
959
981
|
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
960
982
|
case PrimitiveKind::Float32: {
|
|
961
|
-
|
|
983
|
+
float f;
|
|
984
|
+
if (!TryNumber(value, &f)) [[unlikely]] {
|
|
962
985
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
963
986
|
return;
|
|
964
987
|
}
|
|
965
988
|
|
|
966
|
-
float f = GetNumber<float>(value);
|
|
967
989
|
#if defined(__ARM_PCS_VFP)
|
|
968
990
|
memcpy(&out_reg->d0, &f, 4);
|
|
969
991
|
#else
|
|
@@ -971,12 +993,12 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
971
993
|
#endif
|
|
972
994
|
} break;
|
|
973
995
|
case PrimitiveKind::Float64: {
|
|
974
|
-
|
|
996
|
+
double d;
|
|
997
|
+
if (!TryNumber(value, &d)) [[unlikely]] {
|
|
975
998
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
976
999
|
return;
|
|
977
1000
|
}
|
|
978
1001
|
|
|
979
|
-
double d = GetNumber<double>(value);
|
|
980
1002
|
#if defined(__ARM_PCS_VFP)
|
|
981
1003
|
out_reg->d0 = d;
|
|
982
1004
|
#else
|
|
@@ -985,21 +1007,8 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
985
1007
|
} break;
|
|
986
1008
|
case PrimitiveKind::Callback: {
|
|
987
1009
|
void *ptr;
|
|
988
|
-
|
|
989
|
-
if (value.IsFunction()) {
|
|
990
|
-
Napi::Function func2 = value.As<Napi::Function>();
|
|
991
|
-
|
|
992
|
-
ptr = ReserveTrampoline(type->ref.proto, func2);
|
|
993
|
-
if (!ptr) [[unlikely]]
|
|
994
|
-
return;
|
|
995
|
-
} else if (CheckValueTag(value, type->ref.marker)) {
|
|
996
|
-
ptr = value.As<Napi::External<void>>().Data();
|
|
997
|
-
} else if (IsNullOrUndefined(value)) {
|
|
998
|
-
ptr = nullptr;
|
|
999
|
-
} else {
|
|
1000
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
|
|
1010
|
+
if (!PushCallback(value, type, &ptr)) [[unlikely]]
|
|
1001
1011
|
return;
|
|
1002
|
-
}
|
|
1003
1012
|
|
|
1004
1013
|
out_reg->r0 = (uint32_t)ptr;
|
|
1005
1014
|
} break;
|
|
@@ -1015,12 +1024,6 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
1015
1024
|
err_guard.Disable();
|
|
1016
1025
|
}
|
|
1017
1026
|
|
|
1018
|
-
void *GetTrampoline(int16_t idx, const FunctionInfo *proto)
|
|
1019
|
-
{
|
|
1020
|
-
bool vec = proto->forward_fp || IsFloat(proto->ret.type);
|
|
1021
|
-
return Trampolines[idx][vec];
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1024
1027
|
}
|
|
1025
1028
|
|
|
1026
1029
|
#endif
|