koffi 1.0.2 → 1.0.5

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.
Files changed (36) hide show
  1. package/README.md +24 -21
  2. package/build/qemu/1.0.5/koffi_darwin_x64.tar.gz +0 -0
  3. package/build/qemu/1.0.5/koffi_freebsd_arm64.tar.gz +0 -0
  4. package/build/qemu/1.0.5/koffi_freebsd_ia32.tar.gz +0 -0
  5. package/build/qemu/1.0.5/koffi_freebsd_x64.tar.gz +0 -0
  6. package/build/qemu/1.0.5/koffi_linux_arm.tar.gz +0 -0
  7. package/build/qemu/1.0.5/koffi_linux_arm64.tar.gz +0 -0
  8. package/build/qemu/1.0.5/koffi_linux_ia32.tar.gz +0 -0
  9. package/build/qemu/1.0.5/koffi_linux_x64.tar.gz +0 -0
  10. package/build/qemu/1.0.5/koffi_win32_ia32.tar.gz +0 -0
  11. package/build/qemu/1.0.5/koffi_win32_x64.tar.gz +0 -0
  12. package/package.json +1 -1
  13. package/src/abi_arm32.cc +119 -211
  14. package/src/abi_arm64.cc +92 -113
  15. package/src/abi_x64_sysv.cc +106 -131
  16. package/src/abi_x64_win.cc +78 -94
  17. package/src/abi_x86.cc +80 -95
  18. package/src/call.cc +144 -19
  19. package/src/call.hh +39 -3
  20. package/src/ffi.cc +11 -2
  21. package/src/ffi.hh +6 -12
  22. package/src/util.cc +0 -127
  23. package/src/util.hh +0 -16
  24. package/test/misc.c +66 -0
  25. package/test/misc.js +47 -0
  26. package/vendor/libcc/libcc.hh +1 -1
  27. package/build/qemu/1.0.2/koffi_darwin_x64.tar.gz +0 -0
  28. package/build/qemu/1.0.2/koffi_freebsd_arm64.tar.gz +0 -0
  29. package/build/qemu/1.0.2/koffi_freebsd_ia32.tar.gz +0 -0
  30. package/build/qemu/1.0.2/koffi_freebsd_x64.tar.gz +0 -0
  31. package/build/qemu/1.0.2/koffi_linux_arm.tar.gz +0 -0
  32. package/build/qemu/1.0.2/koffi_linux_arm64.tar.gz +0 -0
  33. package/build/qemu/1.0.2/koffi_linux_ia32.tar.gz +0 -0
  34. package/build/qemu/1.0.2/koffi_linux_x64.tar.gz +0 -0
  35. package/build/qemu/1.0.2/koffi_win32_ia32.tar.gz +0 -0
  36. package/build/qemu/1.0.2/koffi_win32_x64.tar.gz +0 -0
@@ -181,34 +181,25 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
181
181
  return true;
182
182
  }
183
183
 
