libffi: added ARM64 support for Windows (#486)

*  libffi: added ARM64 support for Windows

    1. ported sysv.S to win64_armasm.S for armasm64 assembler
    2. added msvc_build folder for visual studio solution
    3. updated README.md for the same
    4. MSVC solution created with the changes, and below test suites are tested
       with test script written in python.

       libffi.bhaible
       libffi.call
    5. Basic functionality of above test suites are getting passed

Signed-off-by: ossdev07 <ossdev@puresoftware.com>

* Update README.md
This commit is contained in:
ossdev07
2019-06-25 22:01:22 -04:00
committed by Anthony Green
parent 80d07104c3
commit d856743e6b
12 changed files with 1594 additions and 64 deletions
+9 -2
View File
@@ -51,6 +51,7 @@ tested:
| --------------- | ---------------- | ----------------------- |
| AArch64 (ARM64) | iOS | Clang |
| AArch64 | Linux | GCC |
| AArch64 | Windows | MSVC |
| Alpha | Linux | GCC |
| Alpha | Tru64 | GCC |
| ARC | Linux | GCC |
@@ -169,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.
@@ -195,8 +201,9 @@ 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
+33
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
+130
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>
@@ -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>
@@ -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>
+512
View File
@@ -0,0 +1,512 @@
/* -----------------------------------------------------------------*-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 <ffitarget.h>
#ifndef LIBFFI_ASM
#if defined(_MSC_VER) && !defined(__clang__)
#define __attribute__(X)
#endif
#include <stddef.h>
#include <limits.h>
/* 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;
unsigned isVariadic;
#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
@@ -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 <alloca.h> 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 <dlfcn.h> 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 <inttypes.h> 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 <memory.h> 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 <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
//#define HAVE_STDLIB_H 0
#define LACKS_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#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. */
#define HAVE_SYS_MMAN_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> 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 <sys/types.h> 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
+108 -53
View File
@@ -19,7 +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__)
#if defined(__aarch64__) || defined(__arm64__)|| defined (_M_ARM64)
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
@@ -27,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. */
@@ -75,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
@@ -316,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)
{
@@ -369,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)
{
@@ -438,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
@@ -589,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++)
@@ -652,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->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
{
#endif /* for handling armasm calling convention */
if (state.nsrn + elems <= N_V_ARG_REG)
{
dest = &context->v[state.nsrn];
@@ -661,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)
{
@@ -682,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
{
@@ -876,55 +908,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->isVariadic)
{
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)
@@ -945,4 +1000,4 @@ ffi_closure_SYSV_inner (ffi_cif *cif,
return flags;
}
#endif /* __arm64__ */
#endif /* (__aarch64__) || defined(__arm64__)|| defined (_M_ARM64)*/
+9 -2
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;
@@ -70,12 +74,15 @@ typedef enum ffi_abi
#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
+504
View File
@@ -0,0 +1,504 @@
/* 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
/* Use a stack frame allocated by our caller. */
PROLOG_NOP stp x29, x30, [x1, #32]
/* For unwind information, Windows has to store fp and lr */
PROLOG_SAVE_REG_PAIR x29, x30, #-32!
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, #32]
/* 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
/* 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
+5 -5
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. */
@@ -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;
@@ -896,7 +896,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
+4 -2
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->isVariadic = 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
}