Compare commits

...

5 Commits

Author SHA1 Message Date
Steve Dower
35a5081d07 Import libffi master 2019-10-11 10:42:20 -07:00
Paul Monson
82244f9715 Add support for Windows ARM32 in libffi (#9) 2019-04-17 13:49:13 -07:00
Steve Dower
d160812995 Make even more things binary 2019-03-29 11:06:34 -07:00
Steve Dower
68f488bcf4 Add attributes 2019-03-29 10:38:46 -07:00
Paul Monson
ed22026f39 Reconfigure libffi headers (#10) 2019-03-07 10:19:25 -08:00
39 changed files with 1541 additions and 216 deletions

View File

@@ -8,9 +8,12 @@ shallow_clone: true
# 32- and 64-bit clang/mingw
# and perhaps more.
image: Visual Studio 2013
image: Visual Studio 2017
platform:
- x64
- x86
- arm
- arm64
environment:
global:
@@ -18,30 +21,48 @@ environment:
CYG_CACHE: C:/cygwin/var/cache/setup
CYG_MIRROR: http://mirrors.kernel.org/sourceware/cygwin/
matrix:
- VSVER: 12
- VSVER: 15
install:
- ps: >-
If ($env:Platform -Match "x86") {
$env:VCVARS_PLATFORM="x86"
$env:BUILD="x86-pc-cygwin"
$env:HOST="x86-pc-windows"
$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\vcvarsall.bat" %VCVARS_PLATFORM%
- 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='/cygdrive/c/projects/libffi/msvcc.sh -m64' CXX='/cygdrive/c/projects/libffi/msvcc.sh -m64' 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/x86/ffitarget.h include; make; find .;)"
- 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`)"
# FIXME: "make check" currently fails. It just looks like msvcc needs

4
.gitattributes vendored Normal file
View File

@@ -0,0 +1,4 @@
* text=auto
*.sln text eol=crlf
*.vcxproj* text eol=crlf

4
.gitignore vendored
View File

@@ -36,3 +36,7 @@ build_*/
darwin_*/
src/arm/trampoline.S
**/texinfo.tex
x86_64-w64-cygwin
i686-pc-cygwin
arm-w32-cygwin

View File

@@ -10,7 +10,16 @@ function build_linux()
make
make dist
make check RUNTESTFLAGS="-a $RUNTESTFLAGS"
cat */testsuite/libffi.log
gzip -c -9 */testsuite/libffi.log > libffi.log.gz
echo ================================================================
echo The logs are too long for travis to handle, so we compress and
echo uuencode them. Download, decode and uncompress if you need to
echo read them.
echo ================================================================
uuencode libffi.log.gz -
echo ================================================================
echo ================================================================
}
function build_ios()

View File

@@ -8,14 +8,17 @@ if [[ $TRAVIS_OS_NAME != 'linux' ]]; then
brew install libtool dejagnu;
else
sudo apt-get update
sudo apt-get install dejagnu texinfo
sudo apt-get install dejagnu texinfo sharutils
case "$HOST" in
i386-pc-linux-gnu)
sudo apt-get install gcc-multilib g++-multilib
;;
moxie-elf)
echo 'deb http://repos.moxielogic.org:7114/MoxieLogic moxiedev main' | sudo tee -a /etc/apt/sources.list
sudo apt-get update -qq
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
# debug...
curl https://repos.moxielogic.org:7114/MoxieLogic/dists/moxiedev/main/binary-amd64/Packages
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
;;
esac

View File

@@ -79,9 +79,11 @@ noinst_HEADERS = \
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 \

View File

@@ -51,11 +51,13 @@ tested:
| --------------- | ---------------- | ----------------------- |
| 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 |
| HPPA | HPUX | GCC |
@@ -168,6 +170,11 @@ 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.
@@ -194,9 +201,11 @@ See the git log for details at http://github.com/libffi/libffi.
Add RISC-V support.
New API in support of GO closures.
Default to Microsoft's 64 bit long double ABI with Visual C++.
GNU compiler uses 80 bits (128 in memory) FFI_GNUW64 ABI.
Many new tests cases and bug fixes.
GNU compiler uses 80 bits (128 in memory) FFI_GNUW64 ABI.
Many new tests cases and bug fixes.
Add windows on arm64 (WOA) support.
Add Windows 32-bit arm support.
3.2.1 Nov-12-14
Build fix for non-iOS AArch64 targets.

View File

@@ -6,6 +6,11 @@
# 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
MSVC=1
;;
aarch64*-*-*)
TARGET=AARCH64; TARGETDIR=aarch64
SOURCES="ffi.c sysv.S"
@@ -23,6 +28,11 @@ case "${host}" in
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"
@@ -74,12 +84,6 @@ case "${host}" in
fi
if test "${ax_cv_c_compiler_vendor}" = "microsoft"; then
MSVC=1
if test $ac_cv_sizeof_size_t = 4; then
# libffi does not support microsoft tools for 32-bit windows
# hosts. Try porting src/x86/sysv.S to intel assembly
# format.
UNSUPPORTED=1
fi
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
@@ -248,6 +252,12 @@ esac
# ... but some of the cases above share configury.
case "${TARGET}" in
ARM_WIN32)
SOURCES="ffi.c sysv_msvc_arm32.S"
;;
ARM_WIN64)
SOURCES="ffi.c win64_armasm.S"
;;
MIPS)
SOURCES="ffi.c o32.S n32.S"
;;
@@ -265,7 +275,11 @@ case "${TARGET}" in
SOURCES="ffi.c ffi_sysv.c sysv.S ppc_closure.S"
;;
X86 | X86_DARWIN | X86_FREEBSD | X86_WIN32)
SOURCES="ffi.c sysv.S"
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

View File

@@ -283,11 +283,13 @@ FFI_API size_t ffi_raw_size (ffi_cif *cif);
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);
#endif
FFI_API
void ffi_java_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_java_raw *raw);
@@ -414,6 +416,7 @@ ffi_prep_raw_closure_loc (ffi_raw_closure*,
void *user_data,
void *codeloc);
#if !FFI_NATIVE_RAW_API
FFI_API ffi_status
ffi_prep_java_raw_closure (ffi_java_raw_closure*,
ffi_cif *cif,
@@ -426,6 +429,7 @@ ffi_prep_java_raw_closure_loc (ffi_java_raw_closure*,
void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*),
void *user_data,
void *codeloc);
#endif
#endif /* FFI_CLOSURES */

View File

@@ -99,6 +99,10 @@ ffi_status ffi_prep_cif_core(ffi_cif *cif,
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
{

View File

@@ -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])
])

View File

@@ -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

View File

@@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{115502C0-BE05-4767-BF19-5C87D805FAD6}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>FfistaticLib</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
<ProjectName>Ffi_staticLib_arm64</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>FFI_BUILDING_DLL;_DEBUG;_LIB;USE_DL_PREFIX;ARM64;_M_ARM64;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..\..\include;.\aarch64_include;..\..\src\aarch64;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<IgnoreStandardIncludePath>false</IgnoreStandardIncludePath>
<BrowseInformation>true</BrowseInformation>
<OmitFramePointers>
</OmitFramePointers>
<WholeProgramOptimization>false</WholeProgramOptimization>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>FFI_BUILDING_DLL;USE_DL_PREFIX;ARM64;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>..\..\include;.\aarch64_include;..\..\src\aarch64;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<OmitFramePointers>true</OmitFramePointers>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<AdditionalUsingDirectories>..\..\src;..\..\src\aarch64;%(AdditionalUsingDirectories)</AdditionalUsingDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<ProjectReference>
<LinkLibraryDependencies>true</LinkLibraryDependencies>
</ProjectReference>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include=".\aarch64_include\ffi.h" />
<ClInclude Include=".\aarch64_include\fficonfig.h" />
<ClInclude Include="..\..\src\aarch64\ffitarget.h" />
<ClInclude Include="..\include\ffi_cfi.h" />
<ClInclude Include="..\include\ffi_common.h" />
<ClInclude Include="..\..\src\aarch64\internal.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\closures.c" />
<ClCompile Include="..\..\src\dlmalloc.c" />
<ClCompile Include="..\..\src\aarch64\ffi.c" />
<ClCompile Include="..\..\src\prep_cif.c" />
<ClCompile Include="..\..\src\types.c" />
</ItemGroup>
<!--ItemGroup>
<Object Include="..\..\..\..\Downloads\libffi-master-win64\src\aarch64\win64_armasm.obj" />
</ItemGroup-->
<ItemGroup>
<CustomBuild Include="..\..\src\aarch64\win64_armasm.S">
<!--ExcludedFromBuild Condition="'$(Platform)'!='ARM64'">true</ExcludedFromBuild -->
<Command>
cl /FA /EP /nologo /I"..\..\include" /I".\aarch64_include" /I"..\..\src\aarch64" "%(FullPath)" &gt; $(IntDir)win64_armasm.i
armasm64 $(IntDir)win64_armasm.i /I"src\" /I"..\..\include" /I"..\..\src\aarch64" -o "$(IntDir)win64_armasm.obj"
</Command>
<Outputs>win64_armasm.obj;%(Outputs)</Outputs>
</CustomBuild>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\include\ffi.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\ffi_cfi.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\ffi_common.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\fficonfig.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\ffitarget.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\include\internal.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="src\closures.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\dlmalloc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\ffi.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\prep_cif.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="src\types.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="src\win64_armasm.S" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>

View File

@@ -49,26 +49,9 @@ extern "C" {
#endif
/* Specify which architecture libffi is configured for. */
/* --- Begin CPython patch ---
ZCW: This is patched by us to avoid having to keep two mostly-identical files.
#ifndef X86_WIN32
#define X86_WIN32
#ifndef AARCH64
#define AARCH64
#endif
*/
#ifdef _MSC_VER
#ifdef _WIN64
# ifndef X86_WIN64
# define X86_WIN64
# endif
#else
# ifndef X86_WIN32
# define X86_WIN32
# endif
#endif
#endif /* _MSC_VER */
/* --- End CPython patch --- */
/* ---- System configuration information --------------------------------- */
@@ -134,10 +117,8 @@ typedef struct _ffi_type
#if defined _MSC_VER
# if defined FFI_BUILDING_DLL /* Building libffi.DLL with msvcc.sh */
# define FFI_API __declspec(dllexport)
#error FFI_BUILDING_DLL should not be defined
# elif !defined FFI_BUILDING /* Importing libffi.DLL */
# define FFI_API __declspec(dllimport)
#error FFI_BUILDING should be defined
# else /* Building/linking static library */
# define FFI_API
# endif
@@ -216,7 +197,7 @@ FFI_EXTERN ffi_type ffi_type_float;
FFI_EXTERN ffi_type ffi_type_double;
FFI_EXTERN ffi_type ffi_type_pointer;
#if 1
#ifndef _M_ARM64
FFI_EXTERN ffi_type ffi_type_longdouble;
#else
#define ffi_type_longdouble ffi_type_double
@@ -503,7 +484,7 @@ ffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type,
#define FFI_TYPE_INT 1
#define FFI_TYPE_FLOAT 2
#define FFI_TYPE_DOUBLE 3
#if 1
#ifndef _M_ARM64
#define FFI_TYPE_LONGDOUBLE 4
#else
#define FFI_TYPE_LONGDOUBLE FFI_TYPE_DOUBLE
@@ -519,9 +500,9 @@ ffi_status ffi_get_struct_offsets (ffi_abi abi, ffi_type *struct_type,
#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
#define FFI_TYPE_LAST FFI_TYPE_COMPLEX
#ifdef __cplusplus
}

View File

@@ -1,14 +1,6 @@
/* fficonfig.h. Originally created by configure, now hand_maintained for MSVC. */
/* fficonfig.h. Generated from fficonfig.h.in by configure. */
/* fficonfig.h.in. Generated from configure.ac by autoheader. */
/* Define this for MSVC, but not for mingw32! */
#ifdef _MSC_VER
#define __attribute__(x) /* */
#endif
#define alloca _alloca
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
@@ -21,10 +13,7 @@
/* #undef C_ALLOCA */
/* Define to the flags needed for the .section .eh_frame directive. */
/* #undef EH_FRAME_FLAGS */
/* using static library */
#define FFI_BUILDING 1
#define EH_FRAME_FLAGS "a"
/* Define this if you want extra debugging. */
/* #undef FFI_DEBUG */
@@ -49,10 +38,10 @@
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
*/
/* #undef HAVE_ALLOCA_H */
/*#define HAVE_ALLOCA_H 1 */
/* Define if your assembler supports .cfi_* directives. */
/* #undef HAVE_AS_CFI_PSEUDO_OP */
#define HAVE_AS_CFI_PSEUDO_OP 1
/* Define if your assembler supports .register. */
/* #undef HAVE_AS_REGISTER_PSEUDO_OP */
@@ -68,26 +57,23 @@
/* #undef HAVE_AS_X86_64_UNWIND_SECTION_TYPE */
/* Define if your assembler supports PC relative relocs. */
#define HAVE_AS_X86_PCREL 1
/* #undef HAVE_AS_X86_PCREL */
/* Define to 1 if you have the <dlfcn.h> header file. */
/* #undef HAVE_DLFCN_H */
#define HAVE_DLFCN_H 1
/* Define if __attribute__((visibility("hidden"))) is supported. */
/* #undef HAVE_HIDDEN_VISIBILITY_ATTRIBUTE */
#define HAVE_HIDDEN_VISIBILITY_ATTRIBUTE 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define if you have the long double type and it is bigger than a double */
/* #undef HAVE_LONG_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 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Define to 1 if you have the `memcpy' function. */
#define HAVE_MEMCPY 1
@@ -95,37 +81,37 @@
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `mkostemp' function. */
/* #undef HAVE_MKOSTEMP */
#define HAVE_MKOSTEMP 1
/* Define to 1 if you have the `mmap' function. */
/* #undef HAVE_MMAP */
#define HAVE_MMAP 1
/* Define if mmap with MAP_ANON(YMOUS) works. */
/* #undef HAVE_MMAP_ANON */
#define HAVE_MMAP_ANON 1
/* Define if mmap of /dev/zero works. */
/* #undef HAVE_MMAP_DEV_ZERO */
#define HAVE_MMAP_DEV_ZERO 1
/* Define if read-only mmap of a plain file works. */
/* #undef HAVE_MMAP_FILE */
#define HAVE_MMAP_FILE 1
/* Define if .eh_frame sections should be read-only. */
/* #undef HAVE_RO_EH_FRAME */
#define HAVE_RO_EH_FRAME 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
//#define HAVE_STDLIB_H 0
#define LACKS_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
/* #undef HAVE_STRINGS_H */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/mman.h> header file. */
/* #undef HAVE_SYS_MMAN_H */
#define HAVE_SYS_MMAN_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
@@ -134,14 +120,18 @@
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
/* #undef HAVE_UNISTD_H */
#define HAVE_UNISTD_H 1
/* Define to 1 if GNU symbol versioning is used for libatomic. */
/* #undef LIBFFI_GNU_SYMBOL_VERSIONING */
#define LIBFFI_GNU_SYMBOL_VERSIONING 1
/* Define to the sub-directory where libtool stores uninstalled libraries. */
/* 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"
@@ -167,10 +157,7 @@
#define SIZEOF_DOUBLE 8
/* The size of `long double', as computed by sizeof. */
#define SIZEOF_LONG_DOUBLE 12
/* Define if you have the long double type and it is bigger than a double */
#define HAVE_LONG_DOUBLE 1
#define SIZEOF_LONG_DOUBLE 8
/* The size of `size_t', as computed by sizeof. */
#define SIZEOF_SIZE_T 8

View File

@@ -60,7 +60,7 @@ do
case $1
in
--verbose)
$verbose=1
verbose=1
shift 1
;;
--version)
@@ -80,6 +80,16 @@ do
safeseh=
shift 1
;;
-marm)
ml='armasm'
safeseh=
shift 1
;;
-marm64)
ml='armasm64'
safeseh=
shift 1
;;
-clang-cl)
cl="clang-cl"
shift 1
@@ -237,6 +247,7 @@ do
else
output="-Fe$2"
fi
armasm_output="-o $2"
if [ -n "$assembly" ]; then
args="$args $output"
else
@@ -289,13 +300,27 @@ if [ -n "$assembly" ]; then
fi
ppsrc="$outdir/$(basename $src|sed 's/.S$/.asm/g')"
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 $?
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"

