diff mbox series

[v6,08/26] tcg: Build ffi data structures for helpers

Message ID 20210502235727.1979457-9-richard.henderson@linaro.org
State Superseded
Headers show
Series TCI fixes and cleanups | expand

Commit Message

Richard Henderson May 2, 2021, 11:57 p.m. UTC
Add libffi as a build requirement for TCI.
Add libffi to the dockerfiles to satisfy that requirement.

Construct an ffi_cif structure for each unique typemask.
Record the result in a separate hash table for later lookup;
this allows helper_table to stay const.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

---
 meson.build                                   |  9 ++-
 tcg/tcg.c                                     | 58 +++++++++++++++++++
 tests/docker/dockerfiles/alpine.docker        |  1 +
 tests/docker/dockerfiles/centos7.docker       |  1 +
 tests/docker/dockerfiles/centos8.docker       |  1 +
 tests/docker/dockerfiles/debian10.docker      |  1 +
 .../dockerfiles/fedora-i386-cross.docker      |  1 +
 .../dockerfiles/fedora-win32-cross.docker     |  1 +
 .../dockerfiles/fedora-win64-cross.docker     |  1 +
 tests/docker/dockerfiles/fedora.docker        |  1 +
 tests/docker/dockerfiles/ubuntu.docker        |  1 +
 tests/docker/dockerfiles/ubuntu1804.docker    |  1 +
 tests/docker/dockerfiles/ubuntu2004.docker    |  1 +
 13 files changed, 77 insertions(+), 1 deletion(-)

-- 
2.25.1

Comments

Philippe Mathieu-Daudé May 31, 2021, 6:55 p.m. UTC | #1
Hi Richard,

On 5/3/21 1:57 AM, Richard Henderson wrote:
> Add libffi as a build requirement for TCI.

> Add libffi to the dockerfiles to satisfy that requirement.

> 

> Construct an ffi_cif structure for each unique typemask.

> Record the result in a separate hash table for later lookup;

> this allows helper_table to stay const.

> 

> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

> ---

>  meson.build                                   |  9 ++-

>  tcg/tcg.c                                     | 58 +++++++++++++++++++

>  tests/docker/dockerfiles/alpine.docker        |  1 +

>  tests/docker/dockerfiles/centos7.docker       |  1 +

>  tests/docker/dockerfiles/centos8.docker       |  1 +

>  tests/docker/dockerfiles/debian10.docker      |  1 +

>  .../dockerfiles/fedora-i386-cross.docker      |  1 +

>  .../dockerfiles/fedora-win32-cross.docker     |  1 +

>  .../dockerfiles/fedora-win64-cross.docker     |  1 +

>  tests/docker/dockerfiles/fedora.docker        |  1 +

>  tests/docker/dockerfiles/ubuntu.docker        |  1 +

>  tests/docker/dockerfiles/ubuntu1804.docker    |  1 +

>  tests/docker/dockerfiles/ubuntu2004.docker    |  1 +

>  13 files changed, 77 insertions(+), 1 deletion(-)


> @@ -1135,6 +1152,47 @@ void tcg_context_init(TCGContext *s)

>                              (gpointer)&all_helpers[i]);

>      }

>  

> +#ifdef CONFIG_TCG_INTERPRETER

> +    /* g_direct_hash/equal for direct comparisons on uint32_t.  */


Why not use g_int_hash() then?

Otherwise,
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>


> +    ffi_table = g_hash_table_new(NULL, NULL);

