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.
Files changed (37) hide show
  1. package/CMakeLists.txt +7 -7
  2. package/README.md +18 -28
  3. package/build/qemu/1.1.3/koffi_darwin_x64.tar.gz +0 -0
  4. package/build/qemu/1.1.3/koffi_freebsd_arm64.tar.gz +0 -0
  5. package/build/qemu/1.1.3/koffi_freebsd_ia32.tar.gz +0 -0
  6. package/build/qemu/1.1.3/koffi_freebsd_x64.tar.gz +0 -0
  7. package/build/qemu/1.1.3/koffi_linux_arm.tar.gz +0 -0
  8. package/build/qemu/1.1.3/koffi_linux_arm64.tar.gz +0 -0
  9. package/build/qemu/1.1.3/koffi_linux_ia32.tar.gz +0 -0
  10. package/build/qemu/1.1.3/koffi_linux_x64.tar.gz +0 -0
  11. package/build/qemu/1.1.3/koffi_openbsd_x64.tar.gz +0 -0
  12. package/build/qemu/1.1.3/koffi_win32_ia32.tar.gz +0 -0
  13. package/build/qemu/1.1.3/koffi_win32_x64.tar.gz +0 -0
  14. package/package.json +1 -1
  15. package/qemu/registry/machines.json +47 -3
  16. package/qemu/registry/sha256sum.txt +16 -12
  17. package/src/abi_arm32.cc +43 -4
  18. package/src/abi_arm64.cc +22 -5
  19. package/src/abi_x64_sysv.cc +1 -1
  20. package/src/abi_x64_win.cc +1 -1
  21. package/src/abi_x86.cc +10 -4
  22. package/src/ffi.cc +43 -21
  23. package/src/ffi.hh +7 -2
  24. package/src/parser.cc +16 -4
  25. package/test/CMakeLists.txt +3 -0
  26. package/vendor/libcc/libcc.cc +7 -7
  27. package/vendor/libcc/libcc.hh +4 -1
  28. package/build/qemu/1.1.2/koffi_darwin_x64.tar.gz +0 -0
  29. package/build/qemu/1.1.2/koffi_freebsd_arm64.tar.gz +0 -0
  30. package/build/qemu/1.1.2/koffi_freebsd_ia32.tar.gz +0 -0
  31. package/build/qemu/1.1.2/koffi_freebsd_x64.tar.gz +0 -0
  32. package/build/qemu/1.1.2/koffi_linux_arm.tar.gz +0 -0
  33. package/build/qemu/1.1.2/koffi_linux_arm64.tar.gz +0 -0
  34. package/build/qemu/1.1.2/koffi_linux_ia32.tar.gz +0 -0
  35. package/build/qemu/1.1.2/koffi_linux_x64.tar.gz +0 -0
  36. package/build/qemu/1.1.2/koffi_win32_ia32.tar.gz +0 -0
  37. 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(WIN32)
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(WIN32)
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
- elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i[3456]86|x86|AMD64")
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: Type parser
27
-
28
- The following platforms __are officially supported and tested__ at the moment:
29
-
30
- Platform | Architecture | Sync calls | Async calls | Callbacks | Pre-built binary
31
- --------- | -------------------------------- | ---------- | ----------- | --------- | ----------------
32
- Windows | x86 (cdecl, stdcall, fastcall) | 🟩 Yes | 🟩 Yes | 🟥 No | 🟩 Yes
33
- Windows | x86_64 | 🟩 Yes | 🟩 Yes | 🟥 No | 🟩 Yes
34
- Linux | x86 | 🟩 Yes | 🟩 Yes | 🟥 No | 🟩 Yes
35
- Linux | x86_64 | 🟩 Yes | 🟩 Yes | 🟥 No | 🟩 Yes
36
- Linux | ARM32+VFP Little Endian | 🟩 Yes | 🟩 Yes | 🟥 No | 🟩 Yes
37
- Linux | ARM64 Little Endian | 🟩 Yes | 🟩 Yes | 🟥 No | 🟩 Yes
38
- FreeBSD | x86 | 🟩 Yes | 🟩 Yes | 🟥 No | 🟩 Yes
39
- FreeBSD | x86_64 | 🟩 Yes | 🟩 Yes | 🟥 No | 🟩 Yes
40
- FreeBSD | ARM64 Little Endian | 🟩 Yes | 🟩 Yes | 🟥 No | 🟩 Yes
41
- macOS | x86_64 | 🟩 Yes | 🟩 Yes | 🟥 No | 🟩 Yes
42
- macOS | ARM64 (M1) Little Endian | 🟩 Yes | 🟩 Yes | 🟥 No | 🟥 No
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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "koffi",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "description": "Fast and simple FFI (foreign function interface) for Node.js",
5
5
  "keywords": [
6
6
  "foreign",
@@ -253,7 +253,7 @@
253
253
  },
