koffi 1.0.1 → 1.0.4
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 +12 -11
- package/README.md +23 -20
- package/build/qemu/1.0.4/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/1.0.4/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/1.0.4/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/1.0.4/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/1.0.4/koffi_linux_arm.tar.gz +0 -0
- package/build/qemu/1.0.4/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/1.0.4/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/1.0.4/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/1.0.4/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/1.0.4/koffi_win32_x64.tar.gz +0 -0
- package/package.json +8 -4
- package/qemu/qemu.js +794 -0
- package/qemu/registry/machines.json +415 -0
- package/qemu/registry/sha256sum.txt +45 -0
- package/src/{call_arm32.cc → abi_arm32.cc} +153 -219
- package/src/{call_arm32_fwd.S → abi_arm32_fwd.S} +0 -0
- package/src/{call_arm64.cc → abi_arm64.cc} +130 -123
- package/src/{call_arm64_fwd.S → abi_arm64_fwd.S} +0 -0
- package/src/{call_x64_sysv.cc → abi_x64_sysv.cc} +138 -135
- package/src/{call_x64_sysv_fwd.S → abi_x64_sysv_fwd.S} +0 -0
- package/src/{call_x64_win.cc → abi_x64_win.cc} +107 -99
- package/src/{call_x64_win_fwd.asm → abi_x64_win_fwd.asm} +0 -0
- package/src/{call_x86.cc → abi_x86.cc} +110 -107
- package/src/{call_x86_fwd.S → abi_x86_fwd.S} +0 -0
- package/src/{call_x86_fwd.asm → abi_x86_fwd.asm} +0 -0
- package/src/call.cc +353 -0
- package/src/call.hh +132 -4
- package/src/ffi.cc +16 -2
- package/src/ffi.hh +8 -12
- package/src/util.cc +7 -280
- package/src/util.hh +0 -107
- package/test/CMakeLists.txt +1 -0
- package/test/misc.c +355 -0
- package/test/misc.def +3 -0
- package/test/misc.js +227 -0
- package/test/raylib.js +165 -0
- package/test/sqlite.js +104 -0
- package/vendor/libcc/libcc.hh +1 -1
- package/build/qemu/1.0.1/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_linux_arm.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/1.0.1/koffi_win32_x64.tar.gz +0 -0
|
@@ -51,31 +51,19 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
|
|
|
51
51
|
return true;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
|
|
54
|
+
bool CallData::Prepare(const Napi::CallbackInfo &info)
|
|
55
55
|
{
|
|
56
|
-
Napi::Env env = info.Env();
|
|
57
|
-
CallData call(env, instance, func);
|
|
58
|
-
|
|
59
|
-
// Sanity checks
|
|
60
|
-
if (info.Length() < (uint32_t)func->parameters.len) {
|
|
61
|
-
ThrowError<Napi::TypeError>(env, "Expected %1 arguments, got %2", func->parameters.len, info.Length());
|
|
62
|
-
return env.Null();
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
uint8_t *return_ptr = nullptr;
|
|
66
56
|
uint64_t *args_ptr = nullptr;
|
|
67
57
|
|
|
68
58
|
// Pass return value in register or through memory
|
|
69
|
-
if (RG_UNLIKELY(!
|
|
70
|
-
return
|
|
59
|
+
if (RG_UNLIKELY(!AllocStack(func->args_size, 16, &args_ptr)))
|
|
60
|
+
return false;
|
|
71
61
|
if (!func->ret.regular) {
|
|
72
|
-
if (RG_UNLIKELY(!
|
|
73
|
-
return
|
|
62
|
+
if (RG_UNLIKELY(!AllocHeap(func->ret.type->size, 16, &return_ptr)))
|
|
63
|
+
return false;
|
|
74
64
|
*(uint8_t **)(args_ptr++) = return_ptr;
|
|
75
65
|
}
|
|
76
66
|
|
|
77
|
-
LocalArray<OutObject, MaxOutParameters> out_objects;
|
|
78
|
-
|
|
79
67
|
// Push arguments
|
|
80
68
|
for (Size i = 0; i < func->parameters.len; i++) {
|
|
81
69
|
const ParameterInfo ¶m = func->parameters[i];
|
|
@@ -89,7 +77,7 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
89
77
|
case PrimitiveKind::Bool: {
|
|
90
78
|
if (RG_UNLIKELY(!value.IsBoolean())) {
|
|
91
79
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected boolean", GetValueType(instance, value), i + 1);
|
|
92
|
-
return
|
|
80
|
+
return false;
|
|
93
81
|
}
|
|
94
82
|
|
|
95
83
|
bool b = value.As<Napi::Boolean>();
|
|
@@ -106,46 +94,42 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
106
94
|
case PrimitiveKind::UInt64: {
|
|
107
95
|
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
108
96
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
|
|
109
|
-
return
|
|
97
|
+
return false;
|
|
110
98
|
}
|
|
111
99
|
|
|
112
100
|
int64_t v = CopyNumber<int64_t>(value);
|
|
113
101
|
*(args_ptr++) = (uint64_t)v;
|
|
114
102
|
} break;
|
|
115
|
-
case PrimitiveKind::Float32: {
|
|
116
|
-
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
117
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
|
|
118
|
-
return env.Null();
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
float f = CopyNumber<float>(value);
|
|
122
|
-
*(float *)(args_ptr++) = f;
|
|
123
|
-
} break;
|
|
124
|
-
case PrimitiveKind::Float64: {
|
|
125
|
-
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
126
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
|
|
127
|
-
return env.Null();
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
double d = CopyNumber<double>(value);
|
|
131
|
-
*(double *)(args_ptr++) = d;
|
|
132
|
-
} break;
|
|
133
103
|
case PrimitiveKind::String: {
|
|
134
104
|
const char *str;
|
|
135
105
|
if (RG_LIKELY(value.IsString())) {
|
|
136
|
-
str =
|
|
106
|
+
str = PushString(value);
|
|
137
107
|
if (RG_UNLIKELY(!str))
|
|
138
|
-
return
|
|
108
|
+
return false;
|
|
139
109
|
} else if (IsNullOrUndefined(value)) {
|
|
140
110
|
str = nullptr;
|
|
141
111
|
} else {
|
|
142
112
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected string", GetValueType(instance, value), i + 1);
|
|
143
|
-
return
|
|
113
|
+
return false;
|
|
144
114
|
}
|
|
145
115
|
|
|
146
116
|
*(const char **)(args_ptr++) = str;
|
|
147
117
|
} break;
|
|
118
|
+
case PrimitiveKind::String16: {
|
|
119
|
+
const char16_t *str16;
|
|
120
|
+
if (RG_LIKELY(value.IsString())) {
|
|
121
|
+
str16 = PushString16(value);
|
|
122
|
+
if (RG_UNLIKELY(!str16))
|
|
123
|
+
return false;
|
|
124
|
+
} else if (IsNullOrUndefined(value)) {
|
|
125
|
+
str16 = nullptr;
|
|
126
|
+
} else {
|
|
127
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected string", GetValueType(instance, value), i + 1);
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
148
130
|
|
|
131
|
+
*(const char16_t **)(args_ptr++) = str16;
|
|
132
|
+
} break;
|
|
149
133
|
case PrimitiveKind::Pointer: {
|
|
150
134
|
uint8_t *ptr;
|
|
151
135
|
|
|
@@ -154,12 +138,12 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
154
138
|
} else if (IsObject(value) && param.type->ref->primitive == PrimitiveKind::Record) {
|
|
155
139
|
Napi::Object obj = value.As<Napi::Object>();
|
|
156
140
|
|
|
157
|
-
if (RG_UNLIKELY(!
|
|
158
|
-
return
|
|
141
|
+
if (RG_UNLIKELY(!AllocHeap(param.type->ref->size, 16, &ptr)))
|
|
142
|
+
return false;
|
|
159
143
|
|
|
160
144
|
if (param.directions & 1) {
|
|
161
|
-
if (!
|
|
162
|
-
return
|
|
145
|
+
if (!PushObject(obj, param.type->ref, ptr))
|
|
146
|
+
return false;
|
|
163
147
|
} else {
|
|
164
148
|
memset(ptr, 0, param.type->size);
|
|
165
149
|
}
|
|
@@ -171,97 +155,121 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
171
155
|
ptr = nullptr;
|
|
172
156
|
} else {
|
|
173
157
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected %3", GetValueType(instance, value), i + 1, param.type->name);
|
|
174
|
-
return
|
|
158
|
+
return false;
|
|
175
159
|
}
|
|
176
160
|
|
|
177
161
|
*(uint8_t **)(args_ptr++) = ptr;
|
|
178
162
|
} break;
|
|
179
|
-
|
|
180
163
|
case PrimitiveKind::Record: {
|
|
181
164
|
if (RG_UNLIKELY(!IsObject(value))) {
|
|
182
165
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected object", GetValueType(instance, value), i + 1);
|
|
183
|
-
return
|
|
166
|
+
return false;
|
|
184
167
|
}
|
|
185
168
|
|
|
186
169
|
uint8_t *ptr;
|
|
187
170
|
if (param.regular) {
|
|
188
171
|
ptr = (uint8_t *)(args_ptr++);
|
|
189
172
|
} else {
|
|
190
|
-
if (RG_UNLIKELY(!
|
|
191
|
-
return
|
|
173
|
+
if (RG_UNLIKELY(!AllocHeap(param.type->size, 16, &ptr)))
|
|
174
|
+
return false;
|
|
192
175
|
*(uint8_t **)(args_ptr++) = ptr;
|
|
193
176
|
}
|
|
194
177
|
|
|
195
178
|
Napi::Object obj = value.As<Napi::Object>();
|
|
196
|
-
if (!
|
|
197
|
-
return
|
|
179
|
+
if (!PushObject(obj, param.type, ptr))
|
|
180
|
+
return false;
|
|
181
|
+
} break;
|
|
182
|
+
case PrimitiveKind::Float32: {
|
|
183
|
+
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
184
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
float f = CopyNumber<float>(value);
|
|
189
|
+
*(float *)(args_ptr++) = f;
|
|
190
|
+
} break;
|
|
191
|
+
case PrimitiveKind::Float64: {
|
|
192
|
+
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
193
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
double d = CopyNumber<double>(value);
|
|
198
|
+
*(double *)(args_ptr++) = d;
|
|
198
199
|
} break;
|
|
199
200
|
}
|
|
200
201
|
}
|
|
201
202
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
}
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
205
|
|
|
206
|
+
void CallData::Execute()
|
|
207
|
+
{
|
|
206
208
|
#define PERFORM_CALL(Suffix) \
|
|
207
209
|
([&]() { \
|
|
208
|
-
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func,
|
|
209
|
-
: ForwardCall ## Suffix(func->func,
|
|
210
|
-
PopOutArguments(out_objects); \
|
|
210
|
+
auto ret = (func->forward_fp ? ForwardCallX ## Suffix(func->func, GetSP()) \
|
|
211
|
+
: ForwardCall ## Suffix(func->func, GetSP())); \
|
|
211
212
|
return ret; \
|
|
212
213
|
})()
|
|
213
214
|
|
|
214
|
-
// Execute and convert return value
|
|
215
215
|
switch (func->ret.type->primitive) {
|
|
216
|
-
case PrimitiveKind::
|
|
217
|
-
|
|
216
|
+
case PrimitiveKind::Void:
|
|
217
|
+
case PrimitiveKind::Bool:
|
|
218
|
+
case PrimitiveKind::Int8:
|
|
219
|
+
case PrimitiveKind::UInt8:
|
|
220
|
+
case PrimitiveKind::Int16:
|
|
221
|
+
case PrimitiveKind::UInt16:
|
|
222
|
+
case PrimitiveKind::Int32:
|
|
223
|
+
case PrimitiveKind::UInt32:
|
|
224
|
+
case PrimitiveKind::Int64:
|
|
225
|
+
case PrimitiveKind::UInt64:
|
|
226
|
+
case PrimitiveKind::String:
|
|
227
|
+
case PrimitiveKind::String16:
|
|
228
|
+
case PrimitiveKind::Pointer:
|
|
229
|
+
case PrimitiveKind::Record: { result.u64 = PERFORM_CALL(G); } break;
|
|
230
|
+
case PrimitiveKind::Float32: { result.f = PERFORM_CALL(F); } break;
|
|
231
|
+
case PrimitiveKind::Float64: { result.d = PERFORM_CALL(D); } break;
|
|
232
|
+
}
|
|
218
233
|
|
|
219
|
-
|
|
220
|
-
|
|
234
|
+
#undef PERFORM_CALL
|
|
235
|
+
}
|
|
221
236
|
|
|
222
|
-
|
|
223
|
-
|
|
237
|
+
Napi::Value CallData::Complete()
|
|
238
|
+
{
|
|
239
|
+
for (const OutObject &obj: out_objects) {
|
|
240
|
+
PopObject(obj.obj, obj.ptr, obj.type);
|
|
241
|
+
}
|
|
224
242
|
|
|
225
|
-
|
|
243
|
+
switch (func->ret.type->primitive) {
|
|
244
|
+
case PrimitiveKind::Void: return env.Null();
|
|
245
|
+
case PrimitiveKind::Bool: return Napi::Boolean::New(env, result.u32);
|
|
246
|
+
case PrimitiveKind::Int8:
|
|
247
|
+
case PrimitiveKind::UInt8:
|
|
248
|
+
case PrimitiveKind::Int16:
|
|
249
|
+
case PrimitiveKind::UInt16:
|
|
250
|
+
case PrimitiveKind::Int32:
|
|
251
|
+
case PrimitiveKind::UInt32: return Napi::Number::New(env, (double)result.u32);
|
|
252
|
+
case PrimitiveKind::Int64: return Napi::BigInt::New(env, (int64_t)result.u64);
|
|
253
|
+
case PrimitiveKind::UInt64: return Napi::BigInt::New(env, result.u64);
|
|
254
|
+
case PrimitiveKind::String: return Napi::String::New(env, (const char *)result.ptr);
|
|
255
|
+
case PrimitiveKind::String16: return Napi::String::New(env, (const char16_t *)result.ptr);
|
|
256
|
+
case PrimitiveKind::Pointer: {
|
|
257
|
+
Napi::External<void> external = Napi::External<void>::New(env, result.ptr);
|
|
258
|
+
SetValueTag(instance, external, func->ret.type);
|
|
259
|
+
|
|
260
|
+
return external;
|
|
226
261
|
} break;
|
|
262
|
+
case PrimitiveKind::Record: {
|
|
263
|
+
const uint8_t *ptr = return_ptr ? (const uint8_t *)return_ptr
|
|
264
|
+
: (const uint8_t *)&result.buf;
|
|
227
265
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
switch (func->ret.type->primitive) {
|
|
232
|
-
case PrimitiveKind::Void: return env.Null();
|
|
233
|
-
case PrimitiveKind::Bool: return Napi::Boolean::New(env, rax);
|
|
234
|
-
case PrimitiveKind::Int8: return Napi::Number::New(env, (double)rax);
|
|
235
|
-
case PrimitiveKind::UInt8: return Napi::Number::New(env, (double)rax);
|
|
236
|
-
case PrimitiveKind::Int16: return Napi::Number::New(env, (double)rax);
|
|
237
|
-
case PrimitiveKind::UInt16: return Napi::Number::New(env, (double)rax);
|
|
238
|
-
case PrimitiveKind::Int32: return Napi::Number::New(env, (double)rax);
|
|
239
|
-
case PrimitiveKind::UInt32: return Napi::Number::New(env, (double)rax);
|
|
240
|
-
case PrimitiveKind::Int64: return Napi::BigInt::New(env, (int64_t)rax);
|
|
241
|
-
case PrimitiveKind::UInt64: return Napi::BigInt::New(env, rax);
|
|
242
|
-
case PrimitiveKind::Float32: { RG_UNREACHABLE(); } break;
|
|
243
|
-
case PrimitiveKind::Float64: { RG_UNREACHABLE(); } break;
|
|
244
|
-
case PrimitiveKind::String: return Napi::String::New(env, (const char *)rax);
|
|
245
|
-
case PrimitiveKind::Pointer: {
|
|
246
|
-
void *ptr = (void *)rax;
|
|
247
|
-
|
|
248
|
-
Napi::External<void> external = Napi::External<void>::New(env, ptr);
|
|
249
|
-
SetValueTag(instance, external, func->ret.type);
|
|
250
|
-
|
|
251
|
-
return external;
|
|
252
|
-
} break;
|
|
253
|
-
|
|
254
|
-
case PrimitiveKind::Record: {
|
|
255
|
-
const uint8_t *ptr = return_ptr ? return_ptr : (const uint8_t *)&rax;
|
|
256
|
-
Napi::Object obj = PopObject(env, ptr, func->ret.type);
|
|
257
|
-
return obj;
|
|
258
|
-
} break;
|
|
259
|
-
}
|
|
266
|
+
Napi::Object obj = PopObject(ptr, func->ret.type);
|
|
267
|
+
return obj;
|
|
260
268
|
} break;
|
|
269
|
+
case PrimitiveKind::Float32: return Napi::Number::New(env, (double)result.f);
|
|
270
|
+
case PrimitiveKind::Float64: return Napi::Number::New(env, result.d);
|
|
261
271
|
}
|
|
262
272
|
|
|
263
|
-
#undef PERFORM_CALL
|
|
264
|
-
|
|
265
273
|
RG_UNREACHABLE();
|
|
266
274
|
}
|
|
267
275
|
|
|
File without changes
|
|
@@ -82,36 +82,24 @@ bool AnalyseFunction(InstanceData *instance, FunctionInfo *func)
|
|
|
82
82
|
return true;
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
bool CallData::Prepare(const Napi::CallbackInfo &info)
|
|
86
86
|
{
|
|
87
|
-
Napi::Env env = info.Env();
|
|
88
|
-
CallData call(env, instance, func);
|
|
89
|
-
|
|
90
|
-
// Sanity checks
|
|
91
|
-
if (info.Length() < (uint32_t)func->parameters.len) {
|
|
92
|
-
ThrowError<Napi::TypeError>(env, "Expected %1 arguments, got %2", func->parameters.len, info.Length());
|
|
93
|
-
return env.Null();
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
uint8_t *return_ptr = nullptr;
|
|
97
87
|
uint32_t *args_ptr = nullptr;
|
|
98
88
|
uint32_t *fast_ptr = nullptr;
|
|
99
89
|
|
|
100
90
|
// Pass return value in register or through memory
|
|
101
|
-
if (RG_UNLIKELY(!
|
|
102
|
-
return
|
|
91
|
+
if (RG_UNLIKELY(!AllocStack(func->args_size, 16, &args_ptr)))
|
|
92
|
+
return false;
|
|
103
93
|
if (func->convention == CallConvention::Fastcall) {
|
|
104
94
|
fast_ptr = args_ptr;
|
|
105
95
|
args_ptr += 4;
|
|
106
96
|
}
|
|
107
97
|
if (!func->ret.trivial) {
|
|
108
|
-
if (RG_UNLIKELY(!
|
|
109
|
-
return
|
|
98
|
+
if (RG_UNLIKELY(!AllocHeap(func->ret.type->size, 16, &return_ptr)))
|
|
99
|
+
return false;
|
|
110
100
|
*((func->ret.fast ? fast_ptr : args_ptr)++) = (uint32_t)return_ptr;
|
|
111
101
|
}
|
|
112
102
|
|
|
113
|
-
LocalArray<OutObject, MaxOutParameters> out_objects;
|
|
114
|
-
|
|
115
103
|
// Push arguments
|
|
116
104
|
for (Size i = 0; i < func->parameters.len; i++) {
|
|
117
105
|
const ParameterInfo ¶m = func->parameters[i];
|
|
@@ -125,7 +113,7 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
125
113
|
case PrimitiveKind::Bool: {
|
|
126
114
|
if (RG_UNLIKELY(!value.IsBoolean())) {
|
|
127
115
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected boolean", GetValueType(instance, value), i + 1);
|
|
128
|
-
return
|
|
116
|
+
return false;
|
|
129
117
|
}
|
|
130
118
|
|
|
131
119
|
bool b = value.As<Napi::Boolean>();
|
|
@@ -139,7 +127,7 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
139
127
|
case PrimitiveKind::UInt32: {
|
|
140
128
|
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
141
129
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
|
|
142
|
-
return
|
|
130
|
+
return false;
|
|
143
131
|
}
|
|
144
132
|
|
|
145
133
|
int32_t v = CopyNumber<int32_t>(value);
|
|
@@ -149,47 +137,43 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
149
137
|
case PrimitiveKind::UInt64: {
|
|
150
138
|
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
151
139
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
|
|
152
|
-
return
|
|
140
|
+
return false;
|
|
153
141
|
}
|
|
154
142
|
|
|
155
143
|
int64_t v = CopyNumber<int64_t>(value);
|
|
156
144
|
*(uint64_t *)args_ptr = (uint64_t)v;
|
|
157
145
|
args_ptr += 2;
|
|
158
146
|
} break;
|
|
159
|
-
case PrimitiveKind::Float32: {
|
|
160
|
-
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
161
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
|
|
162
|
-
return env.Null();
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
float f = CopyNumber<float>(value);
|
|
166
|
-
*(float *)((param.fast ? fast_ptr : args_ptr)++) = f;
|
|
167
|
-
} break;
|
|
168
|
-
case PrimitiveKind::Float64: {
|
|
169
|
-
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
170
|
-
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
|
|
171
|
-
return env.Null();
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
double d = CopyNumber<double>(value);
|
|
175
|
-
*(double *)args_ptr = d;
|
|
176
|
-
args_ptr += 2;
|
|
177
|
-
} break;
|
|
178
147
|
case PrimitiveKind::String: {
|
|
179
148
|
const char *str;
|
|
180
149
|
if (RG_LIKELY(value.IsString())) {
|
|
181
|
-
str =
|
|
150
|
+
str = PushString(value);
|
|
182
151
|
if (RG_UNLIKELY(!str))
|
|
183
|
-
return
|
|
152
|
+
return false;
|
|
184
153
|
} else if (IsNullOrUndefined(value)) {
|
|
185
154
|
str = nullptr;
|
|
186
155
|
} else {
|
|
187
156
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected string", GetValueType(instance, value), i + 1);
|
|
188
|
-
return
|
|
157
|
+
return false;
|
|
189
158
|
}
|
|
190
159
|
|
|
191
160
|
*(const char **)((param.fast ? fast_ptr : args_ptr)++) = str;
|
|
192
161
|
} break;
|
|
162
|
+
case PrimitiveKind::String16: {
|
|
163
|
+
const char16_t *str16;
|
|
164
|
+
if (RG_LIKELY(value.IsString())) {
|
|
165
|
+
str16 = PushString16(value);
|
|
166
|
+
if (RG_UNLIKELY(!str16))
|
|
167
|
+
return false;
|
|
168
|
+
} else if (IsNullOrUndefined(value)) {
|
|
169
|
+
str16 = nullptr;
|
|
170
|
+
} else {
|
|
171
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected string", GetValueType(instance, value), i + 1);
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
*(const char16_t **)((param.fast ? fast_ptr : args_ptr)++) = str16;
|
|
176
|
+
} break;
|
|
193
177
|
case PrimitiveKind::Pointer: {
|
|
194
178
|
uint8_t *ptr;
|
|
195
179
|
|
|
@@ -198,12 +182,12 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
198
182
|
} else if (IsObject(value) && param.type->ref->primitive == PrimitiveKind::Record) {
|
|
199
183
|
Napi::Object obj = value.As<Napi::Object>();
|
|
200
184
|
|
|
201
|
-
if (RG_UNLIKELY(!
|
|
202
|
-
return
|
|
185
|
+
if (RG_UNLIKELY(!AllocHeap(param.type->ref->size, 16, &ptr)))
|
|
186
|
+
return false;
|
|
203
187
|
|
|
204
188
|
if (param.directions & 1) {
|
|
205
|
-
if (!
|
|
206
|
-
return
|
|
189
|
+
if (!PushObject(obj, param.type->ref, ptr))
|
|
190
|
+
return false;
|
|
207
191
|
} else {
|
|
208
192
|
memset(ptr, 0, param.type->size);
|
|
209
193
|
}
|
|
@@ -215,104 +199,123 @@ Napi::Value TranslateCall(InstanceData *instance, const FunctionInfo *func, cons
|
|
|
215
199
|
ptr = nullptr;
|
|
216
200
|
} else {
|
|
217
201
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected %3", GetValueType(instance, value), i + 1, param.type->name);
|
|
218
|
-
return
|
|
202
|
+
return false;
|
|
219
203
|
}
|
|
220
204
|
|
|
221
205
|
*(uint8_t **)((param.fast ? fast_ptr : args_ptr)++) = ptr;
|
|
222
206
|
} break;
|
|
223
|
-
|
|
224
207
|
case PrimitiveKind::Record: {
|
|
225
208
|
if (RG_UNLIKELY(!IsObject(value))) {
|
|
226
209
|
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected object", GetValueType(instance, value), i + 1);
|
|
227
|
-
return
|
|
210
|
+
return false;
|
|
228
211
|
}
|
|
229
212
|
|
|
230
213
|
Napi::Object obj = value.As<Napi::Object>();
|
|
231
214
|
|
|
232
215
|
if (param.fast) {
|
|
233
216
|
uint8_t *ptr = (uint8_t *)(fast_ptr++);
|
|
234
|
-
if (!
|
|
235
|
-
return
|
|
217
|
+
if (!PushObject(obj, param.type, ptr))
|
|
218
|
+
return false;
|
|
236
219
|
} else {
|
|
237
220
|
uint8_t *ptr = (uint8_t *)AlignUp(args_ptr, param.type->align);
|
|
238
|
-
if (!
|
|
239
|
-
return
|
|
221
|
+
if (!PushObject(obj, param.type, ptr))
|
|
222
|
+
return false;
|
|
240
223
|
args_ptr = (uint32_t *)AlignUp(ptr + param.type->size, 4);
|
|
241
224
|
}
|
|
242
225
|
} break;
|
|
226
|
+
case PrimitiveKind::Float32: {
|
|
227
|
+
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
228
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
float f = CopyNumber<float>(value);
|
|
233
|
+
*(float *)((param.fast ? fast_ptr : args_ptr)++) = f;
|
|
234
|
+
} break;
|
|
235
|
+
case PrimitiveKind::Float64: {
|
|
236
|
+
if (RG_UNLIKELY(!value.IsNumber() && !value.IsBigInt())) {
|
|
237
|
+
ThrowError<Napi::TypeError>(env, "Unexpected %1 value for argument %2, expected number", GetValueType(instance, value), i + 1);
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
double d = CopyNumber<double>(value);
|
|
242
|
+
*(double *)args_ptr = d;
|
|
243
|
+
args_ptr += 2;
|
|
244
|
+
} break;
|
|
243
245
|
}
|
|
244
246
|
}
|
|
245
247
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}
|
|
248
|
+
return true;
|
|
249
|
+
}
|
|
249
250
|
|
|
251
|
+
void CallData::Execute()
|
|
252
|
+
{
|
|
250
253
|
#define PERFORM_CALL(Suffix) \
|
|
251
254
|
([&]() { \
|
|
252
|
-
auto ret = (func->convention == CallConvention::Fastcall ? ForwardCallR ## Suffix(func->func,
|
|
253
|
-
: ForwardCall ## Suffix(func->func,
|
|
254
|
-
PopOutArguments(out_objects); \
|
|
255
|
+
auto ret = (func->convention == CallConvention::Fastcall ? ForwardCallR ## Suffix(func->func, GetSP()) \
|
|
256
|
+
: ForwardCall ## Suffix(func->func, GetSP())); \
|
|
255
257
|
return ret; \
|
|
256
258
|
})()
|
|
257
259
|
|
|
258
260
|
// Execute and convert return value
|
|
259
261
|
switch (func->ret.type->primitive) {
|
|
260
|
-
case PrimitiveKind::
|
|
261
|
-
|
|
262
|
+
case PrimitiveKind::Void:
|
|
263
|
+
case PrimitiveKind::Bool:
|
|
264
|
+
case PrimitiveKind::Int8:
|
|
265
|
+
case PrimitiveKind::UInt8:
|
|
266
|
+
case PrimitiveKind::Int16:
|
|
267
|
+
case PrimitiveKind::UInt16:
|
|
268
|
+
case PrimitiveKind::Int32:
|
|
269
|
+
case PrimitiveKind::UInt32:
|
|
270
|
+
case PrimitiveKind::Int64:
|
|
271
|
+
case PrimitiveKind::UInt64:
|
|
272
|
+
case PrimitiveKind::String:
|
|
273
|
+
case PrimitiveKind::String16:
|
|
274
|
+
case PrimitiveKind::Pointer:
|
|
275
|
+
case PrimitiveKind::Record: { result.u64 = PERFORM_CALL(G); } break;
|
|
276
|
+
case PrimitiveKind::Float32: { result.f = PERFORM_CALL(F); } break;
|
|
277
|
+
case PrimitiveKind::Float64: { result.d = PERFORM_CALL(D); } break;
|
|
278
|
+
}
|
|
262
279
|
|
|
263
|
-
|
|
264
|
-
|
|
280
|
+
#undef PERFORM_CALL
|
|
281
|
+
}
|
|
265
282
|
|
|
266
|
-
|
|
267
|
-
|
|
283
|
+
Napi::Value CallData::Complete()
|
|
284
|
+
{
|
|
285
|
+
for (const OutObject &obj: out_objects) {
|
|
286
|
+
PopObject(obj.obj, obj.ptr, obj.type);
|
|
287
|
+
}
|
|
268
288
|
|
|
269
|
-
|
|
289
|
+
switch (func->ret.type->primitive) {
|
|
290
|
+
case PrimitiveKind::Void: return env.Null();
|
|
291
|
+
case PrimitiveKind::Bool: return Napi::Boolean::New(env, result.u32);
|
|
292
|
+
case PrimitiveKind::Int8:
|
|
293
|
+
case PrimitiveKind::UInt8:
|
|
294
|
+
case PrimitiveKind::Int16:
|
|
295
|
+
case PrimitiveKind::UInt16:
|
|
296
|
+
case PrimitiveKind::Int32:
|
|
297
|
+
case PrimitiveKind::UInt32: return Napi::Number::New(env, (double)result.u32);
|
|
298
|
+
case PrimitiveKind::Int64: return Napi::BigInt::New(env, (int64_t)result.u64);
|
|
299
|
+
case PrimitiveKind::UInt64: return Napi::BigInt::New(env, result.u64);
|
|
300
|
+
case PrimitiveKind::String: return Napi::String::New(env, (const char *)result.ptr);
|
|
301
|
+
case PrimitiveKind::String16: return Napi::String::New(env, (const char16_t *)result.ptr);
|
|
302
|
+
case PrimitiveKind::Pointer: {
|
|
303
|
+
Napi::External<void> external = Napi::External<void>::New(env, result.ptr);
|
|
304
|
+
SetValueTag(instance, external, func->ret.type);
|
|
305
|
+
|
|
306
|
+
return external;
|
|
270
307
|
} break;
|
|
308
|
+
case PrimitiveKind::Record: {
|
|
309
|
+
const uint8_t *ptr = return_ptr ? (const uint8_t *)return_ptr
|
|
310
|
+
: (const uint8_t *)&result.buf;
|
|
271
311
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
// treat it the same: it is trivial only on Windows (see AnalyseFunction).
|
|
275
|
-
uint64_t raw = PERFORM_CALL(G);
|
|
276
|
-
struct {
|
|
277
|
-
uint32_t rax;
|
|
278
|
-
uint32_t rdx;
|
|
279
|
-
} ret;
|
|
280
|
-
memcpy(&ret, &raw, RG_SIZE(raw));
|
|
281
|
-
|
|
282
|
-
switch (func->ret.type->primitive) {
|
|
283
|
-
case PrimitiveKind::Void: return env.Null();
|
|
284
|
-
case PrimitiveKind::Bool: return Napi::Boolean::New(env, ret.rax);
|
|
285
|
-
case PrimitiveKind::Int8: return Napi::Number::New(env, (double)ret.rax);
|
|
286
|
-
case PrimitiveKind::UInt8: return Napi::Number::New(env, (double)ret.rax);
|
|
287
|
-
case PrimitiveKind::Int16: return Napi::Number::New(env, (double)ret.rax);
|
|
288
|
-
case PrimitiveKind::UInt16: return Napi::Number::New(env, (double)ret.rax);
|
|
289
|
-
case PrimitiveKind::Int32: return Napi::Number::New(env, (double)ret.rax);
|
|
290
|
-
case PrimitiveKind::UInt32: return Napi::Number::New(env, (double)ret.rax);
|
|
291
|
-
case PrimitiveKind::Int64: return Napi::BigInt::New(env, (int64_t)raw);
|
|
292
|
-
case PrimitiveKind::UInt64: return Napi::BigInt::New(env, raw);
|
|
293
|
-
case PrimitiveKind::Float32: { RG_UNREACHABLE(); } break;
|
|
294
|
-
case PrimitiveKind::Float64: { RG_UNREACHABLE(); } break;
|
|
295
|
-
case PrimitiveKind::String: return Napi::String::New(env, (const char *)ret.rax);
|
|
296
|
-
case PrimitiveKind::Pointer: {
|
|
297
|
-
void *ptr = (void *)ret.rax;
|
|
298
|
-
|
|
299
|
-
Napi::External<void> external = Napi::External<void>::New(env, ptr);
|
|
300
|
-
SetValueTag(instance, external, func->ret.type);
|
|
301
|
-
|
|
302
|
-
return external;
|
|
303
|
-
} break;
|
|
304
|
-
|
|
305
|
-
case PrimitiveKind::Record: {
|
|
306
|
-
const uint8_t *ptr = return_ptr ? return_ptr : (const uint8_t *)&ret;
|
|
307
|
-
Napi::Object obj = PopObject(env, ptr, func->ret.type);
|
|
308
|
-
return obj;
|
|
309
|
-
} break;
|
|
310
|
-
}
|
|
312
|
+
Napi::Object obj = PopObject(ptr, func->ret.type);
|
|
313
|
+
return obj;
|
|
311
314
|
} break;
|
|
315
|
+
case PrimitiveKind::Float32: return Napi::Number::New(env, (double)result.f);
|
|
316
|
+
case PrimitiveKind::Float64: return Napi::Number::New(env, result.d);
|
|
312
317
|
}
|
|
313
318
|
|
|
314
|
-
#undef PERFORM_CALL
|
|
315
|
-
|
|
316
319
|
RG_UNREACHABLE();
|
|
317
320
|
}
|
|
318
321
|
|
|
File without changes
|
|
File without changes
|