From 434d1f6cbc8e3d02dc974f160ed8a4c68f584d7a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 24 Aug 2026 23:40:51 +0100 Subject: [PATCH] asm: implement liveness stale checks --- src/check_asm_cfg.cpp | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/check_asm_cfg.cpp b/src/check_asm_cfg.cpp index be86c91b1..a6c717b27 100644 --- a/src/check_asm_cfg.cpp +++ b/src/check_asm_cfg.cpp @@ -664,10 +664,12 @@ gb_internal bool check_asm_cfg_liveness(AsmCtx *asm_ctx, AsmCfg *cfg, Entity *en u16 const REG_TOP = asm_ctx->CLOBBER_REGS_NAMED; u16 exit_live = 0; + u16 output_regs = 0; for_array(i, entity->AsmTemplate.decls) { auto const &ed = entity->AsmTemplate.decls[i]; if (ed.param_group == AsmTemplateEntityDeclParamGroup_Output) { - exit_live |= cfg->decl_pin_bit[i]; // pinned/view-inherited output reg, if any + exit_live |= cfg->decl_pin_bit[i]; // pinned/view-inherited output reg, if any + output_regs |= cfg->decl_pin_bit[i]; } } for (String const ® : entity->AsmTemplate.clobber_registers_set) { @@ -753,9 +755,16 @@ gb_internal bool check_asm_cfg_liveness(AsmCtx *asm_ctx, AsmCfg *cfg, Entity *en if ((dead & bit) == 0) { continue; } - warning(f->node->name, - "'%.*s' writes %%%s but its value is never read before being overwritten or the template ends", - LIT(f->name), asm_ctx->clobber_reg_bit_name(bit)); + if ((bit & output_regs) != 0) { + warning(f->node->name, + "'%.*s' writes output register %%%s, but that value is overwritten before the template returns; " + "the output's final value does not come from this instruction", + LIT(f->name), asm_ctx->clobber_reg_bit_name(bit)); + } else { + warning(f->node->name, + "'%.*s' writes %%%s but its value is never read before being overwritten or the template ends", + LIT(f->name), asm_ctx->clobber_reg_bit_name(bit)); + } } live = (live & ~f->gen_regs) | (f->read_regs & REG_TOP); }