Skip to content

Commit 53e9dab

Browse files
authored
Added volatile_load intrinsic (#987)
This PR adds the [volatile_load](https://doc.rust-lang.org/std/intrinsics/fn.volatile_load.html) intrinsic. For this semantics, memory being "volatile" is meaningless as the we are not compiling any further, and aren't modeling any compiler optimisations that could occur if we were to. Therefore this is implemented as a simple dereference of the pointer and read of the value at the location into the destination.
1 parent a322781 commit 53e9dab

3 files changed

Lines changed: 43 additions & 0 deletions

File tree

kmir/src/kmir/kdist/mir-semantics/intrinsics.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,26 @@ write the value to that location.
143143
... </k>
144144
```
145145

146+
#### Volatile Load (`std::intrinsics::volatile_load`, `std::ptr::read_volatile`)
147+
148+
The `volatile_load` intrinsic reads a value from a memory location through a pointer, ensuring the read is not
149+
optimised away by the compiler. Unlike normal loads, volatile loads are guaranteed to occur exactly once and
150+
in order with respect to other volatile operations. In the semantics, this is equivalent to a regular load
151+
through a dereferenced pointer. We extract the place from the pointer operand, add a deref projection, and
152+
read the value from that location into the destination. Since `#setLocalValue` is strict in its second argument,
153+
the dereferenced operand is evaluated (i.e., the value is read from memory) before being written to `DEST`.
154+
155+
```k
156+
rule <k> #execIntrinsic(IntrinsicFunction(symbol("volatile_load")), operandCopy(place(LOCAL, PROJ)) .Operands, DEST, _SPAN)
157+
=> #setLocalValue(DEST, operandCopy(place(LOCAL, appendP(PROJ, projectionElemDeref .ProjectionElems))))
158+
... </k>
159+
160+
// for `operandMove` the pointer is moved, but the pointed-to value is copied (read, not consumed)
161+
rule <k> #execIntrinsic(IntrinsicFunction(symbol("volatile_load")), operandMove(place(LOCAL, PROJ)) .Operands, DEST, _SPAN)
162+
=> #setLocalValue(DEST, operandCopy(place(LOCAL, appendP(PROJ, projectionElemDeref .ProjectionElems))))
163+
... </k>
164+
```
165+
146166
#### Ptr Offset Computations (`std::intrinsics::ptr_offset_from`, `std::intrinsics::ptr_offset_from_unsigned`)
147167

148168
The `ptr_offset_from[_unsigned]` calculates the distance between two pointers within the same allocation,
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
fn main() {
2+
let a: i32 = 5555;
3+
let a_ptr = &a as *const _;
4+
5+
let b: i32;
6+
unsafe {
7+
b = std::ptr::read_volatile(a_ptr);
8+
}
9+
10+
assert!(b == 5555);
11+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#![feature(core_intrinsics)]
2+
fn main() {
3+
let a: i32 = 5555;
4+
let a_ptr = &a as *const _;
5+
6+
let b: i32;
7+
unsafe {
8+
b = std::intrinsics::volatile_load(a_ptr);
9+
}
10+
11+
assert!(b == 5555);
12+
}

0 commit comments

Comments
 (0)