184
- Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
184
+ bool CallData::Prepare(const Napi::CallbackInfo &info)
185
185
  {
186
- // Sanity checks
187
- if (info.Length() < (uint32_t)func->parameters.len) {
188
- ThrowError<Napi::TypeError>(env, "Expected %1 arguments, got %2", func->parameters.len, info.Length());
189
- return env.Null();
190
- }
191
-
192
- uint8_t *return_ptr = nullptr;
193
186
  uint8_t *args_ptr = nullptr;
194
187
  uint64_t *gpr_ptr = nullptr;
195
188
  uint64_t *xmm_ptr = nullptr;
196
189
 
197
190
  // Return through registers unless it's too big
198
191
  if (RG_UNLIKELY(!AllocStack(func->args_size, 16, &args_ptr)))
199
- return env.Null();
192
+ return false;
200
193
  if (RG_UNLIKELY(!AllocStack(8 * 8, 8, &xmm_ptr)))
201
- return env.Null();
194
+ return false;
202
195
  if (RG_UNLIKELY(!AllocStack(6 * 8, 8, &gpr_ptr)))
203
- return env.Null();
196
+ return false;
204
197
  if (func->ret.use_memory) {
205
198
  if (RG_UNLIKELY(!AllocHeap(func->ret.type->size, 16, &return_ptr)))
206
- return env.Null();
199
+ return false;
207
200
  *(uint8_t **)(gpr_ptr++) = return_ptr;
208
201
  }
209
202
 
210
- LocalArray<OutObject, MaxOutParameters> out_objects;
211
-
212
203
  // Push arguments
213
204
  for (Size i = 0; i < func->parameters.len; i++) {
214
205
  const ParameterInfo &param = func->parameters[i];
@@ -222,7 +213,7 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
222
213
  case PrimitiveKind::Bool: {
223
214
  if (RG_UNLIKELY(!value.IsBoolean())) {
224
215
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argmument %2, expected boolean", GetValueType(instance, value), i + 1);
225
- return env.Null();
216
+ return false;
226
217
  }
227
218
 
228
219
  bool b = value.As<Napi::Boolean>();
@@ -244,7 +235,7 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
244
235
  case PrimitiveKind::UInt64: {
245
236
  if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
246
237
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
247
- return env.Null();
238
+ return false;
248
239
  }
249
240
 
250
241
  int64_t v = CopyNumber<int64_t>(value);
@@ -257,49 +248,17 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
257
248
  args_ptr += 8;
258
249
  }
259
250
  } break;
260
- case PrimitiveKind::Float32: {
261
- if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
262
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
263
- return env.Null();
264
- }
265
-
266
- float f = CopyNumber<float>(value);
267
-
268
- if (RG_LIKELY(param.xmm_count)) {
269
- memcpy(xmm_ptr++, &f, 4);
270
- } else {
271
- args_ptr = AlignUp(args_ptr, 4);
272
- memcpy(args_ptr, &f, 4);
273
- args_ptr += 8;
274
- }
275
- } break;
276
- case PrimitiveKind::Float64: {
277
- if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
278
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
279
- return env.Null();
280
- }
281
-
282
- double d = CopyNumber<double>(value);
283
-
284
- if (RG_LIKELY(param.xmm_count)) {
285
- memcpy(xmm_ptr++, &d, 8);
286
- } else {
287
- args_ptr = AlignUp(args_ptr, 8);
288
- memcpy(args_ptr, &d, 8);
289
- args_ptr += 8;
290
- }
291
- } break;
292
251
  case PrimitiveKind::String: {
293
252
  const char *str;
294
253
  if (RG_LIKELY(value.IsString())) {
295
254
  str = PushString(value);
296
255
  if (RG_UNLIKELY(!str))
297
- return env.Null();
256
+ return false;
298
257
  } else if (IsNullOrUndefined(value)) {
299
258
  str = nullptr;
300
259
  } else {
301
260
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected string", GetValueType(instance, value), i + 1);
302
- return env.Null();
261
+ return false;
303
262
  }
304
263
 
305
264
  if (RG_LIKELY(param.gpr_count)) {
@@ -315,12 +274,12 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
315
274
  if (RG_LIKELY(value.IsString())) {
316
275
  str16 = PushString16(value);
317
276
  if (RG_UNLIKELY(!str16))
318
- return env.Null();
277
+ return false;
319
278
  } else if (IsNullOrUndefined(value)) {
320
279
  str16 = nullptr;
321
280
  } else {
322
281
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected string", GetValueType(instance, value), i + 1);
323
- return env.Null();
282
+ return false;
324
283
  }
325
284
 
326
285
  if (RG_LIKELY(param.gpr_count)) {
@@ -340,11 +299,11 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
340
299
  Napi::Object obj = value.As<Napi::Object>();
341
300
 
342
301
  if (RG_UNLIKELY(!AllocHeap(param.type->ref->size, 16, &ptr)))
343
- return env.Null();
302
+ return false;
344
303
 
345
304
  if (param.directions & 1) {
346
305
  if (!PushObject(obj, param.type->ref, ptr))
347
- return env.Null();
306
+ return false;
348
307
  } else {
349
308
  memset(ptr, 0, param.type->size);
350
309
  }
@@ -356,7 +315,7 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
356
315
  ptr = nullptr;
357
316
  } else {
358
317
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected %3", GetValueType(instance, value), i + 1, param.type->name);
359
- return env.Null();
318
+ return false;
360
319
  }
361
320
 
362
321
  if (RG_LIKELY(param.gpr_count)) {
@@ -367,11 +326,10 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
367
326
  args_ptr += 8;
368
327
  }
369
328
  } break;
370
-
371
329
  case PrimitiveKind::Record: {
372
330
  if (RG_UNLIKELY(!IsObject(value))) {
373
331
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected object", GetValueType(instance, value), i + 1);
374
- return env.Null();
332
+ return false;
375
333
  }
376
334
 
377
335
  Napi::Object obj = value.As<Napi::Object>();
@@ -381,7 +339,7 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
381
339
 
382
340
  uint64_t buf[2] = {};
383
341
  if (!PushObject(obj, param.type, (uint8_t *)buf))
384
- return env.Null();
342
+ return false;
385
343
 
386
344
  if (param.gpr_first) {
387
345
  uint64_t *ptr = buf;
@@ -405,112 +363,129 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
405
363
  } else if (param.use_memory) {
406
364
  args_ptr = AlignUp(args_ptr, param.type->align);
407
365
  if (!PushObject(obj, param.type, args_ptr))
408
- return env.Null();
366
+ return false;
409
367
  args_ptr += AlignLen(param.type->size, 8);
410
368
  }
411
369
  } break;
370
+ case PrimitiveKind::Float32: {
371
+ if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
372
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
373
+ return false;
374
+ }
375
+
376
+ float f = CopyNumber<float>(value);
377
+
378
+ if (RG_LIKELY(param.xmm_count)) {
379
+ memcpy(xmm_ptr++, &f, 4);
380
+ } else {
381
+ args_ptr = AlignUp(args_ptr, 4);
382
+ memcpy(args_ptr, &f, 4);
383
+ args_ptr += 8;
384
+ }
385
+ } break;
386
+ case PrimitiveKind::Float64: {
387
+ if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
388
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
389
+ return false;
390
+ }
391
+
392
+ double d = CopyNumber<double>(value);
393
+
394
+ if (RG_LIKELY(param.xmm_count)) {
395
+ memcpy(xmm_ptr++, &d, 8);
396
+ } else {
397
+ args_ptr = AlignUp(args_ptr, 8);
398
+ memcpy(args_ptr, &d, 8);
399
+ args_ptr += 8;
400
+ }
401
+ } break;
412
402
  }
