koffi 3.0.2 → 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 +25 -7
- package/cnoke.cjs +9 -9
- package/doc/benchmarks.md +2 -2
- package/doc/callbacks.md +7 -26
- 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 +66 -24
- package/lib/native/base/base.hh +55 -153
- package/package.json +15 -15
- package/src/koffi/CMakeLists.txt +19 -17
- package/src/koffi/index.cjs +15 -10
- package/src/koffi/index.js +6 -6
- package/src/koffi/indirect.cjs +15 -10
- package/src/koffi/indirect.js +6 -6
- 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.js +3 -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
|
@@ -74,16 +74,16 @@ inline void *Code2Op(AbiOpcode code)
|
|
|
74
74
|
|
|
75
75
|
bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
|
|
76
76
|
{
|
|
77
|
-
func->ret.regular = IsRegularSize(func->ret.type->size, 8);
|
|
77
|
+
func->ret.abi.regular = IsRegularSize(func->ret.type->size, 8);
|
|
78
78
|
|
|
79
79
|
for (Size i = 0; i < func->parameters.len; i++) {
|
|
80
|
-
int16_t arg = (int16_t)(!func->ret.regular + i);
|
|
80
|
+
int16_t arg = (int16_t)(!func->ret.abi.regular + i);
|
|
81
81
|
ParameterInfo ¶m = func->parameters[i];
|
|
82
82
|
|
|
83
|
-
param.regular = IsRegularSize(param.type->size, 8);
|
|
83
|
+
param.abi.regular = IsRegularSize(param.type->size, 8);
|
|
84
84
|
|
|
85
85
|
if (param.type->primitive == PrimitiveKind::Record || param.type->primitive == PrimitiveKind::Union) {
|
|
86
|
-
AbiOpcode code = param.regular ? AbiOpcode::PushAggregateReg : AbiOpcode::PushAggregateMem;
|
|
86
|
+
AbiOpcode code = param.abi.regular ? AbiOpcode::PushAggregateReg : AbiOpcode::PushAggregateMem;
|
|
87
87
|
|
|
88
88
|
func->sync.Append({ .op = Code2Op(code), .a = param.offset, .b1 = (int16_t)(arg * 8), .b2 = (int16_t)param.directions, .type = param.type });
|
|
89
89
|
func->async.Append({ .op = Code2Op(code), .a = param.offset, .b1 = (int16_t)(arg * 8), .b2 = (int16_t)param.directions, .type = param.type });
|
|
@@ -100,7 +100,7 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
|
|
|
100
100
|
|
|
101
101
|
// At least 4 parameter registers
|
|
102
102
|
{
|
|
103
|
-
Size count = std::max((Size)4, func->parameters.len + !func->ret.regular);
|
|
103
|
+
Size count = std::max((Size)4, func->parameters.len + !func->ret.abi.regular);
|
|
104
104
|
func->stk_size = AlignLen(8 * count, 16);
|
|
105
105
|
}
|
|
106
106
|
|
|
@@ -168,7 +168,7 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
|
|
|
168
168
|
|
|
169
169
|
case PrimitiveKind::Record:
|
|
170
170
|
case PrimitiveKind::Union: {
|
|
171
|
-
if (func->ret.regular) {
|
|
171
|
+
if (func->ret.abi.regular) {
|
|
172
172
|
AbiOpcode run = func->forward_fp ? AbiOpcode::RunAggregateRegX : AbiOpcode::RunAggregateReg;
|
|
173
173
|
AbiOpcode call = func->forward_fp ? AbiOpcode::CallGX : AbiOpcode::CallG;
|
|
174
174
|
|
|
@@ -370,14 +370,9 @@ namespace {
|
|
|
370
370
|
OP(PushAggregateReg) {
|
|
371
371
|
napi_value arg = args[inst->a];
|
|
372
372
|
|
|
373
|
-
if (!IsObject(call->env, arg)) [[unlikely]] {
|
|
374
|
-
ThrowError<Napi::TypeError>(call->env, "Unexpected %1 value, expected object", GetValueType(call->instance, arg));
|
|
375
|
-
return call->env.Null();
|
|
376
|
-
}
|
|
377
|
-
|
|
378
373
|
uint8_t *ptr = (uint8_t *)(base + inst->b1);
|
|
379
374
|
|
|
380
|
-
if (!call->PushObject(arg, inst->type, ptr))
|
|
375
|
+
if (!call->PushObject(arg, inst->type, ptr)) [[unlikely]]
|
|
381
376
|
return call->env.Null();
|
|
382
377
|
|
|
383
378
|
NEXT();
|
|
@@ -385,15 +380,10 @@ namespace {
|
|
|
385
380
|
OP(PushAggregateMem) {
|
|
386
381
|
napi_value arg = args[inst->a];
|
|
387
382
|
|
|
388
|
-
if (!IsObject(call->env, arg)) [[unlikely]] {
|
|
389
|
-
ThrowError<Napi::TypeError>(call->env, "Unexpected %1 value, expected object", GetValueType(call->instance, arg));
|
|
390
|
-
return call->env.Null();
|
|
391
|
-
}
|
|
392
|
-
|
|
393
383
|
uint8_t *ptr = call->AllocHeap(inst->type->size);
|
|
394
384
|
*(uint8_t **)(base + inst->b1) = ptr;
|
|
395
385
|
|
|
396
|
-
if (!call->PushObject(arg, inst->type, ptr))
|
|
386
|
+
if (!call->PushObject(arg, inst->type, ptr)) [[unlikely]]
|
|
397
387
|
return call->env.Null();
|
|
398
388
|
|
|
399
389
|
NEXT();
|
|
@@ -415,7 +405,7 @@ namespace {
|
|
|
415
405
|
#define DISPOSE(Ptr) \
|
|
416
406
|
do { \
|
|
417
407
|
if (inst->type->dispose) { \
|
|
418
|
-
inst->type->dispose(call->
|
|
408
|
+
inst->type->dispose(call->instance, inst->type, (Ptr)); \
|
|
419
409
|
} \
|
|
420
410
|
} while (false)
|
|
421
411
|
|
|
@@ -443,42 +433,42 @@ namespace {
|
|
|
443
433
|
OP(RunUInt64S) { INTEGER_SWAP(G, uint64_t); }
|
|
444
434
|
OP(RunString) {
|
|
445
435
|
uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
|
|
446
|
-
napi_value value =
|
|
436
|
+
napi_value value = NewString(call->env, (const char *)rax);
|
|
447
437
|
DISPOSE((void *)rax);
|
|
448
438
|
return value;
|
|
449
439
|
}
|
|
450
440
|
OP(RunString16) {
|
|
451
441
|
uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
|
|
452
|
-
napi_value value =
|
|
442
|
+
napi_value value = NewString(call->env, (const char16_t *)rax);
|
|
453
443
|
DISPOSE((void *)rax);
|
|
454
444
|
return value;
|
|
455
445
|
}
|
|
456
446
|
OP(RunString32) {
|
|
457
447
|
uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
|
|
458
|
-
napi_value value =
|
|
448
|
+
napi_value value = NewString(call->env, (const char32_t *)rax);
|
|
459
449
|
DISPOSE((void *)rax);
|
|
460
450
|
return value;
|
|
461
451
|
}
|
|
462
452
|
OP(RunPointer) {
|
|
463
453
|
uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
|
|
464
|
-
napi_value value =
|
|
454
|
+
napi_value value = WrapPointer(call->env, inst->type, (void *)rax);
|
|
465
455
|
DISPOSE((void *)rax);
|
|
466
456
|
return value;
|
|
467
457
|
}
|
|
468
458
|
OP(RunCallback) {
|
|
469
459
|
uint64_t rax = WRAP(ForwardCallG(call->native, base, &call->saved_sp));
|
|
470
|
-
return
|
|
460
|
+
return WrapPointer(call->env, inst->type, (void *)rax);
|
|
471
461
|
}
|
|
472
462
|
OP(RunRecord) { K_UNREACHABLE(); return call->env.Null(); }
|
|
473
463
|
OP(RunUnion) { K_UNREACHABLE(); return call->env.Null(); }
|
|
474
464
|
OP(RunArray) { K_UNREACHABLE(); return call->env.Null(); }
|
|
475
465
|
OP(RunFloat32) {
|
|
476
466
|
float f = WRAP(ForwardCallF(call->native, base, &call->saved_sp));
|
|
477
|
-
return
|
|
467
|
+
return NewFloat(call->env, f);
|
|
478
468
|
}
|
|
479
469
|
OP(RunFloat64) {
|
|
480
470
|
double d = WRAP(ForwardCallD(call->native, base, &call->saved_sp));
|
|
481
|
-
return
|
|
471
|
+
return NewFloat(call->env, d);
|
|
482
472
|
}
|
|
483
473
|
OP(RunPrototype) { K_UNREACHABLE(); return call->env.Null(); }
|
|
484
474
|
OP(RunAggregateReg) {
|
|
@@ -514,42 +504,42 @@ namespace {
|
|
|
514
504
|
OP(RunUInt64SX) { INTEGER_SWAP(GX, uint64_t); }
|
|
515
505
|
OP(RunStringX) {
|
|
516
506
|
uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
|
|
517
|
-
napi_value value =
|
|
507
|
+
napi_value value = NewString(call->env, (const char *)rax);
|
|
518
508
|
DISPOSE((void *)rax);
|
|
519
509
|
return value;
|
|
520
510
|
}
|
|
521
511
|
OP(RunString16X) {
|
|
522
512
|
uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
|
|
523
|
-
napi_value value =
|
|
513
|
+
napi_value value = NewString(call->env, (const char16_t *)rax);
|
|
524
514
|
DISPOSE((void *)rax);
|
|
525
515
|
return value;
|
|
526
516
|
}
|
|
527
517
|
OP(RunString32X) {
|
|
528
518
|
uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
|
|
529
|
-
napi_value value =
|
|
519
|
+
napi_value value = NewString(call->env, (const char32_t *)rax);
|
|
530
520
|
DISPOSE((void *)rax);
|
|
531
521
|
return value;
|
|
532
522
|
}
|
|
533
523
|
OP(RunPointerX) {
|
|
534
524
|
uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
|
|
535
|
-
napi_value value =
|
|
525
|
+
napi_value value = WrapPointer(call->env, inst->type, (void *)rax);
|
|
536
526
|
DISPOSE((void *)rax);
|
|
537
527
|
return value;
|
|
538
528
|
}
|
|
539
529
|
OP(RunCallbackX) {
|
|
540
530
|
uint64_t rax = WRAP(ForwardCallGX(call->native, base, &call->saved_sp));
|
|
541
|
-
return
|
|
531
|
+
return WrapPointer(call->env, inst->type, (void *)rax);
|
|
542
532
|
}
|
|
543
533
|
OP(RunRecordX) { K_UNREACHABLE(); return call->env.Null(); }
|
|
544
534
|
OP(RunUnionX) { K_UNREACHABLE(); return call->env.Null(); }
|
|
545
535
|
OP(RunArrayX) { K_UNREACHABLE(); return call->env.Null(); }
|
|
546
536
|
OP(RunFloat32X) {
|
|
547
537
|
float f = WRAP(ForwardCallFX(call->native, base, &call->saved_sp));
|
|
548
|
-
return
|
|
538
|
+
return NewFloat(call->env, f);
|
|
549
539
|
}
|
|
550
540
|
OP(RunFloat64X) {
|
|
551
541
|
double d = WRAP(ForwardCallDX(call->native, base, &call->saved_sp));
|
|
552
|
-
return
|
|
542
|
+
return NewFloat(call->env, d);
|
|
553
543
|
}
|
|
554
544
|
OP(RunPrototypeX) { K_UNREACHABLE(); return call->env.Null(); }
|
|
555
545
|
OP(RunAggregateRegX) {
|
|
@@ -575,7 +565,7 @@ namespace {
|
|
|
575
565
|
do { \
|
|
576
566
|
if (inst->type->dispose) { \
|
|
577
567
|
void *ptr = *(void **)base; \
|
|
578
|
-
inst->type->dispose(call->
|
|
568
|
+
inst->type->dispose(call->instance, inst->type, ptr); \
|
|
579
569
|
} \
|
|
580
570
|
} while (false)
|
|
581
571
|
#define INTEGER(CType) \
|
|
@@ -632,42 +622,42 @@ namespace {
|
|
|
632
622
|
OP(ReturnUInt64S) { INTEGER_SWAP(uint64_t); }
|
|
633
623
|
OP(ReturnString) {
|
|
634
624
|
uint64_t rax = *(uint64_t *)base;
|
|
635
|
-
napi_value value =
|
|
625
|
+
napi_value value = NewString(call->env, (const char *)rax);
|
|
636
626
|
DISPOSE();
|
|
637
627
|
return value;
|
|
638
628
|
}
|
|
639
629
|
OP(ReturnString16) {
|
|
640
630
|
uint64_t rax = *(uint64_t *)base;
|
|
641
|
-
napi_value value =
|
|
631
|
+
napi_value value = NewString(call->env, (const char16_t *)rax);
|
|
642
632
|
DISPOSE();
|
|
643
633
|
return value;
|
|
644
634
|
}
|
|
645
635
|
OP(ReturnString32) {
|
|
646
636
|
uint64_t rax = *(uint64_t *)base;
|
|
647
|
-
napi_value value =
|
|
637
|
+
napi_value value = NewString(call->env, (const char32_t *)rax);
|
|
648
638
|
DISPOSE();
|
|
649
639
|
return value;
|
|
650
640
|
}
|
|
651
641
|
OP(ReturnPointer) {
|
|
652
642
|
uint64_t rax = *(uint64_t *)base;
|
|
653
|
-
napi_value value =
|
|
643
|
+
napi_value value = WrapPointer(call->env, inst->type, (void *)rax);
|
|
654
644
|
DISPOSE();
|
|
655
645
|
return value;
|
|
656
646
|
}
|
|
657
647
|
OP(ReturnCallback) {
|
|
658
648
|
uint64_t rax = *(uint64_t *)base;
|
|
659
|
-
return
|
|
649
|
+
return WrapPointer(call->env, inst->type, (void *)rax);
|
|
660
650
|
}
|
|
661
651
|
OP(ReturnRecord) { K_UNREACHABLE(); return call->env.Null(); }
|
|
662
652
|
OP(ReturnUnion) { K_UNREACHABLE(); return call->env.Null(); }
|
|
663
653
|
OP(ReturnArray) { K_UNREACHABLE(); return call->env.Null(); }
|
|
664
654
|
OP(ReturnFloat32) {
|
|
665
655
|
float f = *(float *)base;
|
|
666
|
-
return
|
|
656
|
+
return NewFloat(call->env, f);
|
|
667
657
|
}
|
|
668
658
|
OP(ReturnFloat64) {
|
|
669
659
|
double d = *(double *)base;
|
|
670
|
-
return
|
|
660
|
+
return NewFloat(call->env, d);
|
|
671
661
|
}
|
|
672
662
|
OP(ReturnPrototype) { K_UNREACHABLE(); return call->env.Null(); }
|
|
673
663
|
OP(ReturnAggregateReg) { return DecodeObject(call->instance, base, inst->type); }
|
|
@@ -778,7 +768,7 @@ void CallData::Relay(Size idx, uint8_t *sp)
|
|
|
778
768
|
uint64_t *xmm_ptr = gpr_ptr + 4;
|
|
779
769
|
uint64_t *stk_ptr = (uint64_t *)caller_sp;
|
|
780
770
|
|
|
781
|
-
uint8_t *return_ptr = !proto->ret.regular ? (uint8_t *)gpr_ptr[0] : nullptr;
|
|
771
|
+
uint8_t *return_ptr = !proto->ret.abi.regular ? (uint8_t *)gpr_ptr[0] : nullptr;
|
|
782
772
|
|
|
783
773
|
K_DEFER_N(err_guard) {
|
|
784
774
|
trampoline->state = -1;
|
|
@@ -889,56 +879,52 @@ void CallData::Relay(Size idx, uint8_t *sp)
|
|
|
889
879
|
const char *str = *(const char **)(j < 4 ? gpr_ptr + j : stk_ptr);
|
|
890
880
|
stk_ptr += (j >= 4);
|
|
891
881
|
|
|
892
|
-
arguments[i] =
|
|
882
|
+
arguments[i] = NewString(env, str);
|
|
893
883
|
|
|
894
884
|
if (param.type->dispose) {
|
|
895
|
-
param.type->dispose(
|
|
885
|
+
param.type->dispose(instance, param.type, str);
|
|
896
886
|
}
|
|
897
887
|
} break;
|
|
898
888
|
case PrimitiveKind::String16: {
|
|
899
889
|
const char16_t *str16 = *(const char16_t **)(j < 4 ? gpr_ptr + j : stk_ptr);
|
|
900
890
|
stk_ptr += (j >= 4);
|
|
901
891
|
|
|
902
|
-
arguments[i] =
|
|
892
|
+
arguments[i] = NewString(env, str16);
|
|
903
893
|
|
|
904
894
|
if (param.type->dispose) {
|
|
905
|
-
param.type->dispose(
|
|
895
|
+
param.type->dispose(instance, param.type, str16);
|
|
906
896
|
}
|
|
907
897
|
} break;
|
|
908
898
|
case PrimitiveKind::String32: {
|
|
909
899
|
const char32_t *str32 = *(const char32_t **)(j < 4 ? gpr_ptr + j : stk_ptr);
|
|
910
900
|
stk_ptr += (j >= 4);
|
|
911
901
|
|
|
912
|
-
arguments[i] =
|
|
902
|
+
arguments[i] = NewString(env, str32);
|
|
913
903
|
|
|
914
904
|
if (param.type->dispose) {
|
|
915
|
-
param.type->dispose(
|
|
905
|
+
param.type->dispose(instance, param.type, str32);
|
|
916
906
|
}
|
|
917
907
|
} break;
|
|
918
908
|
case PrimitiveKind::Pointer: {
|
|
919
909
|
void *ptr2 = *(void **)(j < 4 ? gpr_ptr + j : stk_ptr);
|
|
920
910
|
stk_ptr += (j >= 4);
|
|
921
911
|
|
|
922
|
-
arguments[i] =
|
|
912
|
+
arguments[i] = WrapPointer(env, param.type->ref.type, ptr2);
|
|
923
913
|
|
|
924
914
|
if (param.type->dispose) {
|
|
925
|
-
param.type->dispose(
|
|
915
|
+
param.type->dispose(instance, param.type, ptr2);
|
|
926
916
|
}
|
|
927
917
|
} break;
|
|
928
918
|
case PrimitiveKind::Callback: {
|
|
929
919
|
void *ptr2 = *(void **)(j < 4 ? gpr_ptr + j : stk_ptr);
|
|
930
920
|
stk_ptr += (j >= 4);
|
|
931
921
|
|
|
932
|
-
arguments[i] =
|
|
933
|
-
|
|
934
|
-
if (param.type->dispose) {
|
|
935
|
-
param.type->dispose(env, param.type, ptr2);
|
|
936
|
-
}
|
|
922
|
+
arguments[i] = WrapPointer(env, param.type->ref.type, ptr2);
|
|
937
923
|
} break;
|
|
938
924
|
case PrimitiveKind::Record:
|
|
939
925
|
case PrimitiveKind::Union: {
|
|
940
926
|
uint8_t *ptr;
|
|
941
|
-
if (param.regular) {
|
|
927
|
+
if (param.abi.regular) {
|
|
942
928
|
ptr = (uint8_t *)(j < 4 ? gpr_ptr + j : stk_ptr);
|
|
943
929
|
} else {
|
|
944
930
|
ptr = *(uint8_t **)(j < 4 ? gpr_ptr + j : stk_ptr);
|
|
@@ -952,13 +938,13 @@ void CallData::Relay(Size idx, uint8_t *sp)
|
|
|
952
938
|
float f = *(float *)(j < 4 ? xmm_ptr + j : stk_ptr);
|
|
953
939
|
stk_ptr += (j >= 4);
|
|
954
940
|
|
|
955
|
-
arguments[i] =
|
|
941
|
+
arguments[i] = NewFloat(env, f);
|
|
956
942
|
} break;
|
|
957
943
|
case PrimitiveKind::Float64: {
|
|
958
944
|
double d = *(double *)(j < 4 ? xmm_ptr + j : stk_ptr);
|
|
959
945
|
stk_ptr += (j >= 4);
|
|
960
946
|
|
|
961
|
-
arguments[i] =
|
|
947
|
+
arguments[i] = NewFloat(env, d);
|
|
962
948
|
} break;
|
|
963
949
|
|
|
964
950
|
case PrimitiveKind::Prototype: { K_UNREACHABLE(); } break;
|
|
@@ -1049,17 +1035,13 @@ void CallData::Relay(Size idx, uint8_t *sp)
|
|
|
1049
1035
|
} break;
|
|
1050
1036
|
case PrimitiveKind::Record:
|
|
1051
1037
|
case PrimitiveKind::Union: {
|
|
1052
|
-
if (!IsObject(env, value)) [[unlikely]] {
|
|
1053
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
|
|
1054
|
-
return;
|
|
1055
|
-
}
|
|
1056
|
-
|
|
1057
1038
|
if (return_ptr) {
|
|
1058
|
-
if (!PushObject(value, type, return_ptr))
|
|
1039
|
+
if (!PushObject(value, type, return_ptr)) [[unlikely]]
|
|
1059
1040
|
return;
|
|
1060
1041
|
out_reg->rax = (uint64_t)return_ptr;
|
|
1061
1042
|
} else {
|
|
1062
|
-
PushObject(value, type, (uint8_t *)&out_reg->rax)
|
|
1043
|
+
if (!PushObject(value, type, (uint8_t *)&out_reg->rax)) [[unlikely]]
|
|
1044
|
+
return;
|
|
1063
1045
|
}
|
|
1064
1046
|
} break;
|
|
1065
1047
|
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|