254
254
 
255
255
  "info": {
256
- "version": 1,
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": 1,
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": 1,
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
- 6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b *qemu/freebsd_arm64/VERSION
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
- a19ad06aec7972f3b95a56fb9bb8ac8a6afcd61b586f398691d58c704e8c466e *qemu/freebsd_arm64/disk.qcow2
30
- 10f2bc603b171368cacda43485f8f72567af0a9a490b7e0fa0c14c983ae66f16 *qemu/freebsd_arm64/xvfb-run.sh
31
- 6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b *qemu/freebsd_x64/VERSION
32
- 06eef544fe9c61d3905b0e588c306d1dedac7ee7d4c01df154ff6ed64e25ef77 *qemu/freebsd_x64/install.sh
33
- 060b66901313ddfcd434c20a7b13052b3e5126e43c4e44884b85191560bd99eb *qemu/freebsd_x64/disk.qcow2
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
- 8191cea63d738cdca6df0b2d2d6953675e1dd33cac4d98fff88ba4367b182b64 *qemu/freebsd_i386/disk.qcow2
38
- 10f2bc603b171368cacda43485f8f72567af0a9a490b7e0fa0c14c983ae66f16 *qemu/freebsd_i386/xvfb-run.sh
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, 1, 4)) {
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, 1, 4)) {
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, 1, 4)) {
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
- #ifdef __APPLE__
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 (IsHFA(param.type, 1, 4)) {
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
- #ifdef __APPLE__
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
@@ -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(_WIN64)
14
+ #if defined(__x86_64__) && !defined(_WIN32)
15
15
 
16
16
  #include "vendor/libcc/libcc.hh"
17
17
  #include "ffi.hh"
@@ -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
- #ifdef _WIN64
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 : 0;
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->convention == CallConvention::Fastcall) {
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->convention == CallConvention::Fastcall ? ForwardCallR ## Suffix(func->func, stack.ptr) \
263
- : ForwardCall ## Suffix(func->func, stack.ptr)); \
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 = AllocateAndAlign16(&mem->mem_alloc, Mebibytes(1));
399
- mem->heap = AllocateAndAlign16(&mem->mem_alloc, Mebibytes(2));
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
- Size parameters_len = parameters.Length();
606
+ uint32_t parameters_len = parameters.Length();
601
607
 
602
608
  if (parameters_len) {
603
- Napi::String str = ((Napi::Value)parameters[(uint32_t)(parameters_len - 1)]).As<Napi::String>();
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 = AllocateAndAlign16(&mem->mem_alloc, Mebibytes(2));
936
- mem->heap = AllocateAndAlign16(&mem->mem_alloc, Mebibytes(4));
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 (TestStr(buf, "char") && indirect) {
173
- buf.RemoveFrom(0);
174
- Fmt(&buf, "string");
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
- indirect--;
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) {
@@ -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)
@@ -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
- static void SetSignalHandler(int signal, struct sigaction *prev, void (*func)(int))
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, nullptr, DefaultSignalHandler);
3790
- SetSignalHandler(SIGTERM, nullptr, DefaultSignalHandler);
3791
- SetSignalHandler(SIGHUP, nullptr, DefaultSignalHandler);
3792
- SetSignalHandler(SIGPIPE, nullptr, [](int) {});
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, nullptr, [](int) {});
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, nullptr, [](int) { message = true; });
4171
+ SetSignalHandler(SIGUSR1, [](int) { message = true; });
4172
4172
 
4173
4173
  if (timeout >= 0) {
4174
4174
  struct timespec ts;
@@ -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