The documentation says that “Volatile operations are intended to act on I/O memory, and are guaranteed not to be elided or reordered by the compiler across other volatile operations.”, and so I expect this call to always exist, but it seems not to be the case.
I have this code:
unsafe {
core::arch::asm!("nop");
core::arch::asm!("nop");
core::arch::asm!("nop");
let ptr = 0x12ff000 as *mut u32;
ptr.write_volatile(kernel_len as u32);
core::arch::asm!("cli");
core::arch::asm!("hlt");
}
are you sure you are not inspecting the output of different code?
because in your snippet, there is a memory store instruction, it is not deleted, it just write to a different address (-0x1000 instead of 0x12ff000), where kernel_len is in the %edi register,
It is only me (at the end of a week of work) or there are other people that feel that answers like this one are AI-generated and add absolutely nothing to the discussion?
I just commented out a few lines above the block to make this code work. In any case, no matter what actions I change elsewhere in the code or compiler settings, this call MUST exist because the documentation says “intended to act on I/O memory, and are guaranteed not to be elided”.
Not just that, the answer is blatantly wrong. "If the compiler determines that the write operation has no noticeable effect, the write_volatile() call can be optimized." --no it can't, it directly contradicts the documentation and intention.
@mrjbom Can you provide an actual complete reproducible example that we can inspect? The snippet you provided isn't complete enough to make any conclusions. I can't reproduce your error:
playground::foo:
push rax
nop
nop
nop
mov dword ptr [19918848], edi
cli
hlt
pop rax
ret
again, it is NOT elided, the instruction is there, but for unknown reasons, the address is wrong.
but, as others said, you didn't provide a reproducible case, so it cannot be decided where the discrepancy came from, for example, it might well be your disassembler.
here's similar code on the playground, and it gives the correct output, nowhere to see the mysterious -0x1000
input:
pub fn foo(kernel_len: u64) {
unsafe {
core::arch::asm!("nop");
core::arch::asm!("nop");
core::arch::asm!("nop");
let ptr = 0x12ff000 as *mut u32;
ptr.write_volatile(kernel_len as u32);
core::arch::asm!("cli");
core::arch::asm!("hlt");
}
}
Guarantees, since assembler inserts cannot be optimized.
In addition, nowhere else in the code can a sequence of nop; nop; nop; nop; ... cli; hlt;
I unambiguously check the right code, moreover I checked the address itself in memory and the right value was not there.
Unfortunately, I am not able to replicate this situation in godbolt or play rust.