413
403
  }
414
404
 
415
- if (instance->debug) {
416
- DumpDebug();
417
- }
405
+ return true;
406
+ }
418
407
 
408
+ void CallData::Execute()
409
+ {
419
410
  #define PERFORM_CALL(Suffix) \
420
411
  ([&]() { \
421
412
  auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func, GetSP()) \
422
413
  : ForwardCall ## Suffix(func->func, GetSP())); \
423
- PopOutArguments(out_objects); \
424
414
  return ret; \
425
415
  })()
426
416
 
427
417
  // Execute and convert return value
428
418
  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;
419
+ case PrimitiveKind::Void:
420
+ case PrimitiveKind::Bool:
437
421
  case PrimitiveKind::Int8:
438
422
  case PrimitiveKind::UInt8:
439
423
  case PrimitiveKind::Int16:
440
424
  case PrimitiveKind::UInt16:
441
425
  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;
454
- case PrimitiveKind::Float32: {
455
- float f = PERFORM_CALL(F);
456
- return Napi::Number::New(env, (double)f);
457
- } break;
458
- case PrimitiveKind::Float64: {
459
- Xmm0RaxRet ret = PERFORM_CALL(DG);
460
- return Napi::Number::New(env, ret.xmm0);
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;
479
-
426
+ case PrimitiveKind::UInt32:
427
+ case PrimitiveKind::Int64:
428
+ case PrimitiveKind::UInt64:
429
+ case PrimitiveKind::String:
430
+ case PrimitiveKind::String16:
431
+ case PrimitiveKind::Pointer: { result.u64 = PERFORM_CALL(GG).rax; } break;
480
432
  case PrimitiveKind::Record: {
481
433
  if (func->ret.gpr_first && !func->ret.xmm_count) {
482
434
  RaxRdxRet ret = PERFORM_CALL(GG);
483
-
484
- Napi::Object obj = PopObject(env, (const uint8_t *)&ret, func->ret.type);
485
- return obj;
435
+ memcpy_safe(&result.buf, &ret, RG_SIZE(ret));
486
436
  } else if (func->ret.gpr_first) {
487
437
  RaxXmm0Ret ret = PERFORM_CALL(GD);
488
-
489
- Napi::Object obj = PopObject(env, (const uint8_t *)&ret, func->ret.type);
490
- return obj;
491
- } else if (func->ret.xmm_count) {
438
+ memcpy_safe(&result.buf, &ret, RG_SIZE(ret));
439
+ } else if (func->ret.xmm_count == 2) {
440
+ Xmm0Xmm1Ret ret = PERFORM_CALL(DD);
441
+ memcpy_safe(&result.buf, &ret, RG_SIZE(ret));
442
+ } else {
492
443
  Xmm0RaxRet ret = PERFORM_CALL(DG);
444
+ memcpy_safe(&result.buf, &ret, RG_SIZE(ret));
445
+ }
446
+ } break;
447
+ case PrimitiveKind::Float32: { result.f = PERFORM_CALL(F); } break;
448
+ case PrimitiveKind::Float64: { result.d = PERFORM_CALL(DG).xmm0; } break;
449
+ }
493
450
 
