koffi 1.0.5 → 1.1.0-beta.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 +4 -0
- package/README.md +54 -24
- package/build/qemu/1.1.0-beta.2/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/1.1.0-beta.2/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/1.1.0-beta.2/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/1.1.0-beta.2/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/1.1.0-beta.2/koffi_linux_arm.tar.gz +0 -0
- package/build/qemu/1.1.0-beta.2/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/1.1.0-beta.2/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/1.1.0-beta.2/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/1.1.0-beta.2/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/1.1.0-beta.2/koffi_win32_x64.tar.gz +0 -0
- package/package.json +1 -1
- package/qemu/qemu.js +12 -5
- package/qemu/registry/machines.json +20 -10
- package/src/abi_arm32.cc +40 -51
- package/src/abi_arm64.cc +71 -138
- package/src/abi_x64_sysv.cc +37 -13
- package/src/abi_x64_win.cc +16 -6
- package/src/abi_x86.cc +16 -6
- package/src/call.cc +564 -58
- package/src/call.hh +32 -44
- package/src/ffi.cc +218 -19
- package/src/ffi.hh +27 -11
- package/src/parser.cc +4 -0
- package/src/util.cc +72 -0
- package/src/util.hh +2 -0
- package/test/misc.c +16 -10
- 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/test/misc.js +0 -227
package/src/call.cc
CHANGED
|
@@ -20,19 +20,24 @@
|
|
|
20
20
|
|
|
21
21
|
namespace RG {
|
|
22
22
|
|
|
23
|
-
CallData::CallData(Napi::Env env,
|
|
24
|
-
: env(env), instance(
|
|
25
|
-
|
|
26
|
-
old_stack_mem(instance->stack_mem), old_heap_mem(instance->heap_mem)
|
|
23
|
+
CallData::CallData(Napi::Env env, const FunctionInfo *func, InstanceMemory *mem, bool debug)
|
|
24
|
+
: env(env), instance(env.GetInstanceData<InstanceData>()), func(func), debug(debug),
|
|
25
|
+
mem(mem), old_stack_mem(mem->stack), old_heap_mem(mem->heap)
|
|
27
26
|
{
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
mem->depth++;
|
|
28
|
+
|
|
29
|
+
RG_ASSERT(AlignUp(mem->stack.ptr, 16) == mem->stack.ptr);
|
|
30
|
+
RG_ASSERT(AlignUp(mem->stack.end(), 16) == mem->stack.end());
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
CallData::~CallData()
|
|
33
34
|
{
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
mem->stack = old_stack_mem;
|
|
36
|
+
mem->heap = old_heap_mem;
|
|
37
|
+
|
|
38
|
+
if (!--mem->depth && mem->temporary) {
|
|
39
|
+
delete mem;
|
|
40
|
+
}
|
|
36
41
|
}
|
|
37
42
|
|
|
38
43
|
const char *CallData::PushString(const Napi::Value &value)
|
|
@@ -45,8 +50,8 @@ const char *CallData::PushString(const Napi::Value &value)
|
|
|
45
50
|
size_t len = 0;
|
|
46
51
|
napi_status status;
|
|
47
52
|
|
|
48
|
-
buf.ptr = (char *)
|
|
49
|
-
buf.len = std::max((Size)0,
|
|
53
|
+
buf.ptr = (char *)mem->heap.ptr;
|
|
54
|
+
buf.len = std::max((Size)0, mem->heap.len - Kibibytes(32));
|
|
50
55
|
|
|
51
56
|
status = napi_get_value_string_utf8(env, value, buf.ptr, (size_t)buf.len, &len);
|
|
52
57
|
RG_ASSERT(status == napi_ok);
|
|
@@ -54,15 +59,15 @@ const char *CallData::PushString(const Napi::Value &value)
|
|
|
54
59
|
len++;
|
|
55
60
|
|
|
56
61
|
if (RG_LIKELY(len < (size_t)buf.len)) {
|
|
57
|
-
|
|
58
|
-
|
|
62
|
+
mem->heap.ptr += (Size)len;
|
|
63
|
+
mem->heap.len -= (Size)len;
|
|
59
64
|
} else {
|
|
60
65
|
status = napi_get_value_string_utf8(env, value, nullptr, 0, &len);
|
|
61
66
|
RG_ASSERT(status == napi_ok);
|
|
62
67
|
|
|
63
68
|
len++;
|
|
64
69
|
|
|
65
|
-
buf.ptr = (char *)Allocator::Allocate(&big_alloc, (Size)len);
|
|
70
|
+
buf.ptr = (char *)Allocator::Allocate(&mem->big_alloc, (Size)len);
|
|
66
71
|
buf.len = (Size)len;
|
|
67
72
|
|
|
68
73
|
status = napi_get_value_string_utf8(env, value, buf.ptr, (size_t)buf.len, &len);
|
|
@@ -82,8 +87,8 @@ const char16_t *CallData::PushString16(const Napi::Value &value)
|
|
|
82
87
|
size_t len = 0;
|
|
83
88
|
napi_status status;
|
|
84
89
|
|
|
85
|
-
buf.ptr = (char16_t *)
|
|
86
|
-
buf.len = std::max((Size)0,
|
|
90
|
+
buf.ptr = (char16_t *)mem->heap.ptr;
|
|
91
|
+
buf.len = std::max((Size)0, mem->heap.len - Kibibytes(32)) / 2;
|
|
87
92
|
|
|
88
93
|
status = napi_get_value_string_utf16(env, value, buf.ptr, (size_t)buf.len, &len);
|
|
89
94
|
RG_ASSERT(status == napi_ok);
|
|
@@ -91,15 +96,15 @@ const char16_t *CallData::PushString16(const Napi::Value &value)
|
|
|
91
96
|
len++;
|
|
92
97
|
|
|
93
98
|
if (RG_LIKELY(len < (size_t)buf.len)) {
|
|
94
|
-
|
|
95
|
-
|
|
99
|
+
mem->heap.ptr += (Size)len * 2;
|
|
100
|
+
mem->heap.len -= (Size)len * 2;
|
|
96
101
|
} else {
|
|
97
102
|
status = napi_get_value_string_utf16(env, value, nullptr, 0, &len);
|
|
98
103
|
RG_ASSERT(status == napi_ok);
|
|
99
104
|
|
|
100
105
|
len++;
|
|
101
106
|
|
|
102
|
-
buf.ptr = (char16_t *)Allocator::Allocate(&big_alloc, (Size)len * 2);
|
|
107
|
+
buf.ptr = (char16_t *)Allocator::Allocate(&mem->big_alloc, (Size)len * 2);
|
|
103
108
|
buf.len = (Size)len;
|
|
104
109
|
|
|
105
110
|
status = napi_get_value_string_utf16(env, value, buf.ptr, (size_t)buf.len, &len);
|
|
@@ -109,11 +114,8 @@ const char16_t *CallData::PushString16(const Napi::Value &value)
|
|
|
109
114
|
return buf.ptr;
|
|
110
115
|
}
|
|
111
116
|
|
|
112
|
-
bool CallData::PushObject(const Napi::Object &obj, const TypeInfo *type, uint8_t *dest)
|
|
117
|
+
bool CallData::PushObject(const Napi::Object &obj, const TypeInfo *type, uint8_t *dest, int16_t realign)
|
|
113
118
|
{
|
|
114
|
-
Napi::Env env = obj.Env();
|
|
115
|
-
InstanceData *instance = env.GetInstanceData<InstanceData>();
|
|
116
|
-
|
|
117
119
|
RG_ASSERT(IsObject(obj));
|
|
118
120
|
RG_ASSERT(type->primitive == PrimitiveKind::Record);
|
|
119
121
|
|
|
@@ -125,21 +127,21 @@ bool CallData::PushObject(const Napi::Object &obj, const TypeInfo *type, uint8_t
|
|
|
125
127
|
return false;
|
|
126
128
|
}
|
|
127
129
|
|
|
128
|
-
|
|
130
|
+
int16_t align = std::max(member.align, realign);
|
|
131
|
+
dest = AlignUp(dest, align);
|
|
129
132
|
|
|
130
133
|
switch (member.type->primitive) {
|
|
131
134
|
case PrimitiveKind::Void: { RG_UNREACHABLE(); } break;
|
|
132
135
|
|
|
133
136
|
case PrimitiveKind::Bool: {
|
|
134
137
|
if (RG_UNLIKELY(!value.IsBoolean())) {
|
|
135
|
-
ThrowError<Napi::TypeError>(env, "Unexpected
|
|
138
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for member '%2', expected boolean", GetValueType(instance, value), member.name);
|
|
136
139
|
return false;
|
|
137
140
|
}
|
|
138
141
|
|
|
139
142
|
bool b = value.As<Napi::Boolean>();
|
|
140
143
|
*(bool *)dest = b;
|
|
141
144
|
} break;
|
|
142
|
-
|
|
143
145
|
case PrimitiveKind::Int8:
|
|
144
146
|
case PrimitiveKind::UInt8:
|
|
145
147
|
case PrimitiveKind::Int16:
|
|
@@ -149,7 +151,7 @@ bool CallData::PushObject(const Napi::Object &obj, const TypeInfo *type, uint8_t
|
|
|
149
151
|
case PrimitiveKind::Int64:
|
|
150
152
|
case PrimitiveKind::UInt64: {
|
|
151
153
|
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
152
|
-
ThrowError<Napi::TypeError>(env, "Unexpected
|
|
154
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for member '%2', expected number", GetValueType(instance, value), member.name);
|
|
153
155
|
return false;
|
|
154
156
|
}
|
|
155
157
|
|
|
@@ -158,7 +160,7 @@ bool CallData::PushObject(const Napi::Object &obj, const TypeInfo *type, uint8_t
|
|
|
158
160
|
} break;
|
|
159
161
|
case PrimitiveKind::String: {
|
|
160
162
|
if (RG_UNLIKELY(!value.IsString())) {
|
|
161
|
-
ThrowError<Napi::TypeError>(env, "Unexpected
|
|
163
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for member '%2', expected string", GetValueType(instance, value), member.name);
|
|
162
164
|
return false;
|
|
163
165
|
}
|
|
164
166
|
|
|
@@ -169,7 +171,7 @@ bool CallData::PushObject(const Napi::Object &obj, const TypeInfo *type, uint8_t
|
|
|
169
171
|
} break;
|
|
170
172
|
case PrimitiveKind::String16: {
|
|
171
173
|
if (RG_UNLIKELY(!value.IsString())) {
|
|
172
|
-
ThrowError<Napi::TypeError>(env, "Unexpected
|
|
174
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for member '%2', expected string", GetValueType(instance, value), member.name);
|
|
173
175
|
return false;
|
|
174
176
|
}
|
|
175
177
|
|
|
@@ -190,31 +192,41 @@ bool CallData::PushObject(const Napi::Object &obj, const TypeInfo *type, uint8_t
|
|
|
190
192
|
} break;
|
|
191
193
|
case PrimitiveKind::Record: {
|
|
192
194
|
if (RG_UNLIKELY(!IsObject(value))) {
|
|
193
|
-
ThrowError<Napi::TypeError>(env, "Unexpected
|
|
195
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for member '%2', expected object", GetValueType(instance, value), member.name);
|
|
194
196
|
return false;
|
|
195
197
|
}
|
|
196
198
|
|
|
197
199
|
Napi::Object obj = value.As<Napi::Object>();
|
|
198
|
-
if (!PushObject(obj, member.type, dest))
|
|
200
|
+
if (!PushObject(obj, member.type, dest, realign))
|
|
201
|
+
return false;
|
|
202
|
+
} break;
|
|
203
|
+
case PrimitiveKind::Array: {
|
|
204
|
+
if (RG_UNLIKELY(!value.IsArray() && !value.IsTypedArray())) {
|
|
205
|
+
ThrowError<Napi::TypeError>(env, "Unexpected value %1 for member '%2', expected array", GetValueType(instance, value), member.name);
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
Napi::Array array = value.As<Napi::Array>();
|
|
210
|
+
if (!PushArray(array, member.type, dest, realign))
|
|
199
211
|
return false;
|
|
200
212
|
} break;
|
|
201
213
|
case PrimitiveKind::Float32: {
|
|
202
214
|
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
203
|
-
ThrowError<Napi::TypeError>(env, "Unexpected
|
|
215
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for member '%2', expected number", GetValueType(instance, value), member.name);
|
|
204
216
|
return false;
|
|
205
217
|
}
|
|
206
218
|
|
|
207
219
|
float f = CopyNumber<float>(value);
|
|
208
|
-
|
|
220
|
+
*(float *)dest = f;
|
|
209
221
|
} break;
|
|
210
222
|
case PrimitiveKind::Float64: {
|
|
211
223
|
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
212
|
-
ThrowError<Napi::TypeError>(env, "Unexpected
|
|
224
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for member '%2', expected number", GetValueType(instance, value), member.name);
|
|
213
225
|
return false;
|
|
214
226
|
}
|
|
215
227
|
|
|
216
228
|
double d = CopyNumber<double>(value);
|
|
217
|
-
|
|
229
|
+
*(double *)dest = d;
|
|
218
230
|
} break;
|
|
219
231
|
}
|
|
220
232
|
|
|
@@ -224,65 +236,297 @@ bool CallData::PushObject(const Napi::Object &obj, const TypeInfo *type, uint8_t
|
|
|
224
236
|
return true;
|
|
225
237
|
}
|
|
226
238
|
|
|
227
|
-
|
|
239
|
+
bool CallData::PushArray(const Napi::Object &obj, const TypeInfo *type, uint8_t *dest, int16_t realign)
|
|
228
240
|
{
|
|
229
|
-
|
|
230
|
-
|
|
241
|
+
RG_ASSERT(obj.IsArray() || obj.IsTypedArray());
|
|
242
|
+
RG_ASSERT(type->primitive == PrimitiveKind::Array);
|
|
243
|
+
|
|
244
|
+
uint32_t len = type->size / type->ref->size;
|
|
245
|
+
|
|
246
|
+
if (obj.IsArray()) {
|
|
247
|
+
Napi::Array array = obj.As<Napi::Array>();
|
|
248
|
+
|
|
249
|
+
if (array.Length() != len) {
|
|
250
|
+
ThrowError<Napi::Error>(env, "Expected array of length %1, got %2", len, array.Length());
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
switch (type->ref->primitive) {
|
|
255
|
+
case PrimitiveKind::Void: { RG_UNREACHABLE(); } break;
|
|
256
|
+
|
|
257
|
+
case PrimitiveKind::Bool: {
|
|
258
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
259
|
+
Napi::Value value = array[i];
|
|
260
|
+
|
|
261
|
+
int16_t align = std::max(type->ref->align, realign);
|
|
262
|
+
dest = AlignUp(dest, align);
|
|
263
|
+
|
|
264
|
+
if (RG_UNLIKELY(!value.IsBoolean())) {
|
|
265
|
+
ThrowError<Napi::TypeError>(env, "Unexpected value %1 in array, expected boolean", GetValueType(instance, value));
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
bool b = value.As<Napi::Boolean>();
|
|
270
|
+
*(bool *)dest = b;
|
|
271
|
+
|
|
272
|
+
dest += type->ref->size;
|
|
273
|
+
}
|
|
274
|
+
} break;
|
|
275
|
+
case PrimitiveKind::Int8:
|
|
276
|
+
case PrimitiveKind::UInt8:
|
|
277
|
+
case PrimitiveKind::Int16:
|
|
278
|
+
case PrimitiveKind::UInt16:
|
|
279
|
+
case PrimitiveKind::Int32:
|
|
280
|
+
case PrimitiveKind::UInt32:
|
|
281
|
+
case PrimitiveKind::Int64:
|
|
282
|
+
case PrimitiveKind::UInt64: {
|
|
283
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
284
|
+
Napi::Value value = array[i];
|
|
285
|
+
|
|
286
|
+
int16_t align = std::max(type->ref->align, realign);
|
|
287
|
+
dest = AlignUp(dest, align);
|
|
288
|
+
|
|
289
|
+
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
290
|
+
ThrowError<Napi::TypeError>(env, "Unexpected value %1 in array, expected number", GetValueType(instance, value));
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
int64_t v = CopyNumber<int64_t>(value);
|
|
295
|
+
memcpy(dest, &v, type->ref->size); // Little Endian
|
|
296
|
+
|
|
297
|
+
dest += type->ref->size;
|
|
298
|
+
}
|
|
299
|
+
} break;
|
|
300
|
+
case PrimitiveKind::String: {
|
|
301
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
302
|
+
Napi::Value value = array[i];
|
|
303
|
+
|
|
304
|
+
int16_t align = std::max(type->ref->align, realign);
|
|
305
|
+
dest = AlignUp(dest, align);
|
|
306
|
+
|
|
307
|
+
if (RG_UNLIKELY(!value.IsString())) {
|
|
308
|
+
ThrowError<Napi::TypeError>(env, "Unexpected value %1 in array, expected string", GetValueType(instance, value));
|
|
309
|
+
return false;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const char *str = PushString(value);
|
|
313
|
+
if (RG_UNLIKELY(!str))
|
|
314
|
+
return false;
|
|
315
|
+
*(const char **)dest = str;
|
|
316
|
+
|
|
317
|
+
dest += type->ref->size;
|
|
318
|
+
}
|
|
319
|
+
} break;
|
|
320
|
+
case PrimitiveKind::String16: {
|
|
321
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
322
|
+
Napi::Value value = array[i];
|
|
323
|
+
|
|
324
|
+
int16_t align = std::max(type->ref->align, realign);
|
|
325
|
+
dest = AlignUp(dest, align);
|
|
326
|
+
|
|
327
|
+
if (RG_UNLIKELY(!value.IsString())) {
|
|
328
|
+
ThrowError<Napi::TypeError>(env, "Unexpected value %1 in array, expected string", GetValueType(instance, value));
|
|
329
|
+
return false;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const char16_t *str16 = PushString16(value);
|
|
333
|
+
if (RG_UNLIKELY(!str16))
|
|
334
|
+
return false;
|
|
335
|
+
*(const char16_t **)dest = str16;
|
|
336
|
+
|
|
337
|
+
dest += type->ref->size;
|
|
338
|
+
}
|
|
339
|
+
} break;
|
|
340
|
+
case PrimitiveKind::Pointer: {
|
|
341
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
342
|
+
Napi::Value value = array[i];
|
|
343
|
+
|
|
344
|
+
int16_t align = std::max(type->ref->align, realign);
|
|
345
|
+
dest = AlignUp(dest, align);
|
|
346
|
+
|
|
347
|
+
if (RG_UNLIKELY(!CheckValueTag(instance, value, type->ref))) {
|
|
348
|
+
ThrowError<Napi::TypeError>(env, "Unexpected value %1 in array, expected %2", GetValueType(instance, value), type->ref->name);
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
Napi::External external = value.As<Napi::External<void>>();
|
|
353
|
+
*(void **)dest = external.Data();
|
|
354
|
+
|
|
355
|
+
dest += type->ref->size;
|
|
356
|
+
}
|
|
357
|
+
} break;
|
|
358
|
+
case PrimitiveKind::Record: {
|
|
359
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
360
|
+
Napi::Value value = array[i];
|
|
361
|
+
|
|
362
|
+
int16_t align = std::max(type->ref->align, realign);
|
|
363
|
+
dest = AlignUp(dest, align);
|
|
364
|
+
|
|
365
|
+
if (RG_UNLIKELY(!IsObject(value))) {
|
|
366
|
+
ThrowError<Napi::TypeError>(env, "Unexpected value %1 in array, expected object", GetValueType(instance, value));
|
|
367
|
+
return false;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
Napi::Object obj = value.As<Napi::Object>();
|
|
371
|
+
if (!PushObject(obj, type->ref, dest, realign))
|
|
372
|
+
return false;
|
|
373
|
+
|
|
374
|
+
dest += type->ref->size;
|
|
375
|
+
}
|
|
376
|
+
} break;
|
|
377
|
+
case PrimitiveKind::Array: {
|
|
378
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
379
|
+
Napi::Value value = array[i];
|
|
380
|
+
|
|
381
|
+
int16_t align = std::max(type->ref->align, realign);
|
|
382
|
+
dest = AlignUp(dest, align);
|
|
383
|
+
|
|
384
|
+
if (RG_UNLIKELY(!value.IsArray() && !value.IsTypedArray())) {
|
|
385
|
+
ThrowError<Napi::TypeError>(env, "Unexpected value %1 in array, expected array", GetValueType(instance, value));
|
|
386
|
+
return false;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
Napi::Array array = value.As<Napi::Array>();
|
|
390
|
+
if (!PushArray(array, type->ref, dest, realign))
|
|
391
|
+
return false;
|
|
392
|
+
|
|
393
|
+
dest += type->ref->size;
|
|
394
|
+
}
|
|
395
|
+
} break;
|
|
396
|
+
case PrimitiveKind::Float32: {
|
|
397
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
398
|
+
Napi::Value value = array[i];
|
|
399
|
+
|
|
400
|
+
int16_t align = std::max(type->ref->align, realign);
|
|
401
|
+
dest = AlignUp(dest, align);
|
|
402
|
+
|
|
403
|
+
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
404
|
+
ThrowError<Napi::TypeError>(env, "Unexpected value %1 in array, expected number", GetValueType(instance, value));
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
float f = CopyNumber<float>(value);
|
|
409
|
+
*(float *)dest = f;
|
|
410
|
+
|
|
411
|
+
dest += type->ref->size;
|
|
412
|
+
}
|
|
413
|
+
} break;
|
|
414
|
+
case PrimitiveKind::Float64: {
|
|
415
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
416
|
+
Napi::Value value = array[i];
|
|
417
|
+
|
|
418
|
+
int16_t align = std::max(type->ref->align, realign);
|
|
419
|
+
dest = AlignUp(dest, align);
|
|
420
|
+
|
|
421
|
+
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
422
|
+
ThrowError<Napi::TypeError>(env, "Unexpected value %1 in array, expected number", GetValueType(instance, value));
|
|
423
|
+
return false;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
double d = CopyNumber<double>(value);
|
|
427
|
+
*(double *)dest = d;
|
|
428
|
+
|
|
429
|
+
dest += type->ref->size;
|
|
430
|
+
}
|
|
431
|
+
} break;
|
|
432
|
+
}
|
|
433
|
+
} else {
|
|
434
|
+
Napi::TypedArray array = obj.As<Napi::TypedArray>();
|
|
435
|
+
const uint8_t *buf = (const uint8_t *)array.ArrayBuffer().Data();
|
|
436
|
+
|
|
437
|
+
if (array.ElementLength() != len) {
|
|
438
|
+
ThrowError<Napi::Error>(env, "Expected array of length %1, got %2", len, array.ElementLength());
|
|
439
|
+
return false;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
bool match;
|
|
443
|
+
switch (type->ref->primitive) {
|
|
444
|
+
case PrimitiveKind::Int8: { match = (array.TypedArrayType() == napi_int8_array); } break;
|
|
445
|
+
case PrimitiveKind::UInt8: { match = (array.TypedArrayType() == napi_uint8_array); } break;
|
|
446
|
+
case PrimitiveKind::Int16: { match = (array.TypedArrayType() == napi_int16_array); } break;
|
|
447
|
+
case PrimitiveKind::UInt16: { match = (array.TypedArrayType() == napi_uint16_array); } break;
|
|
448
|
+
case PrimitiveKind::Int32: { match = (array.TypedArrayType() == napi_int32_array); } break;
|
|
449
|
+
case PrimitiveKind::UInt32: { match = (array.TypedArrayType() == napi_uint32_array); } break;
|
|
450
|
+
case PrimitiveKind::Float32: { match = (array.TypedArrayType() == napi_float32_array); } break;
|
|
451
|
+
case PrimitiveKind::Float64: { match = (array.TypedArrayType() == napi_float64_array); } break;
|
|
452
|
+
|
|
453
|
+
default: { match = false; } break;
|
|
454
|
+
}
|
|
455
|
+
if (!match) {
|
|
456
|
+
ThrowError<Napi::TypeError>(env, "TypedArray is not approriate for %1 array", type->ref->name);
|
|
457
|
+
return false;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
461
|
+
int16_t align = std::max(type->ref->align, realign);
|
|
462
|
+
dest = AlignUp(dest, align);
|
|
463
|
+
|
|
464
|
+
memcpy(dest, buf + i * type->ref->size, type->ref->size);
|
|
465
|
+
|
|
466
|
+
dest += type->ref->size;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
231
469
|
|
|
470
|
+
return true;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
void CallData::PopObject(Napi::Object obj, const uint8_t *src, const TypeInfo *type, int16_t realign)
|
|
474
|
+
{
|
|
232
475
|
RG_ASSERT(type->primitive == PrimitiveKind::Record);
|
|
233
476
|
|
|
234
477
|
for (const RecordMember &member: type->members) {
|
|
235
|
-
|
|
478
|
+
int16_t align = std::max(realign, member.align);
|
|
479
|
+
src = AlignUp(src, align);
|
|
236
480
|
|
|
237
481
|
switch (member.type->primitive) {
|
|
238
482
|
case PrimitiveKind::Void: { RG_UNREACHABLE(); } break;
|
|
239
483
|
|
|
240
484
|
case PrimitiveKind::Bool: {
|
|
241
|
-
bool b = *(bool *)
|
|
485
|
+
bool b = *(bool *)src;
|
|
242
486
|
obj.Set(member.name, Napi::Boolean::New(env, b));
|
|
243
487
|
} break;
|
|
244
488
|
case PrimitiveKind::Int8: {
|
|
245
|
-
double d = (double)*(int8_t *)
|
|
489
|
+
double d = (double)*(int8_t *)src;
|
|
246
490
|
obj.Set(member.name, Napi::Number::New(env, d));
|
|
247
491
|
} break;
|
|
248
492
|
case PrimitiveKind::UInt8: {
|
|
249
|
-
double d = (double)*(uint8_t *)
|
|
493
|
+
double d = (double)*(uint8_t *)src;
|
|
250
494
|
obj.Set(member.name, Napi::Number::New(env, d));
|
|
251
495
|
} break;
|
|
252
496
|
case PrimitiveKind::Int16: {
|
|
253
|
-
double d = (double)*(int16_t *)
|
|
497
|
+
double d = (double)*(int16_t *)src;
|
|
254
498
|
obj.Set(member.name, Napi::Number::New(env, d));
|
|
255
499
|
} break;
|
|
256
500
|
case PrimitiveKind::UInt16: {
|
|
257
|
-
double d = (double)*(uint16_t *)
|
|
501
|
+
double d = (double)*(uint16_t *)src;
|
|
258
502
|
obj.Set(member.name, Napi::Number::New(env, d));
|
|
259
503
|
} break;
|
|
260
504
|
case PrimitiveKind::Int32: {
|
|
261
|
-
double d = (double)*(int32_t *)
|
|
505
|
+
double d = (double)*(int32_t *)src;
|
|
262
506
|
obj.Set(member.name, Napi::Number::New(env, d));
|
|
263
507
|
} break;
|
|
264
508
|
case PrimitiveKind::UInt32: {
|
|
265
|
-
double d = (double)*(uint32_t *)
|
|
509
|
+
double d = (double)*(uint32_t *)src;
|
|
266
510
|
obj.Set(member.name, Napi::Number::New(env, d));
|
|
267
511
|
} break;
|
|
268
512
|
case PrimitiveKind::Int64: {
|
|
269
|
-
int64_t v = *(int64_t *)
|
|
513
|
+
int64_t v = *(int64_t *)src;
|
|
270
514
|
obj.Set(member.name, Napi::BigInt::New(env, v));
|
|
271
515
|
} break;
|
|
272
516
|
case PrimitiveKind::UInt64: {
|
|
273
|
-
uint64_t v = *(uint64_t *)
|
|
517
|
+
uint64_t v = *(uint64_t *)src;
|
|
274
518
|
obj.Set(member.name, Napi::BigInt::New(env, v));
|
|
275
519
|
} break;
|
|
276
520
|
case PrimitiveKind::String: {
|
|
277
|
-
const char *str = *(const char **)
|
|
521
|
+
const char *str = *(const char **)src;
|
|
278
522
|
obj.Set(member.name, Napi::String::New(env, str));
|
|
279
523
|
} break;
|
|
280
524
|
case PrimitiveKind::String16: {
|
|
281
|
-
const char16_t *str16 = *(const char16_t **)
|
|
525
|
+
const char16_t *str16 = *(const char16_t **)src;
|
|
282
526
|
obj.Set(member.name, Napi::String::New(env, str16));
|
|
283
527
|
} break;
|
|
284
528
|
case PrimitiveKind::Pointer: {
|
|
285
|
-
void *ptr2 = *(void **)
|
|
529
|
+
void *ptr2 = *(void **)src;
|
|
286
530
|
|
|
287
531
|
Napi::External<void> external = Napi::External<void>::New(env, ptr2);
|
|
288
532
|
SetValueTag(instance, external, member.type);
|
|
@@ -290,32 +534,294 @@ void CallData::PopObject(Napi::Object obj, const uint8_t *ptr, const TypeInfo *t
|
|
|
290
534
|
obj.Set(member.name, external);
|
|
291
535
|
} break;
|
|
292
536
|
case PrimitiveKind::Record: {
|
|
293
|
-
Napi::Object obj2 = PopObject(
|
|
537
|
+
Napi::Object obj2 = PopObject(src, member.type, realign);
|
|
538
|
+
obj.Set(member.name, obj2);
|
|
539
|
+
} break;
|
|
540
|
+
case PrimitiveKind::Array: {
|
|
541
|
+
Napi::Object obj2 = PopArray(src, member.type, realign);
|
|
294
542
|
obj.Set(member.name, obj2);
|
|
295
543
|
} break;
|
|
296
544
|
case PrimitiveKind::Float32: {
|
|
297
545
|
float f;
|
|
298
|
-
memcpy(&f,
|
|
546
|
+
memcpy(&f, src, 4);
|
|
299
547
|
obj.Set(member.name, Napi::Number::New(env, (double)f));
|
|
300
548
|
} break;
|
|
301
549
|
case PrimitiveKind::Float64: {
|
|
302
550
|
double d;
|
|
303
|
-
memcpy(&d,
|
|
551
|
+
memcpy(&d, src, 8);
|
|
304
552
|
obj.Set(member.name, Napi::Number::New(env, d));
|
|
305
553
|
} break;
|
|
306
554
|
}
|
|
307
555
|
|
|
308
|
-
|
|
556
|
+
src += member.type->size;
|
|
309
557
|
}
|
|
310
558
|
}
|
|
311
559
|
|
|
312
|
-
Napi::Object CallData::PopObject(const uint8_t *
|
|
560
|
+
Napi::Object CallData::PopObject(const uint8_t *src, const TypeInfo *type, int16_t realign)
|
|
313
561
|
{
|
|
314
562
|
Napi::Object obj = Napi::Object::New(env);
|
|
315
|
-
PopObject(obj,
|
|
563
|
+
PopObject(obj, src, type, realign);
|
|
316
564
|
return obj;
|
|
317
565
|
}
|
|
318
566
|
|
|
567
|
+
Napi::Object CallData::PopArray(const uint8_t *src, const TypeInfo *type, int16_t realign)
|
|
568
|
+
{
|
|
569
|
+
RG_ASSERT(type->primitive == PrimitiveKind::Array);
|
|
570
|
+
|
|
571
|
+
uint32_t len = type->size / type->ref->size;
|
|
572
|
+
|
|
573
|
+
switch (type->ref->primitive) {
|
|
574
|
+
case PrimitiveKind::Void: { RG_UNREACHABLE(); } break;
|
|
575
|
+
|
|
576
|
+
case PrimitiveKind::Bool: {
|
|
577
|
+
Napi::Array array = Napi::Array::New(env);
|
|
578
|
+
|
|
579
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
580
|
+
int16_t align = std::max(realign, type->ref->align);
|
|
581
|
+
src = AlignUp(src, align);
|
|
582
|
+
|
|
583
|
+
bool b = *(bool *)src;
|
|
584
|
+
array.Set(i, Napi::Boolean::New(env, b));
|
|
585
|
+
|
|
586
|
+
src += type->ref->size;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
return array;
|
|
590
|
+
} break;
|
|
591
|
+
case PrimitiveKind::Int8: {
|
|
592
|
+
Napi::Int8Array array = Napi::Int8Array::New(env, len);
|
|
593
|
+
|
|
594
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
595
|
+
int16_t align = std::max(realign, type->ref->align);
|
|
596
|
+
src = AlignUp(src, align);
|
|
597
|
+
|
|
598
|
+
int8_t v = *(int8_t *)src;
|
|
599
|
+
array[i] = v;
|
|
600
|
+
|
|
601
|
+
src += type->ref->size;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
return array;
|
|
605
|
+
} break;
|
|
606
|
+
case PrimitiveKind::UInt8: {
|
|
607
|
+
Napi::Uint8Array array = Napi::Uint8Array::New(env, len);
|
|
608
|
+
|
|
609
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
610
|
+
int16_t align = std::max(realign, type->ref->align);
|
|
611
|
+
src = AlignUp(src, align);
|
|
612
|
+
|
|
613
|
+
uint8_t v = *(uint8_t *)src;
|
|
614
|
+
array[i] = v;
|
|
615
|
+
|
|
616
|
+
src += type->ref->size;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
return array;
|
|
620
|
+
} break;
|
|
621
|
+
case PrimitiveKind::Int16: {
|
|
622
|
+
Napi::Int16Array array = Napi::Int16Array::New(env, len);
|
|
623
|
+
|
|
624
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
625
|
+
int16_t align = std::max(realign, type->ref->align);
|
|
626
|
+
src = AlignUp(src, align);
|
|
627
|
+
|
|
628
|
+
int16_t v = *(int16_t *)src;
|
|
629
|
+
array[i] = v;
|
|
630
|
+
|
|
631
|
+
src += type->ref->size;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
return array;
|
|
635
|
+
} break;
|
|
636
|
+
case PrimitiveKind::UInt16: {
|
|
637
|
+
Napi::Uint16Array array = Napi::Uint16Array::New(env, len);
|
|
638
|
+
|
|
639
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
640
|
+
int16_t align = std::max(realign, type->ref->align);
|
|
641
|
+
src = AlignUp(src, align);
|
|
642
|
+
|
|
643
|
+
uint16_t v = *(uint16_t *)src;
|
|
644
|
+
array[i] = v;
|
|
645
|
+
|
|
646
|
+
src += type->ref->size;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
return array;
|
|
650
|
+
} break;
|
|
651
|
+
case PrimitiveKind::Int32: {
|
|
652
|
+
Napi::Int32Array array = Napi::Int32Array::New(env, len);
|
|
653
|
+
|
|
654
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
655
|
+
int16_t align = std::max(realign, type->ref->align);
|
|
656
|
+
src = AlignUp(src, align);
|
|
657
|
+
|
|
658
|
+
int32_t v = *(int32_t *)src;
|
|
659
|
+
array[i] = v;
|
|
660
|
+
|
|
661
|
+
src += type->ref->size;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
return array;
|
|
665
|
+
} break;
|
|
666
|
+
case PrimitiveKind::UInt32: {
|
|
667
|
+
Napi::Uint32Array array = Napi::Uint32Array::New(env, len);
|
|
668
|
+
|
|
669
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
670
|
+
int16_t align = std::max(realign, type->ref->align);
|
|
671
|
+
src = AlignUp(src, align);
|
|
672
|
+
|
|
673
|
+
uint32_t v = *(uint32_t *)src;
|
|
674
|
+
array[i] = v;
|
|
675
|
+
|
|
676
|
+
src += type->ref->size;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
return array;
|
|
680
|
+
} break;
|
|
681
|
+
case PrimitiveKind::Int64: {
|
|
682
|
+
Napi::Array array = Napi::Array::New(env);
|
|
683
|
+
|
|
684
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
685
|
+
int16_t align = std::max(realign, type->ref->align);
|
|
686
|
+
src = AlignUp(src, align);
|
|
687
|
+
|
|
688
|
+
int64_t v = *(int64_t *)src;
|
|
689
|
+
array.Set(i, Napi::BigInt::New(env, v));
|
|
690
|
+
|
|
691
|
+
src += type->ref->size;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
return array;
|
|
695
|
+
} break;
|
|
696
|
+
case PrimitiveKind::UInt64: {
|
|
697
|
+
Napi::Array array = Napi::Array::New(env);
|
|
698
|
+
|
|
699
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
700
|
+
int16_t align = std::max(realign, type->ref->align);
|
|
701
|
+
src = AlignUp(src, align);
|
|
702
|
+
|
|
703
|
+
uint64_t v = *(uint64_t *)src;
|
|
704
|
+
array.Set(i, Napi::BigInt::New(env, v));
|
|
705
|
+
|
|
706
|
+
src += type->ref->size;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
return array;
|
|
710
|
+
} break;
|
|
711
|
+
case PrimitiveKind::String: {
|
|
712
|
+
Napi::Array array = Napi::Array::New(env);
|
|
713
|
+
|
|
714
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
715
|
+
int16_t align = std::max(realign, type->ref->align);
|
|
716
|
+
src = AlignUp(src, align);
|
|
717
|
+
|
|
718
|
+
const char *str = *(const char **)src;
|
|
719
|
+
array.Set(i, Napi::String::New(env, str));
|
|
720
|
+
|
|
721
|
+
src += type->ref->size;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
return array;
|
|
725
|
+
} break;
|
|
726
|
+
case PrimitiveKind::String16: {
|
|
727
|
+
Napi::Array array = Napi::Array::New(env);
|
|
728
|
+
|
|
729
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
730
|
+
int16_t align = std::max(realign, type->ref->align);
|
|
731
|
+
src = AlignUp(src, align);
|
|
732
|
+
|
|
733
|
+
const char16_t *str16 = *(const char16_t **)src;
|
|
734
|
+
array.Set(i, Napi::String::New(env, str16));
|
|
735
|
+
|
|
736
|
+
src += type->ref->size;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
return array;
|
|
740
|
+
} break;
|
|
741
|
+
case PrimitiveKind::Pointer: {
|
|
742
|
+
Napi::Array array = Napi::Array::New(env);
|
|
743
|
+
|
|
744
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
745
|
+
int16_t align = std::max(realign, type->ref->align);
|
|
746
|
+
src = AlignUp(src, align);
|
|
747
|
+
|
|
748
|
+
void *ptr2 = *(void **)src;
|
|
749
|
+
|
|
750
|
+
Napi::External<void> external = Napi::External<void>::New(env, ptr2);
|
|
751
|
+
SetValueTag(instance, external, type->ref);
|
|
752
|
+
|
|
753
|
+
array.Set(i, external);
|
|
754
|
+
|
|
755
|
+
src += type->ref->size;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
return array;
|
|
759
|
+
} break;
|
|
760
|
+
case PrimitiveKind::Record: {
|
|
761
|
+
Napi::Array array = Napi::Array::New(env);
|
|
762
|
+
|
|
763
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
764
|
+
int16_t align = std::max(realign, type->ref->align);
|
|
765
|
+
src = AlignUp(src, align);
|
|
766
|
+
|
|
767
|
+
Napi::Object obj = PopObject(src, type->ref, realign);
|
|
768
|
+
array.Set(i, obj);
|
|
769
|
+
|
|
770
|
+
src += type->ref->size;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
return array;
|
|
774
|
+
} break;
|
|
775
|
+
case PrimitiveKind::Array: {
|
|
776
|
+
Napi::Array array = Napi::Array::New(env);
|
|
777
|
+
|
|
778
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
779
|
+
int16_t align = std::max(realign, type->ref->align);
|
|
780
|
+
src = AlignUp(src, align);
|
|
781
|
+
|
|
782
|
+
Napi::Object obj = PopArray(src, type->ref, realign);
|
|
783
|
+
array.Set(i, obj);
|
|
784
|
+
|
|
785
|
+
src += type->ref->size;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
return array;
|
|
789
|
+
} break;
|
|
790
|
+
case PrimitiveKind::Float32: {
|
|
791
|
+
Napi::Float32Array array = Napi::Float32Array::New(env, len);
|
|
792
|
+
|
|
793
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
794
|
+
int16_t align = std::max(realign, type->ref->align);
|
|
795
|
+
src = AlignUp(src, align);
|
|
796
|
+
|
|
797
|
+
float f = *(float *)src;
|
|
798
|
+
array[i] = f;
|
|
799
|
+
|
|
800
|
+
src += type->ref->size;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
return array;
|
|
804
|
+
} break;
|
|
805
|
+
case PrimitiveKind::Float64: {
|
|
806
|
+
Napi::Float64Array array = Napi::Float64Array::New(env, len);
|
|
807
|
+
|
|
808
|
+
for (uint32_t i = 0; i < len; i++) {
|
|
809
|
+
int16_t align = std::max(realign, type->ref->align);
|
|
810
|
+
src = AlignUp(src, align);
|
|
811
|
+
|
|
812
|
+
double d = *(double *)src;
|
|
813
|
+
array[i] = d;
|
|
814
|
+
|
|
815
|
+
src += type->ref->size;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
return array;
|
|
819
|
+
} break;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
RG_UNREACHABLE();
|
|
823
|
+
}
|
|
824
|
+
|
|
319
825
|
static void DumpMemory(const char *type, Span<const uint8_t> bytes)
|
|
320
826
|
{
|
|
321
827
|
if (bytes.len) {
|
|
@@ -346,8 +852,8 @@ void CallData::DumpDebug() const
|
|
|
346
852
|
}
|
|
347
853
|
PrintLn(stderr, "Return: %1 (%2)", func->ret.type->name, FmtMemSize(func->ret.type->size));
|
|
348
854
|
|
|
349
|
-
DumpMemory("Stack",
|
|
350
|
-
DumpMemory("Heap",
|
|
855
|
+
DumpMemory("Stack", stack);
|
|
856
|
+
DumpMemory("Heap", heap);
|
|
351
857
|
}
|
|
352
858
|
|
|
353
859
|
}
|