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.
- package/README.md +24 -21
- package/build/qemu/1.0.5/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/1.0.5/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/1.0.5/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/1.0.5/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/1.0.5/koffi_linux_arm.tar.gz +0 -0
- package/build/qemu/1.0.5/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/1.0.5/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/1.0.5/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/1.0.5/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/1.0.5/koffi_win32_x64.tar.gz +0 -0
- package/package.json +1 -1
- package/src/abi_arm32.cc +119 -211
- package/src/abi_arm64.cc +92 -113
- package/src/abi_x64_sysv.cc +106 -131
- package/src/abi_x64_win.cc +78 -94
- package/src/abi_x86.cc +80 -95
- package/src/call.cc +144 -19
- package/src/call.hh +39 -3
- package/src/ffi.cc +11 -2
- package/src/ffi.hh +6 -12
- package/src/util.cc +0 -127
- package/src/util.hh +0 -16
- package/test/misc.c +66 -0
- package/test/misc.js +47 -0
- package/vendor/libcc/libcc.hh +1 -1
- 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/README.md
CHANGED
|
@@ -16,34 +16,37 @@ Koffi is a fast and easy-to-use FFI module for Node.js, with support for primiti
|
|
|
16
16
|
|
|
17
17
|
After the release of version 1.0, the following features are planned:
|
|
18
18
|
|
|
19
|
-
* 1.1:
|
|
20
|
-
* 1.2:
|
|
19
|
+
* 1.1: Asynchronous calls
|
|
20
|
+
* 1.2: C to JS callbacks
|
|
21
|
+
* 1.3: Unions and (fixed size) array types
|
|
21
22
|
|
|
22
23
|
The following platforms __are officially supported and tested__ at the moment:
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
--------- | -------------------------------- |
|
|
26
|
-
Windows | x86 (cdecl, stdcall, fastcall) | 🟩
|
|
27
|
-
Windows | x86_64 | 🟩
|
|
28
|
-
Linux | x86 | 🟩
|
|
29
|
-
Linux | x86_64 | 🟩
|
|
30
|
-
Linux | ARM32+VFP Little Endian | 🟩
|
|
31
|
-
Linux | ARM64 Little Endian | 🟩
|
|
32
|
-
FreeBSD | x86 | 🟩
|
|
33
|
-
FreeBSD | x86_64 | 🟩
|
|
34
|
-
FreeBSD | ARM64 Little Endian | 🟩
|
|
35
|
-
macOS | x86_64 | 🟩
|
|
36
|
-
macOS | ARM64 (M1) Little Endian | 🟩
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
OpenBSD |
|
|
40
|
-
|
|
25
|
+
Platform | Architecture | JS to C | C to JS (callback) | Pre-built binary
|
|
26
|
+
--------- | -------------------------------- | -------- | ------------------ | ----------------
|
|
27
|
+
Windows | x86 (cdecl, stdcall, fastcall) | 🟩 Yes | 🟥 No | 🟩 Yes
|
|
28
|
+
Windows | x86_64 | 🟩 Yes | 🟥 No | 🟩 Yes
|
|
29
|
+
Linux | x86 | 🟩 Yes | 🟥 No | 🟩 Yes
|
|
30
|
+
Linux | x86_64 | 🟩 Yes | 🟥 No | 🟩 Yes
|
|
31
|
+
Linux | ARM32+VFP Little Endian | 🟩 Yes | 🟥 No | 🟩 Yes
|
|
32
|
+
Linux | ARM64 Little Endian | 🟩 Yes | 🟥 No | 🟩 Yes
|
|
33
|
+
FreeBSD | x86 | 🟩 Yes | 🟥 No | 🟩 Yes
|
|
34
|
+
FreeBSD | x86_64 | 🟩 Yes | 🟥 No | 🟩 Yes
|
|
35
|
+
FreeBSD | ARM64 Little Endian | 🟩 Yes | 🟥 No | 🟩 Yes
|
|
36
|
+
macOS | x86_64 | 🟩 Yes | 🟥 No | 🟩 Yes
|
|
37
|
+
macOS | ARM64 (M1) Little Endian | 🟩 Yes | 🟥 No | 🟥 No
|
|
38
|
+
OpenBSD | x86_64 | 🟧 Maybe | 🟥 No | 🟥 No
|
|
39
|
+
OpenBSD | x86 | 🟧 Maybe | 🟥 No | 🟥 No
|
|
40
|
+
OpenBSD | ARM64 Little Endian | 🟧 Maybe | 🟥 No | 🟥 No
|
|
41
|
+
NetBSD | x86_64 | 🟧 Maybe | 🟥 No | 🟥 No
|
|
42
|
+
NetBSD | x86 | 🟧 Maybe | 🟥 No | 🟥 No
|
|
43
|
+
NetBSD | ARM64 Little Endian | 🟧 Maybe | 🟥 No | 🟥 No
|
|
41
44
|
|
|
42
45
|
🟩 Tested, fully operational
|
|
43
46
|
🟧 May work, but not actively tested
|
|
44
47
|
🟥 Does not work yet
|
|
45
48
|
|
|
46
|
-
This is still in development, bugs are to expected. More tests will come in the near future.
|
|
49
|
+
This is still in development, bugs are to be expected. More tests will come in the near future.
|
|
47
50
|
|
|
48
51
|
# Get started
|
|
49
52
|
|
|
@@ -101,7 +104,7 @@ MessageBoxA(null, 'Hello', 'Foobar', MB_ICONINFORMATION);
|
|
|
101
104
|
|
|
102
105
|
## Raylib example
|
|
103
106
|
|
|
104
|
-
This section assumes you know how to build C shared libraries, such as Raylib. You may need to fix the
|
|
107
|
+
This section assumes you know how to build C shared libraries, such as Raylib. You may need to fix the path to the library before you can do anything.
|
|
105
108
|
|
|
106
109
|
```js
|
|
107
110
|
const koffi = require('koffi');
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
package/src/abi_arm32.cc
CHANGED
|
@@ -162,74 +162,8 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
|
|
|
162
162
|
return true;
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
|
|
165
|
+
bool CallData::Prepare(const Napi::CallbackInfo &info)
|
|
166
166
|
{
|
|
167
|
-
Napi::Env env = obj.Env();
|
|
168
|
-
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
169
|
-
|
|
170
|
-
RG_ASSERT(IsObject(obj));
|
|
171
|
-
RG_ASSERT(type->primitive == PrimitiveKind::Record);
|
|
172
|
-
RG_ASSERT(AlignUp(dest, type->members[0].type->size) == dest);
|
|
173
|
-
|
|
174
|
-
for (const RecordMember &member: type->members) {
|
|
175
|
-
Napi::Value value = obj.Get(member.name);
|
|
176
|
-
|
|
177
|
-
if (member.type->primitive == PrimitiveKind::Float32) {
|
|
178
|
-
if (!value.IsNumber() && !value.IsBigInt()) {
|
|
179
|
-
ThrowError<Napi::TypeError>(env, "Unexpected value %1 for member '%2', expected number", GetValueType(instance, value), member.name);
|
|
180
|
-
return false;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
*(float *)dest = CopyNumber<float>(value);
|
|
184
|
-
} else if (member.type->primitive == PrimitiveKind::Float64) {
|
|
185
|
-
if (!value.IsNumber() && !value.IsBigInt()) {
|
|
186
|
-
ThrowError<Napi::TypeError>(env, "Unexpected value %1 for member '%2', expected number", GetValueType(instance, value), member.name);
|
|
187
|
-
return false;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
*(double *)dest = CopyNumber<double>(value);
|
|
191
|
-
} else {
|
|
192
|
-
RG_UNREACHABLE();
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
dest += type->members[0].type->size;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
return true;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
static Napi::Object PopHFA(napi_env env, const uint8_t *ptr, const TypeInfo *type)
|
|
202
|
-
{
|
|
203
|
-
RG_ASSERT(type->primitive == PrimitiveKind::Record);
|
|
204
|
-
|
|
205
|
-
Napi::Object obj = Napi::Object::New(env);
|
|
206
|
-
|
|
207
|
-
for (const RecordMember &member: type->members) {
|
|
208
|
-
if (member.type->primitive == PrimitiveKind::Float32) {
|
|
209
|
-
float f = *(float *)ptr;
|
|
210
|
-
obj.Set(member.name, Napi::Number::New(env, (double)f));
|
|
211
|
-
} else if (member.type->primitive == PrimitiveKind::Float64) {
|
|
212
|
-
double d = *(double *)ptr;
|
|
213
|
-
obj.Set(member.name, Napi::Number::New(env, d));
|
|
214
|
-
} else {
|
|
215
|
-
RG_UNREACHABLE();
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
ptr += member.type->size;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
return obj;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
|
|
225
|
-
{
|
|
226
|
-
// Sanity checks
|
|
227
|
-
if (info.Length() < (uint32_t)func->parameters.len) {
|
|
228
|
-
ThrowError<Napi::TypeError>(env, "Expected %1 arguments, got %2", func->parameters.len, info.Length());
|
|
229
|
-
return env.Null();
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
uint8_t *return_ptr = nullptr;
|
|
233
167
|
uint8_t *args_ptr = nullptr;
|
|
234
168
|
uint32_t *gpr_ptr = nullptr;
|
|
235
169
|
uint32_t *vec_ptr = nullptr;
|
|
@@ -239,19 +173,17 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
|
|
|
239
173
|
// In the armv7hf calling convention, some arguments can end up
|
|
240
174
|
// partially in GPR, partially in the stack.
|
|
241
175
|
if (RG_UNLIKELY(!AllocStack(func->args_size, 16, &args_ptr)))
|
|
242
|
-
return
|
|
176
|
+
return false;
|
|
243
177
|
if (RG_UNLIKELY(!AllocStack(4 * 4, 8, &gpr_ptr)))
|
|
244
|
-
return
|
|
178
|
+
return false;
|
|
245
179
|
if (RG_UNLIKELY(!AllocStack(8 * 8, 8, &vec_ptr)))
|
|
246
|
-
return
|
|
180
|
+
return false;
|
|
247
181
|
if (func->ret.use_memory) {
|
|
248
182
|
if (RG_UNLIKELY(!AllocHeap(func->ret.type->size, 16, &return_ptr)))
|
|
249
|
-
return
|
|
183
|
+
return false;
|
|
250
184
|
*(uint8_t **)(gpr_ptr++) = return_ptr;
|
|
251
185
|
}
|
|
252
186
|
|
|
253
|
-
LocalArray<OutObject, MaxOutParameters> out_objects;
|
|
254
|
-
|
|
255
187
|
// Push arguments
|
|
256
188
|
for (Size i = 0; i < func->parameters.len; i++) {
|
|
257
189
|
const ParameterInfo ¶m = func->parameters[i];
|
|
@@ -265,7 +197,7 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
|
|
|
265
197
|
case PrimitiveKind::Bool: {
|
|
266
198
|
if (RG_UNLIKELY(!value.IsBoolean())) {
|
|
267
199
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected boolean", GetValueType(instance, value), i + 1);
|
|
268
|
-
return
|
|
200
|
+
return false;
|
|
269
201
|
}
|
|
270
202
|
|
|
271
203
|
bool b = value.As<Napi::Boolean>();
|
|
@@ -285,7 +217,7 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
|
|
|
285
217
|
case PrimitiveKind::UInt32: {
|
|
286
218
|
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
287
219
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
|
|
288
|
-
return
|
|
220
|
+
return false;
|
|
289
221
|
}
|
|
290
222
|
|
|
291
223
|
int64_t v = CopyNumber<int64_t>(value);
|
|
@@ -301,7 +233,7 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
|
|
|
301
233
|
case PrimitiveKind::UInt64: {
|
|
302
234
|
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
303
235
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
|
|
304
|
-
return
|
|
236
|
+
return false;
|
|
305
237
|
}
|
|
306
238
|
|
|
307
239
|
int64_t v = CopyNumber<int64_t>(value);
|
|
@@ -315,54 +247,17 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
|
|
|
315
247
|
args_ptr += 8;
|
|
316
248
|
}
|
|
317
249
|
} break;
|
|
318
|
-
case PrimitiveKind::Float32: {
|
|
319
|
-
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
320
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
|
|
321
|
-
return env.Null();
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
float f = CopyNumber<float>(value);
|
|
325
|
-
|
|
326
|
-
if (RG_LIKELY(param.vec_count)) {
|
|
327
|
-
memcpy(vec_ptr++, &f, 4);
|
|
328
|
-
} else if (param.gpr_count) {
|
|
329
|
-
memcpy(gpr_ptr++, &f, 4);
|
|
330
|
-
} else {
|
|
331
|
-
memcpy(args_ptr, &f, 4);
|
|
332
|
-
args_ptr += 4;
|
|
333
|
-
}
|
|
334
|
-
} break;
|
|
335
|
-
case PrimitiveKind::Float64: {
|
|
336
|
-
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
337
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
|
|
338
|
-
return env.Null();
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
double d = CopyNumber<double>(value);
|
|
342
|
-
|
|
343
|
-
if (RG_LIKELY(param.vec_count)) {
|
|
344
|
-
memcpy(vec_ptr, &d, 8);
|
|
345
|
-
vec_ptr += 2;
|
|
346
|
-
} else if (param.gpr_count) {
|
|
347
|
-
memcpy(gpr_ptr, &d, 8);
|
|
348
|
-
gpr_ptr += 2;
|
|
349
|
-
} else {
|
|
350
|
-
args_ptr = AlignUp(args_ptr, 8);
|
|
351
|
-
memcpy(args_ptr, &d, 8);
|
|
352
|
-
args_ptr += 8;
|
|
353
|
-
}
|
|
354
|
-
} break;
|
|
355
250
|
case PrimitiveKind::String: {
|
|
356
251
|
const char *str;
|
|
357
252
|
if (RG_LIKELY(value.IsString())) {
|
|
358
253
|
str = PushString(value);
|
|
359
254
|
if (RG_UNLIKELY(!str))
|
|
360
|
-
return
|
|
255
|
+
return false;
|
|
361
256
|
} else if (IsNullOrUndefined(value)) {
|
|
362
257
|
str = nullptr;
|
|
363
258
|
} else {
|
|
364
259
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected string", GetValueType(instance, value), i + 1);
|
|
365
|
-
return
|
|
260
|
+
return false;
|
|
366
261
|
}
|
|
367
262
|
|
|
368
263
|
if (RG_LIKELY(param.gpr_count)) {
|
|
@@ -377,12 +272,12 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
|
|
|
377
272
|
if (RG_LIKELY(value.IsString())) {
|
|
378
273
|
str16 = PushString16(value);
|
|
379
274
|
if (RG_UNLIKELY(!str16))
|
|
380
|
-
return
|
|
275
|
+
return false;
|
|
381
276
|
} else if (IsNullOrUndefined(value)) {
|
|
382
277
|
str16 = nullptr;
|
|
383
278
|
} else {
|
|
384
279
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected string", GetValueType(instance, value), i + 1);
|
|
385
|
-
return
|
|
280
|
+
return false;
|
|
386
281
|
}
|
|
387
282
|
|
|
388
283
|
if (RG_LIKELY(param.gpr_count)) {
|
|
@@ -401,11 +296,11 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
|
|
|
401
296
|
Napi::Object obj = value.As<Napi::Object>();
|
|
402
297
|
|
|
403
298
|
if (RG_UNLIKELY(!AllocHeap(param.type->ref->size, 16, &ptr)))
|
|
404
|
-
return
|
|
299
|
+
return false;
|
|
405
300
|
|
|
406
301
|
if (param.directions & 1) {
|
|
407
302
|
if (!PushObject(obj, param.type->ref, ptr))
|
|
408
|
-
return
|
|
303
|
+
return false;
|
|
409
304
|
} else {
|
|
410
305
|
memset(ptr, 0, param.type->size);
|
|
411
306
|
}
|
|
@@ -417,7 +312,7 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
|
|
|
417
312
|
ptr = nullptr;
|
|
418
313
|
} else {
|
|
419
314
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected %3", GetValueType(instance, value), i + 1, param.type->name);
|
|
420
|
-
return
|
|
315
|
+
return false;
|
|
421
316
|
}
|
|
422
317
|
|
|
423
318
|
if (RG_LIKELY(param.gpr_count)) {
|
|
@@ -427,140 +322,153 @@ Napi::Value CallData::Execute(const Napi::CallbackInfo &info)
|
|
|
427
322
|
args_ptr += 4;
|
|
428
323
|
}
|
|
429
324
|
} break;
|
|
430
|
-
|
|
431
325
|
case PrimitiveKind::Record: {
|
|
432
326
|
if (RG_UNLIKELY(!IsObject(value))) {
|
|
433
327
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected object", GetValueType(instance, value), i + 1);
|
|
434
|
-
return
|
|
328
|
+
return false;
|
|
435
329
|
}
|
|
436
330
|
|
|
437
331
|
Napi::Object obj = value.As<Napi::Object>();
|
|
438
332
|
|
|
439
333
|
if (param.vec_count) {
|
|
440
|
-
if (!
|
|
441
|
-
return
|
|
334
|
+
if (!PushObject(obj, param.type, (uint8_t *)vec_ptr))
|
|
335
|
+
return false;
|
|
442
336
|
vec_ptr += param.vec_count;
|
|
443
|
-
} else {
|
|
444
|
-
|
|
445
|
-
RG_ASSERT(param.type->align <= 8);
|
|
337
|
+
} else if (param.gpr_count) {
|
|
338
|
+
RG_ASSERT(param.type->align <= 8);
|
|
446
339
|
|
|
447
|
-
|
|
448
|
-
|
|
340
|
+
if (!PushObject(obj, param.type, (uint8_t *)gpr_ptr))
|
|
341
|
+
return false;
|
|
449
342
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
343
|
+
gpr_ptr += param.gpr_count;
|
|
344
|
+
args_ptr += AlignLen(param.type->size - param.gpr_count * 4, 4);
|
|
345
|
+
} else if (param.type->size) {
|
|
346
|
+
int16_t align = (param.type->align <= 4) ? 4 : 8;
|
|
454
347
|
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
348
|
+
args_ptr = AlignUp(args_ptr, align);
|
|
349
|
+
if (!PushObject(obj, param.type, args_ptr))
|
|
350
|
+
return false;
|
|
351
|
+
args_ptr += AlignLen(param.type->size, 4);
|
|
352
|
+
}
|
|
353
|
+
} break;
|
|
354
|
+
case PrimitiveKind::Float32: {
|
|
355
|
+
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
356
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
|
|
357
|
+
return false;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
float f = CopyNumber<float>(value);
|
|
361
|
+
|
|
362
|
+
if (RG_LIKELY(param.vec_count)) {
|
|
363
|
+
memcpy(vec_ptr++, &f, 4);
|
|
364
|
+
} else if (param.gpr_count) {
|
|
365
|
+
memcpy(gpr_ptr++, &f, 4);
|
|
366
|
+
} else {
|
|
367
|
+
memcpy(args_ptr, &f, 4);
|
|
368
|
+
args_ptr += 4;
|
|
369
|
+
}
|
|
370
|
+
} break;
|
|
371
|
+
case PrimitiveKind::Float64: {
|
|
372
|
+
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
373
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
|
|
374
|
+
return false;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
double d = CopyNumber<double>(value);
|
|
378
|
+
|
|
379
|
+
if (RG_LIKELY(param.vec_count)) {
|
|
380
|
+
memcpy(vec_ptr, &d, 8);
|
|
381
|
+
vec_ptr += 2;
|
|
382
|
+
} else if (param.gpr_count) {
|
|
383
|
+
memcpy(gpr_ptr, &d, 8);
|
|
384
|
+
gpr_ptr += 2;
|
|
385
|
+
} else {
|
|
386
|
+
args_ptr = AlignUp(args_ptr, 8);
|
|
387
|
+
memcpy(args_ptr, &d, 8);
|
|
388
|
+
args_ptr += 8;
|
|
460
389
|
}
|
|
461
390
|
} break;
|
|
462
391
|
}
|
|
463
392
|
}
|
|
464
393
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
}
|
|
394
|
+
return true;
|
|
395
|
+
}
|
|
468
396
|
|
|
397
|
+
void CallData::Execute()
|
|
398
|
+
{
|
|
469
399
|
#define PERFORM_CALL(Suffix) \
|
|
470
400
|
([&]() { \
|
|
471
401
|
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func, GetSP()) \
|
|
472
402
|
: ForwardCall ## Suffix(func->func, GetSP())); \
|
|
473
|
-
PopOutArguments(out_objects); \
|
|
474
403
|
return ret; \
|
|
475
404
|
})()
|
|
476
405
|
|
|
477
406
|
// Execute and convert return value
|
|
478
407
|
switch (func->ret.type->primitive) {
|
|
479
|
-
case PrimitiveKind::Void:
|
|
480
|
-
|
|
481
|
-
return env.Null();
|
|
482
|
-
} break;
|
|
483
|
-
case PrimitiveKind::Bool: {
|
|
484
|
-
uint32_t r0 = (uint32_t)PERFORM_CALL(GG);
|
|
485
|
-
return Napi::Boolean::New(env, r0);
|
|
486
|
-
} break;
|
|
408
|
+
case PrimitiveKind::Void:
|
|
409
|
+
case PrimitiveKind::Bool:
|
|
487
410
|
case PrimitiveKind::Int8:
|
|
488
411
|
case PrimitiveKind::UInt8:
|
|
489
412
|
case PrimitiveKind::Int16:
|
|
490
413
|
case PrimitiveKind::UInt16:
|
|
491
414
|
case PrimitiveKind::Int32:
|
|
492
|
-
case PrimitiveKind::UInt32:
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
case PrimitiveKind::
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
float f = PERFORM_CALL(F);
|
|
506
|
-
return Napi::Number::New(env, (double)f);
|
|
507
|
-
} break;
|
|
508
|
-
case PrimitiveKind::Float64: {
|
|
509
|
-
HfaRet ret = PERFORM_CALL(DDDD);
|
|
510
|
-
return Napi::Number::New(env, (double)ret.d0);
|
|
511
|
-
} break;
|
|
512
|
-
case PrimitiveKind::String: {
|
|
513
|
-
uint32_t r0 = (uint32_t)PERFORM_CALL(GG);
|
|
514
|
-
return Napi::String::New(env, (const char *)r0);
|
|
515
|
-
} break;
|
|
516
|
-
case PrimitiveKind::String16: {
|
|
517
|
-
uint32_t r0 = (uint32_t)PERFORM_CALL(GG);
|
|
518
|
-
return Napi::String::New(env, (const char16_t *)r0);
|
|
415
|
+
case PrimitiveKind::UInt32:
|
|
416
|
+
case PrimitiveKind::Int64:
|
|
417
|
+
case PrimitiveKind::UInt64:
|
|
418
|
+
case PrimitiveKind::String:
|
|
419
|
+
case PrimitiveKind::String16:
|
|
420
|
+
case PrimitiveKind::Pointer: { result.u64 = PERFORM_CALL(GG); } break;
|
|
421
|
+
case PrimitiveKind::Record: {
|
|
422
|
+
if (func->ret.vec_count) {
|
|
423
|
+
HfaRet ret = PERFORM_CALL(DDDD);
|
|
424
|
+
memcpy_safe(&result.buf, &ret, RG_SIZE(ret));
|
|
425
|
+
} else {
|
|
426
|
+
result.u64 = PERFORM_CALL(GG);
|
|
427
|
+
}
|
|
519
428
|
} break;
|
|
520
|
-
case PrimitiveKind::
|
|
521
|
-
|
|
522
|
-
|
|
429
|
+
case PrimitiveKind::Float32: { result.f = PERFORM_CALL(F); } break;
|
|
430
|
+
case PrimitiveKind::Float64: { result.d = PERFORM_CALL(DDDD).d0; } break;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
#undef PERFORM_CALL
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
Napi::Value CallData::Complete()
|
|
437
|
+
{
|
|
438
|
+
for (const OutObject &obj: out_objects) {
|
|
439
|
+
PopObject(obj.obj, obj.ptr, obj.type);
|
|
440
|
+
}
|
|
523
441
|
|
|
524
|
-
|
|
442
|
+
switch (func->ret.type->primitive) {
|
|
443
|
+
case PrimitiveKind::Void: return env.Null();
|
|
444
|
+
case PrimitiveKind::Bool: return Napi::Boolean::New(env, result.u32);
|
|
445
|
+
case PrimitiveKind::Int8:
|
|
446
|
+
case PrimitiveKind::UInt8:
|
|
447
|
+
case PrimitiveKind::Int16:
|
|
448
|
+
case PrimitiveKind::UInt16:
|
|
449
|
+
case PrimitiveKind::Int32:
|
|
450
|
+
case PrimitiveKind::UInt32: return Napi::Number::New(env, (double)result.u32);
|
|
451
|
+
case PrimitiveKind::Int64: return Napi::BigInt::New(env, (int64_t)result.u64);
|
|
452
|
+
case PrimitiveKind::UInt64: return Napi::BigInt::New(env, result.u64);
|
|
453
|
+
case PrimitiveKind::String: return Napi::String::New(env, (const char *)result.ptr);
|
|
454
|
+
case PrimitiveKind::String16: return Napi::String::New(env, (const char16_t *)result.ptr);
|
|
455
|
+
case PrimitiveKind::Pointer: {
|
|
456
|
+
Napi::External<void> external = Napi::External<void>::New(env, result.ptr);
|
|
525
457
|
SetValueTag(instance, external, func->ret.type);
|
|
526
458
|
|
|
527
459
|
return external;
|
|
528
460
|
} break;
|
|
529
|
-
|
|
530
461
|
case PrimitiveKind::Record: {
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
uint64_t ret = PERFORM_CALL(GG);
|
|
535
|
-
uint32_t r0 = (uint32_t)ret;
|
|
462
|
+
const uint8_t *ptr = return_ptr ? (const uint8_t *)return_ptr
|
|
463
|
+
: (const uint8_t *)&result.buf;
|
|
536
464
|
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
} else if (func->ret.vec_count) {
|
|
540
|
-
HfaRet ret = PERFORM_CALL(DDDD);
|
|
541
|
-
|
|
542
|
-
Napi::Object obj = PopHFA(env, (const uint8_t *)&ret, func->ret.type);
|
|
543
|
-
return obj;
|
|
544
|
-
} else if (func->ret.type->size) {
|
|
545
|
-
RG_ASSERT(return_ptr);
|
|
546
|
-
|
|
547
|
-
uint64_t ret = PERFORM_CALL(GG);
|
|
548
|
-
uint32_t r0 = (uint32_t)ret;
|
|
549
|
-
RG_ASSERT(r0 == (uint32_t)return_ptr);
|
|
550
|
-
|
|
551
|
-
Napi::Object obj = PopObject(env, return_ptr, func->ret.type);
|
|
552
|
-
return obj;
|
|
553
|
-
} else {
|
|
554
|
-
PERFORM_CALL(GG);
|
|
555
|
-
|
|
556
|
-
Napi::Object obj = Napi::Object::New(env);
|
|
557
|
-
return obj;
|
|
558
|
-
}
|
|
465
|
+
Napi::Object obj = PopObject(ptr, func->ret.type);
|
|
466
|
+
return obj;
|
|
559
467
|
} break;
|
|
468
|
+
case PrimitiveKind::Float32: return Napi::Number::New(env, (double)result.f);
|
|
469
|
+
case PrimitiveKind::Float64: return Napi::Number::New(env, result.d);
|
|
560
470
|
}
|
|
561
471
|
|
|
562
|
-
#undef PERFORM_CALL
|
|
563
|
-
|
|
564
472
|
RG_UNREACHABLE();
|
|
565
473
|
}
|
|
566
474
|
|