Skip to content

Commit a6b298f

Browse files
authored
Support for i128 tcg temp (#51) + add -Werror and fix compilation warnings
* Added testcase and binary for i128. * Add symbolic handling for i128. * Enable werror and tcg debug asserts, fix compilation warnings. * Fix casting error appearing with GCC 13. (to reproduce, compile QEMU with gcc 13 using --cc).
1 parent adc2711 commit a6b298f

File tree

16 files changed

+193
-52
lines changed

16 files changed

+193
-52
lines changed

Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ RUN ./configure \
3535
--target-list=x86_64-linux-user,riscv64-linux-user \
3636
--enable-debug \
3737
--symcc-source=/symcc \
38-
--symcc-build=/symcc/build
38+
--symcc-build=/symcc/build \
39+
--enable-debug-tcg \
40+
--enable-werror
3941

4042
RUN make -j
4143

accel/tcg/tcg-runtime-sym-vec.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ void *HELPER(sym_cmp_vec)(
387387
CPUArchState *env,
388388
void *arg1_concrete, void *arg1_symbolic,
389389
void *arg2_concrete, void *arg2_symbolic,
390-
TCGCond comparison_operator, void *result_concrete,
390+
/* TCGCond */ uint32_t comparison_operator, void *result_concrete,
391391
uint64_t vector_size, uint64_t vece
392392
) {
393393
g_assert(vector_size == 64 || vector_size == 128 || vector_size == 256);
@@ -468,7 +468,7 @@ void *HELPER(sym_ternary_vec)(
468468
CPUArchState *env,
469469
void *arg1_concrete, void *arg1_symbolic,
470470
void *arg2_concrete, void *arg2_symbolic,
471-
TCGCond comparison_operator, void *concrete_result,
471+
/* TCGCond */ uint32_t comparison_operator, void *concrete_result,
472472
uint64_t vector_size, uint64_t vece
473473
) {
474474
g_assert(vector_size == 64 || vector_size == 128 || vector_size == 256);

include/tcg/tcg.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,8 @@ typedef struct TCGTemp {
416416
unsigned int temp_allocated:1;
417417
unsigned int temp_subindex:1;
418418

419+
/* Maximum len of subindex. Must be the same size as temp_subindex */
420+
unsigned int temp_subindex_len:1;
419421
/* If true, this temp contains a symbolic expression. */
420422
unsigned int symbolic_expression:1;
421423

@@ -632,10 +634,15 @@ static inline TCGTemp *tcgv_i32_temp(TCGv_i32 v)
632634
#endif
633635

634636
static inline TCGTemp *temp_expr(TCGTemp *ts) {
635-
tcg_debug_assert(temp_idx(ts) + 1 < tcg_ctx->nb_temps);
637+
// Length of subindex. For now, it can only be 0 or 1 (for i128)
638+
// Could become bigger in the future.
639+
unsigned char temp_sz = ts->temp_subindex_len;
640+
641+
tcg_debug_assert(temp_idx(ts) + temp_sz + 1 < tcg_ctx->nb_temps);
636642
tcg_debug_assert(!ts->symbolic_expression);
637-
tcg_debug_assert((ts + 1)->symbolic_expression);
638-
return ts + 1;
643+
tcg_debug_assert((ts + temp_sz + 1)->symbolic_expression);
644+
645+
return ts + temp_sz + 1;
639646
}
640647

641648
static inline TCGTemp *tcgv_i64_temp(TCGv_i64 v)

tcg/tcg-op-ldst.c

Lines changed: 76 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -453,31 +453,31 @@ void tcg_gen_qemu_st_i64_chk(TCGv_i64 val, TCGTemp *addr, TCGArg idx,
453453
* does not require 16-byte atomicity, and it would be adventagous
454454
* to avoid a call to a helper function.
455455
*/
456-
static bool use_two_i64_for_i128(MemOp mop)
457-
{
458-
#ifdef CONFIG_SOFTMMU
459-
/* Two softmmu tlb lookups is larger than one function call. */
460-
return false;
461-
#else
462-
/*
463-
* For user-only, two 64-bit operations may well be smaller than a call.
464-
* Determine if that would be legal for the requested atomicity.
465-
*/
466-
switch (mop & MO_ATOM_MASK) {
467-
case MO_ATOM_NONE:
468-
case MO_ATOM_IFALIGN_PAIR:
469-
return true;
470-
case MO_ATOM_IFALIGN:
471-
case MO_ATOM_SUBALIGN:
472-
case MO_ATOM_WITHIN16:
473-
case MO_ATOM_WITHIN16_PAIR:
474-
/* In a serialized context, no atomicity is required. */
475-
return !(tcg_ctx->gen_tb->cflags & CF_PARALLEL);
476-
default:
477-
g_assert_not_reached();
478-
}
479-
#endif
480-
}
456+
// static bool use_two_i64_for_i128(MemOp mop)
457+
// {
458+
// #ifdef CONFIG_SOFTMMU
459+
// /* Two softmmu tlb lookups is larger than one function call. */
460+
// return false;
461+
// #else
462+
// /*
463+
// * For user-only, two 64-bit operations may well be smaller than a call.
464+
// * Determine if that would be legal for the requested atomicity.
465+
// */
466+
// switch (mop & MO_ATOM_MASK) {
467+
// case MO_ATOM_NONE:
468+
// case MO_ATOM_IFALIGN_PAIR:
469+
// return true;
470+
// case MO_ATOM_IFALIGN:
471+
// case MO_ATOM_SUBALIGN:
472+
// case MO_ATOM_WITHIN16:
473+
// case MO_ATOM_WITHIN16_PAIR:
474+
// /* In a serialized context, no atomicity is required. */
475+
// return !(tcg_ctx->gen_tb->cflags & CF_PARALLEL);
476+
// default:
477+
// g_assert_not_reached();
478+
// }
479+
// #endif
480+
// }
481481

482482
static void canonicalize_memop_i128_as_i64(MemOp ret[2], MemOp orig)
483483
{
@@ -551,7 +551,7 @@ static void tcg_gen_qemu_ld_i128_int(TCGv_i128 val, TCGTemp *addr,
551551
tcg_gen_req_mo(TCG_MO_LD_LD | TCG_MO_ST_LD);
552552

553553
/* TODO: For now, force 32-bit hosts to use the helper. */
554-
if (TCG_TARGET_HAS_qemu_ldst_i128 && TCG_TARGET_REG_BITS == 64) {
554+
/* if (TCG_TARGET_HAS_qemu_ldst_i128 && TCG_TARGET_REG_BITS == 64) {
555555
TCGv_i64 lo, hi;
556556
bool need_bswap = false;
557557
MemOpIdx oi = orig_oi;
@@ -577,11 +577,13 @@ static void tcg_gen_qemu_ld_i128_int(TCGv_i128 val, TCGTemp *addr,
577577
tcg_gen_bswap64_i64(lo, lo);
578578
tcg_gen_bswap64_i64(hi, hi);
579579
}
580-
} else if (use_two_i64_for_i128(memop)) {
580+
} else if (use_two_i64_for_i128(memop)) { */
581+
// Always take this path to get symbolic propagation
581582
MemOp mop[2];
582583
TCGTemp *addr_p8;
583584
TCGv_i64 x, y;
584585
bool need_bswap;
586+
TCGv_i64 load_size, mmu_idx;
585587

586588
canonicalize_memop_i128_as_i64(mop, memop);
587589
need_bswap = (mop[0] ^ memop) & MO_BSWAP;
@@ -607,6 +609,14 @@ static void tcg_gen_qemu_ld_i128_int(TCGv_i128 val, TCGTemp *addr,
607609

608610
gen_ldst_i64(opc, x, addr, make_memop_idx(mop[0], idx));
609611

612+
/* Perform the symbolic memory access. Doing so _after_ the concrete
613+
* operation ensures that the target address is in the TLB. */
614+
mmu_idx = tcg_constant_i64(idx);
615+
load_size = tcg_constant_i64(1 << MO_64);
616+
gen_helper_sym_load_guest_i64(tcgv_i64_expr(x), cpu_env,
617+
temp_tcgv_i64(addr), tcgv_i64_expr(temp_tcgv_i64(addr)),
618+
load_size, mmu_idx);
619+
610620
if (need_bswap) {
611621
tcg_gen_bswap64_i64(x, x);
612622
}
@@ -622,20 +632,27 @@ static void tcg_gen_qemu_ld_i128_int(TCGv_i128 val, TCGTemp *addr,
622632
}
623633

624634
gen_ldst_i64(opc, y, addr_p8, make_memop_idx(mop[1], idx));
635+
636+
/* Perform the symbolic memory access. Doing so _after_ the concrete
637+
* operation ensures that the target address is in the TLB. */
638+
gen_helper_sym_load_guest_i64(tcgv_i64_expr(y), cpu_env,
639+
temp_tcgv_i64(addr_p8), tcgv_i64_expr(temp_tcgv_i64(addr_p8)),
640+
load_size, mmu_idx);
641+
625642
tcg_temp_free_internal(addr_p8);
626643

627644
if (need_bswap) {
628645
tcg_gen_bswap64_i64(y, y);
629646
}
630-
} else {
647+
/* } else {
631648
if (tcg_ctx->addr_type == TCG_TYPE_I32) {
632649
ext_addr = tcg_temp_ebb_new_i64();
633650
tcg_gen_extu_i32_i64(ext_addr, temp_tcgv_i32(addr));
634651
addr = tcgv_i64_temp(ext_addr);
635652
}
636653
gen_helper_ld_i128(val, cpu_env, temp_tcgv_i64(addr),
637654
tcg_constant_i32(orig_oi));
638-
}
655+
} */
639656

640657
plugin_gen_mem_callbacks(ext_addr, addr, orig_oi, QEMU_PLUGIN_MEM_R);
641658
}
@@ -661,7 +678,7 @@ static void tcg_gen_qemu_st_i128_int(TCGv_i128 val, TCGTemp *addr,
661678

662679
/* TODO: For now, force 32-bit hosts to use the helper. */
663680

664-
if (TCG_TARGET_HAS_qemu_ldst_i128 && TCG_TARGET_REG_BITS == 64) {
681+
/* if (TCG_TARGET_HAS_qemu_ldst_i128 && TCG_TARGET_REG_BITS == 64) {
665682
TCGv_i64 lo, hi;
666683
MemOpIdx oi = orig_oi;
667684
bool need_bswap = false;
@@ -689,10 +706,12 @@ static void tcg_gen_qemu_st_i128_int(TCGv_i128 val, TCGTemp *addr,
689706
tcg_temp_free_i64(lo);
690707
tcg_temp_free_i64(hi);
691708
}
692-
} else if (use_two_i64_for_i128(memop)) {
709+
} else if (use_two_i64_for_i128(memop)) { */
710+
// Always take this path to get symbolic propagation
693711
MemOp mop[2];
694712
TCGTemp *addr_p8;
695713
TCGv_i64 x, y, b = NULL;
714+
TCGv_i64 store_size, mmu_idx;
696715

697716
canonicalize_memop_i128_as_i64(mop, memop);
698717

@@ -718,6 +737,15 @@ static void tcg_gen_qemu_st_i128_int(TCGv_i128 val, TCGTemp *addr,
718737

719738
gen_ldst_i64(opc, x, addr, make_memop_idx(mop[0], idx));
720739

740+
/* Perform the symbolic memory access. Doing so _after_ the concrete
741+
* operation ensures that the target address is in the TLB. */
742+
mmu_idx = tcg_constant_i64(idx);
743+
store_size = tcg_constant_i64(1 << MO_64);
744+
gen_helper_sym_store_guest_i64(cpu_env,
745+
x, tcgv_i64_expr(x),
746+
temp_tcgv_i64(addr), tcgv_i64_expr(temp_tcgv_i64(addr)),
747+
store_size, mmu_idx);
748+
721749
if (tcg_ctx->addr_type == TCG_TYPE_I32) {
722750
TCGv_i32 t = tcg_temp_ebb_new_i32();
723751
tcg_gen_addi_i32(t, temp_tcgv_i32(addr), 8);
@@ -731,20 +759,35 @@ static void tcg_gen_qemu_st_i128_int(TCGv_i128 val, TCGTemp *addr,
731759
if (b) {
732760
tcg_gen_bswap64_i64(b, y);
733761
gen_ldst_i64(opc, b, addr_p8, make_memop_idx(mop[1], idx));
762+
763+
/* Perform the symbolic memory access. Doing so _after_ the concrete
764+
* operation ensures that the target address is in the TLB. */
765+
gen_helper_sym_store_guest_i64(cpu_env,
766+
b, tcgv_i64_expr(b),
767+
temp_tcgv_i64(addr_p8), tcgv_i64_expr(temp_tcgv_i64(addr_p8)),
768+
store_size, mmu_idx);
769+
734770
tcg_temp_free_i64(b);
735771
} else {
736772
gen_ldst_i64(opc, y, addr_p8, make_memop_idx(mop[1], idx));
773+
774+
/* Perform the symbolic memory access. Doing so _after_ the concrete
775+
* operation ensures that the target address is in the TLB. */
776+
gen_helper_sym_store_guest_i64(cpu_env,
777+
y, tcgv_i64_expr(y),
778+
temp_tcgv_i64(addr_p8), tcgv_i64_expr(temp_tcgv_i64(addr_p8)),
779+
store_size, mmu_idx);
737780
}
738781
tcg_temp_free_internal(addr_p8);
739-
} else {
782+
/* } else {
740783
if (tcg_ctx->addr_type == TCG_TYPE_I32) {
741784
ext_addr = tcg_temp_ebb_new_i64();
742785
tcg_gen_extu_i32_i64(ext_addr, temp_tcgv_i32(addr));
743786
addr = tcgv_i64_temp(ext_addr);
744787
}
745788
gen_helper_st_i128(cpu_env, temp_tcgv_i64(addr), val,
746789
tcg_constant_i32(orig_oi));
747-
}
790+
} */
748791

749792
plugin_gen_mem_callbacks(ext_addr, addr, orig_oi, QEMU_PLUGIN_MEM_W);
750793
}

tcg/tcg-op-vec.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ void vec_gen_4(TCGOpcode opc, TCGType type, unsigned vece,
279279
op->args[3] = c;
280280
}
281281

282-
static void vec_gen_6(TCGOpcode opc, TCGType type, unsigned vece, TCGArg r,
282+
/* static void vec_gen_6(TCGOpcode opc, TCGType type, unsigned vece, TCGArg r,
283283
TCGArg a, TCGArg b, TCGArg c, TCGArg d, TCGArg e)
284284
{
285285
TCGOp *op = tcg_emit_op(opc, 6);
@@ -291,7 +291,7 @@ static void vec_gen_6(TCGOpcode opc, TCGType type, unsigned vece, TCGArg r,
291291
op->args[3] = c;
292292
op->args[4] = d;
293293
op->args[5] = e;
294-
}
294+
} */
295295

296296
static void vec_gen_op2(TCGOpcode opc, unsigned vece, TCGv_vec r, TCGv_vec a)
297297
{
@@ -562,7 +562,7 @@ void tcg_gen_eqv_vec(unsigned vece, TCGv_vec r, TCGv_vec a, TCGv_vec b)
562562
/* } */
563563
}
564564

565-
static bool do_op2(unsigned vece, TCGv_vec r, TCGv_vec a, TCGOpcode opc)
565+
/* static bool do_op2(unsigned vece, TCGv_vec r, TCGv_vec a, TCGOpcode opc)
566566
{
567567
TCGTemp *rt = tcgv_vec_temp(r);
568568
TCGTemp *at = tcgv_vec_temp(a);
@@ -584,7 +584,7 @@ static bool do_op2(unsigned vece, TCGv_vec r, TCGv_vec a, TCGOpcode opc)
584584
return false;
585585
}
586586
return true;
587-
}
587+
} */
588588

589589
void tcg_gen_not_vec(unsigned vece, TCGv_vec r, TCGv_vec a)
590590
{
@@ -1067,14 +1067,14 @@ void tcg_gen_cmpsel_vec(TCGCond cond, unsigned vece, TCGv_vec r,
10671067
TCGTemp *bt = tcgv_vec_temp(b);
10681068
TCGTemp *ct = tcgv_vec_temp(c);
10691069
TCGTemp *dt = tcgv_vec_temp(d);
1070-
TCGArg ri = temp_arg(rt);
1070+
/* TCGArg ri = temp_arg(rt);
10711071
TCGArg ai = temp_arg(at);
10721072
TCGArg bi = temp_arg(bt);
10731073
TCGArg ci = temp_arg(ct);
1074-
TCGArg di = temp_arg(dt);
1074+
TCGArg di = temp_arg(dt); */
10751075
TCGType type = rt->base_type;
10761076
const TCGOpcode *hold_list;
1077-
int can;
1077+
/* int can; */
10781078

10791079
tcg_debug_assert(at->base_type >= type);
10801080
tcg_debug_assert(bt->base_type >= type);
@@ -1083,7 +1083,7 @@ void tcg_gen_cmpsel_vec(TCGCond cond, unsigned vece, TCGv_vec r,
10831083

10841084
tcg_assert_listed_vecop(INDEX_op_cmpsel_vec);
10851085
hold_list = tcg_swap_vecop_list(NULL);
1086-
can = tcg_can_emit_vec_op(INDEX_op_cmpsel_vec, type, vece);
1086+
/* can = tcg_can_emit_vec_op(INDEX_op_cmpsel_vec, type, vece); */
10871087

10881088
/*
10891089
TODO (SymQEMU):

tcg/tcg.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1509,6 +1509,7 @@ void tcg_func_start(TCGContext *s)
15091509

15101510
static TCGTemp *tcg_temp_alloc(TCGContext *s)
15111511
{
1512+
/* Not necessarily true with i128
15121513
int last_temp_idx = s->nb_temps - 1;
15131514
if (last_temp_idx > 0) {
15141515
if (last_temp_idx % 2 == 0) {
@@ -1517,6 +1518,7 @@ static TCGTemp *tcg_temp_alloc(TCGContext *s)
15171518
g_assert((s->temps[last_temp_idx].symbolic_expression));
15181519
}
15191520
}
1521+
*/
15201522

15211523
int n = s->nb_temps++;
15221524

@@ -1711,13 +1713,13 @@ TCGTemp *tcg_temp_new_internal(TCGType type, TCGTempKind kind)
17111713
ts->temp_allocated = 1;
17121714
ts->kind = kind;
17131715

1716+
// To change if subindex can take bigger values
1717+
tcg_debug_assert(n >= 0 && n - 1 <= 1);
1718+
ts->temp_subindex_len = n - 1;
1719+
17141720
if (n == 1) {
17151721
ts->type = type;
17161722
} else {
1717-
/* The current implementation of SymQEMU does not support this case
1718-
* as the symbolic version of a TCGTemp is expected to be located right after the concrete version */
1719-
g_assert_not_reached();
1720-
17211723
ts->type = TCG_TYPE_REG;
17221724

17231725
for (int i = 1; i < n; ++i) {
@@ -1728,6 +1730,7 @@ TCGTemp *tcg_temp_new_internal(TCGType type, TCGTempKind kind)
17281730
ts2->type = TCG_TYPE_REG;
17291731
ts2->temp_allocated = 1;
17301732
ts2->temp_subindex = i;
1733+
ts2->temp_subindex_len = n - 1;
17311734
ts2->kind = kind;
17321735
}
17331736
}
@@ -1736,9 +1739,29 @@ TCGTemp *tcg_temp_new_internal(TCGType type, TCGTempKind kind)
17361739
ts_expr->base_type = TCG_TYPE_PTR;
17371740
ts_expr->type = TCG_TYPE_PTR;
17381741
ts_expr->temp_allocated = 1;
1742+
ts_expr->temp_subindex = 0;
17391743
ts_expr->kind = kind;
17401744
ts_expr->symbolic_expression = 1;
17411745

1746+
// We allocate multiple symbolic expressions if n > 1 since TCG's i128 are
1747+
// split in 64 bits blocks for now, so it is more convenient.
1748+
// It could be more efficient to have 1 symbolic expression if later TCG's i128 are
1749+
// handled as a single block.
1750+
if (n > 1) {
1751+
for (int i = 1; i < n; ++i) {
1752+
TCGTemp *ts2_expr = tcg_temp_alloc(s);
1753+
1754+
tcg_debug_assert(ts2_expr == ts_expr + i);
1755+
tcg_debug_assert(ts2_expr == ts + n + i);
1756+
ts2_expr->base_type = TCG_TYPE_PTR;
1757+
ts2_expr->type = TCG_TYPE_PTR;
1758+
ts2_expr->temp_allocated = 1;
1759+
ts2_expr->temp_subindex = i;
1760+
ts2_expr->kind = kind;
1761+
ts2_expr->symbolic_expression = 1;
1762+
}
1763+
}
1764+
17421765
return ts;
17431766
}
17441767

0 commit comments

Comments
 (0)