Compare commits

..

No commits in common. "master" and "snapshots" have entirely different histories.

29 changed files with 149 additions and 428 deletions

View File

@ -23,9 +23,9 @@ fi
function build_linux()
{
./autogen.sh
./configure ${HOST+--host=$HOST} ${CONFIGURE_OPTIONS} || cat */config.log
ls -l */config.log
cat */config.log
make
make dist
DEJAGNU=$(pwd)/.ci/site.exp BOARDSDIR=$(pwd)/.ci runtest --version

View File

@ -6,7 +6,7 @@ if [[ $RUNNER_OS != 'Linux' ]]; then
# brew update > brew-update.log 2>&1
# fix an issue with libtool on travis by reinstalling it
brew uninstall libtool;
brew install automake libtool dejagnu gcc@15;
brew install automake libtool dejagnu;
# Download and extract the rlgl client
wget -qO - https://rl.gl/cli/rlgl-darwin-amd64.tgz | \

View File

@ -5,7 +5,6 @@
BUILD-ERROR
RUNTIME-ERROR
FEATURE-REQUEST
QUESTION
# Operating systems
ANDROID

View File

@ -73,7 +73,7 @@ jobs:
fail-fast: false
matrix:
platform: [macos-13, macos-14, macos-15]
compilers: [CC=gcc-15 CXX=g++-15, CC=clang CXX=g++-15]
compilers: [CC=gcc CXX=g++, CC=clang CXX=clang++]
steps:
- run: git config --global core.autocrlf input

View File

@ -19,7 +19,7 @@ env:
# "info" field, or in Makefile.envs:
# https://github.com/pyodide/pyodide/blob/main/Makefile.envs#L2
PYTHON_VERSION: 3.12.7
EMSCRIPTEN_VERSION: 4.0.10
EMSCRIPTEN_VERSION: 3.1.58
EM_CACHE_FOLDER: emsdk-cache
jobs:
@ -39,21 +39,6 @@ jobs:
actions-cache-folder: ${{ env.EM_CACHE_FOLDER }}
test-dejagnu:
strategy:
matrix:
target:
- name: wasm32
host: wasm32
configureflags:
testflags:
- name: wasm64
host: wasm64
configureflags:
testflags: -sMEMORY64=1
- name: wasm64-2
host: wasm64
configureflags: WASM64_MEMORY64=2
testflags: -sMEMORY64=2
runs-on: ubuntu-24.04
needs: [setup-emsdk-cache]
steps:
@ -77,26 +62,11 @@ jobs:
version: ${{ env.EMSCRIPTEN_VERSION }}
actions-cache-folder: ${{ env.EM_CACHE_FOLDER }}
- name: Setup node.js
uses: actions/setup-node@v4
with:
node-version: 24
# This step updates emsdk's configuration file ".emscripten" to point to
# nodejs installed in the previous step.
- name: Configure emsdk to use the installed node.js
run: sed -i -E 's|NODE_JS = .*|NODE_JS = '"'$(which node)'"'|g' ${EMSDK}/.emscripten
- name: Install dependencies
run: sudo apt-get install dejagnu libltdl-dev
- name: Run tests
run: testsuite/emscripten/node-tests.sh
env:
TARGET_HOST: ${{ matrix.target.host }}
EXTRA_CONFIGURE_FLAGS: ${{ matrix.target.configureflags }}
EXTRA_CFLAGS: ${{ matrix.target.testflags }}
EXTRA_TEST_LDFLAGS: ${{ matrix.target.testflags }}
- name: Install rlgl and run
run: |
@ -107,21 +77,6 @@ jobs:
exit $?
build:
strategy:
matrix:
target:
- name: wasm32
host: wasm32
configureflags:
testflags:
- name: wasm64
host: wasm64
configureflags:
testflags: -sMEMORY64=1
- name: wasm64-2
host: wasm64
configureflags: WASM64_MEMORY64=2
testflags: -sMEMORY64=2
runs-on: ubuntu-24.04
needs: [setup-emsdk-cache]
steps:
@ -145,9 +100,6 @@ jobs:
- name: Build
run: ./testsuite/emscripten/build.sh
env:
TARGET_HOST: ${{ matrix.target.host }}
EXTRA_CONFIGURE_FLAGS: ${{ matrix.target.configureflags }}
- name: Build tests
run: |
@ -155,23 +107,16 @@ jobs:
cp -r testsuite/libffi.closures testsuite/libffi.closures.test
./testsuite/emscripten/build-tests.sh testsuite/libffi.call.test
./testsuite/emscripten/build-tests.sh testsuite/libffi.closures.test
env:
EXTRA_CFLAGS: ${{ matrix.target.testflags }}
EXTRA_LD_FLAGS: ${{ matrix.target.testflags }}
- name: Store artifacts
uses: actions/upload-artifact@v4
with:
name: built-tests-${{ matrix.target.name }}
name: built-tests
path: ./testsuite/libffi.c*/
test:
strategy:
matrix:
target:
- name: wasm32
- name: wasm64
- name: wasm64-2
browser: ["chrome"]
# FIXME: selenium can't find gecko driver for "firefox"
runs-on: ubuntu-24.04
@ -183,7 +128,7 @@ jobs:
- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: built-tests-${{ matrix.target.name }}
name: built-tests
path: ./testsuite/
- uses: conda-incubator/setup-miniconda@v3

View File

@ -8,43 +8,33 @@ jobs:
dist:
runs-on: ubuntu-latest
steps:
- name: Install tools
run: |
sudo apt update
sudo apt install texlive texinfo autoconf automake libtool libltdl-dev
- uses: actions/checkout@v4
with: {fetch-depth: 0}
- name: Compute snapshot VERSION
id: ver
run: |
DESC=$(git describe --long --tags --match 'v[0-9]*' 2>/dev/null || echo "")
VERSION=$(echo "$DESC" | sed -E 's/^v//; s/-([0-9]+)-g/\.\1+g/')
if [[ -z "$VERSION" || "$VERSION" == "$DESC" ]]; then
VERSION="3.5.1-dev.0+g$(git rev-parse --short HEAD)"
fi
echo "VERSION=$VERSION" >> "$GITHUB_ENV"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
- name: Patch configure.ac
run: |
sed -Ei "s/^(AC_INIT\(\[libffi\],\s*\[)[^]]+/\1${VERSION}/" configure.ac
sed -Ei "s/^(FFI_VERSION_STRING=\")[^\"]+/\1${VERSION}/" configure.ac
- run: autoreconf -fi
- run: ./configure
- run: make dist # produces libffi-${VERSION}.tar.gz
- name: Wipe old snapshot assets
uses: mknejp/delete-release-assets@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
tag: snapshots # ← whatever tag your nightly release uses
fail-if-no-assets: false
assets: |
libffi-*.tar.*
libffi-*.zip
fetch-depth: 0 # git describe needs full history
- name: Install autotools
run: sudo apt-get update && sudo apt-get -y install autoconf automake libtool texinfo libltdl-dev texlive
- name: Stamp snapshot version into configure.ac
run: |
VERSION="$(git describe --tags --long --match 'v[0-9]*' | sed -e 's/^v//' -e 's/-/.dev./' -e 's/-/+g/')"
echo "VERSION=$VERSION" >> "$GITHUB_ENV"
# 1) AC_INIT second argument
# AC_INIT([libffi],[<old>],[bug-address])
sed -E -i "s/^(AC_INIT\(\[libffi\],\s*\[)[^]]+/\1$VERSION/" configure.ac
# 2) FFI_VERSION_STRING="..."
sed -E -i "s/^(FFI_VERSION_STRING=\")[^\"]+/\1$VERSION/" configure.ac
- name: autogen
run: ./autogen.sh
- name: Configure
run: ./configure
- name: Build dist tarball
run: make dist
- name: Create (or update) “snapshots” release
uses: softprops/action-gh-release@v2

View File

@ -63,11 +63,11 @@ noinst_HEADERS = src/aarch64/ffitarget.h src/aarch64/internal.h \
src/or1k/ffitarget.h src/pa/ffitarget.h \
src/powerpc/ffitarget.h src/powerpc/asm.h \
src/powerpc/ffi_powerpc.h src/powerpc/internal.h \
src/riscv/ffitarget.h src/riscv/internal.h \
src/riscv/ffitarget.h \
src/s390/ffitarget.h src/s390/internal.h src/sh/ffitarget.h \
src/sh64/ffitarget.h src/sparc/ffitarget.h \
src/sparc/internal.h src/tile/ffitarget.h src/vax/ffitarget.h \
src/wasm/ffitarget.h \
src/wasm32/ffitarget.h \
src/x86/ffitarget.h src/x86/internal.h src/x86/internal64.h \
src/x86/asmnames.h src/xtensa/ffitarget.h src/dlmalloc.c \
src/kvx/ffitarget.h src/kvx/asm.h \
@ -98,7 +98,7 @@ EXTRA_libffi_la_SOURCES = src/aarch64/ffi.c src/aarch64/sysv.S \
src/sh64/sysv.S src/sparc/ffi.c src/sparc/ffi64.c \
src/sparc/v8.S src/sparc/v9.S src/tile/ffi.c src/tile/tile.S \
src/vax/ffi.c src/vax/elfbsd.S src/x86/ffi.c src/x86/sysv.S \
src/wasm/ffi.c \
src/wasm32/ffi.c \
src/x86/ffiw64.c src/x86/win64.S src/x86/ffi64.c \
src/x86/unix64.S src/x86/sysv_intel.S src/x86/win64_intel.S \
src/xtensa/ffi.c src/xtensa/sysv.S src/kvx/ffi.c \

View File

@ -1,7 +1,8 @@
Status
======
libffi-3.5.2 was released on August 2, 2025.
libffi-3.5.0 was released on June 8, 2025. Check the libffi web
page for updates: <URL:http://sourceware.org/libffi/>.
What is libffi?
@ -102,7 +103,6 @@ tested:
| TILE-Gx/TILEPro | Linux | GCC |
| VAX | OpenBSD/vax | GCC |
| WASM32 | Emscripten | EMCC |
| WASM64 | Emscripten | EMCC |
| X86 | FreeBSD | GCC |
| X86 | GNU HURD | GCC |
| X86 | Interix | GCC |
@ -114,7 +114,6 @@ tested:
| X86 | Solaris | Oracle Solaris Studio C |
| X86 | Windows/Cygwin | GCC |
| X86 | Windows/MinGW | GCC |
| X86-64 | DragonFly BSD | GCC |
| X86-64 | FreeBSD | GCC |
| X86-64 | Linux | GCC |
| X86-64 | Linux/x32 | GCC |
@ -204,14 +203,6 @@ History
See the git log for details at http://github.com/libffi/libffi.
3.5.2 Aug-2-2025
Add wasm64 support.
Add DragonFly BSD support.
Ensure trampoline file descriptors are closed on exec.
3.5.1 Jun-10-2025
Fix symbol versioning error.
3.5.0 Jun-8-2025
Add FFI_VERSION_STRING and FFI_VERSION_NUMBER macros, as well
as ffi_get_version() and ffi_get_version_number() functions.

View File

@ -2,11 +2,11 @@ dnl Process this with autoconf to create configure
AC_PREREQ([2.68])
AC_INIT([libffi],[3.5.2],[http://github.com/libffi/libffi/issues])
AC_INIT([libffi],[3.5.1-dev],[http://github.com/libffi/libffi/issues])
AC_CONFIG_HEADERS([fficonfig.h])
FFI_VERSION_STRING="3.5.2"
FFI_VERSION_NUMBER=30502
FFI_VERSION_STRING="3.5.1-dev"
FFI_VERSION_NUMBER=30501
AC_SUBST(FFI_VERSION_STRING)
AC_SUBST(FFI_VERSION_NUMBER)
@ -123,8 +123,6 @@ AC_C_BIGENDIAN
GCC_AS_CFI_PSEUDO_OP
AC_ARG_VAR([WASM64_MEMORY64], [Used only for the wasm64 target. Set to 1 (default) or 2 for Emscripten's -sMEMORY64 mode])
case "$TARGET" in
SPARC)
AC_CACHE_CHECK([assembler and linker support unaligned pc related relocs],
@ -184,15 +182,6 @@ case "$TARGET" in
[Define if the compiler uses zarch features.])
fi
;;
wasm64)
if test -z "$WASM64_MEMORY64"; then
WASM64_MEMORY64=1
fi
CFLAGS="$CFLAGS -sMEMORY64=$WASM64_MEMORY64"
;;
LOONGARCH64)
CFLAGS="$CFLAGS -mcmodel=medium"
;;
esac
AC_CACHE_CHECK([whether compiler supports pointer authentication],
@ -241,7 +230,7 @@ case "$target" in
[Cannot use PROT_EXEC on this target, so, we revert to
alternative means])
;;
*-apple-* | *-*-dragonfly* | *-*-freebsd* | *-*-kfreebsd* | *-*-openbsd* | *-pc-solaris* | *-linux-android*)
*-apple-* | *-*-freebsd* | *-*-kfreebsd* | *-*-openbsd* | *-pc-solaris* | *-linux-android*)
AC_DEFINE(FFI_MMAP_EXEC_WRIT, 1,
[Cannot use malloc on this target, so, we revert to
alternative means])
@ -395,8 +384,7 @@ case "$target" in
fi
;;
*arm*-*-linux-* | aarch64*-*-linux-* | i*86-*-linux-* | x86_64-*-linux-* \
| loongarch*-*-linux-* | s390x*-linux-* | powerpc*-linux-* \
| riscv*-linux-*)
| loongarch*-*-linux-* | s390x*-linux-* | powerpc*-linux-*)
AC_DEFINE(FFI_EXEC_STATIC_TRAMP, 1,
[Define this if you want statically defined trampolines])
;;