View File

@@ -19,6 +19,7 @@ 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 <stdio.h>
#include <stdlib.h>
#include <stdint.h>
@@ -26,6 +27,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include <ffi.h>
#include <ffi_common.h>
#include "internal.h"
#ifdef _M_ARM64
#include <windows.h> /* FlushInstructionCache */
#endif
/* Force FFI_TYPE_LONGDOUBLE to be different than FFI_TYPE_DOUBLE;
all further uses in this file will refer to the 128-bit type. */
@@ -74,6 +78,8 @@ ffi_clear_cache (void *start, void *end)
sys_icache_invalidate (start, (char *)end - (char *)start);
#elif defined (__GNUC__)
__builtin___clear_cache (start, end);
#elif defined (_M_ARM64)
FlushInstructionCache(GetCurrentProcess(), start, (char*)end - (char*)start);
#else
#error "Missing builtin to flush instruction cache"
#endif
@@ -315,6 +321,9 @@ extend_integer_type (void *source, int type)
}
}
#if defined(_MSC_VER)
void extend_hfa_type (void *dest, void *src, int h);
#else
static void
extend_hfa_type (void *dest, void *src, int h)
{
@@ -368,7 +377,11 @@ extend_hfa_type (void *dest, void *src, int h)
: "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)
{
@@ -437,6 +450,7 @@ compress_hfa_type (void *dest, void *reg, int h)
}
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
@@ -454,7 +468,7 @@ allocate_int_to_reg_or_stack (struct call_context *context,
return allocate_to_stack (state, stack, size, size);
}
ffi_status
ffi_status FFI_HIDDEN
ffi_prep_cif_machdep (ffi_cif *cif)
{
ffi_type *rtype = cif->rtype;
@@ -539,9 +553,9 @@ ffi_prep_cif_machdep (ffi_cif *cif)
#if defined (__APPLE__)
/* Perform Apple-specific 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)
{
ffi_status status = ffi_prep_cif_machdep (cif);
cif->aarch64_nfixedargs = nfixedargs;
@@ -588,8 +602,8 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue,
/* Allocate consectutive stack for everything we'll need. */
context = alloca (sizeof(struct call_context) + stack_bytes + 32 + rsize);
stack = context + 1;
frame = stack + stack_bytes;
rvalue = (rsize ? frame + 32 : orig_rvalue);
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++)
@@ -651,6 +665,22 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue,
if (h)
{
int elems = 4 - (h & 3);
#ifdef _M_ARM64 /* for handling armasm calling convention */
if (cif->is_variadic)
{
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
{
#endif /* for handling armasm calling convention */
if (state.nsrn + elems <= N_V_ARG_REG)
{
dest = &context->v[state.nsrn];
@@ -660,6 +690,9 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue,
}
state.nsrn = N_V_ARG_REG;
dest = allocate_to_stack (&state, stack, ty->alignment, s);
#ifdef _M_ARM64 /* for handling armasm calling convention */
}
#endif /* for handling armasm calling convention */
}
else if (s > 16)
{
@@ -681,7 +714,7 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *orig_rvalue,
X registers, then the argument is copied into
consecutive X registers. */
dest = &context->x[state.ngrn];
state.ngrn += n;
state.ngrn += (unsigned int)n;
}
else
{
@@ -773,6 +806,16 @@ ffi_prep_closure_loc (ffi_closure *closure,
*(UINT64 *)(tramp + 16) = (uintptr_t)start;
ffi_clear_cache(tramp, tramp + FFI_TRAMPOLINE_SIZE);
/* Also flush the cache for code mapping. */
#ifdef _M_ARM64
// 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;
@@ -871,55 +914,78 @@ ffi_closure_SYSV_inner (ffi_cif *cif,
if (h)
{
n = 4 - (h & 3);
if (state.nsrn + n <= N_V_ARG_REG)
{
void *reg = &context->v[state.nsrn];
state.nsrn += n;
#ifdef _M_ARM64 /* 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 _M_ARM64 /* 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 *));
}
else
{
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;
/* 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.nsrn = N_V_ARG_REG;
avalue[i] = allocate_to_stack (&state, stack,
ty->alignment, s);
}
}
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 *));
}
else
{
n = (s + 7) / 8;
if (state.ngrn + n <= N_X_ARG_REG)
{
avalue[i] = &context->x[state.ngrn];
state.ngrn += n;
}
else
{
state.ngrn = N_X_ARG_REG;
avalue[i] = allocate_to_stack (&state, stack,
ty->alignment, s);
}
}
break;
default:
abort();
}
default:
abort();
}
#if defined (__APPLE__)
if (i + 1 == cif->aarch64_nfixedargs)
@@ -939,3 +1005,5 @@ ffi_closure_SYSV_inner (ffi_cif *cif,
return flags;
}
#endif /* (__aarch64__) || defined(__arm64__)|| defined (_M_ARM64)*/

View File

@@ -32,6 +32,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
#define FFI_SIZEOF_JAVA_RAW 4
typedef unsigned long long ffi_arg;
typedef signed long long ffi_sarg;
#elif defined(_M_ARM64)
#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;
@@ -65,17 +69,24 @@ typedef enum ffi_abi
#define FFI_TRAMPOLINE_CLOSURE_OFFSET FFI_TRAMPOLINE_SIZE
#endif
#ifdef _M_ARM64
#define FFI_EXTRA_CIF_FIELDS unsigned is_variadic
#endif
/* ---- Internal ---- */
#if defined (__APPLE__)
#define FFI_TARGET_SPECIFIC_VARIADIC
#define FFI_EXTRA_CIF_FIELDS unsigned aarch64_nfixedargs
#else
/* iOS reserves x18 for the system. Disable Go closures until
#elif !defined(_M_ARM64)
/* 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 _M_ARM64
/* No complex type on Windows */
#define FFI_TARGET_HAS_COMPLEX_TYPE
#endif
#endif

View File

@@ -19,6 +19,7 @@ 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 <fficonfig.h>
#include <ffi.h>
@@ -198,9 +199,9 @@ CNAME(ffi_call_SYSV):
cfi_endproc
.globl CNAME(ffi_call_SYSV)
FFI_HIDDEN(CNAME(ffi_call_SYSV))
#ifdef __ELF__
.type CNAME(ffi_call_SYSV), #function
.hidden CNAME(ffi_call_SYSV)
.size CNAME(ffi_call_SYSV), .-CNAME(ffi_call_SYSV)
#endif
@@ -237,9 +238,9 @@ CNAME(ffi_closure_SYSV_V):
cfi_endproc
.globl CNAME(ffi_closure_SYSV_V)
FFI_HIDDEN(CNAME(ffi_closure_SYSV_V))
#ifdef __ELF__
.type CNAME(ffi_closure_SYSV_V), #function
.hidden CNAME(ffi_closure_SYSV_V)
.size CNAME(ffi_closure_SYSV_V), . - CNAME(ffi_closure_SYSV_V)
#endif
@@ -349,9 +350,9 @@ CNAME(ffi_closure_SYSV):
cfi_endproc
.globl CNAME(ffi_closure_SYSV)
FFI_HIDDEN(CNAME(ffi_closure_SYSV))
#ifdef __ELF__
.type CNAME(ffi_closure_SYSV), #function
.hidden CNAME(ffi_closure_SYSV)
.size CNAME(ffi_closure_SYSV), . - CNAME(ffi_closure_SYSV)
#endif
@@ -369,9 +370,9 @@ CNAME(ffi_closure_trampoline_table_page):
.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
.hidden CNAME(ffi_closure_trampoline_table_page)
.size CNAME(ffi_closure_trampoline_table_page), . - CNAME(ffi_closure_trampoline_table_page)
#endif
#endif
@@ -396,9 +397,9 @@ CNAME(ffi_go_closure_SYSV_V):
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
.hidden CNAME(ffi_go_closure_SYSV_V)
.size CNAME(ffi_go_closure_SYSV_V), . - CNAME(ffi_go_closure_SYSV_V)
#endif
@@ -425,12 +426,13 @@ CNAME(ffi_go_closure_SYSV):
cfi_endproc
.globl CNAME(ffi_go_closure_SYSV)
FFI_HIDDEN(CNAME(ffi_go_closure_SYSV))
#ifdef __ELF__
.type CNAME(ffi_go_closure_SYSV), #function
.hidden CNAME(ffi_go_closure_SYSV)
.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

506
src/aarch64/win64_armasm.S Normal file
View File

@@ -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 <fficonfig.h>
#include <ffi.h>
#include <ffi_cfi.h>
#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, ALLIGN=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

View File

@@ -28,6 +28,7 @@
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#if defined(__arm__) || defined(_M_ARM)
#include <fficonfig.h>
#include <ffi.h>
#include <ffi_common.h>
@@ -35,6 +36,11 @@
#include <stdlib.h>
#include "internal.h"
#if defined(_MSC_VER) && defined(_M_ARM)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
#if FFI_EXEC_TRAMPOLINE_TABLE
#ifdef __MACH__
@@ -42,7 +48,11 @@
#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
/* Forward declares. */
@@ -88,10 +98,20 @@ ffi_put_arg (ffi_type *ty, void *src, void *dst)
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:
@@ -210,7 +230,7 @@ ffi_prep_args_VFP (ffi_cif *cif, int flags, void *rvalue,
}
/* Perform machine dependent cif processing */
ffi_status
ffi_status FFI_HIDDEN
ffi_prep_cif_machdep (ffi_cif *cif)
{
int flags = 0, cabi = cif->abi;
@@ -301,7 +321,7 @@ ffi_prep_cif_machdep (ffi_cif *cif)
}
/* Perform machine dependent cif processing for variadic calls */
ffi_status
ffi_status FFI_HIDDEN
ffi_prep_cif_machdep_var (ffi_cif * cif,
unsigned int nfixedargs, unsigned int ntotalargs)
{
@@ -571,15 +591,28 @@ ffi_prep_closure_loc (ffi_closure * closure,
config[0] = closure;
config[1] = closure_func;
#else
memcpy (closure->tramp, ffi_arm_trampoline, 8);
#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 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
closure->cif = cif;
@@ -781,7 +814,7 @@ place_vfp_arg (ffi_cif *cif, int h)
}
/* 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))
@@ -803,7 +836,7 @@ place_vfp_arg (ffi_cif *cif, int h)
static void
layout_vfp_args (ffi_cif * cif)
{
int i;
unsigned int i;
/* Init VFP fields */
cif->vfp_used = 0;
cif->vfp_nargs = 0;
@@ -817,3 +850,5 @@ layout_vfp_args (ffi_cif * cif)
break;
}
}
#endif /* __arm__ or _M_ARM */

View File

@@ -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,
@@ -57,7 +57,9 @@ typedef enum ffi_abi {
signed char vfp_args[16] \
#define FFI_TARGET_SPECIFIC_VARIADIC
#ifndef _M_ARM
#define FFI_TARGET_HAS_COMPLEX_TYPE
#endif
/* ---- Definitions for closures ----------------------------------------- */
@@ -74,8 +76,13 @@ typedef enum ffi_abi {
#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

View File

@@ -25,6 +25,7 @@
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#ifdef __arm__
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
@@ -377,6 +378,7 @@ ARM_FUNC_START(ffi_arm_trampoline)
ARM_FUNC_END(ffi_arm_trampoline)
#endif /* FFI_EXEC_TRAMPOLINE_TABLE */
#endif /* __arm__ */
#if defined __ELF__ && defined __linux__
.section .note.GNU-stack,"",%progbits

311
src/arm/sysv_msvc_arm32.S Normal file
View File

@@ -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 <fficonfig.h>
#include <ffi.h>
#include <ffi_cfi.h>
#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

View File

@@ -122,7 +122,7 @@ ffi_closure_free (void *ptr)
# define FFI_MMAP_EXEC_WRIT 1
# define HAVE_MNTENT 1
# endif
# if defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)
# if defined(X86_WIN32) || defined(X86_WIN64) || defined(_M_ARM64) || defined(__OS2__)
/* Windows systems may have Data Execution Protection (DEP) enabled,
which requires the use of VirtualMalloc/VirtualFree to alloc/free
executable memory. */
@@ -172,7 +172,7 @@ struct ffi_trampoline_table
struct ffi_trampoline_table_entry
{
void *(*trampoline) ();
void *(*trampoline) (void);
ffi_trampoline_table_entry *next;
};
@@ -385,7 +385,7 @@ ffi_closure_free (void *ptr)
#endif
#include <string.h>
#include <stdio.h>
#if !defined(X86_WIN32) && !defined(X86_WIN64)
#if !defined(X86_WIN32) && !defined(X86_WIN64) && !defined(_M_ARM64)
#ifdef HAVE_MNTENT
#include <mntent.h>
#endif /* HAVE_MNTENT */
@@ -511,7 +511,7 @@ 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(X86_WIN32) || defined(X86_WIN64) || defined(_M_ARM64) || 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);
@@ -525,7 +525,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(X86_WIN32) || defined(X86_WIN64) || defined(_M_ARM64) || 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;
@@ -789,7 +789,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
@@ -801,7 +807,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;
}
@@ -896,7 +907,7 @@ segment_holding_code (mstate m, char* addr)
}
#endif
#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(__OS2__)) || defined (__CYGWIN__) || defined(__INTERIX) */
#endif /* !(defined(X86_WIN32) || defined(X86_WIN64) || defined(_M_ARM64) || 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
@@ -921,6 +932,13 @@ ffi_closure_alloc (size_t size, void **code)
return ptr;
}
void *
ffi_data_to_code_pointer (void *data)
{
msegmentptr seg = segment_holding (gm, data);
return add_segment_exec_offset (data, seg);
}
/* 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
@@ -960,6 +978,12 @@ ffi_closure_free (void *ptr)
free (ptr);
}
void *
ffi_data_to_code_pointer (void *data)
{
return data;
}
# endif /* ! FFI_MMAP_EXEC_WRIT */
#endif /* FFI_CLOSURES */

View File

@@ -297,10 +297,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 +318,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 +352,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

View File

@@ -121,8 +121,9 @@ ffi_call_int (ffi_cif *cif,
# 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
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)
memcpy (rvalue, (char *) smst_buffer + 8 - rsize, rsize);
else
#endif

View File

@@ -63,10 +63,30 @@ ffi_prep_types_linux64 (ffi_abi abi)
static unsigned int
discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum)
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
{
*elnum = 2;
return FFI_TYPE_LONGDOUBLE;
}
#endif
case FFI_TYPE_FLOAT:
case FFI_TYPE_DOUBLE:
*elnum = 1;
@@ -79,7 +99,7 @@ discover_homogeneous_aggregate (const ffi_type *t, unsigned int *elnum)
while (*el)
{
unsigned int el_elt, el_elnum = 0;
el_elt = discover_homogeneous_aggregate (*el, &el_elnum);
el_elt = discover_homogeneous_aggregate (abi, *el, &el_elnum);
if (el_elt == 0
|| (base_elt && base_elt != el_elt))
return 0;
@@ -112,7 +132,7 @@ ffi_prep_cif_linux64_core (ffi_cif *cif)
unsigned bytes;
unsigned i, fparg_count = 0, intarg_count = 0;
unsigned flags = cif->flags;
unsigned int elt, elnum;
unsigned elt, elnum, rtype;
#if FFI_TYPE_LONGDOUBLE == FFI_TYPE_DOUBLE
/* If compiled without long double support.. */
@@ -138,7 +158,11 @@ ffi_prep_cif_linux64_core (ffi_cif *cif)
#endif
/* Return value handling. */
switch (cif->rtype->type)
rtype = cif->rtype->type;
#if _CALL_ELF == 2
homogeneous:
#endif
switch (rtype)
{
#if FFI_TYPE_LONGDOUBLE != FFI_TYPE_DOUBLE
case FFI_TYPE_LONGDOUBLE:
@@ -164,19 +188,18 @@ ffi_prep_cif_linux64_core (ffi_cif *cif)
case FFI_TYPE_STRUCT:
#if _CALL_ELF == 2
elt = discover_homogeneous_aggregate (cif->rtype, &elnum);
elt = discover_homogeneous_aggregate (cif->abi, cif->rtype, &elnum);
if (elt)
{
if (elt == FFI_TYPE_DOUBLE)
flags |= FLAG_RETURNS_64BITS;
flags |= FLAG_RETURNS_FP | FLAG_RETURNS_SMST;
break;
}
{
flags |= FLAG_RETURNS_SMST;
rtype = elt;
goto homogeneous;
}
if (cif->rtype->size <= 16)
{
flags |= FLAG_RETURNS_SMST;
break;
}
{
flags |= FLAG_RETURNS_SMST;
break;
}
#endif
intarg_count++;
flags |= FLAG_RETVAL_REFERENCE;
@@ -224,7 +247,7 @@ ffi_prep_cif_linux64_core (ffi_cif *cif)
intarg_count = FFI_ALIGN (intarg_count, align);
}
intarg_count += ((*ptr)->size + 7) / 8;
elt = discover_homogeneous_aggregate (*ptr, &elnum);
elt = discover_homogeneous_aggregate (cif->abi, *ptr, &elnum);
if (elt)
{
fparg_count += elnum;
@@ -391,7 +414,7 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
valp rest;
valp next_arg;
/* 'fpr_base' points at the space for fpr3, and grows upwards as
/* 'fpr_base' points at the space for f1, and grows upwards as
we use FPR registers. */
valp fpr_base;
unsigned int fparg_count;
@@ -492,7 +515,9 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
/* Fall through. */
#endif
case FFI_TYPE_DOUBLE:
#if _CALL_ELF != 2
do_double:
#endif
double_tmp = **p_argv.d;
if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
{
@@ -511,7 +536,9 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
break;
case FFI_TYPE_FLOAT:
#if _CALL_ELF != 2
do_float:
#endif
double_tmp = **p_argv.f;
if (fparg_count < NUM_FPR_ARG_REGISTERS64 && i < nfixedargs)
{
@@ -548,9 +575,13 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
if (align > 16)
align = 16;
if (align > 1)
next_arg.p = FFI_ALIGN (next_arg.p, align);
{
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 (*ptr, &elnum);
elt = discover_homogeneous_aggregate (ecif->cif->abi, *ptr, &elnum);
if (elt)
{
#if _CALL_ELF == 2
@@ -576,11 +607,9 @@ ffi_prep_args64 (extended_cif *ecif, unsigned long *const stack)
fparg_count++;
}
while (--elnum != 0);
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;
}
else
do
@@ -813,7 +842,7 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif,
if (align > 1)
pst = (unsigned long *) FFI_ALIGN ((size_t) pst, align);
}
elt = discover_homogeneous_aggregate (arg_types[i], &elnum);
elt = discover_homogeneous_aggregate (cif->abi, arg_types[i], &elnum);
if (elt)
{
#if _CALL_ELF == 2
@@ -915,7 +944,9 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif,
/* Fall through. */
#endif
case FFI_TYPE_DOUBLE:
#if _CALL_ELF != 2
do_double:
#endif
/* On the outgoing stack all values are aligned to 8 */
/* there are 13 64bit floating point registers */
@@ -930,7 +961,9 @@ ffi_closure_helper_LINUX64 (ffi_cif *cif,
break;
case FFI_TYPE_FLOAT:
#if _CALL_ELF != 2
do_float:
#endif
if (pfr < end_pfr && i < nfixedargs)
{
/* Float values are stored as doubles in the

View File

@@ -143,7 +143,7 @@ ffi_closure_LINUX64:
stfd %f12, -104+(11*8)(%r1)
stfd %f13, -104+(12*8)(%r1)
# load up the pointer to the saved fpr registers */
# load up the pointer to the saved fpr registers
addi %r8, %r1, -104
# load up the pointer to the result storage

View File

@@ -129,7 +129,9 @@ ffi_status FFI_HIDDEN ffi_prep_cif_core(ffi_cif *cif, ffi_abi abi,
cif->rtype = rtype;
cif->flags = 0;
#ifdef _M_ARM64
cif->is_variadic = isvariadic;
#endif
#if HAVE_LONG_DOUBLE_VARIANT
ffi_prep_types (abi);
#endif
@@ -199,7 +201,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
}

View File

@@ -29,7 +29,7 @@
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#ifndef __x86_64__
#if defined(__i386__) || defined(_M_IX86)
#include <ffi.h>
#include <ffi_common.h>
#include <stdint.h>
@@ -756,4 +756,4 @@ ffi_raw_call(ffi_cif *cif, void (*fn)(void), void *rvalue, ffi_raw *avalue)
ffi_call_i386 (frame, stack);
}
#endif /* !FFI_NO_RAW_API */
#endif /* !__x86_64__ */
#endif /* __i386__ */

View File

@@ -282,7 +282,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)
{
@@ -293,7 +293,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. */
@@ -394,7 +394,7 @@ extern ffi_status
ffi_prep_cif_machdep_efi64(ffi_cif *cif);
#endif
ffi_status
ffi_status FFI_HIDDEN
ffi_prep_cif_machdep (ffi_cif *cif)
{
int gprcount, ssecount, i, avn, ngpr, nsse;
@@ -451,9 +451,11 @@ ffi_prep_cif_machdep (ffi_cif *cif)
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)

View File

@@ -25,6 +25,7 @@
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#if defined(__x86_64__) || defined(_M_AMD64)
#include <ffi.h>
#include <ffi_common.h>
#include <stdlib.h>
@@ -33,7 +34,7 @@
#ifdef X86_WIN64
#define EFI64(name) name
#else
#define EFI64(name) name##_efi64
#define EFI64(name) FFI_HIDDEN name##_efi64
#endif
struct win64_call_frame
@@ -48,7 +49,7 @@ struct win64_call_frame
extern void ffi_call_win64 (void *stack, struct win64_call_frame *,
void *closure) FFI_HIDDEN;
ffi_status
ffi_status FFI_HIDDEN
EFI64(ffi_prep_cif_machdep)(ffi_cif *cif)
{
int flags, n;
@@ -306,3 +307,5 @@ ffi_closure_win64_inner(ffi_cif *cif,
fun (cif, rvalue, avalue, user_data);
return flags;
}
#endif /* __x86_64__ */

View File

@@ -26,7 +26,7 @@
DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------- */
#ifndef __x86_64__
#ifdef __i386__
#ifndef _MSC_VER
#define LIBFFI_ASM
@@ -1122,7 +1122,7 @@ L(EFDE9):
#endif /* __APPLE__ */
#endif /* ifndef _MSC_VER */
#endif /* ifndef __x86_64__ */
#endif /* ifdef __i386__ */
#if defined __ELF__ && defined __linux__
.section .note.GNU-stack,"",@progbits

View File

@@ -1,3 +1,4 @@
#ifdef __x86_64__
#define LIBFFI_ASM
#include <fficonfig.h>
#include <ffi.h>
@@ -42,6 +43,7 @@
.align 8
.globl C(ffi_call_win64)
FFI_HIDDEN(C(ffi_call_win64))
SEH(.seh_proc ffi_call_win64)
C(ffi_call_win64):
@@ -169,6 +171,7 @@ E(0b, FFI_TYPE_SMALL_STRUCT_4B)
.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):
@@ -188,6 +191,7 @@ C(ffi_go_closure_win64):
.align 8
.globl C(ffi_closure_win64)
FFI_HIDDEN(C(ffi_closure_win64))
SEH(.seh_proc ffi_closure_win64)
C(ffi_closure_win64):
@@ -226,6 +230,7 @@ C(ffi_closure_win64):
cfi_endproc
SEH(.seh_endproc)
#endif /* __x86_64__ */
#if defined __ELF__ && defined __linux__
.section .note.GNU-stack,"",@progbits

View File

@@ -1,4 +1,4 @@
# 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.
# 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
@@ -480,11 +480,11 @@ proc run-many-tests { testcases extra_flags } {
switch $compiler_vendor {
"clang" {
set common "-W -Wall"
set optimizations { "-O0" "-O2" "-Os" }
set optimizations { "-O0" "-O2" }
}
"gnu" {
set common "-W -Wall -Wno-psabi"
set optimizations { "-O0" "-O2" "-Os" "-O2 -fomit-frame-pointer" }
set optimizations { "-O0" "-O2" "-O2 -fomit-frame-pointer" }
}
default {
# Assume we are using the vendor compiler.

View File

@@ -33,19 +33,20 @@ 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