Skip to content

Commit eee67f1

Browse files
committed
Rollback id_map on width validation failure to prevent undefined IDs
When width validation in emit_pattern detected a mismatch and returned None, IDs allocated by recursive emit_term calls remained in id_map. Later extractions could find these stale entries via constant dedup keys (e.g. "const_<type>_42"), referencing IDs for instructions that were never emitted — causing "use of undefined id" validation errors. Save next_id before the operand emission loop and restore it (along with pruning id_map) when width validation fails.
1 parent eb06849 commit eee67f1

1 file changed

Lines changed: 13 additions & 0 deletions

File tree

  • rust/spirv-tools-opt/src/direct

rust/spirv-tools-opt/src/direct/emit.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,9 @@ fn emit_pattern(
13251325
} else {
13261326
operand_type
13271327
};
1328+
// Save next_id before recursive emission so we can rollback
1329+
// id_map on width validation failure (see below).
1330+
let saved_next_id = *ctx.next_id;
13281331
let mut synth = Vec::new();
13291332
let mut operand_ids = Vec::with_capacity(arity);
13301333
for arg in &args[..arity] {
@@ -1337,13 +1340,23 @@ fn emit_pattern(
13371340
// and i64 are both IntExpr). When extraction picks a mismatched-width
13381341
// operand, the emitted instruction would be invalid. Bail out so the
13391342
// extraction loop keeps the original instruction.
1343+
//
1344+
// On failure, rollback id_map entries created by the recursive
1345+
// emit_term calls above. Without this, constant dedup keys
1346+
// (e.g. "const_<type>_42") would point to IDs that were allocated
1347+
// but never defined, causing "undefined id" errors downstream.
13401348
let result_width = ctx.type_widths.get(&op_result_type);
13411349
if result_width.is_some() && result_class == operand_class {
13421350
for op_id in &operand_ids {
13431351
if let rspirv::dr::Operand::IdRef(id) = op_id {
13441352
if let Some(arg_type) = ctx.id_to_type.get(id) {
13451353
let arg_width = ctx.type_widths.get(arg_type);
13461354
if arg_width.is_some() && arg_width != result_width {
1355+
// Rollback: remove all id_map entries whose
1356+
// values are IDs allocated during this attempt.
1357+
let rollback = saved_next_id;
1358+
*ctx.next_id = rollback;
1359+
ctx.id_map.retain(|_, v| *v < rollback);
13471360
return None;
13481361
}
13491362
}

0 commit comments

Comments
 (0)