494
- Napi::Object obj = PopObject(env, (const uint8_t *)&ret, func->ret.type);
495
- return obj;
496
- } else if (func->ret.type->size) {
497
- RG_ASSERT(return_ptr);
451
+ #undef PERFORM_CALL
452
+ }
498
453
 
499
- RaxRdxRet ret = PERFORM_CALL(GG);
500
- RG_ASSERT(ret.rax == (uint64_t)return_ptr);
454
+ Napi::Value CallData::Complete()
455
+ {
456
+ for (const OutObject &obj: out_objects) {
457
+ PopObject(obj.obj, obj.ptr, obj.type);
458
+ }
501
459
 
502
- Napi::Object obj = PopObject(env, return_ptr, func->ret.type);
503
- return obj;
504
- } else {
505
- PERFORM_CALL(GG);
460
+ switch (func->ret.type->primitive) {
461
+ case PrimitiveKind::Void: return env.Null();
462
+ case PrimitiveKind::Bool: return Napi::Boolean::New(env, result.u32);
463
+ case PrimitiveKind::Int8:
464
+ case PrimitiveKind::UInt8:
465
+ case PrimitiveKind::Int16:
466
+ case PrimitiveKind::UInt16:
467
+ case PrimitiveKind::Int32:
468
+ case PrimitiveKind::UInt32: return Napi::Number::New(env, (double)result.u32);
469
+ case PrimitiveKind::Int64: return Napi::BigInt::New(env, (int64_t)result.u64);
470
+ case PrimitiveKind::UInt64: return Napi::BigInt::New(env, result.u64);
471
+ case PrimitiveKind::String: return Napi::String::New(env, (const char *)result.ptr);
472
+ case PrimitiveKind::String16: return Napi::String::New(env, (const char16_t *)result.ptr);
473
+ case PrimitiveKind::Pointer: {
474
+ Napi::External<void> external = Napi::External<void>::New(env, result.ptr);
475
+ SetValueTag(instance, external, func->ret.type);
506
476
 
507
- Napi::Object obj = Napi::Object::New(env);
508
- return obj;
509
- }
477
+ return external;
510
478
  } break;
511
- }
479
+ case PrimitiveKind::Record: {
480
+ const uint8_t *ptr = return_ptr ? (const uint8_t *)return_ptr
481
+ : (const uint8_t *)&result.buf;
512
482
 
513
- #undef PERFORM_CALL
483
+ Napi::Object obj = PopObject(ptr, func->ret.type);
484
+ return obj;
485
+ } break;
486
+ case PrimitiveKind::Float32: return Napi::Number::New(env, (double)result.f);
487
+ case PrimitiveKind::Float64: return Napi::Number::New(env, result.d);
488
+ }
514
489
 
515
490
  RG_UNREACHABLE();
516
491
  }
@@ -51,28 +51,19 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
51
51
  return true;
52
52
  }
53
53
 
