koffi 3.0.1 → 3.1.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 +32 -3
- package/cnoke.cjs +2 -2
- package/doc/benchmarks.md +1 -1
- package/doc/callbacks.md +7 -26
- package/doc/{input.md → composites.md} +161 -147
- package/doc/contribute.md +3 -2
- package/doc/index.md +0 -14
- package/doc/{functions.md → load.md} +54 -113
- package/doc/migration.md +4 -7
- package/doc/misc.md +0 -103
- package/doc/output.md +5 -11
- package/doc/pointers.md +76 -17
- package/doc/primitives.md +151 -0
- package/doc/start.md +3 -13
- package/doc/types.md +88 -0
- package/doc/unions.md +0 -186
- package/doc/values.md +134 -0
- package/index.d.ts +375 -308
- package/lib/native/base/base.cc +66 -24
- package/lib/native/base/base.hh +55 -153
- package/package.json +16 -16
- package/src/koffi/CMakeLists.txt +20 -17
- package/src/koffi/index.cjs +30 -111
- package/src/koffi/index.js +22 -96
- package/src/koffi/indirect.cjs +30 -111
- package/src/koffi/indirect.js +24 -24
- package/src/koffi/src/abi/arm64.cc +48 -62
- package/src/koffi/src/abi/riscv64.cc +39 -57
- package/src/koffi/src/abi/x64sysv.cc +39 -57
- package/src/koffi/src/abi/x64win.cc +48 -65
- package/src/koffi/src/abi/x86.cc +47 -59
- package/src/koffi/src/call.cc +426 -209
- package/src/koffi/src/call.hh +7 -11
- package/src/koffi/src/ffi.cc +534 -303
- package/src/koffi/src/ffi.hh +71 -15
- package/src/koffi/src/parser.cc +5 -3
- package/src/koffi/src/parser.hh +2 -2
- package/src/koffi/src/static.cjs +122 -0
- package/src/koffi/src/static.js +125 -0
- package/src/koffi/src/type.cc +725 -0
- package/src/koffi/src/type.hh +71 -0
- package/src/koffi/src/util.cc +117 -1202
- package/src/koffi/src/util.hh +158 -156
- package/src/koffi/src/uv.cc +17 -11
- package/src/koffi/src/uv.hh +2 -1
- package/vendor/node-addon-api/README.md +1 -1
- package/vendor/node-addon-api/napi-inl.h +213 -35
- package/vendor/node-addon-api/napi.h +118 -7
- package/doc/variables.md +0 -102
- package/indirect.d.ts +0 -322
package/src/koffi/src/abi/x86.cc
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
#include "lib/native/base/base.hh"
|
|
7
7
|
#include "../ffi.hh"
|
|
8
8
|
#include "../call.hh"
|
|
9
|
+
#include "../type.hh"
|
|
9
10
|
#include "../util.hh"
|
|
10
11
|
#if defined(_WIN32)
|
|
11
12
|
#include "../win32.hh"
|
|
@@ -80,10 +81,10 @@ bool AnalyseFunction(Napi::Env env, InstanceData *instance, FunctionInfo *func)
|
|
|
80
81
|
if (func->ret.type->primitive != PrimitiveKind::Record &&
|
|
81
82
|
func->ret.type->primitive != PrimitiveKind::Union) {
|
|
82
83
|
K_ASSERT(IsRegularSize(func->ret.type->size, 8));
|
|
83
|
-
func->ret.
|
|
84
|
+
func->ret.abi.regular = true;
|
|
84
85
|
#if defined(_WIN32) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
|
|
85
86
|
} else {
|
|
86
|
-
func->ret.
|
|
87
|
+
func->ret.abi.regular = IsRegularSize(func->ret.type->size, 8);
|
|
87
88
|
#endif
|
|
88
89
|
}
|
|
89
90
|
|
|
@@ -94,7 +95,7 @@ bool AnalyseFunction(Napi::Env env, InstanceData *instance, FunctionInfo *func)
|
|
|
94
95
|
Size fast_offset = 0;
|
|
95
96
|
Size stk_offset = fast ? 4 : 0;
|
|
96
97
|
|
|
97
|
-
if (!func->ret.
|
|
98
|
+
if (!func->ret.abi.regular) {
|
|
98
99
|
#if defined(_WIN32)
|
|
99
100
|
stk_offset++;
|
|
100
101
|
#else
|
|
@@ -224,7 +225,7 @@ bool AnalyseFunction(Napi::Env env, InstanceData *instance, FunctionInfo *func)
|
|
|
224
225
|
}
|
|
225
226
|
#endif
|
|
226
227
|
|
|
227
|
-
if (func->ret.
|
|
228
|
+
if (func->ret.abi.regular) {
|
|
228
229
|
AbiOpcode run = fast ? AbiOpcode::RunAggregateGR : AbiOpcode::RunAggregateG;
|
|
229
230
|
AbiOpcode call = fast ? AbiOpcode::CallGR : AbiOpcode::CallG;
|
|
230
231
|
|
|
@@ -269,13 +270,13 @@ bool AnalyseFunction(Napi::Env env, InstanceData *instance, FunctionInfo *func)
|
|
|
269
270
|
case CallConvention::Stdcall: {
|
|
270
271
|
K_ASSERT(!func->variadic);
|
|
271
272
|
|
|
272
|
-
Size suffix = (stk_offset - !func->ret.
|
|
273
|
+
Size suffix = (stk_offset - !func->ret.abi.regular) * 4;
|
|
273
274
|
func->decorated_name = Fmt(&instance->str_alloc, "_%1@%2", func->name, suffix).ptr;
|
|
274
275
|
} break;
|
|
275
276
|
case CallConvention::Fastcall: {
|
|
276
277
|
K_ASSERT(!func->variadic);
|
|
277
278
|
|
|
278
|
-
Size suffix = (fast_offset + stk_offset - 4 - !func->ret.
|
|
279
|
+
Size suffix = (fast_offset + stk_offset - 4 - !func->ret.abi.regular) * 4;
|
|
279
280
|
func->decorated_name = Fmt(&instance->str_alloc, "@%1@%2", func->name, suffix).ptr;
|
|
280
281
|
} break;
|
|
281
282
|
case CallConvention::Thiscall: {
|
|
@@ -462,14 +463,9 @@ napi_value RunLoop(CallData *call, napi_value *args, uint8_t *base, const AbiIns
|
|
|
462
463
|
OP(PushAggregateStack) {
|
|
463
464
|
napi_value arg = args[inst->a];
|
|
464
465
|
|
|
465
|
-
if (!IsObject(call->env, arg)) [[unlikely]] {
|
|
466
|
-
ThrowError<Napi::TypeError>(call->env, "Unexpected %1 value, expected object", GetValueType(call->instance, arg));
|
|
467
|
-
return call->env.Null();
|
|
468
|
-
}
|
|
469
|
-
|
|
470
466
|
uint8_t *ptr = (uint8_t *)(base + inst->b1);
|
|
471
467
|
|
|
472
|
-
if (!call->PushObject(arg, inst->type, ptr))
|
|
468
|
+
if (!call->PushObject(arg, inst->type, ptr)) [[unlikely]]
|
|
473
469
|
return call->env.Null();
|
|
474
470
|
|
|
475
471
|
NEXT();
|
|
@@ -503,7 +499,7 @@ napi_value RunLoop(CallData *call, napi_value *args, uint8_t *base, const AbiIns
|
|
|
503
499
|
#define DISPOSE(Ptr) \
|
|
504
500
|
do { \
|
|
505
501
|
if (inst->type->dispose) { \
|
|
506
|
-
inst->type->dispose(call->
|
|
502
|
+
inst->type->dispose(call->instance, inst->type, (Ptr)); \
|
|
507
503
|
} \
|
|
508
504
|
} while (false)
|
|
509
505
|
|
|
@@ -531,42 +527,42 @@ napi_value RunLoop(CallData *call, napi_value *args, uint8_t *base, const AbiIns
|
|
|
531
527
|
OP(RunUInt64S) { INTEGER64_SWAP(G, uint64_t); }
|
|
532
528
|
OP(RunString) {
|
|
533
529
|
uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, base, &call->saved_sp));
|
|
534
|
-
napi_value value =
|
|
530
|
+
napi_value value = NewString(call->env, (const char *)eax);
|
|
535
531
|
DISPOSE((void *)eax);
|
|
536
532
|
return value;
|
|
537
533
|
}
|
|
538
534
|
OP(RunString16) {
|
|
539
535
|
uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, base, &call->saved_sp));
|
|
540
|
-
napi_value value =
|
|
536
|
+
napi_value value = NewString(call->env, (const char16_t *)eax);
|
|
541
537
|
DISPOSE((void *)eax);
|
|
542
538
|
return value;
|
|
543
539
|
}
|
|
544
540
|
OP(RunString32) {
|
|
545
541
|
uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, base, &call->saved_sp));
|
|
546
|
-
napi_value value =
|
|
542
|
+
napi_value value = NewString(call->env, (const char32_t *)eax);
|
|
547
543
|
DISPOSE((void *)eax);
|
|
548
544
|
return value;
|
|
549
545
|
}
|
|
550
546
|
OP(RunPointer) {
|
|
551
547
|
uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, base, &call->saved_sp));
|
|
552
|
-
napi_value value =
|
|
548
|
+
napi_value value = WrapPointer(call->env, inst->type, (void *)eax);
|
|
553
549
|
DISPOSE((void *)eax);
|
|
554
550
|
return value;
|
|
555
551
|
}
|
|
556
552
|
OP(RunCallback) {
|
|
557
553
|
uint32_t eax = (uint32_t)WRAP(ForwardCallG(call->native, base, &call->saved_sp));
|
|
558
|
-
return
|
|
554
|
+
return WrapPointer(call->env, inst->type, (void *)eax);
|
|
559
555
|
}
|
|
560
556
|
OP(RunRecord) { K_UNREACHABLE(); return call->env.Null(); }
|
|
561
557
|
OP(RunUnion) { K_UNREACHABLE(); return call->env.Null(); }
|
|
562
558
|
OP(RunArray) { K_UNREACHABLE(); return call->env.Null(); }
|
|
563
559
|
OP(RunFloat32) {
|
|
564
560
|
float f = WRAP(ForwardCallF(call->native, base, &call->saved_sp));
|
|
565
|
-
return
|
|
561
|
+
return NewFloat(call->env, f);
|
|
566
562
|
}
|
|
567
563
|
OP(RunFloat64) {
|
|
568
564
|
double d = WRAP(ForwardCallD(call->native, base, &call->saved_sp));
|
|
569
|
-
return
|
|
565
|
+
return NewFloat(call->env, d);
|
|
570
566
|
}
|
|
571
567
|
OP(RunPrototype) { K_UNREACHABLE(); return call->env.Null(); }
|
|
572
568
|
OP(RunAggregateG) {
|
|
@@ -610,42 +606,42 @@ napi_value RunLoop(CallData *call, napi_value *args, uint8_t *base, const AbiIns
|
|
|
610
606
|
OP(RunUInt64SR) { INTEGER64_SWAP(GR, uint64_t); }
|
|
611
607
|
OP(RunStringR) {
|
|
612
608
|
uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, base, &call->saved_sp));
|
|
613
|
-
napi_value value =
|
|
609
|
+
napi_value value = NewString(call->env, (const char *)eax);
|
|
614
610
|
DISPOSE((void *)eax);
|
|
615
611
|
return value;
|
|
616
612
|
}
|
|
617
613
|
OP(RunString16R) {
|
|
618
614
|
uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, base, &call->saved_sp));
|
|
619
|
-
napi_value value =
|
|
615
|
+
napi_value value = NewString(call->env, (const char16_t *)eax);
|
|
620
616
|
DISPOSE((void *)eax);
|
|
621
617
|
return value;
|
|
622
618
|
}
|
|
623
619
|
OP(RunString32R) {
|
|
624
620
|
uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, base, &call->saved_sp));
|
|
625
|
-
napi_value value =
|
|
621
|
+
napi_value value = NewString(call->env, (const char32_t *)eax);
|
|
626
622
|
DISPOSE((void *)eax);
|
|
627
623
|
return value;
|
|
628
624
|
}
|
|
629
625
|
OP(RunPointerR) {
|
|
630
626
|
uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, base, &call->saved_sp));
|
|
631
|
-
napi_value value =
|
|
627
|
+
napi_value value = WrapPointer(call->env, inst->type, (void *)eax);
|
|
632
628
|
DISPOSE((void *)eax);
|
|
633
629
|
return value;
|
|
634
630
|
}
|
|
635
631
|
OP(RunCallbackR) {
|
|
636
632
|
uint32_t eax = (uint32_t)WRAP(ForwardCallGR(call->native, base, &call->saved_sp));
|
|
637
|
-
return
|
|
633
|
+
return WrapPointer(call->env, inst->type, (void *)eax);
|
|
638
634
|
}
|
|
639
635
|
OP(RunRecordR) { K_UNREACHABLE(); return call->env.Null(); }
|
|
640
636
|
OP(RunUnionR) { K_UNREACHABLE(); return call->env.Null(); }
|
|
641
637
|
OP(RunArrayR) { K_UNREACHABLE(); return call->env.Null(); }
|
|
642
638
|
OP(RunFloat32R) {
|
|
643
639
|
float f = WRAP(ForwardCallFR(call->native, base, &call->saved_sp));
|
|
644
|
-
return
|
|
640
|
+
return NewFloat(call->env, f);
|
|
645
641
|
}
|
|
646
642
|
OP(RunFloat64R) {
|
|
647
643
|
double d = WRAP(ForwardCallDR(call->native, base, &call->saved_sp));
|
|
648
|
-
return
|
|
644
|
+
return NewFloat(call->env, d);
|
|
649
645
|
}
|
|
650
646
|
OP(RunPrototypeR) { K_UNREACHABLE(); return call->env.Null(); }
|
|
651
647
|
OP(RunAggregateGR) {
|
|
@@ -685,7 +681,7 @@ napi_value RunLoop(CallData *call, napi_value *args, uint8_t *base, const AbiIns
|
|
|
685
681
|
do { \
|
|
686
682
|
if (inst->type->dispose) { \
|
|
687
683
|
void *ptr = *(void **)base; \
|
|
688
|
-
inst->type->dispose(call->
|
|
684
|
+
inst->type->dispose(call->instance, inst->type, ptr); \
|
|
689
685
|
} \
|
|
690
686
|
} while (false)
|
|
691
687
|
#define INTEGER32(CType) \
|
|
@@ -757,42 +753,42 @@ napi_value RunLoop(CallData *call, napi_value *args, uint8_t *base, const AbiIns
|
|
|
757
753
|
OP(ReturnUInt64S) { INTEGER64_SWAP(uint64_t); }
|
|
758
754
|
OP(ReturnString) {
|
|
759
755
|
uint32_t eax = *(uint32_t *)base;
|
|
760
|
-
napi_value value =
|
|
756
|
+
napi_value value = NewString(call->env, (const char *)eax);
|
|
761
757
|
DISPOSE();
|
|
762
758
|
return value;
|
|
763
759
|
}
|
|
764
760
|
OP(ReturnString16) {
|
|
765
761
|
uint32_t eax = *(uint32_t *)base;
|
|
766
|
-
napi_value value =
|
|
762
|
+
napi_value value = NewString(call->env, (const char16_t *)eax);
|
|
767
763
|
DISPOSE();
|
|
768
764
|
return value;
|
|
769
765
|
}
|
|
770
766
|
OP(ReturnString32) {
|
|
771
767
|
uint32_t eax = *(uint32_t *)base;
|
|
772
|
-
napi_value value =
|
|
768
|
+
napi_value value = NewString(call->env, (const char32_t *)eax);
|
|
773
769
|
DISPOSE();
|
|
774
770
|
return value;
|
|
775
771
|
}
|
|
776
772
|
OP(ReturnPointer) {
|
|
777
773
|
uint32_t eax = *(uint32_t *)base;
|
|
778
|
-
napi_value value =
|
|
774
|
+
napi_value value = WrapPointer(call->env, inst->type, (void *)eax);
|
|
779
775
|
DISPOSE();
|
|
780
776
|
return value;
|
|
781
777
|
}
|
|
782
778
|
OP(ReturnCallback) {
|
|
783
779
|
uint32_t eax = *(uint32_t *)base;
|
|
784
|
-
return
|
|
780
|
+
return WrapPointer(call->env, inst->type, (void *)eax);
|
|
785
781
|
}
|
|
786
782
|
OP(ReturnRecord) { K_UNREACHABLE(); return call->env.Null(); }
|
|
787
783
|
OP(ReturnUnion) { K_UNREACHABLE(); return call->env.Null(); }
|
|
788
784
|
OP(ReturnArray) { K_UNREACHABLE(); return call->env.Null(); }
|
|
789
785
|
OP(ReturnFloat32) {
|
|
790
786
|
float f = *(float *)base;
|
|
791
|
-
return
|
|
787
|
+
return NewFloat(call->env, f);
|
|
792
788
|
}
|
|
793
789
|
OP(ReturnFloat64) {
|
|
794
790
|
double d = *(double *)base;
|
|
795
|
-
return
|
|
791
|
+
return NewFloat(call->env, d);
|
|
796
792
|
}
|
|
797
793
|
OP(ReturnPrototype) { K_UNREACHABLE(); return call->env.Null(); }
|
|
798
794
|
OP(ReturnAggregateReg) { return DecodeObject(call->instance, (const uint8_t *)base, inst->type); }
|
|
@@ -858,8 +854,8 @@ void CallData::Relay(Size idx, uint8_t *sp)
|
|
|
858
854
|
|
|
859
855
|
uint32_t *args_ptr = (uint32_t *)caller_sp;
|
|
860
856
|
|
|
861
|
-
uint8_t *return_ptr = !proto->ret.
|
|
862
|
-
args_ptr += !proto->ret.
|
|
857
|
+
uint8_t *return_ptr = !proto->ret.abi.regular ? (uint8_t *)args_ptr[0] : nullptr;
|
|
858
|
+
args_ptr += !proto->ret.abi.regular;
|
|
863
859
|
|
|
864
860
|
if (proto->convention == CallConvention::Stdcall) {
|
|
865
861
|
out_reg->ret_pop = (int)proto->ret_pop;
|
|
@@ -960,43 +956,39 @@ void CallData::Relay(Size idx, uint8_t *sp)
|
|
|
960
956
|
} break;
|
|
961
957
|
case PrimitiveKind::String: {
|
|
962
958
|
const char *str = *(const char **)(args_ptr++);
|
|
963
|
-
arguments[i] =
|
|
959
|
+
arguments[i] = NewString(env, str);
|
|
964
960
|
|
|
965
961
|
if (param.type->dispose) {
|
|
966
|
-
param.type->dispose(
|
|
962
|
+
param.type->dispose(instance, param.type, str);
|
|
967
963
|
}
|
|
968
964
|
} break;
|
|
969
965
|
case PrimitiveKind::String16: {
|
|
970
966
|
const char16_t *str16 = *(const char16_t **)(args_ptr++);
|
|
971
|
-
arguments[i] =
|
|
967
|
+
arguments[i] = NewString(env, str16);
|
|
972
968
|
|
|
973
969
|
if (param.type->dispose) {
|
|
974
|
-
param.type->dispose(
|
|
970
|
+
param.type->dispose(instance, param.type, str16);
|
|
975
971
|
}
|
|
976
972
|
} break;
|
|
977
973
|
case PrimitiveKind::String32: {
|
|
978
974
|
const char32_t *str32 = *(const char32_t **)(args_ptr++);
|
|
979
|
-
arguments[i] =
|
|
975
|
+
arguments[i] = NewString(env, str32);
|
|
980
976
|
|
|
981
977
|
if (param.type->dispose) {
|
|
982
|
-
param.type->dispose(
|
|
978
|
+
param.type->dispose(instance, param.type, str32);
|
|
983
979
|
}
|
|
984
980
|
} break;
|
|
985
981
|
case PrimitiveKind::Pointer: {
|
|
986
982
|
void *ptr2 = *(void **)(args_ptr++);
|
|
987
|
-
arguments[i] =
|
|
983
|
+
arguments[i] = WrapPointer(env, param.type->ref.type, ptr2);
|
|
988
984
|
|
|
989
985
|
if (param.type->dispose) {
|
|
990
|
-
param.type->dispose(
|
|
986
|
+
param.type->dispose(instance, param.type, ptr2);
|
|
991
987
|
}
|
|
992
988
|
} break;
|
|
993
989
|
case PrimitiveKind::Callback: {
|
|
994
990
|
void *ptr2 = *(void **)(args_ptr++);
|
|
995
|
-
arguments[i] =
|
|
996
|
-
|
|
997
|
-
if (param.type->dispose) {
|
|
998
|
-
param.type->dispose(env, param.type, ptr2);
|
|
999
|
-
}
|
|
991
|
+
arguments[i] = WrapPointer(env, param.type->ref.type, ptr2);
|
|
1000
992
|
} break;
|
|
1001
993
|
case PrimitiveKind::Record:
|
|
1002
994
|
case PrimitiveKind::Union: {
|
|
@@ -1008,13 +1000,13 @@ void CallData::Relay(Size idx, uint8_t *sp)
|
|
|
1008
1000
|
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
1009
1001
|
case PrimitiveKind::Float32: {
|
|
1010
1002
|
float f = *(float *)(args_ptr++);
|
|
1011
|
-
arguments[i] =
|
|
1003
|
+
arguments[i] = NewFloat(env, f);
|
|
1012
1004
|
} break;
|
|
1013
1005
|
case PrimitiveKind::Float64: {
|
|
1014
1006
|
double d = *(double *)args_ptr;
|
|
1015
1007
|
args_ptr += 2;
|
|
1016
1008
|
|
|
1017
|
-
arguments[i] =
|
|
1009
|
+
arguments[i] = NewFloat(env, d);
|
|
1018
1010
|
} break;
|
|
1019
1011
|
|
|
1020
1012
|
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
@@ -1136,17 +1128,13 @@ void CallData::Relay(Size idx, uint8_t *sp)
|
|
|
1136
1128
|
} break;
|
|
1137
1129
|
case PrimitiveKind::Record:
|
|
1138
1130
|
case PrimitiveKind::Union: {
|
|
1139
|
-
if (!IsObject(env, value)) [[unlikely]] {
|
|
1140
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
|
|
1141
|
-
return;
|
|
1142
|
-
}
|
|
1143
|
-
|
|
1144
1131
|
if (return_ptr) {
|
|
1145
|
-
if (!PushObject(value, type, return_ptr))
|
|
1132
|
+
if (!PushObject(value, type, return_ptr)) [[unlikely]]
|
|
1146
1133
|
return;
|
|
1147
1134
|
out_reg->eax = (uint32_t)return_ptr;
|
|
1148
1135
|
} else {
|
|
1149
|
-
PushObject(value, type, (uint8_t *)&out_reg->eax)
|
|
1136
|
+
if (!PushObject(value, type, (uint8_t *)&out_reg->eax))
|
|
1137
|
+
return;
|
|
1150
1138
|
}
|
|
1151
1139
|
|
|
1152
1140
|
out_reg->ret_type = 0;
|