Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions kmir/src/kmir/kdist/mir-semantics/intrinsics.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,26 @@ write the value to that location.
... </k>
```

#### Volatile Load (`std::intrinsics::volatile_load`, `std::ptr::read_volatile`)

The `volatile_load` intrinsic reads a value from a memory location through a pointer, ensuring the read is not
optimised away by the compiler. Unlike normal loads, volatile loads are guaranteed to occur exactly once and
in order with respect to other volatile operations. In the semantics, this is equivalent to a regular load
through a dereferenced pointer. We extract the place from the pointer operand, add a deref projection, and
read the value from that location into the destination. Since `#setLocalValue` is strict in its second argument,
the dereferenced operand is evaluated (i.e., the value is read from memory) before being written to `DEST`.

```k
rule <k> #execIntrinsic(IntrinsicFunction(symbol("volatile_load")), operandCopy(place(LOCAL, PROJ)) .Operands, DEST, _SPAN)
=> #setLocalValue(DEST, operandCopy(place(LOCAL, appendP(PROJ, projectionElemDeref .ProjectionElems))))
... </k>

// for `operandMove` the pointer is moved, but the pointed-to value is copied (read, not consumed)
rule <k> #execIntrinsic(IntrinsicFunction(symbol("volatile_load")), operandMove(place(LOCAL, PROJ)) .Operands, DEST, _SPAN)
=> #setLocalValue(DEST, operandCopy(place(LOCAL, appendP(PROJ, projectionElemDeref .ProjectionElems))))
... </k>
```

#### Ptr Offset Computations (`std::intrinsics::ptr_offset_from`, `std::intrinsics::ptr_offset_from_unsigned`)

The `ptr_offset_from[_unsigned]` calculates the distance between two pointers within the same allocation,
Expand Down
11 changes: 11 additions & 0 deletions kmir/src/tests/integration/data/prove-rs/read_volatile.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
fn main() {
let a: i32 = 5555;
let a_ptr = &a as *const _;

let b: i32;
unsafe {
b = std::ptr::read_volatile(a_ptr);
}

assert!(b == 5555);
}
12 changes: 12 additions & 0 deletions kmir/src/tests/integration/data/prove-rs/volatile_load.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#![feature(core_intrinsics)]
fn main() {
let a: i32 = 5555;
let a_ptr = &a as *const _;

let b: i32;
unsafe {
b = std::intrinsics::volatile_load(a_ptr);
}

assert!(b == 5555);
}
Loading