> +    for (i = 0; i < ARRAY_SIZE(all_helpers); ++i) {

> +        struct {

> +            ffi_cif cif;

> +            ffi_type *args[];

> +        } *ca;

> +        uint32_t typemask = all_helpers[i].typemask;

> +        gpointer hash = (gpointer)(uintptr_t)typemask;

> +        ffi_status status;

> +        int nargs;

> +

> +        if (g_hash_table_lookup(ffi_table, hash)) {

> +            continue;

> +        }

> +

> +        /* Ignoring the return type, find the last non-zero field. */

> +        nargs = 32 - clz32(typemask >> 3);

> +        nargs = DIV_ROUND_UP(nargs, 3);

> +

> +        ca = g_malloc0(sizeof(*ca) + nargs * sizeof(ffi_type *));

> +        ca->cif.rtype = typecode_to_ffi[typemask & 7];

> +        ca->cif.nargs = nargs;

> +

> +        if (nargs != 0) {

> +            ca->cif.arg_types = ca->args;

> +            for (i = 0; i < nargs; ++i) {

> +                int typecode = extract32(typemask, (i + 1) * 3, 3);

> +                ca->args[i] = typecode_to_ffi[typecode];

> +            }

> +        }

> +

> +        status = ffi_prep_cif(&ca->cif, FFI_DEFAULT_ABI, nargs,

> +                              ca->cif.rtype, ca->cif.arg_types);

> +        assert(status == FFI_OK);

> +

> +        g_hash_table_insert(ffi_table, hash, (gpointer)&ca->cif);

> +    }

> +#endif

> +

>      tcg_target_init(s);

>      process_op_defs(s);
Richard Henderson June 1, 2021, 2:33 p.m. UTC | #2
On 5/31/21 11:55 AM, Philippe Mathieu-Daudé wrote:
> Hi Richard,

> 

> On 5/3/21 1:57 AM, Richard Henderson wrote:

>> Add libffi as a build requirement for TCI.

>> Add libffi to the dockerfiles to satisfy that requirement.

>>

>> Construct an ffi_cif structure for each unique typemask.

>> Record the result in a separate hash table for later lookup;

>> this allows helper_table to stay const.

>>

>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

>> ---

>>   meson.build                                   |  9 ++-

>>   tcg/tcg.c                                     | 58 +++++++++++++++++++

>>   tests/docker/dockerfiles/alpine.docker        |  1 +

>>   tests/docker/dockerfiles/centos7.docker       |  1 +

>>   tests/docker/dockerfiles/centos8.docker       |  1 +

>>   tests/docker/dockerfiles/debian10.docker      |  1 +

>>   .../dockerfiles/fedora-i386-cross.docker      |  1 +

>>   .../dockerfiles/fedora-win32-cross.docker     |  1 +

>>   .../dockerfiles/fedora-win64-cross.docker     |  1 +

>>   tests/docker/dockerfiles/fedora.docker        |  1 +

>>   tests/docker/dockerfiles/ubuntu.docker        |  1 +

>>   tests/docker/dockerfiles/ubuntu1804.docker    |  1 +

>>   tests/docker/dockerfiles/ubuntu2004.docker    |  1 +

>>   13 files changed, 77 insertions(+), 1 deletion(-)

> 

>> @@ -1135,6 +1152,47 @@ void tcg_context_init(TCGContext *s)

>>                               (gpointer)&all_helpers[i]);

>>       }

>>   

>> +#ifdef CONFIG_TCG_INTERPRETER

>> +    /* g_direct_hash/equal for direct comparisons on uint32_t.  */

> 

> Why not use g_int_hash() then?


g_int_hash takes a pointer to an int; this stores the int directly as the hash key.


r~

> 

> Otherwise,

> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> 

>> +    ffi_table = g_hash_table_new(NULL, NULL);

