koffi 1.0.1 → 1.0.4

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 (50) hide show
  1. package/CMakeLists.txt +12 -11
  2. package/README.md +23 -20
  3. package/build/qemu/1.0.4/koffi_darwin_x64.tar.gz +0 -0
  4. package/build/qemu/1.0.4/koffi_freebsd_arm64.tar.gz +0 -0
  5. package/build/qemu/1.0.4/koffi_freebsd_ia32.tar.gz +0 -0
  6. package/build/qemu/1.0.4/koffi_freebsd_x64.tar.gz +0 -0
  7. package/build/qemu/1.0.4/koffi_linux_arm.tar.gz +0 -0
  8. package/build/qemu/1.0.4/koffi_linux_arm64.tar.gz +0 -0
  9. package/build/qemu/1.0.4/koffi_linux_ia32.tar.gz +0 -0
  10. package/build/qemu/1.0.4/koffi_linux_x64.tar.gz +0 -0
  11. package/build/qemu/1.0.4/koffi_win32_ia32.tar.gz +0 -0
  12. package/build/qemu/1.0.4/koffi_win32_x64.tar.gz +0 -0
  13. package/package.json +8 -4
  14. package/qemu/qemu.js +794 -0
  15. package/qemu/registry/machines.json +415 -0
  16. package/qemu/registry/sha256sum.txt +45 -0
  17. package/src/{call_arm32.cc → abi_arm32.cc} +153 -219
  18. package/src/{call_arm32_fwd.S → abi_arm32_fwd.S} +0 -0
  19. package/src/{call_arm64.cc → abi_arm64.cc} +130 -123
  20. package/src/{call_arm64_fwd.S → abi_arm64_fwd.S} +0 -0
  21. package/src/{call_x64_sysv.cc → abi_x64_sysv.cc} +138 -135
  22. package/src/{call_x64_sysv_fwd.S → abi_x64_sysv_fwd.S} +0 -0
  23. package/src/{call_x64_win.cc → abi_x64_win.cc} +107 -99
  24. package/src/{call_x64_win_fwd.asm → abi_x64_win_fwd.asm} +0 -0
  25. package/src/{call_x86.cc → abi_x86.cc} +110 -107
  26. package/src/{call_x86_fwd.S → abi_x86_fwd.S} +0 -0
  27. package/src/{call_x86_fwd.asm → abi_x86_fwd.asm} +0 -0
  28. package/src/call.cc +353 -0
  29. package/src/call.hh +132 -4
  30. package/src/ffi.cc +16 -2
  31. package/src/ffi.hh +8 -12
  32. package/src/util.cc +7 -280
  33. package/src/util.hh +0 -107
  34. package/test/CMakeLists.txt +1 -0
  35. package/test/misc.c +355 -0
  36. package/test/misc.def +3 -0
  37. package/test/misc.js +227 -0
  38. package/test/raylib.js +165 -0
  39. package/test/sqlite.js +104 -0
  40. package/vendor/libcc/libcc.hh +1 -1
  41. package/build/qemu/1.0.1/koffi_darwin_x64.tar.gz +0 -0
  42. package/build/qemu/1.0.1/koffi_freebsd_arm64.tar.gz +0 -0
  43. package/build/qemu/1.0.1/koffi_freebsd_ia32.tar.gz +0 -0
  44. package/build/qemu/1.0.1/koffi_freebsd_x64.tar.gz +0 -0
  45. package/build/qemu/1.0.1/koffi_linux_arm.tar.gz +0 -0
  46. package/build/qemu/1.0.1/koffi_linux_arm64.tar.gz +0 -0
  47. package/build/qemu/1.0.1/koffi_linux_ia32.tar.gz +0 -0
  48. package/build/qemu/1.0.1/koffi_linux_x64.tar.gz +0 -0
  49. package/build/qemu/1.0.1/koffi_win32_ia32.tar.gz +0 -0
  50. package/build/qemu/1.0.1/koffi_win32_x64.tar.gz +0 -0
