koffi 2.15.0 → 2.16.0-beta.1
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/CHANGELOG.md +7 -0
- package/build/koffi/darwin_arm64/koffi.node +0 -0
- package/build/koffi/darwin_x64/koffi.node +0 -0
- package/build/koffi/freebsd_arm64/koffi.node +0 -0
- package/build/koffi/freebsd_ia32/koffi.node +0 -0
- package/build/koffi/freebsd_x64/koffi.node +0 -0
- package/build/koffi/linux_arm64/koffi.node +0 -0
- package/build/koffi/linux_armhf/koffi.node +0 -0
- package/build/koffi/linux_ia32/koffi.node +0 -0
- package/build/koffi/linux_loong64/koffi.node +0 -0
- package/build/koffi/linux_riscv64d/koffi.node +0 -0
- package/build/koffi/linux_x64/koffi.node +0 -0
- package/build/koffi/musl_arm64/koffi.node +0 -0
- package/build/koffi/musl_x64/koffi.node +0 -0
- package/build/koffi/openbsd_ia32/koffi.node +0 -0
- package/build/koffi/openbsd_x64/koffi.node +0 -0
- package/build/koffi/win32_arm64/koffi.node +0 -0
- package/build/koffi/win32_ia32/koffi.node +0 -0
- package/build/koffi/win32_x64/koffi.node +0 -0
- package/doc/pages/index.md +4 -2
- package/doc/pages/misc.md +2 -0
- package/doc/templates/code.html +1 -2
- package/doc/templates/page.html +1 -2
- package/index.d.ts +11 -9
- package/index.js +9 -9
- package/indirect.js +9 -9
- package/lib/native/base/base.cc +79 -44
- package/lib/native/base/base.hh +31 -33
- package/package.json +2 -2
- package/src/cnoke/assets/FindCNoke.cmake +16 -10
- package/src/cnoke/assets/win_delay_hook.c +4 -0
- package/src/cnoke/src/builder.js +49 -46
- package/src/koffi/CMakeLists.txt +18 -8
- package/src/koffi/src/abi_arm32.cc +222 -219
- package/src/koffi/src/abi_arm32_asm.S +1 -29
- package/src/koffi/src/abi_arm64.cc +257 -235
- package/src/koffi/src/abi_arm64_asm.S +1 -32
- package/src/koffi/src/abi_arm64_asm.asm +1 -23
- package/src/koffi/src/abi_loong64_asm.S +1 -25
- package/src/koffi/src/abi_riscv64.cc +220 -217
- package/src/koffi/src/abi_riscv64_asm.S +1 -25
- package/src/koffi/src/abi_x64_sysv.cc +196 -192
- package/src/koffi/src/abi_x64_sysv_asm.S +1 -31
- package/src/koffi/src/abi_x64_win.cc +188 -172
- package/src/koffi/src/abi_x64_win_asm.S +144 -0
- package/src/koffi/src/abi_x64_win_asm.asm +1 -21
- package/src/koffi/src/abi_x86.cc +224 -189
- package/src/koffi/src/abi_x86_asm.S +6 -25
- package/src/koffi/src/abi_x86_asm.asm +9 -22
- package/src/koffi/src/call.cc +246 -428
- package/src/koffi/src/call.hh +9 -8
- package/src/koffi/src/ffi.cc +142 -88
- package/src/koffi/src/ffi.hh +13 -59
- package/src/koffi/src/primitives.inc +39 -0
- package/src/koffi/src/trampolines/armasm.inc +0 -32770
- package/src/koffi/src/trampolines/gnu.inc +0 -24578
- package/src/koffi/src/trampolines/masm32.inc +0 -32770
- package/src/koffi/src/trampolines/masm64.inc +0 -32770
- package/src/koffi/src/trampolines/prototypes.inc +16385 -16385
- package/src/koffi/src/util.cc +155 -112
- package/src/koffi/src/util.hh +77 -40
- package/vendor/node-api-headers/CHANGELOG.md +22 -0
- package/vendor/node-api-headers/README.md +6 -17
- package/vendor/node-api-headers/include/js_native_api.h +3 -13
- package/vendor/node-api-headers/include/js_native_api_types.h +15 -0
- package/vendor/node-api-headers/include/node_api.h +0 -4
- package/vendor/node-api-headers/include/node_api_types.h +6 -0
- package/vendor/node-api-headers/package.json +1 -1
- package/vendor/node-api-headers/scripts/update-headers.js +6 -0
|
@@ -52,8 +52,6 @@ extern "C" napi_value CallSwitchStack(Napi::Function *func, size_t argc, napi_va
|
|
|
52
52
|
uint8_t *old_sp, Span<uint8_t> *new_stack,
|
|
53
53
|
napi_value (*call)(Napi::Function *func, size_t argc, napi_value *argv));
|
|
54
54
|
|
|
55
|
-
#include "trampolines/prototypes.inc"
|
|
56
|
-
|
|
57
55
|
static inline void ExpandPair(const uint8_t raw[16], int size1, int size2, uint64_t out_regs[2])
|
|
58
56
|
{
|
|
59
57
|
memcpy(out_regs + 0, raw, size1);
|
|
@@ -150,213 +148,258 @@ bool AnalyseFunction(Napi::Env, InstanceData *, FunctionInfo *func)
|
|
|
150
148
|
|
|
151
149
|
bool CallData::Prepare(const FunctionInfo *func, const Napi::CallbackInfo &info)
|
|
152
150
|
{
|
|
153
|
-
uint64_t *
|
|
154
|
-
uint64_t *gpr_ptr =
|
|
155
|
-
uint64_t *
|
|
151
|
+
uint64_t *vec_ptr = AllocStack<uint64_t>(16 * 8 + func->args_size);
|
|
152
|
+
uint64_t *gpr_ptr = vec_ptr + 8;
|
|
153
|
+
uint64_t *args_ptr = vec_ptr + 16;
|
|
156
154
|
|
|
157
|
-
|
|
158
|
-
if (!AllocStack(func->args_size, 16, &args_ptr)) [[unlikely]]
|
|
159
|
-
return false;
|
|
160
|
-
if (!AllocStack(8 * 8, 8, &gpr_ptr)) [[unlikely]]
|
|
161
|
-
return false;
|
|
162
|
-
if (!AllocStack(8 * 8, 8, &vec_ptr)) [[unlikely]]
|
|
155
|
+
if (!vec_ptr) [[unlikely]]
|
|
163
156
|
return false;
|
|
164
157
|
if (func->ret.use_memory) {
|
|
165
158
|
return_ptr = AllocHeap(func->ret.type->size, 16);
|
|
166
159
|
*(uint8_t **)(gpr_ptr++) = return_ptr;
|
|
167
160
|
}
|
|
168
161
|
|
|
162
|
+
Size i = -1;
|
|
163
|
+
|
|
164
|
+
static const void *const DispatchTable[] = {
|
|
165
|
+
#define PRIMITIVE(Name) && Name,
|
|
166
|
+
#include "primitives.inc"
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
#define LOOP
|
|
170
|
+
#define CASE(Primitive) \
|
|
171
|
+
do { \
|
|
172
|
+
PrimitiveKind next = func->primitives[++i]; \
|
|
173
|
+
goto *DispatchTable[(int)next]; \
|
|
174
|
+
} while (false); \
|
|
175
|
+
Primitive:
|
|
176
|
+
#define OR(Primitive) \
|
|
177
|
+
Primitive:
|
|
178
|
+
|
|
169
179
|
#define PUSH_INTEGER(CType) \
|
|
170
180
|
do { \
|
|
171
|
-
|
|
181
|
+
const ParameterInfo ¶m = func->parameters[i]; \
|
|
182
|
+
Napi::Value value = info[param.offset]; \
|
|
183
|
+
\
|
|
184
|
+
CType v; \
|
|
185
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
172
186
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
173
187
|
return false; \
|
|
174
188
|
} \
|
|
175
189
|
\
|
|
176
|
-
CType v = GetNumber<CType>(value); \
|
|
177
190
|
*((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint64_t)v; \
|
|
178
191
|
} while (false)
|
|
179
192
|
#define PUSH_INTEGER_SWAP(CType) \
|
|
180
193
|
do { \
|
|
181
|
-
|
|
194
|
+
const ParameterInfo ¶m = func->parameters[i]; \
|
|
195
|
+
Napi::Value value = info[param.offset]; \
|
|
196
|
+
\
|
|
197
|
+
CType v; \
|
|
198
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
182
199
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
183
200
|
return false; \
|
|
184
201
|
} \
|
|
185
202
|
\
|
|
186
|
-
CType v = GetNumber<CType>(value); \
|
|
187
203
|
*((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint64_t)ReverseBytes(v); \
|
|
188
204
|
} while (false)
|
|
189
205
|
|
|
190
206
|
// Push arguments
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
K_ASSERT(param.directions >= 1 && param.directions <= 3);
|
|
207
|
+
LOOP {
|
|
208
|
+
CASE(Void) { K_UNREACHABLE(); };
|
|
194
209
|
|
|
195
|
-
|
|
210
|
+
CASE(Bool) {
|
|
211
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
212
|
+
Napi::Value value = info[param.offset];
|
|
196
213
|
|
|
197
|
-
|
|
198
|
-
|
|
214
|
+
bool b;
|
|
215
|
+
if (napi_get_value_bool(env, value, &b) != napi_ok) [[unlikely]] {
|
|
216
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
199
219
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
220
|
+
*((param.gpr_count ? gpr_ptr : args_ptr)++) = (uint64_t)b;
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
CASE(Int8) { PUSH_INTEGER(int8_t); };
|
|
224
|
+
CASE(UInt8) { PUSH_INTEGER(uint8_t); };
|
|
225
|
+
CASE(Int16) { PUSH_INTEGER(int16_t); };
|
|
226
|
+
CASE(Int16S) { PUSH_INTEGER_SWAP(int16_t); };
|
|
227
|
+
CASE(UInt16) { PUSH_INTEGER(uint16_t); };
|
|
228
|
+
CASE(UInt16S) { PUSH_INTEGER_SWAP(uint16_t); };
|
|
229
|
+
CASE(Int32) { PUSH_INTEGER(int32_t); };
|
|
230
|
+
CASE(Int32S) { PUSH_INTEGER_SWAP(int32_t); };
|
|
231
|
+
CASE(UInt32) { PUSH_INTEGER(uint32_t); };
|
|
232
|
+
CASE(UInt32S) { PUSH_INTEGER_SWAP(uint32_t); };
|
|
233
|
+
CASE(Int64) { PUSH_INTEGER(int64_t); };
|
|
234
|
+
CASE(Int64S) { PUSH_INTEGER_SWAP(int64_t); };
|
|
235
|
+
CASE(UInt64) { PUSH_INTEGER(uint64_t); };
|
|
236
|
+
CASE(UInt64S) { PUSH_INTEGER_SWAP(uint64_t); };
|
|
237
|
+
|
|
238
|
+
CASE(String) {
|
|
239
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
240
|
+
Napi::Value value = info[param.offset];
|
|
205
241
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
case PrimitiveKind::Int8: { PUSH_INTEGER(int8_t); } break;
|
|
210
|
-
case PrimitiveKind::UInt8: { PUSH_INTEGER(uint8_t); } break;
|
|
211
|
-
case PrimitiveKind::Int16: { PUSH_INTEGER(int16_t); } break;
|
|
212
|
-
case PrimitiveKind::Int16S: { PUSH_INTEGER_SWAP(int16_t); } break;
|
|
213
|
-
case PrimitiveKind::UInt16: { PUSH_INTEGER(uint16_t); } break;
|
|
214
|
-
case PrimitiveKind::UInt16S: { PUSH_INTEGER_SWAP(uint16_t); } break;
|
|
215
|
-
case PrimitiveKind::Int32: { PUSH_INTEGER(int32_t); } break;
|
|
216
|
-
case PrimitiveKind::Int32S: { PUSH_INTEGER_SWAP(int32_t); } break;
|
|
217
|
-
case PrimitiveKind::UInt32: { PUSH_INTEGER(uint32_t); } break;
|
|
218
|
-
case PrimitiveKind::UInt32S: { PUSH_INTEGER_SWAP(uint32_t); } break;
|
|
219
|
-
case PrimitiveKind::Int64: { PUSH_INTEGER(int64_t); } break;
|
|
220
|
-
case PrimitiveKind::Int64S: { PUSH_INTEGER_SWAP(int64_t); } break;
|
|
221
|
-
case PrimitiveKind::UInt64: { PUSH_INTEGER(uint64_t); } break;
|
|
222
|
-
case PrimitiveKind::UInt64S: { PUSH_INTEGER_SWAP(uint64_t); } break;
|
|
223
|
-
case PrimitiveKind::String: {
|
|
224
|
-
const char *str;
|
|
225
|
-
if (!PushString(value, param.directions, &str)) [[unlikely]]
|
|
226
|
-
return false;
|
|
242
|
+
const char *str;
|
|
243
|
+
if (!PushString(value, param.directions, &str)) [[unlikely]]
|
|
244
|
+
return false;
|
|
227
245
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
return false;
|
|
246
|
+
*(const char **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str;
|
|
247
|
+
};
|
|
248
|
+
CASE(String16) {
|
|
249
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
250
|
+
Napi::Value value = info[param.offset];
|
|
234
251
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
const char32_t *str32;
|
|
239
|
-
if (!PushString32(value, param.directions, &str32)) [[unlikely]]
|
|
240
|
-
return false;
|
|
252
|
+
const char16_t *str16;
|
|
253
|
+
if (!PushString16(value, param.directions, &str16)) [[unlikely]]
|
|
254
|
+
return false;
|
|
241
255
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
return false;
|
|
256
|
+
*(const char16_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str16;
|
|
257
|
+
};
|
|
258
|
+
CASE(String32) {
|
|
259
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
260
|
+
Napi::Value value = info[param.offset];
|
|
248
261
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
case PrimitiveKind::Union: {
|
|
253
|
-
if (!IsObject(value)) [[unlikely]] {
|
|
254
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
|
|
255
|
-
return false;
|
|
256
|
-
}
|
|
262
|
+
const char32_t *str32;
|
|
263
|
+
if (!PushString32(value, param.directions, &str32)) [[unlikely]]
|
|
264
|
+
return false;
|
|
257
265
|
|
|
258
|
-
|
|
266
|
+
*(const char32_t **)((param.gpr_count ? gpr_ptr : args_ptr)++) = str32;
|
|
267
|
+
};
|
|
259
268
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
uint64_t regs[2] = { 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull };
|
|
264
|
-
{
|
|
265
|
-
uint8_t buf[16] = {};
|
|
266
|
-
if (!PushObject(obj, param.type, buf))
|
|
267
|
-
return false;
|
|
268
|
-
ExpandPair(buf, param.reg_size[0], param.reg_size[1], regs);
|
|
269
|
-
}
|
|
269
|
+
CASE(Pointer) {
|
|
270
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
271
|
+
Napi::Value value = info[param.offset];
|
|
270
272
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
*(gpr_ptr++) = regs[1];
|
|
275
|
-
} else if (param.vec_count == 1) {
|
|
276
|
-
*(vec_ptr++) = regs[1];
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
args_ptr = std::max(gpr_ptr, args_ptr);
|
|
280
|
-
} else if (param.vec_count) {
|
|
281
|
-
*(vec_ptr++) = regs[0];
|
|
282
|
-
if (param.vec_count == 2) {
|
|
283
|
-
*(vec_ptr++) = regs[1];
|
|
284
|
-
} else if (param.gpr_count == 1) {
|
|
285
|
-
*(gpr_ptr++) = regs[1];
|
|
286
|
-
}
|
|
287
|
-
} else {
|
|
288
|
-
K_ASSERT(param.type->align <= 8);
|
|
273
|
+
void *ptr;
|
|
274
|
+
if (!PushPointer(value, param.type, param.directions, &ptr)) [[unlikely]]
|
|
275
|
+
return false;
|
|
289
276
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
}
|
|
293
|
-
} else {
|
|
294
|
-
uint8_t *ptr = AllocHeap(param.type->size, 16);
|
|
277
|
+
*(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
|
|
278
|
+
};
|
|
295
279
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
280
|
+
CASE(Record) OR(Union) {
|
|
281
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
282
|
+
Napi::Value value = info[param.offset];
|
|
299
283
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
284
|
+
if (!IsObject(value)) [[unlikely]] {
|
|
285
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected object", GetValueType(instance, value));
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
304
288
|
|
|
305
|
-
|
|
289
|
+
Napi::Object obj = value.As<Napi::Object>();
|
|
290
|
+
|
|
291
|
+
if (!param.use_memory) {
|
|
292
|
+
K_ASSERT(param.type->size <= 16);
|
|
293
|
+
|
|
294
|
+
uint64_t regs[2] = { 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull };
|
|
295
|
+
{
|
|
296
|
+
uint8_t buf[16] = {};
|
|
297
|
+
if (!PushObject(obj, param.type, buf))
|
|
306
298
|
return false;
|
|
307
|
-
|
|
308
|
-
} break;
|
|
309
|
-
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
310
|
-
case PrimitiveKind::Float32: {
|
|
311
|
-
if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
|
|
312
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
313
|
-
return false;
|
|
299
|
+
ExpandPair(buf, param.reg_size[0], param.reg_size[1], regs);
|
|
314
300
|
}
|
|
315
301
|
|
|
316
|
-
|
|
302
|
+
if (param.gpr_first) {
|
|
303
|
+
*(gpr_ptr++) = regs[0];
|
|
304
|
+
if (param.gpr_count == 2) {
|
|
305
|
+
*(gpr_ptr++) = regs[1];
|
|
306
|
+
} else if (param.vec_count == 1) {
|
|
307
|
+
*(vec_ptr++) = regs[1];
|
|
308
|
+
}
|
|
317
309
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
*(
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
310
|
+
args_ptr = std::max(gpr_ptr, args_ptr);
|
|
311
|
+
} else if (param.vec_count) {
|
|
312
|
+
*(vec_ptr++) = regs[0];
|
|
313
|
+
if (param.vec_count == 2) {
|
|
314
|
+
*(vec_ptr++) = regs[1];
|
|
315
|
+
} else if (param.gpr_count == 1) {
|
|
316
|
+
*(gpr_ptr++) = regs[1];
|
|
317
|
+
}
|
|
324
318
|
} else {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
case PrimitiveKind::Float64: {
|
|
330
|
-
if (!value.IsNumber() && !value.IsBigInt()) [[unlikely]] {
|
|
331
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
332
|
-
return false;
|
|
319
|
+
K_ASSERT(param.type->align <= 8);
|
|
320
|
+
|
|
321
|
+
MemCpy(args_ptr, regs, param.type->size);
|
|
322
|
+
args_ptr += (param.type->size + 7) / 8;
|
|
333
323
|
}
|
|
324
|
+
} else {
|
|
325
|
+
uint8_t *ptr = AllocHeap(param.type->size, 16);
|
|
334
326
|
|
|
335
|
-
|
|
327
|
+
if (param.gpr_count) {
|
|
328
|
+
K_ASSERT(param.gpr_count == 1);
|
|
329
|
+
K_ASSERT(param.vec_count == 0);
|
|
336
330
|
|
|
337
|
-
|
|
338
|
-
*(double *)(vec_ptr++) = d;
|
|
339
|
-
} else if (param.gpr_count) {
|
|
340
|
-
*(double *)(gpr_ptr++) = d;
|
|
331
|
+
*(uint8_t **)(gpr_ptr++) = ptr;
|
|
341
332
|
} else {
|
|
342
|
-
*(
|
|
333
|
+
*(uint8_t **)(args_ptr++) = ptr;
|
|
343
334
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
void *ptr;
|
|
347
|
-
if (!PushCallback(value, param.type, &ptr)) [[unlikely]]
|
|
335
|
+
|
|
336
|
+
if (!PushObject(obj, param.type, ptr))
|
|
348
337
|
return false;
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
CASE(Array) { K_UNREACHABLE(); };
|
|
349
341
|
|
|
350
|
-
|
|
351
|
-
|
|
342
|
+
CASE(Float32) {
|
|
343
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
344
|
+
Napi::Value value = info[param.offset];
|
|
352
345
|
|
|
353
|
-
|
|
354
|
-
|
|
346
|
+
float f;
|
|
347
|
+
if (!TryNumber(value, &f)) [[unlikely]] {
|
|
348
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (param.vec_count) [[likely]] {
|
|
353
|
+
memset((uint8_t *)vec_ptr + 4, 0xFF, 4);
|
|
354
|
+
*(float *)(vec_ptr++) = f;
|
|
355
|
+
} else if (param.gpr_count) {
|
|
356
|
+
memset((uint8_t *)gpr_ptr + 4, 0xFF, 4);
|
|
357
|
+
*(float *)(gpr_ptr++) = f;
|
|
358
|
+
} else {
|
|
359
|
+
memset(args_ptr, 0xFF, 8);
|
|
360
|
+
*(float *)(args_ptr++) = f;
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
CASE(Float64) {
|
|
364
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
365
|
+
Napi::Value value = info[param.offset];
|
|
366
|
+
|
|
367
|
+
double d;
|
|
368
|
+
if (!TryNumber(value, &d)) [[unlikely]] {
|
|
369
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
370
|
+
return false;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (param.vec_count) [[likely]] {
|
|
374
|
+
*(double *)(vec_ptr++) = d;
|
|
375
|
+
} else if (param.gpr_count) {
|
|
376
|
+
*(double *)(gpr_ptr++) = d;
|
|
377
|
+
} else {
|
|
378
|
+
*(double *)(args_ptr++) = d;
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
CASE(Callback) {
|
|
383
|
+
const ParameterInfo ¶m = func->parameters[i];
|
|
384
|
+
Napi::Value value = info[param.offset];
|
|
385
|
+
|
|
386
|
+
void *ptr;
|
|
387
|
+
if (!PushCallback(value, param.type, &ptr)) [[unlikely]]
|
|
388
|
+
return false;
|
|
389
|
+
|
|
390
|
+
*(void **)((param.gpr_count ? gpr_ptr : args_ptr)++) = ptr;
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
CASE(Prototype) { /* End loop */ };
|
|
355
394
|
}
|
|
356
395
|
|
|
357
396
|
#undef PUSH_INTEGER_SWAP
|
|
358
397
|
#undef PUSH_INTEGER
|
|
359
398
|
|
|
399
|
+
#undef OR
|
|
400
|
+
#undef CASE
|
|
401
|
+
#undef LOOP
|
|
402
|
+
|
|
360
403
|
new_sp = mem->stack.end();
|
|
361
404
|
|
|
362
405
|
return true;
|
|
@@ -450,17 +493,8 @@ Napi::Value CallData::Complete(const FunctionInfo *func)
|
|
|
450
493
|
case PrimitiveKind::String: return result.ptr ? Napi::String::New(env, (const char *)result.ptr) : env.Null();
|
|
451
494
|
case PrimitiveKind::String16: return result.ptr ? Napi::String::New(env, (const char16_t *)result.ptr) : env.Null();
|
|
452
495
|
case PrimitiveKind::String32: return result.ptr ? MakeStringFromUTF32(env, (const char32_t *)result.ptr) : env.Null();
|
|
453
|
-
case PrimitiveKind::Pointer:
|
|
454
|
-
case PrimitiveKind::Callback:
|
|
455
|
-
if (result.ptr) {
|
|
456
|
-
Napi::External<void> external = Napi::External<void>::New(env, result.ptr);
|
|
457
|
-
SetValueTag(external, func->ret.type->ref.marker);
|
|
458
|
-
|
|
459
|
-
return external;
|
|
460
|
-
} else {
|
|
461
|
-
return env.Null();
|
|
462
|
-
}
|
|
463
|
-
} break;
|
|
496
|
+
case PrimitiveKind::Pointer: return result.ptr ? WrapPointer(env, func->ret.type->ref.type, result.ptr) : env.Null();
|
|
497
|
+
case PrimitiveKind::Callback: return result.ptr ? WrapCallback(env, func->ret.type->ref.type, result.ptr) : env.Null();
|
|
464
498
|
case PrimitiveKind::Record:
|
|
465
499
|
case PrimitiveKind::Union: {
|
|
466
500
|
if (return_ptr) {
|
|
@@ -640,18 +674,21 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
640
674
|
Napi::Value arg = str32 ? MakeStringFromUTF32(env, str32) : env.Null();
|
|
641
675
|
arguments.Append(arg);
|
|
642
676
|
} break;
|
|
643
|
-
case PrimitiveKind::Pointer:
|
|
644
|
-
case PrimitiveKind::Callback: {
|
|
677
|
+
case PrimitiveKind::Pointer: {
|
|
645
678
|
void *ptr2 = *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++);
|
|
646
679
|
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
SetValueTag(external, param.type->ref.marker);
|
|
680
|
+
Napi::Value p = ptr2 ? WrapPointer(env, param.type->ref.type, ptr2) : env.Null();
|
|
681
|
+
arguments.Append(p);
|
|
650
682
|
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
arguments.Append(env.Null());
|
|
683
|
+
if (param.type->dispose) {
|
|
684
|
+
param.type->dispose(env, param.type, ptr2);
|
|
654
685
|
}
|
|
686
|
+
} break;
|
|
687
|
+
case PrimitiveKind::Callback: {
|
|
688
|
+
void *ptr2 = *(void **)((param.gpr_count ? gpr_ptr : args_ptr)++);
|
|
689
|
+
|
|
690
|
+
Napi::Value p = ptr2 ? WrapCallback(env, param.type->ref.type, ptr2) : env.Null();
|
|
691
|
+
arguments.Append(p);
|
|
655
692
|
|
|
656
693
|
if (param.type->dispose) {
|
|
657
694
|
param.type->dispose(env, param.type, ptr2);
|
|
@@ -737,22 +774,22 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
737
774
|
|
|
738
775
|
#define RETURN_INTEGER(CType) \
|
|
739
776
|
do { \
|
|
740
|
-
|
|
777
|
+
CType v; \
|
|
778
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
741
779
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
742
780
|
return; \
|
|
743
781
|
} \
|
|
744
782
|
\
|
|
745
|
-
CType v = GetNumber<CType>(value); \
|
|
746
783
|
out_reg->a0 = (uint64_t)v; \
|
|
747
784
|
} while (false)
|
|
748
785
|
#define RETURN_INTEGER_SWAP(CType) \
|
|
749
786
|
do { \
|
|
750
|
-
|
|
787
|
+
CType v; \
|
|
788
|
+
if (!TryNumber(value, &v)) [[unlikely]] { \
|
|
751
789
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value)); \
|
|
752
790
|
return; \
|
|
753
791
|
} \
|
|
754
792
|
\
|
|
755
|
-
CType v = GetNumber<CType>(value); \
|
|
756
793
|
out_reg->a0 = (uint64_t)ReverseBytes(v); \
|
|
757
794
|
} while (false)
|
|
758
795
|
|
|
@@ -760,12 +797,12 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
760
797
|
switch (type->primitive) {
|
|
761
798
|
case PrimitiveKind::Void: {} break;
|
|
762
799
|
case PrimitiveKind::Bool: {
|
|
763
|
-
|
|
800
|
+
bool b;
|
|
801
|
+
if (napi_get_value_bool(env, value, &b) != napi_ok) [[unlikely]] {
|
|
764
802
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected boolean", GetValueType(instance, value));
|
|
765
803
|
return;
|
|
766
804
|
}
|
|
767
805
|
|
|
768
|
-
bool b = value.As<Napi::Boolean>();
|
|
769
806
|
out_reg->a0 = (uint64_t)b;
|
|
770
807
|
} break;
|
|
771
808
|
case PrimitiveKind::Int8: { RETURN_INTEGER(int8_t); } break;
|
|
@@ -804,24 +841,9 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
804
841
|
out_reg->a0 = (uint64_t)str32;
|
|
805
842
|
} break;
|
|
806
843
|
case PrimitiveKind::Pointer: {
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
if (CheckValueTag(value, type->ref.marker)) {
|
|
810
|
-
ptr = value.As<Napi::External<uint8_t>>().Data();
|
|
811
|
-
} else if (IsObject(value) && (type->ref.type->primitive == PrimitiveKind::Record ||
|
|
812
|
-
type->ref.type->primitive == PrimitiveKind::Union)) {
|
|
813
|
-
Napi::Object obj = value.As<Napi::Object>();
|
|
814
|
-
|
|
815
|
-
ptr = AllocHeap(type->ref.type->size, 16);
|
|
816
|
-
|
|
817
|
-
if (!PushObject(obj, type->ref.type, ptr))
|
|
818
|
-
return;
|
|
819
|
-
} else if (IsNullOrUndefined(value)) {
|
|
820
|
-
ptr = nullptr;
|
|
821
|
-
} else {
|
|
822
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
|
|
844
|
+
void *ptr;
|
|
845
|
+
if (!PushPointer(value, type, 1, &ptr)) [[unlikely]]
|
|
823
846
|
return;
|
|
824
|
-
}
|
|
825
847
|
|
|
826
848
|
out_reg->a0 = (uint64_t)ptr;
|
|
827
849
|
} break;
|
|
@@ -864,41 +886,28 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
864
886
|
} break;
|
|
865
887
|
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
866
888
|
case PrimitiveKind::Float32: {
|
|
867
|
-
|
|
889
|
+
float f;
|
|
890
|
+
if (!TryNumber(value, &f)) [[unlikely]] {
|
|
868
891
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
869
892
|
return;
|
|
870
893
|
}
|
|
871
894
|
|
|
872
|
-
float f = GetNumber<float>(value);
|
|
873
895
|
memset((uint8_t *)&out_reg->fa0 + 4, 0xFF, 4);
|
|
874
896
|
memcpy(&out_reg->fa0, &f, 4);
|
|
875
897
|
} break;
|
|
876
898
|
case PrimitiveKind::Float64: {
|
|
877
|
-
|
|
899
|
+
double d;
|
|
900
|
+
if (!TryNumber(value, &d)) [[unlikely]] {
|
|
878
901
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected number", GetValueType(instance, value));
|
|
879
902
|
return;
|
|
880
903
|
}
|
|
881
904
|
|
|
882
|
-
double d = GetNumber<double>(value);
|
|
883
905
|
out_reg->fa0 = d;
|
|
884
906
|
} break;
|
|
885
907
|
case PrimitiveKind::Callback: {
|
|
886
908
|
void *ptr;
|
|
887
|
-
|
|
888
|
-
if (value.IsFunction()) {
|
|
889
|
-
Napi::Function func2 = value.As<Napi::Function>();
|
|
890
|
-
|
|
891
|
-
ptr = ReserveTrampoline(type->ref.proto, func2);
|
|
892
|
-
if (!ptr) [[unlikely]]
|
|
893
|
-
return;
|
|
894
|
-
} else if (CheckValueTag(value, type->ref.marker)) {
|
|
895
|
-
ptr = value.As<Napi::External<void>>().Data();
|
|
896
|
-
} else if (IsNullOrUndefined(value)) {
|
|
897
|
-
ptr = nullptr;
|
|
898
|
-
} else {
|
|
899
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value, expected %2", GetValueType(instance, value), type->name);
|
|
909
|
+
if (!PushCallback(value, type, &ptr)) [[unlikely]]
|
|
900
910
|
return;
|
|
901
|
-
}
|
|
902
911
|
|
|
903
912
|
out_reg->a0 = (uint64_t)ptr;
|
|
904
913
|
} break;
|
|
@@ -912,12 +921,6 @@ void CallData::Relay(Size idx, uint8_t *own_sp, uint8_t *caller_sp, bool switch_
|
|
|
912
921
|
err_guard.Disable();
|
|
913
922
|
}
|
|
914
923
|
|
|
915
|
-
void *GetTrampoline(int16_t idx, const FunctionInfo *proto)
|
|
916
|
-
{
|
|
917
|
-
bool fp = proto->forward_fp || proto->ret.vec_count;
|
|
918
|
-
return Trampolines[idx][fp];
|
|
919
|
-
}
|
|
920
|
-
|
|
921
924
|
}
|
|
922
925
|
|
|
923
926
|
#endif
|
|
@@ -131,36 +131,12 @@ ForwardCallXDD:
|
|
|
131
131
|
.global RelayCallback
|
|
132
132
|
.global CallSwitchStack
|
|
133
133
|
|
|
134
|
-
# First, make a copy of
|
|
134
|
+
# First, make a copy of argument registers.
|
|
135
135
|
# Then call the C function RelayCallback with the following arguments:
|
|
136
136
|
# static trampoline ID, a pointer to the saved GPR array, a pointer to the stack
|
|
137
137
|
# arguments of this call, and a pointer to a struct that will contain the result registers.
|
|
138
138
|
# After the call, simply load these registers from the output struct.
|
|
139
139
|
.macro trampoline id
|
|
140
|
-
addi sp, sp, -176
|
|
141
|
-
sd ra, 0(sp)
|
|
142
|
-
sd a0, 8(sp)
|
|
143
|
-
sd a1, 16(sp)
|
|
144
|
-
sd a2, 24(sp)
|
|
145
|
-
sd a3, 32(sp)
|
|
146
|
-
sd a4, 40(sp)
|
|
147
|
-
sd a5, 48(sp)
|
|
148
|
-
sd a6, 56(sp)
|
|
149
|
-
sd a7, 64(sp)
|
|
150
|
-
li a0, \id
|
|
151
|
-
addi a1, sp, 8
|
|
152
|
-
addi a2, sp, 176
|
|
153
|
-
addi a3, sp, 136
|
|
154
|
-
call RelayCallback
|
|
155
|
-
ld ra, 0(sp)
|
|
156
|
-
ld a0, 136(sp)
|
|
157
|
-
ld a1, 144(sp)
|
|
158
|
-
addi sp, sp, 176
|
|
159
|
-
ret
|
|
160
|
-
.endm
|
|
161
|
-
|
|
162
|
-
# Same thing, but also forwards the floating-point argument registers and loads them at the end.
|
|
163
|
-
.macro trampoline_vec id
|
|
164
140
|
addi sp, sp, -176
|
|
165
141
|
sd ra, 0(sp)
|
|
166
142
|
sd a0, 8(sp)
|