This takes the TCGHelperInfo directly, which will allow us to generate helpers at run-time.
Signed-off-by: Emilio G. Cota <c...@braap.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; -- 2.17.1