diff mbox series

[RFC,08/48] tcg: export tcg_gen_runtime_helper

Message ID 20181025172057.20414-9-cota@braap.org
State New
Headers show
Series Plugin support | expand

Commit Message

Emilio Cota Oct. 25, 2018, 5:20 p.m. UTC
This takes the TCGHelperInfo directly, which will allow us to generate
helpers at run-time.

Signed-off-by: Emilio G. Cota <cota@braap.org>
---
 tcg/tcg.h |  2 ++
 tcg/tcg.c | 50 +++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 47 insertions(+), 5 deletions(-)

Comments

Alex Bennée Nov. 14, 2018, 4:44 p.m. UTC | #1
Emilio G. Cota <cota@braap.org> writes:

> This takes the TCGHelperInfo directly, which will allow us to generate
> helpers at run-time.
>
> Signed-off-by: Emilio G. Cota <cota@braap.org>

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

> ---
>  tcg/tcg.h |  2 ++
>  tcg/tcg.c | 50 +++++++++++++++++++++++++++++++++++++++++++++-----
>  2 files changed, 47 insertions(+), 5 deletions(-)
>
> diff --git a/tcg/tcg.h b/tcg/tcg.h
> index 9f9643b470..3fa434d891 100644
> --- a/tcg/tcg.h
> +++ b/tcg/tcg.h
> @@ -1077,6 +1077,8 @@ do {\
>  bool tcg_op_supported(TCGOpcode op);
>
>  void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args);
> +void tcg_gen_runtime_helper(const TCGHelperInfo *orig, TCGTemp *ret, int nargs,
> +                            TCGTemp **args);
>
>  TCGOp *tcg_emit_op(TCGOpcode opc);
>  void tcg_op_remove(TCGContext *s, TCGOp *op);
> diff --git a/tcg/tcg.c b/tcg/tcg.c
> index 08b6926894..87e02da740 100644
> --- a/tcg/tcg.c
> +++ b/tcg/tcg.c
> @@ -1642,15 +1642,13 @@ bool tcg_op_supported(TCGOpcode op)
>  /* Note: we convert the 64 bit args to 32 bit and do some alignment
>     and endian swap. Maybe it would be better to do the alignment
>     and endian swap in tcg_reg_alloc_call(). */
> -void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
> +static void do_tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, int nargs,
> +                             TCGTemp **args)
>  {
>      int i, real_args, nb_rets, pi;
>      unsigned sizemask, flags;
> -    TCGHelperInfo *info;
> -    uint32_t hash = tcg_helper_func_hash(func);
>      TCGOp *op;
>
> -    info = qht_lookup_custom(&helper_table, func, hash, tcg_helper_lookup_cmp);
>      flags = info->flags;
>      sizemask = info->sizemask;
>
> @@ -1774,7 +1772,7 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
>          op->args[pi++] = temp_arg(args[i]);
>          real_args++;
>      }
> -    op->args[pi++] = (uintptr_t)func;
> +    op->args[pi++] = (uintptr_t)info->func;
>      op->args[pi++] = flags;
>      TCGOP_CALLI(op) = real_args;
>
> @@ -1812,6 +1810,48 @@ void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
>  #endif /* TCG_TARGET_EXTEND_ARGS */
>  }
>
> +void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
> +{
> +    TCGHelperInfo *info;
> +    uint32_t hash = tcg_helper_func_hash(func);
> +
> +    /*
> +     * Here we can get away with tcg_helper_lookup_cmp, which only looks
> +     * at the function pointer, since we have the compile-time guarantee
> +     * that @func can only be in one TCGHelperInfo.
> +     */
> +    info = qht_lookup_custom(&helper_table, func, hash, tcg_helper_lookup_cmp);
> +    do_tcg_gen_callN(info, ret, nargs, args);
> +}
> +
> +void tcg_gen_runtime_helper(const TCGHelperInfo *orig, TCGTemp *ret, int nargs,
> +                            TCGTemp **args)
> +{
> +    TCGHelperInfo *info;
> +    uint32_t hash = tcg_helper_func_hash(orig->func);
> +
> +    /*
> +     * Use the full TCGHelperInfo lookup, since there is no guarantee that func
> +     * will be unique to each TCGHelperInfo. For instance, we could have the
> +     * same helper function registered in several TCGHelperInfo's, each of them
> +     * with different flags.
> +     */
> +    info = qht_lookup(&helper_table, orig, hash);
> +    if (info == NULL) {
> +        void *existing = NULL;
> +
> +        /* @orig might be in the stack, so we need to allocate a new struct */
> +        info = g_new(TCGHelperInfo, 1);
> +        memcpy(info, orig, sizeof(TCGHelperInfo));
> +        qht_insert(&helper_table, info, hash, &existing);
> +        if (unlikely(existing)) {
> +            g_free(info);
> +            info = existing;
> +        }
> +    }
> +    do_tcg_gen_callN(info, ret, nargs, args);
> +}
> +
>  static void tcg_reg_alloc_start(TCGContext *s)
>  {
>      int i, n;


--
Alex Bennée
diff mbox series

Patch

diff --git a/tcg/tcg.h b/tcg/tcg.h
index 9f9643b470..3fa434d891 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -1077,6 +1077,8 @@  do {\
 bool tcg_op_supported(TCGOpcode op);
 
 void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args);
+void tcg_gen_runtime_helper(const TCGHelperInfo *orig, TCGTemp *ret, int nargs,
+                            TCGTemp **args);
 
 TCGOp *tcg_emit_op(TCGOpcode opc);
 void tcg_op_remove(TCGContext *s, TCGOp *op);
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 08b6926894..87e02da740 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1642,15 +1642,13 @@  bool tcg_op_supported(TCGOpcode op)
 /* Note: we convert the 64 bit args to 32 bit and do some alignment
    and endian swap. Maybe it would be better to do the alignment
    and endian swap in tcg_reg_alloc_call(). */
-void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
+static void do_tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, int nargs,
+                             TCGTemp **args)
 {
     int i, real_args, nb_rets, pi;
     unsigned sizemask, flags;
-    TCGHelperInfo *info;
-    uint32_t hash = tcg_helper_func_hash(func);
     TCGOp *op;
 
-    info = qht_lookup_custom(&helper_table, func, hash, tcg_helper_lookup_cmp);
     flags = info->flags;
     sizemask = info->sizemask;
 
@@ -1774,7 +1772,7 @@  void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
         op->args[pi++] = temp_arg(args[i]);
         real_args++;
     }
