diff --git a/native/libffi/.appveyor.yml b/native/libffi/.appveyor.yml new file mode 100644 index 0000000000..ece8a948c9 --- /dev/null +++ b/native/libffi/.appveyor.yml @@ -0,0 +1,66 @@ +shallow_clone: true + +# We're currently only testing libffi built with Microsoft's +# tools. +# This matrix should be expanded to include at least: +# 32- and 64-bit gcc/cygwin +# 32- and 64-bit gcc/mingw +# 32- and 64-bit clang/mingw +# and perhaps more. + +image: Visual Studio 2017 +platform: + - x64 + - x86 + - arm + - arm64 + +environment: + global: + CYG_ROOT: C:/cygwin + CYG_CACHE: C:/cygwin/var/cache/setup + CYG_MIRROR: http://mirrors.kernel.org/sourceware/cygwin/ + matrix: + - VSVER: 15 + +install: + - ps: >- + If ($env:Platform -Match "x86") { + $env:VCVARS_PLATFORM="x86" + $env:BUILD="i686-pc-cygwin" + $env:HOST="i686-pc-cygwin" + $env:MSVCC="/cygdrive/c/projects/libffi/msvcc.sh" + $env:SRC_ARCHITECTURE="x86" + } ElseIf ($env:Platform -Match "arm64") { + $env:VCVARS_PLATFORM="x86_arm64" + $env:BUILD="i686-pc-cygwin" + $env:HOST="aarch64-w64-cygwin" + $env:MSVCC="/cygdrive/c/projects/libffi/msvcc.sh -marm64" + $env:SRC_ARCHITECTURE="aarch64" + } ElseIf ($env:Platform -Match "arm") { + $env:VCVARS_PLATFORM="x86_arm" + $env:BUILD="i686-pc-cygwin" + $env:HOST="arm-w32-cygwin" + $env:MSVCC="/cygdrive/c/projects/libffi/msvcc.sh -marm" + $env:SRC_ARCHITECTURE="arm" + } Else { + $env:VCVARS_PLATFORM="amd64" + $env:BUILD="x86_64-w64-cygwin" + $env:HOST="x86_64-w64-cygwin" + $env:MSVCC="/cygdrive/c/projects/libffi/msvcc.sh -m64" + $env:SRC_ARCHITECTURE="x86" + } + - 'appveyor DownloadFile https://cygwin.com/setup-x86.exe -FileName setup.exe' + - 'setup.exe -qnNdO -R "%CYG_ROOT%" -s "%CYG_MIRROR%" -l "%CYG_CACHE%" -P dejagnu >NUL' + - '%CYG_ROOT%/bin/bash -lc "cygcheck -dc cygwin"' + - echo call VsDevCmd to set VS150COMNTOOLS + - call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\Tools\VsDevCmd.bat" + - ps: $env:VSCOMNTOOLS=(Get-Content ("env:VS" + "$env:VSVER" + "0COMNTOOLS")) + - echo "Using Visual Studio %VSVER%.0 at %VSCOMNTOOLS%" + - call "%VSCOMNTOOLS%..\..\vc\Auxiliary\Build\vcvarsall.bat" %VCVARS_PLATFORM% + +build_script: + - c:\cygwin\bin\sh -lc "(cd $OLDPWD; ./autogen.sh;)" + - c:\cygwin\bin\sh -lc "(cd $OLDPWD; ./configure CC='%MSVCC%' CXX='%MSVCC%' LD='link' CPP='cl -nologo -EP' CXXCPP='cl -nologo -EP' CPPFLAGS='-DFFI_BUILDING_DLL' AR='/cygdrive/c/projects/libffi/.travis/ar-lib lib' NM='dumpbin -symbols' STRIP=':' --build=$BUILD --host=$HOST;)" + - c:\cygwin\bin\sh -lc "(cd $OLDPWD; cp src/%SRC_ARCHITECTURE%/ffitarget.h include; make; find .;)" + - c:\cygwin\bin\sh -lc "(cd $OLDPWD; cp `find . -name 'libffi-?.dll'` $HOST/testsuite/; make check; cat `find ./ -name libffi.log`)" diff --git a/native/libffi/.gitattributes b/native/libffi/.gitattributes new file mode 100644 index 0000000000..f7d3833e78 --- /dev/null +++ b/native/libffi/.gitattributes @@ -0,0 +1,4 @@ +* text=auto + +*.sln text eol=crlf +*.vcxproj* text eol=crlf diff --git a/native/libffi/.github/issue_template.md b/native/libffi/.github/issue_template.md new file mode 100644 index 0000000000..e197e2cea7 --- /dev/null +++ b/native/libffi/.github/issue_template.md @@ -0,0 +1,10 @@ +## System Details + + + + +## Problems Description + + + + diff --git a/native/libffi/.gitignore b/native/libffi/.gitignore index 1158ecef28..0f90100eaa 100644 --- a/native/libffi/.gitignore +++ b/native/libffi/.gitignore @@ -5,10 +5,11 @@ .dirstamp *.la Makefile +!testsuite/libffi.bhaible/Makefile Makefile.in aclocal.m4 compile -config.* +!.travis/compile configure depcomp doc/libffi.info @@ -33,3 +34,5 @@ libffi.xcodeproj/xcuserdata libffi.xcodeproj/project.xcworkspace build_*/ darwin_*/ +src/arm/trampoline.S +**/texinfo.tex \ No newline at end of file diff --git a/native/libffi/.travis.yml b/native/libffi/.travis.yml index 6c14fcd0b0..e0a69fa778 100644 --- a/native/libffi/.travis.yml +++ b/native/libffi/.travis.yml @@ -1,22 +1,83 @@ +--- +sudo: required + language: cpp -compiler: - - gcc - - clang -env: - - - - HOST=i386-pc-linux-gnu + +# For qemu-powered targets, get the list of supported processors from +# travis by setting QEMU_CPU=help, then set -mcpu= for the compilers +# accordingly. + matrix: - exclude: - - compiler: clang - env: HOST=i386-pc-linux-gnu + include: + - os: linux + env: HOST=powerpc-eabisim RUNTESTFLAGS="--target_board powerpc-eabisim" DEJAGNU="/opt/.travis/site.exp" + - os: linux + env: HOST=or1k-elf RUNTESTFLAGS="--target_board or1k-sim" DEJAGNU="/opt/.travis/site.exp" + - os: linux + env: HOST=m32r-elf RUNTESTFLAGS="--target_board m32r-sim" DEJAGNU="/opt/.travis/site.exp" + - os: linux + env: HOST=bfin-elf RUNTESTFLAGS="--target_board bfin-sim" DEJAGNU="/opt/.travis/site.exp" +# This configuration is still using the native x86 toolchain? +# - os: osx +# env: HOST=aarch64-apple-darwin13 + - os: osx + env: HOST=x86_64-apple-darwin10 + - os: linux + env: HOST=x86_64-w64-mingw32 MEVAL='export CC="x86_64-w64-mingw32-gcc" && CXX="x86_64-w64-mingw32-g++" RUNTESTFLAGS="--target_board wine-sim" DEJAGNU="$TRAVIS_BUILD_DIR/.travis/site.exp" CONFIGURE_OPTIONS=--disable-shared LIBFFI_TEST_OPTIMIZATION="-O2" + - os: linux + env: HOST=sh4-linux-gnu CONFIGURE_OPTIONS=--disable-shared QEMU_LD_PREFIX=/usr/sh4-linux-gnu + - os: linux + env: HOST=alpha-linux-gnu CONFIGURE_OPTIONS=--disable-shared QEMU_LD_PREFIX=/usr/alpha-linux-gnu + - os: linux + env: HOST=m68k-linux-gnu MEVAL='export CC="m68k-linux-gnu-gcc-8 -mcpu=547x" && CXX="m68k-linux-gnu-g++-8 -mcpu=547x"' CONFIGURE_OPTIONS=--disable-shared QEMU_LD_PREFIX=/usr/m68k-linux-gnu QEMU_CPU=cfv4e + - os: linux + arch: s390x + env: HOST=s390x-linux-gnu + - os: linux + arch: ppc64le + env: HOST=ppc64le-linux-gnu + - os: linux + arch: arm64 + env: HOST=aarch64-linux-gnu + - os: linux + arch: arm64 + env: HOST=aarch64-linux-gnu + compiler: clang + - os: linux + env: HOST=arm32v7-linux-gnu LIBFFI_TEST_OPTIMIZATION="-O0" + - os: linux + env: HOST=arm32v7-linux-gnu LIBFFI_TEST_OPTIMIZATION="-O2" + - os: linux + env: HOST=arm32v7-linux-gnu LIBFFI_TEST_OPTIMIZATION="-O2 -fomit-frame-pointer" +# The sparc64 linux system in the GCC compile farm is non-responsive. +# - os: linux +# env: HOST=sparc64-linux-gnu +# The mips64 linux system in the GCC compile farm is not allowing logins +# - os: linux +# env: HOST=mips64el-linux-gnu + - os: linux + compiler: gcc + env: HOST=i386-pc-linux-gnu MEVAL='export CC="$CC -m32" && CXX="$CXX -m32"' + - os: linux + compiler: gcc + - os: linux + compiler: gcc + env: CONFIGURE_OPTIONS=--disable-shared + - os: linux + compiler: clang + - os: linux + compiler: clang + env: CONFIGURE_OPTIONS=--disable-shared + - os: linux + env: HOST=moxie-elf MEVAL='export PATH=/opt/moxielogic/bin:$PATH && CC=moxie-elf-gcc && CXX=moxie-elf-g++' LDFLAGS=-Tsim.ld RUNTESTFLAGS="--target_board moxie-sim" DEJAGNU="$TRAVIS_BUILD_DIR/.travis/site.exp" + +before_install: + - if test x"$MEVAL" != x; then eval ${MEVAL}; fi -before_script: - - sudo apt-get install dejagnu texinfo - - if [ "$HOST" = i386-pc-linux-gnu ] ; then sudo apt-get install gcc-multilib g++-multilib && CC="$CC -m32" && CXX="$CXX -m32" ; fi +install: + - travis_wait 30 ./.travis/install.sh script: - - ./autogen.sh - - ./configure ${HOST+--host=$HOST} - - make - - make dist - - make check + - if ! test x"$MEVAL" = x; then eval ${MEVAL}; fi + - travis_wait 115 sleep infinity & + - ./.travis/build.sh \ No newline at end of file diff --git a/native/libffi/.travis/ar-lib b/native/libffi/.travis/ar-lib new file mode 100755 index 0000000000..0baa4f6076 --- /dev/null +++ b/native/libffi/.travis/ar-lib @@ -0,0 +1,270 @@ +#! /bin/sh +# Wrapper for Microsoft lib.exe + +me=ar-lib +scriptversion=2012-03-01.08; # UTC + +# Copyright (C) 2010-2018 Free Software Foundation, Inc. +# Written by Peter Rosin . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + + +# func_error message +func_error () +{ + echo "$me: $1" 1>&2 + exit 1 +} + +file_conv= + +# func_file_conv build_file +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv in + mingw) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_at_file at_file operation archive +# Iterate over all members in AT_FILE performing OPERATION on ARCHIVE +# for each of them. +# When interpreting the content of the @FILE, do NOT use func_file_conv, +# since the user would need to supply preconverted file names to +# binutils ar, at least for MinGW. +func_at_file () +{ + operation=$2 + archive=$3 + at_file_contents=`cat "$1"` + eval set x "$at_file_contents" + shift + + for member + do + $AR -NOLOGO $operation:"$member" "$archive" || exit $? + done +} + +case $1 in + '') + func_error "no command. Try '$0 --help' for more information." + ;; + -h | --h*) + cat < libffi.log + + ./rlgl l --key=${RLGL_KEY} https://rl.gl + ID=$(./rlgl start) + ./rlgl e --id=$ID --policy=https://github.com/libffi/rlgl-policy.git libffi.log + exit $? +} + +function build_linux() +{ + ./autogen.sh + ./configure ${HOST+--host=$HOST} ${CONFIGURE_OPTIONS} || cat */config.log + make + make dist + make check RUNTESTFLAGS="-a $RUNTESTFLAGS" + + ./rlgl l --key=${RLGL_KEY} https://rl.gl + ID=$(./rlgl start) + ./rlgl e --id=$ID --policy=https://github.com/libffi/rlgl-policy.git */testsuite/libffi.log + exit $? +} + +function build_foreign_linux() +{ + ${DOCKER} run --rm -t -i -v $(pwd):/opt ${SET_QEMU_CPU} -e LIBFFI_TEST_OPTIMIZATION="${LIBFFI_TEST_OPTIMIZATION}" $2 bash -c /opt/.travis/build-in-container.sh + + ./rlgl l --key=${RLGL_KEY} https://rl.gl + ID=$(./rlgl start) + ./rlgl e --id=$ID --policy=https://github.com/libffi/rlgl-policy.git */testsuite/libffi.log + exit $? +} + +function build_cross_linux() +{ + ${DOCKER} run --rm -t -i -v $(pwd):/opt ${SET_QEMU_CPU} -e HOST="${HOST}" -e CC="${HOST}-gcc-8 ${GCC_OPTIONS}" -e CXX="${HOST}-g++-8 ${GCC_OPTIONS}" -e LIBFFI_TEST_OPTIMIZATION="${LIBFFI_TEST_OPTIMIZATION}" moxielogic/cross-ci-build-container:latest bash -c /opt/.travis/build-in-container.sh + + ./rlgl l --key=${RLGL_KEY} https://rl.gl + ID=$(./rlgl start) + ./rlgl e --id=$ID --policy=https://github.com/libffi/rlgl-policy.git */testsuite/libffi.log + exit $? +} + +function build_cross() +{ + ${DOCKER} pull quay.io/moxielogic/libffi-ci-${HOST} + ${DOCKER} run --rm -t -i -v $(pwd):/opt -e HOST="${HOST}" -e CC="${HOST}-gcc ${GCC_OPTIONS}" -e CXX="${HOST}-g++ ${GCC_OPTIONS}" -e TRAVIS_BUILD_DIR=/opt -e DEJAGNU="${DEJAGNU}" -e RUNTESTFLAGS="${RUNTESTFLAGS}" -e LIBFFI_TEST_OPTIMIZATION="${LIBFFI_TEST_OPTIMIZATION}" quay.io/moxielogic/libffi-ci-${HOST} bash -c /opt/.travis/build-cross-in-container.sh + + ./rlgl l --key=${RLGL_KEY} https://rl.gl + ID=$(./rlgl start) + ./rlgl e --id=$ID --policy=https://github.com/libffi/rlgl-policy.git */testsuite/libffi.log + exit $? +} + +function build_ios() +{ + which python +# export PYTHON_BIN=/usr/local/bin/python + ./generate-darwin-source-and-headers.py --only-ios + xcodebuild -showsdks + xcodebuild -project libffi.xcodeproj -target "libffi-iOS" -configuration Release -sdk iphoneos11.4 + exit $? +} + +function build_macosx() +{ + which python +# export PYTHON_BIN=/usr/local/bin/python + ./generate-darwin-source-and-headers.py --only-osx + xcodebuild -showsdks + xcodebuild -project libffi.xcodeproj -target "libffi-Mac" -configuration Release -sdk macosx10.13 + echo "Finished build" + exit $? +} + +case "$HOST" in + arm-apple-darwin*) + ./autogen.sh + build_ios + ;; + x86_64-apple-darwin*) + ./autogen.sh + build_macosx + ;; + arm32v7-linux-gnu) + ./autogen.sh + build_foreign_linux arm moxielogic/arm32v7-ci-build-container:latest + ;; + mips64el-linux-gnu | sparc64-linux-gnu) + build_cfarm + ;; + bfin-elf ) + ./autogen.sh + GCC_OPTIONS=-msim build_cross + ;; + m32r-elf ) + ./autogen.sh + build_cross + ;; + or1k-elf ) + ./autogen.sh + build_cross + ;; + powerpc-eabisim ) + ./autogen.sh + build_cross + ;; + m68k-linux-gnu ) + ./autogen.sh + GCC_OPTIONS=-mcpu=547x build_cross_linux + ;; + alpha-linux-gnu | sh4-linux-gnu ) + ./autogen.sh + build_cross_linux + ;; + *) + ./autogen.sh + build_linux + ;; +esac diff --git a/native/libffi/.travis/compile b/native/libffi/.travis/compile new file mode 100755 index 0000000000..655932a224 --- /dev/null +++ b/native/libffi/.travis/compile @@ -0,0 +1,351 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2018-03-27.18; # UTC + +# Copyright (C) 1999-2018 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -warn) + eat=1 + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ + icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/native/libffi/.travis/install.sh b/native/libffi/.travis/install.sh new file mode 100755 index 0000000000..2420245710 --- /dev/null +++ b/native/libffi/.travis/install.sh @@ -0,0 +1,71 @@ +#!/bin/bash +set -x + +if [[ $TRAVIS_OS_NAME != 'linux' ]]; then + brew update > brew-update.log 2>&1 + # fix an issue with libtool on travis by reinstalling it + brew uninstall libtool; + brew install libtool dejagnu; + + # Download and extract the rlgl client + wget -qO - https://rl.gl/cli/rlgl-darwin-amd64.tgz | \ + tar --strip-components=2 -xvzf - ./rlgl/rlgl; + +else + # Download and extract the rlgl client + case $HOST in + aarch64-linux-gnu) + wget -qO - https://rl.gl/cli/rlgl-linux-arm.tgz | \ + tar --strip-components=2 -xvzf - ./rlgl/rlgl; + ;; + ppc64le-linux-gnu) + wget -qO - https://rl.gl/cli/rlgl-linux-ppc64le.tgz | \ + tar --strip-components=2 -xvzf - ./rlgl/rlgl; + ;; + s390x-linux-gnu) + wget -qO - https://rl.gl/cli/rlgl-linux-s390x.tgz | \ + tar --strip-components=2 -xvzf - ./rlgl/rlgl; + ;; + *) + wget -qO - https://rl.gl/cli/rlgl-linux-amd64.tgz | \ + tar --strip-components=2 -xvzf - ./rlgl/rlgl; + ;; + esac + + sudo apt-get clean # clear the cache + sudo apt-get update + case $HOST in + mips64el-linux-gnu | sparc64-linux-gnu) + ;; + alpha-linux-gnu | arm32v7-linux-gnu | m68k-linux-gnu | sh4-linux-gnu) + sudo apt-get install qemu-user-static + ;; + hppa-linux-gnu ) + sudo apt-get install -y qemu-user-static g++-5-hppa-linux-gnu + ;; + i386-pc-linux-gnu) + sudo apt-get install gcc-multilib g++-multilib; + ;; + moxie-elf) + echo 'deb https://repos.moxielogic.org:7114/MoxieLogic moxiedev main' | sudo tee -a /etc/apt/sources.list + sudo apt-get clean # clear the cache + sudo apt-get update ## -qq + sudo apt-get update + sudo apt-get install -y --allow-unauthenticated moxielogic-moxie-elf-gcc moxielogic-moxie-elf-gcc-c++ moxielogic-moxie-elf-gcc-libstdc++ moxielogic-moxie-elf-gdb-sim + ;; + x86_64-w64-mingw32) + sudo apt-get install gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 wine; + ;; + i686-w32-mingw32) + sudo apt-get install gcc-mingw-w64-i686 g++-mingw-w64-i686 wine; + ;; + esac + case $HOST in + arm32v7-linux-gnu) + # don't install host tools + ;; + *) + sudo apt-get install dejagnu texinfo sharutils + ;; + esac +fi diff --git a/native/libffi/.travis/m32r-sim.exp b/native/libffi/.travis/m32r-sim.exp new file mode 100644 index 0000000000..c18123f28f --- /dev/null +++ b/native/libffi/.travis/m32r-sim.exp @@ -0,0 +1,58 @@ +# Copyright (C) 2010, 2019 Free Software Foundation, Inc. +# +# This file is part of DejaGnu. +# +# DejaGnu is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# DejaGnu is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with DejaGnu; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, MA 02110, USA. + +# This is a list of toolchains that are supported on this board. +set_board_info target_install {m32r-elf} + +# Load the generic configuration for this board. This will define a basic set +# of routines needed by the tool to communicate with the board. +load_generic_config "sim" + +# basic-sim.exp is a basic description for the standard Cygnus simulator. +load_base_board_description "basic-sim" + +# "m32r" is the name of the sim subdir in devo/sim. +setup_sim m32r + +# No multilib options needed by default. +process_multilib_options "" + +# We only support newlib on this target. We assume that all multilib +# options have been specified before we get here. + +set_board_info compiler "[find_gcc]" +set_board_info cflags "[libgloss_include_flags] [newlib_include_flags]" +set_board_info ldflags "[libgloss_link_flags] [newlib_link_flags]" + +# Configuration settings for testsuites +set_board_info noargs 1 +set_board_info gdb,nosignals 1 +set_board_info gdb,noresults 1 +set_board_info gdb,cannot_call_functions 1 +set_board_info gdb,skip_float_tests 1 +set_board_info gdb,can_reverse 1 +set_board_info gdb,use_precord 1 + +# More time is needed +set_board_info gcc,timeout 800 +set_board_info gdb,timeout 60 + +# Used by a few gcc.c-torture testcases to delimit how large the stack can +# be. +set_board_info gcc,stack_size 5000 + diff --git a/native/libffi/.travis/moxie-sim.exp b/native/libffi/.travis/moxie-sim.exp new file mode 100644 index 0000000000..32979ea6be --- /dev/null +++ b/native/libffi/.travis/moxie-sim.exp @@ -0,0 +1,60 @@ +# Copyright (C) 2010 Free Software Foundation, Inc. +# +# This file is part of DejaGnu. +# +# DejaGnu is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# DejaGnu is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with DejaGnu; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, MA 02110, USA. + +# This is a list of toolchains that are supported on this board. +set_board_info target_install {moxie-elf} + +# Load the generic configuration for this board. This will define a basic set +# of routines needed by the tool to communicate with the board. +load_generic_config "sim" + +# basic-sim.exp is a basic description for the standard Cygnus simulator. +load_base_board_description "basic-sim" + +# "moxie" is the name of the sim subdir in devo/sim. +setup_sim moxie + +# No multilib options needed by default. +process_multilib_options "" + +# We only support newlib on this target. We assume that all multilib +# options have been specified before we get here. + +set_board_info compiler "[find_gcc]" +set_board_info cflags "[libgloss_include_flags] [newlib_include_flags]" +set_board_info ldflags "[libgloss_link_flags] [newlib_link_flags]" +# No linker script needed. +set_board_info ldscript "-Tsim.ld" + +# Configuration settings for testsuites +set_board_info noargs 1 +set_board_info gdb,nosignals 1 +set_board_info gdb,noresults 1 +set_board_info gdb,cannot_call_functions 1 +set_board_info gdb,skip_float_tests 1 +set_board_info gdb,can_reverse 1 +set_board_info gdb,use_precord 1 + +# More time is needed +set_board_info gcc,timeout 800 +set_board_info gdb,timeout 60 + +# Used by a few gcc.c-torture testcases to delimit how large the stack can +# be. +set_board_info gcc,stack_size 5000 + diff --git a/native/libffi/.travis/or1k-sim.exp b/native/libffi/.travis/or1k-sim.exp new file mode 100644 index 0000000000..3920413ee1 --- /dev/null +++ b/native/libffi/.travis/or1k-sim.exp @@ -0,0 +1,58 @@ +# Copyright (C) 2010, 2019 Free Software Foundation, Inc. +# +# This file is part of DejaGnu. +# +# DejaGnu is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# DejaGnu is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with DejaGnu; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, MA 02110, USA. + +# This is a list of toolchains that are supported on this board. +set_board_info target_install {or1k-elf} + +# Load the generic configuration for this board. This will define a basic set +# of routines needed by the tool to communicate with the board. +load_generic_config "sim" + +# basic-sim.exp is a basic description for the standard Cygnus simulator. +load_base_board_description "basic-sim" + +# "or1k" is the name of the sim subdir in devo/sim. +setup_sim or1k + +# No multilib options needed by default. +process_multilib_options "" + +# We only support newlib on this target. We assume that all multilib +# options have been specified before we get here. + +set_board_info compiler "[find_gcc]" +set_board_info cflags "[libgloss_include_flags] [newlib_include_flags]" +set_board_info ldflags "[libgloss_link_flags] [newlib_link_flags]" + +# Configuration settings for testsuites +set_board_info noargs 1 +set_board_info gdb,nosignals 1 +set_board_info gdb,noresults 1 +set_board_info gdb,cannot_call_functions 1 +set_board_info gdb,skip_float_tests 1 +set_board_info gdb,can_reverse 1 +set_board_info gdb,use_precord 1 + +# More time is needed +set_board_info gcc,timeout 800 +set_board_info gdb,timeout 60 + +# Used by a few gcc.c-torture testcases to delimit how large the stack can +# be. +set_board_info gcc,stack_size 5000 + diff --git a/native/libffi/.travis/powerpc-eabisim.exp b/native/libffi/.travis/powerpc-eabisim.exp new file mode 100644 index 0000000000..285fd4f6fe --- /dev/null +++ b/native/libffi/.travis/powerpc-eabisim.exp @@ -0,0 +1,58 @@ +# Copyright (C) 2010, 2019 Free Software Foundation, Inc. +# +# This file is part of DejaGnu. +# +# DejaGnu is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# DejaGnu is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with DejaGnu; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, MA 02110, USA. + +# This is a list of toolchains that are supported on this board. +set_board_info target_install {powerpc-eabisim} + +# Load the generic configuration for this board. This will define a basic set +# of routines needed by the tool to communicate with the board. +load_generic_config "sim" + +# basic-sim.exp is a basic description for the standard Cygnus simulator. +load_base_board_description "basic-sim" + +# "powerpc" is the name of the sim subdir in devo/sim. +setup_sim powerpc + +# No multilib options needed by default. +process_multilib_options "" + +# We only support newlib on this target. We assume that all multilib +# options have been specified before we get here. + +set_board_info compiler "[find_gcc]" +set_board_info cflags "[libgloss_include_flags] [newlib_include_flags]" +set_board_info ldflags "[libgloss_link_flags] [newlib_link_flags]" + +# Configuration settings for testsuites +set_board_info noargs 1 +set_board_info gdb,nosignals 1 +set_board_info gdb,noresults 1 +set_board_info gdb,cannot_call_functions 1 +set_board_info gdb,skip_float_tests 1 +set_board_info gdb,can_reverse 1 +set_board_info gdb,use_precord 1 + +# More time is needed +set_board_info gcc,timeout 800 +set_board_info gdb,timeout 60 + +# Used by a few gcc.c-torture testcases to delimit how large the stack can +# be. +set_board_info gcc,stack_size 5000 + diff --git a/native/libffi/.travis/site.exp b/native/libffi/.travis/site.exp new file mode 100644 index 0000000000..644ec63185 --- /dev/null +++ b/native/libffi/.travis/site.exp @@ -0,0 +1,27 @@ +# Copyright (C) 2008, 2010, 2018, 2019 Anthony Green + +# Make sure we look in the right place for the board description files. +if ![info exists boards_dir] { + set boards_dir {} +} + +lappend boards_dir $::env(TRAVIS_BUILD_DIR)/.travis + +verbose "Global Config File: target_triplet is $target_triplet" 2 +global target_list + +case "$target_triplet" in { + { "bfin-elf" } { + set target_list "bfin-sim" + } + { "m32r-elf" } { + set target_list "m32r-sim" + } + { "moxie-elf" } { + set target_list "moxie-sim" + } + { "or1k-elf" } { + set target_list "or1k-sim" + } +} + diff --git a/native/libffi/.travis/wine-sim.exp b/native/libffi/.travis/wine-sim.exp new file mode 100644 index 0000000000..1ad603817a --- /dev/null +++ b/native/libffi/.travis/wine-sim.exp @@ -0,0 +1,55 @@ +# Copyright (C) 2010, 2019 Free Software Foundation, Inc. +# +# This file is part of DejaGnu. +# +# DejaGnu is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# DejaGnu is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with DejaGnu; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, MA 02110, USA. + +# This is a list of toolchains that are supported on this board. +set_board_info target_install {i686-w64-mingw32} + +# Load the generic configuration for this board. This will define a basic set +# of routines needed by the tool to communicate with the board. +load_generic_config "sim" + +set_board_info sim "wineconsole --backend=curses" +set_board_info is_simulator 1 + +# No multilib options needed by default. +process_multilib_options "" + +# We only support newlib on this target. We assume that all multilib +# options have been specified before we get here. + +set_board_info compiler "[find_gcc]" +set_board_info cflags "[libgloss_include_flags] [newlib_include_flags]" +set_board_info ldflags "[libgloss_link_flags] [newlib_link_flags]" + +# Configuration settings for testsuites +set_board_info noargs 1 +set_board_info gdb,nosignals 1 +set_board_info gdb,noresults 1 +set_board_info gdb,cannot_call_functions 1 +set_board_info gdb,skip_float_tests 1 +set_board_info gdb,can_reverse 1 +set_board_info gdb,use_precord 1 + +# More time is needed +set_board_info gcc,timeout 800 +set_board_info gdb,timeout 60 + +# Used by a few gcc.c-torture testcases to delimit how large the stack can +# be. +set_board_info gcc,stack_size 5000 + diff --git a/native/libffi/ChangeLog.libffi b/native/libffi/ChangeLog.libffi deleted file mode 100644 index 49ba8dad3a..0000000000 --- a/native/libffi/ChangeLog.libffi +++ /dev/null @@ -1,584 +0,0 @@ -2011-02-08 Andreas Tobler - - * testsuite/lib/libffi.exp: Tweak for stand-alone mode. - -2009-12-25 Samuli Suominen - - * configure.ac: Undefine _AC_ARG_VAR_PRECIOUS for autoconf 2.64. - * configure: Rebuilt. - * fficonfig.h.in: Rebuilt. - -2009-06-16 Andrew Haley - - * testsuite/libffi.call/cls_align_sint64.c, - testsuite/libffi.call/cls_align_uint64.c, - testsuite/libffi.call/cls_longdouble_va.c, - testsuite/libffi.call/cls_ulonglong.c, - testsuite/libffi.call/return_ll1.c, - testsuite/libffi.call/stret_medium2.c: Fix printf format - specifiers. - * testsuite/libffi.call/huge_struct.c: Ad x86 XFAILs. - * testsuite/libffi.call/float2.c: Fix dg-excess-errors. - * testsuite/libffi.call/ffitest.h, - testsuite/libffi.special/ffitestcxx.h (PRIdLL, PRIuLL): Define. - -2009-06-12 Andrew Haley - - * testsuite/libffi.call/cls_align_sint64.c, - testsuite/libffi.call/cls_align_uint64.c, - testsuite/libffi.call/cls_ulonglong.c, - testsuite/libffi.call/return_ll1.c, - testsuite/libffi.call/stret_medium2.c: Fix printf format - specifiers. - testsuite/libffi.special/unwindtest.cc: include stdint.h. - -2009-06-11 Timothy Wall - - * Makefile.am, - configure.ac, - include/ffi.h.in, - include/ffi_common.h, - src/closures.c, - src/dlmalloc.c, - src/x86/ffi.c, - src/x86/ffitarget.h, - src/x86/win64.S (new), - README: Added win64 support (mingw or MSVC) - * Makefile.in, - include/Makefile.in, - man/Makefile.in, - testsuite/Makefile.in, - configure, - aclocal.m4: Regenerated - * ltcf-c.sh: properly escape cygwin/w32 path - * man/ffi_call.3: Clarify size requirements for return value. - * src/x86/ffi64.c: Fix filename in comment. - * src/x86/win32.S: Remove unused extern. - - * testsuite/libffi.call/closure_fn0.c, - testsuite/libffi.call/closure_fn1.c, - testsuite/libffi.call/closure_fn2.c, - testsuite/libffi.call/closure_fn3.c, - testsuite/libffi.call/closure_fn4.c, - testsuite/libffi.call/closure_fn5.c, - testsuite/libffi.call/closure_fn6.c, - testsuite/libffi.call/closure_stdcall.c, - testsuite/libffi.call/cls_12byte.c, - testsuite/libffi.call/cls_16byte.c, - testsuite/libffi.call/cls_18byte.c, - testsuite/libffi.call/cls_19byte.c, - testsuite/libffi.call/cls_1_1byte.c, - testsuite/libffi.call/cls_20byte.c, - testsuite/libffi.call/cls_20byte1.c, - testsuite/libffi.call/cls_24byte.c, - testsuite/libffi.call/cls_2byte.c, - testsuite/libffi.call/cls_3_1byte.c, - testsuite/libffi.call/cls_3byte1.c, - testsuite/libffi.call/cls_3byte2.c, - testsuite/libffi.call/cls_4_1byte.c, - testsuite/libffi.call/cls_4byte.c, - testsuite/libffi.call/cls_5_1_byte.c, - testsuite/libffi.call/cls_5byte.c, - testsuite/libffi.call/cls_64byte.c, - testsuite/libffi.call/cls_6_1_byte.c, - testsuite/libffi.call/cls_6byte.c, - testsuite/libffi.call/cls_7_1_byte.c, - testsuite/libffi.call/cls_7byte.c, - testsuite/libffi.call/cls_8byte.c, - testsuite/libffi.call/cls_9byte1.c, - testsuite/libffi.call/cls_9byte2.c, - testsuite/libffi.call/cls_align_double.c, - testsuite/libffi.call/cls_align_float.c, - testsuite/libffi.call/cls_align_longdouble.c, - testsuite/libffi.call/cls_align_longdouble_split.c, - testsuite/libffi.call/cls_align_longdouble_split2.c, - testsuite/libffi.call/cls_align_pointer.c, - testsuite/libffi.call/cls_align_sint16.c, - testsuite/libffi.call/cls_align_sint32.c, - testsuite/libffi.call/cls_align_sint64.c, - testsuite/libffi.call/cls_align_uint16.c, - testsuite/libffi.call/cls_align_uint32.c, - testsuite/libffi.call/cls_align_uint64.c, - testsuite/libffi.call/cls_dbls_struct.c, - testsuite/libffi.call/cls_double.c, - testsuite/libffi.call/cls_double_va.c, - testsuite/libffi.call/cls_float.c, - testsuite/libffi.call/cls_longdouble.c, - testsuite/libffi.call/cls_longdouble_va.c, - testsuite/libffi.call/cls_multi_schar.c, - testsuite/libffi.call/cls_multi_sshort.c, - testsuite/libffi.call/cls_multi_sshortchar.c, - testsuite/libffi.call/cls_multi_uchar.c, - testsuite/libffi.call/cls_multi_ushort.c, - testsuite/libffi.call/cls_multi_ushortchar.c, - testsuite/libffi.call/cls_pointer.c, - testsuite/libffi.call/cls_pointer_stack.c, - testsuite/libffi.call/cls_schar.c, - testsuite/libffi.call/cls_sint.c, - testsuite/libffi.call/cls_sshort.c, - testsuite/libffi.call/cls_uchar.c, - testsuite/libffi.call/cls_uint.c, - testsuite/libffi.call/cls_ulonglong.c, - testsuite/libffi.call/cls_ushort.c, - testsuite/libffi.call/err_bad_abi.c, - testsuite/libffi.call/err_bad_typedef.c, - testsuite/libffi.call/float2.c, - testsuite/libffi.call/huge_struct.c, - testsuite/libffi.call/nested_struct.c, - testsuite/libffi.call/nested_struct1.c, - testsuite/libffi.call/nested_struct10.c, - testsuite/libffi.call/nested_struct2.c, - testsuite/libffi.call/nested_struct3.c, - testsuite/libffi.call/nested_struct4.c, - testsuite/libffi.call/nested_struct5.c, - testsuite/libffi.call/nested_struct6.c, - testsuite/libffi.call/nested_struct7.c, - testsuite/libffi.call/nested_struct8.c, - testsuite/libffi.call/nested_struct9.c, - testsuite/libffi.call/problem1.c, - testsuite/libffi.call/return_ldl.c, - testsuite/libffi.call/return_ll1.c, - testsuite/libffi.call/stret_large.c, - testsuite/libffi.call/stret_large2.c, - testsuite/libffi.call/stret_medium.c, - testsuite/libffi.call/stret_medium2.c, - testsuite/libffi.special/unwindtest.cc: use ffi_closure_alloc instead - of checking for MMAP. Use intptr_t instead of long casts. - -2009-06-04 Andrew Haley - - * src/powerpc/ffitarget.h: Fix misapplied merge from gcc. - -2009-06-04 Andrew Haley - - * src/mips/o32.S, - src/mips/n32.S: Fix licence formatting. - -2009-06-04 Andrew Haley - - * src/x86/darwin.S: Fix licence formatting. - src/x86/win32.S: Likewise. - src/sh64/sysv.S: Likewise. - src/sh/sysv.S: Likewise. - -2009-06-04 Andrew Haley - - * src/sh64/ffi.c: Remove lint directives. Was missing from merge - of Andreas Tobler's patch from 2006-04-22. - -2009-06-04 Andrew Haley - - * src/sh/ffi.c: Apply missing hunk from Alexandre Oliva's patch of - 2007-03-07. - -2008-12-26 Timothy Wall - - * testsuite/libffi.call/cls_longdouble.c, - testsuite/libffi.call/cls_longdouble_va.c, - testsuite/libffi.call/cls_align_longdouble.c, - testsuite/libffi.call/cls_align_longdouble_split.c, - testsuite/libffi.call/cls_align_longdouble_split2.c: mark expected - failures on x86_64 cygwin/mingw. - -2008-12-22 Timothy Wall - - * testsuite/libffi.call/closure_fn0.c, - testsuite/libffi.call/closure_fn1.c, - testsuite/libffi.call/closure_fn2.c, - testsuite/libffi.call/closure_fn3.c, - testsuite/libffi.call/closure_fn4.c, - testsuite/libffi.call/closure_fn5.c, - testsuite/libffi.call/closure_fn6.c, - testsuite/libffi.call/closure_loc_fn0.c, - testsuite/libffi.call/closure_stdcall.c, - testsuite/libffi.call/cls_align_pointer.c, - testsuite/libffi.call/cls_pointer.c, - testsuite/libffi.call/cls_pointer_stack.c: use portable cast from - pointer to integer (intptr_t). - * testsuite/libffi.call/cls_longdouble.c: disable for win64. - -2008-12-19 Anthony Green - - * configure.ac: Bump version to 3.0.8. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * libtool-version: Increment revision. - * README: Update for new release. - -2008-11-11 Anthony Green - - * configure.ac: Bump version to 3.0.7. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * libtool-version: Increment revision. - * README: Update for new release. - -2008-08-25 Andreas Tobler - - * src/powerpc/ffitarget.h (ffi_abi): Add FFI_LINUX and - FFI_LINUX_SOFT_FLOAT to the POWERPC_FREEBSD enum. - Add note about flag bits used for FFI_SYSV_TYPE_SMALL_STRUCT. - Adjust copyright notice. - * src/powerpc/ffi.c: Add two new flags to indicate if we have one - register or two register to use for FFI_SYSV structs. - (ffi_prep_cif_machdep): Pass the right register flag introduced above. - (ffi_closure_helper_SYSV): Fix the return type for - FFI_SYSV_TYPE_SMALL_STRUCT. Comment. - Adjust copyright notice. - -2008-07-24 Anthony Green - - * testsuite/libffi.call/cls_dbls_struct.c, - testsuite/libffi.call/cls_double_va.c, - testsuite/libffi.call/cls_longdouble.c, - testsuite/libffi.call/cls_longdouble_va.c, - testsuite/libffi.call/cls_pointer.c, - testsuite/libffi.call/cls_pointer_stack.c, - testsuite/libffi.call/err_bad_abi.c: Clean up failures from - compiler warnings. - -2008-07-17 Anthony Green - - * configure.ac: Bump version to 3.0.6. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * libtool-version: Increment revision. Add documentation. - * README: Update for new release. - -2008-07-16 Kaz Kojima - - * src/sh/ffi.c (ffi_prep_closure_loc): Turn INSN into an unsigned - int. - -2008-07-16 Kaz Kojima - - * src/sh/sysv.S: Add .note.GNU-stack on Linux. - * src/sh64/sysv.S: Likewise. - -2008-04-03 Anthony Green - - * libffi.pc.in (Libs): Add -L${libdir}. - * configure.ac: Bump version to 3.0.5. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * libtool-version: Increment revision. - * README: Update for new release. - -2008-04-03 Anthony Green - Xerces Ranby - - * include/ffi.h.in: Wrap definition of target architecture to - protect from double definitions. - -2008-03-22 Moriyoshi Koizumi - - * src/x86/ffi.c (ffi_prep_closure_loc): Fix for bug revealed in - closure_loc_fn0.c. - * testsuite/libffi.call/closure_loc_fn0.c (closure_loc_test_fn0): - New test. - -2008-03-04 Anthony Green - Blake Chaffin - hos@tamanegi.org - - * testsuite/libffi.call/cls_align_longdouble_split2.c - testsuite/libffi.call/cls_align_longdouble_split.c - testsuite/libffi.call/cls_dbls_struct.c - testsuite/libffi.call/cls_double_va.c - testsuite/libffi.call/cls_longdouble.c - testsuite/libffi.call/cls_longdouble_va.c - testsuite/libffi.call/cls_pointer.c - testsuite/libffi.call/cls_pointer_stack.c - testsuite/libffi.call/err_bad_abi.c - testsuite/libffi.call/err_bad_typedef.c - testsuite/libffi.call/huge_struct.c - testsuite/libffi.call/stret_large2.c - testsuite/libffi.call/stret_large.c - testsuite/libffi.call/stret_medium2.c - testsuite/libffi.call/stret_medium.c: New tests from Apple. - -2008-02-26 Jakub Jelinek - Anthony Green - - * src/alpha/osf.S: Add .note.GNU-stack on Linux. - * src/s390/sysv.S: Likewise. - * src/powerpc/linux64.S: Likewise. - * src/powerpc/linux64_closure.S: Likewise. - * src/powerpc/ppc_closure.S: Likewise. - * src/powerpc/sysv.S: Likewise. - * src/x86/unix64.S: Likewise. - * src/x86/sysv.S: Likewise. - * src/sparc/v8.S: Likewise. - * src/sparc/v9.S: Likewise. - * src/m68k/sysv.S: Likewise. - * src/ia64/unix.S: Likewise. - * src/arm/sysv.S: Likewise. - -2008-02-26 Anthony Green - Thomas Heller - - * src/x86/ffi.c (ffi_closure_SYSV_inner): Change C++ comment to C - comment. - -2008-02-26 Anthony Green - Thomas Heller - - * include/ffi.h.in: Change void (*)() to void (*)(void). - -2008-02-26 Anthony Green - Thomas Heller - - * src/alpha/ffi.c: Change void (*)() to void (*)(void). - src/alpha/osf.S, src/arm/ffi.c, src/frv/ffi.c, src/ia64/ffi.c, - src/ia64/unix.S, src/java_raw_api.c, src/m32r/ffi.c, - src/mips/ffi.c, src/pa/ffi.c, src/pa/hpux32.S, src/pa/linux.S, - src/powerpc/ffi.c, src/powerpc/ffi_darwin.c, src/raw_api.c, - src/s390/ffi.c, src/sh/ffi.c, src/sh64/ffi.c, src/sparc/ffi.c, - src/x86/ffi.c, src/x86/unix64.S, src/x86/darwin64.S, - src/x86/ffi64.c: Ditto. - -2008-02-24 Anthony Green - - * configure.ac: Accept openbsd*, not just openbsd. - Bump version to 3.0.4. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * libtool-version: Increment revision. - * README: Update for new release. - -2008-02-22 Anthony Green - - * README: Clean up list of tested platforms. - -2008-02-22 Anthony Green - - * configure.ac: Bump version to 3.0.3. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * libtool-version: Increment revision. - * README: Update for new release. Clean up test docs. - -2008-02-22 Bjoern Koenig - Andreas Tobler - - * configure.ac: Add amd64-*-freebsd* target. - * configure: Regenerate. - -2008-02-22 Thomas Heller - - * configure.ac: Add x86 OpenBSD support. - * configure: Rebuilt. - -2008-02-21 Thomas Heller - - * README: Change "make test" to "make check". - -2008-02-21 Anthony Green - - * configure.ac: Bump version to 3.0.2. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * libtool-version: Increment revision. - * README: Update for new release. - -2008-02-21 Björn König - - * src/x86/freebsd.S: New file. - * configure.ac: Add x86 FreeBSD support. - * Makefile.am: Ditto. - -2008-02-15 Anthony Green - - * configure.ac: Bump version to 3.0.1. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * libtool-version: Increment revision. - * README: Update for new release. - -2008-02-15 David Daney - - * src/mips/ffi.c: Remove extra '>' from include directive. - (ffi_prep_closure_loc): Use clear_location instead of tramp. - -2008-02-15 Anthony Green - - * configure.ac: Bump version to 3.0.0. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - -2008-02-15 David Daney - - * src/mips/ffi.c (USE__BUILTIN___CLEAR_CACHE): - Define (conditionally), and use it to include cachectl.h. - (ffi_prep_closure_loc): Fix cache flushing. - * src/mips/ffitarget.h (_ABIN32, _ABI64, _ABIO32): Define. - -2008-02-15 Anthony Green - - * man/ffi_call.3, man/ffi_prep_cif.3, man/ffi.3: - Update dates and remove all references to ffi_prep_closure. - * configure.ac: Bump version to 2.99.9. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - -2008-02-15 Anthony Green - - * man/ffi_prep_closure.3: Delete. - * man/Makefile.am (EXTRA_DIST): Remove ffi_prep_closure.3. - (man_MANS): Ditto. - * man/Makefile.in: Rebuilt. - * configure.ac: Bump version to 2.99.8. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - -2008-02-14 Anthony Green - - * configure.ac: Bump version to 2.99.7. - * configure, doc/stamp-vti, doc/version.texi: Rebuilt. - * include/ffi.h.in LICENSE src/debug.c src/closures.c - src/ffitest.c src/s390/sysv.S src/s390/ffitarget.h - src/types.c src/m68k/ffitarget.h src/raw_api.c src/frv/ffi.c - src/frv/ffitarget.h src/sh/ffi.c src/sh/sysv.S - src/sh/ffitarget.h src/powerpc/ffitarget.h src/pa/ffi.c - src/pa/ffitarget.h src/pa/linux.S src/java_raw_api.c - src/cris/ffitarget.h src/x86/ffi.c src/x86/sysv.S - src/x86/unix64.S src/x86/win32.S src/x86/ffitarget.h - src/x86/ffi64.c src/x86/darwin.S src/ia64/ffi.c - src/ia64/ffitarget.h src/ia64/ia64_flags.h src/ia64/unix.S - src/sparc/ffi.c src/sparc/v9.S src/sparc/ffitarget.h - src/sparc/v8.S src/alpha/ffi.c src/alpha/ffitarget.h - src/alpha/osf.S src/sh64/ffi.c src/sh64/sysv.S - src/sh64/ffitarget.h src/mips/ffi.c src/mips/ffitarget.h - src/mips/n32.S src/mips/o32.S src/arm/ffi.c src/arm/sysv.S - src/arm/ffitarget.h src/prep_cif.c: Update license text. - -2008-02-14 Anthony Green - - * README: Update tested platforms. - * configure.ac: Bump version to 2.99.6. - * configure: Rebuilt. - -2008-02-14 Anthony Green - - * configure.ac: Bump version to 2.99.5. - * configure: Rebuilt. - * Makefile.am (EXTRA_DIST): Add darwin64.S - * Makefile.in: Rebuilt. - * testsuite/lib/libffi-dg.exp: Remove libstdc++ bits from GCC tree. - * LICENSE: Update WARRANTY. - -2008-02-14 Anthony Green - - * libffi.pc.in (libdir): Fix libdir definition. - * configure.ac: Bump version to 2.99.4. - * configure: Rebuilt. - -2008-02-14 Anthony Green - - * README: Update. - * libffi.info: New file. - * doc/stamp-vti: New file. - * configure.ac: Bump version to 2.99.3. - * configure: Rebuilt. - -2008-02-14 Anthony Green - - * Makefile.am (SUBDIRS): Add man dir. - * Makefile.in: Rebuilt. - * configure.ac: Create Makefile. - * configure: Rebuilt. - * man/ffi_call.3 man/ffi_prep_cif.3 man/ffi_prep_closure.3 - man/Makefile.am man/Makefile.in: New files. - -2008-02-14 Tom Tromey - - * aclocal.m4, Makefile.in, configure, fficonfig.h.in: Rebuilt. - * mdate-sh, texinfo.tex: New files. - * Makefile.am (info_TEXINFOS): New variable. - * doc/libffi.texi: New file. - * doc/version.texi: Likewise. - -2008-02-14 Anthony Green - - * Makefile.am (AM_CFLAGS): Don't compile with -D$(TARGET). - (lib_LTLIBRARIES): Define. - (toolexeclib_LIBRARIES): Undefine. - * Makefile.in: Rebuilt. - * configure.ac: Reset version to 2.99.1. - * configure.in: Rebuilt. - -2008-02-14 Anthony Green - - * libffi.pc.in: Use @PACKAGE_NAME@ and @PACKAGE_VERSION@. - * configure.ac: Reset version to 2.99.1. - * configure.in: Rebuilt. - * Makefile.am (EXTRA_DIST): Add ChangeLog.libffi. - * Makefile.in: Rebuilt. - * LICENSE: Update copyright notice. - -2008-02-14 Anthony Green - - * include/Makefile.am (nodist_includes_HEADERS): Define. Don't - distribute ffitarget.h or ffi.h from the build include dir. - * Makefile.in: Rebuilt. - -2008-02-14 Anthony Green - - * include/Makefile.am (includesdir): Install headers under libdir. - (pkgconfigdir): Define. Install libffi.pc. - * include/Makefile.in: Rebuilt. - * libffi.pc.in: Create. - * libtool-version: Increment CURRENT - * configure.ac: Add libffi.pc.in - * configure: Rebuilt. - -2008-02-03 Anthony Green - - * include/Makefile.am (includesdir): Fix header install with - DESTDIR. - * include/Makefile.in: Rebuilt. - -2008-02-03 Timothy Wall - - * src/x86/ffi.c (FFI_INIT_TRAMPOLINE_STDCALL): Calculate jump return - offset based on code pointer, not data pointer. - -2008-02-01 Anthony Green - - * include/Makefile.am: Fix header installs. - * Makefile.am: Ditto. - * include/Makefile.in: Rebuilt. - * Makefile.in: Ditto. - -2008-02-01 Anthony Green - - * src/x86/ffi.c (FFI_INIT_TRAMPOLINE_STDCALL, - FFI_INIT_TRAMPOLINE): Revert my broken changes to twall's last - patch. - -2008-01-31 Anthony Green - - * Makefile.am (EXTRA_DIST): Add missing files. - * testsuite/Makefile.am: Ditto. - * Makefile.in, testsuite/Makefile.in: Rebuilt. - -2008-01-31 Timothy Wall - - * testsuite/libffi.call/closure_stdcall.c: Add test for stdcall - closures. - * src/x86/ffitarget.h: Increase size of trampoline for stdcall - closures. - * src/x86/win32.S: Add assembly for stdcall closure. - * src/x86/ffi.c: Initialize stdcall closure trampoline. - -2008-01-30 H.J. Lu - - PR libffi/34612 - * src/x86/sysv.S (ffi_closure_SYSV): Pop 4 byte from stack when - returning struct. - - * testsuite/libffi.call/call.exp: Add "-O2 -fomit-frame-pointer" - tests. - -2008-01-30 Anthony Green - - * Makefile.am, include/Makefile.am: Move headers to - libffi_la_SOURCES for new automake. - * Makefile.in, include/Makefile.in: Rebuilt. - - * testsuite/lib/wrapper.exp: Copied from gcc tree to allow for - execution outside of gcc tree. - * testsuite/lib/target-libpath.exp: Ditto. - - * testsuite/lib/libffi-dg.exp: Many changes to allow for execution - outside of gcc tree. - diff --git a/native/libffi/ChangeLog.libffi-3.1 b/native/libffi/ChangeLog.libffi-3.1 index 8f7f50d6f9..8216dc8194 100644 --- a/native/libffi/ChangeLog.libffi-3.1 +++ b/native/libffi/ChangeLog.libffi-3.1 @@ -1,3 +1,14 @@ +<<<<<<< HEAD:native/libffi/ChangeLog.libffi-3.1 +======= +Libffi change logs used to be maintained in separate ChangeLog files. +These days we generate them directly from the git commit messages. +The old ChangeLog files are saved here in order to maintain the historical +record. + +============================================================================= +From the old ChangeLog.libffi-3.1 file... + +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878:native/libffi/ChangeLog.old 2014-03-16 Josh Triplett * ChangeLog: Archive to ChangeLog.libffi-3.1 and delete. Future @@ -5998,3 +6009,1402 @@ Thu Jul 8 14:28:42 1999 Anthony Green * src/x86/ChangeLog: Removed. * ChangeLog.v1: Created. + +============================================================================= +From the old ChangeLog.libffi file.... + +2011-02-08 Andreas Tobler + + * testsuite/lib/libffi.exp: Tweak for stand-alone mode. + +2009-12-25 Samuli Suominen + + * configure.ac: Undefine _AC_ARG_VAR_PRECIOUS for autoconf 2.64. + * configure: Rebuilt. + * fficonfig.h.in: Rebuilt. + +2009-06-16 Andrew Haley + + * testsuite/libffi.call/cls_align_sint64.c, + testsuite/libffi.call/cls_align_uint64.c, + testsuite/libffi.call/cls_longdouble_va.c, + testsuite/libffi.call/cls_ulonglong.c, + testsuite/libffi.call/return_ll1.c, + testsuite/libffi.call/stret_medium2.c: Fix printf format + specifiers. + * testsuite/libffi.call/huge_struct.c: Ad x86 XFAILs. + * testsuite/libffi.call/float2.c: Fix dg-excess-errors. + * testsuite/libffi.call/ffitest.h, + testsuite/libffi.special/ffitestcxx.h (PRIdLL, PRIuLL): Define. + +2009-06-12 Andrew Haley + + * testsuite/libffi.call/cls_align_sint64.c, + testsuite/libffi.call/cls_align_uint64.c, + testsuite/libffi.call/cls_ulonglong.c, + testsuite/libffi.call/return_ll1.c, + testsuite/libffi.call/stret_medium2.c: Fix printf format + specifiers. + testsuite/libffi.special/unwindtest.cc: include stdint.h. + +2009-06-11 Timothy Wall + + * Makefile.am, + configure.ac, + include/ffi.h.in, + include/ffi_common.h, + src/closures.c, + src/dlmalloc.c, + src/x86/ffi.c, + src/x86/ffitarget.h, + src/x86/win64.S (new), + README: Added win64 support (mingw or MSVC) + * Makefile.in, + include/Makefile.in, + man/Makefile.in, + testsuite/Makefile.in, + configure, + aclocal.m4: Regenerated + * ltcf-c.sh: properly escape cygwin/w32 path + * man/ffi_call.3: Clarify size requirements for return value. + * src/x86/ffi64.c: Fix filename in comment. + * src/x86/win32.S: Remove unused extern. + + * testsuite/libffi.call/closure_fn0.c, + testsuite/libffi.call/closure_fn1.c, + testsuite/libffi.call/closure_fn2.c, + testsuite/libffi.call/closure_fn3.c, + testsuite/libffi.call/closure_fn4.c, + testsuite/libffi.call/closure_fn5.c, + testsuite/libffi.call/closure_fn6.c, + testsuite/libffi.call/closure_stdcall.c, + testsuite/libffi.call/cls_12byte.c, + testsuite/libffi.call/cls_16byte.c, + testsuite/libffi.call/cls_18byte.c, + testsuite/libffi.call/cls_19byte.c, + testsuite/libffi.call/cls_1_1byte.c, + testsuite/libffi.call/cls_20byte.c, + testsuite/libffi.call/cls_20byte1.c, + testsuite/libffi.call/cls_24byte.c, + testsuite/libffi.call/cls_2byte.c, + testsuite/libffi.call/cls_3_1byte.c, + testsuite/libffi.call/cls_3byte1.c, + testsuite/libffi.call/cls_3byte2.c, + testsuite/libffi.call/cls_4_1byte.c, + testsuite/libffi.call/cls_4byte.c, + testsuite/libffi.call/cls_5_1_byte.c, + testsuite/libffi.call/cls_5byte.c, + testsuite/libffi.call/cls_64byte.c, + testsuite/libffi.call/cls_6_1_byte.c, + testsuite/libffi.call/cls_6byte.c, + testsuite/libffi.call/cls_7_1_byte.c, + testsuite/libffi.call/cls_7byte.c, + testsuite/libffi.call/cls_8byte.c, + testsuite/libffi.call/cls_9byte1.c, + testsuite/libffi.call/cls_9byte2.c, + testsuite/libffi.call/cls_align_double.c, + testsuite/libffi.call/cls_align_float.c, + testsuite/libffi.call/cls_align_longdouble.c, + testsuite/libffi.call/cls_align_longdouble_split.c, + testsuite/libffi.call/cls_align_longdouble_split2.c, + testsuite/libffi.call/cls_align_pointer.c, + testsuite/libffi.call/cls_align_sint16.c, + testsuite/libffi.call/cls_align_sint32.c, + testsuite/libffi.call/cls_align_sint64.c, + testsuite/libffi.call/cls_align_uint16.c, + testsuite/libffi.call/cls_align_uint32.c, + testsuite/libffi.call/cls_align_uint64.c, + testsuite/libffi.call/cls_dbls_struct.c, + testsuite/libffi.call/cls_double.c, + testsuite/libffi.call/cls_double_va.c, + testsuite/libffi.call/cls_float.c, + testsuite/libffi.call/cls_longdouble.c, + testsuite/libffi.call/cls_longdouble_va.c, + testsuite/libffi.call/cls_multi_schar.c, + testsuite/libffi.call/cls_multi_sshort.c, + testsuite/libffi.call/cls_multi_sshortchar.c, + testsuite/libffi.call/cls_multi_uchar.c, + testsuite/libffi.call/cls_multi_ushort.c, + testsuite/libffi.call/cls_multi_ushortchar.c, + testsuite/libffi.call/cls_pointer.c, + testsuite/libffi.call/cls_pointer_stack.c, + testsuite/libffi.call/cls_schar.c, + testsuite/libffi.call/cls_sint.c, + testsuite/libffi.call/cls_sshort.c, + testsuite/libffi.call/cls_uchar.c, + testsuite/libffi.call/cls_uint.c, + testsuite/libffi.call/cls_ulonglong.c, + testsuite/libffi.call/cls_ushort.c, + testsuite/libffi.call/err_bad_abi.c, + testsuite/libffi.call/err_bad_typedef.c, + testsuite/libffi.call/float2.c, + testsuite/libffi.call/huge_struct.c, + testsuite/libffi.call/nested_struct.c, + testsuite/libffi.call/nested_struct1.c, + testsuite/libffi.call/nested_struct10.c, + testsuite/libffi.call/nested_struct2.c, + testsuite/libffi.call/nested_struct3.c, + testsuite/libffi.call/nested_struct4.c, + testsuite/libffi.call/nested_struct5.c, + testsuite/libffi.call/nested_struct6.c, + testsuite/libffi.call/nested_struct7.c, + testsuite/libffi.call/nested_struct8.c, + testsuite/libffi.call/nested_struct9.c, + testsuite/libffi.call/problem1.c, + testsuite/libffi.call/return_ldl.c, + testsuite/libffi.call/return_ll1.c, + testsuite/libffi.call/stret_large.c, + testsuite/libffi.call/stret_large2.c, + testsuite/libffi.call/stret_medium.c, + testsuite/libffi.call/stret_medium2.c, + testsuite/libffi.special/unwindtest.cc: use ffi_closure_alloc instead + of checking for MMAP. Use intptr_t instead of long casts. + +2009-06-04 Andrew Haley + + * src/powerpc/ffitarget.h: Fix misapplied merge from gcc. + +2009-06-04 Andrew Haley + + * src/mips/o32.S, + src/mips/n32.S: Fix licence formatting. + +2009-06-04 Andrew Haley + + * src/x86/darwin.S: Fix licence formatting. + src/x86/win32.S: Likewise. + src/sh64/sysv.S: Likewise. + src/sh/sysv.S: Likewise. + +2009-06-04 Andrew Haley + + * src/sh64/ffi.c: Remove lint directives. Was missing from merge + of Andreas Tobler's patch from 2006-04-22. + +2009-06-04 Andrew Haley + + * src/sh/ffi.c: Apply missing hunk from Alexandre Oliva's patch of + 2007-03-07. + +2008-12-26 Timothy Wall + + * testsuite/libffi.call/cls_longdouble.c, + testsuite/libffi.call/cls_longdouble_va.c, + testsuite/libffi.call/cls_align_longdouble.c, + testsuite/libffi.call/cls_align_longdouble_split.c, + testsuite/libffi.call/cls_align_longdouble_split2.c: mark expected + failures on x86_64 cygwin/mingw. + +2008-12-22 Timothy Wall + + * testsuite/libffi.call/closure_fn0.c, + testsuite/libffi.call/closure_fn1.c, + testsuite/libffi.call/closure_fn2.c, + testsuite/libffi.call/closure_fn3.c, + testsuite/libffi.call/closure_fn4.c, + testsuite/libffi.call/closure_fn5.c, + testsuite/libffi.call/closure_fn6.c, + testsuite/libffi.call/closure_loc_fn0.c, + testsuite/libffi.call/closure_stdcall.c, + testsuite/libffi.call/cls_align_pointer.c, + testsuite/libffi.call/cls_pointer.c, + testsuite/libffi.call/cls_pointer_stack.c: use portable cast from + pointer to integer (intptr_t). + * testsuite/libffi.call/cls_longdouble.c: disable for win64. + +2008-12-19 Anthony Green + + * configure.ac: Bump version to 3.0.8. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + * libtool-version: Increment revision. + * README: Update for new release. + +2008-11-11 Anthony Green + + * configure.ac: Bump version to 3.0.7. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + * libtool-version: Increment revision. + * README: Update for new release. + +2008-08-25 Andreas Tobler + + * src/powerpc/ffitarget.h (ffi_abi): Add FFI_LINUX and + FFI_LINUX_SOFT_FLOAT to the POWERPC_FREEBSD enum. + Add note about flag bits used for FFI_SYSV_TYPE_SMALL_STRUCT. + Adjust copyright notice. + * src/powerpc/ffi.c: Add two new flags to indicate if we have one + register or two register to use for FFI_SYSV structs. + (ffi_prep_cif_machdep): Pass the right register flag introduced above. + (ffi_closure_helper_SYSV): Fix the return type for + FFI_SYSV_TYPE_SMALL_STRUCT. Comment. + Adjust copyright notice. + +2008-07-24 Anthony Green + + * testsuite/libffi.call/cls_dbls_struct.c, + testsuite/libffi.call/cls_double_va.c, + testsuite/libffi.call/cls_longdouble.c, + testsuite/libffi.call/cls_longdouble_va.c, + testsuite/libffi.call/cls_pointer.c, + testsuite/libffi.call/cls_pointer_stack.c, + testsuite/libffi.call/err_bad_abi.c: Clean up failures from + compiler warnings. + +2008-07-17 Anthony Green + + * configure.ac: Bump version to 3.0.6. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + * libtool-version: Increment revision. Add documentation. + * README: Update for new release. + +2008-07-16 Kaz Kojima + + * src/sh/ffi.c (ffi_prep_closure_loc): Turn INSN into an unsigned + int. + +2008-07-16 Kaz Kojima + + * src/sh/sysv.S: Add .note.GNU-stack on Linux. + * src/sh64/sysv.S: Likewise. + +2008-04-03 Anthony Green + + * libffi.pc.in (Libs): Add -L${libdir}. + * configure.ac: Bump version to 3.0.5. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + * libtool-version: Increment revision. + * README: Update for new release. + +2008-04-03 Anthony Green + Xerces Ranby + + * include/ffi.h.in: Wrap definition of target architecture to + protect from double definitions. + +2008-03-22 Moriyoshi Koizumi + + * src/x86/ffi.c (ffi_prep_closure_loc): Fix for bug revealed in + closure_loc_fn0.c. + * testsuite/libffi.call/closure_loc_fn0.c (closure_loc_test_fn0): + New test. + +2008-03-04 Anthony Green + Blake Chaffin + hos@tamanegi.org + + * testsuite/libffi.call/cls_align_longdouble_split2.c + testsuite/libffi.call/cls_align_longdouble_split.c + testsuite/libffi.call/cls_dbls_struct.c + testsuite/libffi.call/cls_double_va.c + testsuite/libffi.call/cls_longdouble.c + testsuite/libffi.call/cls_longdouble_va.c + testsuite/libffi.call/cls_pointer.c + testsuite/libffi.call/cls_pointer_stack.c + testsuite/libffi.call/err_bad_abi.c + testsuite/libffi.call/err_bad_typedef.c + testsuite/libffi.call/huge_struct.c + testsuite/libffi.call/stret_large2.c + testsuite/libffi.call/stret_large.c + testsuite/libffi.call/stret_medium2.c + testsuite/libffi.call/stret_medium.c: New tests from Apple. + +2008-02-26 Jakub Jelinek + Anthony Green + + * src/alpha/osf.S: Add .note.GNU-stack on Linux. + * src/s390/sysv.S: Likewise. + * src/powerpc/linux64.S: Likewise. + * src/powerpc/linux64_closure.S: Likewise. + * src/powerpc/ppc_closure.S: Likewise. + * src/powerpc/sysv.S: Likewise. + * src/x86/unix64.S: Likewise. + * src/x86/sysv.S: Likewise. + * src/sparc/v8.S: Likewise. + * src/sparc/v9.S: Likewise. + * src/m68k/sysv.S: Likewise. + * src/ia64/unix.S: Likewise. + * src/arm/sysv.S: Likewise. + +2008-02-26 Anthony Green + Thomas Heller + + * src/x86/ffi.c (ffi_closure_SYSV_inner): Change C++ comment to C + comment. + +2008-02-26 Anthony Green + Thomas Heller + + * include/ffi.h.in: Change void (*)() to void (*)(void). + +2008-02-26 Anthony Green + Thomas Heller + + * src/alpha/ffi.c: Change void (*)() to void (*)(void). + src/alpha/osf.S, src/arm/ffi.c, src/frv/ffi.c, src/ia64/ffi.c, + src/ia64/unix.S, src/java_raw_api.c, src/m32r/ffi.c, + src/mips/ffi.c, src/pa/ffi.c, src/pa/hpux32.S, src/pa/linux.S, + src/powerpc/ffi.c, src/powerpc/ffi_darwin.c, src/raw_api.c, + src/s390/ffi.c, src/sh/ffi.c, src/sh64/ffi.c, src/sparc/ffi.c, + src/x86/ffi.c, src/x86/unix64.S, src/x86/darwin64.S, + src/x86/ffi64.c: Ditto. + +2008-02-24 Anthony Green + + * configure.ac: Accept openbsd*, not just openbsd. + Bump version to 3.0.4. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + * libtool-version: Increment revision. + * README: Update for new release. + +2008-02-22 Anthony Green + + * README: Clean up list of tested platforms. + +2008-02-22 Anthony Green + + * configure.ac: Bump version to 3.0.3. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + * libtool-version: Increment revision. + * README: Update for new release. Clean up test docs. + +2008-02-22 Bjoern Koenig + Andreas Tobler + + * configure.ac: Add amd64-*-freebsd* target. + * configure: Regenerate. + +2008-02-22 Thomas Heller + + * configure.ac: Add x86 OpenBSD support. + * configure: Rebuilt. + +2008-02-21 Thomas Heller + + * README: Change "make test" to "make check". + +2008-02-21 Anthony Green + + * configure.ac: Bump version to 3.0.2. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + * libtool-version: Increment revision. + * README: Update for new release. + +2008-02-21 Björn König + + * src/x86/freebsd.S: New file. + * configure.ac: Add x86 FreeBSD support. + * Makefile.am: Ditto. + +2008-02-15 Anthony Green + + * configure.ac: Bump version to 3.0.1. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + * libtool-version: Increment revision. + * README: Update for new release. + +2008-02-15 David Daney + + * src/mips/ffi.c: Remove extra '>' from include directive. + (ffi_prep_closure_loc): Use clear_location instead of tramp. + +2008-02-15 Anthony Green + + * configure.ac: Bump version to 3.0.0. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + +2008-02-15 David Daney + + * src/mips/ffi.c (USE__BUILTIN___CLEAR_CACHE): + Define (conditionally), and use it to include cachectl.h. + (ffi_prep_closure_loc): Fix cache flushing. + * src/mips/ffitarget.h (_ABIN32, _ABI64, _ABIO32): Define. + +2008-02-15 Anthony Green + + * man/ffi_call.3, man/ffi_prep_cif.3, man/ffi.3: + Update dates and remove all references to ffi_prep_closure. + * configure.ac: Bump version to 2.99.9. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + +2008-02-15 Anthony Green + + * man/ffi_prep_closure.3: Delete. + * man/Makefile.am (EXTRA_DIST): Remove ffi_prep_closure.3. + (man_MANS): Ditto. + * man/Makefile.in: Rebuilt. + * configure.ac: Bump version to 2.99.8. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + +2008-02-14 Anthony Green + + * configure.ac: Bump version to 2.99.7. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + * include/ffi.h.in LICENSE src/debug.c src/closures.c + src/ffitest.c src/s390/sysv.S src/s390/ffitarget.h + src/types.c src/m68k/ffitarget.h src/raw_api.c src/frv/ffi.c + src/frv/ffitarget.h src/sh/ffi.c src/sh/sysv.S + src/sh/ffitarget.h src/powerpc/ffitarget.h src/pa/ffi.c + src/pa/ffitarget.h src/pa/linux.S src/java_raw_api.c + src/cris/ffitarget.h src/x86/ffi.c src/x86/sysv.S + src/x86/unix64.S src/x86/win32.S src/x86/ffitarget.h + src/x86/ffi64.c src/x86/darwin.S src/ia64/ffi.c + src/ia64/ffitarget.h src/ia64/ia64_flags.h src/ia64/unix.S + src/sparc/ffi.c src/sparc/v9.S src/sparc/ffitarget.h + src/sparc/v8.S src/alpha/ffi.c src/alpha/ffitarget.h + src/alpha/osf.S src/sh64/ffi.c src/sh64/sysv.S + src/sh64/ffitarget.h src/mips/ffi.c src/mips/ffitarget.h + src/mips/n32.S src/mips/o32.S src/arm/ffi.c src/arm/sysv.S + src/arm/ffitarget.h src/prep_cif.c: Update license text. + +2008-02-14 Anthony Green + + * README: Update tested platforms. + * configure.ac: Bump version to 2.99.6. + * configure: Rebuilt. + +2008-02-14 Anthony Green + + * configure.ac: Bump version to 2.99.5. + * configure: Rebuilt. + * Makefile.am (EXTRA_DIST): Add darwin64.S + * Makefile.in: Rebuilt. + * testsuite/lib/libffi-dg.exp: Remove libstdc++ bits from GCC tree. + * LICENSE: Update WARRANTY. + +2008-02-14 Anthony Green + + * libffi.pc.in (libdir): Fix libdir definition. + * configure.ac: Bump version to 2.99.4. + * configure: Rebuilt. + +2008-02-14 Anthony Green + + * README: Update. + * libffi.info: New file. + * doc/stamp-vti: New file. + * configure.ac: Bump version to 2.99.3. + * configure: Rebuilt. + +2008-02-14 Anthony Green + + * Makefile.am (SUBDIRS): Add man dir. + * Makefile.in: Rebuilt. + * configure.ac: Create Makefile. + * configure: Rebuilt. + * man/ffi_call.3 man/ffi_prep_cif.3 man/ffi_prep_closure.3 + man/Makefile.am man/Makefile.in: New files. + +2008-02-14 Tom Tromey + + * aclocal.m4, Makefile.in, configure, fficonfig.h.in: Rebuilt. + * mdate-sh, texinfo.tex: New files. + * Makefile.am (info_TEXINFOS): New variable. + * doc/libffi.texi: New file. + * doc/version.texi: Likewise. + +2008-02-14 Anthony Green + + * Makefile.am (AM_CFLAGS): Don't compile with -D$(TARGET). + (lib_LTLIBRARIES): Define. + (toolexeclib_LIBRARIES): Undefine. + * Makefile.in: Rebuilt. + * configure.ac: Reset version to 2.99.1. + * configure.in: Rebuilt. + +2008-02-14 Anthony Green + + * libffi.pc.in: Use @PACKAGE_NAME@ and @PACKAGE_VERSION@. + * configure.ac: Reset version to 2.99.1. + * configure.in: Rebuilt. + * Makefile.am (EXTRA_DIST): Add ChangeLog.libffi. + * Makefile.in: Rebuilt. + * LICENSE: Update copyright notice. + +2008-02-14 Anthony Green + + * include/Makefile.am (nodist_includes_HEADERS): Define. Don't + distribute ffitarget.h or ffi.h from the build include dir. + * Makefile.in: Rebuilt. + +2008-02-14 Anthony Green + + * include/Makefile.am (includesdir): Install headers under libdir. + (pkgconfigdir): Define. Install libffi.pc. + * include/Makefile.in: Rebuilt. + * libffi.pc.in: Create. + * libtool-version: Increment CURRENT + * configure.ac: Add libffi.pc.in + * configure: Rebuilt. + +2008-02-03 Anthony Green + + * include/Makefile.am (includesdir): Fix header install with + DESTDIR. + * include/Makefile.in: Rebuilt. + +2008-02-03 Timothy Wall + + * src/x86/ffi.c (FFI_INIT_TRAMPOLINE_STDCALL): Calculate jump return + offset based on code pointer, not data pointer. + +2008-02-01 Anthony Green + + * include/Makefile.am: Fix header installs. + * Makefile.am: Ditto. + * include/Makefile.in: Rebuilt. + * Makefile.in: Ditto. + +2008-02-01 Anthony Green + + * src/x86/ffi.c (FFI_INIT_TRAMPOLINE_STDCALL, + FFI_INIT_TRAMPOLINE): Revert my broken changes to twall's last + patch. + +2008-01-31 Anthony Green + + * Makefile.am (EXTRA_DIST): Add missing files. + * testsuite/Makefile.am: Ditto. + * Makefile.in, testsuite/Makefile.in: Rebuilt. + +2008-01-31 Timothy Wall + + * testsuite/libffi.call/closure_stdcall.c: Add test for stdcall + closures. + * src/x86/ffitarget.h: Increase size of trampoline for stdcall + closures. + * src/x86/win32.S: Add assembly for stdcall closure. + * src/x86/ffi.c: Initialize stdcall closure trampoline. + +2008-01-30 H.J. Lu + + PR libffi/34612 + * src/x86/sysv.S (ffi_closure_SYSV): Pop 4 byte from stack when + returning struct. + + * testsuite/libffi.call/call.exp: Add "-O2 -fomit-frame-pointer" + tests. + +2008-01-30 Anthony Green + + * Makefile.am, include/Makefile.am: Move headers to + libffi_la_SOURCES for new automake. + * Makefile.in, include/Makefile.in: Rebuilt. + + * testsuite/lib/wrapper.exp: Copied from gcc tree to allow for + execution outside of gcc tree. + * testsuite/lib/target-libpath.exp: Ditto. + + * testsuite/lib/libffi-dg.exp: Many changes to allow for execution + outside of gcc tree. + + +============================================================================= +From the old ChangeLog.libgcj file.... + +2004-01-14 Kelley Cook + + * configure.in: Add in AC_PREREQ(2.13) + +2003-02-20 Alexandre Oliva + + * configure.in: Propagate ORIGINAL_LD_FOR_MULTILIBS to + config.status. + * configure: Rebuilt. + +2002-01-27 Alexandre Oliva + + * configure.in (toolexecdir, toolexeclibdir): Set and AC_SUBST. + Remove USE_LIBDIR conditional. + * Makefile.am (toolexecdir, toolexeclibdir): Don't override. + * Makefile.in, configure: Rebuilt. + +Mon Aug 9 18:33:38 1999 Rainer Orth + + * include/Makefile.in: Rebuilt. + * Makefile.in: Rebuilt + * Makefile.am (toolexeclibdir): Add $(MULTISUBDIR) even for native + builds. + Use USE_LIBDIR. + + * configure: Rebuilt. + * configure.in (USE_LIBDIR): Define for native builds. + Use lowercase in configure --help explanations. + +1999-08-08 Anthony Green + + * include/ffi.h.in (FFI_FN): Remove `...'. + +1999-08-08 Anthony Green + + * Makefile.in: Rebuilt. + * Makefile.am (AM_CFLAGS): Compile with -fexceptions. + + * src/x86/sysv.S: Add exception handling metadata. + + +============================================================================= + +The libffi version 1 ChangeLog archive. + +Version 1 of libffi had per-directory ChangeLogs. Current and future +versions have a single ChangeLog file in the root directory. The +version 1 ChangeLogs have all been concatenated into this file for +future reference only. + +--- libffi ---------------------------------------------------------------- + +Mon Oct 5 02:17:50 1998 Anthony Green + + * configure.in: Boosted rev. + * configure, Makefile.in, aclocal.m4: Rebuilt. + * README: Boosted rev and updated release notes. + +Mon Oct 5 01:03:03 1998 Anthony Green + + * configure.in: Boosted rev. + * configure, Makefile.in, aclocal.m4: Rebuilt. + * README: Boosted rev and updated release notes. + +1998-07-25 Andreas Schwab + + * m68k/ffi.c (ffi_prep_cif_machdep): Use bitmask for cif->flags. + Correctly handle small structures. + (ffi_prep_args): Also handle small structures. + (ffi_call): Pass size of return type to ffi_call_SYSV. + * m68k/sysv.S: Adjust for above changes. Correctly align small + structures in the return value. + + * types.c (uint64, sint64) [M68K]: Change alignment to 4. + +Fri Apr 17 17:26:58 1998 Anthony Green + + * configure.in: Boosted rev. + * configure,Makefile.in,aclocal.m4: Rebuilt. + * README: Boosted rev and added release notes. + +Sun Feb 22 00:50:41 1998 Geoff Keating + + * configure.in: Add PowerPC config bits. + +1998-02-14 Andreas Schwab + + * configure.in: Add m68k config bits. Change AC_CANONICAL_SYSTEM + to AC_CANONICAL_HOST, this is not a compiler. Use $host instead + of $target. Remove AC_CHECK_SIZEOF(char), we already know the + result. Fix argument of AC_ARG_ENABLE. + * configure, fficonfig.h.in: Rebuilt. + +Tue Feb 10 20:53:40 1998 Richard Henderson + + * configure.in: Add Alpha config bits. + +Tue May 13 13:39:20 1997 Anthony Green + + * README: Updated dates and reworded Irix comments. + + * configure.in: Removed AC_PROG_RANLIB. + + * Makefile.in, aclocal.m4, config.guess, config.sub, configure, + ltmain.sh, */Makefile.in: libtoolized again and rebuilt with + automake and autoconf. + +Sat May 10 18:44:50 1997 Tom Tromey + + * configure, aclocal.m4: Rebuilt. + * configure.in: Don't compute EXTRADIST; now handled in + src/Makefile.in. Removed macros implied by AM_INIT_AUTOMAKE. + Don't run AM_MAINTAINER_MODE. + +Thu May 8 14:34:05 1997 Anthony Green + + * missing, ltmain.sh, ltconfig.sh: Created. These are new files + required by automake and libtool. + + * README: Boosted rev to 1.14. Added notes. + + * acconfig.h: Moved PACKAGE and VERSION for new automake. + + * configure.in: Changes for libtool. + + * Makefile.am (check): make test now make check. Uses libtool now. + + * Makefile.in, configure.in, aclocal.h, fficonfig.h.in: Rebuilt. + +Thu May 1 16:27:07 1997 Anthony Green + + * missing: Added file required by new automake. + +Tue Nov 26 14:10:42 1996 Anthony Green + + * acconfig.h: Added USING_PURIFY flag. This is defined when + --enable-purify-safety was used at configure time. + + * configure.in (allsources): Added --enable-purify-safety switch. + (VERSION): Boosted rev to 1.13. + * configure: Rebuilt. + +Fri Nov 22 06:46:12 1996 Anthony Green + + * configure.in (VERSION): Boosted rev to 1.12. + Removed special CFLAGS hack for gcc. + * configure: Rebuilt. + + * README: Boosted rev to 1.12. Added notes. + + * Many files: Cygnus Support changed to Cygnus Solutions. + +Wed Oct 30 11:15:25 1996 Anthony Green + + * configure.in (VERSION): Boosted rev to 1.11. + * configure: Rebuilt. + + * README: Boosted rev to 1.11. Added notes about GNU make. + +Tue Oct 29 12:25:12 1996 Anthony Green + + * configure.in: Fixed -Wall trick. + (VERSION): Boosted rev. + * configure: Rebuilt + + * acconfig.h: Needed for --enable-debug configure switch. + + * README: Boosted rev to 1.09. Added more notes on building + libffi, and LCLint. + + * configure.in: Added --enable-debug switch. Boosted rev to + 1.09. + * configure: Rebuilt + +Tue Oct 15 13:11:28 1996 Anthony Green + + * configure.in (VERSION): Boosted rev to 1.08 + * configure: Rebuilt. + + * README: Added n32 bug fix notes. + + * Makefile.am: Added "make lint" production. + * Makefile.in: Rebuilt. + +Mon Oct 14 10:54:46 1996 Anthony Green + + * README: Added web page reference. + + * configure.in, README: Boosted rev to 1.05 + * configure: Rebuilt. + + * README: Fixed n32 sample code. + +Fri Oct 11 17:09:28 1996 Anthony Green + + * README: Added sparc notes. + + * configure.in, README: Boosted rev to 1.04. + * configure: Rebuilt. + +Thu Oct 10 10:31:03 1996 Anthony Green + + * configure.in, README: Boosted rev to 1.03. + * configure: Rebuilt. + + * README: Added struct notes. + + * Makefile.am (EXTRA_DIST): Added LICENSE to distribution. + * Makefile.in: Rebuilt. + + * README: Removed Linux section. No special notes now + because aggregates arg/return types work. + +Wed Oct 9 16:16:42 1996 Anthony Green + + * README, configure.in (VERSION): Boosted rev to 1.02 + * configure: Rebuilt. + +Tue Oct 8 11:56:33 1996 Anthony Green + + * README (NOTE): Added n32 notes. + + * Makefile.am: Added test production. + * Makefile: Rebuilt + + * README: spell checked! + + * configure.in (VERSION): Boosted rev to 1.01 + * configure: Rebuilt. + +Mon Oct 7 15:50:22 1996 Anthony Green + + * configure.in: Added nasty bit to support SGI tools. + * configure: Rebuilt. + + * README: Added SGI notes. Added note about automake bug. + +Mon Oct 7 11:00:28 1996 Anthony Green + + * README: Rewrote intro, and fixed examples. + +Fri Oct 4 10:19:55 1996 Anthony Green + + * configure.in: -D$TARGET is no longer used as a compiler switch. + It is now inserted into ffi.h at configure time. + * configure: Rebuilt. + + * FFI_ABI and FFI_STATUS are now ffi_abi and ffi_status. + +Thu Oct 3 13:47:34 1996 Anthony Green + + * README, LICENSE: Created. Wrote some docs. + + * configure.in: Don't barf on i586-unknown-linuxaout. + Added EXTRADIST code for "make dist". + * configure: Rebuilt. + + * */Makefile.in: Rebuilt with patched automake. + +Tue Oct 1 17:12:25 1996 Anthony Green + + * Makefile.am, aclocal.m4, config.guess, config.sub, + configure.in, fficonfig.h.in, install-sh, mkinstalldirs, + stamp-h.in: Created + * Makefile.in, configure: Generated + +--- libffi/include -------------------------------------------------------- + +Tue Feb 24 13:09:36 1998 Anthony Green + + * ffi_mips.h: Updated FFI_TYPE_STRUCT_* values based on + ffi.h.in changes. This is a work-around for SGI's "simple" + assembler. + +Sun Feb 22 00:51:55 1998 Geoff Keating + + * ffi.h.in: PowerPC support. + +1998-02-14 Andreas Schwab + + * ffi.h.in: Add m68k support. + (FFI_TYPE_LONGDOUBLE): Make it a separate value. + +Tue Feb 10 20:55:16 1998 Richard Henderson + + * ffi.h.in (SIZEOF_ARG): Use a pointer type by default. + + * ffi.h.in: Alpha support. + +Fri Nov 22 06:48:45 1996 Anthony Green + + * ffi.h.in, ffi_common.h: Cygnus Support -> Cygnus Solutions. + +Wed Nov 20 22:31:01 1996 Anthony Green + + * ffi.h.in: Added ffi_type_void definition. + +Tue Oct 29 12:22:40 1996 Anthony Green + + * Makefile.am (hack_DATA): Always install ffi_mips.h. + + * ffi.h.in: Removed FFI_DEBUG. It's now in the correct + place (acconfig.h). + Added #include for size_t definition. + +Tue Oct 15 17:23:35 1996 Anthony Green + + * ffi.h.in, ffi_common.h, ffi_mips.h: More clean up. + Commented out #define of FFI_DEBUG. + +Tue Oct 15 13:01:06 1996 Anthony Green + + * ffi_common.h: Added bool definition. + + * ffi.h.in, ffi_common.h: Clean up based on LCLint output. + Added funny /*@...@*/ comments to annotate source. + +Mon Oct 14 12:29:23 1996 Anthony Green + + * ffi.h.in: Interface changes based on feedback from Jim + Blandy. + +Fri Oct 11 16:49:35 1996 Anthony Green + + * ffi.h.in: Small change for sparc support. + +Thu Oct 10 14:53:37 1996 Anthony Green + + * ffi_mips.h: Added FFI_TYPE_STRUCT_* definitions for + special structure return types. + +Wed Oct 9 13:55:57 1996 Anthony Green + + * ffi.h.in: Added SIZEOF_ARG definition for X86 + +Tue Oct 8 11:40:36 1996 Anthony Green + + * ffi.h.in (FFI_FN): Added macro for eliminating compiler warnings. + Use it to case your function pointers to the proper type. + + * ffi_mips.h (SIZEOF_ARG): Added magic to fix type promotion bug. + + * Makefile.am (EXTRA_DIST): Added ffi_mips.h to EXTRA_DIST. + * Makefile: Rebuilt. + + * ffi_mips.h: Created. Moved all common mips definitions here. + +Mon Oct 7 10:58:12 1996 Anthony Green + + * ffi.h.in: The SGI assember is very picky about parens. Redefined + some macros to avoid problems. + + * ffi.h.in: Added FFI_DEFAULT_ABI definitions. Also added + externs for pointer, and 64bit integral ffi_types. + +Fri Oct 4 09:51:37 1996 Anthony Green + + * ffi.h.in: Added FFI_ABI member to ffi_cif and changed + function prototypes accordingly. + Added #define @TARGET@. Now programs including ffi.h don't + have to specify this themselves. + +Thu Oct 3 15:36:44 1996 Anthony Green + + * ffi.h.in: Changed ffi_prep_cif's values from void* to void** + + * Makefile.am (EXTRA_DIST): Added EXTRA_DIST for "make dist" + to work. + * Makefile.in: Regenerated. + +Wed Oct 2 10:16:59 1996 Anthony Green + + * Makefile.am: Created + * Makefile.in: Generated + + * ffi_common.h: Added rcsid comment + +Tue Oct 1 17:13:51 1996 Anthony Green + + * ffi.h.in, ffi_common.h: Created + +--- libffi/src ------------------------------------------------------------ + +Mon Oct 5 02:17:50 1998 Anthony Green + + * arm/ffi.c, arm/sysv.S: Created. + + * Makefile.am: Added arm files. + * Makefile.in: Rebuilt. + +Mon Oct 5 01:41:38 1998 Anthony Green + + * Makefile.am (libffi_la_LDFLAGS): Incremented revision. + +Sun Oct 4 16:27:17 1998 Anthony Green + + * alpha/osf.S (ffi_call_osf): Patch for DU assembler. + + * ffitest.c (main): long long and long double return values work + for x86. + +Fri Apr 17 11:50:58 1998 Anthony Green + + * Makefile.in: Rebuilt. + + * ffitest.c (main): Floating point tests not executed for systems + with broken lond double (SunOS 4 w/ GCC). + + * types.c: Fixed x86 alignment info for long long types. + +Thu Apr 16 07:15:28 1998 Anthony Green + + * ffitest.c: Added more notes about GCC bugs under Irix 6. + +Wed Apr 15 08:42:22 1998 Anthony Green + + * ffitest.c (struct5): New test function. + (main): New test with struct5. + +Thu Mar 5 10:48:11 1998 Anthony Green + + * prep_cif.c (initialize_aggregate): Fix assertion for + nested structures. + +Tue Feb 24 16:33:41 1998 Anthony Green + + * prep_cif.c (ffi_prep_cif): Added long double support for sparc. + +Sun Feb 22 00:52:18 1998 Geoff Keating + + * powerpc/asm.h: New file. + * powerpc/ffi.c: New file. + * powerpc/sysv.S: New file. + * Makefile.am: PowerPC port. + * ffitest.c (main): Allow all tests to run even in presence of gcc + bug on PowerPC. + +1998-02-17 Anthony Green + + * mips/ffi.c: Fixed comment typo. + + * x86/ffi.c (ffi_prep_cif_machdep), x86/sysv.S (retfloat): + Fixed x86 long double return handling. + + * types.c: Fixed x86 long double alignment info. + +1998-02-14 Andreas Schwab + + * types.c: Add m68k support. + + * ffitest.c (floating): Add long double parameter. + (return_ll, ldblit): New functions to test long long and long + double return value. + (main): Fix type error in assignment of ts[1-4]_type.elements. + Add tests for long long and long double arguments and return + values. + + * prep_cif.c (ffi_prep_cif) [M68K]: Don't allocate argument for + struct value pointer. + + * m68k/ffi.c, m68k/sysv.S: New files. + * Makefile.am: Add bits for m68k port. Add kludge to work around + automake deficiency. + (test): Don't require "." in $PATH. + * Makefile.in: Rebuilt. + +Wed Feb 11 07:36:50 1998 Anthony Green + + * Makefile.in: Rebuilt. + +Tue Feb 10 20:56:00 1998 Richard Henderson + + * alpha/ffi.c, alpha/osf.S: New files. + * Makefile.am: Alpha port. + +Tue Nov 18 14:12:07 1997 Anthony Green + + * mips/ffi.c (ffi_prep_cif_machdep): Initialize rstruct_flag + for n32. + +Tue Jun 3 17:18:20 1997 Anthony Green + + * ffitest.c (main): Added hack to get structure tests working + correctly. + +Sat May 10 19:06:42 1997 Tom Tromey + + * Makefile.in: Rebuilt. + * Makefile.am (EXTRA_DIST): Explicitly list all distributable + files in subdirs. + (VERSION, CC): Removed. + +Thu May 8 17:19:01 1997 Anthony Green + + * Makefile.am: Many changes for new automake and libtool. + * Makefile.in: Rebuilt. + +Fri Nov 22 06:57:56 1996 Anthony Green + + * ffitest.c (main): Fixed test case for non mips machines. + +Wed Nov 20 22:31:59 1996 Anthony Green + + * types.c: Added ffi_type_void declaration. + +Tue Oct 29 13:07:19 1996 Anthony Green + + * ffitest.c (main): Fixed character constants. + (main): Emit warning for structure test 3 failure on Sun. + + * Makefile.am (VPATH): Fixed VPATH def'n so automake won't + strip it out. + Moved distdir hack from libffi to automake. + (ffitest): Added missing -c for $(COMPILE) (change in automake). + * Makefile.in: Rebuilt. + +Tue Oct 15 13:08:20 1996 Anthony Green + + * Makefile.am: Added "make lint" production. + * Makefile.in: Rebuilt. + + * prep_cif.c (STACK_ARG_SIZE): Improved STACK_ARG_SIZE macro. + Clean up based on LCLint output. Added funny /*@...@*/ comments to + annotate source. + + * ffitest.c, debug.c: Cleaned up code. + +Mon Oct 14 12:26:56 1996 Anthony Green + + * ffitest.c: Changes based on interface changes. + + * prep_cif.c (ffi_prep_cif): Cleaned up interface based on + feedback from Jim Blandy. + +Fri Oct 11 15:53:18 1996 Anthony Green + + * ffitest.c: Reordered tests while porting to sparc. + Made changes to handle lame structure passing for sparc. + Removed calls to fflush(). + + * prep_cif.c (ffi_prep_cif): Added special case for sparc + aggregate type arguments. + +Thu Oct 10 09:56:51 1996 Anthony Green + + * ffitest.c (main): Added structure passing/returning tests. + + * prep_cif.c (ffi_prep_cif): Perform proper initialization + of structure return types if needed. + (initialize_aggregate): Bug fix + +Wed Oct 9 16:04:20 1996 Anthony Green + + * types.c: Added special definitions for x86 (double doesn't + need double word alignment). + + * ffitest.c: Added many tests + +Tue Oct 8 09:19:22 1996 Anthony Green + + * prep_cif.c (ffi_prep_cif): Fixed assertion. + + * debug.c (ffi_assert): Must return a non void now. + + * Makefile.am: Added test production. + * Makefile: Rebuilt. + + * ffitest.c (main): Created. + + * types.c: Created. Stripped common code out of */ffi.c. + + * prep_cif.c: Added missing stdlib.h include. + + * debug.c (ffi_type_test): Used "a" to eliminate compiler + warnings in non-debug builds. Included ffi_common.h. + +Mon Oct 7 15:36:42 1996 Anthony Green + + * Makefile.am: Added a rule for .s -> .o + This is required by the SGI compiler. + * Makefile: Rebuilt. + +Fri Oct 4 09:51:08 1996 Anthony Green + + * prep_cif.c (initialize_aggregate): Moved abi specification + to ffi_prep_cif(). + +Thu Oct 3 15:37:37 1996 Anthony Green + + * prep_cif.c (ffi_prep_cif): Changed values from void* to void**. + (initialize_aggregate): Fixed aggregate type initialization. + + * Makefile.am (EXTRA_DIST): Added support code for "make dist". + * Makefile.in: Regenerated. + +Wed Oct 2 11:41:57 1996 Anthony Green + + * debug.c, prep_cif: Created. + + * Makefile.am: Added debug.o and prep_cif.o to OBJ. + * Makefile.in: Regenerated. + + * Makefile.am (INCLUDES): Added missing -I../include + * Makefile.in: Regenerated. + +Tue Oct 1 17:11:51 1996 Anthony Green + + * error.c, Makefile.am: Created. + * Makefile.in: Generated. + +--- libffi/src/x86 -------------------------------------------------------- + +Sun Oct 4 16:27:17 1998 Anthony Green + + * sysv.S (retlongdouble): Fixed long long return value support. + * ffi.c (ffi_prep_cif_machdep): Ditto. + +Wed May 13 04:30:33 1998 Anthony Green + + * ffi.c (ffi_prep_cif_machdep): Fixed long double return value + support. + +Wed Apr 15 08:43:20 1998 Anthony Green + + * ffi.c (ffi_prep_args): small struct support was missing. + +Thu May 8 16:53:58 1997 Anthony Green + + * objects.mak: Removed. + +Mon Dec 2 15:12:58 1996 Tom Tromey + + * sysv.S: Use .balign, for a.out Linux boxes. + +Tue Oct 15 13:06:50 1996 Anthony Green + + * ffi.c: Clean up based on LCLint output. + Added funny /*@...@*/ comments to annotate source. + +Fri Oct 11 16:43:38 1996 Anthony Green + + * ffi.c (ffi_call): Added assertion for bad ABIs. + +Wed Oct 9 13:57:27 1996 Anthony Green + + * sysv.S (retdouble): Fixed double return problems. + + * ffi.c (ffi_call): Corrected fn arg definition. + (ffi_prep_cif_machdep): Fixed double return problems + +Tue Oct 8 12:12:49 1996 Anthony Green + + * ffi.c: Moved ffi_type definitions to types.c. + (ffi_prep_args): Fixed type promotion bug. + +Mon Oct 7 15:53:06 1996 Anthony Green + + * ffi.c (FFI_*_TYPEDEF): Removed redundant ';' + +Fri Oct 4 09:54:53 1996 Anthony Green + + * ffi.c (ffi_call): Removed FFI_ABI arg, and swapped + remaining args. + +Wed Oct 2 10:07:05 1996 Anthony Green + + * ffi.c, sysv.S, objects.mak: Created. + (ffi_prep_cif): cif->rvalue no longer initialized to NULL. + (ffi_prep_cif_machdep): Moved machine independent cif processing + to src/prep_cif.c. Introduced ffi_prep_cif_machdep(). + +--- libffi/src/mips ------------------------------------------------------- + +Tue Feb 17 17:18:07 1998 Anthony Green + + * o32.S: Fixed typo in comment. + + * ffi.c (ffi_prep_cif_machdep): Fixed argument processing. + +Thu May 8 16:53:58 1997 Anthony Green + + * o32.s, n32.s: Wrappers for SGI tool support. + + * objects.mak: Removed. + +Tue Oct 29 14:37:45 1996 Anthony Green + + * ffi.c (ffi_prep_args): Changed int z to size_t z. + +Tue Oct 15 13:17:25 1996 Anthony Green + + * n32.S: Fixed bad stack munging. + + * ffi.c: Moved prototypes for ffi_call_?32() to here from + ffi_mips.h because extended_cif is not defined in ffi_mips.h. + +Mon Oct 14 12:42:02 1996 Anthony Green + + * ffi.c: Interface changes based on feedback from Jim Blandy. + +Thu Oct 10 11:22:16 1996 Anthony Green + + * n32.S, ffi.c: Lots of changes to support passing and + returning structures with the n32 calling convention. + + * n32.S: Fixed fn pointer bug. + + * ffi.c (ffi_prep_cif_machdep): Fix for o32 structure + return values. + (ffi_prep_args): Fixed n32 structure passing when structures + partially fit in registers. + +Wed Oct 9 13:49:25 1996 Anthony Green + + * objects.mak: Added n32.o. + + * n32.S: Created. + + * ffi.c (ffi_prep_args): Added magic to support proper + n32 processing. + +Tue Oct 8 10:37:35 1996 Anthony Green + + * ffi.c: Moved ffi_type definitions to types.c. + (ffi_prep_args): Fixed type promotion bug. + + * o32.S: This code is only built for o32 compiles. + A lot of the #define cruft has moved to ffi_mips.h. + + * ffi.c (ffi_prep_cif_machdep): Fixed arg flags. Second arg + is only processed if the first is either a float or double. + +Mon Oct 7 15:33:59 1996 Anthony Green + + * o32.S: Modified to compile under each of o32, n32 and n64. + + * ffi.c (FFI_*_TYPEDEF): Removed redundant ';' + +Fri Oct 4 09:53:25 1996 Anthony Green + + * ffi.c (ffi_call): Removed FFI_ABI arg, and swapped + remaining args. + +Wed Oct 2 17:41:22 1996 Anthony Green + + * o32.S: Removed crufty definitions. + +Wed Oct 2 12:53:42 1996 Anthony Green + + * ffi.c (ffi_prep_cif): cif->rvalue no longer initialized to NULL. + (ffi_prep_cif_machdep): Moved all machine independent cif processing + to src/prep_cif.c. Introduced ffi_prep_cif_machdep. Return types + of FFI_TYPE_STRUCT are no different than FFI_TYPE_INT. + +Tue Oct 1 17:11:02 1996 Anthony Green + + * ffi.c, o32.S, object.mak: Created + +--- libffi/src/sparc ------------------------------------------------------ + +Tue Feb 24 16:33:18 1998 Anthony Green + + * ffi.c (ffi_prep_args): Added long double support. + +Thu May 8 16:53:58 1997 Anthony Green + + * objects.mak: Removed. + +Thu May 1 16:07:56 1997 Anthony Green + + * v8.S: Fixed minor portability problem reported by + Russ McManus . + +Tue Nov 26 14:12:43 1996 Anthony Green + + * v8.S: Used STACKFRAME define elsewhere. + + * ffi.c (ffi_prep_args): Zero out space when USING_PURIFY + is set. + (ffi_prep_cif_machdep): Allocate the correct stack frame + space for functions with < 6 args. + +Tue Oct 29 15:08:55 1996 Anthony Green + + * ffi.c (ffi_prep_args): int z is now size_t z. + +Mon Oct 14 13:31:24 1996 Anthony Green + + * v8.S (ffi_call_V8): Gordon rewrites this again. It looks + great now. + + * ffi.c (ffi_call): The comment about hijacked registers + is no longer valid after gordoni hacked v8.S. + + * v8.S (ffi_call_V8): Rewrote with gordoni. Much simpler. + + * v8.S, ffi.c: ffi_call() had changed to accept more than + two args, so v8.S had to change (because it hijacks incoming + arg registers). + + * ffi.c: Interface changes based on feedback from Jim Blandy. + +Thu Oct 10 17:48:16 1996 Anthony Green + + * ffi.c, v8.S, objects.mak: Created. + + diff --git a/native/libffi/ChangeLog.libgcj b/native/libffi/ChangeLog.libgcj deleted file mode 100644 index ea5d02f19b..0000000000 --- a/native/libffi/ChangeLog.libgcj +++ /dev/null @@ -1,40 +0,0 @@ -2004-01-14 Kelley Cook - - * configure.in: Add in AC_PREREQ(2.13) - -2003-02-20 Alexandre Oliva - - * configure.in: Propagate ORIGINAL_LD_FOR_MULTILIBS to - config.status. - * configure: Rebuilt. - -2002-01-27 Alexandre Oliva - - * configure.in (toolexecdir, toolexeclibdir): Set and AC_SUBST. - Remove USE_LIBDIR conditional. - * Makefile.am (toolexecdir, toolexeclibdir): Don't override. - * Makefile.in, configure: Rebuilt. - -Mon Aug 9 18:33:38 1999 Rainer Orth - - * include/Makefile.in: Rebuilt. - * Makefile.in: Rebuilt - * Makefile.am (toolexeclibdir): Add $(MULTISUBDIR) even for native - builds. - Use USE_LIBDIR. - - * configure: Rebuilt. - * configure.in (USE_LIBDIR): Define for native builds. - Use lowercase in configure --help explanations. - -1999-08-08 Anthony Green - - * include/ffi.h.in (FFI_FN): Remove `...'. - -1999-08-08 Anthony Green - - * Makefile.in: Rebuilt. - * Makefile.am (AM_CFLAGS): Compile with -fexceptions. - - * src/x86/sysv.S: Add exception handling metadata. - diff --git a/native/libffi/ChangeLog.old b/native/libffi/ChangeLog.old new file mode 100644 index 0000000000..8216dc8194 --- /dev/null +++ b/native/libffi/ChangeLog.old @@ -0,0 +1,7410 @@ +<<<<<<< HEAD:native/libffi/ChangeLog.libffi-3.1 +======= +Libffi change logs used to be maintained in separate ChangeLog files. +These days we generate them directly from the git commit messages. +The old ChangeLog files are saved here in order to maintain the historical +record. + +============================================================================= +From the old ChangeLog.libffi-3.1 file... + +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878:native/libffi/ChangeLog.old +2014-03-16 Josh Triplett + + * ChangeLog: Archive to ChangeLog.libffi-3.1 and delete. Future + changelogs will come from git, with autogenerated snapshots shipped in + distributed tarballs. + +2014-03-16 Josh Triplett + + Add support for stdcall, thiscall, and fastcall on non-Windows + x86-32. + + Linux supports the stdcall calling convention, either via + functions explicitly declared with the stdcall attribute, or via + code compiled with -mrtd which effectively makes stdcall the + default. + + This introduces FFI_STDCALL, FFI_THISCALL, and FFI_FASTCALL on + non-Windows x86-32 platforms, as non-default calling conventions. + + * Makefile.am: Compile in src/x86/win32.S on non-Windows x86-32. + * src/x86/ffitarget.h: Add FFI_STDCALL, FFI_THISCALL, and + FFI_FASTCALL on non-Windows x86-32. Increase trampoline size to + accomodate these calling conventions, and unify some ifdeffery. + * src/x86/ffi.c: Add support for FFI_STDCALL, FFI_THISCALL, and + FFI_FASTCALL on non-Windows x86-32 platforms; update ifdeffery. + * src/x86/win32.S: Support compiling on non-Windows x86-32 + platforms. On those platforms, avoid redefining the SYSV symbols + already provided by src/x86/sysv.S. + * testsuite/libffi.call/closure_stdcall.c: Run on non-Windows. + #define __stdcall if needed. + * testsuite/libffi.call/closure_thiscall.c: Run on non-Windows. + #define __fastcall if needed. + * testsuite/libffi.call/fastthis1_win32.c: Run on non-Windows. + * testsuite/libffi.call/fastthis2_win32.c: Ditto. + * testsuite/libffi.call/fastthis3_win32.c: Ditto. + * testsuite/libffi.call/many2_win32.c: Ditto. + * testsuite/libffi.call/many_win32.c: Ditto. + * testsuite/libffi.call/strlen2_win32.c: Ditto. + * testsuite/libffi.call/strlen_win32.c: Ditto. + * testsuite/libffi.call/struct1_win32.c: Ditto. + * testsuite/libffi.call/struct2_win32.c: Ditto. + +2014-03-16 Josh Triplett + + * prep_cif.c: Remove unnecessary ifdef for X86_WIN32. + ffi_prep_cif_core had a special case for X86_WIN32, checking for + FFI_THISCALL in addition to the FFI_FIRST_ABI-to-FFI_LAST_ABI + range before returning FFI_BAD_ABI. However, on X86_WIN32, + FFI_THISCALL already falls in that range, making the special case + unnecessary. Remove it. + +2014-03-16 Josh Triplett + + * testsuite/libffi.call/closure_stdcall.c, + testsuite/libffi.call/closure_thiscall.c: Remove fragile stack + pointer checks. These files included inline assembly to save the + stack pointer before and after the call, and compare the values. + However, compilers can and do leave the stack in different states + for these two pieces of inline assembly, such as by saving a + temporary value on the stack across the call; observed with gcc + -Os, and verified as spurious through careful inspection of + disassembly. + +2014-03-16 Josh Triplett + + * testsuite/libffi.call/many.c: Avoid spurious failure due to + excess floating-point precision. + * testsuite/libffi.call/many_win32.c: Ditto. + +2014-03-16 Josh Triplett + + * libtool-ldflags: Re-add. + +2014-03-16 Josh Triplett + + * Makefile.in, aclocal.m4, compile, config.guess, config.sub, + configure, depcomp, include/Makefile.in, install-sh, + libtool-ldflags, ltmain.sh, m4/libtool.m4, m4/ltoptions.m4, + m4/ltsugar.m4, m4/ltversion.m4, m4/lt~obsolete.m4, + man/Makefile.in, mdate-sh, missing, testsuite/Makefile.in: Delete + autogenerated files from version control. + * .gitignore: Add autogenerated files. + * autogen.sh: New script to generate the autogenerated files. + * README: Document requirement to run autogen.sh when building + directly from version control. + * .travis.yml: Run autogen.sh + +2014-03-14 Anthony Green + + * configure, Makefile.in: Rebuilt. + +2014-03-10 Mike Hommey + + * configure.ac: Allow building for mipsel with Android NDK r8. + * Makefile.am (AM_MAKEFLAGS): Replace double quotes with single + quotes. + +2014-03-10 Landry Breuil + + * configure.ac: Ensure the linker supports @unwind sections in libffi. + +2014-03-01 Anthony Green + + * Makefile.am (EXTRA_DIST): Replace old scripts with + generate-darwin-source-and-headers.py. + * Makefile.in: Rebuilt. + +2014-02-28 Anthony Green + + * Makefile.am (AM_CFLAGS): Reintroduce missing -DFFI_DEBUG for + --enable-debug builds. + * Makefile.in: Rebuilt. + +2014-02-28 Makoto Kato + + * src/closures.c: Fix build failure when using clang for Android. + +2014-02-28 Marcin Wojdyr + + * libffi.pc.in (toolexeclibdir): use -L${toolexeclibdir} instead + of -L${libdir}. + +2014-02-28 Paulo Pizarro + + * src/bfin/sysv.S: Calling functions in shared libraries requires + considering the GOT. + +2014-02-28 Josh Triplett + + * src/x86/ffi64.c (classify_argument): Handle case where + FFI_TYPE_LONGDOUBLE == FFI_TYPE_DOUBLE. + +2014-02-28 Anthony Green + + * ltmain.sh: Generate with libtool-2.4.2.418. + * m4/libtool.m4, m4/ltoptions.m4, m4/ltversion.m4: Ditto. + * configure: Rebuilt. + +2014-02-28 Dominik Vogt + + * configure.ac (AC_ARG_ENABLE struct): Fix typo in help + message. + (AC_ARG_ENABLE raw_api): Ditto. + * configure, fficonfig.h.in: Rebuilt. + +2014-02-28 Will Newton + + * src/arm/sysv.S: Initialize IP register with FP. + +2014-02-28 Yufeng Zhang + + * src/aarch64/sysv.S (ffi_closure_SYSV): Use x29 as the + main CFA reg; update cfi_rel_offset. + +2014-02-15 Marcus Comstedt + + * src/powerpc/ffi_linux64.c, src/powerpc/linux64_closure.S: Remove + assumption on contents of r11 in closure. + +2014-02-09 Heiher + + * src/mips/n32.S: Fix call floating point va function. + +2014-01-21 Zachary Waldowski + + * src/aarch64/ffi.c: Fix missing semicolons on assertions under + debug mode. + +2013-12-30 Zachary Waldowski + + * .gitignore: Exclude darwin_* generated source and build_* trees. + * src/aarch64/ffi.c, src/arm/ffi.c, src/x86/ffi.c: Inhibit Clang + previous prototype warnings. + * src/arm/ffi.c: Prevent NULL dereference, fix short type warning + * src/dlmalloc.c: Fix warnings from set_segment_flags return type, + and the native use of size_t for malloc on platforms + * src/arm/sysv.S: Use unified syntax. Clang clean-ups for + ARM_FUNC_START. + * generate-osx-source-and-headers.py: Remove. + * build-ios.sh: Remove. + * libffi.xcodeproj/project.pbxproj: Rebuild targets. Include + x86_64+aarch64 pieces in library. Export headers properly. + * src/x86/ffi64.c: More Clang warning clean-ups. + * src/closures.c (open_temp_exec_file_dir): Use size_t. + * src/prep_cif.c (ffi_prep_cif_core): Cast ALIGN result. + * src/aarch64/sysv.S: Use CNAME for global symbols. Only use + .size for ELF targets. + * src/aarch64/ffi.c: Clean up for double == long double. Clean up + from Clang warnings. Use Clang cache invalidation builtin. Use + size_t in place of unsigned in many places. Accommodate for + differences in Apple AArch64 ABI. + +2013-12-02 Daniel Rodríguez Troitiño + + * generate-darwin-source-and-headers.py: Clean up, modernize, + merged version of previous scripts. + +2013-11-21 Anthony Green + + * configure, Makefile.in, include/Makefile.in, include/ffi.h.in, + man/Makefile.in, testsuite/Makefile.in, fficonfig.h.in: Rebuilt. + +2013-11-21 Alan Modra + + * Makefile.am (EXTRA_DIST): Add new src/powerpc files. + (nodist_libffi_la_SOURCES ): Likewise. + * configure.ac (HAVE_LONG_DOUBLE_VARIANT): Define for powerpc. + * include/ffi.h.in (ffi_prep_types): Declare. + * src/prep_cif.c (ffi_prep_cif_core): Call ffi_prep_types. + * src/types.c (FFI_NONCONST_TYPEDEF): Define and use for + HAVE_LONG_DOUBLE_VARIANT. + * src/powerpc/ffi_powerpc.h: New file. + * src/powerpc/ffi.c: Split into.. + * src/powerpc/ffi_sysv.c: ..new file, and.. + * src/powerpc/ffi_linux64.c: ..new file, rewriting parts. + * src/powerpc/ffitarget.h (enum ffi_abi): Rewrite powerpc ABI + selection as bits controlling features. + * src/powerpc/linux64.S: For consistency, use POWERPC64 rather + than __powerpc64__. + * src/powerpc/linux64_closure.S: Likewise. + * src/powerpc/ppc_closure.S: Likewise. Move .note.FNU-stack + inside guard. + * src/powerpc/sysv.S: Likewise. + * configure: Regenerate. + * fficonfig.h.in: Regenerate. + * Makefile.in: Regenerate. + +2013-11-20 Alan Modra + + * src/powerpc/ffi.c (ffi_prep_cif_machdep_core): Use + NUM_FPR_ARG_REGISTERS64 and NUM_GPR_ARG_REGISTERS64 not their + 32-bit versions for 64-bit code. + * src/powerpc/linux64_closure.S: Don't use the return value area + as a parameter save area on ELFv2. + +2013-11-18 Iain Sandoe + + * src/powerpc/darwin.S (EH): Correct use of pcrel FDE encoding. + * src/powerpc/darwin_closure.S (EH): Likewise. Modernise picbase + labels. + +2013-11-18 Anthony Green + + * src/arm/ffi.c (ffi_call): Hoist declaration of temp to top of + function. + * src/arm/ffi.c (ffi_closure_inner): Moderize function declaration + to appease compiler. + Thanks for Gregory P. Smith . + +2013-11-18 Anthony Green + + * README (tested): Mention PowerPC ELFv2. + +2013-11-16 Alan Modra + + * src/powerpc/ppc_closure.S: Move errant #endif to where it belongs. + Don't bl .Luint128. + +2013-11-16 Alan Modra + + * src/powerpc/ffi.c (ffi_prep_cif_machdep_core): Use #if _CALL_ELF + test to select parameter save sizing for ELFv2 vs. ELFv1. + * src/powerpc/ffitarget.h (FFI_V2_TYPE_FLOAT_HOMOG, + FFI_V2_TYPE_DOUBLE_HOMOG, FFI_V2_TYPE_SMALL_STRUCT): Define. + (FFI_TRAMPOLINE_SIZE): Define variant for ELFv2. + * src/powerpc/ffi.c (FLAG_ARG_NEEDS_PSAVE): Define. + (discover_homogeneous_aggregate): New function. + (ffi_prep_args64): Adjust start of param save area for ELFv2. + Handle homogenous floating point struct parms. + (ffi_prep_cif_machdep_core): Adjust space calculation for ELFv2. + Handle ELFv2 return values. Set FLAG_ARG_NEEDS_PSAVE. Handle + homogenous floating point structs. + (ffi_call): Increase size of smst_buffer for ELFv2. Handle ELFv2. + (flush_icache): Compile for ELFv2. + (ffi_prep_closure_loc): Set up ELFv2 trampoline. + (ffi_closure_helper_LINUX64): Don't return all structs directly + to caller. Handle homogenous floating point structs. Handle + ELFv2 struct return values. + * src/powerpc/linux64.S (ffi_call_LINUX64): Set up r2 for + ELFv2. Adjust toc save location. Call function pointer using + r12. Handle FLAG_RETURNS_SMST. Don't predict branches. + * src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Set up r2 + for ELFv2. Define ELFv2 versions of STACKFRAME, PARMSAVE, and + RETVAL. Handle possibly missing parameter save area. Handle + ELFv2 return values. + (.note.GNU-stack): Move inside outer #ifdef. + +2013-11-16 Alan Modra + + * src/powerpc/ffi.c (ffi_prep_cif_machdep): Revert 2013-02-08 + change. Do not consume an int arg when returning a small struct + for FFI_SYSV ABI. + (ffi_call): Only use bounce buffer when FLAG_RETURNS_SMST. + Properly copy bounce buffer to destination. + * src/powerpc/sysv.S: Revert 2013-02-08 change. + * src/powerpc/ppc_closure.S: Remove stray '+'. + +2013-11-16 Alan Modra + + * src/powerpc/ffi.c (ffi_prep_args64): Align struct parameters + according to __STRUCT_PARM_ALIGN__. + (ffi_prep_cif_machdep_core): Likewise. + (ffi_closure_helper_LINUX64): Likewise. + +2013-11-16 Alan Modra + + * src/powerpc/linux64.S (ffi_call_LINUX64): Tweak restore of r28. + (.note.GNU-stack): Move inside outer #ifdef. + * src/powerpc/linux64_closure.S (STACKFRAME, PARMSAVE, + RETVAL): Define and use throughout. + (ffi_closure_LINUX64): Save fprs before buying stack. + (.note.GNU-stack): Move inside outer #ifdef. + +2013-11-16 Alan Modra + + * src/powerpc/ffitarget.h (FFI_TARGET_SPECIFIC_VARIADIC): Define. + (FFI_EXTRA_CIF_FIELDS): Define. + * src/powerpc/ffi.c (ffi_prep_args64): Save fprs as per the + ABI, not to both fpr and param save area. + (ffi_prep_cif_machdep_core): Renamed from ffi_prep_cif_machdep. + Keep initial flags. Formatting. Remove dead FFI_LINUX_SOFT_FLOAT + code. + (ffi_prep_cif_machdep, ffi_prep_cif_machdep_var): New functions. + (ffi_closure_helper_LINUX64): Pass floating point as per ABI, + not to both fpr and parameter save areas. + + * libffi/testsuite/libffi.call/cls_double_va.c (main): Correct + function cast and don't call ffi_prep_cif. + * libffi/testsuite/libffi.call/cls_longdouble_va.c (main): Likewise. + +2013-11-15 Andrew Haley + + * doc/libffi.texi (Closure Example): Fix the sample code. + * doc/libffi.info, doc/stamp-vti, doc/version.texi: Rebuilt. + +2013-11-15 Andrew Haley + + * testsuite/libffi.call/va_struct1.c (main): Fix broken test. + * testsuite/libffi.call/cls_uint_va.c (cls_ret_T_fn): Likewise + * testsuite/libffi.call/cls_struct_va1.c (test_fn): Likewise. + * testsuite/libffi.call/va_1.c (main): Likewise. + +2013-11-14 David Schneider + + * src/arm/ffi.c: Fix register allocation for mixed float and + doubles. + * testsuite/libffi.call/cls_many_mixed_float_double.c: Testcase + for many mixed float and double arguments. + +2013-11-13 Alan Modra + + * doc/libffi.texi (Simple Example): Correct example code. + * doc/libffi.info, doc/stamp-vti, doc/version.texi: Rebuilt. + +2013-11-13 Anthony Green + + * include/ffi_common.h: Respect HAVE_ALLOCA_H for GNU compiler + based build. (Thanks to tmr111116 on github) + +2013-11-09 Anthony Green + + * m4/libtool.m4: Refresh. + * configure, Makefile.in: Rebuilt. + * README: Add more notes about next release. + +2013-11-09 Shigeharu TAKENO + + * m4/ax_gcc_archflag.m4 (ax_gcc_arch): Don't recognize + UltraSPARC-IIi as ultrasparc3. + +2013-11-06 Mark Kettenis + + * src/x86/freebsd.S (ffi_call_SYSV): Align the stack pointer to + 16-bytes. + +2013-11-06 Konstantin Belousov + + * src/x86/freebsd.S (ffi_closure_raw_SYSV): Mark the assembler + source as not requiring executable stack. + +2013-11-02 Anthony Green + + * doc/libffi.texi (The Basics): Clarify return value buffer size + requirements. Also, NULL result buffer pointers are no longer + supported. + * doc/libffi.info: Rebuilt. + +2013-11-02 Mischa Jonker + + * Makefile.am (nodist_libffi_la_SOURCES): Fix build error. + * Makefile.in: Rebuilt. + +2013-11-02 David Schneider + + * src/arm/ffi.c: more robust argument handling for closures on arm hardfloat + * testsuite/libffi.call/many_mixed.c: New file. + * testsuite/libffi.call/cls_many_mixed_args.c: More tests. + +2013-11-02 Vitaly Budovski + + * src/x86/ffi.c (ffi_prep_cif_machdep): Don't align stack for win32. + +2013-10-23 Mark H Weaver + + * src/mips/ffi.c: Fix handling of uint32_t arguments on the + MIPS N32 ABI. + +2013-10-13 Sandra Loosemore + + * README: Add Nios II to table of supported platforms. + * Makefile.am (EXTRA_DIST): Add nios2 files. + (nodist_libffi_la_SOURCES): Likewise. + * Makefile.in: Regenerated. + * configure.ac (nios2*-linux*): New host. + (NIOS2): Add AM_CONDITIONAL. + * configure: Regenerated. + * src/nios2/ffi.c: New. + * src/nios2/ffitarget.h: New. + * src/nios2/sysv.S: New. + * src/prep_cif.c (initialize_aggregate): Handle extra structure + alignment via FFI_AGGREGATE_ALIGNMENT. + (ffi_prep_cif_core): Conditionalize structure return for NIOS2. + +2013-10-10 Sandra Loosemore + + * testsuite/libffi.call/cls_many_mixed_args.c (cls_ret_double_fn): + Fix uninitialized variable. + +2013-10-11 Marcus Shawcroft + + * testsuite/libffi.call/many.c (many): Replace * with +. + +2013-10-08 Ondřej Bílka + + * src/aarch64/ffi.c, src/aarch64/sysv.S, src/arm/ffi.c, + src/arm/gentramp.sh, src/bfin/sysv.S, src/closures.c, + src/dlmalloc.c, src/ia64/ffi.c, src/microblaze/ffi.c, + src/microblaze/sysv.S, src/powerpc/darwin_closure.S, + src/powerpc/ffi.c, src/powerpc/ffi_darwin.c, src/sh/ffi.c, + src/tile/tile.S, testsuite/libffi.call/nested_struct11.c: Fix + spelling errors. + +2013-10-08 Anthony Green + + * aclocal.m4, compile, config.guess, config.sub, depcomp, + install-sh, mdate-sh, missing, texinfo.tex: Update from upstream. + * configure.ac: Update version to 3.0.14-rc0. + * Makefile.in, configure, Makefile.in, include/Makefile.in, + man/Makefile.in, testsuite/Makefile.in: Rebuilt. + * README: Mention M88K and VAX. + +2013-07-15 Miod Vallat + + * Makefile.am, + configure.ac, + src/m88k/ffi.c, + src/m88k/ffitarget.h, + src/m88k/obsd.S, + src/vax/elfbsd.S, + src/vax/ffi.c, + src/vax/ffitarget.h: Add m88k and vax support. + +2013-06-24 Alan Modra + + * src/powerpc/ffi.c (ffi_prep_args_SYSV): Move var declaration + before statements. + (ffi_prep_args64): Support little-endian. + (ffi_closure_helper_SYSV, ffi_closure_helper_LINUX64): Likewise. + * src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Likewise. + * src/powerpc/ppc_closure.S (ffi_closure_SYSV): Likewise. + +2013-06-12 Mischa Jonker + + * configure.ac: Add support for ARC. + * Makefile.am: Likewise. + * README: Add ARC details. + * src/arc/arcompact.S: New. + * src/arc/ffi.c: Likewise. + * src/arc/ffitarget.h: Likewise. + +2013-03-28 David Schneider + + * src/arm/ffi.c: Fix support for ARM hard-float calling convention. + * src/arm/sysv.S: call different methods for SYSV and VFP ABIs. + * testsuite/libffi.call/cls_many_mixed_args.c: testcase for a closure with + mixed arguments, many doubles. + * testsuite/libffi.call/many_double.c: testcase for calling a function using + more than 8 doubles. + * testcase/libffi.call/many.c: use absolute value to check result against an + epsilon + +2013-03-17 Anthony Green + + * README: Update for 3.0.13. + * configure.ac: Ditto. + * configure: Rebuilt. + * doc/*: Update version. + +2013-03-17 Dave Korn + + * src/closures.c (is_emutramp_enabled + [!FFI_MMAP_EXEC_EMUTRAMP_PAX]): Move default definition outside + enclosing #if scope. + +2013-03-17 Anthony Green + + * configure.ac: Only modify toolexecdir in certain cases. + * configure: Rebuilt. + +2013-03-16 Gilles Talis + + * src/powerpc/ffi.c (ffi_prep_args_SYSV): Don't use + fparg_count,etc on __NO_FPRS__ targets. + +2013-03-16 Alan Hourihane + + * src/m68k/sysv.S (epilogue): Don't use extb instruction on + m680000 machines. + +2013-03-16 Alex Gaynor + + * src/x86/ffi.c (ffi_prep_cif_machdep): Always align stack. + +2013-03-13 Markos Chandras + + * configure.ac: Add support for Imagination Technologies Meta. + * Makefile.am: Likewise. + * README: Add Imagination Technologies Meta details. + * src/metag/ffi.c: New. + * src/metag/ffitarget.h: Likewise. + * src/metag/sysv.S: Likewise. + +2013-02-24 Andreas Schwab + + * doc/libffi.texi (Structures): Fix missing category argument of + @deftp. + +2013-02-11 Anthony Green + + * configure.ac: Update release number to 3.0.12. + * configure: Rebuilt. + * README: Update release info. + +2013-02-10 Anthony Green + + * README: Add Moxie. + * src/moxie/ffi.c: Created. + * src/moxie/eabi.S: Created. + * src/moxie/ffitarget.h: Created. + * Makefile.am (nodist_libffi_la_SOURCES): Add Moxie. + * Makefile.in: Rebuilt. + * configure.ac: Add Moxie. + * configure: Rebuilt. + * testsuite/libffi.call/huge_struct.c: Disable format string + warnings for moxie*-*-elf tests. + +2013-02-10 Anthony Green + + * Makefile.am (LTLDFLAGS): Fix reference. + * Makefile.in: Rebuilt. + +2013-02-10 Anthony Green + + * README: Update supported platforms. Update test results link. + +2013-02-09 Anthony Green + + * testsuite/libffi.call/negint.c: Remove forced -O2. + * testsuite/libffi.call/many2.c (foo): Remove GCCism. + * testsuite/libffi.call/ffitest.h: Add default PRIuPTR definition. + + * src/sparc/v8.S (ffi_closure_v8): Import ancient ulonglong + closure return type fix developed by Martin v. Löwis for cpython + fork. + +2013-02-08 Andreas Tobler + + * src/powerpc/ffi.c (ffi_prep_cif_machdep): Fix small struct + support. + * src/powerpc/sysv.S: Ditto. + +2013-02-08 Anthony Green + + * testsuite/libffi.call/cls_longdouble.c: Remove xfail for + arm*-*-*. + +2013-02-08 Anthony Green + + * src/sparc/ffi.c (ffi_prep_closure_loc): Fix cache flushing for GCC. + +2013-02-08 Matthias Klose + + * man/ffi_prep_cif.3: Clean up for debian linter. + +2013-02-08 Peter Bergner + + * src/powerpc/ffi.c (ffi_prep_args_SYSV): Account for FP args pushed + on the stack. + +2013-02-08 Anthony Green + + * Makefile.am (EXTRA_DIST): Add missing files. + * testsuite/Makefile.am (EXTRA_DIST): Ditto. + * Makefile.in: Rebuilt. + +2013-02-08 Anthony Green + + * configure.ac: Move sparc asm config checks to within functions + for compatibility with sun tools. + * configure: Rebuilt. + * src/sparc/ffi.c (ffi_prep_closure_loc): Flush cache on v9 + systems. + * src/sparc/v8.S (ffi_flush_icache): Implement a sparc v9 cache + flusher. + +2013-02-08 Nathan Rossi + + * src/microblaze/ffi.c (ffi_closure_call_SYSV): Fix handling of + small big-endian structures. + (ffi_prep_args): Ditto. + +2013-02-07 Anthony Green + + * src/sparc/v8.S (ffi_call_v8): Fix typo from last patch + (effectively hiding ffi_call_v8). + +2013-02-07 Anthony Green + + * configure.ac: Update bug reporting address. + * configure.in: Rebuild. + + * src/sparc/v8.S (ffi_flush_icache): Out-of-line cache flusher for + Sun compiler. + * src/sparc/ffi.c (ffi_call): Remove warning. + Call ffi_flush_icache for non-GCC builds. + (ffi_prep_closure_loc): Use ffi_flush_icache. + + * Makefile.am (EXTRA_DIST): Add libtool-ldflags. + * Makefile.in: Rebuilt. + * libtool-ldflags: New file. + +2013-02-07 Daniel Schepler + + * configure.ac: Correctly identify x32 systems as 64-bit. + * m4/libtool.m4: Remove libtool expr error. + * aclocal.m4, configure: Rebuilt. + +2013-02-07 Anthony Green + + * configure.ac: Fix GCC usage test. + * configure: Rebuilt. + * README: Mention LLVM/GCC x86_64 issue. + * testsuite/Makefile.in: Rebuilt. + +2013-02-07 Anthony Green + + * testsuite/libffi.call/cls_double_va.c (main): Replace // style + comments with /* */ for xlc compiler. + * testsuite/libffi.call/stret_large.c (main): Ditto. + * testsuite/libffi.call/stret_large2.c (main): Ditto. + * testsuite/libffi.call/nested_struct1.c (main): Ditto. + * testsuite/libffi.call/huge_struct.c (main): Ditto. + * testsuite/libffi.call/float_va.c (main): Ditto. + * testsuite/libffi.call/cls_struct_va1.c (main): Ditto. + * testsuite/libffi.call/cls_pointer_stack.c (main): Ditto. + * testsuite/libffi.call/cls_pointer.c (main): Ditto. + * testsuite/libffi.call/cls_longdouble_va.c (main): Ditto. + +2013-02-06 Anthony Green + + * man/ffi_prep_cif.3: Clean up for debian lintian checker. + +2013-02-06 Anthony Green + + * Makefile.am (pkgconfigdir): Add missing pkgconfig install bits. + * Makefile.in: Rebuild. + +2013-02-02 Mark H Weaver + + * src/x86/ffi64.c (ffi_call): Sign-extend integer arguments passed + via general purpose registers. + +2013-01-21 Nathan Rossi + + * README: Add MicroBlaze details. + * Makefile.am: Add MicroBlaze support. + * configure.ac: Likewise. + * src/microblaze/ffi.c: New. + * src/microblaze/ffitarget.h: Likewise. + * src/microblaze/sysv.S: Likewise. + +2013-01-21 Nathan Rossi + * testsuite/libffi.call/return_uc.c: Fixed issue. + +2013-01-21 Chris Zankel + + * README: Add Xtensa support. + * Makefile.am: Likewise. + * configure.ac: Likewise. + * Makefile.in Regenerate. + * configure: Likewise. + * src/prep_cif.c: Handle Xtensa. + * src/xtensa: New directory. + * src/xtensa/ffi.c: New file. + * src/xtensa/ffitarget.h: Ditto. + * src/xtensa/sysv.S: Ditto. + +2013-01-11 Anthony Green + + * src/powerpc/ffi_darwin.c (ffi_prep_args): Replace // style + comments with /* */ for xlc compiler. + * src/powerpc/aix.S (ffi_call_AIX): Ditto. + * testsuite/libffi.call/ffitest.h (allocate_mmap): Delete + deprecated inline function. + * testsuite/libffi.special/ffitestcxx.h: Ditto. + * README: Add update for AIX support. + +2013-01-11 Anthony Green + + * configure.ac: Robustify pc relative reloc check. + * m4/ax_cc_maxopt.m4: Don't -malign-double. This is an ABI + changing option for 32-bit x86. + * aclocal.m4, configure: Rebuilt. + * README: Update supported target list. + +2013-01-10 Anthony Green + + * README (tested): Add Compiler column to table. + +2013-01-10 Anthony Green + + * src/x86/ffi64.c (struct register_args): Make sse array and array + of unions for sunpro compiler compatibility. + +2013-01-10 Anthony Green + + * configure.ac: Test target platform size_t size. Handle both 32 + and 64-bit builds for x86_64-* and i?86-* targets (allowing for + CFLAG option to change default settings). + * configure, aclocal.m4: Rebuilt. + +2013-01-10 Anthony Green + + * testsuite/libffi.special/special.exp: Only run exception + handling tests when using GNU compiler. + + * m4/ax_compiler_vendor.m4: New file. + * configure.ac: Test for compiler vendor and don't use + AX_CFLAGS_WARN_ALL with the sun compiler. + * aclocal.m4, configure: Rebuilt. + +2013-01-10 Anthony Green + + * include/ffi_common.h: Don't use GCCisms to define types when + building with the SUNPRO compiler. + +2013-01-10 Anthony Green + + * configure.ac: Put local.exp in the right place. + * configure: Rebuilt. + + * src/x86/ffi.c: Update comment about regparm function attributes. + * src/x86/sysv.S (ffi_closure_SYSV): The SUNPRO compiler requires + that all function arguments be passed on the stack (no regparm + support). + +2013-01-08 Anthony Green + + * configure.ac: Generate local.exp. This sets CC_FOR_TARGET + when we are using the vendor compiler. + * testsuite/Makefile.am (EXTRA_DEJAGNU_SITE_CONFIG): Point to + ../local.exp. + * configure, testsuite/Makefile.in: Rebuilt. + + * testsuite/libffi.call/call.exp: Run tests with different + options, depending on whether or not we are using gcc or the + vendor compiler. + * testsuite/lib/libffi.exp (libffi-init): Set using_gcc based on + whether or not we are building/testing with gcc. + +2013-01-08 Anthony Green + + * configure.ac: Switch x86 solaris target to X86 by default. + * configure: Rebuilt. + +2013-01-08 Anthony Green + + * configure.ac: Fix test for read-only eh_frame. + * configure: Rebuilt. + +2013-01-08 Anthony Green + + * src/x86/sysv.S, src/x86/unix64.S: Only emit DWARF unwind info + when building with the GNU toolchain. + * testsuite/libffi.call/ffitest.h (CHECK): Fix for Solaris vendor + compiler. + +2013-01-07 Thorsten Glaser + + * testsuite/libffi.call/cls_uchar_va.c, + testsuite/libffi.call/cls_ushort_va.c, + testsuite/libffi.call/va_1.c: Testsuite fixes. + +2013-01-07 Thorsten Glaser + + * src/m68k/ffi.c (CIF_FLAGS_SINT8, CIF_FLAGS_SINT16): Define. + (ffi_prep_cif_machdep): Fix 8-bit and 16-bit signed calls. + * src/m68k/sysv.S (ffi_call_SYSV, ffi_closure_SYSV): Ditto. + +2013-01-04 Anthony Green + + * Makefile.am (AM_CFLAGS): Don't automatically add -fexceptions + and -Wall. This is set in the configure script after testing for + GCC. + * Makefile.in: Rebuilt. + +2013-01-02 rofl0r + + * src/powerpc/ffi.c (ffi_prep_cif_machdep): Fix build error on ppc + when long double == double. + +2013-01-02 Reini Urban + + * Makefile.am (libffi_la_LDFLAGS): Add -no-undefined to LDFLAGS + (required for shared libs on cygwin/mingw). + * Makefile.in: Rebuilt. + +2012-10-31 Alan Modra + + * src/powerpc/linux64_closure.S: Add new ABI support. + * src/powerpc/linux64.S: Likewise. + +2012-10-30 Magnus Granberg + Pavel Labushev + + * configure.ac: New options pax_emutramp + * configure, fficonfig.h.in: Regenerated + * src/closures.c: New function emutramp_enabled_check() and + checks. + +2012-10-30 Frederick Cheung + + * configure.ac: Enable FFI_MAP_EXEC_WRIT for Darwin 12 (mountain + lion) and future version. + * configure: Rebuild. + +2012-10-30 James Greenhalgh + Marcus Shawcroft + + * README: Add details of aarch64 port. + * src/aarch64/ffi.c: New. + * src/aarch64/ffitarget.h: Likewise. + * src/aarch64/sysv.S: Likewise. + * Makefile.am: Support aarch64. + * configure.ac: Support aarch64. + * Makefile.in, configure: Rebuilt. + +2012-10-30 James Greenhalgh + Marcus Shawcroft + + * testsuite/lib/libffi.exp: Add support for aarch64. + * testsuite/libffi.call/cls_struct_va1.c: New. + * testsuite/libffi.call/cls_uchar_va.c: Likewise. + * testsuite/libffi.call/cls_uint_va.c: Likewise. + * testsuite/libffi.call/cls_ulong_va.c: Likewise. + * testsuite/libffi.call/cls_ushort_va.c: Likewise. + * testsuite/libffi.call/nested_struct11.c: Likewise. + * testsuite/libffi.call/uninitialized.c: Likewise. + * testsuite/libffi.call/va_1.c: Likewise. + * testsuite/libffi.call/va_struct1.c: Likewise. + * testsuite/libffi.call/va_struct2.c: Likewise. + * testsuite/libffi.call/va_struct3.c: Likewise. + +2012-10-12 Walter Lee + + * Makefile.am: Add TILE-Gx/TILEPro support. + * configure.ac: Likewise. + * Makefile.in: Regenerate. + * configure: Likewise. + * src/prep_cif.c (ffi_prep_cif_core): Handle TILE-Gx/TILEPro. + * src/tile: New directory. + * src/tile/ffi.c: New file. + * src/tile/ffitarget.h: Ditto. + * src/tile/tile.S: Ditto. + +2012-10-12 Matthias Klose + + * generate-osx-source-and-headers.py: Normalize whitespace. + +2012-09-14 David Edelsohn + + * configure: Regenerated. + +2012-08-26 Andrew Pinski + + PR libffi/53014 + * src/mips/ffi.c (ffi_prep_closure_loc): Allow n32 with soft-float and n64 with + soft-float. + +2012-08-08 Uros Bizjak + + * src/s390/ffi.c (ffi_prep_closure_loc): Don't ASSERT ABI test, + just return FFI_BAD_ABI when things are wrong. + +2012-07-18 H.J. Lu + + PR libffi/53982 + PR libffi/53973 + * src/x86/ffitarget.h: Check __ILP32__ instead of __LP64__ for x32. + (FFI_SIZEOF_JAVA_RAW): Defined to 4 for x32. + +2012-05-16 H.J. Lu + + * configure: Regenerated. + +2012-05-05 Nicolas Lelong + + * libffi.xcodeproj/project.pbxproj: Fixes. + * README: Update for iOS builds. + +2012-04-23 Alexandre Keunecke I. de Mendonca + + * configure.ac: Add Blackfin/sysv support + * Makefile.am: Add Blackfin/sysv support + * src/bfin/ffi.c: Add Blackfin/sysv support + * src/bfin/ffitarget.h: Add Blackfin/sysv support + +2012-04-11 Anthony Green + + * Makefile.am (EXTRA_DIST): Add new script. + * Makefile.in: Rebuilt. + +2012-04-11 Zachary Waldowski + + * generate-ios-source-and-headers.py, + libffi.xcodeproj/project.pbxproj: Support a Mac static library via + Xcode. Set iOS compatibility to 4.0. Move iOS trampoline + generation into an Xcode "run script" phase. Include both as + Xcode build scripts. Don't always regenerate config files. + +2012-04-10 Anthony Green + + * src/powerpc/ffi_darwin.c (ffi_prep_args): Add missing semicolon. + +2012-04-06 Anthony Green + + * Makefile.am (EXTRA_DIST): Add new iOS/xcode files. + * Makefile.in: Rebuilt. + +2012-04-06 Mike Lewis + + * generate-ios-source-and-headers.py: New file. + * libffi.xcodeproj/project.pbxproj: New file. + * README: Update instructions on building iOS binary. + * build-ios.sh: Delete. + +2012-04-06 Anthony Green + + * src/x86/ffi64.c (UINT128): Define differently for Intel and GNU + compilers, then use it. + +2012-04-06 H.J. Lu + + * m4/libtool.m4 (_LT_ENABLE_LOCK): Support x32. + +2012-04-06 Anthony Green + + * testsuite/Makefile.am (EXTRA_DIST): Add missing test cases. + * testsuite/Makefile.in: Rebuilt. + +2012-04-05 Zachary Waldowski + + * include/ffi.h.in: Add missing trampoline table fields. + * src/arm/sysv.S: Fix ENTRY definition, and wrap symbol references + in CNAME. + * src/x86/ffi.c: Wrap Windows specific code in ifdefs. + +2012-04-02 Peter Bergner + + * src/powerpc/ffi.c (ffi_prep_args_SYSV): Declare double_tmp. + Silence casting pointer to integer of different size warning. + Delete goto to previously deleted label. + (ffi_call): Silence possibly undefined warning. + (ffi_closure_helper_SYSV): Declare variable type. + +2012-04-02 Peter Rosin + + * src/x86/win32.S (ffi_call_win32): Sign/zero extend the return + value in the Intel version as is already done for the AT&T version. + (ffi_closure_SYSV): Likewise. + (ffi_closure_raw_SYSV): Likewise. + (ffi_closure_STDCALL): Likewise. + +2012-03-29 Peter Rosin + + * src/x86/win32.S (ffi_closure_raw_THISCALL): Unify the frame + generation, fix the ENDP label and remove the surplus third arg + from the 'lea' insn. + +2012-03-29 Peter Rosin + + * src/x86/win32.S (ffi_closure_raw_SYSV): Make the 'stubraw' label + visible outside the PROC, so that ffi_closure_raw_THISCALL can see + it. Also instruct the assembler to add a frame to the function. + +2012-03-23 Peter Rosin + + * Makefile.am (AM_CPPFLAGS): Add -DFFI_BUILDING. + * Makefile.in: Rebuilt. + * include/ffi.h.in [MSVC]: Add __declspec(dllimport) decorations + to all data exports, when compiling libffi clients using MSVC. + +2012-03-29 Peter Rosin + + * src/x86/ffitarget.h (ffi_abi): Add new ABI FFI_MS_CDECL and + make it the default for MSVC. + (FFI_TYPE_MS_STRUCT): New structure return convention. + * src/x86/ffi.c (ffi_prep_cif_machdep): Tweak the structure + return convention for FFI_MS_CDECL to be FFI_TYPE_MS_STRUCT + instead of an ordinary FFI_TYPE_STRUCT. + (ffi_prep_args): Treat FFI_TYPE_MS_STRUCT as FFI_TYPE_STRUCT. + (ffi_call): Likewise. + (ffi_prep_incoming_args_SYSV): Likewise. + (ffi_raw_call): Likewise. + (ffi_prep_closure_loc): Treat FFI_MS_CDECL as FFI_SYSV. + * src/x86/win32.S (ffi_closure_SYSV): For FFI_TYPE_MS_STRUCT, + return a pointer to the result structure in eax and don't pop + that pointer from the stack, the caller takes care of it. + (ffi_call_win32): Treat FFI_TYPE_MS_STRUCT as FFI_TYPE_STRUCT. + (ffi_closure_raw_SYSV): Likewise. + +2012-03-22 Peter Rosin + + * testsuite/libffi.call/closure_stdcall.c [MSVC]: Add inline + assembly version with Intel syntax. + * testsuite/libffi.call/closure_thiscall.c [MSVC]: Likewise. + +2012-03-23 Peter Rosin + + * testsuite/libffi.call/ffitest.h: Provide abstration of + __attribute__((fastcall)) in the form of a __FASTCALL__ + define. Define it to __fastcall for MSVC. + * testsuite/libffi.call/fastthis1_win32.c: Use the above. + * testsuite/libffi.call/fastthis2_win32.c: Likewise. + * testsuite/libffi.call/fastthis3_win32.c: Likewise. + * testsuite/libffi.call/strlen2_win32.c: Likewise. + * testsuite/libffi.call/struct1_win32.c: Likewise. + * testsuite/libffi.call/struct2_win32.c: Likewise. + +2012-03-22 Peter Rosin + + * src/x86/win32.S [MSVC] (ffi_closure_THISCALL): Remove the manual + frame on function entry, MASM adds one automatically. + +2012-03-22 Peter Rosin + + * testsuite/libffi.call/ffitest.h [MSVC]: Add kludge for missing + bits in the MSVC headers. + +2012-03-22 Peter Rosin + + * testsuite/libffi.call/cls_12byte.c: Adjust to the C89 style + with no declarations after statements. + * testsuite/libffi.call/cls_16byte.c: Likewise. + * testsuite/libffi.call/cls_18byte.c: Likewise. + * testsuite/libffi.call/cls_19byte.c: Likewise. + * testsuite/libffi.call/cls_1_1byte.c: Likewise. + * testsuite/libffi.call/cls_20byte.c: Likewise. + * testsuite/libffi.call/cls_20byte1.c: Likewise. + * testsuite/libffi.call/cls_24byte.c: Likewise. + * testsuite/libffi.call/cls_2byte.c: Likewise. + * testsuite/libffi.call/cls_3_1byte.c: Likewise. + * testsuite/libffi.call/cls_3byte1.c: Likewise. + * testsuite/libffi.call/cls_3byte2.c: Likewise. + * testsuite/libffi.call/cls_4_1byte.c: Likewise. + * testsuite/libffi.call/cls_4byte.c: Likewise. + * testsuite/libffi.call/cls_5_1_byte.c: Likewise. + * testsuite/libffi.call/cls_5byte.c: Likewise. + * testsuite/libffi.call/cls_64byte.c: Likewise. + * testsuite/libffi.call/cls_6_1_byte.c: Likewise. + * testsuite/libffi.call/cls_6byte.c: Likewise. + * testsuite/libffi.call/cls_7_1_byte.c: Likewise. + * testsuite/libffi.call/cls_7byte.c: Likewise. + * testsuite/libffi.call/cls_8byte.c: Likewise. + * testsuite/libffi.call/cls_9byte1.c: Likewise. + * testsuite/libffi.call/cls_9byte2.c: Likewise. + * testsuite/libffi.call/cls_align_double.c: Likewise. + * testsuite/libffi.call/cls_align_float.c: Likewise. + * testsuite/libffi.call/cls_align_longdouble.c: Likewise. + * testsuite/libffi.call/cls_align_longdouble_split.c: Likewise. + * testsuite/libffi.call/cls_align_longdouble_split2.c: Likewise. + * testsuite/libffi.call/cls_align_pointer.c: Likewise. + * testsuite/libffi.call/cls_align_sint16.c: Likewise. + * testsuite/libffi.call/cls_align_sint32.c: Likewise. + * testsuite/libffi.call/cls_align_sint64.c: Likewise. + * testsuite/libffi.call/cls_align_uint16.c: Likewise. + * testsuite/libffi.call/cls_align_uint32.c: Likewise. + * testsuite/libffi.call/cls_align_uint64.c: Likewise. + * testsuite/libffi.call/cls_dbls_struct.c: Likewise. + * testsuite/libffi.call/cls_pointer_stack.c: Likewise. + * testsuite/libffi.call/err_bad_typedef.c: Likewise. + * testsuite/libffi.call/huge_struct.c: Likewise. + * testsuite/libffi.call/nested_struct.c: Likewise. + * testsuite/libffi.call/nested_struct1.c: Likewise. + * testsuite/libffi.call/nested_struct10.c: Likewise. + * testsuite/libffi.call/nested_struct2.c: Likewise. + * testsuite/libffi.call/nested_struct3.c: Likewise. + * testsuite/libffi.call/nested_struct4.c: Likewise. + * testsuite/libffi.call/nested_struct5.c: Likewise. + * testsuite/libffi.call/nested_struct6.c: Likewise. + * testsuite/libffi.call/nested_struct7.c: Likewise. + * testsuite/libffi.call/nested_struct8.c: Likewise. + * testsuite/libffi.call/nested_struct9.c: Likewise. + * testsuite/libffi.call/stret_large.c: Likewise. + * testsuite/libffi.call/stret_large2.c: Likewise. + * testsuite/libffi.call/stret_medium.c: Likewise. + * testsuite/libffi.call/stret_medium2.c: Likewise. + * testsuite/libffi.call/struct1.c: Likewise. + * testsuite/libffi.call/struct1_win32.c: Likewise. + * testsuite/libffi.call/struct2.c: Likewise. + * testsuite/libffi.call/struct2_win32.c: Likewise. + * testsuite/libffi.call/struct3.c: Likewise. + * testsuite/libffi.call/struct4.c: Likewise. + * testsuite/libffi.call/struct5.c: Likewise. + * testsuite/libffi.call/struct6.c: Likewise. + * testsuite/libffi.call/struct7.c: Likewise. + * testsuite/libffi.call/struct8.c: Likewise. + * testsuite/libffi.call/struct9.c: Likewise. + * testsuite/libffi.call/testclosure.c: Likewise. + +2012-03-21 Peter Rosin + + * testsuite/libffi.call/float_va.c (float_va_fn): Use %f when + printing doubles (%lf is for long doubles). + (main): Likewise. + +2012-03-21 Peter Rosin + + * testsuite/lib/target-libpath.exp [*-*-cygwin*, *-*-mingw*] + (set_ld_library_path_env_vars): Add the library search dir to PATH + (and save PATH for later). + (restore_ld_library_path_env_vars): Restore PATH. + +2012-03-21 Peter Rosin + + * testsuite/lib/target-libpath.exp [*-*-cygwin*, *-*-mingw*] + (set_ld_library_path_env_vars): Add the library search dir to PATH + (and save PATH for later). + (restore_ld_library_path_env_vars): Restore PATH. + +2012-03-20 Peter Rosin + + * testsuite/libffi.call/strlen2_win32.c (main): Remove bug. + * src/x86/win32.S [MSVC] (ffi_closure_SYSV): Make the 'stub' label + visible outside the PROC, so that ffi_closure_THISCALL can see it. + +2012-03-20 Peter Rosin + + * testsuite/libffi.call/strlen2_win32.c (main): Remove bug. + * src/x86/win32.S [MSVC] (ffi_closure_SYSV): Make the 'stub' label + visible outside the PROC, so that ffi_closure_THISCALL can see it. + +2012-03-19 Alan Hourihane + + * src/m68k/ffi.c: Add MINT support. + * src/m68k/sysv.S: Ditto. + +2012-03-06 Chung-Lin Tang + + * src/arm/ffi.c (ffi_call): Add __ARM_EABI__ guard around call to + ffi_call_VFP(). + (ffi_prep_closure_loc): Add __ARM_EABI__ guard around use of + ffi_closure_VFP. + * src/arm/sysv.S: Add __ARM_EABI__ guard around VFP code. + +2012-03-19 chennam + + * src/powerpc/ffi_darwin.c (ffi_prep_closure_loc): Fix AIX closure + support. + +2012-03-13 Kaz Kojima + + * src/sh/ffi.c (ffi_prep_closure_loc): Don't ASSERT ABI test, + just return FFI_BAD_ABI when things are wrong. + * src/sh64/ffi.c (ffi_prep_closure_loc): Ditto. + +2012-03-09 David Edelsohn + + * src/powerpc/aix_closure.S (ffi_closure_ASM): Adjust for Darwin64 + change to return value of ffi_closure_helper_DARWIN and load type + from return type. + +2012-03-03 H.J. Lu + + * src/x86/ffi64.c (ffi_call): Cast the return value to unsigned + long. + (ffi_prep_closure_loc): Cast to 64bit address in trampoline. + (ffi_closure_unix64_inner): Cast return pointer to unsigned long + first. + + * src/x86/ffitarget.h (FFI_SIZEOF_ARG): Defined to 8 for x32. + (ffi_arg): Set to unsigned long long for x32. + (ffi_sarg): Set to long long for x32. + +2012-03-03 H.J. Lu + + * src/prep_cif.c (ffi_prep_cif_core): Properly check bad ABI. + +2012-03-03 Andoni Morales Alastruey + + * configure.ac: Add -no-undefined for both 32- and 64-bit x86 + windows-like hosts. + * configure: Rebuilt. + +2012-02-27 Mikael Pettersson + + PR libffi/52223 + * Makefile.am (FLAGS_TO_PASS): Define. + * Makefile.in: Regenerate. + +2012-02-23 Anthony Green + + * src/*/ffitarget.h: Ensure that users never include ffitarget.h + directly. + +2012-02-23 Kai Tietz + + PR libffi/52221 + * src/x86/ffi.c (ffi_closure_raw_THISCALL): New + prototype. + (ffi_prep_raw_closure_loc): Use ffi_closure_raw_THISCALL for + thiscall-convention. + (ffi_raw_call): Use ffi_prep_args_raw. + * src/x86/win32.S (ffi_closure_raw_THISCALL): Add + implementation for stub. + +2012-02-10 Kai Tietz + + * configure.ac (AM_LTLDFLAGS): Add -no-undefine for x64 + windows target. + * configure: Regenerated. + +2012-02-08 Kai Tietz + + * src/prep_cif.c (ffi_prep_cif): Allow for X86_WIN32 + also FFI_THISCALL. + * src/x86/ffi.c (ffi_closure_THISCALL): Add prototype. + (FFI_INIT_TRAMPOLINE_THISCALL): New trampoline code. + (ffi_prep_closure_loc): Add FFI_THISCALL support. + * src/x86/ffitarget.h (FFI_TRAMPOLINE_SIZE): Adjust size. + * src/x86/win32.S (ffi_closure_THISCALL): New closure code + for thiscall-calling convention. + * testsuite/libffi.call/closure_thiscall.c: New test. + +2012-01-28 Kai Tietz + + * src/libffi/src/x86/ffi.c (ffi_call_win32): Add new + argument to prototype for specify calling-convention. + (ffi_call): Add support for stdcall/thiscall convention. + (ffi_prep_args): Likewise. + (ffi_raw_call): Likewise. + * src/x86/ffitarget.h (ffi_abi): Add FFI_THISCALL and + FFI_FASTCALL. + * src/x86/win32.S (_ffi_call_win32): Add support for + fastcall/thiscall calling-convention calls. + * testsuite/libffi.call/fastthis1_win32.c: New test. + * testsuite/libffi.call/fastthis2_win32.c: New test. + * testsuite/libffi.call/fastthis3_win32.c: New test. + * testsuite/libffi.call/strlen2_win32.c: New test. + * testsuite/libffi.call/many2_win32.c: New test. + * testsuite/libffi.call/struct1_win32.c: New test. + * testsuite/libffi.call/struct2_win32.c: New test. + +2012-01-23 Uros Bizjak + + * src/alpha/ffi.c (ffi_prep_closure_loc): Check for bad ABI. + +2012-01-23 Anthony Green + Chris Young + + * configure.ac: Add Amiga support. + * configure: Rebuilt. + +2012-01-23 Dmitry Nadezhin + + * include/ffi_common.h (LIKELY, UNLIKELY): Fix definitions. + +2012-01-23 Andreas Schwab + + * src/m68k/sysv.S (ffi_call_SYSV): Properly test for plain + mc68000. Test for __HAVE_68881__ in addition to __MC68881__. + +2012-01-19 Jakub Jelinek + + PR rtl-optimization/48496 + * src/ia64/ffi.c (ffi_call): Fix up aliasing violations. + +2012-01-09 Rainer Orth + + * configure.ac (i?86-*-*): Set TARGET to X86_64. + * configure: Regenerate. + +2011-12-07 Andrew Pinski + + PR libffi/50051 + * src/mips/n32.S: Add ".set mips4". + +2011-11-21 Andreas Tobler + + * configure: Regenerate. + +2011-11-12 David Gilbert + + * doc/libffi.texi, include/ffi.h.in, include/ffi_common.h, + man/Makefile.am, man/ffi.3, man/ffi_prep_cif.3, + man/ffi_prep_cif_var.3, src/arm/ffi.c, src/arm/ffitarget.h, + src/cris/ffi.c, src/prep_cif.c, + testsuite/libffi.call/cls_double_va.c, + testsuite/libffi.call/cls_longdouble_va.c, + testsuite/libffi.call/float_va.c: Many changes to support variadic + function calls. + +2011-11-12 Kyle Moffett + + * src/powerpc/ffi.c, src/powerpc/ffitarget.h, + src/powerpc/ppc_closure.S, src/powerpc/sysv.S: Many changes for + softfloat powerpc variants. + +2011-11-12 Petr Salinger + + * configure.ac (FFI_EXEC_TRAMPOLINE_TABLE): Fix kfreebsd support. + * configure: Rebuilt. + +2011-11-12 Timothy Wall + + * src/arm/ffi.c (ffi_prep_args, ffi_prep_incoming_args_SYSV): Max + alignment of 4 for wince on ARM. + +2011-11-12 Kyle Moffett + Anthony Green + + * src/ppc/sysv.S, src/ppc/ffi.c: Remove use of ppc string + instructions (not available on some cores, like the PPC440). + +2011-11-12 Kimura Wataru + + * m4/ax_enable_builddir: Change from string comparison to numeric + comparison for wc output. + * configure.ac: Enable FFI_MMAP_EXEC_WRIT for darwin11 aka Mac OS + X 10.7. + * configure: Rebuilt. + +2011-11-12 Anthony Green + + * Makefile.am (AM_CCASFLAGS): Add -g option to build assembly + files with debug info. + * Makefile.in: Rebuilt. + +2011-11-12 Jasper Lievisse Adriaanse + + * README: Update list of supported OpenBSD systems. + +2011-11-12 Anthony Green + + * libtool-version: Update. + * Makefile.am (nodist_libffi_la_SOURCES): Add src/debug.c if + FFI_DEBUG. + (libffi_la_SOURCES): Remove src/debug.c + (EXTRA_DIST): Add src/debug.c + * Makefile.in: Rebuilt. + * README: Update for 3.0.11. + +2011-11-10 Richard Henderson + + * configure.ac (GCC_AS_CFI_PSEUDO_OP): Use it instead of inline check. + * configure, aclocal.m4: Rebuild. + +2011-09-04 Iain Sandoe + + PR libffi/49594 + * src/powerpc/darwin_closure.S (stubs): Make the stub binding + helper reference track the architecture pointer size. + +2011-08-25 Andrew Haley + + * src/arm/ffi.c (FFI_INIT_TRAMPOLINE): Remove hard-coded assembly + instructions. + * src/arm/sysv.S (ffi_arm_trampoline): Put them here instead. + +2011-07-11 Andrew Haley + + * src/arm/ffi.c (FFI_INIT_TRAMPOLINE): Clear icache. + +2011-06-29 Rainer Orth + + * testsuite/libffi.call/cls_double_va.c: Move PR number to comment. + * testsuite/libffi.call/cls_longdouble_va.c: Likewise. + +2011-06-29 Rainer Orth + + PR libffi/46660 + * testsuite/libffi.call/cls_double_va.c: xfail dg-output on + mips-sgi-irix6*. + * testsuite/libffi.call/cls_longdouble_va.c: Likewise. + +2011-06-14 Rainer Orth + + * testsuite/libffi.call/huge_struct.c (test_large_fn): Use PRIu8, + PRId8 instead of %hhu, %hhd. + * testsuite/libffi.call/ffitest.h [__alpha__ && __osf__] (PRId8, + PRIu8): Define. + [__sgi__] (PRId8, PRIu8): Define. + +2011-04-29 Rainer Orth + + * src/alpha/osf.S (UA_SI, FDE_ENCODING, FDE_ENCODE, FDE_ARANGE): + Define. + Use them to handle ELF vs. ECOFF differences. + [__osf__] (_GLOBAL__F_ffi_call_osf): Define. + +2011-03-30 Timothy Wall + + * src/powerpc/darwin.S: Fix unknown FDE encoding. + * src/powerpc/darwin_closure.S: ditto. + +2011-02-25 Anthony Green + + * src/powerpc/ffi.c (ffi_prep_closure_loc): Allow for more + 32-bit ABIs. + +2011-02-15 Anthony Green + + * m4/ax_cc_maxopt.m4: Don't -malign-double or use -ffast-math. + * configure: Rebuilt. + +2011-02-13 Ralf Wildenhues + + * configure: Regenerate. + +2011-02-13 Anthony Green + + * include/ffi_common.h (UNLIKELY, LIKELY): Define. + * src/x86/ffi64.c (UNLIKELY, LIKELY): Remove definition. + * src/prep_cif.c (UNLIKELY, LIKELY): Remove definition. + + * src/prep_cif.c (initialize_aggregate): Convert assertion into + FFI_BAD_TYPEDEF return. Initialize arg size and alignment to 0. + + * src/pa/ffi.c (ffi_prep_closure_loc): Don't ASSERT ABI test, + just return FFI_BAD_ABI when things are wrong. + * src/arm/ffi.c (ffi_prep_closure_loc): Ditto. + * src/powerpc/ffi.c (ffi_prep_closure_loc): Ditto. + * src/mips/ffi.c (ffi_prep_closure_loc): Ditto. + * src/ia64/ffi.c (ffi_prep_closure_loc): Ditto. + * src/avr32/ffi.c (ffi_prep_closure_loc): Ditto. + +2011-02-11 Anthony Green + + * src/sparc/ffi.c (ffi_prep_closure_loc): Don't ASSERT ABI test, + just return FFI_BAD_ABI when things are wrong. + +2012-02-11 Eric Botcazou + + * src/sparc/v9.S (STACKFRAME): Bump to 176. + +2011-02-09 Stuart Shelton + + http://bugs.gentoo.org/show_bug.cgi?id=286911 + * src/mips/ffitarget.h: Clean up error messages. + * src/java_raw_api.c (ffi_java_translate_args): Cast raw arg to + ffi_raw*. + * include/ffi.h.in: Add pragma for SGI compiler. + +2011-02-09 Anthony Green + + * configure.ac: Add powerpc64-*-darwin* support. + +2011-02-09 Anthony Green + + * README: Mention Interix. + +2011-02-09 Jonathan Callen + + * configure.ac: Add Interix to win32/cygwin/mingw case. + * configure: Ditto. + * src/closures.c: Treat Interix like Cygwin, instead of as a + generic win32. + +2011-02-09 Anthony Green + + * testsuite/libffi.call/err_bad_typedef.c: Remove xfail. + * testsuite/libffi.call/err_bad_abi.c: Remove xfail. + * src/x86/ffi64.c (UNLIKELY, LIKELY): Define. + (ffi_prep_closure_loc): Check for bad ABI. + * src/prep_cif.c (UNLIKELY, LIKELY): Define. + (initialize_aggregate): Check for bad types. + +2011-02-09 Landon Fuller + + * Makefile.am (EXTRA_DIST): Add build-ios.sh, src/arm/gentramp.sh, + src/arm/trampoline.S. + (nodist_libffi_la_SOURCES): Add src/arc/trampoline.S. + * configure.ac (FFI_EXEC_TRAMPOLINE_TABLE): Define. + * src/arm/ffi.c (ffi_trampoline_table) + (ffi_closure_trampoline_table_page, ffi_trampoline_table_entry) + (FFI_TRAMPOLINE_CODELOC_CONFIG, FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET) + (FFI_TRAMPOLINE_COUNT, ffi_trampoline_lock, ffi_trampoline_tables) + (ffi_trampoline_table_alloc, ffi_closure_alloc, ffi_closure_free): + Define for FFI_EXEC_TRAMPOLINE_TABLE case (iOS). + (ffi_prep_closure_loc): Handl FFI_EXEC_TRAMPOLINE_TABLE case + separately. + * src/arm/sysv.S: Handle Apple iOS host. + * src/closures.c: Handle FFI_EXEC_TRAMPOLINE_TABLE case. + * build-ios.sh: New file. + * fficonfig.h.in, configure, Makefile.in: Rebuilt. + * README: Mention ARM iOS. + +2011-02-08 Oren Held + + * src/dlmalloc.c (_STRUCT_MALLINFO): Define in order to avoid + redefinition of mallinfo on HP-UX. + +2011-02-08 Ginn Chen + + * src/sparc/ffi.c (ffi_call): Make compatible with Solaris Studio + aggregate return ABI. Flush cache. + (ffi_prep_closure_loc): Flush cache. + +2011-02-11 Anthony Green + + From Tom Honermann : + * src/powerpc/aix.S (ffi_call_AIX): Support for xlc toolchain on + AIX. Declare .ffi_prep_args. Insert nops after branch + instructions so that the AIX linker can insert TOC reload + instructions. + * src/powerpc/aix_closure.S: Declare .ffi_closure_helper_DARWIN. + +2011-02-08 Ed + + * src/powerpc/asm.h: Fix grammar nit in comment. + +2011-02-08 Uli Link + + * include/ffi.h.in (FFI_64_BIT_MAX): Define and use. + +2011-02-09 Rainer Orth + + PR libffi/46661 + * testsuite/libffi.call/cls_pointer.c (main): Cast void * to + uintptr_t first. + * testsuite/libffi.call/cls_pointer_stack.c (main): Likewise. + +2011-02-08 Rafael Avila de Espindola + + * configure.ac: Fix x86 test for pc related relocs. + * configure: Rebuilt. + +2011-02-07 Joel Sherrill + + * libffi/src/m68k/ffi.c: Add RTEMS support for cache flushing. + Handle case when CPU variant does not have long double support. + * libffi/src/m68k/sysv.S: Add support for mc68000, Coldfire, + and cores with soft floating point. + +2011-02-07 Joel Sherrill + + * configure.ac: Add mips*-*-rtems* support. + * configure: Regenerate. + * src/mips/ffitarget.h: Ensure needed constants are available + for targets which do not have sgidefs.h. + +2011-01-26 Dave Korn + + PR target/40125 + * configure.ac (AM_LTLDFLAGS): Add -bindir option for windows DLLs. + * configure: Regenerate. + +2010-12-18 Iain Sandoe + + PR libffi/29152 + PR libffi/42378 + * src/powerpc/darwin_closure.S: Provide Darwin64 implementation, + update comments. + * src/powerpc/ffitarget.h (POWERPC_DARWIN64): New, + (FFI_TRAMPOLINE_SIZE): Update for Darwin64. + * src/powerpc/darwin.S: Provide Darwin64 implementation, + update comments. + * src/powerpc/ffi_darwin.c: Likewise. + +2010-12-06 Rainer Orth + + * configure.ac (libffi_cv_as_ascii_pseudo_op): Use double + backslashes. + (libffi_cv_as_string_pseudo_op): Likewise. + * configure: Regenerate. + +2010-12-03 Chung-Lin Tang + + * src/arm/sysv.S (ffi_closure_SYSV): Add UNWIND to .pad directive. + (ffi_closure_VFP): Same. + (ffi_call_VFP): Move down to before ffi_closure_VFP. Add '.fpu vfp' + directive. + +2010-12-01 Rainer Orth + + * testsuite/libffi.call/ffitest.h [__sgi] (PRId64, PRIu64): Define. + (PRIuPTR): Define. + +2010-11-29 Richard Henderson + Rainer Orth + + * src/x86/sysv.S (FDE_ENCODING, FDE_ENCODE): Define. + (.eh_frame): Use FDE_ENCODING. + (.LASFDE1, .LASFDE2, LASFDE3): Simplify with FDE_ENCODE. + +2010-11-22 Jacek Caban + + * configure.ac: Check for symbol underscores on mingw-w64. + * configure: Rebuilt. + * src/x86/win64.S: Correctly access extern symbols in respect to + underscores. + +2010-11-15 Rainer Orth + + * testsuite/lib/libffi-dg.exp: Rename ... + * testsuite/lib/libffi.exp: ... to this. + * libffi/testsuite/libffi.call/call.exp: Don't load libffi-dg.exp. + * libffi/testsuite/libffi.special/special.exp: Likewise. + +2010-10-28 Chung-Lin Tang + + * src/arm/ffi.c (ffi_prep_args): Add VFP register argument handling + code, new parameter, and return value. Update comments. + (ffi_prep_cif_machdep): Add case for VFP struct return values. Add + call to layout_vfp_args(). + (ffi_call_SYSV): Update declaration. + (ffi_call_VFP): New declaration. + (ffi_call): Add VFP struct return conditions. Call ffi_call_VFP() + when ABI is FFI_VFP. + (ffi_closure_VFP): New declaration. + (ffi_closure_SYSV_inner): Add new vfp_args parameter, update call to + ffi_prep_incoming_args_SYSV(). + (ffi_prep_incoming_args_SYSV): Update parameters. Add VFP argument + case handling. + (ffi_prep_closure_loc): Pass ffi_closure_VFP to trampoline + construction under VFP hard-float. + (rec_vfp_type_p): New function. + (vfp_type_p): Same. + (place_vfp_arg): Same. + (layout_vfp_args): Same. + * src/arm/ffitarget.h (ffi_abi): Add FFI_VFP. Define FFI_DEFAULT_ABI + based on __ARM_PCS_VFP. + (FFI_EXTRA_CIF_FIELDS): Define for adding VFP hard-float specific + fields. + (FFI_TYPE_STRUCT_VFP_FLOAT): Define internally used type code. + (FFI_TYPE_STRUCT_VFP_DOUBLE): Same. + * src/arm/sysv.S (ffi_call_SYSV): Change call of ffi_prep_args() to + direct call. Move function pointer load upwards. + (ffi_call_VFP): New function. + (ffi_closure_VFP): Same. + + * testsuite/lib/libffi-dg.exp (check-flags): New function. + (dg-skip-if): New function. + * testsuite/libffi.call/cls_double_va.c: Skip if target is arm*-*-* + and compiler options include -mfloat-abi=hard. + * testsuite/libffi.call/cls_longdouble_va.c: Same. + +2010-10-01 Jakub Jelinek + + PR libffi/45677 + * src/x86/ffi64.c (ffi_prep_cif_machdep): Ensure cif->bytes is + a multiple of 8. + * testsuite/libffi.call/many2.c: New test. + +2010-08-20 Mark Wielaard + + * src/closures.c (open_temp_exec_file_mnt): Check if getmntent_r + returns NULL. + +2010-08-09 Andreas Tobler + + * configure.ac: Add target powerpc64-*-freebsd*. + * configure: Regenerate. + * testsuite/libffi.call/cls_align_longdouble_split.c: Pass + -mlong-double-128 only to linux targets. + * testsuite/libffi.call/cls_align_longdouble_split2.c: Likewise. + * testsuite/libffi.call/cls_longdouble.c: Likewise. + * testsuite/libffi.call/huge_struct.c: Likewise. + +2010-08-05 Dan Witte + + * Makefile.am: Pass FFI_DEBUG define to msvcc.sh for linking to the + debug CRT when --enable-debug is given. + * configure.ac: Define it. + * msvcc.sh: Translate -g and -DFFI_DEBUG appropriately. + +2010-08-04 Dan Witte + + * src/x86/ffitarget.h: Add X86_ANY define for all x86/x86_64 + platforms. + * src/x86/ffi.c: Remove redundant ifdef checks. + * src/prep_cif.c: Push stack space computation into src/x86/ffi.c + for X86_ANY so return value space doesn't get added twice. + +2010-08-03 Neil Rashbrooke + + * msvcc.sh: Don't pass -safeseh to ml64 because behavior is buggy. + +2010-07-22 Dan Witte + + * src/*/ffitarget.h: Make FFI_LAST_ABI one past the last valid ABI. + * src/prep_cif.c: Fix ABI assertion. + * src/cris/ffi.c: Ditto. + +2010-07-10 Evan Phoenix + + * src/closures.c (selinux_enabled_check): Fix strncmp usage bug. + +2010-07-07 Dan Horák + + * include/ffi.h.in: Protect #define with #ifndef. + * src/powerpc/ffitarget.h: Ditto. + * src/s390/ffitarget.h: Ditto. + * src/sparc/ffitarget.h: Ditto. + +2010-07-07 Neil Roberts + + * src/x86/sysv.S (ffi_call_SYSV): Align the stack pointer to + 16-bytes. + +2010-07-02 Jakub Jelinek + + * Makefile.am (AM_MAKEFLAGS): Pass also mandir to submakes. + * Makefile.in: Regenerated. + +2010-05-19 Rainer Orth + + * configure.ac (libffi_cv_as_x86_pcrel): Check for illegal in as + output, too. + (libffi_cv_as_ascii_pseudo_op): Check for .ascii. + (libffi_cv_as_string_pseudo_op): Check for .string. + * configure: Regenerate. + * fficonfig.h.in: Regenerate. + * src/x86/sysv.S (.eh_frame): Use .ascii, .string or error. + +2010-05-11 Dan Witte + + * doc/libffi.tex: Document previous change. + +2010-05-11 Makoto Kato + + * src/x86/ffi.c (ffi_call): Don't copy structs passed by value. + +2010-05-05 Michael Kohler + + * src/dlmalloc.c (dlfree): Fix spelling. + * src/ia64/ffi.c (ffi_prep_cif_machdep): Ditto. + * configure.ac: Ditto. + * configure: Rebuilt. + +2010-04-13 Dan Witte + + * msvcc.sh: Build with -W3 instead of -Wall. + * src/powerpc/ffi_darwin.c: Remove build warnings. + * src/x86/ffi.c: Ditto. + * src/x86/ffitarget.h: Ditto. + +2010-04-12 Dan Witte + Walter Meinl + + * configure.ac: Add OS/2 support. + * configure: Rebuilt. + * src/closures.c: Ditto. + * src/dlmalloc.c: Ditto. + * src/x86/win32.S: Ditto. + +2010-04-07 Jakub Jelinek + + * testsuite/libffi.call/err_bad_abi.c: Remove unused args variable. + +2010-04-02 Ralf Wildenhues + + * Makefile.in: Regenerate. + * aclocal.m4: Regenerate. + * include/Makefile.in: Regenerate. + * man/Makefile.in: Regenerate. + * testsuite/Makefile.in: Regenerate. + +2010-03-30 Dan Witte + + * msvcc.sh: Disable build warnings. + * README (tested): Clarify windows build procedure. + +2010-03-15 Rainer Orth + + * configure.ac (libffi_cv_as_x86_64_unwind_section_type): New test. + * configure: Regenerate. + * fficonfig.h.in: Regenerate. + * libffi/src/x86/unix64.S (.eh_frame) + [HAVE_AS_X86_64_UNWIND_SECTION_TYPE]: Use @unwind section type. + +2010-03-14 Matthias Klose + + * src/x86/ffi64.c: Fix typo in comment. + * src/x86/ffi.c: Use /* ... */ comment style. + +2010-02-24 Rainer Orth + + * doc/libffi.texi (The Closure API): Fix typo. + * doc/libffi.info: Remove. + +2010-02-15 Matthias Klose + + * src/arm/sysv.S (__ARM_ARCH__): Define for processor + __ARM_ARCH_7EM__. + +2010-01-15 Anthony Green + + * README: Add notes on building with Microsoft Visual C++. + +2010-01-15 Daniel Witte + + * msvcc.sh: New file. + + * src/x86/win32.S: Port assembly routines to MSVC and #ifdef. + * src/x86/ffi.c: Tweak function declaration and remove excess + parens. + * include/ffi.h.in: Add __declspec(align(8)) to typedef struct + ffi_closure. + + * src/x86/ffi.c: Merge ffi_call_SYSV and ffi_call_STDCALL into new + function ffi_call_win32 on X86_WIN32. + * src/x86/win32.S (ffi_call_SYSV): Rename to ffi_call_win32. + (ffi_call_STDCALL): Remove. + + * src/prep_cif.c (ffi_prep_cif): Move stack space allocation code + to ffi_prep_cif_machdep for x86. + * src/x86/ffi.c (ffi_prep_cif_machdep): To here. + +2010-01-15 Oliver Kiddle + + * src/x86/ffitarget.h (ffi_abi): Check for __i386 and __amd64 for + Sun Studio compiler compatibility. + +2010-01-12 Conrad Irwin + + * doc/libffi.texi: Add closure example. + +2010-01-07 Rainer Orth + + PR libffi/40701 + * testsuite/libffi.call/ffitest.h [__alpha__ && __osf__] (PRIdLL, + PRIuLL, PRId64, PRIu64, PRIuPTR): Define. + * testsuite/libffi.call/cls_align_sint64.c: Add -Wno-format on + alpha*-dec-osf*. + * testsuite/libffi.call/cls_align_uint64.c: Likewise. + * testsuite/libffi.call/cls_ulonglong.c: Likewise. + * testsuite/libffi.call/return_ll1.c: Likewise. + * testsuite/libffi.call/stret_medium2.c: Likewise. + * testsuite/libffi.special/ffitestcxx.h (allocate_mmap): Cast + MAP_FAILED to char *. + +2010-01-06 Rainer Orth + + * src/mips/n32.S: Use .abicalls and .eh_frame with __GNUC__. + +2009-12-31 Anthony Green + + * README: Update for libffi 3.0.9. + +2009-12-27 Matthias Klose + + * configure.ac (HAVE_LONG_DOUBLE): Define for mips when + appropriate. + * configure: Rebuilt. + +2009-12-26 Anthony Green + + * testsuite/libffi.call/cls_longdouble_va.c: Mark as xfail for + avr32*-*-*. + * testsuite/libffi.call/cls_double_va.c: Ditto. + +2009-12-26 Andreas Tobler + + * testsuite/libffi.call/ffitest.h: Conditionally include stdint.h + and inttypes.h. + * testsuite/libffi.special/unwindtest.cc: Ditto. + +2009-12-26 Andreas Tobler + + * configure.ac: Add amd64-*-openbsd*. + * configure: Rebuilt. + * testsuite/lib/libffi-dg.exp (libffi_target_compile): Link + openbsd programs with -lpthread. + +2009-12-26 Anthony Green + + * testsuite/libffi.call/cls_double_va.c, + testsuite/libffi.call/cls_longdouble.c, + testsuite/libffi.call/cls_longdouble_va.c, + testsuite/libffi.call/cls_pointer.c, + testsuite/libffi.call/cls_pointer_stack.c: Remove xfail for + mips*-*-* and arm*-*-*. + * testsuite/libffi.call/cls_align_longdouble_split.c, + testsuite/libffi.call/cls_align_longdouble_split2.c, + testsuite/libffi.call/stret_medium2.c, + testsuite/libffi.call/stret_medium.c, + testsuite/libffi.call/stret_large.c, + testsuite/libffi.call/stret_large2.c: Remove xfail for arm*-*-*. + +2009-12-31 Kay Tietz + + * testsuite/libffi.call/ffitest.h, + testsuite/libffi.special/ffitestcxx.h (PRIdLL, PRuLL): Fix + definitions. + +2009-12-31 Carlo Bramini + + * configure.ac (AM_LTLDFLAGS): Define for windows hosts. + * Makefile.am (libffi_la_LDFLAGS): Add AM_LTLDFLAGS. + * configure: Rebuilt. + * Makefile.in: Rebuilt. + +2009-12-31 Anthony Green + Blake Chaffin. + + * testsuite/libffi.call/huge_struct.c: New test case from Blake + Chaffin @ Apple. + +2009-12-28 David Edelsohn + + * src/powerpc/ffi_darwin.c (ffi_prep_args): Copy abi and nargs to + local variables. + (aix_adjust_aggregate_sizes): New function. + (ffi_prep_cif_machdep): Call it. + +2009-12-26 Andreas Tobler + + * configure.ac: Define FFI_MMAP_EXEC_WRIT for the given targets. + * configure: Regenerate. + * fficonfig.h.in: Likewise. + * src/closures.c: Remove the FFI_MMAP_EXEC_WRIT definition for + Solaris/x86. + +2009-12-26 Andreas Schwab + + * src/powerpc/ffi.c (ffi_prep_args_SYSV): Advance intarg_count + when a float arguments is passed in memory. + (ffi_closure_helper_SYSV): Mark general registers as used up when + a 64bit or soft-float long double argument is passed in memory. + +2009-12-25 Matthias Klose + + * man/ffi_call.3: Fix #include in examples. + * doc/libffi.texi: Add dircategory. + +2009-12-25 Frank Everdij + + * include/ffi.h.in: Placed '__GNUC__' ifdef around + '__attribute__((aligned(8)))' in ffi_closure, fixes compile for + IRIX MIPSPro c99. + * include/ffi_common.h: Added '__sgi' define to non + '__attribute__((__mode__()))' integer typedefs. + * src/mips/ffi.c (ffi_call, ffi_closure_mips_inner_O32, + ffi_closure_mips_inner_N32): Added 'defined(_MIPSEB)' to BE check. + (ffi_closure_mips_inner_O32, ffi_closure_mips_inner_N32): Added + FFI_LONGDOUBLE support and alignment(N32 only). + * src/mips/ffitarget.h: Corrected '#include ' for IRIX and + fixed non '__attribute__((__mode__()))' integer typedefs. + * src/mips/n32.S: Put '#ifdef linux' around '.abicalls' and '.eh_frame' + since they are Linux/GNU Assembler specific. + +2009-12-25 Bradley Smith + + * configure.ac, Makefile.am, src/avr32/ffi.c, + src/avr32/ffitarget.h, + src/avr32/sysv.S: Add AVR32 port. + * configure, Makefile.in: Rebuilt. + +2009-12-21 Andreas Tobler + + * configure.ac: Make i?86 build on FreeBSD and OpenBSD. + * configure: Regenerate. + +2009-12-15 John David Anglin + + * testsuite/libffi.call/ffitest.h: Define PRIuPTR on PA HP-UX. + +2009-12-13 John David Anglin + + * src/pa/ffi.c (ffi_closure_inner_pa32): Handle FFI_TYPE_LONGDOUBLE + type on HP-UX. + +2012-02-13 Kai Tietz + + PR libffi/52221 + * src/x86/ffi.c (ffi_prep_raw_closure_loc): Add thiscall + support for X86_WIN32. + (FFI_INIT_TRAMPOLINE_THISCALL): Fix displacement. + +2009-12-11 Eric Botcazou + + * src/sparc/ffi.c (ffi_closure_sparc_inner_v9): Properly align 'long + double' arguments. + +2009-12-11 Eric Botcazou + + * testsuite/libffi.call/ffitest.h: Define PRIuPTR on Solaris < 10. + +2009-12-10 Rainer Orth + + PR libffi/40700 + * src/closures.c [X86_64 && __sun__ && __svr4__] + (FFI_MMAP_EXEC_WRIT): Define. + +2009-12-08 David Daney + + * testsuite/libffi.call/stret_medium.c: Remove xfail for mips*-*-* + * testsuite/libffi.call/cls_align_longdouble_split2.c: Same. + * testsuite/libffi.call/stret_large.c: Same. + * testsuite/libffi.call/cls_align_longdouble_split.c: Same. + * testsuite/libffi.call/stret_large2.c: Same. + * testsuite/libffi.call/stret_medium2.c: Same. + +2009-12-07 David Edelsohn + + * src/powerpc/aix_closure.S (libffi_closure_ASM): Fix tablejump + typo. + +2009-12-05 David Edelsohn + + * src/powerpc/aix.S: Update AIX32 code to be consistent with AIX64 + code. + * src/powerpc/aix_closure.S: Same. + +2009-12-05 Ralf Wildenhues + + * Makefile.in: Regenerate. + * configure: Regenerate. + * include/Makefile.in: Regenerate. + * man/Makefile.in: Regenerate. + * testsuite/Makefile.in: Regenerate. + +2009-12-04 David Edelsohn + + * src/powerpc/aix_closure.S: Reorganize 64-bit code to match + linux64_closure.S. + +2009-12-04 Uros Bizjak + + PR libffi/41908 + * src/x86/ffi64.c (classify_argument): Update from + gcc/config/i386/i386.c. + (ffi_closure_unix64_inner): Do not use the address of two consecutive + SSE registers directly. + * testsuite/libffi.call/cls_dbls_struct.c (main): Remove xfail + for x86_64 linux targets. + +2009-12-04 David Edelsohn + + * src/powerpc/ffi_darwin.c (ffi_closure_helper_DARWIN): Increment + pfr for long double split between fpr13 and stack. + +2009-12-03 David Edelsohn + + * src/powerpc/ffi_darwin.c (ffi_prep_args): Increment next_arg and + fparg_count twice for long double. + +2009-12-03 David Edelsohn + + PR libffi/42243 + * src/powerpc/ffi_darwin.c (ffi_prep_args): Remove extra parentheses. + +2009-12-03 Uros Bizjak + + * testsuite/libffi.call/cls_longdouble_va.c (main): Fix format string. + Remove xfails for x86 linux targets. + +2009-12-02 David Edelsohn + + * src/powerpc/ffi_darwin.c (ffi_prep_args): Fix typo in INT64 + case. + +2009-12-01 David Edelsohn + + * src/powerpc/aix.S (ffi_call_AIX): Convert to more standard + register usage. Call ffi_prep_args directly. Add long double + return value support. + * src/powerpc/ffi_darwin.c (ffi_prep_args): Double arg increment + applies to FFI_TYPE_DOUBLE. Correct fpr_base increment typo. + Separate FFI_TYPE_SINT32 and FFI_TYPE_UINT32 cases. + (ffi_prep_cif_machdep): Only 16 byte stack alignment in 64 bit + mode. + (ffi_closure_helper_DARWIN): Remove nf and ng counters. Move temp + into case. + * src/powerpc/aix_closure.S: Maintain 16 byte stack alignment. + Allocate result area between params and FPRs. + +2009-11-30 David Edelsohn + + PR target/35484 + * src/powerpc/ffitarget.h (POWERPC64): Define for PPC64 Linux and + AIX64. + * src/powerpc/aix.S: Implement AIX64 version. + * src/powerpc/aix_closure.S: Implement AIX64 version. + (ffi_closure_ASM): Use extsb, lha and displament addresses. + * src/powerpc/ffi_darwin.c (ffi_prep_args): Implement AIX64 + support. + (ffi_prep_cif_machdep): Same. + (ffi_call): Same. + (ffi_closure_helper_DARWIN): Same. + +2009-11-02 Andreas Tobler + + PR libffi/41908 + * testsuite/libffi.call/testclosure.c: New test. + +2009-09-28 Kai Tietz + + * src/x86/win64.S (_ffi_call_win64 stack): Remove for gnu + assembly version use of ___chkstk. + +2009-09-23 Matthias Klose + + PR libffi/40242, PR libffi/41443 + * src/arm/sysv.S (__ARM_ARCH__): Define for processors + __ARM_ARCH_6T2__, __ARM_ARCH_6M__, __ARM_ARCH_7__, + __ARM_ARCH_7A__, __ARM_ARCH_7R__, __ARM_ARCH_7M__. + Change the conditionals to __SOFTFP__ || __ARM_EABI__ + for -mfloat-abi=softfp to work. + +2009-09-17 Loren J. Rittle + + PR testsuite/32843 (strikes again) + * src/x86/ffi.c (ffi_prep_cif_machdep): Add X86_FREEBSD to + enable proper extension on char and short. + +2009-09-15 David Daney + + * src/java_raw_api.c (ffi_java_raw_to_rvalue): Remove special + handling for FFI_TYPE_POINTER. + * src/mips/ffitarget.h (FFI_TYPE_STRUCT_D_SOFT, + FFI_TYPE_STRUCT_F_SOFT, FFI_TYPE_STRUCT_DD_SOFT, + FFI_TYPE_STRUCT_FF_SOFT, FFI_TYPE_STRUCT_FD_SOFT, + FFI_TYPE_STRUCT_DF_SOFT, FFI_TYPE_STRUCT_SOFT): New defines. + (FFI_N32_SOFT_FLOAT, FFI_N64_SOFT_FLOAT): New ffi_abi enumerations. + (enum ffi_abi): Set FFI_DEFAULT_ABI for soft-float. + * src/mips/n32.S (ffi_call_N32): Add handling for soft-float + structure and pointer returns. + (ffi_closure_N32): Add handling for pointer returns. + * src/mips/ffi.c (ffi_prep_args, calc_n32_struct_flags, + calc_n32_return_struct_flags): Handle soft-float. + (ffi_prep_cif_machdep): Handle soft-float, fix pointer handling. + (ffi_call_N32): Declare proper argument types. + (ffi_call, copy_struct_N32, ffi_closure_mips_inner_N32): Handle + soft-float. + +2009-08-24 Ralf Wildenhues + + * configure.ac (AC_PREREQ): Bump to 2.64. + +2009-08-22 Ralf Wildenhues + + * Makefile.am (install-html, install-pdf): Remove. + * Makefile.in: Regenerate. + + * Makefile.in: Regenerate. + * aclocal.m4: Regenerate. + * configure: Regenerate. + * fficonfig.h.in: Regenerate. + * include/Makefile.in: Regenerate. + * man/Makefile.in: Regenerate. + * testsuite/Makefile.in: Regenerate. + +2011-08-22 Jasper Lievisse Adriaanse + + * configure.ac: Add OpenBSD/hppa and OpenBSD/powerpc support. + * configure: Rebuilt. + +2009-07-30 Ralf Wildenhues + + * configure.ac (_AC_ARG_VAR_PRECIOUS): Use m4_rename_force. + +2009-07-24 Dave Korn + + PR libffi/40807 + * src/x86/ffi.c (ffi_prep_cif_machdep): Also use sign/zero-extending + return types for X86_WIN32. + * src/x86/win32.S (_ffi_call_SYSV): Handle omitted return types. + (_ffi_call_STDCALL, _ffi_closure_SYSV, _ffi_closure_raw_SYSV, + _ffi_closure_STDCALL): Likewise. + + * src/closures.c (is_selinux_enabled): Define to const 0 for Cygwin. + (dlmmap, dlmunmap): Also use these functions on Cygwin. + +2009-07-11 Richard Sandiford + + PR testsuite/40699 + PR testsuite/40707 + PR testsuite/40709 + * testsuite/lib/libffi-dg.exp: Revert 2009-07-02, 2009-07-01 and + 2009-06-30 commits. + +2009-07-01 Richard Sandiford + + * testsuite/lib/libffi-dg.exp (libffi-init): Set ld_library_path + to "" before adding paths. (This reinstates an assignment that + was removed by my 2009-06-30 commit, but changes the initial + value from "." to "".) + +2009-07-01 H.J. Lu + + PR testsuite/40601 + * testsuite/lib/libffi-dg.exp (libffi-init): Properly set + gccdir. Adjust ld_library_path for gcc only if gccdir isn't + empty. + +2009-06-30 Richard Sandiford + + * testsuite/lib/libffi-dg.exp (libffi-init): Don't add "." + to ld_library_path. Use add_path. Add just find_libgcc_s + to ld_library_path, not every libgcc multilib directory. + +2009-06-16 Wim Lewis + + * src/powerpc/ffi.c: Avoid clobbering cr3 and cr4, which are + supposed to be callee-saved. + * src/powerpc/sysv.S (small_struct_return_value): Fix overrun of + return buffer for odd-size structs. + +2009-06-16 Andreas Tobler + + PR libffi/40444 + * testsuite/lib/libffi-dg.exp (libffi_target_compile): Add + allow_stack_execute for Darwin. + +2009-06-16 Andrew Haley + + * configure.ac (TARGETDIR): Add missing blank lines. + * configure: Regenerate. + +2009-06-16 Andrew Haley + + * testsuite/libffi.call/cls_align_sint64.c, + testsuite/libffi.call/cls_align_uint64.c, + testsuite/libffi.call/cls_longdouble_va.c, + testsuite/libffi.call/cls_ulonglong.c, + testsuite/libffi.call/return_ll1.c, + testsuite/libffi.call/stret_medium2.c: Fix printf format + specifiers. + * testsuite/libffi.call/ffitest.h, + testsuite/libffi.special/ffitestcxx.h (PRIdLL, PRIuLL): Define. + +2009-06-15 Andrew Haley + + * testsuite/libffi.call/err_bad_typedef.c: xfail everywhere. + * testsuite/libffi.call/err_bad_abi.c: Likewise. + +2009-06-12 Andrew Haley + + * Makefile.am: Remove info_TEXINFOS. + +2009-06-12 Andrew Haley + + * ChangeLog.libffi: testsuite/libffi.call/cls_align_sint64.c, + testsuite/libffi.call/cls_align_uint64.c, + testsuite/libffi.call/cls_ulonglong.c, + testsuite/libffi.call/return_ll1.c, + testsuite/libffi.call/stret_medium2.c: Fix printf format + specifiers. + testsuite/libffi.special/unwindtest.cc: include stdint.h. + +2009-06-11 Timothy Wall + + * Makefile.am, + configure.ac, + include/ffi.h.in, + include/ffi_common.h, + src/closures.c, + src/dlmalloc.c, + src/x86/ffi.c, + src/x86/ffitarget.h, + src/x86/win64.S (new), + README: Added win64 support (mingw or MSVC) + * Makefile.in, + include/Makefile.in, + man/Makefile.in, + testsuite/Makefile.in, + configure, + aclocal.m4: Regenerated + * ltcf-c.sh: properly escape cygwin/w32 path + * man/ffi_call.3: Clarify size requirements for return value. + * src/x86/ffi64.c: Fix filename in comment. + * src/x86/win32.S: Remove unused extern. + + * testsuite/libffi.call/closure_fn0.c, + testsuite/libffi.call/closure_fn1.c, + testsuite/libffi.call/closure_fn2.c, + testsuite/libffi.call/closure_fn3.c, + testsuite/libffi.call/closure_fn4.c, + testsuite/libffi.call/closure_fn5.c, + testsuite/libffi.call/closure_fn6.c, + testsuite/libffi.call/closure_stdcall.c, + testsuite/libffi.call/cls_12byte.c, + testsuite/libffi.call/cls_16byte.c, + testsuite/libffi.call/cls_18byte.c, + testsuite/libffi.call/cls_19byte.c, + testsuite/libffi.call/cls_1_1byte.c, + testsuite/libffi.call/cls_20byte.c, + testsuite/libffi.call/cls_20byte1.c, + testsuite/libffi.call/cls_24byte.c, + testsuite/libffi.call/cls_2byte.c, + testsuite/libffi.call/cls_3_1byte.c, + testsuite/libffi.call/cls_3byte1.c, + testsuite/libffi.call/cls_3byte2.c, + testsuite/libffi.call/cls_4_1byte.c, + testsuite/libffi.call/cls_4byte.c, + testsuite/libffi.call/cls_5_1_byte.c, + testsuite/libffi.call/cls_5byte.c, + testsuite/libffi.call/cls_64byte.c, + testsuite/libffi.call/cls_6_1_byte.c, + testsuite/libffi.call/cls_6byte.c, + testsuite/libffi.call/cls_7_1_byte.c, + testsuite/libffi.call/cls_7byte.c, + testsuite/libffi.call/cls_8byte.c, + testsuite/libffi.call/cls_9byte1.c, + testsuite/libffi.call/cls_9byte2.c, + testsuite/libffi.call/cls_align_double.c, + testsuite/libffi.call/cls_align_float.c, + testsuite/libffi.call/cls_align_longdouble.c, + testsuite/libffi.call/cls_align_longdouble_split.c, + testsuite/libffi.call/cls_align_longdouble_split2.c, + testsuite/libffi.call/cls_align_pointer.c, + testsuite/libffi.call/cls_align_sint16.c, + testsuite/libffi.call/cls_align_sint32.c, + testsuite/libffi.call/cls_align_sint64.c, + testsuite/libffi.call/cls_align_uint16.c, + testsuite/libffi.call/cls_align_uint32.c, + testsuite/libffi.call/cls_align_uint64.c, + testsuite/libffi.call/cls_dbls_struct.c, + testsuite/libffi.call/cls_double.c, + testsuite/libffi.call/cls_double_va.c, + testsuite/libffi.call/cls_float.c, + testsuite/libffi.call/cls_longdouble.c, + testsuite/libffi.call/cls_longdouble_va.c, + testsuite/libffi.call/cls_multi_schar.c, + testsuite/libffi.call/cls_multi_sshort.c, + testsuite/libffi.call/cls_multi_sshortchar.c, + testsuite/libffi.call/cls_multi_uchar.c, + testsuite/libffi.call/cls_multi_ushort.c, + testsuite/libffi.call/cls_multi_ushortchar.c, + testsuite/libffi.call/cls_pointer.c, + testsuite/libffi.call/cls_pointer_stack.c, + testsuite/libffi.call/cls_schar.c, + testsuite/libffi.call/cls_sint.c, + testsuite/libffi.call/cls_sshort.c, + testsuite/libffi.call/cls_uchar.c, + testsuite/libffi.call/cls_uint.c, + testsuite/libffi.call/cls_ulonglong.c, + testsuite/libffi.call/cls_ushort.c, + testsuite/libffi.call/err_bad_abi.c, + testsuite/libffi.call/err_bad_typedef.c, + testsuite/libffi.call/float2.c, + testsuite/libffi.call/huge_struct.c, + testsuite/libffi.call/nested_struct.c, + testsuite/libffi.call/nested_struct1.c, + testsuite/libffi.call/nested_struct10.c, + testsuite/libffi.call/nested_struct2.c, + testsuite/libffi.call/nested_struct3.c, + testsuite/libffi.call/nested_struct4.c, + testsuite/libffi.call/nested_struct5.c, + testsuite/libffi.call/nested_struct6.c, + testsuite/libffi.call/nested_struct7.c, + testsuite/libffi.call/nested_struct8.c, + testsuite/libffi.call/nested_struct9.c, + testsuite/libffi.call/problem1.c, + testsuite/libffi.call/return_ldl.c, + testsuite/libffi.call/return_ll1.c, + testsuite/libffi.call/stret_large.c, + testsuite/libffi.call/stret_large2.c, + testsuite/libffi.call/stret_medium.c, + testsuite/libffi.call/stret_medium2.c, + testsuite/libffi.special/unwindtest.cc: use ffi_closure_alloc instead + of checking for MMAP. Use intptr_t instead of long casts. + +2009-06-11 Kaz Kojima + + * testsuite/libffi.call/cls_longdouble_va.c: Add xfail sh*-*-linux-*. + * testsuite/libffi.call/err_bad_abi.c: Add xfail sh*-*-*. + * testsuite/libffi.call/err_bad_typedef.c: Likewise. + +2009-06-09 Andrew Haley + + * src/x86/freebsd.S: Add missing file. + +2009-06-08 Andrew Haley + + Import from libffi 3.0.8: + + * doc/libffi.texi: New file. + * doc/libffi.info: Likewise. + * doc/stamp-vti: Likewise. + * man/Makefile.am: New file. + * man/ffi_call.3: New file. + + * Makefile.am (EXTRA_DIST): Add src/x86/darwin64.S, + src/dlmalloc.c. + (nodist_libffi_la_SOURCES): Add X86_FREEBSD. + + * configure.ac: Bump version to 3.0.8. + parisc*-*-linux*: Add. + i386-*-freebsd* | i386-*-openbsd*: Add. + powerpc-*-beos*: Add. + AM_CONDITIONAL X86_FREEBSD: Add. + AC_CONFIG_FILES: Add man/Makefile. + + * include/ffi.h.in (FFI_FN): Change void (*)() to void (*)(void). + +2009-06-08 Andrew Haley + + * README: Import from libffi 3.0.8. + +2009-06-08 Andrew Haley + + * testsuite/libffi.call/err_bad_abi.c: Add xfails. + * testsuite/libffi.call/cls_longdouble_va.c: Add xfails. + * testsuite/libffi.call/cls_dbls_struct.c: Add xfail x86_64-*-linux-*. + * testsuite/libffi.call/err_bad_typedef.c: Add xfails. + + * testsuite/libffi.call/stret_medium2.c: Add __UNUSED__ to args. + * testsuite/libffi.call/stret_medium.c: Likewise. + * testsuite/libffi.call/stret_large2.c: Likewise. + * testsuite/libffi.call/stret_large.c: Likewise. + +2008-12-26 Timothy Wall + + * testsuite/libffi.call/cls_longdouble.c, + testsuite/libffi.call/cls_longdouble_va.c, + testsuite/libffi.call/cls_align_longdouble.c, + testsuite/libffi.call/cls_align_longdouble_split.c, + testsuite/libffi.call/cls_align_longdouble_split2.c: mark expected + failures on x86_64 cygwin/mingw. + +2008-12-22 Timothy Wall + + * testsuite/libffi.call/closure_fn0.c, + testsuite/libffi.call/closure_fn1.c, + testsuite/libffi.call/closure_fn2.c, + testsuite/libffi.call/closure_fn3.c, + testsuite/libffi.call/closure_fn4.c, + testsuite/libffi.call/closure_fn5.c, + testsuite/libffi.call/closure_fn6.c, + testsuite/libffi.call/closure_loc_fn0.c, + testsuite/libffi.call/closure_stdcall.c, + testsuite/libffi.call/cls_align_pointer.c, + testsuite/libffi.call/cls_pointer.c, + testsuite/libffi.call/cls_pointer_stack.c: use portable cast from + pointer to integer (intptr_t). + * testsuite/libffi.call/cls_longdouble.c: disable for win64. + +2008-07-24 Anthony Green + + * testsuite/libffi.call/cls_dbls_struct.c, + testsuite/libffi.call/cls_double_va.c, + testsuite/libffi.call/cls_longdouble.c, + testsuite/libffi.call/cls_longdouble_va.c, + testsuite/libffi.call/cls_pointer.c, + testsuite/libffi.call/cls_pointer_stack.c, + testsuite/libffi.call/err_bad_abi.c: Clean up failures from + compiler warnings. + +2008-03-04 Anthony Green + Blake Chaffin + hos@tamanegi.org + + * testsuite/libffi.call/cls_align_longdouble_split2.c + testsuite/libffi.call/cls_align_longdouble_split.c + testsuite/libffi.call/cls_dbls_struct.c + testsuite/libffi.call/cls_double_va.c + testsuite/libffi.call/cls_longdouble.c + testsuite/libffi.call/cls_longdouble_va.c + testsuite/libffi.call/cls_pointer.c + testsuite/libffi.call/cls_pointer_stack.c + testsuite/libffi.call/err_bad_abi.c + testsuite/libffi.call/err_bad_typedef.c + testsuite/libffi.call/stret_large2.c + testsuite/libffi.call/stret_large.c + testsuite/libffi.call/stret_medium2.c + testsuite/libffi.call/stret_medium.c: New tests from Apple. + +2009-06-05 Andrew Haley + + * src/x86/ffitarget.h, src/x86/ffi.c: Merge stdcall changes from + libffi. + +2009-06-04 Andrew Haley + + * src/x86/ffitarget.h, src/x86/win32.S, src/x86/ffi.c: Back out + stdcall changes. + +2008-02-26 Anthony Green + Thomas Heller + + * src/x86/ffi.c (ffi_closure_SYSV_inner): Change C++ comment to C + comment. + +2008-02-03 Timothy Wall + + * src/x86/ffi.c (FFI_INIT_TRAMPOLINE_STDCALL): Calculate jump return + offset based on code pointer, not data pointer. + +2008-01-31 Timothy Wall + + * testsuite/libffi.call/closure_stdcall.c: Add test for stdcall + closures. + * src/x86/ffitarget.h: Increase size of trampoline for stdcall + closures. + * src/x86/win32.S: Add assembly for stdcall closure. + * src/x86/ffi.c: Initialize stdcall closure trampoline. + +2009-06-04 Andrew Haley + + * include/ffi.h.in: Change void (*)() to void (*)(void). + * src/x86/ffi.c: Likewise. + +2009-06-04 Andrew Haley + + * src/powerpc/ppc_closure.S: Insert licence header. + * src/powerpc/linux64_closure.S: Likewise. + * src/m68k/sysv.S: Likewise. + + * src/sh64/ffi.c: Change void (*)() to void (*)(void). + * src/powerpc/ffi.c: Likewise. + * src/powerpc/ffi_darwin.c: Likewise. + * src/m32r/ffi.c: Likewise. + * src/sh64/ffi.c: Likewise. + * src/x86/ffi64.c: Likewise. + * src/alpha/ffi.c: Likewise. + * src/alpha/osf.S: Likewise. + * src/frv/ffi.c: Likewise. + * src/s390/ffi.c: Likewise. + * src/pa/ffi.c: Likewise. + * src/pa/hpux32.S: Likewise. + * src/ia64/unix.S: Likewise. + * src/ia64/ffi.c: Likewise. + * src/sparc/ffi.c: Likewise. + * src/mips/ffi.c: Likewise. + * src/sh/ffi.c: Likewise. + +2008-02-15 David Daney + + * src/mips/ffi.c (USE__BUILTIN___CLEAR_CACHE): + Define (conditionally), and use it to include cachectl.h. + (ffi_prep_closure_loc): Fix cache flushing. + * src/mips/ffitarget.h (_ABIN32, _ABI64, _ABIO32): Define. + +2009-06-04 Andrew Haley + + include/ffi.h.in, + src/arm/ffitarget.h, + src/arm/ffi.c, + src/arm/sysv.S, + src/powerpc/ffitarget.h, + src/closures.c, + src/sh64/ffitarget.h, + src/sh64/ffi.c, + src/sh64/sysv.S, + src/types.c, + src/x86/ffi64.c, + src/x86/ffitarget.h, + src/x86/win32.S, + src/x86/darwin.S, + src/x86/ffi.c, + src/x86/sysv.S, + src/x86/unix64.S, + src/alpha/ffitarget.h, + src/alpha/ffi.c, + src/alpha/osf.S, + src/m68k/ffitarget.h, + src/frv/ffitarget.h, + src/frv/ffi.c, + src/s390/ffitarget.h, + src/s390/sysv.S, + src/cris/ffitarget.h, + src/pa/linux.S, + src/pa/ffitarget.h, + src/pa/ffi.c, + src/raw_api.c, + src/ia64/ffitarget.h, + src/ia64/unix.S, + src/ia64/ffi.c, + src/ia64/ia64_flags.h, + src/java_raw_api.c, + src/debug.c, + src/sparc/v9.S, + src/sparc/ffitarget.h, + src/sparc/ffi.c, + src/sparc/v8.S, + src/mips/ffitarget.h, + src/mips/n32.S, + src/mips/o32.S, + src/mips/ffi.c, + src/prep_cif.c, + src/sh/ffitarget.h, + src/sh/ffi.c, + src/sh/sysv.S: Update license text. + +2009-05-22 Dave Korn + + * src/x86/win32.S (_ffi_closure_STDCALL): New function. + (.eh_frame): Add FDE for it. + +2009-05-22 Dave Korn + + * configure.ac: Also check if assembler supports pc-relative + relocs on X86_WIN32 targets. + * configure: Regenerate. + * src/x86/win32.S (ffi_prep_args): Declare extern, not global. + (_ffi_call_SYSV): Add missing function type symbol .def and + add EH markup labels. + (_ffi_call_STDCALL): Likewise. + (_ffi_closure_SYSV): Likewise. + (_ffi_closure_raw_SYSV): Likewise. + (.eh_frame): Add hand-crafted EH data. + +2009-04-09 Jakub Jelinek + + * testsuite/lib/libffi-dg.exp: Change copyright header to refer to + version 3 of the GNU General Public License and to point readers + at the COPYING3 file and the FSF's license web page. + * testsuite/libffi.call/call.exp: Likewise. + * testsuite/libffi.special/special.exp: Likewise. + +2009-03-01 Ralf Wildenhues + + * configure: Regenerate. + +2008-12-18 Rainer Orth + + PR libffi/26048 + * configure.ac (HAVE_AS_X86_PCREL): New test. + * configure: Regenerate. + * fficonfig.h.in: Regenerate. + * src/x86/sysv.S [!FFI_NO_RAW_API]: Precalculate + RAW_CLOSURE_CIF_OFFSET, RAW_CLOSURE_FUN_OFFSET, + RAW_CLOSURE_USER_DATA_OFFSET for the Solaris 10/x86 assembler. + (.eh_frame): Only use SYMBOL-. iff HAVE_AS_X86_PCREL. + * src/x86/unix64.S (.Lstore_table): Move to .text section. + (.Lload_table): Likewise. + (.eh_frame): Only use SYMBOL-. iff HAVE_AS_X86_PCREL. + +2008-12-18 Ralf Wildenhues + + * configure: Regenerate. + +2008-11-21 Eric Botcazou + + * src/sparc/ffi.c (ffi_prep_cif_machdep): Add support for + signed/unsigned int8/16 return values. + * src/sparc/v8.S (ffi_call_v8): Likewise. + (ffi_closure_v8): Likewise. + +2008-09-26 Peter O'Gorman + Steve Ellcey + + * configure: Regenerate for new libtool. + * Makefile.in: Ditto. + * include/Makefile.in: Ditto. + * aclocal.m4: Ditto. + +2008-08-25 Andreas Tobler + + * src/powerpc/ffitarget.h (ffi_abi): Add FFI_LINUX and + FFI_LINUX_SOFT_FLOAT to the POWERPC_FREEBSD enum. + Add note about flag bits used for FFI_SYSV_TYPE_SMALL_STRUCT. + Adjust copyright notice. + * src/powerpc/ffi.c: Add two new flags to indicate if we have one + register or two register to use for FFI_SYSV structs. + (ffi_prep_cif_machdep): Pass the right register flag introduced above. + (ffi_closure_helper_SYSV): Fix the return type for + FFI_SYSV_TYPE_SMALL_STRUCT. Comment. + Adjust copyright notice. + +2008-07-16 Kaz Kojima + + * src/sh/ffi.c (ffi_prep_closure_loc): Turn INSN into an unsigned + int. + +2008-06-17 Ralf Wildenhues + + * configure: Regenerate. + * include/Makefile.in: Regenerate. + * testsuite/Makefile.in: Regenerate. + +2008-06-07 Joseph Myers + + * configure.ac (parisc*-*-linux*, powerpc-*-sysv*, + powerpc-*-beos*): Remove. + * configure: Regenerate. + +2008-05-09 Julian Brown + + * Makefile.am (LTLDFLAGS): New. + (libffi_la_LDFLAGS): Use above. + * Makefile.in: Regenerate. + +2008-04-18 Paolo Bonzini + + PR bootstrap/35457 + * aclocal.m4: Regenerate. + * configure: Regenerate. + +2008-03-26 Kaz Kojima + + * src/sh/sysv.S: Add .note.GNU-stack on Linux. + * src/sh64/sysv.S: Likewise. + +2008-03-26 Daniel Jacobowitz + + * src/arm/sysv.S: Fix ARM comment marker. + +2008-03-26 Jakub Jelinek + + * src/alpha/osf.S: Add .note.GNU-stack on Linux. + * src/s390/sysv.S: Likewise. + * src/powerpc/ppc_closure.S: Likewise. + * src/powerpc/sysv.S: Likewise. + * src/x86/unix64.S: Likewise. + * src/x86/sysv.S: Likewise. + * src/sparc/v8.S: Likewise. + * src/sparc/v9.S: Likewise. + * src/m68k/sysv.S: Likewise. + * src/arm/sysv.S: Likewise. + +2008-03-16 Ralf Wildenhues + + * aclocal.m4: Regenerate. + * configure: Likewise. + * Makefile.in: Likewise. + * include/Makefile.in: Likewise. + * testsuite/Makefile.in: Likewise. + +2008-02-12 Bjoern Koenig + Andreas Tobler + + * configure.ac: Add amd64-*-freebsd* target. + * configure: Regenerate. + +2008-01-30 H.J. Lu + + PR libffi/34612 + * src/x86/sysv.S (ffi_closure_SYSV): Pop 4 byte from stack when + returning struct. + + * testsuite/libffi.call/call.exp: Add "-O2 -fomit-frame-pointer" + tests. + +2008-01-24 David Edelsohn + + * configure: Regenerate. + +2008-01-06 Andreas Tobler + + * src/x86/ffi.c (ffi_prep_cif_machdep): Fix thinko. + +2008-01-05 Andreas Tobler + + PR testsuite/32843 + * src/x86/ffi.c (ffi_prep_cif_machdep): Add code for + signed/unsigned int8/16 for X86_DARWIN. + Updated copyright info. + Handle one and two byte structs with special cif->flags. + * src/x86/ffitarget.h: Add special types for one and two byte structs. + Updated copyright info. + * src/x86/darwin.S (ffi_call_SYSV): Rewrite to use a jump table like + sysv.S + Remove code to pop args from the stack after call. + Special-case signed/unsigned for int8/16, one and two byte structs. + (ffi_closure_raw_SYSV): Handle FFI_TYPE_UINT8, + FFI_TYPE_SINT8, FFI_TYPE_UINT16, FFI_TYPE_SINT16, FFI_TYPE_UINT32, + FFI_TYPE_SINT32. + Updated copyright info. + +2007-12-08 David Daney + + * src/mips/n32.S (ffi_call_N32): Replace dadd with ADDU, dsub with + SUBU, add with ADDU and use smaller code sequences. + +2007-12-07 David Daney + + * src/mips/ffi.c (ffi_prep_cif_machdep): Handle long double return + type. + +2007-12-06 David Daney + + * include/ffi.h.in (FFI_SIZEOF_JAVA_RAW): Define if not already + defined. + (ffi_java_raw): New typedef. + (ffi_java_raw_call, ffi_java_ptrarray_to_raw, + ffi_java_raw_to_ptrarray): Change parameter types from ffi_raw to + ffi_java_raw. + (ffi_java_raw_closure) : Same. + (ffi_prep_java_raw_closure, ffi_prep_java_raw_closure_loc): Change + parameter types. + * src/java_raw_api.c (ffi_java_raw_size): Replace FFI_SIZEOF_ARG with + FFI_SIZEOF_JAVA_RAW. + (ffi_java_raw_to_ptrarray): Change type of raw to ffi_java_raw. + Replace FFI_SIZEOF_ARG with FFI_SIZEOF_JAVA_RAW. Use + sizeof(ffi_java_raw) for alignment calculations. + (ffi_java_ptrarray_to_raw): Same. + (ffi_java_rvalue_to_raw): Add special handling for FFI_TYPE_POINTER + if FFI_SIZEOF_JAVA_RAW == 4. + (ffi_java_raw_to_rvalue): Same. + (ffi_java_raw_call): Change type of raw to ffi_java_raw. + (ffi_java_translate_args): Same. + (ffi_prep_java_raw_closure_loc, ffi_prep_java_raw_closure): Change + parameter types. + * src/mips/ffitarget.h (FFI_SIZEOF_JAVA_RAW): Define for N32 ABI. + +2007-12-06 David Daney + + * src/mips/n32.S (ffi_closure_N32): Use 64-bit add instruction on + pointer values. + +2007-12-01 Andreas Tobler + + PR libffi/31937 + * src/powerpc/ffitarget.h: Introduce new ABI FFI_LINUX_SOFT_FLOAT. + Add local FFI_TYPE_UINT128 to handle soft-float long-double-128. + * src/powerpc/ffi.c: Distinguish between __NO_FPRS__ and not and + set the NUM_FPR_ARG_REGISTERS according to. + Add support for potential soft-float support under hard-float + architecture. + (ffi_prep_args_SYSV): Set NUM_FPR_ARG_REGISTERS to 0 in case of + FFI_LINUX_SOFT_FLOAT, handle float, doubles and long-doubles according + to the FFI_LINUX_SOFT_FLOAT ABI. + (ffi_prep_cif_machdep): Likewise. + (ffi_closure_helper_SYSV): Likewise. + * src/powerpc/ppc_closure.S: Make sure not to store float/double + on archs where __NO_FPRS__ is true. + Add FFI_TYPE_UINT128 support. + * src/powerpc/sysv.S: Add support for soft-float long-double-128. + Adjust copyright notice. + +2007-11-25 Andreas Tobler + + * src/closures.c: Move defintion of MAYBE_UNUSED from here to ... + * include/ffi_common.h: ... here. + Update copyright. + +2007-11-17 Andreas Tobler + + * src/powerpc/sysv.S: Load correct cr to compare if we have long double. + * src/powerpc/linux64.S: Likewise. + * src/powerpc/ffi.c: Add a comment to show which part goes into cr6. + * testsuite/libffi.call/return_ldl.c: New test. + +2007-09-04 + + * src/arm/sysv.S (UNWIND): New. + (Whole file): Conditionally compile unwinder directives. + * src/arm/sysv.S: Add unwinder directives. + + * src/arm/ffi.c (ffi_prep_args): Align structs by at least 4 bytes. + Only treat r0 as a struct address if we're actually returning a + struct by address. + Only copy the bytes that are actually within a struct. + (ffi_prep_cif_machdep): A Composite Type not larger than 4 bytes + is returned in r0, not passed by address. + (ffi_call): Allocate a word-sized temporary for the case where + a composite is returned in r0. + (ffi_prep_incoming_args_SYSV): Align as necessary. + +2007-08-05 Steven Newbury + + * src/arm/ffi.c (FFI_INIT_TRAMPOLINE): Use __clear_cache instead of + directly using the sys_cacheflush syscall. + +2007-07-27 Andrew Haley + + * src/arm/sysv.S (ffi_closure_SYSV): Add soft-float. + +2007-09-03 Maciej W. Rozycki + + * Makefile.am: Unify MIPS_IRIX and MIPS_LINUX into MIPS. + * configure.ac: Likewise. + * Makefile.in: Regenerate. + * include/Makefile.in: Likewise. + * testsuite/Makefile.in: Likewise. + * configure: Likewise. + +2007-08-24 David Daney + + * testsuite/libffi.call/return_sl.c: New test. + +2007-08-10 David Daney + + * testsuite/libffi.call/cls_multi_ushort.c, + testsuite/libffi.call/cls_align_uint16.c, + testsuite/libffi.call/nested_struct1.c, + testsuite/libffi.call/nested_struct3.c, + testsuite/libffi.call/cls_7_1_byte.c, + testsuite/libffi.call/nested_struct5.c, + testsuite/libffi.call/cls_double.c, + testsuite/libffi.call/nested_struct7.c, + testsuite/libffi.call/cls_sint.c, + testsuite/libffi.call/nested_struct9.c, + testsuite/libffi.call/cls_20byte1.c, + testsuite/libffi.call/cls_multi_sshortchar.c, + testsuite/libffi.call/cls_align_sint64.c, + testsuite/libffi.call/cls_3byte2.c, + testsuite/libffi.call/cls_multi_schar.c, + testsuite/libffi.call/cls_multi_uchar.c, + testsuite/libffi.call/cls_19byte.c, + testsuite/libffi.call/cls_9byte1.c, + testsuite/libffi.call/cls_align_float.c, + testsuite/libffi.call/closure_fn1.c, + testsuite/libffi.call/problem1.c, + testsuite/libffi.call/closure_fn3.c, + testsuite/libffi.call/cls_sshort.c, + testsuite/libffi.call/closure_fn5.c, + testsuite/libffi.call/cls_align_double.c, + testsuite/libffi.call/nested_struct.c, + testsuite/libffi.call/cls_2byte.c, + testsuite/libffi.call/nested_struct10.c, + testsuite/libffi.call/cls_4byte.c, + testsuite/libffi.call/cls_6byte.c, + testsuite/libffi.call/cls_8byte.c, + testsuite/libffi.call/cls_multi_sshort.c, + testsuite/libffi.call/cls_align_sint16.c, + testsuite/libffi.call/cls_align_uint32.c, + testsuite/libffi.call/cls_20byte.c, + testsuite/libffi.call/cls_float.c, + testsuite/libffi.call/nested_struct2.c, + testsuite/libffi.call/cls_5_1_byte.c, + testsuite/libffi.call/nested_struct4.c, + testsuite/libffi.call/cls_24byte.c, + testsuite/libffi.call/nested_struct6.c, + testsuite/libffi.call/cls_64byte.c, + testsuite/libffi.call/nested_struct8.c, + testsuite/libffi.call/cls_uint.c, + testsuite/libffi.call/cls_multi_ushortchar.c, + testsuite/libffi.call/cls_schar.c, + testsuite/libffi.call/cls_uchar.c, + testsuite/libffi.call/cls_align_uint64.c, + testsuite/libffi.call/cls_ulonglong.c, + testsuite/libffi.call/cls_align_longdouble.c, + testsuite/libffi.call/cls_1_1byte.c, + testsuite/libffi.call/cls_12byte.c, + testsuite/libffi.call/cls_3_1byte.c, + testsuite/libffi.call/cls_3byte1.c, + testsuite/libffi.call/cls_4_1byte.c, + testsuite/libffi.call/cls_6_1_byte.c, + testsuite/libffi.call/cls_16byte.c, + testsuite/libffi.call/cls_18byte.c, + testsuite/libffi.call/closure_fn0.c, + testsuite/libffi.call/cls_9byte2.c, + testsuite/libffi.call/closure_fn2.c, + testsuite/libffi.call/closure_fn4.c, + testsuite/libffi.call/cls_ushort.c, + testsuite/libffi.call/closure_fn6.c, + testsuite/libffi.call/cls_5byte.c, + testsuite/libffi.call/cls_align_pointer.c, + testsuite/libffi.call/cls_7byte.c, + testsuite/libffi.call/cls_align_sint32.c, + testsuite/libffi.special/unwindtest_ffi_call.cc, + testsuite/libffi.special/unwindtest.cc: Remove xfail for mips64*-*-*. + +2007-08-10 David Daney + + PR libffi/28313 + * configure.ac: Don't treat mips64 as a special case. + * Makefile.am (nodist_libffi_la_SOURCES): Add n32.S. + * configure: Regenerate + * Makefile.in: Ditto. + * fficonfig.h.in: Ditto. + * src/mips/ffitarget.h (REG_L, REG_S, SUBU, ADDU, SRL, LI): Indent. + (LA, EH_FRAME_ALIGN, FDE_ADDR_BYTES): New preprocessor macros. + (FFI_DEFAULT_ABI): Set for n64 case. + (FFI_CLOSURES, FFI_TRAMPOLINE_SIZE): Define for n32 and n64 cases. + * src/mips/n32.S (ffi_call_N32): Add debug macros and labels for FDE. + (ffi_closure_N32): New function. + (.eh_frame): New section + * src/mips/o32.S: Clean up comments. + (ffi_closure_O32): Pass ffi_closure parameter in $12. + * src/mips/ffi.c: Use FFI_MIPS_N32 instead of + _MIPS_SIM == _ABIN32 throughout. + (FFI_MIPS_STOP_HERE): New, use in place of + ffi_stop_here. + (ffi_prep_args): Use unsigned long to hold pointer values. Rewrite + to support n32/n64 ABIs. + (calc_n32_struct_flags): Rewrite. + (calc_n32_return_struct_flags): Remove unused variable. Reverse + position of flag bits. + (ffi_prep_cif_machdep): Rewrite n32 portion. + (ffi_call): Enable for n64. Add special handling for small structure + return values. + (ffi_prep_closure_loc): Add n32 and n64 support. + (ffi_closure_mips_inner_O32): Add cast to silence warning. + (copy_struct_N32, ffi_closure_mips_inner_N32): New functions. + +2007-08-08 David Daney + + * testsuite/libffi.call/ffitest.h (ffi_type_mylong): Remove definition. + * testsuite/libffi.call/cls_align_uint16.c (main): Use correct type + specifiers. + * testsuite/libffi.call/nested_struct1.c (main): Ditto. + * testsuite/libffi.call/cls_sint.c (main): Ditto. + * testsuite/libffi.call/nested_struct9.c (main): Ditto. + * testsuite/libffi.call/cls_20byte1.c (main): Ditto. + * testsuite/libffi.call/cls_9byte1.c (main): Ditto. + * testsuite/libffi.call/closure_fn1.c (main): Ditto. + * testsuite/libffi.call/closure_fn3.c (main): Ditto. + * testsuite/libffi.call/return_dbl2.c (main): Ditto. + * testsuite/libffi.call/cls_sshort.c (main): Ditto. + * testsuite/libffi.call/return_fl3.c (main): Ditto. + * testsuite/libffi.call/closure_fn5.c (main): Ditto. + * testsuite/libffi.call/nested_struct.c (main): Ditto. + * testsuite/libffi.call/nested_struct10.c (main): Ditto. + * testsuite/libffi.call/return_ll1.c (main): Ditto. + * testsuite/libffi.call/cls_8byte.c (main): Ditto. + * testsuite/libffi.call/cls_align_uint32.c (main): Ditto. + * testsuite/libffi.call/cls_align_sint16.c (main): Ditto. + * testsuite/libffi.call/cls_20byte.c (main): Ditto. + * testsuite/libffi.call/nested_struct2.c (main): Ditto. + * testsuite/libffi.call/cls_24byte.c (main): Ditto. + * testsuite/libffi.call/nested_struct6.c (main): Ditto. + * testsuite/libffi.call/cls_uint.c (main): Ditto. + * testsuite/libffi.call/cls_12byte.c (main): Ditto. + * testsuite/libffi.call/cls_16byte.c (main): Ditto. + * testsuite/libffi.call/closure_fn0.c (main): Ditto. + * testsuite/libffi.call/cls_9byte2.c (main): Ditto. + * testsuite/libffi.call/closure_fn2.c (main): Ditto. + * testsuite/libffi.call/return_dbl1.c (main): Ditto. + * testsuite/libffi.call/closure_fn4.c (main): Ditto. + * testsuite/libffi.call/closure_fn6.c (main): Ditto. + * testsuite/libffi.call/cls_align_sint32.c (main): Ditto. + +2007-08-07 Andrew Haley + + * src/x86/sysv.S (ffi_closure_raw_SYSV): Fix typo in previous + checkin. + +2007-08-06 Andrew Haley + + PR testsuite/32843 + * src/x86/sysv.S (ffi_closure_raw_SYSV): Handle FFI_TYPE_UINT8, + FFI_TYPE_SINT8, FFI_TYPE_UINT16, FFI_TYPE_SINT16, FFI_TYPE_UINT32, + FFI_TYPE_SINT32. + +2007-08-02 David Daney + + * testsuite/libffi.call/return_ul.c (main): Define return type as + ffi_arg. Use proper printf conversion specifier. + +2007-07-30 Andrew Haley + + PR testsuite/32843 + * src/x86/ffi.c (ffi_prep_cif_machdep): in x86 case, add code for + signed/unsigned int8/16. + * src/x86/sysv.S (ffi_call_SYSV): Rewrite to: + Use a jump table. + Remove code to pop args from the stack after call. + Special-case signed/unsigned int8/16. + * testsuite/libffi.call/return_sc.c (main): Revert. + +2007-07-26 Richard Guenther + + PR testsuite/32843 + * testsuite/libffi.call/return_sc.c (main): Verify call + result as signed char, not ffi_arg. + +2007-07-16 Rainer Orth + + * configure.ac (i?86-*-solaris2.1[0-9]): Set TARGET to X86_64. + * configure: Regenerate. + +2007-07-11 David Daney + + * src/mips/ffi.c: Don't include sys/cachectl.h. + (ffi_prep_closure_loc): Use __builtin___clear_cache() instead of + cacheflush(). + +2007-05-18 Aurelien Jarno + + * src/arm/ffi.c (ffi_prep_closure_loc): Renamed and ajusted + from (ffi_prep_closure): ... this. + (FFI_INIT_TRAMPOLINE): Adjust. + +2005-12-31 Phil Blundell + + * src/arm/ffi.c (ffi_prep_incoming_args_SYSV, + ffi_closure_SYSV_inner, ffi_prep_closure): New, add closure support. + * src/arm/sysv.S(ffi_closure_SYSV): Likewise. + * src/arm/ffitarget.h (FFI_TRAMPOLINE_SIZE): Likewise. + (FFI_CLOSURES): Enable closure support. + +2007-07-03 Andrew Haley + + * testsuite/libffi.call/cls_multi_ushort.c, + testsuite/libffi.call/cls_align_uint16.c, + testsuite/libffi.call/nested_struct1.c, + testsuite/libffi.call/nested_struct3.c, + testsuite/libffi.call/cls_7_1_byte.c, + testsuite/libffi.call/cls_double.c, + testsuite/libffi.call/nested_struct5.c, + testsuite/libffi.call/nested_struct7.c, + testsuite/libffi.call/cls_sint.c, + testsuite/libffi.call/nested_struct9.c, + testsuite/libffi.call/cls_20byte1.c, + testsuite/libffi.call/cls_multi_sshortchar.c, + testsuite/libffi.call/cls_align_sint64.c, + testsuite/libffi.call/cls_3byte2.c, + testsuite/libffi.call/cls_multi_schar.c, + testsuite/libffi.call/cls_multi_uchar.c, + testsuite/libffi.call/cls_19byte.c, + testsuite/libffi.call/cls_9byte1.c, + testsuite/libffi.call/cls_align_float.c, + testsuite/libffi.call/closure_fn1.c, + testsuite/libffi.call/problem1.c, + testsuite/libffi.call/closure_fn3.c, + testsuite/libffi.call/cls_sshort.c, + testsuite/libffi.call/closure_fn5.c, + testsuite/libffi.call/cls_align_double.c, + testsuite/libffi.call/cls_2byte.c, + testsuite/libffi.call/nested_struct.c, + testsuite/libffi.call/nested_struct10.c, + testsuite/libffi.call/cls_4byte.c, + testsuite/libffi.call/cls_6byte.c, + testsuite/libffi.call/cls_8byte.c, + testsuite/libffi.call/cls_multi_sshort.c, + testsuite/libffi.call/cls_align_uint32.c, + testsuite/libffi.call/cls_align_sint16.c, + testsuite/libffi.call/cls_float.c, + testsuite/libffi.call/cls_20byte.c, + testsuite/libffi.call/cls_5_1_byte.c, + testsuite/libffi.call/nested_struct2.c, + testsuite/libffi.call/cls_24byte.c, + testsuite/libffi.call/nested_struct4.c, + testsuite/libffi.call/nested_struct6.c, + testsuite/libffi.call/cls_64byte.c, + testsuite/libffi.call/nested_struct8.c, + testsuite/libffi.call/cls_uint.c, + testsuite/libffi.call/cls_multi_ushortchar.c, + testsuite/libffi.call/cls_schar.c, + testsuite/libffi.call/cls_uchar.c, + testsuite/libffi.call/cls_align_uint64.c, + testsuite/libffi.call/cls_ulonglong.c, + testsuite/libffi.call/cls_align_longdouble.c, + testsuite/libffi.call/cls_1_1byte.c, + testsuite/libffi.call/cls_12byte.c, + testsuite/libffi.call/cls_3_1byte.c, + testsuite/libffi.call/cls_3byte1.c, + testsuite/libffi.call/cls_4_1byte.c, + testsuite/libffi.call/cls_6_1_byte.c, + testsuite/libffi.call/cls_16byte.c, + testsuite/libffi.call/cls_18byte.c, + testsuite/libffi.call/closure_fn0.c, + testsuite/libffi.call/cls_9byte2.c, + testsuite/libffi.call/closure_fn2.c, + testsuite/libffi.call/closure_fn4.c, + testsuite/libffi.call/cls_ushort.c, + testsuite/libffi.call/closure_fn6.c, + testsuite/libffi.call/cls_5byte.c, + testsuite/libffi.call/cls_align_pointer.c, + testsuite/libffi.call/cls_7byte.c, + testsuite/libffi.call/cls_align_sint32.c, + testsuite/libffi.special/unwindtest_ffi_call.cc, + testsuite/libffi.special/unwindtest.cc: Enable for ARM. + +2007-07-05 H.J. Lu + + * aclocal.m4: Regenerated. + +2007-06-02 Paolo Bonzini + + * configure: Regenerate. + +2007-05-23 Steve Ellcey + + * Makefile.in: Regenerate. + * configure: Regenerate. + * aclocal.m4: Regenerate. + * include/Makefile.in: Regenerate. + * testsuite/Makefile.in: Regenerate. + +2007-05-10 Roman Zippel + + * src/m68k/ffi.c (ffi_prep_incoming_args_SYSV, + ffi_closure_SYSV_inner,ffi_prep_closure): New, add closure support. + * src/m68k/sysv.S(ffi_closure_SYSV,ffi_closure_struct_SYSV): Likewise. + * src/m68k/ffitarget.h (FFI_TRAMPOLINE_SIZE): Likewise. + (FFI_CLOSURES): Enable closure support. + +2007-05-10 Roman Zippel + + * configure.ac (HAVE_AS_CFI_PSEUDO_OP): New test. + * configure: Regenerate. + * fficonfig.h.in: Regenerate. + * src/m68k/sysv.S (CFI_STARTPROC,CFI_ENDPROC, + CFI_OFFSET,CFI_DEF_CFA): New macros. + (ffi_call_SYSV): Add callframe annotation. + +2007-05-10 Roman Zippel + + * src/m68k/ffi.c (ffi_prep_args,ffi_prep_cif_machdep): Fix + numerous test suite failures. + * src/m68k/sysv.S (ffi_call_SYSV): Likewise. + +2007-04-11 Paolo Bonzini + + * Makefile.am (EXTRA_DIST): Bring up to date. + * Makefile.in: Regenerate. + * src/frv/eabi.S: Remove RCS keyword. + +2007-04-06 Richard Henderson + + * configure.ac: Tidy target case. + (HAVE_LONG_DOUBLE): Allow the target to override. + * configure: Regenerate. + * include/ffi.h.in: Don't define ffi_type_foo if + LIBFFI_HIDE_BASIC_TYPES is defined. + (ffi_type_longdouble): If not HAVE_LONG_DOUBLE, define + to ffi_type_double. + * types.c (LIBFFI_HIDE_BASIC_TYPES): Define. + (FFI_TYPEDEF, ffi_type_void): Mark the data const. + (ffi_type_longdouble): Special case for Alpha. Don't define + if long double == double. + + * src/alpha/ffi.c (FFI_TYPE_LONGDOUBLE): Assert unique value. + (ffi_prep_cif_machdep): Handle it as the 128-bit type. + (ffi_call, ffi_closure_osf_inner): Likewise. + (ffi_closure_osf_inner): Likewise. Mark hidden. + (ffi_call_osf, ffi_closure_osf): Mark hidden. + * src/alpha/ffitarget.h (FFI_LAST_ABI): Tidy definition. + * src/alpha/osf.S (ffi_call_osf, ffi_closure_osf): Mark hidden. + (load_table): Handle 128-bit long double. + + * testsuite/libffi.call/float4.c: Add -mieee for alpha. + +2007-04-06 Tom Tromey + + PR libffi/31491: + * README: Fixed bug in example. + +2007-04-03 Jakub Jelinek + + * src/closures.c: Include sys/statfs.h. + (_GNU_SOURCE): Define on Linux. + (FFI_MMAP_EXEC_SELINUX): Define. + (selinux_enabled): New variable. + (selinux_enabled_check): New function. + (is_selinux_enabled): Define. + (dlmmap): Use it. + +2007-03-24 Uros Bizjak + + * testsuite/libffi.call/return_fl2.c (return_fl): Mark as static. + Use 'volatile float sum' to create sum of floats to avoid false + negative due to excess precision on ix86 targets. + (main): Ditto. + +2007-03-08 Alexandre Oliva + + * src/powerpc/ffi.c (flush_icache): Fix left-over from previous + patch. + (ffi_prep_closure_loc): Remove unneeded casts. Add needed ones. + +2007-03-07 Alexandre Oliva + + * include/ffi.h.in (ffi_closure_alloc, ffi_closure_free): New. + (ffi_prep_closure_loc): New. + (ffi_prep_raw_closure_loc): New. + (ffi_prep_java_raw_closure_loc): New. + * src/closures.c: New file. + * src/dlmalloc.c [FFI_MMAP_EXEC_WRIT] (struct malloc_segment): + Replace sflags with exec_offset. + [FFI_MMAP_EXEC_WRIT] (mmap_exec_offset, add_segment_exec_offset, + sub_segment_exec_offset): New macros. + (get_segment_flags, set_segment_flags, check_segment_merge): New + macros. + (is_mmapped_segment, is_extern_segment): Use get_segment_flags. + (add_segment, sys_alloc, create_mspace, create_mspace_with_base, + destroy_mspace): Use new macros. + (sys_alloc): Silence warning. + * Makefile.am (libffi_la_SOURCES): Add src/closures.c. + * Makefile.in: Rebuilt. + * src/prep_cif [FFI_CLOSURES] (ffi_prep_closure): Implement in + terms of ffi_prep_closure_loc. + * src/raw_api.c (ffi_prep_raw_closure_loc): Renamed and adjusted + from... + (ffi_prep_raw_closure): ... this. Re-implement in terms of the + renamed version. + * src/java_raw_api (ffi_prep_java_raw_closure_loc): Renamed and + adjusted from... + (ffi_prep_java_raw_closure): ... this. Re-implement in terms of + the renamed version. + * src/alpha/ffi.c (ffi_prep_closure_loc): Renamed from + (ffi_prep_closure): ... this. + * src/pa/ffi.c: Likewise. + * src/cris/ffi.c: Likewise. Adjust. + * src/frv/ffi.c: Likewise. + * src/ia64/ffi.c: Likewise. + * src/mips/ffi.c: Likewise. + * src/powerpc/ffi_darwin.c: Likewise. + * src/s390/ffi.c: Likewise. + * src/sh/ffi.c: Likewise. + * src/sh64/ffi.c: Likewise. + * src/sparc/ffi.c: Likewise. + * src/x86/ffi64.c: Likewise. + * src/x86/ffi.c: Likewise. + (FFI_INIT_TRAMPOLINE): Adjust. + (ffi_prep_raw_closure_loc): Renamed and adjusted from... + (ffi_prep_raw_closure): ... this. + * src/powerpc/ffi.c (ffi_prep_closure_loc): Renamed from + (ffi_prep_closure): ... this. + (flush_icache): Adjust. + +2007-03-07 Alexandre Oliva + + * src/dlmalloc.c: New file, imported version 2.8.3 of Doug + Lea's malloc. + +2007-03-01 Brooks Moses + + * Makefile.am: Add dummy install-pdf target. + * Makefile.in: Regenerate + +2007-02-13 Andreas Krebbel + + * src/s390/ffi.c (ffi_prep_args, ffi_prep_cif_machdep, + ffi_closure_helper_SYSV): Add long double handling. + +2007-02-02 Jakub Jelinek + + * src/powerpc/linux64.S (ffi_call_LINUX64): Move restore of r2 + immediately after bctrl instruction. + +2007-01-18 Alexandre Oliva + + * Makefile.am (all-recursive, install-recursive, + mostlyclean-recursive, clean-recursive, distclean-recursive, + maintainer-clean-recursive): Add missing targets. + * Makefile.in: Rebuilt. + +2006-12-14 Andreas Tobler + + * configure.ac: Add TARGET for x86_64-*-darwin*. + * Makefile.am (nodist_libffi_la_SOURCES): Add rules for 64-bit sources + for X86_DARWIN. + * src/x86/ffitarget.h: Set trampoline size for x86_64-*-darwin*. + * src/x86/darwin64.S: New file for x86_64-*-darwin* support. + * configure: Regenerate. + * Makefile.in: Regenerate. + * include/Makefile.in: Regenerate. + * testsuite/Makefile.in: Regenerate. + * testsuite/libffi.special/unwindtest_ffi_call.cc: New test case for + ffi_call only. + +2006-12-13 Andreas Tobler + + * aclocal.m4: Regenerate with aclocal -I .. as written in the + Makefile.am. + +2006-10-31 Geoffrey Keating + + * src/powerpc/ffi_darwin.c (darwin_adjust_aggregate_sizes): New. + (ffi_prep_cif_machdep): Call darwin_adjust_aggregate_sizes for + Darwin. + * testsuite/libffi.call/nested_struct4.c: Remove Darwin XFAIL. + * testsuite/libffi.call/nested_struct6.c: Remove Darwin XFAIL. + +2006-10-10 Paolo Bonzini + Sandro Tolaini + + * configure.ac [i*86-*-darwin*]: Set X86_DARWIN symbol and + conditional. + * configure: Regenerated. + * Makefile.am (nodist_libffi_la_SOURCES) [X86_DARWIN]: New case. + (EXTRA_DIST): Add src/x86/darwin.S. + * Makefile.in: Regenerated. + * include/Makefile.in: Regenerated. + * testsuite/Makefile.in: Regenerated. + + * src/x86/ffi.c (ffi_prep_cif_machdep) [X86_DARWIN]: Treat like + X86_WIN32, and additionally align stack to 16 bytes. + * src/x86/darwin.S: New, based on sysv.S. + * src/prep_cif.c (ffi_prep_cif) [X86_DARWIN]: Align > 8-byte structs. + +2006-09-12 David Daney + + PR libffi/23935 + * include/Makefile.am: Install both ffi.h and ffitarget.h in + $(libdir)/gcc/$(target_alias)/$(gcc_version)/include. + * aclocal.m4: Regenerated for automake 1.9.6. + * Makefile.in: Regenerated. + * include/Makefile.in: Regenerated. + * testsuite/Makefile.in: Regenerated. + +2006-08-17 Andreas Tobler + + * include/ffi_common.h (struct): Revert accidental commit. + +2006-08-15 Andreas Tobler + + * include/ffi_common.h: Remove lint directives. + * include/ffi.h.in: Likewise. + +2006-07-25 Torsten Schoenfeld + + * include/ffi.h.in (ffi_type_ulong, ffi_type_slong): Define correctly + for 32-bit architectures. + * testsuite/libffi.call/return_ul.c: New test case. + +2006-07-19 David Daney + + * testsuite/libffi.call/closure_fn6.c: Remove xfail for mips, + xfail remains for mips64. + +2006-05-23 Carlos O'Donell + + * Makefile.am: Add install-html target. Add install-html to .PHONY + * Makefile.in: Regenerate. + * aclocal.m4: Regenerate. + * include/Makefile.in: Regenerate. + * testsuite/Makefile.in: Regenerate. + +2006-05-18 John David Anglin + + * pa/ffi.c (ffi_prep_args_pa32): Load floating point arguments from + stack slot. + +2006-04-22 Andreas Tobler + + * README: Remove notice about 'Crazy Comments'. + * src/debug.c: Remove lint directives. Cleanup white spaces. + * src/java_raw_api.c: Likewise. + * src/prep_cif.c: Likewise. + * src/raw_api.c: Likewise. + * src/ffitest.c: Delete. No longer needed, all test cases migrated + to the testsuite. + * src/arm/ffi.c: Remove lint directives. + * src/m32r/ffi.c: Likewise. + * src/pa/ffi.c: Likewise. + * src/powerpc/ffi.c: Likewise. + * src/powerpc/ffi_darwin.c: Likewise. + * src/sh/ffi.c: Likewise. + * src/sh64/ffi.c: Likewise. + * src/x86/ffi.c: Likewise. + * testsuite/libffi.call/float2.c: Likewise. + * testsuite/libffi.call/promotion.c: Likewise. + * testsuite/libffi.call/struct1.c: Likewise. + +2006-04-13 Andreas Tobler + + * src/pa/hpux32.S: Correct unwind offset calculation for + ffi_closure_pa32. + * src/pa/linux.S: Likewise. + +2006-04-12 James E Wilson + + PR libgcj/26483 + * src/ia64/ffi.c (stf_spill, ldf_fill): Rewrite as macros. + (hfa_type_load): Call stf_spill. + (hfa_type_store): Call ldf_fill. + (ffi_call): Adjust calls to above routines. Add local temps for + macro result. + +2006-04-10 Matthias Klose + + * testsuite/lib/libffi-dg.exp (libffi-init): Recognize multilib + directory names containing underscores. + +2006-04-07 James E Wilson + + * testsuite/libffi.call/float4.c: New testcase. + +2006-04-05 John David Anglin + Andreas Tobler + + * Makefile.am: Add PA_HPUX port. + * Makefile.in: Regenerate. + * include/Makefile.in: Likewise. + * testsuite/Makefile.in: Likewise. + * configure.ac: Add PA_HPUX rules. + * configure: Regenerate. + * src/pa/ffitarget.h: Rename linux target to PA_LINUX. + Add PA_HPUX and PA64_HPUX. + Rename FFI_LINUX ABI to FFI_PA32 ABI. + (FFI_TRAMPOLINE_SIZE): Define for 32-bit HP-UX targets. + (FFI_TYPE_SMALL_STRUCT2): Define. + (FFI_TYPE_SMALL_STRUCT4): Likewise. + (FFI_TYPE_SMALL_STRUCT8): Likewise. + (FFI_TYPE_SMALL_STRUCT3): Redefine. + (FFI_TYPE_SMALL_STRUCT5): Likewise. + (FFI_TYPE_SMALL_STRUCT6): Likewise. + (FFI_TYPE_SMALL_STRUCT7): Likewise. + * src/pa/ffi.c (ROUND_DOWN): Delete. + (fldw, fstw, fldd, fstd): Use '__asm__'. + (ffi_struct_type): Add support for FFI_TYPE_SMALL_STRUCT2, + FFI_TYPE_SMALL_STRUCT4 and FFI_TYPE_SMALL_STRUCT8. + (ffi_prep_args_LINUX): Rename to ffi_prep_args_pa32. Update comment. + Simplify incrementing of stack slot variable. Change type of local + 'n' to unsigned int. + (ffi_size_stack_LINUX): Rename to ffi_size_stack_pa32. Handle long + double on PA_HPUX. + (ffi_prep_cif_machdep): Likewise. + (ffi_call): Likewise. + (ffi_closure_inner_LINUX): Rename to ffi_closure_inner_pa32. Change + return type to ffi_status. Simplify incrementing of stack slot + variable. Only copy floating point argument registers when PA_LINUX + is true. Reformat debug statement. + Add support for FFI_TYPE_SMALL_STRUCT2, FFI_TYPE_SMALL_STRUCT4 and + FFI_TYPE_SMALL_STRUCT8. + (ffi_closure_LINUX): Rename to ffi_closure_pa32. Add 'extern' to + declaration. + (ffi_prep_closure): Make linux trampoline conditional on PA_LINUX. + Add nops to cache flush. Add trampoline for PA_HPUX. + * src/pa/hpux32.S: New file. + * src/pa/linux.S (ffi_call_LINUX): Rename to ffi_call_pa32. Rename + ffi_prep_args_LINUX to ffi_prep_args_pa32. + Localize labels. Add support for 2, 4 and 8-byte small structs. Handle + unaligned destinations in 3, 5, 6 and 7-byte small structs. Order + argument type checks so that common argument types appear first. + (ffi_closure_LINUX): Rename to ffi_closure_pa32. Rename + ffi_closure_inner_LINUX to ffi_closure_inner_pa32. + +2006-03-24 Alan Modra + + * src/powerpc/ffitarget.h (enum ffi_abi): Add FFI_LINUX. Default + for 32-bit using IBM extended double format. Fix FFI_LAST_ABI. + * src/powerpc/ffi.c (ffi_prep_args_SYSV): Handle linux variant of + FFI_TYPE_LONGDOUBLE. + (ffi_prep_args64): Assert using IBM extended double. + (ffi_prep_cif_machdep): Don't munge FFI_TYPE_LONGDOUBLE type. + Handle FFI_LINUX FFI_TYPE_LONGDOUBLE return and args. + (ffi_call): Handle FFI_LINUX. + (ffi_closure_helper_SYSV): Non FFI_LINUX long double return needs + gpr3 return pointer as for struct return. Handle FFI_LINUX + FFI_TYPE_LONGDOUBLE return and args. Don't increment "nf" + unnecessarily. + * src/powerpc/ppc_closure.S (ffi_closure_SYSV): Load both f1 and f2 + for FFI_TYPE_LONGDOUBLE. Move epilogue insns into case table. + Don't use r6 as pointer to results, instead use sp offset. Don't + make a special call to load lr with case table address, instead + use offset from previous call. + * src/powerpc/sysv.S (ffi_call_SYSV): Save long double return. + * src/powerpc/linux64.S (ffi_call_LINUX64): Simplify long double + return. + +2006-03-15 Kaz Kojima + + * src/sh64/ffi.c (ffi_prep_cif_machdep): Handle float arguments + passed with FP registers correctly. + (ffi_closure_helper_SYSV): Likewise. + * src/sh64/sysv.S: Likewise. + +2006-03-01 Andreas Tobler + + * testsuite/libffi.special/unwindtest.cc (closure_test_fn): Mark cif, + args and userdata unused. + (closure_test_fn1): Mark cif and userdata unused. + (main): Remove unused res. + +2006-02-28 Andreas Tobler + + * testsuite/libffi.call/call.exp: Adjust FSF address. Add test runs for + -O2, -O3, -Os and the warning flags -W -Wall. + * testsuite/libffi.special/special.exp: Likewise. + * testsuite/libffi.call/ffitest.h: Add an __UNUSED__ macro to mark + unused parameter unused for gcc or else do nothing. + * testsuite/libffi.special/ffitestcxx.h: Likewise. + * testsuite/libffi.call/cls_12byte.c (cls_struct_12byte_gn): Mark cif + and userdata unused. + * testsuite/libffi.call/cls_16byte.c (cls_struct_16byte_gn): Likewise. + * testsuite/libffi.call/cls_18byte.c (cls_struct_18byte_gn): Likewise. + * testsuite/libffi.call/cls_19byte.c (cls_struct_19byte_gn): Likewise. + * testsuite/libffi.call/cls_1_1byte.c (cls_struct_1_1byte_gn): Likewise. + * testsuite/libffi.call/cls_20byte.c (cls_struct_20byte_gn): Likewise. + * testsuite/libffi.call/cls_20byte1.c (cls_struct_20byte_gn): Likewise. + * testsuite/libffi.call/cls_24byte.c (cls_struct_24byte_gn): Likewise. + * testsuite/libffi.call/cls_2byte.c (cls_struct_2byte_gn): Likewise. + * testsuite/libffi.call/cls_3_1byte.c (cls_struct_3_1byte_gn): Likewise. + * testsuite/libffi.call/cls_3byte1.c (cls_struct_3byte_gn): Likewise. + * testsuite/libffi.call/cls_3byte2.c (cls_struct_3byte_gn1): Likewise. + * testsuite/libffi.call/cls_4_1byte.c (cls_struct_4_1byte_gn): Likewise. + * testsuite/libffi.call/cls_4byte.c (cls_struct_4byte_gn): Likewise. + * testsuite/libffi.call/cls_5_1_byte.c (cls_struct_5byte_gn): Likewise. + * testsuite/libffi.call/cls_5byte.c (cls_struct_5byte_gn): Likewise. + * testsuite/libffi.call/cls_64byte.c (cls_struct_64byte_gn): Likewise. + * testsuite/libffi.call/cls_6_1_byte.c (cls_struct_6byte_gn): Likewise. + * testsuite/libffi.call/cls_6byte.c (cls_struct_6byte_gn): Likewise. + * testsuite/libffi.call/cls_7_1_byte.c (cls_struct_7byte_gn): Likewise. + * testsuite/libffi.call/cls_7byte.c (cls_struct_7byte_gn): Likewise. + * testsuite/libffi.call/cls_8byte.c (cls_struct_8byte_gn): Likewise. + * testsuite/libffi.call/cls_9byte1.c (cls_struct_9byte_gn): Likewise. + * testsuite/libffi.call/cls_9byte2.c (cls_struct_9byte_gn): Likewise. + * testsuite/libffi.call/cls_align_double.c (cls_struct_align_gn): + Likewise. + * testsuite/libffi.call/cls_align_float.c (cls_struct_align_gn): + Likewise. + * testsuite/libffi.call/cls_align_longdouble.c (cls_struct_align_gn): + Likewise. + * testsuite/libffi.call/cls_align_pointer.c (cls_struct_align_fn): Cast + void* to avoid compiler warning. + (main): Likewise. + (cls_struct_align_gn): Mark cif and userdata unused. + * testsuite/libffi.call/cls_align_sint16.c (cls_struct_align_gn): + Likewise. + * testsuite/libffi.call/cls_align_sint32.c (cls_struct_align_gn): + Likewise. + * testsuite/libffi.call/cls_align_sint64.c (cls_struct_align_gn): + Likewise. + * testsuite/libffi.call/cls_align_uint16.c (cls_struct_align_gn): + Likewise. + * testsuite/libffi.call/cls_align_uint32.c (cls_struct_align_gn): + Likewise. + * testsuite/libffi.call/cls_double.c (cls_ret_double_fn): Likewise. + * testsuite/libffi.call/cls_float.c (cls_ret_float_fn): Likewise. + * testsuite/libffi.call/cls_multi_schar.c (test_func_gn): Mark cif and + data unused. + (main): Cast res_call to silence gcc. + * testsuite/libffi.call/cls_multi_sshort.c (test_func_gn): Mark cif and + data unused. + (main): Cast res_call to silence gcc. + * testsuite/libffi.call/cls_multi_sshortchar.c (test_func_gn): Mark cif + and data unused. + (main): Cast res_call to silence gcc. + * testsuite/libffi.call/cls_multi_uchar.c (test_func_gn): Mark cif and + data unused. + (main): Cast res_call to silence gcc. + * testsuite/libffi.call/cls_multi_ushort.c (test_func_gn): Mark cif and + data unused. + (main): Cast res_call to silence gcc. + * testsuite/libffi.call/cls_multi_ushortchar.c (test_func_gn): Mark cif + and data unused. + (main): Cast res_call to silence gcc. + * testsuite/libffi.call/cls_schar.c (cls_ret_schar_fn): Mark cif and + userdata unused. + (cls_ret_schar_fn): Cast printf parameter to silence gcc. + * testsuite/libffi.call/cls_sint.c (cls_ret_sint_fn): Mark cif and + userdata unused. + (cls_ret_sint_fn): Cast printf parameter to silence gcc. + * testsuite/libffi.call/cls_sshort.c (cls_ret_sshort_fn): Mark cif and + userdata unused. + (cls_ret_sshort_fn): Cast printf parameter to silence gcc. + * testsuite/libffi.call/cls_uchar.c (cls_ret_uchar_fn): Mark cif and + userdata unused. + (cls_ret_uchar_fn): Cast printf parameter to silence gcc. + * testsuite/libffi.call/cls_uint.c (cls_ret_uint_fn): Mark cif and + userdata unused. + (cls_ret_uint_fn): Cast printf parameter to silence gcc. + * testsuite/libffi.call/cls_ulonglong.c (cls_ret_ulonglong_fn): Mark cif + and userdata unused. + * testsuite/libffi.call/cls_ushort.c (cls_ret_ushort_fn): Mark cif and + userdata unused. + (cls_ret_ushort_fn): Cast printf parameter to silence gcc. + * testsuite/libffi.call/float.c (floating): Remove unused parameter e. + * testsuite/libffi.call/float1.c (main): Remove unused variable i. + Cleanup white spaces. + * testsuite/libffi.call/negint.c (checking): Remove unused variable i. + * testsuite/libffi.call/nested_struct.c (cls_struct_combined_gn): Mark + cif and userdata unused. + * testsuite/libffi.call/nested_struct1.c (cls_struct_combined_gn): + Likewise. + * testsuite/libffi.call/nested_struct10.c (B_gn): Likewise. + * testsuite/libffi.call/nested_struct2.c (B_fn): Adjust printf + formatters to silence gcc. + (B_gn): Mark cif and userdata unused. + * testsuite/libffi.call/nested_struct3.c (B_gn): Mark cif and userdata + unused. + * testsuite/libffi.call/nested_struct4.c: Mention related PR. + (B_gn): Mark cif and userdata unused. + * testsuite/libffi.call/nested_struct5.c (B_gn): Mark cif and userdata + unused. + * testsuite/libffi.call/nested_struct6.c: Mention related PR. + (B_gn): Mark cif and userdata unused. + * testsuite/libffi.call/nested_struct7.c (B_gn): Mark cif and userdata + unused. + * testsuite/libffi.call/nested_struct8.c (B_gn): Likewise. + * testsuite/libffi.call/nested_struct9.c (B_gn): Likewise. + * testsuite/libffi.call/problem1.c (stub): Likewise. + * testsuite/libffi.call/pyobjc-tc.c (main): Cast the result to silence + gcc. + * testsuite/libffi.call/return_fl2.c (return_fl): Add the note mentioned + in the last commit for this test case in the test case itself. + * testsuite/libffi.call/closure_fn0.c (closure_test_fn0): Mark cif as + unused. + * testsuite/libffi.call/closure_fn1.c (closure_test_fn1): Likewise. + * testsuite/libffi.call/closure_fn2.c (closure_test_fn2): Likewise. + * testsuite/libffi.call/closure_fn3.c (closure_test_fn3): Likewise. + * testsuite/libffi.call/closure_fn4.c (closure_test_fn0): Likewise. + * testsuite/libffi.call/closure_fn5.c (closure_test_fn5): Likewise. + * testsuite/libffi.call/closure_fn6.c (closure_test_fn0): Likewise. + +2006-02-22 Kaz Kojima + + * src/sh/sysv.S: Fix register numbers in the FDE for + ffi_closure_SYSV. + +2006-02-20 Andreas Tobler + + * testsuite/libffi.call/return_fl2.c (return_fl): Remove static + declaration to avoid a false negative on ix86. See PR323. + +2006-02-18 Kaz Kojima + + * src/sh/ffi.c (ffi_closure_helper_SYSV): Remove unused variable + and cast integer to void * if needed. Update the pointer to + the FP register saved area correctly. + +2006-02-17 Andreas Tobler + + * testsuite/libffi.call/nested_struct6.c: XFAIL this test until PR25630 + is fixed. + * testsuite/libffi.call/nested_struct4.c: Likewise. + +2006-02-16 Andreas Tobler + + * testsuite/libffi.call/return_dbl.c: New test case. + * testsuite/libffi.call/return_dbl1.c: Likewise. + * testsuite/libffi.call/return_dbl2.c: Likewise. + * testsuite/libffi.call/return_fl.c: Likewise. + * testsuite/libffi.call/return_fl1.c: Likewise. + * testsuite/libffi.call/return_fl2.c: Likewise. + * testsuite/libffi.call/return_fl3.c: Likewise. + * testsuite/libffi.call/closure_fn6.c: Likewise. + + * testsuite/libffi.call/nested_struct2.c: Remove ffi_type_mylong + definition. + * testsuite/libffi.call/ffitest.h: Add ffi_type_mylong definition + here to be used by other test cases too. + + * testsuite/libffi.call/nested_struct10.c: New test case. + * testsuite/libffi.call/nested_struct9.c: Likewise. + * testsuite/libffi.call/nested_struct8.c: Likewise. + * testsuite/libffi.call/nested_struct7.c: Likewise. + * testsuite/libffi.call/nested_struct6.c: Likewise. + * testsuite/libffi.call/nested_struct5.c: Likewise. + * testsuite/libffi.call/nested_struct4.c: Likewise. + +2006-01-21 Andreas Tobler + + * configure.ac: Enable libffi for sparc64-*-freebsd*. + * configure: Rebuilt. + +2006-01-18 Jakub Jelinek + + * src/powerpc/sysv.S (smst_two_register): Don't call __ashldi3, + instead do the shifting inline. + * src/powerpc/ppc_closure.S (ffi_closure_SYSV): Don't compute %r5 + shift count unconditionally. Simplify load sequences for 1, 2, 3, 4 + and 8 byte structs, for the remaining struct sizes don't call + __lshrdi3, instead do the shifting inline. + +2005-12-07 Thiemo Seufer + + * src/mips/ffitarget.h: Remove obsolete sgidefs.h include. Add + missing parentheses. + * src/mips/o32.S (ffi_call_O32): Code formatting. Define + and use A3_OFF, FP_OFF, RA_OFF. Micro-optimizations. + (ffi_closure_O32): Likewise, but with newly defined A3_OFF2, + A2_OFF2, A1_OFF2, A0_OFF2, RA_OFF2, FP_OFF2, S0_OFF2, GP_OFF2, + V1_OFF2, V0_OFF2, FA_1_1_OFF2, FA_1_0_OFF2, FA_0_1_OFF2, + FA_0_0_OFF2. + * src/mips/ffi.c (ffi_prep_args): Code formatting. Fix + endianness bugs. + (ffi_prep_closure): Improve trampoline instruction scheduling. + (ffi_closure_mips_inner_O32): Fix endianness bugs. + +2005-12-03 Alan Modra + + * src/powerpc/ffi.c: Formatting. + (ffi_prep_args_SYSV): Avoid possible aliasing problems by using unions. + (ffi_prep_args64): Likewise. + +2005-09-30 Geoffrey Keating + + * testsuite/lib/libffi-dg.exp (libffi_target_compile): For + darwin, use -shared-libgcc not -lgcc_s, and explain why. + +2005-09-26 Tom Tromey + + * testsuite/libffi.call/float1.c (value_type): New typedef. + (CANARY): New define. + (main): Check for result buffer overflow. + * src/powerpc/linux64.S: Handle linux64 long double returns. + * src/powerpc/ffi.c (FLAG_RETURNS_128BITS): New constant. + (ffi_prep_cif_machdep): Handle linux64 long double returns. + +2005-08-25 Alan Modra + + PR target/23404 + * src/powerpc/ffi.c (ffi_prep_args_SYSV): Correct placement of stack + homed fp args. + (ffi_status ffi_prep_cif_machdep): Correct stack sizing for same. + +2005-08-11 Jakub Jelinek + + * configure.ac (HAVE_HIDDEN_VISIBILITY_ATTRIBUTE): New test. + (AH_BOTTOM): Add FFI_HIDDEN definition. + * configure: Rebuilt. + * fficonfig.h.in: Rebuilt. + * src/powerpc/ffi.c (hidden): Remove. + (ffi_closure_LINUX64, ffi_prep_args64, ffi_call_LINUX64, + ffi_closure_helper_LINUX64): Use FFI_HIDDEN instead of hidden. + * src/powerpc/linux64_closure.S (ffi_closure_LINUX64, + .ffi_closure_LINUX64): Use FFI_HIDDEN instead of .hidden. + * src/x86/ffi.c (ffi_closure_SYSV, ffi_closure_raw_SYSV): Remove, + add FFI_HIDDEN to its prototype. + (ffi_closure_SYSV_inner): New. + * src/x86/sysv.S (ffi_closure_SYSV, ffi_closure_raw_SYSV): New. + * src/x86/win32.S (ffi_closure_SYSV, ffi_closure_raw_SYSV): New. + +2005-08-10 Alfred M. Szmidt + + PR libffi/21819: + * configure: Rebuilt. + * configure.ac: Handle i*86-*-gnu*. + +2005-08-09 Jakub Jelinek + + * src/powerpc/ppc_closure.S (ffi_closure_SYSV): Use + DW_CFA_offset_extended_sf rather than + DW_CFA_GNU_negative_offset_extended. + * src/powerpc/sysv.S (ffi_call_SYSV): Likewise. + +2005-07-22 SUGIOKA Toshinobu + + * src/sh/sysv.S (ffi_call_SYSV): Stop argument popping correctly + on sh3. + (ffi_closure_SYSV): Change the stack layout for sh3 struct argument. + * src/sh/ffi.c (ffi_prep_args): Fix sh3 argument copy, when it is + partially on register. + (ffi_closure_helper_SYSV): Likewise. + (ffi_prep_cif_machdep): Don't set too many cif->flags. + +2005-07-20 Kaz Kojima + + * src/sh/ffi.c (ffi_call): Handle small structures correctly. + Remove empty line. + * src/sh64/ffi.c (simple_type): Remove. + (return_type): Handle small structures correctly. + (ffi_prep_args): Likewise. + (ffi_call): Likewise. + (ffi_closure_helper_SYSV): Likewise. + * src/sh64/sysv.S (ffi_call_SYSV): Handle 1, 2 and 4-byte return. + Emit position independent code if PIC and remove wrong datalabel + prefixes from EH data. + +2005-07-19 Andreas Tobler + + * Makefile.am (nodist_libffi_la_SOURCES): Add POWERPC_FREEBSD. + * Makefile.in: Regenerate. + * include/Makefile.in: Likewise. + * testsuite/Makefile.in: Likewise. + * configure.ac: Add POWERPC_FREEBSD rules. + * configure: Regenerate. + * src/powerpc/ffitarget.h: Add POWERPC_FREEBSD rules. + (FFI_SYSV_TYPE_SMALL_STRUCT): Define. + * src/powerpc/ffi.c: Add flags to handle small structure returns + in ffi_call_SYSV. + (ffi_prep_cif_machdep): Handle small structures for SYSV 4 ABI. + Aka FFI_SYSV. + (ffi_closure_helper_SYSV): Likewise. + * src/powerpc/ppc_closure.S: Add return types for small structures. + * src/powerpc/sysv.S: Add bits to handle small structures for + final SYSV 4 ABI. + +2005-07-10 Andreas Tobler + + * testsuite/libffi.call/cls_5_1_byte.c: New test file. + * testsuite/libffi.call/cls_6_1_byte.c: Likewise. + * testsuite/libffi.call/cls_7_1_byte.c: Likewise. + +2005-07-05 Randolph Chung + + * src/pa/ffi.c (ffi_struct_type): Rename FFI_TYPE_SMALL_STRUCT1 + as FFI_TYPE_SMALL_STRUCT3. Break out handling for 5-7 byte + structures. Kill compilation warnings. + (ffi_closure_inner_LINUX): Print return values as hex in debug + message. Rename FFI_TYPE_SMALL_STRUCT1 as FFI_TYPE_SMALL_STRUCT3. + Properly handle 5-7 byte structure returns. + * src/pa/ffitarget.h (FFI_TYPE_SMALL_STRUCT1) + (FFI_TYPE_SMALL_STRUCT2): Remove. + (FFI_TYPE_SMALL_STRUCT3, FFI_TYPE_SMALL_STRUCT5) + (FFI_TYPE_SMALL_STRUCT6, FFI_TYPE_SMALL_STRUCT7): Define. + * src/pa/linux.S: Mark source file as using PA1.1 assembly. + (checksmst1, checksmst2): Remove. + (checksmst3): Optimize handling of 3-byte struct returns. + (checksmst567): Properly handle 5-7 byte struct returns. + +2005-06-15 Rainer Orth + + PR libgcj/21943 + * src/mips/n32.S: Enforce PIC code. + * src/mips/o32.S: Likewise. + +2005-06-15 Rainer Orth + + * configure.ac: Treat i*86-*-solaris2.10 and up as X86_64. + * configure: Regenerate. + +2005-06-01 Alan Modra + + * src/powerpc/ppc_closure.S (ffi_closure_SYSV): Don't use JUMPTARGET + to call ffi_closure_helper_SYSV. Append @local instead. + * src/powerpc/sysv.S (ffi_call_SYSV): Likewise for ffi_prep_args_SYSV. + +2005-05-17 Kelley Cook + + * configure.ac: Use AC_C_BIGENDIAN instead of AC_C_BIGENDIAN_CROSS. + Use AC_CHECK_SIZEOF instead of AC_COMPILE_CHECK_SIZEOF. + * Makefile.am (ACLOCAL_AMFLAGS): Remove -I ../config. + * aclocal.m4, configure, fficonfig.h.in, Makefile.in, + include/Makefile.in, testsuite/Makefile.in: Regenerate. + +2005-05-09 Mike Stump + + * configure: Regenerate. + +2005-05-08 Richard Henderson + + PR libffi/21285 + * src/alpha/osf.S: Update unwind into to match code. + +2005-05-04 Andreas Degert + Richard Henderson + + * src/x86/ffi64.c (ffi_prep_cif_machdep): Save sse-used flag in + bit 11 of flags. + (ffi_call): Mask return type field. Pass ssecount to ffi_call_unix64. + (ffi_prep_closure): Set carry bit if sse-used flag set. + * src/x86/unix64.S (ffi_call_unix64): Add ssecount argument. + Only load sse registers if ssecount non-zero. + (ffi_closure_unix64): Only save sse registers if carry set on entry. + +2005-04-29 Ralf Corsepius + + * configure.ac: Add i*86-*-rtems*, sparc*-*-rtems*, + powerpc-*rtems*, arm*-*-rtems*, sh-*-rtems*. + * configure: Regenerate. + +2005-04-20 Hans-Peter Nilsson + + * testsuite/lib/libffi-dg.exp (libffi-dg-test-1): In regsub use, + have Tcl8.3-compatible intermediate variable. + +2005-04-18 Simon Posnjak + Hans-Peter Nilsson + + * Makefile.am: Add CRIS support. + * configure.ac: Likewise. + * Makefile.in, configure, testsuite/Makefile.in, + include/Makefile.in: Regenerate. + * src/cris: New directory. + * src/cris/ffi.c, src/cris/sysv.S, src/cris/ffitarget.h: New files. + * src/prep_cif.c (ffi_prep_cif): Wrap in #ifndef __CRIS__. + + * testsuite/lib/libffi-dg.exp (libffi-dg-test-1): Replace \n with + \r?\n in output tests. + +2005-04-12 Mike Stump + + * configure: Regenerate. + +2005-03-30 Hans Boehm + + * src/ia64/ffitarget.h (ffi_arg): Use long long instead of DI. + +2005-03-30 Steve Ellcey + + * src/ia64/ffitarget.h (ffi_arg) ADD DI attribute. + (ffi_sarg) Ditto. + * src/ia64/unix.S (ffi_closure_unix): Extend gp + to 64 bits in ILP32 mode. + Load 64 bits even for short data. + +2005-03-23 Mike Stump + + * src/powerpc/darwin.S: Update for -m64 multilib. + * src/powerpc/darwin_closure.S: Likewise. + +2005-03-21 Zack Weinberg + + * configure.ac: Do not invoke TL_AC_GCC_VERSION. + Do not set tool_include_dir. + * aclocal.m4, configure, Makefile.in, testsuite/Makefile.in: + Regenerate. + * include/Makefile.am: Set gcc_version and toollibffidir. + * include/Makefile.in: Regenerate. + +2005-02-22 Andrew Haley + + * src/powerpc/ffi.c (ffi_prep_cif_machdep): Bump alignment to + odd-numbered register pairs for 64-bit integer types. + +2005-02-23 Andreas Tobler + + PR libffi/20104 + * testsuite/libffi.call/return_ll1.c: New test case. + +2005-02-11 Janis Johnson + + * testsuite/libffi.call/cls_align_longdouble.c: Remove dg-options. + * testsuite/libffi.call/float.c: Ditto. + * testsuite/libffi.call/float2.c: Ditto. + * testsuite/libffi.call/float3.c: Ditto. + +2005-02-08 Andreas Tobler + + * src/frv/ffitarget.h: Remove PPC stuff which does not belong to frv. + +2005-01-12 Eric Botcazou + + * testsuite/libffi.special/special.exp (cxx_options): Add + -shared-libgcc. + +2004-12-31 Richard Henderson + + * src/types.c (FFI_AGGREGATE_TYPEDEF): Remove. + (FFI_TYPEDEF): Rename from FFI_INTEGRAL_TYPEDEF. Replace size and + offset parameters with a type parameter; deduce size and structure + alignment. Update all users. + +2004-12-31 Richard Henderson + + * src/types.c (FFI_TYPE_POINTER): Define with sizeof. + (FFI_TYPE_LONGDOUBLE): Fix for ia64. + * src/ia64/ffitarget.h (struct ffi_ia64_trampoline_struct): Move + into ffi_prep_closure. + * src/ia64/ia64_flags.h, src/ia64/ffi.c, src/ia64/unix.S: Rewrite + from scratch. + +2004-12-27 Richard Henderson + + * src/x86/unix64.S: Fix typo in unwind info. + +2004-12-25 Richard Henderson + + * src/x86/ffi64.c (struct register_args): Rename from stackLayout. + (enum x86_64_reg_class): Add X86_64_COMPLEX_X87_CLASS. + (merge_classes): Check for it. + (SSE_CLASS_P): New. + (classify_argument): Pass byte_offset by value; perform all updates + inside struct case. + (examine_argument): Add classes argument; handle + X86_64_COMPLEX_X87_CLASS. + (ffi_prep_args): Merge into ... + (ffi_call): ... here. Share stack frame with ffi_call_unix64. + (ffi_prep_cif_machdep): Setup cif->flags for proper structure return. + (ffi_fill_return_value): Remove. + (ffi_prep_closure): Remove dead assert. + (ffi_closure_unix64_inner): Rename from ffi_closure_UNIX64_inner. + Rewrite to use struct register_args instead of va_list. Create + flags for handling structure returns. + * src/x86/unix64.S: Remove dead strings. + (ffi_call_unix64): Rename from ffi_call_UNIX64. Rewrite to share + stack frame with ffi_call. Handle structure returns properly. + (float2sse, floatfloat2sse, double2sse): Remove. + (sse2float, sse2double, sse2floatfloat): Remove. + (ffi_closure_unix64): Rename from ffi_closure_UNIX64. Rewrite + to handle structure returns properly. + +2004-12-08 David Edelsohn + + * Makefile.am (AM_MAKEFLAGS): Remove duplicate LIBCFLAGS and + PICFLAG. + * Makefile.in: Regenerated. + +2004-12-02 Richard Sandiford + + * configure.ac: Use TL_AC_GCC_VERSION to set gcc_version. + * configure, aclocal.m4, Makefile.in: Regenerate. + * include/Makefile.in, testsuite/Makefile.in: Regenerate. + +2004-11-29 Kelley Cook + + * configure: Regenerate for libtool change. + +2004-11-25 Kelley Cook + + * configure: Regenerate for libtool reversion. + +2004-11-24 Kelley Cook + + * configure: Regenerate for libtool change. + +2004-11-23 John David Anglin + + * testsuite/lib/libffi-dg.exp: Use new procs in target-libpath.exp. + +2004-11-23 Richard Sandiford + + * src/mips/o32.S (ffi_call_O32, ffi_closure_O32): Use jalr instead + of jal. Use an absolute encoding for the frame information. + +2004-11-23 Kelley Cook + + * Makefile.am: Remove no-dependencies. Add ACLOCAL_AMFLAGS. + * acinclude.m4: Delete logic for sincludes. + * aclocal.m4, Makefile.in, configure: Regenerate. + * include/Makefile: Likewise. + * testsuite/Makefile: Likewise. + +2004-11-22 Eric Botcazou + + * src/sparc/ffi.c (ffi_prep_closure): Align doubles and 64-bit integers + on a 8-byte boundary. + * src/sparc/v8.S (ffi_closure_v8): Reserve frame space for arguments. + +2004-10-27 Richard Earnshaw + + * src/arm/ffi.c (ffi_prep_cif_machdep): Handle functions that return + long long values. Round stack allocation to a multiple of 8 bytes + for ATPCS compatibility. + * src/arm/sysv.S (ffi_call_SYSV): Rework to avoid use of APCS register + names. Handle returning long long types. Add Thumb and interworking + support. Improve soft-float code. + +2004-10-27 Richard Earnshaw + + * testsuite/lib/libffi-db.exp (load_gcc_lib): New function. + (libffi_exit): New function. + (libffi_init): Build the testglue wrapper if needed. + +2004-10-25 Eric Botcazou + + PR other/18138 + * testsuite/lib/libffi-dg.exp: Accept more than one multilib libgcc. + +2004-10-25 Kazuhiro Inaoka + + * src/m32r/libffitarget.h (FFI_CLOSURES): Set to 0. + +2004-10-20 Kaz Kojima + + * src/sh/sysv.S (ffi_call_SYSV): Don't align for double data. + * testsuite/libffi.call/float3.c: New test case. + +2004-10-18 Kaz Kojima + + * src/sh/ffi.c (ffi_prep_closure): Set T bit in trampoline for + the function returning a structure pointed with R2. + * src/sh/sysv.S (ffi_closure_SYSV): Use R2 as the pointer to + the structure return value if T bit set. Emit position + independent code and EH data if PIC. + +2004-10-13 Kazuhiro Inaoka + + * Makefile.am: Add m32r support. + * configure.ac: Likewise. + * Makefile.in: Regenerate. + * confiugre: Regenerate. + * src/types.c: Add m32r port to FFI_INTERNAL_TYPEDEF + (uint64, sint64, double, longdouble) + * src/m32r: New directory. + * src/m32r/ffi.c: New file. + * src/m32r/sysv.S: Likewise. + * src/m32r/ffitarget.h: Likewise. + +2004-10-02 Kaz Kojima + + * testsuite/libffi.call/negint.c: New test case. + +2004-09-14 H.J. Lu + + PR libgcj/17465 + * testsuite/lib/libffi-dg.exp: Don't use global ld_library_path. + Set up LD_LIBRARY_PATH, SHLIB_PATH, LD_LIBRARYN32_PATH, + LD_LIBRARY64_PATH, LD_LIBRARY_PATH_32, LD_LIBRARY_PATH_64 and + DYLD_LIBRARY_PATH. + +2004-09-05 Andreas Tobler + + * testsuite/libffi.call/many_win32.c: Remove whitespaces. + * testsuite/libffi.call/promotion.c: Likewise. + * testsuite/libffi.call/return_ll.c: Remove unused var. Cleanup + whitespaces. + * testsuite/libffi.call/return_sc.c: Likewise. + * testsuite/libffi.call/return_uc.c: Likewise. + +2004-09-05 Andreas Tobler + + * src/powerpc/darwin.S: Fix comments and identation. + * src/powerpc/darwin_closure.S: Likewise. + +2004-09-02 Andreas Tobler + + * src/powerpc/ffi_darwin.c: Add flag for longdouble return values. + (ffi_prep_args): Handle longdouble arguments. + (ffi_prep_cif_machdep): Set flags for longdouble. Calculate space for + longdouble. + (ffi_closure_helper_DARWIN): Add closure handling for longdouble. + * src/powerpc/darwin.S (_ffi_call_DARWIN): Add handling of longdouble + values. + * src/powerpc/darwin_closure.S (_ffi_closure_ASM): Likewise. + * src/types.c: Defined longdouble size and alignment for darwin. + +2004-09-02 Andreas Tobler + + * src/powerpc/aix.S: Remove whitespaces. + * src/powerpc/aix_closure.S: Likewise. + * src/powerpc/asm.h: Likewise. + * src/powerpc/ffi.c: Likewise. + * src/powerpc/ffitarget.h: Likewise. + * src/powerpc/linux64.S: Likewise. + * src/powerpc/linux64_closure.S: Likewise. + * src/powerpc/ppc_closure.S: Likewise. + * src/powerpc/sysv.S: Likewise. + +2004-08-30 Anthony Green + + * Makefile.am: Add frv support. + * Makefile.in, testsuite/Makefile.in: Rebuilt. + * configure.ac: Read configure.host. + * configure.in: Read configure.host. + * configure.host: New file. frv-elf needs libgloss. + * include/ffi.h.in: Force ffi_closure to have a nice big (8) + alignment. This is needed to frv and shouldn't harm the others. + * include/ffi_common.h (ALIGN_DOWN): New macro. + * src/frv/ffi.c, src/frv/ffitarget.h, src/frv/eabi.S: New files. + +2004-08-24 David Daney + + * testsuite/libffi.call/closure_fn0.c: Xfail mips64* instead of mips*. + * testsuite/libffi.call/closure_fn1.c: Likewise. + * testsuite/libffi.call/closure_fn2.c Likewise. + * testsuite/libffi.call/closure_fn3.c: Likewise. + * testsuite/libffi.call/closure_fn4.c: Likewise. + * testsuite/libffi.call/closure_fn5.c: Likewise. + * testsuite/libffi.call/cls_18byte.c: Likewise. + * testsuite/libffi.call/cls_19byte.c: Likewise. + * testsuite/libffi.call/cls_1_1byte.c: Likewise. + * testsuite/libffi.call/cls_20byte.c: Likewise. + * testsuite/libffi.call/cls_20byte1.c: Likewise. + * testsuite/libffi.call/cls_24byte.c: Likewise. + * testsuite/libffi.call/cls_2byte.c: Likewise. + * testsuite/libffi.call/cls_3_1byte.c: Likewise. + * testsuite/libffi.call/cls_3byte1.c: Likewise. + * testsuite/libffi.call/cls_3byte2.c: Likewise. + * testsuite/libffi.call/cls_4_1byte.c: Likewise. + * testsuite/libffi.call/cls_4byte.c: Likewise. + * testsuite/libffi.call/cls_64byte.c: Likewise. + * testsuite/libffi.call/cls_6byte.c: Likewise. + * testsuite/libffi.call/cls_7byte.c: Likewise. + * testsuite/libffi.call/cls_8byte.c: Likewise. + * testsuite/libffi.call/cls_9byte1.c: Likewise. + * testsuite/libffi.call/cls_9byte2.c: Likewise. + * testsuite/libffi.call/cls_align_double.c: Likewise. + * testsuite/libffi.call/cls_align_float.c: Likewise. + * testsuite/libffi.call/cls_align_longdouble.c: Likewise. + * testsuite/libffi.call/cls_align_pointer.c: Likewise. + * testsuite/libffi.call/cls_align_sint16.c: Likewise. + * testsuite/libffi.call/cls_align_sint32.c: Likewise. + * testsuite/libffi.call/cls_align_sint64.c: Likewise. + * testsuite/libffi.call/cls_align_uint16.c: Likewise. + * testsuite/libffi.call/cls_align_uint32.c: Likewise. + * testsuite/libffi.call/cls_align_uint64.c: Likewise. + * testsuite/libffi.call/cls_double.c: Likewise. + * testsuite/libffi.call/cls_float.c: Likewise. + * testsuite/libffi.call/cls_multi_schar.c: Likewise. + * testsuite/libffi.call/cls_multi_sshort.c: Likewise. + * testsuite/libffi.call/cls_multi_sshortchar.c: Likewise. + * testsuite/libffi.call/cls_multi_uchar.c: Likewise. + * testsuite/libffi.call/cls_multi_ushort.c: Likewise. + * testsuite/libffi.call/cls_multi_ushortchar.c: Likewise. + * testsuite/libffi.call/cls_schar.c: Likewise. + * testsuite/libffi.call/cls_sint.c: Likewise. + * testsuite/libffi.call/cls_sshort.c: Likewise. + * testsuite/libffi.call/cls_uchar.c: Likewise. + * testsuite/libffi.call/cls_uint.c: Likewise. + * testsuite/libffi.call/cls_ulonglong.c: Likewise. + * testsuite/libffi.call/cls_ushort.c: Likewise. + * testsuite/libffi.call/nested_struct.c: Likewise. + * testsuite/libffi.call/nested_struct1.c: Likewise. + * testsuite/libffi.call/nested_struct2.c: Likewise. + * testsuite/libffi.call/nested_struct3.c: Likewise. + * testsuite/libffi.call/problem1.c: Likewise. + * testsuite/libffi.special/unwindtest.cc: Likewise. + * testsuite/libffi.call/cls_12byte.c: Likewise and set return value + to zero. + * testsuite/libffi.call/cls_16byte.c: Likewise. + * testsuite/libffi.call/cls_5byte.c: Likewise. + +2004-08-23 David Daney + + PR libgcj/13141 + * src/mips/ffitarget.h (FFI_O32_SOFT_FLOAT): New ABI. + * src/mips/ffi.c (ffi_prep_args): Fix alignment calculation. + (ffi_prep_cif_machdep): Handle FFI_O32_SOFT_FLOAT floating point + parameters and return types. + (ffi_call): Handle FFI_O32_SOFT_FLOAT ABI. + (ffi_prep_closure): Ditto. + (ffi_closure_mips_inner_O32): Handle FFI_O32_SOFT_FLOAT ABI, fix + alignment calculations. + * src/mips/o32.S (ffi_closure_O32): Don't use floating point + instructions if FFI_O32_SOFT_FLOAT, make stack frame ABI compliant. + +2004-08-14 Casey Marshall + + * src/mips/ffi.c (ffi_pref_cif_machdep): set `cif->flags' to + contain `FFI_TYPE_UINT64' as return type for any 64-bit + integer (O32 ABI only). + (ffi_prep_closure): new function. + (ffi_closure_mips_inner_O32): new function. + * src/mips/ffitarget.h: Define `FFI_CLOSURES' and + `FFI_TRAMPOLINE_SIZE' appropriately if the ABI is o32. + * src/mips/o32.S (ffi_call_O32): add labels for .eh_frame. Return + 64 bit integers correctly. + (ffi_closure_O32): new function. + Added DWARF-2 unwind info for both functions. + +2004-08-10 Andrew Haley + + * src/x86/ffi64.c (ffi_prep_args ): 8-align all stack arguments. + +2004-08-01 Robert Millan + + * configure.ac: Detect knetbsd-gnu and kfreebsd-gnu. + * configure: Regenerate. + +2004-07-30 Maciej W. Rozycki + + * acinclude.m4 (AC_FUNC_MMAP_BLACKLIST): Check for + and mmap() explicitly instead of relying on preset autoconf cache + variables. + * aclocal.m4: Regenerate. + * configure: Regenerate. + +2004-07-11 Ulrich Weigand + + * src/s390/ffi.c (ffi_prep_args): Fix C aliasing violation. + (ffi_check_float_struct): Remove unused prototype. + +2004-06-30 Geoffrey Keating + + * src/powerpc/ffi_darwin.c (flush_icache): ';' is a comment + character on Darwin, use '\n\t' instead. + +2004-06-26 Matthias Klose + + * libtool-version: Fix typo in revision/age. + +2004-06-17 Matthias Klose + + * libtool-version: New. + * Makefile.am (libffi_la_LDFLAGS): Use -version-info for soname. + * Makefile.in: Regenerate. + +2004-06-15 Paolo Bonzini + + * Makefile.am: Remove useless multilib rules. + * Makefile.in: Regenerate. + * aclocal.m4: Regenerate with automake 1.8.5. + * configure.ac: Remove useless multilib configury. + * configure: Regenerate. + +2004-06-15 Paolo Bonzini + + * .cvsignore: New file. + +2004-06-10 Jakub Jelinek + + * src/ia64/unix.S (ffi_call_unix): Insert group barrier break + fp_done. + (ffi_closure_UNIX): Fix f14/f15 adjustment if FLOAT_SZ is ever + changed from 8. + +2004-06-06 Sean McNeil + + * configure.ac: Add x86_64-*-freebsd* support. + * configure: Regenerate. + +2004-04-26 Joe Buck + + Bug 15093 + * configure.ac: Test for existence of mmap and sys/mman.h before + checking blacklist. Fix suggested by Jim Wilson. + * configure: Regenerate. + +2004-04-26 Matt Austern + + * src/powerpc/darwin.S: Go through a non-lazy pointer for initial + FDE location. + * src/powerpc/darwin_closure.S: Likewise. + +2004-04-24 Andreas Tobler + + * testsuite/libffi.call/cls_multi_schar.c (main): Fix initialization + error. Reported by Thomas Heller . + * testsuite/libffi.call/cls_multi_sshort.c (main): Likewise. + * testsuite/libffi.call/cls_multi_ushort.c (main): Likewise. + +2004-03-20 Matthias Klose + + * src/pa/linux.S: Fix typo. + +2004-03-19 Matthias Klose + + * Makefile.am: Update. + * Makefile.in: Regenerate. + * src/pa/ffi.h.in: Remove. + * src/pa/ffitarget.h: New file. + +2004-02-10 Randolph Chung + + * Makefile.am: Add PA support. + * Makefile.in: Regenerate. + * include/Makefile.in: Regenerate. + * configure.ac: Add PA target. + * configure: Regenerate. + * src/pa/ffi.c: New file. + * src/pa/ffi.h.in: Add PA support. + * src/pa/linux.S: New file. + * prep_cif.c: Add PA support. + +2004-03-16 Hosaka Yuji + + * src/types.c: Fix alignment size of X86_WIN32 case int64 and + double. + * src/x86/ffi.c (ffi_prep_args): Replace ecif->cif->rtype->type + with ecif->cif->flags. + (ffi_call, ffi_prep_incoming_args_SYSV): Replace cif->rtype->type + with cif->flags. + (ffi_prep_cif_machdep): Add X86_WIN32 struct case. + (ffi_closure_SYSV): Add 1 or 2-bytes struct case for X86_WIN32. + * src/x86/win32.S (retstruct1b, retstruct2b, sc_retstruct1b, + sc_retstruct2b): Add for 1 or 2-bytes struct case. + +2004-03-15 Kelley Cook + + * configure.in: Rename file to ... + * configure.ac: ... this. + * fficonfig.h.in: Regenerate. + * Makefile.in: Regenerate. + * include/Makefile.in: Regenerate. + * testsuite/Makefile.in: Regenerate. + +2004-03-12 Matt Austern + + * src/powerpc/darwin.S: Fix EH information so it corresponds to + changes in EH format resulting from addition of linkonce support. + * src/powerpc/darwin_closure.S: Likewise. + +2004-03-11 Andreas Tobler + Paolo Bonzini + + * Makefile.am (AUTOMAKE_OPTIONS): Set them. + Remove VPATH. Remove rules for object files. Remove multilib support. + (AM_CCASFLAGS): Add. + * configure.in (AC_CONFIG_HEADERS): Relace AM_CONFIG_HEADER. + (AC_PREREQ): Bump version to 2.59. + (AC_INIT): Fill with version info and bug address. + (ORIGINAL_LD_FOR_MULTILIBS): Remove. + (AM_ENABLE_MULTILIB): Use this instead of AC_ARG_ENABLE. + De-precious CC so that the right flags are passed down to multilibs. + (AC_MSG_ERROR): Replace obsolete macro AC_ERROR. + (AC_CONFIG_FILES): Replace obsolete macro AC_LINK_FILES. + (AC_OUTPUT): Reorganize the output with AC_CONFIG_COMMANDS. + * configure: Rebuilt. + * aclocal.m4: Likewise. + * Makefile.in, include/Makefile.in, testsuite/Makefile.in: Likewise. + * fficonfig.h.in: Likewise. + +2004-03-11 Andreas Schwab + + * src/ia64/ffi.c (ffi_prep_incoming_args_UNIX): Get floating point + arguments from fp registers only for the first 8 parameter slots. + Don't convert a float parameter when passed in memory. + +2004-03-09 Hans-Peter Nilsson + + * configure: Regenerate for config/accross.m4 correction. + +2004-02-25 Matt Kraai + + * src/powerpc/ffi.c (ffi_prep_args_SYSV): Change + ecif->cif->bytes to bytes. + (ffi_prep_cif_machdep): Add braces around nested if statement. + +2004-02-09 Alan Modra + + * src/types.c (pointer): POWERPC64 has 8 byte pointers. + + * src/powerpc/ffi.c (ffi_prep_args64): Correct long double handling. + (ffi_closure_helper_LINUX64): Fix typo. + * testsuite/libffi.call/cls_align_longdouble.c: Pass -mlong-double-128 + for powerpc64-*-*. + * testsuite/libffi.call/float.c: Likewise. + * testsuite/libffi.call/float2.c: Likewise. + +2004-02-08 Alan Modra + + * src/powerpc/ffi.c (ffi_prep_cif_machdep ): Correct + long double function return and long double arg handling. + (ffi_closure_helper_LINUX64): Formatting. Delete unused "ng" var. + Use "end_pfr" instead of "nf". Correct long double handling. + Localise "temp". + * src/powerpc/linux64.S (ffi_call_LINUX64): Save f2 long double + return value. + * src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Allocate + space for long double return value. Adjust stack frame and offsets. + Load f2 long double return. + +2004-02-07 Alan Modra + + * src/types.c: Use 16 byte long double for POWERPC64. + +2004-01-25 Eric Botcazou + + * src/sparc/ffi.c (ffi_prep_args_v9): Shift the parameter array + when the structure return address is passed in %o0. + (ffi_V9_return_struct): Rename into ffi_v9_layout_struct. + (ffi_v9_layout_struct): Align the field following a nested structure + on a word boundary. Use memmove instead of memcpy. + (ffi_call): Update call to ffi_V9_return_struct. + (ffi_prep_closure): Define 'ctx' only for V8. + (ffi_closure_sparc_inner): Clone into ffi_closure_sparc_inner_v8 + and ffi_closure_sparc_inner_v9. + (ffi_closure_sparc_inner_v8): Return long doubles by reference. + Always skip the structure return address. For structures and long + doubles, copy the argument directly. + (ffi_closure_sparc_inner_v9): Skip the structure return address only + if required. Shift the maximum floating-point slot accordingly. For + big structures, copy the argument directly; otherwise, left-justify the + argument and call ffi_v9_layout_struct to lay out the structure on + the stack. + * src/sparc/v8.S: Undef STACKFRAME before defining it. + (ffi_closure_v8): Pass the structure return address. Update call to + ffi_closure_sparc_inner_v8. Short-circuit FFI_TYPE_INT handling. + Skip the 'unimp' insn when returning long doubles and structures. + * src/sparc/v9.S: Undef STACKFRAME before defining it. + (ffi_closure_v9): Increase the frame size by 2 words. Short-circuit + FFI_TYPE_INT handling. Load structures both in integers and + floating-point registers on return. + * README: Update status of the SPARC port. + +2004-01-24 Andreas Tobler + + * testsuite/libffi.call/pyobjc-tc.c (main): Treat result value + as of type ffi_arg. + * testsuite/libffi.call/struct3.c (main): Fix CHECK. + +2004-01-22 Ulrich Weigand + + * testsuite/libffi.call/cls_uint.c (cls_ret_uint_fn): Treat result + value as of type ffi_arg, not unsigned int. + +2004-01-21 Michael Ritzert + + * ffi64.c (ffi_prep_args): Cast the RHS of an assignment instead + of the LHS. + +2004-01-12 Andreas Tobler + + * testsuite/lib/libffi-dg.exp: Set LD_LIBRARY_PATH_32 for + Solaris. + +2004-01-08 Rainer Orth + + * testsuite/libffi.call/ffitest.h (allocate_mmap): Cast MAP_FAILED + to void *. + +2003-12-10 Richard Henderson + + * testsuite/libffi.call/cls_align_pointer.c: Cast pointers to + size_t instead of int. + +2003-12-04 Hosaka Yuji + + * testsuite/libffi.call/many_win32.c: Include . + * testsuite/libffi.call/many_win32.c (main): Replace variable + int i with unsigned long ul. + + * testsuite/libffi.call/cls_align_uint64.c: New test case. + * testsuite/libffi.call/cls_align_sint64.c: Likewise. + * testsuite/libffi.call/cls_align_uint32.c: Likewise. + * testsuite/libffi.call/cls_align_sint32.c: Likewise. + * testsuite/libffi.call/cls_align_uint16.c: Likewise. + * testsuite/libffi.call/cls_align_sint16.c: Likewise. + * testsuite/libffi.call/cls_align_float.c: Likewise. + * testsuite/libffi.call/cls_align_double.c: Likewise. + * testsuite/libffi.call/cls_align_longdouble.c: Likewise. + * testsuite/libffi.call/cls_align_pointer.c: Likewise. + +2003-12-02 Hosaka Yuji + + PR other/13221 + * src/x86/ffi.c (ffi_prep_args, ffi_prep_incoming_args_SYSV): + Align arguments to 32 bits. + +2003-12-01 Andreas Tobler + + PR other/13221 + * testsuite/libffi.call/cls_multi_sshort.c: New test case. + * testsuite/libffi.call/cls_multi_sshortchar.c: Likewise. + * testsuite/libffi.call/cls_multi_uchar.c: Likewise. + * testsuite/libffi.call/cls_multi_schar.c: Likewise. + * testsuite/libffi.call/cls_multi_ushortchar.c: Likewise. + * testsuite/libffi.call/cls_multi_ushort.c: Likewise. + + * testsuite/libffi.special/unwindtest.cc: Cosmetics. + +2003-11-26 Kaveh R. Ghazi + + * testsuite/libffi.call/ffitest.h: Include . + * testsuite/libffi.special/ffitestcxx.h: Likewise. + +2003-11-22 Andreas Tobler + + * Makefile.in: Rebuilt. + * configure: Likewise. + * testsuite/libffi.special/unwindtest.cc: Convert the mmap to + the right type. + +2003-11-21 Andreas Jaeger + Andreas Tobler + + * acinclude.m4: Add AC_FUNC_MMAP_BLACKLIST. + * configure.in: Call AC_FUNC_MMAP_BLACKLIST. + * Makefile.in: Rebuilt. + * aclocal.m4: Likewise. + * configure: Likewise. + * fficonfig.h.in: Likewise. + * testsuite/lib/libffi-dg.exp: Add include dir. + * testsuite/libffi.call/ffitest.h: Add MMAP definitions. + * testsuite/libffi.special/ffitestcxx.h: Likewise. + * testsuite/libffi.call/closure_fn0.c: Use MMAP functionality + for ffi_closure if available. + * testsuite/libffi.call/closure_fn1.c: Likewise. + * testsuite/libffi.call/closure_fn2.c: Likewise. + * testsuite/libffi.call/closure_fn3.c: Likewise. + * testsuite/libffi.call/closure_fn4.c: Likewise. + * testsuite/libffi.call/closure_fn5.c: Likewise. + * testsuite/libffi.call/cls_12byte.c: Likewise. + * testsuite/libffi.call/cls_16byte.c: Likewise. + * testsuite/libffi.call/cls_18byte.c: Likewise. + * testsuite/libffi.call/cls_19byte.c: Likewise. + * testsuite/libffi.call/cls_1_1byte.c: Likewise. + * testsuite/libffi.call/cls_20byte.c: Likewise. + * testsuite/libffi.call/cls_20byte1.c: Likewise. + * testsuite/libffi.call/cls_24byte.c: Likewise. + * testsuite/libffi.call/cls_2byte.c: Likewise. + * testsuite/libffi.call/cls_3_1byte.c: Likewise. + * testsuite/libffi.call/cls_3byte1.c: Likewise. + * testsuite/libffi.call/cls_3byte2.c: Likewise. + * testsuite/libffi.call/cls_4_1byte.c: Likewise. + * testsuite/libffi.call/cls_4byte.c: Likewise. + * testsuite/libffi.call/cls_5byte.c: Likewise. + * testsuite/libffi.call/cls_64byte.c: Likewise. + * testsuite/libffi.call/cls_6byte.c: Likewise. + * testsuite/libffi.call/cls_7byte.c: Likewise. + * testsuite/libffi.call/cls_8byte.c: Likewise. + * testsuite/libffi.call/cls_9byte1.c: Likewise. + * testsuite/libffi.call/cls_9byte2.c: Likewise. + * testsuite/libffi.call/cls_double.c: Likewise. + * testsuite/libffi.call/cls_float.c: Likewise. + * testsuite/libffi.call/cls_schar.c: Likewise. + * testsuite/libffi.call/cls_sint.c: Likewise. + * testsuite/libffi.call/cls_sshort.c: Likewise. + * testsuite/libffi.call/cls_uchar.c: Likewise. + * testsuite/libffi.call/cls_uint.c: Likewise. + * testsuite/libffi.call/cls_ulonglong.c: Likewise. + * testsuite/libffi.call/cls_ushort.c: Likewise. + * testsuite/libffi.call/nested_struct.c: Likewise. + * testsuite/libffi.call/nested_struct1.c: Likewise. + * testsuite/libffi.call/nested_struct2.c: Likewise. + * testsuite/libffi.call/nested_struct3.c: Likewise. + * testsuite/libffi.call/problem1.c: Likewise. + * testsuite/libffi.special/unwindtest.cc: Likewise. + +2003-11-20 Andreas Tobler + + * testsuite/lib/libffi-dg.exp: Make the -lgcc_s conditional. + +2003-11-19 Andreas Tobler + + * testsuite/lib/libffi-dg.exp: Add DYLD_LIBRARY_PATH for darwin. + Add -lgcc_s to additional flags. + +2003-11-12 Andreas Tobler + + * configure.in, include/Makefile.am: PR libgcj/11147, install + the ffitarget.h header file in a gcc versioned and target + dependent place. + * configure: Regenerated. + * Makefile.in, include/Makefile.in: Likewise. + * testsuite/Makefile.in: Likewise. + +2003-11-09 Andreas Tobler + + * testsuite/libffi.call/closure_fn0.c: Print result and check + with dg-output to make debugging easier. + * testsuite/libffi.call/closure_fn1.c: Likewise. + * testsuite/libffi.call/closure_fn2.c: Likewise. + * testsuite/libffi.call/closure_fn3.c: Likewise. + * testsuite/libffi.call/closure_fn4.c: Likewise. + * testsuite/libffi.call/closure_fn5.c: Likewise. + * testsuite/libffi.call/cls_12byte.c: Likewise. + * testsuite/libffi.call/cls_16byte.c: Likewise. + * testsuite/libffi.call/cls_18byte.c: Likewise. + * testsuite/libffi.call/cls_19byte.c: Likewise. + * testsuite/libffi.call/cls_1_1byte.c: Likewise. + * testsuite/libffi.call/cls_20byte.c: Likewise. + * testsuite/libffi.call/cls_20byte1.c: Likewise. + * testsuite/libffi.call/cls_24byte.c: Likewise. + * testsuite/libffi.call/cls_2byte.c: Likewise. + * testsuite/libffi.call/cls_3_1byte.c: Likewise. + * testsuite/libffi.call/cls_3byte1.c: Likewise. + * testsuite/libffi.call/cls_3byte2.c: Likewise. + * testsuite/libffi.call/cls_4_1byte.c: Likewise. + * testsuite/libffi.call/cls_4byte.c: Likewise. + * testsuite/libffi.call/cls_5byte.c: Likewise. + * testsuite/libffi.call/cls_64byte.c: Likewise. + * testsuite/libffi.call/cls_6byte.c: Likewise. + * testsuite/libffi.call/cls_7byte.c: Likewise. + * testsuite/libffi.call/cls_8byte.c: Likewise. + * testsuite/libffi.call/cls_9byte1.c: Likewise. + * testsuite/libffi.call/cls_9byte2.c: Likewise. + * testsuite/libffi.call/cls_double.c: Likewise. + * testsuite/libffi.call/cls_float.c: Likewise. + * testsuite/libffi.call/cls_schar.c: Likewise. + * testsuite/libffi.call/cls_sint.c: Likewise. + * testsuite/libffi.call/cls_sshort.c: Likewise. + * testsuite/libffi.call/cls_uchar.c: Likewise. + * testsuite/libffi.call/cls_uint.c: Likewise. + * testsuite/libffi.call/cls_ulonglong.c: Likewise. + * testsuite/libffi.call/cls_ushort.c: Likewise. + * testsuite/libffi.call/problem1.c: Likewise. + + * testsuite/libffi.special/unwindtest.cc: Make ffi_closure + static. + +2003-11-08 Andreas Tobler + + * testsuite/libffi.call/cls_9byte2.c: New test case. + * testsuite/libffi.call/cls_9byte1.c: Likewise. + * testsuite/libffi.call/cls_64byte.c: Likewise. + * testsuite/libffi.call/cls_20byte1.c: Likewise. + * testsuite/libffi.call/cls_19byte.c: Likewise. + * testsuite/libffi.call/cls_18byte.c: Likewise. + * testsuite/libffi.call/closure_fn4.c: Likewise. + * testsuite/libffi.call/closure_fn5.c: Likewise. + * testsuite/libffi.call/cls_schar.c: Likewise. + * testsuite/libffi.call/cls_sint.c: Likewise. + * testsuite/libffi.call/cls_sshort.c: Likewise. + * testsuite/libffi.call/nested_struct2.c: Likewise. + * testsuite/libffi.call/nested_struct3.c: Likewise. + +2003-11-08 Andreas Tobler + + * testsuite/libffi.call/cls_double.c: Do a check on the result. + * testsuite/libffi.call/cls_uchar.c: Likewise. + * testsuite/libffi.call/cls_uint.c: Likewise. + * testsuite/libffi.call/cls_ulonglong.c: Likewise. + * testsuite/libffi.call/cls_ushort.c: Likewise. + * testsuite/libffi.call/return_sc.c: Cleanup whitespaces. + +2003-11-06 Andreas Tobler + + * src/prep_cif.c (ffi_prep_cif): Move the validity check after + the initialization. + +2003-10-23 Andreas Tobler + + * src/java_raw_api.c (ffi_java_ptrarray_to_raw): Replace + FFI_ASSERT(FALSE) with FFI_ASSERT(0). + +2003-10-22 David Daney + + * src/mips/ffitarget.h: Replace undefined UINT32 and friends with + __attribute__((__mode__(__SI__))) and friends. + +2003-10-22 Andreas Schwab + + * src/ia64/ffi.c: Replace FALSE/TRUE with false/true. + +2003-10-21 Andreas Tobler + + * configure.in: AC_LINK_FILES(ffitarget.h). + * configure: Regenerate. + * Makefile.in: Likewise. + * include/Makefile.in: Likewise. + * testsuite/Makefile.in: Likewise. + * fficonfig.h.in: Likewise. + +2003-10-21 Paolo Bonzini + Richard Henderson + + Avoid that ffi.h includes fficonfig.h. + + * Makefile.am (EXTRA_DIST): Include ffitarget.h files + (TARGET_SRC_MIPS_GCC): Renamed to TARGET_SRC_MIPS_IRIX. + (TARGET_SRC_MIPS_SGI): Removed. + (MIPS_GCC): Renamed to TARGET_SRC_MIPS_IRIX. + (MIPS_SGI): Removed. + (CLEANFILES): Removed. + (mostlyclean-am, clean-am, mostlyclean-sub, clean-sub): New + targets. + * acconfig.h: Removed. + * configure.in: Compute sizeofs only for double and long double. + Use them to define and subst HAVE_LONG_DOUBLE. Include comments + into AC_DEFINE instead of using acconfig.h. Create + include/ffitarget.h instead of include/fficonfig.h. Rename + MIPS_GCC to MIPS_IRIX, drop MIPS_SGI since we are in gcc's tree. + AC_DEFINE EH_FRAME_FLAGS. + * include/Makefile.am (DISTCLEANFILES): New automake macro. + (hack_DATA): Add ffitarget.h. + * include/ffi.h.in: Remove all system specific definitions. + Declare raw API even if it is not installed, why bother? + Use limits.h instead of SIZEOF_* to define ffi_type_*. Do + not define EH_FRAME_FLAGS, it is in fficonfig.h now. Include + ffitarget.h instead of fficonfig.h. Remove ALIGN macro. + (UINT_ARG, INT_ARG): Removed, use ffi_arg and ffi_sarg instead. + * include/ffi_common.h (bool): Do not define. + (ffi_assert): Accept failed assertion. + (ffi_type_test): Return void and accept file/line. + (FFI_ASSERT): Pass stringized failed assertion. + (FFI_ASSERT_AT): New macro. + (FFI_ASSERT_VALID_TYPE): New macro. + (UINT8, SINT8, UINT16, SINT16, UINT32, SINT32, + UINT64, SINT64): Define here with gcc's __attribute__ macro + instead of in ffi.h + (FLOAT32, ALIGN): Define here instead of in ffi.h + * include/ffi-mips.h: Removed. Its content moved to + src/mips/ffitarget.h after separating assembly and C sections. + * src/alpha/ffi.c, src/alpha/ffi.c, src/java_raw_api.c + src/prep_cif.c, src/raw_api.c, src/ia64/ffi.c, + src/mips/ffi.c, src/mips/n32.S, src/mips/o32.S, + src/mips/ffitarget.h, src/sparc/ffi.c, src/x86/ffi64.c: + SIZEOF_ARG -> FFI_SIZEOF_ARG. + * src/ia64/ffi.c: Include stdbool.h (provided by GCC 2.95+). + * src/debug.c (ffi_assert): Accept stringized failed assertion. + (ffi_type_test): Rewritten. + * src/prep-cif.c (initialize_aggregate, ffi_prep_cif): Call + FFI_ASSERT_VALID_TYPE. + * src/alpha/ffitarget.h, src/arm/ffitarget.h, + src/ia64/ffitarget.h, src/m68k/ffitarget.h, + src/mips/ffitarget.h, src/powerpc/ffitarget.h, + src/s390/ffitarget.h, src/sh/ffitarget.h, + src/sh64/ffitarget.h, src/sparc/ffitarget.h, + src/x86/ffitarget.h: New files. + * src/alpha/osf.S, src/arm/sysv.S, src/ia64/unix.S, + src/m68k/sysv.S, src/mips/n32.S, src/mips/o32.S, + src/powerpc/aix.S, src/powerpc/darwin.S, + src/powerpc/ffi_darwin.c, src/powerpc/linux64.S, + src/powerpc/linux64_closure.S, src/powerpc/ppc_closure.S, + src/powerpc/sysv.S, src/s390/sysv.S, src/sh/sysv.S, + src/sh64/sysv.S, src/sparc/v8.S, src/sparc/v9.S, + src/x86/sysv.S, src/x86/unix64.S, src/x86/win32.S: + include fficonfig.h + +2003-10-20 Rainer Orth + + * src/mips/ffi.c: Use _ABIN32, _ABIO32 instead of external + _MIPS_SIM_NABI32, _MIPS_SIM_ABI32. + +2003-10-19 Andreas Tobler + + * src/powerpc/ffi_darwin.c (ffi_prep_args): Declare bytes again. + Used when FFI_DEBUG = 1. + +2003-10-14 Alan Modra + + * src/types.c (double, longdouble): Default POWERPC64 to 8 byte size + and align. + +2003-10-06 Rainer Orth + + * include/ffi_mips.h: Define FFI_MIPS_N32 for N32/N64 ABIs, + FFI_MIPS_O32 for O32 ABI. + +2003-10-01 Andreas Tobler + + * testsuite/lib/libffi-dg.exp: Set LD_LIBRARY_PATH_64 for + SPARC64. Cleanup whitespaces. + +2003-09-19 Andreas Tobler + + * testsuite/libffi.call/closure_fn0.c: Xfail mips, arm, + strongarm, xscale. Cleanup whitespaces. + * testsuite/libffi.call/closure_fn1.c: Likewise. + * testsuite/libffi.call/closure_fn2.c: Likewise. + * testsuite/libffi.call/closure_fn3.c: Likewise. + * testsuite/libffi.call/cls_12byte.c: Likewise. + * testsuite/libffi.call/cls_16byte.c: Likewise. + * testsuite/libffi.call/cls_1_1byte.c: Likewise. + * testsuite/libffi.call/cls_20byte.c: Likewise. + * testsuite/libffi.call/cls_24byte.c: Likewise. + * testsuite/libffi.call/cls_2byte.c: Likewise. + * testsuite/libffi.call/cls_3_1byte.c: Likewise. + * testsuite/libffi.call/cls_3byte1.c: Likewise. + * testsuite/libffi.call/cls_3byte2.c: Likewise. + * testsuite/libffi.call/cls_4_1byte.c: Likewise. + * testsuite/libffi.call/cls_4byte.c: Likewise. + * testsuite/libffi.call/cls_5byte.c: Likewise. + * testsuite/libffi.call/cls_6byte.c: Likewise. + * testsuite/libffi.call/cls_7byte.c: Likewise. + * testsuite/libffi.call/cls_8byte.c: Likewise. + * testsuite/libffi.call/cls_double.c: Likewise. + * testsuite/libffi.call/cls_float.c: Likewise. + * testsuite/libffi.call/cls_uchar.c: Likewise. + * testsuite/libffi.call/cls_uint.c: Likewise. + * testsuite/libffi.call/cls_ulonglong.c: Likewise. + * testsuite/libffi.call/cls_ushort.c: Likewise. + * testsuite/libffi.call/nested_struct.c: Likewise. + * testsuite/libffi.call/nested_struct1.c: Likewise. + * testsuite/libffi.call/problem1.c: Likewise. + * testsuite/libffi.special/unwindtest.cc: Likewise. + * testsuite/libffi.call/pyobjc-tc.c: Cleanup whitespaces. + +2003-09-18 David Edelsohn + + * src/powerpc/aix.S: Cleanup whitespaces. + * src/powerpc/aix_closure.S: Likewise. + +2003-09-18 Andreas Tobler + + * src/powerpc/darwin.S: Cleanup whitespaces, comment formatting. + * src/powerpc/darwin_closure.S: Likewise. + * src/powerpc/ffi_darwin.c: Likewise. + +2003-09-18 Andreas Tobler + David Edelsohn + + * src/types.c (double): Add AIX and Darwin to the right TYPEDEF. + * src/powerpc/aix_closure.S: Remove the pointer to the outgoing + parameter stack. + * src/powerpc/darwin_closure.S: Likewise. + * src/powerpc/ffi_darwin.c (ffi_prep_args): Handle structures + according to the Darwin/AIX ABI. + (ffi_prep_cif_machdep): Likewise. + (ffi_closure_helper_DARWIN): Likewise. + Remove the outgoing parameter stack logic. Simplify the evaluation + of the different CASE types. + (ffi_prep_clousure): Avoid the casts on lvalues. Change the branch + statement in the trampoline code. + +2003-09-18 Kaz Kojima + + * src/sh/ffi.c (ffi_prep_args): Take account into the alignement + for the register size. + (ffi_closure_helper_SYSV): Handle the structure return value + address correctly. + (ffi_closure_helper_SYSV): Return the appropriate type when + the registers are used for the structure return value. + * src/sh/sysv.S (ffi_closure_SYSV): Fix the stack layout for + the 64-bit return value. Update copyright years. + +2003-09-17 Rainer Orth + + * testsuite/lib/libffi-dg.exp (libffi_target_compile): Search in + srcdir for ffi_mips.h. + +2003-09-12 Alan Modra + + * src/prep_cif.c (initialize_aggregate): Include tail padding in + structure size. + * src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Correct + placement of float result. + * testsuite/libffi.special/unwindtest.cc (closure_test_fn1): Correct + cast of "resp" for big-endian 64 bit machines. + +2003-09-11 Alan Modra + + * src/types.c (double, longdouble): Merge identical SH and ARM + typedefs, and add POWERPC64. + * src/powerpc/ffi.c (ffi_prep_args64): Correct next_arg calc for + struct split over gpr and rest. + (ffi_prep_cif_machdep): Correct intarg_count for structures. + * src/powerpc/linux64.S (ffi_call_LINUX64): Fix gpr offsets. + +2003-09-09 Andreas Tobler + + * src/powerpc/ffi.c (ffi_closure_helper_SYSV) Handle struct + passing correctly. + +2003-09-09 Alan Modra + + * configure: Regenerate. + +2003-09-04 Andreas Tobler + + * Makefile.am: Remove build rules for ffitest. + * Makefile.in: Rebuilt. + +2003-09-04 Andreas Tobler + + * src/java_raw_api.c: Include to fix compiler warning + about implicit declaration of abort(). + +2003-09-04 Andreas Tobler + + * Makefile.am: Add dejagnu test framework. Fixes PR other/11411. + * Makefile.in: Rebuilt. + * configure.in: Add dejagnu test framework. + * configure: Rebuilt. + + * testsuite/Makefile.am: New file. + * testsuite/Makefile.in: Built + * testsuite/lib/libffi-dg.exp: New file. + * testsuite/config/default.exp: Likewise. + * testsuite/libffi.call/call.exp: Likewise. + * testsuite/libffi.call/ffitest.h: Likewise. + * testsuite/libffi.call/closure_fn0.c: Likewise. + * testsuite/libffi.call/closure_fn1.c: Likewise. + * testsuite/libffi.call/closure_fn2.c: Likewise. + * testsuite/libffi.call/closure_fn3.c: Likewise. + * testsuite/libffi.call/cls_1_1byte.c: Likewise. + * testsuite/libffi.call/cls_3_1byte.c: Likewise. + * testsuite/libffi.call/cls_4_1byte.c: Likewise. + * testsuite/libffi.call/cls_2byte.c: Likewise. + * testsuite/libffi.call/cls_3byte1.c: Likewise. + * testsuite/libffi.call/cls_3byte2.c: Likewise. + * testsuite/libffi.call/cls_4byte.c: Likewise. + * testsuite/libffi.call/cls_5byte.c: Likewise. + * testsuite/libffi.call/cls_6byte.c: Likewise. + * testsuite/libffi.call/cls_7byte.c: Likewise. + * testsuite/libffi.call/cls_8byte.c: Likewise. + * testsuite/libffi.call/cls_12byte.c: Likewise. + * testsuite/libffi.call/cls_16byte.c: Likewise. + * testsuite/libffi.call/cls_20byte.c: Likewise. + * testsuite/libffi.call/cls_24byte.c: Likewise. + * testsuite/libffi.call/cls_double.c: Likewise. + * testsuite/libffi.call/cls_float.c: Likewise. + * testsuite/libffi.call/cls_uchar.c: Likewise. + * testsuite/libffi.call/cls_uint.c: Likewise. + * testsuite/libffi.call/cls_ulonglong.c: Likewise. + * testsuite/libffi.call/cls_ushort.c: Likewise. + * testsuite/libffi.call/float.c: Likewise. + * testsuite/libffi.call/float1.c: Likewise. + * testsuite/libffi.call/float2.c: Likewise. + * testsuite/libffi.call/many.c: Likewise. + * testsuite/libffi.call/many_win32.c: Likewise. + * testsuite/libffi.call/nested_struct.c: Likewise. + * testsuite/libffi.call/nested_struct1.c: Likewise. + * testsuite/libffi.call/pyobjc-tc.c: Likewise. + * testsuite/libffi.call/problem1.c: Likewise. + * testsuite/libffi.call/promotion.c: Likewise. + * testsuite/libffi.call/return_ll.c: Likewise. + * testsuite/libffi.call/return_sc.c: Likewise. + * testsuite/libffi.call/return_uc.c: Likewise. + * testsuite/libffi.call/strlen.c: Likewise. + * testsuite/libffi.call/strlen_win32.c: Likewise. + * testsuite/libffi.call/struct1.c: Likewise. + * testsuite/libffi.call/struct2.c: Likewise. + * testsuite/libffi.call/struct3.c: Likewise. + * testsuite/libffi.call/struct4.c: Likewise. + * testsuite/libffi.call/struct5.c: Likewise. + * testsuite/libffi.call/struct6.c: Likewise. + * testsuite/libffi.call/struct7.c: Likewise. + * testsuite/libffi.call/struct8.c: Likewise. + * testsuite/libffi.call/struct9.c: Likewise. + * testsuite/libffi.special/special.exp: New file. + * testsuite/libffi.special/ffitestcxx.h: Likewise. + * testsuite/libffi.special/unwindtest.cc: Likewise. + + +2003-08-13 Kaz Kojima + + * src/sh/ffi.c (OFS_INT16): Set 0 for little endian case. Update + copyright years. + +2003-08-02 Alan Modra + + * src/powerpc/ffi.c (ffi_prep_args64): Modify for changed gcc + structure passing. + (ffi_closure_helper_LINUX64): Likewise. + * src/powerpc/linux64.S: Remove code writing to parm save area. + * src/powerpc/linux64_closure.S (ffi_closure_LINUX64): Use return + address in lr from ffi_closure_helper_LINUX64 call to calculate + table address. Optimize function tail. + +2003-07-28 Andreas Tobler + + * src/sparc/ffi.c: Handle all floating point registers. + * src/sparc/v9.S: Likewise. Fixes second part of PR target/11410. + +2003-07-11 Gerald Pfeifer + + * README: Note that libffi is not part of GCC. Update the project + URL and status. + +2003-06-19 Franz Sirl + + * src/powerpc/ppc_closure.S: Include ffi.h. + +2003-06-13 Rainer Orth + + * src/x86/sysv.S: Avoid gas-only .uleb128/.sleb128 directives. + Use C style comments. + +2003-06-13 Kaz Kojima + + * Makefile.am: Add SHmedia support. Fix a typo of SH support. + * Makefile.in: Regenerate. + * configure.in (sh64-*-linux*, sh5*-*-linux*): Add target. + * configure: Regenerate. + * include/ffi.h.in: Add SHmedia support. + * src/sh64/ffi.c: New file. + * src/sh64/sysv.S: New file. + +2003-05-16 Jakub Jelinek + + * configure.in (HAVE_RO_EH_FRAME): Check whether .eh_frame section + should be read-only. + * configure: Rebuilt. + * fficonfig.h.in: Rebuilt. + * include/ffi.h.in (EH_FRAME_FLAGS): Define. + * src/alpha/osf.S: Use EH_FRAME_FLAGS. + * src/powerpc/linux64.S: Likewise. + * src/powerpc/linux64_closure.S: Likewise. Include ffi.h. + * src/powerpc/sysv.S: Use EH_FRAME_FLAGS. Use pcrel encoding + if -fpic/-fPIC/-mrelocatable. + * src/powerpc/powerpc_closure.S: Likewise. + * src/sparc/v8.S: If HAVE_RO_EH_FRAME is defined, don't include + #write in .eh_frame flags. + * src/sparc/v9.S: Likewise. + * src/x86/unix64.S: Use EH_FRAME_FLAGS. + * src/x86/sysv.S: Likewise. Use pcrel encoding if -fpic/-fPIC. + * src/s390/sysv.S: Use EH_FRAME_FLAGS. Include ffi.h. + +2003-05-07 Jeff Sturm + + Fixes PR bootstrap/10656 + * configure.in (HAVE_AS_REGISTER_PSEUDO_OP): Test assembler + support for .register pseudo-op. + * src/sparc/v8.S: Use it. + * fficonfig.h.in: Rebuilt. + * configure: Rebuilt. + +2003-04-18 Jakub Jelinek + + * include/ffi.h.in (POWERPC64): Define if 64-bit. + (enum ffi_abi): Add FFI_LINUX64 on POWERPC. + Make it the default on POWERPC64. + (FFI_TRAMPOLINE_SIZE): Define to 24 on POWERPC64. + * configure.in: Change powerpc-*-linux* into powerpc*-*-linux*. + * configure: Rebuilt. + * src/powerpc/ffi.c (hidden): Define. + (ffi_prep_args_SYSV): Renamed from + ffi_prep_args. Cast pointers to unsigned long to shut up warnings. + (NUM_GPR_ARG_REGISTERS64, NUM_FPR_ARG_REGISTERS64, + ASM_NEEDS_REGISTERS64): New. + (ffi_prep_args64): New function. + (ffi_prep_cif_machdep): Handle FFI_LINUX64 ABI. + (ffi_call): Likewise. + (ffi_prep_closure): Likewise. + (flush_icache): Surround by #ifndef POWERPC64. + (ffi_dblfl): New union type. + (ffi_closure_helper_SYSV): Use it to avoid aliasing problems. + (ffi_closure_helper_LINUX64): New function. + * src/powerpc/ppc_closure.S: Surround whole file by #ifndef + __powerpc64__. + * src/powerpc/sysv.S: Likewise. + (ffi_call_SYSV): Rename ffi_prep_args to ffi_prep_args_SYSV. + * src/powerpc/linux64.S: New file. + * src/powerpc/linux64_closure.S: New file. + * Makefile.am (EXTRA_DIST): Add src/powerpc/linux64.S and + src/powerpc/linux64_closure.S. + (TARGET_SRC_POWERPC): Likewise. + + * src/ffitest.c (closure_test_fn, closure_test_fn1, closure_test_fn2, + closure_test_fn3): Fix result printing on big-endian 64-bit + machines. + (main): Print tst2_arg instead of uninitialized tst2_result. + + * src/ffitest.c (main): Hide what closure pointer really points to + from the compiler. + +2003-04-16 Richard Earnshaw + + * configure.in (arm-*-netbsdelf*): Add configuration. + (configure): Regenerated. + +2003-04-04 Loren J. Rittle + + * include/Makefile.in: Regenerate. + +2003-03-21 Zdenek Dvorak + + * libffi/include/ffi.h.in: Define X86 instead of X86_64 in 32 + bit mode. + * libffi/src/x86/ffi.c (ffi_closure_SYSV, ffi_closure_raw_SYSV): + Receive closure pointer through parameter, read args using + __builtin_dwarf_cfa. + (FFI_INIT_TRAMPOLINE): Send closure reference through eax. + +2003-03-12 Andreas Schwab + + * configure.in: Avoid trailing /. in toolexeclibdir. + * configure: Rebuilt. + +2003-03-03 Andreas Tobler + + * src/powerpc/darwin_closure.S: Recode to fit dynamic libraries. + +2003-02-06 Andreas Tobler + + * libffi/src/powerpc/darwin_closure.S: + Fix alignement bug, allocate 8 bytes for the result. + * libffi/src/powerpc/aix_closure.S: + Likewise. + * libffi/src/powerpc/ffi_darwin.c: + Update stackframe description for aix/darwin_closure.S. + +2003-02-06 Jakub Jelinek + + * src/s390/ffi.c (ffi_closure_helper_SYSV): Add hidden visibility + attribute. + +2003-01-31 Christian Cornelssen , + Andreas Schwab + + * configure.in: Adjust command to source config-ml.in to account + for changes to the libffi_basedir definition. + (libffi_basedir): Remove ${srcdir} from value and include trailing + slash if nonempty. + + * configure: Regenerate. + +2003-01-29 Franz Sirl + + * src/powerpc/ppc_closure.S: Recode to fit shared libs. + +2003-01-28 Andrew Haley + + * include/ffi.h.in: Enable FFI_CLOSURES for x86_64. + * src/x86/ffi64.c (ffi_prep_closure): New. + (ffi_closure_UNIX64_inner): New. + * src/x86/unix64.S (ffi_closure_UNIX64): New. + +2003-01-27 Alexandre Oliva + + * configure.in (toolexecdir, toolexeclibdir): Set and AC_SUBST. + Remove USE_LIBDIR conditional. + * Makefile.am (toolexecdir, toolexeclibdir): Don't override. + * Makefile.in, configure: Rebuilt. + +2003-01027 David Edelsohn + + * Makefile.am (TARGET_SRC_POWERPC_AIX): Fix typo. + * Makefile.in: Regenerate. + +2003-01-22 Andrew Haley + + * src/powerpc/darwin.S (_ffi_call_AIX): Add Augmentation size to + unwind info. + +2003-01-21 Andreas Tobler + + * src/powerpc/darwin.S: Add unwind info. + * src/powerpc/darwin_closure.S: Likewise. + +2003-01-14 Andrew Haley + + * src/x86/ffi64.c (ffi_prep_args): Check for void retval. + (ffi_prep_cif_machdep): Likewise. + * src/x86/unix64.S: Add unwind info. + +2003-01-14 Andreas Jaeger + + * src/ffitest.c (main): Only use ffi_closures if those are + supported. + +2003-01-13 Andreas Tobler + + * libffi/src/ffitest.c + add closure testcases + +2003-01-13 Kevin B. Hendricks + + * libffi/src/powerpc/ffi.c + fix alignment bug for float (4 byte aligned iso 8 byte) + +2003-01-09 Geoffrey Keating + + * src/powerpc/ffi_darwin.c: Remove RCS version string. + * src/powerpc/darwin.S: Remove RCS version string. + +2003-01-03 Jeff Sturm + + * include/ffi.h.in: Add closure defines for SPARC, SPARC64. + * src/ffitest.c (main): Use static storage for closure. + * src/sparc/ffi.c (ffi_prep_closure, ffi_closure_sparc_inner): New. + * src/sparc/v8.S (ffi_closure_v8): New. + * src/sparc/v9.S (ffi_closure_v9): New. + +2002-11-10 Ranjit Mathew + + * include/ffi.h.in: Added FFI_STDCALL ffi_type + enumeration for X86_WIN32. + * src/x86/win32.S: Added ffi_call_STDCALL function + definition. + * src/x86/ffi.c (ffi_call/ffi_raw_call): Added + switch cases for recognising FFI_STDCALL and + calling ffi_call_STDCALL if target is X86_WIN32. + * src/ffitest.c (my_stdcall_strlen/stdcall_many): + stdcall versions of the "my_strlen" and "many" + test functions (for X86_WIN32). + Added test cases to test stdcall invocation using + these functions. + +2002-12-02 Kaz Kojima + + * src/sh/sysv.S: Add DWARF2 unwind info. + +2002-11-27 Ulrich Weigand + + * src/s390/sysv.S (.eh_frame section): Make section read-only. + +2002-11-26 Jim Wilson + + * src/types.c (FFI_TYPE_POINTER): Has size 8 on IA64. + +2002-11-23 H.J. Lu + + * acinclude.m4: Add dummy AM_PROG_LIBTOOL. + Include ../config/accross.m4. + * aclocal.m4; Rebuild. + * configure: Likewise. + +2002-11-15 Ulrich Weigand + + * src/s390/sysv.S (.eh_frame section): Adapt to pcrel FDE encoding. + +2002-11-11 DJ Delorie + + * configure.in: Look for common files in the right place. + +2002-10-08 Ulrich Weigand + + * src/java_raw_api.c (ffi_java_raw_to_ptrarray): Interpret + raw data as _Jv_word values, not ffi_raw. + (ffi_java_ptrarray_to_raw): Likewise. + (ffi_java_rvalue_to_raw): New function. + (ffi_java_raw_call): Call it. + (ffi_java_raw_to_rvalue): New function. + (ffi_java_translate_args): Call it. + * src/ffitest.c (closure_test_fn): Interpret return value + as ffi_arg, not int. + * src/s390/ffi.c (ffi_prep_cif_machdep): Add missing + FFI_TYPE_POINTER case. + (ffi_closure_helper_SYSV): Likewise. Also, assume return + values extended to word size. + +2002-10-02 Andreas Jaeger + + * src/x86/ffi64.c (ffi_prep_cif_machdep): Remove debug output. + +2002-10-01 Bo Thorsen + + * include/ffi.h.in: Fix i386 win32 compilation. + +2002-09-30 Ulrich Weigand + + * configure.in: Add s390x-*-linux-* target. + * configure: Regenerate. + * include/ffi.h.in: Define S390X for s390x targets. + (FFI_CLOSURES): Define for s390/s390x. + (FFI_TRAMPOLINE_SIZE): Likewise. + (FFI_NATIVE_RAW_API): Likewise. + * src/prep_cif.c (ffi_prep_cif): Do not compute stack space for s390. + * src/types.c (FFI_TYPE_POINTER): Use 8-byte pointers on s390x. + * src/s390/ffi.c: Major rework of existing code. Add support for + s390x targets. Add closure support. + * src/s390/sysv.S: Likewise. + +2002-09-29 Richard Earnshaw + + * src/arm/sysv.S: Fix typo. + +2002-09-28 Richard Earnshaw + + * src/arm/sysv.S: If we don't have machine/asm.h and the pre-processor + has defined __USER_LABEL_PREFIX__, then use it in CNAME. + (ffi_call_SYSV): Handle soft-float. + +2002-09-27 Bo Thorsen + + * include/ffi.h.in: Fix multilib x86-64 support. + +2002-09-22 Kaveh R. Ghazi + + * Makefile.am (all-multi): Fix multilib parallel build. + +2002-07-19 Kaz Kojima + + * configure.in (sh[34]*-*-linux*): Add brackets. + * configure: Regenerate. + +2002-07-18 Kaz Kojima + + * Makefile.am: Add SH support. + * Makefile.in: Regenerate. + * configure.in (sh-*-linux*, sh[34]*-*-linux*): Add target. + * configure: Regenerate. + * include/ffi.h.in: Add SH support. + * src/sh/ffi.c: New file. + * src/sh/sysv.S: New file. + * src/types.c: Add SH support. + +2002-07-16 Bo Thorsen + + * src/x86/ffi64.c: New file that adds x86-64 support. + * src/x86/unix64.S: New file that handles argument setup for + x86-64. + * src/x86/sysv.S: Don't use this on x86-64. + * src/x86/ffi.c: Don't use this on x86-64. + Remove unused vars. + * src/prep_cif.c (ffi_prep_cif): Don't do stack size calculation + for x86-64. + * src/ffitest.c (struct6): New test that tests a special case in + the x86-64 ABI. + (struct7): Likewise. + (struct8): Likewise. + (struct9): Likewise. + (closure_test_fn): Silence warning about this when it's not used. + (main): Add the new tests. + (main): Fix a couple of wrong casts and silence some compiler warnings. + * include/ffi.h.in: Add x86-64 ABI definition. + * fficonfig.h.in: Regenerate. + * Makefile.am: Add x86-64 support. + * configure.in: Likewise. + * Makefile.in: Regenerate. + * configure: Likewise. + +2002-06-24 Bo Thorsen + + * src/types.c: Merge settings for similar architectures. + Add x86-64 sizes and alignments. + +2002-06-23 Bo Thorsen + + * src/arm/ffi.c (ffi_prep_args): Remove unused vars. + * src/sparc/ffi.c (ffi_prep_args_v8): Likewise. + * src/mips/ffi.c (ffi_prep_args): Likewise. + * src/m68k/ffi.c (ffi_prep_args): Likewise. + +2002-07-18 H.J. Lu (hjl@gnu.org) + + * Makefile.am (TARGET_SRC_MIPS_LINUX): New. + (libffi_la_SOURCES): Support MIPS_LINUX. + (libffi_convenience_la_SOURCES): Likewise. + * Makefile.in: Regenerated. + + * configure.in (mips64*-*): Skip. + (mips*-*-linux*): New. + * configure: Regenerated. + + * src/mips/ffi.c: Include . + +2002-06-06 Ulrich Weigand + + * src/s390/sysv.S: Save/restore %r6. Add DWARF-2 unwind info. + +2002-05-27 Roger Sayle + + * src/x86/ffi.c (ffi_prep_args): Remove reference to avn. + +2002-05-27 Bo Thorsen + + * src/x86/ffi.c (ffi_prep_args): Remove unused variable and + fix formatting. + +2002-05-13 Andreas Tobler + + * src/powerpc/ffi_darwin.c (ffi_prep_closure): Declare fd at + beginning of function (for older apple cc). + +2002-05-08 Alexandre Oliva + + * configure.in (ORIGINAL_LD_FOR_MULTILIBS): Preserve LD at + script entry, and set LD to it when configuring multilibs. + * configure: Rebuilt. + +2002-05-05 Jason Thorpe + + * configure.in (sparc64-*-netbsd*): Add target. + (sparc-*-netbsdelf*): Likewise. + * configure: Regenerate. + +2002-04-28 David S. Miller + + * configure.in, configure: Fix SPARC test in previous change. + +2002-04-29 Gerhard Tonn + + * Makefile.am: Add Linux for S/390 support. + * Makefile.in: Regenerate. + * configure.in: Add Linux for S/390 support. + * configure: Regenerate. + * include/ffi.h.in: Add Linux for S/390 support. + * src/s390/ffi.c: New file from libffi CVS tree. + * src/s390/sysv.S: New file from libffi CVS tree. + +2002-04-28 Jakub Jelinek + + * configure.in (HAVE_AS_SPARC_UA_PCREL): Check for working + %r_disp32(). + * src/sparc/v8.S: Use it. + * src/sparc/v9.S: Likewise. + * fficonfig.h.in: Rebuilt. + * configure: Rebuilt. + +2002-04-08 Hans Boehm + + * src/java_raw_api.c (ffi_java_raw_size): Handle FFI_TYPE_DOUBLE + correctly. + * src/ia64/unix.S: Add unwind information. Fix comments. + Save sp in a way that's compatible with unwind info. + (ffi_call_unix): Correctly restore sp in all cases. + * src/ia64/ffi.c: Add, fix comments. + +2002-04-08 Jakub Jelinek + + * src/sparc/v8.S: Make .eh_frame dependent on target word size. + +2002-04-06 Jason Thorpe + + * configure.in (alpha*-*-netbsd*): Add target. + * configure: Regenerate. + +2002-04-04 Jeff Sturm + + * src/sparc/v8.S: Add unwind info. + * src/sparc/v9.S: Likewise. + +2002-03-30 Krister Walfridsson + + * configure.in: Enable i*86-*-netbsdelf*. + * configure: Rebuilt. + +2002-03-29 David Billinghurst + + PR other/2620 + * src/mips/n32.s: Delete + * src/mips/o32.s: Delete + +2002-03-21 Loren J. Rittle + + * configure.in: Enable alpha*-*-freebsd*. + * configure: Rebuilt. + +2002-03-17 Bryce McKinlay + + * Makefile.am: libfficonvenience -> libffi_convenience. + * Makefile.in: Rebuilt. + + * Makefile.am: Define ffitest_OBJECTS. + * Makefile.in: Rebuilt. + +2002-03-07 Andreas Tobler + David Edelsohn + + * Makefile.am (EXTRA_DIST): Add Darwin and AIX closure files. + (TARGET_SRC_POWERPC_AIX): Add aix_closure.S. + (TARGET_SRC_POWERPC_DARWIN): Add darwin_closure.S. + * Makefile.in: Regenerate. + * include/ffi.h.in: Add AIX and Darwin closure definitions. + * src/powerpc/ffi_darwin.c (ffi_prep_closure): New function. + (flush_icache, flush_range): New functions. + (ffi_closure_helper_DARWIN): New function. + * src/powerpc/aix_closure.S: New file. + * src/powerpc/darwin_closure.S: New file. + +2002-02-24 Jeff Sturm + + * include/ffi.h.in: Add typedef for ffi_arg. + * src/ffitest.c (main): Declare rint with ffi_arg. + +2002-02-21 Andreas Tobler + + * src/powerpc/ffi_darwin.c (ffi_prep_args): Skip appropriate + number of GPRs for floating-point arguments. + +2002-01-31 Anthony Green + + * configure: Rebuilt. + * configure.in: Replace CHECK_SIZEOF and endian tests with + cross-compiler friendly macros. + * aclocal.m4 (AC_COMPILE_CHECK_SIZEOF, AC_C_BIGENDIAN_CROSS): New + macros. + +2002-01-18 David Edelsohn + + * src/powerpc/darwin.S (_ffi_call_AIX): New. + * src/powerpc/aix.S (ffi_call_DARWIN): New. + +2002-01-17 David Edelsohn + + * Makefile.am (EXTRA_DIST): Add Darwin and AIX files. + (TARGET_SRC_POWERPC_AIX): New. + (POWERPC_AIX): New stanza. + * Makefile.in: Regenerate. + * configure.in: Add AIX case. + * configure: Regenerate. + * include/ffi.h.in (ffi_abi): Add FFI_AIX. + * src/powerpc/ffi_darwin.c (ffi_status): Use "long" to scale frame + size. Fix "long double" support. + (ffi_call): Add FFI_AIX case. + * src/powerpc/aix.S: New. + +2001-10-09 John Hornkvist + + Implement Darwin PowerPC ABI. + * configure.in: Handle powerpc-*-darwin*. + * Makefile.am: Set source files for POWERPC_DARWIN. + * configure: Rebuilt. + * Makefile.in: Rebuilt. + * include/ffi.h.in: Define FFI_DARWIN and FFI_DEFAULT_ABI for + POWERPC_DARWIN. + * src/powerpc/darwin.S: New file. + * src/powerpc/ffi_darwin.c: New file. + +2001-10-07 Joseph S. Myers + + * src/x86/ffi.c: Fix spelling error of "separate" as "seperate". + +2001-07-16 Rainer Orth + + * src/x86/sysv.S: Avoid gas-only .balign directive. + Use C style comments. + +2001-07-16 Rainer Orth + + * src/alpha/ffi.c (ffi_prep_closure): Avoid gas-only mnemonic. + Fixes PR bootstrap/3563. + +2001-06-26 Rainer Orth + + * src/alpha/osf.S (ffi_closure_osf): Use .rdata for ECOFF. + +2001-06-25 Rainer Orth + + * configure.in: Recognize sparc*-sun-* host. + * configure: Regenerate. + +2001-06-06 Andrew Haley + + * src/alpha/osf.S (__FRAME_BEGIN__): Conditionalize for ELF. + +2001-06-03 Andrew Haley + + * src/alpha/osf.S: Add unwind info. + * src/powerpc/sysv.S: Add unwind info. + * src/powerpc/ppc_closure.S: Likewise. + +2000-05-31 Jeff Sturm + + * configure.in: Fix AC_ARG_ENABLE usage. + * configure: Rebuilt. + +2001-05-06 Bryce McKinlay + + * configure.in: Remove warning about beta code. + * configure: Rebuilt. + +2001-04-25 Hans Boehm + + * src/ia64/unix.S: Restore stack pointer when returning from + ffi_closure_UNIX. + * src/ia64/ffi.c: Fix typo in comment. + +2001-04-18 Jim Wilson + + * src/ia64/unix.S: Delete unnecessary increment and decrement of loc2 + to eliminate RAW DV. + +2001-04-12 Bryce McKinlay + + * Makefile.am: Make a libtool convenience library. + * Makefile.in: Rebuilt. + +2001-03-29 Bryce McKinlay + + * configure.in: Use different syntax for subdirectory creation. + * configure: Rebuilt. + +2001-03-27 Jon Beniston + + * configure.in: Added X86_WIN32 target (Win32, CygWin, MingW). + * configure: Rebuilt. + * Makefile.am: Added X86_WIN32 target support. + * Makefile.in: Rebuilt. + + * include/ffi.h.in: Added X86_WIN32 target support. + + * src/ffitest.c: Doesn't run structure tests for X86_WIN32 targets. + * src/types.c: Added X86_WIN32 target support. + + * src/x86/win32.S: New file. Based on sysv.S, but with EH + stuff removed and made to work with CygWin's gas. + +2001-03-26 Bryce McKinlay + + * configure.in: Make target subdirectory in build dir. + * Makefile.am: Override suffix based rules to specify correct output + subdirectory. + * Makefile.in: Rebuilt. + * configure: Rebuilt. + +2001-03-23 Kevin B Hendricks + + * src/powerpc/ppc_closure.S: New file. + * src/powerpc/ffi.c (ffi_prep_args): Fixed ABI compatibility bug + involving long long and register pairs. + (ffi_prep_closure): New function. + (flush_icache): Likewise. + (ffi_closure_helper_SYSV): Likewise. + * include/ffi.h.in (FFI_CLOSURES): Define on PPC. + (FFI_TRAMPOLINE_SIZE): Likewise. + (FFI_NATIVE_RAW_API): Likewise. + * Makefile.in: Rebuilt. + * Makefile.am (EXTRA_DIST): Added src/powerpc/ppc_closure.S. + (TARGET_SRC_POWERPC): Likewise. + +2001-03-19 Tom Tromey + + * Makefile.in: Rebuilt. + * Makefile.am (ffitest_LDFLAGS): New macro. + +2001-03-02 Nick Clifton + + * include/ffi.h.in: Remove RCS ident string. + * include/ffi_mips.h: Remove RCS ident string. + * src/debug.c: Remove RCS ident string. + * src/ffitest.c: Remove RCS ident string. + * src/prep_cif.c: Remove RCS ident string. + * src/types.c: Remove RCS ident string. + * src/alpha/ffi.c: Remove RCS ident string. + * src/alpha/osf.S: Remove RCS ident string. + * src/arm/ffi.c: Remove RCS ident string. + * src/arm/sysv.S: Remove RCS ident string. + * src/mips/ffi.c: Remove RCS ident string. + * src/mips/n32.S: Remove RCS ident string. + * src/mips/o32.S: Remove RCS ident string. + * src/sparc/ffi.c: Remove RCS ident string. + * src/sparc/v8.S: Remove RCS ident string. + * src/sparc/v9.S: Remove RCS ident string. + * src/x86/ffi.c: Remove RCS ident string. + * src/x86/sysv.S: Remove RCS ident string. + +2001-02-08 Joseph S. Myers + + * include/ffi.h.in: Change sourceware.cygnus.com references to + gcc.gnu.org. + +2000-12-09 Richard Henderson + + * src/alpha/ffi.c (ffi_call): Simplify struct return test. + (ffi_closure_osf_inner): Index rather than increment avalue + and arg_types. Give ffi_closure_osf the raw return value type. + * src/alpha/osf.S (ffi_closure_osf): Handle return value type + promotion. + +2000-12-07 Richard Henderson + + * src/raw_api.c (ffi_translate_args): Fix typo. + (ffi_prep_closure): Likewise. + + * include/ffi.h.in [ALPHA]: Define FFI_CLOSURES and + FFI_TRAMPOLINE_SIZE. + * src/alpha/ffi.c (ffi_prep_cif_machdep): Adjust minimal + cif->bytes for new ffi_call_osf implementation. + (ffi_prep_args): Absorb into ... + (ffi_call): ... here. Do all stack allocation here and + avoid a callback function. + (ffi_prep_closure, ffi_closure_osf_inner): New. + * src/alpha/osf.S (ffi_call_osf): Reimplement with no callback. + (ffi_closure_osf): New. + +2000-09-10 Alexandre Oliva + + * config.guess, config.sub, install-sh: Removed. + * ltconfig, ltmain.sh, missing, mkinstalldirs: Likewise. + * Makefile.in: Rebuilt. + + * acinclude.m4: Include libtool macros from the top level. + * aclocal.m4, configure: Rebuilt. + +2000-08-22 Alexandre Oliva + + * configure.in [i*86-*-freebsd*] (TARGET, TARGETDIR): Set. + * configure: Rebuilt. + +2000-05-11 Scott Bambrough + + * libffi/src/arm/sysv.S (ffi_call_SYSV): Doubles are not saved to + memory correctly. Use conditional instructions, not branches where + possible. + +2000-05-04 Tom Tromey + + * configure: Rebuilt. + * configure.in: Match `arm*-*-linux-*'. + From Chris Dornan . + +2000-04-28 Jakub Jelinek + + * Makefile.am (SUBDIRS): Define. + (AM_MAKEFLAGS): Likewise. + (Multilib support.): Add section. + * Makefile.in: Rebuilt. + * ltconfig (extra_compiler_flags, extra_compiler_flags_value): + New variables. Set for gcc using -print-multi-lib. Export them + to libtool. + (sparc64-*-linux-gnu*): Use libsuff 64 for search paths. + * ltmain.sh (B|b|V): Don't throw away gcc's -B, -b and -V options + for -shared links. + (extra_compiler_flags_value, extra_compiler_flags): Check these + for extra compiler options which need to be passed down in + compiler_flags. + +2000-04-16 Anthony Green + + * configure: Rebuilt. + * configure.in: Change i*86-pc-linux* to i*86-*-linux*. + +2000-04-14 Jakub Jelinek + + * include/ffi.h.in (SPARC64): Define for 64bit SPARC builds. + Set SPARC FFI_DEFAULT_ABI based on SPARC64 define. + * src/sparc/ffi.c (ffi_prep_args_v8): Renamed from ffi_prep_args. + Replace all void * sizeofs with sizeof(int). + Only compare type with FFI_TYPE_LONGDOUBLE if LONGDOUBLE is + different than DOUBLE. + Remove FFI_TYPE_SINT32 and FFI_TYPE_UINT32 cases (handled elsewhere). + (ffi_prep_args_v9): New function. + (ffi_prep_cif_machdep): Handle V9 ABI and long long on V8. + (ffi_V9_return_struct): New function. + (ffi_call): Handle FFI_V9 ABI from 64bit code and FFI_V8 ABI from + 32bit code (not yet cross-arch calls). + * src/sparc/v8.S: Add struct return delay nop. + Handle long long. + * src/sparc/v9.S: New file. + * src/prep_cif.c (ffi_prep_cif): Return structure pointer + is used on sparc64 only for structures larger than 32 bytes. + Pass by reference for structures is done for structure arguments + larger than 16 bytes. + * src/ffitest.c (main): Use 64bit rint on sparc64. + Run long long tests on sparc. + * src/types.c (FFI_TYPE_POINTER): Pointer is 64bit on alpha and + sparc64. + (FFI_TYPE_LONGDOUBLE): long double is 128 bit aligned to 128 bits + on sparc64. + * configure.in (sparc-*-linux*): New supported target. + (sparc64-*-linux*): Likewise. + * configure: Rebuilt. + * Makefile.am: Add v9.S to SPARC files. + * Makefile.in: Likewise. + (LINK): Surround $(CCLD) into double quotes, so that multilib + compiles work correctly. + +2000-04-04 Alexandre Petit-Bianco + + * configure: Rebuilt. + * configure.in: (i*86-*-solaris*): New libffi target. Patch + proposed by Bryce McKinlay. + +2000-03-20 Tom Tromey + + * Makefile.in: Hand edit for java_raw_api.lo. + +2000-03-08 Bryce McKinlay + + * config.guess, config.sub: Update from the gcc tree. + Fix for PR libgcj/168. + +2000-03-03 Tom Tromey + + * Makefile.in: Fixed ia64 by hand. + + * configure: Rebuilt. + * configure.in (--enable-multilib): New option. + (libffi_basedir): New subst. + (AC_OUTPUT): Added multilib code. + +2000-03-02 Tom Tromey + + * Makefile.in: Rebuilt. + * Makefile.am (TARGET_SRC_IA64): Use `ia64', not `alpha', as + directory name. + +2000-02-25 Hans Boehm + + * src/ia64/ffi.c, src/ia64/ia64_flags.h, src/ia64/unix.S: New + files. + * src/raw_api.c (ffi_translate_args): Fixed typo in argument + list. + (ffi_prep_raw_closure): Use ffi_translate_args, not + ffi_closure_translate. + * src/java_raw_api.c: New file. + * src/ffitest.c (closure_test_fn): New function. + (main): Define `rint' as long long on IA64. Added new test when + FFI_CLOSURES is defined. + * include/ffi.h.in (ALIGN): Use size_t, not unsigned. + (ffi_abi): Recognize IA64. + (ffi_raw): Added `flt' field. + Added "Java raw API" code. + * configure.in: Recognize ia64. + * Makefile.am (TARGET_SRC_IA64): New macro. + (libffi_la_common_SOURCES): Added java_raw_api.c. + (libffi_la_SOURCES): Define in IA64 case. + +2000-01-04 Tom Tromey + + * Makefile.in: Rebuilt with newer automake. + +1999-12-31 Tom Tromey + + * Makefile.am (INCLUDES): Added -I$(top_srcdir)/src. + +1999-09-01 Tom Tromey + + * include/ffi.h.in: Removed PACKAGE and VERSION defines and + undefs. + * fficonfig.h.in: Rebuilt. + * configure: Rebuilt. + * configure.in: Pass 3rd argument to AM_INIT_AUTOMAKE. + Use AM_PROG_LIBTOOL (automake 1.4 compatibility). + * acconfig.h: Don't #undef PACKAGE or VERSION. + +1999-08-09 Anthony Green + + * include/ffi.h.in: Try to work around messy header problem + with PACKAGE and VERSION. + + * configure: Rebuilt. + * configure.in: Change version to 2.00-beta. + + * fficonfig.h.in: Rebuilt. + * acconfig.h (FFI_NO_STRUCTS, FFI_NO_RAW_API): Define. + + * src/x86/ffi.c (ffi_raw_call): Rename. + +1999-08-02 Kresten Krab Thorup + + * src/x86/ffi.c (ffi_closure_SYSV): New function. + (ffi_prep_incoming_args_SYSV): Ditto. + (ffi_prep_closure): Ditto. + (ffi_closure_raw_SYSV): Ditto. + (ffi_prep_raw_closure): More ditto. + (ffi_call_raw): Final ditto. + + * include/ffi.h.in: Add definitions for closure and raw API. + + * src/x86/ffi.c (ffi_prep_cif_machdep): Added case for + FFI_TYPE_UINT64. + + * Makefile.am (libffi_la_common_SOURCES): Added raw_api.c + + * src/raw_api.c: New file. + + * include/ffi.h.in (ffi_raw): New type. + (UINT_ARG, SINT_ARG): New defines. + (ffi_closure, ffi_raw_closure): New types. + (ffi_prep_closure, ffi_prep_raw_closure): New declarations. + + * configure.in: Add check for endianness and sizeof void*. + + * src/x86/sysv.S (ffi_call_SYSV): Call fixup routine via argument, + instead of directly. + + * configure: Rebuilt. + +Thu Jul 8 14:28:42 1999 Anthony Green + + * configure.in: Add x86 and powerpc BeOS configurations. + From Makoto Kato . + +1999-05-09 Anthony Green + + * configure.in: Add warning about this being beta code. + Remove src/Makefile.am from the picture. + * configure: Rebuilt. + + * Makefile.am: Move logic from src/Makefile.am. Add changes + to support libffi as a target library. + * Makefile.in: Rebuilt. + + * aclocal.m4, config.guess, config.sub, ltconfig, ltmain.sh: + Upgraded to new autoconf, automake, libtool. + + * README: Tweaks. + + * LICENSE: Update copyright date. + + * src/Makefile.am, src/Makefile.in: Removed. + +1998-11-29 Anthony Green + + * include/ChangeLog: Removed. + * src/ChangeLog: Removed. + * src/mips/ChangeLog: Removed. + * src/sparc/ChangeLog: Remboved. + * src/x86/ChangeLog: Removed. + + * ChangeLog.v1: Created. + +============================================================================= +From the old ChangeLog.libffi file.... + +2011-02-08 Andreas Tobler + + * testsuite/lib/libffi.exp: Tweak for stand-alone mode. + +2009-12-25 Samuli Suominen + + * configure.ac: Undefine _AC_ARG_VAR_PRECIOUS for autoconf 2.64. + * configure: Rebuilt. + * fficonfig.h.in: Rebuilt. + +2009-06-16 Andrew Haley + + * testsuite/libffi.call/cls_align_sint64.c, + testsuite/libffi.call/cls_align_uint64.c, + testsuite/libffi.call/cls_longdouble_va.c, + testsuite/libffi.call/cls_ulonglong.c, + testsuite/libffi.call/return_ll1.c, + testsuite/libffi.call/stret_medium2.c: Fix printf format + specifiers. + * testsuite/libffi.call/huge_struct.c: Ad x86 XFAILs. + * testsuite/libffi.call/float2.c: Fix dg-excess-errors. + * testsuite/libffi.call/ffitest.h, + testsuite/libffi.special/ffitestcxx.h (PRIdLL, PRIuLL): Define. + +2009-06-12 Andrew Haley + + * testsuite/libffi.call/cls_align_sint64.c, + testsuite/libffi.call/cls_align_uint64.c, + testsuite/libffi.call/cls_ulonglong.c, + testsuite/libffi.call/return_ll1.c, + testsuite/libffi.call/stret_medium2.c: Fix printf format + specifiers. + testsuite/libffi.special/unwindtest.cc: include stdint.h. + +2009-06-11 Timothy Wall + + * Makefile.am, + configure.ac, + include/ffi.h.in, + include/ffi_common.h, + src/closures.c, + src/dlmalloc.c, + src/x86/ffi.c, + src/x86/ffitarget.h, + src/x86/win64.S (new), + README: Added win64 support (mingw or MSVC) + * Makefile.in, + include/Makefile.in, + man/Makefile.in, + testsuite/Makefile.in, + configure, + aclocal.m4: Regenerated + * ltcf-c.sh: properly escape cygwin/w32 path + * man/ffi_call.3: Clarify size requirements for return value. + * src/x86/ffi64.c: Fix filename in comment. + * src/x86/win32.S: Remove unused extern. + + * testsuite/libffi.call/closure_fn0.c, + testsuite/libffi.call/closure_fn1.c, + testsuite/libffi.call/closure_fn2.c, + testsuite/libffi.call/closure_fn3.c, + testsuite/libffi.call/closure_fn4.c, + testsuite/libffi.call/closure_fn5.c, + testsuite/libffi.call/closure_fn6.c, + testsuite/libffi.call/closure_stdcall.c, + testsuite/libffi.call/cls_12byte.c, + testsuite/libffi.call/cls_16byte.c, + testsuite/libffi.call/cls_18byte.c, + testsuite/libffi.call/cls_19byte.c, + testsuite/libffi.call/cls_1_1byte.c, + testsuite/libffi.call/cls_20byte.c, + testsuite/libffi.call/cls_20byte1.c, + testsuite/libffi.call/cls_24byte.c, + testsuite/libffi.call/cls_2byte.c, + testsuite/libffi.call/cls_3_1byte.c, + testsuite/libffi.call/cls_3byte1.c, + testsuite/libffi.call/cls_3byte2.c, + testsuite/libffi.call/cls_4_1byte.c, + testsuite/libffi.call/cls_4byte.c, + testsuite/libffi.call/cls_5_1_byte.c, + testsuite/libffi.call/cls_5byte.c, + testsuite/libffi.call/cls_64byte.c, + testsuite/libffi.call/cls_6_1_byte.c, + testsuite/libffi.call/cls_6byte.c, + testsuite/libffi.call/cls_7_1_byte.c, + testsuite/libffi.call/cls_7byte.c, + testsuite/libffi.call/cls_8byte.c, + testsuite/libffi.call/cls_9byte1.c, + testsuite/libffi.call/cls_9byte2.c, + testsuite/libffi.call/cls_align_double.c, + testsuite/libffi.call/cls_align_float.c, + testsuite/libffi.call/cls_align_longdouble.c, + testsuite/libffi.call/cls_align_longdouble_split.c, + testsuite/libffi.call/cls_align_longdouble_split2.c, + testsuite/libffi.call/cls_align_pointer.c, + testsuite/libffi.call/cls_align_sint16.c, + testsuite/libffi.call/cls_align_sint32.c, + testsuite/libffi.call/cls_align_sint64.c, + testsuite/libffi.call/cls_align_uint16.c, + testsuite/libffi.call/cls_align_uint32.c, + testsuite/libffi.call/cls_align_uint64.c, + testsuite/libffi.call/cls_dbls_struct.c, + testsuite/libffi.call/cls_double.c, + testsuite/libffi.call/cls_double_va.c, + testsuite/libffi.call/cls_float.c, + testsuite/libffi.call/cls_longdouble.c, + testsuite/libffi.call/cls_longdouble_va.c, + testsuite/libffi.call/cls_multi_schar.c, + testsuite/libffi.call/cls_multi_sshort.c, + testsuite/libffi.call/cls_multi_sshortchar.c, + testsuite/libffi.call/cls_multi_uchar.c, + testsuite/libffi.call/cls_multi_ushort.c, + testsuite/libffi.call/cls_multi_ushortchar.c, + testsuite/libffi.call/cls_pointer.c, + testsuite/libffi.call/cls_pointer_stack.c, + testsuite/libffi.call/cls_schar.c, + testsuite/libffi.call/cls_sint.c, + testsuite/libffi.call/cls_sshort.c, + testsuite/libffi.call/cls_uchar.c, + testsuite/libffi.call/cls_uint.c, + testsuite/libffi.call/cls_ulonglong.c, + testsuite/libffi.call/cls_ushort.c, + testsuite/libffi.call/err_bad_abi.c, + testsuite/libffi.call/err_bad_typedef.c, + testsuite/libffi.call/float2.c, + testsuite/libffi.call/huge_struct.c, + testsuite/libffi.call/nested_struct.c, + testsuite/libffi.call/nested_struct1.c, + testsuite/libffi.call/nested_struct10.c, + testsuite/libffi.call/nested_struct2.c, + testsuite/libffi.call/nested_struct3.c, + testsuite/libffi.call/nested_struct4.c, + testsuite/libffi.call/nested_struct5.c, + testsuite/libffi.call/nested_struct6.c, + testsuite/libffi.call/nested_struct7.c, + testsuite/libffi.call/nested_struct8.c, + testsuite/libffi.call/nested_struct9.c, + testsuite/libffi.call/problem1.c, + testsuite/libffi.call/return_ldl.c, + testsuite/libffi.call/return_ll1.c, + testsuite/libffi.call/stret_large.c, + testsuite/libffi.call/stret_large2.c, + testsuite/libffi.call/stret_medium.c, + testsuite/libffi.call/stret_medium2.c, + testsuite/libffi.special/unwindtest.cc: use ffi_closure_alloc instead + of checking for MMAP. Use intptr_t instead of long casts. + +2009-06-04 Andrew Haley + + * src/powerpc/ffitarget.h: Fix misapplied merge from gcc. + +2009-06-04 Andrew Haley + + * src/mips/o32.S, + src/mips/n32.S: Fix licence formatting. + +2009-06-04 Andrew Haley + + * src/x86/darwin.S: Fix licence formatting. + src/x86/win32.S: Likewise. + src/sh64/sysv.S: Likewise. + src/sh/sysv.S: Likewise. + +2009-06-04 Andrew Haley + + * src/sh64/ffi.c: Remove lint directives. Was missing from merge + of Andreas Tobler's patch from 2006-04-22. + +2009-06-04 Andrew Haley + + * src/sh/ffi.c: Apply missing hunk from Alexandre Oliva's patch of + 2007-03-07. + +2008-12-26 Timothy Wall + + * testsuite/libffi.call/cls_longdouble.c, + testsuite/libffi.call/cls_longdouble_va.c, + testsuite/libffi.call/cls_align_longdouble.c, + testsuite/libffi.call/cls_align_longdouble_split.c, + testsuite/libffi.call/cls_align_longdouble_split2.c: mark expected + failures on x86_64 cygwin/mingw. + +2008-12-22 Timothy Wall + + * testsuite/libffi.call/closure_fn0.c, + testsuite/libffi.call/closure_fn1.c, + testsuite/libffi.call/closure_fn2.c, + testsuite/libffi.call/closure_fn3.c, + testsuite/libffi.call/closure_fn4.c, + testsuite/libffi.call/closure_fn5.c, + testsuite/libffi.call/closure_fn6.c, + testsuite/libffi.call/closure_loc_fn0.c, + testsuite/libffi.call/closure_stdcall.c, + testsuite/libffi.call/cls_align_pointer.c, + testsuite/libffi.call/cls_pointer.c, + testsuite/libffi.call/cls_pointer_stack.c: use portable cast from + pointer to integer (intptr_t). + * testsuite/libffi.call/cls_longdouble.c: disable for win64. + +2008-12-19 Anthony Green + + * configure.ac: Bump version to 3.0.8. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + * libtool-version: Increment revision. + * README: Update for new release. + +2008-11-11 Anthony Green + + * configure.ac: Bump version to 3.0.7. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + * libtool-version: Increment revision. + * README: Update for new release. + +2008-08-25 Andreas Tobler + + * src/powerpc/ffitarget.h (ffi_abi): Add FFI_LINUX and + FFI_LINUX_SOFT_FLOAT to the POWERPC_FREEBSD enum. + Add note about flag bits used for FFI_SYSV_TYPE_SMALL_STRUCT. + Adjust copyright notice. + * src/powerpc/ffi.c: Add two new flags to indicate if we have one + register or two register to use for FFI_SYSV structs. + (ffi_prep_cif_machdep): Pass the right register flag introduced above. + (ffi_closure_helper_SYSV): Fix the return type for + FFI_SYSV_TYPE_SMALL_STRUCT. Comment. + Adjust copyright notice. + +2008-07-24 Anthony Green + + * testsuite/libffi.call/cls_dbls_struct.c, + testsuite/libffi.call/cls_double_va.c, + testsuite/libffi.call/cls_longdouble.c, + testsuite/libffi.call/cls_longdouble_va.c, + testsuite/libffi.call/cls_pointer.c, + testsuite/libffi.call/cls_pointer_stack.c, + testsuite/libffi.call/err_bad_abi.c: Clean up failures from + compiler warnings. + +2008-07-17 Anthony Green + + * configure.ac: Bump version to 3.0.6. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + * libtool-version: Increment revision. Add documentation. + * README: Update for new release. + +2008-07-16 Kaz Kojima + + * src/sh/ffi.c (ffi_prep_closure_loc): Turn INSN into an unsigned + int. + +2008-07-16 Kaz Kojima + + * src/sh/sysv.S: Add .note.GNU-stack on Linux. + * src/sh64/sysv.S: Likewise. + +2008-04-03 Anthony Green + + * libffi.pc.in (Libs): Add -L${libdir}. + * configure.ac: Bump version to 3.0.5. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + * libtool-version: Increment revision. + * README: Update for new release. + +2008-04-03 Anthony Green + Xerces Ranby + + * include/ffi.h.in: Wrap definition of target architecture to + protect from double definitions. + +2008-03-22 Moriyoshi Koizumi + + * src/x86/ffi.c (ffi_prep_closure_loc): Fix for bug revealed in + closure_loc_fn0.c. + * testsuite/libffi.call/closure_loc_fn0.c (closure_loc_test_fn0): + New test. + +2008-03-04 Anthony Green + Blake Chaffin + hos@tamanegi.org + + * testsuite/libffi.call/cls_align_longdouble_split2.c + testsuite/libffi.call/cls_align_longdouble_split.c + testsuite/libffi.call/cls_dbls_struct.c + testsuite/libffi.call/cls_double_va.c + testsuite/libffi.call/cls_longdouble.c + testsuite/libffi.call/cls_longdouble_va.c + testsuite/libffi.call/cls_pointer.c + testsuite/libffi.call/cls_pointer_stack.c + testsuite/libffi.call/err_bad_abi.c + testsuite/libffi.call/err_bad_typedef.c + testsuite/libffi.call/huge_struct.c + testsuite/libffi.call/stret_large2.c + testsuite/libffi.call/stret_large.c + testsuite/libffi.call/stret_medium2.c + testsuite/libffi.call/stret_medium.c: New tests from Apple. + +2008-02-26 Jakub Jelinek + Anthony Green + + * src/alpha/osf.S: Add .note.GNU-stack on Linux. + * src/s390/sysv.S: Likewise. + * src/powerpc/linux64.S: Likewise. + * src/powerpc/linux64_closure.S: Likewise. + * src/powerpc/ppc_closure.S: Likewise. + * src/powerpc/sysv.S: Likewise. + * src/x86/unix64.S: Likewise. + * src/x86/sysv.S: Likewise. + * src/sparc/v8.S: Likewise. + * src/sparc/v9.S: Likewise. + * src/m68k/sysv.S: Likewise. + * src/ia64/unix.S: Likewise. + * src/arm/sysv.S: Likewise. + +2008-02-26 Anthony Green + Thomas Heller + + * src/x86/ffi.c (ffi_closure_SYSV_inner): Change C++ comment to C + comment. + +2008-02-26 Anthony Green + Thomas Heller + + * include/ffi.h.in: Change void (*)() to void (*)(void). + +2008-02-26 Anthony Green + Thomas Heller + + * src/alpha/ffi.c: Change void (*)() to void (*)(void). + src/alpha/osf.S, src/arm/ffi.c, src/frv/ffi.c, src/ia64/ffi.c, + src/ia64/unix.S, src/java_raw_api.c, src/m32r/ffi.c, + src/mips/ffi.c, src/pa/ffi.c, src/pa/hpux32.S, src/pa/linux.S, + src/powerpc/ffi.c, src/powerpc/ffi_darwin.c, src/raw_api.c, + src/s390/ffi.c, src/sh/ffi.c, src/sh64/ffi.c, src/sparc/ffi.c, + src/x86/ffi.c, src/x86/unix64.S, src/x86/darwin64.S, + src/x86/ffi64.c: Ditto. + +2008-02-24 Anthony Green + + * configure.ac: Accept openbsd*, not just openbsd. + Bump version to 3.0.4. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + * libtool-version: Increment revision. + * README: Update for new release. + +2008-02-22 Anthony Green + + * README: Clean up list of tested platforms. + +2008-02-22 Anthony Green + + * configure.ac: Bump version to 3.0.3. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + * libtool-version: Increment revision. + * README: Update for new release. Clean up test docs. + +2008-02-22 Bjoern Koenig + Andreas Tobler + + * configure.ac: Add amd64-*-freebsd* target. + * configure: Regenerate. + +2008-02-22 Thomas Heller + + * configure.ac: Add x86 OpenBSD support. + * configure: Rebuilt. + +2008-02-21 Thomas Heller + + * README: Change "make test" to "make check". + +2008-02-21 Anthony Green + + * configure.ac: Bump version to 3.0.2. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + * libtool-version: Increment revision. + * README: Update for new release. + +2008-02-21 Björn König + + * src/x86/freebsd.S: New file. + * configure.ac: Add x86 FreeBSD support. + * Makefile.am: Ditto. + +2008-02-15 Anthony Green + + * configure.ac: Bump version to 3.0.1. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + * libtool-version: Increment revision. + * README: Update for new release. + +2008-02-15 David Daney + + * src/mips/ffi.c: Remove extra '>' from include directive. + (ffi_prep_closure_loc): Use clear_location instead of tramp. + +2008-02-15 Anthony Green + + * configure.ac: Bump version to 3.0.0. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + +2008-02-15 David Daney + + * src/mips/ffi.c (USE__BUILTIN___CLEAR_CACHE): + Define (conditionally), and use it to include cachectl.h. + (ffi_prep_closure_loc): Fix cache flushing. + * src/mips/ffitarget.h (_ABIN32, _ABI64, _ABIO32): Define. + +2008-02-15 Anthony Green + + * man/ffi_call.3, man/ffi_prep_cif.3, man/ffi.3: + Update dates and remove all references to ffi_prep_closure. + * configure.ac: Bump version to 2.99.9. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + +2008-02-15 Anthony Green + + * man/ffi_prep_closure.3: Delete. + * man/Makefile.am (EXTRA_DIST): Remove ffi_prep_closure.3. + (man_MANS): Ditto. + * man/Makefile.in: Rebuilt. + * configure.ac: Bump version to 2.99.8. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + +2008-02-14 Anthony Green + + * configure.ac: Bump version to 2.99.7. + * configure, doc/stamp-vti, doc/version.texi: Rebuilt. + * include/ffi.h.in LICENSE src/debug.c src/closures.c + src/ffitest.c src/s390/sysv.S src/s390/ffitarget.h + src/types.c src/m68k/ffitarget.h src/raw_api.c src/frv/ffi.c + src/frv/ffitarget.h src/sh/ffi.c src/sh/sysv.S + src/sh/ffitarget.h src/powerpc/ffitarget.h src/pa/ffi.c + src/pa/ffitarget.h src/pa/linux.S src/java_raw_api.c + src/cris/ffitarget.h src/x86/ffi.c src/x86/sysv.S + src/x86/unix64.S src/x86/win32.S src/x86/ffitarget.h + src/x86/ffi64.c src/x86/darwin.S src/ia64/ffi.c + src/ia64/ffitarget.h src/ia64/ia64_flags.h src/ia64/unix.S + src/sparc/ffi.c src/sparc/v9.S src/sparc/ffitarget.h + src/sparc/v8.S src/alpha/ffi.c src/alpha/ffitarget.h + src/alpha/osf.S src/sh64/ffi.c src/sh64/sysv.S + src/sh64/ffitarget.h src/mips/ffi.c src/mips/ffitarget.h + src/mips/n32.S src/mips/o32.S src/arm/ffi.c src/arm/sysv.S + src/arm/ffitarget.h src/prep_cif.c: Update license text. + +2008-02-14 Anthony Green + + * README: Update tested platforms. + * configure.ac: Bump version to 2.99.6. + * configure: Rebuilt. + +2008-02-14 Anthony Green + + * configure.ac: Bump version to 2.99.5. + * configure: Rebuilt. + * Makefile.am (EXTRA_DIST): Add darwin64.S + * Makefile.in: Rebuilt. + * testsuite/lib/libffi-dg.exp: Remove libstdc++ bits from GCC tree. + * LICENSE: Update WARRANTY. + +2008-02-14 Anthony Green + + * libffi.pc.in (libdir): Fix libdir definition. + * configure.ac: Bump version to 2.99.4. + * configure: Rebuilt. + +2008-02-14 Anthony Green + + * README: Update. + * libffi.info: New file. + * doc/stamp-vti: New file. + * configure.ac: Bump version to 2.99.3. + * configure: Rebuilt. + +2008-02-14 Anthony Green + + * Makefile.am (SUBDIRS): Add man dir. + * Makefile.in: Rebuilt. + * configure.ac: Create Makefile. + * configure: Rebuilt. + * man/ffi_call.3 man/ffi_prep_cif.3 man/ffi_prep_closure.3 + man/Makefile.am man/Makefile.in: New files. + +2008-02-14 Tom Tromey + + * aclocal.m4, Makefile.in, configure, fficonfig.h.in: Rebuilt. + * mdate-sh, texinfo.tex: New files. + * Makefile.am (info_TEXINFOS): New variable. + * doc/libffi.texi: New file. + * doc/version.texi: Likewise. + +2008-02-14 Anthony Green + + * Makefile.am (AM_CFLAGS): Don't compile with -D$(TARGET). + (lib_LTLIBRARIES): Define. + (toolexeclib_LIBRARIES): Undefine. + * Makefile.in: Rebuilt. + * configure.ac: Reset version to 2.99.1. + * configure.in: Rebuilt. + +2008-02-14 Anthony Green + + * libffi.pc.in: Use @PACKAGE_NAME@ and @PACKAGE_VERSION@. + * configure.ac: Reset version to 2.99.1. + * configure.in: Rebuilt. + * Makefile.am (EXTRA_DIST): Add ChangeLog.libffi. + * Makefile.in: Rebuilt. + * LICENSE: Update copyright notice. + +2008-02-14 Anthony Green + + * include/Makefile.am (nodist_includes_HEADERS): Define. Don't + distribute ffitarget.h or ffi.h from the build include dir. + * Makefile.in: Rebuilt. + +2008-02-14 Anthony Green + + * include/Makefile.am (includesdir): Install headers under libdir. + (pkgconfigdir): Define. Install libffi.pc. + * include/Makefile.in: Rebuilt. + * libffi.pc.in: Create. + * libtool-version: Increment CURRENT + * configure.ac: Add libffi.pc.in + * configure: Rebuilt. + +2008-02-03 Anthony Green + + * include/Makefile.am (includesdir): Fix header install with + DESTDIR. + * include/Makefile.in: Rebuilt. + +2008-02-03 Timothy Wall + + * src/x86/ffi.c (FFI_INIT_TRAMPOLINE_STDCALL): Calculate jump return + offset based on code pointer, not data pointer. + +2008-02-01 Anthony Green + + * include/Makefile.am: Fix header installs. + * Makefile.am: Ditto. + * include/Makefile.in: Rebuilt. + * Makefile.in: Ditto. + +2008-02-01 Anthony Green + + * src/x86/ffi.c (FFI_INIT_TRAMPOLINE_STDCALL, + FFI_INIT_TRAMPOLINE): Revert my broken changes to twall's last + patch. + +2008-01-31 Anthony Green + + * Makefile.am (EXTRA_DIST): Add missing files. + * testsuite/Makefile.am: Ditto. + * Makefile.in, testsuite/Makefile.in: Rebuilt. + +2008-01-31 Timothy Wall + + * testsuite/libffi.call/closure_stdcall.c: Add test for stdcall + closures. + * src/x86/ffitarget.h: Increase size of trampoline for stdcall + closures. + * src/x86/win32.S: Add assembly for stdcall closure. + * src/x86/ffi.c: Initialize stdcall closure trampoline. + +2008-01-30 H.J. Lu + + PR libffi/34612 + * src/x86/sysv.S (ffi_closure_SYSV): Pop 4 byte from stack when + returning struct. + + * testsuite/libffi.call/call.exp: Add "-O2 -fomit-frame-pointer" + tests. + +2008-01-30 Anthony Green + + * Makefile.am, include/Makefile.am: Move headers to + libffi_la_SOURCES for new automake. + * Makefile.in, include/Makefile.in: Rebuilt. + + * testsuite/lib/wrapper.exp: Copied from gcc tree to allow for + execution outside of gcc tree. + * testsuite/lib/target-libpath.exp: Ditto. + + * testsuite/lib/libffi-dg.exp: Many changes to allow for execution + outside of gcc tree. + + +============================================================================= +From the old ChangeLog.libgcj file.... + +2004-01-14 Kelley Cook + + * configure.in: Add in AC_PREREQ(2.13) + +2003-02-20 Alexandre Oliva + + * configure.in: Propagate ORIGINAL_LD_FOR_MULTILIBS to + config.status. + * configure: Rebuilt. + +2002-01-27 Alexandre Oliva + + * configure.in (toolexecdir, toolexeclibdir): Set and AC_SUBST. + Remove USE_LIBDIR conditional. + * Makefile.am (toolexecdir, toolexeclibdir): Don't override. + * Makefile.in, configure: Rebuilt. + +Mon Aug 9 18:33:38 1999 Rainer Orth + + * include/Makefile.in: Rebuilt. + * Makefile.in: Rebuilt + * Makefile.am (toolexeclibdir): Add $(MULTISUBDIR) even for native + builds. + Use USE_LIBDIR. + + * configure: Rebuilt. + * configure.in (USE_LIBDIR): Define for native builds. + Use lowercase in configure --help explanations. + +1999-08-08 Anthony Green + + * include/ffi.h.in (FFI_FN): Remove `...'. + +1999-08-08 Anthony Green + + * Makefile.in: Rebuilt. + * Makefile.am (AM_CFLAGS): Compile with -fexceptions. + + * src/x86/sysv.S: Add exception handling metadata. + + +============================================================================= + +The libffi version 1 ChangeLog archive. + +Version 1 of libffi had per-directory ChangeLogs. Current and future +versions have a single ChangeLog file in the root directory. The +version 1 ChangeLogs have all been concatenated into this file for +future reference only. + +--- libffi ---------------------------------------------------------------- + +Mon Oct 5 02:17:50 1998 Anthony Green + + * configure.in: Boosted rev. + * configure, Makefile.in, aclocal.m4: Rebuilt. + * README: Boosted rev and updated release notes. + +Mon Oct 5 01:03:03 1998 Anthony Green + + * configure.in: Boosted rev. + * configure, Makefile.in, aclocal.m4: Rebuilt. + * README: Boosted rev and updated release notes. + +1998-07-25 Andreas Schwab + + * m68k/ffi.c (ffi_prep_cif_machdep): Use bitmask for cif->flags. + Correctly handle small structures. + (ffi_prep_args): Also handle small structures. + (ffi_call): Pass size of return type to ffi_call_SYSV. + * m68k/sysv.S: Adjust for above changes. Correctly align small + structures in the return value. + + * types.c (uint64, sint64) [M68K]: Change alignment to 4. + +Fri Apr 17 17:26:58 1998 Anthony Green + + * configure.in: Boosted rev. + * configure,Makefile.in,aclocal.m4: Rebuilt. + * README: Boosted rev and added release notes. + +Sun Feb 22 00:50:41 1998 Geoff Keating + + * configure.in: Add PowerPC config bits. + +1998-02-14 Andreas Schwab + + * configure.in: Add m68k config bits. Change AC_CANONICAL_SYSTEM + to AC_CANONICAL_HOST, this is not a compiler. Use $host instead + of $target. Remove AC_CHECK_SIZEOF(char), we already know the + result. Fix argument of AC_ARG_ENABLE. + * configure, fficonfig.h.in: Rebuilt. + +Tue Feb 10 20:53:40 1998 Richard Henderson + + * configure.in: Add Alpha config bits. + +Tue May 13 13:39:20 1997 Anthony Green + + * README: Updated dates and reworded Irix comments. + + * configure.in: Removed AC_PROG_RANLIB. + + * Makefile.in, aclocal.m4, config.guess, config.sub, configure, + ltmain.sh, */Makefile.in: libtoolized again and rebuilt with + automake and autoconf. + +Sat May 10 18:44:50 1997 Tom Tromey + + * configure, aclocal.m4: Rebuilt. + * configure.in: Don't compute EXTRADIST; now handled in + src/Makefile.in. Removed macros implied by AM_INIT_AUTOMAKE. + Don't run AM_MAINTAINER_MODE. + +Thu May 8 14:34:05 1997 Anthony Green + + * missing, ltmain.sh, ltconfig.sh: Created. These are new files + required by automake and libtool. + + * README: Boosted rev to 1.14. Added notes. + + * acconfig.h: Moved PACKAGE and VERSION for new automake. + + * configure.in: Changes for libtool. + + * Makefile.am (check): make test now make check. Uses libtool now. + + * Makefile.in, configure.in, aclocal.h, fficonfig.h.in: Rebuilt. + +Thu May 1 16:27:07 1997 Anthony Green + + * missing: Added file required by new automake. + +Tue Nov 26 14:10:42 1996 Anthony Green + + * acconfig.h: Added USING_PURIFY flag. This is defined when + --enable-purify-safety was used at configure time. + + * configure.in (allsources): Added --enable-purify-safety switch. + (VERSION): Boosted rev to 1.13. + * configure: Rebuilt. + +Fri Nov 22 06:46:12 1996 Anthony Green + + * configure.in (VERSION): Boosted rev to 1.12. + Removed special CFLAGS hack for gcc. + * configure: Rebuilt. + + * README: Boosted rev to 1.12. Added notes. + + * Many files: Cygnus Support changed to Cygnus Solutions. + +Wed Oct 30 11:15:25 1996 Anthony Green + + * configure.in (VERSION): Boosted rev to 1.11. + * configure: Rebuilt. + + * README: Boosted rev to 1.11. Added notes about GNU make. + +Tue Oct 29 12:25:12 1996 Anthony Green + + * configure.in: Fixed -Wall trick. + (VERSION): Boosted rev. + * configure: Rebuilt + + * acconfig.h: Needed for --enable-debug configure switch. + + * README: Boosted rev to 1.09. Added more notes on building + libffi, and LCLint. + + * configure.in: Added --enable-debug switch. Boosted rev to + 1.09. + * configure: Rebuilt + +Tue Oct 15 13:11:28 1996 Anthony Green + + * configure.in (VERSION): Boosted rev to 1.08 + * configure: Rebuilt. + + * README: Added n32 bug fix notes. + + * Makefile.am: Added "make lint" production. + * Makefile.in: Rebuilt. + +Mon Oct 14 10:54:46 1996 Anthony Green + + * README: Added web page reference. + + * configure.in, README: Boosted rev to 1.05 + * configure: Rebuilt. + + * README: Fixed n32 sample code. + +Fri Oct 11 17:09:28 1996 Anthony Green + + * README: Added sparc notes. + + * configure.in, README: Boosted rev to 1.04. + * configure: Rebuilt. + +Thu Oct 10 10:31:03 1996 Anthony Green + + * configure.in, README: Boosted rev to 1.03. + * configure: Rebuilt. + + * README: Added struct notes. + + * Makefile.am (EXTRA_DIST): Added LICENSE to distribution. + * Makefile.in: Rebuilt. + + * README: Removed Linux section. No special notes now + because aggregates arg/return types work. + +Wed Oct 9 16:16:42 1996 Anthony Green + + * README, configure.in (VERSION): Boosted rev to 1.02 + * configure: Rebuilt. + +Tue Oct 8 11:56:33 1996 Anthony Green + + * README (NOTE): Added n32 notes. + + * Makefile.am: Added test production. + * Makefile: Rebuilt + + * README: spell checked! + + * configure.in (VERSION): Boosted rev to 1.01 + * configure: Rebuilt. + +Mon Oct 7 15:50:22 1996 Anthony Green + + * configure.in: Added nasty bit to support SGI tools. + * configure: Rebuilt. + + * README: Added SGI notes. Added note about automake bug. + +Mon Oct 7 11:00:28 1996 Anthony Green + + * README: Rewrote intro, and fixed examples. + +Fri Oct 4 10:19:55 1996 Anthony Green + + * configure.in: -D$TARGET is no longer used as a compiler switch. + It is now inserted into ffi.h at configure time. + * configure: Rebuilt. + + * FFI_ABI and FFI_STATUS are now ffi_abi and ffi_status. + +Thu Oct 3 13:47:34 1996 Anthony Green + + * README, LICENSE: Created. Wrote some docs. + + * configure.in: Don't barf on i586-unknown-linuxaout. + Added EXTRADIST code for "make dist". + * configure: Rebuilt. + + * */Makefile.in: Rebuilt with patched automake. + +Tue Oct 1 17:12:25 1996 Anthony Green + + * Makefile.am, aclocal.m4, config.guess, config.sub, + configure.in, fficonfig.h.in, install-sh, mkinstalldirs, + stamp-h.in: Created + * Makefile.in, configure: Generated + +--- libffi/include -------------------------------------------------------- + +Tue Feb 24 13:09:36 1998 Anthony Green + + * ffi_mips.h: Updated FFI_TYPE_STRUCT_* values based on + ffi.h.in changes. This is a work-around for SGI's "simple" + assembler. + +Sun Feb 22 00:51:55 1998 Geoff Keating + + * ffi.h.in: PowerPC support. + +1998-02-14 Andreas Schwab + + * ffi.h.in: Add m68k support. + (FFI_TYPE_LONGDOUBLE): Make it a separate value. + +Tue Feb 10 20:55:16 1998 Richard Henderson + + * ffi.h.in (SIZEOF_ARG): Use a pointer type by default. + + * ffi.h.in: Alpha support. + +Fri Nov 22 06:48:45 1996 Anthony Green + + * ffi.h.in, ffi_common.h: Cygnus Support -> Cygnus Solutions. + +Wed Nov 20 22:31:01 1996 Anthony Green + + * ffi.h.in: Added ffi_type_void definition. + +Tue Oct 29 12:22:40 1996 Anthony Green + + * Makefile.am (hack_DATA): Always install ffi_mips.h. + + * ffi.h.in: Removed FFI_DEBUG. It's now in the correct + place (acconfig.h). + Added #include for size_t definition. + +Tue Oct 15 17:23:35 1996 Anthony Green + + * ffi.h.in, ffi_common.h, ffi_mips.h: More clean up. + Commented out #define of FFI_DEBUG. + +Tue Oct 15 13:01:06 1996 Anthony Green + + * ffi_common.h: Added bool definition. + + * ffi.h.in, ffi_common.h: Clean up based on LCLint output. + Added funny /*@...@*/ comments to annotate source. + +Mon Oct 14 12:29:23 1996 Anthony Green + + * ffi.h.in: Interface changes based on feedback from Jim + Blandy. + +Fri Oct 11 16:49:35 1996 Anthony Green + + * ffi.h.in: Small change for sparc support. + +Thu Oct 10 14:53:37 1996 Anthony Green + + * ffi_mips.h: Added FFI_TYPE_STRUCT_* definitions for + special structure return types. + +Wed Oct 9 13:55:57 1996 Anthony Green + + * ffi.h.in: Added SIZEOF_ARG definition for X86 + +Tue Oct 8 11:40:36 1996 Anthony Green + + * ffi.h.in (FFI_FN): Added macro for eliminating compiler warnings. + Use it to case your function pointers to the proper type. + + * ffi_mips.h (SIZEOF_ARG): Added magic to fix type promotion bug. + + * Makefile.am (EXTRA_DIST): Added ffi_mips.h to EXTRA_DIST. + * Makefile: Rebuilt. + + * ffi_mips.h: Created. Moved all common mips definitions here. + +Mon Oct 7 10:58:12 1996 Anthony Green + + * ffi.h.in: The SGI assember is very picky about parens. Redefined + some macros to avoid problems. + + * ffi.h.in: Added FFI_DEFAULT_ABI definitions. Also added + externs for pointer, and 64bit integral ffi_types. + +Fri Oct 4 09:51:37 1996 Anthony Green + + * ffi.h.in: Added FFI_ABI member to ffi_cif and changed + function prototypes accordingly. + Added #define @TARGET@. Now programs including ffi.h don't + have to specify this themselves. + +Thu Oct 3 15:36:44 1996 Anthony Green + + * ffi.h.in: Changed ffi_prep_cif's values from void* to void** + + * Makefile.am (EXTRA_DIST): Added EXTRA_DIST for "make dist" + to work. + * Makefile.in: Regenerated. + +Wed Oct 2 10:16:59 1996 Anthony Green + + * Makefile.am: Created + * Makefile.in: Generated + + * ffi_common.h: Added rcsid comment + +Tue Oct 1 17:13:51 1996 Anthony Green + + * ffi.h.in, ffi_common.h: Created + +--- libffi/src ------------------------------------------------------------ + +Mon Oct 5 02:17:50 1998 Anthony Green + + * arm/ffi.c, arm/sysv.S: Created. + + * Makefile.am: Added arm files. + * Makefile.in: Rebuilt. + +Mon Oct 5 01:41:38 1998 Anthony Green + + * Makefile.am (libffi_la_LDFLAGS): Incremented revision. + +Sun Oct 4 16:27:17 1998 Anthony Green + + * alpha/osf.S (ffi_call_osf): Patch for DU assembler. + + * ffitest.c (main): long long and long double return values work + for x86. + +Fri Apr 17 11:50:58 1998 Anthony Green + + * Makefile.in: Rebuilt. + + * ffitest.c (main): Floating point tests not executed for systems + with broken lond double (SunOS 4 w/ GCC). + + * types.c: Fixed x86 alignment info for long long types. + +Thu Apr 16 07:15:28 1998 Anthony Green + + * ffitest.c: Added more notes about GCC bugs under Irix 6. + +Wed Apr 15 08:42:22 1998 Anthony Green + + * ffitest.c (struct5): New test function. + (main): New test with struct5. + +Thu Mar 5 10:48:11 1998 Anthony Green + + * prep_cif.c (initialize_aggregate): Fix assertion for + nested structures. + +Tue Feb 24 16:33:41 1998 Anthony Green + + * prep_cif.c (ffi_prep_cif): Added long double support for sparc. + +Sun Feb 22 00:52:18 1998 Geoff Keating + + * powerpc/asm.h: New file. + * powerpc/ffi.c: New file. + * powerpc/sysv.S: New file. + * Makefile.am: PowerPC port. + * ffitest.c (main): Allow all tests to run even in presence of gcc + bug on PowerPC. + +1998-02-17 Anthony Green + + * mips/ffi.c: Fixed comment typo. + + * x86/ffi.c (ffi_prep_cif_machdep), x86/sysv.S (retfloat): + Fixed x86 long double return handling. + + * types.c: Fixed x86 long double alignment info. + +1998-02-14 Andreas Schwab + + * types.c: Add m68k support. + + * ffitest.c (floating): Add long double parameter. + (return_ll, ldblit): New functions to test long long and long + double return value. + (main): Fix type error in assignment of ts[1-4]_type.elements. + Add tests for long long and long double arguments and return + values. + + * prep_cif.c (ffi_prep_cif) [M68K]: Don't allocate argument for + struct value pointer. + + * m68k/ffi.c, m68k/sysv.S: New files. + * Makefile.am: Add bits for m68k port. Add kludge to work around + automake deficiency. + (test): Don't require "." in $PATH. + * Makefile.in: Rebuilt. + +Wed Feb 11 07:36:50 1998 Anthony Green + + * Makefile.in: Rebuilt. + +Tue Feb 10 20:56:00 1998 Richard Henderson + + * alpha/ffi.c, alpha/osf.S: New files. + * Makefile.am: Alpha port. + +Tue Nov 18 14:12:07 1997 Anthony Green + + * mips/ffi.c (ffi_prep_cif_machdep): Initialize rstruct_flag + for n32. + +Tue Jun 3 17:18:20 1997 Anthony Green + + * ffitest.c (main): Added hack to get structure tests working + correctly. + +Sat May 10 19:06:42 1997 Tom Tromey + + * Makefile.in: Rebuilt. + * Makefile.am (EXTRA_DIST): Explicitly list all distributable + files in subdirs. + (VERSION, CC): Removed. + +Thu May 8 17:19:01 1997 Anthony Green + + * Makefile.am: Many changes for new automake and libtool. + * Makefile.in: Rebuilt. + +Fri Nov 22 06:57:56 1996 Anthony Green + + * ffitest.c (main): Fixed test case for non mips machines. + +Wed Nov 20 22:31:59 1996 Anthony Green + + * types.c: Added ffi_type_void declaration. + +Tue Oct 29 13:07:19 1996 Anthony Green + + * ffitest.c (main): Fixed character constants. + (main): Emit warning for structure test 3 failure on Sun. + + * Makefile.am (VPATH): Fixed VPATH def'n so automake won't + strip it out. + Moved distdir hack from libffi to automake. + (ffitest): Added missing -c for $(COMPILE) (change in automake). + * Makefile.in: Rebuilt. + +Tue Oct 15 13:08:20 1996 Anthony Green + + * Makefile.am: Added "make lint" production. + * Makefile.in: Rebuilt. + + * prep_cif.c (STACK_ARG_SIZE): Improved STACK_ARG_SIZE macro. + Clean up based on LCLint output. Added funny /*@...@*/ comments to + annotate source. + + * ffitest.c, debug.c: Cleaned up code. + +Mon Oct 14 12:26:56 1996 Anthony Green + + * ffitest.c: Changes based on interface changes. + + * prep_cif.c (ffi_prep_cif): Cleaned up interface based on + feedback from Jim Blandy. + +Fri Oct 11 15:53:18 1996 Anthony Green + + * ffitest.c: Reordered tests while porting to sparc. + Made changes to handle lame structure passing for sparc. + Removed calls to fflush(). + + * prep_cif.c (ffi_prep_cif): Added special case for sparc + aggregate type arguments. + +Thu Oct 10 09:56:51 1996 Anthony Green + + * ffitest.c (main): Added structure passing/returning tests. + + * prep_cif.c (ffi_prep_cif): Perform proper initialization + of structure return types if needed. + (initialize_aggregate): Bug fix + +Wed Oct 9 16:04:20 1996 Anthony Green + + * types.c: Added special definitions for x86 (double doesn't + need double word alignment). + + * ffitest.c: Added many tests + +Tue Oct 8 09:19:22 1996 Anthony Green + + * prep_cif.c (ffi_prep_cif): Fixed assertion. + + * debug.c (ffi_assert): Must return a non void now. + + * Makefile.am: Added test production. + * Makefile: Rebuilt. + + * ffitest.c (main): Created. + + * types.c: Created. Stripped common code out of */ffi.c. + + * prep_cif.c: Added missing stdlib.h include. + + * debug.c (ffi_type_test): Used "a" to eliminate compiler + warnings in non-debug builds. Included ffi_common.h. + +Mon Oct 7 15:36:42 1996 Anthony Green + + * Makefile.am: Added a rule for .s -> .o + This is required by the SGI compiler. + * Makefile: Rebuilt. + +Fri Oct 4 09:51:08 1996 Anthony Green + + * prep_cif.c (initialize_aggregate): Moved abi specification + to ffi_prep_cif(). + +Thu Oct 3 15:37:37 1996 Anthony Green + + * prep_cif.c (ffi_prep_cif): Changed values from void* to void**. + (initialize_aggregate): Fixed aggregate type initialization. + + * Makefile.am (EXTRA_DIST): Added support code for "make dist". + * Makefile.in: Regenerated. + +Wed Oct 2 11:41:57 1996 Anthony Green + + * debug.c, prep_cif: Created. + + * Makefile.am: Added debug.o and prep_cif.o to OBJ. + * Makefile.in: Regenerated. + + * Makefile.am (INCLUDES): Added missing -I../include + * Makefile.in: Regenerated. + +Tue Oct 1 17:11:51 1996 Anthony Green + + * error.c, Makefile.am: Created. + * Makefile.in: Generated. + +--- libffi/src/x86 -------------------------------------------------------- + +Sun Oct 4 16:27:17 1998 Anthony Green + + * sysv.S (retlongdouble): Fixed long long return value support. + * ffi.c (ffi_prep_cif_machdep): Ditto. + +Wed May 13 04:30:33 1998 Anthony Green + + * ffi.c (ffi_prep_cif_machdep): Fixed long double return value + support. + +Wed Apr 15 08:43:20 1998 Anthony Green + + * ffi.c (ffi_prep_args): small struct support was missing. + +Thu May 8 16:53:58 1997 Anthony Green + + * objects.mak: Removed. + +Mon Dec 2 15:12:58 1996 Tom Tromey + + * sysv.S: Use .balign, for a.out Linux boxes. + +Tue Oct 15 13:06:50 1996 Anthony Green + + * ffi.c: Clean up based on LCLint output. + Added funny /*@...@*/ comments to annotate source. + +Fri Oct 11 16:43:38 1996 Anthony Green + + * ffi.c (ffi_call): Added assertion for bad ABIs. + +Wed Oct 9 13:57:27 1996 Anthony Green + + * sysv.S (retdouble): Fixed double return problems. + + * ffi.c (ffi_call): Corrected fn arg definition. + (ffi_prep_cif_machdep): Fixed double return problems + +Tue Oct 8 12:12:49 1996 Anthony Green + + * ffi.c: Moved ffi_type definitions to types.c. + (ffi_prep_args): Fixed type promotion bug. + +Mon Oct 7 15:53:06 1996 Anthony Green + + * ffi.c (FFI_*_TYPEDEF): Removed redundant ';' + +Fri Oct 4 09:54:53 1996 Anthony Green + + * ffi.c (ffi_call): Removed FFI_ABI arg, and swapped + remaining args. + +Wed Oct 2 10:07:05 1996 Anthony Green + + * ffi.c, sysv.S, objects.mak: Created. + (ffi_prep_cif): cif->rvalue no longer initialized to NULL. + (ffi_prep_cif_machdep): Moved machine independent cif processing + to src/prep_cif.c. Introduced ffi_prep_cif_machdep(). + +--- libffi/src/mips ------------------------------------------------------- + +Tue Feb 17 17:18:07 1998 Anthony Green + + * o32.S: Fixed typo in comment. + + * ffi.c (ffi_prep_cif_machdep): Fixed argument processing. + +Thu May 8 16:53:58 1997 Anthony Green + + * o32.s, n32.s: Wrappers for SGI tool support. + + * objects.mak: Removed. + +Tue Oct 29 14:37:45 1996 Anthony Green + + * ffi.c (ffi_prep_args): Changed int z to size_t z. + +Tue Oct 15 13:17:25 1996 Anthony Green + + * n32.S: Fixed bad stack munging. + + * ffi.c: Moved prototypes for ffi_call_?32() to here from + ffi_mips.h because extended_cif is not defined in ffi_mips.h. + +Mon Oct 14 12:42:02 1996 Anthony Green + + * ffi.c: Interface changes based on feedback from Jim Blandy. + +Thu Oct 10 11:22:16 1996 Anthony Green + + * n32.S, ffi.c: Lots of changes to support passing and + returning structures with the n32 calling convention. + + * n32.S: Fixed fn pointer bug. + + * ffi.c (ffi_prep_cif_machdep): Fix for o32 structure + return values. + (ffi_prep_args): Fixed n32 structure passing when structures + partially fit in registers. + +Wed Oct 9 13:49:25 1996 Anthony Green + + * objects.mak: Added n32.o. + + * n32.S: Created. + + * ffi.c (ffi_prep_args): Added magic to support proper + n32 processing. + +Tue Oct 8 10:37:35 1996 Anthony Green + + * ffi.c: Moved ffi_type definitions to types.c. + (ffi_prep_args): Fixed type promotion bug. + + * o32.S: This code is only built for o32 compiles. + A lot of the #define cruft has moved to ffi_mips.h. + + * ffi.c (ffi_prep_cif_machdep): Fixed arg flags. Second arg + is only processed if the first is either a float or double. + +Mon Oct 7 15:33:59 1996 Anthony Green + + * o32.S: Modified to compile under each of o32, n32 and n64. + + * ffi.c (FFI_*_TYPEDEF): Removed redundant ';' + +Fri Oct 4 09:53:25 1996 Anthony Green + + * ffi.c (ffi_call): Removed FFI_ABI arg, and swapped + remaining args. + +Wed Oct 2 17:41:22 1996 Anthony Green + + * o32.S: Removed crufty definitions. + +Wed Oct 2 12:53:42 1996 Anthony Green + + * ffi.c (ffi_prep_cif): cif->rvalue no longer initialized to NULL. + (ffi_prep_cif_machdep): Moved all machine independent cif processing + to src/prep_cif.c. Introduced ffi_prep_cif_machdep. Return types + of FFI_TYPE_STRUCT are no different than FFI_TYPE_INT. + +Tue Oct 1 17:11:02 1996 Anthony Green + + * ffi.c, o32.S, object.mak: Created + +--- libffi/src/sparc ------------------------------------------------------ + +Tue Feb 24 16:33:18 1998 Anthony Green + + * ffi.c (ffi_prep_args): Added long double support. + +Thu May 8 16:53:58 1997 Anthony Green + + * objects.mak: Removed. + +Thu May 1 16:07:56 1997 Anthony Green + + * v8.S: Fixed minor portability problem reported by + Russ McManus . + +Tue Nov 26 14:12:43 1996 Anthony Green + + * v8.S: Used STACKFRAME define elsewhere. + + * ffi.c (ffi_prep_args): Zero out space when USING_PURIFY + is set. + (ffi_prep_cif_machdep): Allocate the correct stack frame + space for functions with < 6 args. + +Tue Oct 29 15:08:55 1996 Anthony Green + + * ffi.c (ffi_prep_args): int z is now size_t z. + +Mon Oct 14 13:31:24 1996 Anthony Green + + * v8.S (ffi_call_V8): Gordon rewrites this again. It looks + great now. + + * ffi.c (ffi_call): The comment about hijacked registers + is no longer valid after gordoni hacked v8.S. + + * v8.S (ffi_call_V8): Rewrote with gordoni. Much simpler. + + * v8.S, ffi.c: ffi_call() had changed to accept more than + two args, so v8.S had to change (because it hijacks incoming + arg registers). + + * ffi.c: Interface changes based on feedback from Jim Blandy. + +Thu Oct 10 17:48:16 1996 Anthony Green + + * ffi.c, v8.S, objects.mak: Created. + + diff --git a/native/libffi/LICENSE b/native/libffi/LICENSE index a66fab4f25..c2fd979bde 100644 --- a/native/libffi/LICENSE +++ b/native/libffi/LICENSE @@ -1,4 +1,8 @@ +<<<<<<< HEAD libffi - Copyright (c) 1996-2014 Anthony Green, Red Hat, Inc and others. +======= +libffi - Copyright (c) 1996-2020 Anthony Green, Red Hat, Inc and others. +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 See source files for details. Permission is hereby granted, free of charge, to any person obtaining diff --git a/native/libffi/LICENSE-BUILDTOOLS b/native/libffi/LICENSE-BUILDTOOLS new file mode 100644 index 0000000000..d1d626e008 --- /dev/null +++ b/native/libffi/LICENSE-BUILDTOOLS @@ -0,0 +1,353 @@ +The libffi source distribution contains certain code that is not part +of libffi, and is only used as tooling to assist with the building and +testing of libffi. This includes the msvcc.sh script used to wrap the +Microsoft compiler with GNU compatible command-line options, +make_sunver.pl, and the libffi test code distributed in the +testsuite/libffi.bhaible directory. This code is distributed with +libffi for the purpose of convenience only, and libffi is in no way +derived from this code. + +msvcc.sh an testsuite/libffi.bhaible are both distributed under the +terms of the GNU GPL version 2, as below. + + + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/native/libffi/Makefile.am b/native/libffi/Makefile.am index 0e4045100a..48839d9b13 100644 --- a/native/libffi/Makefile.am +++ b/native/libffi/Makefile.am @@ -5,7 +5,16 @@ AUTOMAKE_OPTIONS = foreign subdir-objects ACLOCAL_AMFLAGS = -I m4 SUBDIRS = include testsuite man +if BUILD_DOCS +## This hack is needed because it doesn't seem possible to make a +## conditional info_TEXINFOS in Automake. At least Automake 1.14 +## either gives errors -- if this attempted in the most +## straightforward way -- or simply unconditionally tries to build the +## info file. +SUBDIRS += doc +endif +<<<<<<< HEAD EXTRA_DIST = LICENSE ChangeLog.v1 ChangeLog.libgcj \ src/aarch64/ffi.c src/aarch64/ffitarget.h src/aarch64/sysv.S \ src/alpha/ffi.c src/alpha/osf.S \ @@ -98,27 +107,107 @@ AM_MAKEFLAGS = \ 'NM=$(NM)' \ 'RANLIB=$(RANLIB)' \ 'DESTDIR=$(DESTDIR)' +======= +EXTRA_DIST = LICENSE ChangeLog.old \ + m4/libtool.m4 m4/lt~obsolete.m4 \ + m4/ltoptions.m4 m4/ltsugar.m4 m4/ltversion.m4 \ + m4/ltversion.m4 src/debug.c msvcc.sh \ + generate-darwin-source-and-headers.py \ + libffi.xcodeproj/project.pbxproj \ + libtool-ldflags libtool-version configure.host README.md \ + libffi.map.in LICENSE-BUILDTOOLS msvc_build make_sunver.pl + +# local.exp is generated by configure +DISTCLEANFILES = local.exp +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 # Subdir rules rely on $(FLAGS_TO_PASS) FLAGS_TO_PASS = $(AM_MAKEFLAGS) MAKEOVERRIDES= +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libffi.pc + toolexeclib_LTLIBRARIES = libffi.la noinst_LTLIBRARIES = libffi_convenience.la libffi_la_SOURCES = src/prep_cif.c src/types.c \ src/raw_api.c src/java_raw_api.c src/closures.c -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = libffi.pc +if FFI_DEBUG +libffi_la_SOURCES += src/debug.c +endif + +noinst_HEADERS = src/aarch64/ffitarget.h src/aarch64/internal.h \ + src/alpha/ffitarget.h src/alpha/internal.h \ + src/arc/ffitarget.h src/arm/ffitarget.h src/arm/internal.h \ + src/avr32/ffitarget.h src/bfin/ffitarget.h \ + src/cris/ffitarget.h src/csky/ffitarget.h src/frv/ffitarget.h \ + src/ia64/ffitarget.h src/ia64/ia64_flags.h \ + src/m32r/ffitarget.h src/m68k/ffitarget.h \ + src/m88k/ffitarget.h src/metag/ffitarget.h \ + src/microblaze/ffitarget.h src/mips/ffitarget.h \ + src/moxie/ffitarget.h src/nios2/ffitarget.h \ + src/or1k/ffitarget.h src/pa/ffitarget.h \ + src/powerpc/ffitarget.h src/powerpc/asm.h \ + src/powerpc/ffi_powerpc.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/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 + +EXTRA_libffi_la_SOURCES = src/aarch64/ffi.c src/aarch64/sysv.S \ + src/aarch64/win64_armasm.S src/alpha/ffi.c src/alpha/osf.S \ + src/arc/ffi.c src/arc/arcompact.S src/arm/ffi.c \ + src/arm/sysv.S src/arm/ffi.c src/arm/sysv_msvc_arm32.S \ + src/avr32/ffi.c src/avr32/sysv.S src/bfin/ffi.c \ + src/bfin/sysv.S src/cris/ffi.c src/cris/sysv.S src/frv/ffi.c \ + src/csky/ffi.c src/csky/sysv.S src/frv/eabi.S src/ia64/ffi.c \ + src/ia64/unix.S src/m32r/ffi.c src/m32r/sysv.S src/m68k/ffi.c \ + src/m68k/sysv.S src/m88k/ffi.c src/m88k/obsd.S \ + src/metag/ffi.c src/metag/sysv.S src/microblaze/ffi.c \ + src/microblaze/sysv.S src/mips/ffi.c src/mips/o32.S \ + src/mips/n32.S src/moxie/ffi.c src/moxie/eabi.S \ + src/nios2/ffi.c src/nios2/sysv.S src/or1k/ffi.c \ + src/or1k/sysv.S src/pa/ffi.c src/pa/linux.S src/pa/hpux32.S \ + src/powerpc/ffi.c src/powerpc/ffi_sysv.c \ + src/powerpc/ffi_linux64.c src/powerpc/sysv.S \ + src/powerpc/linux64.S src/powerpc/linux64_closure.S \ + src/powerpc/ppc_closure.S src/powerpc/aix.S \ + src/powerpc/darwin.S src/powerpc/aix_closure.S \ + src/powerpc/darwin_closure.S src/powerpc/ffi_darwin.c \ + src/riscv/ffi.c src/riscv/sysv.S src/s390/ffi.c \ + src/s390/sysv.S src/sh/ffi.c src/sh/sysv.S src/sh64/ffi.c \ + 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/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 \ + src/kvx/sysv.S + +TARGET_OBJ = @TARGET_OBJ@ +libffi_la_LIBADD = $(TARGET_OBJ) + +libffi_convenience_la_SOURCES = $(libffi_la_SOURCES) +EXTRA_libffi_convenience_la_SOURCES = $(EXTRA_libffi_la_SOURCES) +libffi_convenience_la_LIBADD = $(libffi_la_LIBADD) +libffi_convenience_la_DEPENDENCIES = $(libffi_la_DEPENDENCIES) +nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES) -nodist_libffi_la_SOURCES = +LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/libtool-ldflags $(LDFLAGS)) +AM_CFLAGS = if FFI_DEBUG -nodist_libffi_la_SOURCES += src/debug.c +# Build debug. Define FFI_DEBUG on the commandline so that, when building with +# MSVC, it can link against the debug CRT. +AM_CFLAGS += -DFFI_DEBUG endif +<<<<<<< HEAD if MIPS nodist_libffi_la_SOURCES += src/mips/ffi.c src/mips/o32.S src/mips/n32.S endif @@ -163,10 +252,24 @@ nodist_libffi_la_SOURCES += src/m88k/ffi.c src/m88k/obsd.S endif if MOXIE nodist_libffi_la_SOURCES += src/moxie/ffi.c src/moxie/eabi.S -endif -if MICROBLAZE -nodist_libffi_la_SOURCES += src/microblaze/ffi.c src/microblaze/sysv.S -endif +======= +if LIBFFI_BUILD_VERSIONED_SHLIB +if LIBFFI_BUILD_VERSIONED_SHLIB_GNU +libffi_version_script = -Wl,--version-script,libffi.map +libffi_version_dep = libffi.map +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 +endif +if LIBFFI_BUILD_VERSIONED_SHLIB_SUN +libffi_version_script = -Wl,-M,libffi.map-sun +libffi_version_dep = libffi.map-sun +libffi.map-sun : libffi.map $(top_srcdir)/make_sunver.pl \ + $(libffi_la_OBJECTS) $(libffi_la_LIBADD) + perl $(top_srcdir)/make_sunver.pl libffi.map \ + `echo $(libffi_la_OBJECTS) $(libffi_la_LIBADD) | \ + sed 's,\([^/ ]*\)\.l\([ao]\),.libs/\1.\2,g'` \ + > $@ || (rm -f $@ ; exit 1) +endif +<<<<<<< HEAD if NIOS2 nodist_libffi_la_SOURCES += src/nios2/sysv.S src/nios2/ffi.c endif @@ -236,10 +339,19 @@ endif if VAX nodist_libffi_la_SOURCES += src/vax/elfbsd.S src/vax/ffi.c endif +======= +else +libffi_version_script = +libffi_version_dep = +endif +libffi_version_info = -version-info `grep -v '^\#' $(srcdir)/libtool-version` +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 -libffi_convenience_la_SOURCES = $(libffi_la_SOURCES) -nodist_libffi_convenience_la_SOURCES = $(nodist_libffi_la_SOURCES) +libffi.map: $(top_srcdir)/libffi.map.in + $(COMPILE) -D$(TARGET) -DGENERATE_LIBFFI_MAP \ + -E -x assembler-with-cpp -o $@ $(top_srcdir)/libffi.map.in +<<<<<<< HEAD LTLDFLAGS = $(shell $(SHELL) $(top_srcdir)/libtool-ldflags $(LDFLAGS)) AM_CFLAGS = @@ -250,9 +362,20 @@ AM_CFLAGS += -DFFI_DEBUG endif libffi_la_LDFLAGS = -no-undefined -version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LTLDFLAGS) $(AM_LTLDFLAGS) +======= +libffi_la_LDFLAGS = -no-undefined $(libffi_version_info) $(libffi_version_script) $(LTLDFLAGS) $(AM_LTLDFLAGS) +libffi_la_DEPENDENCIES = $(libffi_la_LIBADD) $(libffi_version_dep) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 AM_CPPFLAGS = -I. -I$(top_srcdir)/include -Iinclude -I$(top_srcdir)/src AM_CCASFLAGS = $(AM_CPPFLAGS) dist-hook: +<<<<<<< HEAD + if [ -d $(top_srcdir)/.git ] ; then (cd $(top_srcdir); git log --no-decorate) ; else echo 'See git log for history.' ; fi > $(distdir)/ChangeLog +======= + d=`(cd $(distdir); pwd)`; (cd doc; make pdf; cp *.pdf $$d/doc) if [ -d $(top_srcdir)/.git ] ; then (cd $(top_srcdir); git log --no-decorate) ; else echo 'See git log for history.' ; fi > $(distdir)/ChangeLog + s=`awk '/was released on/{ print NR; exit}' $(top_srcdir)/README.md`; tail -n +$$(($$s-1)) $(top_srcdir)/README.md > $(distdir)/README.md + +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 diff --git a/native/libffi/README.md b/native/libffi/README.md new file mode 100644 index 0000000000..4225d85345 --- /dev/null +++ b/native/libffi/README.md @@ -0,0 +1,486 @@ +Status +====== + +[![Build Status](https://travis-ci.org/libffi/libffi.svg?branch=master)](https://travis-ci.org/libffi/libffi) +[![Build status](https://ci.appveyor.com/api/projects/status/8lko9vagbx4w2kxq?svg=true)](https://ci.appveyor.com/project/atgreen/libffi) + +libffi-3.4 was released on TBD. Check the libffi web +page for updates: . + + +What is libffi? +=============== + +Compilers for high level languages generate code that follow certain +conventions. These conventions are necessary, in part, for separate +compilation to work. One such convention is the "calling +convention". The "calling convention" is essentially a set of +assumptions made by the compiler about where function arguments will +be found on entry to a function. A "calling convention" also specifies +where the return value for a function is found. + +Some programs may not know at the time of compilation what arguments +are to be passed to a function. For instance, an interpreter may be +told at run-time about the number and types of arguments used to call +a given function. Libffi can be used in such programs to provide a +bridge from the interpreter program to compiled code. + +The libffi library provides a portable, high level programming +interface to various calling conventions. This allows a programmer to +call any function specified by a call interface description at run +time. + +FFI stands for Foreign Function Interface. A foreign function +interface is the popular name for the interface that allows code +written in one language to call code written in another language. The +libffi library really only provides the lowest, machine dependent +layer of a fully featured foreign function interface. A layer must +exist above libffi that handles type conversions for values passed +between the two languages. + + +Supported Platforms +=================== + +Libffi has been ported to many different platforms. + +At the time of release, the following basic configurations have been +tested: + +| Architecture | Operating System | Compiler | +| --------------- | ---------------- | ----------------------- | +| AArch64 (ARM64) | iOS | Clang | +| AArch64 | Linux | GCC | +| AArch64 | Windows | MSVC | +| Alpha | Linux | GCC | +| Alpha | Tru64 | GCC | +| ARC | Linux | GCC | +| ARM | Linux | GCC | +| ARM | iOS | GCC | +| ARM | Windows | MSVC | +| AVR32 | Linux | GCC | +| Blackfin | uClinux | GCC | +| CSKY | Linux | GCC | +| HPPA | HPUX | GCC | +| KVX | Linux | GCC | +| IA-64 | Linux | GCC | +| M68K | FreeMiNT | GCC | +| M68K | Linux | GCC | +| M68K | RTEMS | GCC | +| M88K | OpenBSD/mvme88k | GCC | +| Meta | Linux | GCC | +| MicroBlaze | Linux | GCC | +| MIPS | IRIX | GCC | +| MIPS | Linux | GCC | +| MIPS | RTEMS | GCC | +| MIPS64 | Linux | GCC | +| Moxie | Bare metal | GCC | +| Nios II | Linux | GCC | +| OpenRISC | Linux | GCC | +| PowerPC 32-bit | AIX | IBM XL C | +| PowerPC 64-bit | AIX | IBM XL C | +| PowerPC | AMIGA | GCC | +| PowerPC | Linux | GCC | +| PowerPC | Mac OSX | GCC | +| PowerPC | FreeBSD | GCC | +| PowerPC 64-bit | FreeBSD | GCC | +| PowerPC 64-bit | Linux ELFv1 | GCC | +| PowerPC 64-bit | Linux ELFv2 | GCC | +| RISC-V 32-bit | Linux | GCC | +| RISC-V 64-bit | Linux | GCC | +| S390 | Linux | GCC | +| S390X | Linux | GCC | +| SPARC | Linux | GCC | +| SPARC | Solaris | GCC | +| SPARC | Solaris | Oracle Solaris Studio C | +| SPARC64 | Linux | GCC | +| SPARC64 | FreeBSD | GCC | +| SPARC64 | Solaris | Oracle Solaris Studio C | +| TILE-Gx/TILEPro | Linux | GCC | +| VAX | OpenBSD/vax | GCC | +| X86 | FreeBSD | GCC | +| X86 | GNU HURD | GCC | +| X86 | Interix | GCC | +| X86 | kFreeBSD | GCC | +| X86 | Linux | GCC | +| X86 | OpenBSD | GCC | +| X86 | OS/2 | GCC | +| X86 | Solaris | GCC | +| X86 | Solaris | Oracle Solaris Studio C | +| X86 | Windows/Cygwin | GCC | +| X86 | Windows/MingW | GCC | +| X86-64 | FreeBSD | GCC | +| X86-64 | Linux | GCC | +| X86-64 | Linux/x32 | GCC | +| X86-64 | OpenBSD | GCC | +| X86-64 | Solaris | Oracle Solaris Studio C | +| X86-64 | Windows/Cygwin | GCC | +| X86-64 | Windows/MingW | GCC | +| X86-64 | Mac OSX | GCC | +| Xtensa | Linux | GCC | + +Please send additional platform test results to +libffi-discuss@sourceware.org. + +Installing libffi +================= + +First you must configure the distribution for your particular +system. Go to the directory you wish to build libffi in and run the +"configure" program found in the root directory of the libffi source +distribution. Note that building libffi requires a C99 compatible +compiler. + +If you're building libffi directly from git hosted sources, configure +won't exist yet; run ./autogen.sh first. This will require that you +install autoconf, automake and libtool. + +You may want to tell configure where to install the libffi library and +header files. To do that, use the ``--prefix`` configure switch. Libffi +will install under /usr/local by default. + +If you want to enable extra run-time debugging checks use the the +``--enable-debug`` configure switch. This is useful when your program dies +mysteriously while using libffi. + +Another useful configure switch is ``--enable-purify-safety``. Using this +will add some extra code which will suppress certain warnings when you +are using Purify with libffi. Only use this switch when using +Purify, as it will slow down the library. + +If you don't want to build documentation, use the ``--disable-docs`` +configure switch. + +It's also possible to build libffi on Windows platforms with +Microsoft's Visual C++ compiler. In this case, use the msvcc.sh +wrapper script during configuration like so: + + path/to/configure CC=path/to/msvcc.sh CXX=path/to/msvcc.sh LD=link CPP="cl -nologo -EP" CPPFLAGS="-DFFI_BUILDING_DLL" + +For 64-bit Windows builds, use ``CC="path/to/msvcc.sh -m64"`` and +``CXX="path/to/msvcc.sh -m64"``. You may also need to specify +``--build`` appropriately. + +It is also possible to build libffi on Windows platforms with the LLVM +project's clang-cl compiler, like below: + + path/to/configure CC="path/to/msvcc.sh -clang-cl" CXX="path/to/msvcc.sh -clang-cl" LD=link CPP="clang-cl -EP" + +When building with MSVC under a MingW environment, you may need to +remove the line in configure that sets 'fix_srcfile_path' to a 'cygpath' +command. ('cygpath' is not present in MingW, and is not required when +using MingW-style paths.) + +To build static library for ARM64 with MSVC using visual studio solution, msvc_build folder have + aarch64/Ffi_staticLib.sln + required header files in aarch64/aarch64_include/ + + +SPARC Solaris builds require the use of the GNU assembler and linker. +Point ``AS`` and ``LD`` environment variables at those tool prior to +configuration. + +For iOS builds, the ``libffi.xcodeproj`` Xcode project is available. + +Configure has many other options. Use ``configure --help`` to see them all. + +Once configure has finished, type "make". Note that you must be using +GNU make. You can ftp GNU make from ftp.gnu.org:/pub/gnu/make . + +To ensure that libffi is working as advertised, type "make check". +This will require that you have DejaGNU installed. + +To install the library and header files, type ``make install``. + + +History +======= + +See the git log for details at http://github.com/libffi/libffi. + + 3.4 TBD + Add support for Alibaba's CSKY architecture. + Add support for Intel Control-flow Enforcement Technology (CET). + Add support for ARM Pointer Authentication (PA). + Fix 32-bit PPC regression. + Fix MIPS soft-float problem. + + 3.3 Nov-23-19 + Add RISC-V support. + New API in support of GO closures. + Add IEEE754 binary128 long double support for 64-bit Power + Default to Microsoft's 64 bit long double ABI with Visual C++. + GNU compiler uses 80 bits (128 in memory) FFI_GNUW64 ABI. + Add Windows on ARM64 (WOA) support. + Add Windows 32-bit ARM support. + Raw java (gcj) API deprecated. + Add pre-built PDF documentation to source distribution. + Many new test cases and bug fixes. + + 3.2.1 Nov-12-14 + Build fix for non-iOS AArch64 targets. + + 3.2 Nov-11-14 + Add C99 Complex Type support (currently only supported on + s390). + Add support for PASCAL and REGISTER calling conventions on x86 + Windows/Linux. + Add OpenRISC and Cygwin-64 support. + Bug fixes. + + 3.1 May-19-14 + Add AArch64 (ARM64) iOS support. + Add Nios II support. + Add m88k and DEC VAX support. + Add support for stdcall, thiscall, and fastcall on non-Windows + 32-bit x86 targets such as Linux. + Various Android, MIPS N32, x86, FreeBSD and UltraSPARC IIi + fixes. + Make the testsuite more robust: eliminate several spurious + failures, and respect the $CC and $CXX environment variables. + Archive off the manually maintained ChangeLog in favor of git + log. + + 3.0.13 Mar-17-13 + Add Meta support. + Add missing Moxie bits. + Fix stack alignment bug on 32-bit x86. + Build fix for m68000 targets. + Build fix for soft-float Power targets. + Fix the install dir location for some platforms when building + with GCC (OS X, Solaris). + Fix Cygwin regression. + + 3.0.12 Feb-11-13 + Add Moxie support. + Add AArch64 support. + Add Blackfin support. + Add TILE-Gx/TILEPro support. + Add MicroBlaze support. + Add Xtensa support. + Add support for PaX enabled kernels with MPROTECT. + Add support for native vendor compilers on + Solaris and AIX. + Work around LLVM/GCC interoperability issue on x86_64. + + 3.0.11 Apr-11-12 + Lots of build fixes. + Add support for variadic functions (ffi_prep_cif_var). + Add Linux/x32 support. + Add thiscall, fastcall and MSVC cdecl support on Windows. + Add Amiga and newer MacOS support. + Add m68k FreeMiNT support. + Integration with iOS' xcode build tools. + Fix Octeon and MC68881 support. + Fix code pessimizations. + + 3.0.10 Aug-23-11 + Add support for Apple's iOS. + Add support for ARM VFP ABI. + Add RTEMS support for MIPS and M68K. + Fix instruction cache clearing problems on + ARM and SPARC. + Fix the N64 build on mips-sgi-irix6.5. + Enable builds with Microsoft's compiler. + Enable x86 builds with Oracle's Solaris compiler. + Fix support for calling code compiled with Oracle's Sparc + Solaris compiler. + Testsuite fixes for Tru64 Unix. + Additional platform support. + + 3.0.9 Dec-31-09 + Add AVR32 and win64 ports. Add ARM softfp support. + Many fixes for AIX, Solaris, HP-UX, *BSD. + Several PowerPC and x86-64 bug fixes. + Build DLL for windows. + + 3.0.8 Dec-19-08 + Add *BSD, BeOS, and PA-Linux support. + + 3.0.7 Nov-11-08 + Fix for ppc FreeBSD. + (thanks to Andreas Tobler) + + 3.0.6 Jul-17-08 + Fix for closures on sh. + Mark the sh/sh64 stack as non-executable. + (both thanks to Kaz Kojima) + + 3.0.5 Apr-3-08 + Fix libffi.pc file. + Fix #define ARM for IcedTea users. + Fix x86 closure bug. + + 3.0.4 Feb-24-08 + Fix x86 OpenBSD configury. + + 3.0.3 Feb-22-08 + Enable x86 OpenBSD thanks to Thomas Heller, and + x86-64 FreeBSD thanks to Björn König and Andreas Tobler. + Clean up test instruction in README. + + 3.0.2 Feb-21-08 + Improved x86 FreeBSD support. + Thanks to Björn König. + + 3.0.1 Feb-15-08 + Fix instruction cache flushing bug on MIPS. + Thanks to David Daney. + + 3.0.0 Feb-15-08 + Many changes, mostly thanks to the GCC project. + Cygnus Solutions is now Red Hat. + + [10 years go by...] + + 1.20 Oct-5-98 + Raffaele Sena produces ARM port. + + 1.19 Oct-5-98 + Fixed x86 long double and long long return support. + m68k bug fixes from Andreas Schwab. + Patch for DU assembler compatibility for the Alpha from Richard + Henderson. + + 1.18 Apr-17-98 + Bug fixes and MIPS configuration changes. + + 1.17 Feb-24-98 + Bug fixes and m68k port from Andreas Schwab. PowerPC port from + Geoffrey Keating. Various bug x86, Sparc and MIPS bug fixes. + + 1.16 Feb-11-98 + Richard Henderson produces Alpha port. + + 1.15 Dec-4-97 + Fixed an n32 ABI bug. New libtool, auto* support. + + 1.14 May-13-97 + libtool is now used to generate shared and static libraries. + Fixed a minor portability problem reported by Russ McManus + . + + 1.13 Dec-2-96 + Added --enable-purify-safety to keep Purify from complaining + about certain low level code. + Sparc fix for calling functions with < 6 args. + Linux x86 a.out fix. + + 1.12 Nov-22-96 + Added missing ffi_type_void, needed for supporting void return + types. Fixed test case for non MIPS machines. Cygnus Support + is now Cygnus Solutions. + + 1.11 Oct-30-96 + Added notes about GNU make. + + 1.10 Oct-29-96 + Added configuration fix for non GNU compilers. + + 1.09 Oct-29-96 + Added --enable-debug configure switch. Clean-ups based on LCLint + feedback. ffi_mips.h is always installed. Many configuration + fixes. Fixed ffitest.c for sparc builds. + + 1.08 Oct-15-96 + Fixed n32 problem. Many clean-ups. + + 1.07 Oct-14-96 + Gordon Irlam rewrites v8.S again. Bug fixes. + + 1.06 Oct-14-96 + Gordon Irlam improved the sparc port. + + 1.05 Oct-14-96 + Interface changes based on feedback. + + 1.04 Oct-11-96 + Sparc port complete (modulo struct passing bug). + + 1.03 Oct-10-96 + Passing struct args, and returning struct values works for + all architectures/calling conventions. Expanded tests. + + 1.02 Oct-9-96 + Added SGI n32 support. Fixed bugs in both o32 and Linux support. + Added "make test". + + 1.01 Oct-8-96 + Fixed float passing bug in mips version. Restructured some + of the code. Builds cleanly with SGI tools. + + 1.00 Oct-7-96 + First release. No public announcement. + +Authors & Credits +================= + +libffi was originally written by Anthony Green . + +The developers of the GNU Compiler Collection project have made +innumerable valuable contributions. See the ChangeLog file for +details. + +Some of the ideas behind libffi were inspired by Gianni Mariani's free +gencall library for Silicon Graphics machines. + +The closure mechanism was designed and implemented by Kresten Krab +Thorup. + +Major processor architecture ports were contributed by the following +developers: + + aarch64 Marcus Shawcroft, James Greenhalgh + alpha Richard Henderson + arc Hackers at Synopsis + arm Raffaele Sena + avr32 Bradley Smith + blackfin Alexandre Keunecke I. de Mendonca + cris Simon Posnjak, Hans-Peter Nilsson + csky Ma Jun, Zhang Wenmeng + frv Anthony Green + ia64 Hans Boehm + m32r Kazuhiro Inaoka + m68k Andreas Schwab + m88k Miod Vallat + metag Hackers at Imagination Technologies + microblaze Nathan Rossi + mips Anthony Green, Casey Marshall + mips64 David Daney + moxie Anthony Green + nios ii Sandra Loosemore + openrisc Sebastian Macke + pa Randolph Chung, Dave Anglin, Andreas Tobler + powerpc Geoffrey Keating, Andreas Tobler, + David Edelsohn, John Hornkvist + powerpc64 Jakub Jelinek + riscv Michael Knyszek, Andrew Waterman, Stef O'Rear + s390 Gerhard Tonn, Ulrich Weigand + sh Kaz Kojima + sh64 Kaz Kojima + sparc Anthony Green, Gordon Irlam + tile-gx/tilepro Walter Lee + vax Miod Vallat + x86 Anthony Green, Jon Beniston + x86-64 Bo Thorsen + xtensa Chris Zankel + +Jesper Skov and Andrew Haley both did more than their fair share of +stepping through the code and tracking down bugs. + +Thanks also to Tom Tromey for bug fixes, documentation and +configuration help. + +Thanks to Jim Blandy, who provided some useful feedback on the libffi +interface. + +Andreas Tobler has done a tremendous amount of work on the testsuite. + +Alex Oliva solved the executable page problem for SElinux. + +The list above is almost certainly incomplete and inaccurate. I'm +happy to make corrections or additions upon request. + +If you have a problem, or have found a bug, please send a note to the +author at green@moxielogic.com, or the project mailing list at +libffi-discuss@sourceware.org. diff --git a/native/libffi/acinclude.m4 b/native/libffi/acinclude.m4 index 3e8f8ba570..1a70efb010 100644 --- a/native/libffi/acinclude.m4 +++ b/native/libffi/acinclude.m4 @@ -90,3 +90,390 @@ if test $ac_cv_func_mmap_anon = yes; then [Define if mmap with MAP_ANON(YMOUS) works.]) fi ]) + +dnl ---------------------------------------------------------------------- +dnl This whole bit snagged from libstdc++-v3, via libatomic. + +dnl +dnl LIBFFI_ENABLE +dnl (FEATURE, DEFAULT, HELP-ARG, HELP-STRING) +dnl (FEATURE, DEFAULT, HELP-ARG, HELP-STRING, permit a|b|c) +dnl (FEATURE, DEFAULT, HELP-ARG, HELP-STRING, SHELL-CODE-HANDLER) +dnl +dnl See docs/html/17_intro/configury.html#enable for documentation. +dnl +m4_define([LIBFFI_ENABLE],[dnl +m4_define([_g_switch],[--enable-$1])dnl +m4_define([_g_help],[AC_HELP_STRING(_g_switch$3,[$4 @<:@default=$2@:>@])])dnl + AC_ARG_ENABLE($1,_g_help, + m4_bmatch([$5], + [^permit ], + [[ + case "$enableval" in + m4_bpatsubst([$5],[permit ])) ;; + *) AC_MSG_ERROR(Unknown argument to enable/disable $1) ;; + dnl Idea for future: generate a URL pointing to + dnl "onlinedocs/configopts.html#whatever" + esac + ]], + [^$], + [[ + case "$enableval" in + yes|no) ;; + *) AC_MSG_ERROR(Argument to enable/disable $1 must be yes or no) ;; + esac + ]], + [[$5]]), + [enable_]m4_bpatsubst([$1],-,_)[=][$2]) +m4_undefine([_g_switch])dnl +m4_undefine([_g_help])dnl +]) + +dnl +dnl If GNU ld is in use, check to see if tricky linker opts can be used. If +dnl the native linker is in use, all variables will be defined to something +dnl safe (like an empty string). +dnl +dnl Defines: +dnl SECTION_LDFLAGS='-Wl,--gc-sections' if possible +dnl OPT_LDFLAGS='-Wl,-O1' if possible +dnl LD (as a side effect of testing) +dnl Sets: +dnl with_gnu_ld +dnl libat_ld_is_gold (possibly) +dnl libat_gnu_ld_version (possibly) +dnl +dnl The last will be a single integer, e.g., version 1.23.45.0.67.89 will +dnl set libat_gnu_ld_version to 12345. Zeros cause problems. +dnl +AC_DEFUN([LIBFFI_CHECK_LINKER_FEATURES], [ + # If we're not using GNU ld, then there's no point in even trying these + # tests. Check for that first. We should have already tested for gld + # by now (in libtool), but require it now just to be safe... + test -z "$SECTION_LDFLAGS" && SECTION_LDFLAGS='' + test -z "$OPT_LDFLAGS" && OPT_LDFLAGS='' + AC_REQUIRE([AC_PROG_LD]) + AC_REQUIRE([AC_PROG_AWK]) + + # The name set by libtool depends on the version of libtool. Shame on us + # for depending on an impl detail, but c'est la vie. Older versions used + # ac_cv_prog_gnu_ld, but now it's lt_cv_prog_gnu_ld, and is copied back on + # top of with_gnu_ld (which is also set by --with-gnu-ld, so that actually + # makes sense). We'll test with_gnu_ld everywhere else, so if that isn't + # set (hence we're using an older libtool), then set it. + if test x${with_gnu_ld+set} != xset; then + if test x${ac_cv_prog_gnu_ld+set} != xset; then + # We got through "ac_require(ac_prog_ld)" and still not set? Huh? + with_gnu_ld=no + else + with_gnu_ld=$ac_cv_prog_gnu_ld + fi + fi + + # Start by getting the version number. I think the libtool test already + # does some of this, but throws away the result. + libat_ld_is_gold=no + if $LD --version 2>/dev/null | grep 'GNU gold'> /dev/null 2>&1; then + libat_ld_is_gold=yes + fi + changequote(,) + ldver=`$LD --version 2>/dev/null | + sed -e 's/GNU gold /GNU ld /;s/GNU ld version /GNU ld /;s/GNU ld ([^)]*) /GNU ld /;s/GNU ld \([0-9.][0-9.]*\).*/\1/; q'` + changequote([,]) + libat_gnu_ld_version=`echo $ldver | \ + $AWK -F. '{ if (NF<3) [$]3=0; print ([$]1*100+[$]2)*100+[$]3 }'` + + # Set --gc-sections. + if test "$with_gnu_ld" = "notbroken"; then + # GNU ld it is! Joy and bunny rabbits! + + # All these tests are for C++; save the language and the compiler flags. + # Need to do this so that g++ won't try to link in libstdc++ + ac_test_CFLAGS="${CFLAGS+set}" + ac_save_CFLAGS="$CFLAGS" + CFLAGS='-x c++ -Wl,--gc-sections' + + # Check for -Wl,--gc-sections + # XXX This test is broken at the moment, as symbols required for linking + # are now in libsupc++ (not built yet). In addition, this test has + # cored on solaris in the past. In addition, --gc-sections doesn't + # really work at the moment (keeps on discarding used sections, first + # .eh_frame and now some of the glibc sections for iconv). + # Bzzzzt. Thanks for playing, maybe next time. + AC_MSG_CHECKING([for ld that supports -Wl,--gc-sections]) + AC_TRY_RUN([ + int main(void) + { + try { throw 1; } + catch (...) { }; + return 0; + } + ], [ac_sectionLDflags=yes],[ac_sectionLDflags=no], [ac_sectionLDflags=yes]) + if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" + else + # this is the suspicious part + CFLAGS='' + fi + if test "$ac_sectionLDflags" = "yes"; then + SECTION_LDFLAGS="-Wl,--gc-sections $SECTION_LDFLAGS" + fi + AC_MSG_RESULT($ac_sectionLDflags) + fi + + # Set linker optimization flags. + if test x"$with_gnu_ld" = x"yes"; then + OPT_LDFLAGS="-Wl,-O1 $OPT_LDFLAGS" + fi + + AC_SUBST(SECTION_LDFLAGS) + AC_SUBST(OPT_LDFLAGS) +]) + + +dnl +dnl If GNU ld is in use, check to see if tricky linker opts can be used. If +dnl the native linker is in use, all variables will be defined to something +dnl safe (like an empty string). +dnl +dnl Defines: +dnl SECTION_LDFLAGS='-Wl,--gc-sections' if possible +dnl OPT_LDFLAGS='-Wl,-O1' if possible +dnl LD (as a side effect of testing) +dnl Sets: +dnl with_gnu_ld +dnl libat_ld_is_gold (possibly) +dnl libat_gnu_ld_version (possibly) +dnl +dnl The last will be a single integer, e.g., version 1.23.45.0.67.89 will +dnl set libat_gnu_ld_version to 12345. Zeros cause problems. +dnl +AC_DEFUN([LIBFFI_CHECK_LINKER_FEATURES], [ + # If we're not using GNU ld, then there's no point in even trying these + # tests. Check for that first. We should have already tested for gld + # by now (in libtool), but require it now just to be safe... + test -z "$SECTION_LDFLAGS" && SECTION_LDFLAGS='' + test -z "$OPT_LDFLAGS" && OPT_LDFLAGS='' + AC_REQUIRE([AC_PROG_LD]) + AC_REQUIRE([AC_PROG_AWK]) + + # The name set by libtool depends on the version of libtool. Shame on us + # for depending on an impl detail, but c'est la vie. Older versions used + # ac_cv_prog_gnu_ld, but now it's lt_cv_prog_gnu_ld, and is copied back on + # top of with_gnu_ld (which is also set by --with-gnu-ld, so that actually + # makes sense). We'll test with_gnu_ld everywhere else, so if that isn't + # set (hence we're using an older libtool), then set it. + if test x${with_gnu_ld+set} != xset; then + if test x${ac_cv_prog_gnu_ld+set} != xset; then + # We got through "ac_require(ac_prog_ld)" and still not set? Huh? + with_gnu_ld=no + else + with_gnu_ld=$ac_cv_prog_gnu_ld + fi + fi + + # Start by getting the version number. I think the libtool test already + # does some of this, but throws away the result. + libat_ld_is_gold=no + if $LD --version 2>/dev/null | grep 'GNU gold'> /dev/null 2>&1; then + libat_ld_is_gold=yes + fi + libat_ld_is_lld=no + if $LD --version 2>/dev/null | grep 'LLD '> /dev/null 2>&1; then + libat_ld_is_lld=yes + fi + changequote(,) + ldver=`$LD --version 2>/dev/null | + sed -e 's/GNU gold /GNU ld /;s/GNU ld version /GNU ld /;s/GNU ld ([^)]*) /GNU ld /;s/GNU ld \([0-9.][0-9.]*\).*/\1/; q'` + changequote([,]) + libat_gnu_ld_version=`echo $ldver | \ + $AWK -F. '{ if (NF<3) [$]3=0; print ([$]1*100+[$]2)*100+[$]3 }'` + + # Set --gc-sections. + if test "$with_gnu_ld" = "notbroken"; then + # GNU ld it is! Joy and bunny rabbits! + + # All these tests are for C++; save the language and the compiler flags. + # Need to do this so that g++ won't try to link in libstdc++ + ac_test_CFLAGS="${CFLAGS+set}" + ac_save_CFLAGS="$CFLAGS" + CFLAGS='-x c++ -Wl,--gc-sections' + + # Check for -Wl,--gc-sections + # XXX This test is broken at the moment, as symbols required for linking + # are now in libsupc++ (not built yet). In addition, this test has + # cored on solaris in the past. In addition, --gc-sections doesn't + # really work at the moment (keeps on discarding used sections, first + # .eh_frame and now some of the glibc sections for iconv). + # Bzzzzt. Thanks for playing, maybe next time. + AC_MSG_CHECKING([for ld that supports -Wl,--gc-sections]) + AC_TRY_RUN([ + int main(void) + { + try { throw 1; } + catch (...) { }; + return 0; + } + ], [ac_sectionLDflags=yes],[ac_sectionLDflags=no], [ac_sectionLDflags=yes]) + if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" + else + # this is the suspicious part + CFLAGS='' + fi + if test "$ac_sectionLDflags" = "yes"; then + SECTION_LDFLAGS="-Wl,--gc-sections $SECTION_LDFLAGS" + fi + AC_MSG_RESULT($ac_sectionLDflags) + fi + + # Set linker optimization flags. + if test x"$with_gnu_ld" = x"yes"; then + OPT_LDFLAGS="-Wl,-O1 $OPT_LDFLAGS" + fi + + AC_SUBST(SECTION_LDFLAGS) + AC_SUBST(OPT_LDFLAGS) +]) + + +dnl +dnl Add version tags to symbols in shared library (or not), additionally +dnl marking other symbols as private/local (or not). +dnl +dnl --enable-symvers=style adds a version script to the linker call when +dnl creating the shared library. The choice of version script is +dnl controlled by 'style'. +dnl --disable-symvers does not. +dnl + Usage: LIBFFI_ENABLE_SYMVERS[(DEFAULT)] +dnl Where DEFAULT is either 'yes' or 'no'. Passing `yes' tries to +dnl choose a default style based on linker characteristics. Passing +dnl 'no' disables versioning. +dnl +AC_DEFUN([LIBFFI_ENABLE_SYMVERS], [ + +LIBFFI_ENABLE(symvers,yes,[=STYLE], + [enables symbol versioning of the shared library], + [permit yes|no|gnu*|sun]) + +# If we never went through the LIBFFI_CHECK_LINKER_FEATURES macro, then we +# don't know enough about $LD to do tricks... +AC_REQUIRE([LIBFFI_CHECK_LINKER_FEATURES]) + +# Turn a 'yes' into a suitable default. +if test x$enable_symvers = xyes ; then + # FIXME The following test is too strict, in theory. + if test $enable_shared = no || test "x$LD" = x; then + enable_symvers=no + else + if test $with_gnu_ld = yes ; then + enable_symvers=gnu + else + case ${target_os} in + # Sun symbol versioning exists since Solaris 2.5. + solaris2.[[5-9]]* | solaris2.1[[0-9]]*) + enable_symvers=sun ;; + *) + enable_symvers=no ;; + esac + fi + fi +fi + +# Check if 'sun' was requested on non-Solaris 2 platforms. +if test x$enable_symvers = xsun ; then + case ${target_os} in + solaris2*) + # All fine. + ;; + *) + # Unlikely to work. + AC_MSG_WARN([=== You have requested Sun symbol versioning, but]) + AC_MSG_WARN([=== you are not targetting Solaris 2.]) + AC_MSG_WARN([=== Symbol versioning will be disabled.]) + enable_symvers=no + ;; + esac +fi + +# Check to see if libgcc_s exists, indicating that shared libgcc is possible. +if test $enable_symvers != no; then + AC_MSG_CHECKING([for shared libgcc]) + ac_save_CFLAGS="$CFLAGS" + CFLAGS=' -lgcc_s' + AC_TRY_LINK(, [return 0;], libat_shared_libgcc=yes, libat_shared_libgcc=no) + CFLAGS="$ac_save_CFLAGS" + if test $libat_shared_libgcc = no; then + cat > conftest.c <&1 >/dev/null \ + | sed -n 's/^.* -lgcc_s\([^ ]*\) .*$/\1/p'` +changequote([,])dnl + rm -f conftest.c conftest.so + if test x${libat_libgcc_s_suffix+set} = xset; then + CFLAGS=" -lgcc_s$libat_libgcc_s_suffix" + AC_TRY_LINK(, [return 0;], libat_shared_libgcc=yes) + CFLAGS="$ac_save_CFLAGS" + fi + fi + AC_MSG_RESULT($libat_shared_libgcc) +fi + +# For GNU ld, we need at least this version. The format is described in +# LIBFFI_CHECK_LINKER_FEATURES above. +libat_min_gnu_ld_version=21400 +# XXXXXXXXXXX libat_gnu_ld_version=21390 + +# Check to see if unspecified "yes" value can win, given results above. +# Change "yes" into either "no" or a style name. +if test $enable_symvers != no && test $libat_shared_libgcc = yes; then + if test $with_gnu_ld = yes; then + if test $libat_gnu_ld_version -ge $libat_min_gnu_ld_version ; then + enable_symvers=gnu + elif test $libat_ld_is_gold = yes ; then + enable_symvers=gnu + elif test $libat_ld_is_lld = yes ; then + enable_symvers=gnu + else + # The right tools, the right setup, but too old. Fallbacks? + AC_MSG_WARN(=== Linker version $libat_gnu_ld_version is too old for) + AC_MSG_WARN(=== full symbol versioning support in this release of GCC.) + AC_MSG_WARN(=== You would need to upgrade your binutils to version) + AC_MSG_WARN(=== $libat_min_gnu_ld_version or later and rebuild GCC.) + if test $libat_gnu_ld_version -ge 21200 ; then + # Globbing fix is present, proper block support is not. + dnl AC_MSG_WARN([=== Dude, you are soooo close. Maybe we can fake it.]) + dnl enable_symvers=??? + AC_MSG_WARN([=== Symbol versioning will be disabled.]) + enable_symvers=no + else + # 2.11 or older. + AC_MSG_WARN([=== Symbol versioning will be disabled.]) + enable_symvers=no + fi + fi + elif test $enable_symvers = sun; then + : All interesting versions of Sun ld support sun style symbol versioning. + else + # just fail for now + AC_MSG_WARN([=== You have requested some kind of symbol versioning, but]) + AC_MSG_WARN([=== either you are not using a supported linker, or you are]) + AC_MSG_WARN([=== not building a shared libgcc_s (which is required).]) + AC_MSG_WARN([=== Symbol versioning will be disabled.]) + enable_symvers=no + fi +fi +if test $enable_symvers = gnu; then + AC_DEFINE(LIBFFI_GNU_SYMBOL_VERSIONING, 1, + [Define to 1 if GNU symbol versioning is used for libatomic.]) +fi + +AM_CONDITIONAL(LIBFFI_BUILD_VERSIONED_SHLIB, test $enable_symvers != no) +AM_CONDITIONAL(LIBFFI_BUILD_VERSIONED_SHLIB_GNU, test $enable_symvers = gnu) +AM_CONDITIONAL(LIBFFI_BUILD_VERSIONED_SHLIB_SUN, test $enable_symvers = sun) +AC_MSG_NOTICE(versioning on shared library symbols is $enable_symvers) +]) diff --git a/native/libffi/autogen.sh b/native/libffi/autogen.sh index 822ff97d88..f32a4c18c9 100755 --- a/native/libffi/autogen.sh +++ b/native/libffi/autogen.sh @@ -1,2 +1,6 @@ #!/bin/sh -exec autoreconf -v -f -i \ No newline at end of file +<<<<<<< HEAD +exec autoreconf -v -f -i +======= +exec autoreconf -v -i +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 diff --git a/native/libffi/config.guess b/native/libffi/config.guess new file mode 100644 index 0000000000..e94095c5fb --- /dev/null +++ b/native/libffi/config.guess @@ -0,0 +1,1687 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright 1992-2020 Free Software Foundation, Inc. + +timestamp='2020-07-12' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). +# +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. +# +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# +# Please send patches to . + + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright 1992-2020 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +tmp= +# shellcheck disable=SC2172 +trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15 + +set_cc_for_build() { + # prevent multiple calls if $tmp is already set + test "$tmp" && return 0 + : "${TMPDIR=/tmp}" + # shellcheck disable=SC2039 + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } + dummy=$tmp/dummy + case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in + ,,) echo "int x;" > "$dummy.c" + for driver in cc gcc c89 c99 ; do + if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then + CC_FOR_BUILD="$driver" + break + fi + done + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; + esac +} + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if test -f /.attbin/uname ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +case "$UNAME_SYSTEM" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + set_cc_for_build + cat <<-EOF > "$dummy.c" + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" + + # If ldd exists, use it to detect musl libc. + if command -v ldd >/dev/null && \ + ldd --version 2>&1 | grep -q ^musl + then + LIBC=musl + fi + ;; +esac + +# Note: order is significant - the case branches are not exclusive. + +case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + "/sbin/$sysctl" 2>/dev/null || \ + "/usr/sbin/$sysctl" 2>/dev/null || \ + echo unknown)` + case "$UNAME_MACHINE_ARCH" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + earmv*) + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` + machine="${arch}${endian}"-unknown + ;; + *) machine="$UNAME_MACHINE_ARCH"-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently (or will in the future) and ABI. + case "$UNAME_MACHINE_ARCH" in + earm*) + os=netbsdelf + ;; + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # Determine ABI tags. + case "$UNAME_MACHINE_ARCH" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "$UNAME_VERSION" in + Debian*) + release='-gnu' + ;; + *) + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "$machine-${os}${release}${abi-}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" + exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" + exit ;; + *:MidnightBSD:*:*) + echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" + exit ;; + *:ekkoBSD:*:*) + echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" + exit ;; + *:SolidBSD:*:*) + echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" + exit ;; + *:OS108:*:*) + echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE" + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd"$UNAME_RELEASE" + exit ;; + *:MirBSD:*:*) + echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" + exit ;; + *:Sortix:*:*) + echo "$UNAME_MACHINE"-unknown-sortix + exit ;; + *:Twizzler:*:*) + echo "$UNAME_MACHINE"-unknown-twizzler + exit ;; + *:Redox:*:*) + echo "$UNAME_MACHINE"-unknown-redox + exit ;; + mips:OSF1:*.*) + echo mips-dec-osf1 + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE=alpha ;; + "EV4.5 (21064)") + UNAME_MACHINE=alpha ;; + "LCA4 (21066/21068)") + UNAME_MACHINE=alpha ;; + "EV5 (21164)") + UNAME_MACHINE=alphaev5 ;; + "EV5.6 (21164A)") + UNAME_MACHINE=alphaev56 ;; + "EV5.6 (21164PC)") + UNAME_MACHINE=alphapca56 ;; + "EV5.7 (21164PC)") + UNAME_MACHINE=alphapca57 ;; + "EV6 (21264)") + UNAME_MACHINE=alphaev6 ;; + "EV6.7 (21264A)") + UNAME_MACHINE=alphaev67 ;; + "EV6.8CB (21264C)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8AL (21264B)") + UNAME_MACHINE=alphaev68 ;; + "EV6.8CX (21264D)") + UNAME_MACHINE=alphaev68 ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE=alphaev69 ;; + "EV7 (21364)") + UNAME_MACHINE=alphaev7 ;; + "EV7.9 (21364A)") + UNAME_MACHINE=alphaev79 ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo "$UNAME_MACHINE"-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo "$UNAME_MACHINE"-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix"$UNAME_RELEASE" + exit ;; + arm*:riscos:*:*|arm*:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux"$UNAME_RELEASE" + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + set_cc_for_build + SUN_ARCH=i386 + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH=x86_64 + fi + fi + echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos"$UNAME_RELEASE" + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos"$UNAME_RELEASE" + ;; + sun4) + echo sparc-sun-sunos"$UNAME_RELEASE" + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos"$UNAME_RELEASE" + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint"$UNAME_RELEASE" + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint"$UNAME_RELEASE" + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint"$UNAME_RELEASE" + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten"$UNAME_RELEASE" + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten"$UNAME_RELEASE" + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix"$UNAME_RELEASE" + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix"$UNAME_RELEASE" + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix"$UNAME_RELEASE" + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos"$UNAME_RELEASE" + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] + then + if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ + [ "$TARGET_BINARY_INTERFACE"x = x ] + then + echo m88k-dg-dgux"$UNAME_RELEASE" + else + echo m88k-dg-dguxbcs"$UNAME_RELEASE" + fi + else + echo i586-dg-dgux"$UNAME_RELEASE" + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + fi + echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` + else + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" + fi + echo "$IBM_ARCH"-ibm-aix"$IBM_REV" + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + case "$UNAME_MACHINE" in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "$sc_cpu_version" in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "$sc_kernel_bits" in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "$HP_ARCH" = "" ]; then + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ "$HP_ARCH" = hppa2.0w ] + then + set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH=hppa2.0w + else + HP_ARCH=hppa64 + fi + fi + echo "$HP_ARCH"-hp-hpux"$HPUX_REV" + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux"$HPUX_REV" + exit ;; + 3050*:HI-UX:*:*) + set_cc_for_build + sed 's/^ //' << EOF > "$dummy.c" + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo "$UNAME_MACHINE"-unknown-osf1mk + else + echo "$UNAME_MACHINE"-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi"$UNAME_RELEASE" + exit ;; + *:BSD/OS:*:*) + echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" + exit ;; + arm:FreeBSD:*:*) + UNAME_PROCESSOR=`uname -p` + set_cc_for_build + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabi + else + echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabihf + fi + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case "$UNAME_PROCESSOR" in + amd64) + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; + esac + echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" + exit ;; + i*:CYGWIN*:*) + echo "$UNAME_MACHINE"-pc-cygwin + exit ;; + *:MINGW64*:*) + echo "$UNAME_MACHINE"-pc-mingw64 + exit ;; + *:MINGW*:*) + echo "$UNAME_MACHINE"-pc-mingw32 + exit ;; + *:MSYS*:*) + echo "$UNAME_MACHINE"-pc-msys + exit ;; + i*:PW*:*) + echo "$UNAME_MACHINE"-pc-pw32 + exit ;; + *:Interix*:*) + case "$UNAME_MACHINE" in + x86) + echo i586-pc-interix"$UNAME_RELEASE" + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix"$UNAME_RELEASE" + exit ;; + IA64) + echo ia64-unknown-interix"$UNAME_RELEASE" + exit ;; + esac ;; + i*:UWIN*:*) + echo "$UNAME_MACHINE"-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-pc-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" + exit ;; + *:GNU:*:*) + # the GNU system + echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" + exit ;; + *:Minix:*:*) + echo "$UNAME_MACHINE"-unknown-minix + exit ;; + aarch64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + arm*:Linux:*:*) + set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi + else + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + cris:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + crisv32:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + e2k:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + frv:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + hexagon:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + i*86:Linux:*:*) + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + exit ;; + ia64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + k1om:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + m32r*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + m68*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + set_cc_for_build + IS_GLIBC=0 + test x"${LIBC}" = xgnu && IS_GLIBC=1 + sed 's/^ //' << EOF > "$dummy.c" + #undef CPU + #undef mips + #undef mipsel + #undef mips64 + #undef mips64el + #if ${IS_GLIBC} && defined(_ABI64) + LIBCABI=gnuabi64 + #else + #if ${IS_GLIBC} && defined(_ABIN32) + LIBCABI=gnuabin32 + #else + LIBCABI=${LIBC} + #endif + #endif + + #if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa64r6 + #else + #if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6 + CPU=mipsisa32r6 + #else + #if defined(__mips64) + CPU=mips64 + #else + CPU=mips + #endif + #endif + #endif + + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + MIPS_ENDIAN=el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + MIPS_ENDIAN= + #else + MIPS_ENDIAN= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`" + test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; } + ;; + mips64el:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-"$LIBC" + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-"$LIBC" + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-"$LIBC" + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; + PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; + *) echo hppa-unknown-linux-"$LIBC" ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-"$LIBC" + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-"$LIBC" + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-"$LIBC" + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-"$LIBC" + exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" + exit ;; + sh64*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + sh*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + tile*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + vax:Linux:*:*) + echo "$UNAME_MACHINE"-dec-linux-"$LIBC" + exit ;; + x86_64:Linux:*:*) + set_cc_for_build + LIBCABI=$LIBC + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_X32 >/dev/null + then + LIBCABI="$LIBC"x32 + fi + fi + echo "$UNAME_MACHINE"-pc-linux-"$LIBCABI" + exit ;; + xtensa*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo "$UNAME_MACHINE"-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo "$UNAME_MACHINE"-unknown-stop + exit ;; + i*86:atheos:*:*) + echo "$UNAME_MACHINE"-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo "$UNAME_MACHINE"-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos"$UNAME_RELEASE" + exit ;; + i*86:*DOS:*:*) + echo "$UNAME_MACHINE"-pc-msdosdjgpp + exit ;; + i*86:*:4.*:*) + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" + else + echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}" + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" + else + echo "$UNAME_MACHINE"-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configure will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos"$UNAME_RELEASE" + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos"$UNAME_RELEASE" + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos"$UNAME_RELEASE" + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos"$UNAME_RELEASE" + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv"$UNAME_RELEASE" + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo "$UNAME_MACHINE"-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo "$UNAME_MACHINE"-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux"$UNAME_RELEASE" + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv"$UNAME_RELEASE" + else + echo mips-unknown-sysv"$UNAME_RELEASE" + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux"$UNAME_RELEASE" + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux"$UNAME_RELEASE" + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux"$UNAME_RELEASE" + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux"$UNAME_RELEASE" + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux"$UNAME_RELEASE" + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux"$UNAME_RELEASE" + exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux"$UNAME_RELEASE" + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody"$UNAME_RELEASE" + exit ;; + *:Rhapsody:*:*) + echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" + exit ;; + arm64:Darwin:*:*) + echo aarch64-apple-darwin"$UNAME_RELEASE" + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + if command -v xcode-select > /dev/null 2> /dev/null && \ + ! xcode-select --print-path > /dev/null 2> /dev/null ; then + # Avoid executing cc if there is no toolchain installed as + # cc will be a stub that puts up a graphical alert + # prompting the user to install developer tools. + CC_FOR_BUILD=no_compiler_found + else + set_cc_for_build + fi + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # uname -m returns i386 or x86_64 + UNAME_PROCESSOR=$UNAME_MACHINE + fi + echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = x86; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-*:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSR-*:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSV-*:NONSTOP_KERNEL:*:*) + echo nsv-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk"$UNAME_RELEASE" + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + # shellcheck disable=SC2154 + if test "$cputype" = 386; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo "$UNAME_MACHINE"-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux"$UNAME_RELEASE" + exit ;; + *:DragonFly:*:*) + echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "$UNAME_MACHINE" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" + exit ;; + i*86:rdos:*:*) + echo "$UNAME_MACHINE"-pc-rdos + exit ;; + i*86:AROS:*:*) + echo "$UNAME_MACHINE"-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo "$UNAME_MACHINE"-unknown-esx + exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs + exit ;; + *:Unleashed:*:*) + echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE" + exit ;; +esac + +# No uname command or uname output not recognized. +set_cc_for_build +cat > "$dummy.c" < +#include +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#include +#if defined(_SIZE_T_) || defined(SIGLOST) +#include +#endif +#endif +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); +#endif + +#if defined (vax) +#if !defined (ultrix) +#include +#if defined (BSD) +#if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +#else +#if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#endif +#else + printf ("vax-dec-bsd\n"); exit (0); +#endif +#else +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname un; + uname (&un); + printf ("vax-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif +#endif +#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__) +#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__) +#if defined(_SIZE_T_) || defined(SIGLOST) + struct utsname *un; + uname (&un); + printf ("mips-dec-ultrix%s\n", un.release); exit (0); +#else + printf ("mips-dec-ultrix\n"); exit (0); +#endif +#endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. +test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; } + +echo "$0: unable to guess system type" >&2 + +case "$UNAME_MACHINE:$UNAME_SYSTEM" in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 <&2 <&2 </dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = "$UNAME_MACHINE" +UNAME_RELEASE = "$UNAME_RELEASE" +UNAME_SYSTEM = "$UNAME_SYSTEM" +UNAME_VERSION = "$UNAME_VERSION" +EOF +fi + +exit 1 + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/native/libffi/config.sub b/native/libffi/config.sub new file mode 100644 index 0000000000..14b5150c42 --- /dev/null +++ b/native/libffi/config.sub @@ -0,0 +1,1851 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright 1992-2020 Free Software Foundation, Inc. + +timestamp='2020-08-05' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). + + +# Please send patches to . +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS + +Canonicalize a configuration name. + +Options: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright 1992-2020 Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo "$1" + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Split fields of configuration type +# shellcheck disable=SC2162 +IFS="-" read field1 field2 field3 field4 <&2 + exit 1 + ;; + *-*-*-*) + basic_machine=$field1-$field2 + basic_os=$field3-$field4 + ;; + *-*-*) + # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two + # parts + maybe_os=$field2-$field3 + case $maybe_os in + nto-qnx* | linux-* | uclinux-uclibc* \ + | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \ + | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \ + | storm-chaos* | os2-emx* | rtmk-nova*) + basic_machine=$field1 + basic_os=$maybe_os + ;; + android-linux) + basic_machine=$field1-unknown + basic_os=linux-android + ;; + *) + basic_machine=$field1-$field2 + basic_os=$field3 + ;; + esac + ;; + *-*) + # A lone config we happen to match not fitting any pattern + case $field1-$field2 in + decstation-3100) + basic_machine=mips-dec + basic_os= + ;; + *-*) + # Second component is usually, but not always the OS + case $field2 in + # Prevent following clause from handling this valid os + sun*os*) + basic_machine=$field1 + basic_os=$field2 + ;; + # Manufacturers + dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \ + | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \ + | unicom* | ibm* | next | hp | isi* | apollo | altos* \ + | convergent* | ncr* | news | 32* | 3600* | 3100* \ + | hitachi* | c[123]* | convex* | sun | crds | omron* | dg \ + | ultra | tti* | harris | dolphin | highlevel | gould \ + | cbm | ns | masscomp | apple | axis | knuth | cray \ + | microblaze* | sim | cisco \ + | oki | wec | wrs | winbond) + basic_machine=$field1-$field2 + basic_os= + ;; + *) + basic_machine=$field1 + basic_os=$field2 + ;; + esac + ;; + esac + ;; + *) + # Convert single-component short-hands not valid as part of + # multi-component configurations. + case $field1 in + 386bsd) + basic_machine=i386-pc + basic_os=bsd + ;; + a29khif) + basic_machine=a29k-amd + basic_os=udi + ;; + adobe68k) + basic_machine=m68010-adobe + basic_os=scout + ;; + alliant) + basic_machine=fx80-alliant + basic_os= + ;; + altos | altos3068) + basic_machine=m68k-altos + basic_os= + ;; + am29k) + basic_machine=a29k-none + basic_os=bsd + ;; + amdahl) + basic_machine=580-amdahl + basic_os=sysv + ;; + amiga) + basic_machine=m68k-unknown + basic_os= + ;; + amigaos | amigados) + basic_machine=m68k-unknown + basic_os=amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + basic_os=sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + basic_os=sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + basic_os=bsd + ;; + aros) + basic_machine=i386-pc + basic_os=aros + ;; + aux) + basic_machine=m68k-apple + basic_os=aux + ;; + balance) + basic_machine=ns32k-sequent + basic_os=dynix + ;; + blackfin) + basic_machine=bfin-unknown + basic_os=linux + ;; + cegcc) + basic_machine=arm-unknown + basic_os=cegcc + ;; + convex-c1) + basic_machine=c1-convex + basic_os=bsd + ;; + convex-c2) + basic_machine=c2-convex + basic_os=bsd + ;; + convex-c32) + basic_machine=c32-convex + basic_os=bsd + ;; + convex-c34) + basic_machine=c34-convex + basic_os=bsd + ;; + convex-c38) + basic_machine=c38-convex + basic_os=bsd + ;; + cray) + basic_machine=j90-cray + basic_os=unicos + ;; + crds | unos) + basic_machine=m68k-crds + basic_os= + ;; + da30) + basic_machine=m68k-da30 + basic_os= + ;; + decstation | pmax | pmin | dec3100 | decstatn) + basic_machine=mips-dec + basic_os= + ;; + delta88) + basic_machine=m88k-motorola + basic_os=sysv3 + ;; + dicos) + basic_machine=i686-pc + basic_os=dicos + ;; + djgpp) + basic_machine=i586-pc + basic_os=msdosdjgpp + ;; + ebmon29k) + basic_machine=a29k-amd + basic_os=ebmon + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + basic_os=ose + ;; + gmicro) + basic_machine=tron-gmicro + basic_os=sysv + ;; + go32) + basic_machine=i386-pc + basic_os=go32 + ;; + h8300hms) + basic_machine=h8300-hitachi + basic_os=hms + ;; + h8300xray) + basic_machine=h8300-hitachi + basic_os=xray + ;; + h8500hms) + basic_machine=h8500-hitachi + basic_os=hms + ;; + harris) + basic_machine=m88k-harris + basic_os=sysv3 + ;; + hp300 | hp300hpux) + basic_machine=m68k-hp + basic_os=hpux + ;; + hp300bsd) + basic_machine=m68k-hp + basic_os=bsd + ;; + hppaosf) + basic_machine=hppa1.1-hp + basic_os=osf + ;; + hppro) + basic_machine=hppa1.1-hp + basic_os=proelf + ;; + i386mach) + basic_machine=i386-mach + basic_os=mach + ;; + isi68 | isi) + basic_machine=m68k-isi + basic_os=sysv + ;; + m68knommu) + basic_machine=m68k-unknown + basic_os=linux + ;; + magnum | m3230) + basic_machine=mips-mips + basic_os=sysv + ;; + merlin) + basic_machine=ns32k-utek + basic_os=sysv + ;; + mingw64) + basic_machine=x86_64-pc + basic_os=mingw64 + ;; + mingw32) + basic_machine=i686-pc + basic_os=mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + basic_os=mingw32ce + ;; + monitor) + basic_machine=m68k-rom68k + basic_os=coff + ;; + morphos) + basic_machine=powerpc-unknown + basic_os=morphos + ;; + moxiebox) + basic_machine=moxie-unknown + basic_os=moxiebox + ;; + msdos) + basic_machine=i386-pc + basic_os=msdos + ;; + msys) + basic_machine=i686-pc + basic_os=msys + ;; + mvs) + basic_machine=i370-ibm + basic_os=mvs + ;; + nacl) + basic_machine=le32-unknown + basic_os=nacl + ;; + ncr3000) + basic_machine=i486-ncr + basic_os=sysv4 + ;; + netbsd386) + basic_machine=i386-pc + basic_os=netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + basic_os=linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + basic_os=newsos + ;; + news1000) + basic_machine=m68030-sony + basic_os=newsos + ;; + necv70) + basic_machine=v70-nec + basic_os=sysv + ;; + nh3000) + basic_machine=m68k-harris + basic_os=cxux + ;; + nh[45]000) + basic_machine=m88k-harris + basic_os=cxux + ;; + nindy960) + basic_machine=i960-intel + basic_os=nindy + ;; + mon960) + basic_machine=i960-intel + basic_os=mon960 + ;; + nonstopux) + basic_machine=mips-compaq + basic_os=nonstopux + ;; + os400) + basic_machine=powerpc-ibm + basic_os=os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + basic_os=ose + ;; + os68k) + basic_machine=m68k-none + basic_os=os68k + ;; + paragon) + basic_machine=i860-intel + basic_os=osf + ;; + parisc) + basic_machine=hppa-unknown + basic_os=linux + ;; + psp) + basic_machine=mipsallegrexel-sony + basic_os=psp + ;; + pw32) + basic_machine=i586-unknown + basic_os=pw32 + ;; + rdos | rdos64) + basic_machine=x86_64-pc + basic_os=rdos + ;; + rdos32) + basic_machine=i386-pc + basic_os=rdos + ;; + rom68k) + basic_machine=m68k-rom68k + basic_os=coff + ;; + sa29200) + basic_machine=a29k-amd + basic_os=udi + ;; + sei) + basic_machine=mips-sei + basic_os=seiux + ;; + sequent) + basic_machine=i386-sequent + basic_os= + ;; + sps7) + basic_machine=m68k-bull + basic_os=sysv2 + ;; + st2000) + basic_machine=m68k-tandem + basic_os= + ;; + stratus) + basic_machine=i860-stratus + basic_os=sysv4 + ;; + sun2) + basic_machine=m68000-sun + basic_os= + ;; + sun2os3) + basic_machine=m68000-sun + basic_os=sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + basic_os=sunos4 + ;; + sun3) + basic_machine=m68k-sun + basic_os= + ;; + sun3os3) + basic_machine=m68k-sun + basic_os=sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + basic_os=sunos4 + ;; + sun4) + basic_machine=sparc-sun + basic_os= + ;; + sun4os3) + basic_machine=sparc-sun + basic_os=sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + basic_os=sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + basic_os=solaris2 + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + basic_os= + ;; + sv1) + basic_machine=sv1-cray + basic_os=unicos + ;; + symmetry) + basic_machine=i386-sequent + basic_os=dynix + ;; + t3e) + basic_machine=alphaev5-cray + basic_os=unicos + ;; + t90) + basic_machine=t90-cray + basic_os=unicos + ;; + toad1) + basic_machine=pdp10-xkl + basic_os=tops20 + ;; + tpf) + basic_machine=s390x-ibm + basic_os=tpf + ;; + udi29k) + basic_machine=a29k-amd + basic_os=udi + ;; + ultra3) + basic_machine=a29k-nyu + basic_os=sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + basic_os=none + ;; + vaxv) + basic_machine=vax-dec + basic_os=sysv + ;; + vms) + basic_machine=vax-dec + basic_os=vms + ;; + vsta) + basic_machine=i386-pc + basic_os=vsta + ;; + vxworks960) + basic_machine=i960-wrs + basic_os=vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + basic_os=vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + basic_os=vxworks + ;; + xbox) + basic_machine=i686-pc + basic_os=mingw32 + ;; + ymp) + basic_machine=ymp-cray + basic_os=unicos + ;; + *) + basic_machine=$1 + basic_os= + ;; + esac + ;; +esac + +# Decode 1-component or ad-hoc basic machines +case $basic_machine in + # Here we handle the default manufacturer of certain CPU types. It is in + # some cases the only manufacturer, in others, it is the most popular. + w89k) + cpu=hppa1.1 + vendor=winbond + ;; + op50n) + cpu=hppa1.1 + vendor=oki + ;; + op60c) + cpu=hppa1.1 + vendor=oki + ;; + ibm*) + cpu=i370 + vendor=ibm + ;; + orion105) + cpu=clipper + vendor=highlevel + ;; + mac | mpw | mac-mpw) + cpu=m68k + vendor=apple + ;; + pmac | pmac-mpw) + cpu=powerpc + vendor=apple + ;; + + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + cpu=m68000 + vendor=att + ;; + 3b*) + cpu=we32k + vendor=att + ;; + bluegene*) + cpu=powerpc + vendor=ibm + basic_os=cnk + ;; + decsystem10* | dec10*) + cpu=pdp10 + vendor=dec + basic_os=tops10 + ;; + decsystem20* | dec20*) + cpu=pdp10 + vendor=dec + basic_os=tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + cpu=m68k + vendor=motorola + ;; + dpx2*) + cpu=m68k + vendor=bull + basic_os=sysv3 + ;; + encore | umax | mmax) + cpu=ns32k + vendor=encore + ;; + elxsi) + cpu=elxsi + vendor=elxsi + basic_os=${basic_os:-bsd} + ;; + fx2800) + cpu=i860 + vendor=alliant + ;; + genix) + cpu=ns32k + vendor=ns + ;; + h3050r* | hiux*) + cpu=hppa1.1 + vendor=hitachi + basic_os=hiuxwe2 + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + cpu=m68000 + vendor=hp + ;; + hp9k3[2-9][0-9]) + cpu=m68k + vendor=hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + cpu=hppa1.1 + vendor=hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + cpu=hppa1.1 + vendor=hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + cpu=hppa1.0 + vendor=hp + ;; + i*86v32) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv32 + ;; + i*86v4*) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv4 + ;; + i*86v) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=sysv + ;; + i*86sol2) + cpu=`echo "$1" | sed -e 's/86.*/86/'` + vendor=pc + basic_os=solaris2 + ;; + j90 | j90-cray) + cpu=j90 + vendor=cray + basic_os=${basic_os:-unicos} + ;; + iris | iris4d) + cpu=mips + vendor=sgi + case $basic_os in + irix*) + ;; + *) + basic_os=irix4 + ;; + esac + ;; + miniframe) + cpu=m68000 + vendor=convergent + ;; + *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*) + cpu=m68k + vendor=atari + basic_os=mint + ;; + news-3600 | risc-news) + cpu=mips + vendor=sony + basic_os=newsos + ;; + next | m*-next) + cpu=m68k + vendor=next + case $basic_os in + openstep*) + ;; + nextstep*) + ;; + ns2*) + basic_os=nextstep2 + ;; + *) + basic_os=nextstep3 + ;; + esac + ;; + np1) + cpu=np1 + vendor=gould + ;; + op50n-* | op60c-*) + cpu=hppa1.1 + vendor=oki + basic_os=proelf + ;; + pa-hitachi) + cpu=hppa1.1 + vendor=hitachi + basic_os=hiuxwe2 + ;; + pbd) + cpu=sparc + vendor=tti + ;; + pbb) + cpu=m68k + vendor=tti + ;; + pc532) + cpu=ns32k + vendor=pc532 + ;; + pn) + cpu=pn + vendor=gould + ;; + power) + cpu=power + vendor=ibm + ;; + ps2) + cpu=i386 + vendor=ibm + ;; + rm[46]00) + cpu=mips + vendor=siemens + ;; + rtpc | rtpc-*) + cpu=romp + vendor=ibm + ;; + sde) + cpu=mipsisa32 + vendor=sde + basic_os=${basic_os:-elf} + ;; + simso-wrs) + cpu=sparclite + vendor=wrs + basic_os=vxworks + ;; + tower | tower-32) + cpu=m68k + vendor=ncr + ;; + vpp*|vx|vx-*) + cpu=f301 + vendor=fujitsu + ;; + w65) + cpu=w65 + vendor=wdc + ;; + w89k-*) + cpu=hppa1.1 + vendor=winbond + basic_os=proelf + ;; + none) + cpu=none + vendor=none + ;; + leon|leon[3-9]) + cpu=sparc + vendor=$basic_machine + ;; + leon-*|leon[3-9]-*) + cpu=sparc + vendor=`echo "$basic_machine" | sed 's/-.*//'` + ;; + + *-*) + # shellcheck disable=SC2162 + IFS="-" read cpu vendor <&2 + exit 1 + ;; + esac + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $vendor in + digital*) + vendor=dec + ;; + commodore*) + vendor=cbm + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x$basic_os != x ] +then + +# First recognize some ad-hoc caes, or perhaps split kernel-os, or else just +# set os. +case $basic_os in + gnu/linux*) + kernel=linux + os=`echo $basic_os | sed -e 's|gnu/linux|gnu|'` + ;; + nto-qnx*) + kernel=nto + os=`echo $basic_os | sed -e 's|nto-qnx|qnx|'` + ;; + *-*) + # shellcheck disable=SC2162 + IFS="-" read kernel os <&2 + exit 1 + ;; +esac + +# As a final step for OS-related things, validate the OS-kernel combination +# (given a valid OS), if there is a kernel. +case $kernel-$os in + linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* ) + ;; + -dietlibc* | -newlib* | -musl* | -uclibc* ) + # These are just libc implementations, not actual OSes, and thus + # require a kernel. + echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2 + exit 1 + ;; + kfreebsd*-gnu* | kopensolaris*-gnu*) + ;; + nto-qnx*) + ;; + *-eabi* | *-gnueabi*) + ;; + -*) + # Blank kernel with real OS is always fine. + ;; + *-*) + echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2 + exit 1 + ;; +esac + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +case $vendor in + unknown) + case $cpu-$os in + *-riscix*) + vendor=acorn + ;; + *-sunos*) + vendor=sun + ;; + *-cnk* | *-aix*) + vendor=ibm + ;; + *-beos*) + vendor=be + ;; + *-hpux*) + vendor=hp + ;; + *-mpeix*) + vendor=hp + ;; + *-hiux*) + vendor=hitachi + ;; + *-unos*) + vendor=crds + ;; + *-dgux*) + vendor=dg + ;; + *-luna*) + vendor=omron + ;; + *-genix*) + vendor=ns + ;; + *-clix*) + vendor=intergraph + ;; + *-mvs* | *-opened*) + vendor=ibm + ;; + *-os400*) + vendor=ibm + ;; + s390-* | s390x-*) + vendor=ibm + ;; + *-ptx*) + vendor=sequent + ;; + *-tpf*) + vendor=ibm + ;; + *-vxsim* | *-vxworks* | *-windiss*) + vendor=wrs + ;; + *-aux*) + vendor=apple + ;; + *-hms*) + vendor=hitachi + ;; + *-mpw* | *-macos*) + vendor=apple + ;; + *-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*) + vendor=atari + ;; + *-vos*) + vendor=stratus + ;; + esac + ;; +esac + +echo "$cpu-$vendor-${kernel:+$kernel-}$os" +exit + +# Local variables: +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/native/libffi/configure.ac b/native/libffi/configure.ac index a7bf5eefae..486226eb5c 100644 --- a/native/libffi/configure.ac +++ b/native/libffi/configure.ac @@ -2,7 +2,11 @@ dnl Process this with autoconf to create configure AC_PREREQ(2.68) +<<<<<<< HEAD AC_INIT([libffi], [3.2.1], [http://github.com/atgreen/libffi/issues]) +======= +AC_INIT([libffi], [3.3], [http://github.com/libffi/libffi/issues]) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 AC_CONFIG_HEADERS([fficonfig.h]) AC_CANONICAL_SYSTEM @@ -72,6 +76,7 @@ AM_CONDITIONAL(TESTSUBDIR, test -d $srcdir/testsuite) TARGETDIR="unknown" HAVE_LONG_DOUBLE_VARIANT=0 +<<<<<<< HEAD case "$host" in aarch64*-*-*) TARGET=AARCH64; TARGETDIR=aarch64 @@ -287,16 +292,16 @@ case "$host" in xtensa*-*) TARGET=XTENSA; TARGETDIR=xtensa ;; +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 -esac +. ${srcdir}/configure.host -AC_SUBST(AM_RUNTESTFLAGS) -AC_SUBST(AM_LTLDFLAGS) - -if test $TARGETDIR = unknown; then +if test -n "${UNSUPPORTED}"; then AC_MSG_ERROR(["libffi has not been ported to $host."]) fi +<<<<<<< HEAD AM_CONDITIONAL(MIPS, test x$TARGET = xMIPS) AM_CONDITIONAL(BFIN, test x$TARGET = xBFIN) AM_CONDITIONAL(SPARC, test x$TARGET = xSPARC) @@ -337,6 +342,10 @@ AM_CONDITIONAL(PA64_HPUX, test x$TARGET = xPA64_HPUX) AM_CONDITIONAL(TILE, test x$TARGET = xTILE) AM_CONDITIONAL(VAX, test x$TARGET = xVAX) AM_CONDITIONAL(XTENSA, test x$TARGET = xXTENSA) +======= +AC_SUBST(AM_RUNTESTFLAGS) +AC_SUBST(AM_LTLDFLAGS) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 AC_HEADER_STDC AC_CHECK_FUNCS(memcpy) @@ -367,7 +376,8 @@ AC_C_BIGENDIAN GCC_AS_CFI_PSEUDO_OP -if test x$TARGET = xSPARC; then +case "$TARGET" in + SPARC) AC_CACHE_CHECK([assembler and linker support unaligned pc related relocs], libffi_cv_as_sparc_ua_pcrel, [ save_CFLAGS="$CFLAGS" @@ -396,9 +406,9 @@ if test x$TARGET = xSPARC; then AC_DEFINE(HAVE_AS_REGISTER_PSEUDO_OP, 1, [Define if your assembler supports .register.]) fi -fi + ;; -if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64; then + X86*) AC_CACHE_CHECK([assembler supports pc related relocs], libffi_cv_as_x86_pcrel, [ libffi_cv_as_x86_pcrel=no @@ -411,32 +421,46 @@ if test x$TARGET = xX86 || test x$TARGET = xX86_WIN32 || test x$TARGET = xX86_64 AC_DEFINE(HAVE_AS_X86_PCREL, 1, [Define if your assembler supports PC relative relocs.]) fi + ;; - AC_CACHE_CHECK([assembler .ascii pseudo-op support], - libffi_cv_as_ascii_pseudo_op, [ - libffi_cv_as_ascii_pseudo_op=unknown - # Check if we have .ascii - AC_TRY_COMPILE(,[asm (".ascii \\"string\\"");], - [libffi_cv_as_ascii_pseudo_op=yes], - [libffi_cv_as_ascii_pseudo_op=no]) - ]) - if test "x$libffi_cv_as_ascii_pseudo_op" = xyes; then - AC_DEFINE(HAVE_AS_ASCII_PSEUDO_OP, 1, - [Define if your assembler supports .ascii.]) + S390) + AC_CACHE_CHECK([compiler uses zarch features], + libffi_cv_as_s390_zarch, [ + libffi_cv_as_s390_zarch=no + echo 'void foo(void) { bar(); bar(); }' > conftest.c + if $CC $CFLAGS -S conftest.c > /dev/null 2>&1; then + if grep -q brasl conftest.s; then + libffi_cv_as_s390_zarch=yes + fi + fi + ]) + if test "x$libffi_cv_as_s390_zarch" = xyes; then + AC_DEFINE(HAVE_AS_S390_ZARCH, 1, + [Define if the compiler uses zarch features.]) fi + ;; +esac - AC_CACHE_CHECK([assembler .string pseudo-op support], - libffi_cv_as_string_pseudo_op, [ - libffi_cv_as_string_pseudo_op=unknown - # Check if we have .string - AC_TRY_COMPILE(,[asm (".string \\"string\\"");], - [libffi_cv_as_string_pseudo_op=yes], - [libffi_cv_as_string_pseudo_op=no]) - ]) - if test "x$libffi_cv_as_string_pseudo_op" = xyes; then - AC_DEFINE(HAVE_AS_STRING_PSEUDO_OP, 1, - [Define if your assembler supports .string.]) - fi +AC_CACHE_CHECK([whether compiler supports pointer authentication], + libffi_cv_as_ptrauth, [ + libffi_cv_as_ptrauth=unknown + AC_TRY_COMPILE(,[ +#ifdef __clang__ +# if __has_feature(ptrauth_calls) +# define HAVE_PTRAUTH 1 +# endif +#endif + +#ifndef HAVE_PTRAUTH +# error Pointer authentication not supported +#endif + ], + [libffi_cv_as_ptrauth=yes], + [libffi_cv_as_ptrauth=no]) +]) +if test "x$libffi_cv_as_ptrauth" = xyes; then + AC_DEFINE(HAVE_PTRAUTH, 1, + [Define if your compiler supports pointer authentication.]) fi # On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC. @@ -454,13 +478,13 @@ fi FFI_EXEC_TRAMPOLINE_TABLE=0 case "$target" in - *arm*-apple-darwin*) + *arm*-apple-* | aarch64-apple-*) FFI_EXEC_TRAMPOLINE_TABLE=1 AC_DEFINE(FFI_EXEC_TRAMPOLINE_TABLE, 1, [Cannot use PROT_EXEC on this target, so, we revert to alternative means]) ;; - *-apple-darwin1* | *-*-freebsd* | *-*-kfreebsd* | *-*-openbsd* | *-pc-solaris*) + *-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]) @@ -501,18 +525,16 @@ EOF fi if test "x$GCC" = "xyes"; then + AX_CHECK_COMPILE_FLAG(-fno-lto, libffi_cv_no_lto=-fno-lto) + AC_CACHE_CHECK([whether .eh_frame section should be read-only], libffi_cv_ro_eh_frame, [ - libffi_cv_ro_eh_frame=no + libffi_cv_ro_eh_frame=yes echo 'extern void foo (void); void bar (void) { foo (); foo (); }' > conftest.c - if $CC $CFLAGS -c -fpic -fexceptions -o conftest.o conftest.c > /dev/null 2>&1; then - objdump -h conftest.o > conftest.dump 2>&1 - libffi_eh_frame_line=`grep -n eh_frame conftest.dump | cut -d: -f 1` - libffi_test_line=`expr $libffi_eh_frame_line + 1`p - sed -n $libffi_test_line conftest.dump > conftest.line - if grep READONLY conftest.line > /dev/null; then - libffi_cv_ro_eh_frame=yes - fi + if $CC $CFLAGS -c -fpic -fexceptions $libffi_cv_no_lto -o conftest.o conftest.c > /dev/null 2>&1; then + if readelf -WS conftest.o | grep -q -n 'eh_frame .* WA'; then + libffi_cv_ro_eh_frame=no + fi fi rm -f conftest.* ]) @@ -531,7 +553,7 @@ if test "x$GCC" = "xyes"; then echo 'int __attribute__ ((visibility ("hidden"))) foo (void) { return 1 ; }' > conftest.c libffi_cv_hidden_visibility_attribute=no if AC_TRY_COMMAND(${CC-cc} -Werror -S conftest.c -o conftest.s 1>&AS_MESSAGE_LOG_FD); then - if grep '\.hidden.*foo' conftest.s >/dev/null; then + if egrep '(\.hidden|\.private_extern).*foo' conftest.s >/dev/null; then libffi_cv_hidden_visibility_attribute=yes fi fi @@ -543,10 +565,21 @@ if test "x$GCC" = "xyes"; then fi fi +AC_ARG_ENABLE(docs, + AC_HELP_STRING([--disable-docs], + [Disable building of docs (default: no)]), + [enable_docs=no], + [enable_docs=yes]) +AM_CONDITIONAL(BUILD_DOCS, [test x$enable_docs = xyes]) + AH_BOTTOM([ #ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE #ifdef LIBFFI_ASM +#ifdef __APPLE__ +#define FFI_HIDDEN(name) .private_extern name +#else #define FFI_HIDDEN(name) .hidden name +#endif #else #define FFI_HIDDEN __attribute__ ((visibility ("hidden"))) #endif @@ -562,6 +595,14 @@ AH_BOTTOM([ AC_SUBST(TARGET) AC_SUBST(TARGETDIR) +changequote(<,>) +TARGET_OBJ= +for i in $SOURCES; do + TARGET_OBJ="${TARGET_OBJ} src/${TARGETDIR}/"`echo $i | sed 's/[cS]$/lo/'` +done +changequote([,]) +AC_SUBST(TARGET_OBJ) + AC_SUBST(SHELL) AC_ARG_ENABLE(debug, @@ -590,11 +631,16 @@ AC_ARG_ENABLE(purify-safety, AC_DEFINE(USING_PURIFY, 1, [Define this if you are using Purify and want to suppress spurious messages.]) fi) +AC_ARG_ENABLE(multi-os-directory, +[ --disable-multi-os-directory + disable use of gcc --print-multi-os-directory to change the library installation directory]) + # These variables are only ever used when we cross-build to X86_WIN32. # And we only support this with GCC, so... if test "x$GCC" = "xyes"; then if test -n "$with_cross_host" && test x"$with_cross_host" != x"no"; then +<<<<<<< HEAD toolexecdir="${exec_prefix}"/'$(target_alias)' toolexeclibdir="${toolexecdir}"/lib else @@ -609,17 +655,40 @@ if test "x$GCC" = "xyes"; then AC_SUBST(toolexecdir) else toolexeclibdir="${libdir}" +======= + toolexecdir='${exec_prefix}'/'$(target_alias)' + toolexeclibdir='${toolexecdir}'/lib + else + toolexecdir='${libdir}'/gcc-lib/'$(target_alias)' + toolexeclibdir='${libdir}' + fi + if test x"$enable_multi_os_directory" != x"no"; then + multi_os_directory=`$CC $CFLAGS -print-multi-os-directory` + case $multi_os_directory in + .) ;; # Avoid trailing /. + ../*) toolexeclibdir=$toolexeclibdir/$multi_os_directory ;; + esac + fi + AC_SUBST(toolexecdir) +else + toolexeclibdir='${libdir}' +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 fi AC_SUBST(toolexeclibdir) +# Check linker support. +LIBFFI_ENABLE_SYMVERS + AC_CONFIG_COMMANDS(include, [test -d include || mkdir include]) AC_CONFIG_COMMANDS(src, [ test -d src || mkdir src test -d src/$TARGETDIR || mkdir src/$TARGETDIR ], [TARGETDIR="$TARGETDIR"]) -AC_CONFIG_LINKS(include/ffitarget.h:src/$TARGETDIR/ffitarget.h) - -AC_CONFIG_FILES(include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile libffi.pc) +AC_CONFIG_FILES(include/Makefile include/ffi.h Makefile testsuite/Makefile man/Makefile doc/Makefile libffi.pc) AC_OUTPUT + +# Copy this file instead of using AC_CONFIG_LINK in order to support +# compiling with MSVC, which won't understand cygwin style symlinks. +cp ${srcdir}/src/$TARGETDIR/ffitarget.h include/ffitarget.h diff --git a/native/libffi/configure.host b/native/libffi/configure.host new file mode 100644 index 0000000000..d9623e92f6 --- /dev/null +++ b/native/libffi/configure.host @@ -0,0 +1,326 @@ +# configure.host +# +# This shell script handles all host based configuration for libffi. +# + +# THIS TABLE IS SORTED. KEEP IT THAT WAY. +# Most of the time we can define all the variables all at once... +case "${host}" in + aarch64*-*-cygwin* | aarch64*-*-mingw* | aarch64*-*-win* ) + TARGET=ARM_WIN64; TARGETDIR=aarch64 + if test "${ax_cv_c_compiler_vendor}" = "microsoft"; then + MSVC=1 + fi + ;; + + aarch64*-*-*) + TARGET=AARCH64; TARGETDIR=aarch64 + SOURCES="ffi.c sysv.S" + ;; + + alpha*-*-*) + TARGET=ALPHA; TARGETDIR=alpha; + # Support 128-bit long double, changeable via command-line switch. + HAVE_LONG_DOUBLE='defined(__LONG_DOUBLE_128__)' + SOURCES="ffi.c osf.S" + ;; + + arc*-*-*) + TARGET=ARC; TARGETDIR=arc + SOURCES="ffi.c arcompact.S" + ;; + + arm*-*-cygwin* | arm*-*-mingw* | arm*-*-win* ) + TARGET=ARM_WIN32; TARGETDIR=arm + MSVC=1 + ;; + + arm*-*-*) + TARGET=ARM; TARGETDIR=arm + SOURCES="ffi.c sysv.S" + ;; + + avr32*-*-*) + TARGET=AVR32; TARGETDIR=avr32 + SOURCES="ffi.c sysv.S" + ;; + + bfin*) + TARGET=BFIN; TARGETDIR=bfin + SOURCES="ffi.c sysv.S" + ;; + + cris-*-*) + TARGET=LIBFFI_CRIS; TARGETDIR=cris + SOURCES="ffi.c sysv.S" + ;; + + csky-*-*) + TARGET=CSKY; TARGETDIR=csky + SOURCES="ffi.c sysv.S" + ;; + + frv-*-*) + TARGET=FRV; TARGETDIR=frv + SOURCES="ffi.c eabi.S" + ;; + + hppa*-*-linux* | parisc*-*-linux* | hppa*-*-openbsd*) + TARGET=PA_LINUX; TARGETDIR=pa + SOURCES="ffi.c linux.S" + ;; + hppa*64-*-hpux*) + TARGET=PA64_HPUX; TARGETDIR=pa + ;; + hppa*-*-hpux*) + TARGET=PA_HPUX; TARGETDIR=pa + SOURCES="ffi.c hpux32.S" + ;; + + i?86-*-freebsd* | i?86-*-openbsd*) + TARGET=X86_FREEBSD; TARGETDIR=x86 + ;; + + i?86-*-cygwin* | i?86-*-mingw* | i?86-*-win* | i?86-*-os2* | i?86-*-interix* \ + | x86_64-*-cygwin* | x86_64-*-mingw* | x86_64-*-win* ) + TARGETDIR=x86 + if test $ac_cv_sizeof_size_t = 4; then + TARGET=X86_WIN32 + else + TARGET=X86_WIN64 + fi + if test "${ax_cv_c_compiler_vendor}" = "microsoft"; then + MSVC=1 + fi + # All mingw/cygwin/win32 builds require -no-undefined for sharedlib. + # We must also check with_cross_host to decide if this is a native + # or cross-build and select where to install dlls appropriately. + if test -n "$with_cross_host" && + test x"$with_cross_host" != x"no"; then + AM_LTLDFLAGS='-no-undefined -bindir "$(toolexeclibdir)"'; + else + AM_LTLDFLAGS='-no-undefined -bindir "$(bindir)"'; + fi + ;; + + i?86-*-darwin* | x86_64-*-darwin* | i?86-*-ios | x86_64-*-ios) + TARGETDIR=x86 + if test $ac_cv_sizeof_size_t = 4; then + TARGET=X86_DARWIN + else + TARGET=X86_64 + fi + ;; + + i?86-*-* | x86_64-*-* | amd64-*) + TARGETDIR=x86 + if test $ac_cv_sizeof_size_t = 4; then + case "$host" in + x86_64-*x32|x86_64-x32-*) + TARGET_X32=yes + TARGET=X86_64 + ;; + *) + echo 'int foo (void) { return __x86_64__; }' > conftest.c + if $CC $CFLAGS -Werror -S conftest.c -o conftest.s > /dev/null 2>&1; then + TARGET_X32=yes + TARGET=X86_64 + else + TARGET=X86; + fi + rm -f conftest.* + ;; + esac + else + TARGET=X86_64; + fi + ;; + + ia64*-*-*) + TARGET=IA64; TARGETDIR=ia64 + SOURCES="ffi.c unix.S" + ;; + + kvx-*-*) + TARGET=KVX; TARGETDIR=kvx + SOURCES="ffi.c sysv.S" + ;; + + m32r*-*-*) + TARGET=M32R; TARGETDIR=m32r + SOURCES="ffi.c sysv.S" + ;; + + m68k-*-*) + TARGET=M68K; TARGETDIR=m68k + SOURCES="ffi.c sysv.S" + ;; + + m88k-*-*) + TARGET=M88K; TARGETDIR=m88k + SOURCES="ffi.c obsd.S" + ;; + + microblaze*-*-*) + TARGET=MICROBLAZE; TARGETDIR=microblaze + SOURCES="ffi.c sysv.S" + ;; + + moxie-*-*) + TARGET=MOXIE; TARGETDIR=moxie + SOURCES="ffi.c eabi.S" + ;; + + metag-*-*) + TARGET=METAG; TARGETDIR=metag + SOURCES="ffi.c sysv.S" + ;; + + mips-sgi-irix5.* | mips-sgi-irix6.* | mips*-*-rtems*) + TARGET=MIPS; TARGETDIR=mips + ;; + mips*-*linux* | mips*-*-openbsd* | mips*-*-freebsd*) + # Support 128-bit long double for NewABI. + HAVE_LONG_DOUBLE='defined(__mips64)' + TARGET=MIPS; TARGETDIR=mips + ;; + + nios2*-linux*) + TARGET=NIOS2; TARGETDIR=nios2 + SOURCES="ffi.c sysv.S" + ;; + + or1k*-*-*) + TARGET=OR1K; TARGETDIR=or1k + SOURCES="ffi.c sysv.S" + ;; + + powerpc*-*-linux* | powerpc-*-sysv*) + TARGET=POWERPC; TARGETDIR=powerpc + HAVE_LONG_DOUBLE_VARIANT=1 + ;; + powerpc-*-amigaos*) + TARGET=POWERPC; TARGETDIR=powerpc + ;; + powerpc-*-eabi*) + TARGET=POWERPC; TARGETDIR=powerpc + ;; + powerpc-*-beos*) + TARGET=POWERPC; TARGETDIR=powerpc + ;; + powerpc-*-darwin* | powerpc64-*-darwin*) + TARGET=POWERPC_DARWIN; TARGETDIR=powerpc + ;; + powerpc-*-aix* | rs6000-*-aix*) + TARGET=POWERPC_AIX; TARGETDIR=powerpc + ;; + powerpc-*-freebsd* | powerpc-*-openbsd* | powerpc-*-netbsd*) + TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc + HAVE_LONG_DOUBLE_VARIANT=1 + ;; + powerpcspe-*-freebsd*) + TARGET=POWERPC_FREEBSD; TARGETDIR=powerpc + CFLAGS="$CFLAGS -D__NO_FPRS__" + ;; + powerpc64-*-freebsd* | powerpc64le-*-freebsd*) + TARGET=POWERPC; TARGETDIR=powerpc + ;; + powerpc*-*-rtems*) + TARGET=POWERPC; TARGETDIR=powerpc + ;; + + riscv*-*) + TARGET=RISCV; TARGETDIR=riscv + SOURCES="ffi.c sysv.S" + ;; + + s390-*-* | s390x-*-*) + TARGET=S390; TARGETDIR=s390 + SOURCES="ffi.c sysv.S" + ;; + + sh-*-* | sh[34]*-*-*) + TARGET=SH; TARGETDIR=sh + SOURCES="ffi.c sysv.S" + ;; + sh64-*-* | sh5*-*-*) + TARGET=SH64; TARGETDIR=sh64 + SOURCES="ffi.c sysv.S" + ;; + + sparc*-*-*) + TARGET=SPARC; TARGETDIR=sparc + SOURCES="ffi.c ffi64.c v8.S v9.S" + ;; + + tile*-*) + TARGET=TILE; TARGETDIR=tile + SOURCES="ffi.c tile.S" + ;; + + vax-*-*) + TARGET=VAX; TARGETDIR=vax + SOURCES="ffi.c elfbsd.S" + ;; + + xtensa*-*) + TARGET=XTENSA; TARGETDIR=xtensa + SOURCES="ffi.c sysv.S" + ;; +esac + +# ... but some of the cases above share configury. +case "${TARGET}" in + ARM_WIN32) + SOURCES="ffi.c sysv_msvc_arm32.S" + ;; + ARM_WIN64) + if test "$MSVC" = 1; then + SOURCES="ffi.c win64_armasm.S" + else + SOURCES="ffi.c sysv.S" + fi + ;; + MIPS) + SOURCES="ffi.c o32.S n32.S" + ;; + POWERPC) + SOURCES="ffi.c ffi_sysv.c ffi_linux64.c sysv.S ppc_closure.S" + SOURCES="${SOURCES} linux64.S linux64_closure.S" + ;; + POWERPC_AIX) + SOURCES="ffi_darwin.c aix.S aix_closure.S" + ;; + POWERPC_DARWIN) + SOURCES="ffi_darwin.c darwin.S darwin_closure.S" + ;; + POWERPC_FREEBSD) + SOURCES="ffi.c ffi_sysv.c sysv.S ppc_closure.S" + ;; + X86 | X86_DARWIN | X86_FREEBSD | X86_WIN32) + if test "$MSVC" = 1; then + SOURCES="ffi.c sysv_intel.S" + else + SOURCES="ffi.c sysv.S" + fi + ;; + X86_64) + if test x"$TARGET_X32" = xyes; then + SOURCES="ffi64.c unix64.S" + else + SOURCES="ffi64.c unix64.S ffiw64.c win64.S" + fi + ;; + X86_WIN64) + if test "$MSVC" = 1; then + SOURCES="ffiw64.c win64_intel.S" + else + SOURCES="ffiw64.c win64.S" + fi + ;; +esac + +# If we failed to configure SOURCES, we can't do anything. +if test -z "${SOURCES}"; then + UNSUPPORTED=1 +fi diff --git a/native/libffi/doc/Makefile.am b/native/libffi/doc/Makefile.am new file mode 100644 index 0000000000..43b650aea7 --- /dev/null +++ b/native/libffi/doc/Makefile.am @@ -0,0 +1,3 @@ +## Process this with automake to create Makefile.in + +info_TEXINFOS = libffi.texi diff --git a/native/libffi/doc/libffi.texi b/native/libffi/doc/libffi.texi index b1c9bc367b..f52172fa6d 100644 --- a/native/libffi/doc/libffi.texi +++ b/native/libffi/doc/libffi.texi @@ -1,7 +1,8 @@ \input texinfo @c -*-texinfo-*- @c %**start of header @setfilename libffi.info -@settitle libffi +@include version.texi +@settitle libffi: the portable foreign function interface library @setchapternewpage off @c %**end of header @@ -12,32 +13,43 @@ @syncodeindex pg cp @syncodeindex tp cp -@include version.texi - @copying -This manual is for Libffi, a portable foreign-function interface +This manual is for libffi, a portable foreign function interface library. -Copyright @copyright{} 2008, 2010, 2011 Red Hat, Inc. +Copyright @copyright{} 2008--2019 Anthony Green and Red Hat, Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +``Software''), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: -@quotation -Permission is granted to copy, distribute and/or modify this document -under the terms of the GNU General Public License as published by the -Free Software Foundation; either version 2, or (at your option) any -later version. A copy of the license is included in the -section entitled ``GNU General Public License''. +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -@end quotation @end copying @dircategory Development @direntry -* libffi: (libffi). Portable foreign-function interface library. +* libffi: (libffi). Portable foreign function interface library. @end direntry @titlepage -@title Libffi +@title libffi: a foreign function interface library +@subtitle For Version @value{VERSION} of libffi +@author Anthony Green @page @vskip 0pt plus 1filll @insertcopying @@ -107,6 +119,7 @@ values passed between the two languages. * Multiple ABIs:: Different passing styles on one platform. * The Closure API:: Writing a generic function. * Closure Example:: A closure example. +* Thread Safety:: Thread safety. @end menu @@ -152,16 +165,16 @@ If the function being called is variadic (varargs) then @code{ffi_prep_cif_var} must be used instead of @code{ffi_prep_cif}. @findex ffi_prep_cif_var -@defun ffi_status ffi_prep_cif_var (ffi_cif *@var{cif}, ffi_abi var{abi}, unsigned int @var{nfixedargs}, unsigned int var{ntotalargs}, ffi_type *@var{rtype}, ffi_type **@var{argtypes}) +@defun ffi_status ffi_prep_cif_var (ffi_cif *@var{cif}, ffi_abi @var{abi}, unsigned int @var{nfixedargs}, unsigned int @var{ntotalargs}, ffi_type *@var{rtype}, ffi_type **@var{argtypes}) This initializes @var{cif} according to the given parameters for -a call to a variadic function. In general it's operation is the +a call to a variadic function. In general its operation is the same as for @code{ffi_prep_cif} except that: @var{nfixedargs} is the number of fixed arguments, prior to any variadic arguments. It must be greater than zero. @var{ntotalargs} the total number of arguments, including variadic -and fixed arguments. +and fixed arguments. @var{argtypes} must have this many elements. Note that, different cif's must be prepped for calls to the same function when different numbers of arguments are passed. @@ -172,6 +185,10 @@ Also note that a call to @code{ffi_prep_cif_var} with @end defun +Note that the resulting @code{ffi_cif} holds pointers to all the +@code{ffi_type} objects that were used during initialization. You +must ensure that these type objects have a lifetime at least as long +as that of the @code{ffi_cif}. To call a function using an initialized @code{ffi_cif}, use the @code{ffi_call} function: @@ -189,6 +206,19 @@ bits), and must be suitably aligned; it is the caller's responsibility to ensure this. If @var{cif} declares that the function returns @code{void} (using @code{ffi_type_void}), then @var{rvalue} is ignored. +<<<<<<< HEAD +======= + +In most situations, @samp{libffi} will handle promotion according to +the ABI. However, for historical reasons, there is a special case +with return values that must be handled by your code. In particular, +for integral (not @code{struct}) types that are narrower than the +system register size, the return value will be widened by +@samp{libffi}. @samp{libffi} provides a type, @code{ffi_arg}, that +can be used as the return type. For example, if the CIF was defined +with a return type of @code{char}, @samp{libffi} will try to store a +full @code{ffi_arg} into the return value. +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 @var{avalues} is a vector of @code{void *} pointers that point to the memory locations holding the argument values for a call. If @var{cif} @@ -196,6 +226,13 @@ declares that the function has no arguments (i.e., @var{nargs} was 0), then @var{avalues} is ignored. Note that argument values may be modified by the callee (for instance, structs passed by value); the burden of copying pass-by-value arguments is placed on the caller. + +Note that while the return value must be register-sized, arguments +should exactly match their declared type. For example, if an argument +is a @code{short}, then the entry in @var{avalues} should point to an +object declared as @code{short}; but if the return type is +@code{short}, then @var{rvalue} should point to an object declared as +a larger type -- usually @code{ffi_arg}. @end defun @@ -246,6 +283,8 @@ int main() @menu * Primitive Types:: Built-in types. * Structures:: Structure types. +* Size and Alignment:: Size and alignment of types. +* Arrays Unions Enums:: Arrays, unions, and enumerations. * Type Example:: Structure type example. * Complex:: Complex types. * Complex Type Example:: Complex type example. @@ -370,8 +409,7 @@ when passing to @code{ffi_prep_cif}. @node Structures @subsection Structures -Although @samp{libffi} has no special support for unions or -bit-fields, it is perfectly happy passing structures back and forth. +@samp{libffi} is perfectly happy passing structures back and forth. You must first describe the structure to @samp{libffi} by creating a new @code{ffi_type} object for it. @@ -391,9 +429,166 @@ For a structure, this should be set to @code{FFI_TYPE_STRUCT}. @item ffi_type **elements This is a @samp{NULL}-terminated array of pointers to @code{ffi_type} objects. There is one element per field of the struct. + +Note that @samp{libffi} has no special support for bit-fields. You +must manage these manually. @end table @end deftp +The @code{size} and @code{alignment} fields will be filled in by +@code{ffi_prep_cif} or @code{ffi_prep_cif_var}, as needed. + +@node Size and Alignment +@subsection Size and Alignment + +@code{libffi} will set the @code{size} and @code{alignment} fields of +an @code{ffi_type} object for you. It does so using its knowledge of +the ABI. + +You might expect that you can simply read these fields for a type that +has been laid out by @code{libffi}. However, there are some caveats. + +@itemize @bullet +@item +The size or alignment of some of the built-in types may vary depending +on the chosen ABI. + +@item +The size and alignment of a new structure type will not be set by +@code{libffi} until it has been passed to @code{ffi_prep_cif} or +@code{ffi_get_struct_offsets}. + +@item +A structure type cannot be shared across ABIs. Instead each ABI needs +its own copy of the structure type. +@end itemize + +So, before examining these fields, it is safest to pass the +@code{ffi_type} object to @code{ffi_prep_cif} or +@code{ffi_get_struct_offsets} first. This function will do all the +needed setup. + +@example +ffi_type *desired_type; +ffi_abi desired_abi; +@dots{} +ffi_cif cif; +if (ffi_prep_cif (&cif, desired_abi, 0, desired_type, NULL) == FFI_OK) + @{ + size_t size = desired_type->size; + unsigned short alignment = desired_type->alignment; + @} +@end example + +@code{libffi} also provides a way to get the offsets of the members of +a structure. + +@findex ffi_get_struct_offsets +@defun ffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type, size_t *offsets) +Compute the offset of each element of the given structure type. +@var{abi} is the ABI to use; this is needed because in some cases the +layout depends on the ABI. + +@var{offsets} is an out parameter. The caller is responsible for +providing enough space for all the results to be written -- one +element per element type in @var{struct_type}. If @var{offsets} is +@code{NULL}, then the type will be laid out but not otherwise +modified. This can be useful for accessing the type's size or layout, +as mentioned above. + +This function returns @code{FFI_OK} on success; @code{FFI_BAD_ABI} if +@var{abi} is invalid; or @code{FFI_BAD_TYPEDEF} if @var{struct_type} +is invalid in some way. Note that only @code{FFI_STRUCT} types are +valid here. +@end defun + +@node Arrays Unions Enums +@subsection Arrays, Unions, and Enumerations + +@subsubsection Arrays + +@samp{libffi} does not have direct support for arrays or unions. +However, they can be emulated using structures. + +To emulate an array, simply create an @code{ffi_type} using +@code{FFI_TYPE_STRUCT} with as many members as there are elements in +the array. + +@example +ffi_type array_type; +ffi_type **elements +int i; + +elements = malloc ((n + 1) * sizeof (ffi_type *)); +for (i = 0; i < n; ++i) + elements[i] = array_element_type; +elements[n] = NULL; + +array_type.size = array_type.alignment = 0; +array_type.type = FFI_TYPE_STRUCT; +array_type.elements = elements; +@end example + +Note that arrays cannot be passed or returned by value in C -- +structure types created like this should only be used to refer to +members of real @code{FFI_TYPE_STRUCT} objects. + +However, a phony array type like this will not cause any errors from +@samp{libffi} if you use it as an argument or return type. This may +be confusing. + +@subsubsection Unions + +A union can also be emulated using @code{FFI_TYPE_STRUCT}. In this +case, however, you must make sure that the size and alignment match +the real requirements of the union. + +One simple way to do this is to ensue that each element type is laid +out. Then, give the new structure type a single element; the size of +the largest element; and the largest alignment seen as well. + +This example uses the @code{ffi_prep_cif} trick to ensure that each +element type is laid out. + +@example +ffi_abi desired_abi; +ffi_type union_type; +ffi_type **union_elements; + +int i; +ffi_type element_types[2]; + +element_types[1] = NULL; + +union_type.size = union_type.alignment = 0; +union_type.type = FFI_TYPE_STRUCT; +union_type.elements = element_types; + +for (i = 0; union_elements[i]; ++i) + @{ + ffi_cif cif; + if (ffi_prep_cif (&cif, desired_abi, 0, union_elements[i], NULL) == FFI_OK) + @{ + if (union_elements[i]->size > union_type.size) + @{ + union_type.size = union_elements[i]; + size = union_elements[i]->size; + @} + if (union_elements[i]->alignment > union_type.alignment) + union_type.alignment = union_elements[i]->alignment; + @} + @} +@end example + +@subsubsection Enumerations + +@code{libffi} does not have any special support for C @code{enum}s. +Although any given @code{enum} is implemented using a specific +underlying integral type, exactly which type will be used cannot be +determined by @code{libffi} -- it may depend on the values in the +enumeration or on compiler flags such as @option{-fshort-enums}. +@xref{Structures unions enumerations and bit-fields implementation, , , gcc}, +for more information about how GCC handles enumerations. @node Type Example @subsection Type Example @@ -630,30 +825,47 @@ the closure function: @findex ffi_prep_closure_loc @defun ffi_status ffi_prep_closure_loc (ffi_closure *@var{closure}, ffi_cif *@var{cif}, void (*@var{fun}) (ffi_cif *@var{cif}, void *@var{ret}, void **@var{args}, void *@var{user_data}), void *@var{user_data}, void *@var{codeloc}) -Prepare a closure function. +Prepare a closure function. The arguments to +@code{ffi_prep_closure_loc} are: -@var{closure} is the address of a @code{ffi_closure} object; this is -the writable address returned by @code{ffi_closure_alloc}. +@table @var +@item closure +The address of a @code{ffi_closure} object; this is the writable +address returned by @code{ffi_closure_alloc}. + +@item cif +The @code{ffi_cif} describing the function parameters. Note that this +object, and the types to which it refers, must be kept alive until the +closure itself is freed. -@var{cif} is the @code{ffi_cif} describing the function parameters. +@item user_data +An arbitrary datum that is passed, uninterpreted, to your closure +function. -@var{user_data} is an arbitrary datum that is passed, uninterpreted, -to your closure function. +@item codeloc +The executable address returned by @code{ffi_closure_alloc}. -@var{codeloc} is the executable address returned by -@code{ffi_closure_alloc}. +@item fun +The function which will be called when the closure is invoked. It is +called with the arguments: -@var{fun} is the function which will be called when the closure is -invoked. It is called with the arguments: @table @var @item cif The @code{ffi_cif} passed to @code{ffi_prep_closure_loc}. @item ret A pointer to the memory used for the function's return value. -@var{fun} must fill this, unless the function is declared as returning -@code{void}. -@c FIXME: is this NULL for void-returning functions? + +If the function is declared as returning @code{void}, then this value +is garbage and should not be used. + +Otherwise, @var{fun} must fill the object to which this points, +following the same special promotion behavior as @code{ffi_call}. +That is, in most cases, @var{ret} points to an object of exactly the +size of the type specified when @var{cif} was constructed. However, +integral types narrower than the system register size are widened. In +these cases your program may assume that @var{ret} points to an +@code{ffi_arg} object. @item args A vector of pointers to memory holding the arguments to the function. @@ -662,10 +874,10 @@ A vector of pointers to memory holding the arguments to the function. The same @var{user_data} that was passed to @code{ffi_prep_closure_loc}. @end table +@end table @code{ffi_prep_closure_loc} will return @code{FFI_OK} if everything -went ok, and something else on error. -@c FIXME: what? +went ok, and one of the other @code{ffi_status} values on error. After calling @code{ffi_prep_closure_loc}, you can cast @var{codeloc} to the appropriate pointer-to-function type. @@ -733,6 +945,28 @@ int main() @end example +@node Thread Safety +@section Thread Safety + +@code{libffi} is not completely thread-safe. However, many parts are, +and if you follow some simple rules, you can use it safely in a +multi-threaded program. + +@itemize @bullet +@item +@code{ffi_prep_cif} may modify the @code{ffi_type} objects passed to +it. It is best to ensure that only a single thread prepares a given +@code{ffi_cif} at a time. + +@item +On some platforms, @code{ffi_prep_cif} may modify the size and +alignment of some types, depending on the chosen ABI. On these +platforms, if you switch between ABIs, you must ensure that there is +only one call to @code{ffi_prep_cif} at a time. + +Currently the only affected platform is PowerPC and the only affected +type is @code{long double}. +@end itemize @node Missing Features @chapter Missing Features @@ -747,16 +981,12 @@ Variadic closures. @item There is no support for bit fields in structures. -@item -The closure API is - -@c FIXME: ... - @item The ``raw'' API is undocumented. -@c argument promotion? -@c unions? @c anything else? + +@item +The Go API is undocumented. @end itemize Note that variadic support is very new and tested on a relatively diff --git a/native/libffi/doc/version.texi b/native/libffi/doc/version.texi index ccef70f493..92950d92a8 100644 --- a/native/libffi/doc/version.texi +++ b/native/libffi/doc/version.texi @@ -1,4 +1,11 @@ +<<<<<<< HEAD @set UPDATED 8 November 2014 @set UPDATED-MONTH November 2014 @set EDITION 3.2.1 @set VERSION 3.2.1 +======= +@set UPDATED 22 November 2019 +@set UPDATED-MONTH November 2019 +@set EDITION 3.3 +@set VERSION 3.3 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 diff --git a/native/libffi/generate-darwin-source-and-headers.py b/native/libffi/generate-darwin-source-and-headers.py index 964e861d43..00e9bf0ec3 100644 --- a/native/libffi/generate-darwin-source-and-headers.py +++ b/native/libffi/generate-darwin-source-and-headers.py @@ -14,12 +14,20 @@ class simulator_platform(Platform): sdk = 'iphonesimulator' arch = 'i386' triple = 'i386-apple-darwin11' +<<<<<<< HEAD version_min = '-miphoneos-version-min=5.1.1' +======= + version_min = '-miphoneos-version-min=7.0' +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 prefix = "#ifdef __i386__\n\n" suffix = "\n\n#endif" src_dir = 'x86' +<<<<<<< HEAD src_files = ['darwin.S', 'win32.S', 'ffi.c'] +======= + src_files = ['sysv.S', 'ffi.c', 'internal.h'] +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 class simulator64_platform(Platform): @@ -32,7 +40,11 @@ class simulator64_platform(Platform): prefix = "#ifdef __x86_64__\n\n" suffix = "\n\n#endif" src_dir = 'x86' +<<<<<<< HEAD src_files = ['darwin64.S', 'ffi64.c'] +======= + src_files = ['unix64.S', 'ffi64.c', 'ffiw64.c', 'win64.S', 'internal64.h', 'asmnames.h'] +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 class device_platform(Platform): @@ -40,12 +52,20 @@ class device_platform(Platform): sdk = 'iphoneos' arch = 'armv7' triple = 'arm-apple-darwin11' +<<<<<<< HEAD version_min = '-miphoneos-version-min=5.1.1' +======= + version_min = '-miphoneos-version-min=7.0' +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 prefix = "#ifdef __arm__\n\n" suffix = "\n\n#endif" src_dir = 'arm' +<<<<<<< HEAD src_files = ['sysv.S', 'trampoline.S', 'ffi.c'] +======= + src_files = ['sysv.S', 'ffi.c', 'internal.h'] +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 class device64_platform(Platform): @@ -58,7 +78,11 @@ class device64_platform(Platform): prefix = "#ifdef __arm64__\n\n" suffix = "\n\n#endif" src_dir = 'aarch64' +<<<<<<< HEAD src_files = ['sysv.S', 'ffi.c'] +======= + src_files = ['sysv.S', 'ffi.c', 'internal.h'] +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 class desktop32_platform(Platform): @@ -68,7 +92,11 @@ class desktop32_platform(Platform): triple = 'i386-apple-darwin10' version_min = '-mmacosx-version-min=10.6' src_dir = 'x86' +<<<<<<< HEAD src_files = ['darwin.S', 'win32.S', 'ffi.c'] +======= + src_files = ['sysv.S', 'ffi.c', 'internal.h'] +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 prefix = "#ifdef __i386__\n\n" suffix = "\n\n#endif" @@ -84,16 +112,24 @@ class desktop64_platform(Platform): prefix = "#ifdef __x86_64__\n\n" suffix = "\n\n#endif" src_dir = 'x86' +<<<<<<< HEAD src_files = ['darwin64.S', 'ffi64.c'] +======= + src_files = ['unix64.S', 'ffi64.c', 'ffiw64.c', 'win64.S', 'internal64.h', 'asmnames.h'] +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 def mkdir_p(path): try: os.makedirs(path) except OSError as exc: # Python >2.5 +<<<<<<< HEAD if exc.errno == errno.EEXIST: pass else: +======= + if exc.errno != errno.EEXIST: +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 raise @@ -102,8 +138,16 @@ def move_file(src_dir, dst_dir, filename, file_suffix=None, prefix='', suffix='' out_filename = filename if file_suffix: +<<<<<<< HEAD split_name = os.path.splitext(filename) out_filename = "%s_%s%s" % (split_name[0], file_suffix, split_name[1]) +======= + if filename in ['internal64.h', 'asmnames.h', 'internal.h']: + out_filename = filename + else: + split_name = os.path.splitext(filename) + out_filename = "%s_%s%s" % (split_name[0], file_suffix, split_name[1]) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 with open(os.path.join(src_dir, filename)) as in_file: with open(os.path.join(dst_dir, out_filename), 'w') as out_file: @@ -142,7 +186,11 @@ def xcrun_cmd(cmd): mkdir_p(build_dir) env = dict(CC=xcrun_cmd('clang'), LD=xcrun_cmd('ld'), +<<<<<<< HEAD CFLAGS='%s' % (platform.version_min)) +======= + CFLAGS='%s -fembed-bitcode' % (platform.version_min)) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 working_dir = os.getcwd() try: os.chdir(build_dir) @@ -162,24 +210,33 @@ def xcrun_cmd(cmd): platform_headers[filename].add((platform.prefix, platform.arch, platform.suffix)) +<<<<<<< HEAD def make_tramp(): with open('src/arm/trampoline.S', 'w') as tramp_out: p = subprocess.Popen(['bash', 'src/arm/gentramp.sh'], stdout=tramp_out) p.wait() +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 def generate_source_and_headers(generate_osx=True, generate_ios=True): copy_files('src', 'darwin_common/src', pattern='*.c') copy_files('include', 'darwin_common/include', pattern='*.h') if generate_ios: +<<<<<<< HEAD make_tramp() +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 copy_src_platform_files(simulator_platform) copy_src_platform_files(simulator64_platform) copy_src_platform_files(device_platform) copy_src_platform_files(device64_platform) if generate_osx: +<<<<<<< HEAD copy_src_platform_files(desktop32_platform) +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 copy_src_platform_files(desktop64_platform) platform_headers = collections.defaultdict(set) @@ -190,11 +247,18 @@ def generate_source_and_headers(generate_osx=True, generate_ios=True): build_target(device_platform, platform_headers) build_target(device64_platform, platform_headers) if generate_osx: +<<<<<<< HEAD build_target(desktop32_platform, platform_headers) build_target(desktop64_platform, platform_headers) mkdir_p('darwin_common/include') for header_name, tag_tuples in platform_headers.iteritems(): +======= + build_target(desktop64_platform, platform_headers) + + mkdir_p('darwin_common/include') + for header_name, tag_tuples in platform_headers.items(): +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 basename, suffix = os.path.splitext(header_name) with open(os.path.join('darwin_common/include', header_name), 'w') as header: for tag_tuple in tag_tuples: diff --git a/native/libffi/include/Makefile.am b/native/libffi/include/Makefile.am index fd28024973..c59df9fb3c 100644 --- a/native/libffi/include/Makefile.am +++ b/native/libffi/include/Makefile.am @@ -3,7 +3,7 @@ AUTOMAKE_OPTIONS=foreign DISTCLEANFILES=ffitarget.h -EXTRA_DIST=ffi.h.in ffi_common.h +noinst_HEADERS=ffi_common.h ffi_cfi.h +EXTRA_DIST=ffi.h.in -includesdir = $(libdir)/@PACKAGE_NAME@-@PACKAGE_VERSION@/include -nodist_includes_HEADERS = ffi.h ffitarget.h +nodist_include_HEADERS = ffi.h ffitarget.h diff --git a/native/libffi/include/ffi.h.in b/native/libffi/include/ffi.h.in index f403ae06dd..0960c1a6e7 100644 --- a/native/libffi/include/ffi.h.in +++ b/native/libffi/include/ffi.h.in @@ -1,5 +1,9 @@ /* -----------------------------------------------------------------*-C-*- +<<<<<<< HEAD libffi @VERSION@ - Copyright (c) 2011, 2014 Anthony Green +======= + libffi @VERSION@ - Copyright (c) 2011, 2014, 2019 Anthony Green +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc. Permission is hereby granted, free of charge, to any person @@ -25,23 +29,14 @@ ----------------------------------------------------------------------- */ /* ------------------------------------------------------------------- - The basic API is described in the README file. + Most of the API is documented in doc/libffi.texi. - The raw API is designed to bypass some of the argument packing - and unpacking on architectures for which it can be avoided. + The raw API is designed to bypass some of the argument packing and + unpacking on architectures for which it can be avoided. Routines + are provided to emulate the raw API if the underlying platform + doesn't allow faster implementation. - The closure API allows interpreted functions to be packaged up - inside a C function pointer, so that they can be called as C functions, - with no understanding on the client side that they are interpreted. - It can also be used in other cases in which it is necessary to package - up a user specified parameter and a function pointer as a single - function pointer. - - The closure API must be implemented in order to get its functionality, - e.g. for use by gij. Routines are provided to emulate the raw API - if the underlying platform doesn't allow faster implementation. - - More details on the raw and cloure API can be found in: + More details on the raw API can be found in: http://gcc.gnu.org/ml/java/1999-q3/msg00138.html @@ -106,8 +101,8 @@ extern "C" { # endif #endif -/* The closure code assumes that this works on pointers, i.e. a size_t */ -/* can hold a pointer. */ +/* The closure code assumes that this works on pointers, i.e. a size_t + can hold a pointer. */ typedef struct _ffi_type { @@ -117,6 +112,32 @@ typedef struct _ffi_type struct _ffi_type **elements; } ffi_type; +/* Need minimal decorations for DLLs to work on Windows. GCC has + autoimport and autoexport. Always mark externally visible symbols + as dllimport for MSVC clients, even if it means an extra indirection + when using the static version of the library. + Besides, as a workaround, they can define FFI_BUILDING if they + *know* they are going to link with the static library. */ +#if defined _MSC_VER +# if defined FFI_BUILDING_DLL /* Building libffi.DLL with msvcc.sh */ +# define FFI_API __declspec(dllexport) +# elif !defined FFI_BUILDING /* Importing libffi.DLL */ +# define FFI_API __declspec(dllimport) +# else /* Building/linking static library */ +# define FFI_API +# endif +#else +# define FFI_API +#endif + +/* The externally visible type declarations also need the MSVC DLL + decorations, or they will not be exported from the object file. */ +#if defined LIBFFI_HIDE_BASIC_TYPES +# define FFI_EXTERN FFI_API +#else +# define FFI_EXTERN extern FFI_API +#endif + #ifndef LIBFFI_HIDE_BASIC_TYPES #if SCHAR_MAX == 127 # define ffi_type_uchar ffi_type_uint8 @@ -166,21 +187,7 @@ typedef struct _ffi_type #error "long size not supported" #endif -/* Need minimal decorations for DLLs to works on Windows. */ -/* GCC has autoimport and autoexport. Rely on Libtool to */ -/* help MSVC export from a DLL, but always declare data */ -/* to be imported for MSVC clients. This costs an extra */ -/* indirection for MSVC clients using the static version */ -/* of the library, but don't worry about that. Besides, */ -/* as a workaround, they can define FFI_BUILDING if they */ -/* *know* they are going to link with the static library. */ -#if defined _MSC_VER && !defined FFI_BUILDING -#define FFI_EXTERN extern __declspec(dllimport) -#else -#define FFI_EXTERN extern -#endif - -/* These are defined in types.c */ +/* These are defined in types.c. */ FFI_EXTERN ffi_type ffi_type_void; FFI_EXTERN ffi_type ffi_type_uint8; FFI_EXTERN ffi_type ffi_type_sint8; @@ -217,8 +224,6 @@ typedef enum { FFI_BAD_ABI } ffi_status; -typedef unsigned FFI_TYPE; - typedef struct { ffi_abi abi; unsigned nargs; @@ -231,6 +236,7 @@ typedef struct { #endif } ffi_cif; +<<<<<<< HEAD #if @HAVE_LONG_DOUBLE_VARIANT@ /* Used to adjust size/alignment of ffi types. */ void ffi_prep_types (ffi_abi abi); @@ -245,6 +251,8 @@ ffi_status ffi_prep_cif_core(ffi_cif *cif, ffi_type *rtype, ffi_type **atypes); +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 /* ---- Definitions for the raw API -------------------------------------- */ #ifndef FFI_SIZEOF_ARG @@ -282,27 +290,34 @@ typedef ffi_raw ffi_java_raw; #endif +FFI_API void ffi_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *avalue); -void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw); -void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args); -size_t ffi_raw_size (ffi_cif *cif); +FFI_API void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw); +FFI_API void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args); +FFI_API size_t ffi_raw_size (ffi_cif *cif); -/* This is analogous to the raw API, except it uses Java parameter */ -/* packing, even on 64-bit machines. I.e. on 64-bit machines */ -/* longs and doubles are followed by an empty 64-bit word. */ +/* This is analogous to the raw API, except it uses Java parameter + packing, even on 64-bit machines. I.e. on 64-bit machines longs + and doubles are followed by an empty 64-bit word. */ +#if !FFI_NATIVE_RAW_API +FFI_API void ffi_java_raw_call (ffi_cif *cif, void (*fn)(void), void *rvalue, - ffi_java_raw *avalue); + ffi_java_raw *avalue) __attribute__((deprecated)); +#endif -void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw); -void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args); -size_t ffi_java_raw_size (ffi_cif *cif); +FFI_API +void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw) __attribute__((deprecated)); +FFI_API +void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args) __attribute__((deprecated)); +FFI_API +size_t ffi_java_raw_size (ffi_cif *cif) __attribute__((deprecated)); /* ---- Definitions for closures ----------------------------------------- */ @@ -321,25 +336,42 @@ typedef struct { ffi_cif *cif; void (*fun)(ffi_cif*,void*,void**,void*); void *user_data; +} ffi_closure #ifdef __GNUC__ -} ffi_closure __attribute__((aligned (8))); -#else -} ffi_closure; + __attribute__((aligned (8))) +#endif + ; + +#ifndef __GNUC__ # ifdef __sgi # pragma pack 0 # endif #endif -void *ffi_closure_alloc (size_t size, void **code); -void ffi_closure_free (void *); +FFI_API void *ffi_closure_alloc (size_t size, void **code); +FFI_API void ffi_closure_free (void *); + +#if defined(PA_LINUX) || defined(PA_HPUX) +#define FFI_CLOSURE_PTR(X) ((void *)((unsigned int)(X) | 2)) +#define FFI_RESTORE_PTR(X) ((void *)((unsigned int)(X) & ~3)) +#else +#define FFI_CLOSURE_PTR(X) (X) +#define FFI_RESTORE_PTR(X) (X) +#endif -ffi_status +FFI_API ffi_status ffi_prep_closure (ffi_closure*, ffi_cif *, void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data); + void *user_data) +#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 405) + __attribute__((deprecated ("use ffi_prep_closure_loc instead"))) +#elif defined(__GNUC__) && __GNUC__ >= 3 + __attribute__((deprecated)) +#endif + ; -ffi_status +FFI_API ffi_status ffi_prep_closure_loc (ffi_closure*, ffi_cif *, void (*fun)(ffi_cif*,void*,void**,void*), @@ -360,9 +392,9 @@ typedef struct { #if !FFI_NATIVE_RAW_API - /* if this is enabled, then a raw closure has the same layout + /* If this is enabled, then a raw closure has the same layout as a regular closure. We use this to install an intermediate - handler to do the transaltion, void** -> ffi_raw*. */ + handler to do the transaltion, void** -> ffi_raw*. */ void (*translate_args)(ffi_cif*,void*,void**,void*); void *this_closure; @@ -386,9 +418,9 @@ typedef struct { #if !FFI_NATIVE_RAW_API - /* if this is enabled, then a raw closure has the same layout + /* If this is enabled, then a raw closure has the same layout as a regular closure. We use this to install an intermediate - handler to do the transaltion, void** -> ffi_raw*. */ + handler to do the translation, void** -> ffi_raw*. */ void (*translate_args)(ffi_cif*,void*,void**,void*); void *this_closure; @@ -400,42 +432,62 @@ typedef struct { } ffi_java_raw_closure; -ffi_status +FFI_API ffi_status ffi_prep_raw_closure (ffi_raw_closure*, ffi_cif *cif, void (*fun)(ffi_cif*,void*,ffi_raw*,void*), void *user_data); -ffi_status +FFI_API ffi_status ffi_prep_raw_closure_loc (ffi_raw_closure*, ffi_cif *cif, void (*fun)(ffi_cif*,void*,ffi_raw*,void*), void *user_data, void *codeloc); -ffi_status +#if !FFI_NATIVE_RAW_API +FFI_API ffi_status ffi_prep_java_raw_closure (ffi_java_raw_closure*, ffi_cif *cif, void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*), - void *user_data); + void *user_data) __attribute__((deprecated)); -ffi_status +FFI_API ffi_status ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*, ffi_cif *cif, void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*), void *user_data, - void *codeloc); + void *codeloc) __attribute__((deprecated)); +#endif #endif /* FFI_CLOSURES */ +#if FFI_GO_CLOSURES + +typedef struct { + void *tramp; + ffi_cif *cif; + void (*fun)(ffi_cif*,void*,void**,void*); +} ffi_go_closure; + +FFI_API ffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *, + void (*fun)(ffi_cif*,void*,void**,void*)); + +FFI_API void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure); + +#endif /* FFI_GO_CLOSURES */ + /* ---- Public interface definition -------------------------------------- */ +FFI_API ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs, ffi_type *rtype, ffi_type **atypes); +FFI_API ffi_status ffi_prep_cif_var(ffi_cif *cif, ffi_abi abi, unsigned int nfixedargs, @@ -443,12 +495,17 @@ ffi_status ffi_prep_cif_var(ffi_cif *cif, ffi_type *rtype, ffi_type **atypes); +FFI_API void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue); -/* Useful for eliminating compiler warnings */ +FFI_API +ffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type, + size_t *offsets); + +/* Useful for eliminating compiler warnings. */ #define FFI_FN(f) ((void (*)(void))f) /* ---- Definitions shared with assembly code ---------------------------- */ @@ -477,7 +534,11 @@ void ffi_call(ffi_cif *cif, #define FFI_TYPE_POINTER 14 #define FFI_TYPE_COMPLEX 15 +<<<<<<< HEAD /* This should always refer to the last type code (for sanity checks) */ +======= +/* This should always refer to the last type code (for sanity checks). */ +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #define FFI_TYPE_LAST FFI_TYPE_COMPLEX #ifdef __cplusplus diff --git a/native/libffi/include/ffi_cfi.h b/native/libffi/include/ffi_cfi.h new file mode 100644 index 0000000000..244ce572be --- /dev/null +++ b/native/libffi/include/ffi_cfi.h @@ -0,0 +1,55 @@ +/* ----------------------------------------------------------------------- + ffi_cfi.h - Copyright (c) 2014 Red Hat, Inc. + + Conditionally assemble cfi directives. Only necessary for building libffi. + ----------------------------------------------------------------------- */ + +#ifndef FFI_CFI_H +#define FFI_CFI_H + +#ifdef HAVE_AS_CFI_PSEUDO_OP + +# define cfi_startproc .cfi_startproc +# define cfi_endproc .cfi_endproc +# define cfi_def_cfa(reg, off) .cfi_def_cfa reg, off +# define cfi_def_cfa_register(reg) .cfi_def_cfa_register reg +# define cfi_def_cfa_offset(off) .cfi_def_cfa_offset off +# define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off +# define cfi_offset(reg, off) .cfi_offset reg, off +# define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off +# define cfi_register(r1, r2) .cfi_register r1, r2 +# define cfi_return_column(reg) .cfi_return_column reg +# define cfi_restore(reg) .cfi_restore reg +# define cfi_same_value(reg) .cfi_same_value reg +# define cfi_undefined(reg) .cfi_undefined reg +# define cfi_remember_state .cfi_remember_state +# define cfi_restore_state .cfi_restore_state +# define cfi_window_save .cfi_window_save +# define cfi_personality(enc, exp) .cfi_personality enc, exp +# define cfi_lsda(enc, exp) .cfi_lsda enc, exp +# define cfi_escape(...) .cfi_escape __VA_ARGS__ + +#else + +# define cfi_startproc +# define cfi_endproc +# define cfi_def_cfa(reg, off) +# define cfi_def_cfa_register(reg) +# define cfi_def_cfa_offset(off) +# define cfi_adjust_cfa_offset(off) +# define cfi_offset(reg, off) +# define cfi_rel_offset(reg, off) +# define cfi_register(r1, r2) +# define cfi_return_column(reg) +# define cfi_restore(reg) +# define cfi_same_value(reg) +# define cfi_undefined(reg) +# define cfi_remember_state +# define cfi_restore_state +# define cfi_window_save +# define cfi_personality(enc, exp) +# define cfi_lsda(enc, exp) +# define cfi_escape(...) + +#endif /* HAVE_AS_CFI_PSEUDO_OP */ +#endif /* FFI_CFI_H */ diff --git a/native/libffi/include/ffi_common.h b/native/libffi/include/ffi_common.h index 37f5a9e924..76b9dd6faf 100644 --- a/native/libffi/include/ffi_common.h +++ b/native/libffi/include/ffi_common.h @@ -74,14 +74,35 @@ void ffi_type_test(ffi_type *a, char *file, int line); #define FFI_ASSERT_VALID_TYPE(x) #endif -#define ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1) -#define ALIGN_DOWN(v, a) (((size_t) (v)) & -a) +/* v cast to size_t and aligned up to a multiple of a */ +#define FFI_ALIGN(v, a) (((((size_t) (v))-1) | ((a)-1))+1) +/* v cast to size_t and aligned down to a multiple of a */ +#define FFI_ALIGN_DOWN(v, a) (((size_t) (v)) & -a) /* Perform machine dependent cif processing */ ffi_status ffi_prep_cif_machdep(ffi_cif *cif); ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs, unsigned int ntotalargs); + +#if HAVE_LONG_DOUBLE_VARIANT +/* Used to adjust size/alignment of ffi types. */ +void ffi_prep_types (ffi_abi abi); +#endif + +/* Used internally, but overridden by some architectures */ +ffi_status ffi_prep_cif_core(ffi_cif *cif, + ffi_abi abi, + unsigned int isvariadic, + unsigned int nfixedargs, + unsigned int ntotalargs, + ffi_type *rtype, + ffi_type **atypes); + +/* Translate a data pointer to a code pointer. Needed for closures on + some targets. */ +void *ffi_data_to_code_pointer (void *data) FFI_HIDDEN; + /* Extended cif, used in callback from assembly routine */ typedef struct { diff --git a/native/libffi/libffi.map.in b/native/libffi/libffi.map.in new file mode 100644 index 0000000000..de8778ae40 --- /dev/null +++ b/native/libffi/libffi.map.in @@ -0,0 +1,76 @@ +#define LIBFFI_ASM +#define LIBFFI_H +#include +#include + +/* These version numbers correspond to the libtool-version abi numbers, + not to the libffi release numbers. */ + +LIBFFI_BASE_8.0 { + global: + /* Exported data variables. */ + ffi_type_void; + ffi_type_uint8; + ffi_type_sint8; + ffi_type_uint16; + ffi_type_sint16; + ffi_type_uint32; + ffi_type_sint32; + ffi_type_uint64; + ffi_type_sint64; + ffi_type_float; + ffi_type_double; + ffi_type_longdouble; + ffi_type_pointer; + + /* Exported functions. */ + ffi_call; + ffi_prep_cif; + ffi_prep_cif_var; + + ffi_raw_call; + ffi_ptrarray_to_raw; + ffi_raw_to_ptrarray; + ffi_raw_size; + + ffi_java_raw_call; + ffi_java_ptrarray_to_raw; + ffi_java_raw_to_ptrarray; + ffi_java_raw_size; + + ffi_get_struct_offsets; + local: + *; +}; + +#ifdef FFI_TARGET_HAS_COMPLEX_TYPE +LIBFFI_COMPLEX_8.0 { + global: + /* Exported data variables. */ + ffi_type_complex_float; + ffi_type_complex_double; + ffi_type_complex_longdouble; +} LIBFFI_BASE_8.0; +#endif + +#if FFI_CLOSURES +LIBFFI_CLOSURE_8.0 { + global: + ffi_closure_alloc; + ffi_closure_free; + ffi_prep_closure; + ffi_prep_closure_loc; + ffi_prep_raw_closure; + ffi_prep_raw_closure_loc; + ffi_prep_java_raw_closure; + ffi_prep_java_raw_closure_loc; +} LIBFFI_BASE_8.0; +#endif + +#if FFI_GO_CLOSURES +LIBFFI_GO_CLOSURE_8.0 { + global: + ffi_call_go; + ffi_prep_go_closure; +} LIBFFI_CLOSURE_8.0; +#endif diff --git a/native/libffi/libffi.pc.in b/native/libffi/libffi.pc.in index edf6fde5e2..264877ea71 100644 --- a/native/libffi/libffi.pc.in +++ b/native/libffi/libffi.pc.in @@ -2,7 +2,11 @@ prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ toolexeclibdir=@toolexeclibdir@ +<<<<<<< HEAD includedir=${libdir}/@PACKAGE_NAME@-@PACKAGE_VERSION@/include +======= +includedir=@includedir@ +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 Name: @PACKAGE_NAME@ Description: Library supporting Foreign Function Interfaces diff --git a/native/libffi/libffi.xcodeproj/project.pbxproj b/native/libffi/libffi.xcodeproj/project.pbxproj index 1cf396ffa1..cc49b3d7ed 100644 --- a/native/libffi/libffi.xcodeproj/project.pbxproj +++ b/native/libffi/libffi.xcodeproj/project.pbxproj @@ -7,6 +7,12 @@ objects = { /* Begin PBXBuildFile section */ +<<<<<<< HEAD +======= + 43B5D3F81D35473200D1E1FD /* ffiw64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = 43B5D3F71D35473200D1E1FD /* ffiw64_x86_64.c */; }; + 43B5D3FA1D3547CE00D1E1FD /* win64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = 43B5D3F91D3547CE00D1E1FD /* win64_x86_64.S */; }; + 43E9A5C81D352C1500926A8F /* unix64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = 43E9A5C61D352C1500926A8F /* unix64_x86_64.S */; }; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 DBFA714A187F1D8600A76262 /* ffi.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA713E187F1D8600A76262 /* ffi.h */; }; DBFA714B187F1D8600A76262 /* ffi_common.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA713F187F1D8600A76262 /* ffi_common.h */; }; DBFA714C187F1D8600A76262 /* fficonfig.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7140187F1D8600A76262 /* fficonfig.h */; }; @@ -23,6 +29,7 @@ DBFA7178187F1D9B00A76262 /* sysv_arm64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716D187F1D9B00A76262 /* sysv_arm64.S */; }; DBFA7179187F1D9B00A76262 /* ffi_armv7.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716F187F1D9B00A76262 /* ffi_armv7.c */; }; DBFA717A187F1D9B00A76262 /* sysv_armv7.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7170187F1D9B00A76262 /* sysv_armv7.S */; }; +<<<<<<< HEAD DBFA717B187F1D9B00A76262 /* trampoline_armv7.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7171187F1D9B00A76262 /* trampoline_armv7.S */; }; DBFA717C187F1D9B00A76262 /* darwin64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7173187F1D9B00A76262 /* darwin64_x86_64.S */; }; DBFA717D187F1D9B00A76262 /* darwin_i386.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7174187F1D9B00A76262 /* darwin_i386.S */; }; @@ -38,11 +45,60 @@ DBFA7195187F1DA100A76262 /* darwin_i386.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718B187F1DA100A76262 /* darwin_i386.S */; }; DBFA7196187F1DA100A76262 /* ffi64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */; }; DBFA7197187F1DA100A76262 /* ffi_i386.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718D187F1DA100A76262 /* ffi_i386.c */; }; +======= + DBFA717E187F1D9B00A76262 /* ffi64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */; }; + DBFA718F187F1DA100A76262 /* ffi_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7183187F1DA100A76262 /* ffi_x86_64.h */; }; + DBFA7191187F1DA100A76262 /* fficonfig_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7185187F1DA100A76262 /* fficonfig_x86_64.h */; }; + DBFA7193187F1DA100A76262 /* ffitarget_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = DBFA7187187F1DA100A76262 /* ffitarget_x86_64.h */; }; + DBFA7194187F1DA100A76262 /* unix64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718A187F1DA100A76262 /* unix64_x86_64.S */; }; + DBFA7196187F1DA100A76262 /* ffi64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */; }; + FDB52FB31F6144FA00AA92E6 /* unix64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = 43E9A5C61D352C1500926A8F /* unix64_x86_64.S */; }; + FDB52FB51F6144FA00AA92E6 /* ffi64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */; }; + FDB52FB61F6144FA00AA92E6 /* ffi_armv7.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716F187F1D9B00A76262 /* ffi_armv7.c */; }; + FDB52FB71F6144FA00AA92E6 /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7143187F1D8600A76262 /* closures.c */; }; + FDB52FB81F6144FA00AA92E6 /* sysv_armv7.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7170187F1D9B00A76262 /* sysv_armv7.S */; }; + FDB52FB91F6144FA00AA92E6 /* ffiw64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = 43B5D3F71D35473200D1E1FD /* ffiw64_x86_64.c */; }; + FDB52FBA1F6144FA00AA92E6 /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7147187F1D8600A76262 /* prep_cif.c */; }; + FDB52FBC1F6144FA00AA92E6 /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7148187F1D8600A76262 /* raw_api.c */; }; + FDB52FBD1F6144FA00AA92E6 /* sysv_arm64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716D187F1D9B00A76262 /* sysv_arm64.S */; }; + FDB52FBE1F6144FA00AA92E6 /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7149187F1D8600A76262 /* types.c */; }; + FDB52FBF1F6144FA00AA92E6 /* ffi_arm64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA716C187F1D9B00A76262 /* ffi_arm64.c */; }; + FDB52FC01F6144FA00AA92E6 /* win64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = 43B5D3F91D3547CE00D1E1FD /* win64_x86_64.S */; }; + FDB52FD01F614A8B00AA92E6 /* ffi.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA713E187F1D8600A76262 /* ffi.h */; }; + FDB52FD11F614AA700AA92E6 /* ffi_arm64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA715E187F1D9B00A76262 /* ffi_arm64.h */; }; + FDB52FD21F614AAB00AA92E6 /* ffi_armv7.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA715F187F1D9B00A76262 /* ffi_armv7.h */; }; + FDB52FD41F614AB500AA92E6 /* ffi_x86_64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7161187F1D9B00A76262 /* ffi_x86_64.h */; }; + FDB52FD51F614AE200AA92E6 /* ffi.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA713E187F1D8600A76262 /* ffi.h */; }; + FDB52FD61F614AEA00AA92E6 /* ffi_arm64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA715E187F1D9B00A76262 /* ffi_arm64.h */; }; + FDB52FD71F614AED00AA92E6 /* ffi_x86_64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7161187F1D9B00A76262 /* ffi_x86_64.h */; }; + FDB52FD81F614B8700AA92E6 /* ffitarget.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7141187F1D8600A76262 /* ffitarget.h */; }; + FDB52FD91F614B8E00AA92E6 /* ffitarget_arm64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7166187F1D9B00A76262 /* ffitarget_arm64.h */; }; + FDB52FDA1F614B9300AA92E6 /* ffitarget_armv7.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7167187F1D9B00A76262 /* ffitarget_armv7.h */; }; + FDB52FDD1F614BA900AA92E6 /* ffitarget_x86_64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7169187F1D9B00A76262 /* ffitarget_x86_64.h */; }; + FDB52FDE1F6155E300AA92E6 /* ffitarget.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7141187F1D8600A76262 /* ffitarget.h */; }; + FDB52FDF1F6155EA00AA92E6 /* ffitarget_arm64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7166187F1D9B00A76262 /* ffitarget_arm64.h */; }; + FDB52FE01F6155EF00AA92E6 /* ffitarget_x86_64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7169187F1D9B00A76262 /* ffitarget_x86_64.h */; }; + FDB52FE21F6156FA00AA92E6 /* ffi.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA713E187F1D8600A76262 /* ffi.h */; }; + FDB52FE31F61571A00AA92E6 /* ffi_x86_64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7183187F1DA100A76262 /* ffi_x86_64.h */; }; + FDB52FE41F61571D00AA92E6 /* ffitarget.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7141187F1D8600A76262 /* ffitarget.h */; }; + FDB52FE61F61573100AA92E6 /* ffitarget_x86_64.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DBFA7187187F1DA100A76262 /* ffitarget_x86_64.h */; }; + FDDB2F411F5D66E200EF414E /* ffiw64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = FDDB2F3F1F5D666900EF414E /* ffiw64_x86_64.c */; }; + FDDB2F461F5D691E00EF414E /* win64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = FDDB2F441F5D68C900EF414E /* win64_x86_64.S */; }; + FDDB2F4A1F5D846400EF414E /* ffi64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */; }; + FDDB2F4C1F5D846400EF414E /* prep_cif.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7147187F1D8600A76262 /* prep_cif.c */; }; + FDDB2F4E1F5D846400EF414E /* ffiw64_x86_64.c in Sources */ = {isa = PBXBuildFile; fileRef = FDDB2F3F1F5D666900EF414E /* ffiw64_x86_64.c */; }; + FDDB2F4F1F5D846400EF414E /* types.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7149187F1D8600A76262 /* types.c */; }; + FDDB2F501F5D846400EF414E /* raw_api.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7148187F1D8600A76262 /* raw_api.c */; }; + FDDB2F511F5D846400EF414E /* closures.c in Sources */ = {isa = PBXBuildFile; fileRef = DBFA7143187F1D8600A76262 /* closures.c */; }; + FDDB2F521F5D846400EF414E /* unix64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = DBFA718A187F1DA100A76262 /* unix64_x86_64.S */; }; + FDDB2F531F5D846400EF414E /* win64_x86_64.S in Sources */ = {isa = PBXBuildFile; fileRef = FDDB2F441F5D68C900EF414E /* win64_x86_64.S */; }; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ DB13B1641849DF1E0010F42D /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; +<<<<<<< HEAD buildActionMask = 8; dstPath = "include/$(PRODUCT_NAME)"; dstSubfolderSpec = 16; @@ -105,18 +161,61 @@ DBFA715C187F1D9B00A76262 /* darwin_ios */, DBFA7180187F1DA100A76262 /* darwin_osx */, DB13B1671849DF1E0010F42D /* Products */, +======= + buildActionMask = 12; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + FDB52FD01F614A8B00AA92E6 /* ffi.h in CopyFiles */, + FDB52FD11F614AA700AA92E6 /* ffi_arm64.h in CopyFiles */, + FDB52FD21F614AAB00AA92E6 /* ffi_armv7.h in CopyFiles */, + FDB52FD41F614AB500AA92E6 /* ffi_x86_64.h in CopyFiles */, + FDB52FD81F614B8700AA92E6 /* ffitarget.h in CopyFiles */, + FDB52FD91F614B8E00AA92E6 /* ffitarget_arm64.h in CopyFiles */, + FDB52FDA1F614B9300AA92E6 /* ffitarget_armv7.h in CopyFiles */, + FDB52FDD1F614BA900AA92E6 /* ffitarget_x86_64.h in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDB52FC11F6144FA00AA92E6 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 12; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + FDB52FD51F614AE200AA92E6 /* ffi.h in CopyFiles */, + FDB52FD61F614AEA00AA92E6 /* ffi_arm64.h in CopyFiles */, + FDB52FD71F614AED00AA92E6 /* ffi_x86_64.h in CopyFiles */, + FDB52FDE1F6155E300AA92E6 /* ffitarget.h in CopyFiles */, + FDB52FDF1F6155EA00AA92E6 /* ffitarget_arm64.h in CopyFiles */, + FDB52FE01F6155EF00AA92E6 /* ffitarget_x86_64.h in CopyFiles */, +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 ); sourceTree = ""; }; +<<<<<<< HEAD DB13B1671849DF1E0010F42D /* Products */ = { isa = PBXGroup; children = ( DB13B1661849DF1E0010F42D /* libffi.a */, DB13B1911849DF510010F42D /* ffi.dylib */, +======= + FDB52FE11F6156E000AA92E6 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + FDB52FE21F6156FA00AA92E6 /* ffi.h in CopyFiles */, + FDB52FE31F61571A00AA92E6 /* ffi_x86_64.h in CopyFiles */, + FDB52FE41F61571D00AA92E6 /* ffitarget.h in CopyFiles */, + FDB52FE61F61573100AA92E6 /* ffitarget_x86_64.h in CopyFiles */, +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 ); name = Products; sourceTree = ""; }; +<<<<<<< HEAD DBFA713C187F1D8600A76262 /* darwin_common */ = { isa = PBXGroup; children = ( @@ -180,6 +279,139 @@ DBFA716A187F1D9B00A76262 /* src */ = { isa = PBXGroup; children = ( +======= +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 43B5D3F71D35473200D1E1FD /* ffiw64_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffiw64_x86_64.c; sourceTree = ""; }; + 43B5D3F91D3547CE00D1E1FD /* win64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = win64_x86_64.S; sourceTree = ""; }; + 43E9A5C61D352C1500926A8F /* unix64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = unix64_x86_64.S; sourceTree = ""; }; + 43E9A5DA1D35373600926A8F /* internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = internal.h; sourceTree = ""; }; + 43E9A5DB1D35374400926A8F /* internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = internal.h; sourceTree = ""; }; + 43E9A5DC1D35375400926A8F /* internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = internal.h; sourceTree = ""; }; + 43E9A5DD1D35375400926A8F /* internal64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = internal64.h; sourceTree = ""; }; + DB13B1661849DF1E0010F42D /* libffi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; }; + DB13B1911849DF510010F42D /* ffi.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = ffi.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; + DBFA713E187F1D8600A76262 /* ffi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi.h; sourceTree = ""; }; + DBFA713F187F1D8600A76262 /* ffi_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_common.h; sourceTree = ""; }; + DBFA7140187F1D8600A76262 /* fficonfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig.h; sourceTree = ""; }; + DBFA7141187F1D8600A76262 /* ffitarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget.h; sourceTree = ""; }; + DBFA7143187F1D8600A76262 /* closures.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = closures.c; sourceTree = ""; }; + DBFA7145187F1D8600A76262 /* dlmalloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dlmalloc.c; sourceTree = ""; }; + DBFA7147187F1D8600A76262 /* prep_cif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = prep_cif.c; sourceTree = ""; }; + DBFA7148187F1D8600A76262 /* raw_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = raw_api.c; sourceTree = ""; }; + DBFA7149187F1D8600A76262 /* types.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = types.c; sourceTree = ""; }; + DBFA715E187F1D9B00A76262 /* ffi_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_arm64.h; sourceTree = ""; }; + DBFA715F187F1D9B00A76262 /* ffi_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_armv7.h; sourceTree = ""; }; + DBFA7161187F1D9B00A76262 /* ffi_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_x86_64.h; sourceTree = ""; }; + DBFA7162187F1D9B00A76262 /* fficonfig_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_arm64.h; sourceTree = ""; }; + DBFA7163187F1D9B00A76262 /* fficonfig_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_armv7.h; sourceTree = ""; }; + DBFA7165187F1D9B00A76262 /* fficonfig_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_x86_64.h; sourceTree = ""; }; + DBFA7166187F1D9B00A76262 /* ffitarget_arm64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_arm64.h; sourceTree = ""; }; + DBFA7167187F1D9B00A76262 /* ffitarget_armv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_armv7.h; sourceTree = ""; }; + DBFA7169187F1D9B00A76262 /* ffitarget_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_x86_64.h; sourceTree = ""; }; + DBFA716C187F1D9B00A76262 /* ffi_arm64.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.c; path = ffi_arm64.c; sourceTree = ""; }; + DBFA716D187F1D9B00A76262 /* sysv_arm64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sysv_arm64.S; sourceTree = ""; }; + DBFA716F187F1D9B00A76262 /* ffi_armv7.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.c; path = ffi_armv7.c; sourceTree = ""; }; + DBFA7170187F1D9B00A76262 /* sysv_armv7.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = sysv_armv7.S; sourceTree = ""; }; + DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffi64_x86_64.c; sourceTree = ""; }; + DBFA7183187F1DA100A76262 /* ffi_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffi_x86_64.h; sourceTree = ""; }; + DBFA7185187F1DA100A76262 /* fficonfig_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fficonfig_x86_64.h; sourceTree = ""; }; + DBFA7187187F1DA100A76262 /* ffitarget_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ffitarget_x86_64.h; sourceTree = ""; }; + DBFA718A187F1DA100A76262 /* unix64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = unix64_x86_64.S; sourceTree = ""; }; + DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.c; path = ffi64_x86_64.c; sourceTree = ""; }; + FDB52FC51F6144FA00AA92E6 /* libffi.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; }; + FDDB2F3E1F5D61BC00EF414E /* asmnames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = asmnames.h; sourceTree = ""; }; + FDDB2F3F1F5D666900EF414E /* ffiw64_x86_64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffiw64_x86_64.c; sourceTree = ""; }; + FDDB2F421F5D68C900EF414E /* internal64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = internal64.h; sourceTree = ""; }; + FDDB2F431F5D68C900EF414E /* internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = internal.h; sourceTree = ""; }; + FDDB2F441F5D68C900EF414E /* win64_x86_64.S */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.asm; path = win64_x86_64.S; sourceTree = ""; }; + FDDB2F621F5D846400EF414E /* libffi.a */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libffi.a; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXGroup section */ + DB13B15B1849DEB70010F42D = { + isa = PBXGroup; + children = ( + DBFA713C187F1D8600A76262 /* darwin_common */, + DBFA715C187F1D9B00A76262 /* darwin_ios */, + DBFA7180187F1DA100A76262 /* darwin_osx */, + DB13B1671849DF1E0010F42D /* Products */, + ); + sourceTree = ""; + }; + DB13B1671849DF1E0010F42D /* Products */ = { + isa = PBXGroup; + children = ( + DB13B1661849DF1E0010F42D /* libffi.a */, + DB13B1911849DF510010F42D /* ffi.dylib */, + FDDB2F621F5D846400EF414E /* libffi.a */, + FDB52FC51F6144FA00AA92E6 /* libffi.a */, + ); + name = Products; + sourceTree = ""; + }; + DBFA713C187F1D8600A76262 /* darwin_common */ = { + isa = PBXGroup; + children = ( + DBFA713D187F1D8600A76262 /* include */, + DBFA7142187F1D8600A76262 /* src */, + ); + path = darwin_common; + sourceTree = ""; + }; + DBFA713D187F1D8600A76262 /* include */ = { + isa = PBXGroup; + children = ( + DBFA713E187F1D8600A76262 /* ffi.h */, + DBFA713F187F1D8600A76262 /* ffi_common.h */, + DBFA7140187F1D8600A76262 /* fficonfig.h */, + DBFA7141187F1D8600A76262 /* ffitarget.h */, + ); + path = include; + sourceTree = ""; + }; + DBFA7142187F1D8600A76262 /* src */ = { + isa = PBXGroup; + children = ( + DBFA7143187F1D8600A76262 /* closures.c */, + DBFA7145187F1D8600A76262 /* dlmalloc.c */, + DBFA7147187F1D8600A76262 /* prep_cif.c */, + DBFA7148187F1D8600A76262 /* raw_api.c */, + DBFA7149187F1D8600A76262 /* types.c */, + ); + path = src; + sourceTree = ""; + }; + DBFA715C187F1D9B00A76262 /* darwin_ios */ = { + isa = PBXGroup; + children = ( + DBFA715D187F1D9B00A76262 /* include */, + DBFA716A187F1D9B00A76262 /* src */, + ); + path = darwin_ios; + sourceTree = ""; + }; + DBFA715D187F1D9B00A76262 /* include */ = { + isa = PBXGroup; + children = ( + DBFA715E187F1D9B00A76262 /* ffi_arm64.h */, + DBFA715F187F1D9B00A76262 /* ffi_armv7.h */, + DBFA7161187F1D9B00A76262 /* ffi_x86_64.h */, + DBFA7162187F1D9B00A76262 /* fficonfig_arm64.h */, + DBFA7163187F1D9B00A76262 /* fficonfig_armv7.h */, + DBFA7165187F1D9B00A76262 /* fficonfig_x86_64.h */, + DBFA7166187F1D9B00A76262 /* ffitarget_arm64.h */, + DBFA7167187F1D9B00A76262 /* ffitarget_armv7.h */, + DBFA7169187F1D9B00A76262 /* ffitarget_x86_64.h */, + ); + path = include; + sourceTree = ""; + }; + DBFA716A187F1D9B00A76262 /* src */ = { + isa = PBXGroup; + children = ( +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 DBFA716B187F1D9B00A76262 /* aarch64 */, DBFA716E187F1D9B00A76262 /* arm */, DBFA7172187F1D9B00A76262 /* x86 */, @@ -190,6 +422,10 @@ DBFA716B187F1D9B00A76262 /* aarch64 */ = { isa = PBXGroup; children = ( +<<<<<<< HEAD +======= + 43E9A5DA1D35373600926A8F /* internal.h */, +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 DBFA716C187F1D9B00A76262 /* ffi_arm64.c */, DBFA716D187F1D9B00A76262 /* sysv_arm64.S */, ); @@ -199,9 +435,15 @@ DBFA716E187F1D9B00A76262 /* arm */ = { isa = PBXGroup; children = ( +<<<<<<< HEAD DBFA716F187F1D9B00A76262 /* ffi_armv7.c */, DBFA7170187F1D9B00A76262 /* sysv_armv7.S */, DBFA7171187F1D9B00A76262 /* trampoline_armv7.S */, +======= + 43E9A5DB1D35374400926A8F /* internal.h */, + DBFA716F187F1D9B00A76262 /* ffi_armv7.c */, + DBFA7170187F1D9B00A76262 /* sysv_armv7.S */, +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 ); path = arm; sourceTree = ""; @@ -209,6 +451,7 @@ DBFA7172187F1D9B00A76262 /* x86 */ = { isa = PBXGroup; children = ( +<<<<<<< HEAD DBFA7173187F1D9B00A76262 /* darwin64_x86_64.S */, DBFA7174187F1D9B00A76262 /* darwin_i386.S */, DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */, @@ -234,6 +477,32 @@ DBFA7184187F1DA100A76262 /* fficonfig_i386.h */, DBFA7185187F1DA100A76262 /* fficonfig_x86_64.h */, DBFA7186187F1DA100A76262 /* ffitarget_i386.h */, +======= + 43E9A5DC1D35375400926A8F /* internal.h */, + 43E9A5DD1D35375400926A8F /* internal64.h */, + DBFA7175187F1D9B00A76262 /* ffi64_x86_64.c */, + 43B5D3F71D35473200D1E1FD /* ffiw64_x86_64.c */, + 43E9A5C61D352C1500926A8F /* unix64_x86_64.S */, + 43B5D3F91D3547CE00D1E1FD /* win64_x86_64.S */, + ); + path = x86; + sourceTree = ""; + }; + DBFA7180187F1DA100A76262 /* darwin_osx */ = { + isa = PBXGroup; + children = ( + DBFA7181187F1DA100A76262 /* include */, + DBFA7188187F1DA100A76262 /* src */, + ); + path = darwin_osx; + sourceTree = ""; + }; + DBFA7181187F1DA100A76262 /* include */ = { + isa = PBXGroup; + children = ( + DBFA7183187F1DA100A76262 /* ffi_x86_64.h */, + DBFA7185187F1DA100A76262 /* fficonfig_x86_64.h */, +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 DBFA7187187F1DA100A76262 /* ffitarget_x86_64.h */, ); path = include; @@ -250,10 +519,20 @@ DBFA7189187F1DA100A76262 /* x86 */ = { isa = PBXGroup; children = ( +<<<<<<< HEAD DBFA718A187F1DA100A76262 /* darwin64_x86_64.S */, DBFA718B187F1DA100A76262 /* darwin_i386.S */, DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */, DBFA718D187F1DA100A76262 /* ffi_i386.c */, +======= + FDDB2F431F5D68C900EF414E /* internal.h */, + FDDB2F421F5D68C900EF414E /* internal64.h */, + FDDB2F3E1F5D61BC00EF414E /* asmnames.h */, + DBFA718C187F1DA100A76262 /* ffi64_x86_64.c */, + FDDB2F3F1F5D666900EF414E /* ffiw64_x86_64.c */, + DBFA718A187F1DA100A76262 /* unix64_x86_64.S */, + FDDB2F441F5D68C900EF414E /* win64_x86_64.S */, +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 ); path = x86; sourceTree = ""; @@ -270,11 +549,16 @@ DBFA714A187F1D8600A76262 /* ffi.h in Headers */, DBFA718F187F1DA100A76262 /* ffi_x86_64.h in Headers */, DBFA7191187F1DA100A76262 /* fficonfig_x86_64.h in Headers */, +<<<<<<< HEAD DBFA718E187F1DA100A76262 /* ffi_i386.h in Headers */, DBFA7190187F1DA100A76262 /* fficonfig_i386.h in Headers */, DBFA714B187F1D8600A76262 /* ffi_common.h in Headers */, DBFA7193187F1DA100A76262 /* ffitarget_x86_64.h in Headers */, DBFA7192187F1DA100A76262 /* ffitarget_i386.h in Headers */, +======= + DBFA714B187F1D8600A76262 /* ffi_common.h in Headers */, + DBFA7193187F1DA100A76262 /* ffitarget_x86_64.h in Headers */, +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 ); runOnlyForDeploymentPostprocessing = 0; }; @@ -285,7 +569,11 @@ isa = PBXNativeTarget; buildConfigurationList = DB13B18B1849DF1E0010F42D /* Build configuration list for PBXNativeTarget "libffi-iOS" */; buildPhases = ( +<<<<<<< HEAD DB13B3051849E01C0010F42D /* ShellScript */, +======= + 43B5D3FB1D35480D00D1E1FD /* Run Script */, +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 DB13B1621849DF1E0010F42D /* Sources */, DB13B1641849DF1E0010F42D /* CopyFiles */, ); @@ -299,6 +587,14 @@ productType = "com.apple.product-type.library.static"; }; DB13B1901849DF510010F42D /* libffi-Mac */ = { +<<<<<<< HEAD + isa = PBXNativeTarget; + buildConfigurationList = DB13B1B01849DF520010F42D /* Build configuration list for PBXNativeTarget "libffi-Mac" */; + buildPhases = ( + DB13B3061849E0490010F42D /* ShellScript */, + DB13B18D1849DF510010F42D /* Sources */, + DB13B18F1849DF510010F42D /* Headers */, +======= isa = PBXNativeTarget; buildConfigurationList = DB13B1B01849DF520010F42D /* Build configuration list for PBXNativeTarget "libffi-Mac" */; buildPhases = ( @@ -315,13 +611,59 @@ productReference = DB13B1911849DF510010F42D /* ffi.dylib */; productType = "com.apple.product-type.library.dynamic"; }; + FDB52FB01F6144FA00AA92E6 /* libffi-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDB52FC21F6144FA00AA92E6 /* Build configuration list for PBXNativeTarget "libffi-tvOS" */; + buildPhases = ( + FDB52FB11F6144FA00AA92E6 /* Run Script */, + FDB52FB21F6144FA00AA92E6 /* Sources */, + FDB52FC11F6144FA00AA92E6 /* CopyFiles */, +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 + ); + buildRules = ( + ); + dependencies = ( + ); +<<<<<<< HEAD + name = "libffi-Mac"; + productName = ffi; + productReference = DB13B1911849DF510010F42D /* ffi.dylib */; + productType = "com.apple.product-type.library.dynamic"; +======= + name = "libffi-tvOS"; + productName = ffi; + productReference = FDB52FC51F6144FA00AA92E6 /* libffi.a */; + productType = "com.apple.product-type.library.static"; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 + }; + FDDB2F471F5D846400EF414E /* libffi-static-Mac */ = { + isa = PBXNativeTarget; + buildConfigurationList = FDDB2F5F1F5D846400EF414E /* Build configuration list for PBXNativeTarget "libffi-static-Mac" */; + buildPhases = ( + FDDB2F481F5D846400EF414E /* ShellScript */, + FDDB2F491F5D846400EF414E /* Sources */, + FDB52FE11F6156E000AA92E6 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "libffi-static-Mac"; + productName = ffi; + productReference = FDDB2F621F5D846400EF414E /* libffi.a */; + productType = "com.apple.product-type.library.dynamic"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ DB13B15C1849DEB70010F42D /* Project object */ = { isa = PBXProject; attributes = { +<<<<<<< HEAD LastUpgradeCheck = 0510; +======= + LastUpgradeCheck = 0830; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 }; buildConfigurationList = DB13B15F1849DEB70010F42D /* Build configuration list for PBXProject "libffi" */; compatibilityVersion = "Xcode 3.2"; @@ -336,13 +678,37 @@ projectRoot = ""; targets = ( DB13B1651849DF1E0010F42D /* libffi-iOS */, +<<<<<<< HEAD DB13B1901849DF510010F42D /* libffi-Mac */, +======= + FDB52FB01F6144FA00AA92E6 /* libffi-tvOS */, + DB13B1901849DF510010F42D /* libffi-Mac */, + FDDB2F471F5D846400EF414E /* libffi-static-Mac */, +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 ); }; /* End PBXProject section */ /* Begin PBXShellScriptBuildPhase section */ +<<<<<<< HEAD DB13B3051849E01C0010F42D /* ShellScript */ = { +======= + 43B5D3FB1D35480D00D1E1FD /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if [ ! -f \"./compile\" ]\nthen\nautoreconf -i -f -v\nif [ -f \"../ltmain.sh\" ]\nthen\necho \"fixing ltmain.sh for some reason\"\nmv ../ltmain.sh ./\nautoreconf -i -f -v\nfi\n/usr/bin/python generate-darwin-source-and-headers.py --only-ios\nfi"; + }; + DB13B3061849E0490010F42D /* ShellScript */ = { +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -353,25 +719,53 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; +<<<<<<< HEAD shellScript = "/usr/bin/python generate-darwin-source-and-headers.py --only-ios"; }; DB13B3061849E0490010F42D /* ShellScript */ = { +======= + shellScript = "if [ ! -f \"./compile\" ]\nthen\nautoreconf -i -f -v\nif [ -f \"../ltmain.sh\" ]\nthen\necho \"fixing ltmain.sh for some reason\"\nmv ../ltmain.sh ./\nautoreconf -i -f -v\nfi\n/usr/bin/python generate-darwin-source-and-headers.py --only-osx\nfi"; + }; + FDB52FB11F6144FA00AA92E6 /* Run Script */ = { +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); +<<<<<<< HEAD +======= + name = "Run Script"; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; +<<<<<<< HEAD shellScript = "/usr/bin/python generate-darwin-source-and-headers.py --only-osx"; +======= + shellScript = "if [ ! -f \"./compile\" ]\nthen\nautoreconf -i -f -v\nif [ -f \"../ltmain.sh\" ]\nthen\necho \"fixing ltmain.sh for some reason\"\nmv ../ltmain.sh ./\nautoreconf -i -f -v\nfi\n/usr/bin/python generate-darwin-source-and-headers.py --only-ios\nfi"; + }; + FDDB2F481F5D846400EF414E /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if [ ! -f \"./compile\" ]\nthen\nautoreconf -i -f -v\nif [ -f \"../ltmain.sh\" ]\nthen\necho \"fixing ltmain.sh for some reason\"\nmv ../ltmain.sh ./\nautoreconf -i -f -v\nfi\n/usr/bin/python generate-darwin-source-and-headers.py --only-osx\nfi"; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ DB13B1621849DF1E0010F42D /* Sources */ = { +<<<<<<< HEAD isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -403,6 +797,72 @@ DBFA7159187F1D8600A76262 /* raw_api.c in Sources */, DBFA714F187F1D8600A76262 /* closures.c in Sources */, DBFA7194187F1DA100A76262 /* darwin64_x86_64.S in Sources */, +======= + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 43E9A5C81D352C1500926A8F /* unix64_x86_64.S in Sources */, + DBFA717E187F1D9B00A76262 /* ffi64_x86_64.c in Sources */, + DBFA7179187F1D9B00A76262 /* ffi_armv7.c in Sources */, + DBFA714E187F1D8600A76262 /* closures.c in Sources */, + DBFA717A187F1D9B00A76262 /* sysv_armv7.S in Sources */, + 43B5D3F81D35473200D1E1FD /* ffiw64_x86_64.c in Sources */, + DBFA7156187F1D8600A76262 /* prep_cif.c in Sources */, + DBFA7158187F1D8600A76262 /* raw_api.c in Sources */, + DBFA7178187F1D9B00A76262 /* sysv_arm64.S in Sources */, + DBFA715A187F1D8600A76262 /* types.c in Sources */, + DBFA7177187F1D9B00A76262 /* ffi_arm64.c in Sources */, + 43B5D3FA1D3547CE00D1E1FD /* win64_x86_64.S in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DB13B18D1849DF510010F42D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DBFA7196187F1DA100A76262 /* ffi64_x86_64.c in Sources */, + DBFA7157187F1D8600A76262 /* prep_cif.c in Sources */, + FDDB2F411F5D66E200EF414E /* ffiw64_x86_64.c in Sources */, + DBFA715B187F1D8600A76262 /* types.c in Sources */, + DBFA7159187F1D8600A76262 /* raw_api.c in Sources */, + DBFA714F187F1D8600A76262 /* closures.c in Sources */, + DBFA7194187F1DA100A76262 /* unix64_x86_64.S in Sources */, + FDDB2F461F5D691E00EF414E /* win64_x86_64.S in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDB52FB21F6144FA00AA92E6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDB52FB31F6144FA00AA92E6 /* unix64_x86_64.S in Sources */, + FDB52FB51F6144FA00AA92E6 /* ffi64_x86_64.c in Sources */, + FDB52FB61F6144FA00AA92E6 /* ffi_armv7.c in Sources */, + FDB52FB71F6144FA00AA92E6 /* closures.c in Sources */, + FDB52FB81F6144FA00AA92E6 /* sysv_armv7.S in Sources */, + FDB52FB91F6144FA00AA92E6 /* ffiw64_x86_64.c in Sources */, + FDB52FBA1F6144FA00AA92E6 /* prep_cif.c in Sources */, + FDB52FBC1F6144FA00AA92E6 /* raw_api.c in Sources */, + FDB52FBD1F6144FA00AA92E6 /* sysv_arm64.S in Sources */, + FDB52FBE1F6144FA00AA92E6 /* types.c in Sources */, + FDB52FBF1F6144FA00AA92E6 /* ffi_arm64.c in Sources */, + FDB52FC01F6144FA00AA92E6 /* win64_x86_64.S in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + FDDB2F491F5D846400EF414E /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FDDB2F4A1F5D846400EF414E /* ffi64_x86_64.c in Sources */, + FDDB2F4C1F5D846400EF414E /* prep_cif.c in Sources */, + FDDB2F4E1F5D846400EF414E /* ffiw64_x86_64.c in Sources */, + FDDB2F4F1F5D846400EF414E /* types.c in Sources */, + FDDB2F501F5D846400EF414E /* raw_api.c in Sources */, + FDDB2F511F5D846400EF414E /* closures.c in Sources */, + FDDB2F521F5D846400EF414E /* unix64_x86_64.S in Sources */, + FDDB2F531F5D846400EF414E /* win64_x86_64.S in Sources */, +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 ); runOnlyForDeploymentPostprocessing = 0; }; @@ -410,6 +870,7 @@ /* Begin XCBuildConfiguration section */ DB13B1601849DEB70010F42D /* Debug */ = { +<<<<<<< HEAD isa = XCBuildConfiguration; buildSettings = { HEADER_SEARCH_PATHS = ( @@ -439,6 +900,66 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; +======= + isa = XCBuildConfiguration; + buildSettings = { + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + darwin_common/include, + ); + ONLY_ACTIVE_ARCH = YES; + }; + name = Debug; + }; + DB13B1611849DEB70010F42D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + darwin_common/include, + ); + }; + name = Release; + }; + DB13B1871849DF1E0010F42D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -449,8 +970,85 @@ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DSTROOT = /tmp/ffi.dst; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + darwin_ios/include, + ); + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + PRODUCT_NAME = ffi; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + VALID_ARCHS = "arm64 armv7 armv7s x86_64"; + }; + name = Debug; + }; + DB13B1881849DF1E0010F42D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DSTROOT = /tmp/ffi.dst; + ENABLE_NS_ASSERTIONS = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + darwin_ios/include, + ); + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + PRODUCT_NAME = ffi; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + VALIDATE_PRODUCT = YES; + VALID_ARCHS = "arm64 armv7 armv7s x86_64"; + }; + name = Release; + }; + DB13B1B11849DF520010F42D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", @@ -465,6 +1063,94 @@ GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", + darwin_osx/include, + ); + MACOSX_DEPLOYMENT_TARGET = 10.6; + ONLY_ACTIVE_ARCH = YES; + OTHER_LDFLAGS = "-Wl,-no_compact_unwind"; + PRODUCT_NAME = ffi; + SDKROOT = macosx; + }; + name = Debug; + }; + DB13B1B21849DF520010F42D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + darwin_osx/include, + ); + MACOSX_DEPLOYMENT_TARGET = 10.6; + OTHER_LDFLAGS = "-Wl,-no_compact_unwind"; + PRODUCT_NAME = ffi; + SDKROOT = macosx; + }; + name = Release; + }; + FDB52FC31F6144FA00AA92E6 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; +<<<<<<< HEAD + DSTROOT = /tmp/ffi.dst; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); +<<<<<<< HEAD + GCC_SYMBOLS_PRIVATE_EXTERN = NO; +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", +<<<<<<< HEAD "darwin_ios/include", ); IPHONEOS_DEPLOYMENT_TARGET = 5.0; @@ -485,6 +1171,21 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; +======= + darwin_ios/include, + ); + PRODUCT_NAME = ffi; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TVOS_DEPLOYMENT_TARGET = 9.0; + }; + name = Debug; + }; + FDB52FC41F6144FA00AA92E6 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; @@ -494,9 +1195,13 @@ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = YES; +<<<<<<< HEAD DSTROOT = /tmp/ffi.dst; ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = gnu99; +======= + ENABLE_NS_ASSERTIONS = NO; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -505,6 +1210,7 @@ GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", +<<<<<<< HEAD "darwin_ios/include", ); IPHONEOS_DEPLOYMENT_TARGET = 5.0; @@ -513,11 +1219,23 @@ PRODUCT_NAME = ffi; SDKROOT = iphoneos; SKIP_INSTALL = YES; +======= + darwin_ios/include, + ); + PRODUCT_NAME = ffi; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + TVOS_DEPLOYMENT_TARGET = 9.0; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 VALIDATE_PRODUCT = YES; }; name = Release; }; +<<<<<<< HEAD DB13B1B11849DF520010F42D /* Debug */ = { +======= + FDDB2F601F5D846400EF414E /* Debug */ = { +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -532,9 +1250,16 @@ CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; +<<<<<<< HEAD COPY_PHASE_STRIP = NO; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; +======= + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = NO; + EXECUTABLE_EXTENSION = a; + EXECUTABLE_PREFIX = lib; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_OBJC_EXCEPTIONS = YES; @@ -552,17 +1277,29 @@ GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", +<<<<<<< HEAD "darwin_osx/include", ); MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = "-Wl,-no_compact_unwind"; +======= + darwin_osx/include, + ); + MACH_O_TYPE = staticlib; + MACOSX_DEPLOYMENT_TARGET = 10.6; + ONLY_ACTIVE_ARCH = YES; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 PRODUCT_NAME = ffi; SDKROOT = macosx; }; name = Debug; }; +<<<<<<< HEAD DB13B1B21849DF520010F42D /* Release */ = { +======= + FDDB2F611F5D846400EF414E /* Release */ = { +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; @@ -577,11 +1314,20 @@ CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; +<<<<<<< HEAD COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; ENABLE_NS_ASSERTIONS = NO; +======= + COMBINE_HIDPI_IMAGES = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + EXECUTABLE_EXTENSION = a; + EXECUTABLE_PREFIX = lib; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 GCC_C_LANGUAGE_STANDARD = gnu99; GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -592,10 +1338,17 @@ GCC_WARN_UNUSED_VARIABLE = YES; HEADER_SEARCH_PATHS = ( "$(inherited)", +<<<<<<< HEAD "darwin_osx/include", ); MACOSX_DEPLOYMENT_TARGET = 10.6; OTHER_LDFLAGS = "-Wl,-no_compact_unwind"; +======= + darwin_osx/include, + ); + MACH_O_TYPE = staticlib; + MACOSX_DEPLOYMENT_TARGET = 10.6; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 PRODUCT_NAME = ffi; SDKROOT = macosx; }; @@ -605,6 +1358,12 @@ /* Begin XCConfigurationList section */ DB13B15F1849DEB70010F42D /* Build configuration list for PBXProject "libffi" */ = { +<<<<<<< HEAD + isa = XCConfigurationList; + buildConfigurations = ( + DB13B1601849DEB70010F42D /* Debug */, + DB13B1611849DEB70010F42D /* Release */, +======= isa = XCConfigurationList; buildConfigurations = ( DB13B1601849DEB70010F42D /* Debug */, @@ -627,6 +1386,41 @@ buildConfigurations = ( DB13B1B11849DF520010F42D /* Debug */, DB13B1B21849DF520010F42D /* Release */, +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +<<<<<<< HEAD + DB13B18B1849DF1E0010F42D /* Build configuration list for PBXNativeTarget "libffi-iOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DB13B1871849DF1E0010F42D /* Debug */, + DB13B1881849DF1E0010F42D /* Release */, +======= + FDB52FC21F6144FA00AA92E6 /* Build configuration list for PBXNativeTarget "libffi-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDB52FC31F6144FA00AA92E6 /* Debug */, + FDB52FC41F6144FA00AA92E6 /* Release */, +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +<<<<<<< HEAD + DB13B1B01849DF520010F42D /* Build configuration list for PBXNativeTarget "libffi-Mac" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DB13B1B11849DF520010F42D /* Debug */, + DB13B1B21849DF520010F42D /* Release */, +======= + FDDB2F5F1F5D846400EF414E /* Build configuration list for PBXNativeTarget "libffi-static-Mac" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FDDB2F601F5D846400EF414E /* Debug */, + FDDB2F611F5D846400EF414E /* Release */, +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/native/libffi/libtool-version b/native/libffi/libtool-version index 149a51a2ab..e365bacf94 100644 --- a/native/libffi/libtool-version +++ b/native/libffi/libtool-version @@ -26,4 +26,8 @@ # release, then set age to 0. # # CURRENT:REVISION:AGE +<<<<<<< HEAD 6:4:0 +======= +9:0:1 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 diff --git a/native/libffi/m4/asmcfi.m4 b/native/libffi/m4/asmcfi.m4 index dbf73a0b3e..3e28602274 100644 --- a/native/libffi/m4/asmcfi.m4 +++ b/native/libffi/m4/asmcfi.m4 @@ -2,7 +2,7 @@ AC_DEFUN([GCC_AS_CFI_PSEUDO_OP], [AC_CACHE_CHECK([assembler .cfi pseudo-op support], gcc_cv_as_cfi_pseudo_op, [ gcc_cv_as_cfi_pseudo_op=unknown - AC_TRY_COMPILE([asm (".cfi_startproc\n\t.cfi_endproc");],, + AC_TRY_COMPILE([asm (".cfi_sections\n\t.cfi_startproc\n\t.cfi_endproc");],, [gcc_cv_as_cfi_pseudo_op=yes], [gcc_cv_as_cfi_pseudo_op=no]) ]) diff --git a/native/libffi/m4/ax_append_flag.m4 b/native/libffi/m4/ax_append_flag.m4 index 1d38b76fb8..dd6d8b6140 100644 --- a/native/libffi/m4/ax_append_flag.m4 +++ b/native/libffi/m4/ax_append_flag.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_append_flag.html +# https://www.gnu.org/software/autoconf-archive/ax_append_flag.html # =========================================================================== # # SYNOPSIS @@ -23,47 +23,28 @@ # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2011 Maarten Bosmans # -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. -#serial 2 +#serial 8 AC_DEFUN([AX_APPEND_FLAG], -[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX -AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])dnl -AS_VAR_SET_IF(FLAGS, - [case " AS_VAR_GET(FLAGS) " in - *" $1 "*) - AC_RUN_LOG([: FLAGS already contains $1]) - ;; - *) - AC_RUN_LOG([: FLAGS="$FLAGS $1"]) - AS_VAR_SET(FLAGS, ["AS_VAR_GET(FLAGS) $1"]) - ;; - esac], - [AS_VAR_SET(FLAGS,["$1"])]) +[dnl +AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF +AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])]) +AS_VAR_SET_IF(FLAGS,[ + AS_CASE([" AS_VAR_GET(FLAGS) "], + [*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])], + [ + AS_VAR_APPEND(FLAGS,[" $1"]) + AC_RUN_LOG([: FLAGS="$FLAGS"]) + ]) + ], + [ + AS_VAR_SET(FLAGS,[$1]) + AC_RUN_LOG([: FLAGS="$FLAGS"]) + ]) AS_VAR_POPDEF([FLAGS])dnl ])dnl AX_APPEND_FLAG diff --git a/native/libffi/m4/ax_cc_maxopt.m4 b/native/libffi/m4/ax_cc_maxopt.m4 index 62e3b5330b..9e7f1ee4a1 100644 --- a/native/libffi/m4/ax_cc_maxopt.m4 +++ b/native/libffi/m4/ax_cc_maxopt.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_cc_maxopt.html +# https://www.gnu.org/software/autoconf-archive/ax_cc_maxopt.html # =========================================================================== # # SYNOPSIS @@ -40,7 +40,7 @@ # Public License for more details. # # You should have received a copy of the GNU General Public License along -# with this program. If not, see . +# with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure @@ -55,7 +55,7 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 13 +#serial 17 AC_DEFUN([AX_CC_MAXOPT], [ @@ -115,11 +115,19 @@ if test "$ac_test_CFLAGS" != "set"; then AX_GCC_X86_CPUID(0) AX_GCC_X86_CPUID(1) case $ax_cv_gcc_x86_cpuid_0 in # see AX_GCC_ARCHFLAG - *:756e6547:*:*) # Intel + *:756e6547:6c65746e:49656e69) # Intel case $ax_cv_gcc_x86_cpuid_1 in - *6a?:*[[234]]:*:*|*6[[789b]]?:*:*:*) icc_flags="-xK";; - *f3[[347]]:*:*:*|*f4[1347]:*:*:*) icc_flags="-xP -xN -xW -xK";; - *f??:*:*:*) icc_flags="-xN -xW -xK";; + *0?6[[78ab]]?:*:*:*|?6[[78ab]]?:*:*:*|6[[78ab]]?:*:*:*) icc_flags="-xK" ;; + *0?6[[9d]]?:*:*:*|?6[[9d]]?:*:*:*|6[[9d]]?:*:*:*|*1?65?:*:*:*) icc_flags="-xSSE2 -xB -xK" ;; + *0?6e?:*:*:*|?6e?:*:*:*|6e?:*:*:*) icc_flags="-xSSE3 -xP -xO -xB -xK" ;; + *0?6f?:*:*:*|?6f?:*:*:*|6f?:*:*:*|*1?66?:*:*:*) icc_flags="-xSSSE3 -xT -xB -xK" ;; + *1?6[[7d]]?:*:*:*) icc_flags="-xSSE4.1 -xS -xT -xB -xK" ;; + *1?6[[aef]]?:*:*:*|*2?6[[5cef]]?:*:*:*) icc_flags="-xSSE4.2 -xS -xT -xB -xK" ;; + *2?6[[ad]]?:*:*:*) icc_flags="-xAVX -SSE4.2 -xS -xT -xB -xK" ;; + *3?6[[ae]]?:*:*:*) icc_flags="-xCORE-AVX-I -xAVX -SSE4.2 -xS -xT -xB -xK" ;; + *3?6[[cf]]?:*:*:*|*4?6[[56]]?:*:*:*) icc_flags="-xCORE-AVX2 -xCORE-AVX-I -xAVX -SSE4.2 -xS -xT -xB -xK" ;; + *000?f[[346]]?:*:*:*|?f[[346]]?:*:*:*|f[[346]]?:*:*:*) icc_flags="-xSSE3 -xP -xO -xN -xW -xK" ;; + *00??f??:*:*:*|??f??:*:*:*|?f??:*:*:*|f??:*:*:*) icc_flags="-xSSE2 -xN -xW -xK" ;; esac ;; esac ;; esac @@ -141,7 +149,7 @@ if test "$ac_test_CFLAGS" != "set"; then CFLAGS="-O3 -fomit-frame-pointer" # -malign-double for x86 systems - # LIBFFI -- DON'T DO THIS - CHANGES ABI + # libffi local change -- don't align double, as it changes the ABI # AX_CHECK_COMPILE_FLAG(-malign-double, CFLAGS="$CFLAGS -malign-double") # -fstrict-aliasing for gcc-2.95+ @@ -153,6 +161,11 @@ if test "$ac_test_CFLAGS" != "set"; then AX_GCC_ARCHFLAG($acx_maxopt_portable) ;; + + microsoft) + # default optimization flags for MSVC opt builds + CFLAGS="-O2" + ;; esac if test -z "$CFLAGS"; then diff --git a/native/libffi/m4/ax_cflags_warn_all.m4 b/native/libffi/m4/ax_cflags_warn_all.m4 index 0fa3e186b4..094577e458 100644 --- a/native/libffi/m4/ax_cflags_warn_all.m4 +++ b/native/libffi/m4/ax_cflags_warn_all.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_cflags_warn_all.html +# https://www.gnu.org/software/autoconf-archive/ax_cflags_warn_all.html # =========================================================================== # # SYNOPSIS @@ -43,7 +43,7 @@ # Public License for more details. # # You should have received a copy of the GNU General Public License along -# with this program. If not, see . +# with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure @@ -58,7 +58,7 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 14 +#serial 16 AC_DEFUN([AX_FLAGS_WARN_ALL],[dnl AS_VAR_PUSHDEF([FLAGS],[_AC_LANG_PREFIX[]FLAGS])dnl @@ -84,7 +84,7 @@ done FLAGS="$ac_save_[]FLAGS" ]) AS_VAR_POPDEF([FLAGS])dnl -AC_REQUIRE([AX_APPEND_FLAG]) +AX_REQUIRE_DEFINED([AX_APPEND_FLAG]) case ".$VAR" in .ok|.ok,*) m4_ifvaln($3,$3) ;; .|.no|.no,*) m4_default($4,[m4_ifval($2,[AX_APPEND_FLAG([$2], [$1])])]) ;; diff --git a/native/libffi/m4/ax_check_compile_flag.m4 b/native/libffi/m4/ax_check_compile_flag.m4 index c3a8d695a1..bd753b34d7 100644 --- a/native/libffi/m4/ax_check_compile_flag.m4 +++ b/native/libffi/m4/ax_check_compile_flag.m4 @@ -1,10 +1,10 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html +# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html # =========================================================================== # # SYNOPSIS # -# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS]) +# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT]) # # DESCRIPTION # @@ -19,6 +19,8 @@ # the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to # force the compiler to issue an error when a bad flag is given. # +# INPUT gives an alternative input source to AC_COMPILE_IFELSE. +# # NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this # macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG. # @@ -27,45 +29,24 @@ # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2011 Maarten Bosmans # -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. -#serial 2 +#serial 6 AC_DEFUN([AX_CHECK_COMPILE_FLAG], -[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS _AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1" - AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], + AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])], [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) -AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], +AS_VAR_IF(CACHEVAR,yes, [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl diff --git a/native/libffi/m4/ax_compiler_vendor.m4 b/native/libffi/m4/ax_compiler_vendor.m4 index 73e32ea9ef..73efdb0055 100644 --- a/native/libffi/m4/ax_compiler_vendor.m4 +++ b/native/libffi/m4/ax_compiler_vendor.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html +# https://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html # =========================================================================== # # SYNOPSIS @@ -29,7 +29,7 @@ # Public License for more details. # # You should have received a copy of the GNU General Public License along -# with this program. If not, see . +# with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure @@ -44,22 +44,25 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 11 +#serial 17 AC_DEFUN([AX_COMPILER_VENDOR], [AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor, + dnl Please add if possible support to ax_compiler_version.m4 [# note: don't check for gcc first since some other compilers define __GNUC__ vendors="intel: __ICC,__ECC,__INTEL_COMPILER ibm: __xlc__,__xlC__,__IBMC__,__IBMCPP__ pathscale: __PATHCC__,__PATHSCALE__ clang: __clang__ + cray: _CRAYC + fujitsu: __FUJITSU + sdcc: SDCC, __SDCC gnu: __GNUC__ sun: __SUNPRO_C,__SUNPRO_CC hp: __HP_cc,__HP_aCC dec: __DECC,__DECCXX,__DECC_VER,__DECCXX_VER - borland: __BORLANDC__,__TURBOC__ + borland: __BORLANDC__,__CODEGEARC__,__TURBOC__ comeau: __COMO__ - cray: _CRAYC kai: __KCC lcc: __LCC__ sgi: __sgi,sgi @@ -67,6 +70,7 @@ AC_DEFUN([AX_COMPILER_VENDOR], metrowerks: __MWERKS__ watcom: __WATCOMC__ portland: __PGI + tcc: __TINYC__ unknown: UNKNOWN" for ventest in $vendors; do case $ventest in diff --git a/native/libffi/m4/ax_configure_args.m4 b/native/libffi/m4/ax_configure_args.m4 index 0726b1bc8a..9237efea7a 100644 --- a/native/libffi/m4/ax_configure_args.m4 +++ b/native/libffi/m4/ax_configure_args.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_configure_args.html +# https://www.gnu.org/software/autoconf-archive/ax_configure_args.html # =========================================================================== # # SYNOPSIS @@ -15,7 +15,7 @@ # to rely on eval'ing $ac_configure_args however some old autoconf # versions do not provide that. To ensure maximum portability of autoconf # extension macros this helper can be AC_REQUIRE'd so that -# $ac_configure_args will alsways be present. +# $ac_configure_args will always be present. # # Sadly, the traditional "exec $SHELL" of the enable_builddir macros is # spoiled now and must be replaced by "eval + exit $?". @@ -31,36 +31,15 @@ # # Copyright (c) 2008 Guido U. Draheim # -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. -#serial 9 +#serial 14 AC_DEFUN([AX_CONFIGURE_ARGS],[ - # [$]@ is unsable in 2.60+ but earlier autoconf had no ac_configure_args + # [$]@ is unusable in 2.60+ but earlier autoconf had no ac_configure_args if test "${ac_configure_args+set}" != "set" ; then ac_configure_args= for ac_arg in ${1+"[$]@"}; do diff --git a/native/libffi/m4/ax_enable_builddir.m4 b/native/libffi/m4/ax_enable_builddir.m4 index 3cb2093718..d0106f6e0c 100644 --- a/native/libffi/m4/ax_enable_builddir.m4 +++ b/native/libffi/m4/ax_enable_builddir.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_enable_builddir.html +# https://www.gnu.org/software/autoconf-archive/ax_enable_builddir.html # =========================================================================== # # SYNOPSIS @@ -24,7 +24,7 @@ # toplevel builddir Makefile. It just copies the variables and # rule-targets, each extended with a default rule-execution that recurses # into the build directory of the current "HOST". You can override the -# auto-dection through `config.guess` and build-time of course, as in +# auto-detection through `config.guess` and build-time of course, as in # # make HOST=i386-mingw-cross # @@ -42,7 +42,7 @@ # into. Usually, the last one is the only one used. However, almost all # targets have an additional "*-all" rule which makes the script to # recurse into _all_ variants of the current HOST (!!) setting. The "-all" -# suffix can be overriden for the macro as well. +# suffix can be overridden for the macro as well. # # a special rule is only given for things like "dist" that will copy the # tarball from the builddir to the sourcedir (or $(PUB)) for reason of @@ -64,7 +64,7 @@ # Public License for more details. # # You should have received a copy of the GNU General Public License along -# with this program. If not, see . +# with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure @@ -79,10 +79,11 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 23 +#serial 30 AC_DEFUN([AX_ENABLE_BUILDDIR],[ AC_REQUIRE([AC_CANONICAL_HOST])[]dnl +AC_REQUIRE([AC_CANONICAL_TARGET])[]dnl AC_REQUIRE([AX_CONFIGURE_ARGS])[]dnl AC_REQUIRE([AM_AUX_DIR_EXPAND])[]dnl AC_BEFORE([$0],[AM_INIT_AUTOMAKE])dnl @@ -121,7 +122,11 @@ if test ".$srcdir" = ".." ; then test -f $srcdir/$cache_file && mv $srcdir/$cache_file . AC_MSG_RESULT(....exec $SHELL $srcdir/[$]0 "--srcdir=$srcdir" "--enable-builddir=$SUB" ${1+"[$]@"}) case "[$]0" in # restart +<<<<<<< HEAD [[\\/]]* | ?:[[\\/]]*) # Asbolute name +======= + [[\\/]]* | ?:[[\\/]]*) # Absolute name +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 eval $SHELL "'[$]0'" "'--srcdir=$srcdir'" "'--enable-builddir=$SUB'" $ac_configure_args ;; *) eval $SHELL "'$srcdir/[$]0'" "'--srcdir=$srcdir'" "'--enable-builddir=$SUB'" $ac_configure_args ;; esac ; exit $? diff --git a/native/libffi/m4/ax_gcc_archflag.m4 b/native/libffi/m4/ax_gcc_archflag.m4 index aab2661c30..cc2b6927e3 100644 --- a/native/libffi/m4/ax_gcc_archflag.m4 +++ b/native/libffi/m4/ax_gcc_archflag.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_gcc_archflag.html +# https://www.gnu.org/software/autoconf-archive/ax_gcc_archflag.html # =========================================================================== # # SYNOPSIS @@ -36,7 +36,8 @@ # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2008 Matteo Frigo -# Copyright (c) 2012 Tsukasa Oi +# Copyright (c) 2014 Tsukasa Oi +# Copyright (c) 2017-2018 Alexey Kopytov # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the @@ -49,7 +50,7 @@ # Public License for more details. # # You should have received a copy of the GNU General Public License along -# with this program. If not, see . +# with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure @@ -64,11 +65,13 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 11 +#serial 22 AC_DEFUN([AX_GCC_ARCHFLAG], [AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_SED]) +AC_REQUIRE([AX_COMPILER_VENDOR]) AC_ARG_WITH(gcc-arch, [AS_HELP_STRING([--with-gcc-arch=], [use architecture for gcc -march/-mtune, instead of guessing])], ax_gcc_arch=$withval, ax_gcc_arch=yes) @@ -85,63 +88,70 @@ if test "x$ax_gcc_arch" = xyes; then ax_gcc_arch="" if test "$cross_compiling" = no; then case $host_cpu in - i[[3456]]86*|x86_64*) # use cpuid codes + i[[3456]]86*|x86_64*|amd64*) # use cpuid codes AX_GCC_X86_CPUID(0) AX_GCC_X86_CPUID(1) case $ax_cv_gcc_x86_cpuid_0 in - *:756e6547:*:*) # Intel + *:756e6547:6c65746e:49656e69) # Intel case $ax_cv_gcc_x86_cpuid_1 in - *5[[48]]?:*:*:*) ax_gcc_arch="pentium-mmx pentium" ;; - *5??:*:*:*) ax_gcc_arch=pentium ;; - *0?6[[3456]]?:*:*:*) ax_gcc_arch="pentium2 pentiumpro" ;; - *0?6a?:*[[01]]:*:*) ax_gcc_arch="pentium2 pentiumpro" ;; - *0?6a?:*[[234]]:*:*) ax_gcc_arch="pentium3 pentiumpro" ;; - *0?6[[9de]]?:*:*:*) ax_gcc_arch="pentium-m pentium3 pentiumpro" ;; - *0?6[[78b]]?:*:*:*) ax_gcc_arch="pentium3 pentiumpro" ;; - *0?6f?:*:*:*|*1?66?:*:*:*) ax_gcc_arch="core2 pentium-m pentium3 pentiumpro" ;; + *5[[4578]]?:*:*:*) ax_gcc_arch="pentium-mmx pentium" ;; + *5[[123]]?:*:*:*) ax_gcc_arch=pentium ;; + *0?61?:*:*:*|?61?:*:*:*|61?:*:*:*) ax_gcc_arch=pentiumpro ;; + *0?6[[356]]?:*:*:*|?6[[356]]?:*:*:*|6[[356]]?:*:*:*) ax_gcc_arch="pentium2 pentiumpro" ;; + *0?6[[78ab]]?:*:*:*|?6[[78ab]]?:*:*:*|6[[78ab]]?:*:*:*) ax_gcc_arch="pentium3 pentiumpro" ;; + *0?6[[9d]]?:*:*:*|?6[[9d]]?:*:*:*|6[[9d]]?:*:*:*|*1?65?:*:*:*) ax_gcc_arch="pentium-m pentium3 pentiumpro" ;; + *0?6e?:*:*:*|?6e?:*:*:*|6e?:*:*:*) ax_gcc_arch="yonah pentium-m pentium3 pentiumpro" ;; + *0?6f?:*:*:*|?6f?:*:*:*|6f?:*:*:*|*1?66?:*:*:*) ax_gcc_arch="core2 pentium-m pentium3 pentiumpro" ;; *1?6[[7d]]?:*:*:*) ax_gcc_arch="penryn core2 pentium-m pentium3 pentiumpro" ;; - *1?6[[aef]]?:*:*:*|*2?6[[5cef]]?:*:*:*) ax_gcc_arch="corei7 core2 pentium-m pentium3 pentiumpro" ;; - *1?6c?:*:*:*|*[[23]]?66?:*:*:*) ax_gcc_arch="atom core2 pentium-m pentium3 pentiumpro" ;; - *2?6[[ad]]?:*:*:*) ax_gcc_arch="corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;; - *0?6??:*:*:*) ax_gcc_arch=pentiumpro ;; - *6??:*:*:*) ax_gcc_arch="core2 pentiumpro" ;; - ?000?f3[[347]]:*:*:*|?000?f4[1347]:*:*:*|?000?f6?:*:*:*) - case $host_cpu in - x86_64*) ax_gcc_arch="nocona pentium4 pentiumpro" ;; - *) ax_gcc_arch="prescott pentium4 pentiumpro" ;; - esac ;; - ?000?f??:*:*:*) ax_gcc_arch="pentium4 pentiumpro";; + *1?6[[aef]]?:*:*:*|*2?6e?:*:*:*) ax_gcc_arch="nehalem corei7 core2 pentium-m pentium3 pentiumpro" ;; + *2?6[[5cf]]?:*:*:*) ax_gcc_arch="westmere corei7 core2 pentium-m pentium3 pentiumpro" ;; + *2?6[[ad]]?:*:*:*) ax_gcc_arch="sandybridge corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;; + *3?6[[ae]]?:*:*:*) ax_gcc_arch="ivybridge core-avx-i corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;; + *3?6[[cf]]?:*:*:*|*4?6[[56]]?:*:*:*) ax_gcc_arch="haswell core-avx2 core-avx-i corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;; + *3?6d?:*:*:*|*4?6[[7f]]?:*:*:*|*5?66?:*:*:*) ax_gcc_arch="broadwell core-avx2 core-avx-i corei7-avx corei7 core2 pentium-m pentium3 pentiumpro" ;; + *1?6c?:*:*:*|*2?6[[67]]?:*:*:*|*3?6[[56]]?:*:*:*) ax_gcc_arch="bonnell atom core2 pentium-m pentium3 pentiumpro" ;; + *3?67?:*:*:*|*[[45]]?6[[ad]]?:*:*:*) ax_gcc_arch="silvermont atom core2 pentium-m pentium3 pentiumpro" ;; + *000?f[[012]]?:*:*:*|?f[[012]]?:*:*:*|f[[012]]?:*:*:*) ax_gcc_arch="pentium4 pentiumpro" ;; + *000?f[[346]]?:*:*:*|?f[[346]]?:*:*:*|f[[346]]?:*:*:*) ax_gcc_arch="nocona prescott pentium4 pentiumpro" ;; + # fallback + *5??:*:*:*) ax_gcc_arch=pentium ;; + *??6??:*:*:*) ax_gcc_arch="core2 pentiumpro" ;; + *6??:*:*:*) ax_gcc_arch=pentiumpro ;; + *00??f??:*:*:*|??f??:*:*:*|?f??:*:*:*|f??:*:*:*) ax_gcc_arch="pentium4 pentiumpro" ;; esac ;; - *:68747541:*:*) # AMD + *:68747541:444d4163:69746e65) # AMD case $ax_cv_gcc_x86_cpuid_1 in *5[[67]]?:*:*:*) ax_gcc_arch=k6 ;; - *5[[8d]]?:*:*:*) ax_gcc_arch="k6-2 k6" ;; - *5[[9]]?:*:*:*) ax_gcc_arch="k6-3 k6" ;; - *60?:*:*:*) ax_gcc_arch=k7 ;; + *5[[8]]?:*:*:*) ax_gcc_arch="k6-2 k6" ;; + *5[[9d]]?:*:*:*) ax_gcc_arch="k6-3 k6" ;; *6[[12]]?:*:*:*) ax_gcc_arch="athlon k7" ;; *6[[34]]?:*:*:*) ax_gcc_arch="athlon-tbird k7" ;; - *67?:*:*:*) ax_gcc_arch="athlon-4 athlon k7" ;; - *6[[68a]]?:*:*:*) - AX_GCC_X86_CPUID(0x80000006) # L2 cache size - case $ax_cv_gcc_x86_cpuid_0x80000006 in - *:*:*[[1-9a-f]]??????:*) # (L2 = ecx >> 16) >= 256 - ax_gcc_arch="athlon-xp athlon-4 athlon k7" ;; - *) ax_gcc_arch="athlon-4 athlon k7" ;; - esac ;; - ?00??f[[4cef8b]]?:*:*:*) ax_gcc_arch="athlon64 k8" ;; - ?00??f5?:*:*:*) ax_gcc_arch="opteron k8" ;; - ?00??f7?:*:*:*) ax_gcc_arch="athlon-fx opteron k8" ;; - ?00??f??:*:*:*) ax_gcc_arch="k8" ;; - ?05??f??:*:*:*) ax_gcc_arch="btver1 amdfam10 k8" ;; - ?06??f??:*:*:*) ax_gcc_arch="bdver1 amdfam10 k8" ;; - *f??:*:*:*) ax_gcc_arch="amdfam10 k8" ;; + *6[[678a]]?:*:*:*) ax_gcc_arch="athlon-xp athlon-4 athlon k7" ;; + *000?f[[4578bcef]]?:*:*:*|?f[[4578bcef]]?:*:*:*|f[[4578bcef]]?:*:*:*|*001?f[[4578bcf]]?:*:*:*|1?f[[4578bcf]]?:*:*:*) ax_gcc_arch="athlon64 k8" ;; + *002?f[[13457bcf]]?:*:*:*|2?f[[13457bcf]]?:*:*:*|*004?f[[138bcf]]?:*:*:*|4?f[[138bcf]]?:*:*:*|*005?f[[df]]?:*:*:*|5?f[[df]]?:*:*:*|*006?f[[8bcf]]?:*:*:*|6?f[[8bcf]]?:*:*:*|*007?f[[cf]]?:*:*:*|7?f[[cf]]?:*:*:*|*00c?f1?:*:*:*|c?f1?:*:*:*|*020?f3?:*:*:*|20?f3?:*:*:*) ax_gcc_arch="athlon64-sse3 k8-sse3 athlon64 k8" ;; + *010?f[[245689a]]?:*:*:*|10?f[[245689a]]?:*:*:*|*030?f1?:*:*:*|30?f1?:*:*:*) ax_gcc_arch="barcelona amdfam10 k8" ;; + *050?f[[12]]?:*:*:*|50?f[[12]]?:*:*:*) ax_gcc_arch="btver1 amdfam10 k8" ;; + *060?f1?:*:*:*|60?f1?:*:*:*) ax_gcc_arch="bdver1 amdfam10 k8" ;; + *060?f2?:*:*:*|60?f2?:*:*:*|*061?f[[03]]?:*:*:*|61?f[[03]]?:*:*:*) ax_gcc_arch="bdver2 bdver1 amdfam10 k8" ;; + *063?f0?:*:*:*|63?f0?:*:*:*) ax_gcc_arch="bdver3 bdver2 bdver1 amdfam10 k8" ;; + *07[[03]]?f0?:*:*:*|7[[03]]?f0?:*:*:*) ax_gcc_arch="btver2 btver1 amdfam10 k8" ;; + # fallback + *0[[13]]??f??:*:*:*|[[13]]??f??:*:*:*) ax_gcc_arch="barcelona amdfam10 k8" ;; + *020?f??:*:*:*|20?f??:*:*:*) ax_gcc_arch="athlon64-sse3 k8-sse3 athlon64 k8" ;; + *05??f??:*:*:*|5??f??:*:*:*) ax_gcc_arch="btver1 amdfam10 k8" ;; + *060?f??:*:*:*|60?f??:*:*:*) ax_gcc_arch="bdver1 amdfam10 k8" ;; + *061?f??:*:*:*|61?f??:*:*:*) ax_gcc_arch="bdver2 bdver1 amdfam10 k8" ;; + *06??f??:*:*:*|6??f??:*:*:*) ax_gcc_arch="bdver3 bdver2 bdver1 amdfam10 k8" ;; + *070?f??:*:*:*|70?f??:*:*:*) ax_gcc_arch="btver2 btver1 amdfam10 k8" ;; + *???f??:*:*:*) ax_gcc_arch="amdfam10 k8" ;; esac ;; - *:746e6543:*:*) # IDT + *:746e6543:736c7561:48727561) # IDT / VIA (Centaur) case $ax_cv_gcc_x86_cpuid_1 in *54?:*:*:*) ax_gcc_arch=winchip-c6 ;; - *58?:*:*:*) ax_gcc_arch=winchip2 ;; + *5[[89]]?:*:*:*) ax_gcc_arch=winchip2 ;; + *66?:*:*:*) ax_gcc_arch=winchip2 ;; *6[[78]]?:*:*:*) ax_gcc_arch=c3 ;; - *69?:*:*:*) ax_gcc_arch="c3-2 c3" ;; + *6[[9adf]]?:*:*:*) ax_gcc_arch="c3-2 c3" ;; esac ;; esac if test x"$ax_gcc_arch" = x; then # fallback @@ -155,7 +165,11 @@ case $host_cpu in sparc*) AC_PATH_PROG([PRTDIAG], [prtdiag], [prtdiag], [$PATH:/usr/platform/`uname -i`/sbin/:/usr/platform/`uname -m`/sbin/]) cputype=`(((grep cpu /proc/cpuinfo | cut -d: -f2) ; ($PRTDIAG -v |grep -i sparc) ; grep -i cpu /var/run/dmesg.boot ) | head -n 1) 2> /dev/null` +<<<<<<< HEAD cputype=`echo "$cputype" | tr -d ' -' | sed 's/SPARCIIi/SPARCII/' | tr $as_cr_LETTERS $as_cr_letters` +======= + cputype=`echo "$cputype" | tr -d ' -' | $SED 's/SPARCIIi/SPARCII/' |tr $as_cr_LETTERS $as_cr_letters` +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 case $cputype in *ultrasparciv*) ax_gcc_arch="ultrasparc4 ultrasparc3 ultrasparc v9" ;; *ultrasparciii*) ax_gcc_arch="ultrasparc3 ultrasparc v9" ;; @@ -177,8 +191,8 @@ case $host_cpu in alphaev79) ax_gcc_arch="ev79 ev7 ev69 ev68 ev67" ;; powerpc*) - cputype=`((grep cpu /proc/cpuinfo | head -n 1 | cut -d: -f2 | cut -d, -f1 | sed 's/ //g') ; /usr/bin/machine ; /bin/machine; grep CPU /var/run/dmesg.boot | head -n 1 | cut -d" " -f2) 2> /dev/null` - cputype=`echo $cputype | sed -e 's/ppc//g;s/ *//g'` + cputype=`((grep cpu /proc/cpuinfo | head -n 1 | cut -d: -f2 | cut -d, -f1 | $SED 's/ //g') ; /usr/bin/machine ; /bin/machine; grep CPU /var/run/dmesg.boot | head -n 1 | cut -d" " -f2) 2> /dev/null` + cputype=`echo $cputype | $SED -e 's/ppc//g;s/ *//g'` case $cputype in *750*) ax_gcc_arch="750 G3" ;; *740[[0-9]]*) ax_gcc_arch="$cputype 7400 G4" ;; @@ -188,26 +202,58 @@ case $host_cpu in *POWER4*|*power4*|*gq*) ax_gcc_arch="power4 970";; *POWER5*|*power5*|*gr*|*gs*) ax_gcc_arch="power5 power4 970";; 603ev|8240) ax_gcc_arch="$cputype 603e 603";; + *POWER7*) ax_gcc_arch="power7";; + *POWER8*) ax_gcc_arch="power8";; + *POWER9*) ax_gcc_arch="power9";; + *POWER10*) ax_gcc_arch="power10";; *) ax_gcc_arch=$cputype ;; esac ax_gcc_arch="$ax_gcc_arch powerpc" ;; + aarch64) + cpuimpl=`grep 'CPU implementer' /proc/cpuinfo 2> /dev/null | cut -d: -f2 | tr -d " " | head -n 1` + cpuarch=`grep 'CPU architecture' /proc/cpuinfo 2> /dev/null | cut -d: -f2 | tr -d " " | head -n 1` + cpuvar=`grep 'CPU variant' /proc/cpuinfo 2> /dev/null | cut -d: -f2 | tr -d " " | head -n 1` + case $cpuimpl in + 0x42) case $cpuarch in + 8) case $cpuvar in + 0x0) ax_gcc_arch="thunderx2t99 vulcan armv8.1-a armv8-a+lse armv8-a native" ;; + esac + ;; + esac + ;; + 0x43) case $cpuarch in + 8) case $cpuvar in + 0x0) ax_gcc_arch="thunderx armv8-a native" ;; + 0x1) ax_gcc_arch="thunderx+lse armv8.1-a armv8-a+lse armv8-a native" ;; + esac + ;; + esac + ;; + esac + ;; esac fi # not cross-compiling fi # guess arch if test "x$ax_gcc_arch" != x -a "x$ax_gcc_arch" != xno; then -for arch in $ax_gcc_arch; do - if test "x[]m4_default([$1],yes)" = xyes; then # if we require portable code - flags="-mtune=$arch" - # -mcpu=$arch and m$arch generate nonportable code on every arch except - # x86. And some other arches (e.g. Alpha) don't accept -mtune. Grrr. - case $host_cpu in i*86|x86_64*) flags="$flags -mcpu=$arch -m$arch";; esac - else - flags="-march=$arch -mcpu=$arch -m$arch" - fi - for flag in $flags; do - AX_CHECK_COMPILE_FLAG($flag, [ax_cv_gcc_archflag=$flag; break]) +if test "x[]m4_default([$1],yes)" = xyes; then # if we require portable code + flag_prefixes="-mtune=" + if test "x$ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor" = xclang; then flag_prefixes="-march="; fi + # -mcpu=$arch and m$arch generate nonportable code on every arch except + # x86. And some other arches (e.g. Alpha) don't accept -mtune. Grrr. + case $host_cpu in i*86|x86_64*|amd64*) flag_prefixes="$flag_prefixes -mcpu= -m";; esac +else + flag_prefixes="-march= -mcpu= -m" +fi +for flag_prefix in $flag_prefixes; do + for arch in $ax_gcc_arch; do + flag="$flag_prefix$arch" + AX_CHECK_COMPILE_FLAG($flag, [if test "x$ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor" = xclang; then + if test "x[]m4_default([$1],yes)" = xyes; then + if test "x$flag" = "x-march=$arch"; then flag=-mtune=$arch; fi + fi + fi; ax_cv_gcc_archflag=$flag; break]) done test "x$ax_cv_gcc_archflag" = xunknown || break done diff --git a/native/libffi/m4/ax_gcc_x86_cpuid.m4 b/native/libffi/m4/ax_gcc_x86_cpuid.m4 index 7d46fee021..df954658ee 100644 --- a/native/libffi/m4/ax_gcc_x86_cpuid.m4 +++ b/native/libffi/m4/ax_gcc_x86_cpuid.m4 @@ -1,17 +1,19 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_gcc_x86_cpuid.html +# https://www.gnu.org/software/autoconf-archive/ax_gcc_x86_cpuid.html # =========================================================================== # # SYNOPSIS # # AX_GCC_X86_CPUID(OP) +# AX_GCC_X86_CPUID_COUNT(OP, COUNT) # # DESCRIPTION # # On Pentium and later x86 processors, with gcc or a compiler that has a # compatible syntax for inline assembly instructions, run a small program # that executes the cpuid instruction with input OP. This can be used to -# detect the CPU type. +# detect the CPU type. AX_GCC_X86_CPUID_COUNT takes an additional COUNT +# parameter that gets passed into register ECX before calling cpuid. # # On output, the values of the eax, ebx, ecx, and edx registers are stored # as hexadecimal strings as "eax:ebx:ecx:edx" in the cache variable @@ -28,6 +30,7 @@ # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2008 Matteo Frigo +# Copyright (c) 2015 Michael Petch # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the @@ -40,7 +43,7 @@ # Public License for more details. # # You should have received a copy of the GNU General Public License along -# with this program. If not, see . +# with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure @@ -55,18 +58,25 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 7 +#serial 10 AC_DEFUN([AX_GCC_X86_CPUID], +[AX_GCC_X86_CPUID_COUNT($1, 0) +]) + +AC_DEFUN([AX_GCC_X86_CPUID_COUNT], [AC_REQUIRE([AC_PROG_CC]) AC_LANG_PUSH([C]) AC_CACHE_CHECK(for x86 cpuid $1 output, ax_cv_gcc_x86_cpuid_$1, [AC_RUN_IFELSE([AC_LANG_PROGRAM([#include ], [ - int op = $1, eax, ebx, ecx, edx; + int op = $1, level = $2, eax, ebx, ecx, edx; FILE *f; - __asm__("cpuid" - : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) - : "a" (op)); + __asm__ __volatile__ ("xchg %%ebx, %1\n" + "cpuid\n" + "xchg %%ebx, %1\n" + : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx) + : "a" (op), "2" (level)); + f = fopen("conftest_cpuid", "w"); if (!f) return 1; fprintf(f, "%x:%x:%x:%x\n", eax, ebx, ecx, edx); fclose(f); diff --git a/native/libffi/m4/ax_require_defined.m4 b/native/libffi/m4/ax_require_defined.m4 new file mode 100644 index 0000000000..17c3eab7da --- /dev/null +++ b/native/libffi/m4/ax_require_defined.m4 @@ -0,0 +1,37 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_require_defined.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_REQUIRE_DEFINED(MACRO) +# +# DESCRIPTION +# +# AX_REQUIRE_DEFINED is a simple helper for making sure other macros have +# been defined and thus are available for use. This avoids random issues +# where a macro isn't expanded. Instead the configure script emits a +# non-fatal: +# +# ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found +# +# It's like AC_REQUIRE except it doesn't expand the required macro. +# +# Here's an example: +# +# AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG]) +# +# LICENSE +# +# Copyright (c) 2014 Mike Frysinger +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 2 + +AC_DEFUN([AX_REQUIRE_DEFINED], [dnl + m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])]) +])dnl AX_REQUIRE_DEFINED diff --git a/native/libffi/make_sunver.pl b/native/libffi/make_sunver.pl new file mode 100644 index 0000000000..8a90b1fea0 --- /dev/null +++ b/native/libffi/make_sunver.pl @@ -0,0 +1,333 @@ +#!/usr/bin/perl -w + +# make_sunver.pl +# +# This script takes at least two arguments, a GNU style version script and +# a list of object and archive files, and generates a corresponding Sun +# style version script as follows: +# +# Each glob pattern, C++ mangled pattern or literal in the input script is +# matched against all global symbols in the input objects, emitting those +# that matched (or nothing if no match was found). +# A comment with the original pattern and its type is left in the output +# file to make it easy to understand the matches. +# +# It uses elfdump when present (native), GNU readelf otherwise. +# It depends on the GNU version of c++filt, since it must understand the +# GNU mangling style. + +use FileHandle; +use IPC::Open2; + +# Enforce C locale. +$ENV{'LC_ALL'} = "C"; +$ENV{'LANG'} = "C"; + +# Input version script, GNU style. +my $symvers = shift; + +########## +# Get all the symbols from the library, match them, and add them to a hash. + +my %sym_hash = (); + +# List of objects and archives to process. +my @OBJECTS = (); + +# List of shared objects to omit from processing. +my @SHAREDOBJS = (); + +# Filter out those input archives that have corresponding shared objects to +# avoid adding all symbols matched in the archive to the output map. +foreach $file (@ARGV) { + if (($so = $file) =~ s/\.a$/.so/ && -e $so) { + printf STDERR "omitted $file -> $so\n"; + push (@SHAREDOBJS, $so); + } else { + push (@OBJECTS, $file); + } +} + +# We need to detect and ignore hidden symbols. Solaris nm can only detect +# this in the harder to parse default output format, and GNU nm not at all, +# so use elfdump -s in the native case and GNU readelf -s otherwise. +# GNU objdump -t cannot be used since it produces a variable number of +# columns. + +# The path to elfdump. +my $elfdump = "/usr/ccs/bin/elfdump"; + +if (-f $elfdump) { + open ELFDUMP,$elfdump.' -s '.(join ' ',@OBJECTS).'|' or die $!; + my $skip_arsym = 0; + + while () { + chomp; + + # Ignore empty lines. + if (/^$/) { + # End of archive symbol table, stop skipping. + $skip_arsym = 0 if $skip_arsym; + next; + } + + # Keep skipping until end of archive symbol table. + next if ($skip_arsym); + + # Ignore object name header for individual objects and archives. + next if (/:$/); + + # Ignore table header lines. + next if (/^Symbol Table Section:/); + next if (/index.*value.*size/); + + # Start of archive symbol table: start skipping. + if (/^Symbol Table: \(archive/) { + $skip_arsym = 1; + next; + } + + # Split table. + (undef, undef, undef, undef, $bind, $oth, undef, $shndx, $name) = split; + + # Error out for unknown input. + die "unknown input line:\n$_" unless defined($bind); + + # Ignore local symbols. + next if ($bind eq "LOCL"); + # Ignore hidden symbols. + next if ($oth eq "H"); + # Ignore undefined symbols. + next if ($shndx eq "UNDEF"); + # Error out for unhandled cases. + if ($bind !~ /^(GLOB|WEAK)/ or $oth ne "D") { + die "unhandled symbol:\n$_"; + } + + # Remember symbol. + $sym_hash{$name}++; + } + close ELFDUMP or die "$elfdump error"; +} else { + open READELF, 'readelf -s -W '.(join ' ',@OBJECTS).'|' or die $!; + # Process each symbol. + while () { + chomp; + + # Ignore empty lines. + next if (/^$/); + + # Ignore object name header. + next if (/^File: .*$/); + + # Ignore table header lines. + next if (/^Symbol table.*contains.*:/); + next if (/Num:.*Value.*Size/); + + # Split table. + (undef, undef, undef, undef, $bind, $vis, $ndx, $name) = split; + + # Error out for unknown input. + die "unknown input line:\n$_" unless defined($bind); + + # Ignore local symbols. + next if ($bind eq "LOCAL"); + # Ignore hidden symbols. + next if ($vis eq "HIDDEN"); + # Ignore undefined symbols. + next if ($ndx eq "UND"); + # Error out for unhandled cases. + if ($bind !~ /^(GLOBAL|WEAK)/ or $vis ne "DEFAULT") { + die "unhandled symbol:\n$_"; + } + + # Remember symbol. + $sym_hash{$name}++; + } + close READELF or die "readelf error"; +} + +########## +# The various types of glob patterns. +# +# A glob pattern that is to be applied to the demangled name: 'cxx'. +# A glob patterns that applies directly to the name in the .o files: 'glob'. +# This pattern is ignored; used for local variables (usually just '*'): 'ign'. + +# The type of the current pattern. +my $glob = 'glob'; + +# We're currently inside `extern "C++"', which Sun ld doesn't understand. +my $in_extern = 0; + +# The c++filt command to use. This *must* be GNU c++filt; the Sun Studio +# c++filt doesn't handle the GNU mangling style. +my $cxxfilt = $ENV{'CXXFILT'} || "c++filt"; + +# The current version name. +my $current_version = ""; + +# Was there any attempt to match a symbol to this version? +my $matches_attempted; + +# The number of versions which matched this symbol. +my $matched_symbols; + +open F,$symvers or die $!; + +# Print information about generating this file +print "# This file was generated by make_sunver.pl. DO NOT EDIT!\n"; +print "# It was generated by:\n"; +printf "# %s %s %s\n", $0, $symvers, (join ' ',@ARGV); +printf "# Omitted archives with corresponding shared libraries: %s\n", + (join ' ', @SHAREDOBJS) if $#SHAREDOBJS >= 0; +print "#\n\n"; + +while () { + # Lines of the form '};' + if (/^([ \t]*)(\}[ \t]*;[ \t]*)$/) { + $glob = 'glob'; + if ($in_extern) { + $in_extern--; + print "$1##$2\n"; + } else { + print; + } + next; + } + + # Lines of the form '} SOME_VERSION_NAME_1.0;' + if (/^[ \t]*\}[ \tA-Z0-9_.a-z]+;[ \t]*$/) { + $glob = 'glob'; + # We tried to match symbols agains this version, but none matched. + # Emit dummy hidden symbol to avoid marking this version WEAK. + if ($matches_attempted && $matched_symbols == 0) { + print " hidden:\n"; + print " .force_WEAK_off_$current_version = DATA S0x0 V0x0;\n"; + } + print; next; + } + + # Comment and blank lines + if (/^[ \t]*\#/) { print; next; } + if (/^[ \t]*$/) { print; next; } + + # Lines of the form '{' + if (/^([ \t]*){$/) { + if ($in_extern) { + print "$1##{\n"; + } else { + print; + } + next; + } + + # Lines of the form 'SOME_VERSION_NAME_1.1 {' + if (/^([A-Z0-9_.]+)[ \t]+{$/) { + # Record version name. + $current_version = $1; + # Reset match attempts, #matched symbols for this version. + $matches_attempted = 0; + $matched_symbols = 0; + print; + next; + } + + # Ignore 'global:' + if (/^[ \t]*global:$/) { print; next; } + + # After 'local:', globs should be ignored, they won't be exported. + if (/^[ \t]*local:$/) { + $glob = 'ign'; + print; + next; + } + + # After 'extern "C++"', globs are C++ patterns + if (/^([ \t]*)(extern \"C\+\+\"[ \t]*)$/) { + $in_extern++; + $glob = 'cxx'; + # Need to comment, Sun ld cannot handle this. + print "$1##$2\n"; next; + } + + # Chomp newline now we're done with passing through the input file. + chomp; + + # Catch globs. Note that '{}' is not allowed in globs by this script, + # so only '*' and '[]' are available. + if (/^([ \t]*)([^ \t;{}#]+);?[ \t]*$/) { + my $ws = $1; + my $ptn = $2; + # Turn the glob into a regex by replacing '*' with '.*', '?' with '.'. + # Keep $ptn so we can still print the original form. + ($pattern = $ptn) =~ s/\*/\.\*/g; + $pattern =~ s/\?/\./g; + + if ($glob eq 'ign') { + # We're in a local: * section; just continue. + print "$_\n"; + next; + } + + # Print the glob commented for human readers. + print "$ws##$ptn ($glob)\n"; + # We tried to match a symbol to this version. + $matches_attempted++; + + if ($glob eq 'glob') { + my %ptn_syms = (); + + # Match ptn against symbols in %sym_hash. + foreach my $sym (keys %sym_hash) { + # Maybe it matches one of the patterns based on the symbol in + # the .o file. + $ptn_syms{$sym}++ if ($sym =~ /^$pattern$/); + } + + foreach my $sym (sort keys(%ptn_syms)) { + $matched_symbols++; + print "$ws$sym;\n"; + } + } elsif ($glob eq 'cxx') { + my %dem_syms = (); + + # Verify that we're actually using GNU c++filt. Other versions + # most likely cannot handle GNU style symbol mangling. + my $cxxout = `$cxxfilt --version 2>&1`; + $cxxout =~ m/GNU/ or die "$0 requires GNU c++filt to function"; + + # Talk to c++filt through a pair of file descriptors. + # Need to start a fresh instance per pattern, otherwise the + # process grows to 500+ MB. + my $pid = open2(*FILTIN, *FILTOUT, $cxxfilt) or die $!; + + # Match ptn against symbols in %sym_hash. + foreach my $sym (keys %sym_hash) { + # No? Well, maybe its demangled form matches one of those + # patterns. + printf FILTOUT "%s\n",$sym; + my $dem = ; + chomp $dem; + $dem_syms{$sym}++ if ($dem =~ /^$pattern$/); + } + + close FILTOUT or die "c++filt error"; + close FILTIN or die "c++filt error"; + # Need to wait for the c++filt process to avoid lots of zombies. + waitpid $pid, 0; + + foreach my $sym (sort keys(%dem_syms)) { + $matched_symbols++; + print "$ws$sym;\n"; + } + } else { + # No? Well, then ignore it. + } + next; + } + # Important sanity check. This script can't handle lots of formats + # that GNU ld can, so be sure to error out if one is seen! + die "strange line `$_'"; +} +close F; diff --git a/native/libffi/msvc_build/aarch64/Ffi_staticLib.sln b/native/libffi/msvc_build/aarch64/Ffi_staticLib.sln new file mode 100644 index 0000000000..d9119dfac2 --- /dev/null +++ b/native/libffi/msvc_build/aarch64/Ffi_staticLib.sln @@ -0,0 +1,33 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28302.56 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Ffi_staticLib_arm64", "Ffi_staticLib.vcxproj", "{115502C0-BE05-4767-BF19-5C87D805FAD6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {115502C0-BE05-4767-BF19-5C87D805FAD6}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {115502C0-BE05-4767-BF19-5C87D805FAD6}.Debug|ARM64.Build.0 = Debug|ARM64 + {115502C0-BE05-4767-BF19-5C87D805FAD6}.Debug|x64.ActiveCfg = Debug|ARM64 + {115502C0-BE05-4767-BF19-5C87D805FAD6}.Debug|x86.ActiveCfg = Debug|ARM64 + {115502C0-BE05-4767-BF19-5C87D805FAD6}.Release|ARM64.ActiveCfg = Release|ARM64 + {115502C0-BE05-4767-BF19-5C87D805FAD6}.Release|ARM64.Build.0 = Release|ARM64 + {115502C0-BE05-4767-BF19-5C87D805FAD6}.Release|x64.ActiveCfg = Release|ARM64 + {115502C0-BE05-4767-BF19-5C87D805FAD6}.Release|x86.ActiveCfg = Release|ARM64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {241C54C7-20DD-4897-9376-E6B6D1B43BD5} + EndGlobalSection +EndGlobal diff --git a/native/libffi/msvc_build/aarch64/Ffi_staticLib.vcxproj b/native/libffi/msvc_build/aarch64/Ffi_staticLib.vcxproj new file mode 100644 index 0000000000..3187699ca1 --- /dev/null +++ b/native/libffi/msvc_build/aarch64/Ffi_staticLib.vcxproj @@ -0,0 +1,130 @@ + + + + + Debug + ARM64 + + + Release + ARM64 + + + + 15.0 + {115502C0-BE05-4767-BF19-5C87D805FAD6} + Win32Proj + FfistaticLib + 10.0.17763.0 + Ffi_staticLib_arm64 + + + + StaticLibrary + true + v141 + Unicode + + + StaticLibrary + false + v141 + true + Unicode + + + + + + + + + + + + + + + true + + + false + + + + NotUsing + Level3 + Disabled + true + FFI_BUILDING_DLL;_DEBUG;_LIB;USE_DL_PREFIX;ARM64;_M_ARM64;NDEBUG;%(PreprocessorDefinitions) + true + ..\..\include;.\aarch64_include;..\..\src\aarch64;%(AdditionalIncludeDirectories) + false + true + + + false + + + Windows + true + + + + + NotUsing + Level3 + MaxSpeed + true + true + true + FFI_BUILDING_DLL;USE_DL_PREFIX;ARM64;NDEBUG;_LIB;%(PreprocessorDefinitions) + true + ..\..\include;.\aarch64_include;..\..\src\aarch64;%(AdditionalIncludeDirectories) + true + Speed + true + ..\..\src;..\..\src\aarch64;%(AdditionalUsingDirectories) + + + Windows + true + true + true + + + true + + + + + + + + + + + + + + + + + + + + + + + cl /FA /EP /nologo /I"..\..\include" /I".\aarch64_include" /I"..\..\src\aarch64" "%(FullPath)" > $(IntDir)win64_armasm.i + armasm64 $(IntDir)win64_armasm.i /I"src\" /I"..\..\include" /I"..\..\src\aarch64" -o "$(IntDir)win64_armasm.obj" + + win64_armasm.obj;%(Outputs) + + + + + + \ No newline at end of file diff --git a/native/libffi/msvc_build/aarch64/Ffi_staticLib.vcxproj.filters b/native/libffi/msvc_build/aarch64/Ffi_staticLib.vcxproj.filters new file mode 100644 index 0000000000..1f8c6e13ef --- /dev/null +++ b/native/libffi/msvc_build/aarch64/Ffi_staticLib.vcxproj.filters @@ -0,0 +1,57 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + + \ No newline at end of file diff --git a/native/libffi/msvc_build/aarch64/Ffi_staticLib.vcxproj.user b/native/libffi/msvc_build/aarch64/Ffi_staticLib.vcxproj.user new file mode 100644 index 0000000000..be25078707 --- /dev/null +++ b/native/libffi/msvc_build/aarch64/Ffi_staticLib.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/native/libffi/msvc_build/aarch64/aarch64_include/ffi.h b/native/libffi/msvc_build/aarch64/aarch64_include/ffi.h new file mode 100644 index 0000000000..02f26a2f0f --- /dev/null +++ b/native/libffi/msvc_build/aarch64/aarch64_include/ffi.h @@ -0,0 +1,511 @@ +/* -----------------------------------------------------------------*-C-*- + libffi 3.3-rc0 - Copyright (c) 2011, 2014 Anthony Green + - Copyright (c) 1996-2003, 2007, 2008 Red Hat, Inc. + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the ``Software''), to deal in the Software without + restriction, including without limitation the rights to use, copy, + modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + ----------------------------------------------------------------------- */ + +/* ------------------------------------------------------------------- + Most of the API is documented in doc/libffi.texi. + + The raw API is designed to bypass some of the argument packing and + unpacking on architectures for which it can be avoided. Routines + are provided to emulate the raw API if the underlying platform + doesn't allow faster implementation. + + More details on the raw API can be found in: + + http://gcc.gnu.org/ml/java/1999-q3/msg00138.html + + and + + http://gcc.gnu.org/ml/java/1999-q3/msg00174.html + -------------------------------------------------------------------- */ + +#ifndef LIBFFI_H +#define LIBFFI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Specify which architecture libffi is configured for. */ +#ifndef AARCH64 +#define AARCH64 +#endif + +/* ---- System configuration information --------------------------------- */ + +#include + +#ifndef LIBFFI_ASM + +#if defined(_MSC_VER) && !defined(__clang__) +#define __attribute__(X) +#endif + +#include +#include + +/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example). + But we can find it either under the correct ANSI name, or under GNU + C's internal name. */ + +#define FFI_64_BIT_MAX 9223372036854775807 + +#ifdef LONG_LONG_MAX +# define FFI_LONG_LONG_MAX LONG_LONG_MAX +#else +# ifdef LLONG_MAX +# define FFI_LONG_LONG_MAX LLONG_MAX +# ifdef _AIX52 /* or newer has C99 LLONG_MAX */ +# undef FFI_64_BIT_MAX +# define FFI_64_BIT_MAX 9223372036854775807LL +# endif /* _AIX52 or newer */ +# else +# ifdef __GNUC__ +# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__ +# endif +# ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */ +# ifndef __PPC64__ +# if defined (__IBMC__) || defined (__IBMCPP__) +# define FFI_LONG_LONG_MAX LONGLONG_MAX +# endif +# endif /* __PPC64__ */ +# undef FFI_64_BIT_MAX +# define FFI_64_BIT_MAX 9223372036854775807LL +# endif +# endif +#endif + +/* The closure code assumes that this works on pointers, i.e. a size_t + can hold a pointer. */ + +typedef struct _ffi_type +{ + size_t size; + unsigned short alignment; + unsigned short type; + struct _ffi_type **elements; +} ffi_type; + +/* Need minimal decorations for DLLs to work on Windows. GCC has + autoimport and autoexport. Always mark externally visible symbols + as dllimport for MSVC clients, even if it means an extra indirection + when using the static version of the library. + Besides, as a workaround, they can define FFI_BUILDING if they + *know* they are going to link with the static library. */ +#if defined _MSC_VER +# if defined FFI_BUILDING_DLL /* Building libffi.DLL with msvcc.sh */ +# define FFI_API __declspec(dllexport) +# elif !defined FFI_BUILDING /* Importing libffi.DLL */ +# define FFI_API __declspec(dllimport) +# else /* Building/linking static library */ +# define FFI_API +# endif +#else +# define FFI_API +#endif + +/* The externally visible type declarations also need the MSVC DLL + decorations, or they will not be exported from the object file. */ +#if defined LIBFFI_HIDE_BASIC_TYPES +# define FFI_EXTERN FFI_API +#else +# define FFI_EXTERN extern FFI_API +#endif + +#ifndef LIBFFI_HIDE_BASIC_TYPES +#if SCHAR_MAX == 127 +# define ffi_type_uchar ffi_type_uint8 +# define ffi_type_schar ffi_type_sint8 +#else + #error "char size not supported" +#endif + +#if SHRT_MAX == 32767 +# define ffi_type_ushort ffi_type_uint16 +# define ffi_type_sshort ffi_type_sint16 +#elif SHRT_MAX == 2147483647 +# define ffi_type_ushort ffi_type_uint32 +# define ffi_type_sshort ffi_type_sint32 +#else + #error "short size not supported" +#endif + +#if INT_MAX == 32767 +# define ffi_type_uint ffi_type_uint16 +# define ffi_type_sint ffi_type_sint16 +#elif INT_MAX == 2147483647 +# define ffi_type_uint ffi_type_uint32 +# define ffi_type_sint ffi_type_sint32 +#elif INT_MAX == 9223372036854775807 +# define ffi_type_uint ffi_type_uint64 +# define ffi_type_sint ffi_type_sint64 +#else + #error "int size not supported" +#endif + +#if LONG_MAX == 2147483647 +# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX + #error "no 64-bit data type supported" +# endif +#elif LONG_MAX != FFI_64_BIT_MAX + #error "long size not supported" +#endif + +#if LONG_MAX == 2147483647 +# define ffi_type_ulong ffi_type_uint32 +# define ffi_type_slong ffi_type_sint32 +#elif LONG_MAX == FFI_64_BIT_MAX +# define ffi_type_ulong ffi_type_uint64 +# define ffi_type_slong ffi_type_sint64 +#else + #error "long size not supported" +#endif + +/* These are defined in types.c. */ +FFI_EXTERN ffi_type ffi_type_void; +FFI_EXTERN ffi_type ffi_type_uint8; +FFI_EXTERN ffi_type ffi_type_sint8; +FFI_EXTERN ffi_type ffi_type_uint16; +FFI_EXTERN ffi_type ffi_type_sint16; +FFI_EXTERN ffi_type ffi_type_uint32; +FFI_EXTERN ffi_type ffi_type_sint32; +FFI_EXTERN ffi_type ffi_type_uint64; +FFI_EXTERN ffi_type ffi_type_sint64; +FFI_EXTERN ffi_type ffi_type_float; +FFI_EXTERN ffi_type ffi_type_double; +FFI_EXTERN ffi_type ffi_type_pointer; + +#ifndef _M_ARM64 +FFI_EXTERN ffi_type ffi_type_longdouble; +#else +#define ffi_type_longdouble ffi_type_double +#endif + +#ifdef FFI_TARGET_HAS_COMPLEX_TYPE +FFI_EXTERN ffi_type ffi_type_complex_float; +FFI_EXTERN ffi_type ffi_type_complex_double; +#if 1 +FFI_EXTERN ffi_type ffi_type_complex_longdouble; +#else +#define ffi_type_complex_longdouble ffi_type_complex_double +#endif +#endif +#endif /* LIBFFI_HIDE_BASIC_TYPES */ + +typedef enum { + FFI_OK = 0, + FFI_BAD_TYPEDEF, + FFI_BAD_ABI +} ffi_status; + +typedef struct { + ffi_abi abi; + unsigned nargs; + ffi_type **arg_types; + ffi_type *rtype; + unsigned bytes; + unsigned flags; +#ifdef FFI_EXTRA_CIF_FIELDS + FFI_EXTRA_CIF_FIELDS; +#endif +} ffi_cif; + +/* ---- Definitions for the raw API -------------------------------------- */ + +#ifndef FFI_SIZEOF_ARG +# if LONG_MAX == 2147483647 +# define FFI_SIZEOF_ARG 4 +# elif LONG_MAX == FFI_64_BIT_MAX +# define FFI_SIZEOF_ARG 8 +# endif +#endif + +#ifndef FFI_SIZEOF_JAVA_RAW +# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG +#endif + +typedef union { + ffi_sarg sint; + ffi_arg uint; + float flt; + char data[FFI_SIZEOF_ARG]; + void* ptr; +} ffi_raw; + +#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8 +/* This is a special case for mips64/n32 ABI (and perhaps others) where + sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */ +typedef union { + signed int sint; + unsigned int uint; + float flt; + char data[FFI_SIZEOF_JAVA_RAW]; + void* ptr; +} ffi_java_raw; +#else +typedef ffi_raw ffi_java_raw; +#endif + + +FFI_API +void ffi_raw_call (ffi_cif *cif, + void (*fn)(void), + void *rvalue, + ffi_raw *avalue); + +FFI_API void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw); +FFI_API void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args); +FFI_API size_t ffi_raw_size (ffi_cif *cif); + +/* This is analogous to the raw API, except it uses Java parameter + packing, even on 64-bit machines. I.e. on 64-bit machines longs + and doubles are followed by an empty 64-bit word. */ + +FFI_API +void ffi_java_raw_call (ffi_cif *cif, + void (*fn)(void), + void *rvalue, + ffi_java_raw *avalue); + +FFI_API +void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw); +FFI_API +void ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args); +FFI_API +size_t ffi_java_raw_size (ffi_cif *cif); + +/* ---- Definitions for closures ----------------------------------------- */ + +#if FFI_CLOSURES + +#ifdef _MSC_VER +__declspec(align(8)) +#endif +typedef struct { +#if 0 + void *trampoline_table; + void *trampoline_table_entry; +#else + char tramp[FFI_TRAMPOLINE_SIZE]; +#endif + ffi_cif *cif; + void (*fun)(ffi_cif*,void*,void**,void*); + void *user_data; +} ffi_closure +#ifdef __GNUC__ + __attribute__((aligned (8))) +#endif + ; + +#ifndef __GNUC__ +# ifdef __sgi +# pragma pack 0 +# endif +#endif + +FFI_API void *ffi_closure_alloc (size_t size, void **code); +FFI_API void ffi_closure_free (void *); + +FFI_API ffi_status +ffi_prep_closure (ffi_closure*, + ffi_cif *, + void (*fun)(ffi_cif*,void*,void**,void*), + void *user_data) +#if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 405) + __attribute__((deprecated ("use ffi_prep_closure_loc instead"))) +#elif defined(__GNUC__) && __GNUC__ >= 3 + __attribute__((deprecated)) +#endif + ; + +FFI_API ffi_status +ffi_prep_closure_loc (ffi_closure*, + ffi_cif *, + void (*fun)(ffi_cif*,void*,void**,void*), + void *user_data, + void*codeloc); + +#ifdef __sgi +# pragma pack 8 +#endif +typedef struct { +#if 0 + void *trampoline_table; + void *trampoline_table_entry; +#else + char tramp[FFI_TRAMPOLINE_SIZE]; +#endif + ffi_cif *cif; + +#if !FFI_NATIVE_RAW_API + + /* If this is enabled, then a raw closure has the same layout + as a regular closure. We use this to install an intermediate + handler to do the transaltion, void** -> ffi_raw*. */ + + void (*translate_args)(ffi_cif*,void*,void**,void*); + void *this_closure; + +#endif + + void (*fun)(ffi_cif*,void*,ffi_raw*,void*); + void *user_data; + +} ffi_raw_closure; + +typedef struct { +#if 0 + void *trampoline_table; + void *trampoline_table_entry; +#else + char tramp[FFI_TRAMPOLINE_SIZE]; +#endif + + ffi_cif *cif; + +#if !FFI_NATIVE_RAW_API + + /* If this is enabled, then a raw closure has the same layout + as a regular closure. We use this to install an intermediate + handler to do the translation, void** -> ffi_raw*. */ + + void (*translate_args)(ffi_cif*,void*,void**,void*); + void *this_closure; + +#endif + + void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*); + void *user_data; + +} ffi_java_raw_closure; + +FFI_API ffi_status +ffi_prep_raw_closure (ffi_raw_closure*, + ffi_cif *cif, + void (*fun)(ffi_cif*,void*,ffi_raw*,void*), + void *user_data); + +FFI_API ffi_status +ffi_prep_raw_closure_loc (ffi_raw_closure*, + ffi_cif *cif, + void (*fun)(ffi_cif*,void*,ffi_raw*,void*), + void *user_data, + void *codeloc); + +FFI_API ffi_status +ffi_prep_java_raw_closure (ffi_java_raw_closure*, + ffi_cif *cif, + void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*), + void *user_data); + +FFI_API ffi_status +ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*, + ffi_cif *cif, + void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*), + void *user_data, + void *codeloc); + +#endif /* FFI_CLOSURES */ + +#if FFI_GO_CLOSURES + +typedef struct { + void *tramp; + ffi_cif *cif; + void (*fun)(ffi_cif*,void*,void**,void*); +} ffi_go_closure; + +FFI_API ffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *, + void (*fun)(ffi_cif*,void*,void**,void*)); + +FFI_API void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure); + +#endif /* FFI_GO_CLOSURES */ + +/* ---- Public interface definition -------------------------------------- */ + +FFI_API +ffi_status ffi_prep_cif(ffi_cif *cif, + ffi_abi abi, + unsigned int nargs, + ffi_type *rtype, + ffi_type **atypes); + +FFI_API +ffi_status ffi_prep_cif_var(ffi_cif *cif, + ffi_abi abi, + unsigned int nfixedargs, + unsigned int ntotalargs, + ffi_type *rtype, + ffi_type **atypes); + +FFI_API +void ffi_call(ffi_cif *cif, + void (*fn)(void), + void *rvalue, + void **avalue); + +FFI_API +ffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type, + size_t *offsets); + +/* Useful for eliminating compiler warnings. */ +#define FFI_FN(f) ((void (*)(void))f) + +/* ---- Definitions shared with assembly code ---------------------------- */ + +#endif + +/* If these change, update src/mips/ffitarget.h. */ +#define FFI_TYPE_VOID 0 +#define FFI_TYPE_INT 1 +#define FFI_TYPE_FLOAT 2 +#define FFI_TYPE_DOUBLE 3 +#ifndef _M_ARM64 +#define FFI_TYPE_LONGDOUBLE 4 +#else +#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE +#endif +#define FFI_TYPE_UINT8 5 +#define FFI_TYPE_SINT8 6 +#define FFI_TYPE_UINT16 7 +#define FFI_TYPE_SINT16 8 +#define FFI_TYPE_UINT32 9 +#define FFI_TYPE_SINT32 10 +#define FFI_TYPE_UINT64 11 +#define FFI_TYPE_SINT64 12 +#define FFI_TYPE_STRUCT 13 +#define FFI_TYPE_POINTER 14 +#define FFI_TYPE_COMPLEX 15 +/* This should always refer to the last type code (for sanity checks). */ +#define FFI_TYPE_LAST FFI_TYPE_COMPLEX + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/native/libffi/msvc_build/aarch64/aarch64_include/fficonfig.h b/native/libffi/msvc_build/aarch64/aarch64_include/fficonfig.h new file mode 100644 index 0000000000..b3d89b03ec --- /dev/null +++ b/native/libffi/msvc_build/aarch64/aarch64_include/fficonfig.h @@ -0,0 +1,219 @@ +/* fficonfig.h. Generated from fficonfig.h.in by configure. */ +/* fficonfig.h.in. Generated from configure.ac by autoheader. */ + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +/* #undef CRAY_STACKSEG_END */ + +/* Define to 1 if using `alloca.c'. */ +/* #undef C_ALLOCA */ + +/* Define to the flags needed for the .section .eh_frame directive. */ +#define EH_FRAME_FLAGS "a" + +/* Define this if you want extra debugging. */ +/* #undef FFI_DEBUG */ + +/* Cannot use PROT_EXEC on this target, so, we revert to alternative means */ +/* #undef FFI_EXEC_TRAMPOLINE_TABLE */ + +/* Define this if you want to enable pax emulated trampolines */ +/* #undef FFI_MMAP_EXEC_EMUTRAMP_PAX */ + +/* Cannot use malloc on this target, so, we revert to alternative means */ +/* #undef FFI_MMAP_EXEC_WRIT */ + +/* Define this if you do not want support for the raw API. */ +/* #undef FFI_NO_RAW_API */ + +/* Define this if you do not want support for aggregate types. */ +/* #undef FFI_NO_STRUCTS */ + +/* Define to 1 if you have `alloca', as a function or macro. */ +#define HAVE_ALLOCA 1 + +/* Define to 1 if you have and it should be used (not on Ultrix). + */ +/*#define HAVE_ALLOCA_H 1 */ + +/* Define if your assembler supports .cfi_* directives. */ +#define HAVE_AS_CFI_PSEUDO_OP 1 + +/* Define if your assembler supports .register. */ +/* #undef HAVE_AS_REGISTER_PSEUDO_OP */ + +/* Define if the compiler uses zarch features. */ +/* #undef HAVE_AS_S390_ZARCH */ + +/* Define if your assembler and linker support unaligned PC relative relocs. + */ +/* #undef HAVE_AS_SPARC_UA_PCREL */ + +/* Define if your assembler supports unwind section type. */ +/* #undef HAVE_AS_X86_64_UNWIND_SECTION_TYPE */ + +/* Define if your assembler supports PC relative relocs. */ +/* #undef HAVE_AS_X86_PCREL */ + +/* Define to 1 if you have the header file. */ +#define HAVE_DLFCN_H 1 + +/* Define if __attribute__((visibility("hidden"))) is supported. */ +#define HAVE_HIDDEN_VISIBILITY_ATTRIBUTE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define if you have the long double type and it is bigger than a double */ +#define HAVE_LONG_DOUBLE 1 + +/* Define if you support more than one size of the long double type */ +/* #undef HAVE_LONG_DOUBLE_VARIANT */ + +/* Define to 1 if you have the `memcpy' function. */ +#define HAVE_MEMCPY 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mkostemp' function. */ +#define HAVE_MKOSTEMP 1 + +/* Define to 1 if you have the `mmap' function. */ +#define HAVE_MMAP 1 + +/* Define if mmap with MAP_ANON(YMOUS) works. */ +#define HAVE_MMAP_ANON 1 + +/* Define if mmap of /dev/zero works. */ +#define HAVE_MMAP_DEV_ZERO 1 + +/* Define if read-only mmap of a plain file works. */ +#define HAVE_MMAP_FILE 1 + +/* Define if .eh_frame sections should be read-only. */ +#define HAVE_RO_EH_FRAME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +//#define HAVE_STDLIB_H 0 +#define LACKS_STDLIB_H 1 +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_MMAN_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if GNU symbol versioning is used for libatomic. */ +#define LIBFFI_GNU_SYMBOL_VERSIONING 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +/* #undef NO_MINUS_C_MINUS_O */ + +/* Name of package */ +#define PACKAGE "libffi" + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "http://github.com/libffi/libffi/issues" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "libffi" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "libffi 3.3-rc0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "libffi" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "3.3-rc0" + +/* The size of `double', as computed by sizeof. */ +#define SIZEOF_DOUBLE 8 + +/* The size of `long double', as computed by sizeof. */ +#define SIZEOF_LONG_DOUBLE 8 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 8 + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at runtime. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +/* #undef STACK_DIRECTION */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define if symbols are underscored. */ +/* #undef SYMBOL_UNDERSCORE */ + +/* Define this if you are using Purify and want to suppress spurious messages. + */ +/* #undef USING_PURIFY */ + +/* Version number of package */ +#define VERSION "3.3-rc0" + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Define to `unsigned int' if does not define. */ +/* #undef size_t */ + + +#ifdef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE +#ifdef LIBFFI_ASM +#ifdef __APPLE__ +#define FFI_HIDDEN(name) .private_extern name +#else +#define FFI_HIDDEN(name) .hidden name +#endif +#else +#define FFI_HIDDEN __attribute__ ((visibility ("hidden"))) +#endif +#else +#ifdef LIBFFI_ASM +#define FFI_HIDDEN(name) +#else +#define FFI_HIDDEN +#endif +#endif + diff --git a/native/libffi/msvcc.sh b/native/libffi/msvcc.sh index 984722773c..556351ba89 100755 --- a/native/libffi/msvcc.sh +++ b/native/libffi/msvcc.sh @@ -44,17 +44,32 @@ args_orig=$@ args="-nologo -W3" +<<<<<<< HEAD +======= +linkargs= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 static_crt= debug_crt= cl="cl" ml="ml" safeseh="-safeseh" output= +libpaths= +libversion=7 +verbose= while [ $# -gt 0 ] do case $1 in + --verbose) + verbose=1 + shift 1 + ;; + --version) + args="-help" + shift 1 + ;; -fexceptions) # Don't enable exceptions for now. #args="$args -EHac" @@ -68,9 +83,24 @@ do safeseh= shift 1 ;; +<<<<<<< HEAD -clang-cl) cl="clang-cl" safeseh= +======= + -marm) + ml='armasm' + safeseh= + shift 1 + ;; + -marm64) + ml='armasm64' + safeseh= + shift 1 + ;; + -clang-cl) + cl="clang-cl" +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 shift 1 ;; -O0) @@ -144,6 +174,7 @@ do shift 1 ;; -I) +<<<<<<< HEAD args="$args -I\"$2\"" includes="$includes -I\"$2\"" shift 2 @@ -151,6 +182,46 @@ do -I*) args="$args -I\"$(echo $1|sed 's/^-I//g')\"" includes="$includes -I\"$(echo $1|sed 's/^-I//g')\"" +======= + p=$(cygpath -m $2) + args="$args -I$p" + includes="$includes -I$p" + shift 2 + ;; + -I*) + p=$(cygpath -m ${1#-I}) + args="$args -I$p" + includes="$includes -I$p" + shift 1 + ;; + -L) + p=$(cygpath -m $2) + linkargs="$linkargs -LIBPATH:$p" + shift 2 + ;; + -L*) + p=$(cygpath -m ${1#-L}) + linkargs="$linkargs -LIBPATH:$p" + shift 1 + ;; + -link) + # add next argument verbatim to linker args + linkargs="$linkargs $2" + shift 2 + ;; + -l*) + case $1 + in + -lffi) + linkargs="$linkargs lib${1#-l}-${libversion}.lib" + ;; + *) + # ignore other libraries like -lm, hope they are + # covered by MSVCRT + # linkargs="$linkargs ${1#-l}.lib" + ;; + esac +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 shift 1 ;; -W|-Wextra) @@ -166,6 +237,18 @@ do # libffi tests -pedantic with -Wall, so drop it also. shift 1 ;; +<<<<<<< HEAD +======= + -warn) + # ignore -warn all from libtool as well. + if test "$2" = "all"; then + shift 2 + else + args="$args -warn" + shift 1 + fi + ;; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 -Werror) args="$args -WX" shift 1 @@ -190,6 +273,7 @@ do else output="-Fe$2" fi + armasm_output="-o $2" if [ -n "$assembly" ]; then args="$args $output" else @@ -214,11 +298,24 @@ do esac done +<<<<<<< HEAD # If -Zi is specified, certain optimizations are implicitly disabled # by MSVC. Add back those optimizations if this is an optimized build. # NOTE: These arguments must come after all others. if [ -n "$opt" ]; then args="$args -link -OPT:REF -OPT:ICF -INCREMENTAL:NO" +======= +if [ -n "$linkargs" ]; then + + # If -Zi is specified, certain optimizations are implicitly disabled + # by MSVC. Add back those optimizations if this is an optimized build. + # NOTE: These arguments must come after all others. + if [ -n "$opt" ]; then + linkargs="$linkargs -OPT:REF -OPT:ICF -INCREMENTAL:NO" + fi + + args="$args -link $linkargs" +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 fi if [ -n "$static_crt" ]; then @@ -236,12 +333,38 @@ if [ -n "$assembly" ]; then outdir="." fi ppsrc="$outdir/$(basename $src|sed 's/.S$/.asm/g')" +<<<<<<< HEAD echo "$cl -nologo -EP $includes $defines $src > $ppsrc" eval "\"$cl\" -nologo -EP $includes $defines $src > $ppsrc || exit $?" +======= + + if [ $ml = "armasm" ]; then + defines="$defines -D_M_ARM" + fi + + if [ $ml = "armasm64" ]; then + defines="$defines -D_M_ARM64" + fi + + if test -n "$verbose"; then + echo "$cl -nologo -EP $includes $defines $src > $ppsrc" + fi + + "$cl" -nologo -EP $includes $defines $src > $ppsrc || exit $? +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 output="$(echo $output | sed 's%/F[dpa][^ ]*%%g')" - args="-nologo $safeseh $single $output $ppsrc" + if [ $ml = "armasm" ]; then + args="-nologo -g -oldit $armasm_output $ppsrc -errorReport:prompt" + elif [ $ml = "armasm64" ]; then + args="-nologo -g $armasm_output $ppsrc -errorReport:prompt" + else + args="-nologo $safeseh $single $output $ppsrc" + fi + + if test -n "$verbose"; then + echo "$ml $args" + fi - echo "$ml $args" eval "\"$ml\" $args" result=$? @@ -249,13 +372,29 @@ if [ -n "$assembly" ]; then #mv *.obj $outdir else args="$md $args" +<<<<<<< HEAD echo "$cl $args" # Return an error code of 1 if an invalid command line parameter is passed # instead of just ignoring it. eval "(\"$cl\" $args 2>&1 1>&3 | \ awk '{print \$0} /D9002/ {error=1} END{exit error}' >&2) 3>&1" +======= + + if test -n "$verbose"; then + echo "$cl $args" + fi + # Return an error code of 1 if an invalid command line parameter is passed + # instead of just ignoring it. Any output that is not a warning or an + # error is filtered so this command behaves more like gcc. cl.exe prints + # the name of the compiled file otherwise, which breaks the dejagnu checks + # for excess warnings and errors. + eval "(\"$cl\" $args 2>&1 1>&3 | \ + awk '{print \$0} /D9002/ {error=1} END{exit error}' >&2) 3>&1 | \ + awk '/warning|error/'" +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 result=$? fi exit $result +# vim: noai:ts=4:sw=4 diff --git a/native/libffi/src/aarch64/ffi.c b/native/libffi/src/aarch64/ffi.c index cdb7816e72..bfc21f9486 100644 --- a/native/libffi/src/aarch64/ffi.c +++ b/native/libffi/src/aarch64/ffi.c @@ -19,11 +19,19 @@ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#if defined(__aarch64__) || defined(__arm64__)|| defined (_M_ARM64) #include - +#include +#include +#include #include #include +#include "internal.h" +#ifdef _WIN32 +#include /* FlushInstructionCache */ +#endif +<<<<<<< HEAD #include /* Stack alignment requirement in bytes */ @@ -37,6 +45,18 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #define N_V_ARG_REG 8 #define AARCH64_FFI_WITH_V (1 << AARCH64_FFI_WITH_V_BIT) +======= +/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE; + all further uses in this file will refer to the 128-bit type. */ +#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE +# if FFI_TYPE_LONGDOUBLE != 4 +# error FFI_TYPE_LONGDOUBLE out of date +# endif +#else +# undef FFI_TYPE_LONGDOUBLE +# define FFI_TYPE_LONGDOUBLE 4 +#endif +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 union _d { @@ -44,15 +64,12 @@ union _d UINT32 s[2]; }; -struct call_context +struct _v { - UINT64 x [AARCH64_N_XREG]; - struct - { - union _d d[2]; - } v [AARCH64_N_VREG]; + union _d d[2] __attribute__((aligned(16))); }; +<<<<<<< HEAD #if defined (__clang__) && defined (__APPLE__) extern void sys_icache_invalidate (void *start, size_t len); @@ -72,33 +89,33 @@ ffi_clear_cache (void *start, void *end) static void * get_x_addr (struct call_context *context, unsigned n) +======= +struct call_context +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 { - return &context->x[n]; -} + struct _v v[N_V_ARG_REG]; + UINT64 x[N_X_ARG_REG]; +}; -static void * -get_s_addr (struct call_context *context, unsigned n) -{ -#if defined __AARCH64EB__ - return &context->v[n].d[1].s[1]; -#else - return &context->v[n].d[0].s[0]; +#if FFI_EXEC_TRAMPOLINE_TABLE + +#ifdef __MACH__ +#ifdef HAVE_PTRAUTH +#include +#endif +#include #endif -} -static void * -get_d_addr (struct call_context *context, unsigned n) -{ -#if defined __AARCH64EB__ - return &context->v[n].d[1]; #else - return &context->v[n].d[0]; + +#if defined (__clang__) && defined (__APPLE__) +extern void sys_icache_invalidate (void *start, size_t len); #endif -} -static void * -get_v_addr (struct call_context *context, unsigned n) +static inline void +ffi_clear_cache (void *start, void *end) { +<<<<<<< HEAD return &context->v[n]; } @@ -181,12 +198,29 @@ get_basic_type_alignment (unsigned short type) return 0; } } +======= +#if defined (__clang__) && defined (__APPLE__) + sys_icache_invalidate (start, (char *)end - (char *)start); +#elif defined (__GNUC__) + __builtin___clear_cache (start, end); +#elif defined (_WIN32) + FlushInstructionCache(GetCurrentProcess(), start, (char*)end - (char*)start); +#else +#error "Missing builtin to flush instruction cache" +#endif +} -/* Return the size in bytes for each of the basic types. */ +#endif +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 -static size_t -get_basic_type_size (unsigned short type) +/* A subroutine of is_vfp_type. Given a structure type, return the type code + of the first non-structure element. Recurse for structure elements. + Return -1 if the structure is in fact empty, i.e. no nested elements. */ + +static int +is_hfa0 (const ffi_type *ty) { +<<<<<<< HEAD switch (type) { case FFI_TYPE_FLOAT: @@ -234,118 +268,122 @@ extern void ffi_closure_SYSV (ffi_closure *); /* Test for an FFI floating point representation. */ +======= + ffi_type **elements = ty->elements; + int i, ret = -1; -static unsigned -is_floating_type (unsigned short type) -{ - return (type == FFI_TYPE_FLOAT || type == FFI_TYPE_DOUBLE - || type == FFI_TYPE_LONGDOUBLE); + if (elements != NULL) + for (i = 0; elements[i]; ++i) + { + ret = elements[i]->type; + if (ret == FFI_TYPE_STRUCT || ret == FFI_TYPE_COMPLEX) + { + ret = is_hfa0 (elements[i]); + if (ret < 0) + continue; + } + break; + } +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 + + return ret; } -/* Test for a homogeneous structure. */ +/* A subroutine of is_vfp_type. Given a structure type, return true if all + of the non-structure elements are the same as CANDIDATE. */ -static unsigned short -get_homogeneous_type (ffi_type *ty) +static int +is_hfa1 (const ffi_type *ty, int candidate) { - if (ty->type == FFI_TYPE_STRUCT && ty->elements) - { - unsigned i; - unsigned short candidate_type - = get_homogeneous_type (ty->elements[0]); - for (i =1; ty->elements[i]; i++) - { - unsigned short iteration_type = 0; - /* If we have a nested struct, we must find its homogeneous type. - If that fits with our candidate type, we are still - homogeneous. */ - if (ty->elements[i]->type == FFI_TYPE_STRUCT - && ty->elements[i]->elements) - { - iteration_type = get_homogeneous_type (ty->elements[i]); - } - else - { - iteration_type = ty->elements[i]->type; - } + ffi_type **elements = ty->elements; + int i; - /* If we are not homogeneous, return FFI_TYPE_STRUCT. */ - if (candidate_type != iteration_type) - return FFI_TYPE_STRUCT; - } - return candidate_type; - } + if (elements != NULL) + for (i = 0; elements[i]; ++i) + { + int t = elements[i]->type; + if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX) + { + if (!is_hfa1 (elements[i], candidate)) + return 0; + } + else if (t != candidate) + return 0; + } - /* Base case, we have no more levels of nesting, so we - are a basic type, and so, trivially homogeneous in that type. */ - return ty->type; + return 1; } -/* Determine the number of elements within a STRUCT. +/* Determine if TY may be allocated to the FP registers. This is both an + fp scalar type as well as an homogenous floating point aggregate (HFA). + That is, a structure consisting of 1 to 4 members of all the same type, + where that type is an fp scalar. - Note, we must handle nested structs. + Returns non-zero iff TY is an HFA. The result is the AARCH64_RET_* + constant for the type. */ - If ty is not a STRUCT this function will return 0. */ - -static unsigned -element_count (ffi_type *ty) +static int +is_vfp_type (const ffi_type *ty) { - if (ty->type == FFI_TYPE_STRUCT && ty->elements) + ffi_type **elements; + int candidate, i; + size_t size, ele_count; + + /* Quickest tests first. */ + candidate = ty->type; + switch (candidate) { - unsigned n; - unsigned elems = 0; - for (n = 0; ty->elements[n]; n++) + default: + return 0; + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + case FFI_TYPE_LONGDOUBLE: + ele_count = 1; + goto done; + case FFI_TYPE_COMPLEX: + candidate = ty->elements[0]->type; + switch (candidate) { - if (ty->elements[n]->type == FFI_TYPE_STRUCT - && ty->elements[n]->elements) - elems += element_count (ty->elements[n]); - else - elems++; + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + case FFI_TYPE_LONGDOUBLE: + ele_count = 2; + goto done; } - return elems; + return 0; + case FFI_TYPE_STRUCT: + break; } - return 0; -} -/* Test for a homogeneous floating point aggregate. + /* No HFA types are smaller than 4 bytes, or larger than 64 bytes. */ + size = ty->size; + if (size < 4 || size > 64) + return 0; - A homogeneous floating point aggregate is a homogeneous aggregate of - a half- single- or double- precision floating point type with one - to four elements. Note that this includes nested structs of the - basic type. */ - -static int -is_hfa (ffi_type *ty) -{ - if (ty->type == FFI_TYPE_STRUCT - && ty->elements[0] - && is_floating_type (get_homogeneous_type (ty))) + /* Find the type of the first non-structure member. */ + elements = ty->elements; + candidate = elements[0]->type; + if (candidate == FFI_TYPE_STRUCT || candidate == FFI_TYPE_COMPLEX) { - unsigned n = element_count (ty); - return n >= 1 && n <= 4; + for (i = 0; ; ++i) + { + candidate = is_hfa0 (elements[i]); + if (candidate >= 0) + break; + } } - return 0; -} - -/* Test if an ffi_type is a candidate for passing in a register. - - This test does not check that sufficient registers of the - appropriate class are actually available, merely that IFF - sufficient registers are available then the argument will be passed - in register(s). - - Note that an ffi_type that is deemed to be a register candidate - will always be returned in registers. - Returns 1 if a register candidate else 0. */ - -static int -is_register_candidate (ffi_type *ty) -{ - switch (ty->type) + /* If the first member is not a floating point type, it's not an HFA. + Also quickly re-check the size of the structure. */ + switch (candidate) { - case FFI_TYPE_VOID: case FFI_TYPE_FLOAT: + ele_count = size / sizeof(float); + if (size != ele_count * sizeof(float)) + return 0; + break; case FFI_TYPE_DOUBLE: +<<<<<<< HEAD #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE case FFI_TYPE_LONGDOUBLE: #endif @@ -380,24 +418,39 @@ is_register_candidate (ffi_type *ty) registers required. */ return (ty->size + 7) / 8 < N_X_ARG_REG; } +======= + ele_count = size / sizeof(double); + if (size != ele_count * sizeof(double)) + return 0; break; - - default: - FFI_ASSERT (0); + case FFI_TYPE_LONGDOUBLE: + ele_count = size / sizeof(long double); + if (size != ele_count * sizeof(long double)) + return 0; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 break; + default: + return 0; } + if (ele_count > 4) + return 0; - return 0; -} - -/* Test if an ffi_type argument or result is a candidate for a vector - register. */ + /* Finally, make sure that all scalar elements are the same type. */ + for (i = 0; elements[i]; ++i) + { + int t = elements[i]->type; + if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX) + { + if (!is_hfa1 (elements[i], candidate)) + return 0; + } + else if (t != candidate) + return 0; + } -static int -is_v_register_candidate (ffi_type *ty) -{ - return is_floating_type (ty->type) - || (ty->type == FFI_TYPE_STRUCT && is_hfa (ty)); + /* All tests succeeded. Encode the result. */ + done: + return candidate * 4 + (4 - (int)ele_count); } /* Representation of the procedure call argument marshalling @@ -419,11 +472,16 @@ struct arg_state /* Initialize a procedure call argument marshalling state. */ static void +<<<<<<< HEAD arg_init (struct arg_state *state, size_t call_frame_size) +======= +arg_init (struct arg_state *state) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 { state->ngrn = 0; state->nsrn = 0; state->nsaa = 0; +<<<<<<< HEAD #if defined (__APPLE__) state->allocating_variadic = 0; @@ -474,17 +532,28 @@ allocate_to_v (struct call_context *context, struct arg_state *state) { FFI_ASSERT (state->nsrn < N_V_ARG_REG); return get_v_addr (context, (state->nsrn)++); +======= +#if defined (__APPLE__) + state->allocating_variadic = 0; +#endif +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 } /* Allocate an aligned slot on the stack and return a pointer to it. */ static void * +<<<<<<< HEAD allocate_to_stack (struct arg_state *state, void *stack, size_t alignment, size_t size) +======= +allocate_to_stack (struct arg_state *state, void *stack, + size_t alignment, size_t size) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 { - void *allocation; + size_t nsaa = state->nsaa; /* Round up the NSAA to the larger of 8 or the natural alignment of the argument's type. */ +<<<<<<< HEAD state->nsaa = ALIGN (state->nsaa, alignment); state->nsaa = ALIGN (state->nsaa, alignment); #if defined (__APPLE__) @@ -495,14 +564,26 @@ allocate_to_stack (struct arg_state *state, void *stack, size_t alignment, #endif allocation = stack + state->nsaa; +======= +#if defined (__APPLE__) + if (state->allocating_variadic && alignment < 8) + alignment = 8; +#else + if (alignment < 8) + alignment = 8; +#endif + + nsaa = FFI_ALIGN (nsaa, alignment); + state->nsaa = nsaa + size; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 - state->nsaa += size; - return allocation; + return (char *)stack + nsaa; } -static void -copy_basic_type (void *dest, void *source, unsigned short type) +static ffi_arg +extend_integer_type (void *source, int type) { +<<<<<<< HEAD /* This is necessary to ensure that basic types are copied sign extended to 64-bits as libffi expects. */ switch (type) @@ -518,85 +599,203 @@ copy_basic_type (void *dest, void *source, unsigned short type) *(long double *) dest = *(long double *) source; break; #endif +======= + switch (type) + { +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 case FFI_TYPE_UINT8: - *(ffi_arg *) dest = *(UINT8 *) source; - break; + return *(UINT8 *) source; case FFI_TYPE_SINT8: - *(ffi_sarg *) dest = *(SINT8 *) source; - break; + return *(SINT8 *) source; case FFI_TYPE_UINT16: - *(ffi_arg *) dest = *(UINT16 *) source; - break; + return *(UINT16 *) source; case FFI_TYPE_SINT16: - *(ffi_sarg *) dest = *(SINT16 *) source; - break; + return *(SINT16 *) source; case FFI_TYPE_UINT32: - *(ffi_arg *) dest = *(UINT32 *) source; - break; + return *(UINT32 *) source; case FFI_TYPE_INT: case FFI_TYPE_SINT32: - *(ffi_sarg *) dest = *(SINT32 *) source; - break; - case FFI_TYPE_POINTER: + return *(SINT32 *) source; case FFI_TYPE_UINT64: - *(ffi_arg *) dest = *(UINT64 *) source; - break; case FFI_TYPE_SINT64: - *(ffi_sarg *) dest = *(SINT64 *) source; + return *(UINT64 *) source; break; +<<<<<<< HEAD case FFI_TYPE_VOID: break; +======= + case FFI_TYPE_POINTER: + return *(uintptr_t *) source; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 default: - FFI_ASSERT (0); + abort(); } } +#if defined(_MSC_VER) +void extend_hfa_type (void *dest, void *src, int h); +#else static void -copy_hfa_to_reg_or_stack (void *memory, - ffi_type *ty, - struct call_context *context, - unsigned char *stack, - struct arg_state *state) +extend_hfa_type (void *dest, void *src, int h) { - unsigned elems = element_count (ty); - if (available_v (state) < elems) - { - /* There are insufficient V registers. Further V register allocations - are prevented, the NSAA is adjusted (by allocate_to_stack ()) - and the argument is copied to memory at the adjusted NSAA. */ - state->nsrn = N_V_ARG_REG; - memcpy (allocate_to_stack (state, stack, ty->alignment, ty->size), - memory, - ty->size); - } - else + ssize_t f = h - AARCH64_RET_S4; + void *x0; + + asm volatile ( + "adr %0, 0f\n" +" add %0, %0, %1\n" +" br %0\n" +"0: ldp s16, s17, [%3]\n" /* S4 */ +" ldp s18, s19, [%3, #8]\n" +" b 4f\n" +" ldp s16, s17, [%3]\n" /* S3 */ +" ldr s18, [%3, #8]\n" +" b 3f\n" +" ldp s16, s17, [%3]\n" /* S2 */ +" b 2f\n" +" nop\n" +" ldr s16, [%3]\n" /* S1 */ +" b 1f\n" +" nop\n" +" ldp d16, d17, [%3]\n" /* D4 */ +" ldp d18, d19, [%3, #16]\n" +" b 4f\n" +" ldp d16, d17, [%3]\n" /* D3 */ +" ldr d18, [%3, #16]\n" +" b 3f\n" +" ldp d16, d17, [%3]\n" /* D2 */ +" b 2f\n" +" nop\n" +" ldr d16, [%3]\n" /* D1 */ +" b 1f\n" +" nop\n" +" ldp q16, q17, [%3]\n" /* Q4 */ +" ldp q18, q19, [%3, #32]\n" +" b 4f\n" +" ldp q16, q17, [%3]\n" /* Q3 */ +" ldr q18, [%3, #32]\n" +" b 3f\n" +" ldp q16, q17, [%3]\n" /* Q2 */ +" b 2f\n" +" nop\n" +" ldr q16, [%3]\n" /* Q1 */ +" b 1f\n" +"4: str q19, [%2, #48]\n" +"3: str q18, [%2, #32]\n" +"2: str q17, [%2, #16]\n" +"1: str q16, [%2]" + : "=&r"(x0) + : "r"(f * 12), "r"(dest), "r"(src) + : "memory", "v16", "v17", "v18", "v19"); +} +#endif + +#if defined(_MSC_VER) +void* compress_hfa_type (void *dest, void *src, int h); +#else +static void * +compress_hfa_type (void *dest, void *reg, int h) +{ + switch (h) { +<<<<<<< HEAD int i; unsigned short type = get_homogeneous_type (ty); for (i = 0; i < elems; i++) +======= + case AARCH64_RET_S1: + if (dest == reg) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 + { +#ifdef __AARCH64EB__ + dest += 12; +#endif + } + else + *(float *)dest = *(float *)reg; + break; + case AARCH64_RET_S2: + asm ("ldp q16, q17, [%1]\n\t" + "st2 { v16.s, v17.s }[0], [%0]" + : : "r"(dest), "r"(reg) : "memory", "v16", "v17"); + break; + case AARCH64_RET_S3: + asm ("ldp q16, q17, [%1]\n\t" + "ldr q18, [%1, #32]\n\t" + "st3 { v16.s, v17.s, v18.s }[0], [%0]" + : : "r"(dest), "r"(reg) : "memory", "v16", "v17", "v18"); + break; + case AARCH64_RET_S4: + asm ("ldp q16, q17, [%1]\n\t" + "ldp q18, q19, [%1, #32]\n\t" + "st4 { v16.s, v17.s, v18.s, v19.s }[0], [%0]" + : : "r"(dest), "r"(reg) : "memory", "v16", "v17", "v18", "v19"); + break; + + case AARCH64_RET_D1: + if (dest == reg) { - void *reg = allocate_to_v (context, state); - copy_basic_type (reg, memory, type); - memory += get_basic_type_size (type); +#ifdef __AARCH64EB__ + dest += 8; +#endif } + else + *(double *)dest = *(double *)reg; + break; + case AARCH64_RET_D2: + asm ("ldp q16, q17, [%1]\n\t" + "st2 { v16.d, v17.d }[0], [%0]" + : : "r"(dest), "r"(reg) : "memory", "v16", "v17"); + break; + case AARCH64_RET_D3: + asm ("ldp q16, q17, [%1]\n\t" + "ldr q18, [%1, #32]\n\t" + "st3 { v16.d, v17.d, v18.d }[0], [%0]" + : : "r"(dest), "r"(reg) : "memory", "v16", "v17", "v18"); + break; + case AARCH64_RET_D4: + asm ("ldp q16, q17, [%1]\n\t" + "ldp q18, q19, [%1, #32]\n\t" + "st4 { v16.d, v17.d, v18.d, v19.d }[0], [%0]" + : : "r"(dest), "r"(reg) : "memory", "v16", "v17", "v18", "v19"); + break; + + default: + if (dest != reg) + return memcpy (dest, reg, 16 * (4 - (h & 3))); + break; } + return dest; } +#endif /* Either allocate an appropriate register for the argument type, or if none are available, allocate a stack slot and return a pointer to the allocated space. */ static void * -allocate_to_register_or_stack (struct call_context *context, - unsigned char *stack, - struct arg_state *state, - unsigned short type) +allocate_int_to_reg_or_stack (struct call_context *context, + struct arg_state *state, + void *stack, size_t size) { - size_t alignment = get_basic_type_alignment (type); - size_t size = alignment; - switch (type) + if (state->ngrn < N_X_ARG_REG) + return &context->x[state->ngrn++]; + + state->ngrn = N_X_ARG_REG; + return allocate_to_stack (state, stack, size, size); +} + +ffi_status FFI_HIDDEN +ffi_prep_cif_machdep (ffi_cif *cif) +{ + ffi_type *rtype = cif->rtype; + size_t bytes = cif->bytes; + int flags, i, n; + + switch (rtype->type) { +<<<<<<< HEAD case FFI_TYPE_FLOAT: /* This is the only case for which the allocated stack size should not match the alignment of the type. */ @@ -612,61 +811,161 @@ allocate_to_register_or_stack (struct call_context *context, if (state->nsrn < N_V_ARG_REG) return allocate_to_v (context, state); state->nsrn = N_V_ARG_REG; +======= + case FFI_TYPE_VOID: + flags = AARCH64_RET_VOID; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 break; #endif case FFI_TYPE_UINT8: - case FFI_TYPE_SINT8: + flags = AARCH64_RET_UINT8; + break; case FFI_TYPE_UINT16: - case FFI_TYPE_SINT16: + flags = AARCH64_RET_UINT16; + break; case FFI_TYPE_UINT32: - case FFI_TYPE_SINT32: + flags = AARCH64_RET_UINT32; + break; + case FFI_TYPE_SINT8: + flags = AARCH64_RET_SINT8; + break; + case FFI_TYPE_SINT16: + flags = AARCH64_RET_SINT16; + break; case FFI_TYPE_INT: - case FFI_TYPE_POINTER: - case FFI_TYPE_UINT64: + case FFI_TYPE_SINT32: + flags = AARCH64_RET_SINT32; + break; case FFI_TYPE_SINT64: - if (state->ngrn < N_X_ARG_REG) - return allocate_to_x (context, state); - state->ngrn = N_X_ARG_REG; + case FFI_TYPE_UINT64: + flags = AARCH64_RET_INT64; break; + case FFI_TYPE_POINTER: + flags = (sizeof(void *) == 4 ? AARCH64_RET_UINT32 : AARCH64_RET_INT64); + break; + + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + case FFI_TYPE_LONGDOUBLE: + case FFI_TYPE_STRUCT: + case FFI_TYPE_COMPLEX: + flags = is_vfp_type (rtype); + if (flags == 0) + { + size_t s = rtype->size; + if (s > 16) + { + flags = AARCH64_RET_VOID | AARCH64_RET_IN_MEM; + bytes += 8; + } + else if (s == 16) + flags = AARCH64_RET_INT128; + else if (s == 8) + flags = AARCH64_RET_INT64; + else + flags = AARCH64_RET_INT128 | AARCH64_RET_NEED_COPY; + } + break; + default: - FFI_ASSERT (0); + abort(); } - return allocate_to_stack (state, stack, alignment, size); -} + for (i = 0, n = cif->nargs; i < n; i++) + if (is_vfp_type (cif->arg_types[i])) + { + flags |= AARCH64_FLAG_ARG_V; + break; + } -/* Copy a value to an appropriate register, or if none are - available, to the stack. */ + /* Round the stack up to a multiple of the stack alignment requirement. */ + cif->bytes = (unsigned) FFI_ALIGN(bytes, 16); + cif->flags = flags; +#if defined (__APPLE__) + cif->aarch64_nfixedargs = 0; +#endif -static void -copy_to_register_or_stack (struct call_context *context, - unsigned char *stack, - struct arg_state *state, - void *value, - unsigned short type) + return FFI_OK; +} + +#if defined (__APPLE__) +/* Perform Apple-specific cif processing for variadic calls */ +ffi_status FFI_HIDDEN +ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs, + unsigned int ntotalargs) +{ + ffi_status status = ffi_prep_cif_machdep (cif); + cif->aarch64_nfixedargs = nfixedargs; + return status; +} +#else +ffi_status FFI_HIDDEN +ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs, unsigned int ntotalargs) { - copy_basic_type ( - allocate_to_register_or_stack (context, stack, state, type), - value, - type); + ffi_status status = ffi_prep_cif_machdep (cif); + cif->flags |= AARCH64_FLAG_VARARG; + return status; } +#endif /* __APPLE__ */ -/* Marshall the arguments from FFI representation to procedure call - context and stack. */ +extern void ffi_call_SYSV (struct call_context *context, void *frame, + void (*fn)(void), void *rvalue, int flags, + void *closure) FFI_HIDDEN; -static unsigned -aarch64_prep_args (struct call_context *context, unsigned char *stack, - extended_cif *ecif) +/* Call a function with the provided arguments and capture the return + value. */ +static void +ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue, + void **avalue, void *closure) { - int i; + struct call_context *context; + void *stack, *frame, *rvalue; struct arg_state state; + size_t stack_bytes, rtype_size, rsize; + int i, nargs, flags, isvariadic = 0; + ffi_type *rtype; - arg_init (&state, ALIGN(ecif->cif->bytes, 16)); + flags = cif->flags; + rtype = cif->rtype; + rtype_size = rtype->size; + stack_bytes = cif->bytes; - for (i = 0; i < ecif->cif->nargs; i++) + if (flags & AARCH64_FLAG_VARARG) + { + isvariadic = 1; + flags &= ~AARCH64_FLAG_VARARG; + } + + /* If the target function returns a structure via hidden pointer, + then we cannot allow a null rvalue. Otherwise, mash a null + rvalue to void return type. */ + rsize = 0; + if (flags & AARCH64_RET_IN_MEM) { - ffi_type *ty = ecif->cif->arg_types[i]; - switch (ty->type) + if (orig_rvalue == NULL) + rsize = rtype_size; + } + else if (orig_rvalue == NULL) + flags &= AARCH64_FLAG_ARG_V; + else if (flags & AARCH64_RET_NEED_COPY) + rsize = 16; + + /* Allocate consectutive stack for everything we'll need. */ + context = alloca (sizeof(struct call_context) + stack_bytes + 32 + rsize); + stack = context + 1; + frame = (void*)((uintptr_t)stack + (uintptr_t)stack_bytes); + rvalue = (rsize ? (void*)((uintptr_t)frame + 32) : orig_rvalue); + + arg_init (&state); + for (i = 0, nargs = cif->nargs; i < nargs; i++) + { + ffi_type *ty = cif->arg_types[i]; + size_t s = ty->size; + void *a = avalue[i]; + int h, t; + + t = ty->type; + switch (t) { case FFI_TYPE_VOID: FFI_ASSERT (0); @@ -674,71 +973,130 @@ aarch64_prep_args (struct call_context *context, unsigned char *stack, /* If the argument is a basic type the argument is allocated to an appropriate register, or if none are available, to the stack. */ +<<<<<<< HEAD case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE case FFI_TYPE_LONGDOUBLE: #endif +======= + case FFI_TYPE_INT: +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 case FFI_TYPE_UINT8: case FFI_TYPE_SINT8: case FFI_TYPE_UINT16: case FFI_TYPE_SINT16: case FFI_TYPE_UINT32: - case FFI_TYPE_INT: case FFI_TYPE_SINT32: - case FFI_TYPE_POINTER: case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: - copy_to_register_or_stack (context, stack, &state, - ecif->avalue[i], ty->type); + case FFI_TYPE_POINTER: + do_pointer: + { + ffi_arg ext = extend_integer_type (a, t); + if (state.ngrn < N_X_ARG_REG) + context->x[state.ngrn++] = ext; + else + { + void *d = allocate_to_stack (&state, stack, ty->alignment, s); + state.ngrn = N_X_ARG_REG; + /* Note that the default abi extends each argument + to a full 64-bit slot, while the iOS abi allocates + only enough space. */ +#ifdef __APPLE__ + memcpy(d, a, s); +#else + *(ffi_arg *)d = ext; +#endif + } + } break; + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + case FFI_TYPE_LONGDOUBLE: case FFI_TYPE_STRUCT: - if (is_hfa (ty)) - { - copy_hfa_to_reg_or_stack (ecif->avalue[i], ty, context, - stack, &state); - } - else if (ty->size > 16) - { - /* If the argument is a composite type that is larger than 16 - bytes, then the argument has been copied to memory, and - the argument is replaced by a pointer to the copy. */ + case FFI_TYPE_COMPLEX: + { + void *dest; - copy_to_register_or_stack (context, stack, &state, - &(ecif->avalue[i]), FFI_TYPE_POINTER); - } - else if (available_x (&state) >= (ty->size + 7) / 8) - { - /* If the argument is a composite type and the size in - double-words is not more than the number of available - X registers, then the argument is copied into consecutive - X registers. */ - int j; - for (j = 0; j < (ty->size + 7) / 8; j++) - { - memcpy (allocate_to_x (context, &state), - &(((UINT64 *) ecif->avalue[i])[j]), - sizeof (UINT64)); + h = is_vfp_type (ty); + if (h) + { + int elems = 4 - (h & 3); + if (cif->abi == FFI_WIN64 && isvariadic) + { + if (state.ngrn + elems <= N_X_ARG_REG) + { + dest = &context->x[state.ngrn]; + state.ngrn += elems; + extend_hfa_type(dest, a, h); + break; + } + state.nsrn = N_X_ARG_REG; + dest = allocate_to_stack(&state, stack, ty->alignment, s); + } + else + { + if (state.nsrn + elems <= N_V_ARG_REG) + { + dest = &context->v[state.nsrn]; + state.nsrn += elems; + extend_hfa_type (dest, a, h); + break; + } + state.nsrn = N_V_ARG_REG; + dest = allocate_to_stack (&state, stack, ty->alignment, s); + } + } + else if (s > 16) + { + /* If the argument is a composite type that is larger than 16 + bytes, then the argument has been copied to memory, and + the argument is replaced by a pointer to the copy. */ + a = &avalue[i]; + t = FFI_TYPE_POINTER; + s = sizeof (void *); + goto do_pointer; + } + else + { + size_t n = (s + 7) / 8; + if (state.ngrn + n <= N_X_ARG_REG) + { + /* If the argument is a composite type and the size in + double-words is not more than the number of available + X registers, then the argument is copied into + consecutive X registers. */ + dest = &context->x[state.ngrn]; + state.ngrn += (unsigned int)n; + } + else + { + /* Otherwise, there are insufficient X registers. Further + X register allocations are prevented, the NSAA is + adjusted and the argument is copied to memory at the + adjusted NSAA. */ + state.ngrn = N_X_ARG_REG; + dest = allocate_to_stack (&state, stack, ty->alignment, s); + } } - } - else - { - /* Otherwise, there are insufficient X registers. Further X - register allocations are prevented, the NSAA is adjusted - (by allocate_to_stack ()) and the argument is copied to - memory at the adjusted NSAA. */ - state.ngrn = N_X_ARG_REG; - - memcpy (allocate_to_stack (&state, stack, ty->alignment, - ty->size), ecif->avalue + i, ty->size); + memcpy (dest, a, s); } break; default: - FFI_ASSERT (0); - break; + abort(); + } + +#if defined (__APPLE__) + if (i + 1 == cif->aarch64_nfixedargs) + { + state.ngrn = N_X_ARG_REG; + state.nsrn = N_V_ARG_REG; + state.allocating_variadic = 1; } +<<<<<<< HEAD #if defined (__APPLE__) if (i + 1 == ecif->cif->aarch64_nfixedargs) @@ -748,15 +1106,21 @@ aarch64_prep_args (struct call_context *context, unsigned char *stack, state.allocating_variadic = 1; } +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #endif } - return ecif->cif->aarch64_flags; + ffi_call_SYSV (context, frame, fn, rvalue, flags, closure); + + if (flags & AARCH64_RET_NEED_COPY) + memcpy (orig_rvalue, rvalue, rtype_size); } -ffi_status -ffi_prep_cif_machdep (ffi_cif *cif) +void +ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue) { +<<<<<<< HEAD /* Round the stack up to a multiple of the stack alignment requirement. */ cif->bytes = (cif->bytes + (AARCH64_STACK_ALIGN - 1)) & ~ (AARCH64_STACK_ALIGN - 1); @@ -809,9 +1173,17 @@ ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, /* Call a function with the provided arguments and capture the return value. */ +======= + ffi_call_int (cif, fn, rvalue, avalue, NULL); +} + +#ifdef FFI_GO_CLOSURES +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 void -ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, + void **avalue, void *closure) { +<<<<<<< HEAD extended_cif ecif; ecif.cif = cif; @@ -902,16 +1274,15 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) FFI_ASSERT (0); break; } +======= + ffi_call_int (cif, fn, rvalue, avalue, closure); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 } - -static unsigned char trampoline [] = -{ 0x70, 0x00, 0x00, 0x58, /* ldr x16, 1f */ - 0x91, 0x00, 0x00, 0x10, /* adr x17, 2f */ - 0x00, 0x02, 0x1f, 0xd6 /* br x16 */ -}; +#endif /* FFI_GO_CLOSURES */ /* Build a trampoline. */ +<<<<<<< HEAD #define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX,FLAGS) \ ({unsigned char *__tramp = (unsigned char*)(TRAMP); \ UINT64 __fun = (UINT64)(FUN); \ @@ -923,9 +1294,13 @@ static unsigned char trampoline [] = memcpy (__tramp + 28, &__flags, sizeof (__flags)); \ ffi_clear_cache(__tramp, __tramp + FFI_TRAMPOLINE_SIZE); \ }) +======= +extern void ffi_closure_SYSV (void) FFI_HIDDEN; +extern void ffi_closure_SYSV_V (void) FFI_HIDDEN; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 ffi_status -ffi_prep_closure_loc (ffi_closure* closure, +ffi_prep_closure_loc (ffi_closure *closure, ffi_cif* cif, void (*fun)(ffi_cif*,void*,void**,void*), void *user_data, @@ -934,16 +1309,80 @@ ffi_prep_closure_loc (ffi_closure* closure, if (cif->abi != FFI_SYSV) return FFI_BAD_ABI; - FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_SYSV, codeloc, - cif->aarch64_flags); + void (*start)(void); + + if (cif->flags & AARCH64_FLAG_ARG_V) + start = ffi_closure_SYSV_V; + else + start = ffi_closure_SYSV; + +#if FFI_EXEC_TRAMPOLINE_TABLE +#ifdef __MACH__ +#ifdef HAVE_PTRAUTH + codeloc = ptrauth_strip (codeloc, ptrauth_key_asia); +#endif + void **config = (void **)((uint8_t *)codeloc - PAGE_MAX_SIZE); + config[0] = closure; + config[1] = start; +#endif +#else + static const unsigned char trampoline[16] = { + 0x90, 0x00, 0x00, 0x58, /* ldr x16, tramp+16 */ + 0xf1, 0xff, 0xff, 0x10, /* adr x17, tramp+0 */ + 0x00, 0x02, 0x1f, 0xd6 /* br x16 */ + }; + char *tramp = closure->tramp; + + memcpy (tramp, trampoline, sizeof(trampoline)); + + *(UINT64 *)(tramp + 16) = (uintptr_t)start; + + ffi_clear_cache(tramp, tramp + FFI_TRAMPOLINE_SIZE); + + /* Also flush the cache for code mapping. */ +#ifdef _WIN32 + // Not using dlmalloc.c for Windows ARM64 builds + // so calling ffi_data_to_code_pointer() isn't necessary + unsigned char *tramp_code = tramp; + #else + unsigned char *tramp_code = ffi_data_to_code_pointer (tramp); + #endif + ffi_clear_cache (tramp_code, tramp_code + FFI_TRAMPOLINE_SIZE); +#endif - closure->cif = cif; + closure->cif = cif; + closure->fun = fun; closure->user_data = user_data; - closure->fun = fun; return FFI_OK; } +#ifdef FFI_GO_CLOSURES +extern void ffi_go_closure_SYSV (void) FFI_HIDDEN; +extern void ffi_go_closure_SYSV_V (void) FFI_HIDDEN; + +ffi_status +ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif* cif, + void (*fun)(ffi_cif*,void*,void**,void*)) +{ + void (*start)(void); + + if (cif->abi != FFI_SYSV) + return FFI_BAD_ABI; + + if (cif->flags & AARCH64_FLAG_ARG_V) + start = ffi_go_closure_SYSV_V; + else + start = ffi_go_closure_SYSV; + + closure->tramp = start; + closure->cif = cif; + closure->fun = fun; + + return FFI_OK; +} +#endif /* FFI_GO_CLOSURES */ + /* Primary handler to setup and invoke a function within a closure. A closure when invoked enters via the assembler wrapper @@ -960,48 +1399,65 @@ ffi_prep_closure_loc (ffi_closure* closure, descriptors, invokes the wrapped function, then marshalls the return value back into the call context. */ +<<<<<<< HEAD void FFI_HIDDEN ffi_closure_SYSV_inner (ffi_closure *closure, struct call_context *context, void *stack) +======= +int FFI_HIDDEN +ffi_closure_SYSV_inner (ffi_cif *cif, + void (*fun)(ffi_cif*,void*,void**,void*), + void *user_data, + struct call_context *context, + void *stack, void *rvalue, void *struct_rvalue) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 { - ffi_cif *cif = closure->cif; void **avalue = (void**) alloca (cif->nargs * sizeof (void*)); - void *rvalue = NULL; - int i; + int i, h, nargs, flags; struct arg_state state; - arg_init (&state, ALIGN(cif->bytes, 16)); + arg_init (&state); - for (i = 0; i < cif->nargs; i++) + for (i = 0, nargs = cif->nargs; i < nargs; i++) { ffi_type *ty = cif->arg_types[i]; + int t = ty->type; + size_t n, s = ty->size; - switch (ty->type) + switch (t) { case FFI_TYPE_VOID: FFI_ASSERT (0); break; + case FFI_TYPE_INT: case FFI_TYPE_UINT8: case FFI_TYPE_SINT8: case FFI_TYPE_UINT16: case FFI_TYPE_SINT16: case FFI_TYPE_UINT32: case FFI_TYPE_SINT32: - case FFI_TYPE_INT: - case FFI_TYPE_POINTER: case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: +<<<<<<< HEAD case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: #if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE case FFI_TYPE_LONGDOUBLE: avalue[i] = allocate_to_register_or_stack (context, stack, &state, ty->type); +======= + case FFI_TYPE_POINTER: + avalue[i] = allocate_int_to_reg_or_stack (context, &state, stack, s); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 break; #endif + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + case FFI_TYPE_LONGDOUBLE: case FFI_TYPE_STRUCT: +<<<<<<< HEAD if (is_hfa (ty)) { unsigned n = element_count (ty); @@ -1159,21 +1615,103 @@ ffi_closure_SYSV_inner (ffi_closure *closure, struct call_context *context, { size_t size = ALIGN (cif->rtype->size, sizeof (UINT64)) ; memcpy (get_x_addr (context, 0), rvalue, size); +======= + case FFI_TYPE_COMPLEX: + h = is_vfp_type (ty); + if (h) + { + n = 4 - (h & 3); +#ifdef _WIN32 /* for handling armasm calling convention */ + if (cif->is_variadic) + { + if (state.ngrn + n <= N_X_ARG_REG) + { + void *reg = &context->x[state.ngrn]; + state.ngrn += (unsigned int)n; + + /* Eeek! We need a pointer to the structure, however the + homogeneous float elements are being passed in individual + registers, therefore for float and double the structure + is not represented as a contiguous sequence of bytes in + our saved register context. We don't need the original + contents of the register storage, so we reformat the + structure into the same memory. */ + avalue[i] = compress_hfa_type(reg, reg, h); + } + else + { + state.ngrn = N_X_ARG_REG; + state.nsrn = N_V_ARG_REG; + avalue[i] = allocate_to_stack(&state, stack, + ty->alignment, s); + } + } + else + { +#endif /* for handling armasm calling convention */ + if (state.nsrn + n <= N_V_ARG_REG) + { + void *reg = &context->v[state.nsrn]; + state.nsrn += (unsigned int)n; + avalue[i] = compress_hfa_type(reg, reg, h); + } + else + { + state.nsrn = N_V_ARG_REG; + avalue[i] = allocate_to_stack(&state, stack, + ty->alignment, s); + } +#ifdef _WIN32 /* for handling armasm calling convention */ + } +#endif /* for handling armasm calling convention */ + } + else if (s > 16) + { + /* Replace Composite type of size greater than 16 with a + pointer. */ + avalue[i] = *(void **) + allocate_int_to_reg_or_stack (context, &state, stack, + sizeof (void *)); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 } else { - FFI_ASSERT (0); + n = (s + 7) / 8; + if (state.ngrn + n <= N_X_ARG_REG) + { + avalue[i] = &context->x[state.ngrn]; + state.ngrn += (unsigned int)n; + } + else + { + state.ngrn = N_X_ARG_REG; + avalue[i] = allocate_to_stack(&state, stack, + ty->alignment, s); + } } break; + default: - FFI_ASSERT (0); - break; - } - } - else - { - memcpy (&rvalue, get_x_addr (context, 8), sizeof (UINT64)); - (closure->fun) (cif, rvalue, avalue, closure->user_data); + abort(); + } + +#if defined (__APPLE__) + if (i + 1 == cif->aarch64_nfixedargs) + { + state.ngrn = N_X_ARG_REG; + state.nsrn = N_V_ARG_REG; + state.allocating_variadic = 1; + } +#endif } + + flags = cif->flags; + if (flags & AARCH64_RET_IN_MEM) + rvalue = struct_rvalue; + + fun (cif, rvalue, avalue, user_data); + + return flags; } +#endif /* (__aarch64__) || defined(__arm64__)|| defined (_M_ARM64)*/ diff --git a/native/libffi/src/aarch64/ffitarget.h b/native/libffi/src/aarch64/ffitarget.h index 4bbced26f0..9f4d41ee07 100644 --- a/native/libffi/src/aarch64/ffitarget.h +++ b/native/libffi/src/aarch64/ffitarget.h @@ -27,37 +27,79 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #endif #ifndef LIBFFI_ASM +#ifdef __ILP32__ +#define FFI_SIZEOF_ARG 8 +#define FFI_SIZEOF_JAVA_RAW 4 +typedef unsigned long long ffi_arg; +typedef signed long long ffi_sarg; +#elif defined(_WIN32) +#define FFI_SIZEOF_ARG 8 +typedef unsigned long long ffi_arg; +typedef signed long long ffi_sarg; +#else typedef unsigned long ffi_arg; typedef signed long ffi_sarg; +#endif typedef enum ffi_abi { FFI_FIRST_ABI = 0, FFI_SYSV, + FFI_WIN64, FFI_LAST_ABI, +#if defined(_WIN32) + FFI_DEFAULT_ABI = FFI_WIN64 +#else FFI_DEFAULT_ABI = FFI_SYSV +#endif } ffi_abi; #endif /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 -#define FFI_TRAMPOLINE_SIZE 36 #define FFI_NATIVE_RAW_API 0 -/* ---- Internal ---- */ +#if defined (FFI_EXEC_TRAMPOLINE_TABLE) && FFI_EXEC_TRAMPOLINE_TABLE +<<<<<<< HEAD #if defined (__APPLE__) #define FFI_TARGET_SPECIFIC_VARIADIC #define FFI_EXTRA_CIF_FIELDS unsigned aarch64_flags; unsigned aarch64_nfixedargs #else #define FFI_EXTRA_CIF_FIELDS unsigned aarch64_flags +======= +#ifdef __MACH__ +#define FFI_TRAMPOLINE_SIZE 16 +#define FFI_TRAMPOLINE_CLOSURE_OFFSET 16 +#else +#error "No trampoline table implementation" #endif -#define AARCH64_FFI_WITH_V_BIT 0 +#else +#define FFI_TRAMPOLINE_SIZE 24 +#define FFI_TRAMPOLINE_CLOSURE_OFFSET FFI_TRAMPOLINE_SIZE +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 +#endif -#define AARCH64_N_XREG 32 -#define AARCH64_N_VREG 32 -#define AARCH64_CALL_CONTEXT_SIZE (AARCH64_N_XREG * 8 + AARCH64_N_VREG * 16) +#ifdef _WIN32 +#define FFI_EXTRA_CIF_FIELDS unsigned is_variadic +#endif +#define FFI_TARGET_SPECIFIC_VARIADIC + +/* ---- Internal ---- */ + +#if defined (__APPLE__) +#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_nfixedargs +#elif !defined(_WIN32) +/* iOS and Windows reserve x18 for the system. Disable Go closures until + a new static chain is chosen. */ +#define FFI_GO_CLOSURES 1 +#endif + +#ifndef _WIN32 +/* No complex type on Windows */ +#define FFI_TARGET_HAS_COMPLEX_TYPE +#endif #endif diff --git a/native/libffi/src/aarch64/internal.h b/native/libffi/src/aarch64/internal.h new file mode 100644 index 0000000000..3d4d0355ba --- /dev/null +++ b/native/libffi/src/aarch64/internal.h @@ -0,0 +1,68 @@ +/* +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +``Software''), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#define AARCH64_RET_VOID 0 +#define AARCH64_RET_INT64 1 +#define AARCH64_RET_INT128 2 + +#define AARCH64_RET_UNUSED3 3 +#define AARCH64_RET_UNUSED4 4 +#define AARCH64_RET_UNUSED5 5 +#define AARCH64_RET_UNUSED6 6 +#define AARCH64_RET_UNUSED7 7 + +/* Note that FFI_TYPE_FLOAT == 2, _DOUBLE == 3, _LONGDOUBLE == 4, + so _S4 through _Q1 are layed out as (TYPE * 4) + (4 - COUNT). */ +#define AARCH64_RET_S4 8 +#define AARCH64_RET_S3 9 +#define AARCH64_RET_S2 10 +#define AARCH64_RET_S1 11 + +#define AARCH64_RET_D4 12 +#define AARCH64_RET_D3 13 +#define AARCH64_RET_D2 14 +#define AARCH64_RET_D1 15 + +#define AARCH64_RET_Q4 16 +#define AARCH64_RET_Q3 17 +#define AARCH64_RET_Q2 18 +#define AARCH64_RET_Q1 19 + +/* Note that each of the sub-64-bit integers gets two entries. */ +#define AARCH64_RET_UINT8 20 +#define AARCH64_RET_UINT16 22 +#define AARCH64_RET_UINT32 24 + +#define AARCH64_RET_SINT8 26 +#define AARCH64_RET_SINT16 28 +#define AARCH64_RET_SINT32 30 + +#define AARCH64_RET_MASK 31 + +#define AARCH64_RET_IN_MEM (1 << 5) +#define AARCH64_RET_NEED_COPY (1 << 6) + +#define AARCH64_FLAG_ARG_V_BIT 7 +#define AARCH64_FLAG_ARG_V (1 << AARCH64_FLAG_ARG_V_BIT) +#define AARCH64_FLAG_VARARG (1 << 8) + +#define N_X_ARG_REG 8 +#define N_V_ARG_REG 8 +#define CALL_CONTEXT_SIZE (N_V_ARG_REG * 16 + N_X_ARG_REG * 8) diff --git a/native/libffi/src/aarch64/sysv.S b/native/libffi/src/aarch64/sysv.S index 169eab804e..ad4d11bdb2 100644 --- a/native/libffi/src/aarch64/sysv.S +++ b/native/libffi/src/aarch64/sysv.S @@ -19,9 +19,15 @@ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#if defined(__aarch64__) || defined(__arm64__) #define LIBFFI_ASM #include #include +<<<<<<< HEAD +======= +#include +#include "internal.h" +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #ifdef HAVE_MACHINE_ASM_H #include @@ -37,6 +43,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #endif #endif +<<<<<<< HEAD #define cfi_adjust_cfa_offset(off) .cfi_adjust_cfa_offset off #define cfi_rel_offset(reg, off) .cfi_rel_offset reg, off #define cfi_restore(reg) .cfi_restore reg @@ -149,80 +156,205 @@ CNAME(ffi_call_SYSV): ldp q2, q3, [x21, #8*32 + 32] ldp q4, q5, [x21, #8*32 + 64] ldp q6, q7, [x21, #8*32 + 96] -1: - /* Load the core argument passing registers. */ - ldp x0, x1, [x21, #0] - ldp x2, x3, [x21, #16] - ldp x4, x5, [x21, #32] - ldp x6, x7, [x21, #48] +======= +#ifdef __AARCH64EB__ +# define BE(X) X +#else +# define BE(X) 0 +#endif - /* Don't forget x8 which may be holding the address of a return buffer. - */ - ldr x8, [x21, #8*8] +#ifdef __ILP32__ +#define PTR_REG(n) w##n +#else +#define PTR_REG(n) x##n +#endif - blr x24 +#ifdef __ILP32__ +#define PTR_SIZE 4 +#else +#define PTR_SIZE 8 +#endif - /* Save the core argument passing registers. */ - stp x0, x1, [x21, #0] - stp x2, x3, [x21, #16] - stp x4, x5, [x21, #32] - stp x6, x7, [x21, #48] +#if FFI_EXEC_TRAMPOLINE_TABLE && defined(__MACH__) && defined(HAVE_PTRAUTH) +# define BR(r) braaz r +# define BLR(r) blraaz r +#else +# define BR(r) br r +# define BLR(r) blr r +#endif - /* Note nothing useful ever comes back in x8! */ + .text + .align 4 - /* Figure out if we should touch the vector registers. */ - tbz x23, #AARCH64_FFI_WITH_V_BIT, 1f +/* ffi_call_SYSV + extern void ffi_call_SYSV (void *stack, void *frame, + void (*fn)(void), void *rvalue, + int flags, void *closure); - /* Save the vector argument passing registers. */ - stp q0, q1, [x21, #8*32 + 0] - stp q2, q3, [x21, #8*32 + 32] - stp q4, q5, [x21, #8*32 + 64] - stp q6, q7, [x21, #8*32 + 96] -1: - /* All done, unwind our stack frame. */ - ldp x21, x22, [x29, # - ffi_call_SYSV_FS] - cfi_restore (x21) - cfi_restore (x22) + Therefore on entry we have: - ldp x23, x24, [x29, # - ffi_call_SYSV_FS + 16] - cfi_restore (x23) - cfi_restore (x24) + x0 stack + x1 frame + x2 fn + x3 rvalue + x4 flags + x5 closure +*/ - mov sp, x29 - cfi_def_cfa_register (sp) + cfi_startproc +CNAME(ffi_call_SYSV): + /* Use a stack frame allocated by our caller. */ + cfi_def_cfa(x1, 32); + stp x29, x30, [x1] + mov x29, x1 + mov sp, x0 + cfi_def_cfa_register(x29) + cfi_rel_offset (x29, 0) + cfi_rel_offset (x30, 8) + + mov x9, x2 /* save fn */ + mov x8, x3 /* install structure return */ +#ifdef FFI_GO_CLOSURES + mov x18, x5 /* install static chain */ +#endif + stp x3, x4, [x29, #16] /* save rvalue and flags */ + + /* Load the vector argument passing registers, if necessary. */ + tbz w4, #AARCH64_FLAG_ARG_V_BIT, 1f + ldp q0, q1, [sp, #0] + ldp q2, q3, [sp, #32] + ldp q4, q5, [sp, #64] + ldp q6, q7, [sp, #96] +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 +1: + /* Load the core argument passing registers, including + the structure return pointer. */ + ldp x0, x1, [sp, #16*N_V_ARG_REG + 0] + ldp x2, x3, [sp, #16*N_V_ARG_REG + 16] + ldp x4, x5, [sp, #16*N_V_ARG_REG + 32] + ldp x6, x7, [sp, #16*N_V_ARG_REG + 48] - ldp x29, x30, [sp], #16 - cfi_adjust_cfa_offset (-16) - cfi_restore (x29) - cfi_restore (x30) + /* Deallocate the context, leaving the stacked arguments. */ + add sp, sp, #CALL_CONTEXT_SIZE - ret + BLR(x9) /* call fn */ +<<<<<<< HEAD .cfi_endproc #ifdef __ELF__ .size CNAME(ffi_call_SYSV), .-CNAME(ffi_call_SYSV) #endif +======= + ldp x3, x4, [x29, #16] /* reload rvalue and flags */ +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 -#define ffi_closure_SYSV_FS (8 * 2 + AARCH64_CALL_CONTEXT_SIZE) + /* Partially deconstruct the stack frame. */ + mov sp, x29 + cfi_def_cfa_register (sp) + ldp x29, x30, [x29] + + /* Save the return value as directed. */ + adr x5, 0f + and w4, w4, #AARCH64_RET_MASK + add x5, x5, x4, lsl #3 + br x5 + + /* Note that each table entry is 2 insns, and thus 8 bytes. + For integer data, note that we're storing into ffi_arg + and therefore we want to extend to 64 bits; these types + have two consecutive entries allocated for them. */ + .align 4 +0: ret /* VOID */ + nop +1: str x0, [x3] /* INT64 */ + ret +2: stp x0, x1, [x3] /* INT128 */ + ret +3: brk #1000 /* UNUSED */ + ret +4: brk #1000 /* UNUSED */ + ret +5: brk #1000 /* UNUSED */ + ret +6: brk #1000 /* UNUSED */ + ret +7: brk #1000 /* UNUSED */ + ret +8: st4 { v0.s, v1.s, v2.s, v3.s }[0], [x3] /* S4 */ + ret +9: st3 { v0.s, v1.s, v2.s }[0], [x3] /* S3 */ + ret +10: stp s0, s1, [x3] /* S2 */ + ret +11: str s0, [x3] /* S1 */ + ret +12: st4 { v0.d, v1.d, v2.d, v3.d }[0], [x3] /* D4 */ + ret +13: st3 { v0.d, v1.d, v2.d }[0], [x3] /* D3 */ + ret +14: stp d0, d1, [x3] /* D2 */ + ret +15: str d0, [x3] /* D1 */ + ret +16: str q3, [x3, #48] /* Q4 */ + nop +17: str q2, [x3, #32] /* Q3 */ + nop +18: stp q0, q1, [x3] /* Q2 */ + ret +19: str q0, [x3] /* Q1 */ + ret +20: uxtb w0, w0 /* UINT8 */ + str x0, [x3] +21: ret /* reserved */ + nop +22: uxth w0, w0 /* UINT16 */ + str x0, [x3] +23: ret /* reserved */ + nop +24: mov w0, w0 /* UINT32 */ + str x0, [x3] +25: ret /* reserved */ + nop +26: sxtb x0, w0 /* SINT8 */ + str x0, [x3] +27: ret /* reserved */ + nop +28: sxth x0, w0 /* SINT16 */ + str x0, [x3] +29: ret /* reserved */ + nop +30: sxtw x0, w0 /* SINT32 */ + str x0, [x3] +31: ret /* reserved */ + nop + + cfi_endproc + + .globl CNAME(ffi_call_SYSV) + FFI_HIDDEN(CNAME(ffi_call_SYSV)) +#ifdef __ELF__ + .type CNAME(ffi_call_SYSV), #function + .size CNAME(ffi_call_SYSV), .-CNAME(ffi_call_SYSV) +#endif /* ffi_closure_SYSV Closure invocation glue. This is the low level code invoked directly by the closure trampoline to setup and call a closure. - On entry x17 points to a struct trampoline_data, x16 has been clobbered + On entry x17 points to a struct ffi_closure, x16 has been clobbered all other registers are preserved. We allocate a call context and save the argument passing registers, then invoked the generic C ffi_closure_SYSV_inner() function to do all the real work, on return we load the result passing registers back from the call context. +*/ - On entry - - extern void - ffi_closure_SYSV (struct trampoline_data *); +#define ffi_closure_SYSV_FS (8*2 + CALL_CONTEXT_SIZE + 64) +<<<<<<< HEAD struct trampoline_data { UINT64 *ffi_closure; @@ -331,3 +463,225 @@ CNAME(ffi_closure_SYSV): #ifdef __ELF__ .size CNAME(ffi_closure_SYSV), .-CNAME(ffi_closure_SYSV) #endif +======= + .align 4 +CNAME(ffi_closure_SYSV_V): + cfi_startproc + stp x29, x30, [sp, #-ffi_closure_SYSV_FS]! + cfi_adjust_cfa_offset (ffi_closure_SYSV_FS) + cfi_rel_offset (x29, 0) + cfi_rel_offset (x30, 8) + + /* Save the argument passing vector registers. */ + stp q0, q1, [sp, #16 + 0] + stp q2, q3, [sp, #16 + 32] + stp q4, q5, [sp, #16 + 64] + stp q6, q7, [sp, #16 + 96] + b 0f + cfi_endproc + + .globl CNAME(ffi_closure_SYSV_V) + FFI_HIDDEN(CNAME(ffi_closure_SYSV_V)) +#ifdef __ELF__ + .type CNAME(ffi_closure_SYSV_V), #function + .size CNAME(ffi_closure_SYSV_V), . - CNAME(ffi_closure_SYSV_V) +#endif + + .align 4 + cfi_startproc +CNAME(ffi_closure_SYSV): + stp x29, x30, [sp, #-ffi_closure_SYSV_FS]! + cfi_adjust_cfa_offset (ffi_closure_SYSV_FS) + cfi_rel_offset (x29, 0) + cfi_rel_offset (x30, 8) +0: + mov x29, sp + + /* Save the argument passing core registers. */ + stp x0, x1, [sp, #16 + 16*N_V_ARG_REG + 0] + stp x2, x3, [sp, #16 + 16*N_V_ARG_REG + 16] + stp x4, x5, [sp, #16 + 16*N_V_ARG_REG + 32] + stp x6, x7, [sp, #16 + 16*N_V_ARG_REG + 48] + + /* Load ffi_closure_inner arguments. */ + ldp PTR_REG(0), PTR_REG(1), [x17, #FFI_TRAMPOLINE_CLOSURE_OFFSET] /* load cif, fn */ + ldr PTR_REG(2), [x17, #FFI_TRAMPOLINE_CLOSURE_OFFSET+PTR_SIZE*2] /* load user_data */ +.Ldo_closure: + add x3, sp, #16 /* load context */ + add x4, sp, #ffi_closure_SYSV_FS /* load stack */ + add x5, sp, #16+CALL_CONTEXT_SIZE /* load rvalue */ + mov x6, x8 /* load struct_rval */ + bl CNAME(ffi_closure_SYSV_inner) + + /* Load the return value as directed. */ +#if FFI_EXEC_TRAMPOLINE_TABLE && defined(__MACH__) && defined(HAVE_PTRAUTH) + autiza x1 +#endif + adr x1, 0f + and w0, w0, #AARCH64_RET_MASK + add x1, x1, x0, lsl #3 + add x3, sp, #16+CALL_CONTEXT_SIZE + br x1 + + /* Note that each table entry is 2 insns, and thus 8 bytes. */ + .align 4 +0: b 99f /* VOID */ + nop +1: ldr x0, [x3] /* INT64 */ + b 99f +2: ldp x0, x1, [x3] /* INT128 */ + b 99f +3: brk #1000 /* UNUSED */ + nop +4: brk #1000 /* UNUSED */ + nop +5: brk #1000 /* UNUSED */ + nop +6: brk #1000 /* UNUSED */ + nop +7: brk #1000 /* UNUSED */ + nop +8: ldr s3, [x3, #12] /* S4 */ + nop +9: ldr s2, [x3, #8] /* S3 */ + nop +10: ldp s0, s1, [x3] /* S2 */ + b 99f +11: ldr s0, [x3] /* S1 */ + b 99f +12: ldr d3, [x3, #24] /* D4 */ + nop +13: ldr d2, [x3, #16] /* D3 */ + nop +14: ldp d0, d1, [x3] /* D2 */ + b 99f +15: ldr d0, [x3] /* D1 */ + b 99f +16: ldr q3, [x3, #48] /* Q4 */ + nop +17: ldr q2, [x3, #32] /* Q3 */ + nop +18: ldp q0, q1, [x3] /* Q2 */ + b 99f +19: ldr q0, [x3] /* Q1 */ + b 99f +20: ldrb w0, [x3, #BE(7)] /* UINT8 */ + b 99f +21: brk #1000 /* reserved */ + nop +22: ldrh w0, [x3, #BE(6)] /* UINT16 */ + b 99f +23: brk #1000 /* reserved */ + nop +24: ldr w0, [x3, #BE(4)] /* UINT32 */ + b 99f +25: brk #1000 /* reserved */ + nop +26: ldrsb x0, [x3, #BE(7)] /* SINT8 */ + b 99f +27: brk #1000 /* reserved */ + nop +28: ldrsh x0, [x3, #BE(6)] /* SINT16 */ + b 99f +29: brk #1000 /* reserved */ + nop +30: ldrsw x0, [x3, #BE(4)] /* SINT32 */ + nop +31: /* reserved */ +99: ldp x29, x30, [sp], #ffi_closure_SYSV_FS + cfi_adjust_cfa_offset (-ffi_closure_SYSV_FS) + cfi_restore (x29) + cfi_restore (x30) + ret + cfi_endproc + + .globl CNAME(ffi_closure_SYSV) + FFI_HIDDEN(CNAME(ffi_closure_SYSV)) +#ifdef __ELF__ + .type CNAME(ffi_closure_SYSV), #function + .size CNAME(ffi_closure_SYSV), . - CNAME(ffi_closure_SYSV) +#endif + +#if FFI_EXEC_TRAMPOLINE_TABLE + +#ifdef __MACH__ +#include + .align PAGE_MAX_SHIFT +CNAME(ffi_closure_trampoline_table_page): + .rept PAGE_MAX_SIZE / FFI_TRAMPOLINE_SIZE + adr x16, -PAGE_MAX_SIZE + ldp x17, x16, [x16] + BR(x16) + nop /* each entry in the trampoline config page is 2*sizeof(void*) so the trampoline itself cannot be smaller than 16 bytes */ + .endr + + .globl CNAME(ffi_closure_trampoline_table_page) + FFI_HIDDEN(CNAME(ffi_closure_trampoline_table_page)) + #ifdef __ELF__ + .type CNAME(ffi_closure_trampoline_table_page), #function + .size CNAME(ffi_closure_trampoline_table_page), . - CNAME(ffi_closure_trampoline_table_page) + #endif +#endif + +#endif /* FFI_EXEC_TRAMPOLINE_TABLE */ + +#ifdef FFI_GO_CLOSURES + .align 4 +CNAME(ffi_go_closure_SYSV_V): + cfi_startproc + stp x29, x30, [sp, #-ffi_closure_SYSV_FS]! + cfi_adjust_cfa_offset (ffi_closure_SYSV_FS) + cfi_rel_offset (x29, 0) + cfi_rel_offset (x30, 8) + + /* Save the argument passing vector registers. */ + stp q0, q1, [sp, #16 + 0] + stp q2, q3, [sp, #16 + 32] + stp q4, q5, [sp, #16 + 64] + stp q6, q7, [sp, #16 + 96] + b 0f + cfi_endproc + + .globl CNAME(ffi_go_closure_SYSV_V) + FFI_HIDDEN(CNAME(ffi_go_closure_SYSV_V)) +#ifdef __ELF__ + .type CNAME(ffi_go_closure_SYSV_V), #function + .size CNAME(ffi_go_closure_SYSV_V), . - CNAME(ffi_go_closure_SYSV_V) +#endif + + .align 4 + cfi_startproc +CNAME(ffi_go_closure_SYSV): + stp x29, x30, [sp, #-ffi_closure_SYSV_FS]! + cfi_adjust_cfa_offset (ffi_closure_SYSV_FS) + cfi_rel_offset (x29, 0) + cfi_rel_offset (x30, 8) +0: + mov x29, sp + + /* Save the argument passing core registers. */ + stp x0, x1, [sp, #16 + 16*N_V_ARG_REG + 0] + stp x2, x3, [sp, #16 + 16*N_V_ARG_REG + 16] + stp x4, x5, [sp, #16 + 16*N_V_ARG_REG + 32] + stp x6, x7, [sp, #16 + 16*N_V_ARG_REG + 48] + + /* Load ffi_closure_inner arguments. */ + ldp PTR_REG(0), PTR_REG(1), [x18, #PTR_SIZE]/* load cif, fn */ + mov x2, x18 /* load user_data */ + b .Ldo_closure + cfi_endproc + + .globl CNAME(ffi_go_closure_SYSV) + FFI_HIDDEN(CNAME(ffi_go_closure_SYSV)) +#ifdef __ELF__ + .type CNAME(ffi_go_closure_SYSV), #function + .size CNAME(ffi_go_closure_SYSV), . - CNAME(ffi_go_closure_SYSV) +#endif +#endif /* FFI_GO_CLOSURES */ +#endif /* __arm64__ */ + +#if defined __ELF__ && defined __linux__ + .section .note.GNU-stack,"",%progbits +#endif + +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 diff --git a/native/libffi/src/aarch64/win64_armasm.S b/native/libffi/src/aarch64/win64_armasm.S new file mode 100644 index 0000000000..7fc185b3d8 --- /dev/null +++ b/native/libffi/src/aarch64/win64_armasm.S @@ -0,0 +1,506 @@ +/* Copyright (c) 2009, 2010, 2011, 2012 ARM Ltd. +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +``Software''), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#define LIBFFI_ASM +#include +#include +#include +#include "internal.h" + + OPT 2 /*disable listing */ +/* For some macros to add unwind information */ +#include "ksarm64.h" + OPT 1 /*re-enable listing */ + +#define BE(X) 0 +#define PTR_REG(n) x##n +#define PTR_SIZE 8 + + IMPORT ffi_closure_SYSV_inner + EXPORT ffi_call_SYSV + EXPORT ffi_closure_SYSV_V + EXPORT ffi_closure_SYSV + EXPORT extend_hfa_type + EXPORT compress_hfa_type +#ifdef FFI_GO_CLOSURES + EXPORT ffi_go_closure_SYSV_V + EXPORT ffi_go_closure_SYSV +#endif + + TEXTAREA, ALIGN=8 + +/* ffi_call_SYSV + extern void ffi_call_SYSV (void *stack, void *frame, + void (*fn)(void), void *rvalue, + int flags, void *closure); + Therefore on entry we have: + x0 stack + x1 frame + x2 fn + x3 rvalue + x4 flags + x5 closure +*/ + + NESTED_ENTRY ffi_call_SYSV_fake + + /* For unwind information, Windows has to store fp and lr */ + PROLOG_SAVE_REG_PAIR x29, x30, #-32! + + ALTERNATE_ENTRY ffi_call_SYSV + /* Use a stack frame allocated by our caller. */ + stp x29, x30, [x1] + mov x29, x1 + mov sp, x0 + + mov x9, x2 /* save fn */ + mov x8, x3 /* install structure return */ +#ifdef FFI_GO_CLOSURES + /*mov x18, x5 install static chain */ +#endif + stp x3, x4, [x29, #16] /* save rvalue and flags */ + + /* Load the vector argument passing registers, if necessary. */ + tbz x4, #AARCH64_FLAG_ARG_V_BIT, ffi_call_SYSV_L1 + ldp q0, q1, [sp, #0] + ldp q2, q3, [sp, #32] + ldp q4, q5, [sp, #64] + ldp q6, q7, [sp, #96] + +ffi_call_SYSV_L1 + /* Load the core argument passing registers, including + the structure return pointer. */ + ldp x0, x1, [sp, #16*N_V_ARG_REG + 0] + ldp x2, x3, [sp, #16*N_V_ARG_REG + 16] + ldp x4, x5, [sp, #16*N_V_ARG_REG + 32] + ldp x6, x7, [sp, #16*N_V_ARG_REG + 48] + + /* Deallocate the context, leaving the stacked arguments. */ + add sp, sp, #CALL_CONTEXT_SIZE + + blr x9 /* call fn */ + + ldp x3, x4, [x29, #16] /* reload rvalue and flags */ + + /* Partially deconstruct the stack frame. */ + mov sp, x29 + ldp x29, x30, [x29] + + /* Save the return value as directed. */ + adr x5, ffi_call_SYSV_return + and w4, w4, #AARCH64_RET_MASK + add x5, x5, x4, lsl #3 + br x5 + + /* Note that each table entry is 2 insns, and thus 8 bytes. + For integer data, note that we're storing into ffi_arg + and therefore we want to extend to 64 bits; these types + have two consecutive entries allocated for them. */ + ALIGN 4 +ffi_call_SYSV_return + ret /* VOID */ + nop + str x0, [x3] /* INT64 */ + ret + stp x0, x1, [x3] /* INT128 */ + ret + brk #1000 /* UNUSED */ + ret + brk #1000 /* UNUSED */ + ret + brk #1000 /* UNUSED */ + ret + brk #1000 /* UNUSED */ + ret + brk #1000 /* UNUSED */ + ret + st4 { v0.s, v1.s, v2.s, v3.s }[0], [x3] /* S4 */ + ret + st3 { v0.s, v1.s, v2.s }[0], [x3] /* S3 */ + ret + stp s0, s1, [x3] /* S2 */ + ret + str s0, [x3] /* S1 */ + ret + st4 { v0.d, v1.d, v2.d, v3.d }[0], [x3] /* D4 */ + ret + st3 { v0.d, v1.d, v2.d }[0], [x3] /* D3 */ + ret + stp d0, d1, [x3] /* D2 */ + ret + str d0, [x3] /* D1 */ + ret + str q3, [x3, #48] /* Q4 */ + nop + str q2, [x3, #32] /* Q3 */ + nop + stp q0, q1, [x3] /* Q2 */ + ret + str q0, [x3] /* Q1 */ + ret + uxtb w0, w0 /* UINT8 */ + str x0, [x3] + ret /* reserved */ + nop + uxth w0, w0 /* UINT16 */ + str x0, [x3] + ret /* reserved */ + nop + mov w0, w0 /* UINT32 */ + str x0, [x3] + ret /* reserved */ + nop + sxtb x0, w0 /* SINT8 */ + str x0, [x3] + ret /* reserved */ + nop + sxth x0, w0 /* SINT16 */ + str x0, [x3] + ret /* reserved */ + nop + sxtw x0, w0 /* SINT32 */ + str x0, [x3] + ret /* reserved */ + nop + + + NESTED_END ffi_call_SYSV_fake + + +/* ffi_closure_SYSV + Closure invocation glue. This is the low level code invoked directly by + the closure trampoline to setup and call a closure. + On entry x17 points to a struct ffi_closure, x16 has been clobbered + all other registers are preserved. + We allocate a call context and save the argument passing registers, + then invoked the generic C ffi_closure_SYSV_inner() function to do all + the real work, on return we load the result passing registers back from + the call context. +*/ + +#define ffi_closure_SYSV_FS (8*2 + CALL_CONTEXT_SIZE + 64) + + NESTED_ENTRY ffi_closure_SYSV_V + PROLOG_SAVE_REG_PAIR x29, x30, #-ffi_closure_SYSV_FS! + + /* Save the argument passing vector registers. */ + stp q0, q1, [sp, #16 + 0] + stp q2, q3, [sp, #16 + 32] + stp q4, q5, [sp, #16 + 64] + stp q6, q7, [sp, #16 + 96] + + b ffi_closure_SYSV_save_argument + NESTED_END ffi_closure_SYSV_V + + NESTED_ENTRY ffi_closure_SYSV + PROLOG_SAVE_REG_PAIR x29, x30, #-ffi_closure_SYSV_FS! + +ffi_closure_SYSV_save_argument + /* Save the argument passing core registers. */ + stp x0, x1, [sp, #16 + 16*N_V_ARG_REG + 0] + stp x2, x3, [sp, #16 + 16*N_V_ARG_REG + 16] + stp x4, x5, [sp, #16 + 16*N_V_ARG_REG + 32] + stp x6, x7, [sp, #16 + 16*N_V_ARG_REG + 48] + + /* Load ffi_closure_inner arguments. */ + ldp PTR_REG(0), PTR_REG(1), [x17, #FFI_TRAMPOLINE_CLOSURE_OFFSET] /* load cif, fn */ + ldr PTR_REG(2), [x17, #FFI_TRAMPOLINE_CLOSURE_OFFSET+PTR_SIZE*2] /* load user_data */ + +do_closure + add x3, sp, #16 /* load context */ + add x4, sp, #ffi_closure_SYSV_FS /* load stack */ + add x5, sp, #16+CALL_CONTEXT_SIZE /* load rvalue */ + mov x6, x8 /* load struct_rval */ + + bl ffi_closure_SYSV_inner + + /* Load the return value as directed. */ + adr x1, ffi_closure_SYSV_return_base + and w0, w0, #AARCH64_RET_MASK + add x1, x1, x0, lsl #3 + add x3, sp, #16+CALL_CONTEXT_SIZE + br x1 + + /* Note that each table entry is 2 insns, and thus 8 bytes. */ + ALIGN 8 +ffi_closure_SYSV_return_base + b ffi_closure_SYSV_epilog /* VOID */ + nop + ldr x0, [x3] /* INT64 */ + b ffi_closure_SYSV_epilog + ldp x0, x1, [x3] /* INT128 */ + b ffi_closure_SYSV_epilog + brk #1000 /* UNUSED */ + nop + brk #1000 /* UNUSED */ + nop + brk #1000 /* UNUSED */ + nop + brk #1000 /* UNUSED */ + nop + brk #1000 /* UNUSED */ + nop + ldr s3, [x3, #12] /* S4 */ + nop + ldr s2, [x3, #8] /* S3 */ + nop + ldp s0, s1, [x3] /* S2 */ + b ffi_closure_SYSV_epilog + ldr s0, [x3] /* S1 */ + b ffi_closure_SYSV_epilog + ldr d3, [x3, #24] /* D4 */ + nop + ldr d2, [x3, #16] /* D3 */ + nop + ldp d0, d1, [x3] /* D2 */ + b ffi_closure_SYSV_epilog + ldr d0, [x3] /* D1 */ + b ffi_closure_SYSV_epilog + ldr q3, [x3, #48] /* Q4 */ + nop + ldr q2, [x3, #32] /* Q3 */ + nop + ldp q0, q1, [x3] /* Q2 */ + b ffi_closure_SYSV_epilog + ldr q0, [x3] /* Q1 */ + b ffi_closure_SYSV_epilog + ldrb w0, [x3, #BE(7)] /* UINT8 */ + b ffi_closure_SYSV_epilog + brk #1000 /* reserved */ + nop + ldrh w0, [x3, #BE(6)] /* UINT16 */ + b ffi_closure_SYSV_epilog + brk #1000 /* reserved */ + nop + ldr w0, [x3, #BE(4)] /* UINT32 */ + b ffi_closure_SYSV_epilog + brk #1000 /* reserved */ + nop + ldrsb x0, [x3, #BE(7)] /* SINT8 */ + b ffi_closure_SYSV_epilog + brk #1000 /* reserved */ + nop + ldrsh x0, [x3, #BE(6)] /* SINT16 */ + b ffi_closure_SYSV_epilog + brk #1000 /* reserved */ + nop + ldrsw x0, [x3, #BE(4)] /* SINT32 */ + nop + /* reserved */ + +ffi_closure_SYSV_epilog + EPILOG_RESTORE_REG_PAIR x29, x30, #ffi_closure_SYSV_FS! + EPILOG_RETURN + NESTED_END ffi_closure_SYSV + + +#ifdef FFI_GO_CLOSURES + NESTED_ENTRY ffi_go_closure_SYSV_V + PROLOG_SAVE_REG_PAIR x29, x30, #-ffi_closure_SYSV_FS! + + /* Save the argument passing vector registers. */ + stp q0, q1, [sp, #16 + 0] + stp q2, q3, [sp, #16 + 32] + stp q4, q5, [sp, #16 + 64] + stp q6, q7, [sp, #16 + 96] + b ffi_go_closure_SYSV_save_argument + NESTED_END ffi_go_closure_SYSV_V + + NESTED_ENTRY ffi_go_closure_SYSV + PROLOG_SAVE_REG_PAIR x29, x30, #-ffi_closure_SYSV_FS! + +ffi_go_closure_SYSV_save_argument + /* Save the argument passing core registers. */ + stp x0, x1, [sp, #16 + 16*N_V_ARG_REG + 0] + stp x2, x3, [sp, #16 + 16*N_V_ARG_REG + 16] + stp x4, x5, [sp, #16 + 16*N_V_ARG_REG + 32] + stp x6, x7, [sp, #16 + 16*N_V_ARG_REG + 48] + + /* Load ffi_closure_inner arguments. */ + ldp PTR_REG(0), PTR_REG(1), [x18, #PTR_SIZE]/* load cif, fn */ + mov x2, x18 /* load user_data */ + b do_closure + NESTED_END ffi_go_closure_SYSV + +#endif /* FFI_GO_CLOSURES */ + + +/* void extend_hfa_type (void *dest, void *src, int h) */ + + LEAF_ENTRY extend_hfa_type + + adr x3, extend_hfa_type_jump_base + and w2, w2, #AARCH64_RET_MASK + sub x2, x2, #AARCH64_RET_S4 + add x3, x3, x2, lsl #4 + br x3 + + ALIGN 4 +extend_hfa_type_jump_base + ldp s16, s17, [x1] /* S4 */ + ldp s18, s19, [x1, #8] + b extend_hfa_type_store_4 + nop + + ldp s16, s17, [x1] /* S3 */ + ldr s18, [x1, #8] + b extend_hfa_type_store_3 + nop + + ldp s16, s17, [x1] /* S2 */ + b extend_hfa_type_store_2 + nop + nop + + ldr s16, [x1] /* S1 */ + b extend_hfa_type_store_1 + nop + nop + + ldp d16, d17, [x1] /* D4 */ + ldp d18, d19, [x1, #16] + b extend_hfa_type_store_4 + nop + + ldp d16, d17, [x1] /* D3 */ + ldr d18, [x1, #16] + b extend_hfa_type_store_3 + nop + + ldp d16, d17, [x1] /* D2 */ + b extend_hfa_type_store_2 + nop + nop + + ldr d16, [x1] /* D1 */ + b extend_hfa_type_store_1 + nop + nop + + ldp q16, q17, [x1] /* Q4 */ + ldp q18, q19, [x1, #16] + b extend_hfa_type_store_4 + nop + + ldp q16, q17, [x1] /* Q3 */ + ldr q18, [x1, #16] + b extend_hfa_type_store_3 + nop + + ldp q16, q17, [x1] /* Q2 */ + b extend_hfa_type_store_2 + nop + nop + + ldr q16, [x1] /* Q1 */ + b extend_hfa_type_store_1 + +extend_hfa_type_store_4 + str q19, [x0, #48] +extend_hfa_type_store_3 + str q18, [x0, #32] +extend_hfa_type_store_2 + str q17, [x0, #16] +extend_hfa_type_store_1 + str q16, [x0] + ret + + LEAF_END extend_hfa_type + + +/* void compress_hfa_type (void *dest, void *reg, int h) */ + + LEAF_ENTRY compress_hfa_type + + adr x3, compress_hfa_type_jump_base + and w2, w2, #AARCH64_RET_MASK + sub x2, x2, #AARCH64_RET_S4 + add x3, x3, x2, lsl #4 + br x3 + + ALIGN 4 +compress_hfa_type_jump_base + ldp q16, q17, [x1] /* S4 */ + ldp q18, q19, [x1, #32] + st4 { v16.s, v17.s, v18.s, v19.s }[0], [x0] + ret + + ldp q16, q17, [x1] /* S3 */ + ldr q18, [x1, #32] + st3 { v16.s, v17.s, v18.s }[0], [x0] + ret + + ldp q16, q17, [x1] /* S2 */ + st2 { v16.s, v17.s }[0], [x0] + ret + nop + + ldr q16, [x1] /* S1 */ + st1 { v16.s }[0], [x0] + ret + nop + + ldp q16, q17, [x1] /* D4 */ + ldp q18, q19, [x1, #32] + st4 { v16.d, v17.d, v18.d, v19.d }[0], [x0] + ret + + ldp q16, q17, [x1] /* D3 */ + ldr q18, [x1, #32] + st3 { v16.d, v17.d, v18.d }[0], [x0] + ret + + ldp q16, q17, [x1] /* D2 */ + st2 { v16.d, v17.d }[0], [x0] + ret + nop + + ldr q16, [x1] /* D1 */ + st1 { v16.d }[0], [x0] + ret + nop + + ldp q16, q17, [x1] /* Q4 */ + ldp q18, q19, [x1, #32] + b compress_hfa_type_store_q4 + nop + + ldp q16, q17, [x1] /* Q3 */ + ldr q18, [x1, #32] + b compress_hfa_type_store_q3 + nop + + ldp q16, q17, [x1] /* Q2 */ + stp q16, q17, [x0] + ret + nop + + ldr q16, [x1] /* Q1 */ + str q16, [x0] + ret + +compress_hfa_type_store_q4 + str q19, [x0, #48] +compress_hfa_type_store_q3 + str q18, [x0, #32] + stp q16, q17, [x0] + ret + + LEAF_END compress_hfa_type + + END \ No newline at end of file diff --git a/native/libffi/src/alpha/ffi.c b/native/libffi/src/alpha/ffi.c index 192f691c4a..7a95e9707c 100644 --- a/native/libffi/src/alpha/ffi.c +++ b/native/libffi/src/alpha/ffi.c @@ -1,8 +1,8 @@ /* ----------------------------------------------------------------------- ffi.c - Copyright (c) 2012 Anthony Green - Copyright (c) 1998, 2001, 2007, 2008 Red Hat, Inc. - - Alpha Foreign Function Interface + Copyright (c) 1998, 2001, 2007, 2008 Red Hat, Inc. + + Alpha Foreign Function Interface Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -28,6 +28,7 @@ #include #include #include +#include "internal.h" /* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE; all further uses in this file will refer to the 128-bit type. */ @@ -40,135 +41,286 @@ # define FFI_TYPE_LONGDOUBLE 4 #endif -extern void ffi_call_osf(void *, unsigned long, unsigned, void *, void (*)(void)) - FFI_HIDDEN; +extern void ffi_call_osf(void *stack, void *frame, unsigned flags, + void *raddr, void (*fn)(void), void *closure) + FFI_HIDDEN; extern void ffi_closure_osf(void) FFI_HIDDEN; +extern void ffi_go_closure_osf(void) FFI_HIDDEN; +/* Promote a float value to its in-register double representation. + Unlike actually casting to double, this does not trap on NaN. */ +static inline UINT64 lds(void *ptr) +{ + UINT64 ret; + asm("lds %0,%1" : "=f"(ret) : "m"(*(UINT32 *)ptr)); + return ret; +} -ffi_status +/* And the reverse. */ +static inline void sts(void *ptr, UINT64 val) +{ + asm("sts %1,%0" : "=m"(*(UINT32 *)ptr) : "f"(val)); +} + +ffi_status FFI_HIDDEN ffi_prep_cif_machdep(ffi_cif *cif) { - /* Adjust cif->bytes to represent a minimum 6 words for the temporary - register argument loading area. */ - if (cif->bytes < 6*FFI_SIZEOF_ARG) - cif->bytes = 6*FFI_SIZEOF_ARG; + size_t bytes = 0; + int flags, i, avn; + ffi_type *rtype, *itype; + + if (cif->abi != FFI_OSF) + return FFI_BAD_ABI; + + /* Compute the size of the argument area. */ + for (i = 0, avn = cif->nargs; i < avn; i++) + { + itype = cif->arg_types[i]; + switch (itype->type) + { + case FFI_TYPE_INT: + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT16: + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + case FFI_TYPE_POINTER: + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + case FFI_TYPE_LONGDOUBLE: + /* All take one 8 byte slot. */ + bytes += 8; + break; + + case FFI_TYPE_VOID: + case FFI_TYPE_STRUCT: + /* Passed by value in N slots. */ + bytes += FFI_ALIGN(itype->size, FFI_SIZEOF_ARG); + break; + + case FFI_TYPE_COMPLEX: + /* _Complex long double passed by reference; others in 2 slots. */ + if (itype->elements[0]->type == FFI_TYPE_LONGDOUBLE) + bytes += 8; + else + bytes += 16; + break; + + default: + abort(); + } + } /* Set the return type flag */ - switch (cif->rtype->type) + rtype = cif->rtype; + switch (rtype->type) { - case FFI_TYPE_STRUCT: + case FFI_TYPE_VOID: + flags = ALPHA_FLAGS(ALPHA_ST_VOID, ALPHA_LD_VOID); + break; + case FFI_TYPE_INT: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT32: + flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_INT32); + break; case FFI_TYPE_FLOAT: + flags = ALPHA_FLAGS(ALPHA_ST_FLOAT, ALPHA_LD_FLOAT); + break; case FFI_TYPE_DOUBLE: - cif->flags = cif->rtype->type; + flags = ALPHA_FLAGS(ALPHA_ST_DOUBLE, ALPHA_LD_DOUBLE); + break; + case FFI_TYPE_UINT8: + flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_UINT8); + break; + case FFI_TYPE_SINT8: + flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_SINT8); + break; + case FFI_TYPE_UINT16: + flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_UINT16); + break; + case FFI_TYPE_SINT16: + flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_SINT16); + break; + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: + case FFI_TYPE_POINTER: + flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_INT64); break; - case FFI_TYPE_LONGDOUBLE: - /* 128-bit long double is returned in memory, like a struct. */ - cif->flags = FFI_TYPE_STRUCT; + case FFI_TYPE_STRUCT: + /* Passed in memory, with a hidden pointer. */ + flags = ALPHA_RET_IN_MEM; break; - - default: - cif->flags = FFI_TYPE_INT; + case FFI_TYPE_COMPLEX: + itype = rtype->elements[0]; + switch (itype->type) + { + case FFI_TYPE_FLOAT: + flags = ALPHA_FLAGS(ALPHA_ST_CPLXF, ALPHA_LD_CPLXF); + break; + case FFI_TYPE_DOUBLE: + flags = ALPHA_FLAGS(ALPHA_ST_CPLXD, ALPHA_LD_CPLXD); + break; + default: + if (rtype->size <= 8) + flags = ALPHA_FLAGS(ALPHA_ST_INT, ALPHA_LD_INT64); + else + flags = ALPHA_RET_IN_MEM; + break; + } break; + default: + abort(); } - + cif->flags = flags; + + /* Include the hidden structure pointer in args requirement. */ + if (flags == ALPHA_RET_IN_MEM) + bytes += 8; + /* Minimum size is 6 slots, so that ffi_call_osf can pop them. */ + if (bytes < 6*8) + bytes = 6*8; + cif->bytes = bytes; + return FFI_OK; } +static unsigned long +extend_basic_type(void *valp, int type, int argn) +{ + switch (type) + { + case FFI_TYPE_SINT8: + return *(SINT8 *)valp; + case FFI_TYPE_UINT8: + return *(UINT8 *)valp; + case FFI_TYPE_SINT16: + return *(SINT16 *)valp; + case FFI_TYPE_UINT16: + return *(UINT16 *)valp; + + case FFI_TYPE_FLOAT: + if (argn < 6) + return lds(valp); + /* FALLTHRU */ + + case FFI_TYPE_INT: + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + /* Note that unsigned 32-bit quantities are sign extended. */ + return *(SINT32 *)valp; + + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + case FFI_TYPE_POINTER: + case FFI_TYPE_DOUBLE: + return *(UINT64 *)valp; -void -ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) + default: + abort(); + } +} + +static void +ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure) { - unsigned long *stack, *argp; - long i, avn; + unsigned long *argp; + long i, avn, argn, flags = cif->flags; ffi_type **arg_types; - + void *frame; + /* If the return value is a struct and we don't have a return value address then we need to make one. */ - if (rvalue == NULL && cif->flags == FFI_TYPE_STRUCT) + if (rvalue == NULL && flags == ALPHA_RET_IN_MEM) rvalue = alloca(cif->rtype->size); /* Allocate the space for the arguments, plus 4 words of temp space for ffi_call_osf. */ - argp = stack = alloca(cif->bytes + 4*FFI_SIZEOF_ARG); + argp = frame = alloca(cif->bytes + 4*FFI_SIZEOF_ARG); + frame += cif->bytes; - if (cif->flags == FFI_TYPE_STRUCT) - *(void **) argp++ = rvalue; + argn = 0; + if (flags == ALPHA_RET_IN_MEM) + argp[argn++] = (unsigned long)rvalue; - i = 0; avn = cif->nargs; arg_types = cif->arg_types; - while (i < avn) + for (i = 0, avn = cif->nargs; i < avn; i++) { - size_t size = (*arg_types)->size; + ffi_type *ty = arg_types[i]; + void *valp = avalue[i]; + int type = ty->type; + size_t size; - switch ((*arg_types)->type) + switch (type) { + case FFI_TYPE_INT: case FFI_TYPE_SINT8: - *(SINT64 *) argp = *(SINT8 *)(* avalue); - break; - case FFI_TYPE_UINT8: - *(SINT64 *) argp = *(UINT8 *)(* avalue); - break; - case FFI_TYPE_SINT16: - *(SINT64 *) argp = *(SINT16 *)(* avalue); - break; - case FFI_TYPE_UINT16: - *(SINT64 *) argp = *(UINT16 *)(* avalue); - break; - case FFI_TYPE_SINT32: case FFI_TYPE_UINT32: - /* Note that unsigned 32-bit quantities are sign extended. */ - *(SINT64 *) argp = *(SINT32 *)(* avalue); - break; - case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: case FFI_TYPE_POINTER: - *(UINT64 *) argp = *(UINT64 *)(* avalue); - break; - case FFI_TYPE_FLOAT: - if (argp - stack < 6) - { - /* Note the conversion -- all the fp regs are loaded as - doubles. The in-register format is the same. */ - *(double *) argp = *(float *)(* avalue); - } - else - *(float *) argp = *(float *)(* avalue); - break; - case FFI_TYPE_DOUBLE: - *(double *) argp = *(double *)(* avalue); + argp[argn] = extend_basic_type(valp, type, argn); + argn++; break; case FFI_TYPE_LONGDOUBLE: - /* 128-bit long double is passed by reference. */ - *(long double **) argp = (long double *)(* avalue); - size = sizeof (long double *); + by_reference: + /* Note that 128-bit long double is passed by reference. */ + argp[argn++] = (unsigned long)valp; break; + case FFI_TYPE_VOID: case FFI_TYPE_STRUCT: - memcpy(argp, *avalue, (*arg_types)->size); + size = ty->size; + memcpy(argp + argn, valp, size); + argn += FFI_ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; + break; + + case FFI_TYPE_COMPLEX: + type = ty->elements[0]->type; + if (type == FFI_TYPE_LONGDOUBLE) + goto by_reference; + + /* Most complex types passed as two separate arguments. */ + size = ty->elements[0]->size; + argp[argn] = extend_basic_type(valp, type, argn); + argp[argn + 1] = extend_basic_type(valp + size, type, argn + 1); + argn += 2; break; default: - FFI_ASSERT(0); + abort(); } - - argp += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; - i++, arg_types++, avalue++; } - ffi_call_osf(stack, cif->bytes, cif->flags, rvalue, fn); + flags = (flags >> ALPHA_ST_SHIFT) & 0xff; + ffi_call_osf(argp, frame, flags, rvalue, fn, closure); +} + +void +ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +{ + ffi_call_int(cif, fn, rvalue, avalue, NULL); } +void +ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure) +{ + ffi_call_int(cif, fn, rvalue, avalue, closure); +} ffi_status ffi_prep_closure_loc (ffi_closure* closure, @@ -204,39 +356,56 @@ ffi_prep_closure_loc (ffi_closure* closure, return FFI_OK; } +ffi_status +ffi_prep_go_closure (ffi_go_closure* closure, + ffi_cif* cif, + void (*fun)(ffi_cif*, void*, void**, void*)) +{ + if (cif->abi != FFI_OSF) + return FFI_BAD_ABI; + + closure->tramp = (void *)ffi_go_closure_osf; + closure->cif = cif; + closure->fun = fun; + + return FFI_OK; +} long FFI_HIDDEN -ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp) +ffi_closure_osf_inner (ffi_cif *cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void *user_data, + void *rvalue, unsigned long *argp) { - ffi_cif *cif; void **avalue; ffi_type **arg_types; - long i, avn, argn; + long i, avn, argn, flags; - cif = closure->cif; avalue = alloca(cif->nargs * sizeof(void *)); - + flags = cif->flags; argn = 0; /* Copy the caller's structure return address to that the closure returns the data directly to the caller. */ - if (cif->flags == FFI_TYPE_STRUCT) + if (flags == ALPHA_RET_IN_MEM) { rvalue = (void *) argp[0]; argn = 1; } - i = 0; - avn = cif->nargs; arg_types = cif->arg_types; - + /* Grab the addresses of the arguments from the stack frame. */ - while (i < avn) + for (i = 0, avn = cif->nargs; i < avn; i++) { - size_t size = arg_types[i]->size; + ffi_type *ty = arg_types[i]; + int type = ty->type; + void *valp = &argp[argn]; + size_t size; - switch (arg_types[i]->type) + switch (type) { + case FFI_TYPE_INT: case FFI_TYPE_SINT8: case FFI_TYPE_UINT8: case FFI_TYPE_SINT16: @@ -246,43 +415,107 @@ ffi_closure_osf_inner(ffi_closure *closure, void *rvalue, unsigned long *argp) case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: case FFI_TYPE_POINTER: + argn += 1; + break; + + case FFI_TYPE_VOID: case FFI_TYPE_STRUCT: - avalue[i] = &argp[argn]; + size = ty->size; + argn += FFI_ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; break; case FFI_TYPE_FLOAT: + /* Floats coming from registers need conversion from double + back to float format. */ if (argn < 6) { - /* Floats coming from registers need conversion from double - back to float format. */ - *(float *)&argp[argn - 6] = *(double *)&argp[argn - 6]; - avalue[i] = &argp[argn - 6]; + valp = &argp[argn - 6]; + sts(valp, argp[argn - 6]); } - else - avalue[i] = &argp[argn]; + argn += 1; break; case FFI_TYPE_DOUBLE: - avalue[i] = &argp[argn - (argn < 6 ? 6 : 0)]; + if (argn < 6) + valp = &argp[argn - 6]; + argn += 1; break; case FFI_TYPE_LONGDOUBLE: + by_reference: /* 128-bit long double is passed by reference. */ - avalue[i] = (long double *) argp[argn]; - size = sizeof (long double *); + valp = (void *)argp[argn]; + argn += 1; + break; + + case FFI_TYPE_COMPLEX: + type = ty->elements[0]->type; + switch (type) + { + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + /* Passed as separate arguments, but they wind up sequential. */ + break; + + case FFI_TYPE_INT: + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT16: + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + /* Passed as separate arguments. Disjoint, but there's room + enough in one slot to hold the pair. */ + size = ty->elements[0]->size; + memcpy(valp + size, valp + 8, size); + break; + + case FFI_TYPE_FLOAT: + /* Passed as separate arguments. Disjoint, and each piece + may need conversion back to float. */ + if (argn < 6) + { + valp = &argp[argn - 6]; + sts(valp, argp[argn - 6]); + } + if (argn + 1 < 6) + sts(valp + 4, argp[argn + 1 - 6]); + else + *(UINT32 *)(valp + 4) = argp[argn + 1]; + break; + + case FFI_TYPE_DOUBLE: + /* Passed as separate arguments. Only disjoint if one part + is in fp regs and the other is on the stack. */ + if (argn < 5) + valp = &argp[argn - 6]; + else if (argn == 5) + { + valp = alloca(16); + ((UINT64 *)valp)[0] = argp[5 - 6]; + ((UINT64 *)valp)[1] = argp[6]; + } + break; + + case FFI_TYPE_LONGDOUBLE: + goto by_reference; + + default: + abort(); + } + argn += 2; break; default: abort (); } - argn += ALIGN(size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; - i++; + avalue[i] = valp; } /* Invoke the closure. */ - closure->fun (cif, rvalue, avalue, closure->user_data); + fun (cif, rvalue, avalue, user_data); /* Tell ffi_closure_osf how to perform return type promotions. */ - return cif->rtype->type; + return (flags >> ALPHA_LD_SHIFT) & 0xff; } diff --git a/native/libffi/src/alpha/ffitarget.h b/native/libffi/src/alpha/ffitarget.h index af145bce83..a02dbd04f6 100644 --- a/native/libffi/src/alpha/ffitarget.h +++ b/native/libffi/src/alpha/ffitarget.h @@ -44,9 +44,13 @@ typedef enum ffi_abi { } ffi_abi; #endif +#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION +#define FFI_TARGET_HAS_COMPLEX_TYPE + /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 +#define FFI_GO_CLOSURES 1 #define FFI_TRAMPOLINE_SIZE 24 #define FFI_NATIVE_RAW_API 0 diff --git a/native/libffi/src/alpha/internal.h b/native/libffi/src/alpha/internal.h new file mode 100644 index 0000000000..44da1922bb --- /dev/null +++ b/native/libffi/src/alpha/internal.h @@ -0,0 +1,23 @@ +#define ALPHA_ST_VOID 0 +#define ALPHA_ST_INT 1 +#define ALPHA_ST_FLOAT 2 +#define ALPHA_ST_DOUBLE 3 +#define ALPHA_ST_CPLXF 4 +#define ALPHA_ST_CPLXD 5 + +#define ALPHA_LD_VOID 0 +#define ALPHA_LD_INT64 1 +#define ALPHA_LD_INT32 2 +#define ALPHA_LD_UINT16 3 +#define ALPHA_LD_SINT16 4 +#define ALPHA_LD_UINT8 5 +#define ALPHA_LD_SINT8 6 +#define ALPHA_LD_FLOAT 7 +#define ALPHA_LD_DOUBLE 8 +#define ALPHA_LD_CPLXF 9 +#define ALPHA_LD_CPLXD 10 + +#define ALPHA_ST_SHIFT 0 +#define ALPHA_LD_SHIFT 8 +#define ALPHA_RET_IN_MEM 0x10000 +#define ALPHA_FLAGS(S, L) (((L) << ALPHA_LD_SHIFT) | (S)) diff --git a/native/libffi/src/alpha/osf.S b/native/libffi/src/alpha/osf.S index 6b9f4dfa03..b0318282a0 100644 --- a/native/libffi/src/alpha/osf.S +++ b/native/libffi/src/alpha/osf.S @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------- - osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011 Red Hat - - Alpha/OSF Foreign Function Interface + osf.S - Copyright (c) 1998, 2001, 2007, 2008, 2011, 2014 Red Hat + + Alpha/OSF Foreign Function Interface Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -24,40 +24,49 @@ DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------------- */ -#define LIBFFI_ASM +#define LIBFFI_ASM #include #include +#include +#include "internal.h" .arch ev6 .text -/* ffi_call_osf (void *args, unsigned long bytes, unsigned flags, - void *raddr, void (*fnaddr)(void)); +/* Aid in building a direct addressed jump table, 4 insns per entry. */ +.macro E index + .align 4 + .org 99b + \index * 16 +.endm + +/* ffi_call_osf (void *stack, void *frame, unsigned flags, + void *raddr, void (*fnaddr)(void), void *closure) - Bit o trickiness here -- ARGS+BYTES is the base of the stack frame + Bit o trickiness here -- FRAME is the base of the stack frame for this function. This has been allocated by ffi_call. We also deallocate some of the stack that has been alloca'd. */ - .align 3 + .align 4 .globl ffi_call_osf .ent ffi_call_osf FFI_HIDDEN(ffi_call_osf) ffi_call_osf: - .frame $15, 32, $26, 0 - .mask 0x4008000, -32 -$LFB1: - addq $16,$17,$1 + cfi_startproc + cfi_def_cfa($17, 32) mov $16, $30 - stq $26, 0($1) - stq $15, 8($1) - stq $18, 16($1) - mov $1, $15 -$LCFI1: + stq $26, 0($17) + stq $15, 8($17) + mov $17, $15 .prologue 0 + cfi_def_cfa_register($15) + cfi_rel_offset($26, 0) + cfi_rel_offset($15, 8) - stq $19, 24($1) - mov $20, $27 + stq $18, 16($17) # save flags into frame + stq $19, 24($17) # save rvalue into frame + mov $20, $27 # fn into place for call + mov $21, $1 # closure into static chain # Load up all of the (potential) argument registers. ldq $16, 0($30) @@ -77,311 +86,197 @@ $LCFI1: lda $30, 48($30) jsr $26, ($27), 0 - ldgp $29, 0($26) - - # If the return value pointer is NULL, assume no return value. - ldq $19, 24($15) - ldq $18, 16($15) +0: + ldah $29, 0($26) !gpdisp!1 + ldq $2, 24($15) # reload rvalue + lda $29, 0($29) !gpdisp!1 + ldq $3, 16($15) # reload flags + lda $1, 99f-0b($26) ldq $26, 0($15) -$LCFI2: - beq $19, $noretval - - # Store the return value out in the proper type. - cmpeq $18, FFI_TYPE_INT, $1 - bne $1, $retint - cmpeq $18, FFI_TYPE_FLOAT, $2 - bne $2, $retfloat - cmpeq $18, FFI_TYPE_DOUBLE, $3 - bne $3, $retdouble - - .align 3 -$noretval: ldq $15, 8($15) - ret + cfi_restore($26) + cfi_restore($15) + cfi_def_cfa($sp, 0) + cmoveq $2, ALPHA_ST_VOID, $3 # mash null rvalue to void + addq $3, $3, $3 + s8addq $3, $1, $1 # 99f + stcode * 16 + jmp $31, ($1), $st_int .align 4 -$retint: - stq $0, 0($19) - nop - ldq $15, 8($15) +99: +E ALPHA_ST_VOID ret - - .align 4 -$retfloat: - sts $f0, 0($19) - nop - ldq $15, 8($15) +E ALPHA_ST_INT +$st_int: + stq $0, 0($2) ret - - .align 4 -$retdouble: - stt $f0, 0($19) - nop - ldq $15, 8($15) +E ALPHA_ST_FLOAT + sts $f0, 0($2) + ret +E ALPHA_ST_DOUBLE + stt $f0, 0($2) + ret +E ALPHA_ST_CPLXF + sts $f0, 0($2) + sts $f1, 4($2) + ret +E ALPHA_ST_CPLXD + stt $f0, 0($2) + stt $f1, 8($2) ret -$LFE1: + cfi_endproc .end ffi_call_osf /* ffi_closure_osf(...) Receives the closure argument in $1. */ - .align 3 +#define CLOSURE_FS (16*8) + + .align 4 + .globl ffi_go_closure_osf + .ent ffi_go_closure_osf + FFI_HIDDEN(ffi_go_closure_osf) + +ffi_go_closure_osf: + cfi_startproc + ldgp $29, 0($27) + subq $30, CLOSURE_FS, $30 + cfi_adjust_cfa_offset(CLOSURE_FS) + stq $26, 0($30) + .prologue 1 + cfi_rel_offset($26, 0) + + stq $16, 10*8($30) + stq $17, 11*8($30) + stq $18, 12*8($30) + + ldq $16, 8($1) # load cif + ldq $17, 16($1) # load fun + mov $1, $18 # closure is user_data + br $do_closure + + cfi_endproc + .end ffi_go_closure_osf + + .align 4 .globl ffi_closure_osf .ent ffi_closure_osf FFI_HIDDEN(ffi_closure_osf) ffi_closure_osf: - .frame $30, 16*8, $26, 0 - .mask 0x4000000, -16*8 -$LFB2: + cfi_startproc ldgp $29, 0($27) - subq $30, 16*8, $30 -$LCFI5: + subq $30, CLOSURE_FS, $30 + cfi_adjust_cfa_offset(CLOSURE_FS) stq $26, 0($30) -$LCFI6: .prologue 1 + cfi_rel_offset($26, 0) # Store all of the potential argument registers in va_list format. - stt $f16, 4*8($30) - stt $f17, 5*8($30) - stt $f18, 6*8($30) - stt $f19, 7*8($30) - stt $f20, 8*8($30) - stt $f21, 9*8($30) stq $16, 10*8($30) stq $17, 11*8($30) stq $18, 12*8($30) + + ldq $16, 24($1) # load cif + ldq $17, 32($1) # load fun + ldq $18, 40($1) # load user_data + +$do_closure: stq $19, 13*8($30) stq $20, 14*8($30) stq $21, 15*8($30) + stt $f16, 4*8($30) + stt $f17, 5*8($30) + stt $f18, 6*8($30) + stt $f19, 7*8($30) + stt $f20, 8*8($30) + stt $f21, 9*8($30) # Call ffi_closure_osf_inner to do the bulk of the work. - mov $1, $16 - lda $17, 2*8($30) - lda $18, 10*8($30) + lda $19, 2*8($30) + lda $20, 10*8($30) jsr $26, ffi_closure_osf_inner - ldgp $29, 0($26) +0: + ldah $29, 0($26) !gpdisp!2 + lda $2, 99f-0b($26) + s4addq $0, 0, $1 # ldcode * 4 + ldq $0, 16($30) # preload return value + s4addq $1, $2, $1 # 99f + ldcode * 16 + lda $29, 0($29) !gpdisp!2 ldq $26, 0($30) - - # Load up the return value in the proper type. - lda $1, $load_table - s4addq $0, $1, $1 - ldl $1, 0($1) - addq $1, $29, $1 + cfi_restore($26) jmp $31, ($1), $load_32 - .align 4 -$load_none: - addq $30, 16*8, $30 +.macro epilogue + addq $30, CLOSURE_FS, $30 + cfi_adjust_cfa_offset(-CLOSURE_FS) ret + .align 4 + cfi_adjust_cfa_offset(CLOSURE_FS) +.endm .align 4 -$load_float: - lds $f0, 16($30) - nop - addq $30, 16*8, $30 - ret +99: +E ALPHA_LD_VOID + epilogue - .align 4 -$load_double: - ldt $f0, 16($30) - nop - addq $30, 16*8, $30 - ret +E ALPHA_LD_INT64 + epilogue - .align 4 -$load_u8: +E ALPHA_LD_INT32 +$load_32: + sextl $0, $0 + epilogue + +E ALPHA_LD_UINT16 + zapnot $0, 3, $0 + epilogue + +E ALPHA_LD_SINT16 #ifdef __alpha_bwx__ - ldbu $0, 16($30) - nop + sextw $0, $0 #else - ldq $0, 16($30) - and $0, 255, $0 + sll $0, 48, $0 + sra $0, 48, $0 #endif - addq $30, 16*8, $30 - ret + epilogue - .align 4 -$load_s8: +E ALPHA_LD_UINT8 + and $0, 0xff, $0 + epilogue + +E ALPHA_LD_SINT8 #ifdef __alpha_bwx__ - ldbu $0, 16($30) sextb $0, $0 #else - ldq $0, 16($30) sll $0, 56, $0 sra $0, 56, $0 #endif - addq $30, 16*8, $30 - ret + epilogue - .align 4 -$load_u16: -#ifdef __alpha_bwx__ - ldwu $0, 16($30) - nop -#else - ldq $0, 16($30) - zapnot $0, 3, $0 -#endif - addq $30, 16*8, $30 - ret +E ALPHA_LD_FLOAT + lds $f0, 16($sp) + epilogue - .align 4 -$load_s16: -#ifdef __alpha_bwx__ - ldwu $0, 16($30) - sextw $0, $0 -#else - ldq $0, 16($30) - sll $0, 48, $0 - sra $0, 48, $0 -#endif - addq $30, 16*8, $30 - ret +E ALPHA_LD_DOUBLE + ldt $f0, 16($sp) + epilogue - .align 4 -$load_32: - ldl $0, 16($30) - nop - addq $30, 16*8, $30 - ret +E ALPHA_LD_CPLXF + lds $f0, 16($sp) + lds $f1, 20($sp) + epilogue - .align 4 -$load_64: - ldq $0, 16($30) - nop - addq $30, 16*8, $30 - ret -$LFE2: +E ALPHA_LD_CPLXD + ldt $f0, 16($sp) + ldt $f1, 24($sp) + epilogue + cfi_endproc .end ffi_closure_osf -#ifdef __ELF__ -.section .rodata -#else -.rdata -#endif -$load_table: - .gprel32 $load_none # FFI_TYPE_VOID - .gprel32 $load_32 # FFI_TYPE_INT - .gprel32 $load_float # FFI_TYPE_FLOAT - .gprel32 $load_double # FFI_TYPE_DOUBLE - .gprel32 $load_none # FFI_TYPE_LONGDOUBLE - .gprel32 $load_u8 # FFI_TYPE_UINT8 - .gprel32 $load_s8 # FFI_TYPE_SINT8 - .gprel32 $load_u16 # FFI_TYPE_UINT16 - .gprel32 $load_s16 # FFI_TYPE_SINT16 - .gprel32 $load_32 # FFI_TYPE_UINT32 - .gprel32 $load_32 # FFI_TYPE_SINT32 - .gprel32 $load_64 # FFI_TYPE_UINT64 - .gprel32 $load_64 # FFI_TYPE_SINT64 - .gprel32 $load_none # FFI_TYPE_STRUCT - .gprel32 $load_64 # FFI_TYPE_POINTER - -/* Assert that the table above is in sync with ffi.h. */ - -#if FFI_TYPE_FLOAT != 2 \ - || FFI_TYPE_DOUBLE != 3 \ - || FFI_TYPE_UINT8 != 5 \ - || FFI_TYPE_SINT8 != 6 \ - || FFI_TYPE_UINT16 != 7 \ - || FFI_TYPE_SINT16 != 8 \ - || FFI_TYPE_UINT32 != 9 \ - || FFI_TYPE_SINT32 != 10 \ - || FFI_TYPE_UINT64 != 11 \ - || FFI_TYPE_SINT64 != 12 \ - || FFI_TYPE_STRUCT != 13 \ - || FFI_TYPE_POINTER != 14 \ - || FFI_TYPE_LAST != 14 -#error "osf.S out of sync with ffi.h" -#endif - -#ifdef __ELF__ -# define UA_SI .4byte -# define FDE_ENCODING 0x1b /* pcrel sdata4 */ -# define FDE_ENCODE(X) .4byte X-. -# define FDE_ARANGE(X) .4byte X -#elif defined __osf__ -# define UA_SI .align 0; .long -# define FDE_ENCODING 0x50 /* aligned absolute */ -# define FDE_ENCODE(X) .align 3; .quad X -# define FDE_ARANGE(X) .align 0; .quad X -#endif - -#ifdef __ELF__ - .section .eh_frame,EH_FRAME_FLAGS,@progbits -#elif defined __osf__ - .data - .align 3 - .globl _GLOBAL__F_ffi_call_osf -_GLOBAL__F_ffi_call_osf: -#endif -__FRAME_BEGIN__: - UA_SI $LECIE1-$LSCIE1 # Length of Common Information Entry -$LSCIE1: - UA_SI 0x0 # CIE Identifier Tag - .byte 0x1 # CIE Version - .ascii "zR\0" # CIE Augmentation - .byte 0x1 # uleb128 0x1; CIE Code Alignment Factor - .byte 0x78 # sleb128 -8; CIE Data Alignment Factor - .byte 26 # CIE RA Column - .byte 0x1 # uleb128 0x1; Augmentation size - .byte FDE_ENCODING # FDE Encoding - .byte 0xc # DW_CFA_def_cfa - .byte 30 # uleb128 column 30 - .byte 0 # uleb128 offset 0 - .align 3 -$LECIE1: -$LSFDE1: - UA_SI $LEFDE1-$LASFDE1 # FDE Length -$LASFDE1: - UA_SI $LASFDE1-__FRAME_BEGIN__ # FDE CIE offset - FDE_ENCODE($LFB1) # FDE initial location - FDE_ARANGE($LFE1-$LFB1) # FDE address range - .byte 0x0 # uleb128 0x0; Augmentation size - - .byte 0x4 # DW_CFA_advance_loc4 - UA_SI $LCFI1-$LFB1 - .byte 0x9a # DW_CFA_offset, column 26 - .byte 4 # uleb128 4*-8 - .byte 0x8f # DW_CFA_offset, column 15 - .byte 0x3 # uleb128 3*-8 - .byte 0xc # DW_CFA_def_cfa - .byte 15 # uleb128 column 15 - .byte 32 # uleb128 offset 32 - - .byte 0x4 # DW_CFA_advance_loc4 - UA_SI $LCFI2-$LCFI1 - .byte 0xda # DW_CFA_restore, column 26 - .align 3 -$LEFDE1: - -$LSFDE3: - UA_SI $LEFDE3-$LASFDE3 # FDE Length -$LASFDE3: - UA_SI $LASFDE3-__FRAME_BEGIN__ # FDE CIE offset - FDE_ENCODE($LFB2) # FDE initial location - FDE_ARANGE($LFE2-$LFB2) # FDE address range - .byte 0x0 # uleb128 0x0; Augmentation size - - .byte 0x4 # DW_CFA_advance_loc4 - UA_SI $LCFI5-$LFB2 - .byte 0xe # DW_CFA_def_cfa_offset - .byte 0x80,0x1 # uleb128 128 - - .byte 0x4 # DW_CFA_advance_loc4 - UA_SI $LCFI6-$LCFI5 - .byte 0x9a # DW_CFA_offset, column 26 - .byte 16 # uleb128 offset 16*-8 - .align 3 -$LEFDE3: -#if defined __osf__ - .align 0 - .long 0 # End of Table -#endif - #if defined __ELF__ && defined __linux__ .section .note.GNU-stack,"",@progbits #endif diff --git a/native/libffi/src/arc/ffi.c b/native/libffi/src/arc/ffi.c index 32f82a7d5b..fa55a24455 100644 --- a/native/libffi/src/arc/ffi.c +++ b/native/libffi/src/arc/ffi.c @@ -46,12 +46,18 @@ void ffi_prep_args (char *stack, extended_cif * ecif) { unsigned int i; +<<<<<<< HEAD int tmp; +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 void **p_argv; char *argp; ffi_type **p_arg; +<<<<<<< HEAD tmp = 0; +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 argp = stack; if (ecif->cif->rtype->type == FFI_TYPE_STRUCT) @@ -73,7 +79,11 @@ ffi_prep_args (char *stack, extended_cif * ecif) /* Align if necessary. */ if ((alignment - 1) & (unsigned) argp) +<<<<<<< HEAD argp = (char *) ALIGN (argp, alignment); +======= + argp = (char *) FFI_ALIGN (argp, alignment); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 z = (*p_arg)->size; if (z < sizeof (int)) @@ -225,7 +235,11 @@ ffi_closure_inner_ARCompact (ffi_closure * closure, void *rvalue, /* Align if necessary. */ if ((alignment - 1) & (unsigned) argp) +<<<<<<< HEAD argp = (char *) ALIGN (argp, alignment); +======= + argp = (char *) FFI_ALIGN (argp, alignment); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 z = (*p_argt)->size; *p_argv = (void *) argp; diff --git a/native/libffi/src/arm/ffi.c b/native/libffi/src/arm/ffi.c index 6691ab57da..88dc16a41b 100644 --- a/native/libffi/src/arm/ffi.c +++ b/native/libffi/src/arm/ffi.c @@ -28,15 +28,43 @@ DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------------- */ +#if defined(__arm__) || defined(_M_ARM) +#include #include #include - +#include #include +#include "internal.h" + +#if defined(_MSC_VER) && defined(_M_ARM) +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#if FFI_EXEC_TRAMPOLINE_TABLE + +#ifdef __MACH__ +#include +#endif + +#else +#ifndef _M_ARM +extern unsigned int ffi_arm_trampoline[2] FFI_HIDDEN; +#else +extern unsigned int ffi_arm_trampoline[3] FFI_HIDDEN; +#endif +#endif + +#if defined(__FreeBSD__) && defined(__arm__) +#include +#include +#endif /* Forward declares. */ -static int vfp_type_p (ffi_type *); +static int vfp_type_p (const ffi_type *); static void layout_vfp_args (ffi_cif *); +<<<<<<< HEAD int ffi_prep_args_SYSV(char *stack, extended_cif *ecif, float *vfp_space); int ffi_prep_args_VFP(char *stack, extended_cif *ecif, float *vfp_space); @@ -121,10 +149,87 @@ static size_t ffi_put_arg(ffi_type **arg_type, void **arg, char *stack) /* ffi_prep_args is called by the assembly routine once stack space has been allocated for the function's arguments +======= +static void * +ffi_align (ffi_type *ty, void *p) +{ + /* Align if necessary */ + size_t alignment; +#ifdef _WIN32_WCE + alignment = 4; +#else + alignment = ty->alignment; + if (alignment < 4) + alignment = 4; +#endif + return (void *) FFI_ALIGN (p, alignment); +} + +static size_t +ffi_put_arg (ffi_type *ty, void *src, void *dst) +{ + size_t z = ty->size; + + switch (ty->type) + { + case FFI_TYPE_SINT8: + *(UINT32 *)dst = *(SINT8 *)src; + break; + case FFI_TYPE_UINT8: + *(UINT32 *)dst = *(UINT8 *)src; + break; + case FFI_TYPE_SINT16: + *(UINT32 *)dst = *(SINT16 *)src; + break; + case FFI_TYPE_UINT16: + *(UINT32 *)dst = *(UINT16 *)src; + break; + + case FFI_TYPE_INT: + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + case FFI_TYPE_POINTER: +#ifndef _MSC_VER + case FFI_TYPE_FLOAT: +#endif + *(UINT32 *)dst = *(UINT32 *)src; + break; + +#ifdef _MSC_VER + // casting a float* to a UINT32* doesn't work on Windows + case FFI_TYPE_FLOAT: + *(uintptr_t *)dst = 0; + *(float *)dst = *(float *)src; + break; +#endif + + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + case FFI_TYPE_DOUBLE: + *(UINT64 *)dst = *(UINT64 *)src; + break; + + case FFI_TYPE_STRUCT: + case FFI_TYPE_COMPLEX: + memcpy (dst, src, z); + break; + + default: + abort(); + } + + return FFI_ALIGN (z, 4); +} + +/* ffi_prep_args is called once stack space has been allocated + for the function's arguments. + +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 The vfp_space parameter is the load area for VFP regs, the return value is cif->vfp_used (word bitset of VFP regs used for passing arguments). These are only used for the VFP hard-float ABI. */ +<<<<<<< HEAD int ffi_prep_args_SYSV(char *stack, extended_cif *ecif, float *vfp_space) { register unsigned int i; @@ -133,14 +238,53 @@ int ffi_prep_args_SYSV(char *stack, extended_cif *ecif, float *vfp_space) register ffi_type **p_arg; argp = stack; +======= +static void +ffi_prep_args_SYSV (ffi_cif *cif, int flags, void *rvalue, + void **avalue, char *argp) +{ + ffi_type **arg_types = cif->arg_types; + int i, n; - if ( ecif->cif->flags == FFI_TYPE_STRUCT ) { - *(void **) argp = ecif->rvalue; - argp += 4; - } + if (flags == ARM_TYPE_STRUCT) + { + *(void **) argp = rvalue; + argp += 4; + } +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 - p_argv = ecif->avalue; + for (i = 0, n = cif->nargs; i < n; i++) + { + ffi_type *ty = arg_types[i]; + argp = ffi_align (ty, argp); + argp += ffi_put_arg (ty, avalue[i], argp); + } +} +static void +ffi_prep_args_VFP (ffi_cif *cif, int flags, void *rvalue, + void **avalue, char *stack, char *vfp_space) +{ + ffi_type **arg_types = cif->arg_types; + int i, n, vi = 0; + char *argp, *regp, *eo_regp; + char stack_used = 0; + char done_with_regs = 0; + + /* The first 4 words on the stack are used for values + passed in core registers. */ + regp = stack; + eo_regp = argp = regp + 16; + + /* If the function returns an FFI_TYPE_STRUCT in memory, + that address is passed in r0 to the function. */ + if (flags == ARM_TYPE_STRUCT) + { + *(void **) regp = rvalue; + regp += 4; + } + +<<<<<<< HEAD for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; (i != 0); i--, p_arg++, p_argv++) @@ -228,81 +372,164 @@ int ffi_prep_args_VFP(char *stack, extended_cif *ecif, float *vfp_space) } /* Indicate the VFP registers used. */ return ecif->cif->vfp_used; +======= + for (i = 0, n = cif->nargs; i < n; i++) + { + ffi_type *ty = arg_types[i]; + void *a = avalue[i]; + int is_vfp_type = vfp_type_p (ty); + + /* Allocated in VFP registers. */ + if (vi < cif->vfp_nargs && is_vfp_type) + { + char *vfp_slot = vfp_space + cif->vfp_args[vi++] * 4; + ffi_put_arg (ty, a, vfp_slot); + continue; + } + /* Try allocating in core registers. */ + else if (!done_with_regs && !is_vfp_type) + { + char *tregp = ffi_align (ty, regp); + size_t size = ty->size; + size = (size < 4) ? 4 : size; // pad + /* Check if there is space left in the aligned register + area to place the argument. */ + if (tregp + size <= eo_regp) + { + regp = tregp + ffi_put_arg (ty, a, tregp); + done_with_regs = (regp == argp); + // ensure we did not write into the stack area + FFI_ASSERT (regp <= argp); + continue; + } + /* In case there are no arguments in the stack area yet, + the argument is passed in the remaining core registers + and on the stack. */ + else if (!stack_used) + { + stack_used = 1; + done_with_regs = 1; + argp = tregp + ffi_put_arg (ty, a, tregp); + FFI_ASSERT (eo_regp < argp); + continue; + } + } + /* Base case, arguments are passed on the stack */ + stack_used = 1; + argp = ffi_align (ty, argp); + argp += ffi_put_arg (ty, a, argp); + } +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 } /* Perform machine dependent cif processing */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) +ffi_status FFI_HIDDEN +ffi_prep_cif_machdep (ffi_cif *cif) { - int type_code; - /* Round the stack up to a multiple of 8 bytes. This isn't needed - everywhere, but it is on some platforms, and it doesn't harm anything - when it isn't needed. */ - cif->bytes = (cif->bytes + 7) & ~7; + int flags = 0, cabi = cif->abi; + size_t bytes = cif->bytes; + + /* Map out the register placements of VFP register args. The VFP + hard-float calling conventions are slightly more sophisticated + than the base calling conventions, so we do it here instead of + in ffi_prep_args(). */ + if (cabi == FFI_VFP) + layout_vfp_args (cif); /* Set the return type flag */ switch (cif->rtype->type) { case FFI_TYPE_VOID: - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: - cif->flags = (unsigned) cif->rtype->type; + flags = ARM_TYPE_VOID; + break; + + case FFI_TYPE_INT: + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT16: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT32: + case FFI_TYPE_POINTER: + flags = ARM_TYPE_INT; break; case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: - cif->flags = (unsigned) FFI_TYPE_SINT64; + flags = ARM_TYPE_INT64; + break; + + case FFI_TYPE_FLOAT: + flags = (cabi == FFI_VFP ? ARM_TYPE_VFP_S : ARM_TYPE_INT); + break; + case FFI_TYPE_DOUBLE: + flags = (cabi == FFI_VFP ? ARM_TYPE_VFP_D : ARM_TYPE_INT64); break; case FFI_TYPE_STRUCT: - if (cif->abi == FFI_VFP - && (type_code = vfp_type_p (cif->rtype)) != 0) + case FFI_TYPE_COMPLEX: + if (cabi == FFI_VFP) { - /* A Composite Type passed in VFP registers, either - FFI_TYPE_STRUCT_VFP_FLOAT or FFI_TYPE_STRUCT_VFP_DOUBLE. */ - cif->flags = (unsigned) type_code; + int h = vfp_type_p (cif->rtype); + + flags = ARM_TYPE_VFP_N; + if (h == 0x100 + FFI_TYPE_FLOAT) + flags = ARM_TYPE_VFP_S; + if (h == 0x100 + FFI_TYPE_DOUBLE) + flags = ARM_TYPE_VFP_D; + if (h != 0) + break; } - else if (cif->rtype->size <= 4) - /* A Composite Type not larger than 4 bytes is returned in r0. */ - cif->flags = (unsigned)FFI_TYPE_INT; + + /* A Composite Type not larger than 4 bytes is returned in r0. + A Composite Type larger than 4 bytes, or whose size cannot + be determined statically ... is stored in memory at an + address passed [in r0]. */ + if (cif->rtype->size <= 4) + flags = ARM_TYPE_INT; else - /* A Composite Type larger than 4 bytes, or whose size cannot - be determined statically ... is stored in memory at an - address passed [in r0]. */ - cif->flags = (unsigned)FFI_TYPE_STRUCT; + { + flags = ARM_TYPE_STRUCT; + bytes += 4; + } break; default: - cif->flags = FFI_TYPE_INT; - break; + abort(); } - /* Map out the register placements of VFP register args. - The VFP hard-float calling conventions are slightly more sophisticated than - the base calling conventions, so we do it here instead of in ffi_prep_args(). */ - if (cif->abi == FFI_VFP) - layout_vfp_args (cif); + /* Round the stack up to a multiple of 8 bytes. This isn't needed + everywhere, but it is on some platforms, and it doesn't harm anything + when it isn't needed. */ + bytes = FFI_ALIGN (bytes, 8); + + /* Minimum stack space is the 4 register arguments that we pop. */ + if (bytes < 4*4) + bytes = 4*4; + + cif->bytes = bytes; + cif->flags = flags; return FFI_OK; } /* Perform machine dependent cif processing for variadic calls */ -ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, - unsigned int nfixedargs, - unsigned int ntotalargs) +ffi_status FFI_HIDDEN +ffi_prep_cif_machdep_var (ffi_cif * cif, + unsigned int nfixedargs, unsigned int ntotalargs) { /* VFP variadic calls actually use the SYSV ABI */ if (cif->abi == FFI_VFP) - cif->abi = FFI_SYSV; + cif->abi = FFI_SYSV; - return ffi_prep_cif_machdep(cif); + return ffi_prep_cif_machdep (cif); } -/* Prototypes for assembly functions, in sysv.S */ -extern void ffi_call_SYSV (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *); -extern void ffi_call_VFP (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *); +/* Prototypes for assembly functions, in sysv.S. */ -void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +struct call_frame { +<<<<<<< HEAD extended_cif ecif; int small_struct = (cif->flags == FFI_TYPE_INT @@ -317,38 +544,62 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) /* If the return value is a struct and we don't have a return */ /* value address then we need to make one */ +======= + void *fp; + void *lr; + void *rvalue; + int flags; + void *closure; +}; + +extern void ffi_call_SYSV (void *stack, struct call_frame *, + void (*fn) (void)) FFI_HIDDEN; +extern void ffi_call_VFP (void *vfp_space, struct call_frame *, + void (*fn) (void), unsigned vfp_used) FFI_HIDDEN; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 - if ((rvalue == NULL) && - (cif->flags == FFI_TYPE_STRUCT)) +static void +ffi_call_int (ffi_cif * cif, void (*fn) (void), void *rvalue, + void **avalue, void *closure) +{ + int flags = cif->flags; + ffi_type *rtype = cif->rtype; + size_t bytes, rsize, vfp_size; + char *stack, *vfp_space, *new_rvalue; + struct call_frame *frame; + + rsize = 0; + if (rvalue == NULL) { - ecif.rvalue = alloca(cif->rtype->size); + /* If the return value is a struct and we don't have a return + value address then we need to make one. Otherwise the return + value is in registers and we can ignore them. */ + if (flags == ARM_TYPE_STRUCT) + rsize = rtype->size; + else + flags = ARM_TYPE_VOID; } - else if (small_struct) - ecif.rvalue = &temp; - else if (vfp_struct) + else if (flags == ARM_TYPE_VFP_N) { /* Largest case is double x 4. */ - ecif.rvalue = alloca(32); + rsize = 32; } - else - ecif.rvalue = rvalue; + else if (flags == ARM_TYPE_INT && rtype->type == FFI_TYPE_STRUCT) + rsize = 4; - switch (cif->abi) - { - case FFI_SYSV: - ffi_call_SYSV (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue); - break; + /* Largest case. */ + vfp_size = (cif->abi == FFI_VFP && cif->vfp_used ? 8*8: 0); - case FFI_VFP: -#ifdef __ARM_EABI__ - ffi_call_VFP (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue); - break; -#endif + bytes = cif->bytes; + stack = alloca (vfp_size + bytes + sizeof(struct call_frame) + rsize); - default: - FFI_ASSERT(0); - break; + vfp_space = NULL; + if (vfp_size) + { + vfp_space = stack; + stack += vfp_size; } +<<<<<<< HEAD if (small_struct) { FFI_ASSERT(rvalue != NULL); @@ -362,32 +613,70 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) } } +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 -/** private members **/ + frame = (struct call_frame *)(stack + bytes); -static void ffi_prep_incoming_args_SYSV (char *stack, void **ret, - void** args, ffi_cif* cif, float *vfp_stack); + new_rvalue = rvalue; + if (rsize) + new_rvalue = (void *)(frame + 1); +<<<<<<< HEAD static void ffi_prep_incoming_args_VFP (char *stack, void **ret, void** args, ffi_cif* cif, float *vfp_stack); void ffi_closure_SYSV (ffi_closure *); +======= + frame->rvalue = new_rvalue; + frame->flags = flags; + frame->closure = closure; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 -void ffi_closure_VFP (ffi_closure *); + if (vfp_space) + { + ffi_prep_args_VFP (cif, flags, new_rvalue, avalue, stack, vfp_space); + ffi_call_VFP (vfp_space, frame, fn, cif->vfp_used); + } + else + { + ffi_prep_args_SYSV (cif, flags, new_rvalue, avalue, stack); + ffi_call_SYSV (stack, frame, fn); + } -/* This function is jumped to by the trampoline */ + if (rvalue && rvalue != new_rvalue) + memcpy (rvalue, new_rvalue, rtype->size); +} +<<<<<<< HEAD unsigned int FFI_HIDDEN ffi_closure_inner (ffi_closure *closure, void **respp, void *args, void *vfp_args) +======= +void +ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 +{ + ffi_call_int (cif, fn, rvalue, avalue, NULL); +} + +#ifdef FFI_GO_CLOSURES +void +ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, + void **avalue, void *closure) { - // our various things... - ffi_cif *cif; - void **arg_area; + ffi_call_int (cif, fn, rvalue, avalue, closure); +} +#endif - cif = closure->cif; - arg_area = (void**) alloca (cif->nargs * sizeof (void*)); +static void * +ffi_prep_incoming_args_SYSV (ffi_cif *cif, void *rvalue, + char *argp, void **avalue) +{ + ffi_type **arg_types = cif->arg_types; + int i, n; +<<<<<<< HEAD /* this call will initialize ARG_AREA, such that each * element in that array points to the corresponding * value on the stack; and if the function returns @@ -397,36 +686,61 @@ ffi_closure_inner (ffi_closure *closure, ffi_prep_incoming_args_VFP(args, respp, arg_area, cif, vfp_args); else ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif, vfp_args); +======= + if (cif->flags == ARM_TYPE_STRUCT) + { + rvalue = *(void **) argp; + argp += 4; + } + else + { + if (cif->rtype->size && cif->rtype->size < 4) + *(uint32_t *) rvalue = 0; + } - (closure->fun) (cif, *respp, arg_area, closure->user_data); + for (i = 0, n = cif->nargs; i < n; i++) + { + ffi_type *ty = arg_types[i]; + size_t z = ty->size; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 - return cif->flags; + argp = ffi_align (ty, argp); + avalue[i] = (void *) argp; + argp += z; + } + + return rvalue; } -/*@-exportheader@*/ -static void -ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, - void **avalue, ffi_cif *cif, - /* Used only under VFP hard-float ABI. */ - float *vfp_stack) -/*@=exportheader@*/ +static void * +ffi_prep_incoming_args_VFP (ffi_cif *cif, void *rvalue, char *stack, + char *vfp_space, void **avalue) { +<<<<<<< HEAD register unsigned int i; register void **p_argv; register char *argp; register ffi_type **p_arg; +======= + ffi_type **arg_types = cif->arg_types; + int i, n, vi = 0; + char *argp, *regp, *eo_regp; + char done_with_regs = 0; + char stack_used = 0; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 - argp = stack; - - if ( cif->flags == FFI_TYPE_STRUCT ) { - *rvalue = *(void **) argp; - argp += 4; - } + regp = stack; + eo_regp = argp = regp + 16; - p_argv = avalue; + if (cif->flags == ARM_TYPE_STRUCT) + { + rvalue = *(void **) regp; + regp += 4; + } - for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) + for (i = 0, n = cif->nargs; i < n; i++) { +<<<<<<< HEAD size_t z; argp = ffi_align(p_arg, argp); @@ -434,16 +748,55 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, z = (*p_arg)->size; /* because we're little endian, this is what it turns into. */ +======= + ffi_type *ty = arg_types[i]; + int is_vfp_type = vfp_type_p (ty); + size_t z = ty->size; + + if (vi < cif->vfp_nargs && is_vfp_type) + { + avalue[i] = vfp_space + cif->vfp_args[vi++] * 4; + continue; + } + else if (!done_with_regs && !is_vfp_type) + { + char *tregp = ffi_align (ty, regp); + + z = (z < 4) ? 4 : z; // pad +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 - *p_argv = (void*) argp; + /* If the arguments either fits into the registers or uses registers + and stack, while we haven't read other things from the stack */ + if (tregp + z <= eo_regp || !stack_used) + { + /* Because we're little endian, this is what it turns into. */ + avalue[i] = (void *) tregp; + regp = tregp + z; + + /* If we read past the last core register, make sure we + have not read from the stack before and continue + reading after regp. */ + if (regp > eo_regp) + { + FFI_ASSERT (!stack_used); + argp = regp; + } + if (regp >= eo_regp) + { + done_with_regs = 1; + stack_used = 1; + } + continue; + } + } - p_argv++; + stack_used = 1; + argp = ffi_align (ty, argp); + avalue[i] = (void *) argp; argp += z; } - - return; -} +<<<<<<< HEAD /*@-exportheader@*/ static void ffi_prep_incoming_args_VFP(char *stack, void **rvalue, @@ -562,220 +915,183 @@ struct ffi_trampoline_table { ffi_trampoline_table *prev; ffi_trampoline_table *next; }; +======= + return rvalue; +} +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 -struct ffi_trampoline_table_entry { - void *(*trampoline)(); - ffi_trampoline_table_entry *next; +struct closure_frame +{ + char vfp_space[8*8] __attribute__((aligned(8))); + char result[8*4]; + char argp[]; }; -/* Override the standard architecture trampoline size */ -// XXX TODO - Fix -#undef FFI_TRAMPOLINE_SIZE -#define FFI_TRAMPOLINE_SIZE 12 - -/* The trampoline configuration is placed at 4080 bytes prior to the trampoline's entry point */ -#define FFI_TRAMPOLINE_CODELOC_CONFIG(codeloc) ((void **) (((uint8_t *) codeloc) - 4080)); - -/* The first 16 bytes of the config page are unused, as they are unaddressable from the trampoline page. */ -#define FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET 16 - -/* Total number of trampolines that fit in one trampoline table */ -#define FFI_TRAMPOLINE_COUNT ((PAGE_SIZE - FFI_TRAMPOLINE_CONFIG_PAGE_OFFSET) / FFI_TRAMPOLINE_SIZE) - -static pthread_mutex_t ffi_trampoline_lock = PTHREAD_MUTEX_INITIALIZER; -static ffi_trampoline_table *ffi_trampoline_tables = NULL; - -static ffi_trampoline_table * -ffi_trampoline_table_alloc () +int FFI_HIDDEN +ffi_closure_inner_SYSV (ffi_cif *cif, + void (*fun) (ffi_cif *, void *, void **, void *), + void *user_data, + struct closure_frame *frame) { - ffi_trampoline_table *table = NULL; + void **avalue = (void **) alloca (cif->nargs * sizeof (void *)); + void *rvalue = ffi_prep_incoming_args_SYSV (cif, frame->result, + frame->argp, avalue); + fun (cif, rvalue, avalue, user_data); + return cif->flags; +} +<<<<<<< HEAD /* Loop until we can allocate two contiguous pages */ while (table == NULL) { vm_address_t config_page = 0x0; kern_return_t kt; +======= +int FFI_HIDDEN +ffi_closure_inner_VFP (ffi_cif *cif, + void (*fun) (ffi_cif *, void *, void **, void *), + void *user_data, + struct closure_frame *frame) +{ + void **avalue = (void **) alloca (cif->nargs * sizeof (void *)); + void *rvalue = ffi_prep_incoming_args_VFP (cif, frame->result, frame->argp, + frame->vfp_space, avalue); + fun (cif, rvalue, avalue, user_data); + return cif->flags; +} +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 - /* Try to allocate two pages */ - kt = vm_allocate (mach_task_self (), &config_page, PAGE_SIZE*2, VM_FLAGS_ANYWHERE); - if (kt != KERN_SUCCESS) { - fprintf(stderr, "vm_allocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); - break; - } +void ffi_closure_SYSV (void) FFI_HIDDEN; +void ffi_closure_VFP (void) FFI_HIDDEN; - /* Now drop the second half of the allocation to make room for the trampoline table */ - vm_address_t trampoline_page = config_page+PAGE_SIZE; - kt = vm_deallocate (mach_task_self (), trampoline_page, PAGE_SIZE); - if (kt != KERN_SUCCESS) { - fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); - break; - } +#ifdef FFI_GO_CLOSURES +void ffi_go_closure_SYSV (void) FFI_HIDDEN; +void ffi_go_closure_VFP (void) FFI_HIDDEN; +#endif - /* Remap the trampoline table to directly follow the config page */ - vm_prot_t cur_prot; - vm_prot_t max_prot; +/* the cif must already be prep'ed */ - kt = vm_remap (mach_task_self (), &trampoline_page, PAGE_SIZE, 0x0, FALSE, mach_task_self (), (vm_address_t) &ffi_closure_trampoline_table_page, FALSE, &cur_prot, &max_prot, VM_INHERIT_SHARE); +#if defined(__FreeBSD__) && defined(__arm__) +#define __clear_cache(start, end) do { \ + struct arm_sync_icache_args ua; \ + \ + ua.addr = (uintptr_t)(start); \ + ua.len = (char *)(end) - (char *)start; \ + sysarch(ARM_SYNC_ICACHE, &ua); \ + } while (0); +#endif - /* If we lost access to the destination trampoline page, drop our config allocation mapping and retry */ - if (kt != KERN_SUCCESS) { - /* Log unexpected failures */ - if (kt != KERN_NO_SPACE) { - fprintf(stderr, "vm_remap() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); - } +ffi_status +ffi_prep_closure_loc (ffi_closure * closure, + ffi_cif * cif, + void (*fun) (ffi_cif *, void *, void **, void *), + void *user_data, void *codeloc) +{ + void (*closure_func) (void) = ffi_closure_SYSV; - vm_deallocate (mach_task_self (), config_page, PAGE_SIZE); - continue; + if (cif->abi == FFI_VFP) + { + /* We only need take the vfp path if there are vfp arguments. */ + if (cif->vfp_used) + closure_func = ffi_closure_VFP; } + else if (cif->abi != FFI_SYSV) + return FFI_BAD_ABI; - /* We have valid trampoline and config pages */ - table = calloc (1, sizeof(ffi_trampoline_table)); - table->free_count = FFI_TRAMPOLINE_COUNT; - table->config_page = config_page; - table->trampoline_page = trampoline_page; - - /* Create and initialize the free list */ - table->free_list_pool = calloc(FFI_TRAMPOLINE_COUNT, sizeof(ffi_trampoline_table_entry)); +#if FFI_EXEC_TRAMPOLINE_TABLE + void **config = (void **)((uint8_t *)codeloc - PAGE_MAX_SIZE); + config[0] = closure; + config[1] = closure_func; +#else - uint16_t i; - for (i = 0; i < table->free_count; i++) { - ffi_trampoline_table_entry *entry = &table->free_list_pool[i]; - entry->trampoline = (void *) (table->trampoline_page + (i * FFI_TRAMPOLINE_SIZE)); +#ifndef _M_ARM + memcpy(closure->tramp, ffi_arm_trampoline, 8); +#else + // cast away function type so MSVC doesn't set the lower bit of the function pointer + memcpy(closure->tramp, (void*)((uintptr_t)ffi_arm_trampoline & 0xFFFFFFFE), FFI_TRAMPOLINE_CLOSURE_OFFSET); +#endif - if (i < table->free_count - 1) - entry->next = &table->free_list_pool[i+1]; - } +#if defined (__QNX__) + msync(closure->tramp, 8, 0x1000000); /* clear data map */ + msync(codeloc, 8, 0x1000000); /* clear insn map */ +#elif defined(_MSC_VER) + FlushInstructionCache(GetCurrentProcess(), closure->tramp, FFI_TRAMPOLINE_SIZE); +#else + __clear_cache(closure->tramp, closure->tramp + 8); /* clear data map */ + __clear_cache(codeloc, codeloc + 8); /* clear insn map */ +#endif +#ifdef _M_ARM + *(void(**)(void))(closure->tramp + FFI_TRAMPOLINE_CLOSURE_FUNCTION) = closure_func; +#else + *(void (**)(void))(closure->tramp + 8) = closure_func; +#endif +#endif - table->free_list = table->free_list_pool; - } + closure->cif = cif; + closure->fun = fun; + closure->user_data = user_data; - return table; + return FFI_OK; } -void * -ffi_closure_alloc (size_t size, void **code) +#ifdef FFI_GO_CLOSURES +ffi_status +ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif, + void (*fun) (ffi_cif *, void *, void **, void *)) { - /* Create the closure */ - ffi_closure *closure = malloc(size); - if (closure == NULL) - return NULL; + void (*closure_func) (void) = ffi_go_closure_SYSV; - pthread_mutex_lock(&ffi_trampoline_lock); - - /* Check for an active trampoline table with available entries. */ - ffi_trampoline_table *table = ffi_trampoline_tables; - if (table == NULL || table->free_list == NULL) { - table = ffi_trampoline_table_alloc (); - if (table == NULL) { - free(closure); - return NULL; + if (cif->abi == FFI_VFP) + { + /* We only need take the vfp path if there are vfp arguments. */ + if (cif->vfp_used) + closure_func = ffi_go_closure_VFP; } + else if (cif->abi != FFI_SYSV) + return FFI_BAD_ABI; - /* Insert the new table at the top of the list */ - table->next = ffi_trampoline_tables; - if (table->next != NULL) - table->next->prev = table; - - ffi_trampoline_tables = table; - } - - /* Claim the free entry */ - ffi_trampoline_table_entry *entry = ffi_trampoline_tables->free_list; - ffi_trampoline_tables->free_list = entry->next; - ffi_trampoline_tables->free_count--; - entry->next = NULL; - - pthread_mutex_unlock(&ffi_trampoline_lock); - - /* Initialize the return values */ - *code = entry->trampoline; - closure->trampoline_table = table; - closure->trampoline_table_entry = entry; + closure->tramp = closure_func; + closure->cif = cif; + closure->fun = fun; - return closure; + return FFI_OK; } +#endif -void -ffi_closure_free (void *ptr) -{ - ffi_closure *closure = ptr; - - pthread_mutex_lock(&ffi_trampoline_lock); - - /* Fetch the table and entry references */ - ffi_trampoline_table *table = closure->trampoline_table; - ffi_trampoline_table_entry *entry = closure->trampoline_table_entry; - - /* Return the entry to the free list */ - entry->next = table->free_list; - table->free_list = entry; - table->free_count++; - - /* If all trampolines within this table are free, and at least one other table exists, deallocate - * the table */ - if (table->free_count == FFI_TRAMPOLINE_COUNT && ffi_trampoline_tables != table) { - /* Remove from the list */ - if (table->prev != NULL) - table->prev->next = table->next; +/* Below are routines for VFP hard-float support. */ - if (table->next != NULL) - table->next->prev = table->prev; +/* A subroutine of vfp_type_p. Given a structure type, return the type code + of the first non-structure element. Recurse for structure elements. + Return -1 if the structure is in fact empty, i.e. no nested elements. */ - /* Deallocate pages */ - kern_return_t kt; - kt = vm_deallocate (mach_task_self (), table->config_page, PAGE_SIZE); - if (kt != KERN_SUCCESS) - fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); - - kt = vm_deallocate (mach_task_self (), table->trampoline_page, PAGE_SIZE); - if (kt != KERN_SUCCESS) - fprintf(stderr, "vm_deallocate() failure: %d at %s:%d\n", kt, __FILE__, __LINE__); - - /* Deallocate free list */ - free (table->free_list_pool); - free (table); - } else if (ffi_trampoline_tables != table) { - /* Otherwise, bump this table to the top of the list */ - table->prev = NULL; - table->next = ffi_trampoline_tables; - if (ffi_trampoline_tables != NULL) - ffi_trampoline_tables->prev = table; - - ffi_trampoline_tables = table; - } +static int +is_hfa0 (const ffi_type *ty) +{ + ffi_type **elements = ty->elements; + int i, ret = -1; - pthread_mutex_unlock (&ffi_trampoline_lock); + if (elements != NULL) + for (i = 0; elements[i]; ++i) + { + ret = elements[i]->type; + if (ret == FFI_TYPE_STRUCT || ret == FFI_TYPE_COMPLEX) + { + ret = is_hfa0 (elements[i]); + if (ret < 0) + continue; + } + break; + } - /* Free the closure */ - free (closure); + return ret; } -#else - -#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ -({ unsigned char *__tramp = (unsigned char*)(TRAMP); \ - unsigned int __fun = (unsigned int)(FUN); \ - unsigned int __ctx = (unsigned int)(CTX); \ - unsigned char *insns = (unsigned char *)(CTX); \ - memcpy (__tramp, ffi_arm_trampoline, sizeof ffi_arm_trampoline); \ - *(unsigned int*) &__tramp[12] = __ctx; \ - *(unsigned int*) &__tramp[16] = __fun; \ - __clear_cache((&__tramp[0]), (&__tramp[19])); /* Clear data mapping. */ \ - __clear_cache(insns, insns + 3 * sizeof (unsigned int)); \ - /* Clear instruction \ - mapping. */ \ - }) - -#endif +/* A subroutine of vfp_type_p. Given a structure type, return true if all + of the non-structure elements are the same as CANDIDATE. */ -/* the cif must already be prep'ed */ - -ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, - void (*fun)(ffi_cif*,void*,void**,void*), - void *user_data, - void *codeloc) +static int +is_hfa1 (const ffi_type *ty, int candidate) { +<<<<<<< HEAD void (*closure_func)(ffi_closure*) = NULL; if (cif->abi == FFI_SYSV) @@ -796,88 +1112,139 @@ ffi_prep_closure_loc (ffi_closure* closure, closure_func, \ codeloc); #endif +======= + ffi_type **elements = ty->elements; + int i; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; + if (elements != NULL) + for (i = 0; elements[i]; ++i) + { + int t = elements[i]->type; + if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX) + { + if (!is_hfa1 (elements[i], candidate)) + return 0; + } + else if (t != candidate) + return 0; + } - return FFI_OK; + return 1; } -/* Below are routines for VFP hard-float support. */ +/* Determine if TY is an homogenous floating point aggregate (HFA). + That is, a structure consisting of 1 to 4 members of all the same type, + where that type is a floating point scalar. -static int rec_vfp_type_p (ffi_type *t, int *elt, int *elnum) + Returns non-zero iff TY is an HFA. The result is an encoded value where + bits 0-7 contain the type code, and bits 8-10 contain the element count. */ + +static int +vfp_type_p (const ffi_type *ty) { - switch (t->type) + ffi_type **elements; + int candidate, i; + size_t size, ele_count; + + /* Quickest tests first. */ + candidate = ty->type; + switch (ty->type) { + default: + return 0; case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: - *elt = (int) t->type; - *elnum = 1; - return 1; + ele_count = 1; + goto done; + case FFI_TYPE_COMPLEX: + candidate = ty->elements[0]->type; + if (candidate != FFI_TYPE_FLOAT && candidate != FFI_TYPE_DOUBLE) + return 0; + ele_count = 2; + goto done; + case FFI_TYPE_STRUCT: + break; + } - case FFI_TYPE_STRUCT_VFP_FLOAT: - *elt = FFI_TYPE_FLOAT; - *elnum = t->size / sizeof (float); - return 1; + /* No HFA types are smaller than 4 bytes, or larger than 32 bytes. */ + size = ty->size; + if (size < 4 || size > 32) + return 0; - case FFI_TYPE_STRUCT_VFP_DOUBLE: - *elt = FFI_TYPE_DOUBLE; - *elnum = t->size / sizeof (double); - return 1; + /* Find the type of the first non-structure member. */ + elements = ty->elements; + candidate = elements[0]->type; + if (candidate == FFI_TYPE_STRUCT || candidate == FFI_TYPE_COMPLEX) + { + for (i = 0; ; ++i) + { + candidate = is_hfa0 (elements[i]); + if (candidate >= 0) + break; + } + } - case FFI_TYPE_STRUCT:; - { - int base_elt = 0, total_elnum = 0; - ffi_type **el = t->elements; - while (*el) - { - int el_elt = 0, el_elnum = 0; - if (! rec_vfp_type_p (*el, &el_elt, &el_elnum) - || (base_elt && base_elt != el_elt) - || total_elnum + el_elnum > 4) - return 0; - base_elt = el_elt; - total_elnum += el_elnum; - el++; - } - *elnum = total_elnum; - *elt = base_elt; - return 1; - } - default: ; + /* If the first member is not a floating point type, it's not an HFA. + Also quickly re-check the size of the structure. */ + switch (candidate) + { + case FFI_TYPE_FLOAT: + ele_count = size / sizeof(float); + if (size != ele_count * sizeof(float)) + return 0; + break; + case FFI_TYPE_DOUBLE: + ele_count = size / sizeof(double); + if (size != ele_count * sizeof(double)) + return 0; + break; + default: + return 0; } - return 0; -} + if (ele_count > 4) + return 0; -static int vfp_type_p (ffi_type *t) -{ - int elt, elnum; - if (rec_vfp_type_p (t, &elt, &elnum)) + /* Finally, make sure that all scalar elements are the same type. */ + for (i = 0; elements[i]; ++i) { - if (t->type == FFI_TYPE_STRUCT) - { - if (elnum == 1) - t->type = elt; - else - t->type = (elt == FFI_TYPE_FLOAT - ? FFI_TYPE_STRUCT_VFP_FLOAT - : FFI_TYPE_STRUCT_VFP_DOUBLE); - } - return (int) t->type; + int t = elements[i]->type; + if (t == FFI_TYPE_STRUCT || t == FFI_TYPE_COMPLEX) + { + if (!is_hfa1 (elements[i], candidate)) + return 0; + } + else if (t != candidate) + return 0; } - return 0; + + /* All tests succeeded. Encode the result. */ + done: + return (ele_count << 8) | candidate; } +<<<<<<< HEAD static int place_vfp_arg (ffi_cif *cif, ffi_type *t) { short reg = cif->vfp_reg_free; int nregs = t->size / sizeof (float); int align = ((t->type == FFI_TYPE_STRUCT_VFP_FLOAT || t->type == FFI_TYPE_FLOAT) ? 1 : 2); +======= +static int +place_vfp_arg (ffi_cif *cif, int h) +{ + unsigned short reg = cif->vfp_reg_free; + int align = 1, nregs = h >> 8; + + if ((h & 0xff) == FFI_TYPE_DOUBLE) + align = 2, nregs *= 2; + +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 /* Align register number. */ if ((reg & 1) && align == 2) reg++; + while (reg + nregs <= 16) { int s, new_used = 0; @@ -892,7 +1259,7 @@ static int place_vfp_arg (ffi_cif *cif, ffi_type *t) } /* Found regs to allocate. */ cif->vfp_used |= new_used; - cif->vfp_args[cif->vfp_nargs++] = reg; + cif->vfp_args[cif->vfp_nargs++] = (signed char)reg; /* Update vfp_reg_free. */ if (cif->vfp_used & (1 << cif->vfp_reg_free)) @@ -903,7 +1270,11 @@ static int place_vfp_arg (ffi_cif *cif, ffi_type *t) cif->vfp_reg_free = reg; } return 0; +<<<<<<< HEAD next_reg: ; +======= + next_reg:; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 } // done, mark all regs as used cif->vfp_reg_free = 16; @@ -911,21 +1282,30 @@ static int place_vfp_arg (ffi_cif *cif, ffi_type *t) return 1; } -static void layout_vfp_args (ffi_cif *cif) +static void +layout_vfp_args (ffi_cif * cif) { - int i; + unsigned int i; /* Init VFP fields */ cif->vfp_used = 0; cif->vfp_nargs = 0; cif->vfp_reg_free = 0; - memset (cif->vfp_args, -1, 16); /* Init to -1. */ + memset (cif->vfp_args, -1, 16); /* Init to -1. */ for (i = 0; i < cif->nargs; i++) { +<<<<<<< HEAD ffi_type *t = cif->arg_types[i]; if (vfp_type_p (t) && place_vfp_arg (cif, t) == 1) { break; } +======= + int h = vfp_type_p (cif->arg_types[i]); + if (h && place_vfp_arg (cif, h) == 1) + break; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 } } + +#endif /* __arm__ or _M_ARM */ diff --git a/native/libffi/src/arm/ffitarget.h b/native/libffi/src/arm/ffitarget.h index 26d494d616..cb57b84880 100644 --- a/native/libffi/src/arm/ffitarget.h +++ b/native/libffi/src/arm/ffitarget.h @@ -43,7 +43,7 @@ typedef enum ffi_abi { FFI_SYSV, FFI_VFP, FFI_LAST_ABI, -#ifdef __ARM_PCS_VFP +#if defined(__ARM_PCS_VFP) || defined(_M_ARM) FFI_DEFAULT_ABI = FFI_VFP, #else FFI_DEFAULT_ABI = FFI_SYSV, @@ -53,19 +53,37 @@ typedef enum ffi_abi { #define FFI_EXTRA_CIF_FIELDS \ int vfp_used; \ - short vfp_reg_free, vfp_nargs; \ + unsigned short vfp_reg_free, vfp_nargs; \ signed char vfp_args[16] \ -/* Internally used. */ -#define FFI_TYPE_STRUCT_VFP_FLOAT (FFI_TYPE_LAST + 1) -#define FFI_TYPE_STRUCT_VFP_DOUBLE (FFI_TYPE_LAST + 2) - #define FFI_TARGET_SPECIFIC_VARIADIC +#ifndef _M_ARM +#define FFI_TARGET_HAS_COMPLEX_TYPE +#endif /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 -#define FFI_TRAMPOLINE_SIZE 20 +#define FFI_GO_CLOSURES 1 #define FFI_NATIVE_RAW_API 0 +#if defined (FFI_EXEC_TRAMPOLINE_TABLE) && FFI_EXEC_TRAMPOLINE_TABLE + +#ifdef __MACH__ +#define FFI_TRAMPOLINE_SIZE 12 +#define FFI_TRAMPOLINE_CLOSURE_OFFSET 8 +#else +#error "No trampoline table implementation" +#endif + +#else +#ifdef _MSC_VER +#define FFI_TRAMPOLINE_SIZE 16 +#define FFI_TRAMPOLINE_CLOSURE_FUNCTION 12 +#else +#define FFI_TRAMPOLINE_SIZE 12 +#endif +#define FFI_TRAMPOLINE_CLOSURE_OFFSET FFI_TRAMPOLINE_SIZE +#endif + #endif diff --git a/native/libffi/src/arm/internal.h b/native/libffi/src/arm/internal.h new file mode 100644 index 0000000000..6cf0b2ae5d --- /dev/null +++ b/native/libffi/src/arm/internal.h @@ -0,0 +1,7 @@ +#define ARM_TYPE_VFP_S 0 +#define ARM_TYPE_VFP_D 1 +#define ARM_TYPE_VFP_N 2 +#define ARM_TYPE_INT64 3 +#define ARM_TYPE_INT 4 +#define ARM_TYPE_VOID 5 +#define ARM_TYPE_STRUCT 6 diff --git a/native/libffi/src/arm/sysv.S b/native/libffi/src/arm/sysv.S index 9b074156c7..71280ece82 100644 --- a/native/libffi/src/arm/sysv.S +++ b/native/libffi/src/arm/sysv.S @@ -1,8 +1,8 @@ /* ----------------------------------------------------------------------- sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc. Copyright (c) 2011 Plausible Labs Cooperative, Inc. - - ARM Foreign Function Interface + + ARM Foreign Function Interface Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -25,9 +25,11 @@ DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------------- */ -#define LIBFFI_ASM +#ifdef __arm__ +#define LIBFFI_ASM #include #include +<<<<<<< HEAD #ifdef HAVE_MACHINE_ASM_H #include #else @@ -77,38 +79,39 @@ #endif #if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ +======= +#include +#include "internal.h" + +/* GCC 4.8 provides __ARM_ARCH; construct it otherwise. */ +#ifndef __ARM_ARCH +# if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ + || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ + || defined(__ARM_ARCH_7EM__) +# define __ARM_ARCH 7 +# elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \ || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__) \ || defined(__ARM_ARCH_6M__) -# undef __ARM_ARCH__ -# define __ARM_ARCH__ 6 -#endif - -#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) \ - || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) \ - || defined(__ARM_ARCH_7EM__) -# undef __ARM_ARCH__ -# define __ARM_ARCH__ 7 -#endif - -#if __ARM_ARCH__ >= 5 -# define call_reg(x) blx x -#elif defined (__ARM_ARCH_4T__) -# define call_reg(x) mov lr, pc ; bx x -# if defined(__thumb__) || defined(__THUMB_INTERWORK__) -# define __INTERWORKING__ +# define __ARM_ARCH 6 +# elif defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \ + || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \ + || defined(__ARM_ARCH_5TEJ__) +# define __ARM_ARCH 5 +# else +# define __ARM_ARCH 4 # endif -#else -# define call_reg(x) mov lr, pc ; mov pc, x #endif /* Conditionally compile unwinder directives. */ #ifdef __ARM_EABI__ -#define UNWIND +# define UNWIND(...) __VA_ARGS__ #else -#define UNWIND @ -#endif +# define UNWIND(...) +#endif +<<<<<<< HEAD .syntax unified #if defined(__thumb__) && !defined(__THUMB_INTERWORK__) @@ -130,23 +133,52 @@ _L__##name: .arm; \ ENTRY(name); \ UNWIND .fnstart +======= +#if defined(HAVE_AS_CFI_PSEUDO_OP) && defined(__ARM_EABI__) + .cfi_sections .debug_frame #endif -.macro RETLDM regs=, cond=, dirn=ia -#if defined (__INTERWORKING__) - .ifc "\regs","" - ldr\cond lr, [sp], #4 - .else - ldm\cond\dirn sp!, {\regs, lr} - .endif - bx\cond lr +#define CONCAT(a, b) CONCAT2(a, b) +#define CONCAT2(a, b) a ## b + +#ifdef __USER_LABEL_PREFIX__ +# define CNAME(X) CONCAT (__USER_LABEL_PREFIX__, X) #else - .ifc "\regs","" - ldr\cond pc, [sp], #4 - .else - ldm\cond\dirn sp!, {\regs, pc} +# define CNAME(X) X +#endif +#ifdef __ELF__ +# define SIZE(X) .size CNAME(X), . - CNAME(X) +# define TYPE(X, Y) .type CNAME(X), Y +#else +# define SIZE(X) +# define TYPE(X, Y) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 +#endif + +#define ARM_FUNC_START_LOCAL(name) \ + .align 3; \ + TYPE(CNAME(name), %function); \ + CNAME(name): + +#define ARM_FUNC_START(name) \ + .globl CNAME(name); \ + FFI_HIDDEN(CNAME(name)); \ + ARM_FUNC_START_LOCAL(name) + +#define ARM_FUNC_END(name) \ + SIZE(name) + +/* Aid in defining a jump table with 8 bytes between entries. */ +/* ??? The clang assembler doesn't handle .if with symbolic expressions. */ +#ifdef __clang__ +# define E(index) +#else +# define E(index) \ + .if . - 0b - 8*index; \ + .error "type table out of sync"; \ .endif #endif +<<<<<<< HEAD .endm @ r0: ffi_prep_args @@ -189,61 +221,121 @@ ARM_FUNC_START(ffi_call_SYSV) @ Remove the space we pushed for the args mov sp, fp +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 - @ Load r2 with the pointer to storage for the return value - ldr r2, [sp, #24] + .text + .syntax unified + .arm - @ Load r3 with the return type code - ldr r3, [sp, #12] +#ifndef __clang__ + /* We require interworking on LDM, which implies ARMv5T, + which implies the existance of BLX. */ + .arch armv5t +#endif - @ If the return value pointer is NULL, assume no return value. - cmp r2, #0 - beq LSYM(Lepilogue) + /* Note that we use STC and LDC to encode VFP instructions, + so that we do not need ".fpu vfp", nor get that added to + the object file attributes. These will not be executed + unless the FFI_VFP abi is used. */ -@ return INT - cmp r3, #FFI_TYPE_INT -#if defined(__SOFTFP__) || defined(__ARM_EABI__) - cmpne r3, #FFI_TYPE_FLOAT -#endif - streq r0, [r2] - beq LSYM(Lepilogue) + @ r0: stack + @ r1: frame + @ r2: fn + @ r3: vfp_used - @ return INT64 - cmp r3, #FFI_TYPE_SINT64 -#if defined(__SOFTFP__) || defined(__ARM_EABI__) - cmpne r3, #FFI_TYPE_DOUBLE +ARM_FUNC_START(ffi_call_VFP) + UNWIND(.fnstart) + cfi_startproc + + cmp r3, #3 @ load only d0 if possible +#ifdef __clang__ + vldrle d0, [r0] + vldmgt r0, {d0-d7} +#else + ldcle p11, cr0, [r0] @ vldrle d0, [r0] + ldcgt p11, cr0, [r0], {16} @ vldmgt r0, {d0-d7} #endif +<<<<<<< HEAD stmiaeq r2, {r0, r1} +======= + add r0, r0, #64 @ discard the vfp register args + /* FALLTHRU */ +ARM_FUNC_END(ffi_call_VFP) -#if !defined(__SOFTFP__) && !defined(__ARM_EABI__) - beq LSYM(Lepilogue) +ARM_FUNC_START(ffi_call_SYSV) + stm r1, {fp, lr} + mov fp, r1 + + @ This is a bit of a lie wrt the origin of the unwind info, but + @ now we've got the usual frame pointer and two saved registers. + UNWIND(.save {fp,lr}) + UNWIND(.setfp fp, sp) + cfi_def_cfa(fp, 8) + cfi_rel_offset(fp, 0) + cfi_rel_offset(lr, 4) + + mov sp, r0 @ install the stack pointer + mov lr, r2 @ move the fn pointer out of the way + ldr ip, [fp, #16] @ install the static chain + ldmia sp!, {r0-r3} @ move first 4 parameters in registers. + blx lr @ call fn +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 -@ return FLOAT - cmp r3, #FFI_TYPE_FLOAT - stfeqs f0, [r2] - beq LSYM(Lepilogue) + @ Load r2 with the pointer to storage for the return value + @ Load r3 with the return type code + ldr r2, [fp, #8] + ldr r3, [fp, #12] -@ return DOUBLE or LONGDOUBLE - cmp r3, #FFI_TYPE_DOUBLE - stfeqd f0, [r2] + @ Deallocate the stack with the arguments. + mov sp, fp + cfi_def_cfa_register(sp) + + @ Store values stored in registers. + .align 3 + add pc, pc, r3, lsl #3 + nop +0: +E(ARM_TYPE_VFP_S) +#ifdef __clang__ + vstr s0, [r2] +#else + stc p10, cr0, [r2] @ vstr s0, [r2] #endif - -LSYM(Lepilogue): -#if defined (__INTERWORKING__) - ldmia sp!, {r0-r3,fp, lr} - bx lr + pop {fp,pc} +E(ARM_TYPE_VFP_D) +#ifdef __clang__ + vstr d0, [r2] #else - ldmia sp!, {r0-r3,fp, pc} + stc p11, cr0, [r2] @ vstr d0, [r2] #endif - -.ffi_call_SYSV_end: - UNWIND .fnend -#ifdef __ELF__ - .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV) + pop {fp,pc} +E(ARM_TYPE_VFP_N) +#ifdef __clang__ + vstm r2, {d0-d3} +#else + stc p11, cr0, [r2], {8} @ vstm r2, {d0-d3} #endif + pop {fp,pc} +E(ARM_TYPE_INT64) + str r1, [r2, #4] + nop +E(ARM_TYPE_INT) + str r0, [r2] + pop {fp,pc} +E(ARM_TYPE_VOID) + pop {fp,pc} + nop +E(ARM_TYPE_STRUCT) + pop {fp,pc} + + cfi_endproc + UNWIND(.fnend) +ARM_FUNC_END(ffi_call_SYSV) /* +<<<<<<< HEAD unsigned int FFI_HIDDEN ffi_closure_inner (closure, respp, args) ffi_closure *closure; @@ -268,56 +360,170 @@ ARM_FUNC_START(ffi_closure_SYSV) cmp r0, #FFI_TYPE_FLOAT #if defined(__SOFTFP__) || defined(__ARM_EABI__) beq .Lretint -#else - beq .Lretfloat +======= + int ffi_closure_inner_* (cif, fun, user_data, frame) +*/ + +ARM_FUNC_START(ffi_go_closure_SYSV) + cfi_startproc + stmdb sp!, {r0-r3} @ save argument regs + cfi_adjust_cfa_offset(16) + ldr r0, [ip, #4] @ load cif + ldr r1, [ip, #8] @ load fun + mov r2, ip @ load user_data + b 0f + cfi_endproc +ARM_FUNC_END(ffi_go_closure_SYSV) + +ARM_FUNC_START(ffi_closure_SYSV) + UNWIND(.fnstart) + cfi_startproc + stmdb sp!, {r0-r3} @ save argument regs + cfi_adjust_cfa_offset(16) + +#if FFI_EXEC_TRAMPOLINE_TABLE + ldr ip, [ip] @ ip points to the config page, dereference to get the ffi_closure* #endif + ldr r0, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET] @ load cif + ldr r1, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+4] @ load fun + ldr r2, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+8] @ load user_data +0: + add ip, sp, #16 @ compute entry sp + sub sp, sp, #64+32 @ allocate frame + cfi_adjust_cfa_offset(64+32) + stmdb sp!, {ip,lr} + + /* Remember that EABI unwind info only applies at call sites. + We need do nothing except note the save of the stack pointer + and the link registers. */ + UNWIND(.save {sp,lr}) + cfi_adjust_cfa_offset(8) + cfi_rel_offset(lr, 4) + + add r3, sp, #8 @ load frame + bl CNAME(ffi_closure_inner_SYSV) + + @ Load values returned in registers. + add r2, sp, #8+64 @ load result + adr r3, CNAME(ffi_closure_ret) + add pc, r3, r0, lsl #3 + cfi_endproc + UNWIND(.fnend) +ARM_FUNC_END(ffi_closure_SYSV) + +ARM_FUNC_START(ffi_go_closure_VFP) + cfi_startproc + stmdb sp!, {r0-r3} @ save argument regs + cfi_adjust_cfa_offset(16) + ldr r0, [ip, #4] @ load cif + ldr r1, [ip, #8] @ load fun + mov r2, ip @ load user_data + b 0f + cfi_endproc +ARM_FUNC_END(ffi_go_closure_VFP) - cmp r0, #FFI_TYPE_DOUBLE -#if defined(__SOFTFP__) || defined(__ARM_EABI__) - beq .Lretlonglong +ARM_FUNC_START(ffi_closure_VFP) + UNWIND(.fnstart) + cfi_startproc + stmdb sp!, {r0-r3} @ save argument regs + cfi_adjust_cfa_offset(16) + +#if FFI_EXEC_TRAMPOLINE_TABLE + ldr ip, [ip] @ ip points to the config page, dereference to get the ffi_closure* +#endif + ldr r0, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET] @ load cif + ldr r1, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+4] @ load fun + ldr r2, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+8] @ load user_data +0: + add ip, sp, #16 + sub sp, sp, #64+32 @ allocate frame + cfi_adjust_cfa_offset(64+32) +#ifdef __clang__ + vstm sp, {d0-d7} +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #else - beq .Lretdouble + stc p11, cr0, [sp], {16} @ vstm sp, {d0-d7} #endif - - cmp r0, #FFI_TYPE_LONGDOUBLE -#if defined(__SOFTFP__) || defined(__ARM_EABI__) - beq .Lretlonglong + stmdb sp!, {ip,lr} + + /* See above. */ + UNWIND(.save {sp,lr}) + cfi_adjust_cfa_offset(8) + cfi_rel_offset(lr, 4) + + add r3, sp, #8 @ load frame + bl CNAME(ffi_closure_inner_VFP) + + @ Load values returned in registers. + add r2, sp, #8+64 @ load result + adr r3, CNAME(ffi_closure_ret) + add pc, r3, r0, lsl #3 + cfi_endproc + UNWIND(.fnend) +ARM_FUNC_END(ffi_closure_VFP) + +/* Load values returned in registers for both closure entry points. + Note that we use LDM with SP in the register set. This is deprecated + by ARM, but not yet unpredictable. */ + +ARM_FUNC_START_LOCAL(ffi_closure_ret) + cfi_startproc + cfi_rel_offset(sp, 0) + cfi_rel_offset(lr, 4) +0: +E(ARM_TYPE_VFP_S) +#ifdef __clang__ + vldr s0, [r2] #else - beq .Lretlongdouble + ldc p10, cr0, [r2] @ vldr s0, [r2] #endif - - cmp r0, #FFI_TYPE_SINT64 - beq .Lretlonglong -.Lclosure_epilogue: - add sp, sp, #16 - ldmfd sp, {sp, pc} -.Lretint: - ldr r0, [sp] - b .Lclosure_epilogue -.Lretlonglong: - ldr r0, [sp] - ldr r1, [sp, #4] - b .Lclosure_epilogue - -#if !defined(__SOFTFP__) && !defined(__ARM_EABI__) -.Lretfloat: - ldfs f0, [sp] - b .Lclosure_epilogue -.Lretdouble: - ldfd f0, [sp] - b .Lclosure_epilogue -.Lretlongdouble: - ldfd f0, [sp] - b .Lclosure_epilogue + ldm sp, {sp,pc} +E(ARM_TYPE_VFP_D) +#ifdef __clang__ + vldr d0, [r2] +#else + ldc p11, cr0, [r2] @ vldr d0, [r2] #endif - -.ffi_closure_SYSV_end: - UNWIND .fnend -#ifdef __ELF__ - .size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV) + ldm sp, {sp,pc} +E(ARM_TYPE_VFP_N) +#ifdef __clang__ + vldm r2, {d0-d3} +#else + ldc p11, cr0, [r2], {8} @ vldm r2, {d0-d3} +#endif + ldm sp, {sp,pc} +E(ARM_TYPE_INT64) + ldr r1, [r2, #4] + nop +E(ARM_TYPE_INT) + ldr r0, [r2] + ldm sp, {sp,pc} +E(ARM_TYPE_VOID) + ldm sp, {sp,pc} + nop +E(ARM_TYPE_STRUCT) + ldm sp, {sp,pc} + cfi_endproc +ARM_FUNC_END(ffi_closure_ret) + +#if FFI_EXEC_TRAMPOLINE_TABLE + +#ifdef __MACH__ +#include + +.align PAGE_MAX_SHIFT +ARM_FUNC_START(ffi_closure_trampoline_table_page) +.rept PAGE_MAX_SIZE / FFI_TRAMPOLINE_SIZE + adr ip, #-PAGE_MAX_SIZE @ the config page is PAGE_MAX_SIZE behind the trampoline page + sub ip, #8 @ account for pc bias + ldr pc, [ip, #4] @ jump to ffi_closure_SYSV or ffi_closure_VFP +.endr +ARM_FUNC_END(ffi_closure_trampoline_table_page) #endif +#else +<<<<<<< HEAD /* Below are VFP hard-float ABI call and closure implementations. Add VFP FPU directive here. This is only compiled into the library under EABI. */ @@ -484,11 +690,16 @@ ARM_FUNC_START(ffi_closure_VFP) .size CNAME(ffi_closure_VFP),.ffi_closure_VFP_end-CNAME(ffi_closure_VFP) #endif #endif - -ENTRY(ffi_arm_trampoline) - stmfd sp!, {r0-r3} - ldr r0, [pc] - ldr pc, [pc] +======= +ARM_FUNC_START(ffi_arm_trampoline) +0: adr ip, 0b + ldr pc, 1f +1: .long 0 +ARM_FUNC_END(ffi_arm_trampoline) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 + +#endif /* FFI_EXEC_TRAMPOLINE_TABLE */ +#endif /* __arm__ */ #if defined __ELF__ && defined __linux__ .section .note.GNU-stack,"",%progbits diff --git a/native/libffi/src/arm/sysv_msvc_arm32.S b/native/libffi/src/arm/sysv_msvc_arm32.S new file mode 100644 index 0000000000..5c99d0207a --- /dev/null +++ b/native/libffi/src/arm/sysv_msvc_arm32.S @@ -0,0 +1,311 @@ +/* ----------------------------------------------------------------------- + sysv.S - Copyright (c) 1998, 2008, 2011 Red Hat, Inc. + Copyright (c) 2011 Plausible Labs Cooperative, Inc. + Copyright (c) 2019 Microsoft Corporation. + + ARM Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#define LIBFFI_ASM +#include +#include +#include +#include "internal.h" +#include "ksarm.h" + + + ; 8 byte aligned AREA to support 8 byte aligned jump tables + MACRO + NESTED_ENTRY_FFI $FuncName, $AreaName, $ExceptHandler + + ; compute the function's labels + __DeriveFunctionLabels $FuncName + + ; determine the area we will put the function into +__FuncArea SETS "|.text|" + IF "$AreaName" != "" +__FuncArea SETS "$AreaName" + ENDIF + + ; set up the exception handler itself +__FuncExceptionHandler SETS "" + IF "$ExceptHandler" != "" +__FuncExceptionHandler SETS "|$ExceptHandler|" + ENDIF + + ; switch to the specified area, jump tables require 8 byte alignment + AREA $__FuncArea,CODE,CODEALIGN,ALIGN=3,READONLY + + ; export the function name + __ExportProc $FuncName + + ; flush any pending literal pool stuff + ROUT + + ; reset the state of the unwind code tracking + __ResetUnwindState + + MEND + +; MACRO +; TABLE_ENTRY $Type, $Table +;$Type_$Table +; MEND + +#define E(index,table) return_##index##_##table + + ; r0: stack + ; r1: frame + ; r2: fn + ; r3: vfp_used + + ; fake entry point exists only to generate exists only to + ; generate .pdata for exception unwinding + NESTED_ENTRY_FFI ffi_call_VFP_fake + PROLOG_PUSH {r11, lr} ; save fp and lr for unwind + + ALTERNATE_ENTRY ffi_call_VFP + cmp r3, #3 ; load only d0 if possible + vldrle d0, [r0] + vldmgt r0, {d0-d7} + add r0, r0, #64 ; discard the vfp register args + b ffi_call_SYSV + NESTED_END ffi_call_VFP_fake + + ; fake entry point exists only to generate exists only to + ; generate .pdata for exception unwinding + NESTED_ENTRY_FFI ffi_call_SYSV_fake + PROLOG_PUSH {r11, lr} ; save fp and lr for unwind + + ALTERNATE_ENTRY ffi_call_SYSV + stm r1, {fp, lr} + mov fp, r1 + + mov sp, r0 ; install the stack pointer + mov lr, r2 ; move the fn pointer out of the way + ldr ip, [fp, #16] ; install the static chain + ldmia sp!, {r0-r3} ; move first 4 parameters in registers. + blx lr ; call fn + + ; Load r2 with the pointer to storage for the return value + ; Load r3 with the return type code + ldr r2, [fp, #8] + ldr r3, [fp, #12] + + ; Deallocate the stack with the arguments. + mov sp, fp + + ; Store values stored in registers. + ALIGN 8 + lsl r3, #3 + add r3, r3, pc + add r3, #8 + mov pc, r3 + + +E(ARM_TYPE_VFP_S, ffi_call) + ALIGN 8 + vstr s0, [r2] + pop {fp,pc} +E(ARM_TYPE_VFP_D, ffi_call) + ALIGN 8 + vstr d0, [r2] + pop {fp,pc} +E(ARM_TYPE_VFP_N, ffi_call) + ALIGN 8 + vstm r2, {d0-d3} + pop {fp,pc} +E(ARM_TYPE_INT64, ffi_call) + ALIGN 8 + str r1, [r2, #4] + nop +E(ARM_TYPE_INT, ffi_call) + ALIGN 8 + str r0, [r2] + pop {fp,pc} +E(ARM_TYPE_VOID, ffi_call) + ALIGN 8 + pop {fp,pc} + nop +E(ARM_TYPE_STRUCT, ffi_call) + ALIGN 8 + cmp r3, #ARM_TYPE_STRUCT + pop {fp,pc} + NESTED_END ffi_call_SYSV_fake + + IMPORT |ffi_closure_inner_SYSV| + /* + int ffi_closure_inner_SYSV + ( + cif, ; r0 + fun, ; r1 + user_data, ; r2 + frame ; r3 + ) + */ + + NESTED_ENTRY_FFI ffi_go_closure_SYSV + stmdb sp!, {r0-r3} ; save argument regs + ldr r0, [ip, #4] ; load cif + ldr r1, [ip, #8] ; load fun + mov r2, ip ; load user_data + b ffi_go_closure_SYSV_0 + NESTED_END ffi_go_closure_SYSV + + ; r3: ffi_closure + + ; fake entry point exists only to generate exists only to + ; generate .pdata for exception unwinding + NESTED_ENTRY_FFI ffi_closure_SYSV_fake + PROLOG_PUSH {r11, lr} ; save fp and lr for unwind + ALTERNATE_ENTRY ffi_closure_SYSV + ldmfd sp!, {ip,r0} ; restore fp (r0 is used for stack alignment) + stmdb sp!, {r0-r3} ; save argument regs + + ldr r0, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET] ; ffi_closure->cif + ldr r1, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+4] ; ffi_closure->fun + ldr r2, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+8] ; ffi_closure->user_data + + ALTERNATE_ENTRY ffi_go_closure_SYSV_0 + add ip, sp, #16 ; compute entry sp + + sub sp, sp, #64+32 ; allocate frame parameter (sizeof(vfp_space) = 64, sizeof(result) = 32) + mov r3, sp ; set frame parameter + stmdb sp!, {ip,lr} + + bl ffi_closure_inner_SYSV ; call the Python closure + + ; Load values returned in registers. + add r2, sp, #64+8 ; address of closure_frame->result + bl ffi_closure_ret ; move result to correct register or memory for type + + ldmfd sp!, {ip,lr} + mov sp, ip ; restore stack pointer + mov pc, lr + NESTED_END ffi_closure_SYSV_fake + + IMPORT |ffi_closure_inner_VFP| + /* + int ffi_closure_inner_VFP + ( + cif, ; r0 + fun, ; r1 + user_data, ; r2 + frame ; r3 + ) + */ + + NESTED_ENTRY_FFI ffi_go_closure_VFP + stmdb sp!, {r0-r3} ; save argument regs + ldr r0, [ip, #4] ; load cif + ldr r1, [ip, #8] ; load fun + mov r2, ip ; load user_data + b ffi_go_closure_VFP_0 + NESTED_END ffi_go_closure_VFP + + ; fake entry point exists only to generate exists only to + ; generate .pdata for exception unwinding + ; r3: closure + NESTED_ENTRY_FFI ffi_closure_VFP_fake + PROLOG_PUSH {r11, lr} ; save fp and lr for unwind + + ALTERNATE_ENTRY ffi_closure_VFP + ldmfd sp!, {ip,r0} ; restore fp (r0 is used for stack alignment) + stmdb sp!, {r0-r3} ; save argument regs + + ldr r0, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET] ; load cif + ldr r1, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+4] ; load fun + ldr r2, [ip, #FFI_TRAMPOLINE_CLOSURE_OFFSET+8] ; load user_data + + ALTERNATE_ENTRY ffi_go_closure_VFP_0 + add ip, sp, #16 ; compute entry sp + sub sp, sp, #32 ; save space for closure_frame->result + vstmdb sp!, {d0-d7} ; push closure_frame->vfp_space + + mov r3, sp ; save closure_frame + stmdb sp!, {ip,lr} + + bl ffi_closure_inner_VFP + + ; Load values returned in registers. + add r2, sp, #64+8 ; load result + bl ffi_closure_ret + ldmfd sp!, {ip,lr} + mov sp, ip ; restore stack pointer + mov pc, lr + NESTED_END ffi_closure_VFP_fake + +/* Load values returned in registers for both closure entry points. + Note that we use LDM with SP in the register set. This is deprecated + by ARM, but not yet unpredictable. */ + + NESTED_ENTRY_FFI ffi_closure_ret + stmdb sp!, {fp,lr} + + ALIGN 8 + lsl r0, #3 + add r0, r0, pc + add r0, #8 + mov pc, r0 + +E(ARM_TYPE_VFP_S, ffi_closure) + ALIGN 8 + vldr s0, [r2] + b call_epilogue +E(ARM_TYPE_VFP_D, ffi_closure) + ALIGN 8 + vldr d0, [r2] + b call_epilogue +E(ARM_TYPE_VFP_N, ffi_closure) + ALIGN 8 + vldm r2, {d0-d3} + b call_epilogue +E(ARM_TYPE_INT64, ffi_closure) + ALIGN 8 + ldr r1, [r2, #4] + nop +E(ARM_TYPE_INT, ffi_closure) + ALIGN 8 + ldr r0, [r2] + b call_epilogue +E(ARM_TYPE_VOID, ffi_closure) + ALIGN 8 + b call_epilogue + nop +E(ARM_TYPE_STRUCT, ffi_closure) + ALIGN 8 + b call_epilogue +call_epilogue + ldmfd sp!, {fp,pc} + NESTED_END ffi_closure_ret + + AREA |.trampoline|, DATA, THUMB, READONLY + EXPORT |ffi_arm_trampoline| +|ffi_arm_trampoline| DATA +thisproc adr ip, thisproc + stmdb sp!, {ip, r0} + ldr pc, [pc, #0] + DCD 0 + ;ENDP + + END \ No newline at end of file diff --git a/native/libffi/src/arm/trampoline.S b/native/libffi/src/arm/trampoline.S deleted file mode 100644 index 935e8de179..0000000000 --- a/native/libffi/src/arm/trampoline.S +++ /dev/null @@ -1,4450 +0,0 @@ -# GENERATED CODE - DO NOT EDIT -# This file was generated by src/arm/gentramp.sh - -# Copyright (c) 2010, Plausible Labs Cooperative, Inc. -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# Software''), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED AS IS'', WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. -# ----------------------------------------------------------------------- - -.text -.align 12 -.globl _ffi_closure_trampoline_table_page -_ffi_closure_trampoline_table_page: - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - - - // trampoline - // Save to stack - stmfd sp!, {r0-r3} - - // Load the context argument from the config page. - // This places the first usable config value at _ffi_closure_trampoline_table-4080 - // This accounts for the above 4-byte stmfd instruction, plus 8 bytes constant when loading from pc. - ldr r0, [pc, #-4092] - - // Load the jump address from the config page. - ldr pc, [pc, #-4092] - diff --git a/native/libffi/src/closures.c b/native/libffi/src/closures.c index 721ff00ea4..49b8a12dfd 100644 --- a/native/libffi/src/closures.c +++ b/native/libffi/src/closures.c @@ -1,5 +1,6 @@ /* ----------------------------------------------------------------------- - closures.c - Copyright (c) 2007, 2009, 2010 Red Hat, Inc. + closures.c - Copyright (c) 2019 Anthony Green + Copyright (c) 2007, 2009, 2010 Red Hat, Inc. Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc Copyright (c) 2011 Plausible Labs Cooperative, Inc. @@ -30,11 +31,92 @@ #define _GNU_SOURCE 1 #endif +#include #include #include +#ifdef __NetBSD__ +#include +#endif + +#if __NetBSD_Version__ - 0 >= 799007200 +/* NetBSD with PROT_MPROTECT */ +#include + +#include +#include + +static const size_t overhead = + (sizeof(max_align_t) > sizeof(void *) + sizeof(size_t)) ? + sizeof(max_align_t) + : sizeof(void *) + sizeof(size_t); + +#define ADD_TO_POINTER(p, d) ((void *)((uintptr_t)(p) + (d))) + +void * +ffi_closure_alloc (size_t size, void **code) +{ + static size_t page_size; + size_t rounded_size; + void *codeseg, *dataseg; + int prot; + + /* Expect that PAX mprotect is active and a separate code mapping is necessary. */ + if (!code) + return NULL; + + /* Obtain system page size. */ + if (!page_size) + page_size = sysconf(_SC_PAGESIZE); + + /* Round allocation size up to the next page, keeping in mind the size field and pointer to code map. */ + rounded_size = (size + overhead + page_size - 1) & ~(page_size - 1); + + /* Primary mapping is RW, but request permission to switch to PROT_EXEC later. */ + prot = PROT_READ | PROT_WRITE | PROT_MPROTECT(PROT_EXEC); + dataseg = mmap(NULL, rounded_size, prot, MAP_ANON | MAP_PRIVATE, -1, 0); + if (dataseg == MAP_FAILED) + return NULL; + + /* Create secondary mapping and switch it to RX. */ + codeseg = mremap(dataseg, rounded_size, NULL, rounded_size, MAP_REMAPDUP); + if (codeseg == MAP_FAILED) { + munmap(dataseg, rounded_size); + return NULL; + } + if (mprotect(codeseg, rounded_size, PROT_READ | PROT_EXEC) == -1) { + munmap(codeseg, rounded_size); + munmap(dataseg, rounded_size); + return NULL; + } + + /* Remember allocation size and location of the secondary mapping for ffi_closure_free. */ + memcpy(dataseg, &rounded_size, sizeof(rounded_size)); + memcpy(ADD_TO_POINTER(dataseg, sizeof(size_t)), &codeseg, sizeof(void *)); + *code = ADD_TO_POINTER(codeseg, overhead); + return ADD_TO_POINTER(dataseg, overhead); +} + +void +ffi_closure_free (void *ptr) +{ + void *codeseg, *dataseg; + size_t rounded_size; + + dataseg = ADD_TO_POINTER(ptr, -overhead); + memcpy(&rounded_size, dataseg, sizeof(rounded_size)); + memcpy(&codeseg, ADD_TO_POINTER(dataseg, sizeof(size_t)), sizeof(void *)); + munmap(dataseg, rounded_size); + munmap(codeseg, rounded_size); +} +#else /* !NetBSD with PROT_MPROTECT */ + #if !FFI_MMAP_EXEC_WRIT && !FFI_EXEC_TRAMPOLINE_TABLE +<<<<<<< HEAD # if __gnu_linux__ && !defined(__ANDROID__) +======= +# if __linux__ && !defined(__ANDROID__) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 /* This macro indicates it may be forbidden to map anonymous memory with both write and execute permission. Code compiled when this option is defined will attempt to map such pages once, but if it @@ -45,7 +127,7 @@ # define FFI_MMAP_EXEC_WRIT 1 # define HAVE_MNTENT 1 # endif -# if defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__) +# if defined(_WIN32) || defined(__OS2__) /* Windows systems may have Data Execution Protection (DEP) enabled, which requires the use of VirtualMalloc/VirtualFree to alloc/free executable memory. */ @@ -54,7 +136,7 @@ #endif #if FFI_MMAP_EXEC_WRIT && !defined FFI_MMAP_EXEC_SELINUX -# ifdef __linux__ +# if defined(__linux__) && !defined(__ANDROID__) /* When defined to 1 check for SELinux and if SELinux is active, don't attempt PROT_EXEC|PROT_WRITE mapping at all, as that might cause audit messages. */ @@ -64,11 +146,222 @@ #if FFI_CLOSURES -# if FFI_EXEC_TRAMPOLINE_TABLE +#if FFI_EXEC_TRAMPOLINE_TABLE + +#ifdef __MACH__ + +#include +#include +#ifdef HAVE_PTRAUTH +#include +#endif +#include +#include + +extern void *ffi_closure_trampoline_table_page; + +typedef struct ffi_trampoline_table ffi_trampoline_table; +typedef struct ffi_trampoline_table_entry ffi_trampoline_table_entry; + +struct ffi_trampoline_table +{ + /* contiguous writable and executable pages */ + vm_address_t config_page; + vm_address_t trampoline_page; + + /* free list tracking */ + uint16_t free_count; + ffi_trampoline_table_entry *free_list; + ffi_trampoline_table_entry *free_list_pool; + + ffi_trampoline_table *prev; + ffi_trampoline_table *next; +}; + +struct ffi_trampoline_table_entry +{ + void *(*trampoline) (void); + ffi_trampoline_table_entry *next; +}; + +/* Total number of trampolines that fit in one trampoline table */ +#define FFI_TRAMPOLINE_COUNT (PAGE_MAX_SIZE / FFI_TRAMPOLINE_SIZE) + +static pthread_mutex_t ffi_trampoline_lock = PTHREAD_MUTEX_INITIALIZER; +static ffi_trampoline_table *ffi_trampoline_tables = NULL; + +static ffi_trampoline_table * +ffi_trampoline_table_alloc (void) +{ + ffi_trampoline_table *table; + vm_address_t config_page; + vm_address_t trampoline_page; + vm_address_t trampoline_page_template; + vm_prot_t cur_prot; + vm_prot_t max_prot; + kern_return_t kt; + uint16_t i; + + /* Allocate two pages -- a config page and a placeholder page */ + config_page = 0x0; + kt = vm_allocate (mach_task_self (), &config_page, PAGE_MAX_SIZE * 2, + VM_FLAGS_ANYWHERE); + if (kt != KERN_SUCCESS) + return NULL; + + /* Remap the trampoline table on top of the placeholder page */ + trampoline_page = config_page + PAGE_MAX_SIZE; + trampoline_page_template = (vm_address_t)&ffi_closure_trampoline_table_page; +#ifdef __arm__ + /* ffi_closure_trampoline_table_page can be thumb-biased on some ARM archs */ + trampoline_page_template &= ~1UL; +#endif + kt = vm_remap (mach_task_self (), &trampoline_page, PAGE_MAX_SIZE, 0x0, + VM_FLAGS_OVERWRITE, mach_task_self (), trampoline_page_template, + FALSE, &cur_prot, &max_prot, VM_INHERIT_SHARE); + if (kt != KERN_SUCCESS) + { + vm_deallocate (mach_task_self (), config_page, PAGE_MAX_SIZE * 2); + return NULL; + } + + /* We have valid trampoline and config pages */ + table = calloc (1, sizeof (ffi_trampoline_table)); + table->free_count = FFI_TRAMPOLINE_COUNT; + table->config_page = config_page; + table->trampoline_page = trampoline_page; + + /* Create and initialize the free list */ + table->free_list_pool = + calloc (FFI_TRAMPOLINE_COUNT, sizeof (ffi_trampoline_table_entry)); + + for (i = 0; i < table->free_count; i++) + { + ffi_trampoline_table_entry *entry = &table->free_list_pool[i]; + entry->trampoline = + (void *) (table->trampoline_page + (i * FFI_TRAMPOLINE_SIZE)); + + if (i < table->free_count - 1) + entry->next = &table->free_list_pool[i + 1]; + } + + table->free_list = table->free_list_pool; + + return table; +} + +static void +ffi_trampoline_table_free (ffi_trampoline_table *table) +{ + /* Remove from the list */ + if (table->prev != NULL) + table->prev->next = table->next; + + if (table->next != NULL) + table->next->prev = table->prev; + + /* Deallocate pages */ + vm_deallocate (mach_task_self (), table->config_page, PAGE_MAX_SIZE * 2); + + /* Deallocate free list */ + free (table->free_list_pool); + free (table); +} + +void * +ffi_closure_alloc (size_t size, void **code) +{ + /* Create the closure */ + ffi_closure *closure = malloc (size); + if (closure == NULL) + return NULL; + + pthread_mutex_lock (&ffi_trampoline_lock); + + /* Check for an active trampoline table with available entries. */ + ffi_trampoline_table *table = ffi_trampoline_tables; + if (table == NULL || table->free_list == NULL) + { + table = ffi_trampoline_table_alloc (); + if (table == NULL) + { + pthread_mutex_unlock (&ffi_trampoline_lock); + free (closure); + return NULL; + } + + /* Insert the new table at the top of the list */ + table->next = ffi_trampoline_tables; + if (table->next != NULL) + table->next->prev = table; + + ffi_trampoline_tables = table; + } + + /* Claim the free entry */ + ffi_trampoline_table_entry *entry = ffi_trampoline_tables->free_list; + ffi_trampoline_tables->free_list = entry->next; + ffi_trampoline_tables->free_count--; + entry->next = NULL; + + pthread_mutex_unlock (&ffi_trampoline_lock); + + /* Initialize the return values */ + *code = entry->trampoline; +#ifdef HAVE_PTRAUTH + *code = ptrauth_sign_unauthenticated (*code, ptrauth_key_asia, 0); +#endif + closure->trampoline_table = table; + closure->trampoline_table_entry = entry; + + return closure; +} + +void +ffi_closure_free (void *ptr) +{ + ffi_closure *closure = ptr; + + pthread_mutex_lock (&ffi_trampoline_lock); + + /* Fetch the table and entry references */ + ffi_trampoline_table *table = closure->trampoline_table; + ffi_trampoline_table_entry *entry = closure->trampoline_table_entry; + + /* Return the entry to the free list */ + entry->next = table->free_list; + table->free_list = entry; + table->free_count++; + + /* If all trampolines within this table are free, and at least one other table exists, deallocate + * the table */ + if (table->free_count == FFI_TRAMPOLINE_COUNT + && ffi_trampoline_tables != table) + { + ffi_trampoline_table_free (table); + } + else if (ffi_trampoline_tables != table) + { + /* Otherwise, bump this table to the top of the list */ + table->prev = NULL; + table->next = ffi_trampoline_tables; + if (ffi_trampoline_tables != NULL) + ffi_trampoline_tables->prev = table; + + ffi_trampoline_tables = table; + } + + pthread_mutex_unlock (&ffi_trampoline_lock); + + /* Free the closure */ + free (closure); +} + +#endif // Per-target implementation; It's unclear what can reasonable be shared between two OS/architecture implementations. -# elif FFI_MMAP_EXEC_WRIT /* !FFI_EXEC_TRAMPOLINE_TABLE */ +#elif FFI_MMAP_EXEC_WRIT /* !FFI_EXEC_TRAMPOLINE_TABLE */ #define USE_LOCKS 1 #define USE_DL_PREFIX 1 @@ -94,14 +387,6 @@ /* Don't allocate more than a page unless needed. */ #define DEFAULT_GRANULARITY ((size_t)malloc_getpagesize) -#if FFI_CLOSURE_TEST -/* Don't release single pages, to avoid a worst-case scenario of - continuously allocating and releasing single pages, but release - pairs of pages, which should do just as well given that allocations - are likely to be small. */ -#define DEFAULT_TRIM_THRESHOLD ((size_t)malloc_getpagesize) -#endif - #include #include #include @@ -111,7 +396,7 @@ #endif #include #include -#if !defined(X86_WIN32) && !defined(X86_WIN64) +#if !defined(_WIN32) #ifdef HAVE_MNTENT #include #endif /* HAVE_MNTENT */ @@ -237,11 +522,11 @@ static int dlmalloc_trim(size_t) MAYBE_UNUSED; static size_t dlmalloc_usable_size(void*) MAYBE_UNUSED; static void dlmalloc_stats(void) MAYBE_UNUSED; -#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) +#if !(defined(_WIN32) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) /* Use these for mmap and munmap within dlmalloc.c. */ static void *dlmmap(void *, size_t, int, int, int, off_t); static int dlmunmap(void *, size_t); -#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */ +#endif /* !(defined(_WIN32) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */ #define mmap dlmmap #define munmap dlmunmap @@ -251,7 +536,7 @@ static int dlmunmap(void *, size_t); #undef mmap #undef munmap -#if !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) +#if !(defined(_WIN32) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) /* A mutex used to synchronize access to *exec* variables in this file. */ static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -308,7 +593,11 @@ open_temp_exec_file_dir (const char *dir) } #endif +<<<<<<< HEAD lendir = strlen (dir); +======= + lendir = (int) strlen (dir); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 tempname = __builtin_alloca (lendir + sizeof (suffix)); if (!tempname) @@ -449,6 +738,36 @@ open_temp_exec_file (void) return fd; } +/* We need to allocate space in a file that will be backing a writable + mapping. Several problems exist with the usual approaches: + - fallocate() is Linux-only + - posix_fallocate() is not available on all platforms + - ftruncate() does not allocate space on filesystems with sparse files + Failure to allocate the space will cause SIGBUS to be thrown when + the mapping is subsequently written to. */ +static int +allocate_space (int fd, off_t offset, off_t len) +{ + static size_t page_size; + + /* Obtain system page size. */ + if (!page_size) + page_size = sysconf(_SC_PAGESIZE); + + unsigned char buf[page_size]; + memset (buf, 0, page_size); + + while (len > 0) + { + off_t to_write = (len < page_size) ? len : page_size; + if (write (fd, buf, to_write) < to_write) + return -1; + len -= to_write; + } + + return 0; +} + /* Map in a chunk of memory from the temporary exec file into separate locations in the virtual memory address space, one writable and one executable. Returns the address of the writable portion, after @@ -470,7 +789,7 @@ dlmmap_locked (void *start, size_t length, int prot, int flags, off_t offset) offset = execsize; - if (ftruncate (execfd, offset + length)) + if (allocate_space (execfd, offset, length)) return MFAIL; flags &= ~(MAP_PRIVATE | MAP_ANONYMOUS); @@ -485,7 +804,13 @@ dlmmap_locked (void *start, size_t length, int prot, int flags, off_t offset) close (execfd); goto retry_open; } - ftruncate (execfd, offset); + if (ftruncate (execfd, offset) != 0) + { + /* Fixme : Error logs can be added here. Returning an error for + * ftruncte() will not add any advantage as it is being + * validating in the error case. */ + } + return MFAIL; } else if (!offset @@ -497,7 +822,12 @@ dlmmap_locked (void *start, size_t length, int prot, int flags, off_t offset) if (start == MFAIL) { munmap (ptr, length); - ftruncate (execfd, offset); + if (ftruncate (execfd, offset) != 0) + { + /* Fixme : Error logs can be added here. Returning an error for + * ftruncte() will not add any advantage as it is being + * validating in the error case. */ + } return start; } @@ -521,10 +851,6 @@ dlmmap (void *start, size_t length, int prot, && flags == (MAP_PRIVATE | MAP_ANONYMOUS) && fd == -1 && offset == 0); -#if FFI_CLOSURE_TEST - printf ("mapping in %zi\n", length); -#endif - if (execfd == -1 && is_emutramp_enabled ()) { ptr = mmap (start, length, prot & ~PROT_EXEC, flags, fd, offset); @@ -570,10 +896,6 @@ dlmunmap (void *start, size_t length) msegmentptr seg = segment_holding (gm, start); void *code; -#if FFI_CLOSURE_TEST - printf ("unmapping %zi\n", length); -#endif - if (seg && (code = add_segment_exec_offset (start, seg)) != start) { int ret = munmap (code, length); @@ -600,7 +922,7 @@ segment_holding_code (mstate m, char* addr) } #endif -#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */ +#endif /* !(defined(_WIN32) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */ /* Allocate a chunk of memory with the given size. Returns a pointer to the writable address, and sets *CODE to the executable @@ -613,7 +935,7 @@ ffi_closure_alloc (size_t size, void **code) if (!code) return NULL; - ptr = dlmalloc (size); + ptr = FFI_CLOSURE_PTR (dlmalloc (size)); if (ptr) { @@ -625,6 +947,20 @@ ffi_closure_alloc (size_t size, void **code) return ptr; } +void * +ffi_data_to_code_pointer (void *data) +{ + msegmentptr seg = segment_holding (gm, data); + /* We expect closures to be allocated with ffi_closure_alloc(), in + which case seg will be non-NULL. However, some users take on the + burden of managing this memory themselves, in which case this + we'll just return data. */ + if (seg) + return add_segment_exec_offset (data, seg); + else + return data; +} + /* Release a chunk of memory allocated with ffi_closure_alloc. If FFI_CLOSURE_FREE_CODE is nonzero, the given address can be the writable or the executable address given. Otherwise, only the @@ -639,29 +975,9 @@ ffi_closure_free (void *ptr) ptr = sub_segment_exec_offset (ptr, seg); #endif - dlfree (ptr); + dlfree (FFI_RESTORE_PTR (ptr)); } - -#if FFI_CLOSURE_TEST -/* Do some internal sanity testing to make sure allocation and - deallocation of pages are working as intended. */ -int main () -{ - void *p[3]; -#define GET(idx, len) do { p[idx] = dlmalloc (len); printf ("allocated %zi for p[%i]\n", (len), (idx)); } while (0) -#define PUT(idx) do { printf ("freeing p[%i]\n", (idx)); dlfree (p[idx]); } while (0) - GET (0, malloc_getpagesize / 2); - GET (1, 2 * malloc_getpagesize - 64 * sizeof (void*)); - PUT (1); - GET (1, 2 * malloc_getpagesize); - GET (2, malloc_getpagesize / 2); - PUT (1); - PUT (0); - PUT (2); - return 0; -} -#endif /* FFI_CLOSURE_TEST */ # else /* ! FFI_MMAP_EXEC_WRIT */ /* On many systems, memory returned by malloc is writable and @@ -675,14 +991,22 @@ ffi_closure_alloc (size_t size, void **code) if (!code) return NULL; - return *code = malloc (size); + return *code = FFI_CLOSURE_PTR (malloc (size)); } void ffi_closure_free (void *ptr) { - free (ptr); + free (FFI_RESTORE_PTR (ptr)); +} + +void * +ffi_data_to_code_pointer (void *data) +{ + return data; } # endif /* ! FFI_MMAP_EXEC_WRIT */ #endif /* FFI_CLOSURES */ + +#endif /* NetBSD with PROT_MPROTECT */ diff --git a/native/libffi/src/cris/ffi.c b/native/libffi/src/cris/ffi.c index aaca5b1cba..9011fdec03 100644 --- a/native/libffi/src/cris/ffi.c +++ b/native/libffi/src/cris/ffi.c @@ -29,7 +29,7 @@ #include #include -#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG) +#define STACK_ARG_SIZE(x) FFI_ALIGN(x, FFI_SIZEOF_ARG) static ffi_status initialize_aggregate_packed_struct (ffi_type * arg) @@ -190,7 +190,7 @@ ffi_prep_cif_core (ffi_cif * cif, FFI_ASSERT_VALID_TYPE (*ptr); if (((*ptr)->alignment - 1) & bytes) - bytes = ALIGN (bytes, (*ptr)->alignment); + bytes = FFI_ALIGN (bytes, (*ptr)->alignment); if ((*ptr)->type == FFI_TYPE_STRUCT) { if ((*ptr)->size > 8) diff --git a/native/libffi/src/csky/ffi.c b/native/libffi/src/csky/ffi.c new file mode 100644 index 0000000000..af50b7c648 --- /dev/null +++ b/native/libffi/src/csky/ffi.c @@ -0,0 +1,395 @@ +/* ----------------------------------------------------------------------- + ffi.c + + CSKY Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#include +#include + +#include + +/* ffi_prep_args is called by the assembly routine once stack space + has been allocated for the function's arguments +*/ +void ffi_prep_args(char *stack, extended_cif *ecif) +{ + register unsigned int i; + register void **p_argv; + register char *argp; + register ffi_type **p_arg; + + argp = stack; + + if ( ecif->cif->flags == FFI_TYPE_STRUCT ) { + *(void **) argp = ecif->rvalue; + argp += 4; + } + + p_argv = ecif->avalue; + + for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; + (i != 0); + i--, p_arg++) + { + size_t z; + size_t alignment; + + /* Align if necessary */ + alignment = (*p_arg)->alignment; +#ifdef __CSKYABIV1__ + /* + * Adapt ABIV1 bug. + * If struct's size is larger than 8 bytes, then it always alignment as 4 bytes. + */ + if (((*p_arg)->type == FFI_TYPE_STRUCT) && ((*p_arg)->size > 8) && (alignment == 8)) { + alignment = 4; + } +#endif + + if ((alignment - 1) & (unsigned) argp) { + argp = (char *) FFI_ALIGN(argp, alignment); + } + + if ((*p_arg)->type == FFI_TYPE_STRUCT) + argp = (char *) FFI_ALIGN(argp, 4); + + z = (*p_arg)->size; + if (z < sizeof(int)) + { + z = sizeof(int); + switch ((*p_arg)->type) + { + case FFI_TYPE_SINT8: + *(signed int *) argp = (signed int)*(SINT8 *)(* p_argv); + break; + + case FFI_TYPE_UINT8: + *(unsigned int *) argp = (unsigned int)*(UINT8 *)(* p_argv); + break; + + case FFI_TYPE_SINT16: + *(signed int *) argp = (signed int)*(SINT16 *)(* p_argv); + break; + + case FFI_TYPE_UINT16: + *(unsigned int *) argp = (unsigned int)*(UINT16 *)(* p_argv); + break; + + case FFI_TYPE_STRUCT: +#ifdef __CSKYBE__ + memcpy((argp + 4 - (*p_arg)->size), *p_argv, (*p_arg)->size); +#else + memcpy(argp, *p_argv, (*p_arg)->size); +#endif + break; + + default: + FFI_ASSERT(0); + } + } + else if (z == sizeof(int)) + { + *(unsigned int *) argp = (unsigned int)*(UINT32 *)(* p_argv); + } + else + { + memcpy(argp, *p_argv, z); + } + p_argv++; + argp += z; + } + + return; +} + +/* Perform machine dependent cif processing */ +ffi_status ffi_prep_cif_machdep(ffi_cif *cif) +{ + /* Round the stack up to a multiple of 8 bytes. This isn't needed + everywhere, but it is on some platforms, and it doesn't hcsky anything + when it isn't needed. */ + cif->bytes = (cif->bytes + 7) & ~7; + + /* Set the return type flag */ + switch (cif->rtype->type) + { + + case FFI_TYPE_DOUBLE: + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + cif->flags = (unsigned) FFI_TYPE_SINT64; + break; + + case FFI_TYPE_STRUCT: + if (cif->rtype->size <= 4) + /* A Composite Type not larger than 4 bytes is returned in r0. */ + cif->flags = (unsigned)FFI_TYPE_INT; + else if (cif->rtype->size <= 8) + /* A Composite Type not larger than 8 bytes is returned in r0, r1. */ + cif->flags = (unsigned)FFI_TYPE_SINT64; + else + /* A Composite Type larger than 8 bytes, or whose size cannot + be determined statically ... is stored in memory at an + address passed [in r0]. */ + cif->flags = (unsigned)FFI_TYPE_STRUCT; + break; + + default: + cif->flags = FFI_TYPE_INT; + break; + } + + return FFI_OK; +} + +/* Perform machine dependent cif processing for variadic calls */ +ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, + unsigned int nfixedargs, + unsigned int ntotalargs) +{ + return ffi_prep_cif_machdep(cif); +} + +/* Prototypes for assembly functions, in sysv.S */ +extern void ffi_call_SYSV (void (*fn)(void), extended_cif *, unsigned, unsigned, unsigned *); + +void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +{ + extended_cif ecif; + + int small_struct = (cif->flags == FFI_TYPE_INT + && cif->rtype->type == FFI_TYPE_STRUCT); + + ecif.cif = cif; + ecif.avalue = avalue; + + unsigned int temp; + + /* If the return value is a struct and we don't have a return */ + /* value address then we need to make one */ + + if ((rvalue == NULL) && + (cif->flags == FFI_TYPE_STRUCT)) + { + ecif.rvalue = alloca(cif->rtype->size); + } + else if (small_struct) + ecif.rvalue = &temp; + else + ecif.rvalue = rvalue; + + switch (cif->abi) + { + case FFI_SYSV: + ffi_call_SYSV (fn, &ecif, cif->bytes, cif->flags, ecif.rvalue); + break; + + default: + FFI_ASSERT(0); + break; + } + if (small_struct) +#ifdef __CSKYBE__ + memcpy (rvalue, ((unsigned char *)&temp + (4 - cif->rtype->size)), cif->rtype->size); +#else + memcpy (rvalue, &temp, cif->rtype->size); +#endif +} + +/** private members **/ + +static void ffi_prep_incoming_args_SYSV (char *stack, void **ret, + void** args, ffi_cif* cif); + +void ffi_closure_SYSV (ffi_closure *); + +/* This function is jumped to by the trampoline */ + +unsigned int +ffi_closure_SYSV_inner (closure, respp, args) + ffi_closure *closure; + void **respp; + void *args; +{ + // our various things... + ffi_cif *cif; + void **arg_area; + + cif = closure->cif; + arg_area = (void**) alloca (cif->nargs * sizeof (void*)); + + /* this call will initialize ARG_AREA, such that each + * element in that array points to the corresponding + * value on the stack; and if the function returns + * a structure, it will re-set RESP to point to the + * structure return address. */ + + ffi_prep_incoming_args_SYSV(args, respp, arg_area, cif); + + (closure->fun) (cif, *respp, arg_area, closure->user_data); + +#ifdef __CSKYBE__ + if (cif->flags == FFI_TYPE_INT && cif->rtype->type == FFI_TYPE_STRUCT) { + unsigned int tmp = 0; + tmp = *(unsigned int *)(*respp); + *(unsigned int *)(*respp) = (tmp >> ((4 - cif->rtype->size) * 8)); + } +#endif + + return cif->flags; +} + + +static void +ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, + void **avalue, ffi_cif *cif) +{ + register unsigned int i; + register void **p_argv; + register char *argp; + register ffi_type **p_arg; + + argp = stack; + + if ( cif->flags == FFI_TYPE_STRUCT ) { + *rvalue = *(void **) argp; + argp += 4; + } + + p_argv = avalue; + + for (i = cif->nargs, p_arg = cif->arg_types; (i != 0); i--, p_arg++) + { + size_t z; + size_t alignment; + + alignment = (*p_arg)->alignment; + if (alignment < 4) + alignment = 4; + +#ifdef __CSKYABIV1__ + /* + * Adapt ABIV1 bug. + * If struct's size is larger than 8 bytes, then it always alignment as 4 bytes. + */ + if (((*p_arg)->type == FFI_TYPE_STRUCT) && ((*p_arg)->size > 8) && (alignment == 8)) { + alignment = 4; + } +#endif + + /* Align if necessary */ + if ((alignment - 1) & (unsigned) argp) { + argp = (char *) FFI_ALIGN(argp, alignment); + } + + z = (*p_arg)->size; + +#ifdef __CSKYBE__ + unsigned int tmp = 0; + if ((*p_arg)->size < 4) { + tmp = *(unsigned int *)argp; + memcpy(argp, ((unsigned char *)&tmp + (4 - (*p_arg)->size)), (*p_arg)->size); + } +#else + /* because we're little endian, this is what it turns into. */ +#endif + *p_argv = (void*) argp; + + p_argv++; + argp += z; + } + + return; +} + +/* How to make a trampoline. */ + +extern unsigned char ffi_csky_trampoline[TRAMPOLINE_SIZE]; + +/* + * Since there is no __clear_cache in libgcc in csky toolchain. + * define ffi_csky_cacheflush in sysv.S. + * void ffi_csky_cacheflush(uint32 start_addr, uint32 size, int cache) + */ +#define CACHEFLUSH_IN_FFI 1 +#if CACHEFLUSH_IN_FFI +extern void ffi_csky_cacheflush(unsigned char *__tramp, unsigned int k, + int i); +#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ +({ unsigned char *__tramp = (unsigned char*)(TRAMP); \ + unsigned int __fun = (unsigned int)(FUN); \ + unsigned int __ctx = (unsigned int)(CTX); \ + unsigned char *insns = (unsigned char *)(CTX); \ + memcpy (__tramp, ffi_csky_trampoline, TRAMPOLINE_SIZE); \ + *(unsigned int*) &__tramp[TRAMPOLINE_SIZE] = __ctx; \ + *(unsigned int*) &__tramp[TRAMPOLINE_SIZE + 4] = __fun; \ + ffi_csky_cacheflush(&__tramp[0], TRAMPOLINE_SIZE, 3); /* Clear data mapping. */ \ + ffi_csky_cacheflush(insns, TRAMPOLINE_SIZE, 3); \ + /* Clear instruction \ + mapping. */ \ + }) +#else +#define FFI_INIT_TRAMPOLINE(TRAMP,FUN,CTX) \ +({ unsigned char *__tramp = (unsigned char*)(TRAMP); \ + unsigned int __fun = (unsigned int)(FUN); \ + unsigned int __ctx = (unsigned int)(CTX); \ + unsigned char *insns = (unsigned char *)(CTX); \ + memcpy (__tramp, ffi_csky_trampoline, TRAMPOLINE_SIZE); \ + *(unsigned int*) &__tramp[TRAMPOLINE_SIZE] = __ctx; \ + *(unsigned int*) &__tramp[TRAMPOLINE_SIZE + 4] = __fun; \ + __clear_cache((&__tramp[0]), (&__tramp[TRAMPOLINE_SIZE-1])); /* Clear data mapping. */ \ + __clear_cache(insns, insns + TRAMPOLINE_SIZE); \ + /* Clear instruction \ + mapping. */ \ + }) +#endif + +/* the cif must already be prep'ed */ + +ffi_status +ffi_prep_closure_loc (ffi_closure* closure, + ffi_cif* cif, + void (*fun)(ffi_cif*,void*,void**,void*), + void *user_data, + void *codeloc) +{ + void (*closure_func)(ffi_closure*) = NULL; + + if (cif->abi == FFI_SYSV) + closure_func = &ffi_closure_SYSV; + else + return FFI_BAD_ABI; + + FFI_INIT_TRAMPOLINE (&closure->tramp[0], \ + closure_func, \ + codeloc); + + closure->cif = cif; + closure->user_data = user_data; + closure->fun = fun; + + return FFI_OK; +} + + diff --git a/native/libffi/src/csky/ffitarget.h b/native/libffi/src/csky/ffitarget.h new file mode 100644 index 0000000000..f770aac66f --- /dev/null +++ b/native/libffi/src/csky/ffitarget.h @@ -0,0 +1,63 @@ +/* -----------------------------------------------------------------*-C-*- + ffitarget.h - Copyright (c) 2012 Anthony Green + Copyright (c) 2010 CodeSourcery + Copyright (c) 1996-2003 Red Hat, Inc. + + Target configuration macros for CSKY. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + ----------------------------------------------------------------------- */ + +#ifndef LIBFFI_TARGET_H +#define LIBFFI_TARGET_H + +#ifndef LIBFFI_H +#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." +#endif + +#ifndef LIBFFI_ASM +typedef unsigned long ffi_arg; +typedef signed long ffi_sarg; + +typedef enum ffi_abi { + FFI_FIRST_ABI = 0, + FFI_SYSV, + FFI_LAST_ABI, + FFI_DEFAULT_ABI = FFI_SYSV, +} ffi_abi; +#endif + +#ifdef __CSKYABIV2__ +#define FFI_ASM_ARGREG_SIZE 16 +#define TRAMPOLINE_SIZE 16 +#define FFI_TRAMPOLINE_SIZE 24 +#else +#define FFI_ASM_ARGREG_SIZE 24 +#define TRAMPOLINE_SIZE 20 +#define FFI_TRAMPOLINE_SIZE 28 +#endif + +/* ---- Definitions for closures ----------------------------------------- */ + +#define FFI_CLOSURES 1 +#define FFI_NATIVE_RAW_API 0 +#endif diff --git a/native/libffi/src/csky/sysv.S b/native/libffi/src/csky/sysv.S new file mode 100644 index 0000000000..21670bfd3d --- /dev/null +++ b/native/libffi/src/csky/sysv.S @@ -0,0 +1,371 @@ +/* ----------------------------------------------------------------------- + sysv.S + + CSKY Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#define LIBFFI_ASM +#include +#include + +.macro CSKY_FUNC_START name + .text + .align 2 + .globl \name + .type \name, @function + \name: +.endm + +#ifdef __CSKYABIV2__ + + /* + * a0: fn + * a1: &ecif + * a2: cif->bytes + * a3: fig->flags + * sp+0: ecif.rvalue + */ +CSKY_FUNC_START ffi_call_SYSV + /* Save registers */ + .cfi_startproc + subi sp, 28 + .cfi_def_cfa_offset 28 + stw a0, (sp, 0x0) + .cfi_offset 0, -28 + stw a1, (sp, 0x4) + .cfi_offset 1, -24 + stw a2, (sp, 0x8) + .cfi_offset 2, -20 + stw a3, (sp, 0xC) + .cfi_offset 3, -16 + stw l0, (sp, 0x10) + .cfi_offset 4, -12 + stw l1, (sp, 0x14) + .cfi_offset 5, -8 + stw lr, (sp, 0x18) + .cfi_offset 15, -4 + + mov l0, sp + .cfi_def_cfa_register 4 + + /* Make room for all of the new args. */ + subu sp, sp, a2 + + /* Place all of the ffi_prep_args in position */ + mov a0, sp + /* a1 already set */ + + /* Call ffi_prep_args(stack, &ecif) */ + jsri ffi_prep_args + + /* move first 4 parameters in registers */ + ldw a0, (sp, 0x0) + ldw a1, (sp, 0x4) + ldw a2, (sp, 0x8) + ldw a3, (sp, 0xC) + + /* and adjust stack */ + subu lr, l0, sp /* cif->bytes == l0 - sp */ + cmphsi lr, 16 + movi l1, 16 + movt lr, l1 + addu sp, sp, lr + + ldw l1, (l0, 0) /* load fn() in advance */ + + /* call (fn) (...) */ + jsr l1 + + /* Remove the space we pushed for the args */ + mov sp, l0 + + /* Load r2 with the pointer to storage for the return value */ + ldw a2, (sp, 0x1C) + + /* Load r3 with the return type code */ + ldw a3, (sp, 0xC) + + /* If the return value pointer is NULL, assume no return value. */ + cmpnei a2, 0 + bf .Lepilogue + + cmpnei a3, FFI_TYPE_STRUCT + bf .Lepilogue + + /* return INT64 */ + cmpnei a3, FFI_TYPE_SINT64 + bt .Lretint + /* stw a0, (a2, 0x0) at .Lretint */ + stw a1, (a2, 0x4) + +.Lretint: + /* return INT */ + stw a0, (a2, 0x0) + +.Lepilogue: + ldw a0, (sp, 0x0) + ldw a1, (sp, 0x4) + ldw a2, (sp, 0x8) + ldw a3, (sp, 0xC) + ldw l0, (sp, 0x10) + ldw l1, (sp, 0x14) + ldw lr, (sp, 0x18) + addi sp, sp, 28 + rts + .cfi_endproc + .size ffi_call_SYSV, .-ffi_call_SYSV + + + /* + * unsigned int FFI_HIDDEN + * ffi_closure_SYSV_inner (closure, respp, args) + * ffi_closure *closure; + * void **respp; + * void *args; + */ +CSKY_FUNC_START ffi_closure_SYSV + .cfi_startproc + mov a2, sp + addi a1, sp, 16 + subi sp, sp, 24 + .cfi_def_cfa_offset 40 + stw a1, (sp, 0x10) + .cfi_offset 1, -24 + stw lr, (sp, 0x14) + .cfi_offset 15, -20 + stw sp, (sp, 0x8) + addi a1, sp, 8 + jsri ffi_closure_SYSV_inner + ldw a0, (sp, 0x0) + /* + * if FFI_TYPE_SINT64, need a1. + * if FFI_TYPE_INT, ignore a1. + */ + ldw a1, (sp, 0x4) + + ldw lr, (sp, 0x14) + addi sp, sp, 40 + rts + .cfi_endproc + .size ffi_closure_SYSV, .-ffi_closure_SYSV + +CSKY_FUNC_START ffi_csky_trampoline + subi sp, sp, 16 + stw a0, (sp, 0x0) + stw a1, (sp, 0x4) + stw a2, (sp, 0x8) + stw a3, (sp, 0xC) + lrw a0, [.Lctx] + lrw a1, [.Lfun] + jmp a1 +.Lctx: + mov a0, a0 + mov a0, a0 +.Lfun: + + .size ffi_csky_trampoline, .-ffi_csky_trampoline + +CSKY_FUNC_START ffi_csky_cacheflush + mov t0, r7 + movi r7, 123 + trap 0 + mov r7, t0 + rts + + .size ffi_csky_cacheflush, .-ffi_csky_cacheflush + +#else /* !__CSKYABIV2__ */ + + /* + * a0: fn + * a1: &ecif + * a2: cif->bytes + * a3: fig->flags + * a4: ecif.rvalue + */ +CSKY_FUNC_START ffi_call_SYSV + /* Save registers */ + .cfi_startproc + subi sp, 32 + subi sp, 8 + .cfi_def_cfa_offset 40 + stw a0, (sp, 0x0) + .cfi_offset 2, -40 + stw a1, (sp, 0x4) + .cfi_offset 3, -36 + stw a2, (sp, 0x8) + .cfi_offset 4, -32 + stw a3, (sp, 0xC) + .cfi_offset 5, -28 + stw a4, (sp, 0x10) + .cfi_offset 6, -24 + stw a5, (sp, 0x14) + .cfi_offset 7, -20 + stw l0, (sp, 0x18) + .cfi_offset 8, -16 + stw l1, (sp, 0x1C) + .cfi_offset 9, -12 + stw lr, (sp, 0x20) + .cfi_offset 15, -8 + + mov l0, sp + .cfi_def_cfa_register 8 + + /* Make room for all of the new args. */ + subu sp, sp, a2 + + /* Place all of the ffi_prep_args in position */ + mov a0, sp + /* a1 already set */ + + /* Call ffi_prep_args(stack, &ecif) */ + jsri ffi_prep_args + + /* move first 4 parameters in registers */ + ldw a0, (sp, 0x0) + ldw a1, (sp, 0x4) + ldw a2, (sp, 0x8) + ldw a3, (sp, 0xC) + ldw a4, (sp, 0x10) + ldw a5, (sp, 0x14) + + /* and adjust stack */ + mov lr, l0 + subu lr, sp /* cif->bytes == l0 - sp */ + movi l1, 24 + cmphs lr, l1 + movt lr, l1 + addu sp, sp, lr + + ldw l1, (l0, 0) /* load fn() in advance */ + + /* call (fn) (...) */ + jsr l1 + + /* Remove the space we pushed for the args */ + mov sp, l0 + + /* Load r2 with the pointer to storage for the return value */ + ldw a2, (sp, 0x10) + + /* Load r3 with the return type code */ + ldw a3, (sp, 0xC) + + /* If the return value pointer is NULL, assume no return value. */ + cmpnei a2, 0 + bf .Lepilogue + + cmpnei a3, FFI_TYPE_STRUCT + bf .Lepilogue + + /* return INT64 */ + cmpnei a3, FFI_TYPE_SINT64 + bt .Lretint + /* stw a0, (a2, 0x0) at .Lretint */ + stw a1, (a2, 0x4) + +.Lretint: + /* return INT */ + stw a0, (a2, 0x0) + +.Lepilogue: + ldw a0, (sp, 0x0) + ldw a1, (sp, 0x4) + ldw a2, (sp, 0x8) + ldw a3, (sp, 0xC) + ldw a4, (sp, 0x10) + ldw a5, (sp, 0x14) + ldw l0, (sp, 0x18) + ldw l1, (sp, 0x1C) + ldw lr, (sp, 0x20) + addi sp, sp, 32 + addi sp, sp, 8 + rts + .cfi_endproc + + .size ffi_call_SYSV, .-ffi_call_SYSV + + + /* + * unsigned int FFI_HIDDEN + * ffi_closure_SYSV_inner (closure, respp, args) + * ffi_closure *closure; + * void **respp; + * void *args; + */ +CSKY_FUNC_START ffi_closure_SYSV + .cfi_startproc + mov a2, sp + mov a1, sp + addi a1, 24 + subi sp, sp, 24 + .cfi_def_cfa_offset 48 + stw a1, (sp, 0x10) + .cfi_offset 3, -32 + stw lr, (sp, 0x14) + .cfi_offset 15, -28 + stw sp, (sp, 0x8) + mov a1, sp + addi a1, 8 + jsri ffi_closure_SYSV_inner + ldw a0, (sp, 0x0) + /* + * if FFI_TYPE_SINT64, need a1. + * if FFI_TYPE_INT, ignore a1. + */ + ldw a1, (sp, 0x4) + + ldw lr, (sp, 0x14) + addi sp, sp, 24 + addi sp, sp, 24 + rts + .cfi_endproc + + .size ffi_closure_SYSV, .-ffi_closure_SYSV + +CSKY_FUNC_START ffi_csky_trampoline + subi sp, 24 + stw a0, (sp, 0x0) + stw a1, (sp, 0x4) + stw a2, (sp, 0x8) + stw a3, (sp, 0xC) + stw a4, (sp, 0x10) + stw a5, (sp, 0x14) + lrw a0, [.Lctx] + lrw a1, [.Lfun] + jmp a1 +.Lctx: + mov a0, a0 + mov a0, a0 +.Lfun: + + .size ffi_csky_trampoline, .-ffi_csky_trampoline + +CSKY_FUNC_START ffi_csky_cacheflush + lrw r1, 123 + trap 0 + rts + + .size ffi_csky_cacheflush, .-ffi_csky_cacheflush + +#endif /* __CSKYABIV2__ */ diff --git a/native/libffi/src/dlmalloc.c b/native/libffi/src/dlmalloc.c index 3f8f1ee7ff..31d03d3be7 100644 --- a/native/libffi/src/dlmalloc.c +++ b/native/libffi/src/dlmalloc.c @@ -438,6 +438,11 @@ DEFAULT_MMAP_THRESHOLD default: 256K */ +#if defined __linux__ && !defined _GNU_SOURCE +/* mremap() on Linux requires this via sys/mman.h */ +#define _GNU_SOURCE 1 +#endif + #ifndef WIN32 #ifdef _WIN32 #define WIN32 1 @@ -2291,7 +2296,7 @@ static size_t traverse_and_check(mstate m); #define treebin_at(M,i) (&((M)->treebins[i])) /* assign tree index for size S to variable I */ -#if defined(__GNUC__) && defined(i386) +#if defined(__GNUC__) && defined(__i386__) #define compute_tree_index(S, I)\ {\ size_t X = S >> TREEBIN_SHIFT;\ @@ -2356,7 +2361,7 @@ static size_t traverse_and_check(mstate m); /* index corresponding to given bit */ -#if defined(__GNUC__) && defined(i386) +#if defined(__GNUC__) && defined(__i386__) #define compute_bit2idx(X, I)\ {\ unsigned int J;\ @@ -2366,7 +2371,7 @@ static size_t traverse_and_check(mstate m); #else /* GNUC */ #if USE_BUILTIN_FFS -#define compute_bit2idx(X, I) I = ffs(X)-1 +#define compute_bit2idx(X, I) I = __builtin_ffs(X)-1 #else /* USE_BUILTIN_FFS */ #define compute_bit2idx(X, I)\ diff --git a/native/libffi/src/frv/ffi.c b/native/libffi/src/frv/ffi.c index 5698c89c35..ed1c65a1a3 100644 --- a/native/libffi/src/frv/ffi.c +++ b/native/libffi/src/frv/ffi.c @@ -107,7 +107,7 @@ void *ffi_prep_args(char *stack, extended_cif *ecif) count += z; } - return (stack + ((count > 24) ? 24 : ALIGN_DOWN(count, 8))); + return (stack + ((count > 24) ? 24 : FFI_ALIGN_DOWN(count, 8))); } /* Perform machine dependent cif processing */ @@ -118,7 +118,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) else cif->flags = cif->rtype->size; - cif->bytes = ALIGN (cif->bytes, 8); + cif->bytes = FFI_ALIGN (cif->bytes, 8); return FFI_OK; } diff --git a/native/libffi/src/ia64/ffi.c b/native/libffi/src/ia64/ffi.c index b77a836ddc..b1d04c3e74 100644 --- a/native/libffi/src/ia64/ffi.c +++ b/native/libffi/src/ia64/ffi.c @@ -220,8 +220,8 @@ hfa_element_type (ffi_type *type, int nested) /* Perform machine dependent cif processing. */ -ffi_status -ffi_prep_cif_machdep(ffi_cif *cif) +static ffi_status +ffi_prep_cif_machdep_core(ffi_cif *cif) { int flags; @@ -271,6 +271,22 @@ ffi_prep_cif_machdep(ffi_cif *cif) return FFI_OK; } +ffi_status +ffi_prep_cif_machdep(ffi_cif *cif) +{ + cif->nfixedargs = cif->nargs; + return ffi_prep_cif_machdep_core(cif); +} + +ffi_status +ffi_prep_cif_machdep_var(ffi_cif *cif, + unsigned int nfixedargs, + unsigned int ntotalargs MAYBE_UNUSED) +{ + cif->nfixedargs = nfixedargs; + return ffi_prep_cif_machdep_core(cif); +} + extern int ffi_call_unix (struct ia64_args *, PTR64, void (*)(void), UINT64); void @@ -454,10 +470,11 @@ ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack, ffi_cif *cif; void **avalue; ffi_type **p_arg; - long i, avn, gpcount, fpcount; + long i, avn, gpcount, fpcount, nfixedargs; cif = closure->cif; avn = cif->nargs; + nfixedargs = cif->nfixedargs; avalue = alloca (avn * sizeof (void *)); /* If the structure return value is passed in memory get that location @@ -468,6 +485,7 @@ ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack, gpcount = fpcount = 0; for (i = 0, p_arg = cif->arg_types; i < avn; i++, p_arg++) { + int named = i < nfixedargs; switch ((*p_arg)->type) { case FFI_TYPE_SINT8: @@ -491,7 +509,7 @@ ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack, break; case FFI_TYPE_FLOAT: - if (gpcount < 8 && fpcount < 8) + if (named && gpcount < 8 && fpcount < 8) { fpreg *addr = &stack->fp_regs[fpcount++]; float result; @@ -505,7 +523,7 @@ ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack, break; case FFI_TYPE_DOUBLE: - if (gpcount < 8 && fpcount < 8) + if (named && gpcount < 8 && fpcount < 8) { fpreg *addr = &stack->fp_regs[fpcount++]; double result; @@ -521,7 +539,7 @@ ffi_closure_unix_inner (ffi_closure *closure, struct ia64_args *stack, case FFI_TYPE_LONGDOUBLE: if (gpcount & 1) gpcount++; - if (LDBL_MANT_DIG == 64 && gpcount < 8 && fpcount < 8) + if (LDBL_MANT_DIG == 64 && named && gpcount < 8 && fpcount < 8) { fpreg *addr = &stack->fp_regs[fpcount++]; __float80 result; diff --git a/native/libffi/src/ia64/ffitarget.h b/native/libffi/src/ia64/ffitarget.h index e68cea6154..fd5b9a0ee1 100644 --- a/native/libffi/src/ia64/ffitarget.h +++ b/native/libffi/src/ia64/ffitarget.h @@ -50,6 +50,7 @@ typedef enum ffi_abi { #define FFI_TRAMPOLINE_SIZE 24 /* Really the following struct, which */ /* can be interpreted as a C function */ /* descriptor: */ +#define FFI_TARGET_SPECIFIC_VARIADIC 1 +#define FFI_EXTRA_CIF_FIELDS unsigned nfixedargs #endif - diff --git a/native/libffi/src/ia64/unix.S b/native/libffi/src/ia64/unix.S index 4d2a86d421..e2547e02b3 100644 --- a/native/libffi/src/ia64/unix.S +++ b/native/libffi/src/ia64/unix.S @@ -175,7 +175,6 @@ ffi_call_unix: ;; .Lst_small_struct: - add sp = -16, sp cmp.lt p6, p0 = 8, in3 cmp.lt p7, p0 = 16, in3 cmp.lt p8, p0 = 24, in3 @@ -191,6 +190,12 @@ ffi_call_unix: (p8) st8 [r18] = r11 mov out1 = sp mov out2 = in3 + ;; + // ia64 software calling convention requires + // top 16 bytes of stack to be scratch space + // PLT resolver uses that scratch space at + // 'memcpy' symbol reolution time + add sp = -16, sp br.call.sptk.many b0 = memcpy# ;; mov ar.pfs = loc0 @@ -529,6 +534,7 @@ ffi_closure_unix: data8 @pcrel(.Lst_int64) // FFI_TYPE_SINT64 data8 @pcrel(.Lst_void) // FFI_TYPE_STRUCT data8 @pcrel(.Lst_int64) // FFI_TYPE_POINTER + data8 @pcrel(.Lst_void) // FFI_TYPE_COMPLEX (not implemented) data8 @pcrel(.Lst_small_struct) // FFI_IA64_TYPE_SMALL_STRUCT data8 @pcrel(.Lst_hfa_float) // FFI_IA64_TYPE_HFA_FLOAT data8 @pcrel(.Lst_hfa_double) // FFI_IA64_TYPE_HFA_DOUBLE @@ -550,6 +556,7 @@ ffi_closure_unix: data8 @pcrel(.Lld_int) // FFI_TYPE_SINT64 data8 @pcrel(.Lld_void) // FFI_TYPE_STRUCT data8 @pcrel(.Lld_int) // FFI_TYPE_POINTER + data8 @pcrel(.Lld_void) // FFI_TYPE_COMPLEX (not implemented) data8 @pcrel(.Lld_small_struct) // FFI_IA64_TYPE_SMALL_STRUCT data8 @pcrel(.Lld_hfa_float) // FFI_IA64_TYPE_HFA_FLOAT data8 @pcrel(.Lld_hfa_double) // FFI_IA64_TYPE_HFA_DOUBLE diff --git a/native/libffi/src/java_raw_api.c b/native/libffi/src/java_raw_api.c index 127123d5bc..114d3e47fc 100644 --- a/native/libffi/src/java_raw_api.c +++ b/native/libffi/src/java_raw_api.c @@ -114,7 +114,7 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args) default: *args = raw; raw += - ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw); + FFI_ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw); } } @@ -142,7 +142,7 @@ ffi_java_raw_to_ptrarray (ffi_cif *cif, ffi_java_raw *raw, void **args) #else /* FFI_SIZEOF_JAVA_RAW != 8 */ *args = (void*) raw; raw += - ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw); + FFI_ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw); #endif /* FFI_SIZEOF_JAVA_RAW == 8 */ } @@ -234,7 +234,7 @@ ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw) #else memcpy ((void*) raw->data, (void*)*args, (*tp)->size); raw += - ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw); + FFI_ALIGN ((*tp)->size, sizeof(ffi_java_raw)) / sizeof(ffi_java_raw); #endif } } diff --git a/native/libffi/src/kvx/asm.h b/native/libffi/src/kvx/asm.h new file mode 100644 index 0000000000..4edba410d8 --- /dev/null +++ b/native/libffi/src/kvx/asm.h @@ -0,0 +1,5 @@ +/* args are passed on registers from r0 up to r11 => 12*8 bytes */ +#define REG_ARGS_SIZE (12*8) +#define KVX_REGISTER_SIZE (8) +#define KVX_ABI_SLOT_SIZE (KVX_REGISTER_SIZE) +#define KVX_ABI_MAX_AGGREGATE_IN_REG_SIZE (4*KVX_ABI_SLOT_SIZE) diff --git a/native/libffi/src/kvx/ffi.c b/native/libffi/src/kvx/ffi.c new file mode 100644 index 0000000000..58f6aef5ca --- /dev/null +++ b/native/libffi/src/kvx/ffi.c @@ -0,0 +1,273 @@ +/* Copyright (c) 2020 Kalray + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +``Software''), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#if defined(__kvx__) +#include +#include +#include +#include +#include +#include "ffi_common.h" +#include "asm.h" + +#define ALIGN(x, a) ALIGN_MASK(x, (typeof(x))(a) - 1) +#define ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) +#define KVX_ABI_STACK_ALIGNMENT (32) +#define KVX_ABI_STACK_ARG_ALIGNMENT (8) +#define max(a,b) ((a) > (b) ? (a) : (b)) + +#ifdef FFI_DEBUG +#define DEBUG_PRINT(...) do{ fprintf( stderr, __VA_ARGS__ ); } while(0) +#else +#define DEBUG_PRINT(...) +#endif + +struct ret_value { + unsigned long int r0; + unsigned long int r1; + unsigned long int r2; + unsigned long int r3; +}; + +extern struct ret_value ffi_call_SYSV(unsigned total_size, + unsigned size, + extended_cif *ecif, + unsigned *rvalue_addr, + void *fn, + unsigned int_ext_method); + +/* Perform machine dependent cif processing */ +ffi_status ffi_prep_cif_machdep(ffi_cif *cif) +{ + cif->flags = cif->rtype->size; + return FFI_OK; +} + +/* ffi_prep_args is called by the assembly routine once stack space + has been allocated for the function's arguments */ + +void *ffi_prep_args(char *stack, unsigned int arg_slots_size, extended_cif *ecif) +{ + char *stacktemp = stack; + char *current_arg_passed_by_value = stack + arg_slots_size; + int i, s; + ffi_type **arg; + int count = 0; + ffi_cif *cif = ecif->cif; + void **argv = ecif->avalue; + + arg = cif->arg_types; + + DEBUG_PRINT("stack: %p\n", stack); + DEBUG_PRINT("arg_slots_size: %u\n", arg_slots_size); + DEBUG_PRINT("current_arg_passed_by_value: %p\n", current_arg_passed_by_value); + DEBUG_PRINT("ecif: %p\n", ecif); + DEBUG_PRINT("ecif->avalue: %p\n", ecif->avalue); + + for (i = 0; i < cif->nargs; i++) { + + s = KVX_ABI_SLOT_SIZE; + switch((*arg)->type) { + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT16: + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: + case FFI_TYPE_POINTER: + DEBUG_PRINT("INT64/32/16/8/FLOAT/DOUBLE or POINTER @%p\n", stack); + *(uint64_t *) stack = *(uint64_t *)(* argv); + break; + + case FFI_TYPE_COMPLEX: + if ((*arg)->size == 8) + *(_Complex float *) stack = *(_Complex float *)(* argv); + else if ((*arg)->size == 16) { + *(_Complex double *) stack = *(_Complex double *)(* argv); + s = 16; + } else + abort(); + break; + case FFI_TYPE_STRUCT: { + char *value; + unsigned int written_size = 0; + DEBUG_PRINT("struct by value @%p\n", stack); + if ((*arg)->size > KVX_ABI_MAX_AGGREGATE_IN_REG_SIZE) { + DEBUG_PRINT("big struct\n"); + *(uint64_t *) stack = (uintptr_t)current_arg_passed_by_value; + value = current_arg_passed_by_value; + current_arg_passed_by_value += (*arg)->size; + written_size = KVX_ABI_SLOT_SIZE; + } else { + value = stack; + written_size = (*arg)->size; + } + memcpy(value, *argv, (*arg)->size); + s = ALIGN(written_size, KVX_ABI_STACK_ARG_ALIGNMENT); + break; + } + default: + printf("Error: unsupported arg type %d\n", (*arg)->type); + abort(); + break; + + } + stack += s; + count += s; + argv++; + arg++; + } +#ifdef FFI_DEBUG + FFI_ASSERT(((intptr_t)(stacktemp + REG_ARGS_SIZE) & (KVX_ABI_STACK_ALIGNMENT-1)) == 0); +#endif + return stacktemp + REG_ARGS_SIZE; +} + +/* Perform machine dependent cif processing when we have a variadic function */ + +ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs, + unsigned int ntotalargs) +{ + cif->flags = cif->rtype->size; + return FFI_OK; +} + +static unsigned long handle_small_int_ext(kvx_intext_method *int_ext_method, + const ffi_type *rtype) +{ + switch (rtype->type) { + case FFI_TYPE_SINT8: + *int_ext_method = KVX_RET_SXBD; + return KVX_REGISTER_SIZE; + + case FFI_TYPE_SINT16: + *int_ext_method = KVX_RET_SXHD; + return KVX_REGISTER_SIZE; + + case FFI_TYPE_SINT32: + *int_ext_method = KVX_RET_SXWD; + return KVX_REGISTER_SIZE; + + case FFI_TYPE_UINT8: + *int_ext_method = KVX_RET_ZXBD; + return KVX_REGISTER_SIZE; + + case FFI_TYPE_UINT16: + *int_ext_method = KVX_RET_ZXHD; + return KVX_REGISTER_SIZE; + + case FFI_TYPE_UINT32: + *int_ext_method = KVX_RET_ZXWD; + return KVX_REGISTER_SIZE; + + default: + *int_ext_method = KVX_RET_NONE; + return rtype->size; + } +} + +void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +{ + int i; + unsigned long int slot_fitting_args_size = 0; + unsigned long int total_size = 0; + unsigned long int big_struct_size = 0; + kvx_intext_method int_extension_method; + ffi_type **arg; + struct ret_value local_rvalue = {0}; + size_t wb_size; + + + /* Calculate size to allocate on stack */ + for (i = 0, arg = cif->arg_types; i < cif->nargs; i++, arg++) { + DEBUG_PRINT("argument %d, type %d, size %lu\n", i, (*arg)->type, (*arg)->size); + if (((*arg)->type == FFI_TYPE_STRUCT) || ((*arg)->type == FFI_TYPE_COMPLEX)) { + if ((*arg)->size <= KVX_ABI_MAX_AGGREGATE_IN_REG_SIZE) { + slot_fitting_args_size += ALIGN((*arg)->size, KVX_ABI_SLOT_SIZE); + } else { + slot_fitting_args_size += KVX_ABI_SLOT_SIZE; /* aggregate passed by reference */ + big_struct_size += ALIGN((*arg)->size, KVX_ABI_SLOT_SIZE); + } + } else if ((*arg)->size <= KVX_ABI_SLOT_SIZE) { + slot_fitting_args_size += KVX_ABI_SLOT_SIZE; + } else { + printf("Error: unsupported arg size %ld arg type %d\n", (*arg)->size, (*arg)->type); + abort(); /* should never happen? */ + } + } + + extended_cif ecif; + ecif.cif = cif; + ecif.avalue = avalue; + ecif.rvalue = rvalue; + + /* This implementation allocates anyway for all register based args */ + slot_fitting_args_size = max(slot_fitting_args_size, REG_ARGS_SIZE); + total_size = slot_fitting_args_size + big_struct_size; + total_size = ALIGN(total_size, KVX_ABI_STACK_ALIGNMENT); + + /* wb_size: write back size, the size we will need to write back to user + * provided buffer. In theory it should always be cif->flags which is + * cif->rtype->size. But libffi API mandates that for integral types + * of size <= system register size, then we *MUST* write back + * the size of system register size. + * in our case, if size <= 8 bytes we must write back 8 bytes. + * floats, complex and structs are not affected, only integrals. + */ + wb_size = handle_small_int_ext(&int_extension_method, cif->rtype); + + switch (cif->abi) { + case FFI_SYSV: + DEBUG_PRINT("total_size: %lu\n", total_size); + DEBUG_PRINT("slot fitting args size: %lu\n", slot_fitting_args_size); + DEBUG_PRINT("rvalue: %p\n", rvalue); + DEBUG_PRINT("fn: %p\n", fn); + DEBUG_PRINT("rsize: %u\n", cif->flags); + DEBUG_PRINT("wb_size: %u\n", wb_size); + DEBUG_PRINT("int_extension_method: %u\n", int_extension_method); + local_rvalue = ffi_call_SYSV(total_size, slot_fitting_args_size, + &ecif, rvalue, fn, int_extension_method); + if ((cif->flags <= KVX_ABI_MAX_AGGREGATE_IN_REG_SIZE) + && (cif->rtype->type != FFI_TYPE_VOID)) + memcpy(rvalue, &local_rvalue, wb_size); + break; + default: + abort(); + break; + } +} + +/* Closures not supported yet */ +ffi_status +ffi_prep_closure_loc (ffi_closure* closure, + ffi_cif* cif, + void (*fun)(ffi_cif*,void*,void**,void*), + void *user_data, + void *codeloc) +{ + return FFI_BAD_ABI; +} + +#endif /* (__kvx__) */ diff --git a/native/libffi/src/kvx/ffitarget.h b/native/libffi/src/kvx/ffitarget.h new file mode 100644 index 0000000000..8df8735e3f --- /dev/null +++ b/native/libffi/src/kvx/ffitarget.h @@ -0,0 +1,75 @@ +/* ----------------------------------------------------------------------- + ffitarget.h - Copyright (c) 2020 Kalray + + KVX Target configuration macros + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#ifndef LIBFFI_TARGET_H +#define LIBFFI_TARGET_H + +#ifndef LIBFFI_H +#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." +#endif + +/* ---- System specific configurations ----------------------------------- */ + +#ifndef LIBFFI_ASM +typedef unsigned long ffi_arg; +typedef signed long ffi_sarg; + +typedef enum ffi_abi { + FFI_FIRST_ABI = 0, + FFI_SYSV, + FFI_LAST_ABI, + FFI_DEFAULT_ABI = FFI_SYSV +} ffi_abi; + +/* Those values are set depending on return type + * they are used in the assembly code in sysv.S + */ +typedef enum kvx_intext_method { + KVX_RET_NONE = 0, + KVX_RET_SXBD = 1, + KVX_RET_SXHD = 2, + KVX_RET_SXWD = 3, + KVX_RET_ZXBD = 4, + KVX_RET_ZXHD = 5, + KVX_RET_ZXWD = 6 +} kvx_intext_method; + +#endif + +/* ---- Definitions for closures ----------------------------------------- */ + +/* This is only to allow Python to compile + * but closures are not supported yet + */ +#define FFI_CLOSURES 1 +#define FFI_TRAMPOLINE_SIZE 0 + +#define FFI_NATIVE_RAW_API 0 +#define FFI_TARGET_SPECIFIC_VARIADIC 1 +#define FFI_TARGET_HAS_COMPLEX_TYPE + +#endif + diff --git a/native/libffi/src/kvx/sysv.S b/native/libffi/src/kvx/sysv.S new file mode 100644 index 0000000000..952afc7063 --- /dev/null +++ b/native/libffi/src/kvx/sysv.S @@ -0,0 +1,127 @@ +/* Copyright (c) 2020 Kalray + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +``Software''), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#if defined(__kvx__) +#define LIBFFI_ASM +#include +#include +#include +#include + +.text +.global ffi_call_SYSV +.type ffi_call_SYSV, @function +.type ffi_prep_args, @function +.align 8 + +/* ffi_call_SYSV + + r0: total size to allocate on stack + r1: size of arg slots + r2: extended cif structure, DO NOT REMOVE: it is used by ffi_prep_args() + r3: return value address + r4: function to call + r5: integer sign extension method to be used +*/ +ffi_call_SYSV: + addd $r12 = $r12, -64 + so (-32)[$r12] = $r20r21r22r23 + ;; + sd (0)[$r12] = $r24 + ;; + get $r23 = $ra + copyd $r20 = $r12 + sbfd $r12 = $r0, $r12 + ;; + copyd $r0 = $r12 + copyd $r21 = $r3 + copyd $r22 = $r4 + copyd $r24 = $r5 + call ffi_prep_args + ;; + lo $r8r9r10r11 = (64)[$r12] + ;; + lo $r4r5r6r7 = (32)[$r12] + ;; + lo $r0r1r2r3 = (0)[$r12] + copyd $r12 = $r0 + /* $r15 is the register used by the ABI to return big (>32 bytes) + * structs by value. + * It is also referred to as the "struct register" in the ABI. + */ + copyd $r15 = $r21 + icall $r22 + ;; + pcrel $r4 = @pcrel(.Ltable) + cb.deqz $r24 ? .Lend + ;; + addx8d $r24 = $r24, $r4 + ;; + igoto $r24 + ;; +.Ltable: +0: /* we should never arrive here */ + goto .Lerror + nop + ;; +1: /* Sign extend byte to double */ + sxbd $r0 = $r0 + goto .Lend + ;; +2: /* Sign extend half to double */ + sxhd $r0 = $r0 + goto .Lend + ;; +3: /* Sign extend word to double */ + sxwd $r0 = $r0 + goto .Lend + ;; +4: /* Zero extend byte to double */ + zxbd $r0 = $r0 + goto .Lend + ;; +5: /* Zero extend half to double */ + zxhd $r0 = $r0 + goto .Lend + ;; +6: /* Zero extend word to double */ + zxwd $r0 = $r0 + /* Fallthrough to .Lend */ + ;; +.Lend: + ld $r24 = (0)[$r12] + ;; + set $ra = $r23 + lo $r20r21r22r23 = (32)[$r20] + addd $r12 = $r20, 64 + ;; + ret + ;; +.Lerror: + errop + ;; + +#endif /* __kvx__ */ + +#if defined __ELF__ && defined __linux__ + .section .note.GNU-stack,"",%progbits +#endif + diff --git a/native/libffi/src/m32r/ffi.c b/native/libffi/src/m32r/ffi.c index 300006349b..ab8fc4e48a 100644 --- a/native/libffi/src/m32r/ffi.c +++ b/native/libffi/src/m32r/ffi.c @@ -61,7 +61,7 @@ void ffi_prep_args(char *stack, extended_cif *ecif) /* Align if necessary. */ if (((*p_arg)->alignment - 1) & (unsigned) argp) - argp = (char *) ALIGN (argp, (*p_arg)->alignment); + argp = (char *) FFI_ALIGN (argp, (*p_arg)->alignment); if (avn != 0) { diff --git a/native/libffi/src/m68k/ffi.c b/native/libffi/src/m68k/ffi.c index 0dee9383a8..033018480c 100644 --- a/native/libffi/src/m68k/ffi.c +++ b/native/libffi/src/m68k/ffi.c @@ -105,7 +105,7 @@ ffi_prep_args (void *stack, extended_cif *ecif) /* Align if necessary. */ if ((sizeof(int) - 1) & z) - z = ALIGN(z, sizeof(int)); + z = FFI_ALIGN(z, sizeof(int)); } p_argv++; @@ -297,7 +297,7 @@ ffi_prep_incoming_args_SYSV (char *stack, void **avalue, ffi_cif *cif) /* Align if necessary */ if ((sizeof(int) - 1) & z) - z = ALIGN(z, sizeof(int)); + z = FFI_ALIGN(z, sizeof(int)); } p_argv++; diff --git a/native/libffi/src/m68k/sysv.S b/native/libffi/src/m68k/sysv.S index ec2b14f3d9..ea40f1100b 100644 --- a/native/libffi/src/m68k/sysv.S +++ b/native/libffi/src/m68k/sysv.S @@ -3,7 +3,7 @@ sysv.S - Copyright (c) 2012 Alan Hourihane Copyright (c) 1998, 2012 Andreas Schwab Copyright (c) 2008 Red Hat, Inc. - Copyright (c) 2012 Thorsten Glaser + Copyright (c) 2012, 2016 Thorsten Glaser m68k Foreign Function Interface @@ -72,6 +72,15 @@ CALLFUNC(ffi_call_SYSV): pea 4(%sp) #if !defined __PIC__ jsr CALLFUNC(ffi_prep_args) +#elif defined(__uClinux__) && defined(__ID_SHARED_LIBRARY__) + move.l _current_shared_library_a5_offset_(%a5),%a0 + move.l CALLFUNC(ffi_prep_args@GOT)(%a0),%a0 + jsr (%a0) +#elif defined(__mcoldfire__) && !defined(__mcfisab__) && !defined(__mcfisac__) + move.l #_GLOBAL_OFFSET_TABLE_@GOTPC,%a0 + lea (-6,%pc,%a0),%a0 + move.l CALLFUNC(ffi_prep_args@GOT)(%a0),%a0 + jsr (%a0) #else bsr.l CALLFUNC(ffi_prep_args@PLTPC) #endif @@ -215,6 +224,15 @@ CALLFUNC(ffi_closure_SYSV): move.l %a0,-(%sp) #if !defined __PIC__ jsr CALLFUNC(ffi_closure_SYSV_inner) +#elif defined(__uClinux__) && defined(__ID_SHARED_LIBRARY__) + move.l _current_shared_library_a5_offset_(%a5),%a0 + move.l CALLFUNC(ffi_closure_SYSV_inner@GOT)(%a0),%a0 + jsr (%a0) +#elif defined(__mcoldfire__) && !defined(__mcfisab__) && !defined(__mcfisac__) + move.l #_GLOBAL_OFFSET_TABLE_@GOTPC,%a0 + lea (-6,%pc,%a0),%a0 + move.l CALLFUNC(ffi_closure_SYSV_inner@GOT)(%a0),%a0 + jsr (%a0) #else bsr.l CALLFUNC(ffi_closure_SYSV_inner@PLTPC) #endif @@ -317,6 +335,15 @@ CALLFUNC(ffi_closure_struct_SYSV): move.l %a0,-(%sp) #if !defined __PIC__ jsr CALLFUNC(ffi_closure_SYSV_inner) +#elif defined(__uClinux__) && defined(__ID_SHARED_LIBRARY__) + move.l _current_shared_library_a5_offset_(%a5),%a0 + move.l CALLFUNC(ffi_closure_SYSV_inner@GOT)(%a0),%a0 + jsr (%a0) +#elif defined(__mcoldfire__) && !defined(__mcfisab__) && !defined(__mcfisac__) + move.l #_GLOBAL_OFFSET_TABLE_@GOTPC,%a0 + lea (-6,%pc,%a0),%a0 + move.l CALLFUNC(ffi_closure_SYSV_inner@GOT)(%a0),%a0 + jsr (%a0) #else bsr.l CALLFUNC(ffi_closure_SYSV_inner@PLTPC) #endif diff --git a/native/libffi/src/m88k/ffi.c b/native/libffi/src/m88k/ffi.c index 68df494955..a14fb20453 100644 --- a/native/libffi/src/m88k/ffi.c +++ b/native/libffi/src/m88k/ffi.c @@ -134,7 +134,11 @@ ffi_prep_args (void *stack, extended_cif *ecif) /* Enforce proper stack alignment of 64-bit types */ if (argp == stackp && a > sizeof (int)) { +<<<<<<< HEAD stackp = (char *) ALIGN(stackp, a); +======= + stackp = (char *) FFI_ALIGN(stackp, a); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 argp = stackp; } @@ -177,7 +181,11 @@ ffi_prep_args (void *stack, extended_cif *ecif) /* Align if necessary. */ if ((sizeof (int) - 1) & z) +<<<<<<< HEAD z = ALIGN(z, sizeof (int)); +======= + z = FFI_ALIGN(z, sizeof (int)); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 p_argv++; @@ -320,7 +328,11 @@ ffi_prep_closure_args_OBSD (ffi_cif *cif, void **avalue, unsigned int *regp, /* Enforce proper stack alignment of 64-bit types */ if (argp == stackp && a > sizeof (int)) { +<<<<<<< HEAD stackp = (char *) ALIGN(stackp, a); +======= + stackp = (char *) FFI_ALIGN(stackp, a); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 argp = stackp; } @@ -331,7 +343,11 @@ ffi_prep_closure_args_OBSD (ffi_cif *cif, void **avalue, unsigned int *regp, /* Align if necessary */ if ((sizeof (int) - 1) & z) +<<<<<<< HEAD z = ALIGN(z, sizeof (int)); +======= + z = FFI_ALIGN(z, sizeof (int)); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 p_argv++; diff --git a/native/libffi/src/metag/ffi.c b/native/libffi/src/metag/ffi.c index 46b383e7a3..3aecb0b811 100644 --- a/native/libffi/src/metag/ffi.c +++ b/native/libffi/src/metag/ffi.c @@ -61,7 +61,7 @@ unsigned int ffi_prep_args(char *stack, extended_cif *ecif) argp -= z; /* Align if necessary */ - argp = (char *) ALIGN_DOWN(ALIGN_DOWN(argp, (*p_arg)->alignment), 4); + argp = (char *) FFI_ALIGN_DOWN(FFI_ALIGN_DOWN(argp, (*p_arg)->alignment), 4); if (z < sizeof(int)) { z = sizeof(int); @@ -93,7 +93,7 @@ unsigned int ffi_prep_args(char *stack, extended_cif *ecif) /* return the size of the arguments to be passed in registers, padded to an 8 byte boundary to preserve stack alignment */ - return ALIGN(MIN(stack - argp, 6*4), 8); + return FFI_ALIGN(MIN(stack - argp, 6*4), 8); } /* Perform machine dependent cif processing */ @@ -112,20 +112,20 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) /* Add any padding if necessary */ if (((*ptr)->alignment - 1) & bytes) - bytes = ALIGN(bytes, (*ptr)->alignment); + bytes = FFI_ALIGN(bytes, (*ptr)->alignment); - bytes += ALIGN((*ptr)->size, 4); + bytes += FFI_ALIGN((*ptr)->size, 4); } /* Ensure arg space is aligned to an 8-byte boundary */ - bytes = ALIGN(bytes, 8); + bytes = FFI_ALIGN(bytes, 8); /* Make space for the return structure pointer */ if (cif->rtype->type == FFI_TYPE_STRUCT) { bytes += sizeof(void*); /* Ensure stack is aligned to an 8-byte boundary */ - bytes = ALIGN(bytes, 8); + bytes = FFI_ALIGN(bytes, 8); } cif->bytes = bytes; @@ -319,7 +319,7 @@ static void ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, if (alignment < 4) alignment = 4; if ((alignment - 1) & (unsigned)argp) - argp = (char *) ALIGN(argp, alignment); + argp = (char *) FFI_ALIGN(argp, alignment); z = (*p_arg)->size; *p_argv = (void*) argp; diff --git a/native/libffi/src/microblaze/ffi.c b/native/libffi/src/microblaze/ffi.c index ea962ea483..df6e33c97d 100644 --- a/native/libffi/src/microblaze/ffi.c +++ b/native/libffi/src/microblaze/ffi.c @@ -35,7 +35,7 @@ extern void ffi_closure_SYSV(void); #define WORD_SIZE sizeof(unsigned int) #define ARGS_REGISTER_SIZE (WORD_SIZE * 6) -#define WORD_ALIGN(x) ALIGN(x, WORD_SIZE) +#define WORD_FFI_ALIGN(x) FFI_ALIGN(x, WORD_SIZE) /* ffi_prep_args is called by the assembly routine once stack space has been allocated for the function's arguments */ @@ -46,12 +46,12 @@ void ffi_prep_args(void* stack, extended_cif* ecif) void** p_argv; void* stack_args_p = stack; - p_argv = ecif->avalue; - if (ecif == NULL || ecif->cif == NULL) { return; /* no description to prepare */ } + p_argv = ecif->avalue; + if ((ecif->cif->rtype != NULL) && (ecif->cif->rtype->type == FFI_TYPE_STRUCT)) { @@ -74,7 +74,7 @@ void ffi_prep_args(void* stack, extended_cif* ecif) int type = (*p_arg)->type; void* value = p_argv[i]; char* addr = stack_args_p; - int aligned_size = WORD_ALIGN(size); + int aligned_size = WORD_FFI_ALIGN(size); /* force word alignment on the stack */ stack_args_p += aligned_size; @@ -259,7 +259,7 @@ void ffi_closure_call_SYSV(void* register_args, void* stack_args, avalue[i] = ptr; break; } - ptr += WORD_ALIGN(arg_types[i]->size); + ptr += WORD_FFI_ALIGN(arg_types[i]->size); } /* set the return type info passed back to the wrapper */ diff --git a/native/libffi/src/mips/ffi.c b/native/libffi/src/mips/ffi.c index 5d0dd70cb3..979ca49f1b 100644 --- a/native/libffi/src/mips/ffi.c +++ b/native/libffi/src/mips/ffi.c @@ -29,6 +29,7 @@ #include #include +#include #include #ifdef __GNUC__ @@ -38,7 +39,9 @@ #endif #ifndef USE__BUILTIN___CLEAR_CACHE -# if defined(__OpenBSD__) +# if defined(__FreeBSD__) +# include +# elif defined(__OpenBSD__) # include # else # include @@ -116,7 +119,7 @@ static void ffi_prep_args(char *stack, if ((a - 1) & (unsigned long) argp) { - argp = (char *) ALIGN(argp, a); + argp = (char *) FFI_ALIGN(argp, a); FIX_ARGP; } @@ -247,7 +250,7 @@ calc_n32_struct_flags(int soft_float, ffi_type *arg, while ((e = arg->elements[index])) { /* Align this object. */ - *loc = ALIGN(*loc, e->alignment); + *loc = FFI_ALIGN(*loc, e->alignment); if (e->type == FFI_TYPE_DOUBLE) { /* Already aligned to FFI_SIZEOF_ARG. */ @@ -262,7 +265,7 @@ calc_n32_struct_flags(int soft_float, ffi_type *arg, index++; } /* Next Argument register at alignment of FFI_SIZEOF_ARG. */ - *arg_reg = ALIGN(*loc, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; + *arg_reg = FFI_ALIGN(*loc, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; return flags; } @@ -322,9 +325,10 @@ calc_n32_return_struct_flags(int soft_float, ffi_type *arg) #endif /* Perform machine dependent cif processing */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) +static ffi_status ffi_prep_cif_machdep_int(ffi_cif *cif, unsigned nfixedargs) { cif->flags = 0; + cif->mips_nfixedargs = nfixedargs; #ifdef FFI_MIPS_O32 /* Set the flags necessary for O32 processing. FFI_O32_SOFT_FLOAT @@ -333,7 +337,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) if (cif->rtype->type != FFI_TYPE_STRUCT && cif->abi == FFI_O32) { - if (cif->nargs > 0) + if (cif->nargs > 0 && cif->nargs == nfixedargs) { switch ((cif->arg_types)[0]->type) { @@ -450,7 +454,9 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) while (count-- > 0 && arg_reg < 8) { type = (cif->arg_types)[index]->type; - if (soft_float) + + // Pass variadic arguments in integer registers even if they're floats + if (soft_float || index >= nfixedargs) { switch (type) { @@ -474,9 +480,9 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) break; case FFI_TYPE_LONGDOUBLE: /* Align it. */ - arg_reg = ALIGN(arg_reg, 2); + arg_reg = FFI_ALIGN(arg_reg, 2); /* Treat it as two adjacent doubles. */ - if (soft_float) + if (soft_float || index >= nfixedargs) { arg_reg += 2; } @@ -493,7 +499,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) case FFI_TYPE_STRUCT: loc = arg_reg * FFI_SIZEOF_ARG; - cif->flags += calc_n32_struct_flags(soft_float, + cif->flags += calc_n32_struct_flags(soft_float || index >= nfixedargs, (cif->arg_types)[index], &loc, &arg_reg); break; @@ -578,17 +584,30 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) return FFI_OK; } +ffi_status ffi_prep_cif_machdep(ffi_cif *cif) +{ + return ffi_prep_cif_machdep_int(cif, cif->nargs); +} + +ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, + unsigned nfixedargs, + unsigned ntotalargs MAYBE_UNUSED) +{ + return ffi_prep_cif_machdep_int(cif, nfixedargs); +} + /* Low level routine for calling O32 functions */ extern int ffi_call_O32(void (*)(char *, extended_cif *, int, int), extended_cif *, unsigned, - unsigned, unsigned *, void (*)(void)); + unsigned, unsigned *, void (*)(void), void *closure); /* Low level routine for calling N32 functions */ extern int ffi_call_N32(void (*)(char *, extended_cif *, int, int), extended_cif *, unsigned, - unsigned, void *, void (*)(void)); + unsigned, void *, void (*)(void), void *closure); -void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +void ffi_call_int(ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure) { extended_cif ecif; @@ -610,7 +629,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) case FFI_O32: case FFI_O32_SOFT_FLOAT: ffi_call_O32(ffi_prep_args, &ecif, cif->bytes, - cif->flags, ecif.rvalue, fn); + cif->flags, ecif.rvalue, fn, closure); break; #endif @@ -642,7 +661,7 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) #endif } ffi_call_N32(ffi_prep_args, &ecif, cif->bytes, - cif->flags, rvalue_copy, fn); + cif->flags, rvalue_copy, fn, closure); if (copy_rvalue) memcpy(ecif.rvalue, rvalue_copy + copy_offset, cif->rtype->size); } @@ -655,11 +674,27 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) } } +void +ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +{ + ffi_call_int (cif, fn, rvalue, avalue, NULL); +} + +void +ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure) +{ + ffi_call_int (cif, fn, rvalue, avalue, closure); +} + + #if FFI_CLOSURES #if defined(FFI_MIPS_O32) extern void ffi_closure_O32(void); +extern void ffi_go_closure_O32(void); #else extern void ffi_closure_N32(void); +extern void ffi_go_closure_N32(void); #endif /* FFI_MIPS_O32 */ ffi_status @@ -698,7 +733,11 @@ ffi_prep_closure_loc (ffi_closure *closure, /* lui $12,high(codeloc) */ tramp[2] = 0x3c0c0000 | ((unsigned)codeloc >> 16); /* jr $25 */ +#if !defined(__mips_isa_rev) || (__mips_isa_rev<6) tramp[3] = 0x03200008; +#else + tramp[3] = 0x03200009; +#endif /* ori $12,low(codeloc) */ tramp[4] = 0x358c0000 | ((unsigned)codeloc & 0xffff); #else @@ -726,7 +765,11 @@ ffi_prep_closure_loc (ffi_closure *closure, /* ori $25,low(fn) */ tramp[10] = 0x37390000 | ((unsigned long)fn & 0xffff); /* jr $25 */ +#if !defined(__mips_isa_rev) || (__mips_isa_rev<6) tramp[11] = 0x03200008; +#else + tramp[11] = 0x03200009; +#endif /* ori $12,low(codeloc) */ tramp[12] = 0x358c0000 | ((unsigned long)codeloc & 0xffff); @@ -736,11 +779,13 @@ ffi_prep_closure_loc (ffi_closure *closure, closure->fun = fun; closure->user_data = user_data; +#if !defined(__FreeBSD__) #ifdef USE__BUILTIN___CLEAR_CACHE __builtin___clear_cache(clear_location, clear_location + FFI_TRAMPOLINE_SIZE); #else cacheflush (clear_location, FFI_TRAMPOLINE_SIZE, ICACHE); #endif +#endif /* ! __FreeBSD__ */ return FFI_OK; } @@ -762,27 +807,28 @@ ffi_prep_closure_loc (ffi_closure *closure, * Based on the similar routine for sparc. */ int -ffi_closure_mips_inner_O32 (ffi_closure *closure, +ffi_closure_mips_inner_O32 (ffi_cif *cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void *user_data, void *rvalue, ffi_arg *ar, double *fpr) { - ffi_cif *cif; void **avaluep; ffi_arg *avalue; ffi_type **arg_types; int i, avn, argn, seen_int; - cif = closure->cif; avalue = alloca (cif->nargs * sizeof (ffi_arg)); avaluep = alloca (cif->nargs * sizeof (ffi_arg)); - seen_int = (cif->abi == FFI_O32_SOFT_FLOAT); + seen_int = (cif->abi == FFI_O32_SOFT_FLOAT) || (cif->mips_nfixedargs != cif->nargs); argn = 0; if ((cif->flags >> (FFI_FLAG_BITS * 2)) == FFI_TYPE_STRUCT) { - rvalue = (void *)(UINT32)ar[0]; + rvalue = (void *)(uintptr_t)ar[0]; argn = 1; + seen_int = 1; } i = 0; @@ -791,6 +837,8 @@ ffi_closure_mips_inner_O32 (ffi_closure *closure, while (i < avn) { + if (arg_types[i]->alignment == 8 && (argn & 0x1)) + argn++; if (i < 2 && !seen_int && (arg_types[i]->type == FFI_TYPE_FLOAT || arg_types[i]->type == FFI_TYPE_DOUBLE || @@ -805,8 +853,6 @@ ffi_closure_mips_inner_O32 (ffi_closure *closure, } else { - if (arg_types[i]->alignment == 8 && (argn & 0x1)) - argn++; switch (arg_types[i]->type) { case FFI_TYPE_SINT8: @@ -835,12 +881,12 @@ ffi_closure_mips_inner_O32 (ffi_closure *closure, } seen_int = 1; } - argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; + argn += FFI_ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; i++; } /* Invoke the closure. */ - (closure->fun) (cif, rvalue, avaluep, closure->user_data); + fun(cif, rvalue, avaluep, user_data); if (cif->abi == FFI_O32_SOFT_FLOAT) { @@ -876,7 +922,7 @@ copy_struct_N32(char *target, unsigned offset, ffi_abi abi, ffi_type *type, char *argp; char *fpp; - o = ALIGN(offset, elt_type->alignment); + o = FFI_ALIGN(offset, elt_type->alignment); arg_offset += o - offset; offset = o; argn += arg_offset / sizeof(ffi_arg); @@ -916,11 +962,12 @@ copy_struct_N32(char *target, unsigned offset, ffi_abi abi, ffi_type *type, * */ int -ffi_closure_mips_inner_N32 (ffi_closure *closure, +ffi_closure_mips_inner_N32 (ffi_cif *cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void *user_data, void *rvalue, ffi_arg *ar, ffi_arg *fpr) { - ffi_cif *cif; void **avaluep; ffi_arg *avalue; ffi_type **arg_types; @@ -928,7 +975,6 @@ ffi_closure_mips_inner_N32 (ffi_closure *closure, int soft_float; ffi_arg *argp; - cif = closure->cif; soft_float = cif->abi == FFI_N64_SOFT_FLOAT || cif->abi == FFI_N32_SOFT_FLOAT; avalue = alloca (cif->nargs * sizeof (ffi_arg)); @@ -956,10 +1002,10 @@ ffi_closure_mips_inner_N32 (ffi_closure *closure, || arg_types[i]->type == FFI_TYPE_DOUBLE || arg_types[i]->type == FFI_TYPE_LONGDOUBLE) { - argp = (argn >= 8 || soft_float) ? ar + argn : fpr + argn; - if ((arg_types[i]->type == FFI_TYPE_LONGDOUBLE) && ((unsigned)argp & (arg_types[i]->alignment-1))) + argp = (argn >= 8 || i >= cif->mips_nfixedargs || soft_float) ? ar + argn : fpr + argn; + if ((arg_types[i]->type == FFI_TYPE_LONGDOUBLE) && ((uintptr_t)argp & (arg_types[i]->alignment-1))) { - argp=(ffi_arg*)ALIGN(argp,arg_types[i]->alignment); + argp=(ffi_arg*)FFI_ALIGN(argp,arg_types[i]->alignment); argn++; } #if defined(__MIPSEB__) || defined(_MIPSEB) @@ -974,7 +1020,7 @@ ffi_closure_mips_inner_N32 (ffi_closure *closure, unsigned type = arg_types[i]->type; if (arg_types[i]->alignment > sizeof(ffi_arg)) - argn = ALIGN(argn, arg_types[i]->alignment / sizeof(ffi_arg)); + argn = FFI_ALIGN(argn, arg_types[i]->alignment / sizeof(ffi_arg)); argp = ar + argn; @@ -1025,7 +1071,7 @@ ffi_closure_mips_inner_N32 (ffi_closure *closure, it was passed in registers. */ avaluep[i] = alloca(arg_types[i]->size); copy_struct_N32(avaluep[i], 0, cif->abi, arg_types[i], - argn, 0, ar, fpr, soft_float); + argn, 0, ar, fpr, i >= cif->mips_nfixedargs || soft_float); break; } @@ -1035,16 +1081,54 @@ ffi_closure_mips_inner_N32 (ffi_closure *closure, break; } } - argn += ALIGN(arg_types[i]->size, sizeof(ffi_arg)) / sizeof(ffi_arg); + argn += FFI_ALIGN(arg_types[i]->size, sizeof(ffi_arg)) / sizeof(ffi_arg); i++; } /* Invoke the closure. */ - (closure->fun) (cif, rvalue, avaluep, closure->user_data); + fun (cif, rvalue, avaluep, user_data); return cif->flags >> (FFI_FLAG_BITS * 8); } #endif /* FFI_MIPS_N32 */ +#if defined(FFI_MIPS_O32) +extern void ffi_closure_O32(void); +extern void ffi_go_closure_O32(void); +#else +extern void ffi_closure_N32(void); +extern void ffi_go_closure_N32(void); +#endif /* FFI_MIPS_O32 */ + +ffi_status +ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif, + void (*fun)(ffi_cif*,void*,void**,void*)) +{ + void * fn; + +#if defined(FFI_MIPS_O32) + if (cif->abi != FFI_O32 && cif->abi != FFI_O32_SOFT_FLOAT) + return FFI_BAD_ABI; + fn = ffi_go_closure_O32; +#else +#if _MIPS_SIM ==_ABIN32 + if (cif->abi != FFI_N32 + && cif->abi != FFI_N32_SOFT_FLOAT) + return FFI_BAD_ABI; +#else + if (cif->abi != FFI_N64 + && cif->abi != FFI_N64_SOFT_FLOAT) + return FFI_BAD_ABI; +#endif + fn = ffi_go_closure_N32; +#endif /* FFI_MIPS_O32 */ + + closure->tramp = (void *)fn; + closure->cif = cif; + closure->fun = fun; + + return FFI_OK; +} + #endif /* FFI_CLOSURES */ diff --git a/native/libffi/src/mips/ffitarget.h b/native/libffi/src/mips/ffitarget.h index 717d65951c..fdd5ca90ac 100644 --- a/native/libffi/src/mips/ffitarget.h +++ b/native/libffi/src/mips/ffitarget.h @@ -32,7 +32,7 @@ #error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." #endif -#ifdef linux +#ifdef __linux__ # include #elif defined(__rtems__) /* @@ -41,7 +41,7 @@ #define _MIPS_SIM_ABI32 1 #define _MIPS_SIM_NABI32 2 #define _MIPS_SIM_ABI64 3 -#elif !defined(__OpenBSD__) +#elif !defined(__OpenBSD__) && !defined(__FreeBSD__) # include #endif @@ -224,24 +224,21 @@ typedef enum ffi_abi { #endif } ffi_abi; -#define FFI_EXTRA_CIF_FIELDS unsigned rstruct_flag +#define FFI_EXTRA_CIF_FIELDS unsigned rstruct_flag; unsigned mips_nfixedargs +#define FFI_TARGET_SPECIFIC_VARIADIC #endif /* !LIBFFI_ASM */ /* ---- Definitions for closures ----------------------------------------- */ -#if defined(FFI_MIPS_O32) #define FFI_CLOSURES 1 -#define FFI_TRAMPOLINE_SIZE 20 -#else -/* N32/N64. */ -# define FFI_CLOSURES 1 -#if _MIPS_SIM==_ABI64 -#define FFI_TRAMPOLINE_SIZE 52 +#define FFI_GO_CLOSURES 1 +#define FFI_NATIVE_RAW_API 0 + +#if defined(FFI_MIPS_O32) || (_MIPS_SIM ==_ABIN32) +# define FFI_TRAMPOLINE_SIZE 20 #else -#define FFI_TRAMPOLINE_SIZE 20 +# define FFI_TRAMPOLINE_SIZE 56 #endif -#endif /* FFI_MIPS_O32 */ -#define FFI_NATIVE_RAW_API 0 #endif diff --git a/native/libffi/src/mips/n32.S b/native/libffi/src/mips/n32.S index c6985d30a6..1a940b6d2a 100644 --- a/native/libffi/src/mips/n32.S +++ b/native/libffi/src/mips/n32.S @@ -37,36 +37,43 @@ #define flags a3 #define raddr a4 #define fn a5 +#define closure a6 -#define SIZEOF_FRAME ( 8 * FFI_SIZEOF_ARG ) +/* Note: to keep stack 16 byte aligned we need even number slots + used 9 slots here +*/ +#define SIZEOF_FRAME ( 10 * FFI_SIZEOF_ARG ) #ifdef __GNUC__ .abicalls #endif +#if !defined(__mips_isa_rev) || (__mips_isa_rev<6) .set mips4 +#endif .text .align 2 .globl ffi_call_N32 .ent ffi_call_N32 ffi_call_N32: -.LFB3: +.LFB0: .frame $fp, SIZEOF_FRAME, ra .mask 0xc0000000,-FFI_SIZEOF_ARG .fmask 0x00000000,0 # Prologue SUBU $sp, SIZEOF_FRAME # Frame size -.LCFI0: +.LCFI00: REG_S $fp, SIZEOF_FRAME - 2*FFI_SIZEOF_ARG($sp) # Save frame pointer REG_S ra, SIZEOF_FRAME - 1*FFI_SIZEOF_ARG($sp) # Save return address -.LCFI1: +.LCFI01: move $fp, $sp -.LCFI3: +.LCFI02: move t9, callback # callback function pointer REG_S bytes, 2*FFI_SIZEOF_ARG($fp) # bytes REG_S flags, 3*FFI_SIZEOF_ARG($fp) # flags REG_S raddr, 4*FFI_SIZEOF_ARG($fp) # raddr REG_S fn, 5*FFI_SIZEOF_ARG($fp) # fn + REG_S closure, 6*FFI_SIZEOF_ARG($fp) # closure # Allocate at least 4 words in the argstack move v0, bytes @@ -107,6 +114,16 @@ loadregs: REG_L t6, 3*FFI_SIZEOF_ARG($fp) # load the flags word into t6. +#ifdef __mips_soft_float + REG_L a0, 0*FFI_SIZEOF_ARG(t9) + REG_L a1, 1*FFI_SIZEOF_ARG(t9) + REG_L a2, 2*FFI_SIZEOF_ARG(t9) + REG_L a3, 3*FFI_SIZEOF_ARG(t9) + REG_L a4, 4*FFI_SIZEOF_ARG(t9) + REG_L a5, 5*FFI_SIZEOF_ARG(t9) + REG_L a6, 6*FFI_SIZEOF_ARG(t9) + REG_L a7, 7*FFI_SIZEOF_ARG(t9) +#else and t4, t6, ((1< 24) ? 24 : ALIGN_DOWN(count, 8))); + return (stack + ((count > 24) ? 24 : FFI_ALIGN_DOWN(count, 8))); } /* Perform machine dependent cif processing */ @@ -111,7 +111,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) else cif->flags = cif->rtype->size; - cif->bytes = ALIGN (cif->bytes, 8); + cif->bytes = FFI_ALIGN (cif->bytes, 8); return FFI_OK; } @@ -159,7 +159,7 @@ void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3, unsigned arg4, unsigned arg5, unsigned arg6) { /* This function is called by a trampoline. The trampoline stows a - pointer to the ffi_closure object in $r7. We must save this + pointer to the ffi_closure object in $r12. We must save this pointer in a place that will persist while we do our work. */ register ffi_closure *creg __asm__ ("$r12"); ffi_closure *closure = creg; @@ -215,7 +215,18 @@ void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3, break; default: /* This is an 8-byte value. */ - avalue[i] = ptr; + if (ptr == (char *) ®ister_args[5]) + { + /* The value is split across two locations */ + unsigned *ip = alloca(8); + avalue[i] = ip; + ip[0] = *(unsigned *) ptr; + ip[1] = *(unsigned *) stack_args; + } + else + { + avalue[i] = ptr; + } ptr += 4; break; } @@ -223,8 +234,10 @@ void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3, /* If we've handled more arguments than fit in registers, start looking at the those passed on the stack. */ - if (ptr == ®ister_args[6]) + if (ptr == (char *) ®ister_args[6]) ptr = stack_args; + else if (ptr == (char *) ®ister_args[7]) + ptr = stack_args + 4; } /* Invoke the closure. */ @@ -257,7 +270,7 @@ ffi_prep_closure_loc (ffi_closure* closure, fn = (unsigned long) ffi_closure_eabi; - tramp[0] = 0x01e0; /* ldi.l $r7, .... */ + tramp[0] = 0x01e0; /* ldi.l $r12, .... */ tramp[1] = cls >> 16; tramp[2] = cls & 0xffff; tramp[3] = 0x1a00; /* jmpa .... */ diff --git a/native/libffi/src/nios2/ffi.c b/native/libffi/src/nios2/ffi.c index 2efa033f9c..36e0d27158 100644 --- a/native/libffi/src/nios2/ffi.c +++ b/native/libffi/src/nios2/ffi.c @@ -101,7 +101,11 @@ void ffi_prep_args (char *stack, extended_cif *ecif) /* Align argp as appropriate for the argument type. */ if ((alignment - 1) & (unsigned) argp) +<<<<<<< HEAD argp = (char *) ALIGN (argp, alignment); +======= + argp = (char *) FFI_ALIGN (argp, alignment); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 /* Copy the argument, promoting integral types smaller than a word to word size. */ @@ -230,7 +234,11 @@ ffi_closure_helper (unsigned char *args, /* Align argp as appropriate for the argument type. */ if ((alignment - 1) & (unsigned) argp) +<<<<<<< HEAD argp = (char *) ALIGN (argp, alignment); +======= + argp = (char *) FFI_ALIGN (argp, alignment); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 /* Arguments smaller than an int are promoted to int. */ if (size < sizeof (int)) diff --git a/native/libffi/src/pa/ffi.c b/native/libffi/src/pa/ffi.c index 4ce2bc6f0e..95e669473e 100644 --- a/native/libffi/src/pa/ffi.c +++ b/native/libffi/src/pa/ffi.c @@ -421,12 +421,15 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack) ffi_cif *cif; void **avalue; void *rvalue; - UINT32 ret[2]; /* function can return up to 64-bits in registers */ + /* Functions can return up to 64-bits in registers. Return address + must be double word aligned. */ + union { double rd; UINT32 ret[2]; } u; ffi_type **p_arg; char *tmp; int i, avn; unsigned int slot = FIRST_ARG_SLOT; register UINT32 r28 asm("r28"); + ffi_closure *c = (ffi_closure *)FFI_RESTORE_PTR (closure); cif = closure->cif; @@ -434,7 +437,7 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack) if (cif->flags == FFI_TYPE_STRUCT) rvalue = (void *)r28; else - rvalue = &ret[0]; + rvalue = &u; avalue = (void **)alloca(cif->nargs * FFI_SIZEOF_ARG); avn = cif->nargs; @@ -529,35 +532,35 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack) } /* Invoke the closure. */ - (closure->fun) (cif, rvalue, avalue, closure->user_data); + (c->fun) (cif, rvalue, avalue, c->user_data); - debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", ret[0], - ret[1]); + debug(3, "after calling function, ret[0] = %08x, ret[1] = %08x\n", u.ret[0], + u.ret[1]); /* Store the result using the lower 2 bytes of the flags. */ switch (cif->flags) { case FFI_TYPE_UINT8: - *(stack - FIRST_ARG_SLOT) = (UINT8)(ret[0] >> 24); + *(stack - FIRST_ARG_SLOT) = (UINT8)(u.ret[0] >> 24); break; case FFI_TYPE_SINT8: - *(stack - FIRST_ARG_SLOT) = (SINT8)(ret[0] >> 24); + *(stack - FIRST_ARG_SLOT) = (SINT8)(u.ret[0] >> 24); break; case FFI_TYPE_UINT16: - *(stack - FIRST_ARG_SLOT) = (UINT16)(ret[0] >> 16); + *(stack - FIRST_ARG_SLOT) = (UINT16)(u.ret[0] >> 16); break; case FFI_TYPE_SINT16: - *(stack - FIRST_ARG_SLOT) = (SINT16)(ret[0] >> 16); + *(stack - FIRST_ARG_SLOT) = (SINT16)(u.ret[0] >> 16); break; case FFI_TYPE_INT: case FFI_TYPE_SINT32: case FFI_TYPE_UINT32: - *(stack - FIRST_ARG_SLOT) = ret[0]; + *(stack - FIRST_ARG_SLOT) = u.ret[0]; break; case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: - *(stack - FIRST_ARG_SLOT) = ret[0]; - *(stack - FIRST_ARG_SLOT - 1) = ret[1]; + *(stack - FIRST_ARG_SLOT) = u.ret[0]; + *(stack - FIRST_ARG_SLOT - 1) = u.ret[1]; break; case FFI_TYPE_DOUBLE: @@ -577,7 +580,7 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack) case FFI_TYPE_SMALL_STRUCT4: tmp = (void*)(stack - FIRST_ARG_SLOT); tmp += 4 - cif->rtype->size; - memcpy((void*)tmp, &ret[0], cif->rtype->size); + memcpy((void*)tmp, &u, cif->rtype->size); break; case FFI_TYPE_SMALL_STRUCT5: @@ -598,7 +601,7 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack) } memset (ret2, 0, sizeof (ret2)); - memcpy ((char *)ret2 + off, ret, 8 - off); + memcpy ((char *)ret2 + off, &u, 8 - off); *(stack - FIRST_ARG_SLOT) = ret2[0]; *(stack - FIRST_ARG_SLOT - 1) = ret2[1]; @@ -630,89 +633,41 @@ ffi_prep_closure_loc (ffi_closure* closure, void *user_data, void *codeloc) { - UINT32 *tramp = (UINT32 *)(closure->tramp); -#ifdef PA_HPUX - UINT32 *tmp; -#endif + ffi_closure *c = (ffi_closure *)FFI_RESTORE_PTR (closure); + + /* The layout of a function descriptor. A function pointer with the PLABEL + bit set points to a function descriptor. */ + struct pa32_fd + { + UINT32 code_pointer; + UINT32 gp; + }; + + struct ffi_pa32_trampoline_struct + { + UINT32 code_pointer; /* Pointer to ffi_closure_unix. */ + UINT32 fake_gp; /* Pointer to closure, installed as gp. */ + UINT32 real_gp; /* Real gp value. */ + }; + + struct ffi_pa32_trampoline_struct *tramp; + struct pa32_fd *fd; if (cif->abi != FFI_PA32) return FFI_BAD_ABI; - /* Make a small trampoline that will branch to our - handler function. Use PC-relative addressing. */ - -#ifdef PA_LINUX - tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */ - tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */ - tramp[2] = 0x4aa10028; /* ldw 20(%r21),%r1 ; load plabel */ - tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */ - tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */ - tramp[5] = 0xeac0c000; /* bv%r0(%r22) ; branch to handler */ - tramp[6] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */ - tramp[7] = ((UINT32)(ffi_closure_pa32) & ~2); - - /* Flush d/icache -- have to flush up 2 two lines because of - alignment. */ - __asm__ volatile( - "fdc 0(%0)\n\t" - "fdc %1(%0)\n\t" - "fic 0(%%sr4, %0)\n\t" - "fic %1(%%sr4, %0)\n\t" - "sync\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n" - : - : "r"((unsigned long)tramp & ~31), - "r"(32 /* stride */) - : "memory"); -#endif + /* Get function descriptor address for ffi_closure_pa32. */ + fd = (struct pa32_fd *)((UINT32)ffi_closure_pa32 & ~3); -#ifdef PA_HPUX - tramp[0] = 0xeaa00000; /* b,l .+8,%r21 ; %r21 <- pc+8 */ - tramp[1] = 0xd6a01c1e; /* depi 0,31,2,%r21 ; mask priv bits */ - tramp[2] = 0x4aa10038; /* ldw 28(%r21),%r1 ; load plabel */ - tramp[3] = 0x36b53ff1; /* ldo -8(%r21),%r21 ; get closure addr */ - tramp[4] = 0x0c201096; /* ldw 0(%r1),%r22 ; address of handler */ - tramp[5] = 0x02c010b4; /* ldsid (%r22),%r20 ; load space id */ - tramp[6] = 0x00141820; /* mtsp %r20,%sr0 ; into %sr0 */ - tramp[7] = 0xe2c00000; /* be 0(%sr0,%r22) ; branch to handler */ - tramp[8] = 0x0c281093; /* ldw 4(%r1),%r19 ; GP of handler */ - tramp[9] = ((UINT32)(ffi_closure_pa32) & ~2); - - /* Flush d/icache -- have to flush three lines because of alignment. */ - __asm__ volatile( - "copy %1,%0\n\t" - "fdc,m %2(%0)\n\t" - "fdc,m %2(%0)\n\t" - "fdc,m %2(%0)\n\t" - "ldsid (%1),%0\n\t" - "mtsp %0,%%sr0\n\t" - "copy %1,%0\n\t" - "fic,m %2(%%sr0,%0)\n\t" - "fic,m %2(%%sr0,%0)\n\t" - "fic,m %2(%%sr0,%0)\n\t" - "sync\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n\t" - "nop\n" - : "=&r" ((unsigned long)tmp) - : "r" ((unsigned long)tramp & ~31), - "r" (32/* stride */) - : "memory"); -#endif + /* Setup trampoline. */ + tramp = (struct ffi_pa32_trampoline_struct *)c->tramp; + tramp->code_pointer = fd->code_pointer; + tramp->fake_gp = (UINT32)codeloc & ~3; + tramp->real_gp = fd->gp; - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; + c->cif = cif; + c->user_data = user_data; + c->fun = fun; return FFI_OK; } diff --git a/native/libffi/src/pa/ffitarget.h b/native/libffi/src/pa/ffitarget.h index fff4c6b382..df1209eb16 100644 --- a/native/libffi/src/pa/ffitarget.h +++ b/native/libffi/src/pa/ffitarget.h @@ -68,12 +68,7 @@ typedef enum ffi_abi { #define FFI_CLOSURES 1 #define FFI_NATIVE_RAW_API 0 - -#ifdef PA_LINUX -#define FFI_TRAMPOLINE_SIZE 32 -#else -#define FFI_TRAMPOLINE_SIZE 40 -#endif +#define FFI_TRAMPOLINE_SIZE 12 #define FFI_TYPE_SMALL_STRUCT2 -1 #define FFI_TYPE_SMALL_STRUCT3 -2 diff --git a/native/libffi/src/pa/hpux32.S b/native/libffi/src/pa/hpux32.S index 40528bad75..d0e5f69529 100644 --- a/native/libffi/src/pa/hpux32.S +++ b/native/libffi/src/pa/hpux32.S @@ -259,7 +259,7 @@ L$done L$FE1 /* void ffi_closure_pa32(void); - Called with closure argument in %r21 */ + Called with closure argument in %r19 */ .SPACE $TEXT$ .SUBSPA $CODE$ @@ -285,7 +285,9 @@ L$CFI22 stw %arg2, -44(%r3) stw %arg3, -48(%r3) - copy %r21, %arg0 + /* Retrieve closure pointer and real gp. */ + copy %r19, %arg0 + ldw 8(%r19), %r19 bl ffi_closure_inner_pa32, %r2 copy %r3, %arg1 ldwm -64(%sp), %r3 diff --git a/native/libffi/src/pa/linux.S b/native/libffi/src/pa/linux.S index f11ae76807..33ef0b137a 100644 --- a/native/libffi/src/pa/linux.S +++ b/native/libffi/src/pa/linux.S @@ -252,7 +252,7 @@ ffi_call_pa32: .LFE1: /* void ffi_closure_pa32(void); - Called with closure argument in %r21 */ + Called with closure argument in %r19 */ .export ffi_closure_pa32,code .import ffi_closure_inner_pa32,code @@ -277,7 +277,9 @@ ffi_closure_pa32: stw %arg2, -44(%r3) stw %arg3, -48(%r3) - copy %r21, %arg0 + /* Retrieve closure pointer and real gp. */ + copy %r19, %arg0 + ldw 8(%r19), %r19 bl ffi_closure_inner_pa32, %r2 copy %r3, %arg1 @@ -297,10 +299,18 @@ ffi_closure_pa32: .LSCIE1: .word 0x0 ;# CIE Identifier Tag .byte 0x1 ;# CIE Version +#ifdef __PIC__ + .ascii "zR\0" ;# CIE Augmentation: 'z' - data, 'R' - DW_EH_PE_... data +#else .ascii "\0" ;# CIE Augmentation +#endif .uleb128 0x1 ;# CIE Code Alignment Factor .sleb128 4 ;# CIE Data Alignment Factor .byte 0x2 ;# CIE RA Column +#ifdef __PIC__ + .uleb128 0x1 ;# Augmentation size + .byte 0x1b ;# FDE Encoding (DW_EH_PE_pcrel|DW_EH_PE_sdata4) +#endif .byte 0xc ;# DW_CFA_def_cfa .uleb128 0x1e .uleb128 0x0 @@ -310,9 +320,15 @@ ffi_closure_pa32: .word .LEFDE1-.LASFDE1 ;# FDE Length .LASFDE1: .word .LASFDE1-.Lframe1 ;# FDE CIE offset - .word .LFB1 ;# FDE initial location +#ifdef __PIC__ + .word .LFB1-. ;# FDE initial location +#else + .word .LFB1 ;# FDE initial location +#endif .word .LFE1-.LFB1 ;# FDE address range - +#ifdef __PIC__ + .uleb128 0x0 ;# Augmentation size: no data +#endif .byte 0x4 ;# DW_CFA_advance_loc4 .word .LCFI11-.LFB1 .byte 0x83 ;# DW_CFA_offset, column 0x3 @@ -338,8 +354,15 @@ ffi_closure_pa32: .word .LEFDE2-.LASFDE2 ;# FDE Length .LASFDE2: .word .LASFDE2-.Lframe1 ;# FDE CIE offset +#ifdef __PIC__ + .word .LFB2-. ;# FDE initial location +#else .word .LFB2 ;# FDE initial location +#endif .word .LFE2-.LFB2 ;# FDE address range +#ifdef __PIC__ + .uleb128 0x0 ;# Augmentation size: no data +#endif .byte 0x4 ;# DW_CFA_advance_loc4 .word .LCFI21-.LFB2 .byte 0x83 ;# DW_CFA_offset, column 0x3 diff --git a/native/libffi/src/powerpc/aix.S b/native/libffi/src/powerpc/aix.S index 349e78c266..7ba541595f 100644 --- a/native/libffi/src/powerpc/aix.S +++ b/native/libffi/src/powerpc/aix.S @@ -106,6 +106,10 @@ ffi_call_AIX: .llong .ffi_call_AIX, TOC[tc0], 0 .csect .text[PR] .ffi_call_AIX: + .function .ffi_call_AIX,.ffi_call_AIX,16,044,LFE..0-LFB..0 + .bf __LINE__ + .line 1 +LFB..0: /* Save registers we use. */ mflr r0 @@ -115,8 +119,10 @@ ffi_call_AIX: std r31, -8(r1) std r0, 16(r1) +LCFI..0: mr r28, r1 /* our AP. */ stdux r1, r1, r4 +LCFI..1: /* Save arguments over call... */ mr r31, r5 /* flags, */ @@ -202,12 +208,16 @@ L(fp_return_value): L(float_return_value): stfs f1, 0(r30) b L(done_return_value) - +LFE..0: #else /* ! __64BIT__ */ .long .ffi_call_AIX, TOC[tc0], 0 .csect .text[PR] .ffi_call_AIX: + .function .ffi_call_AIX,.ffi_call_AIX,16,044,LFE..0-LFB..0 + .bf __LINE__ + .line 1 +LFB..0: /* Save registers we use. */ mflr r0 @@ -217,8 +227,10 @@ L(float_return_value): stw r31, -4(r1) stw r0, 8(r1) +LCFI..0: mr r28, r1 /* out AP. */ stwux r1, r1, r4 +LCFI..1: /* Save arguments over call... */ mr r31, r5 /* flags, */ @@ -304,11 +316,144 @@ L(fp_return_value): L(float_return_value): stfs f1, 0(r30) b L(done_return_value) +LFE..0: #endif + .ef __LINE__ .long 0 .byte 0,0,0,1,128,4,0,0 /* END(ffi_call_AIX) */ + /* void ffi_call_go_AIX(extended_cif *ecif, unsigned long bytes, + * unsigned int flags, unsigned int *rvalue, + * void (*fn)(), + * void (*prep_args)(extended_cif*, unsigned *const), + * void *closure); + * r3=ecif, r4=bytes, r5=flags, r6=rvalue, r7=fn, r8=prep_args, r9=closure + */ + +.csect .text[PR] + .align 2 + .globl ffi_call_go_AIX + .globl .ffi_call_go_AIX +.csect ffi_call_go_AIX[DS] +ffi_call_go_AIX: +#ifdef __64BIT__ + .llong .ffi_call_go_AIX, TOC[tc0], 0 + .csect .text[PR] +.ffi_call_go_AIX: + .function .ffi_call_go_AIX,.ffi_call_go_AIX,16,044,LFE..1-LFB..1 + .bf __LINE__ + .line 1 +LFB..1: + /* Save registers we use. */ + mflr r0 + + std r28,-32(r1) + std r29,-24(r1) + std r30,-16(r1) + std r31, -8(r1) + + std r9, 8(r1) /* closure, saved in cr field. */ + std r0, 16(r1) +LCFI..2: + mr r28, r1 /* our AP. */ + stdux r1, r1, r4 +LCFI..3: + + /* Save arguments over call... */ + mr r31, r5 /* flags, */ + mr r30, r6 /* rvalue, */ + mr r29, r7 /* function address, */ + std r2, 40(r1) + + /* Call ffi_prep_args. */ + mr r4, r1 + bl .ffi_prep_args + nop + + /* Now do the call. */ + ld r0, 0(r29) + ld r2, 8(r29) + ld r11, 8(r28) /* closure */ + /* Set up cr1 with bits 4-7 of the flags. */ + mtcrf 0x40, r31 + mtctr r0 + /* Load all those argument registers. */ + /* We have set up a nice stack frame, just load it into registers. */ + ld r3, 40+(1*8)(r1) + ld r4, 40+(2*8)(r1) + ld r5, 40+(3*8)(r1) + ld r6, 40+(4*8)(r1) + nop + ld r7, 40+(5*8)(r1) + ld r8, 40+(6*8)(r1) + ld r9, 40+(7*8)(r1) + ld r10,40+(8*8)(r1) + + b L1 +LFE..1: +#else /* ! __64BIT__ */ + + .long .ffi_call_go_AIX, TOC[tc0], 0 + .csect .text[PR] +.ffi_call_go_AIX: + .function .ffi_call_go_AIX,.ffi_call_go_AIX,16,044,LFE..1-LFB..1 + .bf __LINE__ + .line 1 + /* Save registers we use. */ +LFB..1: + mflr r0 + + stw r28,-16(r1) + stw r29,-12(r1) + stw r30, -8(r1) + stw r31, -4(r1) + + stw r9, 4(r1) /* closure, saved in cr field. */ + stw r0, 8(r1) +LCFI..2: + mr r28, r1 /* out AP. */ + stwux r1, r1, r4 +LCFI..3: + + /* Save arguments over call... */ + mr r31, r5 /* flags, */ + mr r30, r6 /* rvalue, */ + mr r29, r7 /* function address, */ + stw r2, 20(r1) + + /* Call ffi_prep_args. */ + mr r4, r1 + bl .ffi_prep_args + nop + + /* Now do the call. */ + lwz r0, 0(r29) + lwz r2, 4(r29) + lwz r11, 4(r28) /* closure */ + /* Set up cr1 with bits 4-7 of the flags. */ + mtcrf 0x40, r31 + mtctr r0 + /* Load all those argument registers. */ + /* We have set up a nice stack frame, just load it into registers. */ + lwz r3, 20+(1*4)(r1) + lwz r4, 20+(2*4)(r1) + lwz r5, 20+(3*4)(r1) + lwz r6, 20+(4*4)(r1) + nop + lwz r7, 20+(5*4)(r1) + lwz r8, 20+(6*4)(r1) + lwz r9, 20+(7*4)(r1) + lwz r10,20+(8*4)(r1) + + b L1 +LFE..1: +#endif + .ef __LINE__ + .long 0 + .byte 0,0,0,1,128,4,0,0 +/* END(ffi_call_go_AIX) */ + .csect .text[PR] .align 2 .globl ffi_call_DARWIN @@ -326,3 +471,96 @@ ffi_call_DARWIN: .long 0 .byte 0,0,0,0,0,0,0,0 /* END(ffi_call_DARWIN) */ + +/* EH frame stuff. */ + +#define LR_REGNO 0x41 /* Link Register (65), see rs6000.md */ +#ifdef __64BIT__ +#define PTRSIZE 8 +#define LOG2_PTRSIZE 3 +#define FDE_ENCODING 0x1c /* DW_EH_PE_pcrel|DW_EH_PE_sdata8 */ +#define EH_DATA_ALIGN_FACT 0x78 /* LEB128 -8 */ +#else +#define PTRSIZE 4 +#define LOG2_PTRSIZE 2 +#define FDE_ENCODING 0x1b /* DW_EH_PE_pcrel|DW_EH_PE_sdata4 */ +#define EH_DATA_ALIGN_FACT 0x7c /* LEB128 -4 */ +#endif + .csect _unwind.ro_[RO],4 + .align LOG2_PTRSIZE + .globl _GLOBAL__F_libffi_src_powerpc_aix +_GLOBAL__F_libffi_src_powerpc_aix: +Lframe..1: + .vbyte 4,LECIE..1-LSCIE..1 /* CIE Length */ +LSCIE..1: + .vbyte 4,0 /* CIE Identifier Tag */ + .byte 0x3 /* CIE Version */ + .byte "zR" /* CIE Augmentation */ + .byte 0 + .byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */ + .byte EH_DATA_ALIGN_FACT /* leb128 -4/-8; CIE Data Alignment Factor */ + .byte 0x41 /* CIE RA Column */ + .byte 0x1 /* uleb128 0x1; Augmentation size */ + .byte FDE_ENCODING /* FDE Encoding (pcrel|sdata4/8) */ + .byte 0xc /* DW_CFA_def_cfa */ + .byte 0x1 /* uleb128 0x1; Register r1 */ + .byte 0 /* uleb128 0x0; Offset 0 */ + .align LOG2_PTRSIZE +LECIE..1: +LSFDE..1: + .vbyte 4,LEFDE..1-LASFDE..1 /* FDE Length */ +LASFDE..1: + .vbyte 4,LASFDE..1-Lframe..1 /* FDE CIE offset */ + .vbyte PTRSIZE,LFB..0-$ /* FDE initial location */ + .vbyte PTRSIZE,LFE..0-LFB..0 /* FDE address range */ + .byte 0 /* uleb128 0x0; Augmentation size */ + .byte 0x4 /* DW_CFA_advance_loc4 */ + .vbyte 4,LCFI..0-LFB..0 + .byte 0x11 /* DW_CFA_def_offset_extended_sf */ + .byte LR_REGNO /* uleb128 LR_REGNO; Register LR */ + .byte 0x7e /* leb128 -2; Offset -2 (8/16) */ + .byte 0x9f /* DW_CFA_offset Register r31 */ + .byte 0x1 /* uleb128 0x1; Offset 1 (-4/-8) */ + .byte 0x9e /* DW_CFA_offset Register r30 */ + .byte 0x2 /* uleb128 0x2; Offset 2 (-8/-16) */ + .byte 0x9d /* DW_CFA_offset Register r29 */ + .byte 0x3 /* uleb128 0x3; Offset 3 (-12/-24) */ + .byte 0x9c /* DW_CFA_offset Register r28 */ + .byte 0x4 /* uleb128 0x4; Offset 4 (-16/-32) */ + .byte 0x4 /* DW_CFA_advance_loc4 */ + .vbyte 4,LCFI..1-LCFI..0 + .byte 0xd /* DW_CFA_def_cfa_register */ + .byte 0x1c /* uleb128 28; Register r28 */ + .align LOG2_PTRSIZE +LEFDE..1: +LSFDE..2: + .vbyte 4,LEFDE..2-LASFDE..2 /* FDE Length */ +LASFDE..2: + .vbyte 4,LASFDE..2-Lframe..1 /* FDE CIE offset */ + .vbyte PTRSIZE,LFB..1-$ /* FDE initial location */ + .vbyte PTRSIZE,LFE..1-LFB..1 /* FDE address range */ + .byte 0 /* uleb128 0x0; Augmentation size */ + .byte 0x4 /* DW_CFA_advance_loc4 */ + .vbyte 4,LCFI..2-LFB..1 + .byte 0x11 /* DW_CFA_def_offset_extended_sf */ + .byte LR_REGNO /* uleb128 LR_REGNO; Register LR */ + .byte 0x7e /* leb128 -2; Offset -2 (8/16) */ + .byte 0x9f /* DW_CFA_offset Register r31 */ + .byte 0x1 /* uleb128 0x1; Offset 1 (-4/-8) */ + .byte 0x9e /* DW_CFA_offset Register r30 */ + .byte 0x2 /* uleb128 0x2; Offset 2 (-8/-16) */ + .byte 0x9d /* DW_CFA_offset Register r29 */ + .byte 0x3 /* uleb128 0x3; Offset 3 (-12/-24) */ + .byte 0x9c /* DW_CFA_offset Register r28 */ + .byte 0x4 /* uleb128 0x4; Offset 4 (-16/-32) */ + .byte 0x4 /* DW_CFA_advance_loc4 */ + .vbyte 4,LCFI..3-LCFI..2 + .byte 0xd /* DW_CFA_def_cfa_register */ + .byte 0x1c /* uleb128 28; Register r28 */ + .align LOG2_PTRSIZE +LEFDE..2: + .vbyte 4,0 /* End of FDEs */ + + .csect .text[PR] + .ref _GLOBAL__F_libffi_src_powerpc_aix /* Prevents garbage collection by AIX linker */ + diff --git a/native/libffi/src/powerpc/aix_closure.S b/native/libffi/src/powerpc/aix_closure.S index aabd3c3c1e..132c785edd 100644 --- a/native/libffi/src/powerpc/aix_closure.S +++ b/native/libffi/src/powerpc/aix_closure.S @@ -80,6 +80,7 @@ .set f21,21 .extern .ffi_closure_helper_DARWIN + .extern .ffi_go_closure_helper_DARWIN #define LIBFFI_ASM #define JUMPTARGET(name) name @@ -101,6 +102,10 @@ ffi_closure_ASM: .llong .ffi_closure_ASM, TOC[tc0], 0 .csect .text[PR] .ffi_closure_ASM: + .function .ffi_closure_ASM,.ffi_closure_ASM,16,044,LFE..0-LFB..0 + .bf __LINE__ + .line 1 +LFB..0: /* we want to build up an area for the parameters passed */ /* in registers (both floating point and integer) */ @@ -117,8 +122,7 @@ ffi_closure_ASM: std r9, 48+(6*8)(r1) std r10, 48+(7*8)(r1) std r0, 16(r1) /* save the return address */ - - +LCFI..0: /* 48 Bytes (Linkage Area) */ /* 64 Bytes (params) */ /* 16 Bytes (result) */ @@ -128,6 +132,7 @@ ffi_closure_ASM: stdu r1, -240(r1) /* skip over caller save area keep stack aligned to 16 */ +LCFI..1: /* next save fpr 1 to fpr 13 (aligned to 8) */ stfd f1, 128+(0*8)(r1) @@ -161,6 +166,8 @@ ffi_closure_ASM: bl .ffi_closure_helper_DARWIN nop +.Ldoneclosure: + /* now r3 contains the return type */ /* so use it to look up in a table */ /* so we know how to deal with each type */ @@ -270,12 +277,17 @@ L..finish: mtlr r0 addi r1, r1, 240 blr +LFE..0: #else /* ! __64BIT__ */ .long .ffi_closure_ASM, TOC[tc0], 0 .csect .text[PR] .ffi_closure_ASM: + .function .ffi_closure_ASM,.ffi_closure_ASM,16,044,LFE..0-LFB..0 + .bf __LINE__ + .line 1 +LFB..0: /* we want to build up an area for the parameters passed */ /* in registers (both floating point and integer) */ @@ -292,7 +304,7 @@ L..finish: stw r9, 24+(6*4)(r1) stw r10, 24+(7*4)(r1) stw r0, 8(r1) - +LCFI..0: /* 24 Bytes (Linkage Area) */ /* 32 Bytes (params) */ /* 16 Bytes (result) */ @@ -301,6 +313,7 @@ L..finish: stwu r1, -176(r1) /* skip over caller save area keep stack aligned to 16 */ +LCFI..1: /* next save fpr 1 to fpr 13 (aligned to 8) */ stfd f1, 72+(0*8)(r1) @@ -334,6 +347,8 @@ L..finish: bl .ffi_closure_helper_DARWIN nop +.Ldoneclosure: + /* now r3 contains the return type */ /* so use it to look up in a table */ /* so we know how to deal with each type */ @@ -443,5 +458,237 @@ L..60: L..finish: addi r1, r1, 176 blr +LFE..0: #endif + .ef __LINE__ /* END(ffi_closure_ASM) */ + + +.csect .text[PR] + .align 2 + .globl ffi_go_closure_ASM + .globl .ffi_go_closure_ASM +.csect ffi_go_closure_ASM[DS] +ffi_go_closure_ASM: +#ifdef __64BIT__ + .llong .ffi_go_closure_ASM, TOC[tc0], 0 + .csect .text[PR] +.ffi_go_closure_ASM: + .function .ffi_go_closure_ASM,.ffi_go_closure_ASM,16,044,LFE..1-LFB..1 + .bf __LINE__ + .line 1 +LFB..1: +/* we want to build up an area for the parameters passed */ +/* in registers (both floating point and integer) */ + + /* we store gpr 3 to gpr 10 (aligned to 4) + in the parents outgoing area */ + std r3, 48+(0*8)(r1) + std r4, 48+(1*8)(r1) + std r5, 48+(2*8)(r1) + std r6, 48+(3*8)(r1) + mflr r0 + + std r7, 48+(4*8)(r1) + std r8, 48+(5*8)(r1) + std r9, 48+(6*8)(r1) + std r10, 48+(7*8)(r1) + std r0, 16(r1) /* save the return address */ +LCFI..2: + /* 48 Bytes (Linkage Area) */ + /* 64 Bytes (params) */ + /* 16 Bytes (result) */ + /* 104 Bytes (13*8 from FPR) */ + /* 8 Bytes (alignment) */ + /* 240 Bytes */ + + stdu r1, -240(r1) /* skip over caller save area + keep stack aligned to 16 */ +LCFI..3: + + /* next save fpr 1 to fpr 13 (aligned to 8) */ + stfd f1, 128+(0*8)(r1) + stfd f2, 128+(1*8)(r1) + stfd f3, 128+(2*8)(r1) + stfd f4, 128+(3*8)(r1) + stfd f5, 128+(4*8)(r1) + stfd f6, 128+(5*8)(r1) + stfd f7, 128+(6*8)(r1) + stfd f8, 128+(7*8)(r1) + stfd f9, 128+(8*8)(r1) + stfd f10, 128+(9*8)(r1) + stfd f11, 128+(10*8)(r1) + stfd f12, 128+(11*8)(r1) + stfd f13, 128+(12*8)(r1) + + /* set up registers for the routine that actually does the work */ + mr r3, r11 /* go closure */ + + /* now load up the pointer to the result storage */ + addi r4, r1, 112 + + /* now load up the pointer to the saved gpr registers */ + addi r5, r1, 288 + + /* now load up the pointer to the saved fpr registers */ + addi r6, r1, 128 + + /* make the call */ + bl .ffi_go_closure_helper_DARWIN + nop + + b .Ldoneclosure +LFE..1: + +#else /* ! __64BIT__ */ + + .long .ffi_go_closure_ASM, TOC[tc0], 0 + .csect .text[PR] +.ffi_go_closure_ASM: + .function .ffi_go_closure_ASM,.ffi_go_closure_ASM,16,044,LFE..1-LFB..1 + .bf __LINE__ + .line 1 +LFB..1: +/* we want to build up an area for the parameters passed */ +/* in registers (both floating point and integer) */ + + /* we store gpr 3 to gpr 10 (aligned to 4) + in the parents outgoing area */ + stw r3, 24+(0*4)(r1) + stw r4, 24+(1*4)(r1) + stw r5, 24+(2*4)(r1) + stw r6, 24+(3*4)(r1) + mflr r0 + + stw r7, 24+(4*4)(r1) + stw r8, 24+(5*4)(r1) + stw r9, 24+(6*4)(r1) + stw r10, 24+(7*4)(r1) + stw r0, 8(r1) +LCFI..2: + /* 24 Bytes (Linkage Area) */ + /* 32 Bytes (params) */ + /* 16 Bytes (result) */ + /* 104 Bytes (13*8 from FPR) */ + /* 176 Bytes */ + + stwu r1, -176(r1) /* skip over caller save area + keep stack aligned to 16 */ +LCFI..3: + + /* next save fpr 1 to fpr 13 (aligned to 8) */ + stfd f1, 72+(0*8)(r1) + stfd f2, 72+(1*8)(r1) + stfd f3, 72+(2*8)(r1) + stfd f4, 72+(3*8)(r1) + stfd f5, 72+(4*8)(r1) + stfd f6, 72+(5*8)(r1) + stfd f7, 72+(6*8)(r1) + stfd f8, 72+(7*8)(r1) + stfd f9, 72+(8*8)(r1) + stfd f10, 72+(9*8)(r1) + stfd f11, 72+(10*8)(r1) + stfd f12, 72+(11*8)(r1) + stfd f13, 72+(12*8)(r1) + + /* set up registers for the routine that actually does the work */ + mr r3, 11 /* go closure */ + + /* now load up the pointer to the result storage */ + addi r4, r1, 56 + + /* now load up the pointer to the saved gpr registers */ + addi r5, r1, 200 + + /* now load up the pointer to the saved fpr registers */ + addi r6, r1, 72 + + /* make the call */ + bl .ffi_go_closure_helper_DARWIN + nop + + b .Ldoneclosure +LFE..1: +#endif + .ef __LINE__ +/* END(ffi_go_closure_ASM) */ + +/* EH frame stuff. */ + +#define LR_REGNO 0x41 /* Link Register (65), see rs6000.md */ +#ifdef __64BIT__ +#define PTRSIZE 8 +#define LOG2_PTRSIZE 3 +#define CFA_OFFSET 0xf0,0x01 /* LEB128 240 */ +#define FDE_ENCODING 0x1c /* DW_EH_PE_pcrel|DW_EH_PE_sdata8 */ +#define EH_DATA_ALIGN_FACT 0x78 /* LEB128 -8 */ +#else +#define PTRSIZE 4 +#define LOG2_PTRSIZE 2 +#define CFA_OFFSET 0xb0,0x01 /* LEB128 176 */ +#define FDE_ENCODING 0x1b /* DW_EH_PE_pcrel|DW_EH_PE_sdata4 */ +#define EH_DATA_ALIGN_FACT 0x7c /* LEB128 -4 */ +#endif + + .csect _unwind.ro_[RO],4 + .align LOG2_PTRSIZE + .globl _GLOBAL__F_libffi_src_powerpc_aix_closure +_GLOBAL__F_libffi_src_powerpc_aix_closure: +Lframe..1: + .vbyte 4,LECIE..1-LSCIE..1 /* CIE Length */ +LSCIE..1: + .vbyte 4,0 /* CIE Identifier Tag */ + .byte 0x3 /* CIE Version */ + .byte "zR" /* CIE Augmentation */ + .byte 0 + .byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */ + .byte EH_DATA_ALIGN_FACT /* leb128 -4/-8; CIE Data Alignment Factor */ + .byte LR_REGNO /* CIE RA Column */ + .byte 0x1 /* uleb128 0x1; Augmentation size */ + .byte FDE_ENCODING /* FDE Encoding (pcrel|sdata4/8) */ + .byte 0xc /* DW_CFA_def_cfa */ + .byte 0x1 /* uleb128 0x1; Register r1 */ + .byte 0 /* uleb128 0x0; Offset 0 */ + .align LOG2_PTRSIZE +LECIE..1: +LSFDE..1: + .vbyte 4,LEFDE..1-LASFDE..1 /* FDE Length */ +LASFDE..1: + .vbyte 4,LASFDE..1-Lframe..1 /* FDE CIE offset */ + .vbyte PTRSIZE,LFB..0-$ /* FDE initial location */ + .vbyte PTRSIZE,LFE..0-LFB..0 /* FDE address range */ + .byte 0 /* uleb128 0x0; Augmentation size */ + .byte 0x4 /* DW_CFA_advance_loc4 */ + .vbyte 4,LCFI..1-LCFI..0 + .byte 0xe /* DW_CFA_def_cfa_offset */ + .byte CFA_OFFSET /* uleb128 176/240 */ + .byte 0x4 /* DW_CFA_advance_loc4 */ + .vbyte 4,LCFI..0-LFB..0 + .byte 0x11 /* DW_CFA_offset_extended_sf */ + .byte LR_REGNO /* uleb128 LR_REGNO; Register LR */ + .byte 0x7e /* leb128 -2; Offset -2 (8/16) */ + .align LOG2_PTRSIZE +LEFDE..1: +LSFDE..2: + .vbyte 4,LEFDE..2-LASFDE..2 /* FDE Length */ +LASFDE..2: + .vbyte 4,LASFDE..2-Lframe..1 /* FDE CIE offset */ + .vbyte PTRSIZE,LFB..1-$ /* FDE initial location */ + .vbyte PTRSIZE,LFE..1-LFB..1 /* FDE address range */ + .byte 0 /* uleb128 0x0; Augmentation size */ + .byte 0x4 /* DW_CFA_advance_loc4 */ + .vbyte 4,LCFI..3-LCFI..2 + .byte 0xe /* DW_CFA_def_cfa_offset */ + .byte CFA_OFFSET /* uleb128 176/240 */ + .byte 0x4 /* DW_CFA_advance_loc4 */ + .vbyte 4,LCFI..2-LFB..1 + .byte 0x11 /* DW_CFA_offset_extended_sf */ + .byte LR_REGNO /* uleb128 LR_REGNO; Register LR */ + .byte 0x7e /* leb128 -2; Offset -2 (8/16) */ + .align LOG2_PTRSIZE +LEFDE..2: + .vbyte 4,0 /* End of FDEs */ + + .csect .text[PR] + .ref _GLOBAL__F_libffi_src_powerpc_aix_closure /* Prevents garbage collection by AIX linker */ + diff --git a/native/libffi/src/powerpc/asm.h b/native/libffi/src/powerpc/asm.h index 994f62d079..27b22f670a 100644 --- a/native/libffi/src/powerpc/asm.h +++ b/native/libffi/src/powerpc/asm.h @@ -93,7 +93,7 @@ /* EALIGN is like ENTRY, but does alignment to 'words'*4 bytes past a 2^align boundary. */ #ifdef PROF -#define EALIGN(name, alignt, words) \ +#define EFFI_ALIGN(name, alignt, words) \ ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ .align ALIGNARG(2); \ @@ -104,7 +104,7 @@ EALIGN_W_##words; \ 0: #else /* PROF */ -#define EALIGN(name, alignt, words) \ +#define EFFI_ALIGN(name, alignt, words) \ ASM_GLOBAL_DIRECTIVE C_SYMBOL_NAME(name); \ ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ .align ALIGNARG(alignt); \ diff --git a/native/libffi/src/powerpc/darwin_closure.S b/native/libffi/src/powerpc/darwin_closure.S index c7734d4198..17456058c1 100644 --- a/native/libffi/src/powerpc/darwin_closure.S +++ b/native/libffi/src/powerpc/darwin_closure.S @@ -353,7 +353,7 @@ Lret_type13: bgt Lstructend ; not a special small case b Lsmallstruct ; see if we need more. #else - cmpi 0,r0,4 + cmpwi 0,r0,4 bgt Lfinish ; not by value lg r3,0(r5) b Lfinish @@ -494,8 +494,13 @@ LSFDE1: LASFDE1: .long LASFDE1-EH_frame1 ; FDE CIE offset .g_long Lstartcode-. ; FDE initial location +<<<<<<< HEAD .set L$set$3,LFE1-Lstartcode .g_long L$set$3 ; FDE address range +======= + .set L$set$2,LFE1-Lstartcode + .g_long L$set$2 ; FDE address range +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 .byte 0x0 ; uleb128 0x0; Augmentation size .byte 0x4 ; DW_CFA_advance_loc4 .set L$set$3,LCFI1-LCFI0 diff --git a/native/libffi/src/powerpc/ffi.c b/native/libffi/src/powerpc/ffi.c index efb441bbfc..d56ba68b8a 100644 --- a/native/libffi/src/powerpc/ffi.c +++ b/native/libffi/src/powerpc/ffi.c @@ -70,8 +70,17 @@ ffi_prep_cif_machdep_var (ffi_cif *cif, #endif } +<<<<<<< HEAD void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +======= +static void +ffi_call_int (ffi_cif *cif, + void (*fn) (void), + void *rvalue, + void **avalue, + void *closure) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 { /* The final SYSV ABI says that structures smaller or equal 8 bytes are returned in r3/r4. A draft ABI used by linux instead returns @@ -81,8 +90,14 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) can write r3 and r4 to memory without worrying about struct size. For ELFv2 ABI, use a bounce buffer for homogeneous structs too, +<<<<<<< HEAD for similar reasons. */ unsigned long smst_buffer[8]; +======= + for similar reasons. This bounce buffer must be aligned to 16 + bytes for use with homogeneous structs of vectors (float128). */ + float128 smst_buffer[8]; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 extended_cif ecif; ecif.cif = cif; @@ -97,9 +112,16 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) ecif.rvalue = alloca (cif->rtype->size); #ifdef POWERPC64 +<<<<<<< HEAD ffi_call_LINUX64 (&ecif, -(long) cif->bytes, cif->flags, ecif.rvalue, fn); #else ffi_call_SYSV (&ecif, -cif->bytes, cif->flags, ecif.rvalue, fn); +======= + ffi_call_LINUX64 (&ecif, fn, ecif.rvalue, cif->flags, closure, + -(long) cif->bytes); +#else + ffi_call_SYSV (&ecif, fn, ecif.rvalue, cif->flags, closure, -cif->bytes); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #endif /* Check for a bounce-buffered return value */ @@ -116,8 +138,14 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) # endif /* The SYSV ABI returns a structure of up to 8 bytes in size left-padded in r3/r4, and the ELFv2 ABI similarly returns a +<<<<<<< HEAD structure of up to 8 bytes in size left-padded in r3. */ if (rsize <= 8) +======= + structure of up to 8 bytes in size left-padded in r3. But + note that a structure of a single float is not paddded. */ + if (rsize <= 8 && (cif->flags & FLAG_RETURNS_FP) == 0) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 memcpy (rvalue, (char *) smst_buffer + 8 - rsize, rsize); else #endif @@ -125,7 +153,22 @@ ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) } } +void +ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue) +{ + ffi_call_int (cif, fn, rvalue, avalue, NULL); +} + +<<<<<<< HEAD +======= +void +ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue, + void *closure) +{ + ffi_call_int (cif, fn, rvalue, avalue, closure); +} +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 ffi_status ffi_prep_closure_loc (ffi_closure *closure, ffi_cif *cif, @@ -138,4 +181,22 @@ ffi_prep_closure_loc (ffi_closure *closure, #else return ffi_prep_closure_loc_sysv (closure, cif, fun, user_data, codeloc); #endif +<<<<<<< HEAD +======= +} + +ffi_status +ffi_prep_go_closure (ffi_go_closure *closure, + ffi_cif *cif, + void (*fun) (ffi_cif *, void *, void **, void *)) +{ +#ifdef POWERPC64 + closure->tramp = ffi_go_closure_linux64; +#else + closure->tramp = ffi_go_closure_sysv; +#endif + closure->cif = cif; + closure->fun = fun; + return FFI_OK; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 } diff --git a/native/libffi/src/powerpc/ffi_darwin.c b/native/libffi/src/powerpc/ffi_darwin.c index cf6fb6d4b7..64bb94dfae 100644 --- a/native/libffi/src/powerpc/ffi_darwin.c +++ b/native/libffi/src/powerpc/ffi_darwin.c @@ -34,6 +34,10 @@ extern void ffi_closure_ASM (void); +#if defined (FFI_GO_CLOSURES) +extern void ffi_go_closure_ASM (void); +#endif + enum { /* The assembly depends on these exact flags. For Darwin64 (when FLAG_RETURNS_STRUCT is set): @@ -255,7 +259,7 @@ ffi_prep_args (extended_cif *ecif, unsigned long *const stack) case FFI_TYPE_STRUCT: size_al = (*ptr)->size; #if defined(POWERPC_DARWIN64) - next_arg = (unsigned long *)ALIGN((char *)next_arg, (*ptr)->alignment); + next_arg = (unsigned long *)FFI_ALIGN((char *)next_arg, (*ptr)->alignment); darwin64_pass_struct_by_value (*ptr, (char *) *p_argv, (unsigned) size_al, (unsigned int *) &fparg_count, @@ -266,7 +270,7 @@ ffi_prep_args (extended_cif *ecif, unsigned long *const stack) /* If the first member of the struct is a double, then include enough padding in the struct size to align it to double-word. */ if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) - size_al = ALIGN((*ptr)->size, 8); + size_al = FFI_ALIGN((*ptr)->size, 8); # if defined(POWERPC64) FFI_ASSERT (abi != FFI_DARWIN); @@ -352,7 +356,7 @@ darwin64_struct_size_exceeds_gprs_p (ffi_type *s, char *src, unsigned *nfpr) ffi_type *p = s->elements[i]; /* Find the start of this item (0 for the first one). */ if (i > 0) - struct_offset = ALIGN(struct_offset, p->alignment); + struct_offset = FFI_ALIGN(struct_offset, p->alignment); item_base = src + struct_offset; @@ -436,7 +440,7 @@ darwin64_pass_struct_floats (ffi_type *s, char *src, ffi_type *p = s->elements[i]; /* Find the start of this item (0 for the first one). */ if (i > 0) - struct_offset = ALIGN(struct_offset, p->alignment); + struct_offset = FFI_ALIGN(struct_offset, p->alignment); item_base = src + struct_offset; switch (p->type) @@ -527,7 +531,7 @@ darwin64_struct_floats_to_mem (ffi_type *s, char *dest, double *fprs, unsigned * ffi_type *p = s->elements[i]; /* Find the start of this item (0 for the first one). */ if (i > 0) - struct_offset = ALIGN(struct_offset, p->alignment); + struct_offset = FFI_ALIGN(struct_offset, p->alignment); item_base = dest + struct_offset; switch (p->type) @@ -604,10 +608,10 @@ darwin_adjust_aggregate_sizes (ffi_type *s) align = 4; #endif /* Pad, if necessary, before adding the current item. */ - s->size = ALIGN(s->size, align) + p->size; + s->size = FFI_ALIGN(s->size, align) + p->size; } - s->size = ALIGN(s->size, s->alignment); + s->size = FFI_ALIGN(s->size, s->alignment); /* This should not be necessary on m64, but harmless. */ if (s->elements[0]->type == FFI_TYPE_UINT64 @@ -640,10 +644,10 @@ aix_adjust_aggregate_sizes (ffi_type *s) align = p->alignment; if (i != 0 && p->type == FFI_TYPE_DOUBLE) align = 4; - s->size = ALIGN(s->size, align) + p->size; + s->size = FFI_ALIGN(s->size, align) + p->size; } - s->size = ALIGN(s->size, s->alignment); + s->size = FFI_ALIGN(s->size, s->alignment); if (s->elements[0]->type == FFI_TYPE_UINT64 || s->elements[0]->type == FFI_TYPE_SINT64 @@ -809,9 +813,9 @@ ffi_prep_cif_machdep (ffi_cif *cif) 16-byte-aligned. */ if (fparg_count >= NUM_FPR_ARG_REGISTERS) #if defined (POWERPC64) - intarg_count = ALIGN(intarg_count, 2); + intarg_count = FFI_ALIGN(intarg_count, 2); #else - intarg_count = ALIGN(intarg_count, 4); + intarg_count = FFI_ALIGN(intarg_count, 4); #endif break; #endif @@ -838,7 +842,7 @@ ffi_prep_cif_machdep (ffi_cif *cif) #if defined(POWERPC_DARWIN64) align_words = (*ptr)->alignment >> 3; if (align_words) - intarg_count = ALIGN(intarg_count, align_words); + intarg_count = FFI_ALIGN(intarg_count, align_words); /* Base size of the struct. */ intarg_count += (size_al + 7) / 8; /* If 16 bytes then don't worry about floats. */ @@ -848,11 +852,11 @@ ffi_prep_cif_machdep (ffi_cif *cif) #else align_words = (*ptr)->alignment >> 2; if (align_words) - intarg_count = ALIGN(intarg_count, align_words); + intarg_count = FFI_ALIGN(intarg_count, align_words); /* If the first member of the struct is a double, then align the struct to double-word. if ((*ptr)->elements[0]->type == FFI_TYPE_DOUBLE) - size_al = ALIGN((*ptr)->size, 8); */ + size_al = FFI_ALIGN((*ptr)->size, 8); */ # ifdef POWERPC64 intarg_count += (size_al + 7) / 8; # else @@ -897,7 +901,7 @@ ffi_prep_cif_machdep (ffi_cif *cif) bytes += NUM_GPR_ARG_REGISTERS * sizeof(long); /* The stack space allocated needs to be a multiple of 16 bytes. */ - bytes = ALIGN(bytes, 16) ; + bytes = FFI_ALIGN(bytes, 16) ; cif->flags = flags; cif->bytes = bytes; @@ -908,6 +912,11 @@ ffi_prep_cif_machdep (ffi_cif *cif) extern void ffi_call_AIX(extended_cif *, long, unsigned, unsigned *, void (*fn)(void), void (*fn2)(void)); +#if defined (FFI_GO_CLOSURES) +extern void ffi_call_go_AIX(extended_cif *, long, unsigned, unsigned *, + void (*fn)(void), void (*fn2)(void), void *closure); +#endif + extern void ffi_call_DARWIN(extended_cif *, long, unsigned, unsigned *, void (*fn)(void), void (*fn2)(void), ffi_type*); @@ -946,6 +955,40 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) } } +#if defined (FFI_GO_CLOSURES) +void +ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue, + void *closure) +{ + extended_cif ecif; + + ecif.cif = cif; + ecif.avalue = avalue; + + /* If the return value is a struct and we don't have a return + value address then we need to make one. */ + + if ((rvalue == NULL) && + (cif->rtype->type == FFI_TYPE_STRUCT)) + { + ecif.rvalue = alloca (cif->rtype->size); + } + else + ecif.rvalue = rvalue; + + switch (cif->abi) + { + case FFI_AIX: + ffi_call_go_AIX(&ecif, -(long)cif->bytes, cif->flags, ecif.rvalue, fn, + FFI_FN(ffi_prep_args), closure); + break; + default: + FFI_ASSERT(0); + break; + } +} +#endif + static void flush_icache(char *); static void flush_range(char *, int); @@ -1074,6 +1117,32 @@ ffi_prep_closure_loc (ffi_closure* closure, return FFI_OK; } +#if defined (FFI_GO_CLOSURES) +ffi_status +ffi_prep_go_closure (ffi_go_closure* closure, + ffi_cif* cif, + void (*fun)(ffi_cif*, void*, void**, void*)) +{ + switch (cif->abi) + { + case FFI_AIX: + + FFI_ASSERT (cif->abi == FFI_AIX); + + closure->tramp = (void *)ffi_go_closure_ASM; + closure->cif = cif; + closure->fun = fun; + return FFI_OK; + + // For now, ffi_prep_go_closure is only implemented for AIX, not for Darwin + default: + return FFI_BAD_ABI; + break; + } + return FFI_OK; +} +#endif + static void flush_icache(char *addr) { @@ -1108,6 +1177,12 @@ ffi_type * ffi_closure_helper_DARWIN (ffi_closure *, void *, unsigned long *, ffi_dblfl *); +#if defined (FFI_GO_CLOSURES) +ffi_type * +ffi_go_closure_helper_DARWIN (ffi_go_closure*, void *, + unsigned long *, ffi_dblfl *); +#endif + /* Basically the trampoline invokes ffi_closure_ASM, and on entry, r11 holds the address of the closure. After storing the registers that could possibly contain @@ -1115,8 +1190,10 @@ ffi_closure_helper_DARWIN (ffi_closure *, void *, up space for a return value, ffi_closure_ASM invokes the following helper function to do most of the work. */ -ffi_type * -ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue, +static ffi_type * +ffi_closure_helper_common (ffi_cif* cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void *user_data, void *rvalue, unsigned long *pgr, ffi_dblfl *pfr) { /* rvalue is the pointer to space for return value in closure assembly @@ -1134,14 +1211,12 @@ ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue, void ** avalue; ffi_type ** arg_types; long i, avn; - ffi_cif * cif; ffi_dblfl * end_pfr = pfr + NUM_FPR_ARG_REGISTERS; unsigned size_al; #if defined(POWERPC_DARWIN64) unsigned fpsused = 0; #endif - cif = closure->cif; avalue = alloca (cif->nargs * sizeof(void *)); if (cif->rtype->type == FFI_TYPE_STRUCT) @@ -1208,7 +1283,7 @@ ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue, case FFI_TYPE_STRUCT: size_al = arg_types[i]->size; #if defined(POWERPC_DARWIN64) - pgr = (unsigned long *)ALIGN((char *)pgr, arg_types[i]->alignment); + pgr = (unsigned long *)FFI_ALIGN((char *)pgr, arg_types[i]->alignment); if (size_al < 3 || size_al == 4) { avalue[i] = ((char *)pgr)+8-size_al; @@ -1233,7 +1308,7 @@ ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue, /* If the first member of the struct is a double, then align the struct to double-word. */ if (arg_types[i]->elements[0]->type == FFI_TYPE_DOUBLE) - size_al = ALIGN(arg_types[i]->size, 8); + size_al = FFI_ALIGN(arg_types[i]->size, 8); # if defined(POWERPC64) FFI_ASSERT (cif->abi != FFI_DARWIN); avalue[i] = pgr; @@ -1352,8 +1427,26 @@ ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue, i++; } - (closure->fun) (cif, rvalue, avalue, closure->user_data); + (fun) (cif, rvalue, avalue, user_data); /* Tell ffi_closure_ASM to perform return type promotions. */ return cif->rtype; } + +ffi_type * +ffi_closure_helper_DARWIN (ffi_closure *closure, void *rvalue, + unsigned long *pgr, ffi_dblfl *pfr) +{ + return ffi_closure_helper_common (closure->cif, closure->fun, + closure->user_data, rvalue, pgr, pfr); +} + +#if defined (FFI_GO_CLOSURES) +ffi_type * +ffi_go_closure_helper_DARWIN (ffi_go_closure *closure, void *rvalue, + unsigned long *pgr, ffi_dblfl *pfr) +{ + return ffi_closure_helper_common (closure->cif, closure->fun, + closure, rvalue, pgr, pfr); +} +#endif diff --git a/native/libffi/src/powerpc/ffi_linux64.c b/native/libffi/src/powerpc/ffi_linux64.c index b087af8c60..d97eef16de 100644 --- a/native/libffi/src/powerpc/ffi_linux64.c +++ b/native/libffi/src/powerpc/ffi_linux64.c @@ -38,7 +38,12 @@ /* About the LINUX64 ABI. */ enum { NUM_GPR_ARG_REGISTERS64 = 8, +<<<<<<< HEAD NUM_FPR_ARG_REGISTERS64 = 13 +======= + NUM_FPR_ARG_REGISTERS64 = 13, + NUM_VEC_ARG_REGISTERS64 = 12, +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 }; enum { ASM_NEEDS_REGISTERS64 = 4 }; @@ -62,12 +67,41 @@ ffi_prep_types_linux64 (ffi_abi abi) #endif +<<<<<<< HEAD #if _CALL_ELF == 2 static unsigned int discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum) { switch (t->type) { +======= +static unsigned int +discover_homogeneous_aggregate (ffi_abi abi, + const ffi_type *t, + unsigned int *elnum) +{ + switch (t->type) + { +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + case FFI_TYPE_LONGDOUBLE: + /* 64-bit long doubles are equivalent to doubles. */ + if ((abi & FFI_LINUX_LONG_DOUBLE_128) == 0) + { + *elnum = 1; + return FFI_TYPE_DOUBLE; + } + /* IBM extended precision values use unaligned pairs + of FPRs, but according to the ABI must be considered + distinct from doubles. They are also limited to a + maximum of four members in a homogeneous aggregate. */ + else if ((abi & FFI_LINUX_LONG_DOUBLE_IEEE128) == 0) + { + *elnum = 2; + return FFI_TYPE_LONGDOUBLE; + } + /* Fall through. */ +#endif +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 case FFI_TYPE_FLOAT: case FFI_TYPE_DOUBLE: *elnum = 1; @@ -80,14 +114,28 @@ discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum) while (*el) { unsigned int el_elt, el_elnum = 0; +<<<<<<< HEAD el_elt = discover_homogeneous_aggregate (*el, &el_elnum); +======= + el_elt = discover_homogeneous_aggregate (abi, *el, &el_elnum); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 if (el_elt == 0 || (base_elt && base_elt != el_elt)) return 0; base_elt = el_elt; total_elnum += el_elnum; +<<<<<<< HEAD + if (total_elnum > 8) + return 0; +======= +#if _CALL_ELF == 2 if (total_elnum > 8) return 0; +#else + if (total_elnum > 1) + return 0; +#endif +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 el++; } *elnum = total_elnum; @@ -98,7 +146,10 @@ discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum) return 0; } } +<<<<<<< HEAD #endif +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 /* Perform machine dependent cif processing */ @@ -107,6 +158,7 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) { ffi_type **ptr; unsigned bytes; +<<<<<<< HEAD unsigned i, fparg_count = 0, intarg_count = 0; unsigned flags = cif->flags; #if _CALL_ELF == 2 @@ -116,6 +168,25 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) #if FFI_TYPE_LONGDOUBLE == FFI_TYPE_DOUBLE /* If compiled without long double support.. */ if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) +======= + unsigned i, fparg_count = 0, intarg_count = 0, vecarg_count = 0; + unsigned flags = cif->flags; + unsigned elt, elnum, rtype; + +#if FFI_TYPE_LONGDOUBLE == FFI_TYPE_DOUBLE + /* If compiled without long double support... */ + if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0 || + (cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) + return FFI_BAD_ABI; +#elif !defined(__VEC__) + /* If compiled without vector register support (used by assembly)... */ + if ((cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) + return FFI_BAD_ABI; +#else + /* If the IEEE128 flag is set, but long double is only 64 bits wide... */ + if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) == 0 && + (cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 return FFI_BAD_ABI; #endif @@ -137,10 +208,26 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) #endif /* Return value handling. */ +<<<<<<< HEAD switch (cif->rtype->type) { #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE case FFI_TYPE_LONGDOUBLE: +======= + rtype = cif->rtype->type; +#if _CALL_ELF == 2 +homogeneous: +#endif + switch (rtype) + { +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + case FFI_TYPE_LONGDOUBLE: + if ((cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) + { + flags |= FLAG_RETURNS_VEC; + break; + } +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) flags |= FLAG_RETURNS_128BITS; /* Fall through. */ @@ -157,11 +244,16 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) /* Fall through. */ case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: +<<<<<<< HEAD +======= + case FFI_TYPE_POINTER: +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 flags |= FLAG_RETURNS_64BITS; break; case FFI_TYPE_STRUCT: #if _CALL_ELF == 2 +<<<<<<< HEAD elt = discover_homogeneous_aggregate (cif->rtype, &elnum); if (elt) { @@ -175,6 +267,20 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) flags |= FLAG_RETURNS_SMST; break; } +======= + elt = discover_homogeneous_aggregate (cif->abi, cif->rtype, &elnum); + if (elt) + { + flags |= FLAG_RETURNS_SMST; + rtype = elt; + goto homogeneous; + } + if (cif->rtype->size <= 16) + { + flags |= FLAG_RETURNS_SMST; + break; + } +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #endif intarg_count++; flags |= FLAG_RETVAL_REFERENCE; @@ -196,6 +302,18 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) { #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE case FFI_TYPE_LONGDOUBLE: +<<<<<<< HEAD +======= + if ((cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) + { + vecarg_count++; + /* Align to 16 bytes, plus the 16-byte argument. */ + intarg_count = (intarg_count + 3) & ~0x1; + if (vecarg_count > NUM_VEC_ARG_REGISTERS64) + flags |= FLAG_ARG_NEEDS_PSAVE; + break; + } +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) { fparg_count++; @@ -219,11 +337,29 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) align = 16; align = align / 8; if (align > 1) +<<<<<<< HEAD intarg_count = ALIGN (intarg_count, align); } intarg_count += ((*ptr)->size + 7) / 8; #if _CALL_ELF == 2 elt = discover_homogeneous_aggregate (*ptr, &elnum); +======= + intarg_count = FFI_ALIGN (intarg_count, align); + } + intarg_count += ((*ptr)->size + 7) / 8; + elt = discover_homogeneous_aggregate (cif->abi, *ptr, &elnum); +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + if (elt == FFI_TYPE_LONGDOUBLE && + (cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) + { + vecarg_count += elnum; + if (vecarg_count > NUM_VEC_ARG_REGISTERS64) + flags |= FLAG_ARG_NEEDS_PSAVE; + break; + } + else +#endif +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 if (elt) { fparg_count += elnum; @@ -231,7 +367,10 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) flags |= FLAG_ARG_NEEDS_PSAVE; } else +<<<<<<< HEAD #endif +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 { if (intarg_count > NUM_GPR_ARG_REGISTERS64) flags |= FLAG_ARG_NEEDS_PSAVE; @@ -263,10 +402,23 @@ ffi_prep_cif_linux64_core (ffi_cif *cif) flags |= FLAG_FP_ARGUMENTS; if (intarg_count > 4) flags |= FLAG_4_GPR_ARGUMENTS; +<<<<<<< HEAD +======= + if (vecarg_count != 0) + flags |= FLAG_VEC_ARGUMENTS; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 /* Space for the FPR registers, if needed. */ if (fparg_count != 0) bytes += NUM_FPR_ARG_REGISTERS64 * sizeof (double); +<<<<<<< HEAD +======= + /* Space for the vector registers, if needed, aligned to 16 bytes. */ + if (vecarg_count != 0) { + bytes = (bytes + 15) & ~0xF; + bytes += NUM_VEC_ARG_REGISTERS64 * sizeof (float128); + } +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 /* Stack space. */ #if _CALL_ELF == 2 @@ -349,6 +501,11 @@ ffi_prep_cif_linux64_var (ffi_cif *cif, |--------------------------------------------| | | FPR registers f1-f13 (optional) 13*8 | | |--------------------------------------------| | +<<<<<<< HEAD +======= + | VEC registers v2-v13 (optional) 12*16 | | + |--------------------------------------------| | +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 | Parameter save area | | |--------------------------------------------| | | TOC save area 8 | | @@ -378,6 +535,10 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) unsigned long *ul; float *f; double *d; +<<<<<<< HEAD +======= + float128 *f128; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 size_t p; } valp; @@ -391,11 +552,23 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) valp rest; valp next_arg; +<<<<<<< HEAD /* 'fpr_base' points at the space for fpr3, and grows upwards as +======= + /* 'fpr_base' points at the space for f1, and grows upwards as +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 we use FPR registers. */ valp fpr_base; unsigned int fparg_count; +<<<<<<< HEAD +======= + /* 'vec_base' points at the space for v2, and grows upwards as + we use vector registers. */ + valp vec_base; + unsigned int vecarg_count; + +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 unsigned int i, words, nargs, nfixedargs; ffi_type **ptr; double double_tmp; @@ -412,6 +585,10 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) unsigned long **ul; float **f; double **d; +<<<<<<< HEAD +======= + float128 **f128; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 } p_argv; unsigned long gprvalue; unsigned long align; @@ -426,11 +603,27 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) #endif fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS64; fparg_count = 0; +<<<<<<< HEAD +======= + /* Place the vector args below the FPRs, if used, else the GPRs. */ + if (ecif->cif->flags & FLAG_FP_ARGUMENTS) + vec_base.p = fpr_base.p & ~0xF; + else + vec_base.p = gpr_base.p; + vec_base.f128 -= NUM_VEC_ARG_REGISTERS64; + vecarg_count = 0; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 next_arg.ul = gpr_base.ul; /* Check that everything starts aligned properly. */ FFI_ASSERT (((unsigned long) (char *) stack & 0xF) == 0); FFI_ASSERT (((unsigned long) stacktop.c & 0xF) == 0); +<<<<<<< HEAD +======= + FFI_ASSERT (((unsigned long) gpr_base.c & 0xF) == 0); + FFI_ASSERT (((unsigned long) gpr_end.c & 0xF) == 0); + FFI_ASSERT (((unsigned long) vec_base.c & 0xF) == 0); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 FFI_ASSERT ((bytes & 0xF) == 0); /* Deal with return values that are actually pass-by-reference. */ @@ -449,14 +642,37 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) i < nargs; i++, ptr++, p_argv.v++) { +<<<<<<< HEAD #if _CALL_ELF == 2 unsigned int elt, elnum; #endif +======= + unsigned int elt, elnum; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 switch ((*ptr)->type) { #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE case FFI_TYPE_LONGDOUBLE: +<<<<<<< HEAD +======= + if ((ecif->cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) + { + next_arg.p = FFI_ALIGN (next_arg.p, 16); + if (next_arg.ul == gpr_end.ul) + next_arg.ul = rest.ul; + if (vecarg_count < NUM_VEC_ARG_REGISTERS64 && i < nfixedargs) + memcpy (vec_base.f128++, *p_argv.f128, sizeof (float128)); + else + memcpy (next_arg.f128, *p_argv.f128, sizeof (float128)); + if (++next_arg.f128 == gpr_end.f128) + next_arg.f128 = rest.f128; + vecarg_count++; + FFI_ASSERT (__LDBL_MANT_DIG__ == 113); + FFI_ASSERT (flags & FLAG_VEC_ARGUMENTS); + break; + } +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 if ((ecif->cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) { double_tmp = (*p_argv.d)[0]; @@ -494,6 +710,12 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) /* Fall through. */ #endif case FFI_TYPE_DOUBLE: +<<<<<<< HEAD +======= +#if _CALL_ELF != 2 + do_double: +#endif +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 double_tmp = **p_argv.d; if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) { @@ -512,17 +734,43 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) break; case FFI_TYPE_FLOAT: +<<<<<<< HEAD +======= +#if _CALL_ELF != 2 + do_float: +#endif +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 double_tmp = **p_argv.f; if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs) { *fpr_base.d++ = double_tmp; #if _CALL_ELF != 2 if ((flags & FLAG_COMPAT) != 0) +<<<<<<< HEAD *next_arg.f = (float) double_tmp; #endif } else *next_arg.f = (float) double_tmp; +======= + { +# ifndef __LITTLE_ENDIAN__ + next_arg.f[1] = (float) double_tmp; +# else + next_arg.f[0] = (float) double_tmp; +# endif + } +#endif + } + else + { +# ifndef __LITTLE_ENDIAN__ + next_arg.f[1] = (float) double_tmp; +# else + next_arg.f[0] = (float) double_tmp; +# endif + } +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 if (++next_arg.ul == gpr_end.ul) next_arg.ul = rest.ul; fparg_count++; @@ -536,19 +784,58 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) if (align > 16) align = 16; if (align > 1) +<<<<<<< HEAD next_arg.p = ALIGN (next_arg.p, align); } #if _CALL_ELF == 2 elt = discover_homogeneous_aggregate (*ptr, &elnum); if (elt) { +======= + { + next_arg.p = FFI_ALIGN (next_arg.p, align); + if (next_arg.ul == gpr_end.ul) + next_arg.ul = rest.ul; + } + } + elt = discover_homogeneous_aggregate (ecif->cif->abi, *ptr, &elnum); + if (elt) + { +#if _CALL_ELF == 2 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 union { void *v; float *f; double *d; +<<<<<<< HEAD } arg; arg.v = *p_argv.v; +======= + float128 *f128; + } arg; + + arg.v = *p_argv.v; +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + if (elt == FFI_TYPE_LONGDOUBLE && + (ecif->cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) + { + do + { + if (vecarg_count < NUM_VEC_ARG_REGISTERS64 + && i < nfixedargs) + memcpy (vec_base.f128++, arg.f128, sizeof (float128)); + else + memcpy (next_arg.f128, arg.f128++, sizeof (float128)); + if (++next_arg.f128 == gpr_end.f128) + next_arg.f128 = rest.f128; + vecarg_count++; + } + while (--elnum != 0); + } + else +#endif +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 if (elt == FFI_TYPE_FLOAT) { do @@ -564,11 +851,17 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) fparg_count++; } while (--elnum != 0); +<<<<<<< HEAD if ((next_arg.p & 3) != 0) { if (++next_arg.f == gpr_end.f) next_arg.f = rest.f; } +======= + if ((next_arg.p & 7) != 0) + if (++next_arg.f == gpr_end.f) + next_arg.f = rest.f; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 } else do @@ -583,9 +876,20 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack) fparg_count++; } while (--elnum != 0); +<<<<<<< HEAD } else #endif +======= +#else + if (elt == FFI_TYPE_FLOAT) + goto do_float; + else + goto do_double; +#endif + } + else +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 { words = ((*ptr)->size + 7) / 8; if (next_arg.ul >= gpr_base.ul && next_arg.ul + words > gpr_end.ul) @@ -667,7 +971,12 @@ flush_icache (char *wraddr, char *xaddr, int size) } #endif +<<<<<<< HEAD ffi_status +======= + +ffi_status FFI_HIDDEN +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 ffi_prep_closure_loc_linux64 (ffi_closure *closure, ffi_cif *cif, void (*fun) (ffi_cif *, void *, void **, void *), @@ -688,17 +997,28 @@ ffi_prep_closure_loc_linux64 (ffi_closure *closure, /* 2: .quad context */ *(void **) &tramp[4] = (void *) ffi_closure_LINUX64; *(void **) &tramp[6] = codeloc; +<<<<<<< HEAD flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE); +======= + flush_icache ((char *) tramp, (char *) codeloc, 4 * 4); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #else void **tramp = (void **) &closure->tramp[0]; if (cif->abi < FFI_LINUX || cif->abi >= FFI_LAST_ABI) return FFI_BAD_ABI; +<<<<<<< HEAD /* Copy function address and TOC from ffi_closure_LINUX64. */ memcpy (tramp, (char *) ffi_closure_LINUX64, 16); tramp[2] = tramp[1]; tramp[1] = codeloc; +======= + /* Copy function address and TOC from ffi_closure_LINUX64 OPD. */ + memcpy (&tramp[0], (void **) ffi_closure_LINUX64, sizeof (void *)); + tramp[1] = codeloc; + memcpy (&tramp[2], (void **) ffi_closure_LINUX64 + 1, sizeof (void *)); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #endif closure->cif = cif; @@ -710,22 +1030,43 @@ ffi_prep_closure_loc_linux64 (ffi_closure *closure, int FFI_HIDDEN +<<<<<<< HEAD ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, unsigned long *pst, ffi_dblfl *pfr) +======= +ffi_closure_helper_LINUX64 (ffi_cif *cif, + void (*fun) (ffi_cif *, void *, void **, void *), + void *user_data, + void *rvalue, + unsigned long *pst, + ffi_dblfl *pfr, + float128 *pvec) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 { /* rvalue is the pointer to space for return value in closure assembly */ /* pst is the pointer to parameter save area (r3-r10 are stored into its first 8 slots by ffi_closure_LINUX64) */ /* pfr is the pointer to where f1-f13 are stored in ffi_closure_LINUX64 */ +<<<<<<< HEAD +======= + /* pvec is the pointer to where v2-v13 are stored in ffi_closure_LINUX64 */ +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 void **avalue; ffi_type **arg_types; unsigned long i, avn, nfixedargs; +<<<<<<< HEAD ffi_cif *cif; ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64; unsigned long align; cif = closure->cif; +======= + ffi_dblfl *end_pfr = pfr + NUM_FPR_ARG_REGISTERS64; + float128 *end_pvec = pvec + NUM_VEC_ARG_REGISTERS64; + unsigned long align; + +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 avalue = alloca (cif->nargs * sizeof (void *)); /* Copy the caller's structure return value address so that the @@ -791,6 +1132,7 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, if (align > 16) align = 16; if (align > 1) +<<<<<<< HEAD pst = (unsigned long *) ALIGN ((size_t) pst, align); } elt = 0; @@ -799,11 +1141,23 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, #endif if (elt) { +======= + pst = (unsigned long *) FFI_ALIGN ((size_t) pst, align); + } + elt = discover_homogeneous_aggregate (cif->abi, arg_types[i], &elnum); + if (elt) + { +#if _CALL_ELF == 2 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 union { void *v; unsigned long *ul; float *f; double *d; +<<<<<<< HEAD +======= + float128 *f128; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 size_t p; } to, from; @@ -811,6 +1165,20 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, aggregate size is not greater than the space taken by the registers so store back to the register/parameter save arrays. */ +<<<<<<< HEAD +======= +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + if (elt == FFI_TYPE_LONGDOUBLE && + (cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) + { + if (pvec + elnum <= end_pvec) + to.v = pvec; + else + to.v = pst; + } + else +#endif +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 if (pfr + elnum <= end_pfr) to.v = pfr; else @@ -818,6 +1186,26 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, avalue[i] = to.v; from.ul = pst; +<<<<<<< HEAD +======= +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + if (elt == FFI_TYPE_LONGDOUBLE && + (cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) + { + do + { + if (pvec < end_pvec && i < nfixedargs) + memcpy (to.f128, pvec++, sizeof (float128)); + else + memcpy (to.f128, from.f128, sizeof (float128)); + to.f128++; + from.f128++; + } + while (--elnum != 0); + } + else +#endif +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 if (elt == FFI_TYPE_FLOAT) { do @@ -850,6 +1238,15 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, } while (--elnum != 0); } +<<<<<<< HEAD +======= +#else + if (elt == FFI_TYPE_FLOAT) + goto do_float; + else + goto do_double; +#endif +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 } else { @@ -867,7 +1264,22 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE case FFI_TYPE_LONGDOUBLE: +<<<<<<< HEAD if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) +======= + if ((cif->abi & FFI_LINUX_LONG_DOUBLE_IEEE128) != 0) + { + if (((unsigned long) pst & 0xF) != 0) + ++pst; + if (pvec < end_pvec && i < nfixedargs) + avalue[i] = pvec++; + else + avalue[i] = pst; + pst += 2; + break; + } + else if ((cif->abi & FFI_LINUX_LONG_DOUBLE_128) != 0) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 { if (pfr + 1 < end_pfr && i + 1 < nfixedargs) { @@ -891,6 +1303,12 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, /* Fall through. */ #endif case FFI_TYPE_DOUBLE: +<<<<<<< HEAD +======= +#if _CALL_ELF != 2 + do_double: +#endif +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 /* On the outgoing stack all values are aligned to 8 */ /* there are 13 64bit floating point registers */ @@ -905,6 +1323,12 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, break; case FFI_TYPE_FLOAT: +<<<<<<< HEAD +======= +#if _CALL_ELF != 2 + do_float: +#endif +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 if (pfr < end_pfr && i < nfixedargs) { /* Float values are stored as doubles in the @@ -914,7 +1338,17 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, pfr++; } else +<<<<<<< HEAD avalue[i] = pst; +======= + { +#ifndef __LITTLE_ENDIAN__ + avalue[i] = (char *) pst + 4; +#else + avalue[i] = pst; +#endif + } +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 pst++; break; @@ -925,19 +1359,35 @@ ffi_closure_helper_LINUX64 (ffi_closure *closure, void *rvalue, i++; } +<<<<<<< HEAD (closure->fun) (cif, rvalue, avalue, closure->user_data); +======= + (*fun) (cif, rvalue, avalue, user_data); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 /* Tell ffi_closure_LINUX64 how to perform return type promotions. */ if ((cif->flags & FLAG_RETURNS_SMST) != 0) { +<<<<<<< HEAD if ((cif->flags & FLAG_RETURNS_FP) == 0) return FFI_V2_TYPE_SMALL_STRUCT + cif->rtype->size - 1; +======= + if ((cif->flags & (FLAG_RETURNS_FP | FLAG_RETURNS_VEC)) == 0) + return FFI_V2_TYPE_SMALL_STRUCT + cif->rtype->size - 1; + else if ((cif->flags & FLAG_RETURNS_VEC) != 0) + return FFI_V2_TYPE_VECTOR_HOMOG; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 else if ((cif->flags & FLAG_RETURNS_64BITS) != 0) return FFI_V2_TYPE_DOUBLE_HOMOG; else return FFI_V2_TYPE_FLOAT_HOMOG; } +<<<<<<< HEAD +======= + if ((cif->flags & FLAG_RETURNS_VEC) != 0) + return FFI_V2_TYPE_VECTOR; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 return cif->rtype->type; } #endif diff --git a/native/libffi/src/powerpc/ffi_powerpc.h b/native/libffi/src/powerpc/ffi_powerpc.h index 2e61653d1a..96dd6d3f56 100644 --- a/native/libffi/src/powerpc/ffi_powerpc.h +++ b/native/libffi/src/powerpc/ffi_powerpc.h @@ -31,6 +31,7 @@ enum { /* The assembly depends on these exact flags. */ /* These go in cr7 */ +<<<<<<< HEAD FLAG_RETURNS_SMST = 1 << (31-31), /* Used for FFI_SYSV small structs. */ FLAG_RETURNS_NOTHING = 1 << (31-30), FLAG_RETURNS_FP = 1 << (31-29), @@ -40,13 +41,30 @@ enum { FLAG_RETURNS_128BITS = 1 << (31-27), FLAG_COMPAT = 1 << (31- 8), /* Not used by assembly */ +======= + FLAG_RETURNS_SMST = 1 << (31-31), /* Used for FFI_SYSV small structs. */ + FLAG_RETURNS_NOTHING = 1 << (31-30), + FLAG_RETURNS_FP = 1 << (31-29), + FLAG_RETURNS_VEC = 1 << (31-28), + + /* These go in cr6 */ + FLAG_RETURNS_64BITS = 1 << (31-27), + FLAG_RETURNS_128BITS = 1 << (31-26), + + FLAG_COMPAT = 1 << (31- 8), /* Not used by assembly */ +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 /* These go in cr1 */ FLAG_ARG_NEEDS_COPY = 1 << (31- 7), /* Used by sysv code */ FLAG_ARG_NEEDS_PSAVE = FLAG_ARG_NEEDS_COPY, /* Used by linux64 code */ FLAG_FP_ARGUMENTS = 1 << (31- 6), /* cr1.eq; specified by ABI */ FLAG_4_GPR_ARGUMENTS = 1 << (31- 5), +<<<<<<< HEAD FLAG_RETVAL_REFERENCE = 1 << (31- 4) +======= + FLAG_RETVAL_REFERENCE = 1 << (31- 4), + FLAG_VEC_ARGUMENTS = 1 << (31- 3), +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 }; typedef union @@ -55,6 +73,7 @@ typedef union double d; } ffi_dblfl; +<<<<<<< HEAD void FFI_HIDDEN ffi_closure_SYSV (void); void FFI_HIDDEN ffi_call_SYSV(extended_cif *, unsigned, unsigned, unsigned *, void (*)(void)); @@ -67,11 +86,56 @@ int FFI_HIDDEN ffi_closure_helper_SYSV (ffi_closure *, void *, unsigned long *, void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, unsigned long, unsigned long, unsigned long *, void (*)(void)); void FFI_HIDDEN ffi_closure_LINUX64 (void); +======= +#if defined(__FLOAT128_TYPE__) && defined(__HAVE_FLOAT128) +typedef _Float128 float128; +#elif defined(__FLOAT128__) +typedef __float128 float128; +#else +typedef char float128[16] __attribute__((aligned(16))); +#endif + +void FFI_HIDDEN ffi_closure_SYSV (void); +void FFI_HIDDEN ffi_go_closure_sysv (void); +void FFI_HIDDEN ffi_call_SYSV(extended_cif *, void (*)(void), void *, + unsigned, void *, int); + +void FFI_HIDDEN ffi_prep_types_sysv (ffi_abi); +ffi_status FFI_HIDDEN ffi_prep_cif_sysv (ffi_cif *); +ffi_status FFI_HIDDEN ffi_prep_closure_loc_sysv (ffi_closure *, + ffi_cif *, + void (*) (ffi_cif *, void *, + void **, void *), + void *, void *); +int FFI_HIDDEN ffi_closure_helper_SYSV (ffi_cif *, + void (*) (ffi_cif *, void *, + void **, void *), + void *, void *, unsigned long *, + ffi_dblfl *, unsigned long *); + +void FFI_HIDDEN ffi_call_LINUX64(extended_cif *, void (*) (void), void *, + unsigned long, void *, long); +void FFI_HIDDEN ffi_closure_LINUX64 (void); +void FFI_HIDDEN ffi_go_closure_linux64 (void); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 void FFI_HIDDEN ffi_prep_types_linux64 (ffi_abi); ffi_status FFI_HIDDEN ffi_prep_cif_linux64 (ffi_cif *); ffi_status FFI_HIDDEN ffi_prep_cif_linux64_var (ffi_cif *, unsigned int, unsigned int); void FFI_HIDDEN ffi_prep_args64 (extended_cif *, unsigned long *const); +<<<<<<< HEAD int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_closure *, void *, unsigned long *, ffi_dblfl *); +======= +ffi_status FFI_HIDDEN ffi_prep_closure_loc_linux64 (ffi_closure *, ffi_cif *, + void (*) (ffi_cif *, void *, + void **, void *), + void *, void *); +int FFI_HIDDEN ffi_closure_helper_LINUX64 (ffi_cif *, + void (*) (ffi_cif *, void *, + void **, void *), + void *, void *, + unsigned long *, ffi_dblfl *, + float128 *); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 diff --git a/native/libffi/src/powerpc/ffi_sysv.c b/native/libffi/src/powerpc/ffi_sysv.c index fbe85fe914..38e269acc7 100644 --- a/native/libffi/src/powerpc/ffi_sysv.c +++ b/native/libffi/src/powerpc/ffi_sysv.c @@ -36,7 +36,11 @@ /* About the SYSV ABI. */ +<<<<<<< HEAD #define ASM_NEEDS_REGISTERS 4 +======= +#define ASM_NEEDS_REGISTERS 6 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #define NUM_GPR_ARG_REGISTERS 8 #define NUM_FPR_ARG_REGISTERS 8 @@ -93,7 +97,11 @@ ffi_prep_cif_sysv_core (ffi_cif *cif) { ffi_type **ptr; unsigned bytes; +<<<<<<< HEAD unsigned i, fparg_count = 0, intarg_count = 0; +======= + unsigned i, fpr_count = 0, gpr_count = 0, stack_count = 0; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 unsigned flags = cif->flags; unsigned struct_copy_size = 0; unsigned type = cif->rtype->type; @@ -155,7 +163,11 @@ ffi_prep_cif_sysv_core (ffi_cif *cif) flags |= FLAG_RETURNS_SMST; break; } +<<<<<<< HEAD intarg_count++; +======= + gpr_count++; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 flags |= FLAG_RETVAL_REFERENCE; /* Fall through. */ case FFI_TYPE_VOID: @@ -182,6 +194,7 @@ ffi_prep_cif_sysv_core (ffi_cif *cif) { #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE case FFI_TYPE_LONGDOUBLE: +<<<<<<< HEAD fparg_count++; /* Fall thru */ #endif @@ -193,13 +206,47 @@ ffi_prep_cif_sysv_core (ffi_cif *cif) && intarg_count >= NUM_GPR_ARG_REGISTERS && intarg_count % 2 != 0) intarg_count++; +======= + if (fpr_count >= NUM_FPR_ARG_REGISTERS - 1) + { + fpr_count = NUM_FPR_ARG_REGISTERS; + /* 8-byte align long doubles. */ + stack_count += stack_count & 1; + stack_count += 4; + } + else + fpr_count += 2; +#ifdef __NO_FPRS__ + return FFI_BAD_ABI; +#endif + break; +#endif + + case FFI_TYPE_DOUBLE: + if (fpr_count >= NUM_FPR_ARG_REGISTERS) + { + /* 8-byte align doubles. */ + stack_count += stack_count & 1; + stack_count += 2; + } + else + fpr_count += 1; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #ifdef __NO_FPRS__ return FFI_BAD_ABI; #endif break; case FFI_TYPE_FLOAT: +<<<<<<< HEAD fparg_count++; +======= + if (fpr_count >= NUM_FPR_ARG_REGISTERS) + /* Yes, we don't follow the ABI, but neither does gcc. */ + stack_count += 1; + else + fpr_count += 1; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #ifdef __NO_FPRS__ return FFI_BAD_ABI; #endif @@ -208,11 +255,21 @@ ffi_prep_cif_sysv_core (ffi_cif *cif) case FFI_TYPE_UINT128: /* A long double in FFI_LINUX_SOFT_FLOAT can use only a set of four consecutive gprs. If we do not have enough, we +<<<<<<< HEAD have to adjust the intarg_count value. */ if (intarg_count >= NUM_GPR_ARG_REGISTERS - 3 && intarg_count < NUM_GPR_ARG_REGISTERS) intarg_count = NUM_GPR_ARG_REGISTERS; intarg_count += 4; +======= + have to adjust the gpr_count value. */ + if (gpr_count >= NUM_GPR_ARG_REGISTERS - 3) + gpr_count = NUM_GPR_ARG_REGISTERS; + if (gpr_count >= NUM_GPR_ARG_REGISTERS) + stack_count += 4; + else + gpr_count += 4; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 break; case FFI_TYPE_UINT64: @@ -225,10 +282,21 @@ ffi_prep_cif_sysv_core (ffi_cif *cif) Also, only certain register pairs can be used for passing long long int -- specifically (r3,r4), (r5,r6), (r7,r8), (r9,r10). */ +<<<<<<< HEAD if (intarg_count == NUM_GPR_ARG_REGISTERS-1 || intarg_count % 2 != 0) intarg_count++; intarg_count += 2; +======= + gpr_count += gpr_count & 1; + if (gpr_count >= NUM_GPR_ARG_REGISTERS) + { + stack_count += stack_count & 1; + stack_count += 2; + } + else + gpr_count += 2; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 break; case FFI_TYPE_STRUCT: @@ -249,7 +317,14 @@ ffi_prep_cif_sysv_core (ffi_cif *cif) case FFI_TYPE_SINT8: /* Everything else is passed as a 4-byte word in a GPR, either the object itself or a pointer to it. */ +<<<<<<< HEAD intarg_count++; +======= + if (gpr_count >= NUM_GPR_ARG_REGISTERS) + stack_count += 1; + else + gpr_count += 1; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 break; default: @@ -257,14 +332,21 @@ ffi_prep_cif_sysv_core (ffi_cif *cif) } } +<<<<<<< HEAD if (fparg_count != 0) flags |= FLAG_FP_ARGUMENTS; if (intarg_count > 4) +======= + if (fpr_count != 0) + flags |= FLAG_FP_ARGUMENTS; + if (gpr_count > 4) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 flags |= FLAG_4_GPR_ARGUMENTS; if (struct_copy_size != 0) flags |= FLAG_ARG_NEEDS_COPY; /* Space for the FPR registers, if needed. */ +<<<<<<< HEAD if (fparg_count != 0) bytes += NUM_FPR_ARG_REGISTERS * sizeof (double); @@ -273,6 +355,13 @@ ffi_prep_cif_sysv_core (ffi_cif *cif) bytes += (intarg_count - NUM_GPR_ARG_REGISTERS) * sizeof (int); if (fparg_count > NUM_FPR_ARG_REGISTERS) bytes += (fparg_count - NUM_FPR_ARG_REGISTERS) * sizeof (double); +======= + if (fpr_count != 0) + bytes += NUM_FPR_ARG_REGISTERS * sizeof (double); + + /* Stack space. */ + bytes += stack_count * sizeof (int); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 /* The stack space allocated needs to be a multiple of 16 bytes. */ bytes = (bytes + 15) & ~0xF; @@ -367,13 +456,21 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack) /* 'gpr_base' points at the space for gpr3, and grows upwards as we use GPR registers. */ valp gpr_base; +<<<<<<< HEAD int intarg_count; +======= + valp gpr_end; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #ifndef __NO_FPRS__ /* 'fpr_base' points at the space for fpr1, and grows upwards as we use FPR registers. */ valp fpr_base; +<<<<<<< HEAD int fparg_count; +======= + valp fpr_end; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #endif /* 'copy_space' grows down as we put structures in it. It should @@ -405,11 +502,19 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack) unsigned gprvalue; stacktop.c = (char *) stack + bytes; +<<<<<<< HEAD gpr_base.u = stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS; intarg_count = 0; #ifndef __NO_FPRS__ fpr_base.d = gpr_base.d - NUM_FPR_ARG_REGISTERS; fparg_count = 0; +======= + gpr_end.u = stacktop.u - ASM_NEEDS_REGISTERS; + gpr_base.u = gpr_end.u - NUM_GPR_ARG_REGISTERS; +#ifndef __NO_FPRS__ + fpr_end.d = gpr_base.d; + fpr_base.d = fpr_end.d - NUM_FPR_ARG_REGISTERS; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 copy_space.c = ((flags & FLAG_FP_ARGUMENTS) ? fpr_base.c : gpr_base.c); #else copy_space.c = gpr_base.c; @@ -425,10 +530,14 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack) /* Deal with return values that are actually pass-by-reference. */ if (flags & FLAG_RETVAL_REFERENCE) +<<<<<<< HEAD { *gpr_base.u++ = (unsigned long) (char *) ecif->rvalue; intarg_count++; } +======= + *gpr_base.u++ = (unsigned) (char *) ecif->rvalue; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 /* Now for the arguments. */ p_argv.v = ecif->avalue; @@ -448,6 +557,7 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack) case FFI_TYPE_LONGDOUBLE: double_tmp = (*p_argv.d)[0]; +<<<<<<< HEAD if (fparg_count >= NUM_FPR_ARG_REGISTERS - 1) { if (intarg_count >= NUM_GPR_ARG_REGISTERS @@ -456,6 +566,13 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack) intarg_count++; next_arg.u++; } +======= + if (fpr_base.d >= fpr_end.d - 1) + { + fpr_base.d = fpr_end.d; + if (((next_arg.u - stack) & 1) != 0) + next_arg.u += 1; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 *next_arg.d = double_tmp; next_arg.u += 2; double_tmp = (*p_argv.d)[1]; @@ -468,14 +585,18 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack) double_tmp = (*p_argv.d)[1]; *fpr_base.d++ = double_tmp; } +<<<<<<< HEAD fparg_count += 2; +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 FFI_ASSERT (flags & FLAG_FP_ARGUMENTS); break; # endif case FFI_TYPE_DOUBLE: double_tmp = **p_argv.d; +<<<<<<< HEAD if (fparg_count >= NUM_FPR_ARG_REGISTERS) { if (intarg_count >= NUM_GPR_ARG_REGISTERS @@ -484,17 +605,27 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack) intarg_count++; next_arg.u++; } +======= + if (fpr_base.d >= fpr_end.d) + { + if (((next_arg.u - stack) & 1) != 0) + next_arg.u += 1; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 *next_arg.d = double_tmp; next_arg.u += 2; } else *fpr_base.d++ = double_tmp; +<<<<<<< HEAD fparg_count++; +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 FFI_ASSERT (flags & FLAG_FP_ARGUMENTS); break; case FFI_TYPE_FLOAT: double_tmp = **p_argv.f; +<<<<<<< HEAD if (fparg_count >= NUM_FPR_ARG_REGISTERS) { *next_arg.f = (float) double_tmp; @@ -504,6 +635,15 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack) else *fpr_base.d++ = double_tmp; fparg_count++; +======= + if (fpr_base.d >= fpr_end.d) + { + *next_arg.f = (float) double_tmp; + next_arg.u += 1; + } + else + *fpr_base.d++ = double_tmp; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 FFI_ASSERT (flags & FLAG_FP_ARGUMENTS); break; #endif /* have FPRs */ @@ -513,6 +653,7 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack) is passed in four consecutive GPRs if available. A maximum of 2 long doubles can be passed in gprs. If we do not have 4 GPRs left, the long double is passed on the stack, 4-byte aligned. */ +<<<<<<< HEAD { unsigned int int_tmp; unsigned int ii; @@ -549,6 +690,36 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack) intarg_count++; next_arg.u++; } +======= + if (gpr_base.u >= gpr_end.u - 3) + { + unsigned int ii; + gpr_base.u = gpr_end.u; + for (ii = 0; ii < 4; ii++) + { + unsigned int int_tmp = (*p_argv.ui)[ii]; + *next_arg.u++ = int_tmp; + } + } + else + { + unsigned int ii; + for (ii = 0; ii < 4; ii++) + { + unsigned int int_tmp = (*p_argv.ui)[ii]; + *gpr_base.u++ = int_tmp; + } + } + break; + + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: + if (gpr_base.u >= gpr_end.u - 1) + { + gpr_base.u = gpr_end.u; + if (((next_arg.u - stack) & 1) != 0) + next_arg.u++; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 *next_arg.ll = **p_argv.ll; next_arg.u += 2; } @@ -559,6 +730,7 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack) (r5,r6), (r7,r8), (r9,r10). If next arg is long long but not correct starting register of pair then skip until the proper starting register. */ +<<<<<<< HEAD if (intarg_count % 2 != 0) { intarg_count ++; @@ -567,6 +739,12 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack) *gpr_base.ll++ = **p_argv.ll; } intarg_count += 2; +======= + if (((gpr_end.u - gpr_base.u) & 1) != 0) + gpr_base.u++; + *gpr_base.ll++ = **p_argv.ll; + } +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 break; case FFI_TYPE_STRUCT: @@ -601,17 +779,25 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack) gprvalue = **p_argv.ui; putgpr: +<<<<<<< HEAD if (intarg_count >= NUM_GPR_ARG_REGISTERS) *next_arg.u++ = gprvalue; else *gpr_base.u++ = gprvalue; intarg_count++; +======= + if (gpr_base.u >= gpr_end.u) + *next_arg.u++ = gprvalue; + else + *gpr_base.u++ = gprvalue; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 break; } } /* Check that we didn't overrun the stack... */ FFI_ASSERT (copy_space.c >= next_arg.c); +<<<<<<< HEAD FFI_ASSERT (gpr_base.u <= stacktop.u - ASM_NEEDS_REGISTERS); /* The assert below is testing that the number of integer arguments agrees with the number found in ffi_prep_cif_machdep(). However, intarg_count @@ -624,6 +810,14 @@ ffi_prep_args_SYSV (extended_cif *ecif, unsigned *const stack) <= stacktop.u - ASM_NEEDS_REGISTERS - NUM_GPR_ARG_REGISTERS); #endif FFI_ASSERT (flags & FLAG_4_GPR_ARGUMENTS || intarg_count <= 4); +======= + FFI_ASSERT (gpr_base.u <= gpr_end.u); +#ifndef __NO_FPRS__ + FFI_ASSERT (fpr_base.u <= fpr_end.u); +#endif + FFI_ASSERT (((flags & FLAG_4_GPR_ARGUMENTS) != 0) + == (gpr_end.u - gpr_base.u < 4)); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 } #define MIN_CACHE_LINE_SIZE 8 @@ -654,6 +848,7 @@ ffi_prep_closure_loc_sysv (ffi_closure *closure, tramp = (unsigned int *) &closure->tramp[0]; tramp[0] = 0x7c0802a6; /* mflr r0 */ +<<<<<<< HEAD tramp[1] = 0x4800000d; /* bl 10 */ tramp[4] = 0x7d6802a6; /* mflr r11 */ tramp[5] = 0x7c0803a6; /* mtlr r0 */ @@ -666,6 +861,20 @@ ffi_prep_closure_loc_sysv (ffi_closure *closure, /* Flush the icache. */ flush_icache ((char *)tramp, (char *)codeloc, FFI_TRAMPOLINE_SIZE); +======= + tramp[1] = 0x429f0005; /* bcl 20,31,.+4 */ + tramp[2] = 0x7d6802a6; /* mflr r11 */ + tramp[3] = 0x7c0803a6; /* mtlr r0 */ + tramp[4] = 0x800b0018; /* lwz r0,24(r11) */ + tramp[5] = 0x816b001c; /* lwz r11,28(r11) */ + tramp[6] = 0x7c0903a6; /* mtctr r0 */ + tramp[7] = 0x4e800420; /* bctr */ + *(void **) &tramp[8] = (void *) ffi_closure_SYSV; /* function */ + *(void **) &tramp[9] = codeloc; /* context */ + + /* Flush the icache. */ + flush_icache ((char *)tramp, (char *)codeloc, 8 * 4); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 closure->cif = cif; closure->fun = fun; @@ -682,8 +891,17 @@ ffi_prep_closure_loc_sysv (ffi_closure *closure, following helper function to do most of the work. */ int +<<<<<<< HEAD ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, unsigned long *pgr, ffi_dblfl *pfr, +======= +ffi_closure_helper_SYSV (ffi_cif *cif, + void (*fun) (ffi_cif *, void *, void **, void *), + void *user_data, + void *rvalue, + unsigned long *pgr, + ffi_dblfl *pfr, +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 unsigned long *pst) { /* rvalue is the pointer to space for return value in closure assembly */ @@ -699,7 +917,10 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, #endif long ng = 0; /* number of general registers already used */ +<<<<<<< HEAD ffi_cif *cif = closure->cif; +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 unsigned size = cif->rtype->size; unsigned short rtypenum = cif->rtype->type; @@ -915,7 +1136,11 @@ ffi_closure_helper_SYSV (ffi_closure *closure, void *rvalue, i++; } +<<<<<<< HEAD (closure->fun) (cif, rvalue, avalue, closure->user_data); +======= + (*fun) (cif, rvalue, avalue, user_data); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 /* Tell ffi_closure_SYSV how to perform return type promotions. Because the FFI_SYSV ABI returns the structures <= 8 bytes in diff --git a/native/libffi/src/powerpc/ffitarget.h b/native/libffi/src/powerpc/ffitarget.h index b47b0f5d3a..4f71b2cc25 100644 --- a/native/libffi/src/powerpc/ffitarget.h +++ b/native/libffi/src/powerpc/ffitarget.h @@ -91,15 +91,28 @@ typedef enum ffi_abi { /* This and following bits can reuse FFI_COMPAT values. */ FFI_LINUX_STRUCT_ALIGN = 1, FFI_LINUX_LONG_DOUBLE_128 = 2, +<<<<<<< HEAD +======= + FFI_LINUX_LONG_DOUBLE_IEEE128 = 4, +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 FFI_DEFAULT_ABI = (FFI_LINUX # ifdef __STRUCT_PARM_ALIGN__ | FFI_LINUX_STRUCT_ALIGN # endif # ifdef __LONG_DOUBLE_128__ | FFI_LINUX_LONG_DOUBLE_128 +<<<<<<< HEAD # endif ), FFI_LAST_ABI = 12 +======= +# ifdef __LONG_DOUBLE_IEEE128__ + | FFI_LINUX_LONG_DOUBLE_IEEE128 +# endif +# endif + ), + FFI_LAST_ABI = 16 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 # else /* This bit, always set in new code, must not be set in any of the @@ -138,16 +151,29 @@ typedef enum ffi_abi { #define FFI_CLOSURES 1 #define FFI_NATIVE_RAW_API 0 #if defined (POWERPC) || defined (POWERPC_FREEBSD) +<<<<<<< HEAD +# define FFI_TARGET_SPECIFIC_VARIADIC 1 +# define FFI_EXTRA_CIF_FIELDS unsigned nfixedargs +#endif +======= +# define FFI_GO_CLOSURES 1 # define FFI_TARGET_SPECIFIC_VARIADIC 1 # define FFI_EXTRA_CIF_FIELDS unsigned nfixedargs #endif +#if defined (POWERPC_AIX) +# define FFI_GO_CLOSURES 1 +#endif +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 -/* For additional types like the below, take care about the order in - ppc_closures.S. They must follow after the FFI_TYPE_LAST. */ +/* ppc_closure.S and linux64_closure.S expect this. */ +#define FFI_PPC_TYPE_LAST FFI_TYPE_POINTER -/* Needed for soft-float long-double-128 support. */ -#define FFI_TYPE_UINT128 (FFI_TYPE_LAST + 1) +/* We define additional types below. If generic types are added that + must be supported by powerpc libffi then it is likely that + FFI_PPC_TYPE_LAST needs increasing *and* the jump tables in + ppc_closure.S and linux64_closure.S be extended. */ +<<<<<<< HEAD /* Needed for FFI_SYSV small structure returns. */ #define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 2) @@ -155,6 +181,26 @@ typedef enum ffi_abi { #define FFI_V2_TYPE_FLOAT_HOMOG (FFI_TYPE_LAST + 1) #define FFI_V2_TYPE_DOUBLE_HOMOG (FFI_TYPE_LAST + 2) #define FFI_V2_TYPE_SMALL_STRUCT (FFI_TYPE_LAST + 3) +======= +#if !(FFI_TYPE_LAST == FFI_PPC_TYPE_LAST \ + || (FFI_TYPE_LAST == FFI_TYPE_COMPLEX \ + && !defined FFI_TARGET_HAS_COMPLEX_TYPE)) +# error "You likely have a broken powerpc libffi" +#endif + +/* Needed for soft-float long-double-128 support. */ +#define FFI_TYPE_UINT128 (FFI_PPC_TYPE_LAST + 1) + +/* Needed for FFI_SYSV small structure returns. */ +#define FFI_SYSV_TYPE_SMALL_STRUCT (FFI_PPC_TYPE_LAST + 2) + +/* Used by ELFv2 for homogenous structure returns. */ +#define FFI_V2_TYPE_VECTOR (FFI_PPC_TYPE_LAST + 1) +#define FFI_V2_TYPE_VECTOR_HOMOG (FFI_PPC_TYPE_LAST + 2) +#define FFI_V2_TYPE_FLOAT_HOMOG (FFI_PPC_TYPE_LAST + 3) +#define FFI_V2_TYPE_DOUBLE_HOMOG (FFI_PPC_TYPE_LAST + 4) +#define FFI_V2_TYPE_SMALL_STRUCT (FFI_PPC_TYPE_LAST + 5) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #if _CALL_ELF == 2 # define FFI_TRAMPOLINE_SIZE 32 diff --git a/native/libffi/src/powerpc/linux64.S b/native/libffi/src/powerpc/linux64.S index d2acb7007b..3e529160c5 100644 --- a/native/libffi/src/powerpc/linux64.S +++ b/native/libffi/src/powerpc/linux64.S @@ -32,11 +32,22 @@ #ifdef POWERPC64 .hidden ffi_call_LINUX64 .globl ffi_call_LINUX64 +<<<<<<< HEAD # if _CALL_ELF == 2 .text ffi_call_LINUX64: addis %r2, %r12, .TOC.-ffi_call_LINUX64@ha addi %r2, %r2, .TOC.-ffi_call_LINUX64@l +======= + .text + .cfi_startproc +# if _CALL_ELF == 2 +ffi_call_LINUX64: +# ifndef __PCREL__ + addis %r2, %r12, .TOC.-ffi_call_LINUX64@ha + addi %r2, %r2, .TOC.-ffi_call_LINUX64@l +# endif +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 .localentry ffi_call_LINUX64, . - ffi_call_LINUX64 # else .section ".opd","aw" @@ -57,20 +68,38 @@ ffi_call_LINUX64: .ffi_call_LINUX64: # endif # endif +<<<<<<< HEAD .LFB1: +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 mflr %r0 std %r28, -32(%r1) std %r29, -24(%r1) std %r30, -16(%r1) std %r31, -8(%r1) + std %r7, 8(%r1) /* closure, saved in cr field. */ std %r0, 16(%r1) mr %r28, %r1 /* our AP. */ +<<<<<<< HEAD .LCFI0: stdux %r1, %r1, %r4 mr %r31, %r5 /* flags, */ mr %r30, %r6 /* rvalue, */ mr %r29, %r7 /* function address. */ +======= + .cfi_def_cfa_register 28 + .cfi_offset 65, 16 + .cfi_offset 31, -8 + .cfi_offset 30, -16 + .cfi_offset 29, -24 + .cfi_offset 28, -32 + + stdux %r1, %r1, %r8 + mr %r31, %r6 /* flags, */ + mr %r30, %r5 /* rvalue, */ + mr %r29, %r4 /* function address. */ +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 /* Save toc pointer, not for the ffi_prep_args64 call, but for the later bctrl function call. */ # if _CALL_ELF == 2 @@ -82,9 +111,21 @@ ffi_call_LINUX64: /* Call ffi_prep_args64. */ mr %r4, %r1 # if defined _CALL_LINUX || _CALL_ELF == 2 +<<<<<<< HEAD bl ffi_prep_args64 # else bl .ffi_prep_args64 +======= +# ifdef __PCREL__ + bl ffi_prep_args64@notoc +# else + bl ffi_prep_args64 + nop +# endif +# else + bl .ffi_prep_args64 + nop +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 # endif # if _CALL_ELF == 2 @@ -92,44 +133,78 @@ ffi_call_LINUX64: # else ld %r12, 0(%r29) ld %r2, 8(%r29) +<<<<<<< HEAD ld %r11, 16(%r29) +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 # endif /* Now do the call. */ - /* Set up cr1 with bits 4-7 of the flags. */ - mtcrf 0x40, %r31 + /* Set up cr1 with bits 3-7 of the flags. */ + mtcrf 0xc0, %r31 /* Get the address to call into CTR. */ mtctr %r12 /* Load all those argument registers. */ - ld %r3, -32-(8*8)(%r28) - ld %r4, -32-(7*8)(%r28) - ld %r5, -32-(6*8)(%r28) - ld %r6, -32-(5*8)(%r28) + addi %r29, %r28, -32-(8*8) + ld %r3, (0*8)(%r29) + ld %r4, (1*8)(%r29) + ld %r5, (2*8)(%r29) + ld %r6, (3*8)(%r29) bf- 5, 1f - ld %r7, -32-(4*8)(%r28) - ld %r8, -32-(3*8)(%r28) - ld %r9, -32-(2*8)(%r28) - ld %r10, -32-(1*8)(%r28) + ld %r7, (4*8)(%r29) + ld %r8, (5*8)(%r29) + ld %r9, (6*8)(%r29) + ld %r10, (7*8)(%r29) 1: /* Load all the FP registers. */ bf- 6, 2f - lfd %f1, -32-(21*8)(%r28) - lfd %f2, -32-(20*8)(%r28) - lfd %f3, -32-(19*8)(%r28) - lfd %f4, -32-(18*8)(%r28) - lfd %f5, -32-(17*8)(%r28) - lfd %f6, -32-(16*8)(%r28) - lfd %f7, -32-(15*8)(%r28) - lfd %f8, -32-(14*8)(%r28) - lfd %f9, -32-(13*8)(%r28) - lfd %f10, -32-(12*8)(%r28) - lfd %f11, -32-(11*8)(%r28) - lfd %f12, -32-(10*8)(%r28) - lfd %f13, -32-(9*8)(%r28) + addi %r29, %r29, -(14*8) + lfd %f1, ( 1*8)(%r29) + lfd %f2, ( 2*8)(%r29) + lfd %f3, ( 3*8)(%r29) + lfd %f4, ( 4*8)(%r29) + lfd %f5, ( 5*8)(%r29) + lfd %f6, ( 6*8)(%r29) + lfd %f7, ( 7*8)(%r29) + lfd %f8, ( 8*8)(%r29) + lfd %f9, ( 9*8)(%r29) + lfd %f10, (10*8)(%r29) + lfd %f11, (11*8)(%r29) + lfd %f12, (12*8)(%r29) + lfd %f13, (13*8)(%r29) 2: + /* Load all the vector registers. */ + bf- 3, 3f + addi %r29, %r29, -16 + lvx %v13, 0, %r29 + addi %r29, %r29, -16 + lvx %v12, 0, %r29 + addi %r29, %r29, -16 + lvx %v11, 0, %r29 + addi %r29, %r29, -16 + lvx %v10, 0, %r29 + addi %r29, %r29, -16 + lvx %v9, 0, %r29 + addi %r29, %r29, -16 + lvx %v8, 0, %r29 + addi %r29, %r29, -16 + lvx %v7, 0, %r29 + addi %r29, %r29, -16 + lvx %v6, 0, %r29 + addi %r29, %r29, -16 + lvx %v5, 0, %r29 + addi %r29, %r29, -16 + lvx %v4, 0, %r29 + addi %r29, %r29, -16 + lvx %v3, 0, %r29 + addi %r29, %r29, -16 + lvx %v2, 0, %r29 +3: + /* Make the call. */ + ld %r11, 8(%r28) bctrl /* This must follow the call immediately, the unwinder @@ -145,12 +220,17 @@ ffi_call_LINUX64: bt 31, .Lstruct_return_value bt 30, .Ldone_return_value bt 29, .Lfp_return_value +<<<<<<< HEAD +======= + bt 28, .Lvec_return_value +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 std %r3, 0(%r30) /* Fall through... */ .Ldone_return_value: /* Restore the registers we used and return. */ mr %r1, %r28 + .cfi_def_cfa_register 1 ld %r0, 16(%r28) ld %r28, -32(%r28) mtlr %r0 @@ -159,11 +239,16 @@ ffi_call_LINUX64: ld %r31, -8(%r1) blr +.Lvec_return_value: + stvx %v2, 0, %r30 + b .Ldone_return_value + .Lfp_return_value: - bf 28, .Lfloat_return_value - stfd %f1, 0(%r30) + .cfi_def_cfa_register 28 mtcrf 0x02, %r31 /* cr6 */ - bf 27, .Ldone_return_value + bf 27, .Lfloat_return_value + stfd %f1, 0(%r30) + bf 26, .Ldone_return_value stfd %f2, 8(%r30) b .Ldone_return_value .Lfloat_return_value: @@ -171,8 +256,14 @@ ffi_call_LINUX64: b .Ldone_return_value .Lstruct_return_value: +<<<<<<< HEAD bf 29, .Lsmall_struct bf 28, .Lfloat_homog_return_value +======= + bf 29, .Lvec_homog_or_small_struct + mtcrf 0x02, %r31 /* cr6 */ + bf 27, .Lfloat_homog_return_value +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 stfd %f1, 0(%r30) stfd %f2, 8(%r30) stfd %f3, 16(%r30) @@ -194,11 +285,34 @@ ffi_call_LINUX64: stfs %f8, 28(%r30) b .Ldone_return_value +<<<<<<< HEAD +======= +.Lvec_homog_or_small_struct: + bf 28, .Lsmall_struct + stvx %v2, 0, %r30 + addi %r30, %r30, 16 + stvx %v3, 0, %r30 + addi %r30, %r30, 16 + stvx %v4, 0, %r30 + addi %r30, %r30, 16 + stvx %v5, 0, %r30 + addi %r30, %r30, 16 + stvx %v6, 0, %r30 + addi %r30, %r30, 16 + stvx %v7, 0, %r30 + addi %r30, %r30, 16 + stvx %v8, 0, %r30 + addi %r30, %r30, 16 + stvx %v9, 0, %r30 + b .Ldone_return_value + +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 .Lsmall_struct: std %r3, 0(%r30) std %r4, 8(%r30) b .Ldone_return_value +<<<<<<< HEAD .LFE1: .long 0 .byte 0,12,0,1,128,4,0,0 @@ -208,10 +322,22 @@ ffi_call_LINUX64: # ifdef _CALL_LINUX .size ffi_call_LINUX64,.-.L.ffi_call_LINUX64 # else +======= + .cfi_endproc +# if _CALL_ELF == 2 + .size ffi_call_LINUX64,.-ffi_call_LINUX64 +# else +# ifdef _CALL_LINUX + .size ffi_call_LINUX64,.-.L.ffi_call_LINUX64 +# else + .long 0 + .byte 0,12,0,1,128,4,0,0 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 .size .ffi_call_LINUX64,.-.ffi_call_LINUX64 # endif # endif +<<<<<<< HEAD .section .eh_frame,EH_FRAME_FLAGS,@progbits .Lframe1: .4byte .LECIE1-.LSCIE1 # Length of Common Information Entry @@ -254,6 +380,8 @@ ffi_call_LINUX64: .align 3 .LEFDE1: +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #endif #if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2 diff --git a/native/libffi/src/powerpc/linux64_closure.S b/native/libffi/src/powerpc/linux64_closure.S index 97421a43c2..7f3b4a08a8 100644 --- a/native/libffi/src/powerpc/linux64_closure.S +++ b/native/libffi/src/powerpc/linux64_closure.S @@ -33,11 +33,22 @@ #ifdef POWERPC64 FFI_HIDDEN (ffi_closure_LINUX64) .globl ffi_closure_LINUX64 +<<<<<<< HEAD # if _CALL_ELF == 2 .text ffi_closure_LINUX64: addis %r2, %r12, .TOC.-ffi_closure_LINUX64@ha addi %r2, %r2, .TOC.-ffi_closure_LINUX64@l +======= + .text + .cfi_startproc +# if _CALL_ELF == 2 +ffi_closure_LINUX64: +# ifndef __PCREL__ + addis %r2, %r12, .TOC.-ffi_closure_LINUX64@ha + addi %r2, %r2, .TOC.-ffi_closure_LINUX64@l +# endif +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 .localentry ffi_closure_LINUX64, . - ffi_closure_LINUX64 # else .section ".opd","aw" @@ -60,9 +71,21 @@ ffi_closure_LINUX64: # endif # if _CALL_ELF == 2 +<<<<<<< HEAD # 32 byte special reg save area + 64 byte parm save area # + 64 byte retval area + 13*8 fpr save area + round to 16 # define STACKFRAME 272 +======= +# ifdef __VEC__ +# 32 byte special reg save area + 64 byte parm save area +# + 128 byte retval area + 13*8 fpr save area + 12*16 vec save area + round to 16 +# define STACKFRAME 528 +# else +# 32 byte special reg save area + 64 byte parm save area +# + 64 byte retval area + 13*8 fpr save area + round to 16 +# define STACKFRAME 272 +# endif +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 # define PARMSAVE 32 # define RETVAL PARMSAVE+64 # else @@ -73,6 +96,7 @@ ffi_closure_LINUX64: # define RETVAL PARMSAVE+64 # endif +<<<<<<< HEAD .LFB1: # if _CALL_ELF == 2 ld %r12, FFI_TRAMPOLINE_SIZE(%r11) # closure->cif @@ -121,7 +145,62 @@ ffi_closure_LINUX64: # load up the pointer to the parm save area addi %r5, %r1, PARMSAVE # endif +======= +# if _CALL_ELF == 2 + ld %r12, FFI_TRAMPOLINE_SIZE(%r11) # closure->cif + mflr %r0 + lwz %r12, 28(%r12) # cif->flags + mtcrf 0x40, %r12 + addi %r12, %r1, PARMSAVE + bt 7, 0f + # Our caller has not allocated a parameter save area. + # We need to allocate one here and use it to pass gprs to + # ffi_closure_helper_LINUX64. + addi %r12, %r1, -STACKFRAME+PARMSAVE +0: + # Save general regs into parm save area + std %r3, 0(%r12) + std %r4, 8(%r12) + std %r5, 16(%r12) + std %r6, 24(%r12) + std %r7, 32(%r12) + std %r8, 40(%r12) + std %r9, 48(%r12) + std %r10, 56(%r12) + + # load up the pointer to the parm save area + mr %r7, %r12 +# else + # copy r2 to r11 and load TOC into r2 + mr %r11, %r2 + ld %r2, 16(%r2) + mflr %r0 + # Save general regs into parm save area + # This is the parameter save area set up by our caller. + std %r3, PARMSAVE+0(%r1) + std %r4, PARMSAVE+8(%r1) + std %r5, PARMSAVE+16(%r1) + std %r6, PARMSAVE+24(%r1) + std %r7, PARMSAVE+32(%r1) + std %r8, PARMSAVE+40(%r1) + std %r9, PARMSAVE+48(%r1) + std %r10, PARMSAVE+56(%r1) + + # load up the pointer to the parm save area + addi %r7, %r1, PARMSAVE +# endif + std %r0, 16(%r1) + + # closure->cif + ld %r3, FFI_TRAMPOLINE_SIZE(%r11) + # closure->fun + ld %r4, FFI_TRAMPOLINE_SIZE+8(%r11) + # closure->user_data + ld %r5, FFI_TRAMPOLINE_SIZE+16(%r11) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 + +.Ldoclosure: # next save fpr 1 to fpr 13 stfd %f1, -104+(0*8)(%r1) stfd %f2, -104+(1*8)(%r1) @@ -137,6 +216,7 @@ ffi_closure_LINUX64: stfd %f12, -104+(11*8)(%r1) stfd %f13, -104+(12*8)(%r1) +<<<<<<< HEAD # load up the pointer to the saved fpr registers */ addi %r6, %r1, -104 @@ -155,7 +235,62 @@ ffi_closure_LINUX64: # else bl .ffi_closure_helper_LINUX64 # endif +======= + # load up the pointer to the saved fpr registers + addi %r8, %r1, -104 + +# ifdef __VEC__ + # load up the pointer to the saved vector registers + # 8 bytes padding for 16-byte alignment at -112(%r1) + addi %r9, %r8, -24 + stvx %v13, 0, %r9 + addi %r9, %r9, -16 + stvx %v12, 0, %r9 + addi %r9, %r9, -16 + stvx %v11, 0, %r9 + addi %r9, %r9, -16 + stvx %v10, 0, %r9 + addi %r9, %r9, -16 + stvx %v9, 0, %r9 + addi %r9, %r9, -16 + stvx %v8, 0, %r9 + addi %r9, %r9, -16 + stvx %v7, 0, %r9 + addi %r9, %r9, -16 + stvx %v6, 0, %r9 + addi %r9, %r9, -16 + stvx %v5, 0, %r9 + addi %r9, %r9, -16 + stvx %v4, 0, %r9 + addi %r9, %r9, -16 + stvx %v3, 0, %r9 + addi %r9, %r9, -16 + stvx %v2, 0, %r9 +# endif + + # load up the pointer to the result storage + addi %r6, %r1, -STACKFRAME+RETVAL + + stdu %r1, -STACKFRAME(%r1) + .cfi_def_cfa_offset STACKFRAME + .cfi_offset 65, 16 + + # make the call +# if defined _CALL_LINUX || _CALL_ELF == 2 +# ifdef __PCREL__ + bl ffi_closure_helper_LINUX64@notoc .Lret: +# else + bl ffi_closure_helper_LINUX64 +.Lret: + nop +# endif +# else + bl .ffi_closure_helper_LINUX64 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 +.Lret: + nop +# endif # now r3 contains the return type # so use it to look up in a table @@ -182,7 +317,12 @@ ffi_closure_LINUX64: # case FFI_TYPE_VOID mtlr %r0 addi %r1, %r1, STACKFRAME +<<<<<<< HEAD +======= + .cfi_def_cfa_offset 0 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 blr + .cfi_def_cfa_offset STACKFRAME nop # case FFI_TYPE_INT # ifdef __LITTLE_ENDIAN__ @@ -192,17 +332,32 @@ ffi_closure_LINUX64: # endif mtlr %r0 addi %r1, %r1, STACKFRAME +<<<<<<< HEAD +======= + .cfi_def_cfa_offset 0 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 blr + .cfi_def_cfa_offset STACKFRAME # case FFI_TYPE_FLOAT lfs %f1, RETVAL+0(%r1) mtlr %r0 addi %r1, %r1, STACKFRAME +<<<<<<< HEAD +======= + .cfi_def_cfa_offset 0 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 blr + .cfi_def_cfa_offset STACKFRAME # case FFI_TYPE_DOUBLE lfd %f1, RETVAL+0(%r1) mtlr %r0 addi %r1, %r1, STACKFRAME +<<<<<<< HEAD +======= + .cfi_def_cfa_offset 0 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 blr + .cfi_def_cfa_offset STACKFRAME # case FFI_TYPE_LONGDOUBLE lfd %f1, RETVAL+0(%r1) mtlr %r0 @@ -216,7 +371,12 @@ ffi_closure_LINUX64: # endif mtlr %r0 addi %r1, %r1, STACKFRAME +<<<<<<< HEAD +======= + .cfi_def_cfa_offset 0 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 blr + .cfi_def_cfa_offset STACKFRAME # case FFI_TYPE_SINT8 # ifdef __LITTLE_ENDIAN__ lbz %r3, RETVAL+0(%r1) @@ -235,7 +395,12 @@ ffi_closure_LINUX64: mtlr %r0 .Lfinish: addi %r1, %r1, STACKFRAME +<<<<<<< HEAD +======= + .cfi_def_cfa_offset 0 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 blr + .cfi_def_cfa_offset STACKFRAME # case FFI_TYPE_SINT16 # ifdef __LITTLE_ENDIAN__ lha %r3, RETVAL+0(%r1) @@ -244,7 +409,12 @@ ffi_closure_LINUX64: # endif mtlr %r0 addi %r1, %r1, STACKFRAME +<<<<<<< HEAD +======= + .cfi_def_cfa_offset 0 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 blr + .cfi_def_cfa_offset STACKFRAME # case FFI_TYPE_UINT32 # ifdef __LITTLE_ENDIAN__ lwz %r3, RETVAL+0(%r1) @@ -253,7 +423,12 @@ ffi_closure_LINUX64: # endif mtlr %r0 addi %r1, %r1, STACKFRAME +<<<<<<< HEAD +======= + .cfi_def_cfa_offset 0 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 blr + .cfi_def_cfa_offset STACKFRAME # case FFI_TYPE_SINT32 # ifdef __LITTLE_ENDIAN__ lwa %r3, RETVAL+0(%r1) @@ -262,27 +437,97 @@ ffi_closure_LINUX64: # endif mtlr %r0 addi %r1, %r1, STACKFRAME +<<<<<<< HEAD +======= + .cfi_def_cfa_offset 0 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 blr + .cfi_def_cfa_offset STACKFRAME # case FFI_TYPE_UINT64 ld %r3, RETVAL+0(%r1) mtlr %r0 addi %r1, %r1, STACKFRAME +<<<<<<< HEAD +======= + .cfi_def_cfa_offset 0 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 blr + .cfi_def_cfa_offset STACKFRAME # case FFI_TYPE_SINT64 ld %r3, RETVAL+0(%r1) mtlr %r0 addi %r1, %r1, STACKFRAME +<<<<<<< HEAD +======= + .cfi_def_cfa_offset 0 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 blr + .cfi_def_cfa_offset STACKFRAME # case FFI_TYPE_STRUCT mtlr %r0 addi %r1, %r1, STACKFRAME +<<<<<<< HEAD +======= + .cfi_def_cfa_offset 0 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 blr + .cfi_def_cfa_offset STACKFRAME nop # case FFI_TYPE_POINTER ld %r3, RETVAL+0(%r1) +<<<<<<< HEAD + mtlr %r0 + addi %r1, %r1, STACKFRAME + blr +# case FFI_V2_TYPE_FLOAT_HOMOG + lfs %f1, RETVAL+0(%r1) + lfs %f2, RETVAL+4(%r1) + lfs %f3, RETVAL+8(%r1) + b .Lmorefloat +# case FFI_V2_TYPE_DOUBLE_HOMOG + lfd %f1, RETVAL+0(%r1) + lfd %f2, RETVAL+8(%r1) + lfd %f3, RETVAL+16(%r1) + lfd %f4, RETVAL+24(%r1) + mtlr %r0 + lfd %f5, RETVAL+32(%r1) + lfd %f6, RETVAL+40(%r1) + lfd %f7, RETVAL+48(%r1) + lfd %f8, RETVAL+56(%r1) + addi %r1, %r1, STACKFRAME + blr +.Lmorefloat: + lfs %f4, RETVAL+12(%r1) + mtlr %r0 + lfs %f5, RETVAL+16(%r1) + lfs %f6, RETVAL+20(%r1) + lfs %f7, RETVAL+24(%r1) + lfs %f8, RETVAL+28(%r1) + addi %r1, %r1, STACKFRAME + blr +.Lsmall: +# ifdef __LITTLE_ENDIAN__ + ld %r3,RETVAL+0(%r1) mtlr %r0 + ld %r4,RETVAL+8(%r1) addi %r1, %r1, STACKFRAME blr +======= + mtlr %r0 + addi %r1, %r1, STACKFRAME + .cfi_def_cfa_offset 0 + blr + .cfi_def_cfa_offset STACKFRAME +# case FFI_V2_TYPE_VECTOR + addi %r3, %r1, RETVAL + lvx %v2, 0, %r3 + mtlr %r0 + b .Lfinish +# case FFI_V2_TYPE_VECTOR_HOMOG + addi %r3, %r1, RETVAL + lvx %v2, 0, %r3 + addi %r3, %r3, 16 + b .Lmorevector # case FFI_V2_TYPE_FLOAT_HOMOG lfs %f1, RETVAL+0(%r1) lfs %f2, RETVAL+4(%r1) @@ -299,7 +544,28 @@ ffi_closure_LINUX64: lfd %f7, RETVAL+48(%r1) lfd %f8, RETVAL+56(%r1) addi %r1, %r1, STACKFRAME + .cfi_def_cfa_offset 0 + blr + .cfi_def_cfa_offset STACKFRAME +.Lmorevector: + lvx %v3, 0, %r3 + addi %r3, %r3, 16 + lvx %v4, 0, %r3 + addi %r3, %r3, 16 + lvx %v5, 0, %r3 + mtlr %r0 + addi %r3, %r3, 16 + lvx %v6, 0, %r3 + addi %r3, %r3, 16 + lvx %v7, 0, %r3 + addi %r3, %r3, 16 + lvx %v8, 0, %r3 + addi %r3, %r3, 16 + lvx %v9, 0, %r3 + addi %r1, %r1, STACKFRAME + .cfi_def_cfa_offset 0 blr + .cfi_def_cfa_offset STACKFRAME .Lmorefloat: lfs %f4, RETVAL+12(%r1) mtlr %r0 @@ -308,14 +574,18 @@ ffi_closure_LINUX64: lfs %f7, RETVAL+24(%r1) lfs %f8, RETVAL+28(%r1) addi %r1, %r1, STACKFRAME + .cfi_def_cfa_offset 0 blr + .cfi_def_cfa_offset STACKFRAME .Lsmall: # ifdef __LITTLE_ENDIAN__ ld %r3,RETVAL+0(%r1) mtlr %r0 ld %r4,RETVAL+8(%r1) addi %r1, %r1, STACKFRAME + .cfi_def_cfa_offset 0 blr +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 # else # A struct smaller than a dword is returned in the low bits of r3 # ie. right justified. Larger structs are passed left justified @@ -328,16 +598,27 @@ ffi_closure_LINUX64: mtlr %r0 ld %r4,RETVAL+8(%r1) addi %r1, %r1, STACKFRAME +<<<<<<< HEAD blr +======= + .cfi_def_cfa_offset 0 + blr + .cfi_def_cfa_offset STACKFRAME +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 .Lsmalldown: addi %r5, %r5, FFI_V2_TYPE_SMALL_STRUCT + 7 mtlr %r0 sldi %r5, %r5, 3 addi %r1, %r1, STACKFRAME +<<<<<<< HEAD +======= + .cfi_def_cfa_offset 0 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 srd %r3, %r3, %r5 blr # endif +<<<<<<< HEAD .LFE1: .long 0 .byte 0,12,0,1,128,0,0,0 @@ -385,6 +666,115 @@ ffi_closure_LINUX64: .align 3 .LEFDE1: +======= + .cfi_endproc +# if _CALL_ELF == 2 + .size ffi_closure_LINUX64,.-ffi_closure_LINUX64 +# else +# ifdef _CALL_LINUX + .size ffi_closure_LINUX64,.-.L.ffi_closure_LINUX64 +# else + .long 0 + .byte 0,12,0,1,128,0,0,0 + .size .ffi_closure_LINUX64,.-.ffi_closure_LINUX64 +# endif +# endif + + + FFI_HIDDEN (ffi_go_closure_linux64) + .globl ffi_go_closure_linux64 + .text + .cfi_startproc +# if _CALL_ELF == 2 +ffi_go_closure_linux64: +# ifndef __PCREL__ + addis %r2, %r12, .TOC.-ffi_go_closure_linux64@ha + addi %r2, %r2, .TOC.-ffi_go_closure_linux64@l +# endif + .localentry ffi_go_closure_linux64, . - ffi_go_closure_linux64 +# else + .section ".opd","aw" + .align 3 +ffi_go_closure_linux64: +# ifdef _CALL_LINUX + .quad .L.ffi_go_closure_linux64,.TOC.@tocbase,0 + .type ffi_go_closure_linux64,@function + .text +.L.ffi_go_closure_linux64: +# else + FFI_HIDDEN (.ffi_go_closure_linux64) + .globl .ffi_go_closure_linux64 + .quad .ffi_go_closure_linux64,.TOC.@tocbase,0 + .size ffi_go_closure_linux64,24 + .type .ffi_go_closure_linux64,@function + .text +.ffi_go_closure_linux64: +# endif +# endif + +# if _CALL_ELF == 2 + ld %r12, 8(%r11) # closure->cif + mflr %r0 + lwz %r12, 28(%r12) # cif->flags + mtcrf 0x40, %r12 + addi %r12, %r1, PARMSAVE + bt 7, 0f + # Our caller has not allocated a parameter save area. + # We need to allocate one here and use it to pass gprs to + # ffi_closure_helper_LINUX64. + addi %r12, %r1, -STACKFRAME+PARMSAVE +0: + # Save general regs into parm save area + std %r3, 0(%r12) + std %r4, 8(%r12) + std %r5, 16(%r12) + std %r6, 24(%r12) + std %r7, 32(%r12) + std %r8, 40(%r12) + std %r9, 48(%r12) + std %r10, 56(%r12) + + # load up the pointer to the parm save area + mr %r7, %r12 +# else + mflr %r0 + # Save general regs into parm save area + # This is the parameter save area set up by our caller. + std %r3, PARMSAVE+0(%r1) + std %r4, PARMSAVE+8(%r1) + std %r5, PARMSAVE+16(%r1) + std %r6, PARMSAVE+24(%r1) + std %r7, PARMSAVE+32(%r1) + std %r8, PARMSAVE+40(%r1) + std %r9, PARMSAVE+48(%r1) + std %r10, PARMSAVE+56(%r1) + + # load up the pointer to the parm save area + addi %r7, %r1, PARMSAVE +# endif + std %r0, 16(%r1) + + # closure->cif + ld %r3, 8(%r11) + # closure->fun + ld %r4, 16(%r11) + # user_data + mr %r5, %r11 + b .Ldoclosure + + .cfi_endproc +# if _CALL_ELF == 2 + .size ffi_go_closure_linux64,.-ffi_go_closure_linux64 +# else +# ifdef _CALL_LINUX + .size ffi_go_closure_linux64,.-.L.ffi_go_closure_linux64 +# else + .long 0 + .byte 0,12,0,1,128,0,0,0 + .size .ffi_go_closure_linux64,.-.ffi_go_closure_linux64 +# endif +# endif +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #endif #if (defined __ELF__ && defined __linux__) || _CALL_ELF == 2 diff --git a/native/libffi/src/powerpc/ppc_closure.S b/native/libffi/src/powerpc/ppc_closure.S index 075922cbb0..38c006beb3 100644 --- a/native/libffi/src/powerpc/ppc_closure.S +++ b/native/libffi/src/powerpc/ppc_closure.S @@ -33,13 +33,14 @@ #ifndef POWERPC64 +FFI_HIDDEN(ffi_closure_SYSV) ENTRY(ffi_closure_SYSV) -.LFB1: + .cfi_startproc stwu %r1,-144(%r1) -.LCFI0: + .cfi_def_cfa_offset 144 mflr %r0 -.LCFI1: stw %r0,148(%r1) + .cfi_offset 65, 4 # we want to build up an areas for the parameters passed # in registers (both floating point and integer) @@ -48,6 +49,17 @@ ENTRY(ffi_closure_SYSV) stw %r3, 16(%r1) stw %r4, 20(%r1) stw %r5, 24(%r1) + + # set up registers for the routine that does the work + + # closure->cif + lwz %r3,FFI_TRAMPOLINE_SIZE(%r11) + # closure->fun + lwz %r4,FFI_TRAMPOLINE_SIZE+4(%r11) + # closure->user_data + lwz %r5,FFI_TRAMPOLINE_SIZE+8(%r11) + +.Ldoclosure: stw %r6, 28(%r1) stw %r7, 32(%r1) stw %r8, 36(%r1) @@ -66,23 +78,18 @@ ENTRY(ffi_closure_SYSV) stfd %f8, 104(%r1) #endif - # set up registers for the routine that actually does the work - # get the context pointer from the trampoline - mr %r3,%r11 + # pointer to the result storage + addi %r6,%r1,112 - # now load up the pointer to the result storage - addi %r4,%r1,112 + # pointer to the saved gpr registers + addi %r7,%r1,16 - # now load up the pointer to the saved gpr registers - addi %r5,%r1,16 + # pointer to the saved fpr registers + addi %r8,%r1,48 - # now load up the pointer to the saved fpr registers */ - addi %r6,%r1,48 - - # now load up the pointer to the outgoing parameter - # stack in the previous frame + # pointer to the outgoing parameter save area in the previous frame # i.e. the previous frame pointer + 8 - addi %r7,%r1,152 + addi %r9,%r1,152 # make the call bl ffi_closure_helper_SYSV@local @@ -101,7 +108,6 @@ ENTRY(ffi_closure_SYSV) add %r3,%r3,%r4 # add contents of table to table address mtctr %r3 bctr # jump to it -.LFE1: # Each of the ret_typeX code fragments has to be exactly 16 bytes long # (4 instructions). For cache effectiveness we align to a 16 byte boundary @@ -111,7 +117,9 @@ ENTRY(ffi_closure_SYSV) .Lret_type0: mtlr %r0 addi %r1,%r1,144 + .cfi_def_cfa_offset 0 blr + .cfi_def_cfa_offset 144 nop # case FFI_TYPE_INT @@ -119,31 +127,33 @@ ENTRY(ffi_closure_SYSV) mtlr %r0 .Lfinish: addi %r1,%r1,144 + .cfi_def_cfa_offset 0 blr + .cfi_def_cfa_offset 144 # case FFI_TYPE_FLOAT #ifndef __NO_FPRS__ lfs %f1,112+0(%r1) - mtlr %r0 - addi %r1,%r1,144 #else nop - nop - nop #endif + mtlr %r0 + addi %r1,%r1,144 + .cfi_def_cfa_offset 0 blr + .cfi_def_cfa_offset 144 # case FFI_TYPE_DOUBLE #ifndef __NO_FPRS__ lfd %f1,112+0(%r1) - mtlr %r0 - addi %r1,%r1,144 #else nop - nop - nop #endif + mtlr %r0 + addi %r1,%r1,144 + .cfi_def_cfa_offset 0 blr + .cfi_def_cfa_offset 144 # case FFI_TYPE_LONGDOUBLE #ifndef __NO_FPRS__ @@ -152,10 +162,12 @@ ENTRY(ffi_closure_SYSV) mtlr %r0 b .Lfinish #else - nop - nop - nop + mtlr %r0 + addi %r1,%r1,144 + .cfi_def_cfa_offset 0 blr + .cfi_def_cfa_offset 144 + nop #endif # case FFI_TYPE_UINT8 @@ -166,7 +178,9 @@ ENTRY(ffi_closure_SYSV) #endif mtlr %r0 addi %r1,%r1,144 + .cfi_def_cfa_offset 0 blr + .cfi_def_cfa_offset 144 # case FFI_TYPE_SINT8 #ifdef __LITTLE_ENDIAN__ @@ -186,7 +200,9 @@ ENTRY(ffi_closure_SYSV) #endif mtlr %r0 addi %r1,%r1,144 + .cfi_def_cfa_offset 0 blr + .cfi_def_cfa_offset 144 # case FFI_TYPE_SINT16 #ifdef __LITTLE_ENDIAN__ @@ -196,19 +212,25 @@ ENTRY(ffi_closure_SYSV) #endif mtlr %r0 addi %r1,%r1,144 + .cfi_def_cfa_offset 0 blr + .cfi_def_cfa_offset 144 # case FFI_TYPE_UINT32 lwz %r3,112+0(%r1) mtlr %r0 addi %r1,%r1,144 + .cfi_def_cfa_offset 0 blr + .cfi_def_cfa_offset 144 # case FFI_TYPE_SINT32 lwz %r3,112+0(%r1) mtlr %r0 addi %r1,%r1,144 + .cfi_def_cfa_offset 0 blr + .cfi_def_cfa_offset 144 # case FFI_TYPE_UINT64 lwz %r3,112+0(%r1) @@ -225,14 +247,18 @@ ENTRY(ffi_closure_SYSV) # case FFI_TYPE_STRUCT mtlr %r0 addi %r1,%r1,144 + .cfi_def_cfa_offset 0 blr + .cfi_def_cfa_offset 144 nop # case FFI_TYPE_POINTER lwz %r3,112+0(%r1) mtlr %r0 addi %r1,%r1,144 + .cfi_def_cfa_offset 0 blr + .cfi_def_cfa_offset 144 # case FFI_TYPE_UINT128 lwz %r3,112+0(%r1) @@ -245,20 +271,30 @@ ENTRY(ffi_closure_SYSV) lbz %r3,112+0(%r1) mtlr %r0 addi %r1,%r1,144 + .cfi_def_cfa_offset 0 blr + .cfi_def_cfa_offset 144 # case FFI_SYSV_TYPE_SMALL_STRUCT + 2. Two byte struct. lhz %r3,112+0(%r1) mtlr %r0 addi %r1,%r1,144 + .cfi_def_cfa_offset 0 blr + .cfi_def_cfa_offset 144 # case FFI_SYSV_TYPE_SMALL_STRUCT + 3. Three byte struct. lwz %r3,112+0(%r1) #ifdef __LITTLE_ENDIAN__ mtlr %r0 addi %r1,%r1,144 +<<<<<<< HEAD blr +======= + .cfi_def_cfa_offset 0 + blr + .cfi_def_cfa_offset 144 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #else srwi %r3,%r3,8 mtlr %r0 @@ -269,7 +305,9 @@ ENTRY(ffi_closure_SYSV) lwz %r3,112+0(%r1) mtlr %r0 addi %r1,%r1,144 + .cfi_def_cfa_offset 0 blr + .cfi_def_cfa_offset 144 # case FFI_SYSV_TYPE_SMALL_STRUCT + 5. Five byte struct. lwz %r3,112+0(%r1) @@ -319,65 +357,54 @@ ENTRY(ffi_closure_SYSV) or %r4,%r6,%r4 mtlr %r0 addi %r1,%r1,144 + .cfi_def_cfa_offset 0 blr +<<<<<<< HEAD +======= + .cfi_def_cfa_offset 144 +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #endif .Luint128: lwz %r6,112+12(%r1) mtlr %r0 addi %r1,%r1,144 + .cfi_def_cfa_offset 0 blr +<<<<<<< HEAD +======= + .cfi_endproc +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 END(ffi_closure_SYSV) - .section ".eh_frame",EH_FRAME_FLAGS,@progbits -.Lframe1: - .4byte .LECIE1-.LSCIE1 # Length of Common Information Entry -.LSCIE1: - .4byte 0x0 # CIE Identifier Tag - .byte 0x1 # CIE Version -#if defined _RELOCATABLE || defined __PIC__ - .ascii "zR\0" # CIE Augmentation -#else - .ascii "\0" # CIE Augmentation -#endif - .uleb128 0x1 # CIE Code Alignment Factor - .sleb128 -4 # CIE Data Alignment Factor - .byte 0x41 # CIE RA Column -#if defined _RELOCATABLE || defined __PIC__ - .uleb128 0x1 # Augmentation size - .byte 0x1b # FDE Encoding (pcrel sdata4) -#endif - .byte 0xc # DW_CFA_def_cfa - .uleb128 0x1 - .uleb128 0x0 - .align 2 -.LECIE1: -.LSFDE1: - .4byte .LEFDE1-.LASFDE1 # FDE Length -.LASFDE1: - .4byte .LASFDE1-.Lframe1 # FDE CIE offset -#if defined _RELOCATABLE || defined __PIC__ - .4byte .LFB1-. # FDE initial location -#else - .4byte .LFB1 # FDE initial location -#endif - .4byte .LFE1-.LFB1 # FDE address range -#if defined _RELOCATABLE || defined __PIC__ - .uleb128 0x0 # Augmentation size -#endif - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI0-.LFB1 - .byte 0xe # DW_CFA_def_cfa_offset - .uleb128 144 - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI1-.LCFI0 - .byte 0x11 # DW_CFA_offset_extended_sf - .uleb128 0x41 - .sleb128 -1 - .align 2 -.LEFDE1: +<<<<<<< HEAD +======= +FFI_HIDDEN(ffi_go_closure_sysv) +ENTRY(ffi_go_closure_sysv) + .cfi_startproc + stwu %r1,-144(%r1) + .cfi_def_cfa_offset 144 + mflr %r0 + stw %r0,148(%r1) + .cfi_offset 65, 4 + + stw %r3, 16(%r1) + stw %r4, 20(%r1) + stw %r5, 24(%r1) + + # closure->cif + lwz %r3,4(%r11) + # closure->fun + lwz %r4,8(%r11) + # user_data + mr %r5,%r11 + b .Ldoclosure + .cfi_endproc +END(ffi_go_closure_sysv) + +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #if defined __ELF__ && defined __linux__ .section .note.GNU-stack,"",@progbits #endif diff --git a/native/libffi/src/powerpc/sysv.S b/native/libffi/src/powerpc/sysv.S index fed2380c9f..b05334046d 100644 --- a/native/libffi/src/powerpc/sysv.S +++ b/native/libffi/src/powerpc/sysv.S @@ -31,34 +31,39 @@ #include #ifndef POWERPC64 +<<<<<<< HEAD .globl ffi_prep_args_SYSV +======= +FFI_HIDDEN(ffi_call_SYSV) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 ENTRY(ffi_call_SYSV) -.LFB1: + .cfi_startproc /* Save the old stack pointer as AP. */ - mr %r8,%r1 + mr %r10,%r1 + .cfi_def_cfa_register 10 -.LCFI0: /* Allocate the stack space we need. */ - stwux %r1,%r1,%r4 + stwux %r1,%r1,%r8 /* Save registers we use. */ mflr %r9 - stw %r28,-16(%r8) -.LCFI1: - stw %r29,-12(%r8) -.LCFI2: - stw %r30, -8(%r8) -.LCFI3: - stw %r31, -4(%r8) -.LCFI4: - stw %r9, 4(%r8) -.LCFI5: + stw %r28,-16(%r10) + stw %r29,-12(%r10) + stw %r30, -8(%r10) + stw %r31, -4(%r10) + stw %r9, 4(%r10) + .cfi_offset 65, 4 + .cfi_offset 31, -4 + .cfi_offset 30, -8 + .cfi_offset 29, -12 + .cfi_offset 28, -16 /* Save arguments over call... */ - mr %r31,%r5 /* flags, */ - mr %r30,%r6 /* rvalue, */ - mr %r29,%r7 /* function address, */ - mr %r28,%r8 /* our AP. */ -.LCFI6: + stw %r7, -20(%r10) /* closure, */ + mr %r31,%r6 /* flags, */ + mr %r30,%r5 /* rvalue, */ + mr %r29,%r4 /* function address, */ + mr %r28,%r10 /* our AP. */ + .cfi_def_cfa_register 28 /* Call ffi_prep_args_SYSV. */ mr %r4,%r1 @@ -70,49 +75,49 @@ ENTRY(ffi_call_SYSV) /* Get the address to call into CTR. */ mtctr %r29 /* Load all those argument registers. */ - lwz %r3,-16-(8*4)(%r28) - lwz %r4,-16-(7*4)(%r28) - lwz %r5,-16-(6*4)(%r28) - lwz %r6,-16-(5*4)(%r28) + lwz %r3,-24-(8*4)(%r28) + lwz %r4,-24-(7*4)(%r28) + lwz %r5,-24-(6*4)(%r28) + lwz %r6,-24-(5*4)(%r28) bf- 5,1f nop - lwz %r7,-16-(4*4)(%r28) - lwz %r8,-16-(3*4)(%r28) - lwz %r9,-16-(2*4)(%r28) - lwz %r10,-16-(1*4)(%r28) + lwz %r7,-24-(4*4)(%r28) + lwz %r8,-24-(3*4)(%r28) + lwz %r9,-24-(2*4)(%r28) + lwz %r10,-24-(1*4)(%r28) nop 1: #ifndef __NO_FPRS__ /* Load all the FP registers. */ bf- 6,2f - lfd %f1,-16-(8*4)-(8*8)(%r28) - lfd %f2,-16-(8*4)-(7*8)(%r28) - lfd %f3,-16-(8*4)-(6*8)(%r28) - lfd %f4,-16-(8*4)-(5*8)(%r28) + lfd %f1,-24-(8*4)-(8*8)(%r28) + lfd %f2,-24-(8*4)-(7*8)(%r28) + lfd %f3,-24-(8*4)-(6*8)(%r28) + lfd %f4,-24-(8*4)-(5*8)(%r28) nop - lfd %f5,-16-(8*4)-(4*8)(%r28) - lfd %f6,-16-(8*4)-(3*8)(%r28) - lfd %f7,-16-(8*4)-(2*8)(%r28) - lfd %f8,-16-(8*4)-(1*8)(%r28) + lfd %f5,-24-(8*4)-(4*8)(%r28) + lfd %f6,-24-(8*4)-(3*8)(%r28) + lfd %f7,-24-(8*4)-(2*8)(%r28) + lfd %f8,-24-(8*4)-(1*8)(%r28) #endif 2: /* Make the call. */ + lwz %r11, -20(%r28) bctrl /* Now, deal with the return value. */ - mtcrf 0x01,%r31 /* cr7 */ + mtcrf 0x03,%r31 /* cr6-cr7 */ bt- 31,L(small_struct_return_value) bt- 30,L(done_return_value) #ifndef __NO_FPRS__ bt- 29,L(fp_return_value) #endif stw %r3,0(%r30) - bf+ 28,L(done_return_value) + bf+ 27,L(done_return_value) stw %r4,4(%r30) - mtcrf 0x02,%r31 /* cr6 */ - bf 27,L(done_return_value) + bf 26,L(done_return_value) stw %r5,8(%r30) stw %r6,12(%r30) /* Fall through... */ @@ -125,15 +130,27 @@ L(done_return_value): lwz %r30, -8(%r28) lwz %r29,-12(%r28) lwz %r28,-16(%r28) + .cfi_remember_state + /* At this point we don't have a cfa register. Say all our + saved regs have been restored. */ + .cfi_same_value 65 + .cfi_same_value 31 + .cfi_same_value 30 + .cfi_same_value 29 + .cfi_same_value 28 + /* Hopefully this works.. */ + .cfi_def_cfa_register 1 + .cfi_offset 1, 0 lwz %r1,0(%r1) + .cfi_same_value 1 blr #ifndef __NO_FPRS__ L(fp_return_value): - bf 28,L(float_return_value) + .cfi_restore_state + bf 27,L(float_return_value) stfd %f1,0(%r30) - mtcrf 0x02,%r31 /* cr6 */ - bf 27,L(done_return_value) + bf 26,L(done_return_value) stfd %f2,8(%r30) b L(done_return_value) L(float_return_value): @@ -150,10 +167,14 @@ L(small_struct_return_value): stw %r3, 0(%r30) stw %r4, 4(%r30) b L(done_return_value) +<<<<<<< HEAD +======= + .cfi_endproc +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 -.LFE1: END(ffi_call_SYSV) +<<<<<<< HEAD .section ".eh_frame",EH_FRAME_FLAGS,@progbits .Lframe1: .4byte .LECIE1-.LSCIE1 /* Length of Common Information Entry */ @@ -214,6 +235,8 @@ END(ffi_call_SYSV) .align 2 .LEFDE1: +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #if defined __ELF__ && defined __linux__ .section .note.GNU-stack,"",@progbits #endif diff --git a/native/libffi/src/prep_cif.c b/native/libffi/src/prep_cif.c index be5eae379e..a95f733c94 100644 --- a/native/libffi/src/prep_cif.c +++ b/native/libffi/src/prep_cif.c @@ -29,12 +29,12 @@ /* Round up to FFI_SIZEOF_ARG. */ -#define STACK_ARG_SIZE(x) ALIGN(x, FFI_SIZEOF_ARG) +#define STACK_ARG_SIZE(x) FFI_ALIGN(x, FFI_SIZEOF_ARG) /* Perform machine independent initialization of aggregate type specifications. */ -static ffi_status initialize_aggregate(ffi_type *arg) +static ffi_status initialize_aggregate(ffi_type *arg, size_t *offsets) { ffi_type **ptr; @@ -52,13 +52,15 @@ static ffi_status initialize_aggregate(ffi_type *arg) while ((*ptr) != NULL) { if (UNLIKELY(((*ptr)->size == 0) - && (initialize_aggregate((*ptr)) != FFI_OK))) + && (initialize_aggregate((*ptr), NULL) != FFI_OK))) return FFI_BAD_TYPEDEF; /* Perform a sanity check on the argument type */ FFI_ASSERT_VALID_TYPE(*ptr); - arg->size = ALIGN(arg->size, (*ptr)->alignment); + arg->size = FFI_ALIGN(arg->size, (*ptr)->alignment); + if (offsets) + *offsets++ = arg->size; arg->size += (*ptr)->size; arg->alignment = (arg->alignment > (*ptr)->alignment) ? @@ -74,7 +76,14 @@ static ffi_status initialize_aggregate(ffi_type *arg) struct A { long a; char b; }; struct B { struct A x; char y; }; should find y at an offset of 2*sizeof(long) and result in a total size of 3*sizeof(long). */ - arg->size = ALIGN (arg->size, arg->alignment); + arg->size = FFI_ALIGN (arg->size, arg->alignment); + + /* On some targets, the ABI defines that structures have an additional + alignment beyond the "natural" one based on their elements. */ +#ifdef FFI_AGGREGATE_ALIGNMENT + if (FFI_AGGREGATE_ALIGNMENT > arg->alignment) + arg->alignment = FFI_AGGREGATE_ALIGNMENT; +#endif /* On some targets, the ABI defines that structures have an additional alignment beyond the "natural" one based on their elements. */ @@ -127,13 +136,20 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi, cif->rtype = rtype; cif->flags = 0; +#if (defined(_M_ARM64) || defined(__aarch64__)) && defined(_WIN32) + cif->is_variadic = isvariadic; +#endif +#if HAVE_LONG_DOUBLE_VARIANT + ffi_prep_types (abi); +#endif #if HAVE_LONG_DOUBLE_VARIANT ffi_prep_types (abi); #endif /* Initialize the return type if necessary */ - if ((cif->rtype->size == 0) && (initialize_aggregate(cif->rtype) != FFI_OK)) + if ((cif->rtype->size == 0) + && (initialize_aggregate(cif->rtype, NULL) != FFI_OK)) return FFI_BAD_TYPEDEF; #ifndef FFI_TARGET_HAS_COMPLEX_TYPE @@ -147,9 +163,6 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi, #if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION /* Make space for the return structure pointer */ if (cif->rtype->type == FFI_TYPE_STRUCT -#ifdef SPARC - && (cif->abi != FFI_V9 || cif->rtype->size > 32) -#endif #ifdef TILE && (cif->rtype->size > 10 * FFI_SIZEOF_ARG) #endif @@ -167,7 +180,8 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi, { /* Initialize any uninitialized aggregate type definitions */ - if (((*ptr)->size == 0) && (initialize_aggregate((*ptr)) != FFI_OK)) + if (((*ptr)->size == 0) + && (initialize_aggregate((*ptr), NULL) != FFI_OK)) return FFI_BAD_TYPEDEF; #ifndef FFI_TARGET_HAS_COMPLEX_TYPE @@ -179,6 +193,7 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi, FFI_ASSERT_VALID_TYPE(*ptr); #if !defined FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION +<<<<<<< HEAD #ifdef SPARC if (((*ptr)->type == FFI_TYPE_STRUCT && ((*ptr)->size > 16 || cif->abi != FFI_V9)) @@ -191,6 +206,12 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi, /* Add any padding if necessary */ if (((*ptr)->alignment - 1) & bytes) bytes = (unsigned)ALIGN(bytes, (*ptr)->alignment); +======= + { + /* Add any padding if necessary */ + if (((*ptr)->alignment - 1) & bytes) + bytes = (unsigned)FFI_ALIGN(bytes, (*ptr)->alignment); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #ifdef TILE if (bytes < 10 * FFI_SIZEOF_ARG && @@ -206,7 +227,7 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi, bytes = 6*4; #endif - bytes += STACK_ARG_SIZE((*ptr)->size); + bytes += (unsigned int)STACK_ARG_SIZE((*ptr)->size); } #endif } @@ -251,3 +272,18 @@ ffi_prep_closure (ffi_closure* closure, } #endif + +ffi_status +ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type, size_t *offsets) +{ + if (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI)) + return FFI_BAD_ABI; + if (struct_type->type != FFI_TYPE_STRUCT) + return FFI_BAD_TYPEDEF; + +#if HAVE_LONG_DOUBLE_VARIANT + ffi_prep_types (abi); +#endif + + return initialize_aggregate(struct_type, offsets); +} diff --git a/native/libffi/src/raw_api.c b/native/libffi/src/raw_api.c index 276cb22807..be156116cb 100644 --- a/native/libffi/src/raw_api.c +++ b/native/libffi/src/raw_api.c @@ -43,10 +43,10 @@ ffi_raw_size (ffi_cif *cif) { #if !FFI_NO_STRUCTS if ((*at)->type == FFI_TYPE_STRUCT) - result += ALIGN (sizeof (void*), FFI_SIZEOF_ARG); + result += FFI_ALIGN (sizeof (void*), FFI_SIZEOF_ARG); else #endif - result += ALIGN ((*at)->size, FFI_SIZEOF_ARG); + result += FFI_ALIGN ((*at)->size, FFI_SIZEOF_ARG); } return result; @@ -98,7 +98,7 @@ ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args) default: *args = raw; - raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; + raw += FFI_ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; } } @@ -123,7 +123,7 @@ ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args) else { *args = (void*) raw; - raw += ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*); + raw += FFI_ALIGN ((*tp)->size, sizeof (void*)) / sizeof (void*); } } @@ -186,7 +186,7 @@ ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw) default: memcpy ((void*) raw->data, (void*)*args, (*tp)->size); - raw += ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; + raw += FFI_ALIGN ((*tp)->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; } } } diff --git a/native/libffi/src/riscv/ffi.c b/native/libffi/src/riscv/ffi.c new file mode 100644 index 0000000000..c910858896 --- /dev/null +++ b/native/libffi/src/riscv/ffi.c @@ -0,0 +1,481 @@ +/* ----------------------------------------------------------------------- + ffi.c - Copyright (c) 2015 Michael Knyszek + 2015 Andrew Waterman + 2018 Stef O'Rear + Based on MIPS N32/64 port + + RISC-V Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#include +#include + +#include +#include + +#if __riscv_float_abi_double +#define ABI_FLEN 64 +#define ABI_FLOAT double +#elif __riscv_float_abi_single +#define ABI_FLEN 32 +#define ABI_FLOAT float +#endif + +#define NARGREG 8 +#define STKALIGN 16 +#define MAXCOPYARG (2 * sizeof(double)) + +typedef struct call_context +{ +#if ABI_FLEN + ABI_FLOAT fa[8]; +#endif + size_t a[8]; + /* used by the assembly code to in-place construct its own stack frame */ + char frame[16]; +} call_context; + +typedef struct call_builder +{ + call_context *aregs; + int used_integer; + int used_float; + size_t *used_stack; +} call_builder; + +/* integer (not pointer) less than ABI XLEN */ +/* FFI_TYPE_INT does not appear to be used */ +#if __SIZEOF_POINTER__ == 8 +#define IS_INT(type) ((type) >= FFI_TYPE_UINT8 && (type) <= FFI_TYPE_SINT64) +#else +#define IS_INT(type) ((type) >= FFI_TYPE_UINT8 && (type) <= FFI_TYPE_SINT32) +#endif + +#if ABI_FLEN +typedef struct { + char as_elements, type1, offset2, type2; +} float_struct_info; + +#if ABI_FLEN >= 64 +#define IS_FLOAT(type) ((type) >= FFI_TYPE_FLOAT && (type) <= FFI_TYPE_DOUBLE) +#else +#define IS_FLOAT(type) ((type) == FFI_TYPE_FLOAT) +#endif + +static ffi_type **flatten_struct(ffi_type *in, ffi_type **out, ffi_type **out_end) { + int i; + if (out == out_end) return out; + if (in->type != FFI_TYPE_STRUCT) { + *(out++) = in; + } else { + for (i = 0; in->elements[i]; i++) + out = flatten_struct(in->elements[i], out, out_end); + } + return out; +} + +/* Structs with at most two fields after flattening, one of which is of + floating point type, are passed in multiple registers if sufficient + registers are available. */ +static float_struct_info struct_passed_as_elements(call_builder *cb, ffi_type *top) { + float_struct_info ret = {0, 0, 0, 0}; + ffi_type *fields[3]; + int num_floats, num_ints; + int num_fields = flatten_struct(top, fields, fields + 3) - fields; + + if (num_fields == 1) { + if (IS_FLOAT(fields[0]->type)) { + ret.as_elements = 1; + ret.type1 = fields[0]->type; + } + } else if (num_fields == 2) { + num_floats = IS_FLOAT(fields[0]->type) + IS_FLOAT(fields[1]->type); + num_ints = IS_INT(fields[0]->type) + IS_INT(fields[1]->type); + if (num_floats == 0 || num_floats + num_ints != 2) + return ret; + if (cb->used_float + num_floats > NARGREG || cb->used_integer + (2 - num_floats) > NARGREG) + return ret; + if (!IS_FLOAT(fields[0]->type) && !IS_FLOAT(fields[1]->type)) + return ret; + + ret.type1 = fields[0]->type; + ret.type2 = fields[1]->type; + ret.offset2 = FFI_ALIGN(fields[0]->size, fields[1]->alignment); + ret.as_elements = 1; + } + + return ret; +} +#endif + +/* allocates a single register, float register, or XLEN-sized stack slot to a datum */ +static void marshal_atom(call_builder *cb, int type, void *data) { + size_t value = 0; + switch (type) { + case FFI_TYPE_UINT8: value = *(uint8_t *)data; break; + case FFI_TYPE_SINT8: value = *(int8_t *)data; break; + case FFI_TYPE_UINT16: value = *(uint16_t *)data; break; + case FFI_TYPE_SINT16: value = *(int16_t *)data; break; + /* 32-bit quantities are always sign-extended in the ABI */ + case FFI_TYPE_UINT32: value = *(int32_t *)data; break; + case FFI_TYPE_SINT32: value = *(int32_t *)data; break; +#if __SIZEOF_POINTER__ == 8 + case FFI_TYPE_UINT64: value = *(uint64_t *)data; break; + case FFI_TYPE_SINT64: value = *(int64_t *)data; break; +#endif + case FFI_TYPE_POINTER: value = *(size_t *)data; break; + + /* float values may be recoded in an implementation-defined way + by hardware conforming to 2.1 or earlier, so use asm to + reinterpret floats as doubles */ +#if ABI_FLEN >= 32 + case FFI_TYPE_FLOAT: + asm("" : "=f"(cb->aregs->fa[cb->used_float++]) : "0"(*(float *)data)); + return; +#endif +#if ABI_FLEN >= 64 + case FFI_TYPE_DOUBLE: + asm("" : "=f"(cb->aregs->fa[cb->used_float++]) : "0"(*(double *)data)); + return; +#endif + default: FFI_ASSERT(0); break; + } + + if (cb->used_integer == NARGREG) { + *cb->used_stack++ = value; + } else { + cb->aregs->a[cb->used_integer++] = value; + } +} + +static void unmarshal_atom(call_builder *cb, int type, void *data) { + size_t value; + switch (type) { +#if ABI_FLEN >= 32 + case FFI_TYPE_FLOAT: + asm("" : "=f"(*(float *)data) : "0"(cb->aregs->fa[cb->used_float++])); + return; +#endif +#if ABI_FLEN >= 64 + case FFI_TYPE_DOUBLE: + asm("" : "=f"(*(double *)data) : "0"(cb->aregs->fa[cb->used_float++])); + return; +#endif + } + + if (cb->used_integer == NARGREG) { + value = *cb->used_stack++; + } else { + value = cb->aregs->a[cb->used_integer++]; + } + + switch (type) { + case FFI_TYPE_UINT8: *(uint8_t *)data = value; break; + case FFI_TYPE_SINT8: *(uint8_t *)data = value; break; + case FFI_TYPE_UINT16: *(uint16_t *)data = value; break; + case FFI_TYPE_SINT16: *(uint16_t *)data = value; break; + case FFI_TYPE_UINT32: *(uint32_t *)data = value; break; + case FFI_TYPE_SINT32: *(uint32_t *)data = value; break; +#if __SIZEOF_POINTER__ == 8 + case FFI_TYPE_UINT64: *(uint64_t *)data = value; break; + case FFI_TYPE_SINT64: *(uint64_t *)data = value; break; +#endif + case FFI_TYPE_POINTER: *(size_t *)data = value; break; + default: FFI_ASSERT(0); break; + } +} + +/* adds an argument to a call, or a not by reference return value */ +static void marshal(call_builder *cb, ffi_type *type, int var, void *data) { + size_t realign[2]; + +#if ABI_FLEN + if (!var && type->type == FFI_TYPE_STRUCT) { + float_struct_info fsi = struct_passed_as_elements(cb, type); + if (fsi.as_elements) { + marshal_atom(cb, fsi.type1, data); + if (fsi.offset2) + marshal_atom(cb, fsi.type2, ((char*)data) + fsi.offset2); + return; + } + } + + if (!var && cb->used_float < NARGREG && IS_FLOAT(type->type)) { + marshal_atom(cb, type->type, data); + return; + } +#endif + + if (type->size > 2 * __SIZEOF_POINTER__) { + /* pass by reference */ + marshal_atom(cb, FFI_TYPE_POINTER, &data); + } else if (IS_INT(type->type) || type->type == FFI_TYPE_POINTER) { + marshal_atom(cb, type->type, data); + } else { + /* overlong integers, soft-float floats, and structs without special + float handling are treated identically from this point on */ + + /* variadics are aligned even in registers */ + if (type->alignment > __SIZEOF_POINTER__) { + if (var) + cb->used_integer = FFI_ALIGN(cb->used_integer, 2); + cb->used_stack = (size_t *)FFI_ALIGN(cb->used_stack, 2*__SIZEOF_POINTER__); + } + + memcpy(realign, data, type->size); + if (type->size > 0) + marshal_atom(cb, FFI_TYPE_POINTER, realign); + if (type->size > __SIZEOF_POINTER__) + marshal_atom(cb, FFI_TYPE_POINTER, realign + 1); + } +} + +/* for arguments passed by reference returns the pointer, otherwise the arg is copied (up to MAXCOPYARG bytes) */ +static void *unmarshal(call_builder *cb, ffi_type *type, int var, void *data) { + size_t realign[2]; + void *pointer; + +#if ABI_FLEN + if (!var && type->type == FFI_TYPE_STRUCT) { + float_struct_info fsi = struct_passed_as_elements(cb, type); + if (fsi.as_elements) { + unmarshal_atom(cb, fsi.type1, data); + if (fsi.offset2) + unmarshal_atom(cb, fsi.type2, ((char*)data) + fsi.offset2); + return data; + } + } + + if (!var && cb->used_float < NARGREG && IS_FLOAT(type->type)) { + unmarshal_atom(cb, type->type, data); + return data; + } +#endif + + if (type->size > 2 * __SIZEOF_POINTER__) { + /* pass by reference */ + unmarshal_atom(cb, FFI_TYPE_POINTER, (char*)&pointer); + return pointer; + } else if (IS_INT(type->type) || type->type == FFI_TYPE_POINTER) { + unmarshal_atom(cb, type->type, data); + return data; + } else { + /* overlong integers, soft-float floats, and structs without special + float handling are treated identically from this point on */ + + /* variadics are aligned even in registers */ + if (type->alignment > __SIZEOF_POINTER__) { + if (var) + cb->used_integer = FFI_ALIGN(cb->used_integer, 2); + cb->used_stack = (size_t *)FFI_ALIGN(cb->used_stack, 2*__SIZEOF_POINTER__); + } + + if (type->size > 0) + unmarshal_atom(cb, FFI_TYPE_POINTER, realign); + if (type->size > __SIZEOF_POINTER__) + unmarshal_atom(cb, FFI_TYPE_POINTER, realign + 1); + memcpy(data, realign, type->size); + return data; + } +} + +static int passed_by_ref(call_builder *cb, ffi_type *type, int var) { +#if ABI_FLEN + if (!var && type->type == FFI_TYPE_STRUCT) { + float_struct_info fsi = struct_passed_as_elements(cb, type); + if (fsi.as_elements) return 0; + } +#endif + + return type->size > 2 * __SIZEOF_POINTER__; +} + +/* Perform machine dependent cif processing */ +ffi_status ffi_prep_cif_machdep(ffi_cif *cif) { + cif->riscv_nfixedargs = cif->nargs; + return FFI_OK; +} + +/* Perform machine dependent cif processing when we have a variadic function */ + +ffi_status ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned int nfixedargs, unsigned int ntotalargs) { + cif->riscv_nfixedargs = nfixedargs; + return FFI_OK; +} + +/* Low level routine for calling functions */ +extern void ffi_call_asm (void *stack, struct call_context *regs, + void (*fn) (void), void *closure) FFI_HIDDEN; + +static void +ffi_call_int (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue, + void *closure) +{ + /* this is a conservative estimate, assuming a complex return value and + that all remaining arguments are long long / __int128 */ + size_t arg_bytes = cif->nargs <= 3 ? 0 : + FFI_ALIGN(2 * sizeof(size_t) * (cif->nargs - 3), STKALIGN); + size_t rval_bytes = 0; + if (rvalue == NULL && cif->rtype->size > 2*__SIZEOF_POINTER__) + rval_bytes = FFI_ALIGN(cif->rtype->size, STKALIGN); + size_t alloc_size = arg_bytes + rval_bytes + sizeof(call_context); + + /* the assembly code will deallocate all stack data at lower addresses + than the argument region, so we need to allocate the frame and the + return value after the arguments in a single allocation */ + size_t alloc_base; + /* Argument region must be 16-byte aligned */ + if (_Alignof(max_align_t) >= STKALIGN) { + /* since sizeof long double is normally 16, the compiler will + guarantee alloca alignment to at least that much */ + alloc_base = (size_t)alloca(alloc_size); + } else { + alloc_base = FFI_ALIGN(alloca(alloc_size + STKALIGN - 1), STKALIGN); + } + + if (rval_bytes) + rvalue = (void*)(alloc_base + arg_bytes); + + call_builder cb; + cb.used_float = cb.used_integer = 0; + cb.aregs = (call_context*)(alloc_base + arg_bytes + rval_bytes); + cb.used_stack = (void*)alloc_base; + + int return_by_ref = passed_by_ref(&cb, cif->rtype, 0); + if (return_by_ref) + marshal(&cb, &ffi_type_pointer, 0, &rvalue); + + int i; + for (i = 0; i < cif->nargs; i++) + marshal(&cb, cif->arg_types[i], i >= cif->riscv_nfixedargs, avalue[i]); + + ffi_call_asm ((void *) alloc_base, cb.aregs, fn, closure); + + cb.used_float = cb.used_integer = 0; + if (!return_by_ref && rvalue) + unmarshal(&cb, cif->rtype, 0, rvalue); +} + +void +ffi_call (ffi_cif *cif, void (*fn) (void), void *rvalue, void **avalue) +{ + ffi_call_int(cif, fn, rvalue, avalue, NULL); +} + +void +ffi_call_go (ffi_cif *cif, void (*fn) (void), void *rvalue, + void **avalue, void *closure) +{ + ffi_call_int(cif, fn, rvalue, avalue, closure); +} + +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; + + /* 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) */ +#if __SIZEOF_POINTER__ == 8 + tramp[1] = 0x01033383; /* ld t2, 16(t1) */ +#else + tramp[1] = 0x01032383; /* lw t2, 16(t1) */ +#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; + + __builtin___clear_cache(codeloc, codeloc + FFI_TRAMPOLINE_SIZE); + + return FFI_OK; +} + +extern void ffi_go_closure_asm (void) FFI_HIDDEN; + +ffi_status +ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif, + void (*fun) (ffi_cif *, void *, void **, void *)) +{ + if (cif->abi <= FFI_FIRST_ABI || cif->abi >= FFI_LAST_ABI) + return FFI_BAD_ABI; + + closure->tramp = (void *) ffi_go_closure_asm; + closure->cif = cif; + closure->fun = fun; + + return FFI_OK; +} + +/* Called by the assembly code with aregs pointing to saved argument registers + and stack pointing to the stacked arguments. Return values passed in + registers will be reloaded from aregs. */ +void FFI_HIDDEN +ffi_closure_inner (ffi_cif *cif, + void (*fun) (ffi_cif *, void *, void **, void *), + void *user_data, + size_t *stack, call_context *aregs) +{ + void **avalue = alloca(cif->nargs * sizeof(void*)); + /* storage for arguments which will be copied by unmarshal(). We could + theoretically avoid the copies in many cases and use at most 128 bytes + of memory, but allocating disjoint storage for each argument is + simpler. */ + char *astorage = alloca(cif->nargs * MAXCOPYARG); + void *rvalue; + call_builder cb; + int return_by_ref; + int i; + + cb.aregs = aregs; + cb.used_integer = cb.used_float = 0; + cb.used_stack = stack; + + return_by_ref = passed_by_ref(&cb, cif->rtype, 0); + if (return_by_ref) + unmarshal(&cb, &ffi_type_pointer, 0, &rvalue); + else + rvalue = alloca(cif->rtype->size); + + for (i = 0; i < cif->nargs; i++) + avalue[i] = unmarshal(&cb, cif->arg_types[i], + i >= cif->riscv_nfixedargs, astorage + i*MAXCOPYARG); + + fun (cif, rvalue, avalue, user_data); + + if (!return_by_ref && cif->rtype->type != FFI_TYPE_VOID) { + cb.used_integer = cb.used_float = 0; + marshal(&cb, cif->rtype, 0, rvalue); + } +} diff --git a/native/libffi/src/riscv/ffitarget.h b/native/libffi/src/riscv/ffitarget.h new file mode 100644 index 0000000000..75e6462f5b --- /dev/null +++ b/native/libffi/src/riscv/ffitarget.h @@ -0,0 +1,69 @@ +/* -----------------------------------------------------------------*-C-*- + ffitarget.h - 2014 Michael Knyszek + + Target configuration macros for RISC-V. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + ----------------------------------------------------------------------- */ + +#ifndef LIBFFI_TARGET_H +#define LIBFFI_TARGET_H + +#ifndef LIBFFI_H +#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." +#endif + +#ifndef __riscv +#error "libffi was configured for a RISC-V target but this does not appear to be a RISC-V compiler." +#endif + +#ifndef LIBFFI_ASM + +typedef unsigned long ffi_arg; +typedef signed long ffi_sarg; + +/* FFI_UNUSED_NN and riscv_unused are to maintain ABI compatibility with a + distributed Berkeley patch from 2014, and can be removed at SONAME bump */ +typedef enum ffi_abi { + FFI_FIRST_ABI = 0, + FFI_SYSV, + FFI_UNUSED_1, + FFI_UNUSED_2, + FFI_UNUSED_3, + FFI_LAST_ABI, + + FFI_DEFAULT_ABI = FFI_SYSV +} ffi_abi; + +#endif /* LIBFFI_ASM */ + +/* ---- Definitions for closures ----------------------------------------- */ + +#define FFI_CLOSURES 1 +#define FFI_GO_CLOSURES 1 +#define FFI_TRAMPOLINE_SIZE 24 +#define FFI_NATIVE_RAW_API 0 +#define FFI_EXTRA_CIF_FIELDS unsigned riscv_nfixedargs; unsigned riscv_unused; +#define FFI_TARGET_SPECIFIC_VARIADIC + +#endif + diff --git a/native/libffi/src/riscv/sysv.S b/native/libffi/src/riscv/sysv.S new file mode 100644 index 0000000000..522d0b0055 --- /dev/null +++ b/native/libffi/src/riscv/sysv.S @@ -0,0 +1,293 @@ +/* ----------------------------------------------------------------------- + ffi.c - Copyright (c) 2015 Michael Knyszek + 2015 Andrew Waterman + 2018 Stef O'Rear + + RISC-V Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#define LIBFFI_ASM +#include +#include + +/* Define aliases so that we can handle all ABIs uniformly */ + +#if __SIZEOF_POINTER__ == 8 +#define PTRS 8 +#define LARG ld +#define SARG sd +#else +#define PTRS 4 +#define LARG lw +#define SARG sw +#endif + +#if __riscv_float_abi_double +#define FLTS 8 +#define FLARG fld +#define FSARG fsd +#elif __riscv_float_abi_single +#define FLTS 4 +#define FLARG flw +#define FSARG fsw +#else +#define FLTS 0 +#endif + +#define fp s0 + + .text + .globl ffi_call_asm + .type ffi_call_asm, @function + .hidden ffi_call_asm +/* + struct call_context { + floatreg fa[8]; + intreg a[8]; + intreg pad[rv32 ? 2 : 0]; + intreg save_fp, save_ra; + } + void ffi_call_asm (size_t *stackargs, struct call_context *regargs, + void (*fn) (void), void *closure); +*/ + +#define FRAME_LEN (8 * FLTS + 8 * PTRS + 16) + +ffi_call_asm: + .cfi_startproc + + /* + We are NOT going to set up an ordinary stack frame. In order to pass + the stacked args to the called function, we adjust our stack pointer to + a0, which is in the _caller's_ alloca area. We establish our own stack + frame at the end of the call_context. + + Anything below the arguments will be freed at this point, although we + preserve the call_context so that it can be read back in the caller. + */ + + .cfi_def_cfa 11, FRAME_LEN # interim CFA based on a1 + SARG fp, FRAME_LEN - 2*PTRS(a1) + .cfi_offset 8, -2*PTRS + SARG ra, FRAME_LEN - 1*PTRS(a1) + .cfi_offset 1, -1*PTRS + + addi fp, a1, FRAME_LEN + mv sp, a0 + .cfi_def_cfa 8, 0 # our frame is fully set up + + # Load arguments + mv t1, a2 + mv t2, a3 + +#if FLTS + FLARG fa0, -FRAME_LEN+0*FLTS(fp) + FLARG fa1, -FRAME_LEN+1*FLTS(fp) + FLARG fa2, -FRAME_LEN+2*FLTS(fp) + FLARG fa3, -FRAME_LEN+3*FLTS(fp) + FLARG fa4, -FRAME_LEN+4*FLTS(fp) + FLARG fa5, -FRAME_LEN+5*FLTS(fp) + FLARG fa6, -FRAME_LEN+6*FLTS(fp) + FLARG fa7, -FRAME_LEN+7*FLTS(fp) +#endif + + LARG a0, -FRAME_LEN+8*FLTS+0*PTRS(fp) + LARG a1, -FRAME_LEN+8*FLTS+1*PTRS(fp) + LARG a2, -FRAME_LEN+8*FLTS+2*PTRS(fp) + LARG a3, -FRAME_LEN+8*FLTS+3*PTRS(fp) + LARG a4, -FRAME_LEN+8*FLTS+4*PTRS(fp) + LARG a5, -FRAME_LEN+8*FLTS+5*PTRS(fp) + LARG a6, -FRAME_LEN+8*FLTS+6*PTRS(fp) + LARG a7, -FRAME_LEN+8*FLTS+7*PTRS(fp) + + /* Call */ + jalr t1 + + /* Save return values - only a0/a1 (fa0/fa1) are used */ +#if FLTS + FSARG fa0, -FRAME_LEN+0*FLTS(fp) + FSARG fa1, -FRAME_LEN+1*FLTS(fp) +#endif + + SARG a0, -FRAME_LEN+8*FLTS+0*PTRS(fp) + SARG a1, -FRAME_LEN+8*FLTS+1*PTRS(fp) + + /* Restore and return */ + addi sp, fp, -FRAME_LEN + .cfi_def_cfa 2, FRAME_LEN + LARG ra, -1*PTRS(fp) + .cfi_restore 1 + LARG fp, -2*PTRS(fp) + .cfi_restore 8 + ret + .cfi_endproc + .size ffi_call_asm, .-ffi_call_asm + + +/* + ffi_closure_asm. Expects address of the passed-in ffi_closure in t1. + void ffi_closure_inner (ffi_cif *cif, + void (*fun) (ffi_cif *, void *, void **, void *), + void *user_data, + size_t *stackargs, struct call_context *regargs) +*/ + + .globl ffi_closure_asm + .hidden ffi_closure_asm + .type ffi_closure_asm, @function +ffi_closure_asm: + .cfi_startproc + + addi sp, sp, -FRAME_LEN + .cfi_def_cfa_offset FRAME_LEN + + /* make a frame */ + SARG fp, FRAME_LEN - 2*PTRS(sp) + .cfi_offset 8, -2*PTRS + SARG ra, FRAME_LEN - 1*PTRS(sp) + .cfi_offset 1, -1*PTRS + addi fp, sp, FRAME_LEN + + /* save arguments */ +#if FLTS + FSARG fa0, 0*FLTS(sp) + FSARG fa1, 1*FLTS(sp) + FSARG fa2, 2*FLTS(sp) + FSARG fa3, 3*FLTS(sp) + FSARG fa4, 4*FLTS(sp) + FSARG fa5, 5*FLTS(sp) + FSARG fa6, 6*FLTS(sp) + FSARG fa7, 7*FLTS(sp) +#endif + + SARG a0, 8*FLTS+0*PTRS(sp) + SARG a1, 8*FLTS+1*PTRS(sp) + SARG a2, 8*FLTS+2*PTRS(sp) + SARG a3, 8*FLTS+3*PTRS(sp) + SARG a4, 8*FLTS+4*PTRS(sp) + SARG a5, 8*FLTS+5*PTRS(sp) + SARG a6, 8*FLTS+6*PTRS(sp) + SARG a7, 8*FLTS+7*PTRS(sp) + + /* enter C */ + LARG a0, FFI_TRAMPOLINE_SIZE+0*PTRS(t1) + LARG a1, FFI_TRAMPOLINE_SIZE+1*PTRS(t1) + LARG a2, FFI_TRAMPOLINE_SIZE+2*PTRS(t1) + addi a3, sp, FRAME_LEN + mv a4, sp + + call ffi_closure_inner + + /* return values */ +#if FLTS + FLARG fa0, 0*FLTS(sp) + FLARG fa1, 1*FLTS(sp) +#endif + + LARG a0, 8*FLTS+0*PTRS(sp) + LARG a1, 8*FLTS+1*PTRS(sp) + + /* restore and return */ + LARG ra, FRAME_LEN-1*PTRS(sp) + .cfi_restore 1 + LARG fp, FRAME_LEN-2*PTRS(sp) + .cfi_restore 8 + addi sp, sp, FRAME_LEN + .cfi_def_cfa_offset 0 + ret + .cfi_endproc + .size ffi_closure_asm, .-ffi_closure_asm + +/* + ffi_go_closure_asm. Expects address of the passed-in ffi_go_closure in t2. + void ffi_closure_inner (ffi_cif *cif, + void (*fun) (ffi_cif *, void *, void **, void *), + void *user_data, + size_t *stackargs, struct call_context *regargs) +*/ + + .globl ffi_go_closure_asm + .hidden ffi_go_closure_asm + .type ffi_go_closure_asm, @function +ffi_go_closure_asm: + .cfi_startproc + + addi sp, sp, -FRAME_LEN + .cfi_def_cfa_offset FRAME_LEN + + /* make a frame */ + SARG fp, FRAME_LEN - 2*PTRS(sp) + .cfi_offset 8, -2*PTRS + SARG ra, FRAME_LEN - 1*PTRS(sp) + .cfi_offset 1, -1*PTRS + addi fp, sp, FRAME_LEN + + /* save arguments */ +#if FLTS + FSARG fa0, 0*FLTS(sp) + FSARG fa1, 1*FLTS(sp) + FSARG fa2, 2*FLTS(sp) + FSARG fa3, 3*FLTS(sp) + FSARG fa4, 4*FLTS(sp) + FSARG fa5, 5*FLTS(sp) + FSARG fa6, 6*FLTS(sp) + FSARG fa7, 7*FLTS(sp) +#endif + + SARG a0, 8*FLTS+0*PTRS(sp) + SARG a1, 8*FLTS+1*PTRS(sp) + SARG a2, 8*FLTS+2*PTRS(sp) + SARG a3, 8*FLTS+3*PTRS(sp) + SARG a4, 8*FLTS+4*PTRS(sp) + SARG a5, 8*FLTS+5*PTRS(sp) + SARG a6, 8*FLTS+6*PTRS(sp) + SARG a7, 8*FLTS+7*PTRS(sp) + + /* enter C */ + LARG a0, 1*PTRS(t2) + LARG a1, 2*PTRS(t2) + mv a2, t2 + addi a3, sp, FRAME_LEN + mv a4, sp + + call ffi_closure_inner + + /* return values */ +#if FLTS + FLARG fa0, 0*FLTS(sp) + FLARG fa1, 1*FLTS(sp) +#endif + + LARG a0, 8*FLTS+0*PTRS(sp) + LARG a1, 8*FLTS+1*PTRS(sp) + + /* restore and return */ + LARG ra, FRAME_LEN-1*PTRS(sp) + .cfi_restore 1 + LARG fp, FRAME_LEN-2*PTRS(sp) + .cfi_restore 8 + addi sp, sp, FRAME_LEN + .cfi_def_cfa_offset 0 + ret + .cfi_endproc + .size ffi_go_closure_asm, .-ffi_go_closure_asm diff --git a/native/libffi/src/s390/ffi.c b/native/libffi/src/s390/ffi.c index 520ec7c61f..c75c894d31 100644 --- a/native/libffi/src/s390/ffi.c +++ b/native/libffi/src/s390/ffi.c @@ -1,9 +1,9 @@ /* ----------------------------------------------------------------------- ffi.c - Copyright (c) 2000, 2007 Software AG Copyright (c) 2008 Red Hat, Inc - + S390 Foreign Function Interface - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ``Software''), to deal in the Software without restriction, including @@ -11,10 +11,10 @@ distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. @@ -27,24 +27,23 @@ /* Includes */ /* -------- */ /*====================================================================*/ - + #include #include - -#include -#include - +#include +#include "internal.h" + /*====================== End of Includes =============================*/ - + /*====================================================================*/ /* Defines */ /* ------- */ /*====================================================================*/ -/* Maximum number of GPRs available for argument passing. */ +/* Maximum number of GPRs available for argument passing. */ #define MAX_GPRARGS 5 -/* Maximum number of FPRs available for argument passing. */ +/* Maximum number of FPRs available for argument passing. */ #ifdef __s390x__ #define MAX_FPRARGS 4 #else @@ -54,47 +53,30 @@ /* Round to multiple of 16. */ #define ROUND_SIZE(size) (((size) + 15) & ~15) -/* If these values change, sysv.S must be adapted! */ -#define FFI390_RET_VOID 0 -#define FFI390_RET_STRUCT 1 -#define FFI390_RET_FLOAT 2 -#define FFI390_RET_DOUBLE 3 -#define FFI390_RET_INT32 4 -#define FFI390_RET_INT64 5 - /*===================== End of Defines ===============================*/ - -/*====================================================================*/ -/* Prototypes */ -/* ---------- */ -/*====================================================================*/ - -static void ffi_prep_args (unsigned char *, extended_cif *); -void -#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2) -__attribute__ ((visibility ("hidden"))) -#endif -ffi_closure_helper_SYSV (ffi_closure *, unsigned long *, - unsigned long long *, unsigned long *); -/*====================== End of Prototypes ===========================*/ - /*====================================================================*/ /* Externals */ /* --------- */ /*====================================================================*/ - -extern void ffi_call_SYSV(unsigned, - extended_cif *, - void (*)(unsigned char *, extended_cif *), - unsigned, - void *, - void (*fn)(void)); + +struct call_frame +{ + void *back_chain; + void *eos; + unsigned long gpr_args[5]; + unsigned long gpr_save[9]; + unsigned long long fpr_args[4]; +}; + +extern void FFI_HIDDEN ffi_call_SYSV(struct call_frame *, unsigned, void *, + void (*fn)(void), void *); extern void ffi_closure_SYSV(void); - +extern void ffi_go_closure_SYSV(void); + /*====================== End of Externals ============================*/ - + /*====================================================================*/ /* */ /* Name - ffi_check_struct_type. */ @@ -103,7 +85,7 @@ extern void ffi_closure_SYSV(void); /* general purpose or floating point register. */ /* */ /*====================================================================*/ - + static int ffi_check_struct_type (ffi_type *arg) { @@ -111,7 +93,7 @@ ffi_check_struct_type (ffi_type *arg) /* If the struct has just one element, look at that element to find out whether to consider the struct as floating point. */ - while (arg->type == FFI_TYPE_STRUCT + while (arg->type == FFI_TYPE_STRUCT && arg->elements[0] && !arg->elements[1]) arg = arg->elements[0]; @@ -144,6 +126,7 @@ ffi_check_struct_type (ffi_type *arg) /* Other structs are passed via a pointer to the data. */ return FFI_TYPE_POINTER; } +<<<<<<< HEAD /*======================== End of Routine ============================*/ @@ -328,9 +311,11 @@ ffi_prep_args (unsigned char *stack, extended_cif *ecif) } } } +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 /*======================== End of Routine ============================*/ - + /*====================================================================*/ /* */ /* Name - ffi_prep_cif_machdep. */ @@ -338,8 +323,8 @@ ffi_prep_args (unsigned char *stack, extended_cif *ecif) /* Function - Perform machine dependent CIF processing. */ /* */ /*====================================================================*/ - -ffi_status + +ffi_status FFI_HIDDEN ffi_prep_cif_machdep(ffi_cif *cif) { size_t struct_size = 0; @@ -350,7 +335,7 @@ ffi_prep_cif_machdep(ffi_cif *cif) ffi_type **ptr; int i; - /* Determine return value handling. */ + /* Determine return value handling. */ switch (cif->rtype->type) { @@ -364,7 +349,7 @@ ffi_prep_cif_machdep(ffi_cif *cif) case FFI_TYPE_COMPLEX: cif->flags = FFI390_RET_STRUCT; n_gpr++; /* We need one GPR to pass the pointer. */ - break; + break; /* Floating point values are returned in fpr 0. */ case FFI_TYPE_FLOAT: @@ -403,14 +388,14 @@ ffi_prep_cif_machdep(ffi_cif *cif) cif->flags = FFI390_RET_INT32; #endif break; - + default: FFI_ASSERT (0); break; } /* Now for the arguments. */ - + for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) @@ -438,7 +423,7 @@ ffi_prep_cif_machdep(ffi_cif *cif) } /* Now handle all primitive int/float data types. */ - switch (type) + switch (type) { /* The first MAX_FPRARGS floating point arguments go in FPRs, the rest overflow to the stack. */ @@ -449,7 +434,7 @@ ffi_prep_cif_machdep(ffi_cif *cif) else n_ov += sizeof (double) / sizeof (long); break; - + case FFI_TYPE_FLOAT: if (n_fpr < MAX_FPRARGS) n_fpr++; @@ -459,9 +444,9 @@ ffi_prep_cif_machdep(ffi_cif *cif) /* On 31-bit machines, 64-bit integers are passed in GPR pairs, if one is still available, or else on the stack. If only one - register is free, skip the register (it won't be used for any + register is free, skip the register (it won't be used for any subsequent argument either). */ - + #ifndef __s390x__ case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: @@ -477,7 +462,7 @@ ffi_prep_cif_machdep(ffi_cif *cif) /* Everything else is passed in GPRs (until MAX_GPRARGS have been used) or overflows to the stack. */ - default: + default: if (n_gpr < MAX_GPRARGS) n_gpr++; else @@ -490,12 +475,12 @@ ffi_prep_cif_machdep(ffi_cif *cif) and temporary structure copies. */ cif->bytes = ROUND_SIZE (n_ov * sizeof (long)) + struct_size; - + return FFI_OK; } - + /*======================== End of Routine ============================*/ - + /*====================================================================*/ /* */ /* Name - ffi_call. */ @@ -503,42 +488,195 @@ ffi_prep_cif_machdep(ffi_cif *cif) /* Function - Call the FFI routine. */ /* */ /*====================================================================*/ - -void -ffi_call(ffi_cif *cif, - void (*fn)(void), - void *rvalue, - void **avalue) + +static void +ffi_call_int(ffi_cif *cif, + void (*fn)(void), + void *rvalue, + void **avalue, + void *closure) { int ret_type = cif->flags; - extended_cif ecif; - - ecif.cif = cif; - ecif.avalue = avalue; - ecif.rvalue = rvalue; + size_t rsize = 0, bytes = cif->bytes; + unsigned char *stack, *p_struct; + struct call_frame *frame; + unsigned long *p_ov, *p_gpr; + unsigned long long *p_fpr; + int n_fpr, n_gpr, n_ov, i, n; + ffi_type **arg_types; + + FFI_ASSERT (cif->abi == FFI_SYSV); /* If we don't have a return value, we need to fake one. */ if (rvalue == NULL) { - if (ret_type == FFI390_RET_STRUCT) - ecif.rvalue = alloca (cif->rtype->size); + if (ret_type & FFI390_RET_IN_MEM) + rsize = cif->rtype->size; else ret_type = FFI390_RET_VOID; - } + } + + /* The stack space will be filled with those areas: + + dummy structure return (highest addresses) + FPR argument register save area + GPR argument register save area + stack frame for ffi_call_SYSV + temporary struct copies + overflow argument area (lowest addresses) + + We set up the following pointers: + + p_fpr: bottom of the FPR area (growing upwards) + p_gpr: bottom of the GPR area (growing upwards) + p_ov: bottom of the overflow area (growing upwards) + p_struct: top of the struct copy area (growing downwards) + + All areas are kept aligned to twice the word size. + + Note that we're going to create the stack frame for both + ffi_call_SYSV _and_ the target function right here. This + works because we don't make any function calls with more + than 5 arguments (indeed only memcpy and ffi_call_SYSV), + and thus we don't have any stacked outgoing parameters. */ - switch (cif->abi) + stack = alloca (bytes + sizeof(struct call_frame) + rsize); + frame = (struct call_frame *)(stack + bytes); + if (rsize) + rvalue = frame + 1; + + /* Link the new frame back to the one from this function. */ + frame->back_chain = __builtin_frame_address (0); + + /* Fill in all of the argument stuff. */ + p_ov = (unsigned long *)stack; + p_struct = (unsigned char *)frame; + p_gpr = frame->gpr_args; + p_fpr = frame->fpr_args; + n_fpr = n_gpr = n_ov = 0; + + /* If we returning a structure then we set the first parameter register + to the address of where we are returning this structure. */ + if (cif->flags & FFI390_RET_IN_MEM) + p_gpr[n_gpr++] = (uintptr_t) rvalue; + + /* Now for the arguments. */ + arg_types = cif->arg_types; + for (i = 0, n = cif->nargs; i < n; ++i) { - case FFI_SYSV: - ffi_call_SYSV (cif->bytes, &ecif, ffi_prep_args, - ret_type, ecif.rvalue, fn); - break; - - default: - FFI_ASSERT (0); - break; + ffi_type *ty = arg_types[i]; + void *arg = avalue[i]; + int type = ty->type; + ffi_arg val; + + restart: + switch (type) + { + case FFI_TYPE_SINT8: + val = *(SINT8 *)arg; + goto do_int; + case FFI_TYPE_UINT8: + val = *(UINT8 *)arg; + goto do_int; + case FFI_TYPE_SINT16: + val = *(SINT16 *)arg; + goto do_int; + case FFI_TYPE_UINT16: + val = *(UINT16 *)arg; + goto do_int; + case FFI_TYPE_INT: + case FFI_TYPE_SINT32: + val = *(SINT32 *)arg; + goto do_int; + case FFI_TYPE_UINT32: + val = *(UINT32 *)arg; + goto do_int; + case FFI_TYPE_POINTER: + val = *(uintptr_t *)arg; + do_int: + *(n_gpr < MAX_GPRARGS ? p_gpr + n_gpr++ : p_ov + n_ov++) = val; + break; + + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: +#ifdef __s390x__ + val = *(UINT64 *)arg; + goto do_int; +#else + if (n_gpr == MAX_GPRARGS-1) + n_gpr = MAX_GPRARGS; + if (n_gpr < MAX_GPRARGS) + p_gpr[n_gpr++] = ((UINT32 *) arg)[0], + p_gpr[n_gpr++] = ((UINT32 *) arg)[1]; + else + p_ov[n_ov++] = ((UINT32 *) arg)[0], + p_ov[n_ov++] = ((UINT32 *) arg)[1]; +#endif + break; + + case FFI_TYPE_DOUBLE: + if (n_fpr < MAX_FPRARGS) + p_fpr[n_fpr++] = *(UINT64 *) arg; + else + { +#ifdef __s390x__ + p_ov[n_ov++] = *(UINT64 *) arg; +#else + p_ov[n_ov++] = ((UINT32 *) arg)[0], + p_ov[n_ov++] = ((UINT32 *) arg)[1]; +#endif + } + break; + + case FFI_TYPE_FLOAT: + val = *(UINT32 *)arg; + if (n_fpr < MAX_FPRARGS) + p_fpr[n_fpr++] = (UINT64)val << 32; + else + p_ov[n_ov++] = val; + break; + + case FFI_TYPE_STRUCT: + /* Check how a structure type is passed. */ + type = ffi_check_struct_type (ty); + /* Some structures are passed via a type they contain. */ + if (type != FFI_TYPE_POINTER) + goto restart; + /* ... otherwise, passed by reference. fallthru. */ + +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + case FFI_TYPE_LONGDOUBLE: + /* 16-byte long double is passed via reference. */ +#endif + case FFI_TYPE_COMPLEX: + /* Complex types are passed via reference. */ + p_struct -= ROUND_SIZE (ty->size); + memcpy (p_struct, arg, ty->size); + val = (uintptr_t)p_struct; + goto do_int; + + default: + FFI_ASSERT (0); + break; + } } + + ffi_call_SYSV (frame, ret_type & FFI360_RET_MASK, rvalue, fn, closure); } - + +void +ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +{ + ffi_call_int(cif, fn, rvalue, avalue, NULL); +} + +void +ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure) +{ + ffi_call_int(cif, fn, rvalue, avalue, closure); +} + /*======================== End of Routine ============================*/ /*====================================================================*/ @@ -548,9 +686,11 @@ ffi_call(ffi_cif *cif, /* Function - Call a FFI closure target function. */ /* */ /*====================================================================*/ - -void -ffi_closure_helper_SYSV (ffi_closure *closure, + +void FFI_HIDDEN +ffi_closure_helper_SYSV (ffi_cif *cif, + void (*fun)(ffi_cif*,void*,void**,void*), + void *user_data, unsigned long *p_gpr, unsigned long long *p_fpr, unsigned long *p_ov) @@ -569,21 +709,16 @@ ffi_closure_helper_SYSV (ffi_closure *closure, int i; /* Allocate buffer for argument list pointers. */ + p_arg = avalue = alloca (cif->nargs * sizeof (void *)); - p_arg = avalue = alloca (closure->cif->nargs * sizeof (void *)); - - /* If we returning a structure, pass the structure address - directly to the target function. Otherwise, have the target + /* If we returning a structure, pass the structure address + directly to the target function. Otherwise, have the target function store the return value to the GPR save area. */ - - if (closure->cif->flags == FFI390_RET_STRUCT) + if (cif->flags & FFI390_RET_IN_MEM) rvalue = (void *) p_gpr[n_gpr++]; /* Now for the arguments. */ - - for (ptr = closure->cif->arg_types, i = closure->cif->nargs; - i > 0; - i--, p_arg++, ptr++) + for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, p_arg++, ptr++) { int deref_struct_pointer = 0; int type = (*ptr)->type; @@ -602,7 +737,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, else type = ffi_check_struct_type (*ptr); - /* If we pass the struct via pointer, remember to + /* If we pass the struct via pointer, remember to retrieve the pointer later. */ if (type == FFI_TYPE_POINTER) deref_struct_pointer = 1; @@ -610,30 +745,32 @@ ffi_closure_helper_SYSV (ffi_closure *closure, /* Pointers are passed like UINTs of the same size. */ if (type == FFI_TYPE_POINTER) + { #ifdef __s390x__ - type = FFI_TYPE_UINT64; + type = FFI_TYPE_UINT64; #else - type = FFI_TYPE_UINT32; + type = FFI_TYPE_UINT32; #endif + } /* Now handle all primitive int/float data types. */ - switch (type) + switch (type) { case FFI_TYPE_DOUBLE: if (n_fpr < MAX_FPRARGS) *p_arg = &p_fpr[n_fpr++]; else - *p_arg = &p_ov[n_ov], + *p_arg = &p_ov[n_ov], n_ov += sizeof (double) / sizeof (long); break; - + case FFI_TYPE_FLOAT: if (n_fpr < MAX_FPRARGS) *p_arg = &p_fpr[n_fpr++]; else *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4; break; - + case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: #ifdef __s390x__ @@ -650,7 +787,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, *p_arg = &p_ov[n_ov], n_ov += 2; #endif break; - + case FFI_TYPE_INT: case FFI_TYPE_UINT32: case FFI_TYPE_SINT32: @@ -659,7 +796,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, else *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 4; break; - + case FFI_TYPE_UINT16: case FFI_TYPE_SINT16: if (n_gpr < MAX_GPRARGS) @@ -675,7 +812,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, else *p_arg = (char *)&p_ov[n_ov++] + sizeof (long) - 1; break; - + default: FFI_ASSERT (0); break; @@ -689,10 +826,10 @@ ffi_closure_helper_SYSV (ffi_closure *closure, /* Call the target function. */ - (closure->fun) (closure->cif, rvalue, avalue, closure->user_data); + (fun) (cif, rvalue, avalue, user_data); /* Convert the return value. */ - switch (closure->cif->rtype->type) + switch (cif->rtype->type) { /* Void is easy, and so is struct. */ case FFI_TYPE_VOID: @@ -743,7 +880,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, break; } } - + /*======================== End of Routine ============================*/ /*====================================================================*/ @@ -753,7 +890,7 @@ ffi_closure_helper_SYSV (ffi_closure *closure, /* Function - Prepare a FFI closure. */ /* */ /*====================================================================*/ - + ffi_status ffi_prep_closure_loc (ffi_closure *closure, ffi_cif *cif, @@ -761,32 +898,46 @@ ffi_prep_closure_loc (ffi_closure *closure, void *user_data, void *codeloc) { + static unsigned short const template[] = { + 0x0d10, /* basr %r1,0 */ +#ifndef __s390x__ + 0x9801, 0x1006, /* lm %r0,%r1,6(%r1) */ +#else + 0xeb01, 0x100e, 0x0004, /* lmg %r0,%r1,14(%r1) */ +#endif + 0x07f1 /* br %r1 */ + }; + + unsigned long *tramp = (unsigned long *)&closure->tramp; + if (cif->abi != FFI_SYSV) return FFI_BAD_ABI; -#ifndef __s390x__ - *(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */ - *(short *)&closure->tramp [2] = 0x9801; /* lm %r0,%r1,6(%r1) */ - *(short *)&closure->tramp [4] = 0x1006; - *(short *)&closure->tramp [6] = 0x07f1; /* br %r1 */ - *(long *)&closure->tramp [8] = (long)codeloc; - *(long *)&closure->tramp[12] = (long)&ffi_closure_SYSV; -#else - *(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */ - *(short *)&closure->tramp [2] = 0xeb01; /* lmg %r0,%r1,14(%r1) */ - *(short *)&closure->tramp [4] = 0x100e; - *(short *)&closure->tramp [6] = 0x0004; - *(short *)&closure->tramp [8] = 0x07f1; /* br %r1 */ - *(long *)&closure->tramp[16] = (long)codeloc; - *(long *)&closure->tramp[24] = (long)&ffi_closure_SYSV; -#endif - + memcpy (tramp, template, sizeof(template)); + tramp[2] = (unsigned long)codeloc; + tramp[3] = (unsigned long)&ffi_closure_SYSV; + closure->cif = cif; - closure->user_data = user_data; closure->fun = fun; - + closure->user_data = user_data; + return FFI_OK; } /*======================== End of Routine ============================*/ - + +/* Build a Go language closure. */ + +ffi_status +ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif, + void (*fun)(ffi_cif*,void*,void**,void*)) +{ + if (cif->abi != FFI_SYSV) + return FFI_BAD_ABI; + + closure->tramp = ffi_go_closure_SYSV; + closure->cif = cif; + closure->fun = fun; + + return FFI_OK; +} diff --git a/native/libffi/src/s390/ffitarget.h b/native/libffi/src/s390/ffitarget.h index 0e4868a1c4..d8a4ee4bf1 100644 --- a/native/libffi/src/s390/ffitarget.h +++ b/native/libffi/src/s390/ffitarget.h @@ -58,6 +58,7 @@ typedef enum ffi_abi { /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 +#define FFI_GO_CLOSURES 1 #ifdef S390X #define FFI_TRAMPOLINE_SIZE 32 #else diff --git a/native/libffi/src/s390/internal.h b/native/libffi/src/s390/internal.h new file mode 100644 index 0000000000..b8755786f9 --- /dev/null +++ b/native/libffi/src/s390/internal.h @@ -0,0 +1,11 @@ +/* If these values change, sysv.S must be adapted! */ +#define FFI390_RET_DOUBLE 0 +#define FFI390_RET_FLOAT 1 +#define FFI390_RET_INT64 2 +#define FFI390_RET_INT32 3 +#define FFI390_RET_VOID 4 + +#define FFI360_RET_MASK 7 +#define FFI390_RET_IN_MEM 8 + +#define FFI390_RET_STRUCT (FFI390_RET_VOID | FFI390_RET_IN_MEM) diff --git a/native/libffi/src/s390/sysv.S b/native/libffi/src/s390/sysv.S index 4731a3177b..c4b5006aed 100644 --- a/native/libffi/src/s390/sysv.S +++ b/native/libffi/src/s390/sysv.S @@ -1,9 +1,9 @@ /* ----------------------------------------------------------------------- sysv.S - Copyright (c) 2000 Software AG Copyright (c) 2008 Red Hat, Inc. - + S390 Foreign Function Interface - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ``Software''), to deal in the Software without restriction, including @@ -11,10 +11,10 @@ distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -29,405 +29,296 @@ #include #include + .text + #ifndef __s390x__ - -.text - - # r2: cif->bytes - # r3: &ecif - # r4: ffi_prep_args - # r5: ret_type - # r6: ecif.rvalue - # ov: fn - + + # r2: frame + # r3: ret_type + # r4: ret_addr + # r5: fun + # r6: closure + # This assumes we are using gas. + .balign 8 .globl ffi_call_SYSV + FFI_HIDDEN(ffi_call_SYSV) .type ffi_call_SYSV,%function ffi_call_SYSV: -.LFB1: - stm %r6,%r15,24(%r15) # Save registers -.LCFI0: - basr %r13,0 # Set up base register -.Lbase: - lr %r11,%r15 # Set up frame pointer -.LCFI1: - sr %r15,%r2 - ahi %r15,-96-48 # Allocate stack - lr %r8,%r6 # Save ecif.rvalue - sr %r9,%r9 - ic %r9,.Ltable-.Lbase(%r13,%r5) # Load epilog address - l %r7,96(%r11) # Load function address - st %r11,0(%r15) # Set up back chain - ahi %r11,-48 # Register save area -.LCFI2: - - la %r2,96(%r15) # Save area - # r3 already holds &ecif - basr %r14,%r4 # Call ffi_prep_args - - lm %r2,%r6,0(%r11) # Load arguments - ld %f0,32(%r11) - ld %f2,40(%r11) - la %r14,0(%r13,%r9) # Set return address - br %r7 # ... and call function - -.LretNone: # Return void - l %r4,48+56(%r11) - lm %r6,%r15,48+24(%r11) - br %r4 - -.LretFloat: - l %r4,48+56(%r11) - ste %f0,0(%r8) # Return float - lm %r6,%r15,48+24(%r11) - br %r4 - -.LretDouble: - l %r4,48+56(%r11) - std %f0,0(%r8) # Return double - lm %r6,%r15,48+24(%r11) - br %r4 - -.LretInt32: - l %r4,48+56(%r11) - st %r2,0(%r8) # Return int - lm %r6,%r15,48+24(%r11) - br %r4 - -.LretInt64: - l %r4,48+56(%r11) - stm %r2,%r3,0(%r8) # Return long long - lm %r6,%r15,48+24(%r11) - br %r4 - + .cfi_startproc + st %r6,44(%r2) # Save registers + stm %r12,%r14,48(%r2) + lr %r13,%r2 # Install frame pointer + .cfi_rel_offset r6, 44 + .cfi_rel_offset r12, 48 + .cfi_rel_offset r13, 52 + .cfi_rel_offset r14, 56 + .cfi_def_cfa_register r13 + st %r2,0(%r15) # Set up back chain + sla %r3,3 # ret_type *= 8 + lr %r12,%r4 # Save ret_addr + lr %r1,%r5 # Save fun + lr %r0,%r6 # Install static chain + + # Set return address, so that there is only one indirect jump. +#ifdef HAVE_AS_S390_ZARCH + larl %r14,.Ltable + ar %r14,%r3 +#else + basr %r14,0 +0: la %r14,.Ltable-0b(%r14,%r3) +#endif + + lm %r2,%r6,8(%r13) # Load arguments + ld %f0,64(%r13) + ld %f2,72(%r13) + br %r1 # ... and call function + + .balign 8 .Ltable: - .byte .LretNone-.Lbase # FFI390_RET_VOID - .byte .LretNone-.Lbase # FFI390_RET_STRUCT - .byte .LretFloat-.Lbase # FFI390_RET_FLOAT - .byte .LretDouble-.Lbase # FFI390_RET_DOUBLE - .byte .LretInt32-.Lbase # FFI390_RET_INT32 - .byte .LretInt64-.Lbase # FFI390_RET_INT64 +# FFI390_RET_DOUBLE + std %f0,0(%r12) + j .Ldone + + .balign 8 +# FFI390_RET_FLOAT + ste %f0,0(%r12) + j .Ldone + + .balign 8 +# FFI390_RET_INT64 + st %r3,4(%r12) + nop + # fallthru + + .balign 8 +# FFI390_RET_INT32 + st %r2,0(%r12) + nop + # fallthru + + .balign 8 +# FFI390_RET_VOID +.Ldone: + l %r14,56(%r13) + l %r12,48(%r13) + l %r6,44(%r13) + l %r13,52(%r13) + .cfi_restore 14 + .cfi_restore 13 + .cfi_restore 12 + .cfi_restore 6 + .cfi_def_cfa r15, 96 + br %r14 + .cfi_endproc + .size ffi_call_SYSV,.-ffi_call_SYSV -.LFE1: -.ffi_call_SYSV_end: - .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV + .balign 8 + .globl ffi_go_closure_SYSV + FFI_HIDDEN(ffi_go_closure_SYSV) + .type ffi_go_closure_SYSV,%function +ffi_go_closure_SYSV: + .cfi_startproc + stm %r2,%r6,8(%r15) # Save arguments + lr %r4,%r0 # Load closure -> user_data + l %r2,4(%r4) # ->cif + l %r3,8(%r4) # ->fun + j .Ldoclosure + .cfi_endproc + .balign 8 .globl ffi_closure_SYSV + FFI_HIDDEN(ffi_closure_SYSV) .type ffi_closure_SYSV,%function ffi_closure_SYSV: -.LFB2: + .cfi_startproc + stm %r2,%r6,8(%r15) # Save arguments + lr %r4,%r0 # Closure + l %r2,16(%r4) # ->cif + l %r3,20(%r4) # ->fun + l %r4,24(%r4) # ->user_data +.Ldoclosure: stm %r12,%r15,48(%r15) # Save registers -.LCFI10: + lr %r12,%r15 + .cfi_def_cfa_register r12 + .cfi_rel_offset r6, 24 + .cfi_rel_offset r12, 48 + .cfi_rel_offset r13, 52 + .cfi_rel_offset r14, 56 + .cfi_rel_offset r15, 60 +#ifndef HAVE_AS_S390_ZARCH basr %r13,0 # Set up base register .Lcbase: - stm %r2,%r6,8(%r15) # Save arguments - std %f0,64(%r15) - std %f2,72(%r15) - lr %r1,%r15 # Set up stack frame - ahi %r15,-96 -.LCFI11: - l %r12,.Lchelper-.Lcbase(%r13) # Get helper function - lr %r2,%r0 # Closure - la %r3,8(%r1) # GPRs - la %r4,64(%r1) # FPRs - la %r5,96(%r1) # Overflow - st %r1,0(%r15) # Set up back chain - - bas %r14,0(%r12,%r13) # Call helper - - l %r4,96+56(%r15) - ld %f0,96+64(%r15) # Load return registers - lm %r2,%r3,96+8(%r15) - lm %r12,%r15,96+48(%r15) - br %r4 + l %r1,.Lchelper-.Lcbase(%r13) # Get helper function +#endif + ahi %r15,-96-8 # Set up stack frame + st %r12,0(%r15) # Set up back chain + + std %f0,64(%r12) # Save fp arguments + std %f2,72(%r12) + + la %r5,96(%r12) # Overflow + st %r5,96(%r15) + la %r6,64(%r12) # FPRs + la %r5,8(%r12) # GPRs +#ifdef HAVE_AS_S390_ZARCH + brasl %r14,ffi_closure_helper_SYSV +#else + bas %r14,0(%r1,%r13) # Call helper +#endif + lr %r15,%r12 + .cfi_def_cfa_register r15 + lm %r12,%r14,48(%r12) # Restore saved registers + l %r6,24(%r15) + ld %f0,64(%r15) # Load return registers + lm %r2,%r3,8(%r15) + br %r14 + .cfi_endproc + +#ifndef HAVE_AS_S390_ZARCH .align 4 .Lchelper: .long ffi_closure_helper_SYSV-.Lcbase +#endif -.LFE2: - -.ffi_closure_SYSV_end: - .size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV - - - .section .eh_frame,EH_FRAME_FLAGS,@progbits -.Lframe1: - .4byte .LECIE1-.LSCIE1 # Length of Common Information Entry -.LSCIE1: - .4byte 0x0 # CIE Identifier Tag - .byte 0x1 # CIE Version - .ascii "zR\0" # CIE Augmentation - .uleb128 0x1 # CIE Code Alignment Factor - .sleb128 -4 # CIE Data Alignment Factor - .byte 0xe # CIE RA Column - .uleb128 0x1 # Augmentation size - .byte 0x1b # FDE Encoding (pcrel sdata4) - .byte 0xc # DW_CFA_def_cfa - .uleb128 0xf - .uleb128 0x60 - .align 4 -.LECIE1: -.LSFDE1: - .4byte .LEFDE1-.LASFDE1 # FDE Length -.LASFDE1: - .4byte .LASFDE1-.Lframe1 # FDE CIE offset - .4byte .LFB1-. # FDE initial location - .4byte .LFE1-.LFB1 # FDE address range - .uleb128 0x0 # Augmentation size - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI0-.LFB1 - .byte 0x8f # DW_CFA_offset, column 0xf - .uleb128 0x9 - .byte 0x8e # DW_CFA_offset, column 0xe - .uleb128 0xa - .byte 0x8d # DW_CFA_offset, column 0xd - .uleb128 0xb - .byte 0x8c # DW_CFA_offset, column 0xc - .uleb128 0xc - .byte 0x8b # DW_CFA_offset, column 0xb - .uleb128 0xd - .byte 0x8a # DW_CFA_offset, column 0xa - .uleb128 0xe - .byte 0x89 # DW_CFA_offset, column 0x9 - .uleb128 0xf - .byte 0x88 # DW_CFA_offset, column 0x8 - .uleb128 0x10 - .byte 0x87 # DW_CFA_offset, column 0x7 - .uleb128 0x11 - .byte 0x86 # DW_CFA_offset, column 0x6 - .uleb128 0x12 - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI1-.LCFI0 - .byte 0xd # DW_CFA_def_cfa_register - .uleb128 0xb - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI2-.LCFI1 - .byte 0xe # DW_CFA_def_cfa_offset - .uleb128 0x90 - .align 4 -.LEFDE1: -.LSFDE2: - .4byte .LEFDE2-.LASFDE2 # FDE Length -.LASFDE2: - .4byte .LASFDE2-.Lframe1 # FDE CIE offset - .4byte .LFB2-. # FDE initial location - .4byte .LFE2-.LFB2 # FDE address range - .uleb128 0x0 # Augmentation size - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI10-.LFB2 - .byte 0x8f # DW_CFA_offset, column 0xf - .uleb128 0x9 - .byte 0x8e # DW_CFA_offset, column 0xe - .uleb128 0xa - .byte 0x8d # DW_CFA_offset, column 0xd - .uleb128 0xb - .byte 0x8c # DW_CFA_offset, column 0xc - .uleb128 0xc - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI11-.LCFI10 - .byte 0xe # DW_CFA_def_cfa_offset - .uleb128 0xc0 - .align 4 -.LEFDE2: + .size ffi_closure_SYSV,.-ffi_closure_SYSV #else - -.text - - # r2: cif->bytes - # r3: &ecif - # r4: ffi_prep_args - # r5: ret_type - # r6: ecif.rvalue - # ov: fn - + + # r2: frame + # r3: ret_type + # r4: ret_addr + # r5: fun + # r6: closure + # This assumes we are using gas. + .balign 8 .globl ffi_call_SYSV + FFI_HIDDEN(ffi_call_SYSV) .type ffi_call_SYSV,%function ffi_call_SYSV: -.LFB1: - stmg %r6,%r15,48(%r15) # Save registers -.LCFI0: - larl %r13,.Lbase # Set up base register - lgr %r11,%r15 # Set up frame pointer -.LCFI1: - sgr %r15,%r2 - aghi %r15,-160-80 # Allocate stack - lgr %r8,%r6 # Save ecif.rvalue - llgc %r9,.Ltable-.Lbase(%r13,%r5) # Load epilog address - lg %r7,160(%r11) # Load function address - stg %r11,0(%r15) # Set up back chain - aghi %r11,-80 # Register save area -.LCFI2: - - la %r2,160(%r15) # Save area - # r3 already holds &ecif - basr %r14,%r4 # Call ffi_prep_args - - lmg %r2,%r6,0(%r11) # Load arguments - ld %f0,48(%r11) - ld %f2,56(%r11) - ld %f4,64(%r11) - ld %f6,72(%r11) - la %r14,0(%r13,%r9) # Set return address - br %r7 # ... and call function - -.Lbase: -.LretNone: # Return void - lg %r4,80+112(%r11) - lmg %r6,%r15,80+48(%r11) - br %r4 - -.LretFloat: - lg %r4,80+112(%r11) - ste %f0,0(%r8) # Return float - lmg %r6,%r15,80+48(%r11) - br %r4 - -.LretDouble: - lg %r4,80+112(%r11) - std %f0,0(%r8) # Return double - lmg %r6,%r15,80+48(%r11) - br %r4 - -.LretInt32: - lg %r4,80+112(%r11) - st %r2,0(%r8) # Return int - lmg %r6,%r15,80+48(%r11) - br %r4 - -.LretInt64: - lg %r4,80+112(%r11) - stg %r2,0(%r8) # Return long - lmg %r6,%r15,80+48(%r11) - br %r4 - + .cfi_startproc + stg %r6,88(%r2) # Save registers + stmg %r12,%r14,96(%r2) + lgr %r13,%r2 # Install frame pointer + .cfi_rel_offset r6, 88 + .cfi_rel_offset r12, 96 + .cfi_rel_offset r13, 104 + .cfi_rel_offset r14, 112 + .cfi_def_cfa_register r13 + stg %r2,0(%r15) # Set up back chain + larl %r14,.Ltable # Set up return address + slag %r3,%r3,3 # ret_type *= 8 + lgr %r12,%r4 # Save ret_addr + lgr %r1,%r5 # Save fun + lgr %r0,%r6 # Install static chain + agr %r14,%r3 + lmg %r2,%r6,16(%r13) # Load arguments + ld %f0,128(%r13) + ld %f2,136(%r13) + ld %f4,144(%r13) + ld %f6,152(%r13) + br %r1 # ... and call function + + .balign 8 .Ltable: - .byte .LretNone-.Lbase # FFI390_RET_VOID - .byte .LretNone-.Lbase # FFI390_RET_STRUCT - .byte .LretFloat-.Lbase # FFI390_RET_FLOAT - .byte .LretDouble-.Lbase # FFI390_RET_DOUBLE - .byte .LretInt32-.Lbase # FFI390_RET_INT32 - .byte .LretInt64-.Lbase # FFI390_RET_INT64 +# FFI390_RET_DOUBLE + std %f0,0(%r12) + j .Ldone + + .balign 8 +# FFI390_RET_DOUBLE + ste %f0,0(%r12) + j .Ldone + + .balign 8 +# FFI390_RET_INT64 + stg %r2,0(%r12) + + .balign 8 +# FFI390_RET_INT32 + # Never used, as we always store type ffi_arg. + # But the stg above is 6 bytes and we cannot + # jump around this case, so fall through. + nop + nop + + .balign 8 +# FFI390_RET_VOID +.Ldone: + lg %r14,112(%r13) + lg %r12,96(%r13) + lg %r6,88(%r13) + lg %r13,104(%r13) + .cfi_restore r14 + .cfi_restore r13 + .cfi_restore r12 + .cfi_restore r6 + .cfi_def_cfa r15, 160 + br %r14 + .cfi_endproc + .size ffi_call_SYSV,.-ffi_call_SYSV -.LFE1: -.ffi_call_SYSV_end: - .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV + + .balign 8 + .globl ffi_go_closure_SYSV + FFI_HIDDEN(ffi_go_closure_SYSV) + .type ffi_go_closure_SYSV,%function +ffi_go_closure_SYSV: + .cfi_startproc + stmg %r2,%r6,16(%r15) # Save arguments + lgr %r4,%r0 # Load closure -> user_data + lg %r2,8(%r4) # ->cif + lg %r3,16(%r4) # ->fun + j .Ldoclosure + .cfi_endproc + .size ffi_go_closure_SYSV,.-ffi_go_closure_SYSV + .balign 8 .globl ffi_closure_SYSV + FFI_HIDDEN(ffi_closure_SYSV) .type ffi_closure_SYSV,%function ffi_closure_SYSV: -.LFB2: - stmg %r14,%r15,112(%r15) # Save registers -.LCFI10: + .cfi_startproc stmg %r2,%r6,16(%r15) # Save arguments - std %f0,128(%r15) - std %f2,136(%r15) - std %f4,144(%r15) - std %f6,152(%r15) - lgr %r1,%r15 # Set up stack frame - aghi %r15,-160 -.LCFI11: - lgr %r2,%r0 # Closure - la %r3,16(%r1) # GPRs - la %r4,128(%r1) # FPRs - la %r5,160(%r1) # Overflow - stg %r1,0(%r15) # Set up back chain - + lgr %r4,%r0 # Load closure + lg %r2,32(%r4) # ->cif + lg %r3,40(%r4) # ->fun + lg %r4,48(%r4) # ->user_data +.Ldoclosure: + stmg %r13,%r15,104(%r15) # Save registers + lgr %r13,%r15 + .cfi_def_cfa_register r13 + .cfi_rel_offset r6, 48 + .cfi_rel_offset r13, 104 + .cfi_rel_offset r14, 112 + .cfi_rel_offset r15, 120 + aghi %r15,-160-16 # Set up stack frame + stg %r13,0(%r15) # Set up back chain + + std %f0,128(%r13) # Save fp arguments + std %f2,136(%r13) + std %f4,144(%r13) + std %f6,152(%r13) + la %r5,160(%r13) # Overflow + stg %r5,160(%r15) + la %r6,128(%r13) # FPRs + la %r5,16(%r13) # GPRs brasl %r14,ffi_closure_helper_SYSV # Call helper - lg %r14,160+112(%r15) - ld %f0,160+128(%r15) # Load return registers - lg %r2,160+16(%r15) - la %r15,160(%r15) + lgr %r15,%r13 + .cfi_def_cfa_register r15 + lmg %r13,%r14,104(%r13) # Restore saved registers + lg %r6,48(%r15) + ld %f0,128(%r15) # Load return registers + lg %r2,16(%r15) br %r14 -.LFE2: - -.ffi_closure_SYSV_end: - .size ffi_closure_SYSV,.ffi_closure_SYSV_end-ffi_closure_SYSV - - - - .section .eh_frame,EH_FRAME_FLAGS,@progbits -.Lframe1: - .4byte .LECIE1-.LSCIE1 # Length of Common Information Entry -.LSCIE1: - .4byte 0x0 # CIE Identifier Tag - .byte 0x1 # CIE Version - .ascii "zR\0" # CIE Augmentation - .uleb128 0x1 # CIE Code Alignment Factor - .sleb128 -8 # CIE Data Alignment Factor - .byte 0xe # CIE RA Column - .uleb128 0x1 # Augmentation size - .byte 0x1b # FDE Encoding (pcrel sdata4) - .byte 0xc # DW_CFA_def_cfa - .uleb128 0xf - .uleb128 0xa0 - .align 8 -.LECIE1: -.LSFDE1: - .4byte .LEFDE1-.LASFDE1 # FDE Length -.LASFDE1: - .4byte .LASFDE1-.Lframe1 # FDE CIE offset - .4byte .LFB1-. # FDE initial location - .4byte .LFE1-.LFB1 # FDE address range - .uleb128 0x0 # Augmentation size - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI0-.LFB1 - .byte 0x8f # DW_CFA_offset, column 0xf - .uleb128 0x5 - .byte 0x8e # DW_CFA_offset, column 0xe - .uleb128 0x6 - .byte 0x8d # DW_CFA_offset, column 0xd - .uleb128 0x7 - .byte 0x8c # DW_CFA_offset, column 0xc - .uleb128 0x8 - .byte 0x8b # DW_CFA_offset, column 0xb - .uleb128 0x9 - .byte 0x8a # DW_CFA_offset, column 0xa - .uleb128 0xa - .byte 0x89 # DW_CFA_offset, column 0x9 - .uleb128 0xb - .byte 0x88 # DW_CFA_offset, column 0x8 - .uleb128 0xc - .byte 0x87 # DW_CFA_offset, column 0x7 - .uleb128 0xd - .byte 0x86 # DW_CFA_offset, column 0x6 - .uleb128 0xe - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI1-.LCFI0 - .byte 0xd # DW_CFA_def_cfa_register - .uleb128 0xb - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI2-.LCFI1 - .byte 0xe # DW_CFA_def_cfa_offset - .uleb128 0xf0 - .align 8 -.LEFDE1: -.LSFDE2: - .4byte .LEFDE2-.LASFDE2 # FDE Length -.LASFDE2: - .4byte .LASFDE2-.Lframe1 # FDE CIE offset - .4byte .LFB2-. # FDE initial location - .4byte .LFE2-.LFB2 # FDE address range - .uleb128 0x0 # Augmentation size - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI10-.LFB2 - .byte 0x8f # DW_CFA_offset, column 0xf - .uleb128 0x5 - .byte 0x8e # DW_CFA_offset, column 0xe - .uleb128 0x6 - .byte 0x4 # DW_CFA_advance_loc4 - .4byte .LCFI11-.LCFI10 - .byte 0xe # DW_CFA_def_cfa_offset - .uleb128 0x140 - .align 8 -.LEFDE2: - -#endif + .cfi_endproc + .size ffi_closure_SYSV,.-ffi_closure_SYSV +#endif /* !s390x */ #if defined __ELF__ && defined __linux__ .section .note.GNU-stack,"",@progbits diff --git a/native/libffi/src/sparc/ffi.c b/native/libffi/src/sparc/ffi.c index 9f0fded489..9e406d0af6 100644 --- a/native/libffi/src/sparc/ffi.c +++ b/native/libffi/src/sparc/ffi.c @@ -27,655 +27,442 @@ #include #include - #include +#include "internal.h" +#ifndef SPARC64 -/* ffi_prep_args is called by the assembly routine once stack space - has been allocated for the function's arguments */ - -void ffi_prep_args_v8(char *stack, extended_cif *ecif) -{ - int i; - void **p_argv; - char *argp; - ffi_type **p_arg; - - /* Skip 16 words for the window save area */ - argp = stack + 16*sizeof(int); - - /* This should only really be done when we are returning a structure, - however, it's faster just to do it all the time... - - if ( ecif->cif->rtype->type == FFI_TYPE_STRUCT ) */ - *(int *) argp = (long)ecif->rvalue; - - /* And 1 word for the structure return value. */ - argp += sizeof(int); - -#ifdef USING_PURIFY - /* Purify will probably complain in our assembly routine, unless we - zero out this memory. */ - - ((int*)argp)[0] = 0; - ((int*)argp)[1] = 0; - ((int*)argp)[2] = 0; - ((int*)argp)[3] = 0; - ((int*)argp)[4] = 0; - ((int*)argp)[5] = 0; -#endif - - p_argv = ecif->avalue; - - for (i = ecif->cif->nargs, p_arg = ecif->cif->arg_types; i; i--, p_arg++) - { - size_t z; - - if ((*p_arg)->type == FFI_TYPE_STRUCT -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - || (*p_arg)->type == FFI_TYPE_LONGDOUBLE -#endif - ) - { - *(unsigned int *) argp = (unsigned long)(* p_argv); - z = sizeof(int); - } - else - { - z = (*p_arg)->size; - if (z < sizeof(int)) - { - z = sizeof(int); - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - *(signed int *) argp = *(SINT8 *)(* p_argv); - break; - - case FFI_TYPE_UINT8: - *(unsigned int *) argp = *(UINT8 *)(* p_argv); - break; - - case FFI_TYPE_SINT16: - *(signed int *) argp = *(SINT16 *)(* p_argv); - break; - - case FFI_TYPE_UINT16: - *(unsigned int *) argp = *(UINT16 *)(* p_argv); - break; - - default: - FFI_ASSERT(0); - } - } - else - { - memcpy(argp, *p_argv, z); - } - } - p_argv++; - argp += z; - } - - return; -} - -int ffi_prep_args_v9(char *stack, extended_cif *ecif) -{ - int i, ret = 0; - int tmp; - void **p_argv; - char *argp; - ffi_type **p_arg; - - tmp = 0; - - /* Skip 16 words for the window save area */ - argp = stack + 16*sizeof(long long); - -#ifdef USING_PURIFY - /* Purify will probably complain in our assembly routine, unless we - zero out this memory. */ - - ((long long*)argp)[0] = 0; - ((long long*)argp)[1] = 0; - ((long long*)argp)[2] = 0; - ((long long*)argp)[3] = 0; - ((long long*)argp)[4] = 0; - ((long long*)argp)[5] = 0; -#endif - - p_argv = ecif->avalue; - - if (ecif->cif->rtype->type == FFI_TYPE_STRUCT && - ecif->cif->rtype->size > 32) - { - *(unsigned long long *) argp = (unsigned long)ecif->rvalue; - argp += sizeof(long long); - tmp = 1; - } - - for (i = 0, p_arg = ecif->cif->arg_types; i < ecif->cif->nargs; - i++, p_arg++) - { - size_t z; - - z = (*p_arg)->size; - switch ((*p_arg)->type) - { - case FFI_TYPE_STRUCT: - if (z > 16) - { - /* For structures larger than 16 bytes we pass reference. */ - *(unsigned long long *) argp = (unsigned long)* p_argv; - argp += sizeof(long long); - tmp++; - p_argv++; - continue; - } - /* FALLTHROUGH */ - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: +/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE; + all further uses in this file will refer to the 128-bit type. */ #if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: +# if FFI_TYPE_LONGDOUBLE != 4 +# error FFI_TYPE_LONGDOUBLE out of date +# endif +#else +# undef FFI_TYPE_LONGDOUBLE +# define FFI_TYPE_LONGDOUBLE 4 #endif - ret = 1; /* We should promote into FP regs as well as integer. */ - break; - } - if (z < sizeof(long long)) - { - switch ((*p_arg)->type) - { - case FFI_TYPE_SINT8: - *(signed long long *) argp = *(SINT8 *)(* p_argv); - break; - - case FFI_TYPE_UINT8: - *(unsigned long long *) argp = *(UINT8 *)(* p_argv); - break; - - case FFI_TYPE_SINT16: - *(signed long long *) argp = *(SINT16 *)(* p_argv); - break; - - case FFI_TYPE_UINT16: - *(unsigned long long *) argp = *(UINT16 *)(* p_argv); - break; - - case FFI_TYPE_SINT32: - *(signed long long *) argp = *(SINT32 *)(* p_argv); - break; - - case FFI_TYPE_UINT32: - *(unsigned long long *) argp = *(UINT32 *)(* p_argv); - break; - - case FFI_TYPE_FLOAT: - *(float *) (argp + 4) = *(FLOAT32 *)(* p_argv); /* Right justify */ - break; - - case FFI_TYPE_STRUCT: - memcpy(argp, *p_argv, z); - break; - - default: - FFI_ASSERT(0); - } - z = sizeof(long long); - tmp++; - } - else if (z == sizeof(long long)) - { - memcpy(argp, *p_argv, z); - z = sizeof(long long); - tmp++; - } - else - { - if ((tmp & 1) && (*p_arg)->alignment > 8) - { - tmp++; - argp += sizeof(long long); - } - memcpy(argp, *p_argv, z); - z = 2 * sizeof(long long); - tmp += 2; - } - p_argv++; - argp += z; - } - - return ret; -} /* Perform machine dependent cif processing */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) +ffi_status FFI_HIDDEN +ffi_prep_cif_machdep(ffi_cif *cif) { - int wordsize; - - if (cif->abi != FFI_V9) - { - wordsize = 4; - - /* If we are returning a struct, this will already have been added. - Otherwise we need to add it because it's always got to be there! */ - - if (cif->rtype->type != FFI_TYPE_STRUCT) - cif->bytes += wordsize; - - /* sparc call frames require that space is allocated for 6 args, - even if they aren't used. Make that space if necessary. */ - - if (cif->bytes < 4*6+4) - cif->bytes = 4*6+4; - } - else - { - wordsize = 8; - - /* sparc call frames require that space is allocated for 6 args, - even if they aren't used. Make that space if necessary. */ - - if (cif->bytes < 8*6) - cif->bytes = 8*6; - } - - /* Adjust cif->bytes. to include 16 words for the window save area, - and maybe the struct/union return pointer area, */ - - cif->bytes += 16 * wordsize; - - /* The stack must be 2 word aligned, so round bytes up - appropriately. */ - - cif->bytes = ALIGN(cif->bytes, 2 * wordsize); + ffi_type *rtype = cif->rtype; + int rtt = rtype->type; + size_t bytes; + int i, n, flags; /* Set the return type flag */ - switch (cif->rtype->type) + switch (rtt) { case FFI_TYPE_VOID: + flags = SPARC_RET_VOID; + break; case FFI_TYPE_FLOAT: + flags = SPARC_RET_F_1; + break; case FFI_TYPE_DOUBLE: -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - case FFI_TYPE_LONGDOUBLE: -#endif - cif->flags = cif->rtype->type; + flags = SPARC_RET_F_2; break; - + case FFI_TYPE_LONGDOUBLE: case FFI_TYPE_STRUCT: - if (cif->abi == FFI_V9 && cif->rtype->size > 32) - cif->flags = FFI_TYPE_VOID; - else - cif->flags = FFI_TYPE_STRUCT; + flags = (rtype->size & 0xfff) << SPARC_SIZEMASK_SHIFT; + flags |= SPARC_RET_STRUCT; break; - case FFI_TYPE_SINT8: + flags = SPARC_RET_SINT8; + break; case FFI_TYPE_UINT8: + flags = SPARC_RET_UINT8; + break; case FFI_TYPE_SINT16: + flags = SPARC_RET_SINT16; + break; case FFI_TYPE_UINT16: - if (cif->abi == FFI_V9) - cif->flags = FFI_TYPE_INT; - else - cif->flags = cif->rtype->type; + flags = SPARC_RET_UINT16; + break; + case FFI_TYPE_INT: + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + case FFI_TYPE_POINTER: + flags = SPARC_RET_UINT32; break; - case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: - if (cif->abi == FFI_V9) - cif->flags = FFI_TYPE_INT; - else - cif->flags = FFI_TYPE_SINT64; + flags = SPARC_RET_INT64; break; - - default: - cif->flags = FFI_TYPE_INT; + case FFI_TYPE_COMPLEX: + rtt = rtype->elements[0]->type; + switch (rtt) + { + case FFI_TYPE_FLOAT: + flags = SPARC_RET_F_2; + break; + case FFI_TYPE_DOUBLE: + flags = SPARC_RET_F_4; + break; + case FFI_TYPE_LONGDOUBLE: + flags = SPARC_RET_F_8; + break; + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + flags = SPARC_RET_INT128; + break; + case FFI_TYPE_INT: + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + flags = SPARC_RET_INT64; + break; + case FFI_TYPE_SINT16: + case FFI_TYPE_UINT16: + flags = SP_V8_RET_CPLX16; + break; + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT8: + flags = SP_V8_RET_CPLX8; + break; + default: + abort(); + } break; + default: + abort(); } - return FFI_OK; -} - -int ffi_v9_layout_struct(ffi_type *arg, int off, char *ret, char *intg, char *flt) -{ - ffi_type **ptr = &arg->elements[0]; + cif->flags = flags; - while (*ptr != NULL) + bytes = 0; + for (i = 0, n = cif->nargs; i < n; ++i) { - if (off & ((*ptr)->alignment - 1)) - off = ALIGN(off, (*ptr)->alignment); + ffi_type *ty = cif->arg_types[i]; + size_t z = ty->size; + int tt = ty->type; - switch ((*ptr)->type) + switch (tt) { case FFI_TYPE_STRUCT: - off = ffi_v9_layout_struct(*ptr, off, ret, intg, flt); - off = ALIGN(off, FFI_SIZEOF_ARG); - break; - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE case FFI_TYPE_LONGDOUBLE: -#endif - memmove(ret + off, flt + off, (*ptr)->size); - off += (*ptr)->size; + by_reference: + /* Passed by reference. */ + z = 4; break; + + case FFI_TYPE_COMPLEX: + tt = ty->elements[0]->type; + if (tt == FFI_TYPE_FLOAT || z > 8) + goto by_reference; + /* FALLTHRU */ + default: - memmove(ret + off, intg + off, (*ptr)->size); - off += (*ptr)->size; - break; + z = FFI_ALIGN(z, 4); } - ptr++; + bytes += z; } - return off; -} + /* Sparc call frames require that space is allocated for 6 args, + even if they aren't used. Make that space if necessary. */ + if (bytes < 6 * 4) + bytes = 6 * 4; -#ifdef SPARC64 -extern int ffi_call_v9(void *, extended_cif *, unsigned, - unsigned, unsigned *, void (*fn)(void)); -#else -extern int ffi_call_v8(void *, extended_cif *, unsigned, - unsigned, unsigned *, void (*fn)(void)); -#endif + /* The ABI always requires space for the struct return pointer. */ + bytes += 4; -#ifndef __GNUC__ -void ffi_flush_icache (void *, size_t); -#endif + /* The stack must be 2 word aligned, so round bytes up appropriately. */ + bytes = FFI_ALIGN(bytes, 2 * 4); -void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) -{ - extended_cif ecif; - void *rval = rvalue; + /* Include the call frame to prep_args. */ + bytes += 4*16 + 4*8; + cif->bytes = bytes; - ecif.cif = cif; - ecif.avalue = avalue; + return FFI_OK; +} + +extern void ffi_call_v8(ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, size_t bytes, void *closure) FFI_HIDDEN; - /* If the return value is a struct and we don't have a return */ - /* value address then we need to make one */ +int FFI_HIDDEN +ffi_prep_args_v8(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue) +{ + ffi_type **p_arg; + int flags = cif->flags; + int i, nargs; - ecif.rvalue = rvalue; - if (cif->rtype->type == FFI_TYPE_STRUCT) + if (rvalue == NULL) { - if (cif->rtype->size <= 32) - rval = alloca(64); + if ((flags & SPARC_FLAG_RET_MASK) == SPARC_RET_STRUCT) + { + /* Since we pass the pointer to the callee, we need a value. + We allowed for this space in ffi_call, before ffi_call_v8 + alloca'd the space. */ + rvalue = (char *)argp + cif->bytes; + } else { - rval = NULL; - if (rvalue == NULL) - ecif.rvalue = alloca(cif->rtype->size); + /* Otherwise, we can ignore the return value. */ + flags = SPARC_RET_VOID; } } - switch (cif->abi) - { - case FFI_V8: -#ifdef SPARC64 - /* We don't yet support calling 32bit code from 64bit */ - FFI_ASSERT(0); -#else - if (rvalue && (cif->rtype->type == FFI_TYPE_STRUCT -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - || cif->flags == FFI_TYPE_LONGDOUBLE + /* This could only really be done when we are returning a structure. + However, the space is reserved so we can do it unconditionally. */ + *argp++ = (unsigned long)rvalue; + +#ifdef USING_PURIFY + /* Purify will probably complain in our assembly routine, + unless we zero out this memory. */ + memset(argp, 0, 6*4); #endif - )) + + p_arg = cif->arg_types; + for (i = 0, nargs = cif->nargs; i < nargs; i++) + { + ffi_type *ty = p_arg[i]; + void *a = avalue[i]; + int tt = ty->type; + size_t z; + + switch (tt) { - /* For v8, we need an "unimp" with size of returning struct */ - /* behind "call", so we alloc some executable space for it. */ - /* l7 is used, we need to make sure v8.S doesn't use %l7. */ - unsigned int *call_struct = NULL; - ffi_closure_alloc(32, (void **)&call_struct); - if (call_struct) + case FFI_TYPE_STRUCT: + case FFI_TYPE_LONGDOUBLE: + by_reference: + *argp++ = (unsigned long)a; + break; + + case FFI_TYPE_DOUBLE: + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: + memcpy(argp, a, 8); + argp += 2; + break; + + case FFI_TYPE_INT: + case FFI_TYPE_FLOAT: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT32: + case FFI_TYPE_POINTER: + *argp++ = *(unsigned *)a; + break; + + case FFI_TYPE_UINT8: + *argp++ = *(UINT8 *)a; + break; + case FFI_TYPE_SINT8: + *argp++ = *(SINT8 *)a; + break; + case FFI_TYPE_UINT16: + *argp++ = *(UINT16 *)a; + break; + case FFI_TYPE_SINT16: + *argp++ = *(SINT16 *)a; + break; + + case FFI_TYPE_COMPLEX: + tt = ty->elements[0]->type; + z = ty->size; + if (tt == FFI_TYPE_FLOAT || z > 8) + goto by_reference; + if (z < 4) { - unsigned long f = (unsigned long)fn; - call_struct[0] = 0xae10001f; /* mov %i7, %l7 */ - call_struct[1] = 0xbe10000f; /* mov %o7, %i7 */ - call_struct[2] = 0x03000000 | f >> 10; /* sethi %hi(fn), %g1 */ - call_struct[3] = 0x9fc06000 | (f & 0x3ff); /* jmp %g1+%lo(fn), %o7 */ - call_struct[4] = 0x01000000; /* nop */ - if (cif->rtype->size < 0x7f) - call_struct[5] = cif->rtype->size; /* unimp */ - else - call_struct[5] = 0x01000000; /* nop */ - call_struct[6] = 0x81c7e008; /* ret */ - call_struct[7] = 0xbe100017; /* mov %l7, %i7 */ -#ifdef __GNUC__ - asm volatile ("iflush %0; iflush %0+8; iflush %0+16; iflush %0+24" : : - "r" (call_struct) : "memory"); - /* SPARC v8 requires 5 instructions for flush to be visible */ - asm volatile ("nop; nop; nop; nop; nop"); -#else - ffi_flush_icache (call_struct, 32); -#endif - ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes, - cif->flags, rvalue, call_struct); - ffi_closure_free(call_struct); + memcpy((char *)argp + 4 - z, a, z); + argp++; } else { - ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes, - cif->flags, rvalue, fn); + memcpy(argp, a, z); + argp += z / 4; } + break; + + default: + abort(); } - else - { - ffi_call_v8(ffi_prep_args_v8, &ecif, cif->bytes, - cif->flags, rvalue, fn); - } -#endif - break; - case FFI_V9: -#ifdef SPARC64 - ffi_call_v9(ffi_prep_args_v9, &ecif, cif->bytes, - cif->flags, rval, fn); - if (rvalue && rval && cif->rtype->type == FFI_TYPE_STRUCT) - ffi_v9_layout_struct(cif->rtype, 0, (char *)rvalue, (char *)rval, ((char *)rval)+32); -#else - /* And vice versa */ - FFI_ASSERT(0); -#endif - break; - default: - FFI_ASSERT(0); - break; } + + return flags; +} + +static void +ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure) +{ + size_t bytes = cif->bytes; + + FFI_ASSERT (cif->abi == FFI_V8); + + /* If we've not got a return value, we need to create one if we've + got to pass the return value to the callee. Otherwise ignore it. */ + if (rvalue == NULL + && (cif->flags & SPARC_FLAG_RET_MASK) == SPARC_RET_STRUCT) + bytes += FFI_ALIGN (cif->rtype->size, 8); + + ffi_call_v8(cif, fn, rvalue, avalue, -bytes, closure); } +void +ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +{ + ffi_call_int (cif, fn, rvalue, avalue, NULL); +} -#ifdef SPARC64 -extern void ffi_closure_v9(void); +void +ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure) +{ + ffi_call_int (cif, fn, rvalue, avalue, closure); +} + +#ifdef __GNUC__ +static inline void +ffi_flush_icache (void *p) +{ + /* SPARC v8 requires 5 instructions for flush to be visible */ + asm volatile ("iflush %0; iflush %0+8; nop; nop; nop; nop; nop" + : : "r" (p) : "memory"); +} #else -extern void ffi_closure_v8(void); +extern void ffi_flush_icache (void *) FFI_HIDDEN; #endif +extern void ffi_closure_v8(void) FFI_HIDDEN; +extern void ffi_go_closure_v8(void) FFI_HIDDEN; + ffi_status -ffi_prep_closure_loc (ffi_closure* closure, - ffi_cif* cif, +ffi_prep_closure_loc (ffi_closure *closure, + ffi_cif *cif, void (*fun)(ffi_cif*, void*, void**, void*), void *user_data, void *codeloc) { unsigned int *tramp = (unsigned int *) &closure->tramp[0]; - unsigned long fn; -#ifdef SPARC64 - /* Trampoline address is equal to the closure address. We take advantage - of that to reduce the trampoline size by 8 bytes. */ - if (cif->abi != FFI_V9) - return FFI_BAD_ABI; - fn = (unsigned long) ffi_closure_v9; - tramp[0] = 0x83414000; /* rd %pc, %g1 */ - tramp[1] = 0xca586010; /* ldx [%g1+16], %g5 */ - tramp[2] = 0x81c14000; /* jmp %g5 */ - tramp[3] = 0x01000000; /* nop */ - *((unsigned long *) &tramp[4]) = fn; -#else - unsigned long ctx = (unsigned long) codeloc; + unsigned long ctx = (unsigned long) closure; + unsigned long fn = (unsigned long) ffi_closure_v8; + if (cif->abi != FFI_V8) return FFI_BAD_ABI; - fn = (unsigned long) ffi_closure_v8; + tramp[0] = 0x03000000 | fn >> 10; /* sethi %hi(fn), %g1 */ tramp[1] = 0x05000000 | ctx >> 10; /* sethi %hi(ctx), %g2 */ tramp[2] = 0x81c06000 | (fn & 0x3ff); /* jmp %g1+%lo(fn) */ tramp[3] = 0x8410a000 | (ctx & 0x3ff);/* or %g2, %lo(ctx) */ -#endif closure->cif = cif; closure->fun = fun; closure->user_data = user_data; - /* Flush the Icache. closure is 8 bytes aligned. */ -#ifdef __GNUC__ -#ifdef SPARC64 - asm volatile ("flush %0; flush %0+8" : : "r" (closure) : "memory"); -#else - asm volatile ("iflush %0; iflush %0+8" : : "r" (closure) : "memory"); - /* SPARC v8 requires 5 instructions for flush to be visible */ - asm volatile ("nop; nop; nop; nop; nop"); -#endif -#else - ffi_flush_icache (closure, 16); -#endif + ffi_flush_icache (closure); return FFI_OK; } -int -ffi_closure_sparc_inner_v8(ffi_closure *closure, - void *rvalue, unsigned long *gpr, unsigned long *scratch) +ffi_status +ffi_prep_go_closure (ffi_go_closure *closure, ffi_cif *cif, + void (*fun)(ffi_cif*, void*, void**, void*)) { - ffi_cif *cif; - ffi_type **arg_types; - void **avalue; - int i, argn; - - cif = closure->cif; - arg_types = cif->arg_types; - avalue = alloca(cif->nargs * sizeof(void *)); - - /* Copy the caller's structure return address so that the closure - returns the data directly to the caller. */ - if (cif->flags == FFI_TYPE_STRUCT -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - || cif->flags == FFI_TYPE_LONGDOUBLE -#endif - ) - rvalue = (void *) gpr[0]; - - /* Always skip the structure return address. */ - argn = 1; - - /* Grab the addresses of the arguments from the stack frame. */ - for (i = 0; i < cif->nargs; i++) - { - if (arg_types[i]->type == FFI_TYPE_STRUCT -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - || arg_types[i]->type == FFI_TYPE_LONGDOUBLE -#endif - ) - { - /* Straight copy of invisible reference. */ - avalue[i] = (void *)gpr[argn++]; - } - else if ((arg_types[i]->type == FFI_TYPE_DOUBLE - || arg_types[i]->type == FFI_TYPE_SINT64 - || arg_types[i]->type == FFI_TYPE_UINT64) - /* gpr is 8-byte aligned. */ - && (argn % 2) != 0) - { - /* Align on a 8-byte boundary. */ - scratch[0] = gpr[argn]; - scratch[1] = gpr[argn+1]; - avalue[i] = scratch; - scratch -= 2; - argn += 2; - } - else - { - /* Always right-justify. */ - argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; - avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size; - } - } + if (cif->abi != FFI_V8) + return FFI_BAD_ABI; - /* Invoke the closure. */ - (closure->fun) (cif, rvalue, avalue, closure->user_data); + closure->tramp = ffi_go_closure_v8; + closure->cif = cif; + closure->fun = fun; - /* Tell ffi_closure_sparc how to perform return type promotions. */ - return cif->rtype->type; + return FFI_OK; } -int -ffi_closure_sparc_inner_v9(ffi_closure *closure, - void *rvalue, unsigned long *gpr, double *fpr) +int FFI_HIDDEN +ffi_closure_sparc_inner_v8(ffi_cif *cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void *user_data, void *rvalue, + unsigned long *argp) { - ffi_cif *cif; ffi_type **arg_types; void **avalue; - int i, argn, fp_slot_max; + int i, nargs, flags; - cif = closure->cif; arg_types = cif->arg_types; - avalue = alloca(cif->nargs * sizeof(void *)); + nargs = cif->nargs; + flags = cif->flags; + avalue = alloca(nargs * sizeof(void *)); /* Copy the caller's structure return address so that the closure - returns the data directly to the caller. */ - if (cif->flags == FFI_TYPE_VOID - && cif->rtype->type == FFI_TYPE_STRUCT) + returns the data directly to the caller. Also install it so we + can return the address in %o0. */ + if ((flags & SPARC_FLAG_RET_MASK) == SPARC_RET_STRUCT) { - rvalue = (void *) gpr[0]; - /* Skip the structure return address. */ - argn = 1; + void *new_rvalue = (void *)*argp; + *(void **)rvalue = new_rvalue; + rvalue = new_rvalue; } - else - argn = 0; - fp_slot_max = 16 - argn; + /* Always skip the structure return address. */ + argp++; /* Grab the addresses of the arguments from the stack frame. */ - for (i = 0; i < cif->nargs; i++) + for (i = 0; i < nargs; i++) { - if (arg_types[i]->type == FFI_TYPE_STRUCT) + ffi_type *ty = arg_types[i]; + int tt = ty->type; + void *a = argp; + size_t z; + + switch (tt) { - if (arg_types[i]->size > 16) - { - /* Straight copy of invisible reference. */ - avalue[i] = (void *)gpr[argn++]; - } - else + case FFI_TYPE_STRUCT: + case FFI_TYPE_LONGDOUBLE: + by_reference: + /* Straight copy of invisible reference. */ + a = (void *)*argp; + break; + + case FFI_TYPE_DOUBLE: + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + if ((unsigned long)a & 7) { - /* Left-justify. */ - ffi_v9_layout_struct(arg_types[i], - 0, - (char *) &gpr[argn], - (char *) &gpr[argn], - (char *) &fpr[argn]); - avalue[i] = &gpr[argn]; - argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; + /* Align on a 8-byte boundary. */ + UINT64 *tmp = alloca(8); + *tmp = ((UINT64)argp[0] << 32) | argp[1]; + a = tmp; } - } - else - { - /* Right-justify. */ - argn += ALIGN(arg_types[i]->size, FFI_SIZEOF_ARG) / FFI_SIZEOF_ARG; + argp++; + break; - /* Align on a 16-byte boundary. */ -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - if (arg_types[i]->type == FFI_TYPE_LONGDOUBLE && (argn % 2) != 0) - argn++; -#endif - if (i < fp_slot_max - && (arg_types[i]->type == FFI_TYPE_FLOAT - || arg_types[i]->type == FFI_TYPE_DOUBLE -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - || arg_types[i]->type == FFI_TYPE_LONGDOUBLE -#endif - )) - avalue[i] = ((char *) &fpr[argn]) - arg_types[i]->size; - else - avalue[i] = ((char *) &gpr[argn]) - arg_types[i]->size; + case FFI_TYPE_INT: + case FFI_TYPE_FLOAT: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT32: + case FFI_TYPE_POINTER: + break; + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT16: + a += 2; + break; + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT8: + a += 3; + break; + + case FFI_TYPE_COMPLEX: + tt = ty->elements[0]->type; + z = ty->size; + if (tt == FFI_TYPE_FLOAT || z > 8) + goto by_reference; + if (z < 4) + a += 4 - z; + else if (z > 4) + argp++; + break; + + default: + abort(); } + argp++; + avalue[i] = a; } /* Invoke the closure. */ - (closure->fun) (cif, rvalue, avalue, closure->user_data); + fun (cif, rvalue, avalue, user_data); /* Tell ffi_closure_sparc how to perform return type promotions. */ - return cif->rtype->type; + return flags; } +#endif /* !SPARC64 */ diff --git a/native/libffi/src/sparc/ffi64.c b/native/libffi/src/sparc/ffi64.c new file mode 100644 index 0000000000..9e04061a42 --- /dev/null +++ b/native/libffi/src/sparc/ffi64.c @@ -0,0 +1,608 @@ +/* ----------------------------------------------------------------------- + ffi.c - Copyright (c) 2011, 2013 Anthony Green + Copyright (c) 1996, 2003-2004, 2007-2008 Red Hat, Inc. + + SPARC Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#include +#include +#include +#include "internal.h" + +/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE; + all further uses in this file will refer to the 128-bit type. */ +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE +# if FFI_TYPE_LONGDOUBLE != 4 +# error FFI_TYPE_LONGDOUBLE out of date +# endif +#else +# undef FFI_TYPE_LONGDOUBLE +# define FFI_TYPE_LONGDOUBLE 4 +#endif + +#ifdef SPARC64 + +/* Flatten the contents of a structure to the parts that are passed in + floating point registers. The return is a bit mask wherein bit N + set means bytes [4*n, 4*n+3] are passed in %fN. + + We encode both the (running) size (maximum 32) and mask (maxumum 255) + into one integer. The size is placed in the low byte, so that align + and addition work correctly. The mask is placed in the second byte. */ + +static int +ffi_struct_float_mask (ffi_type *outer_type, int size_mask) +{ + ffi_type **elts; + ffi_type *t; + + if (outer_type->type == FFI_TYPE_COMPLEX) + { + int m = 0, tt = outer_type->elements[0]->type; + size_t z = outer_type->size; + + if (tt == FFI_TYPE_FLOAT + || tt == FFI_TYPE_DOUBLE + || tt == FFI_TYPE_LONGDOUBLE) + m = (1 << (z / 4)) - 1; + return (m << 8) | z; + } + FFI_ASSERT (outer_type->type == FFI_TYPE_STRUCT); + + for (elts = outer_type->elements; (t = *elts) != NULL; elts++) + { + size_t z = t->size; + int o, m, tt; + + size_mask = FFI_ALIGN(size_mask, t->alignment); + switch (t->type) + { + case FFI_TYPE_STRUCT: + size_mask = ffi_struct_float_mask (t, size_mask); + continue; + case FFI_TYPE_COMPLEX: + tt = t->elements[0]->type; + if (tt != FFI_TYPE_FLOAT + && tt != FFI_TYPE_DOUBLE + && tt != FFI_TYPE_LONGDOUBLE) + break; + /* FALLTHRU */ + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + case FFI_TYPE_LONGDOUBLE: + m = (1 << (z / 4)) - 1; /* compute mask for type */ + o = (size_mask >> 2) & 0x3f; /* extract word offset */ + size_mask |= m << (o + 8); /* insert mask into place */ + break; + } + size_mask += z; + } + + size_mask = FFI_ALIGN(size_mask, outer_type->alignment); + FFI_ASSERT ((size_mask & 0xff) == outer_type->size); + + return size_mask; +} + +/* Merge floating point data into integer data. If the structure is + entirely floating point, simply return a pointer to the fp data. */ + +static void * +ffi_struct_float_merge (int size_mask, void *vi, void *vf) +{ + int size = size_mask & 0xff; + int mask = size_mask >> 8; + int n = size >> 2; + + if (mask == 0) + return vi; + else if (mask == (1 << n) - 1) + return vf; + else + { + unsigned int *wi = vi, *wf = vf; + int i; + + for (i = 0; i < n; ++i) + if ((mask >> i) & 1) + wi[i] = wf[i]; + + return vi; + } +} + +/* Similar, but place the data into VD in the end. */ + +void FFI_HIDDEN +ffi_struct_float_copy (int size_mask, void *vd, void *vi, void *vf) +{ + int size = size_mask & 0xff; + int mask = size_mask >> 8; + int n = size >> 2; + + if (mask == 0) + ; + else if (mask == (1 << n) - 1) + vi = vf; + else + { + unsigned int *wd = vd, *wi = vi, *wf = vf; + int i; + + for (i = 0; i < n; ++i) + wd[i] = ((mask >> i) & 1 ? wf : wi)[i]; + return; + } + memcpy (vd, vi, size); +} + +/* Perform machine dependent cif processing */ + +static ffi_status +ffi_prep_cif_machdep_core(ffi_cif *cif) +{ + ffi_type *rtype = cif->rtype; + int rtt = rtype->type; + size_t bytes = 0; + int i, n, flags; + + /* Set the return type flag */ + switch (rtt) + { + case FFI_TYPE_VOID: + flags = SPARC_RET_VOID; + break; + case FFI_TYPE_FLOAT: + flags = SPARC_RET_F_1; + break; + case FFI_TYPE_DOUBLE: + flags = SPARC_RET_F_2; + break; + case FFI_TYPE_LONGDOUBLE: + flags = SPARC_RET_F_4; + break; + + case FFI_TYPE_COMPLEX: + case FFI_TYPE_STRUCT: + if (rtype->size > 32) + { + flags = SPARC_RET_VOID | SPARC_FLAG_RET_IN_MEM; + bytes = 8; + } + else + { + int size_mask = ffi_struct_float_mask (rtype, 0); + int word_size = (size_mask >> 2) & 0x3f; + int all_mask = (1 << word_size) - 1; + int fp_mask = size_mask >> 8; + + flags = (size_mask << SPARC_SIZEMASK_SHIFT) | SPARC_RET_STRUCT; + + /* For special cases of all-int or all-fp, we can return + the value directly without popping through a struct copy. */ + if (fp_mask == 0) + { + if (rtype->alignment >= 8) + { + if (rtype->size == 8) + flags = SPARC_RET_INT64; + else if (rtype->size == 16) + flags = SPARC_RET_INT128; + } + } + else if (fp_mask == all_mask) + switch (word_size) + { + case 1: flags = SPARC_RET_F_1; break; + case 2: flags = SPARC_RET_F_2; break; + case 3: flags = SP_V9_RET_F_3; break; + case 4: flags = SPARC_RET_F_4; break; + /* 5 word structures skipped; handled via RET_STRUCT. */ + case 6: flags = SPARC_RET_F_6; break; + /* 7 word structures skipped; handled via RET_STRUCT. */ + case 8: flags = SPARC_RET_F_8; break; + } + } + break; + + case FFI_TYPE_SINT8: + flags = SPARC_RET_SINT8; + break; + case FFI_TYPE_UINT8: + flags = SPARC_RET_UINT8; + break; + case FFI_TYPE_SINT16: + flags = SPARC_RET_SINT16; + break; + case FFI_TYPE_UINT16: + flags = SPARC_RET_UINT16; + break; + case FFI_TYPE_INT: + case FFI_TYPE_SINT32: + flags = SP_V9_RET_SINT32; + break; + case FFI_TYPE_UINT32: + flags = SPARC_RET_UINT32; + break; + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + case FFI_TYPE_POINTER: + flags = SPARC_RET_INT64; + break; + + default: + abort(); + } + + bytes = 0; + for (i = 0, n = cif->nargs; i < n; ++i) + { + ffi_type *ty = cif->arg_types[i]; + size_t z = ty->size; + size_t a = ty->alignment; + + switch (ty->type) + { + case FFI_TYPE_COMPLEX: + case FFI_TYPE_STRUCT: + /* Large structs passed by reference. */ + if (z > 16) + { + a = z = 8; + break; + } + /* Small structs may be passed in integer or fp regs or both. */ + if (bytes >= 16*8) + break; + if ((ffi_struct_float_mask (ty, 0) & 0xff00) == 0) + break; + /* FALLTHRU */ + case FFI_TYPE_FLOAT: + case FFI_TYPE_DOUBLE: + case FFI_TYPE_LONGDOUBLE: + flags |= SPARC_FLAG_FP_ARGS; + break; + } + bytes = FFI_ALIGN(bytes, a); + bytes += FFI_ALIGN(z, 8); + } + + /* Sparc call frames require that space is allocated for 6 args, + even if they aren't used. Make that space if necessary. */ + if (bytes < 6 * 8) + bytes = 6 * 8; + + /* The stack must be 2 word aligned, so round bytes up appropriately. */ + bytes = FFI_ALIGN(bytes, 16); + + /* Include the call frame to prep_args. */ + bytes += 8*16 + 8*8; + + cif->bytes = bytes; + cif->flags = flags; + return FFI_OK; +} + +ffi_status FFI_HIDDEN +ffi_prep_cif_machdep(ffi_cif *cif) +{ + cif->nfixedargs = cif->nargs; + return ffi_prep_cif_machdep_core(cif); +} + +ffi_status FFI_HIDDEN +ffi_prep_cif_machdep_var(ffi_cif *cif, unsigned nfixedargs, unsigned ntotalargs) +{ + cif->nfixedargs = nfixedargs; + return ffi_prep_cif_machdep_core(cif); +} + +extern void ffi_call_v9(ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, size_t bytes, void *closure) FFI_HIDDEN; + +/* ffi_prep_args is called by the assembly routine once stack space + has been allocated for the function's arguments */ + +int FFI_HIDDEN +ffi_prep_args_v9(ffi_cif *cif, unsigned long *argp, void *rvalue, void **avalue) +{ + ffi_type **p_arg; + int flags = cif->flags; + int i, nargs; + + if (rvalue == NULL) + { + if (flags & SPARC_FLAG_RET_IN_MEM) + { + /* Since we pass the pointer to the callee, we need a value. + We allowed for this space in ffi_call, before ffi_call_v8 + alloca'd the space. */ + rvalue = (char *)argp + cif->bytes; + } + else + { + /* Otherwise, we can ignore the return value. */ + flags = SPARC_RET_VOID; + } + } + +#ifdef USING_PURIFY + /* Purify will probably complain in our assembly routine, + unless we zero out this memory. */ + memset(argp, 0, 6*8); +#endif + + if (flags & SPARC_FLAG_RET_IN_MEM) + *argp++ = (unsigned long)rvalue; + + p_arg = cif->arg_types; + for (i = 0, nargs = cif->nargs; i < nargs; i++) + { + ffi_type *ty = p_arg[i]; + void *a = avalue[i]; + size_t z; + + switch (ty->type) + { + case FFI_TYPE_SINT8: + *argp++ = *(SINT8 *)a; + break; + case FFI_TYPE_UINT8: + *argp++ = *(UINT8 *)a; + break; + case FFI_TYPE_SINT16: + *argp++ = *(SINT16 *)a; + break; + case FFI_TYPE_UINT16: + *argp++ = *(UINT16 *)a; + break; + case FFI_TYPE_INT: + case FFI_TYPE_SINT32: + *argp++ = *(SINT32 *)a; + break; + case FFI_TYPE_UINT32: + case FFI_TYPE_FLOAT: + *argp++ = *(UINT32 *)a; + break; + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + case FFI_TYPE_POINTER: + case FFI_TYPE_DOUBLE: + *argp++ = *(UINT64 *)a; + break; + + case FFI_TYPE_LONGDOUBLE: + case FFI_TYPE_COMPLEX: + case FFI_TYPE_STRUCT: + z = ty->size; + if (z > 16) + { + /* For structures larger than 16 bytes we pass reference. */ + *argp++ = (unsigned long)a; + break; + } + if (((unsigned long)argp & 15) && ty->alignment > 8) + argp++; + memcpy(argp, a, z); + argp += FFI_ALIGN(z, 8) / 8; + break; + + default: + abort(); + } + } + + return flags; +} + +static void +ffi_call_int(ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure) +{ + size_t bytes = cif->bytes; + + FFI_ASSERT (cif->abi == FFI_V9); + + if (rvalue == NULL && (cif->flags & SPARC_FLAG_RET_IN_MEM)) + bytes += FFI_ALIGN (cif->rtype->size, 16); + + ffi_call_v9(cif, fn, rvalue, avalue, -bytes, closure); +} + +void +ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +{ + ffi_call_int(cif, fn, rvalue, avalue, NULL); +} + +void +ffi_call_go(ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure) +{ + ffi_call_int(cif, fn, rvalue, avalue, closure); +} + +#ifdef __GNUC__ +static inline void +ffi_flush_icache (void *p) +{ + asm volatile ("flush %0; flush %0+8" : : "r" (p) : "memory"); +} +#else +extern void ffi_flush_icache (void *) FFI_HIDDEN; +#endif + +extern void ffi_closure_v9(void) FFI_HIDDEN; +extern void ffi_go_closure_v9(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) +{ + unsigned int *tramp = (unsigned int *) &closure->tramp[0]; + unsigned long fn; + + if (cif->abi != FFI_V9) + return FFI_BAD_ABI; + + /* Trampoline address is equal to the closure address. We take advantage + of that to reduce the trampoline size by 8 bytes. */ + fn = (unsigned long) ffi_closure_v9; + tramp[0] = 0x83414000; /* rd %pc, %g1 */ + tramp[1] = 0xca586010; /* ldx [%g1+16], %g5 */ + tramp[2] = 0x81c14000; /* jmp %g5 */ + tramp[3] = 0x01000000; /* nop */ + *((unsigned long *) &tramp[4]) = fn; + + closure->cif = cif; + closure->fun = fun; + closure->user_data = user_data; + + ffi_flush_icache (closure); + + return FFI_OK; +} + +ffi_status +ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif, + void (*fun)(ffi_cif*, void*, void**, void*)) +{ + if (cif->abi != FFI_V9) + return FFI_BAD_ABI; + + closure->tramp = ffi_go_closure_v9; + closure->cif = cif; + closure->fun = fun; + + return FFI_OK; +} + +int FFI_HIDDEN +ffi_closure_sparc_inner_v9(ffi_cif *cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void *user_data, void *rvalue, + unsigned long *gpr, unsigned long *fpr) +{ + ffi_type **arg_types; + void **avalue; + int i, argn, argx, nargs, flags, nfixedargs; + + arg_types = cif->arg_types; + nargs = cif->nargs; + flags = cif->flags; + nfixedargs = cif->nfixedargs; + + avalue = alloca(nargs * sizeof(void *)); + + /* Copy the caller's structure return address so that the closure + returns the data directly to the caller. */ + if (flags & SPARC_FLAG_RET_IN_MEM) + { + rvalue = (void *) gpr[0]; + /* Skip the structure return address. */ + argn = 1; + } + else + argn = 0; + + /* Grab the addresses of the arguments from the stack frame. */ + for (i = 0; i < nargs; i++, argn = argx) + { + int named = i < nfixedargs; + ffi_type *ty = arg_types[i]; + void *a = &gpr[argn]; + size_t z; + + argx = argn + 1; + switch (ty->type) + { + case FFI_TYPE_COMPLEX: + case FFI_TYPE_STRUCT: + z = ty->size; + if (z > 16) + a = *(void **)a; + else + { + argx = argn + FFI_ALIGN (z, 8) / 8; + if (named && argn < 16) + { + int size_mask = ffi_struct_float_mask (ty, 0); + int argn_mask = (0xffff00 >> argn) & 0xff00; + + /* Eliminate fp registers off the end. */ + size_mask = (size_mask & 0xff) | (size_mask & argn_mask); + a = ffi_struct_float_merge (size_mask, gpr+argn, fpr+argn); + } + } + break; + + case FFI_TYPE_LONGDOUBLE: + argn = FFI_ALIGN (argn, 2); + a = (named && argn < 16 ? fpr : gpr) + argn; + argx = argn + 2; + break; + case FFI_TYPE_DOUBLE: + if (named && argn < 16) + a = fpr + argn; + break; + case FFI_TYPE_FLOAT: + if (named && argn < 16) + a = fpr + argn; + a += 4; + break; + + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: + case FFI_TYPE_POINTER: + break; + case FFI_TYPE_INT: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT32: + a += 4; + break; + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT16: + a += 6; + break; + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT8: + a += 7; + break; + + default: + abort(); + } + avalue[i] = a; + } + + /* Invoke the closure. */ + fun (cif, rvalue, avalue, user_data); + + /* Tell ffi_closure_sparc how to perform return type promotions. */ + return flags; +} +#endif /* SPARC64 */ diff --git a/native/libffi/src/sparc/ffitarget.h b/native/libffi/src/sparc/ffitarget.h index d89f7877a8..2f4cd9a7a9 100644 --- a/native/libffi/src/sparc/ffitarget.h +++ b/native/libffi/src/sparc/ffitarget.h @@ -46,21 +46,29 @@ typedef signed long ffi_sarg; typedef enum ffi_abi { FFI_FIRST_ABI = 0, - FFI_V8, - FFI_V8PLUS, - FFI_V9, - FFI_LAST_ABI, #ifdef SPARC64 - FFI_DEFAULT_ABI = FFI_V9 + FFI_V9, + FFI_DEFAULT_ABI = FFI_V9, #else - FFI_DEFAULT_ABI = FFI_V8 + FFI_V8, + FFI_DEFAULT_ABI = FFI_V8, #endif + FFI_LAST_ABI } ffi_abi; #endif +#define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION 1 +#define FFI_TARGET_HAS_COMPLEX_TYPE 1 + +#ifdef SPARC64 +# define FFI_TARGET_SPECIFIC_VARIADIC 1 +# define FFI_EXTRA_CIF_FIELDS unsigned int nfixedargs +#endif + /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 +#define FFI_GO_CLOSURES 1 #define FFI_NATIVE_RAW_API 0 #ifdef SPARC64 diff --git a/native/libffi/src/sparc/internal.h b/native/libffi/src/sparc/internal.h new file mode 100644 index 0000000000..0a66472bad --- /dev/null +++ b/native/libffi/src/sparc/internal.h @@ -0,0 +1,26 @@ +#define SPARC_RET_VOID 0 +#define SPARC_RET_STRUCT 1 +#define SPARC_RET_UINT8 2 +#define SPARC_RET_SINT8 3 +#define SPARC_RET_UINT16 4 +#define SPARC_RET_SINT16 5 +#define SPARC_RET_UINT32 6 +#define SP_V9_RET_SINT32 7 /* v9 only */ +#define SP_V8_RET_CPLX16 7 /* v8 only */ +#define SPARC_RET_INT64 8 +#define SPARC_RET_INT128 9 + +/* Note that F_7 is missing, and is handled by SPARC_RET_STRUCT. */ +#define SPARC_RET_F_8 10 +#define SPARC_RET_F_6 11 +#define SPARC_RET_F_4 12 +#define SPARC_RET_F_2 13 +#define SP_V9_RET_F_3 14 /* v9 only */ +#define SP_V8_RET_CPLX8 14 /* v8 only */ +#define SPARC_RET_F_1 15 + +#define SPARC_FLAG_RET_MASK 15 +#define SPARC_FLAG_RET_IN_MEM 32 +#define SPARC_FLAG_FP_ARGS 64 + +#define SPARC_SIZEMASK_SHIFT 8 diff --git a/native/libffi/src/sparc/v8.S b/native/libffi/src/sparc/v8.S index 6bf7ac056e..a2e4908fd4 100644 --- a/native/libffi/src/sparc/v8.S +++ b/native/libffi/src/sparc/v8.S @@ -1,8 +1,8 @@ /* ----------------------------------------------------------------------- v8.S - Copyright (c) 2013 The Written Word, Inc. Copyright (c) 1996, 1997, 2003, 2004, 2008 Red Hat, Inc. - - SPARC Foreign Function Interface + + SPARC Foreign Function Interface Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -25,179 +25,253 @@ DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------------- */ -#define LIBFFI_ASM +#define LIBFFI_ASM #include #include +#include "internal.h" + +#ifndef SPARC64 -#define STACKFRAME 96 /* Minimum stack framesize for SPARC */ -#define ARGS (64+4) /* Offset of register area in frame */ +#define C2(X, Y) X ## Y +#define C1(X, Y) C2(X, Y) + +#ifdef __USER_LABEL_PREFIX__ +# define C(Y) C1(__USER_LABEL_PREFIX__, Y) +#else +# define C(Y) Y +#endif +#define L(Y) C1(.L, Y) -#ifndef __GNUC__ .text + +#ifndef __GNUC__ .align 8 -.globl ffi_flush_icache -.globl _ffi_flush_icache - -ffi_flush_icache: -_ffi_flush_icache: - add %o0, %o1, %o2 -#ifdef SPARC64 -1: flush %o0 -#else + .globl C(ffi_flush_icache) + .type C(ffi_flush_icache),#function + FFI_HIDDEN(C(ffi_flush_icache)) + +C(ffi_flush_icache): 1: iflush %o0 -#endif - add %o0, 8, %o0 - cmp %o0, %o2 - blt 1b + iflush %o+8 nop nop nop nop nop retl - nop -.ffi_flush_icache_end: - .size ffi_flush_icache,.ffi_flush_icache_end-ffi_flush_icache + nop + .size C(ffi_flush_icache), . - C(ffi_flush_icache) +#endif + +#if defined(__sun__) && defined(__svr4__) +# define E(INDEX) .align 16 +#else +# define E(INDEX) .align 16; .org 2b + INDEX * 16 #endif - .text .align 8 -.globl ffi_call_v8 -.globl _ffi_call_v8 - -ffi_call_v8: -_ffi_call_v8: -.LLFB1: - save %sp, -STACKFRAME, %sp -.LLCFI0: - - sub %sp, %i2, %sp ! alloca() space in stack for frame to set up - add %sp, STACKFRAME, %l0 ! %l0 has start of - ! frame to set up - - mov %l0, %o0 ! call routine to set up frame - call %i0 - mov %i1, %o1 ! (delay) - - ld [%l0+ARGS], %o0 ! call foreign function - ld [%l0+ARGS+4], %o1 - ld [%l0+ARGS+8], %o2 - ld [%l0+ARGS+12], %o3 - ld [%l0+ARGS+16], %o4 - ld [%l0+ARGS+20], %o5 - call %i5 - mov %l0, %sp ! (delay) switch to frame - nop ! STRUCT returning functions skip 12 instead of 8 bytes - - ! If the return value pointer is NULL, assume no return value. - tst %i4 - bz done + .globl C(ffi_call_v8) + .type C(ffi_call_v8),#function + FFI_HIDDEN(C(ffi_call_v8)) + +C(ffi_call_v8): +.LUW0: + ! Allocate a stack frame sized by ffi_call. + save %sp, %o4, %sp +.LUW1: + mov %i0, %o0 ! copy cif + add %sp, 64+32, %o1 ! load args area + mov %i2, %o2 ! copy rvalue + call C(ffi_prep_args_v8) + mov %i3, %o3 ! copy avalue + + add %sp, 32, %sp ! deallocate prep frame + and %o0, SPARC_FLAG_RET_MASK, %l0 ! save return type + srl %o0, SPARC_SIZEMASK_SHIFT, %l1 ! save return size + ld [%sp+64+4], %o0 ! load all argument registers + ld [%sp+64+8], %o1 + ld [%sp+64+12], %o2 + ld [%sp+64+16], %o3 + cmp %l0, SPARC_RET_STRUCT ! struct return needs an unimp 4 + ld [%sp+64+20], %o4 + be 8f + ld [%sp+64+24], %o5 + + ! Call foreign function + call %i1 + mov %i5, %g2 ! load static chain + +0: call 1f ! load pc in %o7 + sll %l0, 4, %l0 +1: add %o7, %l0, %o7 ! o7 = 0b + ret_type*16 + jmp %o7+(2f-0b) + nop + + ! Note that each entry is 4 insns, enforced by the E macro. + .align 16 +2: +E(SPARC_RET_VOID) + ret + restore +E(SPARC_RET_STRUCT) + unimp +E(SPARC_RET_UINT8) + and %o0, 0xff, %o0 + st %o0, [%i2] + ret + restore +E(SPARC_RET_SINT8) + sll %o0, 24, %o0 + b 7f + sra %o0, 24, %o0 +E(SPARC_RET_UINT16) + sll %o0, 16, %o0 + b 7f + srl %o0, 16, %o0 +E(SPARC_RET_SINT16) + sll %o0, 16, %o0 + b 7f + sra %o0, 16, %o0 +E(SPARC_RET_UINT32) +7: st %o0, [%i2] + ret + restore +E(SP_V8_RET_CPLX16) + sth %o0, [%i2+2] + b 9f + srl %o0, 16, %o0 +E(SPARC_RET_INT64) + st %o0, [%i2] + st %o1, [%i2+4] + ret + restore +E(SPARC_RET_INT128) + std %o0, [%i2] + std %o2, [%i2+8] + ret + restore +E(SPARC_RET_F_8) + st %f7, [%i2+7*4] nop - - cmp %i3, FFI_TYPE_INT - be,a done - st %o0, [%i4] ! (delay) - - cmp %i3, FFI_TYPE_FLOAT - be,a done - st %f0, [%i4+0] ! (delay) - - cmp %i3, FFI_TYPE_DOUBLE - be,a double - st %f0, [%i4+0] ! (delay) - - cmp %i3, FFI_TYPE_SINT8 - be,a sint8 - sll %o0, 24, %o0 ! (delay) - - cmp %i3, FFI_TYPE_UINT8 - be,a uint8 - sll %o0, 24, %o0 ! (delay) - - cmp %i3, FFI_TYPE_SINT16 - be,a sint16 - sll %o0, 16, %o0 ! (delay) - - cmp %i3, FFI_TYPE_UINT16 - be,a uint16 - sll %o0, 16, %o0 ! (delay) - - cmp %i3, FFI_TYPE_SINT64 - be,a longlong - st %o0, [%i4+0] ! (delay) -done: + st %f6, [%i2+6*4] + nop +E(SPARC_RET_F_6) + st %f5, [%i2+5*4] + nop + st %f4, [%i2+4*4] + nop +E(SPARC_RET_F_4) + st %f3, [%i2+3*4] + nop + st %f2, [%i2+2*4] + nop +E(SPARC_RET_F_2) + st %f1, [%i2+4] + st %f0, [%i2] ret - restore - -double: - st %f1, [%i4+4] + restore +E(SP_V8_RET_CPLX8) + stb %o0, [%i2+1] + b 0f + srl %o0, 8, %o0 +E(SPARC_RET_F_1) + st %f0, [%i2] ret - restore + restore -sint8: - sra %o0, 24, %o0 - st %o0, [%i4+0] + .align 8 +9: sth %o0, [%i2] ret - restore - -uint8: - srl %o0, 24, %o0 - st %o0, [%i4+0] + restore + .align 8 +0: stb %o0, [%i2] ret - restore + restore -sint16: - sra %o0, 16, %o0 - st %o0, [%i4+0] - ret - restore + ! Struct returning functions expect and skip the unimp here. + ! To make it worse, conforming callees examine the unimp and + ! make sure the low 12 bits of the unimp match the size of + ! the struct being returned. + .align 8 +8: call 1f ! load pc in %o7 + sll %l1, 2, %l0 ! size * 4 +1: sll %l1, 4, %l1 ! size * 16 + add %l0, %l1, %l0 ! size * 20 + add %o7, %l0, %o7 ! o7 = 8b + size*20 + jmp %o7+(2f-8b) + mov %i5, %g2 ! load static chain +2: + +/* The Sun assembler doesn't understand .rept 0x1000. */ +#define rept1 \ + call %i1; \ + nop; \ + unimp (. - 2b) / 20; \ + ret; \ + restore -uint16: - srl %o0, 16, %o0 - st %o0, [%i4+0] - ret - restore +#define rept16 \ + rept1; rept1; rept1; rept1; \ + rept1; rept1; rept1; rept1; \ + rept1; rept1; rept1; rept1; \ + rept1; rept1; rept1; rept1 -longlong: - st %o1, [%i4+4] - ret - restore -.LLFE1: +#define rept256 \ + rept16; rept16; rept16; rept16; \ + rept16; rept16; rept16; rept16; \ + rept16; rept16; rept16; rept16; \ + rept16; rept16; rept16; rept16 -.ffi_call_v8_end: - .size ffi_call_v8,.ffi_call_v8_end-ffi_call_v8 + rept256; rept256; rept256; rept256 + rept256; rept256; rept256; rept256 + rept256; rept256; rept256; rept256 + rept256; rept256; rept256; rept256 +.LUW2: + .size C(ffi_call_v8),. - C(ffi_call_v8) -#undef STACKFRAME -#define STACKFRAME 104 /* 16*4 register window + - 1*4 struct return + - 6*4 args backing store + - 3*4 locals */ + +/* 16*4 register window + 1*4 struct return + 6*4 args backing store + + 8*4 return storage + 1*4 alignment. */ +#define STACKFRAME (16*4 + 4 + 6*4 + 8*4 + 4) /* ffi_closure_v8(...) Receives the closure argument in %g2. */ - .text - .align 8 - .globl ffi_closure_v8 - -ffi_closure_v8: #ifdef HAVE_AS_REGISTER_PSEUDO_OP - .register %g2, #scratch + .register %g2, #scratch #endif -.LLFB2: - ! Reserve frame space for all arguments in case - ! we need to align them on a 8-byte boundary. - ld [%g2+FFI_TRAMPOLINE_SIZE], %g1 - ld [%g1+4], %g1 - sll %g1, 3, %g1 - add %g1, STACKFRAME, %g1 - ! %g1 == STACKFRAME + 8*nargs - neg %g1 - save %sp, %g1, %sp -.LLCFI1: + .align 8 + .globl C(ffi_go_closure_v8) + .type C(ffi_go_closure_v8),#function + FFI_HIDDEN(C(ffi_go_closure_v8)) + +C(ffi_go_closure_v8): +.LUW3: + save %sp, -STACKFRAME, %sp +.LUW4: + ld [%g2+4], %o0 ! load cif + ld [%g2+8], %o1 ! load fun + b 0f + mov %g2, %o2 ! load user_data +.LUW5: + .size C(ffi_go_closure_v8), . - C(ffi_go_closure_v8) + + .align 8 + .globl C(ffi_closure_v8) + .type C(ffi_closure_v8),#function + FFI_HIDDEN(C(ffi_closure_v8)) + +C(ffi_closure_v8): +.LUW6: + save %sp, -STACKFRAME, %sp +.LUW7: + ld [%g2+FFI_TRAMPOLINE_SIZE], %o0 ! load cif + ld [%g2+FFI_TRAMPOLINE_SIZE+4], %o1 ! load fun + ld [%g2+FFI_TRAMPOLINE_SIZE+8], %o2 ! load user_data +0: ! Store all of the potential argument registers in va_list format. st %i0, [%fp+68+0] st %i1, [%fp+68+4] @@ -207,140 +281,163 @@ ffi_closure_v8: st %i5, [%fp+68+20] ! Call ffi_closure_sparc_inner to do the bulk of the work. - mov %g2, %o0 - add %fp, -8, %o1 - add %fp, 64, %o2 + add %fp, -8*4, %o3 call ffi_closure_sparc_inner_v8 - add %fp, -16, %o3 - - ! Load up the return value in the proper type. - ! See ffi_prep_cif_machdep for the list of cases. - cmp %o0, FFI_TYPE_VOID - be done1 - - cmp %o0, FFI_TYPE_INT - be done1 - ld [%fp-8], %i0 - - cmp %o0, FFI_TYPE_FLOAT - be,a done1 - ld [%fp-8], %f0 - - cmp %o0, FFI_TYPE_DOUBLE - be,a done1 - ldd [%fp-8], %f0 - -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - cmp %o0, FFI_TYPE_LONGDOUBLE - be done2 -#endif - - cmp %o0, FFI_TYPE_STRUCT - be done2 - - cmp %o0, FFI_TYPE_SINT64 - be,a done1 - ldd [%fp-8], %i0 - - cmp %o0, FFI_TYPE_UINT64 - be,a done1 - ldd [%fp-8], %i0 - - ld [%fp-8], %i0 -done1: - jmp %i7+8 + add %fp, 64, %o4 + +0: call 1f + and %o0, SPARC_FLAG_RET_MASK, %o0 +1: sll %o0, 4, %o0 ! o0 = o0 * 16 + add %o7, %o0, %o7 ! o7 = 0b + o0*16 + jmp %o7+(2f-0b) + add %fp, -8*4, %i2 + + ! Note that each entry is 4 insns, enforced by the E macro. + .align 16 +2: +E(SPARC_RET_VOID) + ret restore -done2: - ! Skip 'unimp'. +E(SPARC_RET_STRUCT) + ld [%i2], %i0 jmp %i7+12 restore -.LLFE2: - -.ffi_closure_v8_end: - .size ffi_closure_v8,.ffi_closure_v8_end-ffi_closure_v8 +E(SPARC_RET_UINT8) + ldub [%i2+3], %i0 + ret + restore +E(SPARC_RET_SINT8) + ldsb [%i2+3], %i0 + ret + restore +E(SPARC_RET_UINT16) + lduh [%i2+2], %i0 + ret + restore +E(SPARC_RET_SINT16) + ldsh [%i2+2], %i0 + ret + restore +E(SPARC_RET_UINT32) + ld [%i2], %i0 + ret + restore +E(SP_V8_RET_CPLX16) + ld [%i2], %i0 + ret + restore +E(SPARC_RET_INT64) + ldd [%i2], %i0 + ret + restore +E(SPARC_RET_INT128) + ldd [%i2], %i0 + ldd [%i2+8], %i2 + ret + restore +E(SPARC_RET_F_8) + ld [%i2+7*4], %f7 + nop + ld [%i2+6*4], %f6 + nop +E(SPARC_RET_F_6) + ld [%i2+5*4], %f5 + nop + ld [%i2+4*4], %f4 + nop +E(SPARC_RET_F_4) + ld [%i2+3*4], %f3 + nop + ld [%i2+2*4], %f2 + nop +E(SPARC_RET_F_2) + ldd [%i2], %f0 + ret + restore +E(SP_V8_RET_CPLX8) + lduh [%i2], %i0 + ret + restore +E(SPARC_RET_F_1) + ld [%i2], %f0 + ret + restore -#ifdef SPARC64 -#define WS 8 -#define nword xword -#define uanword uaxword -#else -#define WS 4 -#define nword long -#define uanword uaword -#endif +.LUW8: + .size C(ffi_closure_v8), . - C(ffi_closure_v8) #ifdef HAVE_RO_EH_FRAME - .section ".eh_frame",#alloc + .section ".eh_frame",#alloc #else - .section ".eh_frame",#alloc,#write + .section ".eh_frame",#alloc,#write #endif -.LLframe1: - .uaword .LLECIE1-.LLSCIE1 ! Length of Common Information Entry -.LLSCIE1: - .uaword 0x0 ! CIE Identifier Tag - .byte 0x1 ! CIE Version - .ascii "zR\0" ! CIE Augmentation - .byte 0x1 ! uleb128 0x1; CIE Code Alignment Factor - .byte 0x80-WS ! sleb128 -WS; CIE Data Alignment Factor - .byte 0xf ! CIE RA Column - .byte 0x1 ! uleb128 0x1; Augmentation size -#ifdef HAVE_AS_SPARC_UA_PCREL - .byte 0x1b ! FDE Encoding (pcrel sdata4) -#else - .byte 0x50 ! FDE Encoding (aligned absolute) -#endif - .byte 0xc ! DW_CFA_def_cfa - .byte 0xe ! uleb128 0xe - .byte 0x0 ! uleb128 0x0 - .align WS -.LLECIE1: -.LLSFDE1: - .uaword .LLEFDE1-.LLASFDE1 ! FDE Length -.LLASFDE1: - .uaword .LLASFDE1-.LLframe1 ! FDE CIE offset + #ifdef HAVE_AS_SPARC_UA_PCREL - .uaword %r_disp32(.LLFB1) - .uaword .LLFE1-.LLFB1 ! FDE address range +# define FDE_ADDR(X) %r_disp32(X) #else - .align WS - .nword .LLFB1 - .uanword .LLFE1-.LLFB1 ! FDE address range +# define FDE_ADDR(X) X #endif - .byte 0x0 ! uleb128 0x0; Augmentation size - .byte 0x4 ! DW_CFA_advance_loc4 - .uaword .LLCFI0-.LLFB1 - .byte 0xd ! DW_CFA_def_cfa_register - .byte 0x1e ! uleb128 0x1e - .byte 0x2d ! DW_CFA_GNU_window_save - .byte 0x9 ! DW_CFA_register - .byte 0xf ! uleb128 0xf - .byte 0x1f ! uleb128 0x1f - .align WS -.LLEFDE1: -.LLSFDE2: - .uaword .LLEFDE2-.LLASFDE2 ! FDE Length -.LLASFDE2: - .uaword .LLASFDE2-.LLframe1 ! FDE CIE offset + + .align 4 +.LCIE: + .long .LECIE - .LSCIE ! CIE Length +.LSCIE: + .long 0 ! CIE Identifier Tag + .byte 1 ! CIE Version + .ascii "zR\0" ! CIE Augmentation + .byte 4 ! CIE Code Alignment Factor + .byte 0x7c ! CIE Data Alignment Factor + .byte 15 ! CIE RA Column + .byte 1 ! Augmentation size #ifdef HAVE_AS_SPARC_UA_PCREL - .uaword %r_disp32(.LLFB2) - .uaword .LLFE2-.LLFB2 ! FDE address range + .byte 0x1b ! FDE Encoding (pcrel sdata4) #else - .align WS - .nword .LLFB2 - .uanword .LLFE2-.LLFB2 ! FDE address range + .byte 0x50 ! FDE Encoding (aligned absolute) #endif - .byte 0x0 ! uleb128 0x0; Augmentation size - .byte 0x4 ! DW_CFA_advance_loc4 - .uaword .LLCFI1-.LLFB2 - .byte 0xd ! DW_CFA_def_cfa_register - .byte 0x1e ! uleb128 0x1e - .byte 0x2d ! DW_CFA_GNU_window_save - .byte 0x9 ! DW_CFA_register - .byte 0xf ! uleb128 0xf - .byte 0x1f ! uleb128 0x1f - .align WS -.LLEFDE2: - + .byte 0xc, 14, 0 ! DW_CFA_def_cfa, %o6, offset 0 + .align 4 +.LECIE: + + .long .LEFDE1 - .LSFDE1 ! FDE Length +.LSFDE1: + .long .LSFDE1 - .LCIE ! FDE CIE offset + .long FDE_ADDR(.LUW0) ! Initial location + .long .LUW2 - .LUW0 ! Address range + .byte 0 ! Augmentation size + .byte 0x40+1 ! DW_CFA_advance_loc 4 + .byte 0xd, 30 ! DW_CFA_def_cfa_register, %i6 + .byte 0x2d ! DW_CFA_GNU_window_save + .byte 0x9, 15, 31 ! DW_CFA_register, %o7, %i7 + .align 4 +.LEFDE1: + + .long .LEFDE2 - .LSFDE2 ! FDE Length +.LSFDE2: + .long .LSFDE2 - .LCIE ! FDE CIE offset + .long FDE_ADDR(.LUW3) ! Initial location + .long .LUW5 - .LUW3 ! Address range + .byte 0 ! Augmentation size + .byte 0x40+1 ! DW_CFA_advance_loc 4 + .byte 0xd, 30 ! DW_CFA_def_cfa_register, %i6 + .byte 0x2d ! DW_CFA_GNU_window_save + .byte 0x9, 15, 31 ! DW_CFA_register, %o7, %i7 + .align 4 +.LEFDE2: + + .long .LEFDE3 - .LSFDE3 ! FDE Length +.LSFDE3: + .long .LSFDE3 - .LCIE ! FDE CIE offset + .long FDE_ADDR(.LUW6) ! Initial location + .long .LUW8 - .LUW6 ! Address range + .byte 0 ! Augmentation size + .byte 0x40+1 ! DW_CFA_advance_loc 4 + .byte 0xd, 30 ! DW_CFA_def_cfa_register, %i6 + .byte 0x2d ! DW_CFA_GNU_window_save + .byte 0x9, 15, 31 ! DW_CFA_register, %o7, %i7 + .align 4 +.LEFDE3: + +#endif /* !SPARC64 */ #if defined __ELF__ && defined __linux__ .section .note.GNU-stack,"",@progbits #endif diff --git a/native/libffi/src/sparc/v9.S b/native/libffi/src/sparc/v9.S index bf31a2b511..55f8f4324c 100644 --- a/native/libffi/src/sparc/v9.S +++ b/native/libffi/src/sparc/v9.S @@ -27,105 +27,176 @@ #define LIBFFI_ASM #include #include +#include "internal.h" #ifdef SPARC64 -/* Only compile this in for 64bit builds, because otherwise the object file - will have inproper architecture due to used instructions. */ -#define STACKFRAME 176 /* Minimum stack framesize for SPARC 64-bit */ -#define STACK_BIAS 2047 -#define ARGS (128) /* Offset of register area in frame */ - -.text - .align 8 -.globl ffi_call_v9 -.globl _ffi_call_v9 - -ffi_call_v9: -_ffi_call_v9: -.LLFB1: - save %sp, -STACKFRAME, %sp -.LLCFI0: - - sub %sp, %i2, %sp ! alloca() space in stack for frame to set up - add %sp, STACKFRAME+STACK_BIAS, %l0 ! %l0 has start of - ! frame to set up - - mov %l0, %o0 ! call routine to set up frame - call %i0 - mov %i1, %o1 ! (delay) - brz,pt %o0, 1f - ldx [%l0+ARGS], %o0 ! call foreign function - - ldd [%l0+ARGS], %f0 - ldd [%l0+ARGS+8], %f2 - ldd [%l0+ARGS+16], %f4 - ldd [%l0+ARGS+24], %f6 - ldd [%l0+ARGS+32], %f8 - ldd [%l0+ARGS+40], %f10 - ldd [%l0+ARGS+48], %f12 - ldd [%l0+ARGS+56], %f14 - ldd [%l0+ARGS+64], %f16 - ldd [%l0+ARGS+72], %f18 - ldd [%l0+ARGS+80], %f20 - ldd [%l0+ARGS+88], %f22 - ldd [%l0+ARGS+96], %f24 - ldd [%l0+ARGS+104], %f26 - ldd [%l0+ARGS+112], %f28 - ldd [%l0+ARGS+120], %f30 - -1: ldx [%l0+ARGS+8], %o1 - ldx [%l0+ARGS+16], %o2 - ldx [%l0+ARGS+24], %o3 - ldx [%l0+ARGS+32], %o4 - ldx [%l0+ARGS+40], %o5 - call %i5 - sub %l0, STACK_BIAS, %sp ! (delay) switch to frame - - ! If the return value pointer is NULL, assume no return value. - brz,pn %i4, done - nop +#define C2(X, Y) X ## Y +#define C1(X, Y) C2(X, Y) - cmp %i3, FFI_TYPE_INT - be,a,pt %icc, done - stx %o0, [%i4+0] ! (delay) +#ifdef __USER_LABEL_PREFIX__ +# define C(Y) C1(__USER_LABEL_PREFIX__, Y) +#else +# define C(Y) Y +#endif +#define L(Y) C1(.L, Y) - cmp %i3, FFI_TYPE_FLOAT - be,a,pn %icc, done - st %f0, [%i4+0] ! (delay) +#if defined(__sun__) && defined(__svr4__) +# define E(INDEX) .align 16 +#else +# define E(INDEX) .align 16; .org 2b + INDEX * 16 +#endif - cmp %i3, FFI_TYPE_DOUBLE - be,a,pn %icc, done - std %f0, [%i4+0] ! (delay) +#define STACK_BIAS 2047 - cmp %i3, FFI_TYPE_STRUCT - be,pn %icc, dostruct + .text + .align 8 + .globl C(ffi_call_v9) + .type C(ffi_call_v9),#function + FFI_HIDDEN(C(ffi_call_v9)) + +C(ffi_call_v9): +.LUW0: + save %sp, %o4, %sp +.LUW1: + mov %i0, %o0 ! copy cif + add %sp, STACK_BIAS+128+48, %o1 ! load args area + mov %i2, %o2 ! copy rvalue + call C(ffi_prep_args_v9) + mov %i3, %o3 ! copy avalue + + andcc %o0, SPARC_FLAG_FP_ARGS, %g0 ! need fp regs? + add %sp, 48, %sp ! deallocate prep frame + be,pt %xcc, 1f + mov %o0, %l0 ! save flags + + ldd [%sp+STACK_BIAS+128], %f0 ! load all fp arg regs + ldd [%sp+STACK_BIAS+128+8], %f2 + ldd [%sp+STACK_BIAS+128+16], %f4 + ldd [%sp+STACK_BIAS+128+24], %f6 + ldd [%sp+STACK_BIAS+128+32], %f8 + ldd [%sp+STACK_BIAS+128+40], %f10 + ldd [%sp+STACK_BIAS+128+48], %f12 + ldd [%sp+STACK_BIAS+128+56], %f14 + ldd [%sp+STACK_BIAS+128+64], %f16 + ldd [%sp+STACK_BIAS+128+72], %f18 + ldd [%sp+STACK_BIAS+128+80], %f20 + ldd [%sp+STACK_BIAS+128+88], %f22 + ldd [%sp+STACK_BIAS+128+96], %f24 + ldd [%sp+STACK_BIAS+128+104], %f26 + ldd [%sp+STACK_BIAS+128+112], %f28 + ldd [%sp+STACK_BIAS+128+120], %f30 + +1: ldx [%sp+STACK_BIAS+128], %o0 ! load all int arg regs + ldx [%sp+STACK_BIAS+128+8], %o1 + ldx [%sp+STACK_BIAS+128+16], %o2 + ldx [%sp+STACK_BIAS+128+24], %o3 + ldx [%sp+STACK_BIAS+128+32], %o4 + ldx [%sp+STACK_BIAS+128+40], %o5 + call %i1 + mov %i5, %g5 ! load static chain + +0: call 1f ! load pc in %o7 + and %l0, SPARC_FLAG_RET_MASK, %l1 +1: sll %l1, 4, %l1 + add %o7, %l1, %o7 ! o7 = 0b + ret_type*16 + jmp %o7+(2f-0b) + nop - cmp %i3, FFI_TYPE_LONGDOUBLE - bne,pt %icc, done + .align 16 +2: +E(SPARC_RET_VOID) + return %i7+8 + nop +E(SPARC_RET_STRUCT) + add %sp, STACK_BIAS-64+128+48, %l2 + sub %sp, 64, %sp + b 8f + stx %o0, [%l2] +E(SPARC_RET_UINT8) + and %o0, 0xff, %i0 + return %i7+8 + stx %o0, [%o2] +E(SPARC_RET_SINT8) + sll %o0, 24, %o0 + sra %o0, 24, %i0 + return %i7+8 + stx %o0, [%o2] +E(SPARC_RET_UINT16) + sll %o0, 16, %o0 + srl %o0, 16, %i0 + return %i7+8 + stx %o0, [%o2] +E(SPARC_RET_SINT16) + sll %o0, 16, %o0 + sra %o0, 16, %i0 + return %i7+8 + stx %o0, [%o2] +E(SPARC_RET_UINT32) + srl %o0, 0, %i0 + return %i7+8 + stx %o0, [%o2] +E(SP_V9_RET_SINT32) + sra %o0, 0, %i0 + return %i7+8 + stx %o0, [%o2] +E(SPARC_RET_INT64) + stx %o0, [%i2] + return %i7+8 + nop +E(SPARC_RET_INT128) + stx %o0, [%i2] + stx %o1, [%i2+8] + return %i7+8 nop - std %f0, [%i4+0] - std %f2, [%i4+8] - -done: ret - restore - -dostruct: - /* This will not work correctly for unions. */ - stx %o0, [%i4+0] - stx %o1, [%i4+8] - stx %o2, [%i4+16] - stx %o3, [%i4+24] - std %f0, [%i4+32] - std %f2, [%i4+40] - std %f4, [%i4+48] - std %f6, [%i4+56] - ret - restore -.LLFE1: - -.ffi_call_v9_end: - .size ffi_call_v9,.ffi_call_v9_end-ffi_call_v9 +E(SPARC_RET_F_8) + st %f7, [%i2+7*4] + nop + st %f6, [%i2+6*4] + nop +E(SPARC_RET_F_6) + st %f5, [%i2+5*4] + nop + st %f4, [%i2+4*4] + nop +E(SPARC_RET_F_4) + std %f2, [%i2+2*4] + return %i7+8 + std %f0, [%o2] +E(SPARC_RET_F_2) + return %i7+8 + std %f0, [%o2] +E(SP_V9_RET_F_3) + st %f2, [%i2+2*4] + nop + st %f1, [%i2+1*4] + nop +E(SPARC_RET_F_1) + return %i7+8 + st %f0, [%o2] + + ! Finish the SPARC_RET_STRUCT sequence. + .align 8 +8: stx %o1, [%l2+8] + stx %o2, [%l2+16] + stx %o3, [%l2+24] + std %f0, [%l2+32] + std %f2, [%l2+40] + std %f4, [%l2+48] + std %f6, [%l2+56] + + ! Copy the structure into place. + srl %l0, SPARC_SIZEMASK_SHIFT, %o0 ! load size_mask + mov %i2, %o1 ! load dst + mov %l2, %o2 ! load src_gp + call C(ffi_struct_float_copy) + add %l2, 32, %o3 ! load src_fp + + return %i7+8 + nop + +.LUW2: + .size C(ffi_call_v9), . - C(ffi_call_v9) #undef STACKFRAME @@ -138,15 +209,36 @@ dostruct: Receives the closure argument in %g1. */ - .text .align 8 - .globl ffi_closure_v9 + .globl C(ffi_go_closure_v9) + .type C(ffi_go_closure_v9),#function + FFI_HIDDEN(C(ffi_go_closure_v9)) -ffi_closure_v9: -.LLFB2: +C(ffi_go_closure_v9): +.LUW3: save %sp, -STACKFRAME, %sp -.LLCFI1: +.LUW4: + ldx [%g5+8], %o0 + ldx [%g5+16], %o1 + b 0f + mov %g5, %o2 + +.LUW5: + .size C(ffi_go_closure_v9), . - C(ffi_go_closure_v9) + .align 8 + .globl C(ffi_closure_v9) + .type C(ffi_closure_v9),#function + FFI_HIDDEN(C(ffi_closure_v9)) + +C(ffi_closure_v9): +.LUW6: + save %sp, -STACKFRAME, %sp +.LUW7: + ldx [%g1+FFI_TRAMPOLINE_SIZE], %o0 + ldx [%g1+FFI_TRAMPOLINE_SIZE+8], %o1 + ldx [%g1+FFI_TRAMPOLINE_SIZE+16], %o2 +0: ! Store all of the potential argument registers in va_list format. stx %i0, [FP+128+0] stx %i1, [FP+128+8] @@ -174,134 +266,175 @@ ffi_closure_v9: std %f30, [FP-8] ! Call ffi_closure_sparc_inner to do the bulk of the work. - mov %g1, %o0 - add %fp, STACK_BIAS-160, %o1 - add %fp, STACK_BIAS+128, %o2 - call ffi_closure_sparc_inner_v9 - add %fp, STACK_BIAS-128, %o3 - - ! Load up the return value in the proper type. - ! See ffi_prep_cif_machdep for the list of cases. - cmp %o0, FFI_TYPE_VOID - be,pn %icc, done1 - - cmp %o0, FFI_TYPE_INT - be,pn %icc, integer - - cmp %o0, FFI_TYPE_FLOAT - be,a,pn %icc, done1 - ld [FP-160], %f0 - - cmp %o0, FFI_TYPE_DOUBLE - be,a,pn %icc, done1 - ldd [FP-160], %f0 - -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE - cmp %o0, FFI_TYPE_LONGDOUBLE - be,a,pn %icc, longdouble1 - ldd [FP-160], %f0 -#endif + add %fp, STACK_BIAS-160, %o3 + add %fp, STACK_BIAS+128, %o4 + call C(ffi_closure_sparc_inner_v9) + add %fp, STACK_BIAS-128, %o5 + +0: call 1f ! load pc in %o7 + and %o0, SPARC_FLAG_RET_MASK, %o0 +1: sll %o0, 4, %o0 ! o2 = i2 * 16 + add %o7, %o0, %o7 ! o7 = 0b + i2*16 + jmp %o7+(2f-0b) + nop - ! FFI_TYPE_STRUCT - ldx [FP-152], %i1 - ldx [FP-144], %i2 - ldx [FP-136], %i3 + ! Note that we cannot load the data in the delay slot of + ! the return insn because the data is in the stack frame + ! that is deallocated by the return. + .align 16 +2: +E(SPARC_RET_VOID) + return %i7+8 + nop +E(SPARC_RET_STRUCT) + ldx [FP-160], %i0 ldd [FP-160], %f0 - ldd [FP-152], %f2 - ldd [FP-144], %f4 - ldd [FP-136], %f6 - -integer: + b 8f + ldx [FP-152], %i1 +E(SPARC_RET_UINT8) + ldub [FP-160+7], %i0 + return %i7+8 + nop +E(SPARC_RET_SINT8) + ldsb [FP-160+7], %i0 + return %i7+8 + nop +E(SPARC_RET_UINT16) + lduh [FP-160+6], %i0 + return %i7+8 + nop +E(SPARC_RET_SINT16) + ldsh [FP-160+6], %i0 + return %i7+8 + nop +E(SPARC_RET_UINT32) + lduw [FP-160+4], %i0 + return %i7+8 + nop +E(SP_V9_RET_SINT32) + ldsw [FP-160+4], %i0 + return %i7+8 + nop +E(SPARC_RET_INT64) ldx [FP-160], %i0 + return %i7+8 + nop +E(SPARC_RET_INT128) + ldx [FP-160], %i0 + ldx [FP-160+8], %i1 + return %i7+8 + nop +E(SPARC_RET_F_8) + ld [FP-160+7*4], %f7 + nop + ld [FP-160+6*4], %f6 + nop +E(SPARC_RET_F_6) + ld [FP-160+5*4], %f5 + nop + ld [FP-160+4*4], %f4 + nop +E(SPARC_RET_F_4) + ldd [FP-160], %f0 + ldd [FP-160+8], %f2 + return %i7+8 + nop +E(SPARC_RET_F_2) + ldd [FP-160], %f0 + return %i7+8 + nop +E(SP_V9_RET_F_3) + ld [FP-160+2*4], %f2 + nop + ld [FP-160+1*4], %f1 + nop +E(SPARC_RET_F_1) + ld [FP-160], %f0 + return %i7+8 + nop -done1: - ret - restore - -#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE -longdouble1: - ldd [FP-152], %f2 - ret - restore -#endif -.LLFE2: + ! Finish the SPARC_RET_STRUCT sequence. + .align 8 +8: ldd [FP-152], %f2 + ldx [FP-144], %i2 + ldd [FP-144], %f4 + ldx [FP-136], %i3 + ldd [FP-136], %f6 + return %i7+8 + nop -.ffi_closure_v9_end: - .size ffi_closure_v9,.ffi_closure_v9_end-ffi_closure_v9 +.LUW8: + .size C(ffi_closure_v9), . - C(ffi_closure_v9) #ifdef HAVE_RO_EH_FRAME - .section ".eh_frame",#alloc -#else - .section ".eh_frame",#alloc,#write -#endif -.LLframe1: - .uaword .LLECIE1-.LLSCIE1 ! Length of Common Information Entry -.LLSCIE1: - .uaword 0x0 ! CIE Identifier Tag - .byte 0x1 ! CIE Version - .ascii "zR\0" ! CIE Augmentation - .byte 0x1 ! uleb128 0x1; CIE Code Alignment Factor - .byte 0x78 ! sleb128 -8; CIE Data Alignment Factor - .byte 0xf ! CIE RA Column - .byte 0x1 ! uleb128 0x1; Augmentation size -#ifdef HAVE_AS_SPARC_UA_PCREL - .byte 0x1b ! FDE Encoding (pcrel sdata4) + .section ".eh_frame",#alloc #else - .byte 0x50 ! FDE Encoding (aligned absolute) + .section ".eh_frame",#alloc,#write #endif - .byte 0xc ! DW_CFA_def_cfa - .byte 0xe ! uleb128 0xe - .byte 0xff,0xf ! uleb128 0x7ff - .align 8 -.LLECIE1: -.LLSFDE1: - .uaword .LLEFDE1-.LLASFDE1 ! FDE Length -.LLASFDE1: - .uaword .LLASFDE1-.LLframe1 ! FDE CIE offset + #ifdef HAVE_AS_SPARC_UA_PCREL - .uaword %r_disp32(.LLFB1) - .uaword .LLFE1-.LLFB1 ! FDE address range +# define FDE_RANGE(B, E) .long %r_disp32(B), E - B #else - .align 8 - .xword .LLFB1 - .uaxword .LLFE1-.LLFB1 ! FDE address range +# define FDE_RANGE(B, E) .align 8; .xword B, E - B #endif - .byte 0x0 ! uleb128 0x0; Augmentation size - .byte 0x4 ! DW_CFA_advance_loc4 - .uaword .LLCFI0-.LLFB1 - .byte 0xd ! DW_CFA_def_cfa_register - .byte 0x1e ! uleb128 0x1e - .byte 0x2d ! DW_CFA_GNU_window_save - .byte 0x9 ! DW_CFA_register - .byte 0xf ! uleb128 0xf - .byte 0x1f ! uleb128 0x1f + .align 8 -.LLEFDE1: -.LLSFDE2: - .uaword .LLEFDE2-.LLASFDE2 ! FDE Length -.LLASFDE2: - .uaword .LLASFDE2-.LLframe1 ! FDE CIE offset +.LCIE: + .long .LECIE - .LSCIE ! CIE Length +.LSCIE: + .long 0 ! CIE Identifier Tag + .byte 1 ! CIE Version + .ascii "zR\0" ! CIE Augmentation + .byte 4 ! CIE Code Alignment Factor + .byte 0x78 ! CIE Data Alignment Factor + .byte 15 ! CIE RA Column + .byte 1 ! Augmentation size #ifdef HAVE_AS_SPARC_UA_PCREL - .uaword %r_disp32(.LLFB2) - .uaword .LLFE2-.LLFB2 ! FDE address range + .byte 0x1b ! FDE Encoding (pcrel sdata4) #else - .align 8 - .xword .LLFB2 - .uaxword .LLFE2-.LLFB2 ! FDE address range -#endif - .byte 0x0 ! uleb128 0x0; Augmentation size - .byte 0x4 ! DW_CFA_advance_loc4 - .uaword .LLCFI1-.LLFB2 - .byte 0xd ! DW_CFA_def_cfa_register - .byte 0x1e ! uleb128 0x1e - .byte 0x2d ! DW_CFA_GNU_window_save - .byte 0x9 ! DW_CFA_register - .byte 0xf ! uleb128 0xf - .byte 0x1f ! uleb128 0x1f - .align 8 -.LLEFDE2: + .byte 0x50 ! FDE Encoding (aligned absolute) #endif - + .byte 0xc, 14, 0xff, 0xf ! DW_CFA_def_cfa, %o6, offset 0x7ff + .align 8 +.LECIE: + + .long .LEFDE1 - .LSFDE1 ! FDE Length +.LSFDE1: + .long .LSFDE1 - .LCIE ! FDE CIE offset + FDE_RANGE(.LUW0, .LUW2) + .byte 0 ! Augmentation size + .byte 0x40+1 ! DW_CFA_advance_loc 4 + .byte 0xd, 30 ! DW_CFA_def_cfa_register, %i6 + .byte 0x2d ! DW_CFA_GNU_window_save + .byte 0x9, 15, 31 ! DW_CFA_register, %o7, %i7 + .align 8 +.LEFDE1: + + .long .LEFDE2 - .LSFDE2 ! FDE Length +.LSFDE2: + .long .LSFDE2 - .LCIE ! FDE CIE offset + FDE_RANGE(.LUW3, .LUW5) + .byte 0 ! Augmentation size + .byte 0x40+1 ! DW_CFA_advance_loc 4 + .byte 0xd, 30 ! DW_CFA_def_cfa_register, %i6 + .byte 0x2d ! DW_CFA_GNU_window_save + .byte 0x9, 15, 31 ! DW_CFA_register, %o7, %i7 + .align 8 +.LEFDE2: + + .long .LEFDE3 - .LSFDE3 ! FDE Length +.LSFDE3: + .long .LSFDE3 - .LCIE ! FDE CIE offset + FDE_RANGE(.LUW6, .LUW8) + .byte 0 ! Augmentation size + .byte 0x40+1 ! DW_CFA_advance_loc 4 + .byte 0xd, 30 ! DW_CFA_def_cfa_register, %i6 + .byte 0x2d ! DW_CFA_GNU_window_save + .byte 0x9, 15, 31 ! DW_CFA_register, %o7, %i7 + .align 8 +.LEFDE3: + +#endif /* SPARC64 */ #ifdef __linux__ .section .note.GNU-stack,"",@progbits #endif diff --git a/native/libffi/src/types.c b/native/libffi/src/types.c index 7e80aec6eb..eb18c78696 100644 --- a/native/libffi/src/types.c +++ b/native/libffi/src/types.c @@ -38,6 +38,10 @@ struct struct_align_##name { \ char c; \ type x; \ }; \ +<<<<<<< HEAD +======= +FFI_EXTERN \ +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 maybe_const ffi_type ffi_type_##name = { \ sizeof(type), \ offsetof(struct struct_align_##name, x), \ @@ -52,6 +56,10 @@ struct struct_align_complex_##name { \ char c; \ _Complex type x; \ }; \ +<<<<<<< HEAD +======= +FFI_EXTERN \ +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 maybe_const ffi_type ffi_type_complex_##name = { \ sizeof(_Complex type), \ offsetof(struct struct_align_complex_##name, x), \ @@ -60,7 +68,7 @@ maybe_const ffi_type ffi_type_complex_##name = { \ } /* Size and alignment are fake here. They must not be 0. */ -const ffi_type ffi_type_void = { +FFI_EXTERN const ffi_type ffi_type_void = { 1, 1, FFI_TYPE_VOID, NULL }; diff --git a/native/libffi/src/vax/ffi.c b/native/libffi/src/vax/ffi.c index f4d6bbb4f4..c1544fdf53 100644 --- a/native/libffi/src/vax/ffi.c +++ b/native/libffi/src/vax/ffi.c @@ -108,7 +108,11 @@ ffi_prep_args (extended_cif *ecif, void *stack) /* Align if necessary. */ if ((sizeof(int) - 1) & z) +<<<<<<< HEAD z = ALIGN(z, sizeof(int)); +======= + z = FFI_ALIGN(z, sizeof(int)); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 } p_argv++; @@ -215,7 +219,11 @@ ffi_prep_closure_elfbsd (ffi_cif *cif, void **avalue, char *stackp) /* Align if necessary */ if ((sizeof (int) - 1) & z) +<<<<<<< HEAD z = ALIGN(z, sizeof (int)); +======= + z = FFI_ALIGN(z, sizeof (int)); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 p_argv++; stackp += z; diff --git a/native/libffi/src/x86/asmnames.h b/native/libffi/src/x86/asmnames.h new file mode 100644 index 0000000000..7551021e17 --- /dev/null +++ b/native/libffi/src/x86/asmnames.h @@ -0,0 +1,30 @@ +#ifndef ASMNAMES_H +#define ASMNAMES_H + +#define C2(X, Y) X ## Y +#define C1(X, Y) C2(X, Y) +#ifdef __USER_LABEL_PREFIX__ +# define C(X) C1(__USER_LABEL_PREFIX__, X) +#else +# define C(X) X +#endif + +#ifdef __APPLE__ +# define L(X) C1(L, X) +#else +# define L(X) C1(.L, X) +#endif + +#if defined(__ELF__) && defined(__PIC__) +# define PLT(X) X@PLT +#else +# define PLT(X) X +#endif + +#ifdef __ELF__ +# define ENDF(X) .type X,@function; .size X, . - X +#else +# define ENDF(X) +#endif + +#endif /* ASMNAMES_H */ diff --git a/native/libffi/src/x86/darwin.S b/native/libffi/src/x86/darwin.S deleted file mode 100644 index 8f0f0707aa..0000000000 --- a/native/libffi/src/x86/darwin.S +++ /dev/null @@ -1,444 +0,0 @@ -/* ----------------------------------------------------------------------- - darwin.S - Copyright (c) 1996, 1998, 2001, 2002, 2003, 2005 Red Hat, Inc. - Copyright (C) 2008 Free Software Foundation, Inc. - - X86 Foreign Function Interface - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- - */ - -#ifndef __x86_64__ - -#define LIBFFI_ASM -#include -#include - -.text - -.globl _ffi_prep_args - - .align 4 -.globl _ffi_call_SYSV - -_ffi_call_SYSV: -.LFB1: - pushl %ebp -.LCFI0: - movl %esp,%ebp -.LCFI1: - subl $8,%esp - /* Make room for all of the new args. */ - movl 16(%ebp),%ecx - subl %ecx,%esp - - movl %esp,%eax - - /* Place all of the ffi_prep_args in position */ - subl $8,%esp - pushl 12(%ebp) - pushl %eax - call *8(%ebp) - - /* Return stack to previous state and call the function */ - addl $16,%esp - - call *28(%ebp) - - /* Load %ecx with the return type code */ - movl 20(%ebp),%ecx - - /* Protect %esi. We're going to pop it in the epilogue. */ - pushl %esi - - /* If the return value pointer is NULL, assume no return value. */ - cmpl $0,24(%ebp) - jne 0f - - /* Even if there is no space for the return value, we are - obliged to handle floating-point values. */ - cmpl $FFI_TYPE_FLOAT,%ecx - jne noretval - fstp %st(0) - - jmp epilogue -0: - .align 4 - call 1f -.Lstore_table: - .long noretval-.Lstore_table /* FFI_TYPE_VOID */ - .long retint-.Lstore_table /* FFI_TYPE_INT */ - .long retfloat-.Lstore_table /* FFI_TYPE_FLOAT */ - .long retdouble-.Lstore_table /* FFI_TYPE_DOUBLE */ - .long retlongdouble-.Lstore_table /* FFI_TYPE_LONGDOUBLE */ - .long retuint8-.Lstore_table /* FFI_TYPE_UINT8 */ - .long retsint8-.Lstore_table /* FFI_TYPE_SINT8 */ - .long retuint16-.Lstore_table /* FFI_TYPE_UINT16 */ - .long retsint16-.Lstore_table /* FFI_TYPE_SINT16 */ - .long retint-.Lstore_table /* FFI_TYPE_UINT32 */ - .long retint-.Lstore_table /* FFI_TYPE_SINT32 */ - .long retint64-.Lstore_table /* FFI_TYPE_UINT64 */ - .long retint64-.Lstore_table /* FFI_TYPE_SINT64 */ - .long retstruct-.Lstore_table /* FFI_TYPE_STRUCT */ - .long retint-.Lstore_table /* FFI_TYPE_POINTER */ - .long retstruct1b-.Lstore_table /* FFI_TYPE_SMALL_STRUCT_1B */ - .long retstruct2b-.Lstore_table /* FFI_TYPE_SMALL_STRUCT_2B */ -1: - pop %esi - add (%esi, %ecx, 4), %esi - jmp *%esi - - /* Sign/zero extend as appropriate. */ -retsint8: - movsbl %al, %eax - jmp retint - -retsint16: - movswl %ax, %eax - jmp retint - -retuint8: - movzbl %al, %eax - jmp retint - -retuint16: - movzwl %ax, %eax - jmp retint - -retfloat: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - fstps (%ecx) - jmp epilogue - -retdouble: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - fstpl (%ecx) - jmp epilogue - -retlongdouble: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - fstpt (%ecx) - jmp epilogue - -retint64: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - movl %eax,0(%ecx) - movl %edx,4(%ecx) - jmp epilogue - -retstruct1b: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - movb %al,0(%ecx) - jmp epilogue - -retstruct2b: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - movw %ax,0(%ecx) - jmp epilogue - -retint: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - movl %eax,0(%ecx) - -retstruct: - /* Nothing to do! */ - -noretval: -epilogue: - popl %esi - movl %ebp,%esp - popl %ebp - ret - -.LFE1: -.ffi_call_SYSV_end: - - .align 4 -FFI_HIDDEN (ffi_closure_SYSV) -.globl _ffi_closure_SYSV - -_ffi_closure_SYSV: -.LFB2: - pushl %ebp -.LCFI2: - movl %esp, %ebp -.LCFI3: - subl $40, %esp - leal -24(%ebp), %edx - movl %edx, -12(%ebp) /* resp */ - leal 8(%ebp), %edx - movl %edx, 4(%esp) /* args = __builtin_dwarf_cfa () */ - leal -12(%ebp), %edx - movl %edx, (%esp) /* &resp */ - movl %ebx, 8(%esp) -.LCFI7: - call L_ffi_closure_SYSV_inner$stub - movl 8(%esp), %ebx - movl -12(%ebp), %ecx - cmpl $FFI_TYPE_INT, %eax - je .Lcls_retint - - /* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16, - FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32. */ - cmpl $FFI_TYPE_UINT64, %eax - jge 0f - cmpl $FFI_TYPE_UINT8, %eax - jge .Lcls_retint - -0: cmpl $FFI_TYPE_FLOAT, %eax - je .Lcls_retfloat - cmpl $FFI_TYPE_DOUBLE, %eax - je .Lcls_retdouble - cmpl $FFI_TYPE_LONGDOUBLE, %eax - je .Lcls_retldouble - cmpl $FFI_TYPE_SINT64, %eax - je .Lcls_retllong - cmpl $FFI_TYPE_SMALL_STRUCT_1B, %eax - je .Lcls_retstruct1b - cmpl $FFI_TYPE_SMALL_STRUCT_2B, %eax - je .Lcls_retstruct2b - cmpl $FFI_TYPE_STRUCT, %eax - je .Lcls_retstruct -.Lcls_epilogue: - movl %ebp, %esp - popl %ebp - ret -.Lcls_retint: - movl (%ecx), %eax - jmp .Lcls_epilogue -.Lcls_retfloat: - flds (%ecx) - jmp .Lcls_epilogue -.Lcls_retdouble: - fldl (%ecx) - jmp .Lcls_epilogue -.Lcls_retldouble: - fldt (%ecx) - jmp .Lcls_epilogue -.Lcls_retllong: - movl (%ecx), %eax - movl 4(%ecx), %edx - jmp .Lcls_epilogue -.Lcls_retstruct1b: - movsbl (%ecx), %eax - jmp .Lcls_epilogue -.Lcls_retstruct2b: - movswl (%ecx), %eax - jmp .Lcls_epilogue -.Lcls_retstruct: - lea -8(%ebp),%esp - movl %ebp, %esp - popl %ebp - ret $4 -.LFE2: - -#if !FFI_NO_RAW_API - -#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3) -#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4) -#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4) -#define CIF_FLAGS_OFFSET 20 - - .align 4 -FFI_HIDDEN (ffi_closure_raw_SYSV) -.globl _ffi_closure_raw_SYSV - -_ffi_closure_raw_SYSV: -.LFB3: - pushl %ebp -.LCFI4: - movl %esp, %ebp -.LCFI5: - pushl %esi -.LCFI6: - subl $36, %esp - movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */ - movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */ - movl %edx, 12(%esp) /* user_data */ - leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */ - movl %edx, 8(%esp) /* raw_args */ - leal -24(%ebp), %edx - movl %edx, 4(%esp) /* &res */ - movl %esi, (%esp) /* cif */ - call *RAW_CLOSURE_FUN_OFFSET(%eax) /* closure->fun */ - movl CIF_FLAGS_OFFSET(%esi), %eax /* rtype */ - cmpl $FFI_TYPE_INT, %eax - je .Lrcls_retint - - /* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16, - FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32. */ - cmpl $FFI_TYPE_UINT64, %eax - jge 0f - cmpl $FFI_TYPE_UINT8, %eax - jge .Lrcls_retint -0: - cmpl $FFI_TYPE_FLOAT, %eax - je .Lrcls_retfloat - cmpl $FFI_TYPE_DOUBLE, %eax - je .Lrcls_retdouble - cmpl $FFI_TYPE_LONGDOUBLE, %eax - je .Lrcls_retldouble - cmpl $FFI_TYPE_SINT64, %eax - je .Lrcls_retllong -.Lrcls_epilogue: - addl $36, %esp - popl %esi - popl %ebp - ret -.Lrcls_retint: - movl -24(%ebp), %eax - jmp .Lrcls_epilogue -.Lrcls_retfloat: - flds -24(%ebp) - jmp .Lrcls_epilogue -.Lrcls_retdouble: - fldl -24(%ebp) - jmp .Lrcls_epilogue -.Lrcls_retldouble: - fldt -24(%ebp) - jmp .Lrcls_epilogue -.Lrcls_retllong: - movl -24(%ebp), %eax - movl -20(%ebp), %edx - jmp .Lrcls_epilogue -.LFE3: -#endif - -.section __IMPORT,__jump_table,symbol_stubs,self_modifying_code+pure_instructions,5 -L_ffi_closure_SYSV_inner$stub: - .indirect_symbol _ffi_closure_SYSV_inner - hlt ; hlt ; hlt ; hlt ; hlt - - -.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support -EH_frame1: - .set L$set$0,LECIE1-LSCIE1 - .long L$set$0 -LSCIE1: - .long 0x0 - .byte 0x1 - .ascii "zR\0" - .byte 0x1 - .byte 0x7c - .byte 0x8 - .byte 0x1 - .byte 0x10 - .byte 0xc - .byte 0x5 - .byte 0x4 - .byte 0x88 - .byte 0x1 - .align 2 -LECIE1: -.globl _ffi_call_SYSV.eh -_ffi_call_SYSV.eh: -LSFDE1: - .set L$set$1,LEFDE1-LASFDE1 - .long L$set$1 -LASFDE1: - .long LASFDE1-EH_frame1 - .long .LFB1-. - .set L$set$2,.LFE1-.LFB1 - .long L$set$2 - .byte 0x0 - .byte 0x4 - .set L$set$3,.LCFI0-.LFB1 - .long L$set$3 - .byte 0xe - .byte 0x8 - .byte 0x84 - .byte 0x2 - .byte 0x4 - .set L$set$4,.LCFI1-.LCFI0 - .long L$set$4 - .byte 0xd - .byte 0x4 - .align 2 -LEFDE1: -.globl _ffi_closure_SYSV.eh -_ffi_closure_SYSV.eh: -LSFDE2: - .set L$set$5,LEFDE2-LASFDE2 - .long L$set$5 -LASFDE2: - .long LASFDE2-EH_frame1 - .long .LFB2-. - .set L$set$6,.LFE2-.LFB2 - .long L$set$6 - .byte 0x0 - .byte 0x4 - .set L$set$7,.LCFI2-.LFB2 - .long L$set$7 - .byte 0xe - .byte 0x8 - .byte 0x84 - .byte 0x2 - .byte 0x4 - .set L$set$8,.LCFI3-.LCFI2 - .long L$set$8 - .byte 0xd - .byte 0x4 - .align 2 -LEFDE2: - -#if !FFI_NO_RAW_API - -.globl _ffi_closure_raw_SYSV.eh -_ffi_closure_raw_SYSV.eh: -LSFDE3: - .set L$set$10,LEFDE3-LASFDE3 - .long L$set$10 -LASFDE3: - .long LASFDE3-EH_frame1 - .long .LFB3-. - .set L$set$11,.LFE3-.LFB3 - .long L$set$11 - .byte 0x0 - .byte 0x4 - .set L$set$12,.LCFI4-.LFB3 - .long L$set$12 - .byte 0xe - .byte 0x8 - .byte 0x84 - .byte 0x2 - .byte 0x4 - .set L$set$13,.LCFI5-.LCFI4 - .long L$set$13 - .byte 0xd - .byte 0x4 - .byte 0x4 - .set L$set$14,.LCFI6-.LCFI5 - .long L$set$14 - .byte 0x85 - .byte 0x3 - .align 2 -LEFDE3: - -#endif - -#endif /* ifndef __x86_64__ */ diff --git a/native/libffi/src/x86/darwin64.S b/native/libffi/src/x86/darwin64.S deleted file mode 100644 index 2f7394ef4b..0000000000 --- a/native/libffi/src/x86/darwin64.S +++ /dev/null @@ -1,416 +0,0 @@ -/* ----------------------------------------------------------------------- - darwin64.S - Copyright (c) 2006 Free Software Foundation, Inc. - Copyright (c) 2008 Red Hat, Inc. - derived from unix64.S - - x86-64 Foreign Function Interface for Darwin. - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - ``Software''), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR - OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - OTHER DEALINGS IN THE SOFTWARE. - ----------------------------------------------------------------------- */ - -#ifdef __x86_64__ -#define LIBFFI_ASM -#include -#include - - .file "darwin64.S" -.text - -/* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags, - void *raddr, void (*fnaddr)(void)); - - Bit o trickiness here -- ARGS+BYTES is the base of the stack frame - for this function. This has been allocated by ffi_call. We also - deallocate some of the stack that has been alloca'd. */ - - .align 3 - .globl _ffi_call_unix64 - -_ffi_call_unix64: -LUW0: - movq (%rsp), %r10 /* Load return address. */ - leaq (%rdi, %rsi), %rax /* Find local stack base. */ - movq %rdx, (%rax) /* Save flags. */ - movq %rcx, 8(%rax) /* Save raddr. */ - movq %rbp, 16(%rax) /* Save old frame pointer. */ - movq %r10, 24(%rax) /* Relocate return address. */ - movq %rax, %rbp /* Finalize local stack frame. */ -LUW1: - movq %rdi, %r10 /* Save a copy of the register area. */ - movq %r8, %r11 /* Save a copy of the target fn. */ - movl %r9d, %eax /* Set number of SSE registers. */ - - /* Load up all argument registers. */ - movq (%r10), %rdi - movq 8(%r10), %rsi - movq 16(%r10), %rdx - movq 24(%r10), %rcx - movq 32(%r10), %r8 - movq 40(%r10), %r9 - testl %eax, %eax - jnz Lload_sse -Lret_from_load_sse: - - /* Deallocate the reg arg area. */ - leaq 176(%r10), %rsp - - /* Call the user function. */ - call *%r11 - - /* Deallocate stack arg area; local stack frame in redzone. */ - leaq 24(%rbp), %rsp - - movq 0(%rbp), %rcx /* Reload flags. */ - movq 8(%rbp), %rdi /* Reload raddr. */ - movq 16(%rbp), %rbp /* Reload old frame pointer. */ -LUW2: - - /* The first byte of the flags contains the FFI_TYPE. */ - movzbl %cl, %r10d - leaq Lstore_table(%rip), %r11 - movslq (%r11, %r10, 4), %r10 - addq %r11, %r10 - jmp *%r10 - -Lstore_table: - .long Lst_void-Lstore_table /* FFI_TYPE_VOID */ - .long Lst_sint32-Lstore_table /* FFI_TYPE_INT */ - .long Lst_float-Lstore_table /* FFI_TYPE_FLOAT */ - .long Lst_double-Lstore_table /* FFI_TYPE_DOUBLE */ - .long Lst_ldouble-Lstore_table /* FFI_TYPE_LONGDOUBLE */ - .long Lst_uint8-Lstore_table /* FFI_TYPE_UINT8 */ - .long Lst_sint8-Lstore_table /* FFI_TYPE_SINT8 */ - .long Lst_uint16-Lstore_table /* FFI_TYPE_UINT16 */ - .long Lst_sint16-Lstore_table /* FFI_TYPE_SINT16 */ - .long Lst_uint32-Lstore_table /* FFI_TYPE_UINT32 */ - .long Lst_sint32-Lstore_table /* FFI_TYPE_SINT32 */ - .long Lst_int64-Lstore_table /* FFI_TYPE_UINT64 */ - .long Lst_int64-Lstore_table /* FFI_TYPE_SINT64 */ - .long Lst_struct-Lstore_table /* FFI_TYPE_STRUCT */ - .long Lst_int64-Lstore_table /* FFI_TYPE_POINTER */ - - .text - .align 3 -Lst_void: - ret - .align 3 -Lst_uint8: - movzbq %al, %rax - movq %rax, (%rdi) - ret - .align 3 -Lst_sint8: - movsbq %al, %rax - movq %rax, (%rdi) - ret - .align 3 -Lst_uint16: - movzwq %ax, %rax - movq %rax, (%rdi) - .align 3 -Lst_sint16: - movswq %ax, %rax - movq %rax, (%rdi) - ret - .align 3 -Lst_uint32: - movl %eax, %eax - movq %rax, (%rdi) - .align 3 -Lst_sint32: - cltq - movq %rax, (%rdi) - ret - .align 3 -Lst_int64: - movq %rax, (%rdi) - ret - .align 3 -Lst_float: - movss %xmm0, (%rdi) - ret - .align 3 -Lst_double: - movsd %xmm0, (%rdi) - ret -Lst_ldouble: - fstpt (%rdi) - ret - .align 3 -Lst_struct: - leaq -20(%rsp), %rsi /* Scratch area in redzone. */ - - /* We have to locate the values now, and since we don't want to - write too much data into the user's return value, we spill the - value to a 16 byte scratch area first. Bits 8, 9, and 10 - control where the values are located. Only one of the three - bits will be set; see ffi_prep_cif_machdep for the pattern. */ - movd %xmm0, %r10 - movd %xmm1, %r11 - testl $0x100, %ecx - cmovnz %rax, %rdx - cmovnz %r10, %rax - testl $0x200, %ecx - cmovnz %r10, %rdx - testl $0x400, %ecx - cmovnz %r10, %rax - cmovnz %r11, %rdx - movq %rax, (%rsi) - movq %rdx, 8(%rsi) - - /* Bits 12-31 contain the true size of the structure. Copy from - the scratch area to the true destination. */ - shrl $12, %ecx - rep movsb - ret - - /* Many times we can avoid loading any SSE registers at all. - It's not worth an indirect jump to load the exact set of - SSE registers needed; zero or all is a good compromise. */ - .align 3 -LUW3: -Lload_sse: - movdqa 48(%r10), %xmm0 - movdqa 64(%r10), %xmm1 - movdqa 80(%r10), %xmm2 - movdqa 96(%r10), %xmm3 - movdqa 112(%r10), %xmm4 - movdqa 128(%r10), %xmm5 - movdqa 144(%r10), %xmm6 - movdqa 160(%r10), %xmm7 - jmp Lret_from_load_sse - -LUW4: - .align 3 - .globl _ffi_closure_unix64 - -_ffi_closure_unix64: -LUW5: - /* The carry flag is set by the trampoline iff SSE registers - are used. Don't clobber it before the branch instruction. */ - leaq -200(%rsp), %rsp -LUW6: - movq %rdi, (%rsp) - movq %rsi, 8(%rsp) - movq %rdx, 16(%rsp) - movq %rcx, 24(%rsp) - movq %r8, 32(%rsp) - movq %r9, 40(%rsp) - jc Lsave_sse -Lret_from_save_sse: - - movq %r10, %rdi - leaq 176(%rsp), %rsi - movq %rsp, %rdx - leaq 208(%rsp), %rcx - call _ffi_closure_unix64_inner - - /* Deallocate stack frame early; return value is now in redzone. */ - addq $200, %rsp -LUW7: - - /* The first byte of the return value contains the FFI_TYPE. */ - movzbl %al, %r10d - leaq Lload_table(%rip), %r11 - movslq (%r11, %r10, 4), %r10 - addq %r11, %r10 - jmp *%r10 - -Lload_table: - .long Lld_void-Lload_table /* FFI_TYPE_VOID */ - .long Lld_int32-Lload_table /* FFI_TYPE_INT */ - .long Lld_float-Lload_table /* FFI_TYPE_FLOAT */ - .long Lld_double-Lload_table /* FFI_TYPE_DOUBLE */ - .long Lld_ldouble-Lload_table /* FFI_TYPE_LONGDOUBLE */ - .long Lld_int8-Lload_table /* FFI_TYPE_UINT8 */ - .long Lld_int8-Lload_table /* FFI_TYPE_SINT8 */ - .long Lld_int16-Lload_table /* FFI_TYPE_UINT16 */ - .long Lld_int16-Lload_table /* FFI_TYPE_SINT16 */ - .long Lld_int32-Lload_table /* FFI_TYPE_UINT32 */ - .long Lld_int32-Lload_table /* FFI_TYPE_SINT32 */ - .long Lld_int64-Lload_table /* FFI_TYPE_UINT64 */ - .long Lld_int64-Lload_table /* FFI_TYPE_SINT64 */ - .long Lld_struct-Lload_table /* FFI_TYPE_STRUCT */ - .long Lld_int64-Lload_table /* FFI_TYPE_POINTER */ - - .text - .align 3 -Lld_void: - ret - .align 3 -Lld_int8: - movzbl -24(%rsp), %eax - ret - .align 3 -Lld_int16: - movzwl -24(%rsp), %eax - ret - .align 3 -Lld_int32: - movl -24(%rsp), %eax - ret - .align 3 -Lld_int64: - movq -24(%rsp), %rax - ret - .align 3 -Lld_float: - movss -24(%rsp), %xmm0 - ret - .align 3 -Lld_double: - movsd -24(%rsp), %xmm0 - ret - .align 3 -Lld_ldouble: - fldt -24(%rsp) - ret - .align 3 -Lld_struct: - /* There are four possibilities here, %rax/%rdx, %xmm0/%rax, - %rax/%xmm0, %xmm0/%xmm1. We collapse two by always loading - both rdx and xmm1 with the second word. For the remaining, - bit 8 set means xmm0 gets the second word, and bit 9 means - that rax gets the second word. */ - movq -24(%rsp), %rcx - movq -16(%rsp), %rdx - movq -16(%rsp), %xmm1 - testl $0x100, %eax - cmovnz %rdx, %rcx - movd %rcx, %xmm0 - testl $0x200, %eax - movq -24(%rsp), %rax - cmovnz %rdx, %rax - ret - - /* See the comment above Lload_sse; the same logic applies here. */ - .align 3 -LUW8: -Lsave_sse: - movdqa %xmm0, 48(%rsp) - movdqa %xmm1, 64(%rsp) - movdqa %xmm2, 80(%rsp) - movdqa %xmm3, 96(%rsp) - movdqa %xmm4, 112(%rsp) - movdqa %xmm5, 128(%rsp) - movdqa %xmm6, 144(%rsp) - movdqa %xmm7, 160(%rsp) - jmp Lret_from_save_sse - -LUW9: -.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support -EH_frame1: - .set L$set$0,LECIE1-LSCIE1 /* CIE Length */ - .long L$set$0 -LSCIE1: - .long 0x0 /* CIE Identifier Tag */ - .byte 0x1 /* CIE Version */ - .ascii "zR\0" /* CIE Augmentation */ - .byte 0x1 /* uleb128 0x1; CIE Code Alignment Factor */ - .byte 0x78 /* sleb128 -8; CIE Data Alignment Factor */ - .byte 0x10 /* CIE RA Column */ - .byte 0x1 /* uleb128 0x1; Augmentation size */ - .byte 0x10 /* FDE Encoding (pcrel sdata4) */ - .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ - .byte 0x7 /* uleb128 0x7 */ - .byte 0x8 /* uleb128 0x8 */ - .byte 0x90 /* DW_CFA_offset, column 0x10 */ - .byte 0x1 - .align 3 -LECIE1: - .globl _ffi_call_unix64.eh -_ffi_call_unix64.eh: -LSFDE1: - .set L$set$1,LEFDE1-LASFDE1 /* FDE Length */ - .long L$set$1 -LASFDE1: - .long LASFDE1-EH_frame1 /* FDE CIE offset */ - .quad LUW0-. /* FDE initial location */ - .set L$set$2,LUW4-LUW0 /* FDE address range */ - .quad L$set$2 - .byte 0x0 /* Augmentation size */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .set L$set$3,LUW1-LUW0 - .long L$set$3 - - /* New stack frame based off rbp. This is a itty bit of unwind - trickery in that the CFA *has* changed. There is no easy way - to describe it correctly on entry to the function. Fortunately, - it doesn't matter too much since at all points we can correctly - unwind back to ffi_call. Note that the location to which we - moved the return address is (the new) CFA-8, so from the - perspective of the unwind info, it hasn't moved. */ - .byte 0xc /* DW_CFA_def_cfa, %rbp offset 32 */ - .byte 0x6 - .byte 0x20 - .byte 0x80+6 /* DW_CFA_offset, %rbp offset 2*-8 */ - .byte 0x2 - .byte 0xa /* DW_CFA_remember_state */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .set L$set$4,LUW2-LUW1 - .long L$set$4 - .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ - .byte 0x7 - .byte 0x8 - .byte 0xc0+6 /* DW_CFA_restore, %rbp */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .set L$set$5,LUW3-LUW2 - .long L$set$5 - .byte 0xb /* DW_CFA_restore_state */ - - .align 3 -LEFDE1: - .globl _ffi_closure_unix64.eh -_ffi_closure_unix64.eh: -LSFDE3: - .set L$set$6,LEFDE3-LASFDE3 /* FDE Length */ - .long L$set$6 -LASFDE3: - .long LASFDE3-EH_frame1 /* FDE CIE offset */ - .quad LUW5-. /* FDE initial location */ - .set L$set$7,LUW9-LUW5 /* FDE address range */ - .quad L$set$7 - .byte 0x0 /* Augmentation size */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .set L$set$8,LUW6-LUW5 - .long L$set$8 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 208,1 /* uleb128 208 */ - .byte 0xa /* DW_CFA_remember_state */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .set L$set$9,LUW7-LUW6 - .long L$set$9 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x8 - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .set L$set$10,LUW8-LUW7 - .long L$set$10 - .byte 0xb /* DW_CFA_restore_state */ - - .align 3 -LEFDE3: - .subsections_via_symbols - -#endif /* __x86_64__ */ diff --git a/native/libffi/src/x86/ffi.c b/native/libffi/src/x86/ffi.c index 34f80b3bf0..383c74d91d 100644 --- a/native/libffi/src/x86/ffi.c +++ b/native/libffi/src/x86/ffi.c @@ -1,5 +1,6 @@ /* ----------------------------------------------------------------------- - ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008 Red Hat, Inc. + ffi.c - Copyright (c) 2017 Anthony Green + Copyright (c) 1996, 1998, 1999, 2001, 2007, 2008 Red Hat, Inc. Copyright (c) 2002 Ranjit Mathew Copyright (c) 2002 Bo Thorsen Copyright (c) 2002 Roger Sayle @@ -27,6 +28,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------------- */ +<<<<<<< HEAD #include #if !defined(__x86_64__) || defined(_WIN64) || defined(__CYGWIN__) @@ -34,10 +36,15 @@ #include #endif +======= + +#if defined(__i386__) || defined(_M_IX86) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #include #include - +#include #include +<<<<<<< HEAD /* ffi_prep_args is called by the assembly routine once stack space @@ -195,11 +202,33 @@ unsigned int ffi_prep_args(char *stack, extended_cif *ecif) #ifdef X86_WIN64 argp += (z + sizeof(void*) - 1) & ~(sizeof(void*) - 1); +======= +#include "internal.h" + +/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE; + all further uses in this file will refer to the 80-bit type. */ +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE +# if FFI_TYPE_LONGDOUBLE != 4 +# error FFI_TYPE_LONGDOUBLE out of date +# endif #else - argp += z; +# undef FFI_TYPE_LONGDOUBLE +# define FFI_TYPE_LONGDOUBLE 4 +#endif + +#if defined(__GNUC__) && !defined(__declspec) +# define __declspec(x) __attribute__((x)) +#endif + +#if defined(_MSC_VER) && defined(_M_IX86) +/* Stack is not 16-byte aligned on Windows. */ +#define STACK_ALIGN(bytes) (bytes) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 +#else +#define STACK_ALIGN(bytes) FFI_ALIGN (bytes, 16) #endif - } +<<<<<<< HEAD #ifndef X86_WIN64 /* We need to move the register-passed arguments for thiscall/fastcall/register on top of stack, so that those can be moved to registers by call-handler. */ @@ -231,101 +260,146 @@ unsigned int ffi_prep_args(char *stack, extended_cif *ecif) #endif return 0; } - -/* Perform machine dependent cif processing */ -ffi_status ffi_prep_cif_machdep(ffi_cif *cif) +======= +/* Perform machine dependent cif processing. */ +ffi_status FFI_HIDDEN +ffi_prep_cif_machdep(ffi_cif *cif) { - unsigned int i; - ffi_type **ptr; + size_t bytes = 0; + int i, n, flags, cabi = cif->abi; + + switch (cabi) + { + case FFI_SYSV: + case FFI_STDCALL: + case FFI_THISCALL: + case FFI_FASTCALL: + case FFI_MS_CDECL: + case FFI_PASCAL: + case FFI_REGISTER: + break; + default: + return FFI_BAD_ABI; + } +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 - /* Set the return type flag */ switch (cif->rtype->type) { case FFI_TYPE_VOID: + flags = X86_RET_VOID; + break; + case FFI_TYPE_FLOAT: + flags = X86_RET_FLOAT; + break; + case FFI_TYPE_DOUBLE: + flags = X86_RET_DOUBLE; + break; + case FFI_TYPE_LONGDOUBLE: + flags = X86_RET_LDOUBLE; + break; case FFI_TYPE_UINT8: + flags = X86_RET_UINT8; + break; case FFI_TYPE_UINT16: + flags = X86_RET_UINT16; + break; case FFI_TYPE_SINT8: + flags = X86_RET_SINT8; + break; case FFI_TYPE_SINT16: -#ifdef X86_WIN64 - case FFI_TYPE_UINT32: + flags = X86_RET_SINT16; + break; + case FFI_TYPE_INT: case FFI_TYPE_SINT32: -#endif - case FFI_TYPE_SINT64: - case FFI_TYPE_FLOAT: - case FFI_TYPE_DOUBLE: -#ifndef X86_WIN64 -#if FFI_TYPE_DOUBLE != FFI_TYPE_LONGDOUBLE - case FFI_TYPE_LONGDOUBLE: -#endif -#endif - cif->flags = (unsigned) cif->rtype->type; + case FFI_TYPE_UINT32: + case FFI_TYPE_POINTER: + flags = X86_RET_INT32; break; - + case FFI_TYPE_SINT64: case FFI_TYPE_UINT64: -#ifdef X86_WIN64 - case FFI_TYPE_POINTER: -#endif - cif->flags = FFI_TYPE_SINT64; + flags = X86_RET_INT64; break; - case FFI_TYPE_STRUCT: #ifndef X86 + /* ??? This should be a different ABI rather than an ifdef. */ if (cif->rtype->size == 1) - { - cif->flags = FFI_TYPE_SMALL_STRUCT_1B; /* same as char size */ - } + flags = X86_RET_STRUCT_1B; else if (cif->rtype->size == 2) - { - cif->flags = FFI_TYPE_SMALL_STRUCT_2B; /* same as short size */ - } + flags = X86_RET_STRUCT_2B; else if (cif->rtype->size == 4) - { -#ifdef X86_WIN64 - cif->flags = FFI_TYPE_SMALL_STRUCT_4B; -#else - cif->flags = FFI_TYPE_INT; /* same as int type */ -#endif - } + flags = X86_RET_INT32; else if (cif->rtype->size == 8) - { - cif->flags = FFI_TYPE_SINT64; /* same as int64 type */ - } + flags = X86_RET_INT64; else #endif - { -#ifdef X86_WIN32 - if (cif->abi == FFI_MS_CDECL) - cif->flags = FFI_TYPE_MS_STRUCT; - else -#endif - cif->flags = FFI_TYPE_STRUCT; - /* allocate space for return value pointer */ - cif->bytes += ALIGN(sizeof(void*), FFI_SIZEOF_ARG); - } - break; - - default: -#ifdef X86_WIN64 - cif->flags = FFI_TYPE_SINT64; + { + do_struct: + switch (cabi) + { + case FFI_THISCALL: + case FFI_FASTCALL: + case FFI_STDCALL: + case FFI_MS_CDECL: + flags = X86_RET_STRUCTARG; + break; + default: + flags = X86_RET_STRUCTPOP; + break; + } + /* Allocate space for return value pointer. */ + bytes += FFI_ALIGN (sizeof(void*), FFI_SIZEOF_ARG); + } break; - case FFI_TYPE_INT: - cif->flags = FFI_TYPE_SINT32; -#else - cif->flags = FFI_TYPE_INT; -#endif + case FFI_TYPE_COMPLEX: + switch (cif->rtype->elements[0]->type) + { + case FFI_TYPE_DOUBLE: + case FFI_TYPE_LONGDOUBLE: + case FFI_TYPE_SINT64: + case FFI_TYPE_UINT64: + goto do_struct; + case FFI_TYPE_FLOAT: + case FFI_TYPE_INT: + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + flags = X86_RET_INT64; + break; + case FFI_TYPE_SINT16: + case FFI_TYPE_UINT16: + flags = X86_RET_INT32; + break; + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT8: + flags = X86_RET_STRUCT_2B; + break; + default: + return FFI_BAD_TYPEDEF; + } break; + default: + return FFI_BAD_TYPEDEF; } + cif->flags = flags; - for (ptr = cif->arg_types, i = cif->nargs; i > 0; i--, ptr++) + for (i = 0, n = cif->nargs; i < n; i++) { +<<<<<<< HEAD #ifndef X86_WIN64 if (cif->abi != FFI_STDCALL && cif->abi != FFI_FASTCALL && cif->abi != FFI_THISCALL) #endif if (((*ptr)->alignment - 1) & cif->bytes) cif->bytes = ALIGN(cif->bytes, (*ptr)->alignment); cif->bytes += (unsigned)ALIGN((*ptr)->size, FFI_SIZEOF_ARG); +======= + ffi_type *t = cif->arg_types[i]; + + bytes = FFI_ALIGN (bytes, t->alignment); + bytes += FFI_ALIGN (t->size, FFI_SIZEOF_ARG); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 } + cif->bytes = bytes; +<<<<<<< HEAD #ifdef X86_WIN64 /* ensure space for storing four registers */ cif->bytes += 4 * FFI_SIZEOF_ARG; @@ -337,10 +411,37 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) #endif cif->bytes = (cif->bytes + 15) & ~0xF; #endif - +======= return FFI_OK; } +static ffi_arg +extend_basic_type(void *arg, int type) +{ + switch (type) + { + case FFI_TYPE_SINT8: + return *(SINT8 *)arg; + case FFI_TYPE_UINT8: + return *(UINT8 *)arg; + case FFI_TYPE_SINT16: + return *(SINT16 *)arg; + case FFI_TYPE_UINT16: + return *(UINT16 *)arg; + + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT32: + case FFI_TYPE_POINTER: + case FFI_TYPE_FLOAT: + return *(UINT32 *)arg; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 + + default: + abort(); + } +} + +<<<<<<< HEAD #ifdef X86_WIN64 extern int ffi_call_win64(unsigned int (*)(char *, extended_cif *), extended_cif *, @@ -351,10 +452,54 @@ ffi_call_win32(unsigned int (*)(char *, extended_cif *), extended_cif *, unsigned, unsigned, unsigned, unsigned *, void (*fn)(void)); extern void ffi_call_SYSV(void (*)(char *, extended_cif *), extended_cif *, unsigned, unsigned, unsigned *, void (*fn)(void)); +======= +struct call_frame +{ + void *ebp; /* 0 */ + void *retaddr; /* 4 */ + void (*fn)(void); /* 8 */ + int flags; /* 12 */ + void *rvalue; /* 16 */ + unsigned regs[3]; /* 20-28 */ +}; + +struct abi_params +{ + int dir; /* parameter growth direction */ + int static_chain; /* the static chain register used by gcc */ + int nregs; /* number of register parameters */ + int regs[3]; +}; + +static const struct abi_params abi_params[FFI_LAST_ABI] = { + [FFI_SYSV] = { 1, R_ECX, 0 }, + [FFI_THISCALL] = { 1, R_EAX, 1, { R_ECX } }, + [FFI_FASTCALL] = { 1, R_EAX, 2, { R_ECX, R_EDX } }, + [FFI_STDCALL] = { 1, R_ECX, 0 }, + [FFI_PASCAL] = { -1, R_ECX, 0 }, + /* ??? No defined static chain; gcc does not support REGISTER. */ + [FFI_REGISTER] = { -1, R_ECX, 3, { R_EAX, R_EDX, R_ECX } }, + [FFI_MS_CDECL] = { 1, R_ECX, 0 } +}; + +#ifdef HAVE_FASTCALL + #ifdef _MSC_VER + #define FFI_DECLARE_FASTCALL __fastcall + #else + #define FFI_DECLARE_FASTCALL __declspec(fastcall) + #endif +#else + #define FFI_DECLARE_FASTCALL +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #endif -void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +extern void FFI_DECLARE_FASTCALL ffi_call_i386(struct call_frame *, char *) FFI_HIDDEN; + +static void +ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure) { +<<<<<<< HEAD extended_cif ecif; ecif.cif = cif; @@ -370,23 +515,57 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) && cif->rtype->size != 2 && cif->rtype->size != 4 && cif->rtype->size != 8))) +======= + size_t rsize, bytes; + struct call_frame *frame; + char *stack, *argp; + ffi_type **arg_types; + int flags, cabi, i, n, dir, narg_reg; + const struct abi_params *pabi; + + flags = cif->flags; + cabi = cif->abi; + pabi = &abi_params[cabi]; + dir = pabi->dir; + + rsize = 0; + if (rvalue == NULL) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 { - ecif.rvalue = alloca((cif->rtype->size + 0xF) & ~0xF); + switch (flags) + { + case X86_RET_FLOAT: + case X86_RET_DOUBLE: + case X86_RET_LDOUBLE: + case X86_RET_STRUCTPOP: + case X86_RET_STRUCTARG: + /* The float cases need to pop the 387 stack. + The struct cases need to pass a valid pointer to the callee. */ + rsize = cif->rtype->size; + break; + default: + /* We can pretend that the callee returns nothing. */ + flags = X86_RET_VOID; + break; + } } -#else - if (rvalue == NULL - && (cif->flags == FFI_TYPE_STRUCT - || cif->flags == FFI_TYPE_MS_STRUCT)) - { - ecif.rvalue = alloca(cif->rtype->size); - } -#endif - else - ecif.rvalue = rvalue; - - - switch (cif->abi) + + bytes = STACK_ALIGN (cif->bytes); + stack = alloca(bytes + sizeof(*frame) + rsize); + argp = (dir < 0 ? stack + bytes : stack); + frame = (struct call_frame *)(stack + bytes); + if (rsize) + rvalue = frame + 1; + + frame->fn = fn; + frame->flags = flags; + frame->rvalue = rvalue; + frame->regs[pabi->static_chain] = (unsigned)closure; + + narg_reg = 0; + switch (flags) { +<<<<<<< HEAD #ifdef X86_WIN64 case FFI_WIN64: ffi_call_win64(ffi_prep_args, &ecif, cif->bytes, @@ -413,11 +592,32 @@ void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) #endif default: FFI_ASSERT(0); +======= + case X86_RET_STRUCTARG: + /* The pointer is passed as the first argument. */ + if (pabi->nregs > 0) + { + frame->regs[pabi->regs[0]] = (unsigned)rvalue; + narg_reg = 1; + break; + } + /* fallthru */ + case X86_RET_STRUCTPOP: + *(void **)argp = rvalue; + argp += sizeof(void *); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 break; } -} + arg_types = cif->arg_types; + for (i = 0, n = cif->nargs; i < n; i++) + { + ffi_type *ty = arg_types[i]; + void *valp = avalue[i]; + size_t z = ty->size; + int t = ty->type; +<<<<<<< HEAD /** private members **/ /* The following __attribute__((regparm(1))) decorations will have no effect @@ -474,12 +674,73 @@ ffi_closure_win64_inner (ffi_closure *closure, void *args) { TODO: structure sizes of 3 5 6 7 are returned by reference, too!!! */ return cif->rtype->size > sizeof(void *) ? resp : *(void **)resp; +======= + if (z <= FFI_SIZEOF_ARG && t != FFI_TYPE_STRUCT) + { + ffi_arg val = extend_basic_type (valp, t); + + if (t != FFI_TYPE_FLOAT && narg_reg < pabi->nregs) + frame->regs[pabi->regs[narg_reg++]] = val; + else if (dir < 0) + { + argp -= 4; + *(ffi_arg *)argp = val; + } + else + { + *(ffi_arg *)argp = val; + argp += 4; + } + } + else + { + size_t za = FFI_ALIGN (z, FFI_SIZEOF_ARG); + size_t align = FFI_SIZEOF_ARG; + + /* Issue 434: For thiscall and fastcall, if the paramter passed + as 64-bit integer or struct, all following integer parameters + will be passed on stack. */ + if ((cabi == FFI_THISCALL || cabi == FFI_FASTCALL) + && (t == FFI_TYPE_SINT64 + || t == FFI_TYPE_UINT64 + || t == FFI_TYPE_STRUCT)) + narg_reg = 2; + + /* Alignment rules for arguments are quite complex. Vectors and + structures with 16 byte alignment get it. Note that long double + on Darwin does have 16 byte alignment, and does not get this + alignment if passed directly; a structure with a long double + inside, however, would get 16 byte alignment. Since libffi does + not support vectors, we need non concern ourselves with other + cases. */ + if (t == FFI_TYPE_STRUCT && ty->alignment >= 16) + align = 16; + + if (dir < 0) + { + /* ??? These reverse argument ABIs are probably too old + to have cared about alignment. Someone should check. */ + argp -= za; + memcpy (argp, valp, z); + } + else + { + argp = (char *)FFI_ALIGN (argp, align); + memcpy (argp, valp, z); + argp += za; + } + } + } + FFI_ASSERT (dir > 0 || argp == stack); + + ffi_call_i386 (frame, stack); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 } -#else -unsigned int FFI_HIDDEN __attribute__ ((regparm(1))) -ffi_closure_SYSV_inner (ffi_closure *closure, void **respp, void *args) +void +ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) { +<<<<<<< HEAD /* our various things... */ ffi_cif *cif; void **arg_area; @@ -728,6 +989,141 @@ ffi_prep_incoming_args(char *stack, void **rvalue, void **avalue, } /* the cif must already be prep'ed */ +======= + ffi_call_int (cif, fn, rvalue, avalue, NULL); +} + +#ifdef FFI_GO_CLOSURES +void +ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure) +{ + ffi_call_int (cif, fn, rvalue, avalue, closure); +} +#endif + +/** private members **/ + +void FFI_HIDDEN ffi_closure_i386(void); +void FFI_HIDDEN ffi_closure_STDCALL(void); +void FFI_HIDDEN ffi_closure_REGISTER(void); + +struct closure_frame +{ + unsigned rettemp[4]; /* 0 */ + unsigned regs[3]; /* 16-24 */ + ffi_cif *cif; /* 28 */ + void (*fun)(ffi_cif*,void*,void**,void*); /* 32 */ + void *user_data; /* 36 */ +}; + +int FFI_HIDDEN FFI_DECLARE_FASTCALL +ffi_closure_inner (struct closure_frame *frame, char *stack) +{ + ffi_cif *cif = frame->cif; + int cabi, i, n, flags, dir, narg_reg; + const struct abi_params *pabi; + ffi_type **arg_types; + char *argp; + void *rvalue; + void **avalue; + + cabi = cif->abi; + flags = cif->flags; + narg_reg = 0; + rvalue = frame->rettemp; + pabi = &abi_params[cabi]; + dir = pabi->dir; + argp = (dir < 0 ? stack + STACK_ALIGN (cif->bytes) : stack); + + switch (flags) + { + case X86_RET_STRUCTARG: + if (pabi->nregs > 0) + { + rvalue = (void *)frame->regs[pabi->regs[0]]; + narg_reg = 1; + frame->rettemp[0] = (unsigned)rvalue; + break; + } + /* fallthru */ + case X86_RET_STRUCTPOP: + rvalue = *(void **)argp; + argp += sizeof(void *); + frame->rettemp[0] = (unsigned)rvalue; + break; + } + + n = cif->nargs; + avalue = alloca(sizeof(void *) * n); + + arg_types = cif->arg_types; + for (i = 0; i < n; ++i) + { + ffi_type *ty = arg_types[i]; + size_t z = ty->size; + int t = ty->type; + void *valp; + + if (z <= FFI_SIZEOF_ARG && t != FFI_TYPE_STRUCT) + { + if (t != FFI_TYPE_FLOAT && narg_reg < pabi->nregs) + valp = &frame->regs[pabi->regs[narg_reg++]]; + else if (dir < 0) + { + argp -= 4; + valp = argp; + } + else + { + valp = argp; + argp += 4; + } + } + else + { + size_t za = FFI_ALIGN (z, FFI_SIZEOF_ARG); + size_t align = FFI_SIZEOF_ARG; + + /* See the comment in ffi_call_int. */ + if (t == FFI_TYPE_STRUCT && ty->alignment >= 16) + align = 16; + + /* Issue 434: For thiscall and fastcall, if the paramter passed + as 64-bit integer or struct, all following integer parameters + will be passed on stack. */ + if ((cabi == FFI_THISCALL || cabi == FFI_FASTCALL) + && (t == FFI_TYPE_SINT64 + || t == FFI_TYPE_UINT64 + || t == FFI_TYPE_STRUCT)) + narg_reg = 2; + + if (dir < 0) + { + /* ??? These reverse argument ABIs are probably too old + to have cared about alignment. Someone should check. */ + argp -= za; + valp = argp; + } + else + { + argp = (char *)FFI_ALIGN (argp, align); + valp = argp; + argp += za; + } + } + + avalue[i] = valp; + } + + frame->fun (cif, rvalue, avalue, frame->user_data); + + if (cabi == FFI_STDCALL) + return flags + (cif->bytes << X86_RET_POP_SHIFT); + else + return flags; +} +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 ffi_status ffi_prep_closure_loc (ffi_closure* closure, @@ -736,6 +1132,7 @@ ffi_prep_closure_loc (ffi_closure* closure, void *user_data, void *codeloc) { +<<<<<<< HEAD #ifdef X86_WIN64 #define ISFLOAT(IDX) (cif->arg_types[IDX]->type == FFI_TYPE_FLOAT || cif->arg_types[IDX]->type == FFI_TYPE_DOUBLE) #define FLAG(IDX) (cif->nargs>(IDX)&&ISFLOAT(IDX)?(1<<(IDX)):0) @@ -780,38 +1177,109 @@ ffi_prep_closure_loc (ffi_closure* closure, } #ifdef X86_WIN32 else if (cif->abi == FFI_MS_CDECL) +======= + char *tramp = closure->tramp; + void (*dest)(void); + int op = 0xb8; /* movl imm, %eax */ + + switch (cif->abi) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 { - FFI_INIT_TRAMPOLINE (&closure->tramp[0], - &ffi_closure_SYSV, - (void*)codeloc); + case FFI_SYSV: + case FFI_THISCALL: + case FFI_FASTCALL: + case FFI_MS_CDECL: + dest = ffi_closure_i386; + break; + case FFI_STDCALL: + case FFI_PASCAL: + dest = ffi_closure_STDCALL; + break; + case FFI_REGISTER: + dest = ffi_closure_REGISTER; + op = 0x68; /* pushl imm */ + break; + default: + return FFI_BAD_ABI; } -#endif /* X86_WIN32 */ -#endif /* !X86_WIN64 */ - else + + /* endbr32. */ + *(UINT32 *) tramp = 0xfb1e0ff3; + + /* movl or pushl immediate. */ + tramp[4] = op; + *(void **)(tramp + 5) = codeloc; + + /* jmp dest */ + tramp[9] = 0xe9; + *(unsigned *)(tramp + 10) = (unsigned)dest - ((unsigned)codeloc + 14); + + closure->cif = cif; + closure->fun = fun; + closure->user_data = user_data; + + return FFI_OK; +} + +#ifdef FFI_GO_CLOSURES + +void FFI_HIDDEN ffi_go_closure_EAX(void); +void FFI_HIDDEN ffi_go_closure_ECX(void); +void FFI_HIDDEN ffi_go_closure_STDCALL(void); + +ffi_status +ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif, + void (*fun)(ffi_cif*,void*,void**,void*)) +{ + void (*dest)(void); + + switch (cif->abi) { + case FFI_SYSV: + case FFI_MS_CDECL: + dest = ffi_go_closure_ECX; + break; + case FFI_THISCALL: + case FFI_FASTCALL: + dest = ffi_go_closure_EAX; + break; + case FFI_STDCALL: + case FFI_PASCAL: + dest = ffi_go_closure_STDCALL; + break; + case FFI_REGISTER: + default: return FFI_BAD_ABI; } - - closure->cif = cif; - closure->user_data = user_data; - closure->fun = fun; + + closure->tramp = dest; + closure->cif = cif; + closure->fun = fun; return FFI_OK; } +#endif /* FFI_GO_CLOSURES */ + /* ------- Native raw API support -------------------------------- */ #if !FFI_NO_RAW_API +void FFI_HIDDEN ffi_closure_raw_SYSV(void); +void FFI_HIDDEN ffi_closure_raw_THISCALL(void); + ffi_status -ffi_prep_raw_closure_loc (ffi_raw_closure* closure, - ffi_cif* cif, +ffi_prep_raw_closure_loc (ffi_raw_closure *closure, + ffi_cif *cif, void (*fun)(ffi_cif*,void*,ffi_raw*,void*), void *user_data, void *codeloc) { + char *tramp = closure->tramp; + void (*dest)(void); int i; +<<<<<<< HEAD if (cif->abi != FFI_SYSV #ifdef X86_WIN32 && cif->abi != FFI_THISCALL @@ -820,12 +1288,23 @@ ffi_prep_raw_closure_loc (ffi_raw_closure* closure, return FFI_BAD_ABI; /* we currently don't support certain kinds of arguments for raw +======= + /* We currently don't support certain kinds of arguments for raw +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 closures. This should be implemented by a separate assembly language routine, since it would require argument processing, something we don't do now for performance. */ - for (i = cif->nargs-1; i >= 0; i--) + switch (cif->arg_types[i]->type) + { + case FFI_TYPE_STRUCT: + case FFI_TYPE_LONGDOUBLE: + return FFI_BAD_TYPEDEF; + } + + switch (cif->abi) { +<<<<<<< HEAD FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_STRUCT); FFI_ASSERT (cif->arg_types[i]->type != FFI_TYPE_LONGDOUBLE); } @@ -841,15 +1320,34 @@ ffi_prep_raw_closure_loc (ffi_raw_closure* closure, else if (cif->abi == FFI_THISCALL) { FFI_INIT_TRAMPOLINE_RAW_THISCALL (&closure->tramp[0], &ffi_closure_raw_THISCALL, codeloc, cif->bytes); +======= + case FFI_THISCALL: + dest = ffi_closure_raw_THISCALL; + break; + case FFI_SYSV: + dest = ffi_closure_raw_SYSV; + break; + default: + return FFI_BAD_ABI; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 } -#endif - closure->cif = cif; + + /* movl imm, %eax. */ + tramp[0] = 0xb8; + *(void **)(tramp + 1) = codeloc; + + /* jmp dest */ + tramp[5] = 0xe9; + *(unsigned *)(tramp + 6) = (unsigned)dest - ((unsigned)codeloc + 10); + + closure->cif = cif; + closure->fun = fun; closure->user_data = user_data; - closure->fun = fun; return FFI_OK; } +<<<<<<< HEAD static unsigned int ffi_prep_args_raw(char *stack, extended_cif *ecif) { @@ -890,30 +1388,58 @@ ffi_prep_args_raw(char *stack, extended_cif *ecif) * libffi-1.20, this is not the case.) */ +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 void -ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue) +ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *avalue) { - extended_cif ecif; - void **avalue = (void **)fake_avalue; - - ecif.cif = cif; - ecif.avalue = avalue; - - /* If the return value is a struct and we don't have a return */ - /* value address then we need to make one */ - - if (rvalue == NULL - && (cif->flags == FFI_TYPE_STRUCT - || cif->flags == FFI_TYPE_MS_STRUCT)) + size_t rsize, bytes; + struct call_frame *frame; + char *stack, *argp; + ffi_type **arg_types; + int flags, cabi, i, n, narg_reg; + const struct abi_params *pabi; + + flags = cif->flags; + cabi = cif->abi; + pabi = &abi_params[cabi]; + + rsize = 0; + if (rvalue == NULL) { - ecif.rvalue = alloca(cif->rtype->size); + switch (flags) + { + case X86_RET_FLOAT: + case X86_RET_DOUBLE: + case X86_RET_LDOUBLE: + case X86_RET_STRUCTPOP: + case X86_RET_STRUCTARG: + /* The float cases need to pop the 387 stack. + The struct cases need to pass a valid pointer to the callee. */ + rsize = cif->rtype->size; + break; + default: + /* We can pretend that the callee returns nothing. */ + flags = X86_RET_VOID; + break; + } } - else - ecif.rvalue = rvalue; - - - switch (cif->abi) + + bytes = STACK_ALIGN (cif->bytes); + argp = stack = + (void *)((uintptr_t)alloca(bytes + sizeof(*frame) + rsize + 15) & ~16); + frame = (struct call_frame *)(stack + bytes); + if (rsize) + rvalue = frame + 1; + + frame->fn = fn; + frame->flags = flags; + frame->rvalue = rvalue; + + narg_reg = 0; + switch (flags) { +<<<<<<< HEAD #ifndef X86_WIN32 case FFI_SYSV: ffi_call_SYSV(ffi_prep_args_raw, &ecif, cif->bytes, cif->flags, @@ -935,13 +1461,55 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *fake_avalue) #endif default: FFI_ASSERT(0); +======= + case X86_RET_STRUCTARG: + /* The pointer is passed as the first argument. */ + if (pabi->nregs > 0) + { + frame->regs[pabi->regs[0]] = (unsigned)rvalue; + narg_reg = 1; + break; + } + /* fallthru */ + case X86_RET_STRUCTPOP: + *(void **)argp = rvalue; + argp += sizeof(void *); + bytes -= sizeof(void *); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 break; } -} - -#endif -#endif /* !__x86_64__ || X86_WIN64 */ + arg_types = cif->arg_types; + for (i = 0, n = cif->nargs; narg_reg < pabi->nregs && i < n; i++) + { + ffi_type *ty = arg_types[i]; + size_t z = ty->size; + int t = ty->type; + + if (z <= FFI_SIZEOF_ARG && t != FFI_TYPE_STRUCT && t != FFI_TYPE_FLOAT) + { + ffi_arg val = extend_basic_type (avalue, t); + frame->regs[pabi->regs[narg_reg++]] = val; + z = FFI_SIZEOF_ARG; + } + else + { + memcpy (argp, avalue, z); + z = FFI_ALIGN (z, FFI_SIZEOF_ARG); + argp += z; + } + avalue += z; + bytes -= z; + } + if (i < n) + memcpy (argp, avalue, bytes); +<<<<<<< HEAD +======= + ffi_call_i386 (frame, stack); +} +#endif /* !FFI_NO_RAW_API */ +#endif /* __i386__ */ +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 diff --git a/native/libffi/src/x86/ffi64.c b/native/libffi/src/x86/ffi64.c index 5a5e043835..8f513e4a12 100644 --- a/native/libffi/src/x86/ffi64.c +++ b/native/libffi/src/x86/ffi64.c @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------- - ffi64.c - Copyright (c) 2013 The Written Word, Inc. - Copyright (c) 2011 Anthony Green + ffi64.c - Copyright (c) 2011, 2018 Anthony Green + Copyright (c) 2013 The Written Word, Inc. Copyright (c) 2008, 2010 Red Hat, Inc. Copyright (c) 2002, 2007 Bo Thorsen @@ -32,6 +32,8 @@ #include #include +#include +#include "internal64.h" #ifdef __x86_64__ @@ -62,10 +64,15 @@ struct register_args /* Registers for argument passing. */ UINT64 gpr[MAX_GPR_REGS]; union big_int_union sse[MAX_SSE_REGS]; +<<<<<<< HEAD +======= + UINT64 rax; /* ssecount */ + UINT64 r10; /* static chain */ +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 }; extern void ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags, - void *raddr, void (*fnaddr)(void), unsigned ssecount); + void *raddr, void (*fnaddr)(void)) FFI_HIDDEN; /* All reference to register classes here is identical to the code in gcc/config/i386/i386.c. Do *not* change one without the other. */ @@ -167,6 +174,7 @@ classify_argument (ffi_type *type, enum x86_64_reg_class classes[], case FFI_TYPE_UINT64: case FFI_TYPE_SINT64: case FFI_TYPE_POINTER: + do_integer: { size_t size = byte_offset + type->size; @@ -188,7 +196,7 @@ classify_argument (ffi_type *type, enum x86_64_reg_class classes[], } else if (size <= 16) { - classes[0] = classes[1] = X86_64_INTEGERSI_CLASS; + classes[0] = classes[1] = X86_64_INTEGER_CLASS; return 2; } else @@ -214,7 +222,11 @@ classify_argument (ffi_type *type, enum x86_64_reg_class classes[], const size_t UNITS_PER_WORD = 8; size_t words = (type->size + UNITS_PER_WORD - 1) / UNITS_PER_WORD; ffi_type **ptr; +<<<<<<< HEAD int i; +======= + unsigned int i; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 enum x86_64_reg_class subclasses[MAX_CLASSES]; /* If the struct is larger than 32 bytes, pass it on the stack. */ @@ -228,6 +240,7 @@ classify_argument (ffi_type *type, enum x86_64_reg_class classes[], signalize memory class, so handle it as special case. */ if (!words) { + case FFI_TYPE_VOID: classes[0] = X86_64_NO_CLASS; return 1; } @@ -237,7 +250,7 @@ classify_argument (ffi_type *type, enum x86_64_reg_class classes[], { size_t num; - byte_offset = ALIGN (byte_offset, (*ptr)->alignment); + byte_offset = FFI_ALIGN (byte_offset, (*ptr)->alignment); num = classify_argument (*ptr, subclasses, byte_offset % 8); if (num == 0) @@ -276,7 +289,7 @@ classify_argument (ffi_type *type, enum x86_64_reg_class classes[], /* The X86_64_SSEUP_CLASS should be always preceded by X86_64_SSE_CLASS or X86_64_SSEUP_CLASS. */ - if (classes[i] == X86_64_SSEUP_CLASS + if (i > 1 && classes[i] == X86_64_SSEUP_CLASS && classes[i - 1] != X86_64_SSE_CLASS && classes[i - 1] != X86_64_SSEUP_CLASS) { @@ -287,7 +300,7 @@ classify_argument (ffi_type *type, enum x86_64_reg_class classes[], /* If X86_64_X87UP_CLASS isn't preceded by X86_64_X87_CLASS, everything should be passed in memory. */ - if (classes[i] == X86_64_X87UP_CLASS + if (i > 1 && classes[i] == X86_64_X87UP_CLASS && (classes[i - 1] != X86_64_X87_CLASS)) { /* The first one should never be X86_64_X87UP_CLASS. */ @@ -297,11 +310,42 @@ classify_argument (ffi_type *type, enum x86_64_reg_class classes[], } return words; } - - default: - FFI_ASSERT(0); + case FFI_TYPE_COMPLEX: + { + ffi_type *inner = type->elements[0]; + switch (inner->type) + { + case FFI_TYPE_INT: + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT16: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: + goto do_integer; + + case FFI_TYPE_FLOAT: + classes[0] = X86_64_SSE_CLASS; + if (byte_offset % 8) + { + classes[1] = X86_64_SSESF_CLASS; + return 2; + } + return 1; + case FFI_TYPE_DOUBLE: + classes[0] = classes[1] = X86_64_SSEDF_CLASS; + return 2; +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + case FFI_TYPE_LONGDOUBLE: + classes[0] = X86_64_COMPLEX_X87_CLASS; + return 1; +#endif + } + } } - return 0; /* Never reached. */ + abort(); } /* Examine the argument and return set number of register required in each @@ -313,7 +357,12 @@ examine_argument (ffi_type *type, enum x86_64_reg_class classes[MAX_CLASSES], _Bool in_return, int *pngpr, int *pnsse) { size_t n; +<<<<<<< HEAD int i, ngpr, nsse; +======= + unsigned int i; + int ngpr, nsse; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 n = classify_argument (type, classes, 0); if (n == 0) @@ -351,18 +400,80 @@ examine_argument (ffi_type *type, enum x86_64_reg_class classes[MAX_CLASSES], /* Perform machine dependent cif processing. */ -ffi_status +#ifndef __ILP32__ +extern ffi_status +ffi_prep_cif_machdep_efi64(ffi_cif *cif); +#endif + +ffi_status FFI_HIDDEN ffi_prep_cif_machdep (ffi_cif *cif) { +<<<<<<< HEAD int gprcount, ssecount, i, avn, ngpr, nsse, flags; enum x86_64_reg_class classes[MAX_CLASSES]; size_t bytes, n; +======= + int gprcount, ssecount, i, avn, ngpr, nsse; + unsigned flags; + enum x86_64_reg_class classes[MAX_CLASSES]; + size_t bytes, n, rtype_size; + ffi_type *rtype; + +#ifndef __ILP32__ + if (cif->abi == FFI_EFI64 || cif->abi == FFI_GNUW64) + return ffi_prep_cif_machdep_efi64(cif); +#endif + if (cif->abi != FFI_UNIX64) + return FFI_BAD_ABI; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 gprcount = ssecount = 0; - flags = cif->rtype->type; - if (flags != FFI_TYPE_VOID) + rtype = cif->rtype; + rtype_size = rtype->size; + switch (rtype->type) { + case FFI_TYPE_VOID: + flags = UNIX64_RET_VOID; + break; + case FFI_TYPE_UINT8: + flags = UNIX64_RET_UINT8; + break; + case FFI_TYPE_SINT8: + flags = UNIX64_RET_SINT8; + break; + case FFI_TYPE_UINT16: + flags = UNIX64_RET_UINT16; + break; + case FFI_TYPE_SINT16: + flags = UNIX64_RET_SINT16; + break; + case FFI_TYPE_UINT32: + flags = UNIX64_RET_UINT32; + break; + case FFI_TYPE_INT: + case FFI_TYPE_SINT32: + flags = UNIX64_RET_SINT32; + break; + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: + flags = UNIX64_RET_INT64; + break; + case FFI_TYPE_POINTER: + flags = (sizeof(void *) == 4 ? UNIX64_RET_UINT32 : UNIX64_RET_INT64); + break; + case FFI_TYPE_FLOAT: + flags = UNIX64_RET_XMM32; + break; + case FFI_TYPE_DOUBLE: + flags = UNIX64_RET_XMM64; + break; +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + case FFI_TYPE_LONGDOUBLE: + flags = UNIX64_RET_X87; + break; +#endif + case FFI_TYPE_STRUCT: n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); if (n == 0) { @@ -370,22 +481,62 @@ ffi_prep_cif_machdep (ffi_cif *cif) memory is the first argument. Allocate a register for it. */ gprcount++; /* We don't have to do anything in asm for the return. */ - flags = FFI_TYPE_VOID; + flags = UNIX64_RET_VOID | UNIX64_FLAG_RET_IN_MEM; } - else if (flags == FFI_TYPE_STRUCT) + else { - /* Mark which registers the result appears in. */ _Bool sse0 = SSE_CLASS_P (classes[0]); - _Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]); - if (sse0 && !sse1) - flags |= 1 << 8; - else if (!sse0 && sse1) - flags |= 1 << 9; - else if (sse0 && sse1) - flags |= 1 << 10; - /* Mark the true size of the structure. */ - flags |= cif->rtype->size << 12; + + if (rtype_size == 4 && sse0) + flags = UNIX64_RET_XMM32; + else if (rtype_size == 8) + flags = sse0 ? UNIX64_RET_XMM64 : UNIX64_RET_INT64; + else + { + _Bool sse1 = n == 2 && SSE_CLASS_P (classes[1]); + if (sse0 && sse1) + flags = UNIX64_RET_ST_XMM0_XMM1; + else if (sse0) + flags = UNIX64_RET_ST_XMM0_RAX; + else if (sse1) + flags = UNIX64_RET_ST_RAX_XMM0; + else + flags = UNIX64_RET_ST_RAX_RDX; + flags |= rtype_size << UNIX64_SIZE_SHIFT; + } + } + break; + case FFI_TYPE_COMPLEX: + switch (rtype->elements[0]->type) + { + case FFI_TYPE_UINT8: + case FFI_TYPE_SINT8: + case FFI_TYPE_UINT16: + case FFI_TYPE_SINT16: + case FFI_TYPE_INT: + case FFI_TYPE_UINT32: + case FFI_TYPE_SINT32: + case FFI_TYPE_UINT64: + case FFI_TYPE_SINT64: + flags = UNIX64_RET_ST_RAX_RDX | ((unsigned) rtype_size << UNIX64_SIZE_SHIFT); + break; + case FFI_TYPE_FLOAT: + flags = UNIX64_RET_XMM64; + break; + case FFI_TYPE_DOUBLE: + flags = UNIX64_RET_ST_XMM0_XMM1 | (16 << UNIX64_SIZE_SHIFT); + break; +#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE + case FFI_TYPE_LONGDOUBLE: + flags = UNIX64_RET_X87_2; + break; +#endif + default: + return FFI_BAD_TYPEDEF; } + break; + default: + return FFI_BAD_TYPEDEF; } /* Go over all arguments and determine the way they should be passed. @@ -402,7 +553,7 @@ ffi_prep_cif_machdep (ffi_cif *cif) if (align < 8) align = 8; - bytes = ALIGN (bytes, align); + bytes = FFI_ALIGN (bytes, align); bytes += cif->arg_types[i]->size; } else @@ -412,44 +563,54 @@ ffi_prep_cif_machdep (ffi_cif *cif) } } if (ssecount) - flags |= 1 << 11; + flags |= UNIX64_FLAG_XMM_ARGS; + cif->flags = flags; +<<<<<<< HEAD cif->bytes = (unsigned)ALIGN (bytes, 8); +======= + cif->bytes = (unsigned) FFI_ALIGN (bytes, 8); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 return FFI_OK; } -void -ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +static void +ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure) { enum x86_64_reg_class classes[MAX_CLASSES]; char *stack, *argp; ffi_type **arg_types; - int gprcount, ssecount, ngpr, nsse, i, avn; - _Bool ret_in_memory; + int gprcount, ssecount, ngpr, nsse, i, avn, flags; struct register_args *reg_args; /* Can't call 32-bit mode from 64-bit mode. */ FFI_ASSERT (cif->abi == FFI_UNIX64); /* If the return value is a struct and we don't have a return value - address then we need to make one. Note the setting of flags to - VOID above in ffi_prep_cif_machdep. */ - ret_in_memory = (cif->rtype->type == FFI_TYPE_STRUCT - && (cif->flags & 0xff) == FFI_TYPE_VOID); - if (rvalue == NULL && ret_in_memory) - rvalue = alloca (cif->rtype->size); + address then we need to make one. Otherwise we can ignore it. */ + flags = cif->flags; + if (rvalue == NULL) + { + if (flags & UNIX64_FLAG_RET_IN_MEM) + rvalue = alloca (cif->rtype->size); + else + flags = UNIX64_RET_VOID; + } /* Allocate the space for the arguments, plus 4 words of temp space. */ stack = alloca (sizeof (struct register_args) + cif->bytes + 4*8); reg_args = (struct register_args *) stack; argp = stack + sizeof (struct register_args); + reg_args->r10 = (uintptr_t) closure; + gprcount = ssecount = 0; /* If the return value is passed in memory, add the pointer as the first integer argument. */ - if (ret_in_memory) + if (flags & UNIX64_FLAG_RET_IN_MEM) reg_args->gpr[gprcount++] = (unsigned long) rvalue; avn = cif->nargs; @@ -471,7 +632,7 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) align = 8; /* Pass this argument in memory. */ - argp = (void *) ALIGN (argp, align); + argp = (void *) FFI_ALIGN (argp, align); memcpy (argp, avalue[i], size); argp += size; } @@ -479,12 +640,15 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) { /* The argument is passed entirely in registers. */ char *a = (char *) avalue[i]; - int j; + unsigned int j; for (j = 0; j < n; j++, a += 8, size -= 8) { switch (classes[j]) { + case X86_64_NO_CLASS: + case X86_64_SSEUP_CLASS: + break; case X86_64_INTEGER_CLASS: case X86_64_INTEGERSI_CLASS: /* Sign-extend integer arguments passed in general @@ -494,26 +658,26 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) switch (arg_types[i]->type) { case FFI_TYPE_SINT8: - *(SINT64 *)®_args->gpr[gprcount] = (SINT64) *((SINT8 *) a); + reg_args->gpr[gprcount] = (SINT64) *((SINT8 *) a); break; case FFI_TYPE_SINT16: - *(SINT64 *)®_args->gpr[gprcount] = (SINT64) *((SINT16 *) a); + reg_args->gpr[gprcount] = (SINT64) *((SINT16 *) a); break; case FFI_TYPE_SINT32: - *(SINT64 *)®_args->gpr[gprcount] = (SINT64) *((SINT32 *) a); + reg_args->gpr[gprcount] = (SINT64) *((SINT32 *) a); break; default: reg_args->gpr[gprcount] = 0; - memcpy (®_args->gpr[gprcount], a, size < 8 ? size : 8); + memcpy (®_args->gpr[gprcount], a, size); } gprcount++; break; case X86_64_SSE_CLASS: case X86_64_SSEDF_CLASS: - reg_args->sse[ssecount++].i64 = *(UINT64 *) a; + memcpy (®_args->sse[ssecount++].i64, a, sizeof(UINT64)); break; case X86_64_SSESF_CLASS: - reg_args->sse[ssecount++].i32 = *(UINT32 *) a; + memcpy (®_args->sse[ssecount++].i32, a, sizeof(UINT32)); break; default: abort(); @@ -521,13 +685,65 @@ ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) } } } + reg_args->rax = ssecount; ffi_call_unix64 (stack, cif->bytes + sizeof (struct register_args), - cif->flags, rvalue, fn, ssecount); + flags, rvalue, fn); +} + +#ifndef __ILP32__ +extern void +ffi_call_efi64(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue); +#endif + +void +ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +{ +#ifndef __ILP32__ + if (cif->abi == FFI_EFI64 || cif->abi == FFI_GNUW64) + { + ffi_call_efi64(cif, fn, rvalue, avalue); + return; + } +#endif + ffi_call_int (cif, fn, rvalue, avalue, NULL); +} + +#ifdef FFI_GO_CLOSURES + +#ifndef __ILP32__ +extern void +ffi_call_go_efi64(ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure); +#endif + +void +ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure) +{ +#ifndef __ILP32__ + if (cif->abi == FFI_EFI64 || cif->abi == FFI_GNUW64) + { + ffi_call_go_efi64(cif, fn, rvalue, avalue, closure); + return; + } +#endif + ffi_call_int (cif, fn, rvalue, avalue, closure); } +#endif /* FFI_GO_CLOSURES */ -extern void ffi_closure_unix64(void); +extern void ffi_closure_unix64(void) FFI_HIDDEN; +extern void ffi_closure_unix64_sse(void) FFI_HIDDEN; + +#ifndef __ILP32__ +extern ffi_status +ffi_prep_closure_loc_efi64(ffi_closure* closure, + ffi_cif* cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void *user_data, + void *codeloc); +#endif ffi_status ffi_prep_closure_loc (ffi_closure* closure, @@ -536,29 +752,33 @@ ffi_prep_closure_loc (ffi_closure* closure, void *user_data, void *codeloc) { - volatile unsigned short *tramp; - - /* Sanity check on the cif ABI. */ - { - int abi = cif->abi; - if (UNLIKELY (! (abi > FFI_FIRST_ABI && abi < FFI_LAST_ABI))) - return FFI_BAD_ABI; - } - - tramp = (volatile unsigned short *) &closure->tramp[0]; + static const unsigned char trampoline[24] = { + /* endbr64 */ + 0xf3, 0x0f, 0x1e, 0xfa, + /* leaq -0xb(%rip),%r10 # 0x0 */ + 0x4c, 0x8d, 0x15, 0xf5, 0xff, 0xff, 0xff, + /* jmpq *0x7(%rip) # 0x18 */ + 0xff, 0x25, 0x07, 0x00, 0x00, 0x00, + /* nopl 0(%rax) */ + 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00 + }; + void (*dest)(void); + char *tramp = closure->tramp; - tramp[0] = 0xbb49; /* mov , %r11 */ - *((unsigned long long * volatile) &tramp[1]) - = (unsigned long) ffi_closure_unix64; - tramp[5] = 0xba49; /* mov , %r10 */ - *((unsigned long long * volatile) &tramp[6]) - = (unsigned long) codeloc; +#ifndef __ILP32__ + if (cif->abi == FFI_EFI64 || cif->abi == FFI_GNUW64) + return ffi_prep_closure_loc_efi64(closure, cif, fun, user_data, codeloc); +#endif + if (cif->abi != FFI_UNIX64) + return FFI_BAD_ABI; - /* Set the carry bit iff the function uses any sse registers. - This is clc or stc, together with the first byte of the jmp. */ - tramp[10] = cif->flags & (1 << 11) ? 0x49f9 : 0x49f8; + if (cif->flags & UNIX64_FLAG_XMM_ARGS) + dest = ffi_closure_unix64_sse; + else + dest = ffi_closure_unix64; - tramp[11] = 0xe3ff; /* jmp *%r11 */ + memcpy (tramp, trampoline, sizeof(trampoline)); + *(UINT64 *)(tramp + sizeof (trampoline)) = (uintptr_t)dest; closure->cif = cif; closure->fun = fun; @@ -567,24 +787,28 @@ ffi_prep_closure_loc (ffi_closure* closure, return FFI_OK; } -int -ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue, - struct register_args *reg_args, char *argp) +int FFI_HIDDEN +ffi_closure_unix64_inner(ffi_cif *cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void *user_data, + void *rvalue, + struct register_args *reg_args, + char *argp) { - ffi_cif *cif; void **avalue; ffi_type **arg_types; long i, avn; int gprcount, ssecount, ngpr, nsse; - int ret; + int flags; - cif = closure->cif; - avalue = alloca(cif->nargs * sizeof(void *)); + avn = cif->nargs; + flags = cif->flags; + avalue = alloca(avn * sizeof(void *)); gprcount = ssecount = 0; - ret = cif->rtype->type; - if (ret != FFI_TYPE_VOID) + if (flags & UNIX64_FLAG_RET_IN_MEM) { +<<<<<<< HEAD enum x86_64_reg_class classes[MAX_CLASSES]; size_t n = examine_argument (cif->rtype, classes, 1, &ngpr, &nsse); if (n == 0) @@ -605,11 +829,21 @@ ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue, else if (sse0 && !sse1) ret |= 1 << 9; } +======= + /* On return, %rax will contain the address that was passed + by the caller in %rdi. */ + void *r = (void *)(uintptr_t)reg_args->gpr[gprcount++]; + *(void **)rvalue = r; + rvalue = r; + flags = (sizeof(void *) == 4 ? UNIX64_RET_UINT32 : UNIX64_RET_INT64); +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 } - avn = cif->nargs; arg_types = cif->arg_types; +<<<<<<< HEAD +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 for (i = 0; i < avn; ++i) { enum x86_64_reg_class classes[MAX_CLASSES]; @@ -627,7 +861,7 @@ ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue, align = 8; /* Pass this argument in memory. */ - argp = (void *) ALIGN (argp, align); + argp = (void *) FFI_ALIGN (argp, align); avalue[i] = argp; argp += arg_types[i]->size; } @@ -653,7 +887,7 @@ ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue, else { char *a = alloca (16); - int j; + unsigned int j; avalue[i] = a; for (j = 0; j < n; j++, a += 8) @@ -667,10 +901,43 @@ ffi_closure_unix64_inner(ffi_closure *closure, void *rvalue, } /* Invoke the closure. */ - closure->fun (cif, rvalue, avalue, closure->user_data); + fun (cif, rvalue, avalue, user_data); /* Tell assembly how to perform return type promotions. */ - return ret; + return flags; +} + +#ifdef FFI_GO_CLOSURES + +extern void ffi_go_closure_unix64(void) FFI_HIDDEN; +extern void ffi_go_closure_unix64_sse(void) FFI_HIDDEN; + +#ifndef __ILP32__ +extern ffi_status +ffi_prep_go_closure_efi64(ffi_go_closure* closure, ffi_cif* cif, + void (*fun)(ffi_cif*, void*, void**, void*)); +#endif + +ffi_status +ffi_prep_go_closure (ffi_go_closure* closure, ffi_cif* cif, + void (*fun)(ffi_cif*, void*, void**, void*)) +{ +#ifndef __ILP32__ + if (cif->abi == FFI_EFI64 || cif->abi == FFI_GNUW64) + return ffi_prep_go_closure_efi64(closure, cif, fun); +#endif + if (cif->abi != FFI_UNIX64) + return FFI_BAD_ABI; + + closure->tramp = (cif->flags & UNIX64_FLAG_XMM_ARGS + ? ffi_go_closure_unix64_sse + : ffi_go_closure_unix64); + closure->cif = cif; + closure->fun = fun; + + return FFI_OK; } +#endif /* FFI_GO_CLOSURES */ + #endif /* __x86_64__ */ diff --git a/native/libffi/src/x86/ffitarget.h b/native/libffi/src/x86/ffitarget.h index ff0f71857d..9f71e1dde7 100644 --- a/native/libffi/src/x86/ffitarget.h +++ b/native/libffi/src/x86/ffitarget.h @@ -1,5 +1,9 @@ /* -----------------------------------------------------------------*-C-*- +<<<<<<< HEAD ffitarget.h - Copyright (c) 2012, 2014 Anthony Green +======= + ffitarget.h - Copyright (c) 2012, 2014, 2018 Anthony Green +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 Copyright (c) 1996-2003, 2010 Red Hat, Inc. Copyright (C) 2008 Free Software Foundation, Inc. @@ -78,7 +82,9 @@ typedef signed long ffi_sarg; #endif typedef enum ffi_abi { +#if defined(X86_WIN64) FFI_FIRST_ABI = 0, +<<<<<<< HEAD /* ---- Intel x86 Win32 ---------- */ #ifdef X86_WIN32 @@ -89,19 +95,39 @@ typedef enum ffi_abi { FFI_MS_CDECL, FFI_PASCAL, FFI_REGISTER, +======= + FFI_WIN64, /* sizeof(long double) == 8 - microsoft compilers */ + FFI_GNUW64, /* sizeof(long double) == 16 - GNU compilers */ +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 FFI_LAST_ABI, -#ifdef _MSC_VER - FFI_DEFAULT_ABI = FFI_MS_CDECL -#else - FFI_DEFAULT_ABI = FFI_SYSV -#endif +#ifdef __GNUC__ + FFI_DEFAULT_ABI = FFI_GNUW64 +#else + FFI_DEFAULT_ABI = FFI_WIN64 +#endif -#elif defined(X86_WIN64) +#elif defined(X86_64) || (defined (__x86_64__) && defined (X86_DARWIN)) + FFI_FIRST_ABI = 1, + FFI_UNIX64, FFI_WIN64, + FFI_EFI64 = FFI_WIN64, + FFI_GNUW64, FFI_LAST_ABI, - FFI_DEFAULT_ABI = FFI_WIN64 + FFI_DEFAULT_ABI = FFI_UNIX64 +#elif defined(X86_WIN32) + FFI_FIRST_ABI = 0, + FFI_SYSV = 1, + FFI_STDCALL = 2, + FFI_THISCALL = 3, + FFI_FASTCALL = 4, + FFI_MS_CDECL = 5, + FFI_PASCAL = 6, + FFI_REGISTER = 7, + FFI_LAST_ABI, + FFI_DEFAULT_ABI = FFI_MS_CDECL #else +<<<<<<< HEAD /* ---- Intel x86 and AMD x86-64 - */ FFI_SYSV, FFI_UNIX64, /* Unix variants all use the same ABI for x86-64 */ @@ -110,12 +136,18 @@ typedef enum ffi_abi { FFI_STDCALL, FFI_PASCAL, FFI_REGISTER, +======= + FFI_FIRST_ABI = 0, + FFI_SYSV = 1, + FFI_THISCALL = 3, + FFI_FASTCALL = 4, + FFI_STDCALL = 5, + FFI_PASCAL = 6, + FFI_REGISTER = 7, + FFI_MS_CDECL = 8, +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 FFI_LAST_ABI, -#if defined(__i386__) || defined(__i386) FFI_DEFAULT_ABI = FFI_SYSV -#else - FFI_DEFAULT_ABI = FFI_UNIX64 -#endif #endif } ffi_abi; #endif @@ -123,18 +155,21 @@ typedef enum ffi_abi { /* ---- Definitions for closures ----------------------------------------- */ #define FFI_CLOSURES 1 +#define FFI_GO_CLOSURES 1 + #define FFI_TYPE_SMALL_STRUCT_1B (FFI_TYPE_LAST + 1) #define FFI_TYPE_SMALL_STRUCT_2B (FFI_TYPE_LAST + 2) #define FFI_TYPE_SMALL_STRUCT_4B (FFI_TYPE_LAST + 3) #define FFI_TYPE_MS_STRUCT (FFI_TYPE_LAST + 4) -#if defined (X86_64) || (defined (__x86_64__) && defined (X86_DARWIN)) -#define FFI_TRAMPOLINE_SIZE 24 -#define FFI_NATIVE_RAW_API 0 -#else -#ifdef X86_WIN32 -#define FFI_TRAMPOLINE_SIZE 52 +#if defined (X86_64) || defined(X86_WIN64) \ + || (defined (__x86_64__) && defined (X86_DARWIN)) +/* 4 bytes of ENDBR64 + 7 bytes of LEA + 6 bytes of JMP + 7 bytes of NOP + + 8 bytes of pointer. */ +# define FFI_TRAMPOLINE_SIZE 32 +# define FFI_NATIVE_RAW_API 0 #else +<<<<<<< HEAD #ifdef X86_WIN64 #define FFI_TRAMPOLINE_SIZE 29 #define FFI_NATIVE_RAW_API 0 @@ -145,7 +180,21 @@ typedef enum ffi_abi { #endif #ifndef X86_WIN64 #define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */ -#endif +======= +/* 4 bytes of ENDBR32 + 5 bytes of MOV + 5 bytes of JMP + 2 unused + bytes. */ +# define FFI_TRAMPOLINE_SIZE 16 +# define FFI_NATIVE_RAW_API 1 /* x86 has native raw api support */ +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 +#endif + +#if !defined(GENERATE_LIBFFI_MAP) && defined(__ASSEMBLER__) \ + && defined(__CET__) +# include +# define _CET_NOTRACK notrack +#else +# define _CET_ENDBR +# define _CET_NOTRACK #endif #endif diff --git a/native/libffi/src/x86/ffiw64.c b/native/libffi/src/x86/ffiw64.c new file mode 100644 index 0000000000..a43a9ebe94 --- /dev/null +++ b/native/libffi/src/x86/ffiw64.c @@ -0,0 +1,318 @@ +/* ----------------------------------------------------------------------- + ffiw64.c - Copyright (c) 2018 Anthony Green + Copyright (c) 2014 Red Hat, Inc. + + x86 win64 Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#if defined(__x86_64__) || defined(_M_AMD64) +#include +#include +#include +#include + +#ifdef X86_WIN64 +#define EFI64(name) name +#else +#define EFI64(name) FFI_HIDDEN name##_efi64 +#endif + +struct win64_call_frame +{ + UINT64 rbp; /* 0 */ + UINT64 retaddr; /* 8 */ + UINT64 fn; /* 16 */ + UINT64 flags; /* 24 */ + UINT64 rvalue; /* 32 */ +}; + +extern void ffi_call_win64 (void *stack, struct win64_call_frame *, + void *closure) FFI_HIDDEN; + +ffi_status FFI_HIDDEN +EFI64(ffi_prep_cif_machdep)(ffi_cif *cif) +{ + int flags, n; + + switch (cif->abi) + { + case FFI_WIN64: + case FFI_GNUW64: + break; + default: + return FFI_BAD_ABI; + } + + flags = cif->rtype->type; + switch (flags) + { + default: + break; + case FFI_TYPE_LONGDOUBLE: + /* GCC returns long double values by reference, like a struct */ + if (cif->abi == FFI_GNUW64) + flags = FFI_TYPE_STRUCT; + break; + case FFI_TYPE_COMPLEX: + flags = FFI_TYPE_STRUCT; + /* FALLTHRU */ + case FFI_TYPE_STRUCT: + switch (cif->rtype->size) + { + case 8: + flags = FFI_TYPE_UINT64; + break; + case 4: + flags = FFI_TYPE_SMALL_STRUCT_4B; + break; + case 2: + flags = FFI_TYPE_SMALL_STRUCT_2B; + break; + case 1: + flags = FFI_TYPE_SMALL_STRUCT_1B; + break; + } + break; + } + cif->flags = flags; + + /* Each argument either fits in a register, an 8 byte slot, or is + passed by reference with the pointer in the 8 byte slot. */ + n = cif->nargs; + n += (flags == FFI_TYPE_STRUCT); + if (n < 4) + n = 4; + cif->bytes = n * 8; + + return FFI_OK; +} + +static void +ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure) +{ + int i, j, n, flags; + UINT64 *stack; + size_t rsize; + struct win64_call_frame *frame; + + FFI_ASSERT(cif->abi == FFI_GNUW64 || cif->abi == FFI_WIN64); + + flags = cif->flags; + rsize = 0; + + /* If we have no return value for a structure, we need to create one. + Otherwise we can ignore the return type entirely. */ + if (rvalue == NULL) + { + if (flags == FFI_TYPE_STRUCT) + rsize = cif->rtype->size; + else + flags = FFI_TYPE_VOID; + } + + stack = alloca(cif->bytes + sizeof(struct win64_call_frame) + rsize); + frame = (struct win64_call_frame *)((char *)stack + cif->bytes); + if (rsize) + rvalue = frame + 1; + + frame->fn = (uintptr_t)fn; + frame->flags = flags; + frame->rvalue = (uintptr_t)rvalue; + + j = 0; + if (flags == FFI_TYPE_STRUCT) + { + stack[0] = (uintptr_t)rvalue; + j = 1; + } + + for (i = 0, n = cif->nargs; i < n; ++i, ++j) + { + switch (cif->arg_types[i]->size) + { + case 8: + stack[j] = *(UINT64 *)avalue[i]; + break; + case 4: + stack[j] = *(UINT32 *)avalue[i]; + break; + case 2: + stack[j] = *(UINT16 *)avalue[i]; + break; + case 1: + stack[j] = *(UINT8 *)avalue[i]; + break; + default: + stack[j] = (uintptr_t)avalue[i]; + break; + } + } + + ffi_call_win64 (stack, frame, closure); +} + +void +EFI64(ffi_call)(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue) +{ + ffi_call_int (cif, fn, rvalue, avalue, NULL); +} + +void +EFI64(ffi_call_go)(ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure) +{ + ffi_call_int (cif, fn, rvalue, avalue, closure); +} + + +extern void ffi_closure_win64(void) FFI_HIDDEN; + +#ifdef FFI_GO_CLOSURES +extern void ffi_go_closure_win64(void) FFI_HIDDEN; +#endif + +ffi_status +EFI64(ffi_prep_closure_loc)(ffi_closure* closure, + ffi_cif* cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void *user_data, + void *codeloc) +{ + static const unsigned char trampoline[FFI_TRAMPOLINE_SIZE - 8] = { + /* endbr64 */ + 0xf3, 0x0f, 0x1e, 0xfa, + /* leaq -0xb(%rip),%r10 # 0x0 */ + 0x4c, 0x8d, 0x15, 0xf5, 0xff, 0xff, 0xff, + /* jmpq *0x7(%rip) # 0x18 */ + 0xff, 0x25, 0x07, 0x00, 0x00, 0x00, + /* nopl 0(%rax) */ + 0x0f, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00 + }; + char *tramp = closure->tramp; + + switch (cif->abi) + { + case FFI_WIN64: + case FFI_GNUW64: + break; + default: + return FFI_BAD_ABI; + } + + memcpy (tramp, trampoline, sizeof(trampoline)); + *(UINT64 *)(tramp + sizeof (trampoline)) = (uintptr_t)ffi_closure_win64; + + closure->cif = cif; + closure->fun = fun; + closure->user_data = user_data; + + return FFI_OK; +} + +#ifdef FFI_GO_CLOSURES +ffi_status +EFI64(ffi_prep_go_closure)(ffi_go_closure* closure, ffi_cif* cif, + void (*fun)(ffi_cif*, void*, void**, void*)) +{ + switch (cif->abi) + { + case FFI_WIN64: + case FFI_GNUW64: + break; + default: + return FFI_BAD_ABI; + } + + closure->tramp = ffi_go_closure_win64; + closure->cif = cif; + closure->fun = fun; + + return FFI_OK; +} +#endif + +struct win64_closure_frame +{ + UINT64 rvalue[2]; + UINT64 fargs[4]; + UINT64 retaddr; + UINT64 args[]; +}; + +/* Force the inner function to use the MS ABI. When compiling on win64 + this is a nop. When compiling on unix, this simplifies the assembly, + and places the burden of saving the extra call-saved registers on + the compiler. */ +int FFI_HIDDEN __attribute__((ms_abi)) +ffi_closure_win64_inner(ffi_cif *cif, + void (*fun)(ffi_cif*, void*, void**, void*), + void *user_data, + struct win64_closure_frame *frame) +{ + void **avalue; + void *rvalue; + int i, n, nreg, flags; + + avalue = alloca(cif->nargs * sizeof(void *)); + rvalue = frame->rvalue; + nreg = 0; + + /* When returning a structure, the address is in the first argument. + We must also be prepared to return the same address in eax, so + install that address in the frame and pretend we return a pointer. */ + flags = cif->flags; + if (flags == FFI_TYPE_STRUCT) + { + rvalue = (void *)(uintptr_t)frame->args[0]; + frame->rvalue[0] = frame->args[0]; + nreg = 1; + } + + for (i = 0, n = cif->nargs; i < n; ++i, ++nreg) + { + size_t size = cif->arg_types[i]->size; + size_t type = cif->arg_types[i]->type; + void *a; + + if (type == FFI_TYPE_DOUBLE || type == FFI_TYPE_FLOAT) + { + if (nreg < 4) + a = &frame->fargs[nreg]; + else + a = &frame->args[nreg]; + } + else if (size == 1 || size == 2 || size == 4 || size == 8) + a = &frame->args[nreg]; + else + a = (void *)(uintptr_t)frame->args[nreg]; + + avalue[i] = a; + } + + /* Invoke the closure. */ + fun (cif, rvalue, avalue, user_data); + return flags; +} + +#endif /* __x86_64__ */ diff --git a/native/libffi/src/x86/internal.h b/native/libffi/src/x86/internal.h new file mode 100644 index 0000000000..09771ba8cf --- /dev/null +++ b/native/libffi/src/x86/internal.h @@ -0,0 +1,29 @@ +#define X86_RET_FLOAT 0 +#define X86_RET_DOUBLE 1 +#define X86_RET_LDOUBLE 2 +#define X86_RET_SINT8 3 +#define X86_RET_SINT16 4 +#define X86_RET_UINT8 5 +#define X86_RET_UINT16 6 +#define X86_RET_INT64 7 +#define X86_RET_INT32 8 +#define X86_RET_VOID 9 +#define X86_RET_STRUCTPOP 10 +#define X86_RET_STRUCTARG 11 +#define X86_RET_STRUCT_1B 12 +#define X86_RET_STRUCT_2B 13 +#define X86_RET_UNUSED14 14 +#define X86_RET_UNUSED15 15 + +#define X86_RET_TYPE_MASK 15 +#define X86_RET_POP_SHIFT 4 + +#define R_EAX 0 +#define R_EDX 1 +#define R_ECX 2 + +#ifdef __PCC__ +# define HAVE_FASTCALL 0 +#else +# define HAVE_FASTCALL 1 +#endif diff --git a/native/libffi/src/x86/internal64.h b/native/libffi/src/x86/internal64.h new file mode 100644 index 0000000000..512e95523e --- /dev/null +++ b/native/libffi/src/x86/internal64.h @@ -0,0 +1,22 @@ +#define UNIX64_RET_VOID 0 +#define UNIX64_RET_UINT8 1 +#define UNIX64_RET_UINT16 2 +#define UNIX64_RET_UINT32 3 +#define UNIX64_RET_SINT8 4 +#define UNIX64_RET_SINT16 5 +#define UNIX64_RET_SINT32 6 +#define UNIX64_RET_INT64 7 +#define UNIX64_RET_XMM32 8 +#define UNIX64_RET_XMM64 9 +#define UNIX64_RET_X87 10 +#define UNIX64_RET_X87_2 11 +#define UNIX64_RET_ST_XMM0_RAX 12 +#define UNIX64_RET_ST_RAX_XMM0 13 +#define UNIX64_RET_ST_XMM0_XMM1 14 +#define UNIX64_RET_ST_RAX_RDX 15 + +#define UNIX64_RET_LAST 15 + +#define UNIX64_FLAG_RET_IN_MEM (1 << 10) +#define UNIX64_FLAG_XMM_ARGS (1 << 11) +#define UNIX64_SIZE_SHIFT 12 diff --git a/native/libffi/src/x86/sysv.S b/native/libffi/src/x86/sysv.S index 3bd5477e47..d8ab4b0264 100644 --- a/native/libffi/src/x86/sysv.S +++ b/native/libffi/src/x86/sysv.S @@ -1,6 +1,7 @@ /* ----------------------------------------------------------------------- - sysv.S - Copyright (c) 2013 The Written Word, Inc. - - Copyright (c) 1996,1998,2001-2003,2005,2008,2010 Red Hat, Inc. + sysv.S - Copyright (c) 2017 Anthony Green + - Copyright (c) 2013 The Written Word, Inc. + - Copyright (c) 1996,1998,2001-2003,2005,2008,2010 Red Hat, Inc. X86 Foreign Function Interface @@ -25,458 +26,1112 @@ DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------------- */ -#ifndef __x86_64__ +#ifdef __i386__ +#ifndef _MSC_VER #define LIBFFI_ASM #include #include +#include "internal.h" -.text - -.globl ffi_prep_args - - .align 4 -.globl ffi_call_SYSV - .type ffi_call_SYSV,@function - -ffi_call_SYSV: -.LFB1: - pushl %ebp -.LCFI0: - movl %esp,%ebp -.LCFI1: - /* Make room for all of the new args. */ - movl 16(%ebp),%ecx - subl %ecx,%esp - - /* Align the stack pointer to 16-bytes */ - andl $0xfffffff0, %esp - - movl %esp,%eax - - /* Place all of the ffi_prep_args in position */ - pushl 12(%ebp) - pushl %eax - call *8(%ebp) - - /* Return stack to previous state and call the function */ - addl $8,%esp - - call *28(%ebp) - - /* Load %ecx with the return type code */ - movl 20(%ebp),%ecx - - /* Protect %esi. We're going to pop it in the epilogue. */ - pushl %esi - - /* If the return value pointer is NULL, assume no return value. */ - cmpl $0,24(%ebp) - jne 0f - - /* Even if there is no space for the return value, we are - obliged to handle floating-point values. */ - cmpl $FFI_TYPE_FLOAT,%ecx - jne noretval - fstp %st(0) - - jmp epilogue - -0: - call 1f - -.Lstore_table: - .long noretval-.Lstore_table /* FFI_TYPE_VOID */ - .long retint-.Lstore_table /* FFI_TYPE_INT */ - .long retfloat-.Lstore_table /* FFI_TYPE_FLOAT */ - .long retdouble-.Lstore_table /* FFI_TYPE_DOUBLE */ - .long retlongdouble-.Lstore_table /* FFI_TYPE_LONGDOUBLE */ - .long retuint8-.Lstore_table /* FFI_TYPE_UINT8 */ - .long retsint8-.Lstore_table /* FFI_TYPE_SINT8 */ - .long retuint16-.Lstore_table /* FFI_TYPE_UINT16 */ - .long retsint16-.Lstore_table /* FFI_TYPE_SINT16 */ - .long retint-.Lstore_table /* FFI_TYPE_UINT32 */ - .long retint-.Lstore_table /* FFI_TYPE_SINT32 */ - .long retint64-.Lstore_table /* FFI_TYPE_UINT64 */ - .long retint64-.Lstore_table /* FFI_TYPE_SINT64 */ - .long retstruct-.Lstore_table /* FFI_TYPE_STRUCT */ - .long retint-.Lstore_table /* FFI_TYPE_POINTER */ - -1: - pop %esi - add (%esi, %ecx, 4), %esi - jmp *%esi - - /* Sign/zero extend as appropriate. */ -retsint8: - movsbl %al, %eax - jmp retint +#define C2(X, Y) X ## Y +#define C1(X, Y) C2(X, Y) +#ifdef __USER_LABEL_PREFIX__ +# define C(X) C1(__USER_LABEL_PREFIX__, X) +#else +# define C(X) X +#endif -retsint16: - movswl %ax, %eax - jmp retint +#ifdef X86_DARWIN +# define L(X) C1(L, X) +#else +# define L(X) C1(.L, X) +#endif -retuint8: - movzbl %al, %eax - jmp retint +#ifdef __ELF__ +# define ENDF(X) .type X,@function; .size X, . - X +#else +# define ENDF(X) +#endif -retuint16: - movzwl %ax, %eax - jmp retint - -retfloat: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - fstps (%ecx) - jmp epilogue - -retdouble: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - fstpl (%ecx) - jmp epilogue - -retlongdouble: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - fstpt (%ecx) - jmp epilogue - -retint64: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - movl %eax,0(%ecx) - movl %edx,4(%ecx) - jmp epilogue - -retint: - /* Load %ecx with the pointer to storage for the return value */ - movl 24(%ebp),%ecx - movl %eax,0(%ecx) - -retstruct: - /* Nothing to do! */ - -noretval: -epilogue: - popl %esi - movl %ebp,%esp - popl %ebp - ret -.LFE1: -.ffi_call_SYSV_end: - .size ffi_call_SYSV,.ffi_call_SYSV_end-ffi_call_SYSV - - .align 4 -FFI_HIDDEN (ffi_closure_SYSV) -.globl ffi_closure_SYSV - .type ffi_closure_SYSV, @function - -ffi_closure_SYSV: -.LFB2: - pushl %ebp -.LCFI2: - movl %esp, %ebp -.LCFI3: - subl $40, %esp - leal -24(%ebp), %edx - movl %edx, -12(%ebp) /* resp */ - leal 8(%ebp), %edx -#ifdef __SUNPRO_C - /* The SUNPRO compiler doesn't support GCC's regparm function - attribute, so we have to pass all three arguments to - ffi_closure_SYSV_inner on the stack. */ - movl %edx, 8(%esp) /* args = __builtin_dwarf_cfa () */ - leal -12(%ebp), %edx - movl %edx, 4(%esp) /* &resp */ - movl %eax, (%esp) /* closure */ +/* Handle win32 fastcall name mangling. */ +#ifdef X86_WIN32 +# define ffi_call_i386 "@ffi_call_i386@8" +# define ffi_closure_inner "@ffi_closure_inner@8" #else - movl %edx, 4(%esp) /* args = __builtin_dwarf_cfa () */ - leal -12(%ebp), %edx - movl %edx, (%esp) /* &resp */ +# define ffi_call_i386 C(ffi_call_i386) +# define ffi_closure_inner C(ffi_closure_inner) #endif -#if defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE || !defined __PIC__ - call ffi_closure_SYSV_inner + +/* This macro allows the safe creation of jump tables without an + actual table. The entry points into the table are all 8 bytes. + The use of ORG asserts that we're at the correct location. */ +/* ??? The clang assembler doesn't handle .org with symbolic expressions. */ +#if defined(__clang__) || defined(__APPLE__) || (defined (__sun__) && defined(__svr4__)) +# define E(BASE, X) .balign 8 #else - movl %ebx, 8(%esp) -.LCFI7: - call 1f -1: popl %ebx - addl $_GLOBAL_OFFSET_TABLE_+[.-1b], %ebx - call ffi_closure_SYSV_inner@PLT - movl 8(%esp), %ebx +# define E(BASE, X) .balign 8; .org BASE + X * 8 #endif - movl -12(%ebp), %ecx - cmpl $FFI_TYPE_INT, %eax - je .Lcls_retint - - /* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16, - FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32. */ - cmpl $FFI_TYPE_UINT64, %eax - jge 0f - cmpl $FFI_TYPE_UINT8, %eax - jge .Lcls_retint - -0: cmpl $FFI_TYPE_FLOAT, %eax - je .Lcls_retfloat - cmpl $FFI_TYPE_DOUBLE, %eax - je .Lcls_retdouble - cmpl $FFI_TYPE_LONGDOUBLE, %eax - je .Lcls_retldouble - cmpl $FFI_TYPE_SINT64, %eax - je .Lcls_retllong - cmpl $FFI_TYPE_STRUCT, %eax - je .Lcls_retstruct -.Lcls_epilogue: - movl %ebp, %esp - popl %ebp - ret -.Lcls_retint: - movl (%ecx), %eax - jmp .Lcls_epilogue -.Lcls_retfloat: - flds (%ecx) - jmp .Lcls_epilogue -.Lcls_retdouble: - fldl (%ecx) - jmp .Lcls_epilogue -.Lcls_retldouble: - fldt (%ecx) - jmp .Lcls_epilogue -.Lcls_retllong: - movl (%ecx), %eax - movl 4(%ecx), %edx - jmp .Lcls_epilogue -.Lcls_retstruct: - movl %ebp, %esp - popl %ebp - ret $4 -.LFE2: - .size ffi_closure_SYSV, .-ffi_closure_SYSV -#if !FFI_NO_RAW_API + .text + .balign 16 + .globl ffi_call_i386 + FFI_HIDDEN(ffi_call_i386) + +/* This is declared as -/* Precalculate for e.g. the Solaris 10/x86 assembler. */ -#if FFI_TRAMPOLINE_SIZE == 10 -#define RAW_CLOSURE_CIF_OFFSET 12 -#define RAW_CLOSURE_FUN_OFFSET 16 -#define RAW_CLOSURE_USER_DATA_OFFSET 20 -#elif FFI_TRAMPOLINE_SIZE == 24 -#define RAW_CLOSURE_CIF_OFFSET 24 -#define RAW_CLOSURE_FUN_OFFSET 28 -#define RAW_CLOSURE_USER_DATA_OFFSET 32 + void ffi_call_i386(struct call_frame *frame, char *argp) + __attribute__((fastcall)); + + Thus the arguments are present in + + ecx: frame + edx: argp +*/ + +ffi_call_i386: +L(UW0): + # cfi_startproc + _CET_ENDBR +#if !HAVE_FASTCALL + movl 4(%esp), %ecx + movl 8(%esp), %edx +#endif + movl (%esp), %eax /* move the return address */ + movl %ebp, (%ecx) /* store %ebp into local frame */ + movl %eax, 4(%ecx) /* store retaddr into local frame */ + + /* New stack frame based off ebp. This is a itty bit of unwind + trickery in that the CFA *has* changed. There is no easy way + to describe it correctly on entry to the function. Fortunately, + it doesn't matter too much since at all points we can correctly + unwind back to ffi_call. Note that the location to which we + moved the return address is (the new) CFA-4, so from the + perspective of the unwind info, it hasn't moved. */ + movl %ecx, %ebp +L(UW1): + # cfi_def_cfa(%ebp, 8) + # cfi_rel_offset(%ebp, 0) + + movl %edx, %esp /* set outgoing argument stack */ + movl 20+R_EAX*4(%ebp), %eax /* set register arguments */ + movl 20+R_EDX*4(%ebp), %edx + movl 20+R_ECX*4(%ebp), %ecx + + call *8(%ebp) + + movl 12(%ebp), %ecx /* load return type code */ + movl %ebx, 8(%ebp) /* preserve %ebx */ +L(UW2): + # cfi_rel_offset(%ebx, 8) + + andl $X86_RET_TYPE_MASK, %ecx +#ifdef __PIC__ + call C(__x86.get_pc_thunk.bx) +L(pc1): + leal L(store_table)-L(pc1)(%ebx, %ecx, 8), %ebx #else -#define RAW_CLOSURE_CIF_OFFSET ((FFI_TRAMPOLINE_SIZE + 3) & ~3) -#define RAW_CLOSURE_FUN_OFFSET (RAW_CLOSURE_CIF_OFFSET + 4) -#define RAW_CLOSURE_USER_DATA_OFFSET (RAW_CLOSURE_FUN_OFFSET + 4) + leal L(store_table)(,%ecx, 8), %ebx #endif -#define CIF_FLAGS_OFFSET 20 - - .align 4 -FFI_HIDDEN (ffi_closure_raw_SYSV) -.globl ffi_closure_raw_SYSV - .type ffi_closure_raw_SYSV, @function - -ffi_closure_raw_SYSV: -.LFB3: - pushl %ebp -.LCFI4: - movl %esp, %ebp -.LCFI5: - pushl %esi -.LCFI6: - subl $36, %esp - movl RAW_CLOSURE_CIF_OFFSET(%eax), %esi /* closure->cif */ - movl RAW_CLOSURE_USER_DATA_OFFSET(%eax), %edx /* closure->user_data */ - movl %edx, 12(%esp) /* user_data */ - leal 8(%ebp), %edx /* __builtin_dwarf_cfa () */ - movl %edx, 8(%esp) /* raw_args */ - leal -24(%ebp), %edx - movl %edx, 4(%esp) /* &res */ - movl %esi, (%esp) /* cif */ - call *RAW_CLOSURE_FUN_OFFSET(%eax) /* closure->fun */ - movl CIF_FLAGS_OFFSET(%esi), %eax /* rtype */ - cmpl $FFI_TYPE_INT, %eax - je .Lrcls_retint - - /* Handle FFI_TYPE_UINT8, FFI_TYPE_SINT8, FFI_TYPE_UINT16, - FFI_TYPE_SINT16, FFI_TYPE_UINT32, FFI_TYPE_SINT32. */ - cmpl $FFI_TYPE_UINT64, %eax - jge 0f - cmpl $FFI_TYPE_UINT8, %eax - jge .Lrcls_retint -0: - cmpl $FFI_TYPE_FLOAT, %eax - je .Lrcls_retfloat - cmpl $FFI_TYPE_DOUBLE, %eax - je .Lrcls_retdouble - cmpl $FFI_TYPE_LONGDOUBLE, %eax - je .Lrcls_retldouble - cmpl $FFI_TYPE_SINT64, %eax - je .Lrcls_retllong -.Lrcls_epilogue: - addl $36, %esp - popl %esi + movl 16(%ebp), %ecx /* load result address */ + _CET_NOTRACK jmp *%ebx + + .balign 8 +L(store_table): +E(L(store_table), X86_RET_FLOAT) + fstps (%ecx) + jmp L(e1) +E(L(store_table), X86_RET_DOUBLE) + fstpl (%ecx) + jmp L(e1) +E(L(store_table), X86_RET_LDOUBLE) + fstpt (%ecx) + jmp L(e1) +E(L(store_table), X86_RET_SINT8) + movsbl %al, %eax + mov %eax, (%ecx) + jmp L(e1) +E(L(store_table), X86_RET_SINT16) + movswl %ax, %eax + mov %eax, (%ecx) + jmp L(e1) +E(L(store_table), X86_RET_UINT8) + movzbl %al, %eax + mov %eax, (%ecx) + jmp L(e1) +E(L(store_table), X86_RET_UINT16) + movzwl %ax, %eax + mov %eax, (%ecx) + jmp L(e1) +E(L(store_table), X86_RET_INT64) + movl %edx, 4(%ecx) + /* fallthru */ +E(L(store_table), X86_RET_INT32) + movl %eax, (%ecx) + /* fallthru */ +E(L(store_table), X86_RET_VOID) +L(e1): + movl 8(%ebp), %ebx + movl %ebp, %esp popl %ebp +L(UW3): + # cfi_remember_state + # cfi_def_cfa(%esp, 4) + # cfi_restore(%ebx) + # cfi_restore(%ebp) ret -.Lrcls_retint: - movl -24(%ebp), %eax - jmp .Lrcls_epilogue -.Lrcls_retfloat: - flds -24(%ebp) - jmp .Lrcls_epilogue -.Lrcls_retdouble: - fldl -24(%ebp) - jmp .Lrcls_epilogue -.Lrcls_retldouble: - fldt -24(%ebp) - jmp .Lrcls_epilogue -.Lrcls_retllong: - movl -24(%ebp), %eax - movl -20(%ebp), %edx - jmp .Lrcls_epilogue -.LFE3: - .size ffi_closure_raw_SYSV, .-ffi_closure_raw_SYSV +L(UW4): + # cfi_restore_state + +E(L(store_table), X86_RET_STRUCTPOP) + jmp L(e1) +E(L(store_table), X86_RET_STRUCTARG) + jmp L(e1) +E(L(store_table), X86_RET_STRUCT_1B) + movb %al, (%ecx) + jmp L(e1) +E(L(store_table), X86_RET_STRUCT_2B) + movw %ax, (%ecx) + jmp L(e1) + + /* Fill out the table so that bad values are predictable. */ +E(L(store_table), X86_RET_UNUSED14) + ud2 +E(L(store_table), X86_RET_UNUSED15) + ud2 + +L(UW5): + # cfi_endproc +ENDF(ffi_call_i386) + +/* The inner helper is declared as + + void ffi_closure_inner(struct closure_frame *frame, char *argp) + __attribute_((fastcall)) + + Thus the arguments are placed in + + ecx: frame + edx: argp +*/ + +/* Macros to help setting up the closure_data structure. */ + +#if HAVE_FASTCALL +# define closure_FS (40 + 4) +# define closure_CF 0 +#else +# define closure_FS (8 + 40 + 12) +# define closure_CF 8 #endif -#if defined __GNUC__ -/* Only emit dwarf unwind info when building with GNU toolchain. */ +#define FFI_CLOSURE_SAVE_REGS \ + movl %eax, closure_CF+16+R_EAX*4(%esp); \ + movl %edx, closure_CF+16+R_EDX*4(%esp); \ + movl %ecx, closure_CF+16+R_ECX*4(%esp) -#if defined __PIC__ -# if defined __sun__ && defined __svr4__ -/* 32-bit Solaris 2/x86 uses datarel encoding for PIC. GNU ld before 2.22 - doesn't correctly sort .eh_frame_hdr with mixed encodings, so match this. */ -# define FDE_ENCODING 0x30 /* datarel */ -# define FDE_ENCODE(X) X@GOTOFF -# else -# define FDE_ENCODING 0x1b /* pcrel sdata4 */ -# if defined HAVE_AS_X86_PCREL -# define FDE_ENCODE(X) X-. -# else -# define FDE_ENCODE(X) X@rel -# endif -# endif +#define FFI_CLOSURE_COPY_TRAMP_DATA \ + movl FFI_TRAMPOLINE_SIZE(%eax), %edx; /* copy cif */ \ + movl FFI_TRAMPOLINE_SIZE+4(%eax), %ecx; /* copy fun */ \ + movl FFI_TRAMPOLINE_SIZE+8(%eax), %eax; /* copy user_data */ \ + movl %edx, closure_CF+28(%esp); \ + movl %ecx, closure_CF+32(%esp); \ + movl %eax, closure_CF+36(%esp) + +#if HAVE_FASTCALL +# define FFI_CLOSURE_PREP_CALL \ + movl %esp, %ecx; /* load closure_data */ \ + leal closure_FS+4(%esp), %edx; /* load incoming stack */ #else -# define FDE_ENCODING 0 /* absolute */ -# define FDE_ENCODE(X) X +# define FFI_CLOSURE_PREP_CALL \ + leal closure_CF(%esp), %ecx; /* load closure_data */ \ + leal closure_FS+4(%esp), %edx; /* load incoming stack */ \ + movl %ecx, (%esp); \ + movl %edx, 4(%esp) #endif - .section .eh_frame,EH_FRAME_FLAGS,@progbits -.Lframe1: - .long .LECIE1-.LSCIE1 /* Length of Common Information Entry */ -.LSCIE1: - .long 0x0 /* CIE Identifier Tag */ - .byte 0x1 /* CIE Version */ -#ifdef HAVE_AS_ASCII_PSEUDO_OP +#define FFI_CLOSURE_CALL_INNER(UWN) \ + call ffi_closure_inner + +#define FFI_CLOSURE_MASK_AND_JUMP(N, UW) \ + andl $X86_RET_TYPE_MASK, %eax; \ + leal L(C1(load_table,N))(, %eax, 8), %edx; \ + movl closure_CF(%esp), %eax; /* optimiztic load */ \ + _CET_NOTRACK jmp *%edx + #ifdef __PIC__ - .ascii "zR\0" /* CIE Augmentation */ +# if defined X86_DARWIN || defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE +# undef FFI_CLOSURE_MASK_AND_JUMP +# define FFI_CLOSURE_MASK_AND_JUMP(N, UW) \ + andl $X86_RET_TYPE_MASK, %eax; \ + call C(__x86.get_pc_thunk.dx); \ +L(C1(pc,N)): \ + leal L(C1(load_table,N))-L(C1(pc,N))(%edx, %eax, 8), %edx; \ + movl closure_CF(%esp), %eax; /* optimiztic load */ \ + _CET_NOTRACK jmp *%edx +# else +# define FFI_CLOSURE_CALL_INNER_SAVE_EBX +# undef FFI_CLOSURE_CALL_INNER +# define FFI_CLOSURE_CALL_INNER(UWN) \ + movl %ebx, 40(%esp); /* save ebx */ \ +L(C1(UW,UWN)): \ + /* cfi_rel_offset(%ebx, 40); */ \ + call C(__x86.get_pc_thunk.bx); /* load got register */ \ + addl $C(_GLOBAL_OFFSET_TABLE_), %ebx; \ + call ffi_closure_inner@PLT +# undef FFI_CLOSURE_MASK_AND_JUMP +# define FFI_CLOSURE_MASK_AND_JUMP(N, UWN) \ + andl $X86_RET_TYPE_MASK, %eax; \ + leal L(C1(load_table,N))@GOTOFF(%ebx, %eax, 8), %edx; \ + movl 40(%esp), %ebx; /* restore ebx */ \ +L(C1(UW,UWN)): \ + /* cfi_restore(%ebx); */ \ + movl closure_CF(%esp), %eax; /* optimiztic load */ \ + _CET_NOTRACK jmp *%edx +# endif /* DARWIN || HIDDEN */ +#endif /* __PIC__ */ + + .balign 16 + .globl C(ffi_go_closure_EAX) + FFI_HIDDEN(C(ffi_go_closure_EAX)) +C(ffi_go_closure_EAX): +L(UW6): + # cfi_startproc + _CET_ENDBR + subl $closure_FS, %esp +L(UW7): + # cfi_def_cfa_offset(closure_FS + 4) + FFI_CLOSURE_SAVE_REGS + movl 4(%eax), %edx /* copy cif */ + movl 8(%eax), %ecx /* copy fun */ + movl %edx, closure_CF+28(%esp) + movl %ecx, closure_CF+32(%esp) + movl %eax, closure_CF+36(%esp) /* closure is user_data */ + jmp L(do_closure_i386) +L(UW8): + # cfi_endproc +ENDF(C(ffi_go_closure_EAX)) + + .balign 16 + .globl C(ffi_go_closure_ECX) + FFI_HIDDEN(C(ffi_go_closure_ECX)) +C(ffi_go_closure_ECX): +L(UW9): + # cfi_startproc + _CET_ENDBR + subl $closure_FS, %esp +L(UW10): + # cfi_def_cfa_offset(closure_FS + 4) + FFI_CLOSURE_SAVE_REGS + movl 4(%ecx), %edx /* copy cif */ + movl 8(%ecx), %eax /* copy fun */ + movl %edx, closure_CF+28(%esp) + movl %eax, closure_CF+32(%esp) + movl %ecx, closure_CF+36(%esp) /* closure is user_data */ + jmp L(do_closure_i386) +L(UW11): + # cfi_endproc +ENDF(C(ffi_go_closure_ECX)) + +/* The closure entry points are reached from the ffi_closure trampoline. + On entry, %eax contains the address of the ffi_closure. */ + + .balign 16 + .globl C(ffi_closure_i386) + FFI_HIDDEN(C(ffi_closure_i386)) + +C(ffi_closure_i386): +L(UW12): + # cfi_startproc + _CET_ENDBR + subl $closure_FS, %esp +L(UW13): + # cfi_def_cfa_offset(closure_FS + 4) + + FFI_CLOSURE_SAVE_REGS + FFI_CLOSURE_COPY_TRAMP_DATA + + /* Entry point from preceeding Go closures. */ +L(do_closure_i386): + + FFI_CLOSURE_PREP_CALL + FFI_CLOSURE_CALL_INNER(14) + FFI_CLOSURE_MASK_AND_JUMP(2, 15) + + .balign 8 +L(load_table2): +E(L(load_table2), X86_RET_FLOAT) + flds closure_CF(%esp) + jmp L(e2) +E(L(load_table2), X86_RET_DOUBLE) + fldl closure_CF(%esp) + jmp L(e2) +E(L(load_table2), X86_RET_LDOUBLE) + fldt closure_CF(%esp) + jmp L(e2) +E(L(load_table2), X86_RET_SINT8) + movsbl %al, %eax + jmp L(e2) +E(L(load_table2), X86_RET_SINT16) + movswl %ax, %eax + jmp L(e2) +E(L(load_table2), X86_RET_UINT8) + movzbl %al, %eax + jmp L(e2) +E(L(load_table2), X86_RET_UINT16) + movzwl %ax, %eax + jmp L(e2) +E(L(load_table2), X86_RET_INT64) + movl closure_CF+4(%esp), %edx + jmp L(e2) +E(L(load_table2), X86_RET_INT32) + nop + /* fallthru */ +E(L(load_table2), X86_RET_VOID) +L(e2): + addl $closure_FS, %esp +L(UW16): + # cfi_adjust_cfa_offset(-closure_FS) + ret +L(UW17): + # cfi_adjust_cfa_offset(closure_FS) +E(L(load_table2), X86_RET_STRUCTPOP) + addl $closure_FS, %esp +L(UW18): + # cfi_adjust_cfa_offset(-closure_FS) + ret $4 +L(UW19): + # cfi_adjust_cfa_offset(closure_FS) +E(L(load_table2), X86_RET_STRUCTARG) + jmp L(e2) +E(L(load_table2), X86_RET_STRUCT_1B) + movzbl %al, %eax + jmp L(e2) +E(L(load_table2), X86_RET_STRUCT_2B) + movzwl %ax, %eax + jmp L(e2) + + /* Fill out the table so that bad values are predictable. */ +E(L(load_table2), X86_RET_UNUSED14) + ud2 +E(L(load_table2), X86_RET_UNUSED15) + ud2 + +L(UW20): + # cfi_endproc +ENDF(C(ffi_closure_i386)) + + .balign 16 + .globl C(ffi_go_closure_STDCALL) + FFI_HIDDEN(C(ffi_go_closure_STDCALL)) +C(ffi_go_closure_STDCALL): +L(UW21): + # cfi_startproc + _CET_ENDBR + subl $closure_FS, %esp +L(UW22): + # cfi_def_cfa_offset(closure_FS + 4) + FFI_CLOSURE_SAVE_REGS + movl 4(%ecx), %edx /* copy cif */ + movl 8(%ecx), %eax /* copy fun */ + movl %edx, closure_CF+28(%esp) + movl %eax, closure_CF+32(%esp) + movl %ecx, closure_CF+36(%esp) /* closure is user_data */ + jmp L(do_closure_STDCALL) +L(UW23): + # cfi_endproc +ENDF(C(ffi_go_closure_STDCALL)) + +/* For REGISTER, we have no available parameter registers, and so we + enter here having pushed the closure onto the stack. */ + + .balign 16 + .globl C(ffi_closure_REGISTER) + FFI_HIDDEN(C(ffi_closure_REGISTER)) +C(ffi_closure_REGISTER): +L(UW24): + # cfi_startproc + # cfi_def_cfa(%esp, 8) + # cfi_offset(%eip, -8) + _CET_ENDBR + subl $closure_FS-4, %esp +L(UW25): + # cfi_def_cfa_offset(closure_FS + 4) + FFI_CLOSURE_SAVE_REGS + 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 +ENDF(C(ffi_closure_REGISTER)) + +/* For STDCALL (and others), we need to pop N bytes of arguments off + the stack following the closure. The amount needing to be popped + is returned to us from ffi_closure_inner. */ + + .balign 16 + .globl C(ffi_closure_STDCALL) + FFI_HIDDEN(C(ffi_closure_STDCALL)) +C(ffi_closure_STDCALL): +L(UW27): + # cfi_startproc + _CET_ENDBR + subl $closure_FS, %esp +L(UW28): + # cfi_def_cfa_offset(closure_FS + 4) + + FFI_CLOSURE_SAVE_REGS + + /* Entry point from ffi_closure_REGISTER. */ +L(do_closure_REGISTER): + + FFI_CLOSURE_COPY_TRAMP_DATA + + /* Entry point from preceeding Go closure. */ +L(do_closure_STDCALL): + + FFI_CLOSURE_PREP_CALL + FFI_CLOSURE_CALL_INNER(29) + + movl %eax, %ecx + shrl $X86_RET_POP_SHIFT, %ecx /* isolate pop count */ + leal closure_FS(%esp, %ecx), %ecx /* compute popped esp */ + movl closure_FS(%esp), %edx /* move return address */ + movl %edx, (%ecx) + + /* From this point on, the value of %esp upon return is %ecx+4, + and we've copied the return address to %ecx to make return easy. + There's no point in representing this in the unwind info, as + there is always a window between the mov and the ret which + will be wrong from one point of view or another. */ + + FFI_CLOSURE_MASK_AND_JUMP(3, 30) + + .balign 8 +L(load_table3): +E(L(load_table3), X86_RET_FLOAT) + flds closure_CF(%esp) + movl %ecx, %esp + ret +E(L(load_table3), X86_RET_DOUBLE) + fldl closure_CF(%esp) + movl %ecx, %esp + ret +E(L(load_table3), X86_RET_LDOUBLE) + fldt closure_CF(%esp) + movl %ecx, %esp + ret +E(L(load_table3), X86_RET_SINT8) + movsbl %al, %eax + movl %ecx, %esp + ret +E(L(load_table3), X86_RET_SINT16) + movswl %ax, %eax + movl %ecx, %esp + ret +E(L(load_table3), X86_RET_UINT8) + movzbl %al, %eax + movl %ecx, %esp + ret +E(L(load_table3), X86_RET_UINT16) + movzwl %ax, %eax + movl %ecx, %esp + ret +E(L(load_table3), X86_RET_INT64) + movl closure_CF+4(%esp), %edx + movl %ecx, %esp + ret +E(L(load_table3), X86_RET_INT32) + movl %ecx, %esp + ret +E(L(load_table3), X86_RET_VOID) + movl %ecx, %esp + ret +E(L(load_table3), X86_RET_STRUCTPOP) + movl %ecx, %esp + ret +E(L(load_table3), X86_RET_STRUCTARG) + movl %ecx, %esp + ret +E(L(load_table3), X86_RET_STRUCT_1B) + movzbl %al, %eax + movl %ecx, %esp + ret +E(L(load_table3), X86_RET_STRUCT_2B) + movzwl %ax, %eax + movl %ecx, %esp + ret + + /* Fill out the table so that bad values are predictable. */ +E(L(load_table3), X86_RET_UNUSED14) + ud2 +E(L(load_table3), X86_RET_UNUSED15) + ud2 + +L(UW31): + # cfi_endproc +ENDF(C(ffi_closure_STDCALL)) + +#if !FFI_NO_RAW_API + +#define raw_closure_S_FS (16+16+12) + + .balign 16 + .globl C(ffi_closure_raw_SYSV) + FFI_HIDDEN(C(ffi_closure_raw_SYSV)) +C(ffi_closure_raw_SYSV): +L(UW32): + # cfi_startproc + _CET_ENDBR + subl $raw_closure_S_FS, %esp +L(UW33): + # cfi_def_cfa_offset(raw_closure_S_FS + 4) + movl %ebx, raw_closure_S_FS-4(%esp) +L(UW34): + # cfi_rel_offset(%ebx, raw_closure_S_FS-4) + + movl FFI_TRAMPOLINE_SIZE+8(%eax), %edx /* load cl->user_data */ + movl %edx, 12(%esp) + leal raw_closure_S_FS+4(%esp), %edx /* load raw_args */ + movl %edx, 8(%esp) + leal 16(%esp), %edx /* load &res */ + movl %edx, 4(%esp) + movl FFI_TRAMPOLINE_SIZE(%eax), %ebx /* load cl->cif */ + movl %ebx, (%esp) + call *FFI_TRAMPOLINE_SIZE+4(%eax) /* call cl->fun */ + + movl 20(%ebx), %eax /* load cif->flags */ + andl $X86_RET_TYPE_MASK, %eax +#ifdef __PIC__ + call C(__x86.get_pc_thunk.bx) +L(pc4): + leal L(load_table4)-L(pc4)(%ebx, %eax, 8), %ecx #else - .ascii "\0" /* CIE Augmentation */ + leal L(load_table4)(,%eax, 8), %ecx #endif -#elif defined HAVE_AS_STRING_PSEUDO_OP + movl raw_closure_S_FS-4(%esp), %ebx +L(UW35): + # cfi_restore(%ebx) + movl 16(%esp), %eax /* Optimistic load */ + jmp *%ecx + + .balign 8 +L(load_table4): +E(L(load_table4), X86_RET_FLOAT) + flds 16(%esp) + jmp L(e4) +E(L(load_table4), X86_RET_DOUBLE) + fldl 16(%esp) + jmp L(e4) +E(L(load_table4), X86_RET_LDOUBLE) + fldt 16(%esp) + jmp L(e4) +E(L(load_table4), X86_RET_SINT8) + movsbl %al, %eax + jmp L(e4) +E(L(load_table4), X86_RET_SINT16) + movswl %ax, %eax + jmp L(e4) +E(L(load_table4), X86_RET_UINT8) + movzbl %al, %eax + jmp L(e4) +E(L(load_table4), X86_RET_UINT16) + movzwl %ax, %eax + jmp L(e4) +E(L(load_table4), X86_RET_INT64) + movl 16+4(%esp), %edx + jmp L(e4) +E(L(load_table4), X86_RET_INT32) + nop + /* fallthru */ +E(L(load_table4), X86_RET_VOID) +L(e4): + addl $raw_closure_S_FS, %esp +L(UW36): + # cfi_adjust_cfa_offset(-raw_closure_S_FS) + ret +L(UW37): + # cfi_adjust_cfa_offset(raw_closure_S_FS) +E(L(load_table4), X86_RET_STRUCTPOP) + addl $raw_closure_S_FS, %esp +L(UW38): + # cfi_adjust_cfa_offset(-raw_closure_S_FS) + ret $4 +L(UW39): + # cfi_adjust_cfa_offset(raw_closure_S_FS) +E(L(load_table4), X86_RET_STRUCTARG) + jmp L(e4) +E(L(load_table4), X86_RET_STRUCT_1B) + movzbl %al, %eax + jmp L(e4) +E(L(load_table4), X86_RET_STRUCT_2B) + movzwl %ax, %eax + jmp L(e4) + + /* Fill out the table so that bad values are predictable. */ +E(L(load_table4), X86_RET_UNUSED14) + ud2 +E(L(load_table4), X86_RET_UNUSED15) + ud2 + +L(UW40): + # cfi_endproc +ENDF(C(ffi_closure_raw_SYSV)) + +#define raw_closure_T_FS (16+16+8) + + .balign 16 + .globl C(ffi_closure_raw_THISCALL) + FFI_HIDDEN(C(ffi_closure_raw_THISCALL)) +C(ffi_closure_raw_THISCALL): +L(UW41): + # cfi_startproc + _CET_ENDBR + /* Rearrange the stack such that %ecx is the first argument. + This means moving the return address. */ + popl %edx +L(UW42): + # cfi_def_cfa_offset(0) + # cfi_register(%eip, %edx) + pushl %ecx +L(UW43): + # cfi_adjust_cfa_offset(4) + pushl %edx +L(UW44): + # cfi_adjust_cfa_offset(4) + # cfi_rel_offset(%eip, 0) + subl $raw_closure_T_FS, %esp +L(UW45): + # cfi_adjust_cfa_offset(raw_closure_T_FS) + movl %ebx, raw_closure_T_FS-4(%esp) +L(UW46): + # cfi_rel_offset(%ebx, raw_closure_T_FS-4) + + movl FFI_TRAMPOLINE_SIZE+8(%eax), %edx /* load cl->user_data */ + movl %edx, 12(%esp) + leal raw_closure_T_FS+4(%esp), %edx /* load raw_args */ + movl %edx, 8(%esp) + leal 16(%esp), %edx /* load &res */ + movl %edx, 4(%esp) + movl FFI_TRAMPOLINE_SIZE(%eax), %ebx /* load cl->cif */ + movl %ebx, (%esp) + call *FFI_TRAMPOLINE_SIZE+4(%eax) /* call cl->fun */ + + movl 20(%ebx), %eax /* load cif->flags */ + andl $X86_RET_TYPE_MASK, %eax #ifdef __PIC__ - .string "zR" /* CIE Augmentation */ + call C(__x86.get_pc_thunk.bx) +L(pc5): + leal L(load_table5)-L(pc5)(%ebx, %eax, 8), %ecx #else - .string "" /* CIE Augmentation */ + leal L(load_table5)(,%eax, 8), %ecx #endif + movl raw_closure_T_FS-4(%esp), %ebx +L(UW47): + # cfi_restore(%ebx) + movl 16(%esp), %eax /* Optimistic load */ + jmp *%ecx + + .balign 8 +L(load_table5): +E(L(load_table5), X86_RET_FLOAT) + flds 16(%esp) + jmp L(e5) +E(L(load_table5), X86_RET_DOUBLE) + fldl 16(%esp) + jmp L(e5) +E(L(load_table5), X86_RET_LDOUBLE) + fldt 16(%esp) + jmp L(e5) +E(L(load_table5), X86_RET_SINT8) + movsbl %al, %eax + jmp L(e5) +E(L(load_table5), X86_RET_SINT16) + movswl %ax, %eax + jmp L(e5) +E(L(load_table5), X86_RET_UINT8) + movzbl %al, %eax + jmp L(e5) +E(L(load_table5), X86_RET_UINT16) + movzwl %ax, %eax + jmp L(e5) +E(L(load_table5), X86_RET_INT64) + movl 16+4(%esp), %edx + jmp L(e5) +E(L(load_table5), X86_RET_INT32) + nop + /* fallthru */ +E(L(load_table5), X86_RET_VOID) +L(e5): + addl $raw_closure_T_FS, %esp +L(UW48): + # cfi_adjust_cfa_offset(-raw_closure_T_FS) + /* Remove the extra %ecx argument we pushed. */ + ret $4 +L(UW49): + # cfi_adjust_cfa_offset(raw_closure_T_FS) +E(L(load_table5), X86_RET_STRUCTPOP) + addl $raw_closure_T_FS, %esp +L(UW50): + # cfi_adjust_cfa_offset(-raw_closure_T_FS) + ret $8 +L(UW51): + # cfi_adjust_cfa_offset(raw_closure_T_FS) +E(L(load_table5), X86_RET_STRUCTARG) + jmp L(e5) +E(L(load_table5), X86_RET_STRUCT_1B) + movzbl %al, %eax + jmp L(e5) +E(L(load_table5), X86_RET_STRUCT_2B) + movzwl %ax, %eax + jmp L(e5) + + /* Fill out the table so that bad values are predictable. */ +E(L(load_table5), X86_RET_UNUSED14) + ud2 +E(L(load_table5), X86_RET_UNUSED15) + ud2 + +L(UW52): + # cfi_endproc +ENDF(C(ffi_closure_raw_THISCALL)) + +#endif /* !FFI_NO_RAW_API */ + +#ifdef X86_DARWIN +# define COMDAT(X) \ + .section __TEXT,__text,coalesced,pure_instructions; \ + .weak_definition X; \ + FFI_HIDDEN(X) +#elif defined __ELF__ && !(defined(__sun__) && defined(__svr4__)) +# define COMDAT(X) \ + .section .text.X,"axG",@progbits,X,comdat; \ + .globl X; \ + FFI_HIDDEN(X) #else -#error missing .ascii/.string +# define COMDAT(X) #endif - .byte 0x1 /* .uleb128 0x1; CIE Code Alignment Factor */ - .byte 0x7c /* .sleb128 -4; CIE Data Alignment Factor */ - .byte 0x8 /* CIE RA Column */ -#ifdef __PIC__ - .byte 0x1 /* .uleb128 0x1; Augmentation size */ - .byte FDE_ENCODING + +#if defined(__PIC__) + COMDAT(C(__x86.get_pc_thunk.bx)) +C(__x86.get_pc_thunk.bx): + movl (%esp), %ebx + ret +ENDF(C(__x86.get_pc_thunk.bx)) +# if defined X86_DARWIN || defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE + COMDAT(C(__x86.get_pc_thunk.dx)) +C(__x86.get_pc_thunk.dx): + movl (%esp), %edx + ret +ENDF(C(__x86.get_pc_thunk.dx)) +#endif /* DARWIN || HIDDEN */ +#endif /* __PIC__ */ + +/* Sadly, OSX cctools-as doesn't understand .cfi directives at all. */ + +#ifdef __APPLE__ +.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support +EHFrame0: +#elif defined(X86_WIN32) +.section .eh_frame,"r" +#elif defined(HAVE_AS_X86_64_UNWIND_SECTION_TYPE) +.section .eh_frame,EH_FRAME_FLAGS,@unwind +#else +.section .eh_frame,EH_FRAME_FLAGS,@progbits #endif - .byte 0xc /* DW_CFA_def_cfa */ - .byte 0x4 /* .uleb128 0x4 */ - .byte 0x4 /* .uleb128 0x4 */ - .byte 0x88 /* DW_CFA_offset, column 0x8 */ - .byte 0x1 /* .uleb128 0x1 */ - .align 4 -.LECIE1: -.LSFDE1: - .long .LEFDE1-.LASFDE1 /* FDE Length */ -.LASFDE1: - .long .LASFDE1-.Lframe1 /* FDE CIE offset */ - .long FDE_ENCODE(.LFB1) /* FDE initial location */ - .long .LFE1-.LFB1 /* FDE address range */ -#ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ + +#ifdef HAVE_AS_X86_PCREL +# define PCREL(X) X - . +#else +# define PCREL(X) X@rel #endif - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI0-.LFB1 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x8 /* .uleb128 0x8 */ - .byte 0x85 /* DW_CFA_offset, column 0x5 */ - .byte 0x2 /* .uleb128 0x2 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI1-.LCFI0 - .byte 0xd /* DW_CFA_def_cfa_register */ - .byte 0x5 /* .uleb128 0x5 */ - .align 4 -.LEFDE1: -.LSFDE2: - .long .LEFDE2-.LASFDE2 /* FDE Length */ -.LASFDE2: - .long .LASFDE2-.Lframe1 /* FDE CIE offset */ - .long FDE_ENCODE(.LFB2) /* FDE initial location */ - .long .LFE2-.LFB2 /* FDE address range */ -#ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ + +/* Simplify advancing between labels. Assume DW_CFA_advance_loc1 fits. */ +#define ADV(N, P) .byte 2, L(N)-L(P) + + .balign 4 +L(CIE): + .set L(set0),L(ECIE)-L(SCIE) + .long L(set0) /* CIE Length */ +L(SCIE): + .long 0 /* CIE Identifier Tag */ + .byte 1 /* CIE Version */ + .ascii "zR\0" /* CIE Augmentation */ + .byte 1 /* CIE Code Alignment Factor */ + .byte 0x7c /* CIE Data Alignment Factor */ + .byte 0x8 /* CIE RA Column */ + .byte 1 /* Augmentation size */ + .byte 0x1b /* FDE Encoding (pcrel sdata4) */ + .byte 0xc, 4, 4 /* DW_CFA_def_cfa, %esp offset 4 */ + .byte 0x80+8, 1 /* DW_CFA_offset, %eip offset 1*-4 */ + .balign 4 +L(ECIE): + + .set L(set1),L(EFDE1)-L(SFDE1) + .long L(set1) /* FDE Length */ +L(SFDE1): + .long L(SFDE1)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW0)) /* Initial location */ + .long L(UW5)-L(UW0) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW1, UW0) + .byte 0xc, 5, 8 /* DW_CFA_def_cfa, %ebp 8 */ + .byte 0x80+5, 2 /* DW_CFA_offset, %ebp 2*-4 */ + ADV(UW2, UW1) + .byte 0x80+3, 0 /* DW_CFA_offset, %ebx 0*-4 */ + ADV(UW3, UW2) + .byte 0xa /* DW_CFA_remember_state */ + .byte 0xc, 4, 4 /* DW_CFA_def_cfa, %esp 4 */ + .byte 0xc0+3 /* DW_CFA_restore, %ebx */ + .byte 0xc0+5 /* DW_CFA_restore, %ebp */ + ADV(UW4, UW3) + .byte 0xb /* DW_CFA_restore_state */ + .balign 4 +L(EFDE1): + + .set L(set2),L(EFDE2)-L(SFDE2) + .long L(set2) /* FDE Length */ +L(SFDE2): + .long L(SFDE2)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW6)) /* Initial location */ + .long L(UW8)-L(UW6) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW7, UW6) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ + .balign 4 +L(EFDE2): + + .set L(set3),L(EFDE3)-L(SFDE3) + .long L(set3) /* FDE Length */ +L(SFDE3): + .long L(SFDE3)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW9)) /* Initial location */ + .long L(UW11)-L(UW9) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW10, UW9) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ + .balign 4 +L(EFDE3): + + .set L(set4),L(EFDE4)-L(SFDE4) + .long L(set4) /* FDE Length */ +L(SFDE4): + .long L(SFDE4)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW12)) /* Initial location */ + .long L(UW20)-L(UW12) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW13, UW12) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ +#ifdef FFI_CLOSURE_CALL_INNER_SAVE_EBX + ADV(UW14, UW13) + .byte 0x80+3, (40-(closure_FS+4))/-4 /* DW_CFA_offset %ebx */ + ADV(UW15, UW14) + .byte 0xc0+3 /* DW_CFA_restore %ebx */ + ADV(UW16, UW15) +#else + ADV(UW16, UW13) #endif - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI2-.LFB2 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x8 /* .uleb128 0x8 */ - .byte 0x85 /* DW_CFA_offset, column 0x5 */ - .byte 0x2 /* .uleb128 0x2 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI3-.LCFI2 - .byte 0xd /* DW_CFA_def_cfa_register */ - .byte 0x5 /* .uleb128 0x5 */ -#if !defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE && defined __PIC__ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI7-.LCFI3 - .byte 0x83 /* DW_CFA_offset, column 0x3 */ - .byte 0xa /* .uleb128 0xa */ + .byte 0xe, 4 /* DW_CFA_def_cfa_offset */ + ADV(UW17, UW16) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ + ADV(UW18, UW17) + .byte 0xe, 4 /* DW_CFA_def_cfa_offset */ + ADV(UW19, UW18) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ + .balign 4 +L(EFDE4): + + .set L(set5),L(EFDE5)-L(SFDE5) + .long L(set5) /* FDE Length */ +L(SFDE5): + .long L(SFDE5)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW21)) /* Initial location */ + .long L(UW23)-L(UW21) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW22, UW21) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ + .balign 4 +L(EFDE5): + + .set L(set6),L(EFDE6)-L(SFDE6) + .long L(set6) /* FDE Length */ +L(SFDE6): + .long L(SFDE6)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW24)) /* Initial location */ + .long L(UW26)-L(UW24) /* Address range */ + .byte 0 /* Augmentation size */ + .byte 0xe, 8 /* DW_CFA_def_cfa_offset */ + .byte 0x80+8, 2 /* DW_CFA_offset %eip, 2*-4 */ + ADV(UW25, UW24) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ + .balign 4 +L(EFDE6): + + .set L(set7),L(EFDE7)-L(SFDE7) + .long L(set7) /* FDE Length */ +L(SFDE7): + .long L(SFDE7)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW27)) /* Initial location */ + .long L(UW31)-L(UW27) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW28, UW27) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ +#ifdef FFI_CLOSURE_CALL_INNER_SAVE_EBX + ADV(UW29, UW28) + .byte 0x80+3, (40-(closure_FS+4))/-4 /* DW_CFA_offset %ebx */ + ADV(UW30, UW29) + .byte 0xc0+3 /* DW_CFA_restore %ebx */ #endif - .align 4 -.LEFDE2: + .balign 4 +L(EFDE7): #if !FFI_NO_RAW_API + .set L(set8),L(EFDE8)-L(SFDE8) + .long L(set8) /* FDE Length */ +L(SFDE8): + .long L(SFDE8)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW32)) /* Initial location */ + .long L(UW40)-L(UW32) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW33, UW32) + .byte 0xe, raw_closure_S_FS+4 /* DW_CFA_def_cfa_offset */ + ADV(UW34, UW33) + .byte 0x80+3, 2 /* DW_CFA_offset %ebx 2*-4 */ + ADV(UW35, UW34) + .byte 0xc0+3 /* DW_CFA_restore %ebx */ + ADV(UW36, UW35) + .byte 0xe, 4 /* DW_CFA_def_cfa_offset */ + ADV(UW37, UW36) + .byte 0xe, raw_closure_S_FS+4 /* DW_CFA_def_cfa_offset */ + ADV(UW38, UW37) + .byte 0xe, 4 /* DW_CFA_def_cfa_offset */ + ADV(UW39, UW38) + .byte 0xe, raw_closure_S_FS+4 /* DW_CFA_def_cfa_offset */ + .balign 4 +L(EFDE8): -.LSFDE3: - .long .LEFDE3-.LASFDE3 /* FDE Length */ -.LASFDE3: - .long .LASFDE3-.Lframe1 /* FDE CIE offset */ - .long FDE_ENCODE(.LFB3) /* FDE initial location */ - .long .LFE3-.LFB3 /* FDE address range */ -#ifdef __PIC__ - .byte 0x0 /* .uleb128 0x0; Augmentation size */ -#endif - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI4-.LFB3 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .byte 0x8 /* .uleb128 0x8 */ - .byte 0x85 /* DW_CFA_offset, column 0x5 */ - .byte 0x2 /* .uleb128 0x2 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI5-.LCFI4 - .byte 0xd /* DW_CFA_def_cfa_register */ - .byte 0x5 /* .uleb128 0x5 */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LCFI6-.LCFI5 - .byte 0x86 /* DW_CFA_offset, column 0x6 */ - .byte 0x3 /* .uleb128 0x3 */ - .align 4 -.LEFDE3: + .set L(set9),L(EFDE9)-L(SFDE9) + .long L(set9) /* FDE Length */ +L(SFDE9): + .long L(SFDE9)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW41)) /* Initial location */ + .long L(UW52)-L(UW41) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW42, UW41) + .byte 0xe, 0 /* DW_CFA_def_cfa_offset */ + .byte 0x9, 8, 2 /* DW_CFA_register %eip, %edx */ + ADV(UW43, UW42) + .byte 0xe, 4 /* DW_CFA_def_cfa_offset */ + ADV(UW44, UW43) + .byte 0xe, 8 /* DW_CFA_def_cfa_offset */ + .byte 0x80+8, 2 /* DW_CFA_offset %eip 2*-4 */ + ADV(UW45, UW44) + .byte 0xe, raw_closure_T_FS+8 /* DW_CFA_def_cfa_offset */ + ADV(UW46, UW45) + .byte 0x80+3, 3 /* DW_CFA_offset %ebx 3*-4 */ + ADV(UW47, UW46) + .byte 0xc0+3 /* DW_CFA_restore %ebx */ + ADV(UW48, UW47) + .byte 0xe, 8 /* DW_CFA_def_cfa_offset */ + ADV(UW49, UW48) + .byte 0xe, raw_closure_T_FS+8 /* DW_CFA_def_cfa_offset */ + ADV(UW50, UW49) + .byte 0xe, 8 /* DW_CFA_def_cfa_offset */ + ADV(UW51, UW50) + .byte 0xe, raw_closure_T_FS+8 /* DW_CFA_def_cfa_offset */ + .balign 4 +L(EFDE9): +#endif /* !FFI_NO_RAW_API */ +#ifdef _WIN32 + .def @feat.00; + .scl 3; + .type 0; + .endef + .globl @feat.00 +@feat.00 = 1 #endif -#endif -#endif /* ifndef __x86_64__ */ +#ifdef __APPLE__ + .subsections_via_symbols + .section __LD,__compact_unwind,regular,debug + + /* compact unwind for ffi_call_i386 */ + .long C(ffi_call_i386) + .set L1,L(UW5)-L(UW0) + .long L1 + .long 0x04000000 /* use dwarf unwind info */ + .long 0 + .long 0 + + /* compact unwind for ffi_go_closure_EAX */ + .long C(ffi_go_closure_EAX) + .set L2,L(UW8)-L(UW6) + .long L2 + .long 0x04000000 /* use dwarf unwind info */ + .long 0 + .long 0 + + /* compact unwind for ffi_go_closure_ECX */ + .long C(ffi_go_closure_ECX) + .set L3,L(UW11)-L(UW9) + .long L3 + .long 0x04000000 /* use dwarf unwind info */ + .long 0 + .long 0 + + /* compact unwind for ffi_closure_i386 */ + .long C(ffi_closure_i386) + .set L4,L(UW20)-L(UW12) + .long L4 + .long 0x04000000 /* use dwarf unwind info */ + .long 0 + .long 0 + + /* compact unwind for ffi_go_closure_STDCALL */ + .long C(ffi_go_closure_STDCALL) + .set L5,L(UW23)-L(UW21) + .long L5 + .long 0x04000000 /* use dwarf unwind info */ + .long 0 + .long 0 + + /* compact unwind for ffi_closure_REGISTER */ + .long C(ffi_closure_REGISTER) + .set L6,L(UW26)-L(UW24) + .long L6 + .long 0x04000000 /* use dwarf unwind info */ + .long 0 + .long 0 + + /* compact unwind for ffi_closure_STDCALL */ + .long C(ffi_closure_STDCALL) + .set L7,L(UW31)-L(UW27) + .long L7 + .long 0x04000000 /* use dwarf unwind info */ + .long 0 + .long 0 + + /* compact unwind for ffi_closure_raw_SYSV */ + .long C(ffi_closure_raw_SYSV) + .set L8,L(UW40)-L(UW32) + .long L8 + .long 0x04000000 /* use dwarf unwind info */ + .long 0 + .long 0 + + /* compact unwind for ffi_closure_raw_THISCALL */ + .long C(ffi_closure_raw_THISCALL) + .set L9,L(UW52)-L(UW41) + .long L9 + .long 0x04000000 /* use dwarf unwind info */ + .long 0 + .long 0 +#endif /* __APPLE__ */ + +#endif /* ifndef _MSC_VER */ +#endif /* ifdef __i386__ */ #if defined __ELF__ && defined __linux__ .section .note.GNU-stack,"",@progbits diff --git a/native/libffi/src/x86/sysv_intel.S b/native/libffi/src/x86/sysv_intel.S new file mode 100644 index 0000000000..3cafd71ce1 --- /dev/null +++ b/native/libffi/src/x86/sysv_intel.S @@ -0,0 +1,995 @@ +/* ----------------------------------------------------------------------- + sysv.S - Copyright (c) 2017 Anthony Green + - Copyright (c) 2013 The Written Word, Inc. + - Copyright (c) 1996,1998,2001-2003,2005,2008,2010 Red Hat, Inc. + + X86 Foreign Function Interface + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + ----------------------------------------------------------------------- */ + +#ifndef __x86_64__ +#ifdef _MSC_VER + +#define LIBFFI_ASM +#include +#include +#include +#include "internal.h" + +#define C2(X, Y) X ## Y +#define C1(X, Y) C2(X, Y) +#define L(X) C1(L, X) +# define ENDF(X) X ENDP + +/* This macro allows the safe creation of jump tables without an + actual table. The entry points into the table are all 8 bytes. + The use of ORG asserts that we're at the correct location. */ +/* ??? The clang assembler doesn't handle .org with symbolic expressions. */ +#if defined(__clang__) || defined(__APPLE__) || (defined (__sun__) && defined(__svr4__)) +# define E(BASE, X) ALIGN 8 +#else +# define E(BASE, X) ALIGN 8; ORG BASE + X * 8 +#endif + + .686P + .MODEL FLAT + +EXTRN @ffi_closure_inner@8:PROC +_TEXT SEGMENT + +/* This is declared as + + void ffi_call_i386(struct call_frame *frame, char *argp) + __attribute__((fastcall)); + + Thus the arguments are present in + + ecx: frame + edx: argp +*/ + +ALIGN 16 +PUBLIC @ffi_call_i386@8 +@ffi_call_i386@8 PROC +L(UW0): + cfi_startproc + #if !HAVE_FASTCALL + mov ecx, [esp+4] + mov edx, [esp+8] + #endif + mov eax, [esp] /* move the return address */ + mov [ecx], ebp /* store ebp into local frame */ + mov [ecx+4], eax /* store retaddr into local frame */ + + /* New stack frame based off ebp. This is a itty bit of unwind + trickery in that the CFA *has* changed. There is no easy way + to describe it correctly on entry to the function. Fortunately, + it doesn't matter too much since at all points we can correctly + unwind back to ffi_call. Note that the location to which we + moved the return address is (the new) CFA-4, so from the + perspective of the unwind info, it hasn't moved. */ + mov ebp, ecx +L(UW1): + // cfi_def_cfa(%ebp, 8) + // cfi_rel_offset(%ebp, 0) + + mov esp, edx /* set outgoing argument stack */ + mov eax, [20+R_EAX*4+ebp] /* set register arguments */ + mov edx, [20+R_EDX*4+ebp] + mov ecx, [20+R_ECX*4+ebp] + + call dword ptr [ebp+8] + + mov ecx, [12+ebp] /* load return type code */ + mov [ebp+8], ebx /* preserve %ebx */ +L(UW2): + // cfi_rel_offset(%ebx, 8) + + and ecx, X86_RET_TYPE_MASK + lea ebx, [L(store_table) + ecx * 8] + mov ecx, [ebp+16] /* load result address */ + jmp ebx + + ALIGN 8 +L(store_table): +E(L(store_table), X86_RET_FLOAT) + fstp DWORD PTR [ecx] + jmp L(e1) +E(L(store_table), X86_RET_DOUBLE) + fstp QWORD PTR [ecx] + jmp L(e1) +E(L(store_table), X86_RET_LDOUBLE) + fstp QWORD PTR [ecx] + jmp L(e1) +E(L(store_table), X86_RET_SINT8) + movsx eax, al + mov [ecx], eax + jmp L(e1) +E(L(store_table), X86_RET_SINT16) + movsx eax, ax + mov [ecx], eax + jmp L(e1) +E(L(store_table), X86_RET_UINT8) + movzx eax, al + mov [ecx], eax + jmp L(e1) +E(L(store_table), X86_RET_UINT16) + movzx eax, ax + mov [ecx], eax + jmp L(e1) +E(L(store_table), X86_RET_INT64) + mov [ecx+4], edx + /* fallthru */ +E(L(store_table), X86_RET_int 32) + mov [ecx], eax + /* fallthru */ +E(L(store_table), X86_RET_VOID) +L(e1): + mov ebx, [ebp+8] + mov esp, ebp + pop ebp +L(UW3): + // cfi_remember_state + // cfi_def_cfa(%esp, 4) + // cfi_restore(%ebx) + // cfi_restore(%ebp) + ret +L(UW4): + // cfi_restore_state + +E(L(store_table), X86_RET_STRUCTPOP) + jmp L(e1) +E(L(store_table), X86_RET_STRUCTARG) + jmp L(e1) +E(L(store_table), X86_RET_STRUCT_1B) + mov [ecx], al + jmp L(e1) +E(L(store_table), X86_RET_STRUCT_2B) + mov [ecx], ax + jmp L(e1) + + /* Fill out the table so that bad values are predictable. */ +E(L(store_table), X86_RET_UNUSED14) + int 3 +E(L(store_table), X86_RET_UNUSED15) + int 3 + +L(UW5): + // cfi_endproc +ENDF(@ffi_call_i386@8) + +/* The inner helper is declared as + + void ffi_closure_inner(struct closure_frame *frame, char *argp) + __attribute_((fastcall)) + + Thus the arguments are placed in + + ecx: frame + edx: argp +*/ + +/* Macros to help setting up the closure_data structure. */ + +#if HAVE_FASTCALL +# define closure_FS (40 + 4) +# define closure_CF 0 +#else +# define closure_FS (8 + 40 + 12) +# define closure_CF 8 +#endif + +FFI_CLOSURE_SAVE_REGS MACRO + mov [esp + closure_CF+16+R_EAX*4], eax + mov [esp + closure_CF+16+R_EDX*4], edx + mov [esp + closure_CF+16+R_ECX*4], ecx +ENDM + +FFI_CLOSURE_COPY_TRAMP_DATA MACRO + mov edx, [eax+FFI_TRAMPOLINE_SIZE] /* copy cif */ + mov ecx, [eax+FFI_TRAMPOLINE_SIZE+4] /* copy fun */ + mov eax, [eax+FFI_TRAMPOLINE_SIZE+8]; /* copy user_data */ + mov [esp+closure_CF+28], edx + mov [esp+closure_CF+32], ecx + mov [esp+closure_CF+36], eax +ENDM + +#if HAVE_FASTCALL +FFI_CLOSURE_PREP_CALL MACRO + mov ecx, esp /* load closure_data */ + lea edx, [esp+closure_FS+4] /* load incoming stack */ +ENDM +#else +FFI_CLOSURE_PREP_CALL MACRO + lea ecx, [esp+closure_CF] /* load closure_data */ + lea edx, [esp+closure_FS+4] /* load incoming stack */ + mov [esp], ecx + mov [esp+4], edx +ENDM +#endif + +FFI_CLOSURE_CALL_INNER MACRO UWN + call @ffi_closure_inner@8 +ENDM + +FFI_CLOSURE_MASK_AND_JUMP MACRO LABEL + and eax, X86_RET_TYPE_MASK + lea edx, [LABEL+eax*8] + mov eax, [esp+closure_CF] /* optimiztic load */ + jmp edx +ENDM + +ALIGN 16 +PUBLIC ffi_go_closure_EAX +ffi_go_closure_EAX PROC C +L(UW6): + // cfi_startproc + sub esp, closure_FS +L(UW7): + // cfi_def_cfa_offset(closure_FS + 4) + FFI_CLOSURE_SAVE_REGS + mov edx, [eax+4] /* copy cif */ + mov ecx, [eax +8] /* copy fun */ + mov [esp+closure_CF+28], edx + mov [esp+closure_CF+32], ecx + mov [esp+closure_CF+36], eax /* closure is user_data */ + jmp L(do_closure_i386) +L(UW8): + // cfi_endproc +ENDF(ffi_go_closure_EAX) + +ALIGN 16 +PUBLIC ffi_go_closure_ECX +ffi_go_closure_ECX PROC C +L(UW9): + // cfi_startproc + sub esp, closure_FS +L(UW10): + // cfi_def_cfa_offset(closure_FS + 4) + FFI_CLOSURE_SAVE_REGS + mov edx, [ecx+4] /* copy cif */ + mov eax, [ecx+8] /* copy fun */ + mov [esp+closure_CF+28], edx + mov [esp+closure_CF+32], eax + mov [esp+closure_CF+36], ecx /* closure is user_data */ + jmp L(do_closure_i386) +L(UW11): + // cfi_endproc +ENDF(ffi_go_closure_ECX) + +/* The closure entry points are reached from the ffi_closure trampoline. + On entry, %eax contains the address of the ffi_closure. */ + +ALIGN 16 +PUBLIC ffi_closure_i386 +ffi_closure_i386 PROC C +L(UW12): + // cfi_startproc + sub esp, closure_FS +L(UW13): + // cfi_def_cfa_offset(closure_FS + 4) + + FFI_CLOSURE_SAVE_REGS + FFI_CLOSURE_COPY_TRAMP_DATA + + /* Entry point from preceeding Go closures. */ +L(do_closure_i386):: + + FFI_CLOSURE_PREP_CALL + FFI_CLOSURE_CALL_INNER(14) + FFI_CLOSURE_MASK_AND_JUMP L(C1(load_table,2)) + + ALIGN 8 +L(load_table2): +E(L(load_table2), X86_RET_FLOAT) + fld dword ptr [esp+closure_CF] + jmp L(e2) +E(L(load_table2), X86_RET_DOUBLE) + fld qword ptr [esp+closure_CF] + jmp L(e2) +E(L(load_table2), X86_RET_LDOUBLE) + fld qword ptr [esp+closure_CF] + jmp L(e2) +E(L(load_table2), X86_RET_SINT8) + movsx eax, al + jmp L(e2) +E(L(load_table2), X86_RET_SINT16) + movsx eax, ax + jmp L(e2) +E(L(load_table2), X86_RET_UINT8) + movzx eax, al + jmp L(e2) +E(L(load_table2), X86_RET_UINT16) + movzx eax, ax + jmp L(e2) +E(L(load_table2), X86_RET_INT64) + mov edx, [esp+closure_CF+4] + jmp L(e2) +E(L(load_table2), X86_RET_INT32) + nop + /* fallthru */ +E(L(load_table2), X86_RET_VOID) +L(e2): + add esp, closure_FS +L(UW16): + // cfi_adjust_cfa_offset(-closure_FS) + ret +L(UW17): + // cfi_adjust_cfa_offset(closure_FS) +E(L(load_table2), X86_RET_STRUCTPOP) + add esp, closure_FS +L(UW18): + // cfi_adjust_cfa_offset(-closure_FS) + ret 4 +L(UW19): + // cfi_adjust_cfa_offset(closure_FS) +E(L(load_table2), X86_RET_STRUCTARG) + jmp L(e2) +E(L(load_table2), X86_RET_STRUCT_1B) + movzx eax, al + jmp L(e2) +E(L(load_table2), X86_RET_STRUCT_2B) + movzx eax, ax + jmp L(e2) + + /* Fill out the table so that bad values are predictable. */ +E(L(load_table2), X86_RET_UNUSED14) + int 3 +E(L(load_table2), X86_RET_UNUSED15) + int 3 + +L(UW20): + // cfi_endproc +ENDF(ffi_closure_i386) + +ALIGN 16 +PUBLIC ffi_go_closure_STDCALL +ffi_go_closure_STDCALL PROC C +L(UW21): + // cfi_startproc + sub esp, closure_FS +L(UW22): + // cfi_def_cfa_offset(closure_FS + 4) + FFI_CLOSURE_SAVE_REGS + mov edx, [ecx+4] /* copy cif */ + mov eax, [ecx+8] /* copy fun */ + mov [esp+closure_CF+28], edx + mov [esp+closure_CF+32], eax + mov [esp+closure_CF+36], ecx /* closure is user_data */ + jmp L(do_closure_STDCALL) +L(UW23): + // cfi_endproc +ENDF(ffi_go_closure_STDCALL) + +/* For REGISTER, we have no available parameter registers, and so we + enter here having pushed the closure onto the stack. */ + +ALIGN 16 +PUBLIC ffi_closure_REGISTER +ffi_closure_REGISTER PROC C +L(UW24): + // cfi_startproc + // cfi_def_cfa(%esp, 8) + // cfi_offset(%eip, -8) + sub esp, closure_FS-4 +L(UW25): + // cfi_def_cfa_offset(closure_FS + 4) + FFI_CLOSURE_SAVE_REGS + 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 +ENDF(ffi_closure_REGISTER) + +/* For STDCALL (and others), we need to pop N bytes of arguments off + the stack following the closure. The amount needing to be popped + is returned to us from ffi_closure_inner. */ + +ALIGN 16 +PUBLIC ffi_closure_STDCALL +ffi_closure_STDCALL PROC C +L(UW27): + // cfi_startproc + sub esp, closure_FS +L(UW28): + // cfi_def_cfa_offset(closure_FS + 4) + + FFI_CLOSURE_SAVE_REGS + + /* Entry point from ffi_closure_REGISTER. */ +L(do_closure_REGISTER):: + + FFI_CLOSURE_COPY_TRAMP_DATA + + /* Entry point from preceeding Go closure. */ +L(do_closure_STDCALL):: + + FFI_CLOSURE_PREP_CALL + FFI_CLOSURE_CALL_INNER(29) + + mov ecx, eax + shr ecx, X86_RET_POP_SHIFT /* isolate pop count */ + lea ecx, [esp+closure_FS+ecx] /* compute popped esp */ + mov edx, [esp+closure_FS] /* move return address */ + mov [ecx], edx + + /* From this point on, the value of %esp upon return is %ecx+4, + and we've copied the return address to %ecx to make return easy. + There's no point in representing this in the unwind info, as + there is always a window between the mov and the ret which + will be wrong from one point of view or another. */ + + FFI_CLOSURE_MASK_AND_JUMP L(C1(load_table,3)) + + ALIGN 8 +L(load_table3): +E(L(load_table3), X86_RET_FLOAT) + fld DWORD PTR [esp+closure_CF] + mov esp, ecx + ret +E(L(load_table3), X86_RET_DOUBLE) + fld QWORD PTR [esp+closure_CF] + mov esp, ecx + ret +E(L(load_table3), X86_RET_LDOUBLE) + fld QWORD PTR [esp+closure_CF] + mov esp, ecx + ret +E(L(load_table3), X86_RET_SINT8) + movsx eax, al + mov esp, ecx + ret +E(L(load_table3), X86_RET_SINT16) + movsx eax, ax + mov esp, ecx + ret +E(L(load_table3), X86_RET_UINT8) + movzx eax, al + mov esp, ecx + ret +E(L(load_table3), X86_RET_UINT16) + movzx eax, ax + mov esp, ecx + ret +E(L(load_table3), X86_RET_INT64) + mov edx, [esp+closure_CF+4] + mov esp, ecx + ret +E(L(load_table3), X86_RET_int 32) + mov esp, ecx + ret +E(L(load_table3), X86_RET_VOID) + mov esp, ecx + ret +E(L(load_table3), X86_RET_STRUCTPOP) + mov esp, ecx + ret +E(L(load_table3), X86_RET_STRUCTARG) + mov esp, ecx + ret +E(L(load_table3), X86_RET_STRUCT_1B) + movzx eax, al + mov esp, ecx + ret +E(L(load_table3), X86_RET_STRUCT_2B) + movzx eax, ax + mov esp, ecx + ret + + /* Fill out the table so that bad values are predictable. */ +E(L(load_table3), X86_RET_UNUSED14) + int 3 +E(L(load_table3), X86_RET_UNUSED15) + int 3 + +L(UW31): + // cfi_endproc +ENDF(ffi_closure_STDCALL) + +#if !FFI_NO_RAW_API + +#define raw_closure_S_FS (16+16+12) + +ALIGN 16 +PUBLIC ffi_closure_raw_SYSV +ffi_closure_raw_SYSV PROC C +L(UW32): + // cfi_startproc + sub esp, raw_closure_S_FS +L(UW33): + // cfi_def_cfa_offset(raw_closure_S_FS + 4) + mov [esp+raw_closure_S_FS-4], ebx +L(UW34): + // cfi_rel_offset(%ebx, raw_closure_S_FS-4) + + mov edx, [eax+FFI_TRAMPOLINE_SIZE+8] /* load cl->user_data */ + mov [esp+12], edx + lea edx, [esp+raw_closure_S_FS+4] /* load raw_args */ + mov [esp+8], edx + lea edx, [esp+16] /* load &res */ + mov [esp+4], edx + mov ebx, [eax+FFI_TRAMPOLINE_SIZE] /* load cl->cif */ + mov [esp], ebx + call DWORD PTR [eax+FFI_TRAMPOLINE_SIZE+4] /* call cl->fun */ + + mov eax, [ebx+20] /* load cif->flags */ + and eax, X86_RET_TYPE_MASK +// #ifdef __PIC__ +// call __x86.get_pc_thunk.bx +// L(pc4): +// lea ecx, L(load_table4)-L(pc4)(%ebx, %eax, 8), %ecx +// #else + lea ecx, [L(load_table4)+eax+8] +// #endif + mov ebx, [esp+raw_closure_S_FS-4] +L(UW35): + // cfi_restore(%ebx) + mov eax, [esp+16] /* Optimistic load */ + jmp dword ptr [ecx] + + ALIGN 8 +L(load_table4): +E(L(load_table4), X86_RET_FLOAT) + fld DWORD PTR [esp +16] + jmp L(e4) +E(L(load_table4), X86_RET_DOUBLE) + fld QWORD PTR [esp +16] + jmp L(e4) +E(L(load_table4), X86_RET_LDOUBLE) + fld QWORD PTR [esp +16] + jmp L(e4) +E(L(load_table4), X86_RET_SINT8) + movsx eax, al + jmp L(e4) +E(L(load_table4), X86_RET_SINT16) + movsx eax, ax + jmp L(e4) +E(L(load_table4), X86_RET_UINT8) + movzx eax, al + jmp L(e4) +E(L(load_table4), X86_RET_UINT16) + movzx eax, ax + jmp L(e4) +E(L(load_table4), X86_RET_INT64) + mov edx, [esp+16+4] + jmp L(e4) +E(L(load_table4), X86_RET_int 32) + nop + /* fallthru */ +E(L(load_table4), X86_RET_VOID) +L(e4): + add esp, raw_closure_S_FS +L(UW36): + // cfi_adjust_cfa_offset(-raw_closure_S_FS) + ret +L(UW37): + // cfi_adjust_cfa_offset(raw_closure_S_FS) +E(L(load_table4), X86_RET_STRUCTPOP) + add esp, raw_closure_S_FS +L(UW38): + // cfi_adjust_cfa_offset(-raw_closure_S_FS) + ret 4 +L(UW39): + // cfi_adjust_cfa_offset(raw_closure_S_FS) +E(L(load_table4), X86_RET_STRUCTARG) + jmp L(e4) +E(L(load_table4), X86_RET_STRUCT_1B) + movzx eax, al + jmp L(e4) +E(L(load_table4), X86_RET_STRUCT_2B) + movzx eax, ax + jmp L(e4) + + /* Fill out the table so that bad values are predictable. */ +E(L(load_table4), X86_RET_UNUSED14) + int 3 +E(L(load_table4), X86_RET_UNUSED15) + int 3 + +L(UW40): + // cfi_endproc +ENDF(ffi_closure_raw_SYSV) + +#define raw_closure_T_FS (16+16+8) + +ALIGN 16 +PUBLIC ffi_closure_raw_THISCALL +ffi_closure_raw_THISCALL PROC C +L(UW41): + // cfi_startproc + /* Rearrange the stack such that %ecx is the first argument. + This means moving the return address. */ + pop edx +L(UW42): + // cfi_def_cfa_offset(0) + // cfi_register(%eip, %edx) + push ecx +L(UW43): + // cfi_adjust_cfa_offset(4) + push edx +L(UW44): + // cfi_adjust_cfa_offset(4) + // cfi_rel_offset(%eip, 0) + sub esp, raw_closure_T_FS +L(UW45): + // cfi_adjust_cfa_offset(raw_closure_T_FS) + mov [esp+raw_closure_T_FS-4], ebx +L(UW46): + // cfi_rel_offset(%ebx, raw_closure_T_FS-4) + + mov edx, [eax+FFI_TRAMPOLINE_SIZE+8] /* load cl->user_data */ + mov [esp+12], edx + lea edx, [esp+raw_closure_T_FS+4] /* load raw_args */ + mov [esp+8], edx + lea edx, [esp+16] /* load &res */ + mov [esp+4], edx + mov ebx, [eax+FFI_TRAMPOLINE_SIZE] /* load cl->cif */ + mov [esp], ebx + call DWORD PTR [eax+FFI_TRAMPOLINE_SIZE+4] /* call cl->fun */ + + mov eax, [ebx+20] /* load cif->flags */ + and eax, X86_RET_TYPE_MASK +// #ifdef __PIC__ +// call __x86.get_pc_thunk.bx +// L(pc5): +// leal L(load_table5)-L(pc5)(%ebx, %eax, 8), %ecx +// #else + lea ecx, [L(load_table5)+eax*8] +//#endif + mov ebx, [esp+raw_closure_T_FS-4] +L(UW47): + // cfi_restore(%ebx) + mov eax, [esp+16] /* Optimistic load */ + jmp DWORD PTR [ecx] + + AlIGN 4 +L(load_table5): +E(L(load_table5), X86_RET_FLOAT) + fld DWORD PTR [esp +16] + jmp L(e5) +E(L(load_table5), X86_RET_DOUBLE) + fld QWORD PTR [esp +16] + jmp L(e5) +E(L(load_table5), X86_RET_LDOUBLE) + fld QWORD PTR [esp+16] + jmp L(e5) +E(L(load_table5), X86_RET_SINT8) + movsx eax, al + jmp L(e5) +E(L(load_table5), X86_RET_SINT16) + movsx eax, ax + jmp L(e5) +E(L(load_table5), X86_RET_UINT8) + movzx eax, al + jmp L(e5) +E(L(load_table5), X86_RET_UINT16) + movzx eax, ax + jmp L(e5) +E(L(load_table5), X86_RET_INT64) + mov edx, [esp+16+4] + jmp L(e5) +E(L(load_table5), X86_RET_int 32) + nop + /* fallthru */ +E(L(load_table5), X86_RET_VOID) +L(e5): + add esp, raw_closure_T_FS +L(UW48): + // cfi_adjust_cfa_offset(-raw_closure_T_FS) + /* Remove the extra %ecx argument we pushed. */ + ret 4 +L(UW49): + // cfi_adjust_cfa_offset(raw_closure_T_FS) +E(L(load_table5), X86_RET_STRUCTPOP) + add esp, raw_closure_T_FS +L(UW50): + // cfi_adjust_cfa_offset(-raw_closure_T_FS) + ret 8 +L(UW51): + // cfi_adjust_cfa_offset(raw_closure_T_FS) +E(L(load_table5), X86_RET_STRUCTARG) + jmp L(e5) +E(L(load_table5), X86_RET_STRUCT_1B) + movzx eax, al + jmp L(e5) +E(L(load_table5), X86_RET_STRUCT_2B) + movzx eax, ax + jmp L(e5) + + /* Fill out the table so that bad values are predictable. */ +E(L(load_table5), X86_RET_UNUSED14) + int 3 +E(L(load_table5), X86_RET_UNUSED15) + int 3 + +L(UW52): + // cfi_endproc +ENDF(ffi_closure_raw_THISCALL) + +#endif /* !FFI_NO_RAW_API */ + +#ifdef X86_DARWIN +# define COMDAT(X) \ + .section __TEXT,__text,coalesced,pure_instructions; \ + .weak_definition X; \ + FFI_HIDDEN(X) +#elif defined __ELF__ && !(defined(__sun__) && defined(__svr4__)) +# define COMDAT(X) \ + .section .text.X,"axG",@progbits,X,comdat; \ + PUBLIC X; \ + FFI_HIDDEN(X) +#else +# define COMDAT(X) +#endif + +// #if defined(__PIC__) +// COMDAT(C(__x86.get_pc_thunk.bx)) +// C(__x86.get_pc_thunk.bx): +// movl (%esp), %ebx +// ret +// ENDF(C(__x86.get_pc_thunk.bx)) +// # if defined X86_DARWIN || defined HAVE_HIDDEN_VISIBILITY_ATTRIBUTE +// COMDAT(C(__x86.get_pc_thunk.dx)) +// C(__x86.get_pc_thunk.dx): +// movl (%esp), %edx +// ret +// ENDF(C(__x86.get_pc_thunk.dx)) +// #endif /* DARWIN || HIDDEN */ +// #endif /* __PIC__ */ + +#if 0 +/* Sadly, OSX cctools-as doesn't understand .cfi directives at all. */ + +#ifdef __APPLE__ +.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support +EHFrame0: +#elif defined(X86_WIN32) +.section .eh_frame,"r" +#elif defined(HAVE_AS_X86_64_UNWIND_SECTION_TYPE) +.section .eh_frame,EH_FRAME_FLAGS,@unwind +#else +.section .eh_frame,EH_FRAME_FLAGS,@progbits +#endif + +#ifdef HAVE_AS_X86_PCREL +# define PCREL(X) X - . +#else +# define PCREL(X) X@rel +#endif + +/* Simplify advancing between labels. Assume DW_CFA_advance_loc1 fits. */ +#define ADV(N, P) .byte 2, L(N)-L(P) + + .balign 4 +L(CIE): + .set L(set0),L(ECIE)-L(SCIE) + .long L(set0) /* CIE Length */ +L(SCIE): + .long 0 /* CIE Identifier Tag */ + .byte 1 /* CIE Version */ + .ascii "zR\0" /* CIE Augmentation */ + .byte 1 /* CIE Code Alignment Factor */ + .byte 0x7c /* CIE Data Alignment Factor */ + .byte 0x8 /* CIE RA Column */ + .byte 1 /* Augmentation size */ + .byte 0x1b /* FDE Encoding (pcrel sdata4) */ + .byte 0xc, 4, 4 /* DW_CFA_def_cfa, %esp offset 4 */ + .byte 0x80+8, 1 /* DW_CFA_offset, %eip offset 1*-4 */ + .balign 4 +L(ECIE): + + .set L(set1),L(EFDE1)-L(SFDE1) + .long L(set1) /* FDE Length */ +L(SFDE1): + .long L(SFDE1)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW0)) /* Initial location */ + .long L(UW5)-L(UW0) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW1, UW0) + .byte 0xc, 5, 8 /* DW_CFA_def_cfa, %ebp 8 */ + .byte 0x80+5, 2 /* DW_CFA_offset, %ebp 2*-4 */ + ADV(UW2, UW1) + .byte 0x80+3, 0 /* DW_CFA_offset, %ebx 0*-4 */ + ADV(UW3, UW2) + .byte 0xa /* DW_CFA_remember_state */ + .byte 0xc, 4, 4 /* DW_CFA_def_cfa, %esp 4 */ + .byte 0xc0+3 /* DW_CFA_restore, %ebx */ + .byte 0xc0+5 /* DW_CFA_restore, %ebp */ + ADV(UW4, UW3) + .byte 0xb /* DW_CFA_restore_state */ + .balign 4 +L(EFDE1): + + .set L(set2),L(EFDE2)-L(SFDE2) + .long L(set2) /* FDE Length */ +L(SFDE2): + .long L(SFDE2)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW6)) /* Initial location */ + .long L(UW8)-L(UW6) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW7, UW6) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ + .balign 4 +L(EFDE2): + + .set L(set3),L(EFDE3)-L(SFDE3) + .long L(set3) /* FDE Length */ +L(SFDE3): + .long L(SFDE3)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW9)) /* Initial location */ + .long L(UW11)-L(UW9) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW10, UW9) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ + .balign 4 +L(EFDE3): + + .set L(set4),L(EFDE4)-L(SFDE4) + .long L(set4) /* FDE Length */ +L(SFDE4): + .long L(SFDE4)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW12)) /* Initial location */ + .long L(UW20)-L(UW12) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW13, UW12) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ +#ifdef FFI_CLOSURE_CALL_INNER_SAVE_EBX + ADV(UW14, UW13) + .byte 0x80+3, (40-(closure_FS+4))/-4 /* DW_CFA_offset %ebx */ + ADV(UW15, UW14) + .byte 0xc0+3 /* DW_CFA_restore %ebx */ + ADV(UW16, UW15) +#else + ADV(UW16, UW13) +#endif + .byte 0xe, 4 /* DW_CFA_def_cfa_offset */ + ADV(UW17, UW16) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ + ADV(UW18, UW17) + .byte 0xe, 4 /* DW_CFA_def_cfa_offset */ + ADV(UW19, UW18) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ + .balign 4 +L(EFDE4): + + .set L(set5),L(EFDE5)-L(SFDE5) + .long L(set5) /* FDE Length */ +L(SFDE5): + .long L(SFDE5)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW21)) /* Initial location */ + .long L(UW23)-L(UW21) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW22, UW21) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ + .balign 4 +L(EFDE5): + + .set L(set6),L(EFDE6)-L(SFDE6) + .long L(set6) /* FDE Length */ +L(SFDE6): + .long L(SFDE6)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW24)) /* Initial location */ + .long L(UW26)-L(UW24) /* Address range */ + .byte 0 /* Augmentation size */ + .byte 0xe, 8 /* DW_CFA_def_cfa_offset */ + .byte 0x80+8, 2 /* DW_CFA_offset %eip, 2*-4 */ + ADV(UW25, UW24) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ + .balign 4 +L(EFDE6): + + .set L(set7),L(EFDE7)-L(SFDE7) + .long L(set7) /* FDE Length */ +L(SFDE7): + .long L(SFDE7)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW27)) /* Initial location */ + .long L(UW31)-L(UW27) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW28, UW27) + .byte 0xe, closure_FS+4 /* DW_CFA_def_cfa_offset */ +#ifdef FFI_CLOSURE_CALL_INNER_SAVE_EBX + ADV(UW29, UW28) + .byte 0x80+3, (40-(closure_FS+4))/-4 /* DW_CFA_offset %ebx */ + ADV(UW30, UW29) + .byte 0xc0+3 /* DW_CFA_restore %ebx */ +#endif + .balign 4 +L(EFDE7): + +#if !FFI_NO_RAW_API + .set L(set8),L(EFDE8)-L(SFDE8) + .long L(set8) /* FDE Length */ +L(SFDE8): + .long L(SFDE8)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW32)) /* Initial location */ + .long L(UW40)-L(UW32) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW33, UW32) + .byte 0xe, raw_closure_S_FS+4 /* DW_CFA_def_cfa_offset */ + ADV(UW34, UW33) + .byte 0x80+3, 2 /* DW_CFA_offset %ebx 2*-4 */ + ADV(UW35, UW34) + .byte 0xc0+3 /* DW_CFA_restore %ebx */ + ADV(UW36, UW35) + .byte 0xe, 4 /* DW_CFA_def_cfa_offset */ + ADV(UW37, UW36) + .byte 0xe, raw_closure_S_FS+4 /* DW_CFA_def_cfa_offset */ + ADV(UW38, UW37) + .byte 0xe, 4 /* DW_CFA_def_cfa_offset */ + ADV(UW39, UW38) + .byte 0xe, raw_closure_S_FS+4 /* DW_CFA_def_cfa_offset */ + .balign 4 +L(EFDE8): + + .set L(set9),L(EFDE9)-L(SFDE9) + .long L(set9) /* FDE Length */ +L(SFDE9): + .long L(SFDE9)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW41)) /* Initial location */ + .long L(UW52)-L(UW41) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW42, UW41) + .byte 0xe, 0 /* DW_CFA_def_cfa_offset */ + .byte 0x9, 8, 2 /* DW_CFA_register %eip, %edx */ + ADV(UW43, UW42) + .byte 0xe, 4 /* DW_CFA_def_cfa_offset */ + ADV(UW44, UW43) + .byte 0xe, 8 /* DW_CFA_def_cfa_offset */ + .byte 0x80+8, 2 /* DW_CFA_offset %eip 2*-4 */ + ADV(UW45, UW44) + .byte 0xe, raw_closure_T_FS+8 /* DW_CFA_def_cfa_offset */ + ADV(UW46, UW45) + .byte 0x80+3, 3 /* DW_CFA_offset %ebx 3*-4 */ + ADV(UW47, UW46) + .byte 0xc0+3 /* DW_CFA_restore %ebx */ + ADV(UW48, UW47) + .byte 0xe, 8 /* DW_CFA_def_cfa_offset */ + ADV(UW49, UW48) + .byte 0xe, raw_closure_T_FS+8 /* DW_CFA_def_cfa_offset */ + ADV(UW50, UW49) + .byte 0xe, 8 /* DW_CFA_def_cfa_offset */ + ADV(UW51, UW50) + .byte 0xe, raw_closure_T_FS+8 /* DW_CFA_def_cfa_offset */ + .balign 4 +L(EFDE9): +#endif /* !FFI_NO_RAW_API */ + +#ifdef _WIN32 + .def @feat.00; + .scl 3; + .type 0; + .endef + PUBLIC @feat.00 +@feat.00 = 1 +#endif + +#endif /* ifndef _MSC_VER */ +#endif /* ifndef __x86_64__ */ + +#if defined __ELF__ && defined __linux__ + .section .note.GNU-stack,"",@progbits +#endif +#endif + +END \ No newline at end of file diff --git a/native/libffi/src/x86/unix64.S b/native/libffi/src/x86/unix64.S index dcd6bc71ea..89d7db11fe 100644 --- a/native/libffi/src/x86/unix64.S +++ b/native/libffi/src/x86/unix64.S @@ -30,8 +30,24 @@ #define LIBFFI_ASM #include #include +#include "internal64.h" +#include "asmnames.h" -.text + .text + +/* This macro allows the safe creation of jump tables without an + actual table. The entry points into the table are all 8 bytes. + The use of ORG asserts that we're at the correct location. */ +/* ??? The clang assembler doesn't handle .org with symbolic expressions. */ +#if defined(__clang__) || defined(__APPLE__) || (defined (__sun__) && defined(__svr4__)) +# define E(BASE, X) .balign 8 +#else +# ifdef __CET__ +# define E(BASE, X) .balign 8; .org BASE + X * 16 +# else +# define E(BASE, X) .balign 8; .org BASE + X * 8 +# endif +#endif /* ffi_call_unix64 (void *args, unsigned long bytes, unsigned flags, void *raddr, void (*fnaddr)(void)); @@ -40,12 +56,13 @@ for this function. This has been allocated by ffi_call. We also deallocate some of the stack that has been alloca'd. */ - .align 2 - .globl ffi_call_unix64 - .type ffi_call_unix64,@function + .balign 8 + .globl C(ffi_call_unix64) + FFI_HIDDEN(C(ffi_call_unix64)) -ffi_call_unix64: -.LUW0: +C(ffi_call_unix64): +L(UW0): + _CET_ENDBR movq (%rsp), %r10 /* Load return address. */ leaq (%rdi, %rsi), %rax /* Find local stack base. */ movq %rdx, (%rax) /* Save flags. */ @@ -53,24 +70,36 @@ ffi_call_unix64: movq %rbp, 16(%rax) /* Save old frame pointer. */ movq %r10, 24(%rax) /* Relocate return address. */ movq %rax, %rbp /* Finalize local stack frame. */ -.LUW1: + + /* New stack frame based off rbp. This is a itty bit of unwind + trickery in that the CFA *has* changed. There is no easy way + to describe it correctly on entry to the function. Fortunately, + it doesn't matter too much since at all points we can correctly + unwind back to ffi_call. Note that the location to which we + moved the return address is (the new) CFA-8, so from the + perspective of the unwind info, it hasn't moved. */ +L(UW1): + /* cfi_def_cfa(%rbp, 32) */ + /* cfi_rel_offset(%rbp, 16) */ + movq %rdi, %r10 /* Save a copy of the register area. */ movq %r8, %r11 /* Save a copy of the target fn. */ - movl %r9d, %eax /* Set number of SSE registers. */ /* Load up all argument registers. */ movq (%r10), %rdi - movq 8(%r10), %rsi - movq 16(%r10), %rdx - movq 24(%r10), %rcx - movq 32(%r10), %r8 - movq 40(%r10), %r9 + movq 0x08(%r10), %rsi + movq 0x10(%r10), %rdx + movq 0x18(%r10), %rcx + movq 0x20(%r10), %r8 + movq 0x28(%r10), %r9 + movl 0xb0(%r10), %eax /* Set number of SSE registers. */ testl %eax, %eax - jnz .Lload_sse -.Lret_from_load_sse: + jnz L(load_sse) +L(ret_from_load_sse): - /* Deallocate the reg arg area. */ - leaq 176(%r10), %rsp + /* Deallocate the reg arg area, except for r10, then load via pop. */ + leaq 0xb8(%r10), %rsp + popq %r10 /* Call the user function. */ call *%r11 @@ -81,352 +110,512 @@ ffi_call_unix64: movq 0(%rbp), %rcx /* Reload flags. */ movq 8(%rbp), %rdi /* Reload raddr. */ movq 16(%rbp), %rbp /* Reload old frame pointer. */ -.LUW2: +L(UW2): + /* cfi_remember_state */ + /* cfi_def_cfa(%rsp, 8) */ + /* cfi_restore(%rbp) */ /* The first byte of the flags contains the FFI_TYPE. */ + cmpb $UNIX64_RET_LAST, %cl movzbl %cl, %r10d - leaq .Lstore_table(%rip), %r11 - movslq (%r11, %r10, 4), %r10 - addq %r11, %r10 + leaq L(store_table)(%rip), %r11 + ja L(sa) +#ifdef __CET__ + /* NB: Originally, each slot is 8 byte. 4 bytes of ENDBR64 + + 4 bytes NOP padding double slot size to 16 bytes. */ + addl %r10d, %r10d +#endif + leaq (%r11, %r10, 8), %r10 + + /* Prep for the structure cases: scratch area in redzone. */ + leaq -20(%rsp), %rsi jmp *%r10 -.Lstore_table: - .long .Lst_void-.Lstore_table /* FFI_TYPE_VOID */ - .long .Lst_sint32-.Lstore_table /* FFI_TYPE_INT */ - .long .Lst_float-.Lstore_table /* FFI_TYPE_FLOAT */ - .long .Lst_double-.Lstore_table /* FFI_TYPE_DOUBLE */ - .long .Lst_ldouble-.Lstore_table /* FFI_TYPE_LONGDOUBLE */ - .long .Lst_uint8-.Lstore_table /* FFI_TYPE_UINT8 */ - .long .Lst_sint8-.Lstore_table /* FFI_TYPE_SINT8 */ - .long .Lst_uint16-.Lstore_table /* FFI_TYPE_UINT16 */ - .long .Lst_sint16-.Lstore_table /* FFI_TYPE_SINT16 */ - .long .Lst_uint32-.Lstore_table /* FFI_TYPE_UINT32 */ - .long .Lst_sint32-.Lstore_table /* FFI_TYPE_SINT32 */ - .long .Lst_int64-.Lstore_table /* FFI_TYPE_UINT64 */ - .long .Lst_int64-.Lstore_table /* FFI_TYPE_SINT64 */ - .long .Lst_struct-.Lstore_table /* FFI_TYPE_STRUCT */ - .long .Lst_int64-.Lstore_table /* FFI_TYPE_POINTER */ - - .align 2 -.Lst_void: + .balign 8 +L(store_table): +E(L(store_table), UNIX64_RET_VOID) + _CET_ENDBR ret - .align 2 - -.Lst_uint8: - movzbq %al, %rax +E(L(store_table), UNIX64_RET_UINT8) + _CET_ENDBR + movzbl %al, %eax movq %rax, (%rdi) ret - .align 2 -.Lst_sint8: - movsbq %al, %rax +E(L(store_table), UNIX64_RET_UINT16) + _CET_ENDBR + movzwl %ax, %eax movq %rax, (%rdi) ret - .align 2 -.Lst_uint16: - movzwq %ax, %rax +E(L(store_table), UNIX64_RET_UINT32) + _CET_ENDBR + movl %eax, %eax movq %rax, (%rdi) - .align 2 -.Lst_sint16: - movswq %ax, %rax + ret +E(L(store_table), UNIX64_RET_SINT8) + _CET_ENDBR + movsbq %al, %rax movq %rax, (%rdi) ret - .align 2 -.Lst_uint32: - movl %eax, %eax +E(L(store_table), UNIX64_RET_SINT16) + _CET_ENDBR + movswq %ax, %rax movq %rax, (%rdi) - .align 2 -.Lst_sint32: + ret +E(L(store_table), UNIX64_RET_SINT32) + _CET_ENDBR cltq movq %rax, (%rdi) ret - .align 2 -.Lst_int64: +E(L(store_table), UNIX64_RET_INT64) + _CET_ENDBR movq %rax, (%rdi) ret - - .align 2 -.Lst_float: - movss %xmm0, (%rdi) +E(L(store_table), UNIX64_RET_XMM32) + _CET_ENDBR + movd %xmm0, (%rdi) ret - .align 2 -.Lst_double: - movsd %xmm0, (%rdi) +E(L(store_table), UNIX64_RET_XMM64) + _CET_ENDBR + movq %xmm0, (%rdi) ret -.Lst_ldouble: +E(L(store_table), UNIX64_RET_X87) + _CET_ENDBR fstpt (%rdi) ret - - .align 2 -.Lst_struct: - leaq -20(%rsp), %rsi /* Scratch area in redzone. */ - - /* We have to locate the values now, and since we don't want to - write too much data into the user's return value, we spill the - value to a 16 byte scratch area first. Bits 8, 9, and 10 - control where the values are located. Only one of the three - bits will be set; see ffi_prep_cif_machdep for the pattern. */ - movd %xmm0, %r10 - movd %xmm1, %r11 - testl $0x100, %ecx - cmovnz %rax, %rdx - cmovnz %r10, %rax - testl $0x200, %ecx - cmovnz %r10, %rdx - testl $0x400, %ecx - cmovnz %r10, %rax - cmovnz %r11, %rdx - movq %rax, (%rsi) +E(L(store_table), UNIX64_RET_X87_2) + _CET_ENDBR + fstpt (%rdi) + fstpt 16(%rdi) + ret +E(L(store_table), UNIX64_RET_ST_XMM0_RAX) + _CET_ENDBR + movq %rax, 8(%rsi) + jmp L(s3) +E(L(store_table), UNIX64_RET_ST_RAX_XMM0) + _CET_ENDBR + movq %xmm0, 8(%rsi) + jmp L(s2) +E(L(store_table), UNIX64_RET_ST_XMM0_XMM1) + _CET_ENDBR + movq %xmm1, 8(%rsi) + jmp L(s3) +E(L(store_table), UNIX64_RET_ST_RAX_RDX) + _CET_ENDBR movq %rdx, 8(%rsi) - - /* Bits 12-31 contain the true size of the structure. Copy from - the scratch area to the true destination. */ - shrl $12, %ecx +L(s2): + movq %rax, (%rsi) + shrl $UNIX64_SIZE_SHIFT, %ecx rep movsb ret + .balign 8 +L(s3): + movq %xmm0, (%rsi) + shrl $UNIX64_SIZE_SHIFT, %ecx + rep movsb + ret + +L(sa): call PLT(C(abort)) /* Many times we can avoid loading any SSE registers at all. It's not worth an indirect jump to load the exact set of SSE registers needed; zero or all is a good compromise. */ - .align 2 -.LUW3: -.Lload_sse: - movdqa 48(%r10), %xmm0 - movdqa 64(%r10), %xmm1 - movdqa 80(%r10), %xmm2 - movdqa 96(%r10), %xmm3 - movdqa 112(%r10), %xmm4 - movdqa 128(%r10), %xmm5 - movdqa 144(%r10), %xmm6 - movdqa 160(%r10), %xmm7 - jmp .Lret_from_load_sse - -.LUW4: - .size ffi_call_unix64,.-ffi_call_unix64 - - .align 2 - .globl ffi_closure_unix64 - .type ffi_closure_unix64,@function - -ffi_closure_unix64: -.LUW5: - /* The carry flag is set by the trampoline iff SSE registers - are used. Don't clobber it before the branch instruction. */ - leaq -200(%rsp), %rsp -.LUW6: - movq %rdi, (%rsp) - movq %rsi, 8(%rsp) - movq %rdx, 16(%rsp) - movq %rcx, 24(%rsp) - movq %r8, 32(%rsp) - movq %r9, 40(%rsp) - jc .Lsave_sse -.Lret_from_save_sse: - - movq %r10, %rdi - leaq 176(%rsp), %rsi - movq %rsp, %rdx - leaq 208(%rsp), %rcx - call ffi_closure_unix64_inner@PLT + .balign 2 +L(UW3): + /* cfi_restore_state */ +L(load_sse): + movdqa 0x30(%r10), %xmm0 + movdqa 0x40(%r10), %xmm1 + movdqa 0x50(%r10), %xmm2 + movdqa 0x60(%r10), %xmm3 + movdqa 0x70(%r10), %xmm4 + movdqa 0x80(%r10), %xmm5 + movdqa 0x90(%r10), %xmm6 + movdqa 0xa0(%r10), %xmm7 + jmp L(ret_from_load_sse) + +L(UW4): +ENDF(C(ffi_call_unix64)) + +/* 6 general registers, 8 vector registers, + 32 bytes of rvalue, 8 bytes of alignment. */ +#define ffi_closure_OFS_G 0 +#define ffi_closure_OFS_V (6*8) +#define ffi_closure_OFS_RVALUE (ffi_closure_OFS_V + 8*16) +#define ffi_closure_FS (ffi_closure_OFS_RVALUE + 32 + 8) + +/* The location of rvalue within the red zone after deallocating the frame. */ +#define ffi_closure_RED_RVALUE (ffi_closure_OFS_RVALUE - ffi_closure_FS) + + .balign 2 + .globl C(ffi_closure_unix64_sse) + FFI_HIDDEN(C(ffi_closure_unix64_sse)) + +C(ffi_closure_unix64_sse): +L(UW5): + _CET_ENDBR + subq $ffi_closure_FS, %rsp +L(UW6): + /* cfi_adjust_cfa_offset(ffi_closure_FS) */ + + movdqa %xmm0, ffi_closure_OFS_V+0x00(%rsp) + movdqa %xmm1, ffi_closure_OFS_V+0x10(%rsp) + movdqa %xmm2, ffi_closure_OFS_V+0x20(%rsp) + movdqa %xmm3, ffi_closure_OFS_V+0x30(%rsp) + movdqa %xmm4, ffi_closure_OFS_V+0x40(%rsp) + movdqa %xmm5, ffi_closure_OFS_V+0x50(%rsp) + movdqa %xmm6, ffi_closure_OFS_V+0x60(%rsp) + movdqa %xmm7, ffi_closure_OFS_V+0x70(%rsp) + jmp L(sse_entry1) + +L(UW7): +ENDF(C(ffi_closure_unix64_sse)) + + .balign 2 + .globl C(ffi_closure_unix64) + FFI_HIDDEN(C(ffi_closure_unix64)) + +C(ffi_closure_unix64): +L(UW8): + _CET_ENDBR + subq $ffi_closure_FS, %rsp +L(UW9): + /* cfi_adjust_cfa_offset(ffi_closure_FS) */ +L(sse_entry1): + movq %rdi, ffi_closure_OFS_G+0x00(%rsp) + movq %rsi, ffi_closure_OFS_G+0x08(%rsp) + movq %rdx, ffi_closure_OFS_G+0x10(%rsp) + movq %rcx, ffi_closure_OFS_G+0x18(%rsp) + movq %r8, ffi_closure_OFS_G+0x20(%rsp) + movq %r9, ffi_closure_OFS_G+0x28(%rsp) + +#ifdef __ILP32__ + movl FFI_TRAMPOLINE_SIZE(%r10), %edi /* Load cif */ + movl FFI_TRAMPOLINE_SIZE+4(%r10), %esi /* Load fun */ + movl FFI_TRAMPOLINE_SIZE+8(%r10), %edx /* Load user_data */ +#else + movq FFI_TRAMPOLINE_SIZE(%r10), %rdi /* Load cif */ + movq FFI_TRAMPOLINE_SIZE+8(%r10), %rsi /* Load fun */ + movq FFI_TRAMPOLINE_SIZE+16(%r10), %rdx /* Load user_data */ +#endif +L(do_closure): + leaq ffi_closure_OFS_RVALUE(%rsp), %rcx /* Load rvalue */ + movq %rsp, %r8 /* Load reg_args */ + leaq ffi_closure_FS+8(%rsp), %r9 /* Load argp */ + call PLT(C(ffi_closure_unix64_inner)) /* Deallocate stack frame early; return value is now in redzone. */ - addq $200, %rsp -.LUW7: + addq $ffi_closure_FS, %rsp +L(UW10): + /* cfi_adjust_cfa_offset(-ffi_closure_FS) */ /* The first byte of the return value contains the FFI_TYPE. */ + cmpb $UNIX64_RET_LAST, %al movzbl %al, %r10d - leaq .Lload_table(%rip), %r11 - movslq (%r11, %r10, 4), %r10 - addq %r11, %r10 + leaq L(load_table)(%rip), %r11 + ja L(la) +#ifdef __CET__ + /* NB: Originally, each slot is 8 byte. 4 bytes of ENDBR64 + + 4 bytes NOP padding double slot size to 16 bytes. */ + addl %r10d, %r10d +#endif + leaq (%r11, %r10, 8), %r10 + leaq ffi_closure_RED_RVALUE(%rsp), %rsi jmp *%r10 -.Lload_table: - .long .Lld_void-.Lload_table /* FFI_TYPE_VOID */ - .long .Lld_int32-.Lload_table /* FFI_TYPE_INT */ - .long .Lld_float-.Lload_table /* FFI_TYPE_FLOAT */ - .long .Lld_double-.Lload_table /* FFI_TYPE_DOUBLE */ - .long .Lld_ldouble-.Lload_table /* FFI_TYPE_LONGDOUBLE */ - .long .Lld_int8-.Lload_table /* FFI_TYPE_UINT8 */ - .long .Lld_int8-.Lload_table /* FFI_TYPE_SINT8 */ - .long .Lld_int16-.Lload_table /* FFI_TYPE_UINT16 */ - .long .Lld_int16-.Lload_table /* FFI_TYPE_SINT16 */ - .long .Lld_int32-.Lload_table /* FFI_TYPE_UINT32 */ - .long .Lld_int32-.Lload_table /* FFI_TYPE_SINT32 */ - .long .Lld_int64-.Lload_table /* FFI_TYPE_UINT64 */ - .long .Lld_int64-.Lload_table /* FFI_TYPE_SINT64 */ - .long .Lld_struct-.Lload_table /* FFI_TYPE_STRUCT */ - .long .Lld_int64-.Lload_table /* FFI_TYPE_POINTER */ - - .align 2 -.Lld_void: + .balign 8 +L(load_table): +E(L(load_table), UNIX64_RET_VOID) + _CET_ENDBR ret - - .align 2 -.Lld_int8: - movzbl -24(%rsp), %eax +E(L(load_table), UNIX64_RET_UINT8) + _CET_ENDBR + movzbl (%rsi), %eax ret - .align 2 -.Lld_int16: - movzwl -24(%rsp), %eax +E(L(load_table), UNIX64_RET_UINT16) + _CET_ENDBR + movzwl (%rsi), %eax ret - .align 2 -.Lld_int32: - movl -24(%rsp), %eax +E(L(load_table), UNIX64_RET_UINT32) + _CET_ENDBR + movl (%rsi), %eax ret - .align 2 -.Lld_int64: - movq -24(%rsp), %rax +E(L(load_table), UNIX64_RET_SINT8) + _CET_ENDBR + movsbl (%rsi), %eax ret - - .align 2 -.Lld_float: - movss -24(%rsp), %xmm0 +E(L(load_table), UNIX64_RET_SINT16) + _CET_ENDBR + movswl (%rsi), %eax ret - .align 2 -.Lld_double: - movsd -24(%rsp), %xmm0 +E(L(load_table), UNIX64_RET_SINT32) + _CET_ENDBR + movl (%rsi), %eax ret - .align 2 -.Lld_ldouble: - fldt -24(%rsp) +E(L(load_table), UNIX64_RET_INT64) + _CET_ENDBR + movq (%rsi), %rax ret - - .align 2 -.Lld_struct: - /* There are four possibilities here, %rax/%rdx, %xmm0/%rax, - %rax/%xmm0, %xmm0/%xmm1. We collapse two by always loading - both rdx and xmm1 with the second word. For the remaining, - bit 8 set means xmm0 gets the second word, and bit 9 means - that rax gets the second word. */ - movq -24(%rsp), %rcx - movq -16(%rsp), %rdx - movq -16(%rsp), %xmm1 - testl $0x100, %eax - cmovnz %rdx, %rcx - movd %rcx, %xmm0 - testl $0x200, %eax - movq -24(%rsp), %rax - cmovnz %rdx, %rax +E(L(load_table), UNIX64_RET_XMM32) + _CET_ENDBR + movd (%rsi), %xmm0 + ret +E(L(load_table), UNIX64_RET_XMM64) + _CET_ENDBR + movq (%rsi), %xmm0 + ret +E(L(load_table), UNIX64_RET_X87) + _CET_ENDBR + fldt (%rsi) + ret +E(L(load_table), UNIX64_RET_X87_2) + _CET_ENDBR + fldt 16(%rsi) + fldt (%rsi) + ret +E(L(load_table), UNIX64_RET_ST_XMM0_RAX) + _CET_ENDBR + movq 8(%rsi), %rax + jmp L(l3) +E(L(load_table), UNIX64_RET_ST_RAX_XMM0) + _CET_ENDBR + movq 8(%rsi), %xmm0 + jmp L(l2) +E(L(load_table), UNIX64_RET_ST_XMM0_XMM1) + _CET_ENDBR + movq 8(%rsi), %xmm1 + jmp L(l3) +E(L(load_table), UNIX64_RET_ST_RAX_RDX) + _CET_ENDBR + movq 8(%rsi), %rdx +L(l2): + movq (%rsi), %rax + ret + .balign 8 +L(l3): + movq (%rsi), %xmm0 ret - /* See the comment above .Lload_sse; the same logic applies here. */ - .align 2 -.LUW8: -.Lsave_sse: - movdqa %xmm0, 48(%rsp) - movdqa %xmm1, 64(%rsp) - movdqa %xmm2, 80(%rsp) - movdqa %xmm3, 96(%rsp) - movdqa %xmm4, 112(%rsp) - movdqa %xmm5, 128(%rsp) - movdqa %xmm6, 144(%rsp) - movdqa %xmm7, 160(%rsp) - jmp .Lret_from_save_sse - -.LUW9: - .size ffi_closure_unix64,.-ffi_closure_unix64 - -#ifdef __GNUC__ -/* Only emit DWARF unwind info when building with the GNU toolchain. */ - -#ifdef HAVE_AS_X86_64_UNWIND_SECTION_TYPE - .section .eh_frame,"a",@unwind -#else - .section .eh_frame,"a",@progbits -#endif -.Lframe1: - .long .LECIE1-.LSCIE1 /* CIE Length */ -.LSCIE1: - .long 0 /* CIE Identifier Tag */ - .byte 1 /* CIE Version */ - .ascii "zR\0" /* CIE Augmentation */ - .uleb128 1 /* CIE Code Alignment Factor */ - .sleb128 -8 /* CIE Data Alignment Factor */ - .byte 0x10 /* CIE RA Column */ - .uleb128 1 /* Augmentation size */ - .byte 0x1b /* FDE Encoding (pcrel sdata4) */ - .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ - .uleb128 7 - .uleb128 8 - .byte 0x80+16 /* DW_CFA_offset, %rip offset 1*-8 */ - .uleb128 1 - .align 8 -.LECIE1: -.LSFDE1: - .long .LEFDE1-.LASFDE1 /* FDE Length */ -.LASFDE1: - .long .LASFDE1-.Lframe1 /* FDE CIE offset */ -#if HAVE_AS_X86_PCREL - .long .LUW0-. /* FDE initial location */ +L(la): call PLT(C(abort)) + +L(UW11): +ENDF(C(ffi_closure_unix64)) + + .balign 2 + .globl C(ffi_go_closure_unix64_sse) + FFI_HIDDEN(C(ffi_go_closure_unix64_sse)) + +C(ffi_go_closure_unix64_sse): +L(UW12): + _CET_ENDBR + subq $ffi_closure_FS, %rsp +L(UW13): + /* cfi_adjust_cfa_offset(ffi_closure_FS) */ + + movdqa %xmm0, ffi_closure_OFS_V+0x00(%rsp) + movdqa %xmm1, ffi_closure_OFS_V+0x10(%rsp) + movdqa %xmm2, ffi_closure_OFS_V+0x20(%rsp) + movdqa %xmm3, ffi_closure_OFS_V+0x30(%rsp) + movdqa %xmm4, ffi_closure_OFS_V+0x40(%rsp) + movdqa %xmm5, ffi_closure_OFS_V+0x50(%rsp) + movdqa %xmm6, ffi_closure_OFS_V+0x60(%rsp) + movdqa %xmm7, ffi_closure_OFS_V+0x70(%rsp) + jmp L(sse_entry2) + +L(UW14): +ENDF(C(ffi_go_closure_unix64_sse)) + + .balign 2 + .globl C(ffi_go_closure_unix64) + FFI_HIDDEN(C(ffi_go_closure_unix64)) + +C(ffi_go_closure_unix64): +L(UW15): + _CET_ENDBR + subq $ffi_closure_FS, %rsp +L(UW16): + /* cfi_adjust_cfa_offset(ffi_closure_FS) */ +L(sse_entry2): + movq %rdi, ffi_closure_OFS_G+0x00(%rsp) + movq %rsi, ffi_closure_OFS_G+0x08(%rsp) + movq %rdx, ffi_closure_OFS_G+0x10(%rsp) + movq %rcx, ffi_closure_OFS_G+0x18(%rsp) + movq %r8, ffi_closure_OFS_G+0x20(%rsp) + movq %r9, ffi_closure_OFS_G+0x28(%rsp) + +#ifdef __ILP32__ + movl 4(%r10), %edi /* Load cif */ + movl 8(%r10), %esi /* Load fun */ + movl %r10d, %edx /* Load closure (user_data) */ #else - .long .LUW0@rel + movq 8(%r10), %rdi /* Load cif */ + movq 16(%r10), %rsi /* Load fun */ + movq %r10, %rdx /* Load closure (user_data) */ #endif - .long .LUW4-.LUW0 /* FDE address range */ - .uleb128 0x0 /* Augmentation size */ + jmp L(do_closure) - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LUW1-.LUW0 +L(UW17): +ENDF(C(ffi_go_closure_unix64)) - /* New stack frame based off rbp. This is a itty bit of unwind - trickery in that the CFA *has* changed. There is no easy way - to describe it correctly on entry to the function. Fortunately, - it doesn't matter too much since at all points we can correctly - unwind back to ffi_call. Note that the location to which we - moved the return address is (the new) CFA-8, so from the - perspective of the unwind info, it hasn't moved. */ - .byte 0xc /* DW_CFA_def_cfa, %rbp offset 32 */ - .uleb128 6 - .uleb128 32 - .byte 0x80+6 /* DW_CFA_offset, %rbp offset 2*-8 */ - .uleb128 2 - .byte 0xa /* DW_CFA_remember_state */ +/* Sadly, OSX cctools-as doesn't understand .cfi directives at all. */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LUW2-.LUW1 - .byte 0xc /* DW_CFA_def_cfa, %rsp offset 8 */ - .uleb128 7 - .uleb128 8 - .byte 0xc0+6 /* DW_CFA_restore, %rbp */ +#ifdef __APPLE__ +.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support +EHFrame0: +#elif defined(HAVE_AS_X86_64_UNWIND_SECTION_TYPE) +.section .eh_frame,"a",@unwind +#else +.section .eh_frame,"a",@progbits +#endif - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LUW3-.LUW2 - .byte 0xb /* DW_CFA_restore_state */ +#ifdef HAVE_AS_X86_PCREL +# define PCREL(X) X - . +#else +# define PCREL(X) X@rel +#endif - .align 8 -.LEFDE1: -.LSFDE3: - .long .LEFDE3-.LASFDE3 /* FDE Length */ -.LASFDE3: - .long .LASFDE3-.Lframe1 /* FDE CIE offset */ -#if HAVE_AS_X86_PCREL - .long .LUW5-. /* FDE initial location */ +/* Simplify advancing between labels. Assume DW_CFA_advance_loc1 fits. */ +#ifdef __CET__ +/* Use DW_CFA_advance_loc2 when IBT is enabled. */ +# define ADV(N, P) .byte 3; .2byte L(N)-L(P) #else - .long .LUW5@rel +# define ADV(N, P) .byte 2, L(N)-L(P) #endif - .long .LUW9-.LUW5 /* FDE address range */ - .uleb128 0x0 /* Augmentation size */ - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LUW6-.LUW5 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .uleb128 208 + .balign 8 +L(CIE): + .set L(set0),L(ECIE)-L(SCIE) + .long L(set0) /* CIE Length */ +L(SCIE): + .long 0 /* CIE Identifier Tag */ + .byte 1 /* CIE Version */ + .ascii "zR\0" /* CIE Augmentation */ + .byte 1 /* CIE Code Alignment Factor */ + .byte 0x78 /* CIE Data Alignment Factor */ + .byte 0x10 /* CIE RA Column */ + .byte 1 /* Augmentation size */ + .byte 0x1b /* FDE Encoding (pcrel sdata4) */ + .byte 0xc, 7, 8 /* DW_CFA_def_cfa, %rsp offset 8 */ + .byte 0x80+16, 1 /* DW_CFA_offset, %rip offset 1*-8 */ + .balign 8 +L(ECIE): + + .set L(set1),L(EFDE1)-L(SFDE1) + .long L(set1) /* FDE Length */ +L(SFDE1): + .long L(SFDE1)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW0)) /* Initial location */ + .long L(UW4)-L(UW0) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW1, UW0) + .byte 0xc, 6, 32 /* DW_CFA_def_cfa, %rbp 32 */ + .byte 0x80+6, 2 /* DW_CFA_offset, %rbp 2*-8 */ + ADV(UW2, UW1) .byte 0xa /* DW_CFA_remember_state */ - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LUW7-.LUW6 - .byte 0xe /* DW_CFA_def_cfa_offset */ - .uleb128 8 - - .byte 0x4 /* DW_CFA_advance_loc4 */ - .long .LUW8-.LUW7 + .byte 0xc, 7, 8 /* DW_CFA_def_cfa, %rsp 8 */ + .byte 0xc0+6 /* DW_CFA_restore, %rbp */ + ADV(UW3, UW2) .byte 0xb /* DW_CFA_restore_state */ + .balign 8 +L(EFDE1): + + .set L(set2),L(EFDE2)-L(SFDE2) + .long L(set2) /* FDE Length */ +L(SFDE2): + .long L(SFDE2)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW5)) /* Initial location */ + .long L(UW7)-L(UW5) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW6, UW5) + .byte 0xe /* DW_CFA_def_cfa_offset */ + .byte ffi_closure_FS + 8, 1 /* uleb128, assuming 128 <= FS < 255 */ + .balign 8 +L(EFDE2): + + .set L(set3),L(EFDE3)-L(SFDE3) + .long L(set3) /* FDE Length */ +L(SFDE3): + .long L(SFDE3)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW8)) /* Initial location */ + .long L(UW11)-L(UW8) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW9, UW8) + .byte 0xe /* DW_CFA_def_cfa_offset */ + .byte ffi_closure_FS + 8, 1 /* uleb128, assuming 128 <= FS < 255 */ + ADV(UW10, UW9) + .byte 0xe, 8 /* DW_CFA_def_cfa_offset 8 */ +L(EFDE3): + + .set L(set4),L(EFDE4)-L(SFDE4) + .long L(set4) /* FDE Length */ +L(SFDE4): + .long L(SFDE4)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW12)) /* Initial location */ + .long L(UW14)-L(UW12) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW13, UW12) + .byte 0xe /* DW_CFA_def_cfa_offset */ + .byte ffi_closure_FS + 8, 1 /* uleb128, assuming 128 <= FS < 255 */ + .balign 8 +L(EFDE4): + + .set L(set5),L(EFDE5)-L(SFDE5) + .long L(set5) /* FDE Length */ +L(SFDE5): + .long L(SFDE5)-L(CIE) /* FDE CIE offset */ + .long PCREL(L(UW15)) /* Initial location */ + .long L(UW17)-L(UW15) /* Address range */ + .byte 0 /* Augmentation size */ + ADV(UW16, UW15) + .byte 0xe /* DW_CFA_def_cfa_offset */ + .byte ffi_closure_FS + 8, 1 /* uleb128, assuming 128 <= FS < 255 */ + .balign 8 +L(EFDE5): +#ifdef __APPLE__ + .subsections_via_symbols + .section __LD,__compact_unwind,regular,debug + + /* compact unwind for ffi_call_unix64 */ + .quad C(ffi_call_unix64) + .set L1,L(UW4)-L(UW0) + .long L1 + .long 0x04000000 /* use dwarf unwind info */ + .quad 0 + .quad 0 + + /* compact unwind for ffi_closure_unix64_sse */ + .quad C(ffi_closure_unix64_sse) + .set L2,L(UW7)-L(UW5) + .long L2 + .long 0x04000000 /* use dwarf unwind info */ + .quad 0 + .quad 0 + + /* compact unwind for ffi_closure_unix64 */ + .quad C(ffi_closure_unix64) + .set L3,L(UW11)-L(UW8) + .long L3 + .long 0x04000000 /* use dwarf unwind info */ + .quad 0 + .quad 0 + + /* compact unwind for ffi_go_closure_unix64_sse */ + .quad C(ffi_go_closure_unix64_sse) + .set L4,L(UW14)-L(UW12) + .long L4 + .long 0x04000000 /* use dwarf unwind info */ + .quad 0 + .quad 0 + + /* compact unwind for ffi_go_closure_unix64 */ + .quad C(ffi_go_closure_unix64) + .set L5,L(UW17)-L(UW15) + .long L5 + .long 0x04000000 /* use dwarf unwind info */ + .quad 0 + .quad 0 +#endif - .align 8 -.LEFDE3: - -#endif /* __GNUC__ */ - #endif /* __x86_64__ */ - #if defined __ELF__ && defined __linux__ .section .note.GNU-stack,"",@progbits #endif diff --git a/native/libffi/src/x86/win64.S b/native/libffi/src/x86/win64.S index 3f4981c4df..8b18330ed9 100644 --- a/native/libffi/src/x86/win64.S +++ b/native/libffi/src/x86/win64.S @@ -1,6 +1,8 @@ +#ifdef __x86_64__ #define LIBFFI_ASM #include #include +<<<<<<< HEAD /* Constants for ffi_call_win64 */ #define STACK 0 @@ -257,15 +259,40 @@ ret_void$: ffi_call_win64 ENDP _TEXT ENDS END +======= +#include +#include "asmnames.h" +#if defined(HAVE_AS_CFI_PSEUDO_OP) + .cfi_sections .debug_frame +#endif +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 + +#ifdef X86_WIN64 +#define SEH(...) __VA_ARGS__ +#define arg0 %rcx +#define arg1 %rdx +#define arg2 %r8 +#define arg3 %r9 #else +#define SEH(...) +#define arg0 %rdi +#define arg1 %rsi +#define arg2 %rdx +#define arg3 %rcx +#endif -#ifdef SYMBOL_UNDERSCORE -#define SYMBOL_NAME(name) _##name +/* This macro allows the safe creation of jump tables without an + actual table. The entry points into the table are all 8 bytes. + The use of ORG asserts that we're at the correct location. */ +/* ??? The clang assembler doesn't handle .org with symbolic expressions. */ +#if defined(__clang__) || defined(__APPLE__) || (defined (__sun__) && defined(__svr4__)) +# define E(BASE, X) .balign 8 #else -#define SYMBOL_NAME(name) name +# define E(BASE, X) .balign 8; .org BASE + (X) * 8 #endif +<<<<<<< HEAD .text .extern SYMBOL_NAME(ffi_closure_win64_inner) @@ -518,3 +545,211 @@ Lch_done: .seh_endproc #endif /* !_MSC_VER */ +======= + .text + +/* ffi_call_win64 (void *stack, struct win64_call_frame *frame, void *r10) + + Bit o trickiness here -- FRAME is the base of the stack frame + for this function. This has been allocated by ffi_call. We also + deallocate some of the stack that has been alloca'd. */ + + .align 8 + .globl C(ffi_call_win64) + FFI_HIDDEN(C(ffi_call_win64)) + + SEH(.seh_proc ffi_call_win64) +C(ffi_call_win64): + cfi_startproc + _CET_ENDBR + /* Set up the local stack frame and install it in rbp/rsp. */ + movq (%rsp), %rax + movq %rbp, (arg1) + movq %rax, 8(arg1) + movq arg1, %rbp + cfi_def_cfa(%rbp, 16) + cfi_rel_offset(%rbp, 0) + SEH(.seh_pushreg %rbp) + SEH(.seh_setframe %rbp, 0) + SEH(.seh_endprologue) + movq arg0, %rsp + + movq arg2, %r10 + + /* Load all slots into both general and xmm registers. */ + movq (%rsp), %rcx + movsd (%rsp), %xmm0 + movq 8(%rsp), %rdx + movsd 8(%rsp), %xmm1 + movq 16(%rsp), %r8 + movsd 16(%rsp), %xmm2 + movq 24(%rsp), %r9 + movsd 24(%rsp), %xmm3 + + call *16(%rbp) + + movl 24(%rbp), %ecx + movq 32(%rbp), %r8 + leaq 0f(%rip), %r10 + cmpl $FFI_TYPE_SMALL_STRUCT_4B, %ecx + leaq (%r10, %rcx, 8), %r10 + ja 99f + _CET_NOTRACK jmp *%r10 + +/* Below, we're space constrained most of the time. Thus we eschew the + modern "mov, pop, ret" sequence (5 bytes) for "leave, ret" (2 bytes). */ +.macro epilogue + leaveq + cfi_remember_state + cfi_def_cfa(%rsp, 8) + cfi_restore(%rbp) + ret + cfi_restore_state +.endm + + .align 8 +0: +E(0b, FFI_TYPE_VOID) + epilogue +E(0b, FFI_TYPE_INT) + movslq %eax, %rax + movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_FLOAT) + movss %xmm0, (%r8) + epilogue +E(0b, FFI_TYPE_DOUBLE) + movsd %xmm0, (%r8) + epilogue +// FFI_TYPE_LONGDOUBLE may be FFI_TYPE_DOUBLE but we need a different value here. +E(0b, FFI_TYPE_DOUBLE + 1) + call PLT(C(abort)) +E(0b, FFI_TYPE_UINT8) + movzbl %al, %eax + movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_SINT8) + movsbq %al, %rax + jmp 98f +E(0b, FFI_TYPE_UINT16) + movzwl %ax, %eax + movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_SINT16) + movswq %ax, %rax + jmp 98f +E(0b, FFI_TYPE_UINT32) + movl %eax, %eax + movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_SINT32) + movslq %eax, %rax + movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_UINT64) +98: movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_SINT64) + movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_STRUCT) + epilogue +E(0b, FFI_TYPE_POINTER) + movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_COMPLEX) + call PLT(C(abort)) +E(0b, FFI_TYPE_SMALL_STRUCT_1B) + movb %al, (%r8) + epilogue +E(0b, FFI_TYPE_SMALL_STRUCT_2B) + movw %ax, (%r8) + epilogue +E(0b, FFI_TYPE_SMALL_STRUCT_4B) + movl %eax, (%r8) + epilogue + + .align 8 +99: call PLT(C(abort)) + + epilogue + + cfi_endproc + SEH(.seh_endproc) + + +/* 32 bytes of outgoing register stack space, 8 bytes of alignment, + 16 bytes of result, 32 bytes of xmm registers. */ +#define ffi_clo_FS (32+8+16+32) +#define ffi_clo_OFF_R (32+8) +#define ffi_clo_OFF_X (32+8+16) + + .align 8 + .globl C(ffi_go_closure_win64) + FFI_HIDDEN(C(ffi_go_closure_win64)) + + SEH(.seh_proc ffi_go_closure_win64) +C(ffi_go_closure_win64): + cfi_startproc + _CET_ENDBR + /* Save all integer arguments into the incoming reg stack space. */ + movq %rcx, 8(%rsp) + movq %rdx, 16(%rsp) + movq %r8, 24(%rsp) + movq %r9, 32(%rsp) + + movq 8(%r10), %rcx /* load cif */ + movq 16(%r10), %rdx /* load fun */ + movq %r10, %r8 /* closure is user_data */ + jmp 0f + cfi_endproc + SEH(.seh_endproc) + + .align 8 + .globl C(ffi_closure_win64) + FFI_HIDDEN(C(ffi_closure_win64)) + + SEH(.seh_proc ffi_closure_win64) +C(ffi_closure_win64): + cfi_startproc + _CET_ENDBR + /* Save all integer arguments into the incoming reg stack space. */ + movq %rcx, 8(%rsp) + movq %rdx, 16(%rsp) + movq %r8, 24(%rsp) + movq %r9, 32(%rsp) + + movq FFI_TRAMPOLINE_SIZE(%r10), %rcx /* load cif */ + movq FFI_TRAMPOLINE_SIZE+8(%r10), %rdx /* load fun */ + movq FFI_TRAMPOLINE_SIZE+16(%r10), %r8 /* load user_data */ +0: + subq $ffi_clo_FS, %rsp + cfi_adjust_cfa_offset(ffi_clo_FS) + SEH(.seh_stackalloc ffi_clo_FS) + SEH(.seh_endprologue) + + /* Save all sse arguments into the stack frame. */ + movsd %xmm0, ffi_clo_OFF_X(%rsp) + movsd %xmm1, ffi_clo_OFF_X+8(%rsp) + movsd %xmm2, ffi_clo_OFF_X+16(%rsp) + movsd %xmm3, ffi_clo_OFF_X+24(%rsp) + + leaq ffi_clo_OFF_R(%rsp), %r9 + call PLT(C(ffi_closure_win64_inner)) + + /* Load the result into both possible result registers. */ + movq ffi_clo_OFF_R(%rsp), %rax + movsd ffi_clo_OFF_R(%rsp), %xmm0 + + addq $ffi_clo_FS, %rsp + cfi_adjust_cfa_offset(-ffi_clo_FS) + ret + + cfi_endproc + SEH(.seh_endproc) +#endif /* __x86_64__ */ + +#if defined __ELF__ && defined __linux__ + .section .note.GNU-stack,"",@progbits +#endif +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 diff --git a/native/libffi/src/x86/win64_intel.S b/native/libffi/src/x86/win64_intel.S new file mode 100644 index 0000000000..970a4f997a --- /dev/null +++ b/native/libffi/src/x86/win64_intel.S @@ -0,0 +1,238 @@ +#define LIBFFI_ASM +#include +#include +#include +#include "asmnames.h" + +#if defined(HAVE_AS_CFI_PSEUDO_OP) + .cfi_sections .debug_frame +#endif + +#ifdef X86_WIN64 +#define SEH(...) __VA_ARGS__ +#define arg0 rcx +#define arg1 rdx +#define arg2 r8 +#define arg3 r9 +#else +#define SEH(...) +#define arg0 rdi +#define arg1 rsi +#define arg2 rdx +#define arg3 rcx +#endif + +/* This macro allows the safe creation of jump tables without an + actual table. The entry points into the table are all 8 bytes. + The use of ORG asserts that we're at the correct location. */ +/* ??? The clang assembler doesn't handle .org with symbolic expressions. */ +#if defined(__clang__) || defined(__APPLE__) || (defined (__sun__) && defined(__svr4__)) +# define E(BASE, X) ALIGN 8 +#else +# define E(BASE, X) ALIGN 8; ORG BASE + (X) * 8 +#endif + + .CODE + extern PLT(C(abort)):near + extern C(ffi_closure_win64_inner):near + +/* ffi_call_win64 (void *stack, struct win64_call_frame *frame, void *r10) + + Bit o trickiness here -- FRAME is the base of the stack frame + for this function. This has been allocated by ffi_call. We also + deallocate some of the stack that has been alloca'd. */ + + ALIGN 8 + PUBLIC C(ffi_call_win64) + + ; SEH(.safesh ffi_call_win64) +C(ffi_call_win64) proc SEH(frame) + cfi_startproc + /* Set up the local stack frame and install it in rbp/rsp. */ + mov RAX, [RSP] ; movq (%rsp), %rax + mov [arg1], RBP ; movq %rbp, (arg1) + mov [arg1 + 8], RAX; movq %rax, 8(arg1) + mov RBP, arg1; movq arg1, %rbp + cfi_def_cfa(rbp, 16) + cfi_rel_offset(rbp, 0) + SEH(.pushreg rbp) + SEH(.setframe rbp, 0) + SEH(.endprolog) + mov RSP, arg0 ; movq arg0, %rsp + + mov R10, arg2 ; movq arg2, %r10 + + /* Load all slots into both general and xmm registers. */ + mov RCX, [RSP] ; movq (%rsp), %rcx + movsd XMM0, qword ptr [RSP] ; movsd (%rsp), %xmm0 + mov RDX, [RSP + 8] ;movq 8(%rsp), %rdx + movsd XMM1, qword ptr [RSP + 8]; movsd 8(%rsp), %xmm1 + mov R8, [RSP + 16] ; movq 16(%rsp), %r8 + movsd XMM2, qword ptr [RSP + 16] ; movsd 16(%rsp), %xmm2 + mov R9, [RSP + 24] ; movq 24(%rsp), %r9 + movsd XMM3, qword ptr [RSP + 24] ;movsd 24(%rsp), %xmm3 + + CALL qword ptr [RBP + 16] ; call *16(%rbp) + + mov ECX, [RBP + 24] ; movl 24(%rbp), %ecx + mov R8, [RBP + 32] ; movq 32(%rbp), %r8 + LEA R10, ffi_call_win64_tab ; leaq 0f(%rip), %r10 + CMP ECX, FFI_TYPE_SMALL_STRUCT_4B ; cmpl $FFI_TYPE_SMALL_STRUCT_4B, %ecx + LEA R10, [R10 + RCX*8] ; leaq (%r10, %rcx, 8), %r10 + JA L99 ; ja 99f + JMP R10 ; jmp *%r10 + +/* Below, we're space constrained most of the time. Thus we eschew the + modern "mov, pop, ret" sequence (5 bytes) for "leave, ret" (2 bytes). */ +epilogue macro + LEAVE + cfi_remember_state + cfi_def_cfa(rsp, 8) + cfi_restore(rbp) + RET + cfi_restore_state +endm + + ALIGN 8 +ffi_call_win64_tab LABEL NEAR +E(0b, FFI_TYPE_VOID) + epilogue +E(0b, FFI_TYPE_INT) + movsxd rax, eax ; movslq %eax, %rax + mov qword ptr [r8], rax; movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_FLOAT) + movss dword ptr [r8], xmm0 ; movss %xmm0, (%r8) + epilogue +E(0b, FFI_TYPE_DOUBLE) + movsd qword ptr[r8], xmm0; movsd %xmm0, (%r8) + epilogue +// FFI_TYPE_LONGDOUBLE may be FFI_TYPE_DOUBLE but we need a different value here. +E(0b, FFI_TYPE_DOUBLE + 1) + call PLT(C(abort)) +E(0b, FFI_TYPE_UINT8) + movzx eax, al ;movzbl %al, %eax + mov qword ptr[r8], rax; movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_SINT8) + movsx rax, al ; movsbq %al, %rax + jmp L98 +E(0b, FFI_TYPE_UINT16) + movzx eax, ax ; movzwl %ax, %eax + mov qword ptr[r8], rax; movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_SINT16) + movsx rax, ax; movswq %ax, %rax + jmp L98 +E(0b, FFI_TYPE_UINT32) + mov eax, eax; movl %eax, %eax + mov qword ptr[r8], rax ; movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_SINT32) + movsxd rax, eax; movslq %eax, %rax + mov qword ptr [r8], rax; movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_UINT64) +L98 LABEL near + mov qword ptr [r8], rax ; movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_SINT64) + mov qword ptr [r8], rax;movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_STRUCT) + epilogue +E(0b, FFI_TYPE_POINTER) + mov qword ptr [r8], rax ;movq %rax, (%r8) + epilogue +E(0b, FFI_TYPE_COMPLEX) + call PLT(C(abort)) +E(0b, FFI_TYPE_SMALL_STRUCT_1B) + mov byte ptr [r8], al ; movb %al, (%r8) + epilogue +E(0b, FFI_TYPE_SMALL_STRUCT_2B) + mov word ptr [r8], ax ; movw %ax, (%r8) + epilogue +E(0b, FFI_TYPE_SMALL_STRUCT_4B) + mov dword ptr [r8], eax ; movl %eax, (%r8) + epilogue + + align 8 +L99 LABEL near + call PLT(C(abort)) + + epilogue + + cfi_endproc + C(ffi_call_win64) endp + + +/* 32 bytes of outgoing register stack space, 8 bytes of alignment, + 16 bytes of result, 32 bytes of xmm registers. */ +#define ffi_clo_FS (32+8+16+32) +#define ffi_clo_OFF_R (32+8) +#define ffi_clo_OFF_X (32+8+16) + + align 8 + PUBLIC C(ffi_go_closure_win64) + +C(ffi_go_closure_win64) proc + cfi_startproc + /* Save all integer arguments into the incoming reg stack space. */ + mov qword ptr [rsp + 8], rcx; movq %rcx, 8(%rsp) + mov qword ptr [rsp + 16], rdx; movq %rdx, 16(%rsp) + mov qword ptr [rsp + 24], r8; movq %r8, 24(%rsp) + mov qword ptr [rsp + 32], r9 ;movq %r9, 32(%rsp) + + mov rcx, qword ptr [r10 + 8]; movq 8(%r10), %rcx /* load cif */ + mov rdx, qword ptr [r10 + 16]; movq 16(%r10), %rdx /* load fun */ + mov r8, r10 ; movq %r10, %r8 /* closure is user_data */ + jmp ffi_closure_win64_2 + cfi_endproc + C(ffi_go_closure_win64) endp + + align 8 + +PUBLIC C(ffi_closure_win64) +C(ffi_closure_win64) PROC FRAME + cfi_startproc + /* Save all integer arguments into the incoming reg stack space. */ + mov qword ptr [rsp + 8], rcx; movq %rcx, 8(%rsp) + mov qword ptr [rsp + 16], rdx; movq %rdx, 16(%rsp) + mov qword ptr [rsp + 24], r8; movq %r8, 24(%rsp) + mov qword ptr [rsp + 32], r9; movq %r9, 32(%rsp) + + mov rcx, qword ptr [FFI_TRAMPOLINE_SIZE + r10] ;movq FFI_TRAMPOLINE_SIZE(%r10), %rcx /* load cif */ + mov rdx, qword ptr [FFI_TRAMPOLINE_SIZE + 8 + r10] ; movq FFI_TRAMPOLINE_SIZE+8(%r10), %rdx /* load fun */ + mov r8, qword ptr [FFI_TRAMPOLINE_SIZE+16+r10] ;movq FFI_TRAMPOLINE_SIZE+16(%r10), %r8 /* load user_data */ +ffi_closure_win64_2 LABEL near + sub rsp, ffi_clo_FS ;subq $ffi_clo_FS, %rsp + cfi_adjust_cfa_offset(ffi_clo_FS) + SEH(.allocstack ffi_clo_FS) + SEH(.endprolog) + + /* Save all sse arguments into the stack frame. */ + movsd qword ptr [ffi_clo_OFF_X + rsp], xmm0 ; movsd %xmm0, ffi_clo_OFF_X(%rsp) + movsd qword ptr [ffi_clo_OFF_X+8+rsp], xmm1 ; movsd %xmm1, ffi_clo_OFF_X+8(%rsp) + movsd qword ptr [ffi_clo_OFF_X+16+rsp], xmm2 ; movsd %xmm2, ffi_clo_OFF_X+16(%rsp) + movsd qword ptr [ffi_clo_OFF_X+24+rsp], xmm3 ; movsd %xmm3, ffi_clo_OFF_X+24(%rsp) + + lea r9, [ffi_clo_OFF_R + rsp] ; leaq ffi_clo_OFF_R(%rsp), %r9 + call C(ffi_closure_win64_inner) + + /* Load the result into both possible result registers. */ + + mov rax, qword ptr [ffi_clo_OFF_R + rsp] ;movq ffi_clo_OFF_R(%rsp), %rax + movsd xmm0, qword ptr [rsp + ffi_clo_OFF_R] ;movsd ffi_clo_OFF_R(%rsp), %xmm0 + + add rsp, ffi_clo_FS ;addq $ffi_clo_FS, %rsp + cfi_adjust_cfa_offset(-ffi_clo_FS) + ret + + cfi_endproc + C(ffi_closure_win64) endp + +#if defined __ELF__ && defined __linux__ + .section .note.GNU-stack,"",@progbits +#endif +_text ends +end \ No newline at end of file diff --git a/native/libffi/src/xtensa/ffi.c b/native/libffi/src/xtensa/ffi.c index fd94dafbe3..9a0575ff90 100644 --- a/native/libffi/src/xtensa/ffi.c +++ b/native/libffi/src/xtensa/ffi.c @@ -89,7 +89,7 @@ ffi_status ffi_prep_cif_machdep(ffi_cif *cif) /* Round the stack up to a full 4 register frame, just in case (we use this size in movsp). This way, it's also a multiple of 8 bytes for 64-bit arguments. */ - cif->bytes = ALIGN(cif->bytes, 16); + cif->bytes = FFI_ALIGN(cif->bytes, 16); return FFI_OK; } @@ -205,7 +205,7 @@ void ffi_call(ffi_cif* cif, void(*fn)(void), void *rvalue, void **avalue) if (flags == FFI_TYPE_STRUCT && (rsize <= 16 || rvalue == NULL)) { - alloc = alloca(ALIGN(rsize, 4)); + alloc = alloca(FFI_ALIGN(rsize, 4)); ecif.rvalue = alloc; } else diff --git a/native/libffi/src/xtensa/sysv.S b/native/libffi/src/xtensa/sysv.S index 64e6a0918d..e9421796fd 100644 --- a/native/libffi/src/xtensa/sysv.S +++ b/native/libffi/src/xtensa/sysv.S @@ -169,8 +169,13 @@ ENTRY(ffi_cacheflush) entry a1, 16 -1: dhwbi a2, 0 +1: +#if XCHAL_DCACHE_SIZE + dhwbi a2, 0 +#endif +#if XCHAL_ICACHE_SIZE ihi a2, 0 +#endif addi a2, a2, 4 blt a2, a3, 1b diff --git a/native/libffi/testsuite/Makefile.am b/native/libffi/testsuite/Makefile.am index da10465d28..e705afc8a5 100644 --- a/native/libffi/testsuite/Makefile.am +++ b/native/libffi/testsuite/Makefile.am @@ -6,6 +6,7 @@ EXTRA_DEJAGNU_SITE_CONFIG=../local.exp CLEANFILES = *.exe core* *.log *.sum +<<<<<<< HEAD EXTRA_DIST = config/default.exp libffi.call/cls_19byte.c \ libffi.call/cls_align_longdouble_split.c \ libffi.call/closure_loc_fn0.c libffi.call/cls_schar.c \ @@ -83,3 +84,119 @@ libffi.call/va_struct3.c \ libffi.call/strlen2.c \ libffi.call/strlen3.c \ libffi.call/strlen4.c +======= +EXTRA_DIST = lib/target-libpath.exp lib/libffi.exp lib/wrapper.exp \ +libffi.call/strlen4.c libffi.call/struct10.c libffi.call/many_mixed.c \ +libffi.call/float.c libffi.call/struct5.c libffi.call/return_fl3.c \ +libffi.call/return_fl1.c libffi.call/call.exp libffi.call/pyobjc-tc.c \ +libffi.call/float_va.c libffi.call/struct8.c libffi.call/pr1172638.c \ +libffi.call/return_sc.c libffi.call/va_struct1.c \ +libffi.call/align_stdcall.c libffi.call/struct9.c libffi.call/va_1.c \ +libffi.call/va_struct2.c libffi.call/return_fl2.c \ +libffi.call/align_mixed.c libffi.call/ffitest.h libffi.call/struct4.c \ +libffi.call/return_ldl.c libffi.call/float3.c libffi.call/return_sl.c \ +libffi.call/return_dbl1.c libffi.call/err_bad_typedef.c \ +libffi.call/return_ll1.c libffi.call/return_dbl2.c \ +libffi.call/negint.c libffi.closures/nested_struct3.c \ +libffi.call/struct2.c libffi.call/struct3.c libffi.call/return_fl.c \ +libffi.call/offsets.c libffi.call/struct7.c libffi.call/va_struct3.c \ +libffi.call/float1.c libffi.call/uninitialized.c libffi.call/many2.c \ +libffi.call/struct6.c libffi.call/strlen2.c libffi.call/float2.c \ +libffi.call/return_ul.c libffi.call/struct1.c libffi.call/strlen3.c \ +libffi.call/return_dbl.c libffi.call/float4.c libffi.call/many.c \ +libffi.call/strlen.c libffi.call/return_uc.c libffi.call/many_double.c \ +libffi.call/return_ll.c libffi.call/promotion.c \ +libffi.complex/complex_defs_longdouble.inc \ +libffi.complex/cls_align_complex_float.c \ +libffi.complex/cls_complex_va_float.c \ +libffi.complex/cls_complex_struct_float.c \ +libffi.complex/return_complex2_longdouble.c \ +libffi.complex/cls_complex_float.c \ +libffi.complex/return_complex_longdouble.c \ +libffi.complex/return_complex2_float.c libffi.complex/cls_complex.inc \ +libffi.complex/cls_complex_va_longdouble.c \ +libffi.complex/return_complex_double.c \ +libffi.complex/return_complex.inc libffi.complex/many_complex.inc \ +libffi.complex/complex_float.c libffi.complex/cls_align_complex.inc \ +libffi.complex/return_complex2_double.c \ +libffi.complex/many_complex_float.c libffi.complex/ffitest.h \ +libffi.complex/return_complex1_double.c \ +libffi.complex/cls_complex_struct_longdouble.c \ +libffi.complex/complex_defs_double.inc \ +libffi.complex/cls_complex_va_double.c \ +libffi.complex/many_complex_double.c \ +libffi.complex/return_complex2.inc \ +libffi.complex/return_complex1_float.c \ +libffi.complex/complex_longdouble.c \ +libffi.complex/complex_defs_float.inc \ +libffi.complex/cls_complex_double.c \ +libffi.complex/cls_align_complex_double.c \ +libffi.complex/cls_align_complex_longdouble.c \ +libffi.complex/complex_double.c libffi.complex/cls_complex_va.inc \ +libffi.complex/many_complex_longdouble.c libffi.complex/complex.inc \ +libffi.complex/return_complex1_longdouble.c \ +libffi.complex/complex_int.c libffi.complex/cls_complex_longdouble.c \ +libffi.complex/cls_complex_struct_double.c \ +libffi.complex/return_complex1.inc libffi.complex/complex.exp \ +libffi.complex/cls_complex_struct.inc \ +libffi.complex/return_complex_float.c libffi.go/closure1.c \ +libffi.go/aa-direct.c libffi.go/ffitest.h libffi.go/go.exp \ +libffi.go/static-chain.h libffi.bhaible/bhaible.exp \ +libffi.bhaible/test-call.c libffi.bhaible/alignof.h \ +libffi.bhaible/testcases.c libffi.bhaible/test-callback.c \ +libffi.bhaible/Makefile libffi.bhaible/README config/default.exp \ +libffi.closures/cls_multi_sshort.c \ +libffi.closures/cls_align_longdouble_split2.c \ +libffi.closures/cls_1_1byte.c libffi.closures/cls_uint_va.c \ +libffi.closures/cls_3_1byte.c libffi.closures/cls_many_mixed_args.c \ +libffi.closures/cls_20byte1.c libffi.closures/cls_pointer_stack.c \ +libffi.closures/cls_align_float.c libffi.closures/cls_5_1_byte.c \ +libffi.closures/cls_9byte1.c libffi.closures/cls_align_uint32.c \ +libffi.closures/stret_medium.c libffi.closures/cls_3byte1.c \ +libffi.closures/cls_align_uint64.c libffi.closures/cls_longdouble_va.c \ +libffi.closures/cls_align_pointer.c libffi.closures/cls_19byte.c \ +libffi.closures/cls_ushort.c libffi.closures/cls_align_sint32.c \ +libffi.closures/cls_ulonglong.c libffi.closures/cls_struct_va1.c \ +libffi.closures/cls_9byte2.c libffi.closures/closure_fn5.c \ +libffi.closures/cls_5byte.c libffi.closures/cls_3float.c \ +libffi.closures/closure.exp libffi.closures/cls_schar.c \ +libffi.closures/closure_fn4.c libffi.closures/cls_uchar_va.c \ +libffi.closures/closure_fn0.c libffi.closures/huge_struct.c \ +libffi.closures/cls_ushort_va.c \ +libffi.closures/cls_64byte.c libffi.closures/cls_longdouble.c \ +libffi.closures/cls_ulong_va.c libffi.closures/cls_6_1_byte.c \ +libffi.closures/cls_align_uint16.c libffi.closures/closure_fn2.c \ +libffi.closures/unwindtest_ffi_call.cc \ +libffi.closures/cls_multi_ushortchar.c libffi.closures/cls_8byte.c \ +libffi.closures/ffitest.h libffi.closures/nested_struct8.c \ +libffi.closures/cls_pointer.c libffi.closures/nested_struct2.c \ +libffi.closures/nested_struct.c libffi.closures/cls_multi_schar.c \ +libffi.closures/cls_align_longdouble_split.c \ +libffi.closures/cls_uchar.c libffi.closures/nested_struct9.c \ +libffi.closures/cls_float.c libffi.closures/stret_medium2.c \ +libffi.closures/closure_loc_fn0.c libffi.closures/cls_6byte.c \ +libffi.closures/closure_simple.c libffi.closures/cls_align_double.c \ +libffi.closures/cls_multi_uchar.c libffi.closures/cls_4_1byte.c \ +libffi.closures/closure_fn3.c libffi.closures/cls_align_sint64.c \ +libffi.closures/nested_struct1.c libffi.closures/unwindtest.cc \ +libffi.closures/nested_struct5.c libffi.closures/cls_multi_ushort.c \ +libffi.closures/nested_struct11.c \ +libffi.closures/cls_multi_sshortchar.c \ +libffi.closures/cls_align_longdouble.c \ +libffi.closures/cls_dbls_struct.c \ +libffi.closures/cls_many_mixed_float_double.c \ +libffi.closures/stret_large.c libffi.closures/stret_large2.c \ +libffi.closures/cls_align_sint16.c libffi.closures/cls_2byte.c \ +libffi.closures/nested_struct4.c libffi.closures/problem1.c \ +libffi.closures/testclosure.c libffi.closures/nested_struct6.c \ +libffi.closures/cls_4byte.c libffi.closures/cls_24byte.c \ +libffi.closures/nested_struct10.c libffi.closures/cls_uint.c \ +libffi.closures/cls_12byte.c libffi.closures/cls_sint.c \ +libffi.closures/cls_7_1_byte.c libffi.closures/cls_sshort.c \ +libffi.closures/cls_16byte.c libffi.closures/nested_struct7.c \ +libffi.closures/cls_double_va.c libffi.closures/cls_3byte2.c \ +libffi.closures/cls_double.c libffi.closures/cls_7byte.c \ +libffi.closures/closure_fn6.c libffi.closures/closure_fn1.c \ +libffi.closures/cls_20byte.c libffi.closures/cls_18byte.c \ +libffi.closures/err_bad_abi.c +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 diff --git a/native/libffi/testsuite/lib/libffi.exp b/native/libffi/testsuite/lib/libffi.exp index 5051d3175e..0cf035ba3b 100644 --- a/native/libffi/testsuite/lib/libffi.exp +++ b/native/libffi/testsuite/lib/libffi.exp @@ -1,4 +1,8 @@ +<<<<<<< HEAD # Copyright (C) 2003, 2005, 2008, 2009, 2010, 2011, 2014 Free Software Foundation, Inc. +======= +# Copyright (C) 2003, 2005, 2008, 2009, 2010, 2011, 2014, 2019 Free Software Foundation, Inc. +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -24,6 +28,183 @@ load_lib libgloss.exp load_gcc_lib target-libpath.exp load_gcc_lib wrapper.exp +proc check_effective_target_gccbug { } { + global has_gccbug + return $has_gccbug +} + +# Return 1 if the target matches the effective target 'arg', 0 otherwise. +# This can be used with any check_* proc that takes no argument and +# returns only 1 or 0. It could be used with check_* procs that take +# arguments with keywords that pass particular arguments. + +proc is-effective-target { arg } { + global et_index + set selected 0 + if { ![info exists et_index] } { + # Initialize the effective target index that is used in some + # check_effective_target_* procs. + set et_index 0 + } + if { [info procs check_effective_target_${arg}] != [list] } { + set selected [check_effective_target_${arg}] + } else { + error "unknown effective target keyword `$arg'" + } + verbose "is-effective-target: $arg $selected" 2 + return $selected +} + +proc is-effective-target-keyword { arg } { + if { [info procs check_effective_target_${arg}] != [list] } { + return 1 + } else { + return 0 + } +} + +# Intercept the call to the DejaGnu version of dg-process-target to +# support use of an effective-target keyword in place of a list of +# target triplets to xfail or skip a test. +# +# The argument to dg-process-target is the keyword "target" or "xfail" +# followed by a selector: +# target-triplet-1 ... +# effective-target-keyword +# selector-expression +# +# For a target list the result is "S" if the target is selected, "N" otherwise. +# For an xfail list the result is "F" if the target is affected, "P" otherwise. + +# In contexts that allow either "target" or "xfail" the argument can be +# target selector1 xfail selector2 +# which returns "N" if selector1 is not selected, otherwise the result of +# "xfail selector2". +# +# A selector expression appears within curly braces and uses a single logical +# operator: !, &&, or ||. An operand is another selector expression, an +# effective-target keyword, or a list of target triplets within quotes or +# curly braces. + +if { [info procs saved-dg-process-target] == [list] } { + rename dg-process-target saved-dg-process-target + + # Evaluate an operand within a selector expression. + proc selector_opd { op } { + set selector "target" + lappend selector $op + set answer [ expr { [dg-process-target $selector] == "S" } ] + verbose "selector_opd: `$op' $answer" 2 + return $answer + } + + # Evaluate a target triplet list within a selector expression. + # Unlike other operands, this needs to be expanded from a list to + # the same string as "target". + proc selector_list { op } { + set selector "target [join $op]" + set answer [ expr { [dg-process-target $selector] == "S" } ] + verbose "selector_list: `$op' $answer" 2 + return $answer + } + + # Evaluate a selector expression. + proc selector_expression { exp } { + if { [llength $exp] == 2 } { + if [string match "!" [lindex $exp 0]] { + set op1 [lindex $exp 1] + set answer [expr { ! [selector_opd $op1] }] + } else { + # Assume it's a list of target triplets. + set answer [selector_list $exp] + } + } elseif { [llength $exp] == 3 } { + set op1 [lindex $exp 0] + set opr [lindex $exp 1] + set op2 [lindex $exp 2] + if [string match "&&" $opr] { + set answer [expr { [selector_opd $op1] && [selector_opd $op2] }] + } elseif [string match "||" $opr] { + set answer [expr { [selector_opd $op1] || [selector_opd $op2] }] + } else { + # Assume it's a list of target triplets. + set answer [selector_list $exp] + } + } else { + # Assume it's a list of target triplets. + set answer [selector_list $exp] + } + + verbose "selector_expression: `$exp' $answer" 2 + return $answer + } + + # Evaluate "target selector" or "xfail selector". + + proc dg-process-target-1 { args } { + verbose "dg-process-target-1: `$args'" 2 + + # Extract the 'what' keyword from the argument list. + set selector [string trim [lindex $args 0]] + if [regexp "^xfail " $selector] { + set what "xfail" + } elseif [regexp "^target " $selector] { + set what "target" + } else { + error "syntax error in target selector \"$selector\"" + } + + # Extract the rest of the list, which might be a keyword. + regsub "^${what}" $selector "" rest + set rest [string trim $rest] + + if [is-effective-target-keyword $rest] { + # The selector is an effective target keyword. + if [is-effective-target $rest] { + return [expr { $what == "xfail" ? "F" : "S" }] + } else { + return [expr { $what == "xfail" ? "P" : "N" }] + } + } + + if [string match "{*}" $rest] { + if [selector_expression [lindex $rest 0]] { + return [expr { $what == "xfail" ? "F" : "S" }] + } else { + return [expr { $what == "xfail" ? "P" : "N" }] + } + } + + # The selector is not an effective-target keyword, so process + # the list of target triplets. + return [saved-dg-process-target $selector] + } + + # Intercept calls to the DejaGnu function. In addition to + # processing "target selector" or "xfail selector", handle + # "target selector1 xfail selector2". + + proc dg-process-target { args } { + verbose "replacement dg-process-target: `$args'" 2 + + set selector [string trim [lindex $args 0]] + + # If the argument list contains both 'target' and 'xfail', + # process 'target' and, if that succeeds, process 'xfail'. + if [regexp "^target .* xfail .*" $selector] { + set xfail_index [string first "xfail" $selector] + set xfail_selector [string range $selector $xfail_index end] + set target_selector [string range $selector 0 [expr $xfail_index-1]] + set target_selector [string trim $target_selector] + if { [dg-process-target-1 $target_selector] == "N" } { + return "N" + } + return [dg-process-target-1 $xfail_selector] + + } + return [dg-process-target-1 $selector] + } +} # Define libffi callbacks for dg.exp. @@ -89,6 +270,12 @@ proc libffi-dg-test { prog do_what extra_tool_flags } { return [libffi-dg-test-1 target_compile $prog $do_what $extra_tool_flags] } +proc libffi-dg-prune { target_triplet text } { + # We get this with some qemu emulated systems (eg. ppc64le-linux-gnu) + regsub -all "(^|\n)\[^\n\]*unable to perform all requested operations" $text "" text + return $text +} + proc libffi-init { args } { global gluefile wrap_flags; global srcdir @@ -100,46 +287,42 @@ proc libffi-init { args } { global libffi_link_flags global tool_root_dir global ld_library_path + global compiler_vendor - global using_gcc + if ![info exists blddirffi] { + set blddirffi [pwd]/.. + } - set blddirffi [pwd]/.. verbose "libffi $blddirffi" - # Are we building with GCC? - set tmp [grep ../config.status "GCC='yes'"] - if { [string match $tmp "GCC='yes'"] } { - - set using_gcc "yes" - - set gccdir [lookfor_file $tool_root_dir gcc/libgcc.a] - if {$gccdir != ""} { - set gccdir [file dirname $gccdir] - } - verbose "gccdir $gccdir" - - set ld_library_path "." - append ld_library_path ":${gccdir}" + # Which compiler are we building with? + set tmp [grep "$blddirffi/config.log" "^ax_cv_c_compiler_vendor.*$"] + regexp -- {^[^=]*=(.*)$} $tmp nil compiler_vendor - set compiler "${gccdir}/xgcc" - if { [is_remote host] == 0 && [which $compiler] != 0 } { - foreach i "[exec $compiler --print-multi-lib]" { - set mldir "" - regexp -- "\[a-z0-9=_/\.-\]*;" $i mldir - set mldir [string trimright $mldir "\;@"] - if { "$mldir" == "." } { - continue - } - if { [llength [glob -nocomplain ${gccdir}/${mldir}/libgcc_s*.so.*]] >= 1 } { - append ld_library_path ":${gccdir}/${mldir}" + if { [string match $compiler_vendor "gnu"] } { + set gccdir [lookfor_file $tool_root_dir gcc/libgcc.a] + if {$gccdir != ""} { + set gccdir [file dirname $gccdir] + } + verbose "gccdir $gccdir" + + set ld_library_path "." + append ld_library_path ":${gccdir}" + + set compiler "${gccdir}/xgcc" + if { [is_remote host] == 0 && [which $compiler] != 0 } { + foreach i "[exec $compiler --print-multi-lib]" { + set mldir "" + regexp -- "\[a-z0-9=_/\.-\]*;" $i mldir + set mldir [string trimright $mldir "\;@"] + if { "$mldir" == "." } { + continue + } + if { [llength [glob -nocomplain ${gccdir}/${mldir}/libgcc_s*.so.*]] >= 1 } { + append ld_library_path ":${gccdir}/${mldir}" + } } - } - } - - } else { - - set using_gcc "no" - + } } # add the library path for libffi. @@ -179,7 +362,7 @@ proc libffi_target_compile { source dest type options } { global libffi_link_flags global libffi_include global target_triplet - + global compiler_vendor if { [target_info needs_status_wrapper]!="" && [info exists gluefile] } { lappend options "libs=${gluefile}" @@ -189,7 +372,7 @@ proc libffi_target_compile { source dest type options } { # TOOL_OPTIONS must come first, so that it doesn't override testcase # specific options. if [info exists TOOL_OPTIONS] { - lappend options [concat "additional_flags=$TOOL_OPTIONS" $options]; + lappend options "additional_flags=$TOOL_OPTIONS" } # search for ffi_mips.h in srcdir, too @@ -222,14 +405,43 @@ proc libffi_target_compile { source dest type options } { lappend options "libs= -lpthread" } +<<<<<<< HEAD if { [string match "*.cc" $source] } { lappend options "c++" +======= + # this may be required for g++, but just confused clang. + if { [string match "*.cc" $source] } { + lappend options "c++" + } + + if { [string match "arc*-*-linux*" $target_triplet] } { + lappend options "libs= -lpthread" +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 } verbose "options: $options" return [target_compile $source $dest $type $options] } +# TEST should be a preprocessor condition. Returns true if it holds. +proc libffi_feature_test { test } { + set src "ffitest[pid].c" + + set f [open $src "w"] + puts $f "#include " + puts $f $test + puts $f "/* OK */" + puts $f "#else" + puts $f "# error Failed $test" + puts $f "#endif" + close $f + + set lines [libffi_target_compile $src /dev/null assembly ""] + file delete $src + + return [string match "" $lines] +} + # Utility routines. # @@ -278,6 +490,7 @@ proc libffi-dg-runtest { testcases default-extra-flags } { } proc run-many-tests { testcases extra_flags } { +<<<<<<< HEAD global using_gcc if { [string match $using_gcc "yes"] } { set common "-W -Wall -Wno-psabi" @@ -291,12 +504,60 @@ proc run-many-tests { testcases extra_flags } { set targetabis { "" } if [string match $using_gcc "yes"] { if [istarget "i?86-*-*"] { +======= + global compiler_vendor + global has_gccbug + global env + switch $compiler_vendor { + "clang" { + set common "-W -Wall" + if [info exists env(LIBFFI_TEST_OPTIMIZATION)] { + set optimizations [ list $env(LIBFFI_TEST_OPTIMIZATION) ] + } else { + set optimizations { "-O0" "-O2" } + } + } + "gnu" { + set common "-W -Wall -Wno-psabi" + if [info exists env(LIBFFI_TEST_OPTIMIZATION)] { + set optimizations [ list $env(LIBFFI_TEST_OPTIMIZATION) ] + } else { + set optimizations { "-O0" "-O2" } + } + } + default { + # Assume we are using the vendor compiler. + set common "" + if [info exists env(LIBFFI_TEST_OPTIMIZATION)] { + set optimizations [ list $env(LIBFFI_TEST_OPTIMIZATION) ] + } else { + set optimizations { "" } + } + } + } + + info exists env(LD_LIBRARY_PATH) + + set targetabis { "" } + if [string match $compiler_vendor "gnu"] { + if [libffi_feature_test "#ifdef __i386__"] { +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 set targetabis { "" "-DABI_NUM=FFI_STDCALL -DABI_ATTR=__STDCALL__" "-DABI_NUM=FFI_THISCALL -DABI_ATTR=__THISCALL__" "-DABI_NUM=FFI_FASTCALL -DABI_ATTR=__FASTCALL__" } +<<<<<<< HEAD +======= + } elseif { [istarget "x86_64-*-*"] \ + && [libffi_feature_test "#if !defined __ILP32__ \ + && !defined __i386__"] } { + set targetabis { + "" + "-DABI_NUM=FFI_GNUW64 -DABI_ATTR=__MSABI__" + } +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 } } @@ -311,8 +572,27 @@ proc run-many-tests { testcases extra_flags } { foreach opt $optimizations { foreach abi $abis { set options [concat $common $opt $abi] +<<<<<<< HEAD verbose "Testing $testname, $options" 1 dg-test $test $options "" +======= + set has_gccbug false; + if { [string match $compiler_vendor "gnu"] \ + && [string match "*MSABI*" $abi] \ + && ( ( [string match "*DGTEST=57 *" $common] \ + && [string match "*call.c*" $testname] ) \ + || ( [string match "*DGTEST=54 *" $common] \ + && [string match "*callback*" $testname] ) \ + || [string match "*DGTEST=55 *" $common] \ + || [string match "*DGTEST=56 *" $common] ) } then { + if [libffi_feature_test "#if (__GNUC__ < 9) || ((__GNUC__ == 9) && (__GNUC_MINOR__ < 3))"] { + set has_gccbug true; + } + } + verbose "Testing $testname, $options" 1 + verbose "has_gccbug = $has_gccbug" 1 + dg-test $test $options "" +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 } } } diff --git a/native/libffi/testsuite/libffi.bhaible/Makefile b/native/libffi/testsuite/libffi.bhaible/Makefile new file mode 100644 index 0000000000..3322de94f7 --- /dev/null +++ b/native/libffi/testsuite/libffi.bhaible/Makefile @@ -0,0 +1,28 @@ +CC = gcc +CFLAGS = -O2 -Wall +prefix = +includedir = $(prefix)/include +libdir = $(prefix)/lib +CPPFLAGS = -I$(includedir) +LDFLAGS = -L$(libdir) -Wl,-rpath,$(libdir) + +all: check-call check-callback + +test-call: test-call.c testcases.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o test-call test-call.c -lffi + +test-callback: test-callback.c testcases.c + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -o test-callback test-callback.c -lffi + +check-call: test-call + ./test-call > test-call.out + LC_ALL=C uniq -u < test-call.out > failed-call + test '!' -s failed-call + +check-callback: test-callback + ./test-callback > test-callback.out + LC_ALL=C uniq -u < test-callback.out > failed-callback + test '!' -s failed-callback + +clean: + rm -f test-call test-callback test-call.out test-callback.out failed-call failed-callback diff --git a/native/libffi/testsuite/libffi.bhaible/README b/native/libffi/testsuite/libffi.bhaible/README new file mode 100644 index 0000000000..be8540b64f --- /dev/null +++ b/native/libffi/testsuite/libffi.bhaible/README @@ -0,0 +1,78 @@ +This package contains a test suite for libffi. + +This test suite can be compiled with a C compiler. No need for 'expect' +or some other package that is often not installed. + +The test suite consists of 81 C functions, each with a different signature. +* test-call verifies that calling each function directly produces the same + results as calling the function indirectly through 'ffi_call'. +* test-callback verifies that calling each function directly produces the same + results as calling a function that is a callback (object build by + 'ffi_prep_closure_loc') and simulates the original function. + +Each direct or indirect invocation should produce one line of output to +stdout. A correct output consists of paired lines, such as + +void f(void): +void f(void): +int f(void):->99 +int f(void):->99 +int f(int):(1)->2 +int f(int):(1)->2 +int f(2*int):(1,2)->3 +int f(2*int):(1,2)->3 +... + +The Makefile then creates two files: +* failed-call, which consists of the non-paired lines of output of + 'test-call', +* failed-callback, which consists of the non-paired lines of output of + 'test-callback'. + +The test suite passes if both failed-call and failed-callback come out +as empty. + + +How to use the test suite +------------------------- + +1. Modify the Makefile's variables + prefix = the directory in which libffi was installed + CC = the C compiler, often with options such as "-m32" or "-m64" + that enforce a certain ABI, + CFLAGS = optimization options (need to change them only for non-GCC + compilers) +2. Run "make". If it fails already in "test-call", run also + "make check-callback". +3. If this failed, inspect the output files. + + +How to interpret the results +---------------------------- + +The failed-call and failed-callback files consist of paired lines: +The first line is the result of the direct invocation. +The second line is the result of invocation through libffi. + +For example, this output + +uchar f(uchar,ushort,uint,ulong):(97,2,3,4)->255 +uchar f(uchar,ushort,uint,ulong):(97,2,3,4)->0 + +indicates that the arguments were passed correctly, but the return +value came out wrong. + +And this output + +float f(17*float,3*int,L):(0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,6,7,8,561,1105,1729,2465,2821,6601)->15319.1 +float f(17*float,3*int,L):(0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8,-140443648,10,268042216,-72537980,-140443648,-140443648,-140443648,-140443648,-140443648)->-6.47158e+08 + +indicates that integer arguments that come after 17 floating-point arguments +were not passed correctly. + + +Credits +------- + +The test suite is based on the one of GNU libffcall-2.0. +Authors: Bill Triggs, Bruno Haible diff --git a/native/libffi/testsuite/libffi.bhaible/alignof.h b/native/libffi/testsuite/libffi.bhaible/alignof.h new file mode 100644 index 0000000000..00604a513a --- /dev/null +++ b/native/libffi/testsuite/libffi.bhaible/alignof.h @@ -0,0 +1,50 @@ +/* Determine alignment of types. + Copyright (C) 2003-2004, 2006, 2009-2017 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . */ + +#ifndef _ALIGNOF_H +#define _ALIGNOF_H + +#include + +/* alignof_slot (TYPE) + Determine the alignment of a structure slot (field) of a given type, + at compile time. Note that the result depends on the ABI. + This is the same as alignof (TYPE) and _Alignof (TYPE), defined in + if __alignof_is_defined is 1. + Note: The result cannot be used as a value for an 'enum' constant, + due to bugs in HP-UX 10.20 cc and AIX 3.2.5 xlc. */ +#if defined __cplusplus + template struct alignof_helper { char __slot1; type __slot2; }; +# define alignof_slot(type) offsetof (alignof_helper, __slot2) +#else +# define alignof_slot(type) offsetof (struct { char __slot1; type __slot2; }, __slot2) +#endif + +/* alignof_type (TYPE) + Determine the good alignment of an object of the given type at compile time. + Note that this is not necessarily the same as alignof_slot(type). + For example, with GNU C on x86 platforms: alignof_type(double) = 8, but + - when -malign-double is not specified: alignof_slot(double) = 4, + - when -malign-double is specified: alignof_slot(double) = 8. + Note: The result cannot be used as a value for an 'enum' constant, + due to bugs in HP-UX 10.20 cc and AIX 3.2.5 xlc. */ +#if defined __GNUC__ || defined __IBM__ALIGNOF__ +# define alignof_type __alignof__ +#else +# define alignof_type alignof_slot +#endif + +#endif /* _ALIGNOF_H */ diff --git a/native/libffi/testsuite/libffi.bhaible/bhaible.exp b/native/libffi/testsuite/libffi.bhaible/bhaible.exp new file mode 100644 index 0000000000..44aebc5e06 --- /dev/null +++ b/native/libffi/testsuite/libffi.bhaible/bhaible.exp @@ -0,0 +1,63 @@ +# Copyright (C) 2003, 2006, 2009, 2010, 2014, 2018 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING3. If not see +# . + +dg-init +libffi-init + +global srcdir subdir +global compiler_vendor + +# The conversion of this testsuite into a dejagnu compatible testsuite +# was done in a pretty lazy fashion, and requires the use of compiler +# flags to disable warnings for now. +if { [string match $compiler_vendor "gnu"] } { + set warning_options "-Wno-unused-variable -Wno-unused-parameter -Wno-unused-but-set-variable -Wno-uninitialized"; +} +if { [string match $compiler_vendor "microsoft"] } { + # -wd4996 suggest use of vsprintf_s instead of vsprintf + # -wd4116 unnamed type definition + # -wd4101 unreferenced local variable + # -wd4244 warning about implicit double to float conversion + set warning_options "-wd4996 -wd4116 -wd4101 -wd4244"; +} +if { ![string match $compiler_vendor "microsoft"] && ![string match $compiler_vendor "gnu"] } { + set warning_options "-Wno-unused-variable -Wno-unused-parameter -Wno-uninitialized"; +} + + +set tlist [lsort [glob -nocomplain -- $srcdir/$subdir/test-call.c]] + +for {set i 1} {$i < 82} {incr i} { + run-many-tests $tlist [format "-DDGTEST=%d %s" $i $warning_options] +} + +set tlist [lsort [glob -nocomplain -- $srcdir/$subdir/test-callback.c]] + +for {set i 1} {$i < 81} {incr i} { + if { [libffi_feature_test "#if FFI_CLOSURES"] } { + run-many-tests $tlist [format "-DDGTEST=%d %s" $i $warning_options] + } else { + foreach test $tlist { + unsupported [format "%s -DDGTEST=%d %s" $test $i $warning_options] + } + } +} + +dg-finish + +# Local Variables: +# tcl-indent-level:4 +# End: diff --git a/native/libffi/testsuite/libffi.bhaible/test-call.c b/native/libffi/testsuite/libffi.bhaible/test-call.c new file mode 100644 index 0000000000..cf9219e266 --- /dev/null +++ b/native/libffi/testsuite/libffi.bhaible/test-call.c @@ -0,0 +1,1745 @@ +/** + Copyright 1993 Bill Triggs + Copyright 1995-2017 Bruno Haible + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +**/ + +/* { dg-do run { xfail gccbug } } */ + +#include +#include +#include +#include +#include "alignof.h" +#include + +/* libffi testsuite local changes -------------------------------- */ +#ifdef DGTEST +/* Redefine exit(1) as a test failure */ +#define exit(V) (void)((V) ? (abort(), 1) : exit(0)) +int count = 0; +char rbuf1[2048]; +char rbuf2[2048]; +int _fprintf(FILE *stream, const char *format, ...) +{ + va_list args; + va_start(args, format); + + switch (count++) + { + case 0: + case 1: + vsprintf(&rbuf1[strlen(rbuf1)], format, args); + break; + case 2: + printf("%s", rbuf1); + vsprintf(rbuf2, format, args); + break; + case 3: + vsprintf(&rbuf2[strlen(rbuf2)], format, args); + printf("%s", rbuf2); + if (strcmp (rbuf1, rbuf2)) abort(); + break; + } + + va_end(args); + + return 0; +} +#define fprintf _fprintf +#endif +/* --------------------------------------------------------------- */ + +#include "testcases.c" + +#ifndef ABI_NUM +#define ABI_NUM FFI_DEFAULT_ABI +#endif + +/* Definitions that ought to be part of libffi. */ +static ffi_type ffi_type_char; +#define ffi_type_slonglong ffi_type_sint64 +#define ffi_type_ulonglong ffi_type_uint64 + +/* libffi does not support arrays inside structs. */ +#define SKIP_EXTRA_STRUCTS + +#define FFI_PREP_CIF(cif,argtypes,rettype) \ + if (ffi_prep_cif(&(cif),ABI_NUM,sizeof(argtypes)/sizeof(argtypes[0]),&rettype,argtypes) != FFI_OK) abort() +#define FFI_PREP_CIF_NOARGS(cif,rettype) \ + if (ffi_prep_cif(&(cif),ABI_NUM,0,&rettype,NULL) != FFI_OK) abort() +#define FFI_CALL(cif,fn,args,retaddr) \ + ffi_call(&(cif),(void(*)(void))(fn),retaddr,args) + +long clear_traces_i (long a, long b, long c, long d, long e, long f, long g, long h, + long i, long j, long k, long l, long m, long n, long o, long p) +{ return 0; } +float clear_traces_f (float a, float b, float c, float d, float e, float f, float g, + float h, float i, float j, float k, float l, float m, float n, + float o, float p) +{ return 0.0; } +double clear_traces_d (double a, double b, double c, double d, double e, double f, double g, + double h, double i, double j, double k, double l, double m, double n, + double o, double p) +{ return 0.0; } +J clear_traces_J (void) +{ J j; j.l1 = j.l2 = 0; return j; } +void clear_traces (void) +{ clear_traces_i(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); + clear_traces_f(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0); + clear_traces_d(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0); + clear_traces_J(); +} + +void + void_tests (void) +{ +#if (!defined(DGTEST)) || DGTEST == 1 + v_v(); + clear_traces(); + { + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_void); + { + FFI_CALL(cif,v_v,NULL,NULL); + } + } +#endif + return; +} +void + int_tests (void) +{ + int ir; + ffi_arg retvalue; +#if (!defined(DGTEST)) || DGTEST == 2 + ir = i_v(); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + { + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_sint); + { + FFI_CALL(cif,i_v,NULL,&retvalue); + ir = retvalue; + } + } + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 3 + ir = i_i(i1); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_sint); + { + /*const*/ void* args[] = { &i1 }; + FFI_CALL(cif,i_i,args,&retvalue); + ir = retvalue; + } + } + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 4 + ir = i_i2(i1,i2); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_sint); + { + /*const*/ void* args[] = { &i1, &i2 }; + FFI_CALL(cif,i_i2,args,&retvalue); + ir = retvalue; + } + } + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 5 + ir = i_i4(i1,i2,i3,i4); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_sint); + { + /*const*/ void* args[] = { &i1, &i2, &i3, &i4 }; + FFI_CALL(cif,i_i4,args,&retvalue); + ir = retvalue; + } + } + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 6 + ir = i_i8(i1,i2,i3,i4,i5,i6,i7,i8); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_sint); + { + /*const*/ void* args[] = { &i1, &i2, &i3, &i4, &i5, &i6, &i7, &i8 }; + FFI_CALL(cif,i_i8,args,&retvalue); + ir = retvalue; + } + } + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 7 + ir = i_i16(i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15,i16); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_sint); + { + /*const*/ void* args[] = { &i1, &i2, &i3, &i4, &i5, &i6, &i7, &i8, &i9, &i10, &i11, &i12, &i13, &i14, &i15, &i16 }; + FFI_CALL(cif,i_i16,args,&retvalue); + ir = retvalue; + } + } + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + + return; +} +void + float_tests (void) +{ + float fr; + +#if (!defined(DGTEST)) || DGTEST == 8 + fr = f_f(f1); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1 }; + FFI_CALL(cif,f_f,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 9 + fr = f_f2(f1,f2); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2 }; + FFI_CALL(cif,f_f2,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 10 + fr = f_f4(f1,f2,f3,f4); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &f4 }; + FFI_CALL(cif,f_f4,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 11 + fr = f_f8(f1,f2,f3,f4,f5,f6,f7,f8); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8 }; + FFI_CALL(cif,f_f8,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 12 + fr = f_f16(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8, &f9, &f10, &f11, &f12, &f13, &f14, &f15, &f16 }; + FFI_CALL(cif,f_f16,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 13 + fr = f_f24(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18,f19,f20,f21,f22,f23,f24); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8, &f9, &f10, &f11, &f12, &f13, &f14, &f15, &f16, &f17, &f18, &f19, &f20, &f21, &f22, &f23, &f24 }; + FFI_CALL(cif,f_f24,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif +} +void + double_tests (void) +{ + double dr; + +#if (!defined(DGTEST)) || DGTEST == 14 + + dr = d_d(d1); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1 }; + FFI_CALL(cif,d_d,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 15 + dr = d_d2(d1,d2); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2 }; + FFI_CALL(cif,d_d2,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 16 + dr = d_d4(d1,d2,d3,d4); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &d3, &d4 }; + FFI_CALL(cif,d_d4,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 17 + dr = d_d8(d1,d2,d3,d4,d5,d6,d7,d8); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &d3, &d4, &d5, &d6, &d7, &d8 }; + FFI_CALL(cif,d_d8,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 18 + dr = d_d16(d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &d3, &d4, &d5, &d6, &d7, &d8, &d9, &d10, &d11, &d12, &d13, &d14, &d15, &d16 }; + FFI_CALL(cif,d_d16,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + return; +} +void + pointer_tests (void) +{ + void* vpr; + +#if (!defined(DGTEST)) || DGTEST == 19 + vpr = vp_vpdpcpsp(&uc1,&d2,str3,&I4); + fprintf(out,"->0x%p\n",vpr); + fflush(out); + vpr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_pointer, &ffi_type_pointer, &ffi_type_pointer, &ffi_type_pointer }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_pointer); + { + void* puc1 = &uc1; + void* pd2 = &d2; + void* pstr3 = str3; + void* pI4 = &I4; + /*const*/ void* args[] = { &puc1, &pd2, &pstr3, &pI4 }; + FFI_CALL(cif,vp_vpdpcpsp,args,&vpr); + } + } + fprintf(out,"->0x%p\n",vpr); + fflush(out); +#endif + return; +} +void + mixed_number_tests (void) +{ + uchar ucr; + ushort usr; + float fr; + double dr; + long long llr; + + /* Unsigned types. + */ +#if (!defined(DGTEST)) || DGTEST == 20 + ucr = uc_ucsil(uc1, us2, ui3, ul4); + fprintf(out,"->%u\n",ucr); + fflush(out); + ucr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_uchar, &ffi_type_ushort, &ffi_type_uint, &ffi_type_ulong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_uchar); + { + ffi_arg r; + /*const*/ void* args[] = { &uc1, &us2, &ui3, &ul4 }; + FFI_CALL(cif,uc_ucsil,args,&r); + ucr = (uchar) r; + } + } + fprintf(out,"->%u\n",ucr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 21 + /* Mixed int & float types. + */ + dr = d_iidd(i1,i2,d3,d4); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &i1, &i2, &d3, &d4 }; + FFI_CALL(cif,d_iidd,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 22 + dr = d_iiidi(i1,i2,i3,d4,i5); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &i1, &i2, &i3, &d4, &i5 }; + FFI_CALL(cif,d_iiidi,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 23 + dr = d_idid(i1,d2,i3,d4); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_double, &ffi_type_sint, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &i1, &d2, &i3, &d4 }; + FFI_CALL(cif,d_idid,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 24 + dr = d_fdi(f1,d2,i3); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &f1, &d2, &i3 }; + FFI_CALL(cif,d_fdi,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 25 + usr = us_cdcd(c1,d2,c3,d4); + fprintf(out,"->%u\n",usr); + fflush(out); + usr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_char, &ffi_type_double, &ffi_type_char, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_ushort); + { + ffi_arg rint; + /*const*/ void* args[] = { &c1, &d2, &c3, &d4 }; + FFI_CALL(cif,us_cdcd,args,&rint); + usr = (ushort) rint; + } + } + fprintf(out,"->%u\n",usr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 26 + /* Long long types. + */ + llr = ll_iiilli(i1,i2,i3,ll1,i13); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_slonglong, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + { + /*const*/ void* args[] = { &i1, &i2, &i3, &ll1, &i13 }; + FFI_CALL(cif,ll_iiilli,args,&llr); + } + } + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 27 + llr = ll_flli(f13,ll1,i13); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_slonglong, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + { + /*const*/ void* args[] = { &f13, &ll1, &i13 }; + FFI_CALL(cif,ll_flli,args,&llr); + } + } + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 28 + fr = f_fi(f1,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &i9 }; + FFI_CALL(cif,f_fi,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 29 + fr = f_f2i(f1,f2,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &i9 }; + FFI_CALL(cif,f_f2i,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 30 + fr = f_f3i(f1,f2,f3,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &i9 }; + FFI_CALL(cif,f_f3i,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 31 + fr = f_f4i(f1,f2,f3,f4,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &f4, &i9 }; + FFI_CALL(cif,f_f4i,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 32 + fr = f_f7i(f1,f2,f3,f4,f5,f6,f7,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &f4, &f5, &f6, &f7, &i9 }; + FFI_CALL(cif,f_f7i,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 33 + fr = f_f8i(f1,f2,f3,f4,f5,f6,f7,f8,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8, &i9 }; + FFI_CALL(cif,f_f8i,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 34 + fr = f_f12i(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8, &f9, &f10, &f11, &f12, &i9 }; + FFI_CALL(cif,f_f12i,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 35 + fr = f_f13i(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8, &f9, &f10, &f11, &f12, &f13, &i9 }; + FFI_CALL(cif,f_f13i,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 36 + dr = d_di(d1,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &i9 }; + FFI_CALL(cif,d_di,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 37 + dr = d_d2i(d1,d2,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &i9 }; + FFI_CALL(cif,d_d2i,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 38 + dr = d_d3i(d1,d2,d3,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &d3, &i9 }; + FFI_CALL(cif,d_d3i,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 39 + dr = d_d4i(d1,d2,d3,d4,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &d3, &d4, &i9 }; + FFI_CALL(cif,d_d4i,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 40 + dr = d_d7i(d1,d2,d3,d4,d5,d6,d7,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &d3, &d4, &d5, &d6, &d7, &i9 }; + FFI_CALL(cif,d_d7i,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 41 + dr = d_d8i(d1,d2,d3,d4,d5,d6,d7,d8,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &d3, &d4, &d5, &d6, &d7, &d8, &i9 }; + FFI_CALL(cif,d_d8i,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 42 + dr = d_d12i(d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &d3, &d4, &d5, &d6, &d7, &d8, &d9, &d10, &d11, &d12, &i9 }; + FFI_CALL(cif,d_d12i,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 43 + dr = d_d13i(d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &d3, &d4, &d5, &d6, &d7, &d8, &d9, &d10, &d11, &d12, &d13, &i9 }; + FFI_CALL(cif,d_d13i,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + return; +} +void + small_structure_return_tests (void) +{ +#if (!defined(DGTEST)) || DGTEST == 44 + { + Size1 r = S1_v(); + fprintf(out,"->{%c}\n",r.x1); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + { + ffi_type* ffi_type_Size1_elements[] = { &ffi_type_char, NULL }; + ffi_type ffi_type_Size1; + ffi_type_Size1.type = FFI_TYPE_STRUCT; + ffi_type_Size1.size = sizeof(Size1); + ffi_type_Size1.alignment = alignof_slot(Size1); + ffi_type_Size1.elements = ffi_type_Size1_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size1); + { + FFI_CALL(cif,S1_v,NULL,&r); + } + } + fprintf(out,"->{%c}\n",r.x1); + fflush(out); + } +#endif +#if (!defined(DGTEST)) || DGTEST == 45 + { + Size2 r = S2_v(); + fprintf(out,"->{%c%c}\n",r.x1,r.x2); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + { + ffi_type* ffi_type_Size2_elements[] = { &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size2; + ffi_type_Size2.type = FFI_TYPE_STRUCT; + ffi_type_Size2.size = sizeof(Size2); + ffi_type_Size2.alignment = alignof_slot(Size2); + ffi_type_Size2.elements = ffi_type_Size2_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size2); + { + FFI_CALL(cif,S2_v,NULL,&r); + } + } + fprintf(out,"->{%c%c}\n",r.x1,r.x2); + fflush(out); + } +#endif +#if (!defined(DGTEST)) || DGTEST == 46 + { + Size3 r = S3_v(); + fprintf(out,"->{%c%c%c}\n",r.x1,r.x2,r.x3); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + { + ffi_type* ffi_type_Size3_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size3; + ffi_type_Size3.type = FFI_TYPE_STRUCT; + ffi_type_Size3.size = sizeof(Size3); + ffi_type_Size3.alignment = alignof_slot(Size3); + ffi_type_Size3.elements = ffi_type_Size3_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size3); + { + FFI_CALL(cif,S3_v,NULL,&r); + } + } + fprintf(out,"->{%c%c%c}\n",r.x1,r.x2,r.x3); + fflush(out); + } +#endif +#if (!defined(DGTEST)) || DGTEST == 47 + { + Size4 r = S4_v(); + fprintf(out,"->{%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + { + ffi_type* ffi_type_Size4_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size4; + ffi_type_Size4.type = FFI_TYPE_STRUCT; + ffi_type_Size4.size = sizeof(Size4); + ffi_type_Size4.alignment = alignof_slot(Size4); + ffi_type_Size4.elements = ffi_type_Size4_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size4); + { + FFI_CALL(cif,S4_v,NULL,&r); + } + } + fprintf(out,"->{%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4); + fflush(out); + } +#endif +#if (!defined(DGTEST)) || DGTEST == 48 + { + Size7 r = S7_v(); + fprintf(out,"->{%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + { + ffi_type* ffi_type_Size7_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size7; + ffi_type_Size7.type = FFI_TYPE_STRUCT; + ffi_type_Size7.size = sizeof(Size7); + ffi_type_Size7.alignment = alignof_slot(Size7); + ffi_type_Size7.elements = ffi_type_Size7_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size7); + { + FFI_CALL(cif,S7_v,NULL,&r); + } + } + fprintf(out,"->{%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7); + fflush(out); + } +#endif +#if (!defined(DGTEST)) || DGTEST == 49 + { + Size8 r = S8_v(); + fprintf(out,"->{%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + { + ffi_type* ffi_type_Size8_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size8; + ffi_type_Size8.type = FFI_TYPE_STRUCT; + ffi_type_Size8.size = sizeof(Size8); + ffi_type_Size8.alignment = alignof_slot(Size8); + ffi_type_Size8.elements = ffi_type_Size8_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size8); + { + FFI_CALL(cif,S8_v,NULL,&r); + } + } + fprintf(out,"->{%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8); + fflush(out); + } +#endif +#if (!defined(DGTEST)) || DGTEST == 50 + { + Size12 r = S12_v(); + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + { + ffi_type* ffi_type_Size12_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size12; + ffi_type_Size12.type = FFI_TYPE_STRUCT; + ffi_type_Size12.size = sizeof(Size12); + ffi_type_Size12.alignment = alignof_slot(Size12); + ffi_type_Size12.elements = ffi_type_Size12_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size12); + { + FFI_CALL(cif,S12_v,NULL,&r); + } + } + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12); + fflush(out); + } +#endif +#if (!defined(DGTEST)) || DGTEST == 51 + { + Size15 r = S15_v(); + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12,r.x13,r.x14,r.x15); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + { + ffi_type* ffi_type_Size15_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size15; + ffi_type_Size15.type = FFI_TYPE_STRUCT; + ffi_type_Size15.size = sizeof(Size15); + ffi_type_Size15.alignment = alignof_slot(Size15); + ffi_type_Size15.elements = ffi_type_Size15_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size15); + { + FFI_CALL(cif,S15_v,NULL,&r); + } + } + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12,r.x13,r.x14,r.x15); + fflush(out); + } +#endif +#if (!defined(DGTEST)) || DGTEST == 52 + { + Size16 r = S16_v(); + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12,r.x13,r.x14,r.x15,r.x16); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + { + ffi_type* ffi_type_Size16_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size16; + ffi_type_Size16.type = FFI_TYPE_STRUCT; + ffi_type_Size16.size = sizeof(Size16); + ffi_type_Size16.alignment = alignof_slot(Size16); + ffi_type_Size16.elements = ffi_type_Size16_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size16); + { + FFI_CALL(cif,S16_v,NULL,&r); + } + } + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12,r.x13,r.x14,r.x15,r.x16); + fflush(out); + } +#endif +} +void + structure_tests (void) +{ + Int Ir; + Char Cr; + Float Fr; + Double Dr; + J Jr; +#ifndef SKIP_EXTRA_STRUCTS + T Tr; + X Xr; +#endif + +#if (!defined(DGTEST)) || DGTEST == 53 + Ir = I_III(I1,I2,I3); + fprintf(out,"->{%d}\n",Ir.x); + fflush(out); + Ir.x = 0; clear_traces(); + { + ffi_type* ffi_type_Int_elements[] = { &ffi_type_sint, NULL }; + ffi_type ffi_type_Int; + ffi_type_Int.type = FFI_TYPE_STRUCT; + ffi_type_Int.size = sizeof(Int); + ffi_type_Int.alignment = alignof_slot(Int); + ffi_type_Int.elements = ffi_type_Int_elements; + ffi_type* argtypes[] = { &ffi_type_Int, &ffi_type_Int, &ffi_type_Int }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_Int); + { + /*const*/ void* args[] = { &I1, &I2, &I3 }; + FFI_CALL(cif,I_III,args,&Ir); + } + } + fprintf(out,"->{%d}\n",Ir.x); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 54 + Cr = C_CdC(C1,d2,C3); + fprintf(out,"->{'%c'}\n",Cr.x); + fflush(out); + Cr.x = '\0'; clear_traces(); + { + ffi_type* ffi_type_Char_elements[] = { &ffi_type_char, NULL }; + ffi_type ffi_type_Char; + ffi_type_Char.type = FFI_TYPE_STRUCT; + ffi_type_Char.size = sizeof(Char); + ffi_type_Char.alignment = alignof_slot(Char); + ffi_type_Char.elements = ffi_type_Char_elements; + ffi_type* argtypes[] = { &ffi_type_Char, &ffi_type_double, &ffi_type_Char }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_Char); + { + /*const*/ void* args[] = { &C1, &d2, &C3 }; + FFI_CALL(cif,C_CdC,args,&Cr); + } + } + fprintf(out,"->{'%c'}\n",Cr.x); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 55 + Fr = F_Ffd(F1,f2,d3); + fprintf(out,"->{%g}\n",Fr.x); + fflush(out); + Fr.x = 0.0; clear_traces(); + { + ffi_type* ffi_type_Float_elements[] = { &ffi_type_float, NULL }; + ffi_type ffi_type_Float; + ffi_type_Float.type = FFI_TYPE_STRUCT; + ffi_type_Float.size = sizeof(Float); + ffi_type_Float.alignment = alignof_slot(Float); + ffi_type_Float.elements = ffi_type_Float_elements; + ffi_type* argtypes[] = { &ffi_type_Float, &ffi_type_float, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_Float); + { + /*const*/ void* args[] = { &F1, &f2, &d3 }; + FFI_CALL(cif,F_Ffd,args,&Fr); + } + } + fprintf(out,"->{%g}\n",Fr.x); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 56 + Dr = D_fDd(f1,D2,d3); + fprintf(out,"->{%g}\n",Dr.x); + fflush(out); + Dr.x = 0.0; clear_traces(); + { + ffi_type* ffi_type_Double_elements[] = { &ffi_type_double, NULL }; + ffi_type ffi_type_Double; + ffi_type_Double.type = FFI_TYPE_STRUCT; + ffi_type_Double.size = sizeof(Double); + ffi_type_Double.alignment = alignof_slot(Double); + ffi_type_Double.elements = ffi_type_Double_elements; + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_Double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_Double); + { + /*const*/ void* args[] = { &f1, &D2, &d3 }; + FFI_CALL(cif,D_fDd,args,&Dr); + } + } + fprintf(out,"->{%g}\n",Dr.x); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 57 + Dr = D_Dfd(D1,f2,d3); + fprintf(out,"->{%g}\n",Dr.x); + fflush(out); + Dr.x = 0.0; clear_traces(); + { + ffi_type* ffi_type_Double_elements[] = { &ffi_type_double, NULL }; + ffi_type ffi_type_Double; + ffi_type_Double.type = FFI_TYPE_STRUCT; + ffi_type_Double.size = sizeof(Double); + ffi_type_Double.alignment = alignof_slot(Double); + ffi_type_Double.elements = ffi_type_Double_elements; + ffi_type* argtypes[] = { &ffi_type_Double, &ffi_type_float, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_Double); + { + /*const*/ void* args[] = { &D1, &f2, &d3 }; + FFI_CALL(cif,D_Dfd,args,&Dr); + } + } + fprintf(out,"->{%g}\n",Dr.x); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 58 + Jr = J_JiJ(J1,i2,J2); + fprintf(out,"->{%ld,%ld}\n",Jr.l1,Jr.l2); + fflush(out); + Jr.l1 = Jr.l2 = 0; clear_traces(); + { + ffi_type* ffi_type_J_elements[] = { &ffi_type_slong, &ffi_type_slong, NULL }; + ffi_type ffi_type_J; + ffi_type_J.type = FFI_TYPE_STRUCT; + ffi_type_J.size = sizeof(J); + ffi_type_J.alignment = alignof_slot(J); + ffi_type_J.elements = ffi_type_J_elements; + ffi_type* argtypes[] = { &ffi_type_J, &ffi_type_sint, &ffi_type_J }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_J); + { + /*const*/ void* args[] = { &J1, &i2, &J2 }; + FFI_CALL(cif,J_JiJ,args,&Jr); + } + } + fprintf(out,"->{%ld,%ld}\n",Jr.l1,Jr.l2); + fflush(out); +#endif +#ifndef SKIP_EXTRA_STRUCTS +#if (!defined(DGTEST)) || DGTEST == 59 + Tr = T_TcT(T1,' ',T2); + fprintf(out,"->{\"%c%c%c\"}\n",Tr.c[0],Tr.c[1],Tr.c[2]); + fflush(out); + Tr.c[0] = Tr.c[1] = Tr.c[2] = 0; clear_traces(); + { + ffi_type* ffi_type_T_elements[] = { ??, NULL }; + ffi_type ffi_type_T; + ffi_type_T.type = FFI_TYPE_STRUCT; + ffi_type_T.size = sizeof(T); + ffi_type_T.alignment = alignof_slot(T); + ffi_type_T.elements = ffi_type_T_elements; + ffi_type* argtypes[] = { &ffi_type_T, &ffi_type_char, &ffi_type_T }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_T); + { + char space = ' '; + /*const*/ void* args[] = { &T1, &space, &T2 }; + FFI_CALL(cif,T_TcT,args,&Tr); + } + } + fprintf(out,"->{\"%c%c%c\"}\n",Tr.c[0],Tr.c[1],Tr.c[2]); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 60 + Xr = X_BcdB(B1,c2,d3,B2); + fprintf(out,"->{\"%s\",'%c'}\n",Xr.c,Xr.c1); + fflush(out); + Xr.c[0]=Xr.c1='\0'; clear_traces(); + { + ffi_type* ffi_type_X_elements[] = { ??, NULL }; + ffi_type ffi_type_X; + ffi_type_X.type = FFI_TYPE_STRUCT; + ffi_type_X.size = sizeof(X); + ffi_type_X.alignment = alignof_slot(X); + ffi_type_X.elements = ffi_type_X_elements; + ffi_type* argtypes[] = { &ffi_type_X, &ffi_type_char, &ffi_type_double, &ffi_type_X }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_X); + { + /*const*/ void* args[] = { &B1, &c2, &d3, &B2 }; + FFI_CALL(cif,X_BcdB,args,&Xr); + } + } + fprintf(out,"->{\"%s\",'%c'}\n",Xr.c,Xr.c1); + fflush(out); +#endif +#endif + + return; +} + +void + gpargs_boundary_tests (void) +{ + ffi_type* ffi_type_K_elements[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, NULL }; + ffi_type ffi_type_K; + ffi_type* ffi_type_L_elements[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, NULL }; + ffi_type ffi_type_L; + long lr; + long long llr; + float fr; + double dr; + + ffi_type_K.type = FFI_TYPE_STRUCT; + ffi_type_K.size = sizeof(K); + ffi_type_K.alignment = alignof_slot(K); + ffi_type_K.elements = ffi_type_K_elements; + + ffi_type_L.type = FFI_TYPE_STRUCT; + ffi_type_L.size = sizeof(L); + ffi_type_L.alignment = alignof_slot(L); + ffi_type_L.elements = ffi_type_L_elements; + +#if (!defined(DGTEST)) || DGTEST == 61 + lr = l_l0K(K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + { + /*const*/ void* args[] = { &K1, &l9 }; + FFI_CALL(cif,l_l0K,args,&lr); + } + } + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 62 + lr = l_l1K(l1,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + { + /*const*/ void* args[] = { &l1, &K1, &l9 }; + FFI_CALL(cif,l_l1K,args,&lr); + } + } + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 63 + lr = l_l2K(l1,l2,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + { + /*const*/ void* args[] = { &l1, &l2, &K1, &l9 }; + FFI_CALL(cif,l_l2K,args,&lr); + } + } + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 64 + lr = l_l3K(l1,l2,l3,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &K1, &l9 }; + FFI_CALL(cif,l_l3K,args,&lr); + } + } + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 65 + lr = l_l4K(l1,l2,l3,l4,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &K1, &l9 }; + FFI_CALL(cif,l_l4K,args,&lr); + } + } + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 66 + lr = l_l5K(l1,l2,l3,l4,l5,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &l5, &K1, &l9 }; + FFI_CALL(cif,l_l5K,args,&lr); + } + } + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 67 + lr = l_l6K(l1,l2,l3,l4,l5,l6,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &l5, &l6, &K1, &l9 }; + FFI_CALL(cif,l_l6K,args,&lr); + } + } + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 68 + fr = f_f17l3L(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,l6,l7,l8,L1); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_L }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + { + /*const*/ void* args[] = { &f1, &f2, &f3, &f4, &f5, &f6, &f7, &f8, &f9, &f10, &f11, &f12, &f13, &f14, &f15, &f16, &f17, &l6, &l7, &l8, &L1 }; + FFI_CALL(cif,f_f17l3L,args,&fr); + } + } + fprintf(out,"->%g\n",fr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 69 + dr = d_d17l3L(d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16,d17,l6,l7,l8,L1); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_L }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &d1, &d2, &d3, &d4, &d5, &d6, &d7, &d8, &d9, &d10, &d11, &d12, &d13, &d14, &d15, &d16, &d17, &l6, &l7, &l8, &L1 }; + FFI_CALL(cif,d_d17l3L,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 70 + llr = ll_l2ll(l1,l2,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + { + /*const*/ void* args[] = { &l1, &l2, &ll1, &l9 }; + FFI_CALL(cif,ll_l2ll,args,&llr); + } + } + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 71 + llr = ll_l3ll(l1,l2,l3,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &ll1, &l9 }; + FFI_CALL(cif,ll_l3ll,args,&llr); + } + } + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 72 + llr = ll_l4ll(l1,l2,l3,l4,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &ll1, &l9 }; + FFI_CALL(cif,ll_l4ll,args,&llr); + } + } + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 73 + llr = ll_l5ll(l1,l2,l3,l4,l5,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &l5, &ll1, &l9 }; + FFI_CALL(cif,ll_l5ll,args,&llr); + } + } + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 74 + llr = ll_l6ll(l1,l2,l3,l4,l5,l6,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &l5, &l6, &ll1, &l9 }; + FFI_CALL(cif,ll_l6ll,args,&llr); + } + } + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 75 + llr = ll_l7ll(l1,l2,l3,l4,l5,l6,l7,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &l5, &l6, &l7, &ll1, &l9 }; + FFI_CALL(cif,ll_l7ll,args,&llr); + } + } + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 76 + dr = d_l2d(l1,l2,d2,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &l1, &l2, &d2, &l9 }; + FFI_CALL(cif,d_l2d,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 77 + dr = d_l3d(l1,l2,l3,d2,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &d2, &l9 }; + FFI_CALL(cif,d_l3d,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 78 + dr = d_l4d(l1,l2,l3,l4,d2,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &d2, &l9 }; + FFI_CALL(cif,d_l4d,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 79 + dr = d_l5d(l1,l2,l3,l4,l5,d2,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &l5, &d2, &l9 }; + FFI_CALL(cif,d_l5d,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 80 + dr = d_l6d(l1,l2,l3,l4,l5,l6,d2,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &l5, &l6, &d2, &l9 }; + FFI_CALL(cif,d_l6d,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif +#if (!defined(DGTEST)) || DGTEST == 81 + dr = d_l7d(l1,l2,l3,l4,l5,l6,l7,d2,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + { + /*const*/ void* args[] = { &l1, &l2, &l3, &l4, &l5, &l6, &l7, &d2, &l9 }; + FFI_CALL(cif,d_l7d,args,&dr); + } + } + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + return; +} + +int + main (void) +{ + ffi_type_char = (char)(-1) < 0 ? ffi_type_schar : ffi_type_uchar; + out = stdout; + + void_tests(); + int_tests(); + float_tests(); + double_tests(); + pointer_tests(); + mixed_number_tests(); + small_structure_return_tests(); + structure_tests(); + gpargs_boundary_tests(); + + exit(0); +} diff --git a/native/libffi/testsuite/libffi.bhaible/test-callback.c b/native/libffi/testsuite/libffi.bhaible/test-callback.c new file mode 100644 index 0000000000..0b16799d86 --- /dev/null +++ b/native/libffi/testsuite/libffi.bhaible/test-callback.c @@ -0,0 +1,2885 @@ +/* + * Copyright 1993 Bill Triggs + * Copyright 1995-2017 Bruno Haible + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* { dg-do run { xfail gccbug } } */ + +#include +#include +#include +#include +#include "alignof.h" +#include + +/* libffi testsuite local changes -------------------------------- */ +#ifdef DGTEST +/* Redefine exit(1) as a test failure */ +#define exit(V) (void)((V) ? (abort(), 1) : exit(0)) +int count = 0; +char rbuf1[2048]; +char rbuf2[2048]; +int _fprintf(FILE *stream, const char *format, ...) +{ + va_list args; + va_start(args, format); + + switch (count++) + { + case 0: + case 1: + vsprintf(&rbuf1[strlen(rbuf1)], format, args); + break; + case 2: + printf("%s", rbuf1); + vsprintf(rbuf2, format, args); + break; + case 3: + vsprintf(&rbuf2[strlen(rbuf2)], format, args); + printf("%s", rbuf2); + if (strcmp (rbuf1, rbuf2)) abort(); + break; + } + + va_end(args); + + return 0; +} +#define fprintf _fprintf +#endif +/* --------------------------------------------------------------- */ + +#include "testcases.c" + +#ifndef ABI_NUM +#define ABI_NUM FFI_DEFAULT_ABI +#endif + +/* Definitions that ought to be part of libffi. */ +static ffi_type ffi_type_char; +#define ffi_type_slonglong ffi_type_sint64 +#define ffi_type_ulonglong ffi_type_uint64 + +/* libffi does not support arrays inside structs. */ +#define SKIP_EXTRA_STRUCTS + +#define FFI_PREP_CIF(cif,argtypes,rettype) \ + if (ffi_prep_cif(&(cif),ABI_NUM,sizeof(argtypes)/sizeof(argtypes[0]),&rettype,argtypes) != FFI_OK) abort() +#define FFI_PREP_CIF_NOARGS(cif,rettype) \ + if (ffi_prep_cif(&(cif),ABI_NUM,0,&rettype,NULL) != FFI_OK) abort() + +#if defined(__sparc__) && defined(__sun) && defined(__SUNPRO_C) /* SUNWspro cc */ +/* SunPRO cc miscompiles the simulator function for X_BcdB: d.i[1] is + * temporarily stored in %l2 and put onto the stack from %l2, but in between + * the copy of X has used %l2 as a counter without saving and restoring its + * value. + */ +#define SKIP_X +#endif +#if defined(__mipsn32__) && !defined(__GNUC__) +/* The X test crashes for an unknown reason. */ +#define SKIP_X +#endif + + +/* These functions simulate the behaviour of the functions defined in testcases.c. */ + +/* void tests */ +void v_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&v_v) { fprintf(out,"wrong data for v_v\n"); exit(1); } + fprintf(out,"void f(void):\n"); + fflush(out); +} + +/* int tests */ +void i_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&i_v) { fprintf(out,"wrong data for i_v\n"); exit(1); } + {int r=99; + fprintf(out,"int f(void):"); + fflush(out); + *(ffi_arg*)retp = r; +}} +void i_i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&i_i) { fprintf(out,"wrong data for i_i\n"); exit(1); } + int a = *(int*)(*args++); + int r=a+1; + fprintf(out,"int f(int):(%d)",a); + fflush(out); + *(ffi_arg*)retp = r; +} +void i_i2_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&i_i2) { fprintf(out,"wrong data for i_i2\n"); exit(1); } + {int a = *(int*)(*args++); + int b = *(int*)(*args++); + int r=a+b; + fprintf(out,"int f(2*int):(%d,%d)",a,b); + fflush(out); + *(ffi_arg*)retp = r; +}} +void i_i4_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&i_i4) { fprintf(out,"wrong data for i_i4\n"); exit(1); } + {int a = *(int*)(*args++); + int b = *(int*)(*args++); + int c = *(int*)(*args++); + int d = *(int*)(*args++); + int r=a+b+c+d; + fprintf(out,"int f(4*int):(%d,%d,%d,%d)",a,b,c,d); + fflush(out); + *(ffi_arg*)retp = r; +}} +void i_i8_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&i_i8) { fprintf(out,"wrong data for i_i8\n"); exit(1); } + {int a = *(int*)(*args++); + int b = *(int*)(*args++); + int c = *(int*)(*args++); + int d = *(int*)(*args++); + int e = *(int*)(*args++); + int f = *(int*)(*args++); + int g = *(int*)(*args++); + int h = *(int*)(*args++); + int r=a+b+c+d+e+f+g+h; + fprintf(out,"int f(8*int):(%d,%d,%d,%d,%d,%d,%d,%d)",a,b,c,d,e,f,g,h); + fflush(out); + *(ffi_arg*)retp = r; +}} +void i_i16_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&i_i16) { fprintf(out,"wrong data for i_i16\n"); exit(1); } + {int a = *(int*)(*args++); + int b = *(int*)(*args++); + int c = *(int*)(*args++); + int d = *(int*)(*args++); + int e = *(int*)(*args++); + int f = *(int*)(*args++); + int g = *(int*)(*args++); + int h = *(int*)(*args++); + int i = *(int*)(*args++); + int j = *(int*)(*args++); + int k = *(int*)(*args++); + int l = *(int*)(*args++); + int m = *(int*)(*args++); + int n = *(int*)(*args++); + int o = *(int*)(*args++); + int p = *(int*)(*args++); + int r=a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p; + fprintf(out,"int f(16*int):(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)", + a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p); + fflush(out); + *(ffi_arg*)retp = r; +}} + +/* float tests */ +void f_f_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f) { fprintf(out,"wrong data for f_f\n"); exit(1); } + {float a = *(float*)(*args++); + float r=a+1.0; + fprintf(out,"float f(float):(%g)",a); + fflush(out); + *(float*)retp = r; +}} +void f_f2_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f2) { fprintf(out,"wrong data for f_f2\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float r=a+b; + fprintf(out,"float f(2*float):(%g,%g)",a,b); + fflush(out); + *(float*)retp = r; +}} +void f_f4_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f4) { fprintf(out,"wrong data for f_f4\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + float d = *(float*)(*args++); + float r=a+b+c+d; + fprintf(out,"float f(4*float):(%g,%g,%g,%g)",a,b,c,d); + fflush(out); + *(float*)retp = r; +}} +void f_f8_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f8) { fprintf(out,"wrong data for f_f8\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + float d = *(float*)(*args++); + float e = *(float*)(*args++); + float f = *(float*)(*args++); + float g = *(float*)(*args++); + float h = *(float*)(*args++); + float r=a+b+c+d+e+f+g+h; + fprintf(out,"float f(8*float):(%g,%g,%g,%g,%g,%g,%g,%g)",a,b,c,d,e,f,g,h); + fflush(out); + *(float*)retp = r; +}} +void f_f16_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f16) { fprintf(out,"wrong data for f_f16\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + float d = *(float*)(*args++); + float e = *(float*)(*args++); + float f = *(float*)(*args++); + float g = *(float*)(*args++); + float h = *(float*)(*args++); + float i = *(float*)(*args++); + float j = *(float*)(*args++); + float k = *(float*)(*args++); + float l = *(float*)(*args++); + float m = *(float*)(*args++); + float n = *(float*)(*args++); + float o = *(float*)(*args++); + float p = *(float*)(*args++); + float r=a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p; + fprintf(out,"float f(16*float):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g)",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p); + fflush(out); + *(float*)retp = r; +}} +void f_f24_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f24) { fprintf(out,"wrong data for f_f24\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + float d = *(float*)(*args++); + float e = *(float*)(*args++); + float f = *(float*)(*args++); + float g = *(float*)(*args++); + float h = *(float*)(*args++); + float i = *(float*)(*args++); + float j = *(float*)(*args++); + float k = *(float*)(*args++); + float l = *(float*)(*args++); + float m = *(float*)(*args++); + float n = *(float*)(*args++); + float o = *(float*)(*args++); + float p = *(float*)(*args++); + float q = *(float*)(*args++); + float s = *(float*)(*args++); + float t = *(float*)(*args++); + float u = *(float*)(*args++); + float v = *(float*)(*args++); + float w = *(float*)(*args++); + float x = *(float*)(*args++); + float y = *(float*)(*args++); + float r=a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+s+t+u+v+w+x+y; + fprintf(out,"float f(24*float):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g)",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,s,t,u,v,w,x,y); + fflush(out); + *(float*)retp = r; +}} + +/* double tests */ +void d_d_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d) { fprintf(out,"wrong data for d_d\n"); exit(1); } + {double a = *(double*)(*args++); + double r=a+1.0; + fprintf(out,"double f(double):(%g)",a); + fflush(out); + *(double*)retp = r; +}} +void d_d2_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d2) { fprintf(out,"wrong data for d_d2\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double r=a+b; + fprintf(out,"double f(2*double):(%g,%g)",a,b); + fflush(out); + *(double*)retp = r; +}} +void d_d4_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d4) { fprintf(out,"wrong data for d_d4\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double c = *(double*)(*args++); + double d = *(double*)(*args++); + double r=a+b+c+d; + fprintf(out,"double f(4*double):(%g,%g,%g,%g)",a,b,c,d); + fflush(out); + *(double*)retp = r; +}} +void d_d8_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d8) { fprintf(out,"wrong data for d_d8\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double c = *(double*)(*args++); + double d = *(double*)(*args++); + double e = *(double*)(*args++); + double f = *(double*)(*args++); + double g = *(double*)(*args++); + double h = *(double*)(*args++); + double r=a+b+c+d+e+f+g+h; + fprintf(out,"double f(8*double):(%g,%g,%g,%g,%g,%g,%g,%g)",a,b,c,d,e,f,g,h); + fflush(out); + *(double*)retp = r; +}} +void d_d16_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d16) { fprintf(out,"wrong data for d_d16\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double c = *(double*)(*args++); + double d = *(double*)(*args++); + double e = *(double*)(*args++); + double f = *(double*)(*args++); + double g = *(double*)(*args++); + double h = *(double*)(*args++); + double i = *(double*)(*args++); + double j = *(double*)(*args++); + double k = *(double*)(*args++); + double l = *(double*)(*args++); + double m = *(double*)(*args++); + double n = *(double*)(*args++); + double o = *(double*)(*args++); + double p = *(double*)(*args++); + double r=a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p; + fprintf(out,"double f(16*double):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g)",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p); + fflush(out); + *(double*)retp = r; +}} + +/* pointer tests */ +void vp_vpdpcpsp_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&vp_vpdpcpsp) { fprintf(out,"wrong data for vp_vpdpcpsp\n"); exit(1); } + {void* a = *(void* *)(*args++); + double* b = *(double* *)(*args++); + char* c = *(char* *)(*args++); + Int* d = *(Int* *)(*args++); + void* ret = (char*)b + 1; + fprintf(out,"void* f(void*,double*,char*,Int*):(0x%p,0x%p,0x%p,0x%p)",a,b,c,d); + fflush(out); + *(void* *)retp = ret; +}} + +/* mixed number tests */ +void uc_ucsil_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&uc_ucsil) { fprintf(out,"wrong data for uc_ucsil\n"); exit(1); } + {uchar a = *(unsigned char *)(*args++); + ushort b = *(unsigned short *)(*args++); + uint c = *(unsigned int *)(*args++); + ulong d = *(unsigned long *)(*args++); + uchar r = (uchar)-1; + fprintf(out,"uchar f(uchar,ushort,uint,ulong):(%u,%u,%u,%lu)",a,b,c,d); + fflush(out); + *(ffi_arg *)retp = r; +}} +void d_iidd_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_iidd) { fprintf(out,"wrong data for d_iidd\n"); exit(1); } + {int a = *(int*)(*args++); + int b = *(int*)(*args++); + double c = *(double*)(*args++); + double d = *(double*)(*args++); + double r=a+b+c+d; + fprintf(out,"double f(int,int,double,double):(%d,%d,%g,%g)",a,b,c,d); + fflush(out); + *(double*)retp = r; +}} +void d_iiidi_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_iiidi) { fprintf(out,"wrong data for d_iiidi\n"); exit(1); } + {int a = *(int*)(*args++); + int b = *(int*)(*args++); + int c = *(int*)(*args++); + double d = *(double*)(*args++); + int e = *(int*)(*args++); + double r=a+b+c+d+e; + fprintf(out,"double f(int,int,int,double,int):(%d,%d,%d,%g,%d)",a,b,c,d,e); + fflush(out); + *(double*)retp = r; +}} +void d_idid_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_idid) { fprintf(out,"wrong data for d_idid\n"); exit(1); } + {int a = *(int*)(*args++); + double b = *(double*)(*args++); + int c = *(int*)(*args++); + double d = *(double*)(*args++); + double r=a+b+c+d; + fprintf(out,"double f(int,double,int,double):(%d,%g,%d,%g)",a,b,c,d); + fflush(out); + *(double*)retp = r; +}} +void d_fdi_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_fdi) { fprintf(out,"wrong data for d_fdi\n"); exit(1); } + {float a = *(float*)(*args++); + double b = *(double*)(*args++); + int c = *(int*)(*args++); + double r=a+b+c; + fprintf(out,"double f(float,double,int):(%g,%g,%d)",a,b,c); + fflush(out); + *(double*)retp = r; +}} +void us_cdcd_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&us_cdcd) { fprintf(out,"wrong data for us_cdcd\n"); exit(1); } + {char a = *(char*)(*args++); + double b = *(double*)(*args++); + char c = *(char*)(*args++); + double d = *(double*)(*args++); + ushort r = (ushort)(a + b + c + d); + fprintf(out,"ushort f(char,double,char,double):('%c',%g,'%c',%g)",a,b,c,d); + fflush(out); + *(ffi_arg *)retp = r; +}} +void ll_iiilli_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&ll_iiilli) { fprintf(out,"wrong data for ll_iiilli\n"); exit(1); } + {int a = *(int*)(*args++); + int b = *(int*)(*args++); + int c = *(int*)(*args++); + long long d = *(long long *)(*args++); + int e = *(int*)(*args++); + long long r = (long long)(int)a + (long long)(int)b + (long long)(int)c + d + (long long)e; + fprintf(out,"long long f(int,int,int,long long,int):(%d,%d,%d,0x%lx%08lx,%d)",a,b,c,(long)(d>>32),(long)(d&0xffffffff),e); + fflush(out); + *(long long *)retp = r; +}} +void ll_flli_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&ll_flli) { fprintf(out,"wrong data for ll_flli\n"); exit(1); } + {float a = *(float*)(*args++); + long long b = *(long long *)(*args++); + int c = *(int*)(*args++); + long long r = (long long)(int)a + b + (long long)c; + fprintf(out,"long long f(float,long long,int):(%g,0x%lx%08lx,0x%lx)",a,(long)(b>>32),(long)(b&0xffffffff),(long)c); + fflush(out); + *(long long *)retp = r; +}} +void f_fi_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_fi) { fprintf(out,"wrong data for f_fi\n"); exit(1); } + {float a = *(float*)(*args++); + int z = *(int*)(*args++); + float r=a+z; + fprintf(out,"float f(float,int):(%g,%d)",a,z); + fflush(out); + *(float*)retp = r; +}} +void f_f2i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f2i) { fprintf(out,"wrong data for f_f2i\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + int z = *(int*)(*args++); + float r=a+b+z; + fprintf(out,"float f(2*float,int):(%g,%g,%d)",a,b,z); + fflush(out); + *(float*)retp = r; +}} +void f_f3i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f3i) { fprintf(out,"wrong data for f_f3i\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + int z = *(int*)(*args++); + float r=a+b+c+z; + fprintf(out,"float f(3*float,int):(%g,%g,%g,%d)",a,b,c,z); + fflush(out); + *(float*)retp = r; +}} +void f_f4i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f4i) { fprintf(out,"wrong data for f_f4i\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + float d = *(float*)(*args++); + int z = *(int*)(*args++); + float r=a+b+c+d+z; + fprintf(out,"float f(4*float,int):(%g,%g,%g,%g,%d)",a,b,c,d,z); + fflush(out); + *(float*)retp = r; +}} +void f_f7i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f7i) { fprintf(out,"wrong data for f_f7i\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + float d = *(float*)(*args++); + float e = *(float*)(*args++); + float f = *(float*)(*args++); + float g = *(float*)(*args++); + int z = *(int*)(*args++); + float r=a+b+c+d+e+f+g+z; + fprintf(out,"float f(7*float,int):(%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,z); + fflush(out); + *(float*)retp = r; +}} +void f_f8i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f8i) { fprintf(out,"wrong data for f_f8i\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + float d = *(float*)(*args++); + float e = *(float*)(*args++); + float f = *(float*)(*args++); + float g = *(float*)(*args++); + float h = *(float*)(*args++); + int z = *(int*)(*args++); + float r=a+b+c+d+e+f+g+h+z; + fprintf(out,"float f(8*float,int):(%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,z); + fflush(out); + *(float*)retp = r; +}} +void f_f12i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f12i) { fprintf(out,"wrong data for f_f12i\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + float d = *(float*)(*args++); + float e = *(float*)(*args++); + float f = *(float*)(*args++); + float g = *(float*)(*args++); + float h = *(float*)(*args++); + float i = *(float*)(*args++); + float j = *(float*)(*args++); + float k = *(float*)(*args++); + float l = *(float*)(*args++); + int z = *(int*)(*args++); + float r=a+b+c+d+e+f+g+h+i+j+k+l+z; + fprintf(out,"float f(12*float,int):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,i,j,k,l,z); + fflush(out); + *(float*)retp = r; +}} +void f_f13i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f13i) { fprintf(out,"wrong data for f_f13i\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + float d = *(float*)(*args++); + float e = *(float*)(*args++); + float f = *(float*)(*args++); + float g = *(float*)(*args++); + float h = *(float*)(*args++); + float i = *(float*)(*args++); + float j = *(float*)(*args++); + float k = *(float*)(*args++); + float l = *(float*)(*args++); + float m = *(float*)(*args++); + int z = *(int*)(*args++); + float r=a+b+c+d+e+f+g+h+i+j+k+l+m+z; + fprintf(out,"float f(13*float,int):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,i,j,k,l,m,z); + fflush(out); + *(float*)retp = r; +}} +void d_di_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_di) { fprintf(out,"wrong data for d_di\n"); exit(1); } + {double a = *(double*)(*args++); + int z = *(int*)(*args++); + double r=a+z; + fprintf(out,"double f(double,int):(%g,%d)",a,z); + fflush(out); + *(double*)retp = r; +}} +void d_d2i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d2i) { fprintf(out,"wrong data for d_d2i\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + int z = *(int*)(*args++); + double r=a+b+z; + fprintf(out,"double f(2*double,int):(%g,%g,%d)",a,b,z); + fflush(out); + *(double*)retp = r; +}} +void d_d3i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d3i) { fprintf(out,"wrong data for d_d3i\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double c = *(double*)(*args++); + int z = *(int*)(*args++); + double r=a+b+c+z; + fprintf(out,"double f(3*double,int):(%g,%g,%g,%d)",a,b,c,z); + fflush(out); + *(double*)retp = r; +}} +void d_d4i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d4i) { fprintf(out,"wrong data for d_d4i\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double c = *(double*)(*args++); + double d = *(double*)(*args++); + int z = *(int*)(*args++); + double r=a+b+c+d+z; + fprintf(out,"double f(4*double,int):(%g,%g,%g,%g,%d)",a,b,c,d,z); + fflush(out); + *(double*)retp = r; +}} +void d_d7i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d7i) { fprintf(out,"wrong data for d_d7i\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double c = *(double*)(*args++); + double d = *(double*)(*args++); + double e = *(double*)(*args++); + double f = *(double*)(*args++); + double g = *(double*)(*args++); + int z = *(int*)(*args++); + double r=a+b+c+d+e+f+g+z; + fprintf(out,"double f(7*double,int):(%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,z); + fflush(out); + *(double*)retp = r; +}} +void d_d8i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d8i) { fprintf(out,"wrong data for d_d8i\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double c = *(double*)(*args++); + double d = *(double*)(*args++); + double e = *(double*)(*args++); + double f = *(double*)(*args++); + double g = *(double*)(*args++); + double h = *(double*)(*args++); + int z = *(int*)(*args++); + double r=a+b+c+d+e+f+g+h+z; + fprintf(out,"double f(8*double,int):(%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,z); + fflush(out); + *(double*)retp = r; +}} +void d_d12i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d12i) { fprintf(out,"wrong data for d_d12i\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double c = *(double*)(*args++); + double d = *(double*)(*args++); + double e = *(double*)(*args++); + double f = *(double*)(*args++); + double g = *(double*)(*args++); + double h = *(double*)(*args++); + double i = *(double*)(*args++); + double j = *(double*)(*args++); + double k = *(double*)(*args++); + double l = *(double*)(*args++); + int z = *(int*)(*args++); + double r=a+b+c+d+e+f+g+h+i+j+k+l+z; + fprintf(out,"double f(12*double,int):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,i,j,k,l,z); + fflush(out); + *(double*)retp = r; +}} +void d_d13i_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d13i) { fprintf(out,"wrong data for d_d13i\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double c = *(double*)(*args++); + double d = *(double*)(*args++); + double e = *(double*)(*args++); + double f = *(double*)(*args++); + double g = *(double*)(*args++); + double h = *(double*)(*args++); + double i = *(double*)(*args++); + double j = *(double*)(*args++); + double k = *(double*)(*args++); + double l = *(double*)(*args++); + double m = *(double*)(*args++); + int z = *(int*)(*args++); + double r=a+b+c+d+e+f+g+h+i+j+k+l+m+z; + fprintf(out,"double f(13*double,int):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,i,j,k,l,m,z); + fflush(out); + *(double*)retp = r; +}} + +/* small structure return tests */ +void S1_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&S1_v) { fprintf(out,"wrong data for S1_v\n"); exit(1); } + {Size1 r = Size1_1; + fprintf(out,"Size1 f(void):"); + fflush(out); + *(Size1*)retp = r; +}} +void S2_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&S2_v) { fprintf(out,"wrong data for S2_v\n"); exit(1); } + {Size2 r = Size2_1; + fprintf(out,"Size2 f(void):"); + fflush(out); + *(Size2*)retp = r; +}} +void S3_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&S3_v) { fprintf(out,"wrong data for S3_v\n"); exit(1); } + {Size3 r = Size3_1; + fprintf(out,"Size3 f(void):"); + fflush(out); + *(Size3*)retp = r; +}} +void S4_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&S4_v) { fprintf(out,"wrong data for S4_v\n"); exit(1); } + {Size4 r = Size4_1; + fprintf(out,"Size4 f(void):"); + fflush(out); + *(Size4*)retp = r; +}} +void S7_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&S7_v) { fprintf(out,"wrong data for S7_v\n"); exit(1); } + {Size7 r = Size7_1; + fprintf(out,"Size7 f(void):"); + fflush(out); + *(Size7*)retp = r; +}} +void S8_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&S8_v) { fprintf(out,"wrong data for S8_v\n"); exit(1); } + {Size8 r = Size8_1; + fprintf(out,"Size8 f(void):"); + fflush(out); + *(Size8*)retp = r; +}} +void S12_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&S12_v) { fprintf(out,"wrong data for S12_v\n"); exit(1); } + {Size12 r = Size12_1; + fprintf(out,"Size12 f(void):"); + fflush(out); + *(Size12*)retp = r; +}} +void S15_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&S15_v) { fprintf(out,"wrong data for S15_v\n"); exit(1); } + {Size15 r = Size15_1; + fprintf(out,"Size15 f(void):"); + fflush(out); + *(Size15*)retp = r; +}} +void S16_v_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&S16_v) { fprintf(out,"wrong data for S16_v\n"); exit(1); } + {Size16 r = Size16_1; + fprintf(out,"Size16 f(void):"); + fflush(out); + *(Size16*)retp = r; +}} + +/* structure tests */ +void I_III_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&I_III) { fprintf(out,"wrong data for I_III\n"); exit(1); } + {Int a = *(Int*)(*args++); + Int b = *(Int*)(*args++); + Int c = *(Int*)(*args++); + Int r; + r.x = a.x + b.x + c.x; + fprintf(out,"Int f(Int,Int,Int):({%d},{%d},{%d})",a.x,b.x,c.x); + fflush(out); + *(Int*)retp = r; +}} +void C_CdC_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&C_CdC) { fprintf(out,"wrong data for C_CdC\n"); exit(1); } + {Char a = *(Char*)(*args++); + double b = *(double*)(*args++); + Char c = *(Char*)(*args++); + Char r; + r.x = (a.x + c.x)/2; + fprintf(out,"Char f(Char,double,Char):({'%c'},%g,{'%c'})",a.x,b,c.x); + fflush(out); + *(Char*)retp = r; +}} +void F_Ffd_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&F_Ffd) { fprintf(out,"wrong data for F_Ffd\n"); exit(1); } + {Float a = *(Float*)(*args++); + float b = *(float*)(*args++); + double c = *(double*)(*args++); + Float r; + r.x = a.x + b + c; + fprintf(out,"Float f(Float,float,double):({%g},%g,%g)",a.x,b,c); + fflush(out); + *(Float*)retp = r; +}} +void D_fDd_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&D_fDd) { fprintf(out,"wrong data for D_fDd\n"); exit(1); } + {float a = *(float*)(*args++); + Double b = *(Double*)(*args++); + double c = *(double*)(*args++); + Double r; + r.x = a + b.x + c; + fprintf(out,"Double f(float,Double,double):(%g,{%g},%g)",a,b.x,c); + fflush(out); + *(Double*)retp = r; +}} +void D_Dfd_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&D_Dfd) { fprintf(out,"wrong data for D_Dfd\n"); exit(1); } + {Double a = *(Double*)(*args++); + float b = *(float*)(*args++); + double c = *(double*)(*args++); + Double r; + r.x = a.x + b + c; + fprintf(out,"Double f(Double,float,double):({%g},%g,%g)",a.x,b,c); + fflush(out); + *(Double*)retp = r; +}} +void J_JiJ_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&J_JiJ) { fprintf(out,"wrong data for J_JiJ\n"); exit(1); } + {J a = *(J*)(*args++); + int b= *(int*)(*args++); + J c = *(J*)(*args++); + J r; + r.l1 = a.l1+c.l1; r.l2 = a.l2+b+c.l2; + fprintf(out,"J f(J,int,J):({%ld,%ld},%d,{%ld,%ld})",a.l1,a.l2,b,c.l1,c.l2); + fflush(out); + *(J*)retp = r; +}} +#ifndef SKIP_EXTRA_STRUCTS +void T_TcT_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&T_TcT) { fprintf(out,"wrong data for T_TcT\n"); exit(1); } + {T a = *(T*)(*args++); + char b = *(char*)(*args++); + T c = *(T*)(*args++); + T r; + r.c[0]='b'; r.c[1]=c.c[1]; r.c[2]=c.c[2]; + fprintf(out,"T f(T,char,T):({\"%c%c%c\"},'%c',{\"%c%c%c\"})",a.c[0],a.c[1],a.c[2],b,c.c[0],c.c[1],c.c[2]); + fflush(out); + *(T*)retp = r; +}} +void X_BcdB_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&X_BcdB) { fprintf(out,"wrong data for X_BcdB\n"); exit(1); } + {B a = *(B*)(*args++); + char b = *(char*)(*args++); + double c = *(double*)(*args++); + B d = *(B*)(*args++); + static X xr={"return val",'R'}; + X r; + r = xr; + r.c1 = b; + fprintf(out,"X f(B,char,double,B):({%g,{%d,%d,%d}},'%c',%g,{%g,{%d,%d,%d}})", + a.d,a.i[0],a.i[1],a.i[2],b,c,d.d,d.i[0],d.i[1],d.i[2]); + fflush(out); + *(X*)retp = r; +}} +#endif + +/* gpargs boundary tests */ +void l_l0K_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&l_l0K) { fprintf(out,"wrong data for l_l0K\n"); exit(1); } + {K b = *(K*)(*args++); + long c = *(long*)(*args++); + long r = b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(K,long):(%ld,%ld,%ld,%ld,%ld)",b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + *(ffi_arg*)retp = r; +}} +void l_l1K_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&l_l1K) { fprintf(out,"wrong data for l_l1K\n"); exit(1); } + {long a1 = *(long*)(*args++); + K b = *(K*)(*args++); + long c = *(long*)(*args++); + long r = a1 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld)",a1,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + *(ffi_arg*)retp = r; +}} +void l_l2K_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&l_l2K) { fprintf(out,"wrong data for l_l2K\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + K b = *(K*)(*args++); + long c = *(long*)(*args++); + long r = a1 + a2 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(2*long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a1,a2,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + *(ffi_arg*)retp = r; +}} +void l_l3K_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&l_l3K) { fprintf(out,"wrong data for l_l3K\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + K b = *(K*)(*args++); + long c = *(long*)(*args++); + long r = a1 + a2 + a3 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(3*long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a1,a2,a3,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + *(ffi_arg*)retp = r; +}} +void l_l4K_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&l_l4K) { fprintf(out,"wrong data for l_l4K\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + K b = *(K*)(*args++); + long c = *(long*)(*args++); + long r = a1 + a2 + a3 + a4 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(4*long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a1,a2,a3,a4,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + *(ffi_arg*)retp = r; +}} +void l_l5K_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&l_l5K) { fprintf(out,"wrong data for l_l5K\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + long a5 = *(long*)(*args++); + K b = *(K*)(*args++); + long c = *(long*)(*args++); + long r = a1 + a2 + a3 + a4 + a5 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(5*long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a1,a2,a3,a4,a5,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + *(ffi_arg*)retp = r; +}} +void l_l6K_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&l_l6K) { fprintf(out,"wrong data for l_l6K\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + long a5 = *(long*)(*args++); + long a6 = *(long*)(*args++); + K b = *(K*)(*args++); + long c = *(long*)(*args++); + long r = a1 + a2 + a3 + a4 + a5 + a6 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(6*long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a1,a2,a3,a4,a5,a6,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + *(ffi_arg*)retp = r; +}} +void f_f17l3L_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&f_f17l3L) { fprintf(out,"wrong data for f_f17l3L\n"); exit(1); } + {float a = *(float*)(*args++); + float b = *(float*)(*args++); + float c = *(float*)(*args++); + float d = *(float*)(*args++); + float e = *(float*)(*args++); + float f = *(float*)(*args++); + float g = *(float*)(*args++); + float h = *(float*)(*args++); + float i = *(float*)(*args++); + float j = *(float*)(*args++); + float k = *(float*)(*args++); + float l = *(float*)(*args++); + float m = *(float*)(*args++); + float n = *(float*)(*args++); + float o = *(float*)(*args++); + float p = *(float*)(*args++); + float q = *(float*)(*args++); + long s = *(long*)(*args++); + long t = *(long*)(*args++); + long u = *(long*)(*args++); + L z = *(L*)(*args++); + float r = a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+s+t+u+z.l1+z.l2+z.l3+z.l4+z.l5+z.l6; + fprintf(out,"float f(17*float,3*int,L):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,s,t,u,z.l1,z.l2,z.l3,z.l4,z.l5,z.l6); + fflush(out); + *(float*)retp = r; +}} +void d_d17l3L_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_d17l3L) { fprintf(out,"wrong data for d_d17l3L\n"); exit(1); } + {double a = *(double*)(*args++); + double b = *(double*)(*args++); + double c = *(double*)(*args++); + double d = *(double*)(*args++); + double e = *(double*)(*args++); + double f = *(double*)(*args++); + double g = *(double*)(*args++); + double h = *(double*)(*args++); + double i = *(double*)(*args++); + double j = *(double*)(*args++); + double k = *(double*)(*args++); + double l = *(double*)(*args++); + double m = *(double*)(*args++); + double n = *(double*)(*args++); + double o = *(double*)(*args++); + double p = *(double*)(*args++); + double q = *(double*)(*args++); + long s = *(long*)(*args++); + long t = *(long*)(*args++); + long u = *(long*)(*args++); + L z = *(L*)(*args++); + double r = a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+s+t+u+z.l1+z.l2+z.l3+z.l4+z.l5+z.l6; + fprintf(out,"double f(17*double,3*int,L):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,s,t,u,z.l1,z.l2,z.l3,z.l4,z.l5,z.l6); + fflush(out); + *(double*)retp = r; +}} +void ll_l2ll_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&ll_l2ll) { fprintf(out,"wrong data for ll_l2ll\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long long b = *(long long *)(*args++); + long c = *(long*)(*args++); + long long r = (long long) (a1 + a2) + b + c; + fprintf(out,"long long f(2*long,long long,long):(%ld,%ld,0x%lx%08lx,%ld)",a1,a2,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + *(long long *)retp = r; +}} +void ll_l3ll_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&ll_l3ll) { fprintf(out,"wrong data for ll_l3ll\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long long b = *(long long *)(*args++); + long c = *(long*)(*args++); + long long r = (long long) (a1 + a2 + a3) + b + c; + fprintf(out,"long long f(3*long,long long,long):(%ld,%ld,%ld,0x%lx%08lx,%ld)",a1,a2,a3,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + *(long long *)retp = r; +}} +void ll_l4ll_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&ll_l4ll) { fprintf(out,"wrong data for ll_l4ll\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + long long b = *(long long *)(*args++); + long c = *(long*)(*args++); + long long r = (long long) (a1 + a2 + a3 + a4) + b + c; + fprintf(out,"long long f(4*long,long long,long):(%ld,%ld,%ld,%ld,0x%lx%08lx,%ld)",a1,a2,a3,a4,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + *(long long *)retp = r; +}} +void ll_l5ll_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&ll_l5ll) { fprintf(out,"wrong data for ll_l5ll\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + long a5 = *(long*)(*args++); + long long b = *(long long *)(*args++); + long c = *(long*)(*args++); + long long r = (long long) (a1 + a2 + a3 + a4 + a5) + b + c; + fprintf(out,"long long f(5*long,long long,long):(%ld,%ld,%ld,%ld,%ld,0x%lx%08lx,%ld)",a1,a2,a3,a4,a5,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + *(long long *)retp = r; +}} +void ll_l6ll_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&ll_l6ll) { fprintf(out,"wrong data for ll_l6ll\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + long a5 = *(long*)(*args++); + long a6 = *(long*)(*args++); + long long b = *(long long *)(*args++); + long c = *(long*)(*args++); + long long r = (long long) (a1 + a2 + a3 + a4 + a5 + a6) + b + c; + fprintf(out,"long long f(6*long,long long,long):(%ld,%ld,%ld,%ld,%ld,%ld,0x%lx%08lx,%ld)",a1,a2,a3,a4,a5,a6,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + *(long long *)retp = r; +}} +void ll_l7ll_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&ll_l7ll) { fprintf(out,"wrong data for ll_l7ll\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + long a5 = *(long*)(*args++); + long a6 = *(long*)(*args++); + long a7 = *(long*)(*args++); + long long b = *(long long *)(*args++); + long c = *(long*)(*args++); + long long r = (long long) (a1 + a2 + a3 + a4 + a5 + a6 + a7) + b + c; + fprintf(out,"long long f(7*long,long long,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,0x%lx%08lx,%ld)",a1,a2,a3,a4,a5,a6,a7,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + *(long long *)retp = r; +}} +void d_l2d_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_l2d) { fprintf(out,"wrong data for d_l2d\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + double b = *(double*)(*args++); + long c = *(long*)(*args++); + double r = (double) (a1 + a2) + b + c; + fprintf(out,"double f(2*long,double,long):(%ld,%ld,%g,%ld)",a1,a2,b,c); + fflush(out); + *(double*)retp = r; +}} +void d_l3d_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_l3d) { fprintf(out,"wrong data for d_l3d\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + double b = *(double*)(*args++); + long c = *(long*)(*args++); + double r = (double) (a1 + a2 + a3) + b + c; + fprintf(out,"double f(3*long,double,long):(%ld,%ld,%ld,%g,%ld)",a1,a2,a3,b,c); + fflush(out); + *(double*)retp = r; +}} +void d_l4d_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_l4d) { fprintf(out,"wrong data for d_l4d\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + double b = *(double*)(*args++); + long c = *(long*)(*args++); + double r = (double) (a1 + a2 + a3 + a4) + b + c; + fprintf(out,"double f(4*long,double,long):(%ld,%ld,%ld,%ld,%g,%ld)",a1,a2,a3,a4,b,c); + fflush(out); + *(double*)retp = r; +}} +void d_l5d_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_l5d) { fprintf(out,"wrong data for d_l5d\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + long a5 = *(long*)(*args++); + double b = *(double*)(*args++); + long c = *(long*)(*args++); + double r = (double) (a1 + a2 + a3 + a4 + a5) + b + c; + fprintf(out,"double f(5*long,double,long):(%ld,%ld,%ld,%ld,%ld,%g,%ld)",a1,a2,a3,a4,a5,b,c); + fflush(out); + *(double*)retp = r; +}} +void d_l6d_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_l6d) { fprintf(out,"wrong data for d_l6d\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + long a5 = *(long*)(*args++); + long a6 = *(long*)(*args++); + double b = *(double*)(*args++); + long c = *(long*)(*args++); + double r = (double) (a1 + a2 + a3 + a4 + a5 + a6) + b + c; + fprintf(out,"double f(6*long,double,long):(%ld,%ld,%ld,%ld,%ld,%ld,%g,%ld)",a1,a2,a3,a4,a5,a6,b,c); + fflush(out); + *(double*)retp = r; +}} +void d_l7d_simulator (ffi_cif* cif, void* retp, /*const*/ void* /*const*/ *args, void* data) +{ + if (data != (void*)&d_l7d) { fprintf(out,"wrong data for d_l7d\n"); exit(1); } + {long a1 = *(long*)(*args++); + long a2 = *(long*)(*args++); + long a3 = *(long*)(*args++); + long a4 = *(long*)(*args++); + long a5 = *(long*)(*args++); + long a6 = *(long*)(*args++); + long a7 = *(long*)(*args++); + double b = *(double*)(*args++); + long c = *(long*)(*args++); + double r = (double) (a1 + a2 + a3 + a4 + a5 + a6 + a7) + b + c; + fprintf(out,"double f(7*long,double,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,%g,%ld)",a1,a2,a3,a4,a5,a6,a7,b,c); + fflush(out); + *(double*)retp = r; +}} + + +/* + * The way we run these tests - first call the function directly, then + * through vacall() - there is the danger that arguments or results seem + * to be passed correctly, but what we are seeing are in fact the vestiges + * (traces) or the previous call. This may seriously fake the test. + * Avoid this by clearing the registers between the first and the second call. + */ +long clear_traces_i (long a, long b, long c, long d, long e, long f, long g, long h, + long i, long j, long k, long l, long m, long n, long o, long p) +{ return 0; } +float clear_traces_f (float a, float b, float c, float d, float e, float f, float g, + float h, float i, float j, float k, float l, float m, float n, + float o, float p) +{ return 0.0; } +double clear_traces_d (double a, double b, double c, double d, double e, double f, double g, + double h, double i, double j, double k, double l, double m, double n, + double o, double p) +{ return 0.0; } +J clear_traces_J (void) +{ J j; j.l1 = j.l2 = 0; return j; } +void clear_traces (void) +{ clear_traces_i(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); + clear_traces_f(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0); + clear_traces_d(0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0); + clear_traces_J(); +} + +int main (void) +{ + void* callback_code; + void* callback_writable; +#define ALLOC_CALLBACK() \ + callback_writable = ffi_closure_alloc(sizeof(ffi_closure),&callback_code); \ + if (!callback_writable) abort() +#define PREP_CALLBACK(cif,simulator,data) \ + if (ffi_prep_closure_loc(callback_writable,&(cif),simulator,data,callback_code) != FFI_OK) abort() +#define FREE_CALLBACK() \ + ffi_closure_free(callback_writable) + + ffi_type_char = (char)(-1) < 0 ? ffi_type_schar : ffi_type_uchar; + out = stdout; + +#if (!defined(DGTEST)) || DGTEST == 1 + /* void tests */ + v_v(); + clear_traces(); + ALLOC_CALLBACK(); + { + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_void); + PREP_CALLBACK(cif,v_v_simulator,(void*)&v_v); + ((void (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); +#endif + + /* int tests */ + { int ir; + +#if (!defined(DGTEST)) || DGTEST == 2 + ir = i_v(); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_sint); + PREP_CALLBACK(cif,i_v_simulator,(void*)&i_v); + ir = ((int (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 3 + ir = i_i(i1); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_sint); + PREP_CALLBACK(cif,i_i_simulator,(void*)&i_i); + ir = ((int (ABI_ATTR *) (int)) callback_code) (i1); + } + FREE_CALLBACK(); + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 4 + ir = i_i2(i1,i2); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_sint); + PREP_CALLBACK(cif,i_i2_simulator,(void*)&i_i2); + ir = ((int (ABI_ATTR *) (int,int)) callback_code) (i1,i2); + } + FREE_CALLBACK(); + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 5 + ir = i_i4(i1,i2,i3,i4); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_sint); + PREP_CALLBACK(cif,i_i4_simulator,(void*)&i_i4); + ir = ((int (ABI_ATTR *) (int,int,int,int)) callback_code) (i1,i2,i3,i4); + } + FREE_CALLBACK(); + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 6 + ir = i_i8(i1,i2,i3,i4,i5,i6,i7,i8); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_sint); + PREP_CALLBACK(cif,i_i8_simulator,(void*)&i_i8); + ir = ((int (ABI_ATTR *) (int,int,int,int,int,int,int,int)) callback_code) (i1,i2,i3,i4,i5,i6,i7,i8); + } + FREE_CALLBACK(); + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 7 + ir = i_i16(i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15,i16); + fprintf(out,"->%d\n",ir); + fflush(out); + ir = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_sint); + PREP_CALLBACK(cif,i_i16_simulator,(void*)&i_i16); + ir = ((int (ABI_ATTR *) (int,int,int,int,int,int,int,int,int,int,int,int,int,int,int,int)) callback_code) (i1,i2,i3,i4,i5,i6,i7,i8,i9,i10,i11,i12,i13,i14,i15,i16); + } + FREE_CALLBACK(); + fprintf(out,"->%d\n",ir); + fflush(out); +#endif + } + + /* float tests */ + { float fr; + +#if (!defined(DGTEST)) || DGTEST == 8 + fr = f_f(f1); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f_simulator,(void*)&f_f); + fr = ((float (ABI_ATTR *) (float)) callback_code) (f1); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 9 + fr = f_f2(f1,f2); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f2_simulator,(void*)&f_f2); + fr = ((float (ABI_ATTR *) (float,float)) callback_code) (f1,f2); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 10 + fr = f_f4(f1,f2,f3,f4); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f4_simulator,(void*)&f_f4); + fr = ((float (ABI_ATTR *) (float,float,float,float)) callback_code) (f1,f2,f3,f4); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 11 + fr = f_f8(f1,f2,f3,f4,f5,f6,f7,f8); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f8_simulator,(void*)&f_f8); + fr = ((float (ABI_ATTR *) (float,float,float,float,float,float,float,float)) callback_code) (f1,f2,f3,f4,f5,f6,f7,f8); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 12 + fr = f_f16(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f16_simulator,(void*)&f_f16); + fr = ((float (ABI_ATTR *) (float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float)) callback_code) (f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 13 + fr = f_f24(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18,f19,f20,f21,f22,f23,f24); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f24_simulator,(void*)&f_f24); + fr = ((float (ABI_ATTR *) (float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float)) callback_code) (f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,f18,f19,f20,f21,f22,f23,f24); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + + } + + /* double tests */ + { double dr; + +#if (!defined(DGTEST)) || DGTEST == 14 + dr = d_d(d1); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d_simulator,(void*)&d_d); + dr = ((double (ABI_ATTR *) (double)) callback_code) (d1); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 15 + dr = d_d2(d1,d2); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d2_simulator,(void*)&d_d2); + dr = ((double (ABI_ATTR *) (double,double)) callback_code) (d1,d2); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 16 + dr = d_d4(d1,d2,d3,d4); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d4_simulator,(void*)&d_d4); + dr = ((double (ABI_ATTR *) (double,double,double,double)) callback_code) (d1,d2,d3,d4); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 17 + dr = d_d8(d1,d2,d3,d4,d5,d6,d7,d8); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d8_simulator,(void*)&d_d8); + dr = ((double (ABI_ATTR *) (double,double,double,double,double,double,double,double)) callback_code) (d1,d2,d3,d4,d5,d6,d7,d8); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 18 + dr = d_d16(d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d16_simulator,(void*)&d_d16); + dr = ((double (ABI_ATTR *) (double,double,double,double,double,double,double,double,double,double,double,double,double,double,double,double)) callback_code) (d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + } + + /* pointer tests */ + { void* vpr; + +#if (!defined(DGTEST)) || DGTEST == 19 + vpr = vp_vpdpcpsp(&uc1,&d2,str3,&I4); + fprintf(out,"->0x%p\n",vpr); + fflush(out); + vpr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_pointer, &ffi_type_pointer, &ffi_type_pointer, &ffi_type_pointer }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_pointer); + PREP_CALLBACK(cif,vp_vpdpcpsp_simulator,(void*)&vp_vpdpcpsp); + vpr = ((void* (ABI_ATTR *) (void*,double*,char*,Int*)) callback_code) (&uc1,&d2,str3,&I4); + } + FREE_CALLBACK(); + fprintf(out,"->0x%p\n",vpr); + fflush(out); +#endif + } + + /* mixed number tests */ + { uchar ucr; + ushort usr; + float fr; + double dr; + long long llr; + +#if (!defined(DGTEST)) || DGTEST == 20 + ucr = uc_ucsil(uc1,us2,ui3,ul4); + fprintf(out,"->%u\n",ucr); + fflush(out); + ucr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_uchar, &ffi_type_ushort, &ffi_type_uint, &ffi_type_ulong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_uchar); + PREP_CALLBACK(cif,uc_ucsil_simulator,(void*)&uc_ucsil); + ucr = ((uchar (ABI_ATTR *) (uchar,ushort,uint,ulong)) callback_code) (uc1,us2,ui3,ul4); + } + FREE_CALLBACK(); + fprintf(out,"->%u\n",ucr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 21 + dr = d_iidd(i1,i2,d3,d4); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_iidd_simulator,(void*)&d_iidd); + dr = ((double (ABI_ATTR *) (int,int,double,double)) callback_code) (i1,i2,d3,d4); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 22 + dr = d_iiidi(i1,i2,i3,d4,i5); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_iiidi_simulator,(void*)&d_iiidi); + dr = ((double (ABI_ATTR *) (int,int,int,double,int)) callback_code) (i1,i2,i3,d4,i5); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 23 + dr = d_idid(i1,d2,i3,d4); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_double, &ffi_type_sint, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_idid_simulator,(void*)&d_idid); + dr = ((double (ABI_ATTR *) (int,double,int,double)) callback_code) (i1,d2,i3,d4); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 24 + dr = d_fdi(f1,d2,i3); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_fdi_simulator,(void*)&d_fdi); + dr = ((double (ABI_ATTR *) (float,double,int)) callback_code) (f1,d2,i3); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 25 + usr = us_cdcd(c1,d2,c3,d4); + fprintf(out,"->%u\n",usr); + fflush(out); + usr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_char, &ffi_type_double, &ffi_type_char, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_ushort); + PREP_CALLBACK(cif,us_cdcd_simulator,(void*)&us_cdcd); + usr = ((ushort (ABI_ATTR *) (char,double,char,double)) callback_code) (c1,d2,c3,d4); + } + FREE_CALLBACK(); + fprintf(out,"->%u\n",usr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 26 + llr = ll_iiilli(i1,i2,i3,ll1,i13); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_sint, &ffi_type_sint, &ffi_type_sint, &ffi_type_slonglong, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + PREP_CALLBACK(cif,ll_iiilli_simulator,(void*)&ll_iiilli); + llr = ((long long (ABI_ATTR *) (int,int,int,long long,int)) callback_code) (i1,i2,i3,ll1,i13); + } + FREE_CALLBACK(); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 27 + llr = ll_flli(f13,ll1,i13); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_slonglong, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + PREP_CALLBACK(cif,ll_flli_simulator,(void*)&ll_flli); + llr = ((long long (ABI_ATTR *) (float,long long,int)) callback_code) (f13,ll1,i13); + } + FREE_CALLBACK(); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 28 + fr = f_fi(f1,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_fi_simulator,(void*)&f_fi); + fr = ((float (ABI_ATTR *) (float,int)) callback_code) (f1,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 29 + fr = f_f2i(f1,f2,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f2i_simulator,(void*)&f_f2i); + fr = ((float (ABI_ATTR *) (float,float,int)) callback_code) (f1,f2,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 30 + fr = f_f3i(f1,f2,f3,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f3i_simulator,(void*)&f_f3i); + fr = ((float (ABI_ATTR *) (float,float,float,int)) callback_code) (f1,f2,f3,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 31 + fr = f_f4i(f1,f2,f3,f4,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f4i_simulator,(void*)&f_f4i); + fr = ((float (ABI_ATTR *) (float,float,float,float,int)) callback_code) (f1,f2,f3,f4,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 32 + fr = f_f7i(f1,f2,f3,f4,f5,f6,f7,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f7i_simulator,(void*)&f_f7i); + fr = ((float (ABI_ATTR *) (float,float,float,float,float,float,float,int)) callback_code) (f1,f2,f3,f4,f5,f6,f7,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 33 + fr = f_f8i(f1,f2,f3,f4,f5,f6,f7,f8,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f8i_simulator,(void*)&f_f8i); + fr = ((float (ABI_ATTR *) (float,float,float,float,float,float,float,float,int)) callback_code) (f1,f2,f3,f4,f5,f6,f7,f8,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 34 + fr = f_f13i(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,i9); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f13i_simulator,(void*)&f_f13i); + fr = ((float (ABI_ATTR *) (float,float,float,float,float,float,float,float,float,float,float,float,float,int)) callback_code) (f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 35 + dr = d_di(d1,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_di_simulator,(void*)&d_di); + dr = ((double (ABI_ATTR *) (double,int)) callback_code) (d1,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 36 + dr = d_d2i(d1,d2,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d2i_simulator,(void*)&d_d2i); + dr = ((double (ABI_ATTR *) (double,double,int)) callback_code) (d1,d2,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 37 + dr = d_d3i(d1,d2,d3,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d3i_simulator,(void*)&d_d3i); + dr = ((double (ABI_ATTR *) (double,double,double,int)) callback_code) (d1,d2,d3,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 38 + dr = d_d4i(d1,d2,d3,d4,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d4i_simulator,(void*)&d_d4i); + dr = ((double (ABI_ATTR *) (double,double,double,double,int)) callback_code) (d1,d2,d3,d4,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 39 + dr = d_d7i(d1,d2,d3,d4,d5,d6,d7,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d7i_simulator,(void*)&d_d7i); + dr = ((double (ABI_ATTR *) (double,double,double,double,double,double,double,int)) callback_code) (d1,d2,d3,d4,d5,d6,d7,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 40 + dr = d_d8i(d1,d2,d3,d4,d5,d6,d7,d8,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d8i_simulator,(void*)&d_d8i); + dr = ((double (ABI_ATTR *) (double,double,double,double,double,double,double,double,int)) callback_code) (d1,d2,d3,d4,d5,d6,d7,d8,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 41 + dr = d_d12i(d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d12i_simulator,(void*)&d_d12i); + dr = ((double (ABI_ATTR *) (double,double,double,double,double,double,double,double,double,double,double,double,int)) callback_code) (d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 42 + dr = d_d13i(d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,i9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_sint }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d13i_simulator,(void*)&d_d13i); + dr = ((double (ABI_ATTR *) (double,double,double,double,double,double,double,double,double,double,double,double,double,int)) callback_code) (d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,i9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + } + + /* small structure return tests */ +#if (!defined(DGTEST)) || DGTEST == 43 + { + Size1 r = S1_v(); + fprintf(out,"->{%c}\n",r.x1); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Size1_elements[] = { &ffi_type_char, NULL }; + ffi_type ffi_type_Size1; + ffi_type_Size1.type = FFI_TYPE_STRUCT; + ffi_type_Size1.size = sizeof(Size1); + ffi_type_Size1.alignment = alignof_slot(Size1); + ffi_type_Size1.elements = ffi_type_Size1_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size1); + PREP_CALLBACK(cif,S1_v_simulator,(void*)&S1_v); + r = ((Size1 (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); + fprintf(out,"->{%c}\n",r.x1); + fflush(out); + } +#endif + +#if (!defined(DGTEST)) || DGTEST == 44 + { + Size2 r = S2_v(); + fprintf(out,"->{%c%c}\n",r.x1,r.x2); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Size2_elements[] = { &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size2; + ffi_type_Size2.type = FFI_TYPE_STRUCT; + ffi_type_Size2.size = sizeof(Size2); + ffi_type_Size2.alignment = alignof_slot(Size2); + ffi_type_Size2.elements = ffi_type_Size2_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size2); + PREP_CALLBACK(cif,S2_v_simulator,(void*)&S2_v); + r = ((Size2 (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); + fprintf(out,"->{%c%c}\n",r.x1,r.x2); + fflush(out); + } +#endif + +#if (!defined(DGTEST)) || DGTEST == 45 + { + Size3 r = S3_v(); + fprintf(out,"->{%c%c%c}\n",r.x1,r.x2,r.x3); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Size3_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size3; + ffi_type_Size3.type = FFI_TYPE_STRUCT; + ffi_type_Size3.size = sizeof(Size3); + ffi_type_Size3.alignment = alignof_slot(Size3); + ffi_type_Size3.elements = ffi_type_Size3_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size3); + PREP_CALLBACK(cif,S3_v_simulator,(void*)&S3_v); + r = ((Size3 (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); + fprintf(out,"->{%c%c%c}\n",r.x1,r.x2,r.x3); + fflush(out); + } +#endif + +#if (!defined(DGTEST)) || DGTEST == 46 + { + Size4 r = S4_v(); + fprintf(out,"->{%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Size4_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size4; + ffi_type_Size4.type = FFI_TYPE_STRUCT; + ffi_type_Size4.size = sizeof(Size4); + ffi_type_Size4.alignment = alignof_slot(Size4); + ffi_type_Size4.elements = ffi_type_Size4_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size4); + PREP_CALLBACK(cif,S4_v_simulator,(void*)&S4_v); + r = ((Size4 (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); + fprintf(out,"->{%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4); + fflush(out); + } +#endif + +#if (!defined(DGTEST)) || DGTEST == 47 + { + Size7 r = S7_v(); + fprintf(out,"->{%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Size7_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size7; + ffi_type_Size7.type = FFI_TYPE_STRUCT; + ffi_type_Size7.size = sizeof(Size7); + ffi_type_Size7.alignment = alignof_slot(Size7); + ffi_type_Size7.elements = ffi_type_Size7_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size7); + PREP_CALLBACK(cif,S7_v_simulator,(void*)&S7_v); + r = ((Size7 (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); + fprintf(out,"->{%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7); + fflush(out); + } +#endif + +#if (!defined(DGTEST)) || DGTEST == 48 + { + Size8 r = S8_v(); + fprintf(out,"->{%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Size8_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size8; + ffi_type_Size8.type = FFI_TYPE_STRUCT; + ffi_type_Size8.size = sizeof(Size8); + ffi_type_Size8.alignment = alignof_slot(Size8); + ffi_type_Size8.elements = ffi_type_Size8_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size8); + PREP_CALLBACK(cif,S8_v_simulator,(void*)&S8_v); + r = ((Size8 (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); + fprintf(out,"->{%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8); + fflush(out); + } +#endif + +#if (!defined(DGTEST)) || DGTEST == 49 + { + Size12 r = S12_v(); + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Size12_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size12; + ffi_type_Size12.type = FFI_TYPE_STRUCT; + ffi_type_Size12.size = sizeof(Size12); + ffi_type_Size12.alignment = alignof_slot(Size12); + ffi_type_Size12.elements = ffi_type_Size12_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size12); + PREP_CALLBACK(cif,S12_v_simulator,(void*)&S12_v); + r = ((Size12 (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12); + fflush(out); + } +#endif + +#if (!defined(DGTEST)) || DGTEST == 50 + { + Size15 r = S15_v(); + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12,r.x13,r.x14,r.x15); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Size15_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size15; + ffi_type_Size15.type = FFI_TYPE_STRUCT; + ffi_type_Size15.size = sizeof(Size15); + ffi_type_Size15.alignment = alignof_slot(Size15); + ffi_type_Size15.elements = ffi_type_Size15_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size15); + PREP_CALLBACK(cif,S15_v_simulator,(void*)&S15_v); + r = ((Size15 (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12,r.x13,r.x14,r.x15); + fflush(out); + } +#endif + +#if (!defined(DGTEST)) || DGTEST == 51 + { + Size16 r = S16_v(); + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12,r.x13,r.x14,r.x15,r.x16); + fflush(out); + memset(&r,0,sizeof(r)); clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Size16_elements[] = { &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, &ffi_type_char, NULL }; + ffi_type ffi_type_Size16; + ffi_type_Size16.type = FFI_TYPE_STRUCT; + ffi_type_Size16.size = sizeof(Size16); + ffi_type_Size16.alignment = alignof_slot(Size16); + ffi_type_Size16.elements = ffi_type_Size16_elements; + ffi_cif cif; + FFI_PREP_CIF_NOARGS(cif,ffi_type_Size16); + PREP_CALLBACK(cif,S16_v_simulator,(void*)&S16_v); + r = ((Size16 (ABI_ATTR *) (void)) callback_code) (); + } + FREE_CALLBACK(); + fprintf(out,"->{%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c}\n",r.x1,r.x2,r.x3,r.x4,r.x5,r.x6,r.x7,r.x8,r.x9,r.x10,r.x11,r.x12,r.x13,r.x14,r.x15,r.x16); + fflush(out); + } +#endif + + + /* structure tests */ + { Int Ir; + Char Cr; + Float Fr; + Double Dr; + J Jr; +#ifndef SKIP_EXTRA_STRUCTS + T Tr; + X Xr; +#endif + +#if (!defined(DGTEST)) || DGTEST == 52 + Ir = I_III(I1,I2,I3); + fprintf(out,"->{%d}\n",Ir.x); + fflush(out); + Ir.x = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Int_elements[] = { &ffi_type_sint, NULL }; + ffi_type ffi_type_Int; + ffi_type_Int.type = FFI_TYPE_STRUCT; + ffi_type_Int.size = sizeof(Int); + ffi_type_Int.alignment = alignof_slot(Int); + ffi_type_Int.elements = ffi_type_Int_elements; + ffi_type* argtypes[] = { &ffi_type_Int, &ffi_type_Int, &ffi_type_Int }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_Int); + PREP_CALLBACK(cif,I_III_simulator,(void*)&I_III); + Ir = ((Int (ABI_ATTR *) (Int,Int,Int)) callback_code) (I1,I2,I3); + } + FREE_CALLBACK(); + fprintf(out,"->{%d}\n",Ir.x); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 53 + Cr = C_CdC(C1,d2,C3); + fprintf(out,"->{'%c'}\n",Cr.x); + fflush(out); + Cr.x = '\0'; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Char_elements[] = { &ffi_type_char, NULL }; + ffi_type ffi_type_Char; + ffi_type_Char.type = FFI_TYPE_STRUCT; + ffi_type_Char.size = sizeof(Char); + ffi_type_Char.alignment = alignof_slot(Char); + ffi_type_Char.elements = ffi_type_Char_elements; + ffi_type* argtypes[] = { &ffi_type_Char, &ffi_type_double, &ffi_type_Char }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_Char); + PREP_CALLBACK(cif,C_CdC_simulator,(void*)&C_CdC); + Cr = ((Char (ABI_ATTR *) (Char,double,Char)) callback_code) (C1,d2,C3); + } + FREE_CALLBACK(); + fprintf(out,"->{'%c'}\n",Cr.x); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 54 + Fr = F_Ffd(F1,f2,d3); + fprintf(out,"->{%g}\n",Fr.x); + fflush(out); + Fr.x = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Float_elements[] = { &ffi_type_float, NULL }; + ffi_type ffi_type_Float; + ffi_type_Float.type = FFI_TYPE_STRUCT; + ffi_type_Float.size = sizeof(Float); + ffi_type_Float.alignment = alignof_slot(Float); + ffi_type_Float.elements = ffi_type_Float_elements; + ffi_type* argtypes[] = { &ffi_type_Float, &ffi_type_float, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_Float); + PREP_CALLBACK(cif,F_Ffd_simulator,(void*)&F_Ffd); + Fr = ((Float (ABI_ATTR *) (Float,float,double)) callback_code) (F1,f2,d3); + } + FREE_CALLBACK(); + fprintf(out,"->{%g}\n",Fr.x); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 55 + Dr = D_fDd(f1,D2,d3); + fprintf(out,"->{%g}\n",Dr.x); + fflush(out); + Dr.x = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Double_elements[] = { &ffi_type_double, NULL }; + ffi_type ffi_type_Double; + ffi_type_Double.type = FFI_TYPE_STRUCT; + ffi_type_Double.size = sizeof(Double); + ffi_type_Double.alignment = alignof_slot(Double); + ffi_type_Double.elements = ffi_type_Double_elements; + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_Double, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_Double); + PREP_CALLBACK(cif,D_fDd_simulator,(void*)&D_fDd); + Dr = ((Double (ABI_ATTR *) (float,Double,double)) callback_code) (f1,D2,d3); + } + FREE_CALLBACK(); + fprintf(out,"->{%g}\n",Dr.x); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 56 + Dr = D_Dfd(D1,f2,d3); + fprintf(out,"->{%g}\n",Dr.x); + fflush(out); + Dr.x = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_Double_elements[] = { &ffi_type_double, NULL }; + ffi_type ffi_type_Double; + ffi_type_Double.type = FFI_TYPE_STRUCT; + ffi_type_Double.size = sizeof(Double); + ffi_type_Double.alignment = alignof_slot(Double); + ffi_type_Double.elements = ffi_type_Double_elements; + ffi_type* argtypes[] = { &ffi_type_Double, &ffi_type_float, &ffi_type_double }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_Double); + PREP_CALLBACK(cif,D_Dfd_simulator,(void*)&D_Dfd); + Dr = ((Double (ABI_ATTR *) (Double,float,double)) callback_code) (D1,f2,d3); + } + FREE_CALLBACK(); + fprintf(out,"->{%g}\n",Dr.x); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 57 + Jr = J_JiJ(J1,i2,J2); + fprintf(out,"->{%ld,%ld}\n",Jr.l1,Jr.l2); + fflush(out); + Jr.l1 = Jr.l2 = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_J_elements[] = { &ffi_type_slong, &ffi_type_slong, NULL }; + ffi_type ffi_type_J; + ffi_type_J.type = FFI_TYPE_STRUCT; + ffi_type_J.size = sizeof(J); + ffi_type_J.alignment = alignof_slot(J); + ffi_type_J.elements = ffi_type_J_elements; + ffi_type* argtypes[] = { &ffi_type_J, &ffi_type_sint, &ffi_type_J }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_J); + PREP_CALLBACK(cif,J_JiJ_simulator,(void*)&J_JiJ); + Jr = ((J (ABI_ATTR *) (J,int,J)) callback_code) (J1,i2,J2); + } + FREE_CALLBACK(); + fprintf(out,"->{%ld,%ld}\n",Jr.l1,Jr.l2); + fflush(out); +#endif + +#ifndef SKIP_EXTRA_STRUCTS +#if (!defined(DGTEST)) || DGTEST == 58 + Tr = T_TcT(T1,' ',T2); + fprintf(out,"->{\"%c%c%c\"}\n",Tr.c[0],Tr.c[1],Tr.c[2]); + fflush(out); + Tr.c[0] = Tr.c[1] = Tr.c[2] = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_T_elements[] = { ??, NULL }; + ffi_type ffi_type_T; + ffi_type_T.type = FFI_TYPE_STRUCT; + ffi_type_T.size = sizeof(T); + ffi_type_T.alignment = alignof_slot(T); + ffi_type_T.elements = ffi_type_T_elements; + ffi_type* argtypes[] = { &ffi_type_T, &ffi_type_char, &ffi_type_T }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_T); + PREP_CALLBACK(cif,T_TcT_simulator,(void*)&T_TcT); + Tr = ((T (ABI_ATTR *) (T,char,T)) callback_code) (T1,' ',T2); + } + FREE_CALLBACK(); + fprintf(out,"->{\"%c%c%c\"}\n",Tr.c[0],Tr.c[1],Tr.c[2]); + fflush(out); +#endif + +#ifndef SKIP_X +#if (!defined(DGTEST)) || DGTEST == 59 + Xr = X_BcdB(B1,c2,d3,B2); + fprintf(out,"->{\"%s\",'%c'}\n",Xr.c,Xr.c1); + fflush(out); + Xr.c[0]=Xr.c1='\0'; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* ffi_type_X_elements[] = { ??, NULL }; + ffi_type ffi_type_X; + ffi_type_X.type = FFI_TYPE_STRUCT; + ffi_type_X.size = sizeof(X); + ffi_type_X.alignment = alignof_slot(X); + ffi_type_X.elements = ffi_type_X_elements; + ffi_type* argtypes[] = { &ffi_type_X, &ffi_type_char, &ffi_type_double, &ffi_type_X }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_X); + PREP_CALLBACK(cif,X_BcdB_simulator,(void*)&X_BcdB); + Xr = ((X (ABI_ATTR *) (B,char,double,B)) callback_code) (B1,c2,d3,B2); + } + FREE_CALLBACK(); + fprintf(out,"->{\"%s\",'%c'}\n",Xr.c,Xr.c1); + fflush(out); +#endif +#endif +#endif + } + + + /* gpargs boundary tests */ + { + ffi_type* ffi_type_K_elements[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, NULL }; + ffi_type ffi_type_K; + ffi_type* ffi_type_L_elements[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, NULL }; + ffi_type ffi_type_L; + long lr; + long long llr; + float fr; + double dr; + + ffi_type_K.type = FFI_TYPE_STRUCT; + ffi_type_K.size = sizeof(K); + ffi_type_K.alignment = alignof_slot(K); + ffi_type_K.elements = ffi_type_K_elements; + + ffi_type_L.type = FFI_TYPE_STRUCT; + ffi_type_L.size = sizeof(L); + ffi_type_L.alignment = alignof_slot(L); + ffi_type_L.elements = ffi_type_L_elements; + +#if (!defined(DGTEST)) || DGTEST == 60 + lr = l_l0K(K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + PREP_CALLBACK(cif,l_l0K_simulator,(void*)l_l0K); + lr = ((long (ABI_ATTR *) (K,long)) callback_code) (K1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 61 + lr = l_l1K(l1,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + PREP_CALLBACK(cif,l_l1K_simulator,(void*)l_l1K); + lr = ((long (ABI_ATTR *) (long,K,long)) callback_code) (l1,K1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 62 + lr = l_l2K(l1,l2,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + PREP_CALLBACK(cif,l_l2K_simulator,(void*)l_l2K); + lr = ((long (ABI_ATTR *) (long,long,K,long)) callback_code) (l1,l2,K1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 63 + lr = l_l3K(l1,l2,l3,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + PREP_CALLBACK(cif,l_l3K_simulator,(void*)l_l3K); + lr = ((long (ABI_ATTR *) (long,long,long,K,long)) callback_code) (l1,l2,l3,K1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 64 + lr = l_l4K(l1,l2,l3,l4,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + PREP_CALLBACK(cif,l_l4K_simulator,(void*)l_l4K); + lr = ((long (ABI_ATTR *) (long,long,long,long,K,long)) callback_code) (l1,l2,l3,l4,K1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 65 + lr = l_l5K(l1,l2,l3,l4,l5,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + PREP_CALLBACK(cif,l_l5K_simulator,(void*)l_l5K); + lr = ((long (ABI_ATTR *) (long,long,long,long,long,K,long)) callback_code) (l1,l2,l3,l4,l5,K1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 66 + lr = l_l6K(l1,l2,l3,l4,l5,l6,K1,l9); + fprintf(out,"->%ld\n",lr); + fflush(out); + lr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_K, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slong); + PREP_CALLBACK(cif,l_l6K_simulator,(void*)l_l6K); + lr = ((long (ABI_ATTR *) (long,long,long,long,long,long,K,long)) callback_code) (l1,l2,l3,l4,l5,l6,K1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%ld\n",lr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 67 + fr = f_f17l3L(f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,l6,l7,l8,L1); + fprintf(out,"->%g\n",fr); + fflush(out); + fr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_float, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_L }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_float); + PREP_CALLBACK(cif,f_f17l3L_simulator,(void*)&f_f17l3L); + fr = ((float (ABI_ATTR *) (float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,float,long,long,long,L)) callback_code) (f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13,f14,f15,f16,f17,l6,l7,l8,L1); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",fr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 68 + dr = d_d17l3L(d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16,d17,l6,l7,l8,L1); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_double, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_L }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_d17l3L_simulator,(void*)&d_d17l3L); + dr = ((double (ABI_ATTR *) (double,double,double,double,double,double,double,double,double,double,double,double,double,double,double,double,double,long,long,long,L)) callback_code) (d1,d2,d3,d4,d5,d6,d7,d8,d9,d10,d11,d12,d13,d14,d15,d16,d17,l6,l7,l8,L1); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 69 + llr = ll_l2ll(l1,l2,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + PREP_CALLBACK(cif,ll_l2ll_simulator,(void*)ll_l2ll); + llr = ((long long (ABI_ATTR *) (long,long,long long,long)) callback_code) (l1,l2,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 70 + llr = ll_l3ll(l1,l2,l3,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + PREP_CALLBACK(cif,ll_l3ll_simulator,(void*)ll_l3ll); + llr = ((long long (ABI_ATTR *) (long,long,long,long long,long)) callback_code) (l1,l2,l3,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 71 + llr = ll_l4ll(l1,l2,l3,l4,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + PREP_CALLBACK(cif,ll_l4ll_simulator,(void*)ll_l4ll); + llr = ((long long (ABI_ATTR *) (long,long,long,long,long long,long)) callback_code) (l1,l2,l3,l4,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 72 + llr = ll_l5ll(l1,l2,l3,l4,l5,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + PREP_CALLBACK(cif,ll_l5ll_simulator,(void*)ll_l5ll); + llr = ((long long (ABI_ATTR *) (long,long,long,long,long,long long,long)) callback_code) (l1,l2,l3,l4,l5,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 73 + llr = ll_l6ll(l1,l2,l3,l4,l5,l6,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + PREP_CALLBACK(cif,ll_l6ll_simulator,(void*)ll_l6ll); + llr = ((long long (ABI_ATTR *) (long,long,long,long,long,long,long long,long)) callback_code) (l1,l2,l3,l4,l5,l6,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 74 + llr = ll_l7ll(l1,l2,l3,l4,l5,l6,l7,ll1,l9); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); + llr = 0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slonglong, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_slonglong); + PREP_CALLBACK(cif,ll_l7ll_simulator,(void*)ll_l7ll); + llr = ((long long (ABI_ATTR *) (long,long,long,long,long,long,long,long long,long)) callback_code) (l1,l2,l3,l4,l5,l6,l7,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->0x%lx%08lx\n",(long)(llr>>32),(long)(llr&0xffffffff)); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 75 + dr = d_l2d(l1,l2,ll1,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_l2d_simulator,(void*)d_l2d); + dr = ((double (ABI_ATTR *) (long,long,double,long)) callback_code) (l1,l2,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 76 + dr = d_l3d(l1,l2,l3,ll1,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_l3d_simulator,(void*)d_l3d); + dr = ((double (ABI_ATTR *) (long,long,long,double,long)) callback_code) (l1,l2,l3,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 77 + dr = d_l4d(l1,l2,l3,l4,ll1,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_l4d_simulator,(void*)d_l4d); + dr = ((double (ABI_ATTR *) (long,long,long,long,double,long)) callback_code) (l1,l2,l3,l4,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 78 + dr = d_l5d(l1,l2,l3,l4,l5,ll1,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_l5d_simulator,(void*)d_l5d); + dr = ((double (ABI_ATTR *) (long,long,long,long,long,double,long)) callback_code) (l1,l2,l3,l4,l5,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 79 + dr = d_l6d(l1,l2,l3,l4,l5,l6,ll1,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_l6d_simulator,(void*)d_l6d); + dr = ((double (ABI_ATTR *) (long,long,long,long,long,long,double,long)) callback_code) (l1,l2,l3,l4,l5,l6,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + +#if (!defined(DGTEST)) || DGTEST == 80 + dr = d_l7d(l1,l2,l3,l4,l5,l6,l7,ll1,l9); + fprintf(out,"->%g\n",dr); + fflush(out); + dr = 0.0; clear_traces(); + ALLOC_CALLBACK(); + { + ffi_type* argtypes[] = { &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_slong, &ffi_type_double, &ffi_type_slong }; + ffi_cif cif; + FFI_PREP_CIF(cif,argtypes,ffi_type_double); + PREP_CALLBACK(cif,d_l7d_simulator,(void*)d_l7d); + dr = ((double (ABI_ATTR *) (long,long,long,long,long,long,long,double,long)) callback_code) (l1,l2,l3,l4,l5,l6,l7,ll1,l9); + } + FREE_CALLBACK(); + fprintf(out,"->%g\n",dr); + fflush(out); +#endif + + } + + exit(0); +} + diff --git a/native/libffi/testsuite/libffi.bhaible/testcases.c b/native/libffi/testsuite/libffi.bhaible/testcases.c new file mode 100644 index 0000000000..d25ebf48c9 --- /dev/null +++ b/native/libffi/testsuite/libffi.bhaible/testcases.c @@ -0,0 +1,743 @@ +/* + * Copyright 1993 Bill Triggs + * Copyright 1995-2017 Bruno Haible + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* This file defines test functions of selected signatures, that exercise + dark corners of the various ABIs. */ + +#include + +FILE* out; + +#define uchar unsigned char +#define ushort unsigned short +#define uint unsigned int +#define ulong unsigned long + +typedef struct { char x; } Char; +typedef struct { short x; } Short; +typedef struct { int x; } Int; +typedef struct { long x; } Long; +typedef struct { float x; } Float; +typedef struct { double x; } Double; +typedef struct { char c; float f; } A; +typedef struct { double d; int i[3]; } B; +typedef struct { long l1; long l2; } J; +typedef struct { long l1; long l2; long l3; long l4; } K; +typedef struct { long l1; long l2; long l3; long l4; long l5; long l6; } L; +typedef struct { char x1; } Size1; +typedef struct { char x1; char x2; } Size2; +typedef struct { char x1; char x2; char x3; } Size3; +typedef struct { char x1; char x2; char x3; char x4; } Size4; +typedef struct { + char x1; char x2; char x3; char x4; char x5; char x6; char x7; +} Size7; +typedef struct { + char x1; char x2; char x3; char x4; char x5; char x6; char x7; char x8; +} Size8; +typedef struct { + char x1; char x2; char x3; char x4; char x5; char x6; char x7; char x8; + char x9; char x10; char x11; char x12; +} Size12; +typedef struct { + char x1; char x2; char x3; char x4; char x5; char x6; char x7; char x8; + char x9; char x10; char x11; char x12; char x13; char x14; char x15; +} Size15; +typedef struct { + char x1; char x2; char x3; char x4; char x5; char x6; char x7; char x8; + char x9; char x10; char x11; char x12; char x13; char x14; char x15; char x16; +} Size16; +typedef struct { char c[3]; } T; +typedef struct { char c[33],c1; } X; + +char c1='a', c2=127, c3=(char)128, c4=(char)255, c5=-1; +short s1=32767, s2=(short)32768, s3=3, s4=4, s5=5, s6=6, s7=7, s8=8, s9=9; +int i1=1, i2=2, i3=3, i4=4, i5=5, i6=6, i7=7, i8=8, i9=9, + i10=11, i11=12, i12=13, i13=14, i14=15, i15=16, i16=17; +long l1=1, l2=2, l3=3, l4=4, l5=5, l6=6, l7=7, l8=8, l9=9; +long long ll1 = 3875056143130689530LL; +float f1=0.1f, f2=0.2f, f3=0.3f, f4=0.4f, f5=0.5f, f6=0.6f, f7=0.7f, f8=0.8f, f9=0.9f, + f10=1.1f, f11=1.2f, f12=1.3f, f13=1.4f, f14=1.5f, f15=1.6f, f16=1.7f, f17=1.8f, + f18=1.9f, f19=2.1f, f20=2.2f, f21=2.3f, f22=2.4f, f23=2.5f, f24=2.6f; +double d1=0.1, d2=0.2, d3=0.3, d4=0.4, d5=0.5, d6=0.6, d7=0.7, d8=0.8, d9=0.9, + d10=1.1, d11=1.2, d12=1.3, d13=1.4, d14=1.5, d15=1.6, d16=1.7, d17=1.8; + +uchar uc1='a', uc2=127, uc3=128, uc4=255, uc5=(uchar)-1; +ushort us1=1, us2=2, us3=3, us4=4, us5=5, us6=6, us7=7, us8=8, us9=9; +uint ui1=1, ui2=2, ui3=3, ui4=4, ui5=5, ui6=6, ui7=7, ui8=8, ui9=9; +ulong ul1=1, ul2=2, ul3=3, ul4=4, ul5=5, ul6=6, ul7=7, ul8=8, ul9=9; + +char *str1="hello",str2[]="goodbye",*str3="still here?"; +Char C1={'A'}, C2={'B'}, C3={'C'}, C4={'\377'}, C5={(char)(-1)}; +Short S1={1}, S2={2}, S3={3}, S4={4}, S5={5}, S6={6}, S7={7}, S8={8}, S9={9}; +Int I1={1}, I2={2}, I3={3}, I4={4}, I5={5}, I6={6}, I7={7}, I8={8}, I9={9}; +Float F1={0.1f}, F2={0.2f}, F3={0.3f}, F4={0.4f}, F5={0.5f}, F6={0.6f}, F7={0.7f}, F8={0.8f}, F9={0.9f}; +Double D1={0.1}, D2={0.2}, D3={0.3}, D4={0.4}, D5={0.5}, D6={0.6}, D7={0.7}, D8={0.8}, D9={0.9}; + +A A1={'a',0.1f},A2={'b',0.2f},A3={'\377',0.3f}; +B B1={0.1,{1,2,3}},B2={0.2,{5,4,3}}; +J J1={47,11},J2={73,55}; +K K1={19,69,12,28}; +L L1={561,1105,1729,2465,2821,6601}; /* A002997 */ +Size1 Size1_1={'a'}; +Size2 Size2_1={'a','b'}; +Size3 Size3_1={'a','b','c'}; +Size4 Size4_1={'a','b','c','d'}; +Size7 Size7_1={'a','b','c','d','e','f','g'}; +Size8 Size8_1={'a','b','c','d','e','f','g','h'}; +Size12 Size12_1={'a','b','c','d','e','f','g','h','i','j','k','l'}; +Size15 Size15_1={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o'}; +Size16 Size16_1={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p'}; +T T1={{'t','h','e'}},T2={{'f','o','x'}}; +X X1={"abcdefghijklmnopqrstuvwxyzABCDEF",'G'}, X2={"123",'9'}, X3={"return-return-return",'R'}; + +#if defined(__GNUC__) +#define __STDCALL__ __attribute__((stdcall)) +#define __THISCALL__ __attribute__((thiscall)) +#define __FASTCALL__ __attribute__((fastcall)) +#define __MSABI__ __attribute__((ms_abi)) +#else +#define __STDCALL__ __stdcall +#define __THISCALL__ __thiscall +#define __FASTCALL__ __fastcall +#endif + +#ifndef ABI_ATTR +#define ABI_ATTR +#endif + +/* void tests */ +void ABI_ATTR v_v (void) +{ + fprintf(out,"void f(void):\n"); + fflush(out); +} + +/* int tests */ +int ABI_ATTR i_v (void) +{ + int r=99; + fprintf(out,"int f(void):"); + fflush(out); + return r; +} +int ABI_ATTR i_i (int a) +{ + int r=a+1; + fprintf(out,"int f(int):(%d)",a); + fflush(out); + return r; +} +int ABI_ATTR i_i2 (int a, int b) +{ + int r=a+b; + fprintf(out,"int f(2*int):(%d,%d)",a,b); + fflush(out); + return r; +} +int ABI_ATTR i_i4 (int a, int b, int c, int d) +{ + int r=a+b+c+d; + fprintf(out,"int f(4*int):(%d,%d,%d,%d)",a,b,c,d); + fflush(out); + return r; +} +int ABI_ATTR i_i8 (int a, int b, int c, int d, int e, int f, int g, int h) +{ + int r=a+b+c+d+e+f+g+h; + fprintf(out,"int f(8*int):(%d,%d,%d,%d,%d,%d,%d,%d)",a,b,c,d,e,f,g,h); + fflush(out); + return r; +} +int ABI_ATTR i_i16 (int a, int b, int c, int d, int e, int f, int g, int h, + int i, int j, int k, int l, int m, int n, int o, int p) +{ + int r=a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p; + fprintf(out,"int f(16*int):(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)", + a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p); + fflush(out); + return r; +} + +/* float tests */ +float ABI_ATTR f_f (float a) +{ + float r=a+1.0f; + fprintf(out,"float f(float):(%g)",a); + fflush(out); + return r; +} +float ABI_ATTR f_f2 (float a, float b) +{ + float r=a+b; + fprintf(out,"float f(2*float):(%g,%g)",a,b); + fflush(out); + return r; +} +float ABI_ATTR f_f4 (float a, float b, float c, float d) +{ + float r=a+b+c+d; + fprintf(out,"float f(4*float):(%g,%g,%g,%g)",a,b,c,d); + fflush(out); + return r; +} +float ABI_ATTR f_f8 (float a, float b, float c, float d, float e, float f, + float g, float h) +{ + float r=a+b+c+d+e+f+g+h; + fprintf(out,"float f(8*float):(%g,%g,%g,%g,%g,%g,%g,%g)",a,b,c,d,e,f,g,h); + fflush(out); + return r; +} +float ABI_ATTR f_f16 (float a, float b, float c, float d, float e, float f, float g, float h, + float i, float j, float k, float l, float m, float n, float o, float p) +{ + float r=a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p; + fprintf(out,"float f(16*float):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g)",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p); + fflush(out); + return r; +} +float ABI_ATTR f_f24 (float a, float b, float c, float d, float e, float f, float g, float h, + float i, float j, float k, float l, float m, float n, float o, float p, + float q, float s, float t, float u, float v, float w, float x, float y) +{ + float r=a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+s+t+u+v+w+x+y; + fprintf(out,"float f(24*float):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g)",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,s,t,u,v,w,x,y); + fflush(out); + return r; +} + +/* double tests */ +double ABI_ATTR d_d (double a) +{ + double r=a+1.0; + fprintf(out,"double f(double):(%g)",a); + fflush(out); + return r; +} +double ABI_ATTR d_d2 (double a, double b) +{ + double r=a+b; + fprintf(out,"double f(2*double):(%g,%g)",a,b); + fflush(out); + return r; +} +double ABI_ATTR d_d4 (double a, double b, double c, double d) +{ + double r=a+b+c+d; + fprintf(out,"double f(4*double):(%g,%g,%g,%g)",a,b,c,d); + fflush(out); + return r; +} +double ABI_ATTR d_d8 (double a, double b, double c, double d, double e, double f, + double g, double h) +{ + double r=a+b+c+d+e+f+g+h; + fprintf(out,"double f(8*double):(%g,%g,%g,%g,%g,%g,%g,%g)",a,b,c,d,e,f,g,h); + fflush(out); + return r; +} +double ABI_ATTR d_d16 (double a, double b, double c, double d, double e, double f, + double g, double h, double i, double j, double k, double l, + double m, double n, double o, double p) +{ + double r=a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p; + fprintf(out,"double f(16*double):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g)",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p); + fflush(out); + return r; +} + +/* pointer tests */ +void* ABI_ATTR vp_vpdpcpsp (void* a, double* b, char* c, Int* d) +{ + void* ret = (char*)b + 1; + fprintf(out,"void* f(void*,double*,char*,Int*):(0x%p,0x%p,0x%p,0x%p)",a,b,c,d); + fflush(out); + return ret; +} + +/* mixed number tests */ +uchar ABI_ATTR uc_ucsil (uchar a, ushort b, uint c, ulong d) +{ + uchar r = (uchar)-1; + fprintf(out,"uchar f(uchar,ushort,uint,ulong):(%u,%u,%u,%lu)",a,b,c,d); + fflush(out); + return r; +} +double ABI_ATTR d_iidd (int a, int b, double c, double d) +{ + double r = a+b+c+d; + fprintf(out,"double f(int,int,double,double):(%d,%d,%g,%g)",a,b,c,d); + fflush(out); + return r; +} +double ABI_ATTR d_iiidi (int a, int b, int c, double d, int e) +{ + double r = a+b+c+d+e; + fprintf(out,"double f(int,int,int,double,int):(%d,%d,%d,%g,%d)",a,b,c,d,e); + fflush(out); + return r; +} +double ABI_ATTR d_idid (int a, double b, int c, double d) +{ + double r = a+b+c+d; + fprintf(out,"double f(int,double,int,double):(%d,%g,%d,%g)",a,b,c,d); + fflush(out); + return r; +} +double ABI_ATTR d_fdi (float a, double b, int c) +{ + double r = a+b+c; + fprintf(out,"double f(float,double,int):(%g,%g,%d)",a,b,c); + fflush(out); + return r; +} +ushort ABI_ATTR us_cdcd (char a, double b, char c, double d) +{ + ushort r = (ushort)(a + b + c + d); + fprintf(out,"ushort f(char,double,char,double):('%c',%g,'%c',%g)",a,b,c,d); + fflush(out); + return r; +} + +long long ABI_ATTR ll_iiilli (int a, int b, int c, long long d, int e) +{ + long long r = (long long)(int)a+(long long)(int)b+(long long)(int)c+d+(long long)(int)e; + fprintf(out,"long long f(int,int,int,long long,int):(%d,%d,%d,0x%lx%08lx,%d)",a,b,c,(long)(d>>32),(long)(d&0xffffffff),e); + fflush(out); + return r; +} +long long ABI_ATTR ll_flli (float a, long long b, int c) +{ + long long r = (long long)(int)a + b + (long long)c; + fprintf(out,"long long f(float,long long,int):(%g,0x%lx%08lx,0x%lx)",a,(long)(b>>32),(long)(b&0xffffffff),(long)c); + fflush(out); + return r; +} + +float ABI_ATTR f_fi (float a, int z) +{ + float r = a+z; + fprintf(out,"float f(float,int):(%g,%d)",a,z); + fflush(out); + return r; +} +float ABI_ATTR f_f2i (float a, float b, int z) +{ + float r = a+b+z; + fprintf(out,"float f(2*float,int):(%g,%g,%d)",a,b,z); + fflush(out); + return r; +} +float ABI_ATTR f_f3i (float a, float b, float c, int z) +{ + float r = a+b+c+z; + fprintf(out,"float f(3*float,int):(%g,%g,%g,%d)",a,b,c,z); + fflush(out); + return r; +} +float ABI_ATTR f_f4i (float a, float b, float c, float d, int z) +{ + float r = a+b+c+d+z; + fprintf(out,"float f(4*float,int):(%g,%g,%g,%g,%d)",a,b,c,d,z); + fflush(out); + return r; +} +float ABI_ATTR f_f7i (float a, float b, float c, float d, float e, float f, float g, + int z) +{ + float r = a+b+c+d+e+f+g+z; + fprintf(out,"float f(7*float,int):(%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,z); + fflush(out); + return r; +} +float ABI_ATTR f_f8i (float a, float b, float c, float d, float e, float f, float g, + float h, int z) +{ + float r = a+b+c+d+e+f+g+h+z; + fprintf(out,"float f(8*float,int):(%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,z); + fflush(out); + return r; +} +float ABI_ATTR f_f12i (float a, float b, float c, float d, float e, float f, float g, + float h, float i, float j, float k, float l, int z) +{ + float r = a+b+c+d+e+f+g+h+i+j+k+l+z; + fprintf(out,"float f(12*float,int):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,i,j,k,l,z); + fflush(out); + return r; +} +float ABI_ATTR f_f13i (float a, float b, float c, float d, float e, float f, float g, + float h, float i, float j, float k, float l, float m, int z) +{ + float r = a+b+c+d+e+f+g+h+i+j+k+l+m+z; + fprintf(out,"float f(13*float,int):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,i,j,k,l,m,z); + fflush(out); + return r; +} + +double ABI_ATTR d_di (double a, int z) +{ + double r = a+z; + fprintf(out,"double f(double,int):(%g,%d)",a,z); + fflush(out); + return r; +} +double ABI_ATTR d_d2i (double a, double b, int z) +{ + double r = a+b+z; + fprintf(out,"double f(2*double,int):(%g,%g,%d)",a,b,z); + fflush(out); + return r; +} +double ABI_ATTR d_d3i (double a, double b, double c, int z) +{ + double r = a+b+c+z; + fprintf(out,"double f(3*double,int):(%g,%g,%g,%d)",a,b,c,z); + fflush(out); + return r; +} +double ABI_ATTR d_d4i (double a, double b, double c, double d, int z) +{ + double r = a+b+c+d+z; + fprintf(out,"double f(4*double,int):(%g,%g,%g,%g,%d)",a,b,c,d,z); + fflush(out); + return r; +} +double ABI_ATTR d_d7i (double a, double b, double c, double d, double e, double f, + double g, int z) +{ + double r = a+b+c+d+e+f+g+z; + fprintf(out,"double f(7*double,int):(%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,z); + fflush(out); + return r; +} +double ABI_ATTR d_d8i (double a, double b, double c, double d, double e, double f, + double g, double h, int z) +{ + double r = a+b+c+d+e+f+g+h+z; + fprintf(out,"double f(8*double,int):(%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,z); + fflush(out); + return r; +} +double ABI_ATTR d_d12i (double a, double b, double c, double d, double e, double f, + double g, double h, double i, double j, double k, double l, + int z) +{ + double r = a+b+c+d+e+f+g+h+i+j+k+l+z; + fprintf(out,"double f(12*double,int):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,i,j,k,l,z); + fflush(out); + return r; +} +double ABI_ATTR d_d13i (double a, double b, double c, double d, double e, double f, + double g, double h, double i, double j, double k, double l, + double m, int z) +{ + double r = a+b+c+d+e+f+g+h+i+j+k+l+m+z; + fprintf(out,"double f(13*double,int):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%d)",a,b,c,d,e,f,g,h,i,j,k,l,m,z); + fflush(out); + return r; +} + +/* small structure return tests */ +Size1 ABI_ATTR S1_v (void) +{ + fprintf(out,"Size1 f(void):"); + fflush(out); + return Size1_1; +} +Size2 ABI_ATTR S2_v (void) +{ + fprintf(out,"Size2 f(void):"); + fflush(out); + return Size2_1; +} +Size3 ABI_ATTR S3_v (void) +{ + fprintf(out,"Size3 f(void):"); + fflush(out); + return Size3_1; +} +Size4 ABI_ATTR S4_v (void) +{ + fprintf(out,"Size4 f(void):"); + fflush(out); + return Size4_1; +} +Size7 ABI_ATTR S7_v (void) +{ + fprintf(out,"Size7 f(void):"); + fflush(out); + return Size7_1; +} +Size8 ABI_ATTR S8_v (void) +{ + fprintf(out,"Size8 f(void):"); + fflush(out); + return Size8_1; +} +Size12 ABI_ATTR S12_v (void) +{ + fprintf(out,"Size12 f(void):"); + fflush(out); + return Size12_1; +} +Size15 ABI_ATTR S15_v (void) +{ + fprintf(out,"Size15 f(void):"); + fflush(out); + return Size15_1; +} +Size16 ABI_ATTR S16_v (void) +{ + fprintf(out,"Size16 f(void):"); + fflush(out); + return Size16_1; +} + +/* structure tests */ +Int ABI_ATTR I_III (Int a, Int b, Int c) +{ + Int r; + r.x = a.x + b.x + c.x; + fprintf(out,"Int f(Int,Int,Int):({%d},{%d},{%d})",a.x,b.x,c.x); + fflush(out); + return r; +} +Char ABI_ATTR C_CdC (Char a, double b, Char c) +{ + Char r; + r.x = (a.x + c.x)/2; + fprintf(out,"Char f(Char,double,Char):({'%c'},%g,{'%c'})",a.x,b,c.x); + fflush(out); + return r; +} +Float ABI_ATTR F_Ffd (Float a, float b, double c) +{ + Float r; + r.x = (float) (a.x + b + c); + fprintf(out,"Float f(Float,float,double):({%g},%g,%g)",a.x,b,c); + fflush(out); + return r; +} +Double ABI_ATTR D_fDd (float a, Double b, double c) +{ + Double r; + r.x = a + b.x + c; + fprintf(out,"Double f(float,Double,double):(%g,{%g},%g)",a,b.x,c); + fflush(out); + return r; +} +Double ABI_ATTR D_Dfd (Double a, float b, double c) +{ + Double r; + r.x = a.x + b + c; + fprintf(out,"Double f(Double,float,double):({%g},%g,%g)",a.x,b,c); + fflush(out); + return r; +} +J ABI_ATTR J_JiJ (J a, int b, J c) +{ + J r; + r.l1 = a.l1+c.l1; r.l2 = a.l2+b+c.l2; + fprintf(out,"J f(J,int,J):({%ld,%ld},%d,{%ld,%ld})",a.l1,a.l2,b,c.l1,c.l2); + fflush(out); + return r; +} +T ABI_ATTR T_TcT (T a, char b, T c) +{ + T r; + r.c[0]='b'; r.c[1]=c.c[1]; r.c[2]=c.c[2]; + fprintf(out,"T f(T,char,T):({\"%c%c%c\"},'%c',{\"%c%c%c\"})",a.c[0],a.c[1],a.c[2],b,c.c[0],c.c[1],c.c[2]); + fflush(out); + return r; +} +X ABI_ATTR X_BcdB (B a, char b, double c, B d) +{ + static X xr={"return val",'R'}; + X r; + r = xr; + r.c1 = b; + fprintf(out,"X f(B,char,double,B):({%g,{%d,%d,%d}},'%c',%g,{%g,{%d,%d,%d}})", + a.d,a.i[0],a.i[1],a.i[2],b,c,d.d,d.i[0],d.i[1],d.i[2]); + fflush(out); + return r; +} + +/* Test for cases where some argument (especially structure, 'long long', or + 'double') may be passed partially in general-purpose argument registers + and partially on the stack. Different ABIs pass between 4 and 8 arguments + (or none) in general-purpose argument registers. */ + +long ABI_ATTR l_l0K (K b, long c) +{ + long r = b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(K,long):(%ld,%ld,%ld,%ld,%ld)",b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + return r; +} +long ABI_ATTR l_l1K (long a1, K b, long c) +{ + long r = a1 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld)",a1,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + return r; +} +long ABI_ATTR l_l2K (long a1, long a2, K b, long c) +{ + long r = a1 + a2 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(2*long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a1,a2,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + return r; +} +long ABI_ATTR l_l3K (long a1, long a2, long a3, K b, long c) +{ + long r = a1 + a2 + a3 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(3*long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a1,a2,a3,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + return r; +} +long ABI_ATTR l_l4K (long a1, long a2, long a3, long a4, K b, long c) +{ + long r = a1 + a2 + a3 + a4 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(4*long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a1,a2,a3,a4,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + return r; +} +long ABI_ATTR l_l5K (long a1, long a2, long a3, long a4, long a5, K b, long c) +{ + long r = a1 + a2 + a3 + a4 + a5 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(5*long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a1,a2,a3,a4,a5,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + return r; +} +long ABI_ATTR l_l6K (long a1, long a2, long a3, long a4, long a5, long a6, K b, long c) +{ + long r = a1 + a2 + a3 + a4 + a5 + a6 + b.l1 + b.l2 + b.l3 + b.l4 + c; + fprintf(out,"long f(6*long,K,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a1,a2,a3,a4,a5,a6,b.l1,b.l2,b.l3,b.l4,c); + fflush(out); + return r; +} +/* These tests is crafted on the knowledge that for all known ABIs: + * 17 > number of floating-point argument registers, + * 3 < number of general-purpose argument registers < 3 + 6. */ +float ABI_ATTR f_f17l3L (float a, float b, float c, float d, float e, float f, float g, + float h, float i, float j, float k, float l, float m, float n, + float o, float p, float q, + long s, long t, long u, L z) +{ + float r = a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+s+t+u+z.l1+z.l2+z.l3+z.l4+z.l5+z.l6; + fprintf(out,"float f(17*float,3*int,L):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,s,t,u,z.l1,z.l2,z.l3,z.l4,z.l5,z.l6); + fflush(out); + return r; +} +double ABI_ATTR d_d17l3L (double a, double b, double c, double d, double e, double f, + double g, double h, double i, double j, double k, double l, + double m, double n, double o, double p, double q, + long s, long t, long u, L z) +{ + double r = a+b+c+d+e+f+g+h+i+j+k+l+m+n+o+p+q+s+t+u+z.l1+z.l2+z.l3+z.l4+z.l5+z.l6; + fprintf(out,"double f(17*double,3*int,L):(%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%g,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld,%ld)",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,s,t,u,z.l1,z.l2,z.l3,z.l4,z.l5,z.l6); + fflush(out); + return r; +} + +long long ABI_ATTR ll_l2ll (long a1, long a2, long long b, long c) +{ + long long r = (long long) (a1 + a2) + b + c; + fprintf(out,"long long f(2*long,long long,long):(%ld,%ld,0x%lx%08lx,%ld)",a1,a2,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + return r; +} +long long ABI_ATTR ll_l3ll (long a1, long a2, long a3, long long b, long c) +{ + long long r = (long long) (a1 + a2 + a3) + b + c; + fprintf(out,"long long f(3*long,long long,long):(%ld,%ld,%ld,0x%lx%08lx,%ld)",a1,a2,a3,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + return r; +} +long long ABI_ATTR ll_l4ll (long a1, long a2, long a3, long a4, long long b, long c) +{ + long long r = (long long) (a1 + a2 + a3 + a4) + b + c; + fprintf(out,"long long f(4*long,long long,long):(%ld,%ld,%ld,%ld,0x%lx%08lx,%ld)",a1,a2,a3,a4,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + return r; +} +long long ABI_ATTR ll_l5ll (long a1, long a2, long a3, long a4, long a5, long long b, long c) +{ + long long r = (long long) (a1 + a2 + a3 + a4 + a5) + b + c; + fprintf(out,"long long f(5*long,long long,long):(%ld,%ld,%ld,%ld,%ld,0x%lx%08lx,%ld)",a1,a2,a3,a4,a5,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + return r; +} +long long ABI_ATTR ll_l6ll (long a1, long a2, long a3, long a4, long a5, long a6, long long b, long c) +{ + long long r = (long long) (a1 + a2 + a3 + a4 + a5 + a6) + b + c; + fprintf(out,"long long f(6*long,long long,long):(%ld,%ld,%ld,%ld,%ld,%ld,0x%lx%08lx,%ld)",a1,a2,a3,a4,a5,a6,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + return r; +} +long long ABI_ATTR ll_l7ll (long a1, long a2, long a3, long a4, long a5, long a6, long a7, long long b, long c) +{ + long long r = (long long) (a1 + a2 + a3 + a4 + a5 + a6 + a7) + b + c; + fprintf(out,"long long f(7*long,long long,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,0x%lx%08lx,%ld)",a1,a2,a3,a4,a5,a6,a7,(long)(b>>32),(long)(b&0xffffffff),c); + fflush(out); + return r; +} + +double ABI_ATTR d_l2d (long a1, long a2, double b, long c) +{ + double r = (double) (a1 + a2) + b + c; + fprintf(out,"double f(2*long,double,long):(%ld,%ld,%g,%ld)",a1,a2,b,c); + fflush(out); + return r; +} +double ABI_ATTR d_l3d (long a1, long a2, long a3, double b, long c) +{ + double r = (double) (a1 + a2 + a3) + b + c; + fprintf(out,"double f(3*long,double,long):(%ld,%ld,%ld,%g,%ld)",a1,a2,a3,b,c); + fflush(out); + return r; +} +double ABI_ATTR d_l4d (long a1, long a2, long a3, long a4, double b, long c) +{ + double r = (double) (a1 + a2 + a3 + a4) + b + c; + fprintf(out,"double f(4*long,double,long):(%ld,%ld,%ld,%ld,%g,%ld)",a1,a2,a3,a4,b,c); + fflush(out); + return r; +} +double ABI_ATTR d_l5d (long a1, long a2, long a3, long a4, long a5, double b, long c) +{ + double r = (double) (a1 + a2 + a3 + a4 + a5) + b + c; + fprintf(out,"double f(5*long,double,long):(%ld,%ld,%ld,%ld,%ld,%g,%ld)",a1,a2,a3,a4,a5,b,c); + fflush(out); + return r; +} +double ABI_ATTR d_l6d (long a1, long a2, long a3, long a4, long a5, long a6, double b, long c) +{ + double r = (double) (a1 + a2 + a3 + a4 + a5 + a6) + b + c; + fprintf(out,"double f(6*long,double,long):(%ld,%ld,%ld,%ld,%ld,%ld,%g,%ld)",a1,a2,a3,a4,a5,a6,b,c); + fflush(out); + return r; +} +double ABI_ATTR d_l7d (long a1, long a2, long a3, long a4, long a5, long a6, long a7, double b, long c) +{ + double r = (double) (a1 + a2 + a3 + a4 + a5 + a6 + a7) + b + c; + fprintf(out,"double f(7*long,double,long):(%ld,%ld,%ld,%ld,%ld,%ld,%ld,%g,%ld)",a1,a2,a3,a4,a5,a6,a7,b,c); + fflush(out); + return r; +} diff --git a/native/libffi/testsuite/libffi.call/align_mixed.c b/native/libffi/testsuite/libffi.call/align_mixed.c index fe8e254813..6f7cfeee9e 100755 --- a/native/libffi/testsuite/libffi.call/align_mixed.c +++ b/native/libffi/testsuite/libffi.call/align_mixed.c @@ -7,7 +7,10 @@ /* { dg-do run } */ #include "ffitest.h" +<<<<<<< HEAD #include +======= +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 static float ABI_ATTR align_arguments(int i1, double f2, @@ -17,11 +20,24 @@ static float ABI_ATTR align_arguments(int i1, return i1+f2+i3+f4; } +<<<<<<< HEAD int main (void) { ffi_cif cif; ffi_type *args[4] = {&ffi_type_int, &ffi_type_double, &ffi_type_int, &ffi_type_double}; float fa[2] = {1,2}; +======= +int main(void) +{ + ffi_cif cif; + ffi_type *args[4] = { + &ffi_type_sint, + &ffi_type_double, + &ffi_type_sint, + &ffi_type_double + }; + double fa[2] = {1,2}; +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 int ia[2] = {1,2}; void *values[4] = {&ia[0], &fa[0], &ia[1], &fa[1]}; float f, ff; @@ -34,7 +50,11 @@ int main (void) ffi_call(&cif, FFI_FN(align_arguments), &f, values); +<<<<<<< HEAD if (f - ff < FLT_EPSILON) +======= + if (f == ff) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 printf("align arguments tests ok!\n"); else CHECK(0); diff --git a/native/libffi/testsuite/libffi.call/align_stdcall.c b/native/libffi/testsuite/libffi.call/align_stdcall.c new file mode 100644 index 0000000000..5e5cb860cc --- /dev/null +++ b/native/libffi/testsuite/libffi.call/align_stdcall.c @@ -0,0 +1,46 @@ +/* Area: ffi_call + Purpose: Check for proper argument alignment. + Limitations: none. + PR: none. + Originator: (from many_win32.c) */ + +/* { dg-do run } */ + +#include "ffitest.h" + +static float ABI_ATTR align_arguments(int i1, + double f2, + int i3, + double f4) +{ + return i1+f2+i3+f4; +} + +int main(void) +{ + ffi_cif cif; + ffi_type *args[4] = { + &ffi_type_sint, + &ffi_type_double, + &ffi_type_sint, + &ffi_type_double + }; + double fa[2] = {1,2}; + int ia[2] = {1,2}; + void *values[4] = {&ia[0], &fa[0], &ia[1], &fa[1]}; + float f, ff; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, ABI_NUM, 4, + &ffi_type_float, args) == FFI_OK); + + ff = align_arguments(ia[0], fa[0], ia[1], fa[1]);; + + ffi_call(&cif, FFI_FN(align_arguments), &f, values); + + if (f == ff) + printf("align arguments tests ok!\n"); + else + CHECK(0); + exit(0); +} diff --git a/native/libffi/testsuite/libffi.call/call.exp b/native/libffi/testsuite/libffi.call/call.exp index 5177f07f11..9a69f04a51 100644 --- a/native/libffi/testsuite/libffi.call/call.exp +++ b/native/libffi/testsuite/libffi.call/call.exp @@ -19,6 +19,7 @@ libffi-init global srcdir subdir +<<<<<<< HEAD set tlist [lsearch -inline -all -not -glob [lsort [glob -nocomplain -- $srcdir/$subdir/*.{c,cc}]] *complex*] set ctlist [lsearch -inline -all -glob [lsort [glob -nocomplain -- $srcdir/$subdir/*.{c,cc}]] *complex*] @@ -33,7 +34,34 @@ if { ![istarget s390*] } { } else { run-many-tests $ctlist "" +======= +if { [string match $compiler_vendor "microsoft"] } { + # -wd4005 macro redefinition + # -wd4244 implicit conversion to type of smaller size + # -wd4305 truncation to smaller type + # -wd4477 printf %lu of uintptr_t + # -wd4312 implicit conversion to type of greater size + # -wd4311 pointer truncation to unsigned long + # -EHsc C++ Exception Handling (no SEH exceptions) + set additional_options "-wd4005 -wd4244 -wd4305 -wd4477 -wd4312 -wd4311 -EHsc"; +} else { + set additional_options ""; +} + +set tlist [lsort [glob -nocomplain -- $srcdir/$subdir/*.c]] + +run-many-tests $tlist $additional_options +set tlist [lsort [glob -nocomplain -- $srcdir/$subdir/*.cc]] +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 + +# No C++ for or1k +if { [istarget "or1k-*-*"] } { + foreach test $tlist { + unsupported "$test" + } +} else { + run-many-tests $tlist $additional_options } dg-finish diff --git a/native/libffi/testsuite/libffi.call/ffitest.h b/native/libffi/testsuite/libffi.call/ffitest.h index 15d5e44123..1880cc7bf8 100644 --- a/native/libffi/testsuite/libffi.call/ffitest.h +++ b/native/libffi/testsuite/libffi.call/ffitest.h @@ -24,6 +24,10 @@ #define __STDCALL__ __attribute__((stdcall)) #define __THISCALL__ __attribute__((thiscall)) #define __FASTCALL__ __attribute__((fastcall)) +<<<<<<< HEAD +======= +#define __MSABI__ __attribute__((ms_abi)) +>>>>>>> 8cc8f446f5aac13e107161dffbc15d1ee1a58878 #else #define __UNUSED__ #define __STDCALL__ __stdcall @@ -63,7 +67,7 @@ #endif /* MinGW kludge. */ -#ifdef _WIN64 +#if defined(_WIN64) | defined(_WIN32) #define PRIdLL "I64d" #define PRIuLL "I64u" #else @@ -123,12 +127,14 @@ /* MSVC kludge. */ #if defined _MSC_VER +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) #define PRIuPTR "lu" #define PRIu8 "u" #define PRId8 "d" #define PRIu64 "I64u" #define PRId64 "I64d" #endif +#endif #ifndef PRIuPTR #define PRIuPTR "u" diff --git a/native/libffi/testsuite/libffi.call/float1.c b/native/libffi/testsuite/libffi.call/float1.c index 991d059fe4..c48493c6b2 100644 --- a/native/libffi/testsuite/libffi.call/float1.c +++ b/native/libffi/testsuite/libffi.call/float1.c @@ -8,6 +8,8 @@ #include "ffitest.h" #include "float.h" +#include + typedef union { double d; @@ -47,7 +49,7 @@ int main (void) /* These are not always the same!! Check for a reasonable delta */ - CHECK(result[0].d - dblit(f) < DBL_EPSILON); + CHECK(fabs(result[0].d - dblit(f)) < DBL_EPSILON); /* Check the canary. */ for (i = 0; i < sizeof (double); ++i) diff --git a/native/libffi/testsuite/libffi.call/float2.c b/native/libffi/testsuite/libffi.call/float2.c index a0b296cf4b..57cd9e30f9 100644 --- a/native/libffi/testsuite/libffi.call/float2.c +++ b/native/libffi/testsuite/libffi.call/float2.c @@ -3,13 +3,13 @@ Limitations: none. PR: none. Originator: From the original ffitest.c */ - -/* { dg-excess-errors "fails" { target x86_64-*-mingw* x86_64-*-cygwin* } } */ -/* { dg-do run { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */ +/* { dg-do run } */ #include "ffitest.h" #include "float.h" +#include + static long double ldblit(float f) { return (long double) (((long double) f)/ (long double) 3.0); @@ -22,6 +22,7 @@ int main (void) void *values[MAX_ARGS]; float f; long double ld; + long double original; args[0] = &ffi_type_float; values[0] = &f; @@ -32,24 +33,26 @@ int main (void) f = 3.14159; -#if 1 - /* This is ifdef'd out for now. long double support under SunOS/gcc - is pretty much non-existent. You'll get the odd bus error in library - routines like printf(). */ +#if defined(__sun) && defined(__GNUC__) + /* long double support under SunOS/gcc is pretty much non-existent. + You'll get the odd bus error in library routines like printf() */ +#else printf ("%Lf\n", ldblit(f)); #endif + ld = 666; ffi_call(&cif, FFI_FN(ldblit), &ld, values); -#if 1 - /* This is ifdef'd out for now. long double support under SunOS/gcc - is pretty much non-existent. You'll get the odd bus error in library - routines like printf(). */ +#if defined(__sun) && defined(__GNUC__) + /* long double support under SunOS/gcc is pretty much non-existent. + You'll get the odd bus error in library routines like printf() */ +#else printf ("%Lf, %Lf, %Lf, %Lf\n", ld, ldblit(f), ld - ldblit(f), LDBL_EPSILON); #endif /* These are not always the same!! Check for a reasonable delta */ - if (ld - ldblit(f) < LDBL_EPSILON) + original = ldblit(f); + if (((ld > original) ? (ld - original) : (original - ld)) < LDBL_EPSILON) puts("long double return value tests ok!"); else CHECK(0); diff --git a/native/libffi/testsuite/libffi.call/float3.c b/native/libffi/testsuite/libffi.call/float3.c index 76bd5f287c..bab3206a17 100644 --- a/native/libffi/testsuite/libffi.call/float3.c +++ b/native/libffi/testsuite/libffi.call/float3.c @@ -9,6 +9,8 @@ #include "ffitest.h" #include "float.h" +#include + static double floating_1(float a, double b, long double c) { return (double) a + b + (double) c; @@ -49,7 +51,7 @@ int main (void) ffi_call(&cif, FFI_FN(floating_1), &rd, values); - CHECK(rd - floating_1(f, d, ld) < DBL_EPSILON); + CHECK(fabs(rd - floating_1(f, d, ld)) < DBL_EPSILON); args[0] = &ffi_type_longdouble; values[0] = &ld; @@ -66,7 +68,7 @@ int main (void) ffi_call(&cif, FFI_FN(floating_2), &rd, values); - CHECK(rd - floating_2(ld, d, f) < DBL_EPSILON); + CHECK(fabs(rd - floating_2(ld, d, f)) < DBL_EPSILON); exit (0); } diff --git a/native/libffi/testsuite/libffi.call/offsets.c b/native/libffi/testsuite/libffi.call/offsets.c new file mode 100644 index 0000000000..23d88b35d5 --- /dev/null +++ b/native/libffi/testsuite/libffi.call/offsets.c @@ -0,0 +1,46 @@ +/* Area: Struct layout + Purpose: Test ffi_get_struct_offsets + Limitations: none. + PR: none. + Originator: Tom Tromey. */ + +/* { dg-do run } */ +#include "ffitest.h" +#include + +struct test_1 +{ + char c; + float f; + char c2; + int i; +}; + +int +main (void) +{ + ffi_type test_1_type; + ffi_type *test_1_elements[5]; + size_t test_1_offsets[4]; + + test_1_elements[0] = &ffi_type_schar; + test_1_elements[1] = &ffi_type_float; + test_1_elements[2] = &ffi_type_schar; + test_1_elements[3] = &ffi_type_sint; + test_1_elements[4] = NULL; + + test_1_type.size = 0; + test_1_type.alignment = 0; + test_1_type.type = FFI_TYPE_STRUCT; + test_1_type.elements = test_1_elements; + + CHECK (ffi_get_struct_offsets (FFI_DEFAULT_ABI, &test_1_type, test_1_offsets) + == FFI_OK); + CHECK (test_1_type.size == sizeof (struct test_1)); + CHECK (offsetof (struct test_1, c) == test_1_offsets[0]); + CHECK (offsetof (struct test_1, f) == test_1_offsets[1]); + CHECK (offsetof (struct test_1, c2) == test_1_offsets[2]); + CHECK (offsetof (struct test_1, i) == test_1_offsets[3]); + + return 0; +} diff --git a/native/libffi/testsuite/libffi.call/pr1172638.c b/native/libffi/testsuite/libffi.call/pr1172638.c new file mode 100644 index 0000000000..7da1621cd6 --- /dev/null +++ b/native/libffi/testsuite/libffi.call/pr1172638.c @@ -0,0 +1,127 @@ +/* Area: ffi_call + Purpose: Reproduce bug found in python ctypes + Limitations: none. + PR: Fedora 1174037 */ + +/* { dg-do run } */ +#include "ffitest.h" + +typedef struct { + long x; + long y; +} POINT; + +typedef struct { + long left; + long top; + long right; + long bottom; +} RECT; + +static RECT ABI_ATTR pr_test(int i __UNUSED__, RECT ar __UNUSED__, + RECT* br __UNUSED__, POINT cp __UNUSED__, + RECT dr __UNUSED__, RECT *er __UNUSED__, + POINT fp, RECT gr __UNUSED__) +{ + RECT result; + + result.left = fp.x; + result.right = fp.y; + result.top = fp.x; + result.bottom = fp.y; + + return result; +} + +int main (void) +{ + ffi_cif cif; + ffi_type *args[MAX_ARGS]; + void *values[MAX_ARGS]; + ffi_type point_type, rect_type; + ffi_type *point_type_elements[3]; + ffi_type *rect_type_elements[5]; + + int i; + POINT cp, fp; + RECT ar, br, dr, er, gr; + RECT *p1, *p2; + + /* This is a hack to get a properly aligned result buffer */ + RECT *rect_result = + (RECT *) malloc (sizeof(RECT)); + + point_type.size = 0; + point_type.alignment = 0; + point_type.type = FFI_TYPE_STRUCT; + point_type.elements = point_type_elements; + point_type_elements[0] = &ffi_type_slong; + point_type_elements[1] = &ffi_type_slong; + point_type_elements[2] = NULL; + + rect_type.size = 0; + rect_type.alignment = 0; + rect_type.type = FFI_TYPE_STRUCT; + rect_type.elements = rect_type_elements; + rect_type_elements[0] = &ffi_type_slong; + rect_type_elements[1] = &ffi_type_slong; + rect_type_elements[2] = &ffi_type_slong; + rect_type_elements[3] = &ffi_type_slong; + rect_type_elements[4] = NULL; + + args[0] = &ffi_type_sint; + args[1] = &rect_type; + args[2] = &ffi_type_pointer; + args[3] = &point_type; + args[4] = &rect_type; + args[5] = &ffi_type_pointer; + args[6] = &point_type; + args[7] = &rect_type; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, ABI_NUM, 8, &rect_type, args) == FFI_OK); + + i = 1; + ar.left = 2; + ar.right = 3; + ar.top = 4; + ar.bottom = 5; + br.left = 6; + br.right = 7; + br.top = 8; + br.bottom = 9; + cp.x = 10; + cp.y = 11; + dr.left = 12; + dr.right = 13; + dr.top = 14; + dr.bottom = 15; + er.left = 16; + er.right = 17; + er.top = 18; + er.bottom = 19; + fp.x = 20; + fp.y = 21; + gr.left = 22; + gr.right = 23; + gr.top = 24; + gr.bottom = 25; + + values[0] = &i; + values[1] = &ar; + p1 = &br; + values[2] = &p1; + values[3] = &cp; + values[4] = &dr; + p2 = &er; + values[5] = &p2; + values[6] = &fp; + values[7] = &gr; + + ffi_call (&cif, FFI_FN(pr_test), rect_result, values); + + CHECK(rect_result->top == 20); + + free (rect_result); + exit(0); +} diff --git a/native/libffi/testsuite/libffi.call/return_ldl.c b/native/libffi/testsuite/libffi.call/return_ldl.c index 5c2fe65aec..52a92fe071 100644 --- a/native/libffi/testsuite/libffi.call/return_ldl.c +++ b/native/libffi/testsuite/libffi.call/return_ldl.c @@ -3,8 +3,8 @@ Limitations: none. PR: none. Originator: 20071113 */ +/* { dg-do run } */ -/* { dg-do run { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */ #include "ffitest.h" static long double return_ldl(long double ldl) diff --git a/native/libffi/testsuite/libffi.call/struct10.c b/native/libffi/testsuite/libffi.call/struct10.c new file mode 100644 index 0000000000..17b1377424 --- /dev/null +++ b/native/libffi/testsuite/libffi.call/struct10.c @@ -0,0 +1,57 @@ +/* Area: ffi_call + Purpose: Check structures. + Limitations: none. + PR: none. + Originator: Sergei Trofimovich + + The test originally discovered in ruby's bindings + for ffi in https://bugs.gentoo.org/634190 */ + +/* { dg-do run } */ +#include "ffitest.h" + +struct s { + int s32; + float f32; + signed char s8; +}; + +struct s make_s(void) { + struct s r; + r.s32 = 0x1234; + r.f32 = 7.0; + r.s8 = 0x78; + return r; +} + +int main() { + ffi_cif cif; + struct s r; + ffi_type rtype; + ffi_type* s_fields[] = { + &ffi_type_sint, + &ffi_type_float, + &ffi_type_schar, + NULL, + }; + + rtype.size = 0; + rtype.alignment = 0, + rtype.type = FFI_TYPE_STRUCT, + rtype.elements = s_fields, + + r.s32 = 0xbad; + r.f32 = 999.999; + r.s8 = 0x51; + + // Here we emulate the following call: + //r = make_s(); + + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0, &rtype, NULL) == FFI_OK); + ffi_call(&cif, FFI_FN(make_s), &r, NULL); + + CHECK(r.s32 == 0x1234); + CHECK(r.f32 == 7.0); + CHECK(r.s8 == 0x78); + exit(0); +} diff --git a/native/libffi/testsuite/libffi.call/unwindtest.cc b/native/libffi/testsuite/libffi.call/unwindtest.cc index 67cfefeca6..e1145657d1 100644 --- a/native/libffi/testsuite/libffi.call/unwindtest.cc +++ b/native/libffi/testsuite/libffi.call/unwindtest.cc @@ -4,7 +4,7 @@ PR: none. Originator: Jeff Sturm */ -/* { dg-do run } */ +/* { dg-do run { xfail x86_64-apple-darwin* moxie*-*-* } } */ #include "ffitest.h" diff --git a/native/libffi/testsuite/libffi.call/unwindtest_ffi_call.cc b/native/libffi/testsuite/libffi.call/unwindtest_ffi_call.cc index ec611647e3..153d240940 100644 --- a/native/libffi/testsuite/libffi.call/unwindtest_ffi_call.cc +++ b/native/libffi/testsuite/libffi.call/unwindtest_ffi_call.cc @@ -4,7 +4,7 @@ PR: none. Originator: Andreas Tobler 20061213 */ -/* { dg-do run } */ +/* { dg-do run { xfail moxie*-*-* } } */ #include "ffitest.h" diff --git a/native/libffi/testsuite/libffi.call/va_1.c b/native/libffi/testsuite/libffi.call/va_1.c index 7f96809ea9..59d085c832 100644 --- a/native/libffi/testsuite/libffi.call/va_1.c +++ b/native/libffi/testsuite/libffi.call/va_1.c @@ -5,7 +5,7 @@ Originator: ARM Ltd. */ /* { dg-do run } */ -/* { dg-output "" { xfail avr32*-*-* } } */ +/* { dg-output "" { xfail avr32*-*-* m68k-*-* alpha-*-* } } */ #include "ffitest.h" #include diff --git a/native/libffi/testsuite/libffi.closures/closure.exp b/native/libffi/testsuite/libffi.closures/closure.exp new file mode 100644 index 0000000000..ed4145ca84 --- /dev/null +++ b/native/libffi/testsuite/libffi.closures/closure.exp @@ -0,0 +1,67 @@ +# Copyright (C) 2003, 2006, 2009, 2010, 2014, 2019 Free Software Foundation, Inc. +# Copyright (C) 2019 Anthony Green + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING3. If not see +# . + +dg-init +libffi-init + +global srcdir subdir + +if { [string match $compiler_vendor "microsoft"] } { + # -wd4005 macro redefinition + # -wd4244 implicit conversion to type of smaller size + # -wd4305 truncation to smaller type + # -wd4477 printf %lu of uintptr_t + # -wd4312 implicit conversion to type of greater size + # -wd4311 pointer truncation to unsigned long + # -EHsc C++ Exception Handling (no SEH exceptions) + set additional_options "-wd4005 -wd4244 -wd4305 -wd4477 -wd4312 -wd4311 -EHsc"; +} else { + set additional_options ""; +} + +set tlist [lsort [glob -nocomplain -- $srcdir/$subdir/*.c]] + +if { [libffi_feature_test "#if FFI_CLOSURES"] } { + run-many-tests $tlist "" +} else { + foreach test $tlist { + unsupported "$test" + } +} + +set tlist [lsort [glob -nocomplain -- $srcdir/$subdir/*.cc]] + +# No C++ for or1k +if { [istarget "or1k-*-*"] } { + foreach test $tlist { + unsupported "$test" + } +} else { + if { [libffi_feature_test "#if FFI_CLOSURES"] } { + run-many-tests $tlist $additional_options + } else { + foreach test $tlist { + unsupported "$test" + } + } +} + +dg-finish + +# Local Variables: +# tcl-indent-level:4 +# End: diff --git a/native/libffi/testsuite/libffi.call/closure_fn0.c b/native/libffi/testsuite/libffi.closures/closure_fn0.c similarity index 100% rename from native/libffi/testsuite/libffi.call/closure_fn0.c rename to native/libffi/testsuite/libffi.closures/closure_fn0.c diff --git a/native/libffi/testsuite/libffi.call/closure_fn1.c b/native/libffi/testsuite/libffi.closures/closure_fn1.c similarity index 100% rename from native/libffi/testsuite/libffi.call/closure_fn1.c rename to native/libffi/testsuite/libffi.closures/closure_fn1.c diff --git a/native/libffi/testsuite/libffi.call/closure_fn2.c b/native/libffi/testsuite/libffi.closures/closure_fn2.c similarity index 100% rename from native/libffi/testsuite/libffi.call/closure_fn2.c rename to native/libffi/testsuite/libffi.closures/closure_fn2.c diff --git a/native/libffi/testsuite/libffi.call/closure_fn3.c b/native/libffi/testsuite/libffi.closures/closure_fn3.c similarity index 100% rename from native/libffi/testsuite/libffi.call/closure_fn3.c rename to native/libffi/testsuite/libffi.closures/closure_fn3.c diff --git a/native/libffi/testsuite/libffi.call/closure_fn4.c b/native/libffi/testsuite/libffi.closures/closure_fn4.c similarity index 100% rename from native/libffi/testsuite/libffi.call/closure_fn4.c rename to native/libffi/testsuite/libffi.closures/closure_fn4.c diff --git a/native/libffi/testsuite/libffi.call/closure_fn5.c b/native/libffi/testsuite/libffi.closures/closure_fn5.c similarity index 100% rename from native/libffi/testsuite/libffi.call/closure_fn5.c rename to native/libffi/testsuite/libffi.closures/closure_fn5.c diff --git a/native/libffi/testsuite/libffi.call/closure_fn6.c b/native/libffi/testsuite/libffi.closures/closure_fn6.c similarity index 100% rename from native/libffi/testsuite/libffi.call/closure_fn6.c rename to native/libffi/testsuite/libffi.closures/closure_fn6.c diff --git a/native/libffi/testsuite/libffi.call/closure_loc_fn0.c b/native/libffi/testsuite/libffi.closures/closure_loc_fn0.c similarity index 100% rename from native/libffi/testsuite/libffi.call/closure_loc_fn0.c rename to native/libffi/testsuite/libffi.closures/closure_loc_fn0.c diff --git a/native/libffi/testsuite/libffi.closures/closure_simple.c b/native/libffi/testsuite/libffi.closures/closure_simple.c new file mode 100644 index 0000000000..5a4e728d4a --- /dev/null +++ b/native/libffi/testsuite/libffi.closures/closure_simple.c @@ -0,0 +1,55 @@ +/* Area: closure_call + Purpose: Check simple closure handling with all ABIs + Limitations: none. + PR: none. + Originator: */ + +/* { dg-do run } */ +#include "ffitest.h" + +static void +closure_test(ffi_cif* cif __UNUSED__, void* resp, void** args, void* userdata) +{ + *(ffi_arg*)resp = + (int)*(int *)args[0] + (int)(*(int *)args[1]) + + (int)(*(int *)args[2]) + (int)(*(int *)args[3]) + + (int)(intptr_t)userdata; + + printf("%d %d %d %d: %d\n", + (int)*(int *)args[0], (int)(*(int *)args[1]), + (int)(*(int *)args[2]), (int)(*(int *)args[3]), + (int)*(ffi_arg *)resp); + +} + +typedef int (ABI_ATTR *closure_test_type0)(int, int, int, int); + +int main (void) +{ + ffi_cif cif; + void *code; + ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); + ffi_type * cl_arg_types[17]; + int res; + + cl_arg_types[0] = &ffi_type_uint; + cl_arg_types[1] = &ffi_type_uint; + cl_arg_types[2] = &ffi_type_uint; + cl_arg_types[3] = &ffi_type_uint; + cl_arg_types[4] = NULL; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, ABI_NUM, 4, + &ffi_type_sint, cl_arg_types) == FFI_OK); + + CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test, + (void *) 3 /* userdata */, code) == FFI_OK); + + res = (*(closure_test_type0)code)(0, 1, 2, 3); + /* { dg-output "0 1 2 3: 9" } */ + + printf("res: %d\n",res); + /* { dg-output "\nres: 9" } */ + + exit(0); +} diff --git a/native/libffi/testsuite/libffi.call/cls_12byte.c b/native/libffi/testsuite/libffi.closures/cls_12byte.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_12byte.c rename to native/libffi/testsuite/libffi.closures/cls_12byte.c diff --git a/native/libffi/testsuite/libffi.call/cls_16byte.c b/native/libffi/testsuite/libffi.closures/cls_16byte.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_16byte.c rename to native/libffi/testsuite/libffi.closures/cls_16byte.c diff --git a/native/libffi/testsuite/libffi.call/cls_18byte.c b/native/libffi/testsuite/libffi.closures/cls_18byte.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_18byte.c rename to native/libffi/testsuite/libffi.closures/cls_18byte.c diff --git a/native/libffi/testsuite/libffi.call/cls_19byte.c b/native/libffi/testsuite/libffi.closures/cls_19byte.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_19byte.c rename to native/libffi/testsuite/libffi.closures/cls_19byte.c diff --git a/native/libffi/testsuite/libffi.call/cls_1_1byte.c b/native/libffi/testsuite/libffi.closures/cls_1_1byte.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_1_1byte.c rename to native/libffi/testsuite/libffi.closures/cls_1_1byte.c diff --git a/native/libffi/testsuite/libffi.call/cls_20byte.c b/native/libffi/testsuite/libffi.closures/cls_20byte.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_20byte.c rename to native/libffi/testsuite/libffi.closures/cls_20byte.c diff --git a/native/libffi/testsuite/libffi.call/cls_20byte1.c b/native/libffi/testsuite/libffi.closures/cls_20byte1.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_20byte1.c rename to native/libffi/testsuite/libffi.closures/cls_20byte1.c diff --git a/native/libffi/testsuite/libffi.call/cls_24byte.c b/native/libffi/testsuite/libffi.closures/cls_24byte.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_24byte.c rename to native/libffi/testsuite/libffi.closures/cls_24byte.c diff --git a/native/libffi/testsuite/libffi.call/cls_2byte.c b/native/libffi/testsuite/libffi.closures/cls_2byte.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_2byte.c rename to native/libffi/testsuite/libffi.closures/cls_2byte.c diff --git a/native/libffi/testsuite/libffi.call/cls_3_1byte.c b/native/libffi/testsuite/libffi.closures/cls_3_1byte.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_3_1byte.c rename to native/libffi/testsuite/libffi.closures/cls_3_1byte.c diff --git a/native/libffi/testsuite/libffi.call/cls_3byte1.c b/native/libffi/testsuite/libffi.closures/cls_3byte1.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_3byte1.c rename to native/libffi/testsuite/libffi.closures/cls_3byte1.c diff --git a/native/libffi/testsuite/libffi.call/cls_3byte2.c b/native/libffi/testsuite/libffi.closures/cls_3byte2.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_3byte2.c rename to native/libffi/testsuite/libffi.closures/cls_3byte2.c diff --git a/native/libffi/testsuite/libffi.closures/cls_3float.c b/native/libffi/testsuite/libffi.closures/cls_3float.c new file mode 100644 index 0000000000..48888f8405 --- /dev/null +++ b/native/libffi/testsuite/libffi.closures/cls_3float.c @@ -0,0 +1,95 @@ +/* Area: ffi_call, closure_call + Purpose: Check structure passing with different structure size. + Depending on the ABI. Check overlapping. + Limitations:>none. + PR: none. + Originator: 20171026 */ + +/* { dg-do run } */ + +#include "ffitest.h" + +typedef struct cls_struct_3float { + float f; + float g; + float h; +} cls_struct_3float; + +cls_struct_3float cls_struct_3float_fn(struct cls_struct_3float a1, + struct cls_struct_3float a2) +{ + struct cls_struct_3float result; + + result.f = a1.f + a2.f; + result.g = a1.g + a2.g; + result.h = a1.h + a2.h; + + printf("%g %g %g %g %g %g: %g %g %g\n", a1.f, a1.g, a1.h, + a2.f, a2.g, a2.h, result.f, result.g, result.h); + + return result; +} + +static void +cls_struct_3float_gn(ffi_cif *cif __UNUSED__, void* resp, void **args, + void* userdata __UNUSED__) +{ + struct cls_struct_3float a1, a2; + + a1 = *(struct cls_struct_3float*)(args[0]); + a2 = *(struct cls_struct_3float*)(args[1]); + + *(cls_struct_3float*)resp = cls_struct_3float_fn(a1, a2); +} + +int main (void) +{ + ffi_cif cif; + void *code; + ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); + void *args_dbl[3]; + ffi_type* cls_struct_fields[4]; + ffi_type cls_struct_type; + ffi_type* dbl_arg_types[3]; + + struct cls_struct_3float g_dbl = { 1.0f, 2.0f, 3.0f }; + struct cls_struct_3float f_dbl = { 1.0f, 2.0f, 3.0f }; + struct cls_struct_3float res_dbl; + + cls_struct_fields[0] = &ffi_type_float; + cls_struct_fields[1] = &ffi_type_float; + cls_struct_fields[2] = &ffi_type_float; + cls_struct_fields[3] = NULL; + + cls_struct_type.size = 0; + cls_struct_type.alignment = 0; + cls_struct_type.type = FFI_TYPE_STRUCT; + cls_struct_type.elements = cls_struct_fields; + + dbl_arg_types[0] = &cls_struct_type; + dbl_arg_types[1] = &cls_struct_type; + dbl_arg_types[2] = NULL; + + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, + dbl_arg_types) == FFI_OK); + + args_dbl[0] = &g_dbl; + args_dbl[1] = &f_dbl; + args_dbl[2] = NULL; + + ffi_call(&cif, FFI_FN(cls_struct_3float_fn), &res_dbl, args_dbl); + /* { dg-output "1 2 3 1 2 3: 2 4 6" } */ + printf("res: %g %g %g\n", res_dbl.f, res_dbl.g, res_dbl.h); + /* { dg-output "\nres: 2 4 6" } */ + + CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_3float_gn, NULL, code) == + FFI_OK); + + res_dbl = ((cls_struct_3float(*)(cls_struct_3float, + cls_struct_3float))(code))(g_dbl, f_dbl); + /* { dg-output "\n1 2 3 1 2 3: 2 4 6" } */ + printf("res: %g %g %g\n", res_dbl.f, res_dbl.g, res_dbl.h); + /* { dg-output "\nres: 2 4 6" } */ + + exit(0); +} diff --git a/native/libffi/testsuite/libffi.call/cls_4_1byte.c b/native/libffi/testsuite/libffi.closures/cls_4_1byte.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_4_1byte.c rename to native/libffi/testsuite/libffi.closures/cls_4_1byte.c diff --git a/native/libffi/testsuite/libffi.call/cls_4byte.c b/native/libffi/testsuite/libffi.closures/cls_4byte.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_4byte.c rename to native/libffi/testsuite/libffi.closures/cls_4byte.c diff --git a/native/libffi/testsuite/libffi.call/cls_5_1_byte.c b/native/libffi/testsuite/libffi.closures/cls_5_1_byte.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_5_1_byte.c rename to native/libffi/testsuite/libffi.closures/cls_5_1_byte.c diff --git a/native/libffi/testsuite/libffi.call/cls_5byte.c b/native/libffi/testsuite/libffi.closures/cls_5byte.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_5byte.c rename to native/libffi/testsuite/libffi.closures/cls_5byte.c diff --git a/native/libffi/testsuite/libffi.call/cls_64byte.c b/native/libffi/testsuite/libffi.closures/cls_64byte.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_64byte.c rename to native/libffi/testsuite/libffi.closures/cls_64byte.c diff --git a/native/libffi/testsuite/libffi.call/cls_6_1_byte.c b/native/libffi/testsuite/libffi.closures/cls_6_1_byte.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_6_1_byte.c rename to native/libffi/testsuite/libffi.closures/cls_6_1_byte.c diff --git a/native/libffi/testsuite/libffi.call/cls_6byte.c b/native/libffi/testsuite/libffi.closures/cls_6byte.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_6byte.c rename to native/libffi/testsuite/libffi.closures/cls_6byte.c diff --git a/native/libffi/testsuite/libffi.call/cls_7_1_byte.c b/native/libffi/testsuite/libffi.closures/cls_7_1_byte.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_7_1_byte.c rename to native/libffi/testsuite/libffi.closures/cls_7_1_byte.c diff --git a/native/libffi/testsuite/libffi.call/cls_7byte.c b/native/libffi/testsuite/libffi.closures/cls_7byte.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_7byte.c rename to native/libffi/testsuite/libffi.closures/cls_7byte.c diff --git a/native/libffi/testsuite/libffi.call/cls_8byte.c b/native/libffi/testsuite/libffi.closures/cls_8byte.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_8byte.c rename to native/libffi/testsuite/libffi.closures/cls_8byte.c diff --git a/native/libffi/testsuite/libffi.call/cls_9byte1.c b/native/libffi/testsuite/libffi.closures/cls_9byte1.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_9byte1.c rename to native/libffi/testsuite/libffi.closures/cls_9byte1.c diff --git a/native/libffi/testsuite/libffi.call/cls_9byte2.c b/native/libffi/testsuite/libffi.closures/cls_9byte2.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_9byte2.c rename to native/libffi/testsuite/libffi.closures/cls_9byte2.c diff --git a/native/libffi/testsuite/libffi.call/cls_align_double.c b/native/libffi/testsuite/libffi.closures/cls_align_double.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_align_double.c rename to native/libffi/testsuite/libffi.closures/cls_align_double.c diff --git a/native/libffi/testsuite/libffi.call/cls_align_float.c b/native/libffi/testsuite/libffi.closures/cls_align_float.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_align_float.c rename to native/libffi/testsuite/libffi.closures/cls_align_float.c diff --git a/native/libffi/testsuite/libffi.call/cls_align_longdouble.c b/native/libffi/testsuite/libffi.closures/cls_align_longdouble.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_align_longdouble.c rename to native/libffi/testsuite/libffi.closures/cls_align_longdouble.c diff --git a/native/libffi/testsuite/libffi.call/cls_align_longdouble_split.c b/native/libffi/testsuite/libffi.closures/cls_align_longdouble_split.c similarity index 95% rename from native/libffi/testsuite/libffi.call/cls_align_longdouble_split.c rename to native/libffi/testsuite/libffi.closures/cls_align_longdouble_split.c index 15f9365465..cc1c43b8ca 100644 --- a/native/libffi/testsuite/libffi.call/cls_align_longdouble_split.c +++ b/native/libffi/testsuite/libffi.closures/cls_align_longdouble_split.c @@ -4,10 +4,8 @@ PR: none. Originator: 20031203 */ -/* { dg-excess-errors "no long double format" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */ /* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */ /* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */ -/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */ #include "ffitest.h" diff --git a/native/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c b/native/libffi/testsuite/libffi.closures/cls_align_longdouble_split2.c similarity index 95% rename from native/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c rename to native/libffi/testsuite/libffi.closures/cls_align_longdouble_split2.c index ca1c356cbe..5d3bec0719 100644 --- a/native/libffi/testsuite/libffi.call/cls_align_longdouble_split2.c +++ b/native/libffi/testsuite/libffi.closures/cls_align_longdouble_split2.c @@ -5,10 +5,8 @@ Originator: Blake Chaffin 6/18/2007 */ -/* { dg-excess-errors "no long double format" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */ /* { dg-do run { xfail strongarm*-*-* } } */ /* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */ -/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */ #include "ffitest.h" diff --git a/native/libffi/testsuite/libffi.call/cls_align_pointer.c b/native/libffi/testsuite/libffi.closures/cls_align_pointer.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_align_pointer.c rename to native/libffi/testsuite/libffi.closures/cls_align_pointer.c diff --git a/native/libffi/testsuite/libffi.call/cls_align_sint16.c b/native/libffi/testsuite/libffi.closures/cls_align_sint16.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_align_sint16.c rename to native/libffi/testsuite/libffi.closures/cls_align_sint16.c diff --git a/native/libffi/testsuite/libffi.call/cls_align_sint32.c b/native/libffi/testsuite/libffi.closures/cls_align_sint32.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_align_sint32.c rename to native/libffi/testsuite/libffi.closures/cls_align_sint32.c diff --git a/native/libffi/testsuite/libffi.call/cls_align_sint64.c b/native/libffi/testsuite/libffi.closures/cls_align_sint64.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_align_sint64.c rename to native/libffi/testsuite/libffi.closures/cls_align_sint64.c diff --git a/native/libffi/testsuite/libffi.call/cls_align_uint16.c b/native/libffi/testsuite/libffi.closures/cls_align_uint16.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_align_uint16.c rename to native/libffi/testsuite/libffi.closures/cls_align_uint16.c diff --git a/native/libffi/testsuite/libffi.call/cls_align_uint32.c b/native/libffi/testsuite/libffi.closures/cls_align_uint32.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_align_uint32.c rename to native/libffi/testsuite/libffi.closures/cls_align_uint32.c diff --git a/native/libffi/testsuite/libffi.call/cls_align_uint64.c b/native/libffi/testsuite/libffi.closures/cls_align_uint64.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_align_uint64.c rename to native/libffi/testsuite/libffi.closures/cls_align_uint64.c diff --git a/native/libffi/testsuite/libffi.call/cls_dbls_struct.c b/native/libffi/testsuite/libffi.closures/cls_dbls_struct.c similarity index 95% rename from native/libffi/testsuite/libffi.call/cls_dbls_struct.c rename to native/libffi/testsuite/libffi.closures/cls_dbls_struct.c index d6637911e5..e451dea51b 100644 --- a/native/libffi/testsuite/libffi.call/cls_dbls_struct.c +++ b/native/libffi/testsuite/libffi.closures/cls_dbls_struct.c @@ -57,10 +57,10 @@ int main(int argc __UNUSED__, char** argv __UNUSED__) CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_gn, NULL, code) == FFI_OK); ((void*(*)(Dbls))(code))(arg); - /* { dg-output "1.0 2.0\n" } */ + /* { dg-output "1.0 2.0" } */ closure_test_fn(arg); - /* { dg-output "1.0 2.0\n" } */ + /* { dg-output "\n1.0 2.0" } */ return 0; } diff --git a/native/libffi/testsuite/libffi.call/cls_double.c b/native/libffi/testsuite/libffi.closures/cls_double.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_double.c rename to native/libffi/testsuite/libffi.closures/cls_double.c diff --git a/native/libffi/testsuite/libffi.call/cls_double_va.c b/native/libffi/testsuite/libffi.closures/cls_double_va.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_double_va.c rename to native/libffi/testsuite/libffi.closures/cls_double_va.c diff --git a/native/libffi/testsuite/libffi.call/cls_float.c b/native/libffi/testsuite/libffi.closures/cls_float.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_float.c rename to native/libffi/testsuite/libffi.closures/cls_float.c diff --git a/native/libffi/testsuite/libffi.call/cls_longdouble.c b/native/libffi/testsuite/libffi.closures/cls_longdouble.c similarity index 94% rename from native/libffi/testsuite/libffi.call/cls_longdouble.c rename to native/libffi/testsuite/libffi.closures/cls_longdouble.c index 5dc9ac7685..d24e72e4ae 100644 --- a/native/libffi/testsuite/libffi.call/cls_longdouble.c +++ b/native/libffi/testsuite/libffi.closures/cls_longdouble.c @@ -4,12 +4,10 @@ PR: none. Originator: Blake Chaffin */ -/* { dg-excess-errors "no long double format" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */ /* This test is known to PASS on armv7l-unknown-linux-gnueabihf, so I have remove the xfail for arm*-*-* below, until we know more. */ /* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */ /* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */ -/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */ #include "ffitest.h" diff --git a/native/libffi/testsuite/libffi.call/cls_longdouble_va.c b/native/libffi/testsuite/libffi.closures/cls_longdouble_va.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_longdouble_va.c rename to native/libffi/testsuite/libffi.closures/cls_longdouble_va.c diff --git a/native/libffi/testsuite/libffi.closures/cls_many_mixed_args.c b/native/libffi/testsuite/libffi.closures/cls_many_mixed_args.c new file mode 100644 index 0000000000..7fd6c8207a --- /dev/null +++ b/native/libffi/testsuite/libffi.closures/cls_many_mixed_args.c @@ -0,0 +1,70 @@ +/* Area: closure_call + Purpose: Check closures called with many args of mixed types + Limitations: none. + PR: none. + Originator: */ + +/* { dg-do run } */ +#include "ffitest.h" +#include +#include + +#define NARGS 16 + +static void cls_ret_double_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, + void* userdata __UNUSED__) +{ + int i; + double r = 0; + double t; + for(i = 0; i < NARGS; i++) + { + if(i == 4 || i == 9 || i == 11 || i == 13 || i == 15) + { + t = *(long int *)args[i]; + CHECK(t == i+1); + } + else + { + t = *(double *)args[i]; + CHECK(fabs(t - ((i+1) * 0.1)) < FLT_EPSILON); + } + r += t; + } + *(double *)resp = r; +} +typedef double (*cls_ret_double)(double, double, double, double, long int, +double, double, double, double, long int, double, long int, double, long int, +double, long int); + +int main (void) +{ + ffi_cif cif; + void *code; + ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); + ffi_type * cl_arg_types[NARGS]; + double res; + int i; + double expected = 64.9; + + for(i = 0; i < NARGS; i++) + { + if(i == 4 || i == 9 || i == 11 || i == 13 || i == 15) + cl_arg_types[i] = &ffi_type_slong; + else + cl_arg_types[i] = &ffi_type_double; + } + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, NARGS, + &ffi_type_double, cl_arg_types) == FFI_OK); + + CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_double_fn, NULL, code) == FFI_OK); + + res = (((cls_ret_double)code))(0.1, 0.2, 0.3, 0.4, 5, 0.6, 0.7, 0.8, 0.9, 10, + 1.1, 12, 1.3, 14, 1.5, 16); + if (fabs(res - expected) < FLT_EPSILON) + exit(0); + else + abort(); +} diff --git a/native/libffi/testsuite/libffi.closures/cls_many_mixed_float_double.c b/native/libffi/testsuite/libffi.closures/cls_many_mixed_float_double.c new file mode 100644 index 0000000000..62b0697ac0 --- /dev/null +++ b/native/libffi/testsuite/libffi.closures/cls_many_mixed_float_double.c @@ -0,0 +1,55 @@ +/* Area: closure_call + Purpose: Check register allocation for closure calls with many float and double arguments + Limitations: none. + PR: none. + Originator: */ + +/* { dg-do run } */ +#include "ffitest.h" +#include +#include + +#define NARGS 16 + +static void cls_mixed_float_double_fn(ffi_cif* cif , void* ret, void** args, + void* userdata __UNUSED__) +{ + double r = 0; + unsigned int i; + double t; + for(i=0; i < cif->nargs; i++) + { + if(cif->arg_types[i] == &ffi_type_double) { + t = *(((double**)(args))[i]); + } else { + t = *(((float**)(args))[i]); + } + r += t; + } + *((double*)ret) = r; +} +typedef double (*cls_mixed)(double, float, double, double, double, double, double, float, float, double, float, float); + +int main (void) +{ + ffi_cif cif; + ffi_closure *closure; + void* code; + ffi_type *argtypes[12] = {&ffi_type_double, &ffi_type_float, &ffi_type_double, + &ffi_type_double, &ffi_type_double, &ffi_type_double, + &ffi_type_double, &ffi_type_float, &ffi_type_float, + &ffi_type_double, &ffi_type_float, &ffi_type_float}; + + + closure = ffi_closure_alloc(sizeof(ffi_closure), (void**)&code); + if(closure ==NULL) + abort(); + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 12, &ffi_type_double, argtypes) == FFI_OK); + CHECK(ffi_prep_closure_loc(closure, &cif, cls_mixed_float_double_fn, NULL, code) == FFI_OK); + double ret = ((cls_mixed)code)(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2); + ffi_closure_free(closure); + if(fabs(ret - 7.8) < FLT_EPSILON) + exit(0); + else + abort(); +} diff --git a/native/libffi/testsuite/libffi.call/cls_multi_schar.c b/native/libffi/testsuite/libffi.closures/cls_multi_schar.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_multi_schar.c rename to native/libffi/testsuite/libffi.closures/cls_multi_schar.c diff --git a/native/libffi/testsuite/libffi.call/cls_multi_sshort.c b/native/libffi/testsuite/libffi.closures/cls_multi_sshort.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_multi_sshort.c rename to native/libffi/testsuite/libffi.closures/cls_multi_sshort.c diff --git a/native/libffi/testsuite/libffi.call/cls_multi_sshortchar.c b/native/libffi/testsuite/libffi.closures/cls_multi_sshortchar.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_multi_sshortchar.c rename to native/libffi/testsuite/libffi.closures/cls_multi_sshortchar.c diff --git a/native/libffi/testsuite/libffi.call/cls_multi_uchar.c b/native/libffi/testsuite/libffi.closures/cls_multi_uchar.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_multi_uchar.c rename to native/libffi/testsuite/libffi.closures/cls_multi_uchar.c diff --git a/native/libffi/testsuite/libffi.call/cls_multi_ushort.c b/native/libffi/testsuite/libffi.closures/cls_multi_ushort.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_multi_ushort.c rename to native/libffi/testsuite/libffi.closures/cls_multi_ushort.c diff --git a/native/libffi/testsuite/libffi.call/cls_multi_ushortchar.c b/native/libffi/testsuite/libffi.closures/cls_multi_ushortchar.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_multi_ushortchar.c rename to native/libffi/testsuite/libffi.closures/cls_multi_ushortchar.c diff --git a/native/libffi/testsuite/libffi.call/cls_pointer.c b/native/libffi/testsuite/libffi.closures/cls_pointer.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_pointer.c rename to native/libffi/testsuite/libffi.closures/cls_pointer.c diff --git a/native/libffi/testsuite/libffi.call/cls_pointer_stack.c b/native/libffi/testsuite/libffi.closures/cls_pointer_stack.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_pointer_stack.c rename to native/libffi/testsuite/libffi.closures/cls_pointer_stack.c diff --git a/native/libffi/testsuite/libffi.call/cls_schar.c b/native/libffi/testsuite/libffi.closures/cls_schar.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_schar.c rename to native/libffi/testsuite/libffi.closures/cls_schar.c diff --git a/native/libffi/testsuite/libffi.call/cls_sint.c b/native/libffi/testsuite/libffi.closures/cls_sint.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_sint.c rename to native/libffi/testsuite/libffi.closures/cls_sint.c diff --git a/native/libffi/testsuite/libffi.call/cls_sshort.c b/native/libffi/testsuite/libffi.closures/cls_sshort.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_sshort.c rename to native/libffi/testsuite/libffi.closures/cls_sshort.c diff --git a/native/libffi/testsuite/libffi.call/cls_struct_va1.c b/native/libffi/testsuite/libffi.closures/cls_struct_va1.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_struct_va1.c rename to native/libffi/testsuite/libffi.closures/cls_struct_va1.c diff --git a/native/libffi/testsuite/libffi.call/cls_uchar.c b/native/libffi/testsuite/libffi.closures/cls_uchar.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_uchar.c rename to native/libffi/testsuite/libffi.closures/cls_uchar.c diff --git a/native/libffi/testsuite/libffi.call/cls_uchar_va.c b/native/libffi/testsuite/libffi.closures/cls_uchar_va.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_uchar_va.c rename to native/libffi/testsuite/libffi.closures/cls_uchar_va.c diff --git a/native/libffi/testsuite/libffi.call/cls_uint.c b/native/libffi/testsuite/libffi.closures/cls_uint.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_uint.c rename to native/libffi/testsuite/libffi.closures/cls_uint.c diff --git a/native/libffi/testsuite/libffi.call/cls_uint_va.c b/native/libffi/testsuite/libffi.closures/cls_uint_va.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_uint_va.c rename to native/libffi/testsuite/libffi.closures/cls_uint_va.c diff --git a/native/libffi/testsuite/libffi.call/cls_ulong_va.c b/native/libffi/testsuite/libffi.closures/cls_ulong_va.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_ulong_va.c rename to native/libffi/testsuite/libffi.closures/cls_ulong_va.c diff --git a/native/libffi/testsuite/libffi.call/cls_ulonglong.c b/native/libffi/testsuite/libffi.closures/cls_ulonglong.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_ulonglong.c rename to native/libffi/testsuite/libffi.closures/cls_ulonglong.c diff --git a/native/libffi/testsuite/libffi.call/cls_ushort.c b/native/libffi/testsuite/libffi.closures/cls_ushort.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_ushort.c rename to native/libffi/testsuite/libffi.closures/cls_ushort.c diff --git a/native/libffi/testsuite/libffi.call/cls_ushort_va.c b/native/libffi/testsuite/libffi.closures/cls_ushort_va.c similarity index 100% rename from native/libffi/testsuite/libffi.call/cls_ushort_va.c rename to native/libffi/testsuite/libffi.closures/cls_ushort_va.c diff --git a/native/libffi/testsuite/libffi.call/err_bad_abi.c b/native/libffi/testsuite/libffi.closures/err_bad_abi.c similarity index 100% rename from native/libffi/testsuite/libffi.call/err_bad_abi.c rename to native/libffi/testsuite/libffi.closures/err_bad_abi.c diff --git a/native/libffi/testsuite/libffi.closures/ffitest.h b/native/libffi/testsuite/libffi.closures/ffitest.h new file mode 100644 index 0000000000..cfce1ad589 --- /dev/null +++ b/native/libffi/testsuite/libffi.closures/ffitest.h @@ -0,0 +1,138 @@ +#include +#include +#include +#include +#include +#include "fficonfig.h" + +#if defined HAVE_STDINT_H +#include +#endif + +#if defined HAVE_INTTYPES_H +#include +#endif + +#define MAX_ARGS 256 + +#define CHECK(x) (void)(!(x) ? (abort(), 1) : 0) + +/* Define macros so that compilers other than gcc can run the tests. */ +#undef __UNUSED__ +#if defined(__GNUC__) +#define __UNUSED__ __attribute__((__unused__)) +#define __STDCALL__ __attribute__((stdcall)) +#define __THISCALL__ __attribute__((thiscall)) +#define __FASTCALL__ __attribute__((fastcall)) +#define __MSABI__ __attribute__((ms_abi)) +#else +#define __UNUSED__ +#define __STDCALL__ __stdcall +#define __THISCALL__ __thiscall +#define __FASTCALL__ __fastcall +#endif + +#ifndef ABI_NUM +#define ABI_NUM FFI_DEFAULT_ABI +#define ABI_ATTR +#endif + +/* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a + file open. */ +#ifdef HAVE_MMAP_ANON +# undef HAVE_MMAP_DEV_ZERO + +# include +# ifndef MAP_FAILED +# define MAP_FAILED -1 +# endif +# if !defined (MAP_ANONYMOUS) && defined (MAP_ANON) +# define MAP_ANONYMOUS MAP_ANON +# endif +# define USING_MMAP + +#endif + +#ifdef HAVE_MMAP_DEV_ZERO + +# include +# ifndef MAP_FAILED +# define MAP_FAILED -1 +# endif +# define USING_MMAP + +#endif + +/* MinGW kludge. */ +#if defined(_WIN64) | defined(_WIN32) +#define PRIdLL "I64d" +#define PRIuLL "I64u" +#else +#define PRIdLL "lld" +#define PRIuLL "llu" +#endif + +/* Tru64 UNIX kludge. */ +#if defined(__alpha__) && defined(__osf__) +/* Tru64 UNIX V4.0 doesn't support %lld/%lld, but long is 64-bit. */ +#undef PRIdLL +#define PRIdLL "ld" +#undef PRIuLL +#define PRIuLL "lu" +#define PRId8 "hd" +#define PRIu8 "hu" +#define PRId64 "ld" +#define PRIu64 "lu" +#define PRIuPTR "lu" +#endif + +/* PA HP-UX kludge. */ +#if defined(__hppa__) && defined(__hpux__) && !defined(PRIuPTR) +#define PRIuPTR "lu" +#endif + +/* IRIX kludge. */ +#if defined(__sgi) +/* IRIX 6.5 provides all definitions, but only for C99 + compilations. */ +#define PRId8 "hhd" +#define PRIu8 "hhu" +#if (_MIPS_SZLONG == 32) +#define PRId64 "lld" +#define PRIu64 "llu" +#endif +/* This doesn't match , which always has "lld" here, but the + arguments are uint64_t, int64_t, which are unsigned long, long for + 64-bit in . */ +#if (_MIPS_SZLONG == 64) +#define PRId64 "ld" +#define PRIu64 "lu" +#endif +/* This doesn't match , which has "u" here, but the arguments + are uintptr_t, which is always unsigned long. */ +#define PRIuPTR "lu" +#endif + +/* Solaris < 10 kludge. */ +#if defined(__sun__) && defined(__svr4__) && !defined(PRIuPTR) +#if defined(__arch64__) || defined (__x86_64__) +#define PRIuPTR "lu" +#else +#define PRIuPTR "u" +#endif +#endif + +/* MSVC kludge. */ +#if defined _MSC_VER +#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) +#define PRIuPTR "lu" +#define PRIu8 "u" +#define PRId8 "d" +#define PRIu64 "I64u" +#define PRId64 "I64d" +#endif +#endif + +#ifndef PRIuPTR +#define PRIuPTR "u" +#endif diff --git a/native/libffi/testsuite/libffi.call/huge_struct.c b/native/libffi/testsuite/libffi.closures/huge_struct.c similarity index 98% rename from native/libffi/testsuite/libffi.call/huge_struct.c rename to native/libffi/testsuite/libffi.closures/huge_struct.c index 657fe54148..e8e1d8601f 100644 --- a/native/libffi/testsuite/libffi.call/huge_struct.c +++ b/native/libffi/testsuite/libffi.closures/huge_struct.c @@ -5,11 +5,11 @@ Originator: Blake Chaffin 6/18/2007 */ -/* { dg-excess-errors "" { target x86_64-*-mingw* x86_64-*-cygwin* } } */ /* { dg-do run { xfail strongarm*-*-* xscale*-*-* } } */ /* { dg-options -mlong-double-128 { target powerpc64*-*-linux* } } */ -/* { dg-options -Wformat=0 { target moxie*-*-elf } } */ -/* { dg-output "" { xfail x86_64-*-mingw* x86_64-*-cygwin* } } */ +/* { dg-options -Wformat=0 { target moxie*-*-elf or1k-*-* } } */ + +#include #include "ffitest.h" diff --git a/native/libffi/testsuite/libffi.call/nested_struct.c b/native/libffi/testsuite/libffi.closures/nested_struct.c similarity index 100% rename from native/libffi/testsuite/libffi.call/nested_struct.c rename to native/libffi/testsuite/libffi.closures/nested_struct.c diff --git a/native/libffi/testsuite/libffi.call/nested_struct1.c b/native/libffi/testsuite/libffi.closures/nested_struct1.c similarity index 100% rename from native/libffi/testsuite/libffi.call/nested_struct1.c rename to native/libffi/testsuite/libffi.closures/nested_struct1.c diff --git a/native/libffi/testsuite/libffi.call/nested_struct10.c b/native/libffi/testsuite/libffi.closures/nested_struct10.c similarity index 99% rename from native/libffi/testsuite/libffi.call/nested_struct10.c rename to native/libffi/testsuite/libffi.closures/nested_struct10.c index 34a74e7187..3cf2b44abe 100644 --- a/native/libffi/testsuite/libffi.call/nested_struct10.c +++ b/native/libffi/testsuite/libffi.closures/nested_struct10.c @@ -32,6 +32,7 @@ static B B_fn(struct A b2, struct B b3, struct C b4) result.x.a = b2.a + b3.x.a + b3.z + b4.d; result.x.b = b2.b + b3.x.b + b3.y + b4.e; result.y = b2.b + b3.x.b + b4.e; + result.z = 0; printf("%d %d %d %d %d %d %d %d: %d %d %d\n", (int)b2.a, b2.b, (int)b3.x.a, b3.x.b, b3.y, b3.z, (int)b4.d, b4.e, diff --git a/native/libffi/testsuite/libffi.call/nested_struct11.c b/native/libffi/testsuite/libffi.closures/nested_struct11.c similarity index 100% rename from native/libffi/testsuite/libffi.call/nested_struct11.c rename to native/libffi/testsuite/libffi.closures/nested_struct11.c diff --git a/native/libffi/testsuite/libffi.call/nested_struct2.c b/native/libffi/testsuite/libffi.closures/nested_struct2.c similarity index 100% rename from native/libffi/testsuite/libffi.call/nested_struct2.c rename to native/libffi/testsuite/libffi.closures/nested_struct2.c diff --git a/native/libffi/testsuite/libffi.call/nested_struct3.c b/native/libffi/testsuite/libffi.closures/nested_struct3.c similarity index 100% rename from native/libffi/testsuite/libffi.call/nested_struct3.c rename to native/libffi/testsuite/libffi.closures/nested_struct3.c diff --git a/native/libffi/testsuite/libffi.call/nested_struct4.c b/native/libffi/testsuite/libffi.closures/nested_struct4.c similarity index 100% rename from native/libffi/testsuite/libffi.call/nested_struct4.c rename to native/libffi/testsuite/libffi.closures/nested_struct4.c diff --git a/native/libffi/testsuite/libffi.call/nested_struct5.c b/native/libffi/testsuite/libffi.closures/nested_struct5.c similarity index 100% rename from native/libffi/testsuite/libffi.call/nested_struct5.c rename to native/libffi/testsuite/libffi.closures/nested_struct5.c diff --git a/native/libffi/testsuite/libffi.call/nested_struct6.c b/native/libffi/testsuite/libffi.closures/nested_struct6.c similarity index 100% rename from native/libffi/testsuite/libffi.call/nested_struct6.c rename to native/libffi/testsuite/libffi.closures/nested_struct6.c diff --git a/native/libffi/testsuite/libffi.call/nested_struct7.c b/native/libffi/testsuite/libffi.closures/nested_struct7.c similarity index 100% rename from native/libffi/testsuite/libffi.call/nested_struct7.c rename to native/libffi/testsuite/libffi.closures/nested_struct7.c diff --git a/native/libffi/testsuite/libffi.call/nested_struct8.c b/native/libffi/testsuite/libffi.closures/nested_struct8.c similarity index 100% rename from native/libffi/testsuite/libffi.call/nested_struct8.c rename to native/libffi/testsuite/libffi.closures/nested_struct8.c diff --git a/native/libffi/testsuite/libffi.call/nested_struct9.c b/native/libffi/testsuite/libffi.closures/nested_struct9.c similarity index 100% rename from native/libffi/testsuite/libffi.call/nested_struct9.c rename to native/libffi/testsuite/libffi.closures/nested_struct9.c diff --git a/native/libffi/testsuite/libffi.call/problem1.c b/native/libffi/testsuite/libffi.closures/problem1.c similarity index 100% rename from native/libffi/testsuite/libffi.call/problem1.c rename to native/libffi/testsuite/libffi.closures/problem1.c diff --git a/native/libffi/testsuite/libffi.call/stret_large.c b/native/libffi/testsuite/libffi.closures/stret_large.c similarity index 100% rename from native/libffi/testsuite/libffi.call/stret_large.c rename to native/libffi/testsuite/libffi.closures/stret_large.c diff --git a/native/libffi/testsuite/libffi.call/stret_large2.c b/native/libffi/testsuite/libffi.closures/stret_large2.c similarity index 100% rename from native/libffi/testsuite/libffi.call/stret_large2.c rename to native/libffi/testsuite/libffi.closures/stret_large2.c diff --git a/native/libffi/testsuite/libffi.call/stret_medium.c b/native/libffi/testsuite/libffi.closures/stret_medium.c similarity index 100% rename from native/libffi/testsuite/libffi.call/stret_medium.c rename to native/libffi/testsuite/libffi.closures/stret_medium.c diff --git a/native/libffi/testsuite/libffi.call/stret_medium2.c b/native/libffi/testsuite/libffi.closures/stret_medium2.c similarity index 100% rename from native/libffi/testsuite/libffi.call/stret_medium2.c rename to native/libffi/testsuite/libffi.closures/stret_medium2.c diff --git a/native/libffi/testsuite/libffi.call/testclosure.c b/native/libffi/testsuite/libffi.closures/testclosure.c similarity index 100% rename from native/libffi/testsuite/libffi.call/testclosure.c rename to native/libffi/testsuite/libffi.closures/testclosure.c diff --git a/native/libffi/testsuite/libffi.closures/unwindtest.cc b/native/libffi/testsuite/libffi.closures/unwindtest.cc new file mode 100644 index 0000000000..e1145657d1 --- /dev/null +++ b/native/libffi/testsuite/libffi.closures/unwindtest.cc @@ -0,0 +1,117 @@ +/* Area: ffi_closure, unwind info + Purpose: Check if the unwind information is passed correctly. + Limitations: none. + PR: none. + Originator: Jeff Sturm */ + +/* { dg-do run { xfail x86_64-apple-darwin* moxie*-*-* } } */ + +#include "ffitest.h" + +void ABI_ATTR +closure_test_fn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__, + void** args __UNUSED__, void* userdata __UNUSED__) +{ + throw 9; +} + +typedef void (*closure_test_type)(); + +void closure_test_fn1(ffi_cif* cif __UNUSED__, void* resp, + void** args, void* userdata __UNUSED__) + { + *(ffi_arg*)resp = + (int)*(float *)args[0] +(int)(*(float *)args[1]) + + (int)(*(float *)args[2]) + (int)*(float *)args[3] + + (int)(*(signed short *)args[4]) + (int)(*(float *)args[5]) + + (int)*(float *)args[6] + (int)(*(int *)args[7]) + + (int)(*(double*)args[8]) + (int)*(int *)args[9] + + (int)(*(int *)args[10]) + (int)(*(float *)args[11]) + + (int)*(int *)args[12] + (int)(*(int *)args[13]) + + (int)(*(int *)args[14]) + *(int *)args[15] + (int)(intptr_t)userdata; + + printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d: %d\n", + (int)*(float *)args[0], (int)(*(float *)args[1]), + (int)(*(float *)args[2]), (int)*(float *)args[3], + (int)(*(signed short *)args[4]), (int)(*(float *)args[5]), + (int)*(float *)args[6], (int)(*(int *)args[7]), + (int)(*(double *)args[8]), (int)*(int *)args[9], + (int)(*(int *)args[10]), (int)(*(float *)args[11]), + (int)*(int *)args[12], (int)(*(int *)args[13]), + (int)(*(int *)args[14]), *(int *)args[15], + (int)(intptr_t)userdata, (int)*(ffi_arg*)resp); + + throw (int)*(ffi_arg*)resp; +} + +typedef int (*closure_test_type1)(float, float, float, float, signed short, + float, float, int, double, int, int, float, + int, int, int, int); + +int main (void) +{ + ffi_cif cif; + void *code; + ffi_closure *pcl = (ffi_closure *)ffi_closure_alloc(sizeof(ffi_closure), &code); + ffi_type * cl_arg_types[17]; + + { + cl_arg_types[1] = NULL; + + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 0, + &ffi_type_void, cl_arg_types) == FFI_OK); + CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn, NULL, code) == FFI_OK); + + try + { + (*((closure_test_type)(code)))(); + } catch (int exception_code) + { + CHECK(exception_code == 9); + } + + printf("part one OK\n"); + /* { dg-output "part one OK" } */ + } + + { + + cl_arg_types[0] = &ffi_type_float; + cl_arg_types[1] = &ffi_type_float; + cl_arg_types[2] = &ffi_type_float; + cl_arg_types[3] = &ffi_type_float; + cl_arg_types[4] = &ffi_type_sshort; + cl_arg_types[5] = &ffi_type_float; + cl_arg_types[6] = &ffi_type_float; + cl_arg_types[7] = &ffi_type_uint; + cl_arg_types[8] = &ffi_type_double; + cl_arg_types[9] = &ffi_type_uint; + cl_arg_types[10] = &ffi_type_uint; + cl_arg_types[11] = &ffi_type_float; + cl_arg_types[12] = &ffi_type_uint; + cl_arg_types[13] = &ffi_type_uint; + cl_arg_types[14] = &ffi_type_uint; + cl_arg_types[15] = &ffi_type_uint; + cl_arg_types[16] = NULL; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 16, + &ffi_type_sint, cl_arg_types) == FFI_OK); + + CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_fn1, + (void *) 3 /* userdata */, code) == FFI_OK); + try + { + (*((closure_test_type1)code)) + (1.1, 2.2, 3.3, 4.4, 127, 5.5, 6.6, 8, 9, 10, 11, 12.0, 13, + 19, 21, 1); + /* { dg-output "\n1 2 3 4 127 5 6 8 9 10 11 12 13 19 21 1 3: 255" } */ + } catch (int exception_code) + { + CHECK(exception_code == 255); + } + printf("part two OK\n"); + /* { dg-output "\npart two OK" } */ + } + exit(0); +} diff --git a/native/libffi/testsuite/libffi.closures/unwindtest_ffi_call.cc b/native/libffi/testsuite/libffi.closures/unwindtest_ffi_call.cc new file mode 100644 index 0000000000..153d240940 --- /dev/null +++ b/native/libffi/testsuite/libffi.closures/unwindtest_ffi_call.cc @@ -0,0 +1,54 @@ +/* Area: ffi_call, unwind info + Purpose: Check if the unwind information is passed correctly. + Limitations: none. + PR: none. + Originator: Andreas Tobler 20061213 */ + +/* { dg-do run { xfail moxie*-*-* } } */ + +#include "ffitest.h" + +static int checking(int a __UNUSED__, short b __UNUSED__, + signed char c __UNUSED__) +{ + throw 9; +} + +int main (void) +{ + ffi_cif cif; + ffi_type *args[MAX_ARGS]; + void *values[MAX_ARGS]; + ffi_arg rint; + + signed int si; + signed short ss; + signed char sc; + + args[0] = &ffi_type_sint; + values[0] = &si; + args[1] = &ffi_type_sshort; + values[1] = &ss; + args[2] = &ffi_type_schar; + values[2] = ≻ + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, + &ffi_type_sint, args) == FFI_OK); + + si = -6; + ss = -12; + sc = -1; + { + try + { + ffi_call(&cif, FFI_FN(checking), &rint, values); + } catch (int exception_code) + { + CHECK(exception_code == 9); + } + printf("part one OK\n"); + /* { dg-output "part one OK" } */ + } + exit(0); +} diff --git a/native/libffi/testsuite/libffi.complex/cls_align_complex.inc b/native/libffi/testsuite/libffi.complex/cls_align_complex.inc new file mode 100644 index 0000000000..4a812edf05 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/cls_align_complex.inc @@ -0,0 +1,91 @@ +/* -*-c-*- */ +#include "ffitest.h" +#include + +typedef struct cls_struct_align { + unsigned char a; + _Complex T_C_TYPE b; + unsigned char c; +} cls_struct_align; + +cls_struct_align cls_struct_align_fn( + struct cls_struct_align a1, struct cls_struct_align a2) +{ + struct cls_struct_align result; + + result.a = a1.a + a2.a; + result.b = a1.b + a2.b; + result.c = a1.c + a2.c; + + printf("%d %f,%fi %d %d %f,%fi %d: %d %f,%fi %d\n", + a1.a, T_CONV creal (a1.b), T_CONV cimag (a1.b), a1.c, + a2.a, T_CONV creal (a2.b), T_CONV cimag (a2.b), a2.c, + result.a, T_CONV creal (result.b), T_CONV cimag (result.b), result.c); + + return result; +} + +static void +cls_struct_align_gn(ffi_cif* cif __UNUSED__, void* resp, void** args, + void* userdata __UNUSED__) +{ + + struct cls_struct_align a1, a2; + + a1 = *(struct cls_struct_align*)(args[0]); + a2 = *(struct cls_struct_align*)(args[1]); + + *(cls_struct_align*)resp = cls_struct_align_fn(a1, a2); +} + +int main (void) +{ + ffi_cif cif; + void *code; + ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); + void* args_c[5]; + ffi_type* cls_struct_fields[4]; + ffi_type cls_struct_type; + ffi_type* c_arg_types[5]; + + struct cls_struct_align g_c = { 12, 4951 + 7 * I, 127 }; + struct cls_struct_align f_c = { 1, 9320 + 1 * I, 13 }; + struct cls_struct_align res_c; + + cls_struct_type.size = 0; + cls_struct_type.alignment = 0; + cls_struct_type.type = FFI_TYPE_STRUCT; + cls_struct_type.elements = cls_struct_fields; + + cls_struct_fields[0] = &ffi_type_uchar; + cls_struct_fields[1] = &T_FFI_TYPE; + cls_struct_fields[2] = &ffi_type_uchar; + cls_struct_fields[3] = NULL; + + c_arg_types[0] = &cls_struct_type; + c_arg_types[1] = &cls_struct_type; + c_arg_types[2] = NULL; + + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 2, &cls_struct_type, + c_arg_types) == FFI_OK); + + args_c[0] = &g_c; + args_c[1] = &f_c; + args_c[2] = NULL; + + ffi_call(&cif, FFI_FN(cls_struct_align_fn), &res_c, args_c); + /* { dg-output "12 4951,7i 127 1 9320,1i 13: 13 14271,8i 140" } */ + printf("res: %d %f,%fi %d\n", + res_c.a, T_CONV creal (res_c.b), T_CONV cimag (res_c.b), res_c.c); + /* { dg-output "\nres: 13 14271,8i 140" } */ + + CHECK(ffi_prep_closure_loc(pcl, &cif, cls_struct_align_gn, NULL, code) == FFI_OK); + + res_c = ((cls_struct_align(*)(cls_struct_align, cls_struct_align))(code))(g_c, f_c); + /* { dg-output "\n12 4951,7i 127 1 9320,1i 13: 13 14271,8i 140" } */ + printf("res: %d %f,%fi %d\n", + res_c.a, T_CONV creal (res_c.b), T_CONV cimag (res_c.b), res_c.c); + /* { dg-output "\nres: 13 14271,8i 140" } */ + + exit(0); +} diff --git a/native/libffi/testsuite/libffi.complex/cls_align_complex_double.c b/native/libffi/testsuite/libffi.complex/cls_align_complex_double.c new file mode 100644 index 0000000000..0dff23ae47 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/cls_align_complex_double.c @@ -0,0 +1,10 @@ +/* Area: ffi_call, closure_call + Purpose: Check structure alignment of complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_double.inc" +#include "cls_align_complex.inc" diff --git a/native/libffi/testsuite/libffi.complex/cls_align_complex_float.c b/native/libffi/testsuite/libffi.complex/cls_align_complex_float.c new file mode 100644 index 0000000000..0affbd07e5 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/cls_align_complex_float.c @@ -0,0 +1,10 @@ +/* Area: ffi_call, closure_call + Purpose: Check structure alignment of complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_float.inc" +#include "cls_align_complex.inc" diff --git a/native/libffi/testsuite/libffi.complex/cls_align_complex_longdouble.c b/native/libffi/testsuite/libffi.complex/cls_align_complex_longdouble.c new file mode 100644 index 0000000000..7889ba859b --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/cls_align_complex_longdouble.c @@ -0,0 +1,10 @@ +/* Area: ffi_call, closure_call + Purpose: Check structure alignment of complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_longdouble.inc" +#include "cls_align_complex.inc" diff --git a/native/libffi/testsuite/libffi.complex/cls_complex.inc b/native/libffi/testsuite/libffi.complex/cls_complex.inc new file mode 100644 index 0000000000..f9374044e8 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/cls_complex.inc @@ -0,0 +1,42 @@ +/* -*-c-*- */ +#include "ffitest.h" +#include + +static void cls_ret_complex_fn(ffi_cif* cif __UNUSED__, void* resp, void** args, + void* userdata __UNUSED__) + { + _Complex T_C_TYPE *pa; + _Complex T_C_TYPE *pr; + pa = (_Complex T_C_TYPE *)args[0]; + pr = (_Complex T_C_TYPE *)resp; + *pr = *pa; + + printf("%.6f,%.6fi: %.6f,%.6fi\n", + T_CONV creal (*pa), T_CONV cimag (*pa), + T_CONV creal (*pr), T_CONV cimag (*pr)); + } +typedef _Complex T_C_TYPE (*cls_ret_complex)(_Complex T_C_TYPE); + +int main (void) +{ + ffi_cif cif; + void *code; + ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); + ffi_type * cl_arg_types[2]; + _Complex T_C_TYPE res; + + cl_arg_types[0] = &T_FFI_TYPE; + cl_arg_types[1] = NULL; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, + &T_FFI_TYPE, cl_arg_types) == FFI_OK); + + CHECK(ffi_prep_closure_loc(pcl, &cif, cls_ret_complex_fn, NULL, code) == FFI_OK); + + res = (*((cls_ret_complex)code))(0.125 + 128.0 * I); + printf("res: %.6f,%.6fi\n", T_CONV creal (res), T_CONV cimag (res)); + CHECK (res == (0.125 + 128.0 * I)); + + exit(0); +} diff --git a/native/libffi/testsuite/libffi.complex/cls_complex_double.c b/native/libffi/testsuite/libffi.complex/cls_complex_double.c new file mode 100644 index 0000000000..05e35340e0 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/cls_complex_double.c @@ -0,0 +1,10 @@ +/* Area: closure_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_double.inc" +#include "cls_complex.inc" diff --git a/native/libffi/testsuite/libffi.complex/cls_complex_float.c b/native/libffi/testsuite/libffi.complex/cls_complex_float.c new file mode 100644 index 0000000000..5df7849d4c --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/cls_complex_float.c @@ -0,0 +1,10 @@ +/* Area: closure_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_float.inc" +#include "cls_complex.inc" diff --git a/native/libffi/testsuite/libffi.complex/cls_complex_longdouble.c b/native/libffi/testsuite/libffi.complex/cls_complex_longdouble.c new file mode 100644 index 0000000000..2b1c320a20 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/cls_complex_longdouble.c @@ -0,0 +1,10 @@ +/* Area: closure_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_longdouble.inc" +#include "cls_complex.inc" diff --git a/native/libffi/testsuite/libffi.complex/cls_complex_struct.inc b/native/libffi/testsuite/libffi.complex/cls_complex_struct.inc new file mode 100644 index 0000000000..df8708d1c4 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/cls_complex_struct.inc @@ -0,0 +1,71 @@ +/* -*-c-*- */ +#include "ffitest.h" +#include + +typedef struct Cs { + _Complex T_C_TYPE x; + _Complex T_C_TYPE y; +} Cs; + +Cs gc; + +void +closure_test_fn(Cs p) +{ + printf("%.1f,%.1fi %.1f,%.1fi\n", + T_CONV creal (p.x), T_CONV cimag (p.x), + T_CONV creal (p.y), T_CONV cimag (p.y)); + gc = p; +} + +void +closure_test_gn(ffi_cif* cif __UNUSED__, void* resp __UNUSED__, + void** args, void* userdata __UNUSED__) +{ + closure_test_fn(*(Cs*)args[0]); +} + +int main(int argc __UNUSED__, char** argv __UNUSED__) +{ + ffi_cif cif; + + void *code; + ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); + ffi_type *cl_arg_types[1]; + + ffi_type ts1_type; + ffi_type* ts1_type_elements[4]; + + Cs arg = { 1.0 + 11.0 * I, 2.0 + 22.0 * I}; + + ts1_type.size = 0; + ts1_type.alignment = 0; + ts1_type.type = FFI_TYPE_STRUCT; + ts1_type.elements = ts1_type_elements; + + ts1_type_elements[0] = &T_FFI_TYPE; + ts1_type_elements[1] = &T_FFI_TYPE; + ts1_type_elements[2] = NULL; + + cl_arg_types[0] = &ts1_type; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, + &ffi_type_void, cl_arg_types) == FFI_OK); + + CHECK(ffi_prep_closure_loc(pcl, &cif, closure_test_gn, NULL, code) == FFI_OK); + + gc.x = 0.0 + 0.0 * I; + gc.y = 0.0 + 0.0 * I; + ((void*(*)(Cs))(code))(arg); + /* { dg-output "1.0,11.0i 2.0,22.0i\n" } */ + CHECK (gc.x == arg.x && gc.y == arg.y); + + gc.x = 0.0 + 0.0 * I; + gc.y = 0.0 + 0.0 * I; + closure_test_fn(arg); + /* { dg-output "1.0,11.0i 2.0,22.0i\n" } */ + CHECK (gc.x == arg.x && gc.y == arg.y); + + return 0; +} diff --git a/native/libffi/testsuite/libffi.complex/cls_complex_struct_double.c b/native/libffi/testsuite/libffi.complex/cls_complex_struct_double.c new file mode 100644 index 0000000000..ec71346a3f --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/cls_complex_struct_double.c @@ -0,0 +1,10 @@ +/* Area: ffi_call, closure_call + Purpose: Check complex arguments in structs. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_double.inc" +#include "cls_complex_struct.inc" diff --git a/native/libffi/testsuite/libffi.complex/cls_complex_struct_float.c b/native/libffi/testsuite/libffi.complex/cls_complex_struct_float.c new file mode 100644 index 0000000000..96fdf75043 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/cls_complex_struct_float.c @@ -0,0 +1,10 @@ +/* Area: ffi_call, closure_call + Purpose: Check complex arguments in structs. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_float.inc" +#include "cls_complex_struct.inc" diff --git a/native/libffi/testsuite/libffi.complex/cls_complex_struct_longdouble.c b/native/libffi/testsuite/libffi.complex/cls_complex_struct_longdouble.c new file mode 100644 index 0000000000..005b467398 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/cls_complex_struct_longdouble.c @@ -0,0 +1,10 @@ +/* Area: ffi_call, closure_call + Purpose: Check complex arguments in structs. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_longdouble.inc" +#include "cls_complex_struct.inc" diff --git a/native/libffi/testsuite/libffi.complex/cls_complex_va.inc b/native/libffi/testsuite/libffi.complex/cls_complex_va.inc new file mode 100644 index 0000000000..8a3e15f0f6 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/cls_complex_va.inc @@ -0,0 +1,80 @@ +/* -*-c-*- */ +#include "ffitest.h" +#include +#include +#include +#include + +static _Complex T_C_TYPE gComplexValue1 = 1 + 2 * I; +static _Complex T_C_TYPE gComplexValue2 = 3 + 4 * I; + +static int cls_variadic(const char *format, ...) +{ + va_list ap; + _Complex T_C_TYPE p1, p2; + + va_start (ap, format); + p1 = va_arg (ap, _Complex T_C_TYPE); + p2 = va_arg (ap, _Complex T_C_TYPE); + va_end (ap); + + return printf(format, T_CONV creal (p1), T_CONV cimag (p1), + T_CONV creal (p2), T_CONV cimag (p2)); +} + +static void +cls_complex_va_fn(ffi_cif* cif __UNUSED__, void* resp, + void** args, void* userdata __UNUSED__) +{ + char* format = *(char**)args[0]; + gComplexValue1 = *(_Complex T_C_TYPE*)args[1]; + gComplexValue2 = *(_Complex T_C_TYPE*)args[2]; + + *(ffi_arg*)resp = + printf(format, + T_CONV creal (gComplexValue1), T_CONV cimag (gComplexValue1), + T_CONV creal (gComplexValue2), T_CONV cimag (gComplexValue2)); +} + +int main (void) +{ + ffi_cif cif; + void *code; + ffi_closure *pcl = ffi_closure_alloc(sizeof(ffi_closure), &code); + void* args[4]; + ffi_type* arg_types[4]; + char *format = "%.1f,%.1fi %.1f,%.1fi\n"; + + _Complex T_C_TYPE complexArg1 = 1.0 + 22.0 *I; + _Complex T_C_TYPE complexArg2 = 333.0 + 4444.0 *I; + ffi_arg res = 0; + + arg_types[0] = &ffi_type_pointer; + arg_types[1] = &T_FFI_TYPE; + arg_types[2] = &T_FFI_TYPE; + arg_types[3] = NULL; + + /* This printf call is variadic */ + CHECK(ffi_prep_cif_var(&cif, FFI_DEFAULT_ABI, 1, 3, &ffi_type_sint, + arg_types) == FFI_OK); + + args[0] = &format; + args[1] = &complexArg1; + args[2] = &complexArg2; + args[3] = NULL; + + ffi_call(&cif, FFI_FN(cls_variadic), &res, args); + printf("res: %d\n", (int) res); + CHECK (res == 24); + + CHECK(ffi_prep_closure_loc(pcl, &cif, cls_complex_va_fn, NULL, code) + == FFI_OK); + + res = ((int(*)(char *, ...))(code))(format, complexArg1, complexArg2); + CHECK (gComplexValue1 == complexArg1); + CHECK (gComplexValue2 == complexArg2); + printf("res: %d\n", (int) res); + CHECK (res == 24); + + exit(0); +} diff --git a/native/libffi/testsuite/libffi.complex/cls_complex_va_double.c b/native/libffi/testsuite/libffi.complex/cls_complex_va_double.c new file mode 100644 index 0000000000..879ccf3b81 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/cls_complex_va_double.c @@ -0,0 +1,10 @@ +/* Area: ffi_call, closure_call + Purpose: Test complex' passed in variable argument lists. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_double.inc" +#include "cls_complex_va.inc" diff --git a/native/libffi/testsuite/libffi.complex/cls_complex_va_float.c b/native/libffi/testsuite/libffi.complex/cls_complex_va_float.c new file mode 100644 index 0000000000..2b17826045 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/cls_complex_va_float.c @@ -0,0 +1,16 @@ +/* Area: ffi_call, closure_call + Purpose: Test complex' passed in variable argument lists. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +/* Alpha splits _Complex into two arguments. It's illegal to pass + float through varargs, so _Complex float goes badly. In sort of + gets passed as _Complex double, but the compiler doesn't agree + with itself on this issue. */ +/* { dg-do run { xfail alpha*-*-* } } */ + +#include "complex_defs_float.inc" +#include "cls_complex_va.inc" diff --git a/native/libffi/testsuite/libffi.complex/cls_complex_va_longdouble.c b/native/libffi/testsuite/libffi.complex/cls_complex_va_longdouble.c new file mode 100644 index 0000000000..6eca9656ea --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/cls_complex_va_longdouble.c @@ -0,0 +1,10 @@ +/* Area: ffi_call, closure_call + Purpose: Test complex' passed in variable argument lists. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_longdouble.inc" +#include "cls_complex_va.inc" diff --git a/native/libffi/testsuite/libffi.complex/complex.exp b/native/libffi/testsuite/libffi.complex/complex.exp new file mode 100644 index 0000000000..4631db285a --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/complex.exp @@ -0,0 +1,36 @@ +# Copyright (C) 2003, 2006, 2009, 2010, 2014 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING3. If not see +# . + +dg-init +libffi-init + +global srcdir subdir + +set tlist [lsort [glob -nocomplain -- $srcdir/$subdir/*.{c,cc}]] + +if { [libffi_feature_test "#ifdef FFI_TARGET_HAS_COMPLEX_TYPE"] } { + run-many-tests $tlist "" +} else { + foreach test $tlist { + unsupported "$test" + } +} + +dg-finish + +# Local Variables: +# tcl-indent-level:4 +# End: diff --git a/native/libffi/testsuite/libffi.complex/complex.inc b/native/libffi/testsuite/libffi.complex/complex.inc new file mode 100644 index 0000000000..515ae3e60d --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/complex.inc @@ -0,0 +1,51 @@ +/* -*-c-*-*/ +#include "ffitest.h" +#include + +static _Complex T_C_TYPE f_complex(_Complex T_C_TYPE c, int x, int *py) +{ + c = -(2 * creal (c)) + (cimag (c) + 1)* I; + *py += x; + + return c; +} + +int main (void) +{ + ffi_cif cif; + ffi_type *args[MAX_ARGS]; + void *values[MAX_ARGS]; + + _Complex T_C_TYPE tc_arg; + _Complex T_C_TYPE tc_result; + int tc_int_arg_x; + int tc_y; + int *tc_ptr_arg_y = &tc_y; + + args[0] = &T_FFI_TYPE; + args[1] = &ffi_type_sint; + args[2] = &ffi_type_pointer; + values[0] = &tc_arg; + values[1] = &tc_int_arg_x; + values[2] = &tc_ptr_arg_y; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, + &T_FFI_TYPE, args) == FFI_OK); + + tc_arg = 1 + 7 * I; + tc_int_arg_x = 1234; + tc_y = 9876; + ffi_call(&cif, FFI_FN(f_complex), &tc_result, values); + + printf ("%f,%fi %f,%fi, x %d 1234, y %d 11110\n", + T_CONV creal (tc_result), T_CONV cimag (tc_result), + T_CONV creal (2.0), T_CONV creal (8.0), tc_int_arg_x, tc_y); + + CHECK (creal (tc_result) == -2); + CHECK (cimag (tc_result) == 8); + CHECK (tc_int_arg_x == 1234); + CHECK (*tc_ptr_arg_y == 11110); + + exit(0); +} diff --git a/native/libffi/testsuite/libffi.complex/complex_defs_double.inc b/native/libffi/testsuite/libffi.complex/complex_defs_double.inc new file mode 100644 index 0000000000..3583e166d6 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/complex_defs_double.inc @@ -0,0 +1,7 @@ +/* -*-c-*- */ +/* Complex base type. */ +#define T_FFI_TYPE ffi_type_complex_double +/* C type corresponding to the base type. */ +#define T_C_TYPE double +/* C cast for a value of type T_C_TYPE that is passed to printf. */ +#define T_CONV diff --git a/native/libffi/testsuite/libffi.complex/complex_defs_float.inc b/native/libffi/testsuite/libffi.complex/complex_defs_float.inc new file mode 100644 index 0000000000..bbd9375cbf --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/complex_defs_float.inc @@ -0,0 +1,7 @@ +/* -*-c-*- */ +/* Complex base type. */ +#define T_FFI_TYPE ffi_type_complex_float +/* C type corresponding to the base type. */ +#define T_C_TYPE float +/* C cast for a value of type T_C_TYPE that is passed to printf. */ +#define T_CONV (double) diff --git a/native/libffi/testsuite/libffi.complex/complex_defs_longdouble.inc b/native/libffi/testsuite/libffi.complex/complex_defs_longdouble.inc new file mode 100644 index 0000000000..14b9f243f4 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/complex_defs_longdouble.inc @@ -0,0 +1,7 @@ +/* -*-c-*- */ +/* Complex base type. */ +#define T_FFI_TYPE ffi_type_complex_longdouble +/* C type corresponding to the base type. */ +#define T_C_TYPE long double +/* C cast for a value of type T_C_TYPE that is passed to printf. */ +#define T_CONV diff --git a/native/libffi/testsuite/libffi.complex/complex_double.c b/native/libffi/testsuite/libffi.complex/complex_double.c new file mode 100644 index 0000000000..8a3297b2a2 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/complex_double.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check complex types. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_double.inc" +#include "complex.inc" diff --git a/native/libffi/testsuite/libffi.complex/complex_float.c b/native/libffi/testsuite/libffi.complex/complex_float.c new file mode 100644 index 0000000000..5044ebbcaa --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/complex_float.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check complex types. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_float.inc" +#include "complex.inc" diff --git a/native/libffi/testsuite/libffi.complex/complex_int.c b/native/libffi/testsuite/libffi.complex/complex_int.c new file mode 100644 index 0000000000..bac319081e --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/complex_int.c @@ -0,0 +1,86 @@ +/* Area: ffi_call + Purpose: Check non-standard complex types. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "ffitest.h" +#include "ffi.h" +#include + +_Complex int f_complex(_Complex int c, int x, int *py) +{ + __real__ c = -2 * __real__ c; + __imag__ c = __imag__ c + 1; + *py += x; + return c; +} + +/* + * This macro can be used to define new complex type descriptors + * in a platform independent way. + * + * name: Name of the new descriptor is ffi_type_complex_. + * type: The C base type of the complex type. + */ +#define FFI_COMPLEX_TYPEDEF(name, type, ffitype) \ + static ffi_type *ffi_elements_complex_##name [2] = { \ + (ffi_type *)(&ffitype), NULL \ + }; \ + struct struct_align_complex_##name { \ + char c; \ + _Complex type x; \ + }; \ + ffi_type ffi_type_complex_##name = { \ + sizeof(_Complex type), \ + offsetof(struct struct_align_complex_##name, x), \ + FFI_TYPE_COMPLEX, \ + (ffi_type **)ffi_elements_complex_##name \ + } + +/* Define new complex type descriptors using the macro: */ +/* ffi_type_complex_sint */ +FFI_COMPLEX_TYPEDEF(sint, int, ffi_type_sint); +/* ffi_type_complex_uchar */ +FFI_COMPLEX_TYPEDEF(uchar, unsigned char, ffi_type_uint8); + +int main (void) +{ + ffi_cif cif; + ffi_type *args[MAX_ARGS]; + void *values[MAX_ARGS]; + + _Complex int tc_arg; + _Complex int tc_result; + int tc_int_arg_x; + int tc_y; + int *tc_ptr_arg_y = &tc_y; + + args[0] = &ffi_type_complex_sint; + args[1] = &ffi_type_sint; + args[2] = &ffi_type_pointer; + values[0] = &tc_arg; + values[1] = &tc_int_arg_x; + values[2] = &tc_ptr_arg_y; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 3, &ffi_type_complex_sint, args) + == FFI_OK); + + tc_arg = 1 + 7 * I; + tc_int_arg_x = 1234; + tc_y = 9876; + ffi_call(&cif, FFI_FN(f_complex), &tc_result, values); + + printf ("%d,%di %d,%di, x %d 1234, y %d 11110\n", + (int)tc_result, (int)(tc_result * -I), 2, 8, tc_int_arg_x, tc_y); + /* dg-output "-2,8i 2,8i, x 1234 1234, y 11110 11110" */ + CHECK (creal (tc_result) == -2); + CHECK (cimag (tc_result) == 8); + CHECK (tc_int_arg_x == 1234); + CHECK (*tc_ptr_arg_y == 11110); + + exit(0); +} diff --git a/native/libffi/testsuite/libffi.complex/complex_longdouble.c b/native/libffi/testsuite/libffi.complex/complex_longdouble.c new file mode 100644 index 0000000000..7e78366093 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/complex_longdouble.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check complex types. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_longdouble.inc" +#include "complex.inc" diff --git a/native/libffi/testsuite/libffi.complex/ffitest.h b/native/libffi/testsuite/libffi.complex/ffitest.h new file mode 100644 index 0000000000..d27d362d6a --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/ffitest.h @@ -0,0 +1 @@ +#include "../libffi.call/ffitest.h" diff --git a/native/libffi/testsuite/libffi.complex/many_complex.inc b/native/libffi/testsuite/libffi.complex/many_complex.inc new file mode 100644 index 0000000000..e37a774397 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/many_complex.inc @@ -0,0 +1,78 @@ +/* -*-c-*- */ +#include "ffitest.h" + +#include +#include + +static _Complex T_C_TYPE many(_Complex T_C_TYPE c1, + _Complex T_C_TYPE c2, + _Complex T_C_TYPE c3, + _Complex T_C_TYPE c4, + _Complex T_C_TYPE c5, + _Complex T_C_TYPE c6, + _Complex T_C_TYPE c7, + _Complex T_C_TYPE c8, + _Complex T_C_TYPE c9, + _Complex T_C_TYPE c10, + _Complex T_C_TYPE c11, + _Complex T_C_TYPE c12, + _Complex T_C_TYPE c13) +{ + printf("0 :%f,%fi\n" + "1 :%f,%fi\n" + "2 :%f,%fi\n" + "3 :%f,%fi\n" + "4 :%f,%fi\n" + "5 :%f,%fi\n" + "6 :%f,%fi\n" + "7 :%f,%fi\n" + "8 :%f,%fi\n" + "9 :%f,%fi\n" + "10:%f,%fi\n" + "11:%f,%fi\n" + "12:%f,%fi\n", + T_CONV creal (c1), T_CONV cimag (c1), + T_CONV creal (c2), T_CONV cimag (c2), + T_CONV creal (c3), T_CONV cimag (c3), + T_CONV creal (c4), T_CONV cimag (c4), + T_CONV creal (c5), T_CONV cimag (c5), + T_CONV creal (c6), T_CONV cimag (c6), + T_CONV creal (c7), T_CONV cimag (c7), + T_CONV creal (c8), T_CONV cimag (c8), + T_CONV creal (c9), T_CONV cimag (c9), + T_CONV creal (c10), T_CONV cimag (c10), + T_CONV creal (c11), T_CONV cimag (c11), + T_CONV creal (c12), T_CONV cimag (c12), + T_CONV creal (c13), T_CONV cimag (c13)); + + return (c1+c2-c3-c4+c5+c6+c7-c8-c9-c10-c11+c12+c13); +} + +int main (void) +{ + ffi_cif cif; + ffi_type *args[13]; + void *values[13]; + _Complex T_C_TYPE ca[13]; + _Complex T_C_TYPE c, cc; + int i; + + for (i = 0; i < 13; i++) + { + args[i] = &T_FFI_TYPE; + values[i] = &ca[i]; + ca[i] = i + (-20 - i) * I; + } + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 13, &T_FFI_TYPE, args) == FFI_OK); + + ffi_call(&cif, FFI_FN(many), &c, values); + + cc = many(ca[0], ca[1], ca[2], ca[3], ca[4], ca[5], ca[6], ca[7], ca[8], + ca[9], ca[10], ca[11], ca[12]); + CHECK(creal (cc) == creal (c)); + CHECK(cimag (cc) == cimag (c)); + + exit(0); +} diff --git a/native/libffi/testsuite/libffi.complex/many_complex_double.c b/native/libffi/testsuite/libffi.complex/many_complex_double.c new file mode 100644 index 0000000000..3fd53c3354 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/many_complex_double.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex, with many arguments + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_double.inc" +#include "many_complex.inc" diff --git a/native/libffi/testsuite/libffi.complex/many_complex_float.c b/native/libffi/testsuite/libffi.complex/many_complex_float.c new file mode 100644 index 0000000000..c43d21cd9e --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/many_complex_float.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex, with many arguments + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_float.inc" +#include "many_complex.inc" diff --git a/native/libffi/testsuite/libffi.complex/many_complex_longdouble.c b/native/libffi/testsuite/libffi.complex/many_complex_longdouble.c new file mode 100644 index 0000000000..dbab723969 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/many_complex_longdouble.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex, with many arguments + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_longdouble.inc" +#include "many_complex.inc" diff --git a/native/libffi/testsuite/libffi.complex/return_complex.inc b/native/libffi/testsuite/libffi.complex/return_complex.inc new file mode 100644 index 0000000000..8bf0c1fbab --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/return_complex.inc @@ -0,0 +1,37 @@ +/* -*-c-*- */ +#include "ffitest.h" +#include + +static _Complex T_C_TYPE return_c(_Complex T_C_TYPE c) +{ + printf ("%f,%fi\n", T_CONV creal (c), T_CONV cimag (c)); + return 2 * c; +} +int main (void) +{ + ffi_cif cif; + ffi_type *args[MAX_ARGS]; + void *values[MAX_ARGS]; + _Complex T_C_TYPE c, rc, rc2; + T_C_TYPE cr, ci; + + args[0] = &T_FFI_TYPE; + values[0] = &c; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, + &T_FFI_TYPE, args) == FFI_OK); + + for (cr = -127.0; cr < 127; cr++) + { + ci = 1000.0 - cr; + c = cr + ci * I; + ffi_call(&cif, FFI_FN(return_c), &rc, values); + rc2 = return_c(c); + printf ("%f,%fi vs %f,%fi\n", + T_CONV creal (rc), T_CONV cimag (rc), + T_CONV creal (rc2), T_CONV cimag (rc2)); + CHECK(rc == 2 * c); + } + exit(0); +} diff --git a/native/libffi/testsuite/libffi.complex/return_complex1.inc b/native/libffi/testsuite/libffi.complex/return_complex1.inc new file mode 100644 index 0000000000..7cecc0fefa --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/return_complex1.inc @@ -0,0 +1,41 @@ +/* -*-c-*- */ +#include "ffitest.h" +#include + +static _Complex T_C_TYPE return_c(_Complex T_C_TYPE c1, float fl2, unsigned int in3, _Complex T_C_TYPE c4) +{ + return c1 + fl2 + in3 + c4; +} +int main (void) +{ + ffi_cif cif; + ffi_type *args[MAX_ARGS]; + void *values[MAX_ARGS]; + _Complex T_C_TYPE c1, c4, rc, rc2; + float fl2; + unsigned int in3; + args[0] = &T_FFI_TYPE; + args[1] = &ffi_type_float; + args[2] = &ffi_type_uint; + args[3] = &T_FFI_TYPE; + values[0] = &c1; + values[1] = &fl2; + values[2] = &in3; + values[3] = &c4; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, + &T_FFI_TYPE, args) == FFI_OK); + c1 = 127.0 + 255.0 * I; + fl2 = 128.0; + in3 = 255; + c4 = 512.7 + 1024.1 * I; + + ffi_call(&cif, FFI_FN(return_c), &rc, values); + rc2 = return_c(c1, fl2, in3, c4); + printf ("%f,%fi vs %f,%fi\n", + T_CONV creal (rc), T_CONV cimag (rc), + T_CONV creal (rc2), T_CONV cimag (rc2)); + CHECK(rc == rc2); + exit(0); +} diff --git a/native/libffi/testsuite/libffi.complex/return_complex1_double.c b/native/libffi/testsuite/libffi.complex/return_complex1_double.c new file mode 100644 index 0000000000..727410d563 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/return_complex1_double.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_double.inc" +#include "return_complex1.inc" diff --git a/native/libffi/testsuite/libffi.complex/return_complex1_float.c b/native/libffi/testsuite/libffi.complex/return_complex1_float.c new file mode 100644 index 0000000000..a2aeada847 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/return_complex1_float.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_float.inc" +#include "return_complex1.inc" diff --git a/native/libffi/testsuite/libffi.complex/return_complex1_longdouble.c b/native/libffi/testsuite/libffi.complex/return_complex1_longdouble.c new file mode 100644 index 0000000000..103504bf64 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/return_complex1_longdouble.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_longdouble.inc" +#include "return_complex1.inc" diff --git a/native/libffi/testsuite/libffi.complex/return_complex2.inc b/native/libffi/testsuite/libffi.complex/return_complex2.inc new file mode 100644 index 0000000000..265170bf71 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/return_complex2.inc @@ -0,0 +1,44 @@ +/* -*-c-*- */ +#include "ffitest.h" +#include + +_Complex T_C_TYPE +return_c(_Complex T_C_TYPE c1, _Complex T_C_TYPE c2, + unsigned int in3, _Complex T_C_TYPE c4) +{ + volatile _Complex T_C_TYPE r = c1 + c2 + in3 + c4; + return r; +} + +int main (void) +{ + ffi_cif cif; + ffi_type *args[MAX_ARGS]; + void *values[MAX_ARGS]; + _Complex T_C_TYPE c1, c2, c4, rc, rc2; + unsigned int in3; + args[0] = &T_FFI_TYPE; + args[1] = &T_FFI_TYPE; + args[2] = &ffi_type_uint; + args[3] = &T_FFI_TYPE; + values[0] = &c1; + values[1] = &c2; + values[2] = &in3; + values[3] = &c4; + + /* Initialize the cif */ + CHECK(ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 4, + &T_FFI_TYPE, args) == FFI_OK); + c1 = 127.0 + 255.0 * I; + c2 = 128.0 + 256.0; + in3 = 255; + c4 = 512.7 + 1024.1 * I; + + ffi_call(&cif, FFI_FN(return_c), &rc, values); + rc2 = return_c(c1, c2, in3, c4); + printf ("%f,%fi vs %f,%fi\n", + T_CONV creal (rc), T_CONV cimag (rc), + T_CONV creal (rc2), T_CONV cimag (rc2)); + CHECK(rc == rc2); + exit(0); +} diff --git a/native/libffi/testsuite/libffi.complex/return_complex2_double.c b/native/libffi/testsuite/libffi.complex/return_complex2_double.c new file mode 100644 index 0000000000..ab9efacb4a --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/return_complex2_double.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_double.inc" +#include "return_complex2.inc" diff --git a/native/libffi/testsuite/libffi.complex/return_complex2_float.c b/native/libffi/testsuite/libffi.complex/return_complex2_float.c new file mode 100644 index 0000000000..d7f22c2a0c --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/return_complex2_float.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_float.inc" +#include "return_complex2.inc" diff --git a/native/libffi/testsuite/libffi.complex/return_complex2_longdouble.c b/native/libffi/testsuite/libffi.complex/return_complex2_longdouble.c new file mode 100644 index 0000000000..3edea629df --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/return_complex2_longdouble.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_longdouble.inc" +#include "return_complex2.inc" diff --git a/native/libffi/testsuite/libffi.complex/return_complex_double.c b/native/libffi/testsuite/libffi.complex/return_complex_double.c new file mode 100644 index 0000000000..e2497cc84a --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/return_complex_double.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_double.inc" +#include "return_complex.inc" diff --git a/native/libffi/testsuite/libffi.complex/return_complex_float.c b/native/libffi/testsuite/libffi.complex/return_complex_float.c new file mode 100644 index 0000000000..a35528ff93 --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/return_complex_float.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_float.inc" +#include "return_complex.inc" diff --git a/native/libffi/testsuite/libffi.complex/return_complex_longdouble.c b/native/libffi/testsuite/libffi.complex/return_complex_longdouble.c new file mode 100644 index 0000000000..142d7becba --- /dev/null +++ b/native/libffi/testsuite/libffi.complex/return_complex_longdouble.c @@ -0,0 +1,10 @@ +/* Area: ffi_call + Purpose: Check return value complex. + Limitations: none. + PR: none. + Originator: . */ + +/* { dg-do run } */ + +#include "complex_defs_longdouble.inc" +#include "return_complex.inc" diff --git a/native/libffi/testsuite/libffi.go/aa-direct.c b/native/libffi/testsuite/libffi.go/aa-direct.c new file mode 100644 index 0000000000..b00c404ab3 --- /dev/null +++ b/native/libffi/testsuite/libffi.go/aa-direct.c @@ -0,0 +1,34 @@ +/* { dg-do run } */ + +#include "static-chain.h" + +#if defined(__GNUC__) && !defined(__clang__) && defined(STATIC_CHAIN_REG) + +#include "ffitest.h" + +/* Blatent assumption here that the prologue doesn't clobber the + static chain for trivial functions. If this is not true, don't + define STATIC_CHAIN_REG, and we'll test what we can via other tests. */ +void *doit(void) +{ + register void *chain __asm__(STATIC_CHAIN_REG); + return chain; +} + +int main() +{ + ffi_cif cif; + void *result; + + CHECK(ffi_prep_cif(&cif, ABI_NUM, 0, &ffi_type_pointer, NULL) == FFI_OK); + + ffi_call_go(&cif, FFI_FN(doit), &result, NULL, &result); + + CHECK(result == &result); + + return 0; +} + +#else /* UNSUPPORTED */ +int main() { return 0; } +#endif diff --git a/native/libffi/testsuite/libffi.go/closure1.c b/native/libffi/testsuite/libffi.go/closure1.c new file mode 100644 index 0000000000..7b34afc88c --- /dev/null +++ b/native/libffi/testsuite/libffi.go/closure1.c @@ -0,0 +1,28 @@ +/* { dg-do run } */ + +#include "ffitest.h" + +void doit(ffi_cif *cif, void *rvalue, void **avalue, void *closure) +{ + (void)cif; + (void)avalue; + *(void **)rvalue = closure; +} + +typedef void * (*FN)(void); + +int main() +{ + ffi_cif cif; + ffi_go_closure cl; + void *result; + + CHECK(ffi_prep_cif(&cif, ABI_NUM, 0, &ffi_type_pointer, NULL) == FFI_OK); + CHECK(ffi_prep_go_closure(&cl, &cif, doit) == FFI_OK); + + ffi_call_go(&cif, FFI_FN(*(FN *)&cl), &result, NULL, &cl); + + CHECK(result == &cl); + + exit(0); +} diff --git a/native/libffi/testsuite/libffi.go/ffitest.h b/native/libffi/testsuite/libffi.go/ffitest.h new file mode 100644 index 0000000000..d27d362d6a --- /dev/null +++ b/native/libffi/testsuite/libffi.go/ffitest.h @@ -0,0 +1 @@ +#include "../libffi.call/ffitest.h" diff --git a/native/libffi/testsuite/libffi.go/go.exp b/native/libffi/testsuite/libffi.go/go.exp new file mode 100644 index 0000000000..100c5e75b4 --- /dev/null +++ b/native/libffi/testsuite/libffi.go/go.exp @@ -0,0 +1,36 @@ +# Copyright (C) 2003, 2006, 2009, 2010, 2014 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; see the file COPYING3. If not see +# . + +dg-init +libffi-init + +global srcdir subdir + +set tlist [lsort [glob -nocomplain -- $srcdir/$subdir/*.{c,cc}]] + +if { [libffi_feature_test "#ifdef FFI_GO_CLOSURES"] } { + run-many-tests $tlist "" +} else { + foreach test $tlist { + unsupported "$test" + } +} + +dg-finish + +# Local Variables: +# tcl-indent-level:4 +# End: diff --git a/native/libffi/testsuite/libffi.go/static-chain.h b/native/libffi/testsuite/libffi.go/static-chain.h new file mode 100644 index 0000000000..3675b40a54 --- /dev/null +++ b/native/libffi/testsuite/libffi.go/static-chain.h @@ -0,0 +1,19 @@ +#ifdef __aarch64__ +# define STATIC_CHAIN_REG "x18" +#elif defined(__alpha__) +# define STATIC_CHAIN_REG "$1" +#elif defined(__arm__) +# define STATIC_CHAIN_REG "ip" +#elif defined(__sparc__) +# if defined(__arch64__) || defined(__sparcv9) +# define STATIC_CHAIN_REG "g5" +# else +# define STATIC_CHAIN_REG "g2" +# endif +#elif defined(__x86_64__) +# define STATIC_CHAIN_REG "r10" +#elif defined(__i386__) +# ifndef ABI_NUM +# define STATIC_CHAIN_REG "ecx" /* FFI_DEFAULT_ABI only */ +# endif +#endif