54
- Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
54
+ bool CallData::Prepare(const Napi::CallbackInfo &info)
55
55
  {
56
- // Sanity checks
57
- if (info.Length() < (uint32_t)func->parameters.len) {
58
- ThrowError<Napi::TypeError>(env, "Expected %1 arguments, got %2", func->parameters.len, info.Length());
59
- return env.Null();
60
- }
61
-
62
- uint8_t *return_ptr = nullptr;
63
56
  uint64_t *args_ptr = nullptr;
64
57
 
65
58
  // Pass return value in register or through memory
66
59
  if (RG_UNLIKELY(!AllocStack(func->args_size, 16, &args_ptr)))
67
- return env.Null();
60
+ return false;
68
61
  if (!func->ret.regular) {
69
62
  if (RG_UNLIKELY(!AllocHeap(func->ret.type->size, 16, &return_ptr)))
70
- return env.Null();
63
+ return false;
71
64
  *(uint8_t **)(args_ptr++) = return_ptr;
72
65
  }
73
66
 
74
- LocalArray<OutObject, MaxOutParameters> out_objects;
75
-
76
67
  // Push arguments
77
68
  for (Size i = 0; i < func->parameters.len; i++) {
78
69
  const ParameterInfo &param = func->parameters[i];
@@ -86,7 +77,7 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
86
77
  case PrimitiveKind::Bool: {
87
78
  if (RG_UNLIKELY(!value.IsBoolean())) {
88
79
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected boolean", GetValueType(instance, value), i + 1);
89
- return env.Null();
80
+ return false;
90
81
  }
91
82
 
92
83
  bool b = value.As<Napi::Boolean>();
@@ -103,41 +94,23 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
103
94
  case PrimitiveKind::UInt64: {
104
95
  if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
105
96
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
106
- return env.Null();
97
+ return false;
107
98
  }
108
99
 
109
100
  int64_t v = CopyNumber<int64_t>(value);
110
101
  *(args_ptr++) = (uint64_t)v;
111
102
  } break;
112
- case PrimitiveKind::Float32: {
113
- if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
114
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
115
- return env.Null();
116
- }
117
-
118
- float f = CopyNumber<float>(value);
119
- *(float *)(args_ptr++) = f;
120
- } break;
121
- case PrimitiveKind::Float64: {
122
- if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
123
- ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
124
- return env.Null();
125
- }
126
-
127
- double d = CopyNumber<double>(value);
128
- *(double *)(args_ptr++) = d;
129
- } break;
130
103
  case PrimitiveKind::String: {
131
104
  const char *str;
132
105
  if (RG_LIKELY(value.IsString())) {
133
106
  str = PushString(value);
134
107
  if (RG_UNLIKELY(!str))
135
- return env.Null();
108
+ return false;
136
109
  } else if (IsNullOrUndefined(value)) {
137
110
  str = nullptr;
138
111
  } else {
139
112
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected string", GetValueType(instance, value), i + 1);
140
- return env.Null();
113
+ return false;
141
114
  }
142
115
 
143
116
  *(const char **)(args_ptr++) = str;
@@ -147,12 +120,12 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
147
120
  if (RG_LIKELY(value.IsString())) {
148
121
  str16 = PushString16(value);
149
122
  if (RG_UNLIKELY(!str16))
150
- return env.Null();
123
+ return false;
151
124
  } else if (IsNullOrUndefined(value)) {
152
125
  str16 = nullptr;
153
126
  } else {
154
127
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected string", GetValueType(instance, value), i + 1);
155
- return env.Null();
128
+ return false;
156
129
  }
157
130
 
158
131
  *(const char16_t **)(args_ptr++) = str16;
@@ -166,11 +139,11 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
166
139
  Napi::Object obj = value.As<Napi::Object>();
167
140
 
168
141
  if (RG_UNLIKELY(!AllocHeap(param.type->ref->size, 16, &ptr)))
169
- return env.Null();
142
+ return false;
170
143
 
171
144
  if (param.directions & 1) {
172
145
  if (!PushObject(obj, param.type->ref, ptr))
173
- return env.Null();
146
+ return false;
174
147
  } else {
175
148
  memset(ptr, 0, param.type->size);
176
149
  }
@@ -182,16 +155,15 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
182
155
  ptr = nullptr;
183
156
  } else {
184
157
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected %3", GetValueType(instance, value), i + 1, param.type->name);
185
- return env.Null();
158
+ return false;
186
159
  }
187
160
 
188
161
  *(uint8_t **)(args_ptr++) = ptr;
189
162
  } break;
190
-
191
163
  case PrimitiveKind::Record: {
192
164
  if (RG_UNLIKELY(!IsObject(value))) {
193
165
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected object", GetValueType(instance, value), i + 1);
194
- return env.Null();
166
+ return false;
195
167
  }
196
168
 
197
169
  uint8_t *ptr;
@@ -199,93 +171,105 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
199
171
  ptr = (uint8_t *)(args_ptr++);
200
172
  } else {
201
173
  if (RG_UNLIKELY(!AllocHeap(param.type->size, 16, &ptr)))
202
- return env.Null();
174
+ return false;
203
175
  *(uint8_t **)(args_ptr++) = ptr;
204
176
  }
205
177
 
206
178
  Napi::Object obj = value.As<Napi::Object>();
207
179
  if (!PushObject(obj, param.type, ptr))
208
- return env.Null();
180
+ return false;
181
+ } break;
182
+ case PrimitiveKind::Float32: {
183
+ if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
184
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
185
+ return false;
186
+ }
187
+
188
+ float f = CopyNumber<float>(value);
189
+ *(float *)(args_ptr++) = f;
190
+ } break;
191
+ case PrimitiveKind::Float64: {
192
+ if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
193
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
194
+ return false;
195
+ }
196
+
197
+ double d = CopyNumber<double>(value);
198
+ *(double *)(args_ptr++) = d;
209
199
  } break;