@@ -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)
@@ -162,28 +163,24 @@ static bool PushHFA(const Napi::Object &obj, const TypeInfo *type, uint8_t *dest
162
163
  InstanceData *instance = env.GetInstanceData<InstanceData>();
163
164
 
164
165
  RG_ASSERT(IsObject(obj));
166
+ RG_ASSERT(IsHFA(type));
165
167
  RG_ASSERT(type->primitive == PrimitiveKind::Record);
166
- RG_ASSERT(AlignUp(dest, 8) == dest);
168
+ RG_ASSERT(AlignUp(dest, type->members[0].type->size) == dest);
169
+
170
+ bool float32 = (type->members[0].type->primitive == PrimitiveKind::Float32);
167
171
 
168
172
  for (const RecordMember &member: type->members) {
169
173
  Napi::Value value = obj.Get(member.name);
170
174
 
171
- if (member.type->primitive == PrimitiveKind::Float32) {
172
- if (!value.IsNumber() && !value.IsBigInt()) {
173
- ThrowError<Napi::TypeError>(env, "Unexpected value %1 for member '%2', expected number", GetValueType(instance, value), member.name);
174
- return false;
175
- }
175
+ if (!value.IsNumber() && !value.IsBigInt()) {
176
+ ThrowError<Napi::TypeError>(env, "Unexpected value %1 for member '%2', expected number", GetValueType(instance, value), member.name);
177
+ return false;
178
+ }
176
179
 
180
+ if (float32) {
177
181
  *(float *)dest = CopyNumber<float>(value);
178
- } else if (member.type->primitive == PrimitiveKind::Float64) {
179
- if (!value.IsNumber() && !value.IsBigInt()) {
180
- ThrowError<Napi::TypeError>(env, "Unexpected value %1 for member '%2', expected number", GetValueType(instance, value), member.name);
181
- return false;
182
- }
183
-
184
- *(double *)dest = CopyNumber<double>(value);
185
182
  } else {
186
- RG_UNREACHABLE();
183
+ *(double *)dest = CopyNumber<double>(value);
187
184
  }
188
185
 
189
186
  dest += 8;
@@ -195,18 +192,19 @@ static bool PushHFA(const Napi::Object &obj, const TypeInfo *type, uint8_t *dest
195
192
  static Napi::Object PopHFA(napi_env env, const uint8_t *ptr, const TypeInfo *type)
196
193
  {
197
194
  RG_ASSERT(type->primitive == PrimitiveKind::Record);
195
+ RG_ASSERT(IsHFA(type));
198
196
 
199
197
  Napi::Object obj = Napi::Object::New(env);
200
198
 
199
+ bool float32 = (type->members[0].type->primitive == PrimitiveKind::Float32);
200
+
201
201
  for (const RecordMember &member: type->members) {
202
- if (member.type->primitive == PrimitiveKind::Float32) {
202
+ if (float32) {
203
203
  float f = *(float *)ptr;
204
204
  obj.Set(member.name, Napi::Number::New(env, (double)f));
205
- } else if (member.type->primitive == PrimitiveKind::Float64) {
205
+ } else {
206
206
  double d = *(double *)ptr;
207
207
  obj.Set(member.name, Napi::Number::New(env, d));
208
- } else {
209
- RG_UNREACHABLE();
210
208
  }
211
209
 
212
210
  ptr += 8;
@@ -215,37 +213,25 @@ static Napi::Object PopHFA(napi_env env, const uint8_t *ptr, const TypeInfo *typ
215
213
  return obj;
216
214
  }
217
215
 
218
- Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, const Napi::CallbackInfo &info)
216
+ bool CallData::Prepare(const Napi::CallbackInfo &info)
219
217
  {
220
- Napi::Env env = info.Env();
221
- CallData call(env, instance, func);
222
-
223
- // Sanity checks
224
- if (info.Length() < (uint32_t)func->parameters.len) {
225
- ThrowError<Napi::TypeError>(env, "Expected %1 arguments, got %2", func->parameters.len, info.Length());
226
- return env.Null();
227
- }
228
-
229
- uint8_t *return_ptr = nullptr;
230
218
  uint8_t *args_ptr = nullptr;
231
219
  uint64_t *gpr_ptr = nullptr;
232
220
  uint64_t *vec_ptr = nullptr;
233
221
 
234
222
  // Return through registers unless it's too big
235
- if (RG_UNLIKELY(!call.AllocStack(func->args_size, 16, &args_ptr)))
236
- return env.Null();
237
- if (RG_UNLIKELY(!call.AllocStack(8 * 8, 8, &vec_ptr)))
238
- return env.Null();
239
- if (RG_UNLIKELY(!call.AllocStack(9 * 8, 8, &gpr_ptr)))
240
- return env.Null();
223
+ if (RG_UNLIKELY(!AllocStack(func->args_size, 16, &args_ptr)))
224
+ return false;
225
+ if (RG_UNLIKELY(!AllocStack(8 * 8, 8, &vec_ptr)))
226
+ return false;
227
+ if (RG_UNLIKELY(!AllocStack(9 * 8, 8, &gpr_ptr)))
228
+ return false;
241
229
  if (func->ret.use_memory) {
242
- if (RG_UNLIKELY(!call.AllocHeap(func->ret.type->size, 16, &return_ptr)))
243
- return env.Null();
230
+ if (RG_UNLIKELY(!AllocHeap(func->ret.type->size, 16, &return_ptr)))
231
+ return false;
244
232
  gpr_ptr[8] = (uint64_t)return_ptr;
245
233
  }
246
234
 
247
- LocalArray<OutObject, MaxOutParameters> out_objects;
248
-
249
235
  // Push arguments
250
236
  for (Size i = 0; i < func->parameters.len; i++) {
251
237
  const ParameterInfo &param = func->parameters[i];
@@ -259,7 +245,7 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
259
245
  case PrimitiveKind::Bool: {
260
246
  if (RG_UNLIKELY(!value.IsBoolean())) {
261
247
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected boolean", GetValueType(instance, value), i + 1);
262
- return env.Null();
248
+ return false;
263
249
  }
264
250
 
265
251
  bool b = value.As<Napi::Boolean>();
@@ -285,7 +271,7 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
285
271
  case PrimitiveKind::UInt64: {
286
272
  if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
287
273
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
288
- return env.Null();
274
+ return false;
289
275
  }
290
276
 
291
277
  int64_t v = CopyNumber<int64_t>(value);
@@ -305,7 +291,7 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
305
291
  case PrimitiveKind::Float32: {
306
292
  if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
307
293
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
308
- return env.Null();
294
+ return false;
309
295
  }
310
296
 
311
297
  float f = CopyNumber<float>(value);
@@ -325,7 +311,7 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
325
311
  case PrimitiveKind::Float64: {
326
312
  if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
327
313
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
328
- return env.Null();
314
+ return false;
329
315
  }
330
316
 
331
317
  double d = CopyNumber<double>(value);
@@ -341,14 +327,14 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
341
327
  case PrimitiveKind::String: {
342
328
  const char *str;
343
329
  if (RG_LIKELY(value.IsString())) {
344
- str = call.PushString(value);
330
+ str = PushString(value);
345
331
  if (RG_UNLIKELY(!str))
346
- return env.Null();
332
+ return false;
347
333
  } else if (IsNullOrUndefined(value)) {
348
334
  str = nullptr;
349
335
  } else {
350
336
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected string", GetValueType(instance, value), i + 1);
351
- return env.Null();
337
+ return false;
352
338
  }
353
339
 
354
340
  if (RG_LIKELY(param.gpr_count)) {
@@ -359,6 +345,27 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
359
345
  args_ptr += 8;
360
346
  }
361
347
  } break;
348
+ case PrimitiveKind::String16: {
349
+ const char16_t *str16;
350
+ if (RG_LIKELY(value.IsString())) {
351
+ str16 = PushString16(value);
352
+ if (RG_UNLIKELY(!str16))
353
+ return false;
354
+ } else if (IsNullOrUndefined(value)) {
355
+ str16 = nullptr;
356
+ } else {
357
+ ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected string", GetValueType(instance, value), i + 1);
358
+ return false;
359
+ }
360
+
361
+ if (RG_LIKELY(param.gpr_count)) {
362
+ *(gpr_ptr++) = (uint64_t)str16;
363
+ } else {
364
+ args_ptr = AlignUp(args_ptr, 8);
365
+ *(uint64_t *)args_ptr = (uint64_t)str16;
366
+ args_ptr += 8;
367
+ }
368
+ } break;
362
369
  case PrimitiveKind::Pointer: {
363
370
  uint8_t *ptr;
364
371
 
@@ -367,12 +374,12 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
367
374
  } else if (IsObject(value) && param.type->ref->primitive == PrimitiveKind::Record) {
368
375
  Napi::Object obj = value.As<Napi::Object>();
369
376
 
370
- if (RG_UNLIKELY(!call.AllocHeap(param.type->ref->size, 16, &ptr)))
371
- return env.Null();
377
+ if (RG_UNLIKELY(!AllocHeap(param.type->ref->size, 16, &ptr)))
378
+ return false;
372
379
 
373
380
  if (param.directions & 1) {
374
- if (!call.PushObject(obj, param.type->ref, ptr))
375
- return env.Null();
381
+ if (!PushObject(obj, param.type->ref, ptr))
382
+ return false;
376
383
  } else {
377
384
  memset(ptr, 0, param.type->size);
378
385
  }
@@ -384,7 +391,7 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
384
391
  ptr = nullptr;
385
392
  } else {
386
393
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected %3", GetValueType(instance, value), i + 1, param.type->name);
387
- return env.Null();
394
+ return false;
388
395
  }
389
396
 
390
397
  if (RG_LIKELY(param.gpr_count)) {
@@ -399,32 +406,32 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
399
406
  case PrimitiveKind::Record: {
400
407
  if (RG_UNLIKELY(!IsObject(value))) {
401
408
  ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected object", GetValueType(instance, value), i + 1);
402
- return env.Null();
409
+ return false;
403
410
  }
404
411
 
405
412
  Napi::Object obj = value.As<Napi::Object>();
406
413
 
407
414
  if (param.vec_count) {
408
415
  if (!PushHFA(obj, param.type, (uint8_t *)vec_ptr))
409
- return env.Null();
416
+ return false;
410
417
  vec_ptr += param.vec_count;
411
418
  } else if (!param.use_memory) {
412
419
  if (param.gpr_count) {
413
420
  RG_ASSERT(param.type->align <= 8);
414
421
 
415
- if (!call.PushObject(obj, param.type, (uint8_t *)gpr_ptr))
416
- return env.Null();
422
+ if (!PushObject(obj, param.type, (uint8_t *)gpr_ptr))
423
+ return false;
417
424
  gpr_ptr += param.gpr_count;
418
425
  } else if (param.type->size) {
419
426
  args_ptr = AlignUp(args_ptr, 8);
420
- if (!call.PushObject(obj, param.type, args_ptr))
421
- return env.Null();
427
+ if (!PushObject(obj, param.type, args_ptr))
428
+ return false;
422
429
  args_ptr += AlignLen(param.type->size, 8);
423
430
  }
424
431
  } else {
425
432
  uint8_t *ptr;
426
- if (RG_UNLIKELY(!call.AllocHeap(param.type->size, 16, &ptr)))
427
- return env.Null();
433
+ if (RG_UNLIKELY(!AllocHeap(param.type->size, 16, &ptr)))
434
+ return false;
428
435
 
429
436
  if (param.gpr_count) {
430
437
  RG_ASSERT(param.gpr_count == 1);
@@ -437,99 +444,99 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
437
444
  args_ptr += 8;
438
445
  }
439
446
 
440
- if (!call.PushObject(obj, param.type, ptr))
441
- return env.Null();
447
+ if (!PushObject(obj, param.type, ptr))
448
+ return false;
442
449
  }
443
450
  } break;
444
451
  }
445
452
  }
446
453
 
447
- if (instance->debug) {
448
- call.DumpDebug();
449
- }
454
+ return true;
455
+ }
450
456
 
457
+ void CallData::Execute()
458
+ {
451
459
  #define PERFORM_CALL(Suffix) \
452
460
  ([&]() { \
453
- auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func, call.GetSP()) \
454
- : ForwardCall ## Suffix(func->func, call.GetSP())); \
455
- PopOutArguments(out_objects); \
461
+ auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func, GetSP()) \
462
+ : ForwardCall ## Suffix(func->func, GetSP())); \
456
463
  return ret; \
457
464
  })()
458
465
 
459
466
  // Execute and convert return value
460
467
  switch (func->ret.type->primitive) {
461
- case PrimitiveKind::Float32: {
462
- float f = PERFORM_CALL(F);
463
-
464
- return Napi::Number::New(env, (double)f);
465
- } break;
466
-
467
- case PrimitiveKind::Float64: {
468
- HfaRet ret = PERFORM_CALL(DDDD);
469
-
470
- return Napi::Number::New(env, (double)ret.d0);
471
- } break;
472
-
468
+ case PrimitiveKind::Void:
469
+ case PrimitiveKind::Bool:
470
+ case PrimitiveKind::Int8:
471
+ case PrimitiveKind::UInt8:
472
+ case PrimitiveKind::Int16:
473
+ case PrimitiveKind::UInt16:
474
+ case PrimitiveKind::Int32:
475
+ case PrimitiveKind::UInt32:
476
+ case PrimitiveKind::Int64:
477
+ case PrimitiveKind::UInt64:
478
+ case PrimitiveKind::String:
479
+ case PrimitiveKind::String16:
480
+ case PrimitiveKind::Pointer: { result.u64 = PERFORM_CALL(GG).x0; } break;
473
481
  case PrimitiveKind::Record: {
474
482
  if (func->ret.gpr_count) {
475
483
  X0X1Ret ret = PERFORM_CALL(GG);
476
-
477
- Napi::Object obj = PopObject(env, (const uint8_t *)&ret, func->ret.type);
478
- return obj;
484
+ memcpy_safe(&result.buf, &ret, RG_SIZE(ret));
479
485
  } else if (func->ret.vec_count) {
480
486
  HfaRet ret = PERFORM_CALL(DDDD);
487
+ memcpy_safe(&result.buf, &ret, RG_SIZE(ret));
488
+ } else {
489
+ PERFORM_CALL(GG);
490
+ }
491
+ } break;
492
+ case PrimitiveKind::Float32: { result.f = PERFORM_CALL(F); } break;
493
+ case PrimitiveKind::Float64: { result.d = PERFORM_CALL(DDDD).d0; } break;
494
+ }
481
495
 
482
- Napi::Object obj = PopHFA(env, (const uint8_t *)&ret, func->ret.type);
483
- return obj;
484
- } else if (func->ret.type->size) {
485
- RG_ASSERT(return_ptr);
496
+ #undef PERFORM_CALL
497
+ }
486
498
 
487
- X0X1Ret ret = PERFORM_CALL(GG);
488
- RG_ASSERT(ret.x0 == (uint64_t)return_ptr);
499
+ Napi::Value CallData::Complete()
500
+ {
501
+ for (const OutObject &obj: out_objects) {
502
+ PopObject(obj.obj, obj.ptr, obj.type);
503
+ }
489
504
 
490
- Napi::Object obj = PopObject(env, return_ptr, func->ret.type);
505
+ switch (func->ret.type->primitive) {
506
+ case PrimitiveKind::Void: return env.Null();
507
+ case PrimitiveKind::Bool: return Napi::Boolean::New(env, result.u32);
508
+ case PrimitiveKind::Int8:
509
+ case PrimitiveKind::UInt8:
510
+ case PrimitiveKind::Int16:
511
+ case PrimitiveKind::UInt16:
512
+ case PrimitiveKind::Int32:
513
+ case PrimitiveKind::UInt32: return Napi::Number::New(env, (double)result.u32);
514
+ case PrimitiveKind::Int64: return Napi::BigInt::New(env, (int64_t)result.u64);
515
+ case PrimitiveKind::UInt64: return Napi::BigInt::New(env, result.u64);
516
+ case PrimitiveKind::String: return Napi::String::New(env, (const char *)result.ptr);
517
+ case PrimitiveKind::String16: return Napi::String::New(env, (const char16_t *)result.ptr);
518
+ case PrimitiveKind::Pointer: {
519
+ Napi::External<void> external = Napi::External<void>::New(env, result.ptr);
520
+ SetValueTag(instance, external, func->ret.type);
521
+
522
+ return external;
523
+ } break;
524
+ case PrimitiveKind::Record: {
525
+ if (func->ret.vec_count) {
526
+ Napi::Object obj = PopHFA(env, (const uint8_t *)&result.buf, func->ret.type);
491
527
  return obj;
492
528
  } else {
493
- PERFORM_CALL(GG);
529
+ const uint8_t *ptr = return_ptr ? (const uint8_t *)return_ptr
530
+ : (const uint8_t *)&result.buf;
494
531
 
495
- Napi::Object obj = Napi::Object::New(env);
532
+ Napi::Object obj = PopObject(ptr, func->ret.type);
496
533
  return obj;
497
534
  }
498
535
  } 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;
536
+ case PrimitiveKind::Float32: return Napi::Number::New(env, (double)result.f);
537
+ case PrimitiveKind::Float64: return Napi::Number::New(env, result.d);
529
538
  }
530
539
 
531
- #undef PERFORM_CALL
532
-
533
540
  RG_UNREACHABLE();
534
541
  }
535
542
 
File without changes