>> +    for (i = 0; i < ARRAY_SIZE(all_helpers); ++i) {

>> +        struct {

>> +            ffi_cif cif;

>> +            ffi_type *args[];

>> +        } *ca;

>> +        uint32_t typemask = all_helpers[i].typemask;

>> +        gpointer hash = (gpointer)(uintptr_t)typemask;

>> +        ffi_status status;

>> +        int nargs;

>> +

>> +        if (g_hash_table_lookup(ffi_table, hash)) {

>> +            continue;

>> +        }

>> +

>> +        /* Ignoring the return type, find the last non-zero field. */

>> +        nargs = 32 - clz32(typemask >> 3);

>> +        nargs = DIV_ROUND_UP(nargs, 3);

>> +

>> +        ca = g_malloc0(sizeof(*ca) + nargs * sizeof(ffi_type *));

>> +        ca->cif.rtype = typecode_to_ffi[typemask & 7];

>> +        ca->cif.nargs = nargs;

>> +

>> +        if (nargs != 0) {

>> +            ca->cif.arg_types = ca->args;

>> +            for (i = 0; i < nargs; ++i) {

>> +                int typecode = extract32(typemask, (i + 1) * 3, 3);

>> +                ca->args[i] = typecode_to_ffi[typecode];

>> +            }

>> +        }

>> +

>> +        status = ffi_prep_cif(&ca->cif, FFI_DEFAULT_ABI, nargs,

>> +                              ca->cif.rtype, ca->cif.arg_types);

>> +        assert(status == FFI_OK);

>> +

>> +        g_hash_table_insert(ffi_table, hash, (gpointer)&ca->cif);

>> +    }

>> +#endif

>> +

>>       tcg_target_init(s);

>>       process_op_defs(s);
diff mbox series

Patch

diff --git a/meson.build b/meson.build
index c6f4b0cf5e..0bb0b7b28d 100644
--- a/meson.build
+++ b/meson.build
@@ -1942,7 +1942,14 @@  specific_ss.add(when: 'CONFIG_TCG', if_true: files(
   'tcg/tcg-op.c',
   'tcg/tcg.c',
 ))
-specific_ss.add(when: 'CONFIG_TCG_INTERPRETER', if_true: files('tcg/tci.c'))
+
+if get_option('tcg_interpreter')
+  libffi = dependency('libffi', version: '>=3.0',
+                      static: enable_static, method: 'pkg-config',
+                      required: true)
+  specific_ss.add(libffi)
+  specific_ss.add(files('tcg/tci.c'))
+endif
 
 # Work around a gcc bug/misfeature wherein constant propagation looks
 # through an alias:
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 1e5e165bff..8bb65ff1c6 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -67,6 +67,10 @@ 
 #include "sysemu/sysemu.h"
 #include "internal.h"
 
+#ifdef CONFIG_TCG_INTERPRETER
+#include <ffi.h>
+#endif
+
 /* Forward declarations for functions declared in tcg-target.c.inc and
    used here. */
 static void tcg_target_init(TCGContext *s);
@@ -1093,6 +1097,19 @@  static const TCGHelperInfo all_helpers[] = {
 };
 static GHashTable *helper_table;
 
+#ifdef CONFIG_TCG_INTERPRETER
+static GHashTable *ffi_table;
+
+static ffi_type * const typecode_to_ffi[8] = {
+    [dh_typecode_void] = &ffi_type_void,
+    [dh_typecode_i32]  = &ffi_type_uint32,
+    [dh_typecode_s32]  = &ffi_type_sint32,
+    [dh_typecode_i64]  = &ffi_type_uint64,
+    [dh_typecode_s64]  = &ffi_type_sint64,
+    [dh_typecode_ptr]  = &ffi_type_pointer,
+};
+#endif
+
 static int indirect_reg_alloc_order[ARRAY_SIZE(tcg_target_reg_alloc_order)];
 static void process_op_defs(TCGContext *s);
 static TCGTemp *tcg_global_reg_new_internal(TCGContext *s, TCGType type,
@@ -1135,6 +1152,47 @@  void tcg_context_init(TCGContext *s)
                             (gpointer)&all_helpers[i]);
     }
 
