koffi 3.0.0 → 3.0.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/CHANGELOG.md +20 -1
- package/README.md +5 -4
- package/cnoke.cjs +10 -10
- package/doc/benchmarks.md +24 -47
- package/doc/callbacks.md +4 -13
- package/doc/contribute.md +4 -4
- package/doc/index.md +3 -2
- package/doc/migration.md +100 -0
- package/doc/start.md +7 -5
- package/index.d.ts +53 -5
- package/index.js +2 -1
- package/indirect.js +2 -1
- package/package.json +20 -18
- package/src/koffi/CMakeLists.txt +20 -12
- package/src/koffi/index.cjs +92 -129
- package/src/koffi/index.js +128 -113
- package/src/koffi/indirect.cjs +91 -128
- package/src/koffi/indirect.js +129 -40
- package/src/koffi/src/abi/arm64.cc +30 -29
- package/src/koffi/src/abi/riscv64.cc +30 -29
- package/src/koffi/src/abi/x64sysv.cc +26 -25
- package/src/koffi/src/abi/x64win.cc +64 -63
- package/src/koffi/src/abi/x86.cc +67 -65
- package/src/koffi/src/call.cc +210 -99
- package/src/koffi/src/call.hh +2 -1
- package/src/koffi/src/ffi.cc +403 -237
- package/src/koffi/src/ffi.hh +46 -7
- package/src/koffi/src/parser.cc +3 -1
- package/src/koffi/src/primitives.inc +1 -4
- package/src/koffi/src/static.cjs +122 -0
- package/src/koffi/src/static.js +122 -0
- package/src/koffi/src/type.cc +715 -0
- package/src/koffi/src/type.hh +71 -0
- package/src/koffi/src/util.cc +189 -1120
- package/src/koffi/src/util.hh +85 -125
- package/src/koffi/src/uv.cc +16 -10
- package/src/koffi/src/uv.hh +2 -1
package/src/koffi/indirect.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
// src/init.js
|
|
1
|
+
// src/koffi/src/init.js
|
|
2
2
|
import util from "node:util";
|
|
3
3
|
import fs2 from "node:fs";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
|
|
6
|
-
//
|
|
6
|
+
// src/cnoke/src/abi.js
|
|
7
7
|
import fs from "node:fs";
|
|
8
8
|
function determineAbi() {
|
|
9
|
-
let abi = process.arch;
|
|
9
|
+
let abi = process.arch.toString();
|
|
10
10
|
if (abi == "riscv32" || abi == "riscv64") {
|
|
11
11
|
let buf = readFileHeader(process.execPath, 512);
|
|
12
12
|
let header = decodeElfHeader(buf);
|
|
@@ -93,15 +93,15 @@ function decodeElfHeader(buf) {
|
|
|
93
93
|
return header;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
// package.json
|
|
97
|
-
var package_default = { name: "koffi", version: "3.0.
|
|
96
|
+
// src/koffi/package.json
|
|
97
|
+
var package_default = { name: "koffi", version: "3.0.2", cnoke: { api: "../../vendor/node-api-headers", output: "../../bin/Koffi/{{ toolchain }}", node: 16, napi: 8 } };
|
|
98
98
|
|
|
99
|
-
// src/init.js
|
|
100
|
-
var
|
|
99
|
+
// src/koffi/src/init.js
|
|
100
|
+
var require2 = createRequire(import.meta.url);
|
|
101
101
|
function detectPlatform() {
|
|
102
102
|
if (process.versions.napi == null || process.versions.napi < package_default.cnoke.napi) {
|
|
103
103
|
let major = parseInt(process.versions.node, 10);
|
|
104
|
-
throw new Error(`This engine is based on Node ${process.versions.node}, but ${package_default.name} does not support the Node ${major}.x branch (
|
|
104
|
+
throw new Error(`This engine is based on Node ${process.versions.node}, but ${package_default.name} does not support the Node ${major}.x branch (Node-API < ${package_default.cnoke.napi})`);
|
|
105
105
|
}
|
|
106
106
|
let abi = determineAbi();
|
|
107
107
|
let pkg2 = `${process.platform}-${process.arch}`;
|
|
@@ -110,13 +110,20 @@ function detectPlatform() {
|
|
|
110
110
|
triplets2.push(`musl_${abi}`);
|
|
111
111
|
return [package_default.version, pkg2, triplets2];
|
|
112
112
|
}
|
|
113
|
-
function loadDynamic(
|
|
113
|
+
function loadDynamic(dirname, pkg2, triplets2) {
|
|
114
|
+
let suffix = "/../../build/koffi";
|
|
115
|
+
let root = dirname + suffix;
|
|
114
116
|
let roots = [root];
|
|
115
117
|
let native2 = null;
|
|
116
118
|
let err = null;
|
|
117
|
-
if (process
|
|
118
|
-
|
|
119
|
-
|
|
119
|
+
if (process["resourcesPath"] != null) {
|
|
120
|
+
let suffixes = [
|
|
121
|
+
"/koffi",
|
|
122
|
+
"/koffi/build",
|
|
123
|
+
"/node_modules/koffi/build"
|
|
124
|
+
];
|
|
125
|
+
for (let suffix2 of suffixes)
|
|
126
|
+
roots.push(process["resourcesPath"] + suffix2);
|
|
120
127
|
}
|
|
121
128
|
let names = [
|
|
122
129
|
`${import.meta.dirname}/../../../@koromix/koffi-${pkg2}`,
|
|
@@ -126,42 +133,43 @@ function loadDynamic(root, pkg2, triplets2) {
|
|
|
126
133
|
if (!fs2.existsSync(name))
|
|
127
134
|
continue;
|
|
128
135
|
try {
|
|
129
|
-
native2 =
|
|
136
|
+
native2 = require2(name);
|
|
130
137
|
break;
|
|
131
138
|
} catch (e) {
|
|
132
139
|
err ??= e;
|
|
133
140
|
}
|
|
134
141
|
}
|
|
135
|
-
if (native2 == null)
|
|
136
|
-
err ??= new Error("Cannot find the native Koffi module; did you bundle it correctly?");
|
|
142
|
+
if (native2 == null && err != null)
|
|
137
143
|
throw err;
|
|
138
|
-
}
|
|
139
144
|
return native2;
|
|
140
145
|
}
|
|
141
|
-
function wrapNative(native2) {
|
|
146
|
+
function wrapNative(native2, version2) {
|
|
147
|
+
if (native2 == null)
|
|
148
|
+
throw new Error("Cannot find the native Koffi module; did you bundle it correctly?");
|
|
149
|
+
if (native2.version != version2)
|
|
150
|
+
throw new Error("Mismatched native Koffi modules");
|
|
142
151
|
let load = native2.load;
|
|
143
152
|
let register = native2.register;
|
|
144
|
-
|
|
145
|
-
native2.
|
|
153
|
+
let introspect = native2.introspect ?? native2.type;
|
|
154
|
+
native2.sizeof = (spec) => introspect(spec).size;
|
|
155
|
+
native2.alignof = (spec) => introspect(spec).alignment;
|
|
146
156
|
native2.offsetof = (spec, name) => {
|
|
147
|
-
let
|
|
148
|
-
if (
|
|
157
|
+
let info = introspect(spec);
|
|
158
|
+
if (info.primitive != "Record")
|
|
149
159
|
throw new TypeError("The offsetof() function can only be used with record types");
|
|
150
|
-
let member =
|
|
160
|
+
let member = info.members[name];
|
|
151
161
|
if (member == null)
|
|
152
|
-
throw new Error(`Record type ${
|
|
162
|
+
throw new Error(`Record type ${info.name} does not have member '${name}'`);
|
|
153
163
|
return member.offset;
|
|
154
164
|
};
|
|
155
165
|
native2.register = (...args) => {
|
|
156
166
|
if (args.length >= 3 && typeof args[1] == "function") {
|
|
157
|
-
process.emitWarning("Using koffi.register() with a custom this value was deprecated in Koffi
|
|
167
|
+
process.emitWarning("Using koffi.register() with a custom this value was deprecated in Koffi 2.17, use function.bind() instead", "DeprecationWarning", "KOFFI009");
|
|
158
168
|
args[1] = args[1].bind(args[0]);
|
|
159
169
|
args = args.slice(1);
|
|
160
170
|
}
|
|
161
171
|
return register(...args);
|
|
162
172
|
};
|
|
163
|
-
native2.resolve = util.deprecate(native2.type, "The koffi.resolve() function was deprecated in Koffi 3.0, use koffi.type() instead", "KOFFI007");
|
|
164
|
-
native2.introspect = util.deprecate(native2.type, "The koffi.introspect() function was deprecated in Koffi 3.0, use koffi.type() instead", "KOFFI008");
|
|
165
173
|
native2.load = (...args) => {
|
|
166
174
|
let lib = load(...args);
|
|
167
175
|
lib.cdecl = util.deprecate((...args2) => lib.func("__cdecl", ...args2), "The koffi.cdecl() function was deprecated in Koffi 2.7, use koffi.func(...) instead", "KOFFI003");
|
|
@@ -170,22 +178,103 @@ function wrapNative(native2) {
|
|
|
170
178
|
lib.thiscall = util.deprecate((...args2) => lib.func("__thiscall", ...args2), 'The koffi.thiscall() function was deprecated in Koffi 2.7, use koffi.func("__thiscall", ...) instead', "KOFFI006");
|
|
171
179
|
return lib;
|
|
172
180
|
};
|
|
181
|
+
if (native2.introspect == null) {
|
|
182
|
+
native2.resolve = util.deprecate(native2.type, "The koffi.resolve() function was deprecated in Koffi 3.0, use koffi.type() instead", "KOFFI007");
|
|
183
|
+
native2.introspect = util.deprecate(native2.type, "The koffi.introspect() function was deprecated in Koffi 3.0, use koffi.type() instead", "KOFFI008");
|
|
184
|
+
} else {
|
|
185
|
+
native2.resolve = native2.type;
|
|
186
|
+
}
|
|
173
187
|
}
|
|
174
188
|
|
|
175
|
-
// src/
|
|
176
|
-
import { createRequire as createRequire2 } from "node:module";
|
|
177
|
-
var requireNative2 = createRequire2(import.meta.url);
|
|
178
|
-
var BINARY_ROOT = import.meta.dirname + "/../../build/koffi";
|
|
179
|
-
|
|
180
|
-
// index.js
|
|
189
|
+
// src/koffi/indirect.js
|
|
181
190
|
var [version, pkg, triplets] = detectPlatform();
|
|
182
|
-
var native =
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
var
|
|
191
|
+
var native = loadDynamic(import.meta.dirname, pkg, triplets);
|
|
192
|
+
wrapNative(native, version);
|
|
193
|
+
var mod_LibraryHandle = native.LibraryHandle;
|
|
194
|
+
var mod_TypeObject = native.TypeObject;
|
|
195
|
+
var mod_Union = native.Union;
|
|
196
|
+
var mod_address = native.address;
|
|
197
|
+
var mod_alias = native.alias;
|
|
198
|
+
var mod_alignof = native.alignof;
|
|
199
|
+
var mod_alloc = native.alloc;
|
|
200
|
+
var mod_array = native.array;
|
|
201
|
+
var mod_as = native.as;
|
|
202
|
+
var mod_call = native.call;
|
|
203
|
+
var mod_config = native.config;
|
|
204
|
+
var mod_decode = native.decode;
|
|
205
|
+
var mod_disposable = native.disposable;
|
|
206
|
+
var mod_encode = native.encode;
|
|
207
|
+
var mod_enumeration = native.enumeration;
|
|
208
|
+
var mod_errno = native.errno;
|
|
209
|
+
var mod_extension = native.extension;
|
|
210
|
+
var mod_free = native.free;
|
|
211
|
+
var mod_in = native.in;
|
|
212
|
+
var mod_inout = native.inout;
|
|
213
|
+
var mod_introspect = native.introspect;
|
|
214
|
+
var mod_load = native.load;
|
|
215
|
+
var mod_node = native.node;
|
|
216
|
+
var mod_offsetof = native.offsetof;
|
|
217
|
+
var mod_opaque = native.opaque;
|
|
218
|
+
var mod_os = native.os;
|
|
219
|
+
var mod_out = native.out;
|
|
220
|
+
var mod_pack = native.pack;
|
|
221
|
+
var mod_pointer = native.pointer;
|
|
222
|
+
var mod_proto = native.proto;
|
|
223
|
+
var mod_register = native.register;
|
|
224
|
+
var mod_reset = native.reset;
|
|
225
|
+
var mod_resolve = native.resolve;
|
|
226
|
+
var mod_sizeof = native.sizeof;
|
|
227
|
+
var mod_stats = native.stats;
|
|
228
|
+
var mod_struct = native.struct;
|
|
229
|
+
var mod_type = native.type;
|
|
230
|
+
var mod_types = native.types;
|
|
231
|
+
var mod_union = native.union;
|
|
232
|
+
var mod_unregister = native.unregister;
|
|
233
|
+
var mod_version = native.version;
|
|
234
|
+
var mod_view = native.view;
|
|
235
|
+
var indirect_default = native;
|
|
189
236
|
export {
|
|
190
|
-
|
|
237
|
+
mod_LibraryHandle as LibraryHandle,
|
|
238
|
+
mod_TypeObject as TypeObject,
|
|
239
|
+
mod_Union as Union,
|
|
240
|
+
mod_address as address,
|
|
241
|
+
mod_alias as alias,
|
|
242
|
+
mod_alignof as alignof,
|
|
243
|
+
mod_alloc as alloc,
|
|
244
|
+
mod_array as array,
|
|
245
|
+
mod_as as as,
|
|
246
|
+
mod_call as call,
|
|
247
|
+
mod_config as config,
|
|
248
|
+
mod_decode as decode,
|
|
249
|
+
indirect_default as default,
|
|
250
|
+
mod_disposable as disposable,
|
|
251
|
+
mod_encode as encode,
|
|
252
|
+
mod_enumeration as enumeration,
|
|
253
|
+
mod_errno as errno,
|
|
254
|
+
mod_extension as extension,
|
|
255
|
+
mod_free as free,
|
|
256
|
+
mod_in as in,
|
|
257
|
+
mod_inout as inout,
|
|
258
|
+
mod_introspect as introspect,
|
|
259
|
+
mod_load as load,
|
|
260
|
+
mod_node as node,
|
|
261
|
+
mod_offsetof as offsetof,
|
|
262
|
+
mod_opaque as opaque,
|
|
263
|
+
mod_os as os,
|
|
264
|
+
mod_out as out,
|
|
265
|
+
mod_pack as pack,
|
|
266
|
+
mod_pointer as pointer,
|
|
267
|
+
mod_proto as proto,
|
|
268
|
+
mod_register as register,
|
|
269
|
+
mod_reset as reset,
|
|
270
|
+
mod_resolve as resolve,
|
|
271
|
+
mod_sizeof as sizeof,
|
|
272
|
+
mod_stats as stats,
|
|
273
|
+
mod_struct as struct,
|
|
274
|
+
mod_type as type,
|
|
275
|
+
mod_types as types,
|
|
276
|
+
mod_union as union,
|
|
277
|
+
mod_unregister as unregister,
|
|
278
|
+
mod_version as version,
|
|
279
|
+
mod_view as view
|
|
191
280
|
};
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
#include "lib/native/base/base.hh"
|
|
7
7
|
#include "../ffi.hh"
|
|
8
8
|
#include "../call.hh"
|
|
9
|
+
#include "../type.hh"
|
|
9
10
|
#include "../util.hh"
|
|
10
11
|
#if defined(_WIN32)
|
|
11
12
|
#include "../win32.hh"
|
|
@@ -53,17 +54,17 @@ enum class AbiOpcode {
|
|
|
53
54
|
#define PRIMITIVE(Name) Push ## Name,
|
|
54
55
|
#include "../primitives.inc"
|
|
55
56
|
PushAggregateReg,
|
|
56
|
-
|
|
57
|
+
PushAggregateMem,
|
|
57
58
|
#define PRIMITIVE(Name) Run ## Name,
|
|
58
59
|
#include "../primitives.inc"
|
|
59
60
|
RunAggregateGG,
|
|
60
61
|
RunAggregateDDDD,
|
|
61
|
-
|
|
62
|
+
RunAggregateMem,
|
|
62
63
|
#define PRIMITIVE(Name) Run ## Name ## X,
|
|
63
64
|
#include "../primitives.inc"
|
|
64
65
|
RunAggregateGGX,
|
|
65
66
|
RunAggregateDDDDX,
|
|
66
|
-
|
|
67
|
+
RunAggregateMemX,
|
|
67
68
|
Yield,
|
|
68
69
|
CallGG,
|
|
69
70
|
CallF,
|
|
@@ -76,7 +77,7 @@ enum class AbiOpcode {
|
|
|
76
77
|
#define PRIMITIVE(Name) Return ## Name,
|
|
77
78
|
#include "../primitives.inc"
|
|
78
79
|
ReturnAggregateReg,
|
|
79
|
-
|
|
80
|
+
ReturnAggregateMem,
|
|
80
81
|
#if defined(_M_ARM64EC)
|
|
81
82
|
SetVariadicRegisters
|
|
82
83
|
#endif
|
|
@@ -220,8 +221,8 @@ bool AnalyseFunction(Napi::Env, InstanceData *instance, FunctionInfo *func)
|
|
|
220
221
|
|
|
221
222
|
param.abi.indirect = true;
|
|
222
223
|
|
|
223
|
-
func->sync.Append({ .op = Code2Op(AbiOpcode::
|
|
224
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
224
|
+
func->sync.Append({ .op = Code2Op(AbiOpcode::PushAggregateMem), .a = param.offset, .b1 = (int16_t)param.abi.offset, .type = param.type });
|
|
225
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::PushAggregateMem), .a = param.offset, .b1 = (int16_t)param.abi.offset, .type = param.type });
|
|
225
226
|
}
|
|
226
227
|
|
|
227
228
|
break;
|
|
@@ -262,8 +263,8 @@ bool AnalyseFunction(Napi::Env, InstanceData *instance, FunctionInfo *func)
|
|
|
262
263
|
|
|
263
264
|
param.abi.indirect = true;
|
|
264
265
|
|
|
265
|
-
func->sync.Append({ .op = Code2Op(AbiOpcode::
|
|
266
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
266
|
+
func->sync.Append({ .op = Code2Op(AbiOpcode::PushAggregateMem), .a = param.offset, .b1 = (int16_t)param.abi.offset, .type = param.type });
|
|
267
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::PushAggregateMem), .a = param.offset, .b1 = (int16_t)param.abi.offset, .type = param.type });
|
|
267
268
|
}
|
|
268
269
|
|
|
269
270
|
break;
|
|
@@ -340,8 +341,8 @@ bool AnalyseFunction(Napi::Env, InstanceData *instance, FunctionInfo *func)
|
|
|
340
341
|
|
|
341
342
|
param.abi.indirect = true;
|
|
342
343
|
|
|
343
|
-
func->sync.Append({ .op = Code2Op(AbiOpcode::
|
|
344
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
344
|
+
func->sync.Append({ .op = Code2Op(AbiOpcode::PushAggregateMem), .a = param.offset, .b1 = (int16_t)param.abi.offset, .type = param.type });
|
|
345
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::PushAggregateMem), .a = param.offset, .b1 = (int16_t)param.abi.offset, .type = param.type });
|
|
345
346
|
}
|
|
346
347
|
} break;
|
|
347
348
|
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
@@ -508,12 +509,12 @@ bool AnalyseFunction(Napi::Env, InstanceData *instance, FunctionInfo *func)
|
|
|
508
509
|
func->async.Append({ .op = Code2Op(call) });
|
|
509
510
|
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateReg), .type = func->ret.type });
|
|
510
511
|
} else {
|
|
511
|
-
AbiOpcode run = func->forward_fp ? AbiOpcode::
|
|
512
|
+
AbiOpcode run = func->forward_fp ? AbiOpcode::RunAggregateMemX : AbiOpcode::RunAggregateMem;
|
|
512
513
|
AbiOpcode call = func->forward_fp ? AbiOpcode::CallStackX : AbiOpcode::CallStack;
|
|
513
514
|
|
|
514
515
|
func->sync.Append({ .op = Code2Op(run), .a = (int32_t)func->ret.type->size, .type = func->ret.type });
|
|
515
516
|
func->async.Append({ .op = Code2Op(call), .a = (int32_t)func->ret.type->size });
|
|
516
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
517
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateMem), .type = func->ret.type });
|
|
517
518
|
}
|
|
518
519
|
} break;
|
|
519
520
|
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
@@ -716,7 +717,7 @@ namespace {
|
|
|
716
717
|
|
|
717
718
|
NEXT();
|
|
718
719
|
}
|
|
719
|
-
OP(
|
|
720
|
+
OP(PushAggregateMem) {
|
|
720
721
|
napi_value arg = args[inst->a];
|
|
721
722
|
|
|
722
723
|
if (!IsObject(call->env, arg)) [[unlikely]] {
|
|
@@ -817,17 +818,17 @@ namespace {
|
|
|
817
818
|
OP(RunPrototype) { K_UNREACHABLE(); return call->env.Null(); }
|
|
818
819
|
OP(RunAggregateGG) {
|
|
819
820
|
auto ret = WRAP(ForwardCallGG(call->native, base, &call->saved_sp));
|
|
820
|
-
return DecodeObject(call->
|
|
821
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
821
822
|
}
|
|
822
823
|
OP(RunAggregateDDDD) {
|
|
823
824
|
auto ret = WRAP(ForwardCallDDDD(call->native, base, &call->saved_sp));
|
|
824
|
-
return DecodeObject(call->
|
|
825
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
825
826
|
}
|
|
826
|
-
OP(
|
|
827
|
+
OP(RunAggregateMem) {
|
|
827
828
|
uint8_t *ptr = call->AllocHeap(inst->a);
|
|
828
829
|
*(uint8_t **)(base + 8 * 8) = ptr; // x8
|
|
829
830
|
WRAP(ForwardCallGG(call->native, base, &call->saved_sp));
|
|
830
|
-
return DecodeObject(call->
|
|
831
|
+
return DecodeObject(call->instance, ptr, inst->type);
|
|
831
832
|
}
|
|
832
833
|
OP(RunVoidX) {
|
|
833
834
|
WRAP(ForwardCallGGX(call->native, base, &call->saved_sp));
|
|
@@ -893,17 +894,17 @@ namespace {
|
|
|
893
894
|
OP(RunPrototypeX) { K_UNREACHABLE(); return call->env.Null(); }
|
|
894
895
|
OP(RunAggregateGGX) {
|
|
895
896
|
auto ret = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp));
|
|
896
|
-
return DecodeObject(call->
|
|
897
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
897
898
|
}
|
|
898
899
|
OP(RunAggregateDDDDX) {
|
|
899
900
|
auto ret = WRAP(ForwardCallDDDDX(call->native, base, &call->saved_sp));
|
|
900
|
-
return DecodeObject(call->
|
|
901
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
901
902
|
}
|
|
902
|
-
OP(
|
|
903
|
+
OP(RunAggregateMemX) {
|
|
903
904
|
uint8_t *ptr = call->AllocHeap(inst->a);
|
|
904
905
|
*(uint8_t **)(base + 8 * 8) = ptr; // x8
|
|
905
906
|
WRAP(ForwardCallGGX(call->native, base, &call->saved_sp));
|
|
906
|
-
return DecodeObject(call->
|
|
907
|
+
return DecodeObject(call->instance, ptr, inst->type);
|
|
907
908
|
}
|
|
908
909
|
|
|
909
910
|
#undef DISPOSE
|
|
@@ -1026,10 +1027,10 @@ namespace {
|
|
|
1026
1027
|
return Napi::Number::New(call->env, d);
|
|
1027
1028
|
}
|
|
1028
1029
|
OP(ReturnPrototype) { K_UNREACHABLE(); return call->env.Null(); }
|
|
1029
|
-
OP(ReturnAggregateReg) { return DecodeObject(call->
|
|
1030
|
-
OP(
|
|
1030
|
+
OP(ReturnAggregateReg) { return DecodeObject(call->instance, base, inst->type); }
|
|
1031
|
+
OP(ReturnAggregateMem) {
|
|
1031
1032
|
const uint8_t *ptr = *(const uint8_t **)base;
|
|
1032
|
-
return DecodeObject(call->
|
|
1033
|
+
return DecodeObject(call->instance, ptr, inst->type);
|
|
1033
1034
|
}
|
|
1034
1035
|
|
|
1035
1036
|
#if defined(_M_ARM64EC)
|
|
@@ -1053,17 +1054,17 @@ namespace {
|
|
|
1053
1054
|
#define PRIMITIVE(Name) HandlePush ## Name,
|
|
1054
1055
|
#include "../primitives.inc"
|
|
1055
1056
|
HandlePushAggregateReg,
|
|
1056
|
-
|
|
1057
|
+
HandlePushAggregateMem,
|
|
1057
1058
|
#define PRIMITIVE(Name) HandleRun ## Name,
|
|
1058
1059
|
#include "../primitives.inc"
|
|
1059
1060
|
HandleRunAggregateGG,
|
|
1060
1061
|
HandleRunAggregateDDDD,
|
|
1061
|
-
|
|
1062
|
+
HandleRunAggregateMem,
|
|
1062
1063
|
#define PRIMITIVE(Name) HandleRun ## Name ## X,
|
|
1063
1064
|
#include "../primitives.inc"
|
|
1064
1065
|
HandleRunAggregateGGX,
|
|
1065
1066
|
HandleRunAggregateDDDDX,
|
|
1066
|
-
|
|
1067
|
+
HandleRunAggregateMemX,
|
|
1067
1068
|
HandleYield,
|
|
1068
1069
|
HandleCallGG,
|
|
1069
1070
|
HandleCallF,
|
|
@@ -1076,7 +1077,7 @@ namespace {
|
|
|
1076
1077
|
#define PRIMITIVE(Name) HandleReturn ## Name,
|
|
1077
1078
|
#include "../primitives.inc"
|
|
1078
1079
|
HandleReturnAggregateReg,
|
|
1079
|
-
|
|
1080
|
+
HandleReturnAggregateMem,
|
|
1080
1081
|
#if defined(_M_ARM64EC)
|
|
1081
1082
|
HandleSetVariadicRegisters
|
|
1082
1083
|
#endif
|
|
@@ -1242,7 +1243,7 @@ void CallData::Relay(Size idx, uint8_t *sp)
|
|
|
1242
1243
|
uint8_t *ptr = in_ptr + param.abi.offset;
|
|
1243
1244
|
uint8_t *src = param.abi.indirect ? *(uint8_t **)ptr : ptr;
|
|
1244
1245
|
|
|
1245
|
-
arguments[i] = DecodeObject(
|
|
1246
|
+
arguments[i] = DecodeObject(instance, src, param.type);
|
|
1246
1247
|
} break;
|
|
1247
1248
|
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|
|
1248
1249
|
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
#include "lib/native/base/base.hh"
|
|
7
7
|
#include "../ffi.hh"
|
|
8
8
|
#include "../call.hh"
|
|
9
|
+
#include "../type.hh"
|
|
9
10
|
#include "../util.hh"
|
|
10
11
|
|
|
11
12
|
#include <napi.h>
|
|
@@ -52,21 +53,21 @@ enum class AbiOpcode {
|
|
|
52
53
|
#define PRIMITIVE(Name) Push ## Name,
|
|
53
54
|
#include "../primitives.inc"
|
|
54
55
|
PushAggregateReg,
|
|
55
|
-
|
|
56
|
+
PushAggregateMem,
|
|
56
57
|
#define PRIMITIVE(Name) Run ## Name,
|
|
57
58
|
#include "../primitives.inc"
|
|
58
59
|
RunAggregateGG,
|
|
59
60
|
RunAggregateDD,
|
|
60
61
|
RunAggregateGD,
|
|
61
62
|
RunAggregateDG,
|
|
62
|
-
|
|
63
|
+
RunAggregateMem,
|
|
63
64
|
#define PRIMITIVE(Name) Run ## Name ## X,
|
|
64
65
|
#include "../primitives.inc"
|
|
65
66
|
RunAggregateGGX,
|
|
66
67
|
RunAggregateDDX,
|
|
67
68
|
RunAggregateGDX,
|
|
68
69
|
RunAggregateDGX,
|
|
69
|
-
|
|
70
|
+
RunAggregateMemX,
|
|
70
71
|
Yield,
|
|
71
72
|
CallGG,
|
|
72
73
|
CallF,
|
|
@@ -83,7 +84,7 @@ enum class AbiOpcode {
|
|
|
83
84
|
#define PRIMITIVE(Name) Return ## Name,
|
|
84
85
|
#include "../primitives.inc"
|
|
85
86
|
ReturnAggregateReg,
|
|
86
|
-
|
|
87
|
+
ReturnAggregateMem
|
|
87
88
|
};
|
|
88
89
|
|
|
89
90
|
enum class AbiMethod {
|
|
@@ -324,7 +325,7 @@ bool AnalyseFunction(Napi::Env, InstanceData *instance, FunctionInfo *func)
|
|
|
324
325
|
}
|
|
325
326
|
|
|
326
327
|
if (param.type->primitive == PrimitiveKind::Record || param.type->primitive == PrimitiveKind::Union) {
|
|
327
|
-
AbiOpcode code = (param.abi.method != AbiMethod::Memory) ? AbiOpcode::PushAggregateReg : AbiOpcode::
|
|
328
|
+
AbiOpcode code = (param.abi.method != AbiMethod::Memory) ? AbiOpcode::PushAggregateReg : AbiOpcode::PushAggregateMem;
|
|
328
329
|
|
|
329
330
|
func->sync.Append({ .op = Code2Op(code), .a = param.offset, .b1 = (int16_t)param.abi.offsets[0], .b2 = (int16_t)param.abi.offsets[1], .type = param.type });
|
|
330
331
|
func->async.Append({ .op = Code2Op(code), .a = param.offset, .b1 = (int16_t)param.abi.offsets[0], .b2 = (int16_t)param.abi.offsets[1], .type = param.type });
|
|
@@ -407,12 +408,12 @@ bool AnalyseFunction(Napi::Env, InstanceData *instance, FunctionInfo *func)
|
|
|
407
408
|
case PrimitiveKind::Union: {
|
|
408
409
|
switch (func->ret.abi.method) {
|
|
409
410
|
case AbiMethod::Memory: {
|
|
410
|
-
AbiOpcode run = func->forward_fp ? AbiOpcode::
|
|
411
|
+
AbiOpcode run = func->forward_fp ? AbiOpcode::RunAggregateMemX : AbiOpcode::RunAggregateMem;
|
|
411
412
|
AbiOpcode call = func->forward_fp ? AbiOpcode::CallStackX : AbiOpcode::CallStack;
|
|
412
413
|
|
|
413
414
|
func->sync.Append({ .op = Code2Op(run), .a = (int32_t)func->ret.type->size, .type = func->ret.type });
|
|
414
415
|
func->async.Append({ .op = Code2Op(call), .a = (int32_t)func->ret.type->size });
|
|
415
|
-
func->async.Append({ .op = Code2Op(AbiOpcode::
|
|
416
|
+
func->async.Append({ .op = Code2Op(AbiOpcode::ReturnAggregateMem), .type = func->ret.type });
|
|
416
417
|
} break;
|
|
417
418
|
|
|
418
419
|
case AbiMethod::Gpr:
|
|
@@ -643,7 +644,7 @@ namespace {
|
|
|
643
644
|
|
|
644
645
|
NEXT();
|
|
645
646
|
}
|
|
646
|
-
OP(
|
|
647
|
+
OP(PushAggregateMem) {
|
|
647
648
|
napi_value arg = args[inst->a];
|
|
648
649
|
|
|
649
650
|
if (!IsObject(call->env, arg)) [[unlikely]] {
|
|
@@ -746,25 +747,25 @@ namespace {
|
|
|
746
747
|
OP(RunPrototype) { K_UNREACHABLE(); return call->env.Null(); }
|
|
747
748
|
OP(RunAggregateGG) {
|
|
748
749
|
auto ret = WRAP(ForwardCallGG(call->native, base, &call->saved_sp));
|
|
749
|
-
return DecodeObject(call->
|
|
750
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
750
751
|
}
|
|
751
752
|
OP(RunAggregateDD) {
|
|
752
753
|
auto ret = WRAP(ForwardCallDD(call->native, base, &call->saved_sp));
|
|
753
|
-
return DecodeObject(call->
|
|
754
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
754
755
|
}
|
|
755
756
|
OP(RunAggregateGD) {
|
|
756
757
|
auto ret = WRAP(ForwardCallGD(call->native, base, &call->saved_sp));
|
|
757
|
-
return DecodeObject(call->
|
|
758
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
758
759
|
}
|
|
759
760
|
OP(RunAggregateDG) {
|
|
760
761
|
auto ret = WRAP(ForwardCallDG(call->native, base, &call->saved_sp));
|
|
761
|
-
return DecodeObject(call->
|
|
762
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
762
763
|
}
|
|
763
|
-
OP(
|
|
764
|
+
OP(RunAggregateMem) {
|
|
764
765
|
uint8_t *ptr = call->AllocHeap(inst->a);
|
|
765
766
|
*(uint8_t **)base = ptr;
|
|
766
767
|
WRAP(ForwardCallGG(call->native, base, &call->saved_sp));
|
|
767
|
-
return DecodeObject(call->
|
|
768
|
+
return DecodeObject(call->instance, ptr, inst->type);
|
|
768
769
|
}
|
|
769
770
|
OP(RunVoidX) {
|
|
770
771
|
WRAP(ForwardCallGGX(call->native, base, &call->saved_sp));
|
|
@@ -830,25 +831,25 @@ namespace {
|
|
|
830
831
|
OP(RunPrototypeX) { K_UNREACHABLE(); return call->env.Null(); }
|
|
831
832
|
OP(RunAggregateGGX) {
|
|
832
833
|
auto ret = WRAP(ForwardCallGGX(call->native, base, &call->saved_sp));
|
|
833
|
-
return DecodeObject(call->
|
|
834
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
834
835
|
}
|
|
835
836
|
OP(RunAggregateDDX) {
|
|
836
837
|
auto ret = WRAP(ForwardCallDDX(call->native, base, &call->saved_sp));
|
|
837
|
-
return DecodeObject(call->
|
|
838
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
838
839
|
}
|
|
839
840
|
OP(RunAggregateGDX) {
|
|
840
841
|
auto ret = WRAP(ForwardCallGDX(call->native, base, &call->saved_sp));
|
|
841
|
-
return DecodeObject(call->
|
|
842
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
842
843
|
}
|
|
843
844
|
OP(RunAggregateDGX) {
|
|
844
845
|
auto ret = WRAP(ForwardCallDGX(call->native, base, &call->saved_sp));
|
|
845
|
-
return DecodeObject(call->
|
|
846
|
+
return DecodeObject(call->instance, (const uint8_t *)&ret, inst->type);
|
|
846
847
|
}
|
|
847
|
-
OP(
|
|
848
|
+
OP(RunAggregateMemX) {
|
|
848
849
|
uint8_t *ptr = call->AllocHeap(inst->a);
|
|
849
850
|
*(uint8_t **)base = ptr;
|
|
850
851
|
WRAP(ForwardCallGGX(call->native, base, &call->saved_sp));
|
|
851
|
-
return DecodeObject(call->
|
|
852
|
+
return DecodeObject(call->instance, ptr, inst->type);
|
|
852
853
|
}
|
|
853
854
|
|
|
854
855
|
#undef DISPOSE
|
|
@@ -965,10 +966,10 @@ namespace {
|
|
|
965
966
|
return Napi::Number::New(call->env, d);
|
|
966
967
|
}
|
|
967
968
|
OP(ReturnPrototype) { K_UNREACHABLE(); return call->env.Null(); }
|
|
968
|
-
OP(ReturnAggregateReg) { return DecodeObject(call->
|
|
969
|
-
OP(
|
|
969
|
+
OP(ReturnAggregateReg) { return DecodeObject(call->instance, (const uint8_t *)base, inst->type); }
|
|
970
|
+
OP(ReturnAggregateMem) {
|
|
970
971
|
uint64_t a0 = *(uint64_t *)base;
|
|
971
|
-
return DecodeObject(call->
|
|
972
|
+
return DecodeObject(call->instance, (const uint8_t *)a0, inst->type);
|
|
972
973
|
}
|
|
973
974
|
|
|
974
975
|
#undef INTEGER_SWAP
|
|
@@ -981,21 +982,21 @@ namespace {
|
|
|
981
982
|
#define PRIMITIVE(Name) HandlePush ## Name,
|
|
982
983
|
#include "../primitives.inc"
|
|
983
984
|
HandlePushAggregateReg,
|
|
984
|
-
|
|
985
|
+
HandlePushAggregateMem,
|
|
985
986
|
#define PRIMITIVE(Name) HandleRun ## Name,
|
|
986
987
|
#include "../primitives.inc"
|
|
987
988
|
HandleRunAggregateGG,
|
|
988
989
|
HandleRunAggregateDD,
|
|
989
990
|
HandleRunAggregateGD,
|
|
990
991
|
HandleRunAggregateDG,
|
|
991
|
-
|
|
992
|
+
HandleRunAggregateMem,
|
|
992
993
|
#define PRIMITIVE(Name) HandleRun ## Name ## X,
|
|
993
994
|
#include "../primitives.inc"
|
|
994
995
|
HandleRunAggregateGGX,
|
|
995
996
|
HandleRunAggregateDDX,
|
|
996
997
|
HandleRunAggregateGDX,
|
|
997
998
|
HandleRunAggregateDGX,
|
|
998
|
-
|
|
999
|
+
HandleRunAggregateMemX,
|
|
999
1000
|
HandleYield,
|
|
1000
1001
|
HandleCallGG,
|
|
1001
1002
|
HandleCallF,
|
|
@@ -1012,7 +1013,7 @@ namespace {
|
|
|
1012
1013
|
#define PRIMITIVE(Name) HandleReturn ## Name,
|
|
1013
1014
|
#include "../primitives.inc"
|
|
1014
1015
|
HandleReturnAggregateReg,
|
|
1015
|
-
|
|
1016
|
+
HandleReturnAggregateMem
|
|
1016
1017
|
};
|
|
1017
1018
|
|
|
1018
1019
|
FORCE_INLINE napi_value RunLoop(CallData *call, napi_value *args, uint8_t *base, const AbiInstruction *inst)
|
|
@@ -1177,10 +1178,10 @@ void CallData::Relay(Size idx, uint8_t *sp)
|
|
|
1177
1178
|
memcpy(buf, in_ptr + param.abi.offsets[0], 8);
|
|
1178
1179
|
memcpy(buf + 8, in_ptr + param.abi.offsets[1], 8);
|
|
1179
1180
|
|
|
1180
|
-
arguments[i] = DecodeObject(
|
|
1181
|
+
arguments[i] = DecodeObject(instance, buf, param.type);
|
|
1181
1182
|
} else {
|
|
1182
1183
|
uint8_t *ptr = *(uint8_t **)(in_ptr + param.abi.offsets[0]);
|
|
1183
|
-
arguments[i] = DecodeObject(
|
|
1184
|
+
arguments[i] = DecodeObject(instance, ptr, param.type);
|
|
1184
1185
|
}
|
|
1185
1186
|
} break;
|
|
1186
1187
|
case PrimitiveKind::Array: { K_UNREACHABLE(); } break;
|