View File

@ -261,12 +261,7 @@ case "${host}" in
;;
wasm32-*-*)
TARGET=wasm32; TARGETDIR=wasm
SOURCES="ffi.c"
;;
wasm64-*-*)
TARGET=wasm64; TARGETDIR=wasm
TARGET=wasm32; TARGETDIR=wasm32
SOURCES="ffi.c"
;;

View File

@ -1,4 +1,4 @@
@set UPDATED 2 August 2025
@set UPDATED-MONTH August 2025
@set EDITION 3.5.2
@set VERSION 3.5.2
@set UPDATED 8 June 2025
@set UPDATED-MONTH June 2025
@set EDITION 3.5.0
@set VERSION 3.5.0

View File

@ -23,6 +23,13 @@ LIBFFI_BASE_8.0 {
ffi_type_longdouble;
ffi_type_pointer;
/* Exported functions. */
ffi_get_version;
ffi_get_version_number;
ffi_get_default_abi;
ffi_get_closure_size;
ffi_call;
ffi_prep_cif;
ffi_prep_cif_var;
@ -45,19 +52,6 @@ LIBFFI_BASE_8.0 {
*;
};
/* ----------------------------------------------------------------------
Symbols **added in libffi 3.5.0**.
Give them a fresh namespace so that package managers notice when
code requires a newer libffi than 3.4.x.
-------------------------------------------------------------------- */
LIBFFI_BASE_8.1 {
global:
ffi_get_version;
ffi_get_version_number;
ffi_get_default_abi;
ffi_get_closure_size;
} LIBFFI_BASE_8.0;
#ifdef FFI_TARGET_HAS_COMPLEX_TYPE
LIBFFI_COMPLEX_8.0 {
global:

View File

@ -74,12 +74,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
.text
.align 4
#if defined(__ARM_FEATURE_GCS_DEFAULT) && __ARM_FEATURE_GCS_DEFAULT == 1
#define GNU_PROPERTY_AARCH64_GCS (1<<2)
#else
#define GNU_PROPERTY_AARCH64_GCS 0 /* No GCS */
#endif
/* ffi_call_SYSV
extern void ffi_call_SYSV (void *stack, void *frame,
void (*fn)(void), void *rvalue,
@ -698,7 +692,7 @@ CNAME(ffi_go_closure_SYSV):
.asciz "GNU";
.long 0xc0000000; /* GNU_PROPERTY_AARCH64_FEATURE_1_AND */
.long 4;
.long GNU_PROPERTY_AARCH64_BTI | GNU_PROPERTY_AARCH64_POINTER_AUTH | GNU_PROPERTY_AARCH64_GCS;
.long GNU_PROPERTY_AARCH64_BTI | GNU_PROPERTY_AARCH64_POINTER_AUTH;
.long 0;
.popsection;
#endif

View File

@ -120,7 +120,7 @@
#endif
#ifdef __ELF__
#ifndef __clang__
/* We require interworking on LDM, which implies ARMv5T,
which implies the existance of BLX. */
.arch armv5t

View File

@ -29,8 +29,6 @@
#include <ffi.h>
#include <ffi_common.h>
#include "internal.h"
#include <tramp.h>
#include <stdlib.h>
#include <stdint.h>
@ -426,44 +424,34 @@ extern void ffi_closure_asm(void) FFI_HIDDEN;
ffi_status ffi_prep_closure_loc(ffi_closure *closure, ffi_cif *cif, void (*fun)(ffi_cif*,void*,void**,void*), void *user_data, void *codeloc)
{
uint32_t *tramp = (uint32_t *) &closure->tramp[0];
uint64_t fn = (uint64_t) (uintptr_t) ffi_closure_asm;
if (cif->abi <= FFI_FIRST_ABI || cif->abi >= FFI_LAST_ABI)
return FFI_BAD_ABI;
#ifdef FFI_EXEC_STATIC_TRAMP
if (ffi_tramp_is_present (closure))
{
/* Initialize the static trampoline's parameters. */
void (*dest)(void) = ffi_closure_asm;
ffi_tramp_set_parms (closure->ftramp, dest, closure);
}
else
#endif
{
uint32_t *tramp = (uint32_t *) &closure->tramp[0];
uint64_t fn = (uint64_t) (uintptr_t) ffi_closure_asm;
/* we will call ffi_closure_inner with codeloc, not closure, but as long
as the memory is readable it should work */
/* we will call ffi_closure_inner with codeloc, not closure, but as long
as the memory is readable it should work */
tramp[0] = 0x00000317; /* auipc t1, 0 (i.e. t0 <- codeloc) */
tramp[0] = 0x00000317; /* auipc t1, 0 (i.e. t0 <- codeloc) */
#if __SIZEOF_POINTER__ == 8
tramp[1] = 0x01033383; /* ld t2, 16(t1) */
tramp[1] = 0x01033383; /* ld t2, 16(t1) */
#else
tramp[1] = 0x01032383; /* lw t2, 16(t1) */
tramp[1] = 0x01032383; /* lw t2, 16(t1) */
#endif
tramp[2] = 0x00038067; /* jr t2 */
tramp[3] = 0x00000013; /* nop */
tramp[4] = fn;
tramp[5] = fn >> 32;
#if !defined(__FreeBSD__)
__builtin___clear_cache(codeloc, codeloc + FFI_TRAMPOLINE_SIZE);
#endif
}
tramp[2] = 0x00038067; /* jr t2 */
tramp[3] = 0x00000013; /* nop */
tramp[4] = fn;
tramp[5] = fn >> 32;
closure->cif = cif;
closure->fun = fun;
closure->user_data = user_data;
#if !defined(__FreeBSD__)
__builtin___clear_cache(codeloc, codeloc + FFI_TRAMPOLINE_SIZE);
#endif
return FFI_OK;
}
@ -524,14 +512,3 @@ ffi_closure_inner (ffi_cif *cif,
marshal(&cb, cif->rtype, 0, rvalue);
}
}
#ifdef FFI_EXEC_STATIC_TRAMP
void *
ffi_tramp_arch (size_t *tramp_size, size_t *map_size)
{
extern void *trampoline_code_table;
*tramp_size = RISCV_TRAMP_SIZE;
*map_size = RISCV_TRAMP_MAP_SIZE;
return &trampoline_code_table;
}
#endif

View File

@ -1,7 +0,0 @@
#ifdef FFI_EXEC_STATIC_TRAMP
/* For the trampoline table mapping, a mapping size of 4K (base page size)
is chosen. */
#define RISCV_TRAMP_MAP_SHIFT 12
#define RISCV_TRAMP_MAP_SIZE (1 << RISCV_TRAMP_MAP_SHIFT)
#define RISCV_TRAMP_SIZE 16
#endif /* FFI_EXEC_STATIC_TRAMP */

View File

@ -29,7 +29,6 @@
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
#include "internal.h"
/* Define aliases so that we can handle all ABIs uniformly */
@ -292,26 +291,3 @@ ffi_go_closure_asm:
ret
.cfi_endproc
.size ffi_go_closure_asm, .-ffi_go_closure_asm
#ifdef FFI_EXEC_STATIC_TRAMP
/*
trampoline_code_table.
*/
.globl trampoline_code_table
.hidden trampoline_code_table
.type trampoline_code_table, @function
.align RISCV_TRAMP_MAP_SHIFT
trampoline_code_table:
.option push
# Do not allow the jr insn to be encoded as c.jr for alignment purposes
.option norvc
.rept RISCV_TRAMP_MAP_SIZE / RISCV_TRAMP_SIZE
auipc t2, RISCV_TRAMP_MAP_SIZE >> 12
LARG t1, 0(t2)
LARG t2, PTRS(t2)
jr t2
.endr
.option pop
.size trampoline_code_table,.-trampoline_code_table
.align RISCV_TRAMP_MAP_SHIFT
#endif /* FFI_EXEC_STATIC_TRAMP */

View File

@ -209,11 +209,6 @@ ffi_tramp_get_libffi (void)
unsigned long start, end, offset, inode;
uintptr_t addr = (uintptr_t) tramp_globals.text;
int nfields, found;
int open_flags = O_RDONLY;
#ifdef O_CLOEXEC
open_flags |= O_CLOEXEC;
#endif
snprintf (file, PATH_MAX, "/proc/%d/maps", getpid());
fp = fopen (file, "r");
@ -241,7 +236,7 @@ ffi_tramp_get_libffi (void)
if (!found)
return 0;
tramp_globals.fd = open (file, open_flags);
tramp_globals.fd = open (file, O_RDONLY);
if (tramp_globals.fd == -1)
return 0;

View File

@ -59,29 +59,16 @@ EM_JS_DEPS(libffi, "$getWasmTableEntry,$setWasmTableEntry,$getEmptyTableSlot,$co
offsetof(struct, field) == offset, \
"Memory layout of '" #struct "' has changed: '" #field "' is in an unexpected location");
#if __SIZEOF_POINTER__ == 4
#define FFI_EMSCRIPTEN_ABI FFI_WASM32_EMSCRIPTEN
#define PTR_SIG 'i'
#define DEC_PTR(p) p
#define ENC_PTR(p) p
#define DEREF_PTR(addr, offset) DEREF_U32(addr, offset)
#define DEREF_PTR_NUMBER(addr, offset) DEREF_PTR(addr, offset)
CHECK_FIELD_OFFSET(ffi_cif, abi, 4*0);
CHECK_FIELD_OFFSET(ffi_cif, nargs, 4*1);
CHECK_FIELD_OFFSET(ffi_cif, arg_types, 4*2);
CHECK_FIELD_OFFSET(ffi_cif, rtype, 4*3);
CHECK_FIELD_OFFSET(ffi_cif, flags, 4*5);
CHECK_FIELD_OFFSET(ffi_cif, nfixedargs, 4*6);
#define CIF__ABI(addr) DEREF_U32(addr, 0)
#define CIF__NARGS(addr) DEREF_U32(addr, 1)
#define CIF__ARGTYPES(addr) DEREF_U32(addr, 2)
#define CIF__RTYPE(addr) DEREF_U32(addr, 3)
#define CIF__FLAGS(addr) DEREF_U32(addr, 5)
#define CIF__NFIXEDARGS(addr) DEREF_U32(addr, 6)
CHECK_FIELD_OFFSET(ffi_type, size, 0);
@ -94,49 +81,6 @@ CHECK_FIELD_OFFSET(ffi_type, elements, 8);
#define FFI_TYPE__TYPEID(addr) DEREF_U16(addr + 6, 0)
#define FFI_TYPE__ELEMENTS(addr) DEREF_U32(addr + 8, 0)
#elif __SIZEOF_POINTER__ == 8
#define FFI_EMSCRIPTEN_ABI FFI_WASM64_EMSCRIPTEN
#define PTR_SIG 'j'
// DEC_PTR casts a pointer value (comming from Wasm) represented as BigInt (i64) to Number (i53).
// This should be used for a pointer that is expected to be within the i53 range. If the pointer
// value is outside the Number's range, the value will become NaN.
#define DEC_PTR(p) bigintToI53Checked(p)
// ENC_PTR casts a pointer value represented as Number to BigInt (i64)
#define ENC_PTR(p) BigInt(p)
#define DEREF_PTR(addr, offset) DEREF_U64(addr, offset)
#define DEREF_PTR_NUMBER(addr, offset) DEC_PTR(DEREF_PTR(addr, offset))
CHECK_FIELD_OFFSET(ffi_cif, abi, 0);
CHECK_FIELD_OFFSET(ffi_cif, nargs, 4);
CHECK_FIELD_OFFSET(ffi_cif, arg_types, 8);
CHECK_FIELD_OFFSET(ffi_cif, rtype, 16);
CHECK_FIELD_OFFSET(ffi_cif, flags, 28);
CHECK_FIELD_OFFSET(ffi_cif, nfixedargs, 32);
#define CIF__ABI(addr) DEREF_U32(addr, 0)
#define CIF__NARGS(addr) DEREF_U32(addr + 4, 0)
#define CIF__ARGTYPES(addr) DEREF_U64(addr + 8, 0)
#define CIF__RTYPE(addr) DEREF_U64(addr + 16, 0)
#define CIF__FLAGS(addr) DEREF_U32(addr + 28, 0)
#define CIF__NFIXEDARGS(addr) DEREF_U32(addr + 32, 0)
CHECK_FIELD_OFFSET(ffi_type, size, 0);
CHECK_FIELD_OFFSET(ffi_type, alignment, 8);
CHECK_FIELD_OFFSET(ffi_type, type, 10);
CHECK_FIELD_OFFSET(ffi_type, elements, 16);
#define FFI_TYPE__SIZE(addr) DEREF_U64(addr, 0)
#define FFI_TYPE__ALIGN(addr) DEREF_U16(addr + 8, 0)
#define FFI_TYPE__TYPEID(addr) DEREF_U16(addr + 10, 0)
#define FFI_TYPE__ELEMENTS(addr) DEREF_U64(addr + 16, 0)
#else
#error "Unknown pointer size"
#endif
#define ALIGN_ADDRESS(addr, align) (addr &= (~((align) - 1)))
#define STACK_ALLOC(stack, size, align) ((stack -= (size)), ALIGN_ADDRESS(stack, align))
@ -156,7 +100,7 @@ _Static_assert(FFI_BAD_TYPEDEF_MACRO == FFI_BAD_TYPEDEF, "FFI_BAD_TYPEDEF must b
ffi_status FFI_HIDDEN
ffi_prep_cif_machdep(ffi_cif *cif)
{
if (cif->abi != FFI_EMSCRIPTEN_ABI)
if (cif->abi != FFI_WASM32_EMSCRIPTEN)
return FFI_BAD_ABI;
// This is called after ffi_prep_cif_machdep_var so we need to avoid
// overwriting cif->nfixedargs.
@ -200,7 +144,6 @@ ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned nfixedargs, unsigned ntotalargs)
EM_JS_MACROS(
void,
unbox_small_structs, (ffi_type type_ptr), {
type_ptr = DEC_PTR(type_ptr);
var type_id = FFI_TYPE__TYPEID(type_ptr);
while (type_id === FFI_TYPE_STRUCT) {
// Don't unbox single element structs if they are bigger than 16 bytes. This
@ -213,15 +156,15 @@ unbox_small_structs, (ffi_type type_ptr), {
//
// See the Python comment here:
// https://github.com/python/cpython/blob/a16a9f978f42b8a09297c1efbf33877f6388c403/Modules/_ctypes/stgdict.c#L718-L779
if (DEC_PTR(FFI_TYPE__SIZE(type_ptr)) > 16) {
if (FFI_TYPE__SIZE(type_ptr) > 16) {
break;
}
var elements = DEC_PTR(FFI_TYPE__ELEMENTS(type_ptr));
var first_element = DEREF_PTR_NUMBER(elements, 0);
var elements = FFI_TYPE__ELEMENTS(type_ptr);
var first_element = DEREF_U32(elements, 0);
if (first_element === 0) {
type_id = FFI_TYPE_VOID;
break;
} else if (DEREF_PTR_NUMBER(elements, 1) === 0) {
} else if (DEREF_U32(elements, 1) === 0) {
type_ptr = first_element;
type_id = FFI_TYPE__TYPEID(first_element);
} else {
@ -235,15 +178,10 @@ EM_JS_MACROS(
void,
ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
{
cif = DEC_PTR(cif);
fn = DEC_PTR(fn);
rvalue = DEC_PTR(rvalue);
avalue = DEC_PTR(avalue);
var abi = CIF__ABI(cif);
var nargs = CIF__NARGS(cif);
var nfixedargs = CIF__NFIXEDARGS(cif);
var arg_types_ptr = DEC_PTR(CIF__ARGTYPES(cif));
var flags = CIF__FLAGS(cif);
var arg_types_ptr = CIF__ARGTYPES(cif);
var rtype_unboxed = unbox_small_structs(CIF__RTYPE(cif));
var rtype_ptr = rtype_unboxed[0];
var rtype_id = rtype_unboxed[1];
@ -267,7 +205,7 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
// just use this. We also mark a flag that we don't need to convert the return
// value of the dynamic call back to C.
if (rtype_id === FFI_TYPE_LONGDOUBLE || rtype_id === FFI_TYPE_STRUCT) {
args.push(ENC_PTR(rvalue));
args.push(rvalue);
ret_by_arg = true;
}
@ -276,8 +214,8 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
// Javascript to C automatically, here we manually do the inverse conversion
// from C to Javascript.
for (var i = 0; i < nfixedargs; i++) {
var arg_ptr = DEREF_PTR_NUMBER(avalue, i);
var arg_unboxed = unbox_small_structs(DEREF_PTR(arg_types_ptr, i));
var arg_ptr = DEREF_U32(avalue, i);
var arg_unboxed = unbox_small_structs(DEREF_U32(arg_types_ptr, i));
var arg_type_ptr = arg_unboxed[0];
var arg_type_id = arg_unboxed[1];
@ -288,6 +226,7 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
case FFI_TYPE_INT:
case FFI_TYPE_SINT32:
case FFI_TYPE_UINT32:
case FFI_TYPE_POINTER:
args.push(DEREF_U32(arg_ptr, 0));
break;
case FFI_TYPE_FLOAT:
@ -321,14 +260,11 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
// Nontrivial structs are passed by pointer.
// Have to copy the struct onto the stack though because C ABI says it's
// call by value.
var size = DEC_PTR(FFI_TYPE__SIZE(arg_type_ptr));
var size = FFI_TYPE__SIZE(arg_type_ptr);
var align = FFI_TYPE__ALIGN(arg_type_ptr);
STACK_ALLOC(cur_stack_ptr, size, align);
HEAP8.subarray(cur_stack_ptr, cur_stack_ptr+size).set(HEAP8.subarray(arg_ptr, arg_ptr + size));
args.push(ENC_PTR(cur_stack_ptr));
break;
case FFI_TYPE_POINTER:
args.push(DEREF_PTR(arg_ptr, 0));
args.push(cur_stack_ptr);
break;
case FFI_TYPE_COMPLEX:
throw new Error('complex marshalling nyi');
@ -346,11 +282,11 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
// We don't have any way of knowing how many args were actually passed, so we
// just always copy extra nonsense past the end. The ownwards call will know
// not to look at it.
if (flags & VARARGS_FLAG) {
if (nfixedargs != nargs) {
var struct_arg_info = [];
for (var i = nargs - 1; i >= nfixedargs; i--) {
var arg_ptr = DEREF_PTR_NUMBER(avalue, i);
var arg_unboxed = unbox_small_structs(DEREF_PTR(arg_types_ptr, i));
var arg_ptr = DEREF_U32(avalue, i);
var arg_unboxed = unbox_small_structs(DEREF_U32(arg_types_ptr, i));
var arg_type_ptr = arg_unboxed[0];
var arg_type_id = arg_unboxed[1];
switch (arg_type_id) {
@ -367,6 +303,7 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
case FFI_TYPE_INT:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_POINTER:
case FFI_TYPE_FLOAT:
STACK_ALLOC(cur_stack_ptr, 4, 4);
DEREF_U32(cur_stack_ptr, 0) = DEREF_U32(arg_ptr, 0);
@ -389,12 +326,8 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
// Again, struct must be passed by pointer.
// But ABI is by value, so have to copy struct onto stack.
// Currently arguments are going onto stack so we can't put it there now. Come back for this.
STACK_ALLOC(cur_stack_ptr, __SIZEOF_POINTER__, __SIZEOF_POINTER__);
struct_arg_info.push([cur_stack_ptr, arg_ptr, DEC_PTR(FFI_TYPE__SIZE(arg_type_ptr)), FFI_TYPE__ALIGN(arg_type_ptr)]);
break;
case FFI_TYPE_POINTER:
STACK_ALLOC(cur_stack_ptr, __SIZEOF_POINTER__, __SIZEOF_POINTER__);
DEREF_PTR(cur_stack_ptr, 0) = DEREF_PTR(arg_ptr, 0);
STACK_ALLOC(cur_stack_ptr, 4, 4);
struct_arg_info.push([cur_stack_ptr, arg_ptr, FFI_TYPE__SIZE(arg_type_ptr), FFI_TYPE__ALIGN(arg_type_ptr)]);
break;
case FFI_TYPE_COMPLEX:
throw new Error('complex arg marshalling nyi');
@ -403,7 +336,7 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
}
}
// extra normal argument which is the pointer to the varargs.
args.push(ENC_PTR(cur_stack_ptr));
args.push(cur_stack_ptr);
// Now allocate variable struct args on stack too.
for (var i = 0; i < struct_arg_info.length; i++) {
var struct_info = struct_arg_info[i];
@ -413,7 +346,7 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
var align = struct_info[3];
STACK_ALLOC(cur_stack_ptr, size, align);
HEAP8.subarray(cur_stack_ptr, cur_stack_ptr+size).set(HEAP8.subarray(arg_ptr, arg_ptr + size));
DEREF_PTR(arg_target, 0) = ENC_PTR(cur_stack_ptr);
DEREF_U32(arg_target, 0) = cur_stack_ptr;
}
}
stackRestore(cur_stack_ptr);
@ -438,6 +371,7 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
case FFI_TYPE_INT:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_POINTER:
DEREF_U32(rvalue, 0) = result;
break;
case FFI_TYPE_FLOAT:
@ -458,9 +392,6 @@ ffi_call_js, (ffi_cif *cif, ffi_fp fn, void *rvalue, void **avalue),
case FFI_TYPE_SINT64:
DEREF_U64(rvalue, 0) = result;
break;
case FFI_TYPE_POINTER:
DEREF_PTR(rvalue, 0) = result;
break;
case FFI_TYPE_COMPLEX:
throw new Error('complex ret marshalling nyi');
default:
@ -472,8 +403,6 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) {
ffi_call_js(cif, fn, rvalue, avalue);
}
#if __SIZEOF_POINTER__ == 4
CHECK_FIELD_OFFSET(ffi_closure, ftramp, 4*0);
CHECK_FIELD_OFFSET(ffi_closure, cif, 4*1);
CHECK_FIELD_OFFSET(ffi_closure, fun, 4*2);
@ -484,30 +413,12 @@ CHECK_FIELD_OFFSET(ffi_closure, user_data, 4*3);
#define CLOSURE__fun(addr) DEREF_U32(addr, 2)
#define CLOSURE__user_data(addr) DEREF_U32(addr, 3)
#elif __SIZEOF_POINTER__ == 8
CHECK_FIELD_OFFSET(ffi_closure, ftramp, 0);
CHECK_FIELD_OFFSET(ffi_closure, cif, 8);
CHECK_FIELD_OFFSET(ffi_closure, fun, 16);
CHECK_FIELD_OFFSET(ffi_closure, user_data, 24);
#define CLOSURE__wrapper(addr) DEREF_U64(addr, 0)
#define CLOSURE__cif(addr) DEREF_U64(addr, 1)
#define CLOSURE__fun(addr) DEREF_U64(addr, 2)
#define CLOSURE__user_data(addr) DEREF_U64(addr, 3)
#else
#error "Unknown pointer size"
#endif
EM_JS_MACROS(void *, ffi_closure_alloc_js, (size_t size, void **code), {
size = DEC_PTR(size);
code = DEC_PTR(code);
var closure = _malloc(size);
var index = getEmptyTableSlot();
DEREF_PTR(code, 0) = ENC_PTR(index);
CLOSURE__wrapper(closure) = ENC_PTR(index);
return ENC_PTR(closure);
DEREF_U32(code, 0) = index;
CLOSURE__wrapper(closure) = index;
return closure;
})
void * __attribute__ ((visibility ("default")))
@ -516,8 +427,7 @@ ffi_closure_alloc(size_t size, void **code) {
}
EM_JS_MACROS(void, ffi_closure_free_js, (void *closure), {
closure = DEC_PTR(closure);
var index = DEC_PTR(CLOSURE__wrapper(closure));
var index = CLOSURE__wrapper(closure);
freeTableIndexes.push(index);
_free(closure);
})
@ -532,15 +442,10 @@ ffi_status,
ffi_prep_closure_loc_js,
(ffi_closure *closure, ffi_cif *cif, void *fun, void *user_data, void *codeloc),
{
closure = DEC_PTR(closure);
cif = DEC_PTR(cif);
fun = DEC_PTR(fun);
user_data = DEC_PTR(user_data);
codeloc = DEC_PTR(codeloc);
var abi = CIF__ABI(cif);
var nargs = CIF__NARGS(cif);
var nfixedargs = CIF__NFIXEDARGS(cif);
var arg_types_ptr = DEC_PTR(CIF__ARGTYPES(cif));
var arg_types_ptr = CIF__ARGTYPES(cif);
var rtype_unboxed = unbox_small_structs(CIF__RTYPE(cif));
var rtype_ptr = rtype_unboxed[0];
var rtype_id = rtype_unboxed[1];
@ -556,7 +461,7 @@ ffi_prep_closure_loc_js,
case FFI_TYPE_STRUCT:
case FFI_TYPE_LONGDOUBLE:
// Return via a first pointer argument.
sig = 'v' + PTR_SIG;
sig = 'vi';
ret_by_arg = true;
break;
case FFI_TYPE_INT:
@ -566,6 +471,7 @@ ffi_prep_closure_loc_js,
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_POINTER:
sig = 'i';
break;
case FFI_TYPE_FLOAT:
@ -578,9 +484,6 @@ ffi_prep_closure_loc_js,
case FFI_TYPE_SINT64:
sig = 'j';
break;
case FFI_TYPE_POINTER:
sig = PTR_SIG;
break;
case FFI_TYPE_COMPLEX:
throw new Error('complex ret marshalling nyi');
default:
@ -589,11 +492,11 @@ ffi_prep_closure_loc_js,
var unboxed_arg_type_id_list = [];
var unboxed_arg_type_info_list = [];
for (var i = 0; i < nargs; i++) {
var arg_unboxed = unbox_small_structs(DEREF_PTR(arg_types_ptr, i));
var arg_unboxed = unbox_small_structs(DEREF_U32(arg_types_ptr, i));
var arg_type_ptr = arg_unboxed[0];
var arg_type_id = arg_unboxed[1];
unboxed_arg_type_id_list.push(arg_type_id);
unboxed_arg_type_info_list.push([DEC_PTR(FFI_TYPE__SIZE(arg_type_ptr)), FFI_TYPE__ALIGN(arg_type_ptr)]);
unboxed_arg_type_info_list.push([FFI_TYPE__SIZE(arg_type_ptr), FFI_TYPE__ALIGN(arg_type_ptr)]);
}
for (var i = 0; i < nfixedargs; i++) {
switch (unboxed_arg_type_id_list[i]) {
@ -604,6 +507,8 @@ ffi_prep_closure_loc_js,
case FFI_TYPE_SINT16:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_POINTER:
case FFI_TYPE_STRUCT:
sig += 'i';
break;
case FFI_TYPE_FLOAT:
@ -619,10 +524,6 @@ ffi_prep_closure_loc_js,
case FFI_TYPE_SINT64:
sig += 'j';
break;
case FFI_TYPE_STRUCT:
case FFI_TYPE_POINTER:
sig += PTR_SIG;
break;
case FFI_TYPE_COMPLEX:
throw new Error('complex marshalling nyi');
default:
@ -631,7 +532,7 @@ ffi_prep_closure_loc_js,
}
if (nfixedargs < nargs) {
// extra pointer to varargs stack
sig += PTR_SIG;
sig += 'i';
}
LOG_DEBUG("CREATE_CLOSURE", "sig:", sig);
function trampoline() {
@ -650,7 +551,7 @@ ffi_prep_closure_loc_js,
STACK_ALLOC(cur_ptr, 8, 8);
ret_ptr = cur_ptr;
}
cur_ptr -= __SIZEOF_POINTER__ * nargs;
cur_ptr -= 4 * nargs;
var args_ptr = cur_ptr;
var carg_idx = 0;
// Here we either have the actual argument, or a pair of BigInts for long
@ -671,62 +572,58 @@ ffi_prep_closure_loc_js,
case FFI_TYPE_SINT8:
// Bad things happen if we don't align to 4 here
STACK_ALLOC(cur_ptr, 1, 4);
DEREF_PTR(args_ptr, carg_idx) = ENC_PTR(cur_ptr);
DEREF_U32(args_ptr, carg_idx) = cur_ptr;
DEREF_U8(cur_ptr, 0) = cur_arg;
break;
case FFI_TYPE_UINT16:
case FFI_TYPE_SINT16:
// Bad things happen if we don't align to 4 here
STACK_ALLOC(cur_ptr, 2, 4);
DEREF_PTR(args_ptr, carg_idx) = ENC_PTR(cur_ptr);
DEREF_U32(args_ptr, carg_idx) = cur_ptr;
DEREF_U16(cur_ptr, 0) = cur_arg;
break;
case FFI_TYPE_INT:
case FFI_TYPE_UINT32:
case FFI_TYPE_SINT32:
case FFI_TYPE_POINTER:
STACK_ALLOC(cur_ptr, 4, 4);
DEREF_PTR(args_ptr, carg_idx) = ENC_PTR(cur_ptr);
DEREF_U32(args_ptr, carg_idx) = cur_ptr;
DEREF_U32(cur_ptr, 0) = cur_arg;
break;
case FFI_TYPE_STRUCT:
// cur_arg is already a pointer to struct
// copy it onto stack to pass by value
STACK_ALLOC(cur_ptr, arg_size, arg_align);
HEAP8.subarray(cur_ptr, cur_ptr + arg_size).set(HEAP8.subarray(DEC_PTR(cur_arg), DEC_PTR(cur_arg) + arg_size));
DEREF_PTR(args_ptr, carg_idx) = ENC_PTR(cur_ptr);
HEAP8.subarray(cur_ptr, cur_ptr + arg_size).set(HEAP8.subarray(cur_arg, cur_arg + arg_size));
DEREF_U32(args_ptr, carg_idx) = cur_ptr;
break;
case FFI_TYPE_FLOAT:
STACK_ALLOC(cur_ptr, 4, 4);
DEREF_PTR(args_ptr, carg_idx) = ENC_PTR(cur_ptr);
DEREF_U32(args_ptr, carg_idx) = cur_ptr;
DEREF_F32(cur_ptr, 0) = cur_arg;
break;
case FFI_TYPE_DOUBLE:
STACK_ALLOC(cur_ptr, 8, 8);
DEREF_PTR(args_ptr, carg_idx) = ENC_PTR(cur_ptr);
DEREF_U32(args_ptr, carg_idx) = cur_ptr;
DEREF_F64(cur_ptr, 0) = cur_arg;
break;
case FFI_TYPE_UINT64:
case FFI_TYPE_SINT64:
STACK_ALLOC(cur_ptr, 8, 8);
DEREF_PTR(args_ptr, carg_idx) = ENC_PTR(cur_ptr);
DEREF_U32(args_ptr, carg_idx) = cur_ptr;
DEREF_U64(cur_ptr, 0) = cur_arg;
break;
case FFI_TYPE_LONGDOUBLE:
STACK_ALLOC(cur_ptr, 16, 8);
DEREF_PTR(args_ptr, carg_idx) = ENC_PTR(cur_ptr);
DEREF_U32(args_ptr, carg_idx) = cur_ptr;
DEREF_U64(cur_ptr, 0) = cur_arg;
cur_arg = args[jsarg_idx++];
DEREF_U64(cur_ptr, 1) = cur_arg;
break;
case FFI_TYPE_POINTER:
STACK_ALLOC(cur_ptr, __SIZEOF_POINTER__, __SIZEOF_POINTER__);
DEREF_PTR(args_ptr, carg_idx) = ENC_PTR(cur_ptr);
DEREF_PTR(cur_ptr, 0) = cur_arg;
break;
}
}
// If its a varargs call, last js argument is a pointer to the varargs.
var varargs = DEC_PTR(args[args.length - 1]);
var varargs = args[args.length - 1];
// We have no way of knowing how many varargs were actually provided, this
// fills the rest of the stack space allocated with nonsense. The onward
// call will know to ignore the nonsense.
@ -742,20 +639,20 @@ ffi_prep_closure_loc_js,
if (arg_type_id === FFI_TYPE_STRUCT) {
// In this case varargs is a pointer to pointer to struct so we need to
// deref once
var struct_ptr = DEREF_PTR_NUMBER(varargs, 0);
var struct_ptr = DEREF_U32(varargs, 0);
STACK_ALLOC(cur_ptr, arg_size, arg_align);
HEAP8.subarray(cur_ptr, cur_ptr + arg_size).set(HEAP8.subarray(struct_ptr, struct_ptr + arg_size));
DEREF_PTR(args_ptr, carg_idx) = ENC_PTR(cur_ptr);
DEREF_U32(args_ptr, carg_idx) = cur_ptr;
} else {
DEREF_PTR(args_ptr, carg_idx) = ENC_PTR(varargs);
DEREF_U32(args_ptr, carg_idx) = varargs;
}
varargs += __SIZEOF_POINTER__;
varargs += 4;
}
stackRestore(cur_ptr);
stackAlloc(0); // stackAlloc enforces alignment invariants on the stack pointer
LOG_DEBUG("CALL_CLOSURE", "closure:", closure, "fptr", CLOSURE__fun(closure), "cif", CLOSURE__cif(closure));
getWasmTableEntry(CLOSURE__fun(closure))(
CLOSURE__cif(closure), ENC_PTR(ret_ptr), ENC_PTR(args_ptr),
CLOSURE__cif(closure), ret_ptr, args_ptr,
CLOSURE__user_data(closure)
);
stackRestore(orig_stack_ptr);
@ -780,9 +677,9 @@ ffi_prep_closure_loc_js,
return FFI_BAD_TYPEDEF_MACRO;
}
setWasmTableEntry(codeloc, wasm_trampoline);
CLOSURE__cif(closure) = ENC_PTR(cif);
CLOSURE__fun(closure) = ENC_PTR(fun);
CLOSURE__user_data(closure) = ENC_PTR(user_data);
CLOSURE__cif(closure) = cif;
CLOSURE__fun(closure) = fun;
CLOSURE__user_data(closure) = user_data;
return FFI_OK_MACRO;
})
@ -791,7 +688,7 @@ ffi_prep_closure_loc_js,
ffi_status ffi_prep_closure_loc(ffi_closure *closure, ffi_cif *cif,
void (*fun)(ffi_cif *, void *, void **, void *),
void *user_data, void *codeloc) {
if (cif->abi != FFI_EMSCRIPTEN_ABI)
if (cif->abi != FFI_WASM32_EMSCRIPTEN)
return FFI_BAD_ABI;
return ffi_prep_closure_loc_js(closure, cif, (void *)fun, user_data,
codeloc);

View File

@ -42,31 +42,14 @@ typedef void (*ffi_fp)(void);
typedef enum ffi_abi {
FFI_FIRST_ABI = 0,
#if __SIZEOF_POINTER__ == 4
FFI_WASM32, // "raw", no structures, varargs, or closures (not implemented!)
FFI_WASM32_EMSCRIPTEN, // structures, varargs, and split 64-bit params
#elif __SIZEOF_POINTER__ == 8
FFI_WASM64,
FFI_WASM64_EMSCRIPTEN,
#else
#error "Unknown pointer size"
#endif
FFI_LAST_ABI,
#if __SIZEOF_POINTER__ == 4
#ifdef __EMSCRIPTEN__
FFI_DEFAULT_ABI = FFI_WASM32_EMSCRIPTEN
#else
FFI_DEFAULT_ABI = FFI_WASM32
#endif
#elif __SIZEOF_POINTER__ == 8
#ifdef __EMSCRIPTEN__
FFI_DEFAULT_ABI = FFI_WASM64_EMSCRIPTEN
#else
FFI_DEFAULT_ABI = FFI_WASM64
#endif
#else
#error "Unknown pointer size"
#endif
} ffi_abi;
#define FFI_CLOSURES 1

View File

@ -41,6 +41,9 @@
#if defined (X86_64) && defined (__i386__)
#undef X86_64
#warning ******************************************************
#warning ********** X86 IS DEFINED ****************************
#warning ******************************************************
#define X86
#endif

View File

@ -458,7 +458,9 @@ L(UW24):
L(UW25):
# cfi_def_cfa_offset(closure_FS + 4)
FFI_CLOSURE_SAVE_REGS
movl closure_FS-4(%esp), %eax /* load closure */
movl closure_FS-4(%esp), %ecx /* load retaddr */
movl closure_FS(%esp), %eax /* load closure */
movl %ecx, closure_FS(%esp) /* move retaddr */
jmp L(do_closure_REGISTER)
L(UW26):
# cfi_endproc

View File

@ -394,7 +394,9 @@ L(UW24):
L(UW25):
/* cfi_def_cfa_offset(closure_FS + 4) */
FFI_CLOSURE_SAVE_REGS
mov eax, [esp+closure_FS-4] /* load closure */
mov ecx, [esp+closure_FS-4] /* load retaddr */
mov eax, [esp+closure_FS] /* load closure */
mov [esp+closure_FS], ecx /* move retaddr */
jmp L(do_closure_REGISTER)
L(UW26):
/* cfi_endproc */

View File

@ -36,11 +36,11 @@ export PKG_CONFIG_PATH="$TARGET/lib/pkgconfig"
export EM_PKG_CONFIG_PATH="$PKG_CONFIG_PATH"
# Specific variables for cross-compilation
export CHOST="${TARGET_HOST}-unknown-linux" # wasm32-unknown-emscripten
export CHOST="wasm32-unknown-linux" # wasm32-unknown-emscripten
autoreconf -fiv
emconfigure ./configure --host=$CHOST --prefix="$TARGET" --enable-static --disable-shared --disable-dependency-tracking \
--disable-builddir --disable-multi-os-directory --disable-raw-api --disable-docs ${EXTRA_CONFIGURE_FLAGS}
--disable-builddir --disable-multi-os-directory --disable-raw-api --disable-docs
make install
cp fficonfig.h target/include/
cp include/ffi_common.h target/include/

View File

@ -8,16 +8,16 @@ fi
# Common compiler flags
export CFLAGS="-fPIC $EXTRA_CFLAGS"
export CXXFLAGS="$CFLAGS -sNO_DISABLE_EXCEPTION_CATCHING $EXTRA_CXXFLAGS"
export LDFLAGS="-sEXPORTED_FUNCTIONS=_main,_malloc,_free -sALLOW_TABLE_GROWTH -sASSERTIONS -sNO_DISABLE_EXCEPTION_CATCHING -sWASM_BIGINT -Wno-main"
export LDFLAGS="-sEXPORTED_FUNCTIONS=_main,_malloc,_free -sALLOW_TABLE_GROWTH -sASSERTIONS -sNO_DISABLE_EXCEPTION_CATCHING -sWASM_BIGINT"
# Specific variables for cross-compilation
export CHOST="${TARGET_HOST}-unknown-linux" # wasm32-unknown-emscripten
export CHOST="wasm32-unknown-linux" # wasm32-unknown-emscripten
autoreconf -fiv
emconfigure ./configure --prefix="$(pwd)/target" --host=$CHOST --enable-static --disable-shared \
--disable-builddir --disable-multi-os-directory --disable-raw-api --disable-docs ${EXTRA_CONFIGURE_FLAGS} ||
--disable-builddir --disable-multi-os-directory --disable-raw-api --disable-docs ||
(cat config.log && exit 1)
make
EMMAKEN_JUST_CONFIGURE=1 emmake make check \
RUNTESTFLAGS="LDFLAGS_FOR_TARGET='$LDFLAGS $EXTRA_TEST_LDFLAGS'" || (cat testsuite/libffi.log && exit 1)
RUNTESTFLAGS="LDFLAGS_FOR_TARGET='$LDFLAGS'" || (cat testsuite/libffi.log && exit 1)

View File

@ -407,10 +407,6 @@ proc libffi_target_compile { source dest type options } {
lappend options "libs= -lpthread"
}
if { [string match "*-*-freebsd*" $target_triplet] } {
lappend options "libs= -lpthread"
}
lappend options "libs= -lffi"
if { [string match "aarch64*-*-linux*" $target_triplet] } {

View File

@ -28,7 +28,7 @@ closure_test_gn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__,
closure_test_fn(*(Dbls*)args[0]);
}
int main(void)
int main(int argc __UNUSED__, char** argv __UNUSED__)
{
ffi_cif cif;

View File

@ -216,7 +216,8 @@ cls_large_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata __
ui8_5, si8_5);
}
int main (void)
int
main(int argc __UNUSED__, const char** argv __UNUSED__)
{
void *code;
ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code);

View File

@ -8,7 +8,7 @@
#define NUM_THREADS 20
#if defined(_POSIX_BARRIERS) && _POSIX_BARRIERS > 0
#ifdef _POSIX_BARRIERS
pthread_barrier_t barrier;
#endif
@ -21,7 +21,7 @@ void callback(ffi_cif *cif __UNUSED__, void *ret, void **args, void *userdata __
}
void *thread_func(void *arg) {
#if defined(_POSIX_BARRIERS) && _POSIX_BARRIERS > 0
#ifdef _POSIX_BARRIERS
pthread_barrier_wait(&barrier);
#endif
@ -50,7 +50,7 @@ void *thread_func(void *arg) {
int main() {
pthread_t threads[NUM_THREADS];
#if defined(_POSIX_BARRIERS) && _POSIX_BARRIERS > 0
#ifdef _POSIX_BARRIERS
pthread_barrier_init(&barrier, NULL, NUM_THREADS);
#endif
@ -65,7 +65,7 @@ int main() {
pthread_join(threads[i], NULL);
}
#if defined(_POSIX_BARRIERS) && _POSIX_BARRIERS > 0
#ifdef _POSIX_BARRIERS
pthread_barrier_destroy(&barrier);
#endif