+#ifdef CONFIG_TCG_INTERPRETER
+    /* g_direct_hash/equal for direct comparisons on uint32_t.  */
+    ffi_table = g_hash_table_new(NULL, NULL);
+    for (i = 0; i < ARRAY_SIZE(all_helpers); ++i) {
+        struct {
+            ffi_cif cif;
+            ffi_type *args[];
+        } *ca;
+        uint32_t typemask = all_helpers[i].typemask;
+        gpointer hash = (gpointer)(uintptr_t)typemask;
+        ffi_status status;
+        int nargs;
+
+        if (g_hash_table_lookup(ffi_table, hash)) {
+            continue;
+        }
+
+        /* Ignoring the return type, find the last non-zero field. */
+        nargs = 32 - clz32(typemask >> 3);
+        nargs = DIV_ROUND_UP(nargs, 3);
+
+        ca = g_malloc0(sizeof(*ca) + nargs * sizeof(ffi_type *));
+        ca->cif.rtype = typecode_to_ffi[typemask & 7];
+        ca->cif.nargs = nargs;
+
+        if (nargs != 0) {
+            ca->cif.arg_types = ca->args;
+            for (i = 0; i < nargs; ++i) {
+                int typecode = extract32(typemask, (i + 1) * 3, 3);
+                ca->args[i] = typecode_to_ffi[typecode];
+            }
+        }
+
+        status = ffi_prep_cif(&ca->cif, FFI_DEFAULT_ABI, nargs,
+                              ca->cif.rtype, ca->cif.arg_types);
+        assert(status == FFI_OK);
+
+        g_hash_table_insert(ffi_table, hash, (gpointer)&ca->cif);
+    }
+#endif
+
     tcg_target_init(s);
     process_op_defs(s);
 
diff --git a/tests/docker/dockerfiles/alpine.docker b/tests/docker/dockerfiles/alpine.docker
index d63a269aef..017cbbceac 100644
--- a/tests/docker/dockerfiles/alpine.docker
+++ b/tests/docker/dockerfiles/alpine.docker
@@ -20,6 +20,7 @@  ENV PACKAGES \
 	gtk+3.0-dev \
 	libaio-dev \
 	libcap-ng-dev \
+	libffi-dev \
 	libjpeg-turbo-dev \
 	libnfs-dev \
 	libpng-dev \
diff --git a/tests/docker/dockerfiles/centos7.docker b/tests/docker/dockerfiles/centos7.docker
index 75fdb53c7c..fff7c5a424 100644
--- a/tests/docker/dockerfiles/centos7.docker
+++ b/tests/docker/dockerfiles/centos7.docker
@@ -20,6 +20,7 @@  ENV PACKAGES \
     libaio-devel \
     libepoxy-devel \
     libfdt-devel \
+    libffi-devel \
     libgcrypt-devel \
     librdmacm-devel \
     libzstd-devel \
diff --git a/tests/docker/dockerfiles/centos8.docker b/tests/docker/dockerfiles/centos8.docker
index a8c6c528b0..fcab3bc8e4 100644
--- a/tests/docker/dockerfiles/centos8.docker
+++ b/tests/docker/dockerfiles/centos8.docker
@@ -16,6 +16,7 @@  ENV PACKAGES \
     libaio-devel \
     libepoxy-devel \
     libfdt-devel \
+    libffi-devel \
     libgcrypt-devel \
     lzo-devel \
     make \
diff --git a/tests/docker/dockerfiles/debian10.docker b/tests/docker/dockerfiles/debian10.docker
index d034acbd25..1f8bea97b3 100644
--- a/tests/docker/dockerfiles/debian10.docker
+++ b/tests/docker/dockerfiles/debian10.docker
@@ -26,6 +26,7 @@  RUN apt update && \
         gdb-multiarch \
         gettext \
         git \
+        libffi-dev \
         libncurses5-dev \
         ninja-build \
         pkg-config \
