Skip to content

Commit dcf9eff

Browse files
ehildenbclaude
andauthored
Dedupe function selector rules (#1074)
We currently have duplicated rules for function selector check, which makes maintaining them a bit more fragile/brittle. This deduplicates them by sequentializing the check. In particular: - Introduce extra step `#checkFunctionFilter(...)` for creating cut-rules where we have function calls we want to inspect. - Update tests that now need to take extra steps to get to the same state. - Update test expected output where relevant. In addition, this makes a minor update to the `CLAUDE.md` with more fine-grained information about how to run tests and update expected output autonomously. --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 2b6ce41 commit dcf9eff

99 files changed

Lines changed: 205 additions & 213 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CLAUDE.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,22 @@ make test-unit
3232
make test-integration
3333

3434
# Run a single test
35-
uv --directory kmir run pytest kmir/src/tests/integration/test_prove.py::test_prove -k "test_name"
35+
make test-integration TEST_ARGS='-k "test_name"'
3636

3737
# Generate and parse SMIR for test files
3838
make smir-parse-tests
3939
```
4040

41+
You can pass `PARALLEL=N` to increase parallelism for a given test-run.
42+
You can add `TEST_ARGS=--update-expected-output` to update golden output files.
43+
Tests take up to 30 minutes to run, so set your timeout accordingly.
44+
45+
When updating the expected output, make sure to inspect the updated test output and check that it's explained by the changes made to the code.
46+
If not, please provide a brief explanation of could have happend with the test, or what adjustments are needed.
47+
48+
To run individual tests, add `TEST_ARGS='-k "test_id1 or test_id2"'` to the `make` invocation.
49+
For very specific queries, skip make and run the `uv --directory kmir run pytest path/to/test/file.py::test_name[test_selector]` directly with appropriate arguments.
50+
4151
### Code Quality
4252
```bash
4353
# Format code
@@ -162,4 +172,4 @@ uv --directory kmir run kmir show proof_id --full-printer --no-omit-static-info
162172
### Common Issues
163173
- `Function not found` errors: Check if function is in `FUNCTIONS_CELL` (may be intrinsic)
164174
- K compilation errors: Rules must be properly formatted, check syntax
165-
- SMIR generation fails: Ensure using correct Rust nightly version (2024-11-29)
175+
- SMIR generation fails: Ensure using correct Rust nightly version (2024-11-29)

kmir/src/kmir/_prove.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -357,8 +357,7 @@ def _cut_point_rules(
357357
):
358358
cut_point_rules.append('KMIR-CONTROL-FLOW.termCallFunction')
359359
if break_on_function:
360-
cut_point_rules.append('KMIR-CONTROL-FLOW.termCallFunctionFilter')
361-
cut_point_rules.append('KMIR-CONTROL-FLOW.termCallIntrinsicFilter')
360+
cut_point_rules.append('KMIR-CONTROL-FLOW.termCallFunctionFilterMatch')
362361
if break_on_terminator_assert or break_every_terminator or break_every_step:
363362
cut_point_rules.append('KMIR-CONTROL-FLOW.termAssert')
364363
if break_on_terminator_drop or break_every_terminator or break_every_step:

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

Lines changed: 11 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ where the returned result should go.
309309

310310
```k
311311
syntax KItem ::= #execTerminatorCall(fty: Ty, func: MonoItemKind, args: Operands, destination: Place, target: MaybeBasicBlockIdx, unwind: UnwindAction, Span)
312+
syntax KItem ::= #checkFunctionFilter(MonoItemKind)
312313
313314
rule <k> #execTerminator(terminator(terminatorKindCall(operandConstant(constOperand(_, _, mirConst(constantKindZeroSized, Ty, _))), ARGS, DEST, TARGET, UNWIND), SPAN))
314315
=> #execTerminatorCall(Ty, lookupFunction(Ty), ARGS, DEST, TARGET, UNWIND, SPAN)
@@ -336,23 +337,14 @@ where the returned result should go.
336337
// Intrinsic function call - execute directly without state switching
337338
rule [termCallIntrinsic]:
338339
<k> #execTerminatorCall(_, FUNC, ARGS, DEST, TARGET, _UNWIND, SPAN) ~> _
339-
=> #execIntrinsic(FUNC, ARGS, DEST, SPAN) ~> #continueAt(TARGET)
340+
=> #checkFunctionFilter(FUNC) ~> #execIntrinsic(FUNC, ARGS, DEST, SPAN) ~> #continueAt(TARGET)
340341
</k>
341342
requires isIntrinsicFunction(FUNC)
342-
andBool notBool #functionNameMatchesEnv(getFunctionName(FUNC))
343-
344-
// Intrinsic function call to a function in the break-on set - same as termCallIntrinsic but separate rule id for cut-point
345-
rule [termCallIntrinsicFilter]:
346-
<k> #execTerminatorCall(_, FUNC, ARGS, DEST, TARGET, _UNWIND, SPAN) ~> _
347-
=> #execIntrinsic(FUNC, ARGS, DEST, SPAN) ~> #continueAt(TARGET)
348-
</k>
349-
requires isIntrinsicFunction(FUNC)
350-
andBool #functionNameMatchesEnv(getFunctionName(FUNC))
351343
352344
// Regular function call - full state switching and stack setup
353345
rule [termCallFunction]:
354346
<k> #execTerminatorCall(FTY, FUNC, ARGS, DEST, TARGET, UNWIND, SPAN) ~> _
355-
=> #setUpCalleeData(FUNC, ARGS, SPAN)
347+
=> #checkFunctionFilter(FUNC) ~> #setUpCalleeData(FUNC, ARGS, SPAN)
356348
</k>
357349
<currentFunc> CALLER => FTY </currentFunc>
358350
<currentFrame>
@@ -365,25 +357,15 @@ where the returned result should go.
365357
</currentFrame>
366358
<stack> STACK => ListItem(StackFrame(OLDCALLER, OLDDEST, OLDTARGET, OLDUNWIND, LOCALS)) STACK </stack>
367359
requires notBool isIntrinsicFunction(FUNC)
368-
andBool notBool #functionNameMatchesEnv(getFunctionName(FUNC))
369360
370-
// Function call to a function in the break-on set - same as termCallFunction but separate rule id for cut-point
371-
rule [termCallFunctionFilter]:
372-
<k> #execTerminatorCall(FTY, FUNC, ARGS, DEST, TARGET, UNWIND, SPAN) ~> _
373-
=> #setUpCalleeData(FUNC, ARGS, SPAN)
374-
</k>
375-
<currentFunc> CALLER => FTY </currentFunc>
376-
<currentFrame>
377-
<currentBody> _ </currentBody>
378-
<caller> OLDCALLER => CALLER </caller>
379-
<dest> OLDDEST => DEST </dest>
380-
<target> OLDTARGET => TARGET </target>
381-
<unwind> OLDUNWIND => UNWIND </unwind>
382-
<locals> LOCALS </locals>
383-
</currentFrame>
384-
<stack> STACK => ListItem(StackFrame(OLDCALLER, OLDDEST, OLDTARGET, OLDUNWIND, LOCALS)) STACK </stack>
385-
requires notBool isIntrinsicFunction(FUNC)
386-
andBool #functionNameMatchesEnv(getFunctionName(FUNC))
361+
// Filter check injected after every call: fires as a cut-point only when the function matches the break-on list
362+
rule [termCallFunctionFilterMatch]:
363+
<k> #checkFunctionFilter(FUNC) => .K ... </k>
364+
requires #functionNameMatchesEnv(getFunctionName(FUNC))
365+
366+
rule [termCallFunctionFilterNoMatch]:
367+
<k> #checkFunctionFilter(FUNC) => .K ... </k>
368+
requires notBool #functionNameMatchesEnv(getFunctionName(FUNC))
387369
388370
syntax Bool ::= isIntrinsicFunction(MonoItemKind) [function]
389371
rule isIntrinsicFunction(IntrinsicFunction(_)) => true

kmir/src/tests/integration/data/crate-tests/single-bin/single_exe::a_module::twice.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
┌─ 1 (root, init)
33
│ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC
44
5-
│ (44 steps)
5+
│ (46 steps)
66
├─ 3 (split)
77
│ #expect ( BoolVal ( notBool ARG_UINT1:Int +Int ARG_UINT1:Int &Int 18446744073709
88

kmir/src/tests/integration/data/crate-tests/single-bin/single_exe::main.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
┌─ 1 (root, init)
33
│ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC
44
5-
│ (228 steps)
5+
│ (231 steps)
66
├─ 3 (terminal)
77
│ #EndProgram ~> .K
88

kmir/src/tests/integration/data/crate-tests/single-dylib/small_test_dylib::add.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
┌─ 1 (root, init)
33
│ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC
44
5-
│ (35 steps)
5+
│ (36 steps)
66
├─ 3 (split)
77
│ #expect ( BoolVal ( notBool ARG_UINT1:Int +Int ARG_UINT2:Int &Int 18446744073709
88

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
┌─ 1 (root, init)
33
│ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC
44
5-
│ (114 steps)
5+
│ (116 steps)
66
├─ 3 (split)
77
│ #selectBlock ( switchTargets ( ... branches: branch ( 0 , basicBlockIdx ( 1 ) )
88
@@ -14,7 +14,7 @@
1414
┃ ├─ 4
1515
┃ │ #selectBlock ( switchTargets ( ... branches: branch ( 0 , basicBlockIdx ( 1 ) )
1616
┃ │
17-
┃ │ (6 steps)
17+
┃ │ (7 steps)
1818
┃ └─ 6 (stuck, leaf)
1919
┃ #setUpCalleeData ( monoItemFn ( ... name: symbol ( "_ZN3std7process4exit17h<hash>
2020
@@ -25,7 +25,7 @@
2525
├─ 5
2626
│ #selectBlock ( switchTargets ( ... branches: branch ( 0 , basicBlockIdx ( 1 ) )
2727
28-
│ (182 steps)
28+
│ (183 steps)
2929
├─ 7 (terminal)
3030
│ #EndProgram ~> .K
3131

kmir/src/tests/integration/data/crate-tests/two-crate-bin/crate2::main.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
┌─ 1 (root, init)
33
│ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC
44
5-
│ (737 steps)
5+
│ (746 steps)
66
├─ 3 (terminal)
77
│ #EndProgram ~> .K
88

kmir/src/tests/integration/data/crate-tests/two-crate-dylib/crate2::test_crate1_with.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
┌─ 1 (root, init)
33
│ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC
44
5-
│ (216 steps)
5+
│ (220 steps)
66
├─ 3 (terminal)
77
│ #EndProgram ~> .K
88

kmir/src/tests/integration/data/prove-rs/show/assert-inhabited-fail.main.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
│ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC
44
│ span: 0
55
6-
│ (10 steps)
6+
│ (12 steps)
77
└─ 3 (stuck, leaf)
88
#ProgramError ( AssertInhabitedFailure ) ~> .K
99
function: main

0 commit comments

Comments
 (0)