Skip to content

Commit 51d8d8d

Browse files
authored
Backport p-token tweaks (#672)
This is a collection of changes that were (or appeared) useful while working on the P-Token domain data model and advancing the property proofs. Each commit is an addition of its own * Ceil simplification rules for `#mapOffset` (for the legacy backend, might not be necessary after all) * avoid modulus calculations for number truncation (we now have a function for it) * project setup: add markdown selectors `symbolic`/`concrete` so we can separate symbolic backend code blocks * implement `CastKindIntToInt` for `Bool` -> `Int` (related code was observed in the wild). * Implement support for trivial cases of `transmute` (same type only) The "avoid modulus" requires changes (good changes) on the test expectations, the changed `Ceil` simplification changes a hash in one expectation file.
1 parent 07a5f48 commit 51d8d8d

6 files changed

Lines changed: 62 additions & 15 deletions

File tree

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,14 @@ If nothing is removed, the list remains the same. If all elements are removed, n
5252
```
5353

5454
The `#mapOffset` function maps `#adjustRef` over a lists of `Value`s, leaving the list length unchanged.
55+
Definedness of the list and list elements is also guaranteed.
5556

5657
```k
5758
rule size(#mapOffset(L, _)) => size(L) [simplification, preserves-definedness]
59+
60+
rule #Ceil(#mapOffset(L, _)[I]) => #Ceil(L) #And {true #Equals 0 <=Int I} #And {true #Equals I <Int size(L)} [simplification]
61+
62+
rule #Ceil(#mapOffset(L, _)) => #Ceil(L) [simplification]
5863
```
5964

6065
## Simplifications for Int

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

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,30 @@ bit width, signedness, and possibly truncating or 2s-complementing the value.
10561056
[preserves-definedness] // ensures #numTypeOf is defined
10571057
```
10581058

1059+
Boolean values can also be cast to Integers (encoding `true` as `1`).
1060+
1061+
```k
1062+
rule <k> #cast(BoolVal(VAL), castKindIntToInt, _, TY)
1063+
=>
1064+
#intAsType(1, 8, #numTypeOf({TYPEMAP[TY]}:>TypeInfo))
1065+
...
1066+
</k>
1067+
<types> TYPEMAP </types>
1068+
requires #isIntType({TYPEMAP[TY]}:>TypeInfo)
1069+
andBool VAL
1070+
[preserves-definedness] // ensures #numTypeOf is defined
1071+
1072+
rule <k> #cast(BoolVal(VAL), castKindIntToInt, _, TY)
1073+
=>
1074+
#intAsType(0, 8, #numTypeOf({TYPEMAP[TY]}:>TypeInfo))
1075+
...
1076+
</k>
1077+
<types> TYPEMAP </types>
1078+
requires #isIntType({TYPEMAP[TY]}:>TypeInfo)
1079+
andBool notBool VAL
1080+
[preserves-definedness] // ensures #numTypeOf is defined
1081+
```
1082+
10591083
Casts involving `Float` values are currently not implemented.
10601084

10611085
### Casts between pointer types
@@ -1180,15 +1204,37 @@ The original metadata is therefore already stored as `staticSize` to avoid havin
11801204
// [preserves-definedness] // valid type map indexing and sort coercion
11811205
```
11821206

1207+
### `Transmute` casts
1208+
1209+
An unsafe `transmute` operation in Rust is an arbitrary cast between unrelated types based on assumptions that the byte
1210+
representations of the source and target types are somewhat relatable (or else, under full consideration that they are not).
1211+
1212+
Support for `castKindTransmute` in this semantics is very limited because of the high-level data model applied.
1213+
What can be supported without additional layout consideration is trivial casts between the same underlying type (mutable or not).
1214+
1215+
```k
1216+
rule <k> #cast(Reference(_, _, _, _) #as REF, castKindTransmute, TY_SOURCE, TY_TARGET) => REF ... </k>
1217+
<types> TYPEMAP </types>
1218+
requires TY_SOURCE in_keys(TYPEMAP)
1219+
andBool TY_TARGET in_keys(TYPEMAP)
1220+
andBool TYPEMAP[TY_SOURCE] ==K TYPEMAP[TY_TARGET]
1221+
[preserves-definedness] // valid map lookups checked
1222+
1223+
rule <k> #cast(PtrLocal(_, _, _, _) #as PTR, castKindTransmute, TY_SOURCE, TY_TARGET) => PTR ... </k>
1224+
<types> TYPEMAP </types>
1225+
requires TY_SOURCE in_keys(TYPEMAP)
1226+
andBool TY_TARGET in_keys(TYPEMAP)
1227+
andBool TYPEMAP[TY_SOURCE] ==K TYPEMAP[TY_TARGET]
1228+
[preserves-definedness] // valid map lookups checked
1229+
```
1230+
11831231
### Other casts involving pointers
11841232

11851233
| CastKind | Description |
11861234
|------------------------------|-------------|
11871235
| PointerExposeProvenance | |
11881236
| PointerWithExposedProvenance | |
11891237
| FnPtrToPtr | |
1190-
| Transmute | |
1191-
11921238

11931239
## Decoding constants from their bytes representation to values
11941240

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

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -127,27 +127,21 @@ This truncation function is instrumental in the implementation of Integer arithm
127127
true
128128
)
129129
requires #bitWidth(INTTYPE) <=Int WIDTH
130-
[preserves-definedness] // positive shift, divisor non-zero
131130
132131
// widening: nothing to do: VAL does not change (enough bits to represent, no sign change possible)
133132
rule #intAsType(VAL, WIDTH, INTTYPE:IntTy)
134133
=>
135134
Integer(VAL, #bitWidth(INTTYPE), true)
136135
requires WIDTH <Int #bitWidth(INTTYPE)
137136
138-
// converting to unsigned int types
139-
// truncate (if necessary), then add bias to make non-negative, then truncate again
137+
// converting to unsigned int types (simple bitmask)
140138
rule #intAsType(VAL, _, UINTTYPE:UintTy)
141139
=>
142140
Integer(
143-
(VAL %Int (1 <<Int #bitWidth(UINTTYPE) )
144-
+Int (1 <<Int #bitWidth(UINTTYPE)))
145-
%Int (1 <<Int #bitWidth(UINTTYPE) )
146-
,
141+
truncate(VAL, #bitWidth(UINTTYPE), Unsigned),
147142
#bitWidth(UINTTYPE),
148143
false
149144
)
150-
[preserves-definedness] // positive shift, divisor non-zero
151145
```
152146

153147
## Alignment of Primitives

kmir/src/kmir/kdist/plugin.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ def deps(self) -> tuple[str, ...]:
4242
def _default_args(src_dir: Path) -> dict[str, Any]:
4343
return {
4444
'include_dirs': [src_dir],
45-
'md_selector': 'k',
4645
'warnings_to_errors': True,
4746
'syntax_module': 'KMIR-AST',
4847
}
@@ -54,6 +53,7 @@ def _default_args(src_dir: Path) -> dict[str, Any]:
5453
lambda src_dir: {
5554
'main_file': src_dir / 'mir-semantics/kmir.md',
5655
'backend': PykBackend.LLVM,
56+
'md_selector': 'k & ! symbolic',
5757
**_default_args(src_dir),
5858
},
5959
),
@@ -62,13 +62,15 @@ def _default_args(src_dir: Path) -> dict[str, Any]:
6262
'main_file': src_dir / 'mir-semantics/kmir.md',
6363
'backend': PykBackend.LLVM,
6464
'llvm_kompile_type': LLVMKompileType.C,
65+
'md_selector': 'k & ! symbolic',
6566
**_default_args(src_dir),
6667
},
6768
),
6869
'haskell': KompileTarget(
6970
lambda src_dir: {
7071
'main_file': src_dir / 'mir-semantics/kmir.md',
7172
'backend': PykBackend.HASKELL,
73+
'md_selector': 'k & ! concrete',
7274
**_default_args(src_dir),
7375
},
7476
),

kmir/src/tests/integration/data/crate-tests/single-lib/testing::test_add_in_range.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
┃ (branch)
1010
┣━━┓ subst: .Subst
1111
┃ ┃ constraint:
12-
┃ ┃ notBool ARG_UINT1:Int +Int 340282366920938463463374607431768211456 %Int 340282366920938463463374607431768211456 +Int ARG_UINT2:Int +Int 340282366920938463463374607431768211456 %Int 340282366920938463463374607431768211456 <=Int 18446744073709551615
12+
┃ ┃ notBool ARG_UINT1:Int +Int ARG_UINT2:Int <=Int 18446744073709551615
1313
┃ │
1414
┃ ├─ 4
1515
┃ │ #selectBlock ( switchTargets ( ... branches: branch ( 0 , basicBlockIdx ( 1 ) )
@@ -20,7 +20,7 @@
2020
2121
┗━━┓ subst: .Subst
2222
┃ constraint:
23-
┃ ARG_UINT1:Int +Int 340282366920938463463374607431768211456 %Int 340282366920938463463374607431768211456 +Int ARG_UINT2:Int +Int 340282366920938463463374607431768211456 %Int 340282366920938463463374607431768211456 <=Int 18446744073709551615
23+
┃ ARG_UINT1:Int +Int ARG_UINT2:Int <=Int 18446744073709551615
2424
2525
├─ 5
2626
│ #selectBlock ( switchTargets ( ... branches: branch ( 0 , basicBlockIdx ( 1 ) )

kmir/src/tests/integration/data/prove-rs/show/symbolic-args-fail.eats_all_args.expected

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
┃ ┃ │ #EndProgram ~> .K
6161
┃ ┃ │
6262
┃ ┃ ┊ constraint:
63-
┃ ┃ ┊ Ceil_a90d0b00
63+
┃ ┃ ┊ Ceil_3c8e32fd
6464
┃ ┃ ┊ subst: ...
6565
┃ ┃ └─ 2 (leaf, target, terminal)
6666
┃ ┃ #EndProgram ~> .K
@@ -123,7 +123,7 @@
123123
┃ │ #EndProgram ~> .K
124124
┃ │
125125
┃ ┊ constraint:
126-
┃ ┊ Ceil_a90d0b00
126+
┃ ┊ Ceil_3c8e32fd
127127
┃ ┊ subst: ...
128128
┃ └─ 2 (leaf, target, terminal)
129129
┃ #EndProgram ~> .K

0 commit comments

Comments
 (0)