From 75c91feb3619836cd48d57ab7b00d626b5b53596 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 19 Aug 2026 12:56:03 +0100 Subject: [PATCH] Check for output parameters not used but pinned; Check for templates with observable effects but not marked as `#volatile` --- src/check_asm.cpp | 25 ++++++++++++++++++++++++- src/entity.cpp | 3 +++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/check_asm.cpp b/src/check_asm.cpp index 89ce30a3c..124d65a3b 100644 --- a/src/check_asm.cpp +++ b/src/check_asm.cpp @@ -940,6 +940,8 @@ gb_internal void check_mnemonic(AsmCtx *asm_ctx, CheckerContext *ctx, Entity *tm tmpl_entity->AsmTemplate.clobber_memory |= clobber.implies_clobber_memory(); tmpl_entity->AsmTemplate.is_volatile |= clobber.implies_side_effects(); + tmpl_entity->AsmTemplate.has_observable_side_effect |= clobber.implies_side_effects() != 0; + tmpl_entity->AsmTemplate.has_observable_side_effect |= clobber.writes_mem; u16 pinned_mask = 0; for (auto const &ed : tmpl_entity->AsmTemplate.decls) { @@ -1612,7 +1614,6 @@ gb_internal void check_asm_template(AsmCtx *asm_ctx, CheckerContext *ctx, Entity } } - Array operands = {}; operands.allocator = heap_allocator(); array_reserve(&operands, 16); @@ -1766,6 +1767,28 @@ gb_internal void check_asm_template(AsmCtx *asm_ctx, CheckerContext *ctx, Entity if (previous_prefix != 0) { error(previous_prefix_instr, "A prefix must be immediately followed by an instruction, but the template ended"); } + + for (auto const &ed : ate->decls) { + if (!(ed.param_group == AsmTemplateEntityDeclParamGroup_Output && ed.pin.len != 0)) { + continue; + } + u16 bit = asm_ctx->clobber_bit_for_reg_name(ed.pin); + if (bit && (defined_regs & bit) == 0 && straight_line) { + error(ed.entity->token, + "Output '%.*s' is pinned to %%%.*s but nothing in this template writes it", + LIT(ed.entity->token.string), LIT(ed.pin)); + } + } + + GB_ASSERT(entity->kind == Entity_AsmTemplate); + if (results->Tuple.variables.count == 0 && !entity->AsmTemplate.is_volatile && + !entity->AsmTemplate.clobber_memory && + entity->AsmTemplate.has_observable_side_effect) { + warning(entity->token, + "This asm template has an observable effect but declares no outputs " + "and does not #volatile in the specification block; it may be optimized away. " + "Please add #volatile if the effect is intended."); + } } gb_internal void check_asm_template_from_entity(CheckerContext *c, Entity *e, DeclInfo *d) { diff --git a/src/entity.cpp b/src/entity.cpp index 8248515f4..e21ec4483 100644 --- a/src/entity.cpp +++ b/src/entity.cpp @@ -346,6 +346,9 @@ struct Entity { bool is_volatile; bool is_align_stack; + bool has_observable_side_effect; + + bool clobber_flags; bool clobber_memory; StringSet clobber_registers_set;