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