koffi 1.1.2 → 1.1.3
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 +7 -7
- package/README.md +18 -28
- package/build/qemu/1.1.3/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/1.1.3/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/1.1.3/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/1.1.3/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/1.1.3/koffi_linux_arm.tar.gz +0 -0
- package/build/qemu/1.1.3/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/1.1.3/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/1.1.3/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/1.1.3/koffi_openbsd_x64.tar.gz +0 -0
- package/build/qemu/1.1.3/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/1.1.3/koffi_win32_x64.tar.gz +0 -0
- package/package.json +1 -1
- package/qemu/registry/machines.json +47 -3
- package/qemu/registry/sha256sum.txt +16 -12
- package/src/abi_arm32.cc +43 -4
- package/src/abi_arm64.cc +22 -5
- package/src/abi_x64_sysv.cc +1 -1
- package/src/abi_x64_win.cc +1 -1
- package/src/abi_x86.cc +10 -4
- package/src/ffi.cc +43 -21
- package/src/ffi.hh +7 -2
- package/src/parser.cc +16 -4
- package/test/CMakeLists.txt +3 -0
- package/vendor/libcc/libcc.cc +7 -7
- package/vendor/libcc/libcc.hh +4 -1
- package/build/qemu/1.1.2/koffi_darwin_x64.tar.gz +0 -0
- package/build/qemu/1.1.2/koffi_freebsd_arm64.tar.gz +0 -0
- package/build/qemu/1.1.2/koffi_freebsd_ia32.tar.gz +0 -0
- package/build/qemu/1.1.2/koffi_freebsd_x64.tar.gz +0 -0
- package/build/qemu/1.1.2/koffi_linux_arm.tar.gz +0 -0
- package/build/qemu/1.1.2/koffi_linux_arm64.tar.gz +0 -0
- package/build/qemu/1.1.2/koffi_linux_ia32.tar.gz +0 -0
- package/build/qemu/1.1.2/koffi_linux_x64.tar.gz +0 -0
- package/build/qemu/1.1.2/koffi_win32_ia32.tar.gz +0 -0
- package/build/qemu/1.1.2/koffi_win32_x64.tar.gz +0 -0
package/CMakeLists.txt
CHANGED
|
@@ -43,20 +43,20 @@ set(KOFFI_SRC
|
|
|
43
43
|
vendor/libcc/libcc.cc
|
|
44
44
|
)
|
|
45
45
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|
46
|
-
if(
|
|
47
|
-
list(APPEND KOFFI_SRC src/abi_x64_win_fwd.asm)
|
|
48
|
-
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64|arm64")
|
|
46
|
+
if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch|arm")
|
|
49
47
|
list(APPEND KOFFI_SRC src/abi_arm64_fwd.S)
|
|
48
|
+
elseif(WIN32)
|
|
49
|
+
list(APPEND KOFFI_SRC src/abi_x64_win_fwd.asm)
|
|
50
50
|
else()
|
|
51
51
|
list(APPEND KOFFI_SRC src/abi_x64_sysv_fwd.S)
|
|
52
52
|
endif()
|
|
53
53
|
elseif(CMAKE_SIZEOF_VOID_P EQUAL 4)
|
|
54
|
-
if(
|
|
54
|
+
if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm")
|
|
55
|
+
list(APPEND KOFFI_SRC src/abi_arm32_fwd.S)
|
|
56
|
+
elseif(WIN32)
|
|
55
57
|
list(APPEND KOFFI_SRC src/abi_x86_fwd.asm)
|
|
56
|
-
|
|
58
|
+
else()
|
|
57
59
|
list(APPEND KOFFI_SRC src/abi_x86_fwd.S)
|
|
58
|
-
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "armv[678]l")
|
|
59
|
-
list(APPEND KOFFI_SRC src/abi_arm32_fwd.S)
|
|
60
60
|
endif()
|
|
61
61
|
endif()
|
|
62
62
|
|
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* [Raylib results](#raylib-results)
|
|
14
14
|
- [Tests](#tests)
|
|
15
15
|
- [Compilation](#compilation)
|
|
16
|
-
* [Windows](#windows)
|
|
16
|
+
* [Windows](#windows-1)
|
|
17
17
|
* [Other platforms](#other-platforms)
|
|
18
18
|
|
|
19
19
|
# Introduction
|
|
@@ -23,33 +23,23 @@ Koffi is a fast and easy-to-use FFI module for Node.js, with support for primiti
|
|
|
23
23
|
The following features are planned in the near future:
|
|
24
24
|
|
|
25
25
|
* 1.2: C to JS callbacks
|
|
26
|
-
* 1.3:
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
OpenBSD | x86_64 | 🟧 Maybe | 🟧 Maybe | 🟥 No | 🟥 No
|
|
44
|
-
OpenBSD | x86 | 🟧 Maybe | 🟧 Maybe | 🟥 No | 🟥 No
|
|
45
|
-
OpenBSD | ARM64 Little Endian | 🟧 Maybe | 🟧 Maybe | 🟥 No | 🟥 No
|
|
46
|
-
NetBSD | x86_64 | 🟧 Maybe | 🟧 Maybe | 🟥 No | 🟥 No
|
|
47
|
-
NetBSD | x86 | 🟧 Maybe | 🟧 Maybe | 🟥 No | 🟥 No
|
|
48
|
-
NetBSD | ARM64 Little Endian | 🟧 Maybe | 🟧 Maybe | 🟥 No | 🟥 No
|
|
49
|
-
|
|
50
|
-
🟩 Tested, fully operational
|
|
51
|
-
🟧 May work, but not actively tested
|
|
52
|
-
🟥 Does not work yet
|
|
26
|
+
* 1.3: RISC-V support (32 and 64 bit)
|
|
27
|
+
* 1.4: Type parser
|
|
28
|
+
|
|
29
|
+
The following combinations of OS and architectures __are officially supported and tested__ at the moment:
|
|
30
|
+
|
|
31
|
+
ISA / OS | Windows | Linux | macOS | FreeBSD | OpenBSD
|
|
32
|
+
------------------ | -------- | -------- | ----------- | -------- | --------
|
|
33
|
+
x86 (IA32) [^1] | 🟩 Yes | 🟩 Yes | ⬜️ N/A | 🟩 Yes | 🟧 Maybe
|
|
34
|
+
x86_64 (AMD64) | 🟩 Yes | 🟩 Yes | 🟩 Yes | 🟩 Yes | 🟩 Yes
|
|
35
|
+
ARM32 VFP LE | ⬜️ N/A | 🟩 Yes | ⬜️ N/A | 🟧 Maybe | 🟧 Maybe
|
|
36
|
+
ARM32 (no VFP) LE | ⬜️ N/A | 🟧 Maybe | ⬜️ N/A | 🟧 Maybe | 🟧 Maybe
|
|
37
|
+
ARM64 (AArch64) LE | 🟧 Maybe | 🟩 Yes | 🟩 Yes [^2] | 🟩 Yes | 🟧 Maybe
|
|
38
|
+
RISC-V 32 | ⬜️ N/A | 🟥 No | ⬜️ N/A | 🟥 No | 🟥 No
|
|
39
|
+
RISC-V 64 | ⬜️ N/A | 🟥 No | ⬜️ N/A | 🟥 No | 🟥 No
|
|
40
|
+
|
|
41
|
+
[^1]: The following call conventions are supported: cdecl, stdcall, MS fastcall, thiscall
|
|
42
|
+
[^2]: However, we don't provide prebuilt binaries for macOS on Apple M1
|
|
53
43
|
|
|
54
44
|
This is still in development, bugs are to be expected. More tests will come in the near future.
|
|
55
45
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -253,7 +253,7 @@
|
|
|
253
253
|
},
|
|
254
254
|
|
|
255
255
|
"info": {
|
|
256
|
-
"version":
|
|
256
|
+
"version": 2,
|
|
257
257
|
"platform": "freebsd",
|
|
258
258
|
"arch": "x64",
|
|
259
259
|
|
|
@@ -298,7 +298,7 @@
|
|
|
298
298
|
},
|
|
299
299
|
|
|
300
300
|
"info": {
|
|
301
|
-
"version":
|
|
301
|
+
"version": 2,
|
|
302
302
|
"platform": "freebsd",
|
|
303
303
|
"arch": "ia32",
|
|
304
304
|
|
|
@@ -343,7 +343,7 @@
|
|
|
343
343
|
},
|
|
344
344
|
|
|
345
345
|
"info": {
|
|
346
|
-
"version":
|
|
346
|
+
"version": 2,
|
|
347
347
|
"platform": "freebsd",
|
|
348
348
|
"arch": "arm64",
|
|
349
349
|
|
|
@@ -421,5 +421,49 @@
|
|
|
421
421
|
}
|
|
422
422
|
}
|
|
423
423
|
}
|
|
424
|
+
},
|
|
425
|
+
|
|
426
|
+
"openbsd_x64": {
|
|
427
|
+
"name": "OpenBSD x64",
|
|
428
|
+
|
|
429
|
+
"qemu": {
|
|
430
|
+
"binary": "qemu-system-x86_64",
|
|
431
|
+
"arguments": ["-m", "1G", "-smp", 2, "-hda", "disk.qcow2", "-netdev", "user,id=mynet,hostfwd=tcp::22210-:22", "-device", "e1000,netdev=mynet", "-vnc", "127.0.0.1:20"]
|
|
432
|
+
},
|
|
433
|
+
|
|
434
|
+
"info": {
|
|
435
|
+
"version": 1,
|
|
436
|
+
"platform": "openbsd",
|
|
437
|
+
"arch": "x64",
|
|
438
|
+
|
|
439
|
+
"ssh_port": 22210,
|
|
440
|
+
"vnc_port": 5920,
|
|
441
|
+
|
|
442
|
+
"username": "openbsd",
|
|
443
|
+
"password": "openbsd",
|
|
444
|
+
|
|
445
|
+
"shutdown": "sudo shutdown -p now"
|
|
446
|
+
},
|
|
447
|
+
|
|
448
|
+
"builds": {
|
|
449
|
+
"OpenBSD x64": {
|
|
450
|
+
"directory": "/home/openbsd/luigi",
|
|
451
|
+
"build": "node ../cnoke/cnoke.js"
|
|
452
|
+
}
|
|
453
|
+
},
|
|
454
|
+
|
|
455
|
+
"tests": {
|
|
456
|
+
"OpenBSD x64": {
|
|
457
|
+
"directory": "/home/openbsd/luigi",
|
|
458
|
+
"build": {
|
|
459
|
+
"Build": "node ../cnoke/cnoke.js -C test"
|
|
460
|
+
},
|
|
461
|
+
"commands": {
|
|
462
|
+
"Test Sync": "node test/sync.js",
|
|
463
|
+
"Test Async": "node test/async.js",
|
|
464
|
+
"Test SQLite": "node test/sqlite.js"
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
424
468
|
}
|
|
425
469
|
}
|
|
@@ -22,20 +22,20 @@ ed05b84b7759ec945bb5422305a3a3c5b61d89e231844656ea31e07d89451a20 *qemu/debian_i3
|
|
|
22
22
|
292a61c415a99a9c63a9337f1e074bea6c5df594e16bc40ded76141963c67ea4 *qemu/debian_i386/install.sh
|
|
23
23
|
8dc1360e1c23ea21931f5eb94461d15fac6bcec00cf42bf1e590b7fb937e80c1 *qemu/debian_i386/initrd.img-5.10.0-12-686-pae
|
|
24
24
|
338602d969f953cd88c2df736b9f8f7ee53029d233c83c7398258ae5bcb4e286 *qemu/debian_i386/disk.qcow2
|
|
25
|
-
|
|
26
|
-
5daea533330eb8d2f8df946561680e09f8dacc467fbf03d28caa2115d94386b5 *qemu/freebsd_arm64/QEMU_EFI.img
|
|
27
|
-
a083e4e1f58f477e4a9e8ae30f75660e82275b88f77b5e2c7f5d6ee1deb43b41 *qemu/freebsd_arm64/varstore.img
|
|
25
|
+
e5d9d3e1e4a5c980fce4ef3aab5e29b9607b8e5da6e9fe58c3f396009e283cff *qemu/freebsd_arm64/disk.qcow2
|
|
28
26
|
53a4dc48317e1c9de4a088cd45ba39a1810f0bafad75c7f810e18d4e3eb340e3 *qemu/freebsd_arm64/install.sh
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
10f2bc603b171368cacda43485f8f72567af0a9a490b7e0fa0c14c983ae66f16 *qemu/freebsd_x64/xvfb-run.sh
|
|
35
|
-
6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b *qemu/freebsd_i386/VERSION
|
|
27
|
+
5daea533330eb8d2f8df946561680e09f8dacc467fbf03d28caa2115d94386b5 *qemu/freebsd_arm64/QEMU_EFI.img
|
|
28
|
+
8ac20d46117a5a15761bf3070e365141b96ee3283250824f113029e106c62a50 *qemu/freebsd_arm64/varstore.img
|
|
29
|
+
d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35 *qemu/freebsd_arm64/VERSION
|
|
30
|
+
73837b3991eae13f6c346955ea4aa419c8c168cadf70e0a38446db60cf47b0e9 *qemu/freebsd_arm64/xvfb-run.sh
|
|
31
|
+
fd0e51c43d7848564a81ddcb3eecf49103251bffcf25315ef87db01350ad4ac5 *qemu/freebsd_i386/disk.qcow2
|
|
36
32
|
bdeac2cca1d22d70c2d388a50709d5cba3069bbd4bd1bcb102955b0ee12ca3e9 *qemu/freebsd_i386/install.sh
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35 *qemu/freebsd_i386/VERSION
|
|
34
|
+
73837b3991eae13f6c346955ea4aa419c8c168cadf70e0a38446db60cf47b0e9 *qemu/freebsd_i386/xvfb-run.sh
|
|
35
|
+
41649d2f5959388e1c5d8ee89bb084795470a8b9e68d87861b4e95e4102b62cf *qemu/freebsd_x64/disk.qcow2
|
|
36
|
+
06eef544fe9c61d3905b0e588c306d1dedac7ee7d4c01df154ff6ed64e25ef77 *qemu/freebsd_x64/install.sh
|
|
37
|
+
d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35 *qemu/freebsd_x64/VERSION
|
|
38
|
+
73837b3991eae13f6c346955ea4aa419c8c168cadf70e0a38446db60cf47b0e9 *qemu/freebsd_x64/xvfb-run.sh
|
|
39
39
|
16a4f09b3e70b97f5cfb1cf9b913d67d0ec45c4342d202cc9a2b2cfee852a8de *qemu/macos_x64/ESP.qcow2
|
|
40
40
|
5d2ac383371b408398accee7ec27c8c09ea5b74a0de0ceea6513388b15be5d1e *qemu/macos_x64/OVMF_VARS.fd
|
|
41
41
|
d79538ac489f1948b04b65f12c5618c28e4a5de0be062f5cf1d73e422a091a37 *qemu/macos_x64/install.txt
|
|
@@ -43,3 +43,7 @@ d79538ac489f1948b04b65f12c5618c28e4a5de0be062f5cf1d73e422a091a37 *qemu/macos_x64
|
|
|
43
43
|
5cc2d42949c7e4e763db0abeb88299972bafef991d87dbf744a5108ef9190f6f *qemu/macos_x64/OVMF_VARS-1024x768.fd
|
|
44
44
|
53c234e5e8472b6ac51c1ae1cab3fe06fad053beb8ebfd8977b010655bfdd3c3 *qemu/macos_x64/VERSION
|
|
45
45
|
2a247500e8ad9aa479994097ba5976bd881fde4de1516abd14491f3dba9fe060 *qemu/macos_x64/OVMF_CODE.fd
|
|
46
|
+
3a3395f70240d8e3137dfe06ef7dd76255dc597626e087d33abdcc65710f3dff *qemu/openbsd_x64/disk.qcow2
|
|
47
|
+
9dcdabfc12ad2ba2da1b9c3d95dc46311a12d6e3190f1bfd0c9b184ac1577c94 *qemu/openbsd_x64/install.sh
|
|
48
|
+
6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b *qemu/openbsd_x64/VERSION
|
|
49
|
+
7b66bdf8b77fd1c6256ffdab623e37ce099797ad657dcd25af5df0486fadce37 *qemu/openbsd_x64/xvfb-run.sh
|
package/src/abi_arm32.cc
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// You should have received a copy of the GNU Affero General Public License
|
|
12
12
|
// along with this program. If not, see https://www.gnu.org/licenses/.
|
|
13
13
|
|
|
14
|
-
#if defined(__arm__)
|
|
14
|
+
#if defined(__arm__) || (defined(__M_ARM) && !defined(_M_ARM64))
|
|
15
15
|
|
|
16
16
|
#include "vendor/libcc/libcc.hh"
|
|
17
17
|
#include "ffi.hh"
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
#include "util.hh"
|
|
20
20
|
|
|
21
21
|
#include <napi.h>
|
|
22
|
+
#include <signal.h>
|
|
23
|
+
#include <setjmp.h>
|
|
22
24
|
|
|
23
25
|
namespace RG {
|
|
24
26
|
|
|
@@ -37,9 +39,46 @@ extern "C" uint64_t ForwardCallXGG(const void *func, uint8_t *sp);
|
|
|
37
39
|
extern "C" float ForwardCallXF(const void *func, uint8_t *sp);
|
|
38
40
|
extern "C" HfaRet ForwardCallXDDDD(const void *func, uint8_t *sp);
|
|
39
41
|
|
|
42
|
+
static bool DetectVFP()
|
|
43
|
+
{
|
|
44
|
+
// If anything fails, assume VFP is available (true for most Linux platforms)
|
|
45
|
+
static volatile bool vfp = true;
|
|
46
|
+
static jmp_buf env;
|
|
47
|
+
|
|
48
|
+
struct sigaction prev;
|
|
49
|
+
SetSignalHandler(SIGILL, [](int) {
|
|
50
|
+
vfp = false;
|
|
51
|
+
longjmp(env, 1);
|
|
52
|
+
}, &prev);
|
|
53
|
+
|
|
54
|
+
if (!setjmp(env)) {
|
|
55
|
+
__asm__ volatile("vmov.f64 d0, #1.0" ::: "d0");
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return vfp;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
static inline bool HasVFP()
|
|
62
|
+
{
|
|
63
|
+
static bool init = false;
|
|
64
|
+
static bool vfp;
|
|
65
|
+
|
|
66
|
+
if (!init) {
|
|
67
|
+
vfp = DetectVFP();
|
|
68
|
+
init = true;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return vfp;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
static inline bool IsHFA(const TypeInfo *type)
|
|
75
|
+
{
|
|
76
|
+
return HasVFP() && IsHFA(type, 1, 4);
|
|
77
|
+
}
|
|
78
|
+
|
|
40
79
|
bool AnalyseFunction(InstanceData *, FunctionInfo *func)
|
|
41
80
|
{
|
|
42
|
-
if (IsHFA(func->ret.type
|
|
81
|
+
if (IsHFA(func->ret.type)) {
|
|
43
82
|
func->ret.vec_count = func->ret.type->members.len *
|
|
44
83
|
(func->ret.type->members[0].type->size / 4);
|
|
45
84
|
} else if (func->ret.type->primitive != PrimitiveKind::Record ||
|
|
@@ -84,7 +123,7 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
|
|
|
84
123
|
}
|
|
85
124
|
} break;
|
|
86
125
|
case PrimitiveKind::Record: {
|
|
87
|
-
if (IsHFA(param.type
|
|
126
|
+
if (IsHFA(param.type)) {
|
|
88
127
|
int vec_count = (int)(param.type->members.len *
|
|
89
128
|
param.type->members[0].type->size / 4);
|
|
90
129
|
|
|
@@ -112,8 +151,8 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
|
|
|
112
151
|
case PrimitiveKind::Array: { RG_UNREACHABLE(); } break;
|
|
113
152
|
case PrimitiveKind::Float32:
|
|
114
153
|
case PrimitiveKind::Float64: {
|
|
154
|
+
bool vfp = HasVFP() && !param.variadic;
|
|
115
155
|
Size need = param.type->size / 4;
|
|
116
|
-
bool vfp = !param.variadic;
|
|
117
156
|
|
|
118
157
|
if (vfp) {
|
|
119
158
|
if (need <= vec_avail) {
|
package/src/abi_arm64.cc
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// You should have received a copy of the GNU Affero General Public License
|
|
12
12
|
// along with this program. If not, see https://www.gnu.org/licenses/.
|
|
13
13
|
|
|
14
|
-
#if defined(__aarch64__)
|
|
14
|
+
#if defined(__aarch64__) || defined(_M_ARM64)
|
|
15
15
|
|
|
16
16
|
#include "vendor/libcc/libcc.hh"
|
|
17
17
|
#include "ffi.hh"
|
|
@@ -41,9 +41,14 @@ extern "C" X0X1Ret ForwardCallXGG(const void *func, uint8_t *sp);
|
|
|
41
41
|
extern "C" float ForwardCallXF(const void *func, uint8_t *sp);
|
|
42
42
|
extern "C" HfaRet ForwardCallXDDDD(const void *func, uint8_t *sp);
|
|
43
43
|
|
|
44
|
+
static inline bool IsHFA(const TypeInfo *type)
|
|
45
|
+
{
|
|
46
|
+
return IsHFA(type, 1, 4);
|
|
47
|
+
}
|
|
48
|
+
|
|
44
49
|
bool AnalyseFunction(InstanceData *, FunctionInfo *func)
|
|
45
50
|
{
|
|
46
|
-
if (IsHFA(func->ret.type
|
|
51
|
+
if (IsHFA(func->ret.type)) {
|
|
47
52
|
func->ret.vec_count = func->ret.type->members.len;
|
|
48
53
|
} else if (func->ret.type->size <= 16) {
|
|
49
54
|
func->ret.gpr_count = (func->ret.type->size + 7) / 8;
|
|
@@ -81,14 +86,18 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
|
|
|
81
86
|
}
|
|
82
87
|
} break;
|
|
83
88
|
case PrimitiveKind::Record: {
|
|
84
|
-
|
|
89
|
+
bool hfa = IsHFA(param.type);
|
|
90
|
+
|
|
91
|
+
#if defined(_WIN32)
|
|
92
|
+
hfa &= !param.variadic;
|
|
93
|
+
#elif defined(__APPLE__)
|
|
85
94
|
if (param.variadic) {
|
|
86
95
|
param.use_memory = (param.type->size > 16);
|
|
87
96
|
break;
|
|
88
97
|
}
|
|
89
98
|
#endif
|
|
90
99
|
|
|
91
|
-
if (
|
|
100
|
+
if (hfa) {
|
|
92
101
|
int vec_count = (int)param.type->members.len;
|
|
93
102
|
|
|
94
103
|
if (vec_count <= vec_avail) {
|
|
@@ -118,7 +127,15 @@ bool AnalyseFunction(InstanceData *, FunctionInfo *func)
|
|
|
118
127
|
case PrimitiveKind::Array: { RG_UNREACHABLE(); } break;
|
|
119
128
|
case PrimitiveKind::Float32:
|
|
120
129
|
case PrimitiveKind::Float64: {
|
|
121
|
-
#
|
|
130
|
+
#if defined(_WIN32)
|
|
131
|
+
if (param.variadic) {
|
|
132
|
+
if (gpr_avail) {
|
|
133
|
+
param.gpr_count = 1;
|
|
134
|
+
gpr_avail--;
|
|
135
|
+
}
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
#elif defined(__APPLE__)
|
|
122
139
|
if (param.variadic)
|
|
123
140
|
break;
|
|
124
141
|
#endif
|
package/src/abi_x64_sysv.cc
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// You should have received a copy of the GNU Affero General Public License
|
|
12
12
|
// along with this program. If not, see https://www.gnu.org/licenses/.
|
|
13
13
|
|
|
14
|
-
#if defined(__x86_64__) && !defined(
|
|
14
|
+
#if defined(__x86_64__) && !defined(_WIN32)
|
|
15
15
|
|
|
16
16
|
#include "vendor/libcc/libcc.hh"
|
|
17
17
|
#include "ffi.hh"
|
package/src/abi_x64_win.cc
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// You should have received a copy of the GNU Affero General Public License
|
|
12
12
|
// along with this program. If not, see https://www.gnu.org/licenses/.
|
|
13
13
|
|
|
14
|
-
#
|
|
14
|
+
#if defined(_WIN32) && (defined(__x86_64__) || defined(_M_AMD64))
|
|
15
15
|
|
|
16
16
|
#include "vendor/libcc/libcc.hh"
|
|
17
17
|
#include "ffi.hh"
|
package/src/abi_x86.cc
CHANGED
|
@@ -37,7 +37,9 @@ static inline bool IsRegular(Size size)
|
|
|
37
37
|
|
|
38
38
|
bool AnalyseFunction(InstanceData *instance, FunctionInfo *func)
|
|
39
39
|
{
|
|
40
|
-
int fast = (func->convention == CallConvention::Fastcall) ? 2 :
|
|
40
|
+
int fast = (func->convention == CallConvention::Fastcall) ? 2 :
|
|
41
|
+
(func->convention == CallConvention::Thiscall) ? 1 : 0;
|
|
42
|
+
func->fast = fast;
|
|
41
43
|
|
|
42
44
|
if (func->ret.type->primitive != PrimitiveKind::Record) {
|
|
43
45
|
func->ret.trivial = true;
|
|
@@ -77,6 +79,10 @@ bool AnalyseFunction(InstanceData *instance, FunctionInfo *func)
|
|
|
77
79
|
func->decorated_name = Fmt(&instance->str_alloc, "@%1@%2", func->name, params_size).ptr;
|
|
78
80
|
func->args_size += 16;
|
|
79
81
|
} break;
|
|
82
|
+
case CallConvention::Thiscall: {
|
|
83
|
+
RG_ASSERT(!func->variadic);
|
|
84
|
+
func->args_size += 16;
|
|
85
|
+
} break;
|
|
80
86
|
}
|
|
81
87
|
|
|
82
88
|
return true;
|
|
@@ -90,7 +96,7 @@ bool CallData::Prepare(const Napi::CallbackInfo &info)
|
|
|
90
96
|
// Pass return value in register or through memory
|
|
91
97
|
if (RG_UNLIKELY(!AllocStack(func->args_size, 16, &args_ptr)))
|
|
92
98
|
return false;
|
|
93
|
-
if (func->
|
|
99
|
+
if (func->fast) {
|
|
94
100
|
fast_ptr = args_ptr;
|
|
95
101
|
args_ptr += 4;
|
|
96
102
|
}
|
|
@@ -259,8 +265,8 @@ void CallData::Execute()
|
|
|
259
265
|
{
|
|
260
266
|
#define PERFORM_CALL(Suffix) \
|
|
261
267
|
([&]() { \
|
|
262
|
-
auto ret = (func->
|
|
263
|
-
|
|
268
|
+
auto ret = (func->fast ? ForwardCallR ## Suffix(func->func, stack.ptr) \
|
|
269
|
+
: ForwardCall ## Suffix(func->func, stack.ptr)); \
|
|
264
270
|
return ret; \
|
|
265
271
|
})()
|
|
266
272
|
|
package/src/ffi.cc
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
#else
|
|
30
30
|
#include <dlfcn.h>
|
|
31
31
|
#include <unistd.h>
|
|
32
|
+
#include <sys/mman.h>
|
|
32
33
|
#endif
|
|
33
34
|
|
|
34
35
|
#include <napi.h>
|
|
@@ -39,6 +40,11 @@
|
|
|
39
40
|
|
|
40
41
|
namespace RG {
|
|
41
42
|
|
|
43
|
+
const Size SyncStackSize = Mebibytes(2);
|
|
44
|
+
const Size SyncHeapSize = Mebibytes(4);
|
|
45
|
+
const Size AsyncStackSize = Mebibytes(1);
|
|
46
|
+
const Size AsyncHeapSize = Mebibytes(2);
|
|
47
|
+
|
|
42
48
|
// Value does not matter, the tag system uses memory addresses
|
|
43
49
|
const int TypeInfoMarker = 0xDEADBEEF;
|
|
44
50
|
|
|
@@ -369,21 +375,6 @@ static Napi::Value GetTypeDefinition(const Napi::CallbackInfo &info)
|
|
|
369
375
|
return type->defn.Value();
|
|
370
376
|
}
|
|
371
377
|
|
|
372
|
-
static Span<uint8_t> AllocateAndAlign16(Allocator *alloc, Size size)
|
|
373
|
-
{
|
|
374
|
-
RG_ASSERT(AlignLen(size, 16) == size);
|
|
375
|
-
RG_ASSERT(size >= Kibibytes(1));
|
|
376
|
-
|
|
377
|
-
// Account for allocator overhead
|
|
378
|
-
size -= 256;
|
|
379
|
-
|
|
380
|
-
uint8_t *ptr = (uint8_t *)Allocator::Allocate(alloc, size);
|
|
381
|
-
uint8_t *aligned = AlignUp(ptr, 16);
|
|
382
|
-
Size delta = AlignLen(aligned - ptr, 16);
|
|
383
|
-
|
|
384
|
-
return MakeSpan(aligned, size - delta);
|
|
385
|
-
}
|
|
386
|
-
|
|
387
378
|
static InstanceMemory *AllocateAsyncMemory(InstanceData *instance)
|
|
388
379
|
{
|
|
389
380
|
for (Size i = 1; i < instance->memories.len; i++) {
|
|
@@ -395,8 +386,23 @@ static InstanceMemory *AllocateAsyncMemory(InstanceData *instance)
|
|
|
395
386
|
|
|
396
387
|
InstanceMemory *mem = new InstanceMemory();
|
|
397
388
|
|
|
398
|
-
mem->stack =
|
|
399
|
-
|
|
389
|
+
mem->stack.len = AsyncStackSize;
|
|
390
|
+
#if defined(_WIN32)
|
|
391
|
+
mem->stack.ptr = (uint8_t *)VirtualAlloc(nullptr, mem->stack.len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
|
392
|
+
#elif defined(__APPLE__)
|
|
393
|
+
mem->stack.ptr = (uint8_t *)mmap(nullptr, mem->stack.len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
|
394
|
+
#else
|
|
395
|
+
mem->stack.ptr = (uint8_t *)mmap(nullptr, mem->stack.len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_STACK, -1, 0);
|
|
396
|
+
#endif
|
|
397
|
+
RG_CRITICAL(mem->stack.ptr, "Failed to allocate %1 of memory", mem->stack.len);
|
|
398
|
+
|
|
399
|
+
mem->heap.len = AsyncHeapSize;
|
|
400
|
+
#ifdef _WIN32
|
|
401
|
+
mem->heap.ptr = (uint8_t *)VirtualAlloc(nullptr, mem->heap.len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
|
402
|
+
#else
|
|
403
|
+
mem->heap.ptr = (uint8_t *)mmap(nullptr, mem->heap.len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
|
404
|
+
#endif
|
|
405
|
+
RG_CRITICAL(mem->heap.ptr, "Failed to allocate %1 of memory", mem->heap.len);
|
|
400
406
|
|
|
401
407
|
if (instance->memories.Available()) {
|
|
402
408
|
instance->memories.Append(mem);
|
|
@@ -597,10 +603,10 @@ static bool ParseClassicFunction(Napi::Env env, Napi::String name, Napi::Value r
|
|
|
597
603
|
return false;
|
|
598
604
|
}
|
|
599
605
|
|
|
600
|
-
|
|
606
|
+
uint32_t parameters_len = parameters.Length();
|
|
601
607
|
|
|
602
608
|
if (parameters_len) {
|
|
603
|
-
Napi::String str = ((Napi::Value)parameters[
|
|
609
|
+
Napi::String str = ((Napi::Value)parameters[parameters_len - 1]).As<Napi::String>();
|
|
604
610
|
|
|
605
611
|
if (str.IsString() && str.Utf8Value() == "...") {
|
|
606
612
|
func->variadic = true;
|
|
@@ -788,6 +794,7 @@ static Napi::Value LoadSharedLibrary(const Napi::CallbackInfo &info)
|
|
|
788
794
|
ADD_CONVENTION("cdecl", CallConvention::Cdecl);
|
|
789
795
|
ADD_CONVENTION("stdcall", CallConvention::Stdcall);
|
|
790
796
|
ADD_CONVENTION("fastcall", CallConvention::Fastcall);
|
|
797
|
+
ADD_CONVENTION("thiscall", CallConvention::Thiscall);
|
|
791
798
|
|
|
792
799
|
#undef ADD_CONVENTION
|
|
793
800
|
|
|
@@ -932,8 +939,23 @@ InstanceData::InstanceData()
|
|
|
932
939
|
{
|
|
933
940
|
InstanceMemory *mem = new InstanceMemory();
|
|
934
941
|
|
|
935
|
-
mem->stack =
|
|
936
|
-
|
|
942
|
+
mem->stack.len = SyncStackSize;
|
|
943
|
+
#if defined(_WIN32)
|
|
944
|
+
mem->stack.ptr = (uint8_t *)VirtualAlloc(nullptr, mem->stack.len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
|
945
|
+
#elif defined(__APPLE__)
|
|
946
|
+
mem->stack.ptr = (uint8_t *)mmap(nullptr, mem->stack.len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
|
947
|
+
#else
|
|
948
|
+
mem->stack.ptr = (uint8_t *)mmap(nullptr, mem->stack.len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON | MAP_STACK, -1, 0);
|
|
949
|
+
#endif
|
|
950
|
+
RG_CRITICAL(mem->stack.ptr, "Failed to allocate %1 of memory", mem->stack.len);
|
|
951
|
+
|
|
952
|
+
mem->heap.len = SyncHeapSize;
|
|
953
|
+
#ifdef _WIN32
|
|
954
|
+
mem->heap.ptr = (uint8_t *)VirtualAlloc(nullptr, mem->heap.len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
|
955
|
+
#else
|
|
956
|
+
mem->heap.ptr = (uint8_t *)mmap(nullptr, mem->heap.len, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
|
|
957
|
+
#endif
|
|
958
|
+
RG_CRITICAL(mem->heap.ptr, "Failed to allocate %1 of memory", mem->heap.len);
|
|
937
959
|
|
|
938
960
|
memories.Append(mem);
|
|
939
961
|
}
|
package/src/ffi.hh
CHANGED
|
@@ -109,12 +109,14 @@ struct LibraryHolder {
|
|
|
109
109
|
enum class CallConvention {
|
|
110
110
|
Cdecl,
|
|
111
111
|
Stdcall,
|
|
112
|
-
Fastcall
|
|
112
|
+
Fastcall,
|
|
113
|
+
Thiscall
|
|
113
114
|
};
|
|
114
115
|
static const char *const CallConventionNames[] = {
|
|
115
116
|
"Cdecl",
|
|
116
117
|
"Stdcall",
|
|
117
|
-
"Fastcall"
|
|
118
|
+
"Fastcall",
|
|
119
|
+
"Thiscall"
|
|
118
120
|
};
|
|
119
121
|
|
|
120
122
|
struct ParameterInfo {
|
|
@@ -163,6 +165,9 @@ struct FunctionInfo {
|
|
|
163
165
|
#if defined(__arm__) || defined(__aarch64__) || defined(__x86_64__) || defined(_WIN64)
|
|
164
166
|
bool forward_fp;
|
|
165
167
|
#endif
|
|
168
|
+
#if defined(__i386__) || defined(_M_IX86)
|
|
169
|
+
bool fast;
|
|
170
|
+
#endif
|
|
166
171
|
|
|
167
172
|
~FunctionInfo();
|
|
168
173
|
|
package/src/parser.cc
CHANGED
|
@@ -38,6 +38,8 @@ bool PrototypeParser::Parse(const char *str, FunctionInfo *out_func)
|
|
|
38
38
|
out_func->convention = CallConvention::Stdcall;
|
|
39
39
|
} else if (Match("__fastcall")) {
|
|
40
40
|
out_func->convention = CallConvention::Fastcall;
|
|
41
|
+
} else if (Match("__thiscall")) {
|
|
42
|
+
out_func->convention = CallConvention::Thiscall;
|
|
41
43
|
}
|
|
42
44
|
out_func->name = ParseIdentifier();
|
|
43
45
|
|
|
@@ -169,11 +171,21 @@ const TypeInfo *PrototypeParser::ParseType()
|
|
|
169
171
|
}
|
|
170
172
|
buf.ptr[--buf.len] = 0;
|
|
171
173
|
|
|
172
|
-
if (
|
|
173
|
-
buf.
|
|
174
|
-
|
|
174
|
+
if (indirect) {
|
|
175
|
+
const TypeInfo *type = instance->types_map.FindValue(buf.ptr, nullptr);
|
|
176
|
+
PrimitiveKind primitive = type ? type->primitive : PrimitiveKind::Void;
|
|
177
|
+
|
|
178
|
+
if (primitive == PrimitiveKind::Int8 || primitive == PrimitiveKind::UInt8) {
|
|
179
|
+
buf.RemoveFrom(0);
|
|
180
|
+
Fmt(&buf, "string");
|
|
175
181
|
|
|
176
|
-
|
|
182
|
+
indirect--;
|
|
183
|
+
} else if (primitive == PrimitiveKind::Int16 || primitive == PrimitiveKind::UInt16) {
|
|
184
|
+
buf.RemoveFrom(0);
|
|
185
|
+
Fmt(&buf, "string16");
|
|
186
|
+
|
|
187
|
+
indirect--;
|
|
188
|
+
}
|
|
177
189
|
}
|
|
178
190
|
|
|
179
191
|
while (buf.len) {
|
package/test/CMakeLists.txt
CHANGED
|
@@ -42,6 +42,9 @@ else()
|
|
|
42
42
|
-Wno-unused-function -Wno-missing-field-initializers
|
|
43
43
|
-Wno-unused-value -Wno-implicit-fallthrough -Wno-stringop-overflow
|
|
44
44
|
-Wno-unused-result)
|
|
45
|
+
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
|
46
|
+
target_compile_options(raylib PRIVATE -Wno-unknown-warning-option)
|
|
47
|
+
endif()
|
|
45
48
|
endif()
|
|
46
49
|
|
|
47
50
|
if(WIN32)
|
package/vendor/libcc/libcc.cc
CHANGED
|
@@ -3745,7 +3745,7 @@ static std::atomic_bool flag_interrupt = false;
|
|
|
3745
3745
|
static std::atomic_bool explicit_interrupt = false;
|
|
3746
3746
|
static int interrupt_pfd[2] = {-1, -1};
|
|
3747
3747
|
|
|
3748
|
-
|
|
3748
|
+
void SetSignalHandler(int signal, void (*func)(int), struct sigaction *prev)
|
|
3749
3749
|
{
|
|
3750
3750
|
struct sigaction action = {};
|
|
3751
3751
|
|
|
@@ -3786,10 +3786,10 @@ RG_INIT(SetupDefaultHandlers)
|
|
|
3786
3786
|
int ret = setpgid(0, 0);
|
|
3787
3787
|
RG_ASSERT(!ret);
|
|
3788
3788
|
|
|
3789
|
-
SetSignalHandler(SIGINT,
|
|
3790
|
-
SetSignalHandler(SIGTERM,
|
|
3791
|
-
SetSignalHandler(SIGHUP,
|
|
3792
|
-
SetSignalHandler(SIGPIPE,
|
|
3789
|
+
SetSignalHandler(SIGINT, DefaultSignalHandler);
|
|
3790
|
+
SetSignalHandler(SIGTERM, DefaultSignalHandler);
|
|
3791
|
+
SetSignalHandler(SIGHUP, DefaultSignalHandler);
|
|
3792
|
+
SetSignalHandler(SIGPIPE, [](int) {});
|
|
3793
3793
|
}
|
|
3794
3794
|
|
|
3795
3795
|
RG_EXIT(TerminateChildren)
|
|
@@ -3797,7 +3797,7 @@ RG_EXIT(TerminateChildren)
|
|
|
3797
3797
|
pid_t pid = getpid();
|
|
3798
3798
|
RG_ASSERT(pid > 1);
|
|
3799
3799
|
|
|
3800
|
-
SetSignalHandler(SIGTERM,
|
|
3800
|
+
SetSignalHandler(SIGTERM, [](int) {});
|
|
3801
3801
|
kill(-pid, SIGTERM);
|
|
3802
3802
|
}
|
|
3803
3803
|
|
|
@@ -4168,7 +4168,7 @@ WaitForResult WaitForInterrupt(int64_t timeout)
|
|
|
4168
4168
|
static std::atomic_bool message = false;
|
|
4169
4169
|
|
|
4170
4170
|
flag_interrupt = true;
|
|
4171
|
-
SetSignalHandler(SIGUSR1,
|
|
4171
|
+
SetSignalHandler(SIGUSR1, [](int) { message = true; });
|
|
4172
4172
|
|
|
4173
4173
|
if (timeout >= 0) {
|
|
4174
4174
|
struct timespec ts;
|
package/vendor/libcc/libcc.hh
CHANGED
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
#include <utility>
|
|
36
36
|
#if defined(_WIN32)
|
|
37
37
|
#include <intrin.h>
|
|
38
|
-
#elif !defined(__APPLE__) && (!defined(__linux__) || defined(__GLIBC__))
|
|
38
|
+
#elif !defined(__APPLE__) && (!defined(__linux__) || defined(__GLIBC__)) && __has_include(<ucontext.h>)
|
|
39
39
|
#define RG_FIBER_USE_UCONTEXT
|
|
40
40
|
#include <ucontext.h>
|
|
41
41
|
#else
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
#pragma intrinsic(__rdtsc)
|
|
55
55
|
#endif
|
|
56
56
|
|
|
57
|
+
struct sigaction;
|
|
57
58
|
struct BrotliEncoderStateStruct;
|
|
58
59
|
|
|
59
60
|
namespace RG {
|
|
@@ -3929,6 +3930,8 @@ enum class PipeMode {
|
|
|
3929
3930
|
bool CreateOverlappedPipe(bool overlap0, bool overlap1, PipeMode mode, void *out_handles[2]); // HANDLE
|
|
3930
3931
|
void CloseHandleSafe(void **handle_ptr); // HANDLE
|
|
3931
3932
|
#else
|
|
3933
|
+
void SetSignalHandler(int signal, void (*func)(int), struct sigaction *prev = nullptr);
|
|
3934
|
+
|
|
3932
3935
|
bool CreatePipe(int pfd[2]);
|
|
3933
3936
|
void CloseDescriptorSafe(int *fd_ptr);
|
|
3934
3937
|
#endif
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|