tcg: Pass tb and index to tcg_gen_exit_tb separately

Do the cast to uintptr_t within the helper, so that the compiler
can type check the pointer argument. We can also do some more
sanity checking of the index argument.

Backports commit 07ea28b41830f946de3841b0ac61a3413679feb9 from qemu
This commit is contained in:
Richard Henderson 2018-06-07 11:56:25 -04:00 committed by Lioncash
parent 330bb60809
commit 10e2b13650
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
10 changed files with 64 additions and 34 deletions

View file

@ -50,7 +50,7 @@ static inline void gen_tb_start(TCGContext *tcg_ctx, TranslationBlock *tb)
static inline void gen_tb_end(TCGContext *tcg_ctx, TranslationBlock *tb, int num_insns)
{
gen_set_label(tcg_ctx, tcg_ctx->exitreq_label);
tcg_gen_exit_tb(tcg_ctx, (uintptr_t)tb + TB_EXIT_REQUESTED);
tcg_gen_exit_tb(tcg_ctx, tb, TB_EXIT_REQUESTED);
#if 0
if (tb->cflags & CF_USE_ICOUNT) {

View file

@ -404,7 +404,7 @@ static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
if (use_goto_tb(s, n, dest)) {
tcg_gen_goto_tb(tcg_ctx, n);
gen_a64_set_pc_im(s, dest);
tcg_gen_exit_tb(tcg_ctx, (intptr_t)tb + n);
tcg_gen_exit_tb(tcg_ctx, tb, n);
s->base.is_jmp = DISAS_NORETURN;
} else {
gen_a64_set_pc_im(s, dest);
@ -14070,7 +14070,7 @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
gen_a64_set_pc_im(dc, dc->pc);
/* fall through */
case DISAS_EXIT:
tcg_gen_exit_tb(tcg_ctx, 0);
tcg_gen_exit_tb(tcg_ctx, NULL, 0);
break;
case DISAS_JUMP:
tcg_gen_lookup_and_goto_ptr(tcg_ctx);
@ -14099,7 +14099,7 @@ static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
/* The helper doesn't necessarily throw an exception, but we
* must go back to the main loop to check for interrupts anyway.
*/
tcg_gen_exit_tb(tcg_ctx, 0);
tcg_gen_exit_tb(tcg_ctx, NULL, 0);
break;
}
}

View file

@ -1028,7 +1028,7 @@ static inline void gen_bx_excret_final_code(DisasContext *s)
if (is_singlestepping(s)) {
gen_singlestep_exception(s);
} else {
tcg_gen_exit_tb(tcg_ctx, 0);
tcg_gen_exit_tb(tcg_ctx, NULL, 0);
}
gen_set_label(tcg_ctx, excret_label);
/* Yes: this is an exception return.
@ -4376,7 +4376,7 @@ static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
if (use_goto_tb(s, dest)) {
tcg_gen_goto_tb(tcg_ctx, n);
gen_set_pc_im(s, dest);
tcg_gen_exit_tb(tcg_ctx, (uintptr_t)s->base.tb + n);
tcg_gen_exit_tb(tcg_ctx, s->base.tb, n);
} else {
gen_set_pc_im(s, dest);
gen_goto_ptr(s);
@ -12907,7 +12907,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
/* fall through */
default:
/* indicate that the hash table must be used to find the next TB */
tcg_gen_exit_tb(tcg_ctx, 0);
tcg_gen_exit_tb(tcg_ctx, NULL, 0);
break;
case DISAS_NORETURN:
/* nothing more to generate */
@ -12922,7 +12922,7 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
/* The helper doesn't necessarily throw an exception, but we
* must go back to the main loop to check for interrupts anyway.
*/
tcg_gen_exit_tb(tcg_ctx, 0);
tcg_gen_exit_tb(tcg_ctx, NULL, 0);
break;
}
case DISAS_WFE:

View file

@ -2464,7 +2464,7 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num, target_ulong eip)
/* jump to same page: we can use a direct jump */
tcg_gen_goto_tb(tcg_ctx, tb_num);
gen_jmp_im(s, eip);
tcg_gen_exit_tb(tcg_ctx, (uintptr_t)s->base.tb + tb_num);
tcg_gen_exit_tb(tcg_ctx, s->base.tb, tb_num);
s->base.is_jmp = DISAS_NORETURN;
} else {
/* jump to another page */
@ -2904,13 +2904,13 @@ do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, bool jr)
gen_helper_debug(tcg_ctx, tcg_ctx->cpu_env);
} else if (recheck_tf) {
gen_helper_rechecking_single_step(tcg_ctx, tcg_ctx->cpu_env);
tcg_gen_exit_tb(tcg_ctx, 0);
tcg_gen_exit_tb(tcg_ctx, NULL, 0);
} else if (s->tf) {
gen_helper_single_step(tcg_ctx, tcg_ctx->cpu_env);
} else if (jr) {
tcg_gen_lookup_and_goto_ptr(tcg_ctx);
} else {
tcg_gen_exit_tb(tcg_ctx, 0);
tcg_gen_exit_tb(tcg_ctx, NULL, 0);
}
s->base.is_jmp = DISAS_NORETURN;
}
@ -8030,7 +8030,7 @@ case 0x101:
gen_helper_vmrun(tcg_ctx, cpu_env,
tcg_const_i32(tcg_ctx, s->aflag - 1),
tcg_const_i32(tcg_ctx, s->pc - pc_start));
tcg_gen_exit_tb(tcg_ctx, 0);
tcg_gen_exit_tb(tcg_ctx, NULL, 0);
s->base.is_jmp = DISAS_NORETURN;
break;