diff --git a/tests/docker/dockerfiles/fedora-i386-cross.docker b/tests/docker/dockerfiles/fedora-i386-cross.docker
index 966072c08e..b620d7664d 100644
--- a/tests/docker/dockerfiles/fedora-i386-cross.docker
+++ b/tests/docker/dockerfiles/fedora-i386-cross.docker
@@ -5,6 +5,7 @@  ENV PACKAGES \
     findutils \
     gcc \
     git \
+    libffi-devel.i686 \
     libtasn1-devel.i686 \
     libzstd-devel.i686 \
     make \
diff --git a/tests/docker/dockerfiles/fedora-win32-cross.docker b/tests/docker/dockerfiles/fedora-win32-cross.docker
index 81b5659e9c..5072c9c2a6 100644
--- a/tests/docker/dockerfiles/fedora-win32-cross.docker
+++ b/tests/docker/dockerfiles/fedora-win32-cross.docker
@@ -18,6 +18,7 @@  ENV PACKAGES \
     mingw32-gmp \
     mingw32-gnutls \
     mingw32-gtk3 \
+    mingw32-libffi \
     mingw32-libjpeg-turbo \
     mingw32-libpng \
     mingw32-libtasn1 \
diff --git a/tests/docker/dockerfiles/fedora-win64-cross.docker b/tests/docker/dockerfiles/fedora-win64-cross.docker
index bcb428e724..5cdca965c2 100644
--- a/tests/docker/dockerfiles/fedora-win64-cross.docker
+++ b/tests/docker/dockerfiles/fedora-win64-cross.docker
@@ -17,6 +17,7 @@  ENV PACKAGES \
     mingw64-glib2 \
     mingw64-gmp \
     mingw64-gtk3 \
+    mingw64-libffi \
     mingw64-libjpeg-turbo \
     mingw64-libpng \
     mingw64-libtasn1 \
diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker
index 915fdc1845..8140fe67b2 100644
--- a/tests/docker/dockerfiles/fedora.docker
+++ b/tests/docker/dockerfiles/fedora.docker
@@ -32,6 +32,7 @@  ENV PACKAGES \
     libcurl-devel \
     libepoxy-devel \
     libfdt-devel \
+    libffi-devel \
     libiscsi-devel \
     libjpeg-devel \
     libpmem-devel \
diff --git a/tests/docker/dockerfiles/ubuntu.docker b/tests/docker/dockerfiles/ubuntu.docker
index b5ef7a8198..204a7c10a5 100644
--- a/tests/docker/dockerfiles/ubuntu.docker
+++ b/tests/docker/dockerfiles/ubuntu.docker
@@ -28,6 +28,7 @@  ENV PACKAGES \
     libdrm-dev \
     libepoxy-dev \
     libfdt-dev \
+    libffi-dev \
     libgbm-dev \
     libgnutls28-dev \
     libgtk-3-dev \
diff --git a/tests/docker/dockerfiles/ubuntu1804.docker b/tests/docker/dockerfiles/ubuntu1804.docker
index 9b0a19ba5e..4d567a46fe 100644
--- a/tests/docker/dockerfiles/ubuntu1804.docker
+++ b/tests/docker/dockerfiles/ubuntu1804.docker
@@ -16,6 +16,7 @@  ENV PACKAGES \
     libdrm-dev \
     libepoxy-dev \
     libfdt-dev \
+    libffi-dev \
     libgbm-dev \
     libgtk-3-dev \
     libibverbs-dev \
diff --git a/tests/docker/dockerfiles/ubuntu2004.docker b/tests/docker/dockerfiles/ubuntu2004.docker
index 9750016e51..f73631ba84 100644
--- a/tests/docker/dockerfiles/ubuntu2004.docker
+++ b/tests/docker/dockerfiles/ubuntu2004.docker
@@ -19,6 +19,7 @@  ENV PACKAGES flex bison \
     libdrm-dev \
     libepoxy-dev \
     libfdt-dev \
+    libffi-dev \
     libgbm-dev \
     libgtk-3-dev \
     libibverbs-dev \