koffi 1.0.1 → 1.0.2
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/CMakeLists.txt +12 -11
- package/build/qemu/1.0.2/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/1.0.2/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/1.0.2/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/1.0.2/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/1.0.2/koffi_linux_arm.tar.gz +0 -0
- package/build/qemu/1.0.2/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/1.0.2/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/1.0.2/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/1.0.2/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/1.0.2/koffi_win32_x64.tar.gz +0 -0
- package/package.json +8 -4
- package/qemu/qemu.js +794 -0
- package/qemu/registry/machines.json +415 -0
- package/qemu/registry/sha256sum.txt +45 -0
- package/src/{call_arm32.cc → abi_arm32.cc} +76 -50
- package/src/{call_arm32_fwd.S → abi_arm32_fwd.S} +0 -0
- package/src/{call_arm64.cc → abi_arm64.cc} +79 -51
- package/src/{call_arm64_fwd.S → abi_arm64_fwd.S} +0 -0
- package/src/{call_x64_sysv.cc → abi_x64_sysv.cc} +77 -49
- package/src/{call_x64_sysv_fwd.S → abi_x64_sysv_fwd.S} +0 -0
- package/src/{call_x64_win.cc → abi_x64_win.cc} +71 -47
- package/src/{call_x64_win_fwd.asm → abi_x64_win_fwd.asm} +0 -0
- package/src/{call_x86.cc → abi_x86.cc} +74 -56
- package/src/{call_x86_fwd.S → abi_x86_fwd.S} +0 -0
- package/src/{call_x86_fwd.asm → abi_x86_fwd.asm} +0 -0
- package/src/call.cc +228 -0
- package/src/call.hh +96 -4
- package/src/ffi.cc +7 -2
- package/src/ffi.hh +2 -0
- package/src/util.cc +11 -157
- package/src/util.hh +0 -91
- package/test/CMakeLists.txt +1 -0
- package/test/misc.c +289 -0
- package/test/misc.def +3 -0
- package/test/misc.js +180 -0
- package/test/raylib.js +165 -0
- package/test/sqlite.js +104 -0
- package/build/qemu/1.0.1/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_linux_arm.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_win32_x64.tar.gz +0 -0
|
File without changes
|
|
@@ -87,6 +87,7 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
|
|
|
87
87
|
case PrimitiveKind::Int64:
|
|
88
88
|
case PrimitiveKind::UInt64:
|
|
89
89
|
case PrimitiveKind::String:
|
|
90
|
+
case PrimitiveKind::String16:
|
|
90
91
|
case PrimitiveKind::Pointer: {
|
|
91
92
|
#ifdef __APPLE__
|
|
92
93
|
if (param.variadic)
|
|
@@ -215,11 +216,8 @@ static Napi::Object PopHFA(napi_env env, const uint8_t *ptr, const TypeInfo *typ
|
|
|
215
216
|
return obj;
|
|
216
217
|
}
|
|
217
218
|
|
|
218
|
-
Napi::Value
|
|
219
|
+
Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
|
|
219
220
|
{
|
|
220
|
-
Napi::Env env = info.Env();
|
|
221
|
-
CallData call(env, instance, func);
|
|
222
|
-
|
|
223
221
|
// Sanity checks
|
|
224
222
|
if (info.Length() < (uint32_t)func->parameters.len) {
|
|
225
223
|
ThrowError<Napi::TypeError>(env, "Expected %1 arguments, got %2", func->parameters.len, info.Length());
|
|
@@ -232,14 +230,14 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
232
230
|
uint64_t *vec_ptr = nullptr;
|
|
233
231
|
|
|
234
232
|
// Return through registers unless it's too big
|
|
235
|
-
if (RG_UNLIKELY(!
|
|
233
|
+
if (RG_UNLIKELY(!AllocStack(func->args_size, 16, &args_ptr)))
|
|
236
234
|
return env.Null();
|
|
237
|
-
if (RG_UNLIKELY(!
|
|
235
|
+
if (RG_UNLIKELY(!AllocStack(8 * 8, 8, &vec_ptr)))
|
|
238
236
|
return env.Null();
|
|
239
|
-
if (RG_UNLIKELY(!
|
|
237
|
+
if (RG_UNLIKELY(!AllocStack(9 * 8, 8, &gpr_ptr)))
|
|
240
238
|
return env.Null();
|
|
241
239
|
if (func->ret.use_memory) {
|
|
242
|
-
if (RG_UNLIKELY(!
|
|
240
|
+
if (RG_UNLIKELY(!AllocHeap(func->ret.type->size, 16, &return_ptr)))
|
|
243
241
|
return env.Null();
|
|
244
242
|
gpr_ptr[8] = (uint64_t)return_ptr;
|
|
245
243
|
}
|
|
@@ -341,7 +339,7 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
341
339
|
case PrimitiveKind::String: {
|
|
342
340
|
const char *str;
|
|
343
341
|
if (RG_LIKELY(value.IsString())) {
|
|
344
|
-
str =
|
|
342
|
+
str = PushString(value);
|
|
345
343
|
if (RG_UNLIKELY(!str))
|
|
346
344
|
return env.Null();
|
|
347
345
|
} else if (IsNullOrUndefined(value)) {
|
|
@@ -359,6 +357,27 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
359
357
|
args_ptr += 8;
|
|
360
358
|
}
|
|
361
359
|
} break;
|
|
360
|
+
case PrimitiveKind::String16: {
|
|
361
|
+
const char16_t *str16;
|
|
362
|
+
if (RG_LIKELY(value.IsString())) {
|
|
363
|
+
str16 = PushString16(value);
|
|
364
|
+
if (RG_UNLIKELY(!str16))
|
|
365
|
+
return env.Null();
|
|
366
|
+
} else if (IsNullOrUndefined(value)) {
|
|
367
|
+
str16 = nullptr;
|
|
368
|
+
} else {
|
|
369
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected string", GetValueType(instance, value), i + 1);
|
|
370
|
+
return env.Null();
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (RG_LIKELY(param.gpr_count)) {
|
|
374
|
+
*(gpr_ptr++) = (uint64_t)str16;
|
|
375
|
+
} else {
|
|
376
|
+
args_ptr = AlignUp(args_ptr, 8);
|
|
377
|
+
*(uint64_t *)args_ptr = (uint64_t)str16;
|
|
378
|
+
args_ptr += 8;
|
|
379
|
+
}
|
|
380
|
+
} break;
|
|
362
381
|
case PrimitiveKind::Pointer: {
|
|
363
382
|
uint8_t *ptr;
|
|
364
383
|
|
|
@@ -367,11 +386,11 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
367
386
|
} else if (IsObject(value) && param.type->ref->primitive == PrimitiveKind::Record) {
|
|
368
387
|
Napi::Object obj = value.As<Napi::Object>();
|
|
369
388
|
|
|
370
|
-
if (RG_UNLIKELY(!
|
|
389
|
+
if (RG_UNLIKELY(!AllocHeap(param.type->ref->size, 16, &ptr)))
|
|
371
390
|
return env.Null();
|
|
372
391
|
|
|
373
392
|
if (param.directions & 1) {
|
|
374
|
-
if (!
|
|
393
|
+
if (!PushObject(obj, param.type->ref, ptr))
|
|
375
394
|
return env.Null();
|
|
376
395
|
} else {
|
|
377
396
|
memset(ptr, 0, param.type->size);
|
|
@@ -412,18 +431,18 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
412
431
|
if (param.gpr_count) {
|
|
413
432
|
RG_ASSERT(param.type->align <= 8);
|
|
414
433
|
|
|
415
|
-
if (!
|
|
434
|
+
if (!PushObject(obj, param.type, (uint8_t *)gpr_ptr))
|
|
416
435
|
return env.Null();
|
|
417
436
|
gpr_ptr += param.gpr_count;
|
|
418
437
|
} else if (param.type->size) {
|
|
419
438
|
args_ptr = AlignUp(args_ptr, 8);
|
|
420
|
-
if (!
|
|
439
|
+
if (!PushObject(obj, param.type, args_ptr))
|
|
421
440
|
return env.Null();
|
|
422
441
|
args_ptr += AlignLen(param.type->size, 8);
|
|
423
442
|
}
|
|
424
443
|
} else {
|
|
425
444
|
uint8_t *ptr;
|
|
426
|
-
if (RG_UNLIKELY(!
|
|
445
|
+
if (RG_UNLIKELY(!AllocHeap(param.type->size, 16, &ptr)))
|
|
427
446
|
return env.Null();
|
|
428
447
|
|
|
429
448
|
if (param.gpr_count) {
|
|
@@ -437,7 +456,7 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
437
456
|
args_ptr += 8;
|
|
438
457
|
}
|
|
439
458
|
|
|
440
|
-
if (!
|
|
459
|
+
if (!PushObject(obj, param.type, ptr))
|
|
441
460
|
return env.Null();
|
|
442
461
|
}
|
|
443
462
|
} break;
|
|
@@ -445,30 +464,69 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
445
464
|
}
|
|
446
465
|
|
|
447
466
|
if (instance->debug) {
|
|
448
|
-
|
|
467
|
+
DumpDebug();
|
|
449
468
|
}
|
|
450
469
|
|
|
451
470
|
#define PERFORM_CALL(Suffix) \
|
|
452
471
|
([&]() { \
|
|
453
|
-
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func,
|
|
454
|
-
: ForwardCall ## Suffix(func->func,
|
|
472
|
+
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func, GetSP()) \
|
|
473
|
+
: ForwardCall ## Suffix(func->func, GetSP())); \
|
|
455
474
|
PopOutArguments(out_objects); \
|
|
456
475
|
return ret; \
|
|
457
476
|
})()
|
|
458
477
|
|
|
459
478
|
// Execute and convert return value
|
|
460
479
|
switch (func->ret.type->primitive) {
|
|
480
|
+
case PrimitiveKind::Void: {
|
|
481
|
+
PERFORM_CALL(GG);
|
|
482
|
+
return env.Null();
|
|
483
|
+
} break;
|
|
484
|
+
case PrimitiveKind::Bool: {
|
|
485
|
+
X0X1Ret ret = PERFORM_CALL(GG);
|
|
486
|
+
return Napi::Boolean::New(env, ret.x0);
|
|
487
|
+
} break;
|
|
488
|
+
case PrimitiveKind::Int8:
|
|
489
|
+
case PrimitiveKind::UInt8:
|
|
490
|
+
case PrimitiveKind::Int16:
|
|
491
|
+
case PrimitiveKind::UInt16:
|
|
492
|
+
case PrimitiveKind::Int32:
|
|
493
|
+
case PrimitiveKind::UInt32: {
|
|
494
|
+
X0X1Ret ret = PERFORM_CALL(GG);
|
|
495
|
+
return Napi::Number::New(env, (double)ret.x0);
|
|
496
|
+
} break;
|
|
497
|
+
case PrimitiveKind::Int64: {
|
|
498
|
+
X0X1Ret ret = PERFORM_CALL(GG);
|
|
499
|
+
return Napi::BigInt::New(env, (int64_t)ret.x0);
|
|
500
|
+
} break;
|
|
501
|
+
case PrimitiveKind::UInt64: {
|
|
502
|
+
X0X1Ret ret = PERFORM_CALL(GG);
|
|
503
|
+
return Napi::BigInt::New(env, ret.x0);
|
|
504
|
+
} break;
|
|
461
505
|
case PrimitiveKind::Float32: {
|
|
462
506
|
float f = PERFORM_CALL(F);
|
|
463
|
-
|
|
464
507
|
return Napi::Number::New(env, (double)f);
|
|
465
508
|
} break;
|
|
466
|
-
|
|
467
509
|
case PrimitiveKind::Float64: {
|
|
468
510
|
HfaRet ret = PERFORM_CALL(DDDD);
|
|
469
|
-
|
|
470
511
|
return Napi::Number::New(env, (double)ret.d0);
|
|
471
512
|
} break;
|
|
513
|
+
case PrimitiveKind::String: {
|
|
514
|
+
X0X1Ret ret = PERFORM_CALL(GG);
|
|
515
|
+
return Napi::String::New(env, (const char *)ret.x0);
|
|
516
|
+
} break;
|
|
517
|
+
case PrimitiveKind::String16: {
|
|
518
|
+
X0X1Ret ret = PERFORM_CALL(GG);
|
|
519
|
+
return Napi::String::New(env, (const char16_t *)ret.x0);
|
|
520
|
+
} break;
|
|
521
|
+
case PrimitiveKind::Pointer: {
|
|
522
|
+
X0X1Ret ret = PERFORM_CALL(GG);
|
|
523
|
+
void *ptr = (void *)ret.x0;
|
|
524
|
+
|
|
525
|
+
Napi::External<void> external = Napi::External<void>::New(env, ptr);
|
|
526
|
+
SetValueTag(instance, external, func->ret.type);
|
|
527
|
+
|
|
528
|
+
return external;
|
|
529
|
+
} break;
|
|
472
530
|
|
|
473
531
|
case PrimitiveKind::Record: {
|
|
474
532
|
if (func->ret.gpr_count) {
|
|
@@ -496,36 +554,6 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
496
554
|
return obj;
|
|
497
555
|
}
|
|
498
556
|
} break;
|
|
499
|
-
|
|
500
|
-
default: {
|
|
501
|
-
X0X1Ret ret = PERFORM_CALL(GG);
|
|
502
|
-
|
|
503
|
-
switch (func->ret.type->primitive) {
|
|
504
|
-
case PrimitiveKind::Void: return env.Null();
|
|
505
|
-
case PrimitiveKind::Bool: return Napi::Boolean::New(env, ret.x0);
|
|
506
|
-
case PrimitiveKind::Int8: return Napi::Number::New(env, (double)ret.x0);
|
|
507
|
-
case PrimitiveKind::UInt8: return Napi::Number::New(env, (double)ret.x0);
|
|
508
|
-
case PrimitiveKind::Int16: return Napi::Number::New(env, (double)ret.x0);
|
|
509
|
-
case PrimitiveKind::UInt16: return Napi::Number::New(env, (double)ret.x0);
|
|
510
|
-
case PrimitiveKind::Int32: return Napi::Number::New(env, (double)ret.x0);
|
|
511
|
-
case PrimitiveKind::UInt32: return Napi::Number::New(env, (double)ret.x0);
|
|
512
|
-
case PrimitiveKind::Int64: return Napi::BigInt::New(env, (int64_t)ret.x0);
|
|
513
|
-
case PrimitiveKind::UInt64: return Napi::BigInt::New(env, ret.x0);
|
|
514
|
-
case PrimitiveKind::Float32: { RG_UNREACHABLE(); } break;
|
|
515
|
-
case PrimitiveKind::Float64: { RG_UNREACHABLE(); } break;
|
|
516
|
-
case PrimitiveKind::String: return Napi::String::New(env, (const char *)ret.x0);
|
|
517
|
-
case PrimitiveKind::Pointer: {
|
|
518
|
-
void *ptr = (void *)ret.x0;
|
|
519
|
-
|
|
520
|
-
Napi::External<void> external = Napi::External<void>::New(env, ptr);
|
|
521
|
-
SetValueTag(instance, external, func->ret.type);
|
|
522
|
-
|
|
523
|
-
return external;
|
|
524
|
-
} break;
|
|
525
|
-
|
|
526
|
-
case PrimitiveKind::Record: { RG_UNREACHABLE(); } break;
|
|
527
|
-
}
|
|
528
|
-
} break;
|
|
529
557
|
}
|
|
530
558
|
|
|
531
559
|
#undef PERFORM_CALL
|
|
File without changes
|
|
@@ -93,6 +93,7 @@ static Size ClassifyType(const TypeInfo *type, Size offset, Span<RegisterClass>
|
|
|
93
93
|
case PrimitiveKind::Int64:
|
|
94
94
|
case PrimitiveKind::UInt64:
|
|
95
95
|
case PrimitiveKind::String:
|
|
96
|
+
case PrimitiveKind::String16:
|
|
96
97
|
case PrimitiveKind::Pointer: {
|
|
97
98
|
classes[0] = MergeClasses(classes[0], RegisterClass::Integer);
|
|
98
99
|
return 1;
|
|
@@ -180,11 +181,8 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
|
|
|
180
181
|
return true;
|
|
181
182
|
}
|
|
182
183
|
|
|
183
|
-
Napi::Value
|
|
184
|
+
Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
|
|
184
185
|
{
|
|
185
|
-
Napi::Env env = info.Env();
|
|
186
|
-
CallData call(env, instance, func);
|
|
187
|
-
|
|
188
186
|
// Sanity checks
|
|
189
187
|
if (info.Length() < (uint32_t)func->parameters.len) {
|
|
190
188
|
ThrowError<Napi::TypeError>(env, "Expected %1 arguments, got %2", func->parameters.len, info.Length());
|
|
@@ -197,14 +195,14 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
197
195
|
uint64_t *xmm_ptr = nullptr;
|
|
198
196
|
|
|
199
197
|
// Return through registers unless it's too big
|
|
200
|
-
if (RG_UNLIKELY(!
|
|
198
|
+
if (RG_UNLIKELY(!AllocStack(func->args_size, 16, &args_ptr)))
|
|
201
199
|
return env.Null();
|
|
202
|
-
if (RG_UNLIKELY(!
|
|
200
|
+
if (RG_UNLIKELY(!AllocStack(8 * 8, 8, &xmm_ptr)))
|
|
203
201
|
return env.Null();
|
|
204
|
-
if (RG_UNLIKELY(!
|
|
202
|
+
if (RG_UNLIKELY(!AllocStack(6 * 8, 8, &gpr_ptr)))
|
|
205
203
|
return env.Null();
|
|
206
204
|
if (func->ret.use_memory) {
|
|
207
|
-
if (RG_UNLIKELY(!
|
|
205
|
+
if (RG_UNLIKELY(!AllocHeap(func->ret.type->size, 16, &return_ptr)))
|
|
208
206
|
return env.Null();
|
|
209
207
|
*(uint8_t **)(gpr_ptr++) = return_ptr;
|
|
210
208
|
}
|
|
@@ -294,7 +292,7 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
294
292
|
case PrimitiveKind::String: {
|
|
295
293
|
const char *str;
|
|
296
294
|
if (RG_LIKELY(value.IsString())) {
|
|
297
|
-
str =
|
|
295
|
+
str = PushString(value);
|
|
298
296
|
if (RG_UNLIKELY(!str))
|
|
299
297
|
return env.Null();
|
|
300
298
|
} else if (IsNullOrUndefined(value)) {
|
|
@@ -312,6 +310,27 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
312
310
|
args_ptr += 8;
|
|
313
311
|
}
|
|
314
312
|
} break;
|
|
313
|
+
case PrimitiveKind::String16: {
|
|
314
|
+
const char16_t *str16;
|
|
315
|
+
if (RG_LIKELY(value.IsString())) {
|
|
316
|
+
str16 = PushString16(value);
|
|
317
|
+
if (RG_UNLIKELY(!str16))
|
|
318
|
+
return env.Null();
|
|
319
|
+
} else if (IsNullOrUndefined(value)) {
|
|
320
|
+
str16 = nullptr;
|
|
321
|
+
} else {
|
|
322
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected string", GetValueType(instance, value), i + 1);
|
|
323
|
+
return env.Null();
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (RG_LIKELY(param.gpr_count)) {
|
|
327
|
+
*(gpr_ptr++) = (uint64_t)str16;
|
|
328
|
+
} else {
|
|
329
|
+
args_ptr = AlignUp(args_ptr, 8);
|
|
330
|
+
*(uint64_t *)args_ptr = (uint64_t)str16;
|
|
331
|
+
args_ptr += 8;
|
|
332
|
+
}
|
|
333
|
+
} break;
|
|
315
334
|
case PrimitiveKind::Pointer: {
|
|
316
335
|
uint8_t *ptr;
|
|
317
336
|
|
|
@@ -320,11 +339,11 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
320
339
|
} else if (IsObject(value) && param.type->ref->primitive == PrimitiveKind::Record) {
|
|
321
340
|
Napi::Object obj = value.As<Napi::Object>();
|
|
322
341
|
|
|
323
|
-
if (RG_UNLIKELY(!
|
|
342
|
+
if (RG_UNLIKELY(!AllocHeap(param.type->ref->size, 16, &ptr)))
|
|
324
343
|
return env.Null();
|
|
325
344
|
|
|
326
345
|
if (param.directions & 1) {
|
|
327
|
-
if (!
|
|
346
|
+
if (!PushObject(obj, param.type->ref, ptr))
|
|
328
347
|
return env.Null();
|
|
329
348
|
} else {
|
|
330
349
|
memset(ptr, 0, param.type->size);
|
|
@@ -361,7 +380,7 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
361
380
|
RG_ASSERT(param.type->size <= 16);
|
|
362
381
|
|
|
363
382
|
uint64_t buf[2] = {};
|
|
364
|
-
if (!
|
|
383
|
+
if (!PushObject(obj, param.type, (uint8_t *)buf))
|
|
365
384
|
return env.Null();
|
|
366
385
|
|
|
367
386
|
if (param.gpr_first) {
|
|
@@ -385,7 +404,7 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
385
404
|
}
|
|
386
405
|
} else if (param.use_memory) {
|
|
387
406
|
args_ptr = AlignUp(args_ptr, param.type->align);
|
|
388
|
-
if (!
|
|
407
|
+
if (!PushObject(obj, param.type, args_ptr))
|
|
389
408
|
return env.Null();
|
|
390
409
|
args_ptr += AlignLen(param.type->size, 8);
|
|
391
410
|
}
|
|
@@ -394,30 +413,69 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
394
413
|
}
|
|
395
414
|
|
|
396
415
|
if (instance->debug) {
|
|
397
|
-
|
|
416
|
+
DumpDebug();
|
|
398
417
|
}
|
|
399
418
|
|
|
400
419
|
#define PERFORM_CALL(Suffix) \
|
|
401
420
|
([&]() { \
|
|
402
|
-
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func,
|
|
403
|
-
: ForwardCall ## Suffix(func->func,
|
|
421
|
+
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func, GetSP()) \
|
|
422
|
+
: ForwardCall ## Suffix(func->func, GetSP())); \
|
|
404
423
|
PopOutArguments(out_objects); \
|
|
405
424
|
return ret; \
|
|
406
425
|
})()
|
|
407
426
|
|
|
408
427
|
// Execute and convert return value
|
|
409
428
|
switch (func->ret.type->primitive) {
|
|
429
|
+
case PrimitiveKind::Void: {
|
|
430
|
+
PERFORM_CALL(GG);
|
|
431
|
+
return env.Null();
|
|
432
|
+
} break;
|
|
433
|
+
case PrimitiveKind::Bool: {
|
|
434
|
+
RaxRdxRet ret = PERFORM_CALL(GG);
|
|
435
|
+
return Napi::Boolean::New(env, ret.rax);
|
|
436
|
+
} break;
|
|
437
|
+
case PrimitiveKind::Int8:
|
|
438
|
+
case PrimitiveKind::UInt8:
|
|
439
|
+
case PrimitiveKind::Int16:
|
|
440
|
+
case PrimitiveKind::UInt16:
|
|
441
|
+
case PrimitiveKind::Int32:
|
|
442
|
+
case PrimitiveKind::UInt32: {
|
|
443
|
+
RaxRdxRet ret = PERFORM_CALL(GG);
|
|
444
|
+
return Napi::Number::New(env, (double)ret.rax);
|
|
445
|
+
} break;
|
|
446
|
+
case PrimitiveKind::Int64: {
|
|
447
|
+
RaxRdxRet ret = PERFORM_CALL(GG);
|
|
448
|
+
return Napi::BigInt::New(env, (int64_t)ret.rax);
|
|
449
|
+
} break;
|
|
450
|
+
case PrimitiveKind::UInt64: {
|
|
451
|
+
RaxRdxRet ret = PERFORM_CALL(GG);
|
|
452
|
+
return Napi::BigInt::New(env, ret.rax);
|
|
453
|
+
} break;
|
|
410
454
|
case PrimitiveKind::Float32: {
|
|
411
455
|
float f = PERFORM_CALL(F);
|
|
412
|
-
|
|
413
456
|
return Napi::Number::New(env, (double)f);
|
|
414
457
|
} break;
|
|
415
|
-
|
|
416
458
|
case PrimitiveKind::Float64: {
|
|
417
459
|
Xmm0RaxRet ret = PERFORM_CALL(DG);
|
|
418
|
-
|
|
419
460
|
return Napi::Number::New(env, ret.xmm0);
|
|
420
461
|
} break;
|
|
462
|
+
case PrimitiveKind::String: {
|
|
463
|
+
RaxRdxRet ret = PERFORM_CALL(GG);
|
|
464
|
+
return Napi::String::New(env, (const char *)ret.rax);
|
|
465
|
+
} break;
|
|
466
|
+
case PrimitiveKind::String16: {
|
|
467
|
+
RaxRdxRet ret = PERFORM_CALL(GG);
|
|
468
|
+
return Napi::String::New(env, (const char16_t *)ret.rax);
|
|
469
|
+
} break;
|
|
470
|
+
case PrimitiveKind::Pointer: {
|
|
471
|
+
RaxRdxRet ret = PERFORM_CALL(GG);
|
|
472
|
+
void *ptr = (void *)ret.rax;
|
|
473
|
+
|
|
474
|
+
Napi::External<void> external = Napi::External<void>::New(env, ptr);
|
|
475
|
+
SetValueTag(instance, external, func->ret.type);
|
|
476
|
+
|
|
477
|
+
return external;
|
|
478
|
+
} break;
|
|
421
479
|
|
|
422
480
|
case PrimitiveKind::Record: {
|
|
423
481
|
if (func->ret.gpr_first && !func->ret.xmm_count) {
|
|
@@ -450,36 +508,6 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
450
508
|
return obj;
|
|
451
509
|
}
|
|
452
510
|
} break;
|
|
453
|
-
|
|
454
|
-
default: {
|
|
455
|
-
RaxRdxRet ret = PERFORM_CALL(GG);
|
|
456
|
-
|
|
457
|
-
switch (func->ret.type->primitive) {
|
|
458
|
-
case PrimitiveKind::Void: return env.Null();
|
|
459
|
-
case PrimitiveKind::Bool: return Napi::Boolean::New(env, ret.rax);
|
|
460
|
-
case PrimitiveKind::Int8: return Napi::Number::New(env, (double)ret.rax);
|
|
461
|
-
case PrimitiveKind::UInt8: return Napi::Number::New(env, (double)ret.rax);
|
|
462
|
-
case PrimitiveKind::Int16: return Napi::Number::New(env, (double)ret.rax);
|
|
463
|
-
case PrimitiveKind::UInt16: return Napi::Number::New(env, (double)ret.rax);
|
|
464
|
-
case PrimitiveKind::Int32: return Napi::Number::New(env, (double)ret.rax);
|
|
465
|
-
case PrimitiveKind::UInt32: return Napi::Number::New(env, (double)ret.rax);
|
|
466
|
-
case PrimitiveKind::Int64: return Napi::BigInt::New(env, (int64_t)ret.rax);
|
|
467
|
-
case PrimitiveKind::UInt64: return Napi::BigInt::New(env, ret.rax);
|
|
468
|
-
case PrimitiveKind::Float32: { RG_UNREACHABLE(); } break;
|
|
469
|
-
case PrimitiveKind::Float64: { RG_UNREACHABLE(); } break;
|
|
470
|
-
case PrimitiveKind::String: return Napi::String::New(env, (const char *)ret.rax);
|
|
471
|
-
case PrimitiveKind::Pointer: {
|
|
472
|
-
void *ptr = (void *)ret.rax;
|
|
473
|
-
|
|
474
|
-
Napi::External<void> external = Napi::External<void>::New(env, ptr);
|
|
475
|
-
SetValueTag(instance, external, func->ret.type);
|
|
476
|
-
|
|
477
|
-
return external;
|
|
478
|
-
} break;
|
|
479
|
-
|
|
480
|
-
case PrimitiveKind::Record: { RG_UNREACHABLE(); } break;
|
|
481
|
-
}
|
|
482
|
-
} break;
|
|
483
511
|
}
|
|
484
512
|
|
|
485
513
|
#undef PERFORM_CALL
|
|
File without changes
|
|
@@ -51,11 +51,8 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
|
|
|
51
51
|
return true;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
Napi::Value
|
|
54
|
+
Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
|
|
55
55
|
{
|
|
56
|
-
Napi::Env env = info.Env();
|
|
57
|
-
CallData call(env, instance, func);
|
|
58
|
-
|
|
59
56
|
// Sanity checks
|
|
60
57
|
if (info.Length() < (uint32_t)func->parameters.len) {
|
|
61
58
|
ThrowError<Napi::TypeError>(env, "Expected %1 arguments, got %2", func->parameters.len, info.Length());
|
|
@@ -66,10 +63,10 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
66
63
|
uint64_t *args_ptr = nullptr;
|
|
67
64
|
|
|
68
65
|
// Pass return value in register or through memory
|
|
69
|
-
if (RG_UNLIKELY(!
|
|
66
|
+
if (RG_UNLIKELY(!AllocStack(func->args_size, 16, &args_ptr)))
|
|
70
67
|
return env.Null();
|
|
71
68
|
if (!func->ret.regular) {
|
|
72
|
-
if (RG_UNLIKELY(!
|
|
69
|
+
if (RG_UNLIKELY(!AllocHeap(func->ret.type->size, 16, &return_ptr)))
|
|
73
70
|
return env.Null();
|
|
74
71
|
*(uint8_t **)(args_ptr++) = return_ptr;
|
|
75
72
|
}
|
|
@@ -133,7 +130,7 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
133
130
|
case PrimitiveKind::String: {
|
|
134
131
|
const char *str;
|
|
135
132
|
if (RG_LIKELY(value.IsString())) {
|
|
136
|
-
str =
|
|
133
|
+
str = PushString(value);
|
|
137
134
|
if (RG_UNLIKELY(!str))
|
|
138
135
|
return env.Null();
|
|
139
136
|
} else if (IsNullOrUndefined(value)) {
|
|
@@ -145,7 +142,21 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
145
142
|
|
|
146
143
|
*(const char **)(args_ptr++) = str;
|
|
147
144
|
} break;
|
|
145
|
+
case PrimitiveKind::String16: {
|
|
146
|
+
const char16_t *str16;
|
|
147
|
+
if (RG_LIKELY(value.IsString())) {
|
|
148
|
+
str16 = PushString16(value);
|
|
149
|
+
if (RG_UNLIKELY(!str16))
|
|
150
|
+
return env.Null();
|
|
151
|
+
} else if (IsNullOrUndefined(value)) {
|
|
152
|
+
str16 = nullptr;
|
|
153
|
+
} else {
|
|
154
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected string", GetValueType(instance, value), i + 1);
|
|
155
|
+
return env.Null();
|
|
156
|
+
}
|
|
148
157
|
|
|
158
|
+
*(const char16_t **)(args_ptr++) = str16;
|
|
159
|
+
} break;
|
|
149
160
|
case PrimitiveKind::Pointer: {
|
|
150
161
|
uint8_t *ptr;
|
|
151
162
|
|
|
@@ -154,11 +165,11 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
154
165
|
} else if (IsObject(value) && param.type->ref->primitive == PrimitiveKind::Record) {
|
|
155
166
|
Napi::Object obj = value.As<Napi::Object>();
|
|
156
167
|
|
|
157
|
-
if (RG_UNLIKELY(!
|
|
168
|
+
if (RG_UNLIKELY(!AllocHeap(param.type->ref->size, 16, &ptr)))
|
|
158
169
|
return env.Null();
|
|
159
170
|
|
|
160
171
|
if (param.directions & 1) {
|
|
161
|
-
if (!
|
|
172
|
+
if (!PushObject(obj, param.type->ref, ptr))
|
|
162
173
|
return env.Null();
|
|
163
174
|
} else {
|
|
164
175
|
memset(ptr, 0, param.type->size);
|
|
@@ -187,76 +198,89 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
187
198
|
if (param.regular) {
|
|
188
199
|
ptr = (uint8_t *)(args_ptr++);
|
|
189
200
|
} else {
|
|
190
|
-
if (RG_UNLIKELY(!
|
|
201
|
+
if (RG_UNLIKELY(!AllocHeap(param.type->size, 16, &ptr)))
|
|
191
202
|
return env.Null();
|
|
192
203
|
*(uint8_t **)(args_ptr++) = ptr;
|
|
193
204
|
}
|
|
194
205
|
|
|
195
206
|
Napi::Object obj = value.As<Napi::Object>();
|
|
196
|
-
if (!
|
|
207
|
+
if (!PushObject(obj, param.type, ptr))
|
|
197
208
|
return env.Null();
|
|
198
209
|
} break;
|
|
199
210
|
}
|
|
200
211
|
}
|
|
201
212
|
|
|
202
213
|
if (instance->debug) {
|
|
203
|
-
|
|
214
|
+
DumpDebug();
|
|
204
215
|
}
|
|
205
216
|
|
|
206
217
|
#define PERFORM_CALL(Suffix) \
|
|
207
218
|
([&]() { \
|
|
208
|
-
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func,
|
|
209
|
-
: ForwardCall ## Suffix(func->func,
|
|
219
|
+
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func, GetSP()) \
|
|
220
|
+
: ForwardCall ## Suffix(func->func, GetSP())); \
|
|
210
221
|
PopOutArguments(out_objects); \
|
|
211
222
|
return ret; \
|
|
212
223
|
})()
|
|
213
224
|
|
|
214
225
|
// Execute and convert return value
|
|
215
226
|
switch (func->ret.type->primitive) {
|
|
227
|
+
case PrimitiveKind::Void: {
|
|
228
|
+
PERFORM_CALL(G);
|
|
229
|
+
return env.Null();
|
|
230
|
+
} break;
|
|
231
|
+
case PrimitiveKind::Bool: {
|
|
232
|
+
uint64_t rax = PERFORM_CALL(G);
|
|
233
|
+
return Napi::Boolean::New(env, rax);
|
|
234
|
+
} break;
|
|
235
|
+
case PrimitiveKind::Int8:
|
|
236
|
+
case PrimitiveKind::UInt8:
|
|
237
|
+
case PrimitiveKind::Int16:
|
|
238
|
+
case PrimitiveKind::UInt16:
|
|
239
|
+
case PrimitiveKind::Int32:
|
|
240
|
+
case PrimitiveKind::UInt32: {
|
|
241
|
+
uint64_t rax = PERFORM_CALL(G);
|
|
242
|
+
return Napi::Number::New(env, (double)rax);
|
|
243
|
+
} break;
|
|
244
|
+
case PrimitiveKind::Int64: {
|
|
245
|
+
uint64_t rax = PERFORM_CALL(G);
|
|
246
|
+
return Napi::BigInt::New(env, (int64_t)rax);
|
|
247
|
+
} break;
|
|
248
|
+
case PrimitiveKind::UInt64: {
|
|
249
|
+
uint64_t rax = PERFORM_CALL(G);
|
|
250
|
+
return Napi::BigInt::New(env, rax);
|
|
251
|
+
} break;
|
|
216
252
|
case PrimitiveKind::Float32: {
|
|
217
253
|
float f = PERFORM_CALL(F);
|
|
218
|
-
|
|
219
254
|
return Napi::Number::New(env, (double)f);
|
|
220
255
|
} break;
|
|
221
|
-
|
|
222
256
|
case PrimitiveKind::Float64: {
|
|
223
257
|
double d = PERFORM_CALL(D);
|
|
224
|
-
|
|
225
258
|
return Napi::Number::New(env, d);
|
|
226
259
|
} break;
|
|
260
|
+
case PrimitiveKind::String: {
|
|
261
|
+
uint64_t rax = PERFORM_CALL(G);
|
|
262
|
+
return Napi::String::New(env, (const char *)rax);
|
|
263
|
+
} break;
|
|
264
|
+
case PrimitiveKind::String16: {
|
|
265
|
+
uint64_t rax = PERFORM_CALL(G);
|
|
266
|
+
return Napi::String::New(env, (const char16_t *)rax);
|
|
267
|
+
} break;
|
|
268
|
+
case PrimitiveKind::Pointer: {
|
|
269
|
+
uint64_t rax = PERFORM_CALL(G);
|
|
270
|
+
void *ptr = (void *)rax;
|
|
271
|
+
|
|
272
|
+
Napi::External<void> external = Napi::External<void>::New(env, ptr);
|
|
273
|
+
SetValueTag(instance, external, func->ret.type);
|
|
274
|
+
|
|
275
|
+
return external;
|
|
276
|
+
} break;
|
|
227
277
|
|
|
228
|
-
|
|
278
|
+
case PrimitiveKind::Record: {
|
|
229
279
|
uint64_t rax = PERFORM_CALL(G);
|
|
280
|
+
const uint8_t *ptr = return_ptr ? return_ptr : (const uint8_t *)&rax;
|
|
230
281
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
case PrimitiveKind::Bool: return Napi::Boolean::New(env, rax);
|
|
234
|
-
case PrimitiveKind::Int8: return Napi::Number::New(env, (double)rax);
|
|
235
|
-
case PrimitiveKind::UInt8: return Napi::Number::New(env, (double)rax);
|
|
236
|
-
case PrimitiveKind::Int16: return Napi::Number::New(env, (double)rax);
|
|
237
|
-
case PrimitiveKind::UInt16: return Napi::Number::New(env, (double)rax);
|
|
238
|
-
case PrimitiveKind::Int32: return Napi::Number::New(env, (double)rax);
|
|
239
|
-
case PrimitiveKind::UInt32: return Napi::Number::New(env, (double)rax);
|
|
240
|
-
case PrimitiveKind::Int64: return Napi::BigInt::New(env, (int64_t)rax);
|
|
241
|
-
case PrimitiveKind::UInt64: return Napi::BigInt::New(env, rax);
|
|
242
|
-
case PrimitiveKind::Float32: { RG_UNREACHABLE(); } break;
|
|
243
|
-
case PrimitiveKind::Float64: { RG_UNREACHABLE(); } break;
|
|
244
|
-
case PrimitiveKind::String: return Napi::String::New(env, (const char *)rax);
|
|
245
|
-
case PrimitiveKind::Pointer: {
|
|
246
|
-
void *ptr = (void *)rax;
|
|
247
|
-
|
|
248
|
-
Napi::External<void> external = Napi::External<void>::New(env, ptr);
|
|
249
|
-
SetValueTag(instance, external, func->ret.type);
|
|
250
|
-
|
|
251
|
-
return external;
|
|
252
|
-
} break;
|
|
253
|
-
|
|
254
|
-
case PrimitiveKind::Record: {
|
|
255
|
-
const uint8_t *ptr = return_ptr ? return_ptr : (const uint8_t *)&rax;
|
|
256
|
-
Napi::Object obj = PopObject(env, ptr, func->ret.type);
|
|
257
|
-
return obj;
|
|
258
|
-
} break;
|
|
259
|
-
}
|
|
282
|
+
Napi::Object obj = PopObject(env, ptr, func->ret.type);
|
|
283
|
+
return obj;
|
|
260
284
|
} break;
|
|
261
285
|
}
|
|
262
286
|
|
|
File without changes
|