Skip to content

Commit f70f025

Browse files
volatile_{load,store} with statics. Heap allocations. And transmuting wrappers. (#989)
This is a bit of everything in one go, but what I was trying to do was isolate the case seen in [this Kompass test](https://github.com/runtimeverification/kompass/blob/master/src/tests/integration/data/token/spl-token/show/spl_token_domain_data-fail.main.expected) that was discussed in #987. The `volatile_load` is coming from `Box::new` which we are not supporting right now as that does heap allocation. This PR: - Adds failing tests for statics (not decoding properly) - Adds a failing test for `Box::new` - Supports sound transmutation between transparent wrappers (in `#[repr(rust)]` case and their wrapped type. Seen as a `thunk` earlier in the `Box::new` proof and I thought I would solve it now. There are tests for this changed from failing passing in the commit history. So the `volatile_load` is expected to fail until we figure out some support for the things that these tests fail on. This is not blocking any work now so I think it is fine just to add the failing tests --------- Co-authored-by: automergerpr-permission-manager[bot] <190534181+automergerpr-permission-manager[bot]@users.noreply.github.com>
1 parent b6d5c2d commit f70f025

10 files changed

Lines changed: 115 additions & 0 deletions

kmir/src/kmir/kdist/mir-semantics/rt/data.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1606,6 +1606,30 @@ The first cast is reified as a `thunk`, the second one resolves it and eliminate
16061606
andBool lookupTy(TY_DEST_INNER) ==K lookupTy(TY_SRC_OUTER) // and is well-formed (invariant)
16071607
```
16081608

1609+
Transmuting a value `T` into a single-field wrapper struct `G<T>` (or vice versa) is sound when the struct
1610+
has its field at zero offset and `transmute` compiled (guaranteeing equal sizes).
1611+
These are essentially `#[repr(transparent)]` but are `#[repr(rust)]` by default without the annotation and
1612+
thus there are no compiler optimisations to remove the transmute (there would be otherwise for downcast).
1613+
The layout is the same for the wrapped type and so the cast in either direction is sound.
1614+
1615+
```k
1616+
// Up: T -> Wrapper(T)
1617+
rule <k> #cast(VAL:Value, castKindTransmute, TY_SOURCE, TY_TARGET)
1618+
=>
1619+
Aggregate(variantIdx(0), ListItem(VAL))
1620+
...
1621+
</k>
1622+
requires #transparentFieldTy(lookupTy(TY_TARGET)) ==K TY_SOURCE
1623+
1624+
// Down: Wrapper(T) -> T
1625+
rule <k> #cast(Aggregate(variantIdx(0), ListItem(VAL)), castKindTransmute, TY_SOURCE, TY_TARGET)
1626+
=>
1627+
VAL
1628+
...
1629+
</k>
1630+
requires {#transparentFieldTy(lookupTy(TY_SOURCE))}:>Ty ==K TY_TARGET
1631+
```
1632+
16091633
Casting a byte array/slice to an integer reinterprets the bytes in little-endian order.
16101634

16111635
```k
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
fn main() {
2+
let a = Box::new(42i32);
3+
assert!(*a == 42);
4+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
┌─ 1 (root, init)
3+
│ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC
4+
│ span: 0
5+
6+
│ (199 steps)
7+
└─ 3 (stuck, leaf)
8+
#execIntrinsic ( IntrinsicFunction ( symbol ( "volatile_load" ) ) , operandConst
9+
span: 32
10+
11+
12+
┌─ 2 (root, leaf, target, terminal)
13+
│ #EndProgram ~> .K
14+
15+
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
┌─ 1 (root, init)
3+
│ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC
4+
│ span: 0
5+
6+
│ (17 steps)
7+
└─ 3 (stuck, leaf)
8+
#traverseProjection ( toLocal ( 3 ) , thunk ( #decodeConstant ( constantKindAllo
9+
function: main
10+
span: 53
11+
12+
13+
┌─ 2 (root, leaf, target, terminal)
14+
│ #EndProgram ~> .K
15+
16+
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
2+
┌─ 1 (root, init)
3+
│ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC
4+
│ span: 0
5+
6+
│ (17 steps)
7+
└─ 3 (stuck, leaf)
8+
#traverseProjection ( toLocal ( 4 ) , thunk ( #decodeConstant ( constantKindAllo
9+
function: main
10+
span: 57
11+
12+
13+
┌─ 2 (root, leaf, target, terminal)
14+
│ #EndProgram ~> .K
15+
16+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
struct Wrapper(u64);
2+
3+
fn main() {
4+
let wrapped = Wrapper(42);
5+
let val: u64 = unsafe { core::mem::transmute::<Wrapper, u64>(wrapped) };
6+
assert!(val == 42);
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
struct Wrapper(u64);
2+
3+
fn main() {
4+
let val: u64 = 42;
5+
let wrapped: Wrapper = unsafe { core::mem::transmute::<u64, Wrapper>(val) };
6+
assert!(wrapped.0 == 42);
7+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![feature(core_intrinsics)]
2+
static A: i32 = 5555;
3+
4+
fn main() {
5+
let val: i32;
6+
unsafe {
7+
val = std::intrinsics::volatile_load(&A as *const i32);
8+
}
9+
10+
assert!(val == 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+
static mut A: i32 = 5555;
3+
4+
fn main() {
5+
unsafe {
6+
std::intrinsics::volatile_store(&mut A as *mut i32, 7777);
7+
}
8+
9+
unsafe {
10+
assert!(A == 7777);
11+
}
12+
}

kmir/src/tests/integration/test_integration.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@
6565
'test_offset_from-fail',
6666
'ref-ptr-cast-elem-fail',
6767
'ref-ptr-cast-elem-offset-fail',
68+
'volatile_store_static-fail',
69+
'volatile_load_static-fail',
70+
'box_heap_alloc-fail',
6871
]
6972

7073

0 commit comments

Comments
 (0)