From d35ed415c72855a8300b3bff89f92ed4b857c672 Mon Sep 17 00:00:00 2001 From: laiheng Date: Sat, 23 Dec 2023 17:00:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Eriscv64=E6=9E=B6=E6=9E=84?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: laiheng --- BUILD.gn | 32 +++ include/ffi-riscv64.h | 521 ++++++++++++++++++++++++++++++++++++ include/ffi.h | 2 + include/ffitarget-riscv64.h | 68 +++++ include/ffitarget.h | 2 + 5 files changed, 625 insertions(+) create mode 100644 include/ffi-riscv64.h create mode 100644 include/ffitarget-riscv64.h diff --git a/BUILD.gn b/BUILD.gn index 9e7cb8e..edf64e2 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -62,6 +62,38 @@ if (target_cpu == "arm") { "src/x86/unix64.S", ] + configs = [ ":ffi_config" ] + } +} else if (target_cpu == "riscv64") { + config("ffi_config") { + visibility = [ ":*" ] + + include_dirs = [ + ".", + "./include", + "./src/riscv", + ] + + cflags = [ + "-DTARGET=RISCV64", + "-Wno-sign-compare", + "-Wno-implicit-function-declaration", + "-Wno-extern-initializer", + ] + cflags += [ "-mno-relax" ] + } + + ohos_source_set("ffi_source") { + sources = [ + "src/closures.c", + "src/java_raw_api.c", + "src/prep_cif.c", + "src/raw_api.c", + "src/riscv/ffi.c", + "src/riscv/sysv.S", + "src/types.c", + ] + configs = [ ":ffi_config" ] } } else { diff --git a/include/ffi-riscv64.h b/include/ffi-riscv64.h new file mode 100644 index 0000000..ebea64d --- /dev/null +++ b/include/ffi-riscv64.h @@ -0,0 +1,521 @@ +/* -----------------------------------------------------------------*-C-*- + libffi 3.4.2 + - Copyright (c) 2011, 2014, 2019, 2021 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 RISCV +#define RISCV +#endif + +/* ---- System configuration information --------------------------------- */ + +#include + +#ifndef LIBFFI_ASM + +#if defined(_MSC_VER) && !defined(__clang__) +#define __attribute__(X) +#endif + +#include +#include + +/* LONG_LONG_MAX is not always defined (not if STRICT_ANSI, for example). + But we can find it either under the correct ANSI name, or under GNU + C's internal name. */ + +#define FFI_64_BIT_MAX 9223372036854775807 + +#ifdef LONG_LONG_MAX +# define FFI_LONG_LONG_MAX LONG_LONG_MAX +#else +# ifdef LLONG_MAX +# define FFI_LONG_LONG_MAX LLONG_MAX +# ifdef _AIX52 /* or newer has C99 LLONG_MAX */ +# undef FFI_64_BIT_MAX +# define FFI_64_BIT_MAX 9223372036854775807LL +# endif /* _AIX52 or newer */ +# else +# ifdef __GNUC__ +# define FFI_LONG_LONG_MAX __LONG_LONG_MAX__ +# endif +# ifdef _AIX /* AIX 5.1 and earlier have LONGLONG_MAX */ +# ifndef __PPC64__ +# if defined (__IBMC__) || defined (__IBMCPP__) +# define FFI_LONG_LONG_MAX LONGLONG_MAX +# endif +# endif /* __PPC64__ */ +# undef FFI_64_BIT_MAX +# define FFI_64_BIT_MAX 9223372036854775807LL +# endif +# endif +#endif + +/* The closure code assumes that this works on pointers, i.e. a size_t + can hold a pointer. */ + +typedef struct _ffi_type +{ + size_t size; + unsigned short alignment; + unsigned short type; + struct _ffi_type **elements; +} ffi_type; + +/* Need minimal decorations for DLLs to work on Windows. GCC has + autoimport and autoexport. Always mark externally visible symbols + as dllimport for MSVC clients, even if it means an extra indirection + when using the static version of the library. + Besides, as a workaround, they can define FFI_BUILDING if they + *know* they are going to link with the static library. */ +#if defined _MSC_VER +# if defined FFI_BUILDING_DLL /* Building libffi.DLL with msvcc.sh */ +# define FFI_API __declspec(dllexport) +# elif !defined FFI_BUILDING /* Importing libffi.DLL */ +# define FFI_API __declspec(dllimport) +# else /* Building/linking static library */ +# define FFI_API +# endif +#else +# define FFI_API +#endif + +/* The externally visible type declarations also need the MSVC DLL + decorations, or they will not be exported from the object file. */ +#if defined LIBFFI_HIDE_BASIC_TYPES +# define FFI_EXTERN FFI_API +#else +# define FFI_EXTERN extern FFI_API +#endif + +#ifndef LIBFFI_HIDE_BASIC_TYPES +#if SCHAR_MAX == 127 +# define ffi_type_uchar ffi_type_uint8 +# define ffi_type_schar ffi_type_sint8 +#else + #error "char size not supported" +#endif + +#if SHRT_MAX == 32767 +# define ffi_type_ushort ffi_type_uint16 +# define ffi_type_sshort ffi_type_sint16 +#elif SHRT_MAX == 2147483647 +# define ffi_type_ushort ffi_type_uint32 +# define ffi_type_sshort ffi_type_sint32 +#else + #error "short size not supported" +#endif + +#if INT_MAX == 32767 +# define ffi_type_uint ffi_type_uint16 +# define ffi_type_sint ffi_type_sint16 +#elif INT_MAX == 2147483647 +# define ffi_type_uint ffi_type_uint32 +# define ffi_type_sint ffi_type_sint32 +#elif INT_MAX == 9223372036854775807 +# define ffi_type_uint ffi_type_uint64 +# define ffi_type_sint ffi_type_sint64 +#else + #error "int size not supported" +#endif + +#if LONG_MAX == 2147483647 +# if FFI_LONG_LONG_MAX != FFI_64_BIT_MAX + #error "no 64-bit data type supported" +# endif +#elif LONG_MAX != FFI_64_BIT_MAX + #error "long size not supported" +#endif + +#if LONG_MAX == 2147483647 +# define ffi_type_ulong ffi_type_uint32 +# define ffi_type_slong ffi_type_sint32 +#elif LONG_MAX == FFI_64_BIT_MAX +# define ffi_type_ulong ffi_type_uint64 +# define ffi_type_slong ffi_type_sint64 +#else + #error "long size not supported" +#endif + +/* These are defined in types.c. */ +FFI_EXTERN ffi_type ffi_type_void; +FFI_EXTERN ffi_type ffi_type_uint8; +FFI_EXTERN ffi_type ffi_type_sint8; +FFI_EXTERN ffi_type ffi_type_uint16; +FFI_EXTERN ffi_type ffi_type_sint16; +FFI_EXTERN ffi_type ffi_type_uint32; +FFI_EXTERN ffi_type ffi_type_sint32; +FFI_EXTERN ffi_type ffi_type_uint64; +FFI_EXTERN ffi_type ffi_type_sint64; +FFI_EXTERN ffi_type ffi_type_float; +FFI_EXTERN ffi_type ffi_type_double; +FFI_EXTERN ffi_type ffi_type_pointer; + +#if 1 +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_BAD_ARGTYPE +} ffi_status; + +typedef struct { + ffi_abi abi; + unsigned nargs; + ffi_type **arg_types; + ffi_type *rtype; + unsigned bytes; + unsigned flags; +#ifdef FFI_EXTRA_CIF_FIELDS + FFI_EXTRA_CIF_FIELDS; +#endif +} ffi_cif; + +/* ---- Definitions for the raw API -------------------------------------- */ + +#ifndef FFI_SIZEOF_ARG +# if LONG_MAX == 2147483647 +# define FFI_SIZEOF_ARG 4 +# elif LONG_MAX == FFI_64_BIT_MAX +# define FFI_SIZEOF_ARG 8 +# endif +#endif + +#ifndef FFI_SIZEOF_JAVA_RAW +# define FFI_SIZEOF_JAVA_RAW FFI_SIZEOF_ARG +#endif + +typedef union { + ffi_sarg sint; + ffi_arg uint; + float flt; + char data[FFI_SIZEOF_ARG]; + void* ptr; +} ffi_raw; + +#if FFI_SIZEOF_JAVA_RAW == 4 && FFI_SIZEOF_ARG == 8 +/* This is a special case for mips64/n32 ABI (and perhaps others) where + sizeof(void *) is 4 and FFI_SIZEOF_ARG is 8. */ +typedef union { + signed int sint; + unsigned int uint; + float flt; + char data[FFI_SIZEOF_JAVA_RAW]; + void* ptr; +} ffi_java_raw; +#else +typedef ffi_raw ffi_java_raw; +#endif + + +FFI_API +void ffi_raw_call (ffi_cif *cif, + void (*fn)(void), + void *rvalue, + ffi_raw *avalue); + +FFI_API void ffi_ptrarray_to_raw (ffi_cif *cif, void **args, ffi_raw *raw); +FFI_API void ffi_raw_to_ptrarray (ffi_cif *cif, ffi_raw *raw, void **args); +FFI_API size_t ffi_raw_size (ffi_cif *cif); + +/* This is analogous to the raw API, except it uses Java parameter + packing, even on 64-bit machines. I.e. on 64-bit machines longs + and doubles are followed by an empty 64-bit word. */ + +#if !FFI_NATIVE_RAW_API +FFI_API +void ffi_java_raw_call (ffi_cif *cif, + void (*fn)(void), + void *rvalue, + ffi_java_raw *avalue) __attribute__((deprecated)); +#endif + +/* ---- 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 + union { + char tramp[FFI_TRAMPOLINE_SIZE]; + void *ftramp; + }; +#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 *); + +#if defined(PA_LINUX) || defined(PA_HPUX) +#define FFI_CLOSURE_PTR(X) ((void *)((unsigned int)(X) | 2)) +#define FFI_RESTORE_PTR(X) ((void *)((unsigned int)(X) & ~3)) +#else +#define FFI_CLOSURE_PTR(X) (X) +#define FFI_RESTORE_PTR(X) (X) +#endif + +FFI_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); + +#if !FFI_NATIVE_RAW_API +FFI_API ffi_status +ffi_prep_java_raw_closure (ffi_java_raw_closure*, + ffi_cif *cif, + void (*fun)(ffi_cif*,void*,ffi_java_raw*,void*), + void *user_data) __attribute__((deprecated)); + +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) __attribute__((deprecated)); +#endif + +#endif /* FFI_CLOSURES */ + +#if FFI_GO_CLOSURES + +typedef struct { + void *tramp; + ffi_cif *cif; + void (*fun)(ffi_cif*,void*,void**,void*); +} ffi_go_closure; + +FFI_API ffi_status ffi_prep_go_closure (ffi_go_closure*, ffi_cif *, + void (*fun)(ffi_cif*,void*,void**,void*)); + +FFI_API void ffi_call_go (ffi_cif *cif, void (*fn)(void), void *rvalue, + void **avalue, void *closure); + +#endif /* FFI_GO_CLOSURES */ + +/* ---- Public interface definition -------------------------------------- */ + +FFI_API +ffi_status ffi_prep_cif(ffi_cif *cif, + ffi_abi abi, + unsigned int nargs, + ffi_type *rtype, + ffi_type **atypes); + +FFI_API +ffi_status ffi_prep_cif_var(ffi_cif *cif, + ffi_abi abi, + unsigned int nfixedargs, + 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 +#if 1 +#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 \ No newline at end of file diff --git a/include/ffi.h b/include/ffi.h index e32cd73..29d9a08 100644 --- a/include/ffi.h +++ b/include/ffi.h @@ -16,6 +16,8 @@ #include "ffi-powerpc.h" #elif defined(__powerpc64__) #include "ffi-powerpc64.h" +#elif defined(__riscv) && (__riscv_xlen == 64) +#include "ffi-riscv64.h" #else #error "Unsupported Architecture" #endif diff --git a/include/ffitarget-riscv64.h b/include/ffitarget-riscv64.h new file mode 100644 index 0000000..f150143 --- /dev/null +++ b/include/ffitarget-riscv64.h @@ -0,0 +1,68 @@ +/* -----------------------------------------------------------------*-C-*- + ffitarget.h - 2014 Michael Knyszek + + Target configuration macros for RISC-V. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + ``Software''), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + ----------------------------------------------------------------------- */ + +#ifndef LIBFFI_TARGET_H +#define LIBFFI_TARGET_H + +#ifndef LIBFFI_H +#error "Please do not include ffitarget.h directly into your source. Use ffi.h instead." +#endif + +#ifndef __riscv +#error "libffi was configured for a RISC-V target but this does not appear to be a RISC-V compiler." +#endif + +#ifndef LIBFFI_ASM + +typedef unsigned long ffi_arg; +typedef signed long ffi_sarg; + +/* FFI_UNUSED_NN and riscv_unused are to maintain ABI compatibility with a + distributed Berkeley patch from 2014, and can be removed at SONAME bump */ +typedef enum ffi_abi { + FFI_FIRST_ABI = 0, + FFI_SYSV, + FFI_UNUSED_1, + FFI_UNUSED_2, + FFI_UNUSED_3, + FFI_LAST_ABI, + + FFI_DEFAULT_ABI = FFI_SYSV +} ffi_abi; + +#endif /* LIBFFI_ASM */ + +/* ---- Definitions for closures ----------------------------------------- */ + +#define FFI_CLOSURES 1 +#define FFI_GO_CLOSURES 1 +#define FFI_TRAMPOLINE_SIZE 24 +#define FFI_NATIVE_RAW_API 0 +#define FFI_EXTRA_CIF_FIELDS unsigned riscv_nfixedargs; unsigned riscv_unused; +#define FFI_TARGET_SPECIFIC_VARIADIC + +#endif \ No newline at end of file diff --git a/include/ffitarget.h b/include/ffitarget.h index 93a5579..0cfa2f1 100644 --- a/include/ffitarget.h +++ b/include/ffitarget.h @@ -16,6 +16,8 @@ #include "ffitarget-powerpc.h" #elif defined(__powerpc64__) #include "ffitarget-powerpc64.h" +#elif defined(__riscv) && (__riscv_xlen == 64) +#include "ffitarget-riscv64.h" #else #error "Unsupported Architecture" #endif -- Gitee