View file

@ -1528,10 +1528,10 @@ static void gen_jmp_tb(DisasContext *s, int n, uint32_t dest)
} else if (use_goto_tb(s, dest)) {
tcg_gen_goto_tb(tcg_ctx, n);
tcg_gen_movi_i32(tcg_ctx, tcg_ctx->QREG_PC, dest);
tcg_gen_exit_tb(tcg_ctx, (uintptr_t)s->tb + n);
tcg_gen_exit_tb(tcg_ctx, s->tb, n);
} else {
gen_jmp_im(s, dest);
tcg_gen_exit_tb(tcg_ctx, 0);
tcg_gen_exit_tb(tcg_ctx, NULL, 0);
}
s->is_jmp = DISAS_TB_JUMP;
}
@ -6416,7 +6416,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb)
case DISAS_UPDATE:
update_cc_op(dc);
/* indicate that the hash table must be used to find the next TB */
tcg_gen_exit_tb(tcg_ctx, 0);
tcg_gen_exit_tb(tcg_ctx, NULL, 0);
break;
case DISAS_TB_JUMP:
/* nothing more to generate */

View file

@ -4350,7 +4350,7 @@ static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
if (use_goto_tb(ctx, dest)) {
tcg_gen_goto_tb(tcg_ctx, n);
gen_save_pc(ctx, dest);
tcg_gen_exit_tb(tcg_ctx, (uintptr_t)ctx->base.tb + n);
tcg_gen_exit_tb(tcg_ctx, ctx->base.tb, n);
} else {
gen_save_pc(ctx, dest);
if (ctx->base.singlestep_enabled) {
@ -20534,7 +20534,7 @@ static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
gen_goto_tb(ctx, 0, ctx->base.pc_next);
break;
case DISAS_EXIT:
tcg_gen_exit_tb(tcg_ctx, 0);
tcg_gen_exit_tb(tcg_ctx, NULL, 0);
break;
case DISAS_NORETURN:
break;

View file

@ -359,12 +359,12 @@ static inline void gen_goto_tb(DisasContext *s, int tb_num,
tcg_gen_goto_tb(tcg_ctx, tb_num);
tcg_gen_movi_tl(tcg_ctx, tcg_ctx->sparc_cpu_pc, pc);
tcg_gen_movi_tl(tcg_ctx, tcg_ctx->cpu_npc, npc);
tcg_gen_exit_tb(tcg_ctx, (uintptr_t)s->base.tb + tb_num);
tcg_gen_exit_tb(tcg_ctx, s->base.tb, tb_num);
} else {
/* jump to another page: currently not optimized */
tcg_gen_movi_tl(tcg_ctx, tcg_ctx->sparc_cpu_pc, pc);
tcg_gen_movi_tl(tcg_ctx, tcg_ctx->cpu_npc, npc);
tcg_gen_exit_tb(tcg_ctx, 0);
tcg_gen_exit_tb(tcg_ctx, NULL, 0);
}
}
@ -4510,7 +4510,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins
/* End TB to notice changed ASI. */
save_state(dc);
gen_op_next_insn(dc);
tcg_gen_exit_tb(tcg_ctx, 0);
tcg_gen_exit_tb(tcg_ctx, NULL, 0);
dc->base.is_jmp = DISAS_NORETURN;
break;
case 0x6: /* V9 wrfprs */
@ -4519,7 +4519,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins
dc->fprs_dirty = 0;
save_state(dc);
gen_op_next_insn(dc);
tcg_gen_exit_tb(tcg_ctx, 0);
tcg_gen_exit_tb(tcg_ctx, NULL, 0);
dc->base.is_jmp = DISAS_NORETURN;
break;
case 0xf: /* V9 sir, nop if user */
@ -4647,7 +4647,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins
dc->cc_op = CC_OP_FLAGS;
save_state(dc);
gen_op_next_insn(dc);
tcg_gen_exit_tb(tcg_ctx, 0);
tcg_gen_exit_tb(tcg_ctx, NULL, 0);
dc->base.is_jmp = DISAS_NORETURN;
#endif
}
@ -4803,7 +4803,7 @@ static void disas_sparc_insn(DisasContext * dc, unsigned int insn, bool hook_ins
hpstate));
save_state(dc);
gen_op_next_insn(dc);
tcg_gen_exit_tb(tcg_ctx, 0);
tcg_gen_exit_tb(tcg_ctx, NULL, 0);
dc->base.is_jmp = DISAS_NORETURN;
break;
case 1: // htstate
@ -5979,7 +5979,7 @@ static bool sparc_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
save_state(dc);
}
gen_helper_debug(tcg_ctx, tcg_ctx->cpu_env);
tcg_gen_exit_tb(tcg_ctx, 0);
tcg_gen_exit_tb(tcg_ctx, NULL, 0);
dc->base.is_jmp = DISAS_NORETURN;
/* update pc_next so that the current instruction is included in tb->size */
dc->base.pc_next += 4;
@ -6026,7 +6026,7 @@ static void sparc_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
tcg_gen_movi_tl(tcg_ctx, tcg_ctx->sparc_cpu_pc, dc->pc);
}
save_npc(dc);
tcg_gen_exit_tb(tcg_ctx, 0);
tcg_gen_exit_tb(tcg_ctx, NULL, 0);
}
}
}