-    op->args[pi++] = (uintptr_t)func;
+    op->args[pi++] = (uintptr_t)info->func;
     op->args[pi++] = flags;
     TCGOP_CALLI(op) = real_args;
 
@@ -1812,6 +1810,48 @@  void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
 #endif /* TCG_TARGET_EXTEND_ARGS */
 }
 
+void tcg_gen_callN(void *func, TCGTemp *ret, int nargs, TCGTemp **args)
+{
+    TCGHelperInfo *info;
+    uint32_t hash = tcg_helper_func_hash(func);
+
+    /*
+     * Here we can get away with tcg_helper_lookup_cmp, which only looks
+     * at the function pointer, since we have the compile-time guarantee
+     * that @func can only be in one TCGHelperInfo.
+     */
+    info = qht_lookup_custom(&helper_table, func, hash, tcg_helper_lookup_cmp);
+    do_tcg_gen_callN(info, ret, nargs, args);
+}
+
+void tcg_gen_runtime_helper(const TCGHelperInfo *orig, TCGTemp *ret, int nargs,
+                            TCGTemp **args)
+{
+    TCGHelperInfo *info;
+    uint32_t hash = tcg_helper_func_hash(orig->func);
+
+    /*
+     * Use the full TCGHelperInfo lookup, since there is no guarantee that func
+     * will be unique to each TCGHelperInfo. For instance, we could have the
+     * same helper function registered in several TCGHelperInfo's, each of them
+     * with different flags.
+     */
+    info = qht_lookup(&helper_table, orig, hash);
+    if (info == NULL) {
+        void *existing = NULL;
+
+        /* @orig might be in the stack, so we need to allocate a new struct */
+        info = g_new(TCGHelperInfo, 1);
+        memcpy(info, orig, sizeof(TCGHelperInfo));
+        qht_insert(&helper_table, info, hash, &existing);
+        if (unlikely(existing)) {
+            g_free(info);
+            info = existing;
+        }
+    }
+    do_tcg_gen_callN(info, ret, nargs, args);
+}
+
 static void tcg_reg_alloc_start(TCGContext *s)
 {
     int i, n;