koffi 2.14.0 → 2.15.0
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/CHANGELOG.md +26 -1
- package/README.md +1 -1
- 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/doc/assets.ini +2 -1
- package/doc/build.sh +9 -0
- package/doc/pages/404.md +17 -0
- package/doc/pages/index.md +43 -4
- package/doc/pages/misc.md +16 -11
- package/doc/pages/platforms.md +8 -19
- package/doc/pages.ini +4 -7
- package/doc/static/highlight.js +2 -14
- package/doc/static/koffi.css +3 -15
- package/doc/static/perf_windows.png +0 -0
- package/doc/static/print.css +2 -14
- package/index.d.ts +29 -24
- package/index.js +10 -9
- package/indirect.js +10 -9
- package/{src/core → lib/native}/base/base.cc +1753 -1089
- package/{src/core → lib/native}/base/base.hh +868 -572
- package/{src/core → lib/native}/base/crc.inc +3 -21
- package/lib/native/base/crc_gen.py +72 -0
- package/{src/core → lib/native}/base/mimetypes.inc +2 -20
- package/{src/core → lib/native}/base/mimetypes_gen.py +2 -21
- package/lib/native/base/tower.cc +821 -0
- package/lib/native/base/tower.hh +81 -0
- package/{src/core → lib/native}/base/unicode.inc +3 -21
- package/{src/core → lib/native}/base/unicode_gen.py +5 -42
- package/package.json +3 -2
- package/src/cnoke/assets/FindCNoke.cmake +8 -20
- package/src/cnoke/assets/win_delay_hook.c +2 -20
- package/src/cnoke/cnoke.js +2 -21
- package/src/cnoke/src/builder.js +3 -22
- package/src/cnoke/src/index.js +2 -20
- package/src/cnoke/src/tools.js +2 -20
- package/src/koffi/CMakeLists.txt +19 -22
- package/src/koffi/cmake/raylib.cmake +5 -22
- package/src/koffi/cmake/sqlite3.cmake +2 -20
- package/src/koffi/src/abi_arm32.cc +31 -49
- package/src/koffi/src/abi_arm32_asm.S +2 -20
- package/src/koffi/src/abi_arm64.cc +36 -54
- package/src/koffi/src/abi_arm64_asm.S +2 -20
- package/src/koffi/src/abi_arm64_asm.asm +2 -20
- package/src/koffi/src/abi_loong64.cc +2 -20
- package/src/koffi/src/abi_loong64_asm.S +2 -20
- package/src/koffi/src/abi_riscv64.cc +34 -52
- package/src/koffi/src/abi_riscv64_asm.S +2 -20
- package/src/koffi/src/abi_x64_sysv.cc +36 -54
- package/src/koffi/src/abi_x64_sysv_asm.S +2 -20
- package/src/koffi/src/abi_x64_win.cc +32 -50
- package/src/koffi/src/abi_x64_win_asm.asm +2 -20
- package/src/koffi/src/abi_x86.cc +33 -51
- package/src/koffi/src/abi_x86_asm.S +2 -20
- package/src/koffi/src/abi_x86_asm.asm +2 -20
- package/src/koffi/src/call.cc +107 -281
- package/src/koffi/src/call.hh +9 -27
- package/src/koffi/src/errno.inc +2 -20
- package/src/koffi/src/ffi.cc +121 -121
- package/src/koffi/src/ffi.hh +23 -38
- package/src/koffi/src/init.js +2 -20
- package/src/koffi/src/parser.cc +15 -29
- package/src/koffi/src/parser.hh +4 -22
- package/src/koffi/src/trampolines/armasm.inc +0 -21
- package/src/koffi/src/trampolines/gnu.inc +0 -21
- package/src/koffi/src/trampolines/masm32.inc +0 -21
- package/src/koffi/src/trampolines/masm64.inc +0 -21
- package/src/koffi/src/trampolines/prototypes.inc +1 -22
- package/src/koffi/src/util.cc +87 -102
- package/src/koffi/src/util.hh +11 -29
- package/src/koffi/src/uv.cc +193 -0
- package/src/koffi/src/uv.def +10 -0
- package/src/koffi/src/uv.hh +40 -0
- package/src/koffi/src/win32.cc +7 -25
- package/src/koffi/src/win32.hh +4 -22
- package/vendor/node-api-headers/include/uv/aix.h +32 -0
- package/vendor/node-api-headers/include/uv/bsd.h +34 -0
- package/vendor/node-api-headers/include/uv/darwin.h +61 -0
- package/vendor/node-api-headers/include/uv/errno.h +483 -0
- package/vendor/node-api-headers/include/uv/linux.h +34 -0
- package/vendor/node-api-headers/include/uv/os390.h +33 -0
- package/vendor/node-api-headers/include/uv/posix.h +31 -0
- package/vendor/node-api-headers/include/uv/sunos.h +44 -0
- package/vendor/node-api-headers/include/uv/threadpool.h +37 -0
- package/vendor/node-api-headers/include/uv/tree.h +521 -0
- package/vendor/node-api-headers/include/uv/unix.h +512 -0
- package/vendor/node-api-headers/include/uv/version.h +43 -0
- package/vendor/node-api-headers/include/uv/win.h +698 -0
- package/vendor/node-api-headers/include/uv.h +1990 -0
- package/src/core/base/crc_gen.py +0 -109
|
@@ -1,34 +1,16 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
4
|
-
// this software and associated documentation files (the “Software”), to deal in
|
|
5
|
-
// the Software without restriction, including without limitation the rights to use,
|
|
6
|
-
// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
|
7
|
-
// Software, and to permit persons to whom the Software is furnished to do so,
|
|
8
|
-
// subject to the following conditions:
|
|
9
|
-
//
|
|
10
|
-
// The above copyright notice and this permission notice shall be included in all
|
|
11
|
-
// copies or substantial portions of the Software.
|
|
12
|
-
//
|
|
13
|
-
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
|
|
14
|
-
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
15
|
-
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
16
|
-
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
17
|
-
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
18
|
-
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
19
|
-
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
20
|
-
// OTHER DEALINGS IN THE SOFTWARE.
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// SPDX-FileCopyrightText: 2025 Niels Martignène <niels.martignene@protonmail.com>
|
|
21
3
|
|
|
22
4
|
#if __riscv_xlen == 64 || defined(__loongarch64)
|
|
23
5
|
|
|
24
|
-
#include "
|
|
6
|
+
#include "lib/native/base/base.hh"
|
|
25
7
|
#include "ffi.hh"
|
|
26
8
|
#include "call.hh"
|
|
27
9
|
#include "util.hh"
|
|
28
10
|
|
|
29
11
|
#include <napi.h>
|
|
30
12
|
|
|
31
|
-
namespace
|
|
13
|
+
namespace K {
|
|
32
14
|
|
|
33
15
|
struct A0A1Ret {
|
|
34
16
|
uint64_t a0;
|
|
@@ -208,12 +190,12 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
208
190
|
// Push arguments
|
|
209
191
|
for (Size i = 0; i < func->parameters.len; i++) {
|
|
210
192
|
const ParameterInfo ¶m = func->parameters[i];
|
|
211
|
-
|
|
193
|
+
K_ASSERT(param.directions >= 1 && param.directions <= 3);
|
|
212
194
|
|
|
213
195
|
Napi::Value value = info[param.offset];
|
|
214
196
|
|
|
215
197
|
switch (param.type->primitive) {
|
|
216
|
-
case PrimitiveKind::Void: {
|
|
198
|
+
case PrimitiveKind::Void: { K_UNREACHABLE(); } break;
|
|
217
199
|
|
|
218
200
|
case PrimitiveKind::Bool: {
|
|
219
201
|
if (!value.IsBoolean()) [[unlikely]] {
|
|
@@ -276,7 +258,7 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
276
258
|
Napi::Object obj = value.As<Napi::Object>();
|
|
277
259
|
|
|
278
260
|
if (!param.use_memory) {
|
|
279
|
-
|
|
261
|
+
K_ASSERT(param.type->size <= 16);
|
|
280
262
|
|
|
281
263
|
uint64_t regs[2] = { 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull };
|
|
282
264
|
{
|
|
@@ -303,7 +285,7 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
303
285
|
*(gpr_ptr++) = regs[1];
|
|
304
286
|
}
|
|
305
287
|
} else {
|
|
306
|
-
|
|
288
|
+
K_ASSERT(param.type->align <= 8);
|
|
307
289
|
|
|
308
290
|
MemCpy(args_ptr, regs, param.type->size);
|
|
309
291
|
args_ptr += (param.type->size + 7) / 8;
|
|
@@ -312,8 +294,8 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
312
294
|
uint8_t *ptr = AllocHeap(param.type->size, 16);
|
|
313
295
|
|
|
314
296
|
if (param.gpr_count) {
|
|
315
|
-
|
|
316
|
-
|
|
297
|
+
K_ASSERT(param.gpr_count == 1);
|
|
298
|
+
K_ASSERT(param.vec_count == 0);
|
|
317
299
|
|
|
318
300
|
*(uint8_t **)(gpr_ptr++) = ptr;
|
|
319
301
|
} else {
|
|
@@ -324,7 +306,7 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
324
306
|
return false;
|
|
325
307
|
}
|
|
326
308
|
} break;
|
|
327
|
-
case PrimitiveKind::Array: {
|
|
309
|
+
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
328
310
|
case PrimitiveKind::Float32: {
|
|
329
311
|
if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
|
|
330
312
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
@@ -368,7 +350,7 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
368
350
|
*(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
|
|
369
351
|
} break;
|
|
370
352
|
|
|
371
|
-
case PrimitiveKind::Prototype: {
|
|
353
|
+
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
372
354
|
}
|
|
373
355
|
}
|
|
374
356
|
|
|
@@ -416,23 +398,23 @@ void CallData::Execute(const FunctionInfo *func, void *native)
|
|
|
416
398
|
case PrimitiveKind::Union: {
|
|
417
399
|
if (func->ret.gpr_first && !func->ret.vec_count) {
|
|
418
400
|
A0A1Ret ret = PERFORM_CALL(GG);
|
|
419
|
-
memcpy(&result.buf, &ret,
|
|
401
|
+
memcpy(&result.buf, &ret, K_SIZE(ret));
|
|
420
402
|
} else if (func->ret.gpr_first) {
|
|
421
403
|
A0Fa0Ret ret = PERFORM_CALL(GD);
|
|
422
|
-
memcpy(&result.buf, &ret,
|
|
404
|
+
memcpy(&result.buf, &ret, K_SIZE(ret));
|
|
423
405
|
} else if (func->ret.vec_count == 2) {
|
|
424
406
|
Fa0Fa1Ret ret = PERFORM_CALL(DD);
|
|
425
|
-
memcpy(&result.buf, &ret,
|
|
407
|
+
memcpy(&result.buf, &ret, K_SIZE(ret));
|
|
426
408
|
} else {
|
|
427
409
|
Fa0A0Ret ret = PERFORM_CALL(DG);
|
|
428
|
-
memcpy(&result.buf, &ret,
|
|
410
|
+
memcpy(&result.buf, &ret, K_SIZE(ret));
|
|
429
411
|
}
|
|
430
412
|
} break;
|
|
431
|
-
case PrimitiveKind::Array: {
|
|
413
|
+
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
432
414
|
case PrimitiveKind::Float32: { result.f = PERFORM_CALL(F); } break;
|
|
433
415
|
case PrimitiveKind::Float64: { result.d = PERFORM_CALL(DD).fa0; } break;
|
|
434
416
|
|
|
435
|
-
case PrimitiveKind::Prototype: {
|
|
417
|
+
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
436
418
|
}
|
|
437
419
|
|
|
438
420
|
#undef PERFORM_CALL
|
|
@@ -440,7 +422,7 @@ void CallData::Execute(const FunctionInfo *func, void *native)
|
|
|
440
422
|
|
|
441
423
|
Napi::Value CallData::Complete(const FunctionInfo *func)
|
|
442
424
|
{
|
|
443
|
-
|
|
425
|
+
K_DEFER {
|
|
444
426
|
PopOutArguments();
|
|
445
427
|
|
|
446
428
|
if (func->ret.type->dispose) {
|
|
@@ -472,7 +454,7 @@ Napi::Value CallData::Complete(const FunctionInfo *func)
|
|
|
472
454
|
case PrimitiveKind::Callback: {
|
|
473
455
|
if (result.ptr) {
|
|
474
456
|
Napi::External<void> external = Napi::External<void>::New(env, result.ptr);
|
|
475
|
-
SetValueTag(
|
|
457
|
+
SetValueTag(external, func->ret.type->ref.marker);
|
|
476
458
|
|
|
477
459
|
return external;
|
|
478
460
|
} else {
|
|
@@ -492,14 +474,14 @@ Napi::Value CallData::Complete(const FunctionInfo *func)
|
|
|
492
474
|
return obj;
|
|
493
475
|
}
|
|
494
476
|
} break;
|
|
495
|
-
case PrimitiveKind::Array: {
|
|
477
|
+
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
496
478
|
case PrimitiveKind::Float32: return Napi::Number::New(env, (double)result.f);
|
|
497
479
|
case PrimitiveKind::Float64: return Napi::Number::New(env, result.d);
|
|
498
480
|
|
|
499
|
-
case PrimitiveKind::Prototype: {
|
|
481
|
+
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
500
482
|
}
|
|
501
483
|
|
|
502
|
-
|
|
484
|
+
K_UNREACHABLE();
|
|
503
485
|
}
|
|
504
486
|
|
|
505
487
|
void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_stack, BackRegisters *out_reg)
|
|
@@ -519,7 +501,7 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
519
501
|
uint8_t *return_ptr = proto->ret.use_memory ? (uint8_t *)gpr_ptr[0] : nullptr;
|
|
520
502
|
gpr_ptr += proto->ret.use_memory;
|
|
521
503
|
|
|
522
|
-
|
|
504
|
+
K_DEFER_N(err_guard) { memset(out_reg, 0, K_SIZE(*out_reg)); };
|
|
523
505
|
|
|
524
506
|
if (trampoline.generation >= 0 && trampoline.generation != (int32_t)mem->generation) [[unlikely]] {
|
|
525
507
|
ThrowError<Napi::Error>(env, "Cannot use non-registered callback beyond FFI call");
|
|
@@ -533,10 +515,10 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
533
515
|
// Convert to JS arguments
|
|
534
516
|
for (Size i = 0; i < proto->parameters.len; i++) {
|
|
535
517
|
const ParameterInfo ¶m = proto->parameters[i];
|
|
536
|
-
|
|
518
|
+
K_ASSERT(param.directions >= 1 && param.directions <= 3);
|
|
537
519
|
|
|
538
520
|
switch (param.type->primitive) {
|
|
539
|
-
case PrimitiveKind::Void: {
|
|
521
|
+
case PrimitiveKind::Void: { K_UNREACHABLE(); } break;
|
|
540
522
|
|
|
541
523
|
case PrimitiveKind::Bool: {
|
|
542
524
|
bool b = *(bool *)((param.gpr_count ? gpr_ptr : args_ptr)++);
|
|
@@ -664,7 +646,7 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
664
646
|
|
|
665
647
|
if (ptr2) {
|
|
666
648
|
Napi::External<void> external = Napi::External<void>::New(env, ptr2);
|
|
667
|
-
SetValueTag(
|
|
649
|
+
SetValueTag(external, param.type->ref.marker);
|
|
668
650
|
|
|
669
651
|
arguments.Append(external);
|
|
670
652
|
} else {
|
|
@@ -688,7 +670,7 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
688
670
|
regs[0] = *(vec_ptr++);
|
|
689
671
|
regs[1] = *((param.gpr_count ? gpr_ptr : vec_ptr)++);
|
|
690
672
|
} else {
|
|
691
|
-
|
|
673
|
+
K_ASSERT(param.type->align <= 8);
|
|
692
674
|
|
|
693
675
|
MemCpy(regs, args_ptr, param.type->size);
|
|
694
676
|
args_ptr += (param.type->size + 7) / 8;
|
|
@@ -706,7 +688,7 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
706
688
|
arguments.Append(obj);
|
|
707
689
|
}
|
|
708
690
|
} break;
|
|
709
|
-
case PrimitiveKind::Array: {
|
|
691
|
+
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
710
692
|
case PrimitiveKind::Float32: {
|
|
711
693
|
float f;
|
|
712
694
|
if (param.vec_count) [[likely]] {
|
|
@@ -734,7 +716,7 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
734
716
|
arguments.Append(arg);
|
|
735
717
|
} break;
|
|
736
718
|
|
|
737
|
-
case PrimitiveKind::Prototype: {
|
|
719
|
+
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
738
720
|
}
|
|
739
721
|
}
|
|
740
722
|
|
|
@@ -824,7 +806,7 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
824
806
|
case PrimitiveKind::Pointer: {
|
|
825
807
|
uint8_t *ptr;
|
|
826
808
|
|
|
827
|
-
if (CheckValueTag(
|
|
809
|
+
if (CheckValueTag(value, type->ref.marker)) {
|
|
828
810
|
ptr = value.As<Napi::External<uint8_t>>().Data();
|
|
829
811
|
} else if (IsObject(value) && (type->ref.type->primitive == PrimitiveKind::Record ||
|
|
830
812
|
type->ref.type->primitive == PrimitiveKind::Union)) {
|
|
@@ -880,7 +862,7 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
880
862
|
}
|
|
881
863
|
}
|
|
882
864
|
} break;
|
|
883
|
-
case PrimitiveKind::Array: {
|
|
865
|
+
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
884
866
|
case PrimitiveKind::Float32: {
|
|
885
867
|
if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
|
|
886
868
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
@@ -909,7 +891,7 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
909
891
|
ptr = ReserveTrampoline(type->ref.proto, func2);
|
|
910
892
|
if (!ptr) [[unlikely]]
|
|
911
893
|
return;
|
|
912
|
-
} else if (CheckValueTag(
|
|
894
|
+
} else if (CheckValueTag(value, type->ref.marker)) {
|
|
913
895
|
ptr = value.As<Napi::External<void>>().Data();
|
|
914
896
|
} else if (IsNullOrUndefined(value)) {
|
|
915
897
|
ptr = nullptr;
|
|
@@ -921,7 +903,7 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
921
903
|
out_reg->a0 = (uint64_t)ptr;
|
|
922
904
|
} break;
|
|
923
905
|
|
|
924
|
-
case PrimitiveKind::Prototype: {
|
|
906
|
+
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
925
907
|
}
|
|
926
908
|
|
|
927
909
|
#undef RETURN_INTEGER_SWAP
|
|
@@ -1,23 +1,5 @@
|
|
|
1
|
-
#
|
|
2
|
-
#
|
|
3
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
4
|
-
# this software and associated documentation files (the “Software”), to deal in
|
|
5
|
-
# the Software without restriction, including without limitation the rights to use,
|
|
6
|
-
# copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
|
7
|
-
# Software, and to permit persons to whom the Software is furnished to do so,
|
|
8
|
-
# subject to the following conditions:
|
|
9
|
-
#
|
|
10
|
-
# The above copyright notice and this permission notice shall be included in all
|
|
11
|
-
# copies or substantial portions of the Software.
|
|
12
|
-
#
|
|
13
|
-
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
|
|
14
|
-
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
15
|
-
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
16
|
-
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
17
|
-
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
18
|
-
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
19
|
-
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
20
|
-
# OTHER DEALINGS IN THE SOFTWARE.
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# SPDX-FileCopyrightText: 2025 Niels Martignène <niels.martignene@protonmail.com>
|
|
21
3
|
|
|
22
4
|
#define SYMBOL(Symbol) Symbol
|
|
23
5
|
|
|
@@ -1,34 +1,16 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
4
|
-
// this software and associated documentation files (the “Software”), to deal in
|
|
5
|
-
// the Software without restriction, including without limitation the rights to use,
|
|
6
|
-
// copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
|
7
|
-
// Software, and to permit persons to whom the Software is furnished to do so,
|
|
8
|
-
// subject to the following conditions:
|
|
9
|
-
//
|
|
10
|
-
// The above copyright notice and this permission notice shall be included in all
|
|
11
|
-
// copies or substantial portions of the Software.
|
|
12
|
-
//
|
|
13
|
-
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
|
|
14
|
-
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
15
|
-
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
16
|
-
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
17
|
-
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
18
|
-
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
19
|
-
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
20
|
-
// OTHER DEALINGS IN THE SOFTWARE.
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
// SPDX-FileCopyrightText: 2025 Niels Martignène <niels.martignene@protonmail.com>
|
|
21
3
|
|
|
22
4
|
#if defined(__x86_64__) && !defined(_WIN32)
|
|
23
5
|
|
|
24
|
-
#include "
|
|
6
|
+
#include "lib/native/base/base.hh"
|
|
25
7
|
#include "ffi.hh"
|
|
26
8
|
#include "call.hh"
|
|
27
9
|
#include "util.hh"
|
|
28
10
|
|
|
29
11
|
#include <napi.h>
|
|
30
12
|
|
|
31
|
-
namespace
|
|
13
|
+
namespace K {
|
|
32
14
|
|
|
33
15
|
enum class RegisterClass {
|
|
34
16
|
NoClass = 0, // Explicitly 0
|
|
@@ -99,7 +81,7 @@ static inline RegisterClass MergeClasses(RegisterClass cls1, RegisterClass cls2)
|
|
|
99
81
|
|
|
100
82
|
static Size ClassifyType(const TypeInfo *type, Size offset, Span<RegisterClass> classes)
|
|
101
83
|
{
|
|
102
|
-
|
|
84
|
+
K_ASSERT(classes.len > 0);
|
|
103
85
|
|
|
104
86
|
switch (type->primitive) {
|
|
105
87
|
case PrimitiveKind::Void: { return 0; } break;
|
|
@@ -178,10 +160,10 @@ static Size ClassifyType(const TypeInfo *type, Size offset, Span<RegisterClass>
|
|
|
178
160
|
return 1;
|
|
179
161
|
} break;
|
|
180
162
|
|
|
181
|
-
case PrimitiveKind::Prototype: {
|
|
163
|
+
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
182
164
|
}
|
|
183
165
|
|
|
184
|
-
|
|
166
|
+
K_UNREACHABLE();
|
|
185
167
|
}
|
|
186
168
|
|
|
187
169
|
static void AnalyseParameter(ParameterInfo *param, int gpr_avail, int xmm_avail)
|
|
@@ -200,7 +182,7 @@ static void AnalyseParameter(ParameterInfo *param, int gpr_avail, int xmm_avail)
|
|
|
200
182
|
int xmm_count = 0;
|
|
201
183
|
|
|
202
184
|
for (RegisterClass cls: classes) {
|
|
203
|
-
|
|
185
|
+
K_ASSERT(cls != RegisterClass::NoClass);
|
|
204
186
|
|
|
205
187
|
if (cls == RegisterClass::Memory) {
|
|
206
188
|
param->use_memory = true;
|
|
@@ -283,12 +265,12 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
283
265
|
// Push arguments
|
|
284
266
|
for (Size i = 0; i < func->parameters.len; i++) {
|
|
285
267
|
const ParameterInfo ¶m = func->parameters[i];
|
|
286
|
-
|
|
268
|
+
K_ASSERT(param.directions >= 1 && param.directions <= 3);
|
|
287
269
|
|
|
288
270
|
Napi::Value value = info[param.offset];
|
|
289
271
|
|
|
290
272
|
switch (param.type->primitive) {
|
|
291
|
-
case PrimitiveKind::Void: {
|
|
273
|
+
case PrimitiveKind::Void: { K_UNREACHABLE(); } break;
|
|
292
274
|
|
|
293
275
|
case PrimitiveKind::Bool: {
|
|
294
276
|
if (!value.IsBoolean()) [[unlikely]] {
|
|
@@ -351,7 +333,7 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
351
333
|
Napi::Object obj = value.As<Napi::Object>();
|
|
352
334
|
|
|
353
335
|
if (param.gpr_count || param.xmm_count) {
|
|
354
|
-
|
|
336
|
+
K_ASSERT(param.type->size <= 16);
|
|
355
337
|
|
|
356
338
|
uint64_t buf[2] = {};
|
|
357
339
|
if (!PushObject(obj, param.type, (uint8_t *)buf))
|
|
@@ -379,7 +361,7 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
379
361
|
args_ptr += (param.type->size + 7) / 8;
|
|
380
362
|
}
|
|
381
363
|
} break;
|
|
382
|
-
case PrimitiveKind::Array: {
|
|
364
|
+
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
383
365
|
case PrimitiveKind::Float32: {
|
|
384
366
|
if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
|
|
385
367
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
@@ -409,7 +391,7 @@ bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
|
409
391
|
*(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
|
|
410
392
|
} break;
|
|
411
393
|
|
|
412
|
-
case PrimitiveKind::Prototype: {
|
|
394
|
+
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
413
395
|
}
|
|
414
396
|
}
|
|
415
397
|
|
|
@@ -457,23 +439,23 @@ void CallData::Execute(const FunctionInfo *func, void *native)
|
|
|
457
439
|
case PrimitiveKind::Union: {
|
|
458
440
|
if (func->ret.gpr_first && !func->ret.xmm_count) {
|
|
459
441
|
RaxRdxRet ret = PERFORM_CALL(GG);
|
|
460
|
-
memcpy(&result.buf, &ret,
|
|
442
|
+
memcpy(&result.buf, &ret, K_SIZE(ret));
|
|
461
443
|
} else if (func->ret.gpr_first) {
|
|
462
444
|
RaxXmm0Ret ret = PERFORM_CALL(GD);
|
|
463
|
-
memcpy(&result.buf, &ret,
|
|
445
|
+
memcpy(&result.buf, &ret, K_SIZE(ret));
|
|
464
446
|
} else if (func->ret.xmm_count == 2) {
|
|
465
447
|
Xmm0Xmm1Ret ret = PERFORM_CALL(DD);
|
|
466
|
-
memcpy(&result.buf, &ret,
|
|
448
|
+
memcpy(&result.buf, &ret, K_SIZE(ret));
|
|
467
449
|
} else {
|
|
468
450
|
Xmm0RaxRet ret = PERFORM_CALL(DG);
|
|
469
|
-
memcpy(&result.buf, &ret,
|
|
451
|
+
memcpy(&result.buf, &ret, K_SIZE(ret));
|
|
470
452
|
}
|
|
471
453
|
} break;
|
|
472
|
-
case PrimitiveKind::Array: {
|
|
454
|
+
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
473
455
|
case PrimitiveKind::Float32: { result.f = PERFORM_CALL(F); } break;
|
|
474
456
|
case PrimitiveKind::Float64: { result.d = PERFORM_CALL(DG).xmm0; } break;
|
|
475
457
|
|
|
476
|
-
case PrimitiveKind::Prototype: {
|
|
458
|
+
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
477
459
|
}
|
|
478
460
|
|
|
479
461
|
#undef PERFORM_CALL
|
|
@@ -481,7 +463,7 @@ void CallData::Execute(const FunctionInfo *func, void *native)
|
|
|
481
463
|
|
|
482
464
|
Napi::Value CallData::Complete(const FunctionInfo *func)
|
|
483
465
|
{
|
|
484
|
-
|
|
466
|
+
K_DEFER {
|
|
485
467
|
PopOutArguments();
|
|
486
468
|
|
|
487
469
|
if (func->ret.type->dispose) {
|
|
@@ -513,7 +495,7 @@ Napi::Value CallData::Complete(const FunctionInfo *func)
|
|
|
513
495
|
case PrimitiveKind::Callback: {
|
|
514
496
|
if (result.ptr) {
|
|
515
497
|
Napi::External<void> external = Napi::External<void>::New(env, result.ptr);
|
|
516
|
-
SetValueTag(
|
|
498
|
+
SetValueTag(external, func->ret.type->ref.marker);
|
|
517
499
|
|
|
518
500
|
return external;
|
|
519
501
|
} else {
|
|
@@ -528,14 +510,14 @@ Napi::Value CallData::Complete(const FunctionInfo *func)
|
|
|
528
510
|
Napi::Object obj = DecodeObject(env, ptr, func->ret.type);
|
|
529
511
|
return obj;
|
|
530
512
|
} break;
|
|
531
|
-
case PrimitiveKind::Array: {
|
|
513
|
+
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
532
514
|
case PrimitiveKind::Float32: return Napi::Number::New(env, (double)result.f);
|
|
533
515
|
case PrimitiveKind::Float64: return Napi::Number::New(env, result.d);
|
|
534
516
|
|
|
535
|
-
case PrimitiveKind::Prototype: {
|
|
517
|
+
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
536
518
|
}
|
|
537
519
|
|
|
538
|
-
|
|
520
|
+
K_UNREACHABLE();
|
|
539
521
|
}
|
|
540
522
|
|
|
541
523
|
void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_stack, BackRegisters *out_reg)
|
|
@@ -555,7 +537,7 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
555
537
|
uint8_t *return_ptr = proto->ret.use_memory ? (uint8_t *)gpr_ptr[0] : nullptr;
|
|
556
538
|
gpr_ptr += proto->ret.use_memory;
|
|
557
539
|
|
|
558
|
-
|
|
540
|
+
K_DEFER_N(err_guard) { memset(out_reg, 0, K_SIZE(*out_reg)); };
|
|
559
541
|
|
|
560
542
|
if (trampoline.generation >= 0 && trampoline.generation != (int32_t)mem->generation) [[unlikely]] {
|
|
561
543
|
ThrowError<Napi::Error>(env, "Cannot use non-registered callback beyond FFI call");
|
|
@@ -569,10 +551,10 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
569
551
|
// Convert to JS arguments
|
|
570
552
|
for (Size i = 0; i < proto->parameters.len; i++) {
|
|
571
553
|
const ParameterInfo ¶m = proto->parameters[i];
|
|
572
|
-
|
|
554
|
+
K_ASSERT(param.directions >= 1 && param.directions <= 3);
|
|
573
555
|
|
|
574
556
|
switch (param.type->primitive) {
|
|
575
|
-
case PrimitiveKind::Void: {
|
|
557
|
+
case PrimitiveKind::Void: { K_UNREACHABLE(); } break;
|
|
576
558
|
|
|
577
559
|
case PrimitiveKind::Bool: {
|
|
578
560
|
bool b = *(bool *)((param.gpr_count ? gpr_ptr : args_ptr)++);
|
|
@@ -700,7 +682,7 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
700
682
|
|
|
701
683
|
if (ptr2) {
|
|
702
684
|
Napi::External<void> external = Napi::External<void>::New(env, ptr2);
|
|
703
|
-
SetValueTag(
|
|
685
|
+
SetValueTag(external, param.type->ref.marker);
|
|
704
686
|
|
|
705
687
|
arguments.Append(external);
|
|
706
688
|
} else {
|
|
@@ -714,7 +696,7 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
714
696
|
case PrimitiveKind::Record:
|
|
715
697
|
case PrimitiveKind::Union: {
|
|
716
698
|
if (param.gpr_count || param.xmm_count) {
|
|
717
|
-
|
|
699
|
+
K_ASSERT(param.type->size <= 16);
|
|
718
700
|
|
|
719
701
|
uint64_t buf[2] = {};
|
|
720
702
|
|
|
@@ -745,7 +727,7 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
745
727
|
args_ptr += (param.type->size + 7) / 8;
|
|
746
728
|
}
|
|
747
729
|
} break;
|
|
748
|
-
case PrimitiveKind::Array: {
|
|
730
|
+
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
749
731
|
case PrimitiveKind::Float32: {
|
|
750
732
|
float f = *(float *)((param.xmm_count ? xmm_ptr : args_ptr)++);
|
|
751
733
|
|
|
@@ -759,7 +741,7 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
759
741
|
arguments.Append(arg);
|
|
760
742
|
} break;
|
|
761
743
|
|
|
762
|
-
case PrimitiveKind::Prototype: {
|
|
744
|
+
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
763
745
|
}
|
|
764
746
|
}
|
|
765
747
|
|
|
@@ -849,7 +831,7 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
849
831
|
case PrimitiveKind::Pointer: {
|
|
850
832
|
uint8_t *ptr;
|
|
851
833
|
|
|
852
|
-
if (CheckValueTag(
|
|
834
|
+
if (CheckValueTag(value, type->ref.marker)) {
|
|
853
835
|
ptr = value.As<Napi::External<uint8_t>>().Data();
|
|
854
836
|
} else if (IsObject(value) && (type->ref.type->primitive == PrimitiveKind::Record ||
|
|
855
837
|
type->ref.type->primitive == PrimitiveKind::Union)) {
|
|
@@ -882,7 +864,7 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
882
864
|
return;
|
|
883
865
|
out_reg->rax = (uint64_t)return_ptr;
|
|
884
866
|
} else {
|
|
885
|
-
|
|
867
|
+
K_ASSERT(type->size <= 16);
|
|
886
868
|
|
|
887
869
|
uint8_t buf[16] = {};
|
|
888
870
|
if (!PushObject(obj, type, buf))
|
|
@@ -903,7 +885,7 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
903
885
|
}
|
|
904
886
|
}
|
|
905
887
|
} break;
|
|
906
|
-
case PrimitiveKind::Array: {
|
|
888
|
+
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
907
889
|
case PrimitiveKind::Float32: {
|
|
908
890
|
if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
|
|
909
891
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
@@ -933,7 +915,7 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
933
915
|
ptr = ReserveTrampoline(type->ref.proto, func2);
|
|
934
916
|
if (!ptr) [[unlikely]]
|
|
935
917
|
return;
|
|
936
|
-
} else if (CheckValueTag(
|
|
918
|
+
} else if (CheckValueTag(value, type->ref.marker)) {
|
|
937
919
|
ptr = value.As<Napi::External<void>>().Data();
|
|
938
920
|
} else if (IsNullOrUndefined(value)) {
|
|
939
921
|
ptr = nullptr;
|
|
@@ -945,7 +927,7 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
945
927
|
out_reg->rax = (uint64_t)ptr;
|
|
946
928
|
} break;
|
|
947
929
|
|
|
948
|
-
case PrimitiveKind::Prototype: {
|
|
930
|
+
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
949
931
|
}
|
|
950
932
|
|
|
951
933
|
#undef RETURN_INTEGER_SWAP
|
|
@@ -1,23 +1,5 @@
|
|
|
1
|
-
#
|
|
2
|
-
#
|
|
3
|
-
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
4
|
-
# this software and associated documentation files (the “Software”), to deal in
|
|
5
|
-
# the Software without restriction, including without limitation the rights to use,
|
|
6
|
-
# copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
|
7
|
-
# Software, and to permit persons to whom the Software is furnished to do so,
|
|
8
|
-
# subject to the following conditions:
|
|
9
|
-
#
|
|
10
|
-
# The above copyright notice and this permission notice shall be included in all
|
|
11
|
-
# copies or substantial portions of the Software.
|
|
12
|
-
#
|
|
13
|
-
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
|
|
14
|
-
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
15
|
-
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
16
|
-
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
17
|
-
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
18
|
-
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
19
|
-
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
20
|
-
# OTHER DEALINGS IN THE SOFTWARE.
|
|
1
|
+
# SPDX-License-Identifier: MIT
|
|
2
|
+
# SPDX-FileCopyrightText: 2025 Niels Martignène <niels.martignene@protonmail.com>
|
|
21
3
|
|
|
22
4
|
#if defined(__APPLE__)
|
|
23
5
|
#define SYMBOL(Symbol) _ ## Symbol
|