fitzgen opened issue #14572:
The
AtomicRmwandAtomicCasarms ofwrite_operandsin
cranelift/codegen/src/write.rsignore the instruction'sflags. The
printed text therefore loses the endianness, trap code,aligned/readonly
and alias region. The parser accepts all of these flags, so printed CLIF does
not round-trip. For example, abigRMW reparses as native-endian.
.clifTest Casetest interpret function %f() -> i32 { ss0 = explicit_slot 4 block0: v0 = stack_addr.i64 ss0 v1 = iconst.i32 0x01020304 store v1, v0 v2 = iconst.i32 0x10 v3 = atomic_rmw.i32 big add v0, v2 v4 = load.i32 v0 return v4 } ; run: %f() == 0x11020304Steps to Reproduce
clif-util test test.clif clif-util cat test.clif | grep atomic_rmwExpected Results
The test passes, and
clif-util catprints:v3 = atomic_rmw.i32 big add v0, v2Actual Results
The test passes, but
clif-util catprints:v3 = atomic_rmw.i32 add v0, v2 ; v2 = 16That text has no
bigflag. When it is parsed and interpreted, it returns
0x01020314instead of0x11020304.Versions and Environment
Cranelift version or commit:
73b04cff33Operating system: macOS 15.8.1
Architecture: aarch64
fitzgen added the bug label to Issue #14572.
fitzgen added the cranelift label to Issue #14572.
fitzgen commented on issue #14572:
<details><summary>Full LLM report</summary>
CLIF printer drops all
MemFlagsonatomic_rmwandatomic_cas
Date 2026-10-05 Wasmtime commit 73b04cff3317d1e308866eb24359483ac6116669(main)Host macOS 15.8.1 (Darwin 24.6.0), aarch64-apple-darwinModel Claude Opus 5.5 ( claude-opus-5-5)Component cranelift/codegen/src/write.rs(write_operands)Class CLIF text does not round-trip: the printed function has different semantics Severity Low. No effect on compiled code. Printed CLIF is wrong, which misleads debugging, clif-util, test reductions and bugpoint output. The missing alias region, trap code, endianness,notrapandreadonlyflags are exactly what an alias-analysis audit needs to see.Summary
cranelift/codegen/src/write.rs:397-398:AtomicRmw { op, args, .. } => write!(w, " {} {}, {}", op, args[0], args[1]), AtomicCas { args, .. } => write!(w, " {}, {}, {}", args[0], args[1], args[2]),Both arms ignore the instruction's
flagsfield. Every other memory format
printsdfg.mem_flags[flags], including the neighbouring
LoadNoOffset/StoreNoOffset, which coveratomic_loadand
atomic_store. As a result, the printed form ofatomic_rmwandatomic_cas
loses all of the following:
- the endianness (
big/little);- the trap code (
notrap,userN) andaligned/readonly/can_move;- the alias region (
regionN).The reader parses all of these flags for both instructions, so the text no
longer round-trips. The reparsed function is a different program: abig
RMW silently becomes native-endian. A trapping RMW becomes one with the
default trap code, and anotrapRMW becomes one that can trap. A
region-tagged RMW loses its region, which changes what alias analysis may
assume when the text is fed back in.The omission has been there since these formats were first printed. The last
change to these lines was18d9685eb3(2022, "Fix pretty print of
atomic_rmwclif ops"). Wasmtime emitsatomic_rmw/atomic_caswith alias
regions for every Wasm atomic RMW, so CLIF dumps of those instructions (for
example viaWASMTIME_LOGorclif-util wasm) omit the region and trap code
that the compiler actually uses. Notests/disasexpectation currently
contains these instructions, which is part of why this went unnoticed.Existing
precise-outputfiletest expectations already bake in the flag-less
form, so those tests cannot pin an atomic's region or trap code. Examples are
cranelift/filetests/filetests/alias/not-dead-fence-between.clif:87
(atomic_cas v0, v2, v3) and the atomics inalias/fence.clif. Backend error
messages misprint the instruction as well. Pulley reports abigRMW that it
refuses to lower asv4 = atomic_rmw.i32 add v1, v3.A reparsed atomic that has lost its region is not just cosmetic. The alias
analysis treats a store with no region as a fence, so it reasons about the
reparsed function differently from the original.Reproduction
original.clifuses a big-endianatomic_rmw.i32 big addon a stack slot
holding0x01020304.roundtrip.clifis the output of
clif-util cat original.clif, with the same; run:line.$ clif-util test original.clif 1 tests # passes: [0x04030201, 0x11020304] $ clif-util cat original.clif | grep atomic v4 = atomic_rmw.i32 add v1, v3 ; v3 = 16 # `big` is gone $ clif-util test roundtrip.clif Failed test: run: %f() == [67305985, 285344516], actual: [16909060, 16909076] Error: 1 failure
all-atomics.clifshows every flag being dropped:$ clif-util cat all-atomics.clif v3 = atomic_cas v0, v1, v2 # input: atomic_cas.i32 user5 big region0 v4 = atomic_rmw.i32 xchg v0, v1 # input: atomic_rmw.i32 notrap little region0 v5 = atomic_load.i32 user5 big region0 v0 # printed correctly atomic_store user5 big region0 v1, v0 # printed correctlySuggested fix
AtomicRmw { op, args, flags, .. } => { write!(w, "{} {} {}, {}", dfg.mem_flags[flags], op, args[0], args[1]) } AtomicCas { args, flags, .. } => { write!(w, "{} {}, {}, {}", dfg.mem_flags[flags], args[0], args[1], args[2]) }Match the leading-space convention of the other
MemFlagsarms; the
MemFlagsDisplayalready prints its own leading spaces. Then re-bless any filetest
expectations that printatomic_rmworatomic_cas. A parse→print→parse round-trip test over all memory formats
would prevent recurrences.</details>
cfallin closed issue #14572:
The
AtomicRmwandAtomicCasarms ofwrite_operandsin
cranelift/codegen/src/write.rsignore the instruction'sflags. The
printed text therefore loses the endianness, trap code,aligned/readonly
and alias region. The parser accepts all of these flags, so printed CLIF does
not round-trip. For example, abigRMW reparses as native-endian.
.clifTest Casetest interpret function %f() -> i32 { ss0 = explicit_slot 4 block0: v0 = stack_addr.i64 ss0 v1 = iconst.i32 0x01020304 store v1, v0 v2 = iconst.i32 0x10 v3 = atomic_rmw.i32 big add v0, v2 v4 = load.i32 v0 return v4 } ; run: %f() == 0x11020304Steps to Reproduce
clif-util test test.clif clif-util cat test.clif | grep atomic_rmwExpected Results
The test passes, and
clif-util catprints:v3 = atomic_rmw.i32 big add v0, v2Actual Results
The test passes, but
clif-util catprints:v3 = atomic_rmw.i32 add v0, v2 ; v2 = 16That text has no
bigflag. When it is parsed and interpreted, it returns
0x01020314instead of0x11020304.Versions and Environment
Cranelift version or commit:
73b04cff33Operating system: macOS 15.8.1
Architecture: aarch64
cfallin commented on issue #14572:
Closed by #14621.
Last updated: Oct 11 2026 at 04:10 UTC