View file

@ -2588,10 +2588,30 @@ void tcg_gen_extr32_i64(TCGContext *s, TCGv_i64 lo, TCGv_i64 hi, TCGv_i64 arg)
/* QEMU specific operations. */
void tcg_gen_exit_tb(TCGContext *s, TranslationBlock *tb, unsigned idx)
{
uintptr_t val = (uintptr_t)tb + idx;
if (tb == NULL) {
tcg_debug_assert(idx == 0);
} else if (idx <= TB_EXIT_IDXMAX) {
#ifdef CONFIG_DEBUG_TCG
/* This is an exit following a goto_tb. Verify that we have
seen this numbered exit before, via tcg_gen_goto_tb. */
tcg_debug_assert(tcg_ctx->goto_tb_issue_mask & (1 << idx));
#endif
} else {
/* This is an exit via the exitreq label. */
tcg_debug_assert(idx == TB_EXIT_REQUESTED);
}
tcg_gen_op1i(s, INDEX_op_exit_tb, val);
}
void tcg_gen_goto_tb(TCGContext *s, unsigned idx)
{
/* We only support two chained exits. */
tcg_debug_assert(idx <= 1);
tcg_debug_assert(idx <= TB_EXIT_IDXMAX);
#ifdef CONFIG_DEBUG_TCG
/* Verify that we havn't seen this numbered exit before. */
tcg_debug_assert((s->goto_tb_issue_mask & (1 << idx)) == 0);
@ -2608,7 +2628,7 @@ void tcg_gen_lookup_and_goto_ptr(TCGContext *s)
tcg_gen_op1i(s, INDEX_op_goto_ptr, tcgv_ptr_arg(s, ptr));
tcg_temp_free_ptr(s, ptr);
} else {
tcg_gen_exit_tb(s, 0);
tcg_gen_exit_tb(s, NULL, 0);
}
}

View file

@ -789,10 +789,19 @@ static inline void tcg_gen_insn_start(TCGContext *tcg_ctx, target_ulong pc, targ
# error "Unhandled number of operands to insn_start"
#endif
static inline void tcg_gen_exit_tb(TCGContext *s, uintptr_t val)
{
tcg_gen_op1i(s, INDEX_op_exit_tb, val);
}
/**
* tcg_gen_exit_tb() - output exit_tb TCG operation
* @tb: The TranslationBlock from which we are exiting
* @idx: Direct jump slot index, or exit request
*
* See tcg/README for more info about this TCG operation.
* See also tcg.h and the block comment above TB_EXIT_MASK.
*
* For a normal exit from the TB, back to the main loop, @tb should
* be NULL and @idx should be 0. Otherwise, @tb should be valid and
* @idx should be one of the TB_EXIT_ values.
*/
void tcg_gen_exit_tb(TCGContext *s, TranslationBlock *tb, unsigned idx);
/**
* tcg_gen_goto_tb() - output goto_tb TCG operation

View file

@ -1373,9 +1373,10 @@ static inline unsigned get_mmuidx(TCGMemOpIdx oi)
* to this default (which just calls the prologue.code emitted by
* tcg_target_qemu_prologue()).
*/
#define TB_EXIT_MASK 3
#define TB_EXIT_IDX0 0
#define TB_EXIT_IDX1 1
#define TB_EXIT_MASK 3
#define TB_EXIT_IDX0 0
#define TB_EXIT_IDX1 1
#define TB_EXIT_IDXMAX 1
#define TB_EXIT_ICOUNT_EXPIRED 2
#define TB_EXIT_REQUESTED 3