On Fri, 18 Sep 2026 13:10:07 PDT (-0700), Richard Henderson wrote:
With vtype uninitialized, VILL might be set, leading to SIGILL.
Also, assert vtype initialized for whole-register stores and moves.
Cc: Palmer Dabbelt <[email protected]>
Reported-by: Max Chou <[email protected]>
Signed-off-by: Richard Henderson <[email protected]>
---
tcg/riscv64/tcg-target.c.inc | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/tcg/riscv64/tcg-target.c.inc b/tcg/riscv64/tcg-target.c.inc
index 2ce9d47a633..de9a3570b23 100644
--- a/tcg/riscv64/tcg-target.c.inc
+++ b/tcg/riscv64/tcg-target.c.inc
@@ -775,6 +775,7 @@ static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg
ret, TCGReg arg)
case TCG_TYPE_V64:
case TCG_TYPE_V128:
case TCG_TYPE_V256:
+ tcg_debug_assert(s->riscv_cur_type != TCG_TYPE_COUNT);
{
int lmul = type - riscv_lg2_vlenb;
int nf = 1 << MAX(lmul, 0);
@@ -1014,6 +1015,10 @@ static void tcg_out_ld(TCGContext *s, TCGType type,
TCGReg arg,
unsigned idx = type - riscv_lg2_vlenb;
tcg_debug_assert(idx < ARRAY_SIZE(whole_reg_ld));
+ /* We must initialize vtype to something to avoid VILL. */
+ if (s->riscv_cur_type == TCG_TYPE_COUNT) {
+ set_vtype(s, type, MO_8);
+ }
insn = whole_reg_ld[idx];
} else {
static const RISCVInsn unit_stride_ld[] = {
@@ -1046,6 +1051,7 @@ static void tcg_out_st(TCGContext *s, TCGType type,
TCGReg arg,
case TCG_TYPE_V64:
case TCG_TYPE_V128:
case TCG_TYPE_V256:
+ tcg_debug_assert(s->riscv_cur_type != TCG_TYPE_COUNT);
if (type >= riscv_lg2_vlenb) {
static const RISCVInsn whole_reg_st[] = {
OPC_VS1R_V, OPC_VS2R_V, OPC_VS4R_V, OPC_VS8R_V
Thanks! Looks like it was just a lurking bug then.
Reviewed-by: Palmer Dabbelt <[email protected]>
and
Fixes: f63e7089b4 ("tcg/riscv: Add basic support for vector")
though that's old enough I'm not sure it really matters.
It looks like we're clobbering vtype and the rest of the V registers on calls,
so I think we're good there.
I poked through and it looks like every other case that constructs a V
instruction that depends on the vector configuration has a vtype set
immediately before it, so I think the rest of the port is safe. That said, if
I understand the ISA correctly, we need a valid vector configuration before
executing any V instruction (assuming the post-change ISA), so I think we could
also just throw something like this in there and maybe catch some mistakes in
the future?
diff --git a/tcg/riscv64/tcg-target.c.inc b/tcg/riscv64/tcg-target.c.inc
index 2ce9d47a63..42fcc8182e 100644
--- a/tcg/riscv64/tcg-target.c.inc
+++ b/tcg/riscv64/tcg-target.c.inc
@@ -686,18 +686,21 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
static void tcg_out_opc_vv(TCGContext *s, RISCVInsn opc,
TCGReg vd, TCGReg vs2, TCGReg vs1)
{
+ tcg_debug_assert(s->riscv_cur_type != TCG_TYPE_COUNT);
tcg_out32(s, encode_v(opc, vd, vs1, vs2, true));
}
static void tcg_out_opc_vx(TCGContext *s, RISCVInsn opc,
TCGReg vd, TCGReg vs2, TCGReg rs1)
{
+ tcg_debug_assert(s->riscv_cur_type != TCG_TYPE_COUNT);
tcg_out32(s, encode_v(opc, vd, rs1, vs2, true));
}
static void tcg_out_opc_vi(TCGContext *s, RISCVInsn opc,
TCGReg vd, TCGReg vs2, int32_t imm)
{
+ tcg_debug_assert(s->riscv_cur_type != TCG_TYPE_COUNT);
tcg_out32(s, encode_vi(opc, vd, imm, vs2, true));
}
@@ -714,12 +717,14 @@ static void tcg_out_opc_vv_vi(TCGContext *s, RISCVInsn
o_vv, RISCVInsn o_vi,
static void tcg_out_opc_vim_mask(TCGContext *s, RISCVInsn opc, TCGReg vd,
TCGReg vs2, int32_t imm)
{
+ tcg_debug_assert(s->riscv_cur_type != TCG_TYPE_COUNT);
tcg_out32(s, encode_vi(opc, vd, imm, vs2, false));
}
static void tcg_out_opc_vvm_mask(TCGContext *s, RISCVInsn opc, TCGReg vd,
TCGReg vs2, TCGReg vs1)
{
+ tcg_debug_assert(s->riscv_cur_type != TCG_TYPE_COUNT);
tcg_out32(s, encode_v(opc, vd, vs1, vs2, false));
}
@@ -978,6 +983,7 @@ static void tcg_out_vec_ldst(TCGContext *s, RISCVInsn opc,
TCGReg data,
{
tcg_debug_assert(data >= TCG_REG_V0);
tcg_debug_assert(addr < TCG_REG_V0);
+ tcg_debug_assert(s->riscv_cur_type != TCG_TYPE_COUNT);
if (offset) {
tcg_debug_assert(addr != TCG_REG_ZERO);
@@ -1554,6 +1560,7 @@ static void tcg_out_cmpsel(TCGContext *s, TCGType type,
unsigned vece,
static void tcg_out_vshifti(TCGContext *s, RISCVInsn opc_vi, RISCVInsn opc_vx,
TCGReg dst, TCGReg src, unsigned imm)
{
+ tcg_debug_assert(s->riscv_cur_type != TCG_TYPE_COUNT);
if (imm < 32) {
tcg_out_opc_vi(s, opc_vi, dst, src, imm);
} else {