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.
Files changed (39) hide show
  1. package/CMakeLists.txt +4 -0
  2. package/README.md +54 -24
  3. package/build/qemu/1.1.0-beta.2/koffi_darwin_x64.tar.gz +0 -0
  4. package/build/qemu/1.1.0-beta.2/koffi_freebsd_arm64.tar.gz +0 -0
  5. package/build/qemu/1.1.0-beta.2/koffi_freebsd_ia32.tar.gz +0 -0
  6. package/build/qemu/1.1.0-beta.2/koffi_freebsd_x64.tar.gz +0 -0
  7. package/build/qemu/1.1.0-beta.2/koffi_linux_arm.tar.gz +0 -0
  8. package/build/qemu/1.1.0-beta.2/koffi_linux_arm64.tar.gz +0 -0
  9. package/build/qemu/1.1.0-beta.2/koffi_linux_ia32.tar.gz +0 -0
  10. package/build/qemu/1.1.0-beta.2/koffi_linux_x64.tar.gz +0 -0
  11. package/build/qemu/1.1.0-beta.2/koffi_win32_ia32.tar.gz +0 -0
  12. package/build/qemu/1.1.0-beta.2/koffi_win32_x64.tar.gz +0 -0
  13. package/package.json +1 -1
  14. package/qemu/qemu.js +12 -5
  15. package/qemu/registry/machines.json +20 -10
  16. package/src/abi_arm32.cc +40 -51
  17. package/src/abi_arm64.cc +71 -138
  18. package/src/abi_x64_sysv.cc +37 -13
  19. package/src/abi_x64_win.cc +16 -6
  20. package/src/abi_x86.cc +16 -6
  21. package/src/call.cc +564 -58
  22. package/src/call.hh +32 -44
  23. package/src/ffi.cc +218 -19
  24. package/src/ffi.hh +27 -11
  25. package/src/parser.cc +4 -0
  26. package/src/util.cc +72 -0
  27. package/src/util.hh +2 -0
  28. package/test/misc.c +16 -10
  29. package/build/qemu/1.0.5/koffi_darwin_x64.tar.gz +0 -0
  30. package/build/qemu/1.0.5/koffi_freebsd_arm64.tar.gz +0 -0
  31. package/build/qemu/1.0.5/koffi_freebsd_ia32.tar.gz +0 -0
  32. package/build/qemu/1.0.5/koffi_freebsd_x64.tar.gz +0 -0
  33. package/build/qemu/1.0.5/koffi_linux_arm.tar.gz +0 -0
  34. package/build/qemu/1.0.5/koffi_linux_arm64.tar.gz +0 -0
  35. package/build/qemu/1.0.5/koffi_linux_ia32.tar.gz +0 -0
  36. package/build/qemu/1.0.5/koffi_linux_x64.tar.gz +0 -0
  37. package/build/qemu/1.0.5/koffi_win32_ia32.tar.gz +0 -0
  38. package/build/qemu/1.0.5/koffi_win32_x64.tar.gz +0 -0
  39. 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, InstanceData *instance, const FunctionInfo *func)
24
- : env(env), instance(instance), func(func),
25
- stack_mem(&instance->stack_mem), heap_mem(&instance->heap_mem),
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
- RG_ASSERT(AlignUp(stack_mem->ptr, 16) == stack_mem->ptr);
29
- RG_ASSERT(AlignUp(stack_mem->end(), 16) == stack_mem->end());
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
- instance->stack_mem = old_stack_mem;
35
- instance->heap_mem = old_heap_mem;
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 *)heap_mem->ptr;
49
- buf.len = std::max((Size)0, heap_mem->len - Kibibytes(32));
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
- heap_mem->ptr += (Size)len;
58
- heap_mem->len -= (Size)len;
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 *)heap_mem->ptr;
86
- buf.len = std::max((Size)0, heap_mem->len - Kibibytes(32)) / 2;
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
- heap_mem->ptr += (Size)len * 2;
95
- heap_mem->len -= (Size)len * 2;
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
- dest = AlignUp(dest, member.align);
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 value %1 for member '%2', expected boolean", GetValueType(instance, value), member.name);
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 value %1 for member '%2', expected number", GetValueType(instance, value), member.name);
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 value %1 for member '%2', expected string", GetValueType(instance, value), member.name);
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 value %1 for member '%2', expected string", GetValueType(instance, value), member.name);
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 value %1 for member '%2', expected object", GetValueType(instance, value), member.name);
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 value %1 for member '%2', expected number", GetValueType(instance, value), member.name);
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
- memcpy(dest, &f, 4);
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 value %1 for member '%2', expected number", GetValueType(instance, value), member.name);
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
- memcpy(dest, &d, 8);
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
- void CallData::PopObject(Napi::Object obj, const uint8_t *ptr, const TypeInfo *type)
239
+ bool CallData::PushArray(const Napi::Object &obj, const TypeInfo *type, uint8_t *dest, int16_t realign)
228
240
  {
229
- Napi::Env env = obj.Env();
230
- InstanceData *instance = env.GetInstanceData<InstanceData>();
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
- ptr = AlignUp(ptr, member.align);
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 *)ptr;
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 *)ptr;
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 *)ptr;
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 *)ptr;
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 *)ptr;
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 *)ptr;
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 *)ptr;
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 *)ptr;
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 *)ptr;
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 **)ptr;
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 **)ptr;
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 **)ptr;
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(ptr, member.type);
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, ptr, 4);
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, ptr, 8);
551
+ memcpy(&d, src, 8);
304
552
  obj.Set(member.name, Napi::Number::New(env, d));
305
553
  } break;
306
554
  }
307
555
 
308
- ptr += member.type->size;
556
+ src += member.type->size;
309
557
  }
310
558
  }
311
559
 
312
- Napi::Object CallData::PopObject(const uint8_t *ptr, const TypeInfo *type)
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, ptr, type);
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", GetStack());
350
- DumpMemory("Heap", GetHeap());
855
+ DumpMemory("Stack", stack);
856
+ DumpMemory("Heap", heap);
351
857
  }
352
858
 
353
859
  }