From 811672be4ba81818a285fc371d95612505cdf000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Motiejus=20Jak=C5=A1tys?= Date: Fri, 13 Feb 2026 22:11:01 +0000 Subject: [PATCH] astgen: add isAlwaysVoid and endsWithNoReturn checks to rvalue Port two missing checks from upstream AstGen.zig rvalueInner to the C rvalue function: 1. isAlwaysVoid (Zir.zig:1343-1608): When the result refers to an instruction that always produces void (e.g., dbg_stmt, store_node, export, memcpy, etc.), replace the result with void_value before proceeding. This prevents emitting unnecessary type coercions or stores on always-void instructions. 2. endsWithNoReturn (AstGen.zig:11068): When the current GenZir block ends with a noreturn instruction, return the result immediately without emitting any rvalue instructions. This avoids emitting dead ZIR instructions after noreturn. Co-Authored-By: Claude Opus 4.6 --- astgen.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/astgen.c b/astgen.c index 4342bd7a38..9206a2fed3 100644 --- a/astgen.c +++ b/astgen.c @@ -1906,9 +1906,72 @@ static uint32_t rlResultType(GenZir* gz, ResultLoc rl, uint32_t node) { } } +static bool endsWithNoReturn(GenZir* gz); + +// Mirrors Zir.Inst.Tag.isAlwaysVoid (Zir.zig:1343-1608). +static bool isAlwaysVoid(ZirInstTag tag, ZirInstData data) { + switch (tag) { + case ZIR_INST_DBG_STMT: + case ZIR_INST_DBG_VAR_PTR: + case ZIR_INST_DBG_VAR_VAL: + case ZIR_INST_ENSURE_RESULT_USED: + case ZIR_INST_ENSURE_RESULT_NON_ERROR: + case ZIR_INST_ENSURE_ERR_UNION_PAYLOAD_VOID: + case ZIR_INST_SET_EVAL_BRANCH_QUOTA: + case ZIR_INST_ATOMIC_STORE: + case ZIR_INST_STORE_NODE: + case ZIR_INST_STORE_TO_INFERRED_PTR: + case ZIR_INST_VALIDATE_DEREF: + case ZIR_INST_VALIDATE_DESTRUCTURE: + case ZIR_INST_EXPORT: + case ZIR_INST_SET_RUNTIME_SAFETY: + case ZIR_INST_MEMCPY: + case ZIR_INST_MEMSET: + case ZIR_INST_MEMMOVE: + case ZIR_INST_CHECK_COMPTIME_CONTROL_FLOW: + case ZIR_INST_DEFER: + case ZIR_INST_DEFER_ERR_CODE: + case ZIR_INST_SAVE_ERR_RET_INDEX: + case ZIR_INST_RESTORE_ERR_RET_INDEX_UNCONDITIONAL: + case ZIR_INST_RESTORE_ERR_RET_INDEX_FN_ENTRY: + case ZIR_INST_VALIDATE_STRUCT_INIT_TY: + case ZIR_INST_VALIDATE_STRUCT_INIT_RESULT_TY: + case ZIR_INST_VALIDATE_PTR_STRUCT_INIT: + case ZIR_INST_VALIDATE_ARRAY_INIT_TY: + case ZIR_INST_VALIDATE_ARRAY_INIT_RESULT_TY: + case ZIR_INST_VALIDATE_PTR_ARRAY_INIT: + case ZIR_INST_VALIDATE_REF_TY: + case ZIR_INST_VALIDATE_CONST: + return true; + case ZIR_INST_EXTENDED: + switch (data.extended.opcode) { + case ZIR_EXT_BRANCH_HINT: + case ZIR_EXT_BREAKPOINT: + case ZIR_EXT_DISABLE_INSTRUMENTATION: + case ZIR_EXT_DISABLE_INTRINSICS: + return true; + default: + return false; + } + default: + return false; + } +} + // rvalue (AstGen.zig:11051-11224): apply result location wrapping. static uint32_t rvalue( GenZir* gz, ResultLoc rl, uint32_t result, uint32_t node) { + // isAlwaysVoid check (AstGen.zig:11058-11067). + if (result >= ZIR_REF_START_INDEX) { + uint32_t result_index = result - ZIR_REF_START_INDEX; + if (isAlwaysVoid(gz->astgen->inst_tags[result_index], + gz->astgen->inst_datas[result_index])) { + result = ZIR_REF_VOID_VALUE; + } + } + // endsWithNoReturn check (AstGen.zig:11068). + if (endsWithNoReturn(gz)) + return result; switch (rl.tag) { case RL_NONE: case RL_COERCED_TY: