From 7ebc5c462e7c3d140bd5b2f3cb3b75bf53e4aeea Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 24 Aug 2026 11:57:34 +0100 Subject: [PATCH] Correct `#pure` checking for internal branches and effect volatility --- src/check_asm.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/check_asm.cpp b/src/check_asm.cpp index cfe2614b2..61e439e76 100644 --- a/src/check_asm.cpp +++ b/src/check_asm.cpp @@ -1505,11 +1505,15 @@ gb_internal void check_mnemonic(AsmCtx *asm_ctx, CheckerContext *ctx, Entity *tm } bool mem_is_real = has_mem_operand || !has_rm_slot; + bool internal_branch = clobber.has_control() && check_asm_instr_targets_internal_label(instr); + + bool effective_side_effects = clobber.implies_side_effects() && !internal_branch; + tmpl_entity->AsmTemplate.clobber_flags |= clobber.implies_clobber_flags(); tmpl_entity->AsmTemplate.clobber_memory |= clobber.implies_clobber_memory() && mem_is_real; - tmpl_entity->AsmTemplate.is_volatile |= clobber.implies_side_effects(); + tmpl_entity->AsmTemplate.is_volatile |= effective_side_effects; - tmpl_entity->AsmTemplate.has_observable_side_effect |= clobber.implies_side_effects() != 0; + tmpl_entity->AsmTemplate.has_observable_side_effect |= effective_side_effects; tmpl_entity->AsmTemplate.has_observable_side_effect |= clobber.writes_mem && mem_is_real; // #align_stack only matters if the body makes a call (which requires the stack @@ -1698,9 +1702,9 @@ gb_internal void check_mnemonic(AsmCtx *asm_ctx, CheckerContext *ctx, Entity *tm why = "it is nondeterministic"; } else if (clobber.implies_clobber_memory() && mem_is_real) { why = "it accesses memory the compiler cannot see"; - } else if (clobber.implies_side_effects()) { + } else if (effective_side_effects) { why = "it has an observable side effect"; - } else if (clobber.has_control() && !check_asm_instr_targets_internal_label(instr)) { + } else if (!internal_branch && clobber.has_control()) { // Internal jmp/jcc/ret over the template's own labels stays pure; a call // or an indirect/external transfer does not. why = "it possibly transfers control outside the inline 'asm' template";