210
200
  }
211
201
  }
212
202
 
213
- if (instance->debug) {
214
- DumpDebug();
215
- }
203
+ return true;
204
+ }
216
205
 
206
+ void CallData::Execute()
207
+ {
217
208
  #define PERFORM_CALL(Suffix) \
218
209
  ([&]() { \
219
210
  auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func, GetSP()) \
220
211
  : ForwardCall ## Suffix(func->func, GetSP())); \
221
- PopOutArguments(out_objects); \
222
212
  return ret; \
223
213
  })()
224
214
 
225
- // Execute and convert return value
226
215
  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;
216
+ case PrimitiveKind::Void:
217
+ case PrimitiveKind::Bool:
235
218
  case PrimitiveKind::Int8:
236
219
  case PrimitiveKind::UInt8:
237
220
  case PrimitiveKind::Int16:
238
221
  case PrimitiveKind::UInt16:
239
222
  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;
252
- case PrimitiveKind::Float32: {
253
- float f = PERFORM_CALL(F);
254
- return Napi::Number::New(env, (double)f);
255
- } break;
256
- case PrimitiveKind::Float64: {
257
- double d = PERFORM_CALL(D);
258
- return Napi::Number::New(env, d);
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;
223
+ case PrimitiveKind::UInt32:
224
+ case PrimitiveKind::Int64:
225
+ case PrimitiveKind::UInt64:
226
+ case PrimitiveKind::String:
227
+ case PrimitiveKind::String16:
228
+ case PrimitiveKind::Pointer:
229
+ case PrimitiveKind::Record: { result.u64 = PERFORM_CALL(G); } break;
230
+ case PrimitiveKind::Float32: { result.f = PERFORM_CALL(F); } break;
231
+ case PrimitiveKind::Float64: { result.d = PERFORM_CALL(D); } break;
232
+ }
271
233
 
272
- Napi::External<void> external = Napi::External<void>::New(env, ptr);
234
+ #undef PERFORM_CALL
235
+ }
236
+
237
+ Napi::Value CallData::Complete()
238
+ {
239
+ for (const OutObject &obj: out_objects) {
240
+ PopObject(obj.obj, obj.ptr, obj.type);
241
+ }
242
+
243
+ switch (func->ret.type->primitive) {
244
+ case PrimitiveKind::Void: return env.Null();
245
+ case PrimitiveKind::Bool: return Napi::Boolean::New(env, result.u32);
246
+ case PrimitiveKind::Int8:
247
+ case PrimitiveKind::UInt8:
248
+ case PrimitiveKind::Int16:
249
+ case PrimitiveKind::UInt16:
250
+ case PrimitiveKind::Int32:
251
+ case PrimitiveKind::UInt32: return Napi::Number::New(env, (double)result.u32);
252
+ case PrimitiveKind::Int64: return Napi::BigInt::New(env, (int64_t)result.u64);
253
+ case PrimitiveKind::UInt64: return Napi::BigInt::New(env, result.u64);
254
+ case PrimitiveKind::String: return Napi::String::New(env, (const char *)result.ptr);
255
+ case PrimitiveKind::String16: return Napi::String::New(env, (const char16_t *)result.ptr);
256
+ case PrimitiveKind::Pointer: {
257
+ Napi::External<void> external = Napi::External<void>::New(env, result.ptr);
273
258
  SetValueTag(instance, external, func->ret.type);
274
259
 
275
260
  return external;
276
261
  } break;
277
-
278
262
  case PrimitiveKind::Record: {
279
- uint64_t rax = PERFORM_CALL(G);
280
- const uint8_t *ptr = return_ptr ? return_ptr : (const uint8_t *)&rax;
263
+ const uint8_t *ptr = return_ptr ? (const uint8_t *)return_ptr
264
+ : (const uint8_t *)&result.buf;
281
265
 
282
- Napi::Object obj = PopObject(env, ptr, func->ret.type);
266
+ Napi::Object obj = PopObject(ptr, func->ret.type);
283
267
  return obj;
284
268
  } break;
269
+ case PrimitiveKind::Float32: return Napi::Number::New(env, (double)result.f);
270
+ case PrimitiveKind::Float64: return Napi::Number::New(env, result.d);
285
271
  }
286
272
 
287
- #undef PERFORM_CALL
288
-
289
273
  RG_UNREACHABLE();
290
274
  }
291
275