├── kmir ├── src │ ├── kmir │ │ ├── py.typed │ │ ├── kdist │ │ │ ├── __init__.py │ │ │ └── mir-semantics │ │ │ │ ├── cheatcodes.md │ │ │ │ ├── target.md │ │ │ │ └── kmir-ast.md │ │ ├── testing │ │ │ ├── __init__.py │ │ │ └── fixtures.py │ │ ├── __init__.py │ │ ├── build.py │ │ ├── kprint.py │ │ ├── parse │ │ │ └── __main__.py │ │ └── kparse.py │ └── tests │ │ ├── __init__.py │ │ ├── unit │ │ ├── __init__.py │ │ └── test_unit.py │ │ └── integration │ │ ├── __init__.py │ │ ├── data │ │ ├── schema-parse │ │ │ ├── local │ │ │ │ ├── input.json │ │ │ │ ├── reference.kmir │ │ │ │ └── reference.sort │ │ │ ├── span │ │ │ │ ├── input.json │ │ │ │ ├── reference.sort │ │ │ │ └── reference.kmir │ │ │ ├── body │ │ │ │ ├── reference.sort │ │ │ │ ├── input.json │ │ │ │ └── reference.kmir │ │ │ ├── maybelocal │ │ │ │ ├── input.json │ │ │ │ ├── reference.sort │ │ │ │ └── reference.kmir │ │ │ ├── basicblockidx │ │ │ │ ├── input.json │ │ │ │ ├── reference.sort │ │ │ │ └── reference.kmir │ │ │ ├── place │ │ │ │ ├── reference.sort │ │ │ │ ├── input.json │ │ │ │ └── reference.kmir │ │ │ ├── functions │ │ │ │ ├── reference.sort │ │ │ │ ├── input.json │ │ │ │ └── reference.kmir │ │ │ ├── maybebasicblockidx │ │ │ │ ├── input.json │ │ │ │ ├── reference.sort │ │ │ │ └── reference.kmir │ │ │ ├── monoitem │ │ │ │ └── reference.sort │ │ │ ├── operand │ │ │ │ ├── reference.sort │ │ │ │ ├── input.json │ │ │ │ └── reference.kmir │ │ │ ├── rvaluecast │ │ │ │ ├── reference.sort │ │ │ │ ├── input.json │ │ │ │ └── reference.kmir │ │ │ ├── statement │ │ │ │ ├── reference.sort │ │ │ │ ├── input.json │ │ │ │ └── reference.kmir │ │ │ ├── testsort2 │ │ │ │ ├── reference.sort │ │ │ │ ├── input.json │ │ │ │ └── reference.kmir │ │ │ ├── basicblock1 │ │ │ │ ├── reference.sort │ │ │ │ ├── input.json │ │ │ │ └── reference.kmir │ │ │ ├── basicblock2 │ │ │ │ ├── reference.sort │ │ │ │ ├── input.json │ │ │ │ └── reference.kmir │ │ │ ├── rvalueaggregate │ │ │ │ ├── reference.sort │ │ │ │ ├── input.json │ │ │ │ └── reference.kmir │ │ │ ├── statements │ │ │ │ ├── reference.sort │ │ │ │ ├── input.json │ │ │ │ └── reference.kmir │ │ │ ├── statementassign1 │ │ │ │ ├── reference.sort │ │ │ │ ├── input.json │ │ │ │ └── reference.kmir │ │ │ ├── statementassign2 │ │ │ │ ├── reference.sort │ │ │ │ ├── input.json │ │ │ │ └── reference.kmir │ │ │ ├── terminatorgoto │ │ │ │ ├── reference.sort │ │ │ │ ├── input.json │ │ │ │ └── reference.kmir │ │ │ ├── terminatorkindreturn │ │ │ │ ├── input.json │ │ │ │ ├── reference.sort │ │ │ │ └── reference.kmir │ │ │ ├── terminatorreturn │ │ │ │ ├── reference.sort │ │ │ │ ├── input.json │ │ │ │ └── reference.kmir │ │ │ ├── typeinfoenumtype │ │ │ │ └── reference.sort │ │ │ ├── aggregatekindadt │ │ │ │ ├── reference.sort │ │ │ │ ├── input.json │ │ │ │ └── reference.kmir │ │ │ └── terminatorkindgoto │ │ │ │ ├── reference.sort │ │ │ │ ├── input.json │ │ │ │ └── reference.kmir │ │ ├── decode-value │ │ │ ├── bool-false.expected │ │ │ ├── bool-true.expected │ │ │ ├── i8.expected │ │ │ ├── u8.expected │ │ │ ├── i128.expected │ │ │ ├── i16.expected │ │ │ ├── i32.expected │ │ │ ├── i64.expected │ │ │ ├── u16.expected │ │ │ ├── u32.expected │ │ │ ├── str.expected │ │ │ ├── tuple-empty.expected │ │ │ ├── u64.expected │ │ │ ├── enum-option-ref-none.expected │ │ │ ├── enum-2-variants-0-fields.expected │ │ │ ├── enum-option-nonzero-none.expected │ │ │ ├── u128.expected │ │ │ ├── enum-2-variants-1-field.expected │ │ │ ├── enum-1-variant-1-field.expected │ │ │ ├── enum-option-nonzero-some.expected │ │ │ ├── tuple-bool-u32.expected │ │ │ ├── enum-1-variant-2-fields.expected │ │ │ ├── bool-false.json │ │ │ ├── bool-true.json │ │ │ ├── tuple-u8-i32.expected │ │ │ ├── i8.json │ │ │ ├── u8.json │ │ │ ├── tuple-i16-bool-u8.expected │ │ │ ├── i16.json │ │ │ ├── struct-simple-permuted-fields.expected │ │ │ ├── u16.json │ │ │ ├── array-u8-const-len.expected │ │ │ ├── array-u8-implicit-len.expected │ │ │ ├── i32.json │ │ │ ├── u32.json │ │ │ ├── type-table │ │ │ ├── i64.json │ │ │ ├── u64.json │ │ │ ├── str.json │ │ │ ├── i128.json │ │ │ ├── u128.json │ │ │ ├── array-u8-implicit-len.json │ │ │ ├── tuple-empty.json │ │ │ ├── array-u8-const-len.json │ │ │ ├── tuple-bool-u32.json │ │ │ ├── tuple-u8-i32.json │ │ │ ├── enum-1-variant-2-fields.json │ │ │ ├── struct-simple-permuted-fields.json │ │ │ ├── tuple-i16-bool-u8.json │ │ │ └── enum-1-variant-1-field.json │ │ ├── prove-rs │ │ │ ├── niche-enum.rs │ │ │ ├── offset_read.rs │ │ │ ├── offset_write.rs │ │ │ ├── assert-true.rs │ │ │ ├── show │ │ │ │ ├── assert-true.main.cli-prune.expected │ │ │ │ ├── link.arith.smir+unary.smir.counts.expected │ │ │ │ ├── arith.smir.cli-info.expected │ │ │ │ ├── niche-enum.main.expected │ │ │ │ ├── assert-inhabited-fail.main.expected │ │ │ │ ├── assert_eq_exp.main.expected │ │ │ │ ├── bitwise-not-shift.main.expected │ │ │ │ ├── offset-u8-fail.main.expected │ │ │ │ ├── transmute-u8-to-enum-fail.main.expected │ │ │ │ ├── assert-true.main.cli-custom-printer.expected │ │ │ │ ├── assert-true.main.cli-default-printer.expected │ │ │ │ ├── interior-mut-fail.main.expected │ │ │ │ ├── iter_next_2-fail.main.expected │ │ │ │ ├── symbolic-args-fail.main.expected │ │ │ │ ├── iterator-simple-fail.main.expected │ │ │ │ ├── unions-fail.main.expected │ │ │ │ ├── assume-cheatcode-conflict-fail.check_assume_conflict.expected │ │ │ │ ├── transmute-maybe-uninit-fail.main.expected │ │ │ │ ├── transmute-u8-to-enum-changed-discriminant-signed-fail.main.expected │ │ │ │ ├── enum.smir.main.cli-stats-leaves.expected │ │ │ │ ├── local-raw-fail.main.expected │ │ │ │ ├── raw-ptr-cast-fail.main.expected │ │ │ │ ├── symbolic-args-fail.main.cli-stats-leaves.expected │ │ │ │ └── interior-mut3-fail.main.expected │ │ │ ├── array_nest_compare.rs │ │ │ ├── assert-false-fail.rs │ │ │ ├── enum-two-refs-fail.rs │ │ │ ├── offset_struct_field_read.rs │ │ │ ├── branch-negative.rs │ │ │ ├── offset_struct_field_write.rs │ │ │ ├── pointer-cast-length-test-fail.rs │ │ │ ├── assert_eq_exp.rs │ │ │ ├── assert_eq.rs │ │ │ ├── const-empty.rs │ │ │ ├── tuples-simple.rs │ │ │ ├── ref-deref.rs │ │ │ ├── local-raw-fail.rs │ │ │ ├── double-ref-deref.rs │ │ │ ├── primitive-type-bounds.rs │ │ │ ├── strange-ref-deref.rs │ │ │ ├── iterator-simple-fail.rs │ │ │ ├── enum.rs │ │ │ ├── struct.rs │ │ │ ├── if.rs │ │ │ ├── else.rs │ │ │ ├── maybe-uninit.rs │ │ │ ├── array_write.rs │ │ │ ├── interior-mut3-fail.rs │ │ │ ├── const-arithm-simple.rs │ │ │ ├── recursion-simple-match.rs │ │ │ ├── recursion-simple.rs │ │ │ ├── fibonacci.rs │ │ │ ├── stack_assign.rs │ │ │ ├── loop.rs │ │ │ ├── loop-fail.rs │ │ │ ├── assert-inhabited-fail.rs │ │ │ ├── raw-ptr-cast-fail.rs │ │ │ ├── and_then_closure.rs │ │ │ ├── transmute-u8-to-enum-fail.rs │ │ │ ├── mutual_recursion.rs │ │ │ ├── unions-fail.rs │ │ │ ├── transmute-maybe-uninit-fail.rs │ │ │ ├── assume-cheatcode-conflict-fail.rs │ │ │ ├── array_match.rs │ │ │ ├── arith.rs │ │ │ ├── assume-cheatcode.rs │ │ │ ├── iter_next_1.rs │ │ │ ├── iter_next_2-fail.rs │ │ │ ├── sum-to-n-functions.rs │ │ │ ├── struct_with_ref.rs │ │ │ ├── transmute-u8-to-enum.rs │ │ │ ├── bitwise.rs │ │ │ ├── shift_negative_min.rs │ │ │ ├── checked_arithmetic.rs │ │ │ ├── offset-u8-fail.rs │ │ │ ├── closure_access_struct.rs │ │ │ ├── bitwise-not-shift.rs │ │ │ ├── transmute-maybe-uninit.rs │ │ │ ├── interior-mut2.rs │ │ │ ├── interior-mut-fail.rs │ │ │ ├── symbolic-structs-fail.rs │ │ │ ├── transmute-u8-to-enum-changed-discriminant-signed-fail.rs │ │ │ ├── 488-support-function-pointer-calls.rs │ │ │ ├── slice-split-at.rs │ │ │ ├── cmp.rs │ │ │ ├── transmute-u8-to-enum-changed-discriminant.rs │ │ │ ├── intrinsics.rs │ │ │ ├── transmute-try-from-symbolic.rs │ │ │ ├── pointer-cast.rs │ │ │ ├── transmute-bytes.rs │ │ │ ├── symbolic-args-fail.rs │ │ │ ├── test_offset_from-fail.rs │ │ │ └── bitwise-shift.rs │ │ ├── run-rs │ │ │ ├── integers │ │ │ │ ├── div.rs │ │ │ │ ├── modulo.rs │ │ │ │ ├── primitive-type-bounds.rs │ │ │ │ ├── const-arithm-simple.rs │ │ │ │ └── shl_min.rs │ │ │ ├── strings-chars │ │ │ │ ├── str-empty.rs │ │ │ │ ├── str-trivial.rs │ │ │ │ ├── char-trivial.rs │ │ │ │ ├── std-string-empty.rs │ │ │ │ └── std-to-string.rs │ │ │ ├── arrays │ │ │ │ └── array.rs │ │ │ ├── assert │ │ │ │ └── assert_eq.rs │ │ │ ├── closures │ │ │ │ ├── closure-no-args.rs │ │ │ │ └── closure-args.rs │ │ │ ├── tuples │ │ │ │ ├── tuple-eq.rs │ │ │ │ └── tuples-simple.rs │ │ │ ├── slices │ │ │ │ └── slice.rs │ │ │ ├── ref-deref │ │ │ │ ├── ref-deref.rs │ │ │ │ ├── double-ref-deref.rs │ │ │ │ └── strange-ref-deref.rs │ │ │ ├── enums │ │ │ │ └── enum.rs │ │ │ ├── option │ │ │ │ └── option-construction.rs │ │ │ ├── structs │ │ │ │ └── struct.rs │ │ │ ├── floats │ │ │ │ └── float.rs │ │ │ ├── memory │ │ │ │ └── box.rs │ │ │ ├── recursion │ │ │ │ ├── recursion-simple-match.rs │ │ │ │ ├── recursion-simple.rs │ │ │ │ ├── fibonacci.rs │ │ │ │ └── mutual_recursion.rs │ │ │ ├── generics │ │ │ │ └── generic.rs │ │ │ ├── traits │ │ │ │ ├── defined-trait.rs │ │ │ │ └── derive-copy-struct.rs │ │ │ └── functions │ │ │ │ └── sum-to-n.rs │ │ ├── ub │ │ │ ├── README.md │ │ │ ├── oob.rs │ │ │ ├── unaligned_read.rs │ │ │ ├── null_deref.rs │ │ │ ├── mutable_aliasing.rs │ │ │ └── mut_const.rs │ │ ├── crate-tests │ │ │ ├── two-crate-bin │ │ │ │ ├── crate1 │ │ │ │ │ ├── Cargo.toml │ │ │ │ │ ├── Cargo.lock │ │ │ │ │ └── src │ │ │ │ │ │ └── lib.rs │ │ │ │ ├── main-crate │ │ │ │ │ ├── Cargo.toml │ │ │ │ │ ├── Cargo.lock │ │ │ │ │ └── src │ │ │ │ │ │ └── main.rs │ │ │ │ └── crate2::main.expected │ │ │ ├── two-crate-dylib │ │ │ │ ├── crate1 │ │ │ │ │ ├── Cargo.toml │ │ │ │ │ ├── Cargo.lock │ │ │ │ │ └── src │ │ │ │ │ │ └── lib.rs │ │ │ │ ├── main-crate │ │ │ │ │ ├── Cargo.toml │ │ │ │ │ ├── src │ │ │ │ │ │ └── lib.rs │ │ │ │ │ └── Cargo.lock │ │ │ │ └── crate2::test_crate1_with.expected │ │ │ ├── single-bin │ │ │ │ ├── main-crate │ │ │ │ │ ├── Cargo.toml │ │ │ │ │ ├── Cargo.lock │ │ │ │ │ └── src │ │ │ │ │ │ └── main.rs │ │ │ │ ├── single_exe::main.expected │ │ │ │ └── single_exe::a_module::twice.expected │ │ │ ├── single-lib │ │ │ │ ├── main-crate │ │ │ │ │ ├── Cargo.toml │ │ │ │ │ ├── Cargo.lock │ │ │ │ │ └── src │ │ │ │ │ │ └── lib.rs │ │ │ │ └── small_test_lib::testing::test_add_in_range.expected │ │ │ └── single-dylib │ │ │ │ ├── main-crate │ │ │ │ ├── Cargo.lock │ │ │ │ ├── src │ │ │ │ │ └── lib.rs │ │ │ │ └── Cargo.toml │ │ │ │ └── small_test_dylib::add.expected │ │ ├── exec-smir │ │ │ ├── references │ │ │ │ ├── simple.rs │ │ │ │ ├── refAsArg.rs │ │ │ │ ├── doubleRef.rs │ │ │ │ ├── mutableRef.rs │ │ │ │ ├── refReturned.rs │ │ │ │ ├── refAsArg2.rs │ │ │ │ ├── escapingScope.rs │ │ │ │ ├── array_elem_ref.rs │ │ │ │ └── weirdRefs.rs │ │ │ ├── pointers │ │ │ │ ├── offset_read.rs │ │ │ │ ├── offset_write.rs │ │ │ │ ├── offset_struct_field_read.rs │ │ │ │ ├── offset_get_unchecked.rs │ │ │ │ ├── offset_struct_field_write.rs │ │ │ │ ├── pointer-cast-zst.rs │ │ │ │ ├── ref_ptr_cases.rs │ │ │ │ └── pointer-cast-length-test-fail.rs │ │ │ ├── main-a-b-c │ │ │ │ ├── main-a-b-c.rs │ │ │ │ ├── main-a-b-c.run.state │ │ │ │ └── main-a-b-c.state │ │ │ ├── assign-cast │ │ │ │ ├── assign-cast │ │ │ │ ├── assign-cast2 │ │ │ │ └── assign-cast.rs │ │ │ ├── call-with-args │ │ │ │ ├── main-a-b-with-int.rs │ │ │ │ ├── closure-call.rs │ │ │ │ └── main-a-b-with-int.state │ │ │ ├── arrays │ │ │ │ ├── array_indexing.rs │ │ │ │ ├── array_write.rs │ │ │ │ └── array_inlined.rs │ │ │ ├── structs-tuples │ │ │ │ ├── structs-tuples.rs │ │ │ │ └── struct_field_update.rs │ │ │ ├── allocs │ │ │ │ ├── enum-two-refs-fail.rs │ │ │ │ ├── array_const_compare.rs │ │ │ │ ├── array_nest_compare.rs │ │ │ │ └── option_consts.rs │ │ │ ├── arithmetic │ │ │ │ ├── arithmetic.rs │ │ │ │ ├── arithmetic-unchecked-runs.rs │ │ │ │ └── unary.rs │ │ │ ├── niche-enum │ │ │ │ └── niche-enum.rs │ │ │ ├── intrinsic │ │ │ │ ├── blackbox.rs │ │ │ │ ├── blackbox_function_tys.expected.json │ │ │ │ └── raw_eq_simple.rs │ │ │ ├── newtype-pubkey │ │ │ │ └── newtype-pubkey.rs │ │ │ ├── struct-multi │ │ │ │ └── struct-multi.rs │ │ │ ├── enum │ │ │ │ └── enum.rs │ │ │ └── README.md │ │ └── run-smir-random │ │ │ ├── simple-types │ │ │ ├── test.rs │ │ │ ├── init-0.expected │ │ │ ├── init-2.expected │ │ │ ├── init-3.expected │ │ │ ├── init-5.expected │ │ │ ├── init-6.expected │ │ │ ├── init-1.expected │ │ │ ├── init-4.expected │ │ │ ├── init-7.expected │ │ │ ├── init-8.expected │ │ │ └── init-9.expected │ │ │ └── complex-types │ │ │ └── test.rs │ │ ├── utils.py │ │ └── test_functions.py └── pyproject.toml ├── deps ├── k_release ├── uv_release ├── rv-nix-tools ├── uv2nix ├── pyproject-build-systems └── stable-mir-json_release ├── package ├── version └── test-package.sh ├── .gitmodules ├── .gitignore ├── .flake8 ├── nix ├── kmir-source │ └── default.nix ├── kmir-pyk-pyproject │ └── default.nix ├── test │ └── package.nix ├── kmir-pyk │ ├── build-systems-overlay.nix │ └── default.nix ├── README.md └── kmir │ └── default.nix ├── .cruft.json ├── .github ├── workflows │ ├── Dockerfile │ └── p-token-release.yml └── actions │ └── with-docker │ └── action.yml └── LICENSE /kmir/src/kmir/py.typed: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /deps/k_release: -------------------------------------------------------------------------------- 1 | 7.1.304 2 | -------------------------------------------------------------------------------- /deps/uv_release: -------------------------------------------------------------------------------- 1 | 0.9.14 2 | -------------------------------------------------------------------------------- /kmir/src/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /package/version: -------------------------------------------------------------------------------- 1 | 0.4.0 2 | -------------------------------------------------------------------------------- /kmir/src/kmir/kdist/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kmir/src/tests/unit/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kmir/src/kmir/testing/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /deps/rv-nix-tools: -------------------------------------------------------------------------------- 1 | 854d4f05ea78547d46e807b414faad64cea10ae4 -------------------------------------------------------------------------------- /deps/uv2nix: -------------------------------------------------------------------------------- 1 | 4cca323a547a1aaa9b94929c4901bed5343eafe8 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/local/input.json: -------------------------------------------------------------------------------- 1 | 2 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/span/input.json: -------------------------------------------------------------------------------- 1 | 2 2 | -------------------------------------------------------------------------------- /deps/pyproject-build-systems: -------------------------------------------------------------------------------- 1 | 042904167604c681a090c07eb6967b4dd4dae88c 2 | -------------------------------------------------------------------------------- /deps/stable-mir-json_release: -------------------------------------------------------------------------------- 1 | 626e8fed0470078c4d980b6b5b503a3aceb355ec 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/body/reference.sort: -------------------------------------------------------------------------------- 1 | Body 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/maybelocal/input.json: -------------------------------------------------------------------------------- 1 | 2 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/span/reference.sort: -------------------------------------------------------------------------------- 1 | Span 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/basicblockidx/input.json: -------------------------------------------------------------------------------- 1 | 1 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/local/reference.kmir: -------------------------------------------------------------------------------- 1 | local(2) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/local/reference.sort: -------------------------------------------------------------------------------- 1 | Local 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/place/reference.sort: -------------------------------------------------------------------------------- 1 | Place 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/span/reference.kmir: -------------------------------------------------------------------------------- 1 | span(2) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/functions/reference.sort: -------------------------------------------------------------------------------- 1 | FunctionNames -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/maybebasicblockidx/input.json: -------------------------------------------------------------------------------- 1 | 1 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/monoitem/reference.sort: -------------------------------------------------------------------------------- 1 | MonoItem 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/operand/reference.sort: -------------------------------------------------------------------------------- 1 | Operand 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/rvaluecast/reference.sort: -------------------------------------------------------------------------------- 1 | Rvalue 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/statement/reference.sort: -------------------------------------------------------------------------------- 1 | Statement 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/testsort2/reference.sort: -------------------------------------------------------------------------------- 1 | TestSort2 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/bool-false.expected: -------------------------------------------------------------------------------- 1 | BoolVal ( false ) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/bool-true.expected: -------------------------------------------------------------------------------- 1 | BoolVal ( true ) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/i8.expected: -------------------------------------------------------------------------------- 1 | Integer ( -15 , 8 , true ) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/u8.expected: -------------------------------------------------------------------------------- 1 | Integer ( 241 , 8 , false ) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/basicblock1/reference.sort: -------------------------------------------------------------------------------- 1 | BasicBlock 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/basicblock2/reference.sort: -------------------------------------------------------------------------------- 1 | BasicBlock 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/maybelocal/reference.sort: -------------------------------------------------------------------------------- 1 | MaybeLocal 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/rvalueaggregate/reference.sort: -------------------------------------------------------------------------------- 1 | Rvalue 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/statements/reference.sort: -------------------------------------------------------------------------------- 1 | Statements 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/testsort2/input.json: -------------------------------------------------------------------------------- 1 | [5, [1, 2, 3]] 2 | -------------------------------------------------------------------------------- /kmir/src/kmir/__init__.py: -------------------------------------------------------------------------------- 1 | from typing import Final 2 | 3 | VERSION: Final = '0.3.181' 4 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/i128.expected: -------------------------------------------------------------------------------- 1 | Integer ( -15 , 128 , true ) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/i16.expected: -------------------------------------------------------------------------------- 1 | Integer ( -15 , 16 , true ) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/i32.expected: -------------------------------------------------------------------------------- 1 | Integer ( -15 , 32 , true ) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/i64.expected: -------------------------------------------------------------------------------- 1 | Integer ( -15 , 64 , true ) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/u16.expected: -------------------------------------------------------------------------------- 1 | Integer ( 65521 , 16 , false ) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/niche-enum.rs: -------------------------------------------------------------------------------- 1 | ../exec-smir/niche-enum/niche-enum.rs -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/offset_read.rs: -------------------------------------------------------------------------------- 1 | ../exec-smir/pointers/offset_read.rs -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/offset_write.rs: -------------------------------------------------------------------------------- 1 | ../exec-smir/pointers/offset_write.rs -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/basicblockidx/reference.sort: -------------------------------------------------------------------------------- 1 | BasicBlockIdx 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/place/input.json: -------------------------------------------------------------------------------- 1 | {"local":3,"projection":[]} 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/statementassign1/reference.sort: -------------------------------------------------------------------------------- 1 | Statement 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/statementassign2/reference.sort: -------------------------------------------------------------------------------- 1 | Statement 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/terminatorgoto/reference.sort: -------------------------------------------------------------------------------- 1 | Terminator 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/terminatorkindreturn/input.json: -------------------------------------------------------------------------------- 1 | "Return" 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/terminatorreturn/reference.sort: -------------------------------------------------------------------------------- 1 | Terminator 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/typeinfoenumtype/reference.sort: -------------------------------------------------------------------------------- 1 | TypeInfo 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/u32.expected: -------------------------------------------------------------------------------- 1 | Integer ( 4294967281 , 32 , false ) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/assert-true.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | assert!(true) 3 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/assert-true.main.cli-prune.expected: -------------------------------------------------------------------------------- 1 | Pruned nodes: [] -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/aggregatekindadt/reference.sort: -------------------------------------------------------------------------------- 1 | AggregateKind 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/basicblockidx/reference.kmir: -------------------------------------------------------------------------------- 1 | basicBlockIdx(1) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/maybelocal/reference.kmir: -------------------------------------------------------------------------------- 1 | someLocal(local(2)) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/terminatorkindgoto/reference.sort: -------------------------------------------------------------------------------- 1 | TerminatorKind 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/array_nest_compare.rs: -------------------------------------------------------------------------------- 1 | ../exec-smir/allocs/array_nest_compare.rs -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/assert-false-fail.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | assert!(false) 3 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/enum-two-refs-fail.rs: -------------------------------------------------------------------------------- 1 | ../exec-smir/allocs/enum-two-refs-fail.rs -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/integers/div.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | assert!(420 / 10 ==42); 3 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/aggregatekindadt/input.json: -------------------------------------------------------------------------------- 1 | {"Adt":[0,0,[],null,null]} 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/maybebasicblockidx/reference.sort: -------------------------------------------------------------------------------- 1 | MaybeBasicBlockIdx 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/place/reference.kmir: -------------------------------------------------------------------------------- 1 | place(local(3), .ProjectionElems) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/terminatorkindgoto/input.json: -------------------------------------------------------------------------------- 1 | {"Goto":{"target":1}} 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/terminatorkindreturn/reference.sort: -------------------------------------------------------------------------------- 1 | TerminatorKind 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/terminatorreturn/input.json: -------------------------------------------------------------------------------- 1 | {"kind":"Return","span":2} 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/str.expected: -------------------------------------------------------------------------------- 1 | StringVal ( "Hello, World! \xf0\x9f\x8c\x8f" ) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/tuple-empty.expected: -------------------------------------------------------------------------------- 1 | Aggregate ( variantIdx ( 0 ) , .List ) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/u64.expected: -------------------------------------------------------------------------------- 1 | Integer ( 18446744073709551601 , 64 , false ) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/integers/modulo.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | assert!(42 % 10 == 2); 3 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/operand/input.json: -------------------------------------------------------------------------------- 1 | {"Move":{"local":4,"projection":[]}} 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/statement/input.json: -------------------------------------------------------------------------------- 1 | {"kind":{"StorageLive":2},"span":2} 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/terminatorkindreturn/reference.kmir: -------------------------------------------------------------------------------- 1 | terminatorKindReturn 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/enum-option-ref-none.expected: -------------------------------------------------------------------------------- 1 | Aggregate ( variantIdx ( 0 ) , .List ) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/offset_struct_field_read.rs: -------------------------------------------------------------------------------- 1 | ../exec-smir/pointers/offset_struct_field_read.rs -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/maybebasicblockidx/reference.kmir: -------------------------------------------------------------------------------- 1 | someBasicBlockIdx(basicBlockIdx(1)) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/operand/reference.kmir: -------------------------------------------------------------------------------- 1 | operandMove(place(local(4), .ProjectionElems)) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/terminatorgoto/input.json: -------------------------------------------------------------------------------- 1 | {"kind":{"Goto":{"target":1}},"span":2} 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/enum-2-variants-0-fields.expected: -------------------------------------------------------------------------------- 1 | Aggregate ( variantIdx ( 1 ) , .List ) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/enum-option-nonzero-none.expected: -------------------------------------------------------------------------------- 1 | Aggregate ( variantIdx ( 0 ) , .List ) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/branch-negative.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | assert!((1_i8 << 7) + 1 == -127_i8); 3 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/offset_struct_field_write.rs: -------------------------------------------------------------------------------- 1 | ../exec-smir/pointers/offset_struct_field_write.rs -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/terminatorkindgoto/reference.kmir: -------------------------------------------------------------------------------- 1 | terminatorKindGoto(basicBlockIdx(1)) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/terminatorreturn/reference.kmir: -------------------------------------------------------------------------------- 1 | terminator(terminatorKindReturn,span(2)) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/testsort2/reference.kmir: -------------------------------------------------------------------------------- 1 | testSort2(5, ListItem(1) ListItem(2) ListItem(3)) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/u128.expected: -------------------------------------------------------------------------------- 1 | Integer ( 340282366920938463463374607431768211441 , 128 , false ) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/pointer-cast-length-test-fail.rs: -------------------------------------------------------------------------------- 1 | ../exec-smir/pointers/pointer-cast-length-test-fail.rs -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/statement/reference.kmir: -------------------------------------------------------------------------------- 1 | statement(statementKindStorageLive(local(2)), span(2)) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/assert_eq_exp.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let a = 42; 3 | 4 | assert_eq!(3 + 39, a); 5 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/strings-chars/str-empty.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let a = ""; 3 | 4 | assert!(a == ""); 5 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/rvaluecast/input.json: -------------------------------------------------------------------------------- 1 | {"Cast":["IntToInt",{"Move":{"local":4,"projection":[]}},2]} 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/strings-chars/str-trivial.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let a = "a"; 3 | 4 | assert!(a == "a"); 5 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/terminatorgoto/reference.kmir: -------------------------------------------------------------------------------- 1 | terminator(terminatorKindGoto(basicBlockIdx(1)),span(2)) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/arrays/array.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let a = [1, 2, 3, 4]; 3 | 4 | assert!(a == [1, 2, 3, 4]); 5 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/basicblock2/input.json: -------------------------------------------------------------------------------- 1 | {"statements":[], "terminator":{"kind":{"Goto":{"target":1}},"span":2}} 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/ub/README.md: -------------------------------------------------------------------------------- 1 | These rust programs are valid and succeed in compilation however are unsound as they contain UB. -------------------------------------------------------------------------------- /kmir/src/tests/integration/utils.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | 3 | TEST_DATA_DIR = (Path(__file__).parent / 'data').resolve(strict=True) 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "stable-mir-json"] 2 | path = deps/stable-mir-json 3 | url = https://github.com/runtimeverification/stable-mir-json 4 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/enum-2-variants-1-field.expected: -------------------------------------------------------------------------------- 1 | Aggregate ( variantIdx ( 1 ) , ListItem ( BoolVal ( true ) ) ) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/strings-chars/char-trivial.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let a:char = 'a'; 3 | 4 | assert!(a == 'a'); 5 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/assert_eq.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let a = 42; 3 | let b = 3 + 39; 4 | 5 | assert_eq!(b, a); 6 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/strings-chars/std-string-empty.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let a:String = String::new(); 3 | assert!(a == ""); 4 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/enum-1-variant-1-field.expected: -------------------------------------------------------------------------------- 1 | Aggregate ( variantIdx ( 0 ) , ListItem ( Integer ( 255 , 32 , true ) ) ) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/enum-option-nonzero-some.expected: -------------------------------------------------------------------------------- 1 | Aggregate ( variantIdx ( 1 ) , ListItem ( Integer ( 123 , 8 , false ) ) ) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/const-empty.rs: -------------------------------------------------------------------------------- 1 | const EMPTY: () = (); 2 | 3 | fn main() { 4 | let e = (); 5 | assert!(e == EMPTY); 6 | } 7 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/tuples-simple.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let tup:(i32, i32) = (42, 99); 3 | 4 | assert!(tup.0 != tup.1); 5 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/assert/assert_eq.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let a = 42; 3 | let b = 3 + 39; 4 | 5 | assert_eq!(b, a); 6 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/closures/closure-no-args.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let sum = || -> u32 { 42 }; 3 | 4 | assert!(sum() == 42); 5 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/tuples/tuple-eq.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let tup:(i32, i32) = (42, 99); 3 | 4 | assert!(tup == (42, 99)); 5 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/basicblock2/reference.kmir: -------------------------------------------------------------------------------- 1 | basicBlock(.Statements, terminator(terminatorKindGoto(basicBlockIdx(1)),span(2))) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/strings-chars/std-to-string.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let a:String = "abcd".to_string(); 3 | assert!(a == "abcd"); 4 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/tuples/tuples-simple.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let tup:(i32, i32) = (42, 99); 3 | 4 | assert!(tup.0 != tup.1); 5 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/ref-deref.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let a = 42; 3 | let b = &a; 4 | let c = *b; 5 | 6 | assert!(c == 42); 7 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/link.arith.smir+unary.smir.counts.expected: -------------------------------------------------------------------------------- 1 | name: arith,unary 2 | types: 40 3 | functions: 19 4 | items: 20 5 | spans: 130 -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/closures/closure-args.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let sum = |x, y| -> i32 { x + y }; 3 | 4 | assert!(sum(20, 22) == 42); 5 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/slices/slice.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let a = [1, 2, 3, 4]; 3 | 4 | let b = &a[1..3]; 5 | 6 | assert!(b == [2, 3]); 7 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /dist/ 2 | __pycache__/ 3 | .coverage 4 | /deps/.stable-mir-json 5 | /.vscode/ 6 | kmir/src/tests/integration/data/**/target 7 | .DS_Store 8 | proof/ 9 | /result* -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/local-raw-fail.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut x: u32 = 3; 3 | let y: *mut u32 = &mut x; 4 | unsafe { *y = 0; } 5 | } 6 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/ref-deref/ref-deref.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let a = 42; 3 | let b = &a; 4 | let c = *b; 5 | 6 | assert!(c == 42); 7 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/two-crate-bin/crate1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "crate1" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/two-crate-dylib/crate1/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "crate1" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/references/simple.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let x = 42i8; 3 | let y = &x; 4 | let z = *y; 5 | 6 | assert!(z == x); 7 | } 8 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/double-ref-deref.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let a = 42; 3 | let b = &a; 4 | let c = &b; 5 | 6 | assert!(**c == 42); 7 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/primitive-type-bounds.rs: -------------------------------------------------------------------------------- 1 | fn main () { 2 | let a:u32 = 4294967295; 3 | let b:u32 = 4294967294 + 1; 4 | assert!(a == b) 5 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/strange-ref-deref.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let a = 42; 3 | let mut b = &a; 4 | b = &b; 5 | 6 | assert!(*b == 42); 7 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/rvalueaggregate/input.json: -------------------------------------------------------------------------------- 1 | {"Aggregate":["Tuple",[{"Copy":{"local":3,"projection":[]}},{"Copy":{"local":5,"projection":[]}}]]} 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/single-bin/main-crate/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "single-exe" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/iterator-simple-fail.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let arr = [1]; 3 | 4 | for elem in arr { 5 | assert!(elem != 0); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/integers/primitive-type-bounds.rs: -------------------------------------------------------------------------------- 1 | fn main () { 2 | let a:u32 = 4294967295; 3 | let b:u32 = 4294967294 + 1; 4 | assert!(a == b) 5 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/ref-deref/double-ref-deref.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let a = 42; 3 | let b = &a; 4 | let c = &b; 5 | 6 | assert!(**c == 42); 7 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/ref-deref/strange-ref-deref.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let a = 42; 3 | let mut b = &a; 4 | b = &b; 5 | 6 | assert!(*b == 42); 7 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/single-lib/main-crate/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "small-test-lib" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/tuple-bool-u32.expected: -------------------------------------------------------------------------------- 1 | Aggregate ( variantIdx ( 0 ) , ListItem ( BoolVal ( true ) ) 2 | ListItem ( Integer ( 305419896 , 32 , false ) ) ) 3 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/pointers/offset_read.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let arr = [11, 22, 33]; 3 | let subslice = &arr[1..]; 4 | assert!(subslice == [22, 33]); 5 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/rvaluecast/reference.kmir: -------------------------------------------------------------------------------- 1 | rvalueCast 2 | ( 3 | castKindIntToInt, 4 | operandMove(place(local(4), .ProjectionElems)), 5 | ty(2) 6 | ) 7 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/enum-1-variant-2-fields.expected: -------------------------------------------------------------------------------- 1 | Aggregate ( variantIdx ( 0 ) , ListItem ( Integer ( 255 , 16 , true ) ) 2 | ListItem ( BoolVal ( true ) ) ) 3 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/main-a-b-c/main-a-b-c.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | a() 3 | } 4 | fn a() { 5 | b() 6 | } 7 | fn b() { 8 | c() 9 | } 10 | fn c() { 11 | } 12 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/bool-false.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [ 3 | 0 4 | ], 5 | "types": [], 6 | "typeInfo": { 7 | "PrimitiveType": "Bool" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/bool-true.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [ 3 | 1 4 | ], 5 | "types": [], 6 | "typeInfo": { 7 | "PrimitiveType": "Bool" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/tuple-u8-i32.expected: -------------------------------------------------------------------------------- 1 | Aggregate ( variantIdx ( 0 ) , ListItem ( Integer ( 171 , 8 , false ) ) 2 | ListItem ( Integer ( 305419896 , 32 , true ) ) ) 3 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/statementassign1/input.json: -------------------------------------------------------------------------------- 1 | {"kind":{"Assign":[{"local":3,"projection":[]},{"Cast":["IntToInt",{"Move":{"local":4,"projection":[]}},2]}]},"span":6} 2 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 120 3 | extend-select = B9, TC1 4 | extend-ignore = B950,E,W1,W2,W3,W4,W5 5 | per-file-ignores = 6 | */__init__.py: F401 7 | type-checking-strict = true 8 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/assign-cast/assign-cast: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/mir-semantics/HEAD/kmir/src/tests/integration/data/exec-smir/assign-cast/assign-cast -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/assign-cast/assign-cast2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/runtimeverification/mir-semantics/HEAD/kmir/src/tests/integration/data/exec-smir/assign-cast/assign-cast2 -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/enum.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | #![allow(dead_code)] 3 | enum Letter { 4 | A, 5 | B, 6 | } 7 | 8 | fn main() { 9 | let a = Letter::A; 10 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/enums/enum.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | #![allow(dead_code)] 3 | enum Letter { 4 | A, 5 | B, 6 | } 7 | 8 | fn main() { 9 | let a = Letter::A; 10 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/call-with-args/main-a-b-with-int.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | a(10) 3 | } 4 | fn a(s: usize) { 5 | b(s, 11) 6 | } 7 | fn b(_s: usize, _t: i16) { 8 | 9 | } 10 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/struct.rs: -------------------------------------------------------------------------------- 1 | struct St { 2 | a:u32, 3 | b:u32, 4 | } 5 | 6 | fn main() { 7 | let s:St = St { a:1, b:2 }; 8 | 9 | assert!(s.a + 1 == s.b); 10 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/option/option-construction.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | fn main() { 3 | let a:Option = Some(42); 4 | let b:Option = None; 5 | let c:u32 = a.unwrap(); 6 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/ub/oob.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let arr = [1, 2, 3]; 3 | let _x: i32; 4 | unsafe { 5 | let p = arr.as_ptr().add(3); 6 | _x = *p; // <-- UB 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/structs/struct.rs: -------------------------------------------------------------------------------- 1 | struct St { 2 | a:u32, 3 | b:u32, 4 | } 5 | 6 | fn main() { 7 | let s:St = St { a:1, b:2 }; 8 | 9 | assert!(s.a + 1 == s.b); 10 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/aggregatekindadt/reference.kmir: -------------------------------------------------------------------------------- 1 | aggregateKindAdt 2 | ( 3 | adtDef(0), 4 | variantIdx(0), 5 | .GenericArgs, 6 | noUserTypeAnnotationIndex, 7 | noFieldIdx 8 | ) 9 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/i8.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [ 3 | 241 4 | ], 5 | "types": [], 6 | "typeInfo": { 7 | "PrimitiveType": { 8 | "Int": "I8" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/u8.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [ 3 | 241 4 | ], 5 | "types": [], 6 | "typeInfo": { 7 | "PrimitiveType": { 8 | "Uint": "U8" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/pointers/offset_write.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut arr = [11, 22, 33]; 3 | let subslice = &mut arr[1..]; 4 | subslice[0] = 44; 5 | assert!(arr == [11, 44, 33]); 6 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/ub/unaligned_read.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut x: [u8; 4] = [0; 4]; 3 | unsafe { 4 | let p = x.as_mut_ptr().add(1) as *mut u32; 5 | *p = 0xDEADBEEF; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/arrays/array_indexing.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | 3 | let a: [i16; 4] = [1;4]; 4 | 5 | let b = a[0]; 6 | let c = a[b as usize]; 7 | 8 | assert!(b == c); 9 | } 10 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/references/refAsArg.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let x = 42i8; 3 | 4 | let z = f(&x); 5 | 6 | assert!(z == x); 7 | } 8 | 9 | fn f(y: &i8) -> i8{ 10 | *y 11 | } 12 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/if.rs: -------------------------------------------------------------------------------- 1 | fn ite(flag: bool) { 2 | if flag { 3 | assert!(true) 4 | } else { 5 | assert!(false) 6 | } 7 | } 8 | 9 | fn main() { 10 | ite(true) 11 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/tuple-i16-bool-u8.expected: -------------------------------------------------------------------------------- 1 | Aggregate ( variantIdx ( 0 ) , ListItem ( Integer ( 4660 , 16 , true ) ) 2 | ListItem ( BoolVal ( true ) ) 3 | ListItem ( Integer ( 254 , 8 , false ) ) ) 4 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/else.rs: -------------------------------------------------------------------------------- 1 | fn ite(flag: bool) { 2 | if flag { 3 | assert!(false) 4 | } else { 5 | assert!(true) 6 | } 7 | } 8 | 9 | fn main() { 10 | ite(false) 11 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/rvalueaggregate/reference.kmir: -------------------------------------------------------------------------------- 1 | rvalueAggregate 2 | ( 3 | aggregateKindTuple, 4 | operandCopy(place(local(3), .ProjectionElems)) operandCopy(place(local(5), .ProjectionElems)) 5 | ) 6 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/two-crate-bin/main-crate/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "crate2" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | crate1 = { version = "0.1.0", path = "../crate1" } 8 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/i16.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [ 3 | 241, 4 | 255 5 | ], 6 | "types": [], 7 | "typeInfo": { 8 | "PrimitiveType": { 9 | "Int": "I16" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/struct-simple-permuted-fields.expected: -------------------------------------------------------------------------------- 1 | Aggregate ( variantIdx ( 0 ) , ListItem ( Integer ( 15 , 8 , false ) ) 2 | ListItem ( Integer ( 31 , 8 , false ) ) 3 | ListItem ( BoolVal ( true ) ) ) 4 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/u16.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [ 3 | 241, 4 | 255 5 | ], 6 | "types": [], 7 | "typeInfo": { 8 | "PrimitiveType": { 9 | "Uint": "U16" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/maybe-uninit.rs: -------------------------------------------------------------------------------- 1 | use std::mem::MaybeUninit; 2 | fn main() { 3 | let m_init = MaybeUninit::new(1); 4 | let init = unsafe { m_init.assume_init() }; 5 | 6 | assert!(init == 1); 7 | } 8 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/basicblock1/input.json: -------------------------------------------------------------------------------- 1 | {"statements":[{"kind":{"StorageLive":1},"span":2},{"kind":{"StorageLive":2},"span":2},{"kind":{"StorageDead":3},"span":2}], "terminator":{"kind":"Return","span":2}} 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/statementassign2/input.json: -------------------------------------------------------------------------------- 1 | {"kind":{"Assign":[{"local":6,"projection":[]},{"Aggregate":["Tuple",[{"Copy":{"local":3,"projection":[]}},{"Copy":{"local":5,"projection":[]}}]]}]},"span":9} 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/array_write.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | 3 | let mut a: [i16; 4] = [1;4]; 4 | 5 | a[0] = 2; 6 | 7 | let b = &mut (a[1]); 8 | 9 | *b = 2; 10 | 11 | assert!(a[0] == a[1]); 12 | } 13 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/body/input.json: -------------------------------------------------------------------------------- 1 | {"arg_count":0,"blocks":[{"statements":[],"terminator":{"kind":"Return","span":3}}],"locals":[{"mutability":"Mut","span":12,"ty":3}],"span":17,"spread_arg":null,"var_debug_info":[]} 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/two-crate-bin/crate1/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "crate1" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/ub/null_deref.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let p: *const i32 = std::ptr::null(); 3 | let val:i32; 4 | unsafe { 5 | val = *p; 6 | } 7 | crash(val); 8 | } 9 | 10 | fn crash(_arg: i32) {} 11 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/single-bin/main-crate/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "single-exe" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/two-crate-dylib/crate1/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "crate1" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/array-u8-const-len.expected: -------------------------------------------------------------------------------- 1 | Range ( ListItem ( Integer ( 0 , 8 , false ) ) 2 | ListItem ( Integer ( 1 , 8 , false ) ) 3 | ListItem ( Integer ( 2 , 8 , false ) ) 4 | ListItem ( Integer ( 3 , 8 , false ) ) ) 5 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/array-u8-implicit-len.expected: -------------------------------------------------------------------------------- 1 | Range ( ListItem ( Integer ( 0 , 8 , false ) ) 2 | ListItem ( Integer ( 1 , 8 , false ) ) 3 | ListItem ( Integer ( 2 , 8 , false ) ) 4 | ListItem ( Integer ( 3 , 8 , false ) ) ) 5 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/arrays/array_write.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | 3 | let mut a: [i16; 4] = [1;4]; 4 | 5 | a[0] = 2; 6 | 7 | let b = &mut (a[1]); 8 | 9 | *b = 2; 10 | 11 | assert!(a[0] == a[1]); 12 | } 13 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/single-lib/main-crate/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "small-test-lib" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/floats/float.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let a:f32 = 3.5; 3 | let b:f32 = 1.2; 4 | 5 | assert!(a + b == 4.7); 6 | 7 | let c:f64 = 3.5; 8 | let d:f64 = 1.2; 9 | 10 | assert!(c + d == 4.7); 11 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/single-dylib/main-crate/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "small-test-dylib" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/i32.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [ 3 | 241, 4 | 255, 5 | 255, 6 | 255 7 | ], 8 | "types": [], 9 | "typeInfo": { 10 | "PrimitiveType": { 11 | "Int": "I32" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/u32.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [ 3 | 241, 4 | 255, 5 | 255, 6 | 255 7 | ], 8 | "types": [], 9 | "typeInfo": { 10 | "PrimitiveType": { 11 | "Uint": "U32" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/pointers/offset_struct_field_read.rs: -------------------------------------------------------------------------------- 1 | struct Foo { 2 | arr: [u16; 3], 3 | } 4 | 5 | fn main() { 6 | let foo = Foo { arr: [11, 22, 33] }; 7 | let subslice = &foo.arr[1..]; 8 | assert!(subslice == [22, 33]); 9 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/interior-mut3-fail.rs: -------------------------------------------------------------------------------- 1 | use std::cell::UnsafeCell; 2 | 3 | fn main() { 4 | let data = UnsafeCell::new(0); 5 | 6 | unsafe { 7 | *data.get() += 42; 8 | } 9 | 10 | assert!(data.into_inner() == 42) 11 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/memory/box.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let a = Box::new(5); 3 | let b = Box::new(5); 4 | 5 | assert!(a == b); 6 | assert!(*a == *b); 7 | assert!(*a == 5); 8 | // assert!(a == 5); // Not possible to equate Box::(Type) with Type 9 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/two-crate-dylib/main-crate/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "crate2" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | crate-type = ["dylib"] 8 | 9 | [dependencies] 10 | crate1 = { version = "0.1.0", path = "../crate1" } 11 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/const-arithm-simple.rs: -------------------------------------------------------------------------------- 1 | fn test(x: usize, y:usize) -> bool { 2 | return x > y; 3 | } 4 | 5 | 6 | fn main() { 7 | let x:usize = 42; 8 | let y:usize = 0; 9 | let z:bool = test(x, y); 10 | assert!(z); 11 | return (); 12 | } 13 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/statements/input.json: -------------------------------------------------------------------------------- 1 | [ 2 | {"kind":{"StorageLive":2},"span":2}, 3 | {"kind":{"Assign":[{"local":3,"projection":[]},{"Cast":["IntToInt",{"Move":{"local":4,"projection":[]}},2]}]},"span":6}, 4 | {"kind":{"StorageDead":3},"span":2} 5 | ] 6 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/integers/const-arithm-simple.rs: -------------------------------------------------------------------------------- 1 | fn test(x: usize, y:usize) -> bool { 2 | return x > y; 3 | } 4 | 5 | 6 | fn main() { 7 | let x:usize = 42; 8 | let y:usize = 0; 9 | let z:bool = test(x, y); 10 | assert!(z); 11 | return (); 12 | } 13 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/basicblock1/reference.kmir: -------------------------------------------------------------------------------- 1 | basicBlock(statement(statementKindStorageLive(local(1)), span(2)) statement(statementKindStorageLive(local(2)), span(2)) statement(statementKindStorageDead(local(3)), span(2)), terminator(terminatorKindReturn,span(2))) 2 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/recursion-simple-match.rs: -------------------------------------------------------------------------------- 1 | fn sum_to_n_rec(n:u32) -> u32 { 2 | match n { 3 | 0 => 0, 4 | _ => n + sum_to_n_rec(n - 1), 5 | } 6 | } 7 | 8 | fn main() { 9 | let ans = sum_to_n_rec(10); 10 | 11 | assert!(ans == 55); 12 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/recursion-simple.rs: -------------------------------------------------------------------------------- 1 | fn sum_to_n_rec(n:u32) -> u32 { 2 | if n == 0 { 3 | 0 4 | } else { 5 | n + sum_to_n_rec(n - 1) 6 | } 7 | } 8 | 9 | fn main() { 10 | let ans = sum_to_n_rec(10); 11 | 12 | assert!(ans == 55); 13 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/type-table: -------------------------------------------------------------------------------- 1 | [ 2 | [0, { "PrimitiveType": { "Uint": "U8"}}], 3 | [1, { "PrimitiveType": "Bool"}], 4 | [2, { "PrimitiveType": { "Int": "I16"}}], 5 | [3, { "PrimitiveType": { "Int": "I32"}}], 6 | [4, { "PrimitiveType": { "Uint": "U32"}}] 7 | ] 8 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/body/reference.kmir: -------------------------------------------------------------------------------- 1 | body 2 | ( 3 | basicBlock(.Statements, terminator(terminatorKindReturn, span(3))) .BasicBlocks, 4 | localDecl(ty(3), span(12), mutabilityMut) .LocalDecls, 5 | 0, 6 | .VarDebugInfos, 7 | noLocal, 8 | span(17) 9 | ) 10 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/fibonacci.rs: -------------------------------------------------------------------------------- 1 | fn fibonacci(n:u32) -> u32 { 2 | match n { 3 | 0 => 0, 4 | 1 => 1, 5 | _ => fibonacci(n - 2) + fibonacci(n - 1), 6 | } 7 | } 8 | 9 | fn main() { 10 | let ans = fibonacci(5); 11 | 12 | assert!(ans == 5); 13 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/recursion/recursion-simple-match.rs: -------------------------------------------------------------------------------- 1 | fn sum_to_n_rec(n:u32) -> u32 { 2 | match n { 3 | 0 => 0, 4 | _ => n + sum_to_n_rec(n - 1), 5 | } 6 | } 7 | 8 | fn main() { 9 | let ans = sum_to_n_rec(10); 10 | 11 | assert!(ans == 55); 12 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/recursion/recursion-simple.rs: -------------------------------------------------------------------------------- 1 | fn sum_to_n_rec(n:u32) -> u32 { 2 | if n == 0 { 3 | 0 4 | } else { 5 | n + sum_to_n_rec(n - 1) 6 | } 7 | } 8 | 9 | fn main() { 10 | let ans = sum_to_n_rec(10); 11 | 12 | assert!(ans == 55); 13 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/pointers/offset_get_unchecked.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let arr = [11, 22, 33]; 3 | let mid_ref = unsafe { arr.get_unchecked(1) }; 4 | let mid = *mid_ref; 5 | assert!(mid == 22); 6 | let last = unsafe { arr.get_unchecked(2) }; 7 | assert!(*last == 33); 8 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/pointers/offset_struct_field_write.rs: -------------------------------------------------------------------------------- 1 | struct Foo { 2 | arr: [u16; 3], 3 | } 4 | 5 | fn main() { 6 | let mut foo = Foo { arr: [11, 22, 33] }; 7 | let subslice = &mut foo.arr[1..]; 8 | subslice[0] = 44; 9 | assert!(foo.arr == [11, 44, 33]); 10 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/stack_assign.rs: -------------------------------------------------------------------------------- 1 | fn assign<'a>(dst: &mut &'a i32, src: &&'a i32) { 2 | *dst = *src; 3 | } 4 | 5 | fn main() { 6 | let x = 1; 7 | let mut dst = &x; 8 | let src = dst; 9 | 10 | assign(&mut dst, &src); 11 | 12 | assert_eq!(*dst, 1); 13 | } 14 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/ub/mutable_aliasing.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut x = 5; 3 | let p1 = &mut x as *mut i32; 4 | let p2 = &mut x as *mut i32; 5 | unsafe { 6 | *p1 = 10; 7 | assert!(x == 10); 8 | *p2 = 20; 9 | assert!(x == 20); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/i64.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [ 3 | 241, 4 | 255, 5 | 255, 6 | 255, 7 | 255, 8 | 255, 9 | 255, 10 | 255 11 | ], 12 | "types": [], 13 | "typeInfo": { 14 | "PrimitiveType": { 15 | "Int": "I64" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/u64.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [ 3 | 241, 4 | 255, 5 | 255, 6 | 255, 7 | 255, 8 | 255, 9 | 255, 10 | 255 11 | ], 12 | "types": [], 13 | "typeInfo": { 14 | "PrimitiveType": { 15 | "Uint": "U64" 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/loop.rs: -------------------------------------------------------------------------------- 1 | fn property_test() { 2 | let mut x = 0; 3 | let y = 10; 4 | let mut s = 0; 5 | 6 | while x < y { 7 | x += 1; 8 | s += x; 9 | } 10 | 11 | assert!(s == 55); 12 | 13 | } 14 | 15 | fn main() { 16 | property_test(); 17 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/integers/shl_min.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | assert!(-128_i8 << 1 == 0); 3 | assert!(-32768_i16 << 1 == 0); 4 | assert!(-2147483648_i32 << 1 == 0); 5 | assert!(-9223372036854775808_i64 << 1 == 0); 6 | assert!(-170141183460469231731687303715884105728_i128 << 1 == 0); 7 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/recursion/fibonacci.rs: -------------------------------------------------------------------------------- 1 | fn fibonacci(n:u32) -> u32 { 2 | match n { 3 | 0 => 0, 4 | 1 => 1, 5 | _ => fibonacci(n - 2) + fibonacci(n - 1), 6 | } 7 | } 8 | 9 | fn main() { 10 | let ans = fibonacci(5); 11 | 12 | assert!(ans == 5); 13 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/references/doubleRef.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // double references 3 | let x = 42i8; 4 | let y = &x; 5 | let z = &y; 6 | 7 | assert!(**z == x); // uses CopyForDeref(*z) 8 | 9 | assert!(z == &&x); // compare instance &&i8, uses &&&i8 arguments 10 | } 11 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/references/mutableRef.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut x = 42i8; 3 | 4 | f(&mut x); 5 | 6 | assert!(x == 32); 7 | 8 | let xref = &mut x; 9 | 10 | *xref = 22; 11 | 12 | assert!(x == 22); 13 | } 14 | 15 | fn f(y: &mut i8) { 16 | *y = 32 17 | } 18 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/loop-fail.rs: -------------------------------------------------------------------------------- 1 | fn property_test() { 2 | let mut x = 0; 3 | let y = 10; 4 | let mut s = 0; 5 | 6 | while x < y { 7 | x += 1; 8 | s += x; 9 | } 10 | 11 | assert!(s == 56); 12 | 13 | } 14 | 15 | fn main() { 16 | property_test(); 17 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/assert-inhabited-fail.rs: -------------------------------------------------------------------------------- 1 | #![feature(core_intrinsics)] 2 | #![feature(never_type)] 3 | use std::intrinsics::assert_inhabited; 4 | 5 | fn main() { 6 | std::hint::black_box( 7 | assert_inhabited::() // Up to compiler/CodegenBackend to panic or NOOP 8 | ); 9 | } 10 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/raw-ptr-cast-fail.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut data = 11; 3 | let ptr = &data as *const i32; 4 | 5 | let ptr_mut = &mut data as *mut i32; 6 | unsafe { 7 | (*ptr_mut) = 44; 8 | assert_eq!(44, *ptr); // FIXME: fails due to thunks on casts 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/references/refReturned.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let x = 42i8; 3 | 4 | let y = f(&x); 5 | let z = *y; 6 | 7 | assert!(z == x); 8 | } 9 | 10 | // returning references (back, not from locals) 11 | fn f(x:&i8) -> &i8 { 12 | g(x) 13 | } 14 | fn g(x:&i8) -> &i8 { 15 | x 16 | } 17 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/arith.smir.cli-info.expected: -------------------------------------------------------------------------------- 1 | 2 | Types requested: (1, 5, 6) 3 | Type 1: TupleT(components=[], layout=LayoutShape(fields=ArbitraryFields(offsets=[]), variants=Single(index=0), abi=ValueAbi(), abi_align=1, size=MachineSize(num_bits=0))) 4 | Type 5: RefT(pointee_type=37) 5 | Type 6: IntT(info=) -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/statementassign1/reference.kmir: -------------------------------------------------------------------------------- 1 | statement 2 | ( 3 | statementKindAssign 4 | ( 5 | place(local(3), .ProjectionElems), 6 | rvalueCast 7 | ( 8 | castKindIntToInt, 9 | operandMove(place(local(4), .ProjectionElems)), 10 | ty(2) 11 | ) 12 | ), 13 | span(6) 14 | ) 15 | -------------------------------------------------------------------------------- /nix/kmir-source/default.nix: -------------------------------------------------------------------------------- 1 | { lib, nix-gitignore }: 2 | 3 | lib.cleanSource ( 4 | nix-gitignore.gitignoreSourcePure [ 5 | ../../.gitignore 6 | ".github/" 7 | "result*" 8 | # "/deps/" 9 | # do not include submodule directories that might be initilized empty or non-existent 10 | "/deps/stable-mir-json" 11 | ] ../../. 12 | ) 13 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/references/refAsArg2.rs: -------------------------------------------------------------------------------- 1 | // references across several function calls 2 | fn main() { 3 | let x = 42i8; 4 | 5 | let z = f(&x); 6 | 7 | assert!(z == x); 8 | } 9 | 10 | // returning references (back, not from locals) 11 | fn f(x:&i8) -> i8 { 12 | g(x) 13 | } 14 | fn g(x:&i8) -> i8 { 15 | *x 16 | } 17 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/and_then_closure.rs: -------------------------------------------------------------------------------- 1 | use std::result::Result; 2 | 3 | fn wrap(x: &u32) -> Result<&u32, u8> { Ok(x) } 4 | 5 | fn main() { 6 | let single: u32 = 32; 7 | 8 | let wrapped: Result = wrap(&single).and_then(|x: &u32| if *x <= 42 {Ok(42)} else {Err(43)}); 9 | 10 | assert_eq!(wrapped, Ok(42)); 11 | } 12 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/two-crate-bin/main-crate/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "crate1" 7 | version = "0.1.0" 8 | 9 | [[package]] 10 | name = "crate2" 11 | version = "0.1.0" 12 | dependencies = [ 13 | "crate1", 14 | ] 15 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/two-crate-dylib/main-crate/src/lib.rs: -------------------------------------------------------------------------------- 1 | use crate1; 2 | use crate1::MyStruct; 3 | 4 | pub fn test_crate1_with(i: isize) -> MyStruct { 5 | MyStruct::new(i, Some(crate1::MyEnum::Bar(i))) 6 | } 7 | 8 | fn use_unwrap_enum(e: Option) -> crate1::MyEnum { 9 | e.unwrap_or(crate1::MyEnum::Bar(0)) 10 | } 11 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/two-crate-dylib/main-crate/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "crate1" 7 | version = "0.1.0" 8 | 9 | [[package]] 10 | name = "crate2" 11 | version = "0.1.0" 12 | dependencies = [ 13 | "crate1", 14 | ] 15 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/single-bin/main-crate/src/main.rs: -------------------------------------------------------------------------------- 1 | pub fn add(left: u64, right: u64) -> u64 { 2 | left + right 3 | } 4 | 5 | pub mod a_module { 6 | use super::add; 7 | 8 | pub fn twice(x: u64) -> u64{ 9 | add(x, x) 10 | } 11 | } 12 | 13 | pub fn main() { 14 | let x = 42; 15 | assert_eq!(a_module::twice(x), 2 * x); 16 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/references/escapingScope.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let x = 42i8; 3 | 4 | unsafe { 5 | let z = f(&x); 6 | assert!(*z == x); 7 | } 8 | } 9 | 10 | unsafe fn f(_:&i8) -> &i8{ 11 | let x = 42; 12 | unsafe { 13 | let y = &x; 14 | // does not compile! (good) 15 | return y; 16 | } 17 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/statementassign2/reference.kmir: -------------------------------------------------------------------------------- 1 | statement 2 | ( 3 | statementKindAssign 4 | ( 5 | place(local(6), .ProjectionElems), 6 | rvalueAggregate 7 | ( 8 | aggregateKindTuple, 9 | operandCopy(place(local(3), .ProjectionElems)) operandCopy(place(local(5), .ProjectionElems)) 10 | ) 11 | ), 12 | span(9) 13 | ) 14 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/transmute-u8-to-enum-fail.rs: -------------------------------------------------------------------------------- 1 | #[repr(u8)] 2 | #[derive(Clone, Copy, Debug, PartialEq)] 3 | pub enum AccountState { 4 | Uninitialized, 5 | Initialized, 6 | Frozen, 7 | } 8 | 9 | fn main() { 10 | unsafe { 11 | std::hint::black_box( 12 | core::mem::transmute::(4) 13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/single-bin/single_exe::main.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ 5 | │ (228 steps) 6 | ├─ 3 (terminal) 7 | │ #EndProgram ~> .K 8 | │ 9 | ┊ constraint: true 10 | ┊ subst: ... 11 | └─ 2 (leaf, target, terminal) 12 | #EndProgram ~> .K 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/two-crate-bin/crate2::main.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ 5 | │ (736 steps) 6 | ├─ 3 (terminal) 7 | │ #EndProgram ~> .K 8 | │ 9 | ┊ constraint: true 10 | ┊ subst: ... 11 | └─ 2 (leaf, target, terminal) 12 | #EndProgram ~> .K 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/two-crate-dylib/crate2::test_crate1_with.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ 5 | │ (216 steps) 6 | ├─ 3 (terminal) 7 | │ #EndProgram ~> .K 8 | │ 9 | ┊ constraint: true 10 | ┊ subst: ... 11 | └─ 2 (leaf, target, terminal) 12 | #EndProgram ~> .K 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/str.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [ 3 | 72, 4 | 101, 5 | 108, 6 | 108, 7 | 111, 8 | 44, 9 | 32, 10 | 87, 11 | 111, 12 | 114, 13 | 108, 14 | 100, 15 | 33, 16 | 32, 17 | 240, 18 | 159, 19 | 140, 20 | 143 21 | ], 22 | "types": [], 23 | "typeInfo": { 24 | "PrimitiveType": "Str" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-smir-random/simple-types/test.rs: -------------------------------------------------------------------------------- 1 | pub fn test(b: bool, x: u8, y: i32) -> () { 2 | let _x = i32::from(x); 3 | assert!(_x >= 0); 4 | if y >= _x { 5 | assert!(y - _x >= 0); 6 | } else if y >= 0 { 7 | assert!(_x - y >= 0); 8 | } else if b { 9 | assert!(y < 0); 10 | } else { 11 | assert_eq!(b, y >= 0); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/structs-tuples/structs-tuples.rs: -------------------------------------------------------------------------------- 1 | struct S { 2 | field0: i32, 3 | field1: bool, 4 | field2: f64 5 | } 6 | 7 | fn main() { 8 | let s = S { field0: 10, field1: false, field2: 10.0 }; 9 | let t = (11, true, s.field2); 10 | 11 | foo(s.field0, s.field1, s.field2); 12 | foo(t.0, t.1, t.2); 13 | } 14 | 15 | fn foo(_i:i32, _b:bool, _f:f64) { 16 | 17 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/mutual_recursion.rs: -------------------------------------------------------------------------------- 1 | fn is_even(n:u32) -> bool { 2 | if n == 0 { 3 | true 4 | } else { 5 | is_odd(n - 1) 6 | } 7 | } 8 | 9 | fn is_odd(n:u32) -> bool { 10 | if n == 0 { 11 | false 12 | } else { 13 | is_even(n - 1) 14 | } 15 | } 16 | 17 | fn main() { 18 | let ans = is_even(10); 19 | 20 | assert!(ans == true); 21 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/unions-fail.rs: -------------------------------------------------------------------------------- 1 | union Union { 2 | signed: i8, 3 | unsigned: u8, 4 | } 5 | 6 | fn main() { 7 | let s = Union { signed: -1 }; 8 | let u = Union { unsigned: 255 }; 9 | unsafe { 10 | assert!(s.signed == -1); 11 | assert!(u.unsigned == 255); 12 | 13 | assert!(s.unsigned == 255); 14 | assert!(u.signed == -1); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/i128.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [ 3 | 241, 4 | 255, 5 | 255, 6 | 255, 7 | 255, 8 | 255, 9 | 255, 10 | 255, 11 | 255, 12 | 255, 13 | 255, 14 | 255, 15 | 255, 16 | 255, 17 | 255, 18 | 255 19 | ], 20 | "types": [], 21 | "typeInfo": { 22 | "PrimitiveType": { 23 | "Int": "I128" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/u128.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [ 3 | 241, 4 | 255, 5 | 255, 6 | 255, 7 | 255, 8 | 255, 9 | 255, 10 | 255, 11 | 255, 12 | 255, 13 | 255, 14 | 255, 15 | 255, 16 | 255, 17 | 255, 18 | 255 19 | ], 20 | "types": [], 21 | "typeInfo": { 22 | "PrimitiveType": { 23 | "Uint": "U128" 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/pointers/pointer-cast-zst.rs: -------------------------------------------------------------------------------- 1 | struct Wrapper(u32); 2 | 3 | fn roundtrip(ptr: *const Wrapper) -> u32 { 4 | unsafe { 5 | let erased = ptr as *const (); 6 | let restored = erased as *const Wrapper; 7 | (*restored).0 8 | } 9 | } 10 | 11 | fn main() { 12 | let value = Wrapper(0xCAFE_BABE); 13 | assert!(roundtrip(&value) == 0xCAFE_BABE); 14 | } 15 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/niche-enum.main.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ span: 0 5 | │ 6 | │ (740 steps) 7 | ├─ 3 (terminal) 8 | │ #EndProgram ~> .K 9 | │ function: main 10 | │ 11 | ┊ constraint: true 12 | ┊ subst: ... 13 | └─ 2 (leaf, target, terminal) 14 | #EndProgram ~> .K 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/array-u8-implicit-len.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [ 3 | 0, 4 | 1, 5 | 2, 6 | 3 7 | ], 8 | "types": [ 9 | [ 10 | 0, 11 | { 12 | "PrimitiveType": { 13 | "Uint": "U8" 14 | } 15 | } 16 | ] 17 | ], 18 | "typeInfo": { 19 | "ArrayType": { 20 | "elem_type": 0, 21 | "size": null 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/allocs/enum-two-refs-fail.rs: -------------------------------------------------------------------------------- 1 | #[derive(PartialEq, Debug)] 2 | enum Thing<'a> { 3 | Thing( &'a i16, &'a u16) 4 | } 5 | 6 | #[derive(PartialEq, Debug)] 7 | struct Another<'a>(&'a i32, &'a u32); 8 | 9 | fn main() { 10 | assert_eq!(Thing::Thing(&1, &2), Thing::Thing(&1, &2)); 11 | assert_eq!(Another(&1, &2), Another(&1, &2)); 12 | println!("All assertions passed"); 13 | } 14 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/assert-inhabited-fail.main.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ span: 0 5 | │ 6 | │ (10 steps) 7 | └─ 3 (stuck, leaf) 8 | #ProgramError ( AssertInhabitedFailure ) ~> .K 9 | function: main 10 | 11 | 12 | ┌─ 2 (root, leaf, target, terminal) 13 | │ #EndProgram ~> .K 14 | 15 | 16 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/assert_eq_exp.main.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ span: 0 5 | │ 6 | │ (148 steps) 7 | ├─ 3 (terminal) 8 | │ #EndProgram ~> .K 9 | │ function: main 10 | │ 11 | ┊ constraint: true 12 | ┊ subst: ... 13 | └─ 2 (leaf, target, terminal) 14 | #EndProgram ~> .K 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/transmute-maybe-uninit-fail.rs: -------------------------------------------------------------------------------- 1 | #![feature(core_intrinsics)] 2 | use std::mem::MaybeUninit; 3 | 4 | fn main() { 5 | unsafe { 6 | let maybe_unsigned = std::intrinsics::transmute::>(9999); 7 | // Note different types ^^^^ ^^^^ 8 | assert!(maybe_unsigned.assume_init() == 9999); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/recursion/mutual_recursion.rs: -------------------------------------------------------------------------------- 1 | fn is_even(n:u32) -> bool { 2 | if n == 0 { 3 | true 4 | } else { 5 | is_odd(n - 1) 6 | } 7 | } 8 | 9 | fn is_odd(n:u32) -> bool { 10 | if n == 0 { 11 | false 12 | } else { 13 | is_even(n - 1) 14 | } 15 | } 16 | 17 | fn main() { 18 | let ans = is_even(10); 19 | 20 | assert!(ans == true); 21 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/references/array_elem_ref.rs: -------------------------------------------------------------------------------- 1 | // reference into array 2 | 3 | fn f(x: &u32) { 4 | assert!(*x == 0); 5 | } 6 | 7 | fn g(x: *const u32) { 8 | // assert!(unsafe{*x} == 0); // deref alignment check currently failing 9 | } 10 | 11 | fn main() { 12 | let a = [0_u32; 4]; 13 | let i = 3; 14 | let x = &a[i]; 15 | let xx = x as *const u32; 16 | 17 | f(x); 18 | g(xx); 19 | } 20 | 21 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/bitwise-not-shift.main.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ span: 0 5 | │ 6 | │ (837 steps) 7 | ├─ 3 (terminal) 8 | │ #EndProgram ~> .K 9 | │ function: main 10 | │ 11 | ┊ constraint: true 12 | ┊ subst: ... 13 | └─ 2 (leaf, target, terminal) 14 | #EndProgram ~> .K 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/structs-tuples/struct_field_update.rs: -------------------------------------------------------------------------------- 1 | struct MyStruct { 2 | field0: i32, 3 | field1: bool, 4 | field2: f64, 5 | field3: (i32, i32) 6 | } 7 | 8 | fn main() { 9 | 10 | let mut s = MyStruct { field0: 10, field1: false, field2: 10.0, field3: (1, 2) }; 11 | 12 | s.field1 = true; 13 | s.field3.1 = s.field0; 14 | s.field0 = s.field3.0; 15 | s.field2 = 42.9; 16 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/offset-u8-fail.main.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ span: 0 5 | │ 6 | │ (34 steps) 7 | └─ 3 (stuck, leaf) 8 | #traverseProjection ( toLocal ( 1 ) , thunk ( #decodeConstant ( constantKindAllo 9 | span: 48 10 | 11 | 12 | ┌─ 2 (root, leaf, target, terminal) 13 | │ #EndProgram ~> .K 14 | 15 | 16 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/transmute-u8-to-enum-fail.main.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ span: 0 5 | │ 6 | │ (15 steps) 7 | └─ 3 (stuck, leaf) 8 | #ProgramError ( #UBErrorInvalidDiscriminantsInEnumCast ) ~> .K 9 | function: main 10 | 11 | 12 | ┌─ 2 (root, leaf, target, terminal) 13 | │ #EndProgram ~> .K 14 | 15 | 16 | -------------------------------------------------------------------------------- /package/test-package.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -xueo pipefail 4 | 5 | which kmir 6 | kmir --help 7 | 8 | # there is no `kmir version` implemented yet 9 | # kmir version 10 | 11 | # ( \ 12 | # cd kmir/src/tests/integration/data/crate-tests/single-bin/main-crate \ 13 | # && kmir run \ 14 | # ) 15 | 16 | # kmir prove-rs kmir/src/tests/integration/data/prove-rs/if.rs 17 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/assert-true.main.cli-custom-printer.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ span: src/rust/library/std/src/rt.rs:194 5 | │ 6 | │ (7 steps) 7 | ├─ 3 (terminal) 8 | │ #EndProgram ~> .K 9 | │ function: main 10 | │ 11 | ┊ constraint: true 12 | ┊ subst: ... 13 | └─ 2 (leaf, target, terminal) 14 | #EndProgram ~> .K -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/assert-true.main.cli-default-printer.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ span: src/rust/library/std/src/rt.rs:194 5 | │ 6 | │ (7 steps) 7 | ├─ 3 (terminal) 8 | │ #EndProgram ~> .K 9 | │ function: main 10 | │ 11 | ┊ constraint: true 12 | ┊ subst: ... 13 | └─ 2 (leaf, target, terminal) 14 | #EndProgram ~> .K -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/interior-mut-fail.main.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ span: 0 5 | │ 6 | │ (877 steps) 7 | └─ 3 (stuck, leaf) 8 | #setUpCalleeData ( monoItemFn ( ... name: symbol ( "** UNKNOWN FUNCTION **" ) , 9 | span: 32 10 | 11 | 12 | ┌─ 2 (root, leaf, target, terminal) 13 | │ #EndProgram ~> .K 14 | 15 | 16 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/iter_next_2-fail.main.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ span: 0 5 | │ 6 | │ (2000 steps) 7 | └─ 3 (stuck, leaf) 8 | #traverseProjection ( toStack ( 1 , local ( 1 ) ) , Range ( .List ) , .Projectio 9 | span: 146 10 | 11 | 12 | ┌─ 2 (root, leaf, target, terminal) 13 | │ #EndProgram ~> .K 14 | 15 | 16 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/symbolic-args-fail.main.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ span: 0 5 | │ 6 | │ (566 steps) 7 | └─ 3 (stuck, leaf) 8 | #setUpCalleeData ( monoItemFn ( ... name: symbol ( "** UNKNOWN FUNCTION **" ) , 9 | span: 32 10 | 11 | 12 | ┌─ 2 (root, leaf, target, terminal) 13 | │ #EndProgram ~> .K 14 | 15 | 16 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/iterator-simple-fail.main.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ span: 0 5 | │ 6 | │ (491 steps) 7 | └─ 3 (stuck, leaf) 8 | #traverseProjection ( toLocal ( 24 ) , thunk ( #cast ( PtrLocal ( 1 , place ( .. 9 | span: 219 10 | 11 | 12 | ┌─ 2 (root, leaf, target, terminal) 13 | │ #EndProgram ~> .K 14 | 15 | 16 | -------------------------------------------------------------------------------- /kmir/src/kmir/build.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from typing import TYPE_CHECKING 4 | 5 | from pyk.kdist import kdist 6 | 7 | if TYPE_CHECKING: 8 | from typing import Final 9 | 10 | LLVM_DEF_DIR: Final = kdist.which('mir-semantics.llvm') 11 | LLVM_LIB_DIR: Final = kdist.which('mir-semantics.llvm-library') 12 | HASKELL_DEF_DIR: Final = kdist.which('mir-semantics.haskell') 13 | KMIR_SOURCE_DIR: Final = kdist.which('mir-semantics.source') 14 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/arithmetic/arithmetic.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | 3 | let a = 127u8 + 128u8; // 255 4 | let b = a - 255; // 0 5 | 6 | let c = 0 - 100i8 - 28i8; // -128 7 | let d = c as u8 + 127 - a; // 0, underflow when reordered 8 | 9 | let e = a as i16 * c as i16; // -32640 10 | let f = e + c as i16; // -32768 11 | 12 | // println!("{a}\n{b}\n{c}\n{d}\n{e}\n{f}\n"); 13 | } 14 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/assume-cheatcode-conflict-fail.rs: -------------------------------------------------------------------------------- 1 | #![feature(core_intrinsics)] 2 | 3 | // Negative test: assume(x < 10) then assert!(x > 10). 4 | // With correct cheatcode semantics, this path is infeasible and the proof should fail. 5 | 6 | use std::intrinsics::assume; 7 | 8 | #[no_mangle] 9 | pub fn check_assume_conflict(x: u64) { 10 | unsafe { assume(x < 10); } 11 | assert!(x > 10); 12 | } 13 | 14 | fn main() {} 15 | 16 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/unions-fail.main.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ span: 0 5 | │ 6 | │ (76 steps) 7 | └─ 3 (stuck, leaf) 8 | #traverseProjection ( toLocal ( 1 ) , Union ( fieldIdx ( 0 ) , Integer ( -1 , 8 9 | function: main 10 | span: 59 11 | 12 | 13 | ┌─ 2 (root, leaf, target, terminal) 14 | │ #EndProgram ~> .K 15 | 16 | 17 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/generics/generic.rs: -------------------------------------------------------------------------------- 1 | fn index_slice(slice:&[T], index: usize) -> &T { 2 | &(slice[index]) 3 | } 4 | 5 | fn main() { 6 | let numbers = [1, 2, 3, 4, 5]; 7 | let letters = ['a', 'b', 'c', 'd', 'e']; 8 | 9 | let middle_number:&i32 = index_slice(&numbers[..], 2); 10 | let middle_letter:&char = index_slice(&letters[..], 2); 11 | 12 | assert!(*middle_number == 3); 13 | assert!(*middle_letter == 'c'); 14 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/assume-cheatcode-conflict-fail.check_assume_conflict.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ span: 0 5 | │ 6 | │ (61 steps) 7 | └─ 3 (stuck, leaf) 8 | #setUpCalleeData ( monoItemFn ( ... name: symbol ( "** UNKNOWN FUNCTION **" ) , 9 | span: 32 10 | 11 | 12 | ┌─ 2 (root, leaf, target, terminal) 13 | │ #EndProgram ~> .K 14 | 15 | 16 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/statements/reference.kmir: -------------------------------------------------------------------------------- 1 | statement(statementKindStorageLive(local(2)), span(2)) 2 | statement 3 | ( 4 | statementKindAssign 5 | ( 6 | place(local(3), .ProjectionElems), 7 | rvalueCast 8 | ( 9 | castKindIntToInt, 10 | operandMove(place(local(4), .ProjectionElems)), 11 | ty(2) 12 | ) 13 | ), 14 | span(6) 15 | ) 16 | statement(statementKindStorageDead(local(3)), span(2)) 17 | .Statements 18 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/array_match.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let a = [1,2,3u8]; 3 | f(&a); 4 | let a = [4,5,6,7,8,9u8]; 5 | f(&a); 6 | } 7 | 8 | fn f(xs: &[u8]) { 9 | // let [a, b, c, rest @ ..] = xs 10 | // else { panic!("Need at least three elements"); }; 11 | // println!("Array {xs:?} is ( {a}, {b}, {c}, {rest:?} )"); 12 | 13 | if let [a, b, c, rest @ ..] = xs { 14 | assert!(a + b - c == rest.len() as u8); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/ub/mut_const.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let mut prior = 1; 3 | let x = 10; 4 | 5 | // println!("Before: {}", x); 6 | let _y = &x; // <-- need something else on the stack for the offset to work 7 | let prior_mut = &mut prior as *mut i32; 8 | 9 | unsafe { 10 | let prior_alias = prior_mut.add(1); 11 | *prior_alias = 20; 12 | } 13 | 14 | // println!("After: {}", x); 15 | assert!(x == 20); 16 | } 17 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/transmute-maybe-uninit-fail.main.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ span: 0 5 | │ 6 | │ (16 steps) 7 | └─ 3 (stuck, leaf) 8 | #ProgramError ( #UBInvalidTransmuteMaybeUninit ) 9 | ~> #freezer#setLocalValue(_,_)_ 10 | function: main 11 | span: 60 12 | 13 | 14 | ┌─ 2 (root, leaf, target, terminal) 15 | │ #EndProgram ~> .K 16 | 17 | 18 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/transmute-u8-to-enum-changed-discriminant-signed-fail.main.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ span: 0 5 | │ 6 | │ (102 steps) 7 | └─ 3 (stuck, leaf) 8 | #traverseProjection ( toLocal ( 2 ) , thunk ( #decodeConstant ( constantKindAllo 9 | span: 153 10 | 11 | 12 | ┌─ 2 (root, leaf, target, terminal) 13 | │ #EndProgram ~> .K 14 | 15 | 16 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/traits/defined-trait.rs: -------------------------------------------------------------------------------- 1 | trait Summary { 2 | fn summarise(&self) -> String; 3 | } 4 | 5 | #[allow(dead_code)] 6 | struct Container { 7 | number: u32, 8 | } 9 | 10 | impl Summary for Container { 11 | fn summarise(&self) -> String { 12 | "The number is zero or more!".to_string() 13 | } 14 | } 15 | 16 | fn main() { 17 | let con = Container { number:42 }; 18 | assert!(con.summarise() == "The number is zero or more!"); 19 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/arith.rs: -------------------------------------------------------------------------------- 1 | fn add(x: i32, y: i32) -> i32 { 2 | x + y 3 | } 4 | 5 | fn sub(x: i32, y: i32) -> i32 { 6 | x - y 7 | } 8 | 9 | fn mul(x: i32, y: i32) -> i32 { 10 | x * y 11 | } 12 | 13 | fn div(x: i32, y: i32) -> i32 { 14 | x / y 15 | } 16 | 17 | fn main() { 18 | assert!(add(3, 4) == 7); 19 | 20 | // assert!(sub(3, 4) == -1); // FAILING 21 | 22 | assert!(mul(3, 4) == 12); 23 | 24 | // assert!(div(12, 4) == 3); // FAILING 25 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/niche-enum/niche-enum.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug, PartialEq)] 2 | enum SmallInt { 3 | One = 1, 4 | Two = 2, 5 | } 6 | 7 | fn foo(x: u8) -> Option { 8 | match x { 9 | 1 => Some(SmallInt::One), 10 | 2 => Some(SmallInt::Two), 11 | _ => None, 12 | } 13 | } 14 | 15 | fn main() { 16 | assert_eq!(foo(0), None); 17 | assert_eq!(foo(1), Some(SmallInt::One)); 18 | assert_eq!(foo(2), Some(SmallInt::Two)); 19 | } 20 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/assume-cheatcode.rs: -------------------------------------------------------------------------------- 1 | #![feature(core_intrinsics)] 2 | 3 | // Demonstrate and test the assume cheatcode semantics. 4 | // The K semantics should add the condition `x < 100` as a path constraint, 5 | // allowing the following assertion to be proven symbolically for all x. 6 | 7 | use std::intrinsics::assume; 8 | 9 | #[no_mangle] 10 | pub fn check_assume(x: u64) { 11 | unsafe { assume(x < 100); } 12 | assert!(x < 100); 13 | } 14 | 15 | fn main() {} 16 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/arithmetic/arithmetic-unchecked-runs.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | 3 | unsafe { 4 | let a = 127u8 + 127u8; // 254 5 | let b = a.unchecked_add(1); // 255 6 | 7 | let c = 0 - 100i8; // -100 8 | let d = c.unchecked_sub(28); // -128 9 | 10 | let e = b as i16 * d as i16; // -32640 11 | let f = e + d as i16; // -32768 12 | 13 | // println!("{a}\n{b}\n{c}\n{d}\n{e}\n{f}\n"); 14 | 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/iter_next_1.rs: -------------------------------------------------------------------------------- 1 | struct Thing { payload: u16 } 2 | 3 | fn main() { 4 | let a = [Thing{payload: 1}, Thing{payload: 2}, Thing{payload: 3}]; 5 | 6 | let mut i = a.iter(); 7 | let elem = i.next(); 8 | assert!(elem.unwrap().payload == 1); 9 | let elem = i.next(); 10 | assert!(elem.unwrap().payload == 2); 11 | let elem = i.next(); 12 | assert!(elem.unwrap().payload == 3); 13 | // let elem = i.next(); 14 | // assert!(elem.is_none()); 15 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/iter_next_2-fail.rs: -------------------------------------------------------------------------------- 1 | struct Thing { payload: u16 } 2 | 3 | fn main() { 4 | let a = [Thing{payload: 1}, Thing{payload: 2}, Thing{payload: 3}]; 5 | 6 | let mut i = a.iter(); 7 | let elem = i.next(); 8 | assert!(elem.unwrap().payload == 1); 9 | let elem = i.next(); 10 | assert!(elem.unwrap().payload == 2); 11 | let elem = i.next(); 12 | assert!(elem.unwrap().payload == 3); 13 | let elem = i.next(); 14 | assert!(elem.is_none()); 15 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/traits/derive-copy-struct.rs: -------------------------------------------------------------------------------- 1 | #[derive(Copy, Clone)] 2 | struct Container { 3 | number:u32, 4 | } 5 | 6 | fn take_first_container(containers: &[Container]) -> Container { 7 | containers[0] 8 | } 9 | 10 | fn main() { 11 | let con1 = Container { number: 42 }; 12 | let con2 = Container { number: 24 }; 13 | 14 | let cons = [con1, con2]; 15 | 16 | let first:Container = take_first_container(&cons[..]); 17 | 18 | assert!(first.number == 42); 19 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-rs/functions/sum-to-n.rs: -------------------------------------------------------------------------------- 1 | fn sum_to_n(n:usize) -> usize { 2 | let mut sum = 0; 3 | let mut counter = n; 4 | 5 | while counter > 0 { 6 | sum += counter; 7 | counter = counter - 1; 8 | } 9 | return sum; 10 | } 11 | 12 | fn test_sum_to_n() -> () { 13 | let n = 10; 14 | let golden = 55; 15 | let sucess = sum_to_n(n) == golden; 16 | assert!(sucess); 17 | } 18 | 19 | 20 | fn main() { 21 | test_sum_to_n(); 22 | return (); 23 | } 24 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/sum-to-n-functions.rs: -------------------------------------------------------------------------------- 1 | fn sum_to_n(n: usize) -> usize { 2 | let mut sum = 0; 3 | let mut counter = n; 4 | 5 | while counter > 0 { 6 | sum += counter; 7 | counter = counter - 1; 8 | } 9 | return sum; 10 | } 11 | 12 | fn test_sum_to_n() -> () { 13 | let n = 10; 14 | let golden = 55; 15 | let success = sum_to_n(n) == golden; 16 | assert!(success); 17 | } 18 | 19 | fn main() { 20 | test_sum_to_n(); 21 | return (); 22 | } 23 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/struct_with_ref.rs: -------------------------------------------------------------------------------- 1 | struct WithRef<'a> { 2 | a_ref: &'a AThing, 3 | } 4 | 5 | struct AThing { 6 | a_field: i8, 7 | another: i16, 8 | } 9 | 10 | fn main() { 11 | let a_thing = AThing{ a_field: 1, another: 2}; 12 | let a_ref = &a_thing; 13 | let with_ref = WithRef{a_ref}; 14 | 15 | assert!(with_ref.a_ref.a_field == 1 && a_thing.another == 2); // works 16 | f(with_ref); 17 | } 18 | 19 | fn f(w: WithRef) { 20 | assert!(2 * w.a_ref.a_field as i16 == w.a_ref.another); 21 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/allocs/array_const_compare.rs: -------------------------------------------------------------------------------- 1 | const I8_ARRAY: [i8; 3] = [1, -2, 3]; 2 | const U16_ARRAY: [u16; 3] = [100, 200, 300]; 3 | 4 | fn main() { 5 | // the array will be allocated twice, even if the same constant is used 6 | assert_eq!(I8_ARRAY, I8_ARRAY); 7 | // this uses an inlined array constant instead of the global one 8 | assert!(compare_to_stored(U16_ARRAY)); 9 | // println!("All assertions passed!"); 10 | } 11 | 12 | fn compare_to_stored(array: [u16;3]) -> bool { 13 | U16_ARRAY == array 14 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/transmute-u8-to-enum.rs: -------------------------------------------------------------------------------- 1 | #[repr(u8)] 2 | #[derive(Clone, Copy, Debug, PartialEq)] 3 | pub enum AccountState { 4 | Uninitialized, 5 | Initialized, 6 | Frozen, 7 | } 8 | 9 | fn main() { 10 | unsafe { 11 | assert_eq!(core::mem::transmute::(0), AccountState::Uninitialized); 12 | assert_eq!(core::mem::transmute::(1), AccountState::Initialized); 13 | assert_eq!(core::mem::transmute::(2), AccountState::Frozen); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/single-dylib/main-crate/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::process::exit; 2 | 3 | pub fn add(left: u64, right: u64) -> u64 { 4 | left + right 5 | } 6 | 7 | fn assume(cond: bool) { 8 | if !cond { exit(0); } 9 | } 10 | 11 | pub mod testing { 12 | use super::*; 13 | 14 | pub fn test_add_in_range(left: u64, right: u64) { 15 | let sum = left as u128 + right as u128; 16 | assume(sum <= u64::MAX as u128); 17 | let result = add(left, right); 18 | 19 | assert_eq!(result as u128, sum) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/single-lib/main-crate/src/lib.rs: -------------------------------------------------------------------------------- 1 | use std::process::exit; 2 | 3 | pub fn add(left: u64, right: u64) -> u64 { 4 | left + right 5 | } 6 | 7 | fn assume(cond: bool) { 8 | if !cond { exit(0); } 9 | } 10 | 11 | pub mod testing { 12 | use super::*; 13 | 14 | pub fn test_add_in_range(left: u64, right: u64) { 15 | let sum = left as u128 + right as u128; 16 | assume(sum <= u64::MAX as u128); 17 | let result = add(left, right); 18 | 19 | assert_eq!(result as u128, sum) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/intrinsic/blackbox.rs: -------------------------------------------------------------------------------- 1 | use std::hint::black_box; 2 | 3 | fn add_one(x: u32) -> u32 { 4 | x + 1 5 | } 6 | 7 | fn main() { 8 | let input = 10; 9 | 10 | // We are calling `add_one(input)`, which produces the value 11. 11 | // Then, we pass this RESULT (11) into black_box. 12 | let result = black_box(add_one(input)); 13 | 14 | // This forces the compiler to actually execute the `add_one` function, 15 | // because it cannot know what `black_box` will do with the result. 16 | assert_eq!(result, 11); 17 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/single-dylib/main-crate/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "small-test-dylib" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | name = "small_test_dylib" 8 | path = "src/lib.rs" # The source file of the target. 9 | test = false # Is tested by default. 10 | doctest = false # Documentation examples are tested by default. 11 | bench = false # Is benchmarked by default. 12 | doc = false # Is documented by default. 13 | crate-type = ["dylib"] # The crate types to generate. 14 | 15 | [dependencies] 16 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/bitwise.rs: -------------------------------------------------------------------------------- 1 | fn and(x: i32, y: i32) -> i32 { 2 | x & y 3 | } 4 | 5 | fn or(x: i32, y: i32) -> i32 { 6 | x | y 7 | } 8 | 9 | fn xor(x: i32, y: i32) -> i32 { 10 | x ^ y 11 | } 12 | 13 | fn shift_left(x: i32, y: i32) -> i32 { 14 | x << y 15 | } 16 | 17 | fn shift_right(x: i32, y: i32) -> i32 { 18 | x >> y 19 | } 20 | 21 | fn main() { 22 | assert!(and(3, 4) == 0); 23 | 24 | assert!(or(3, 4) == 7); 25 | 26 | assert!(xor(3, 7) == 4); 27 | 28 | assert!(shift_left(1, 4) == 16); 29 | 30 | assert!(shift_right(32, 4) == 2); 31 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/shift_negative_min.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | assert!(1_i8 << 7_u8 == -128); 3 | assert!(1_i16 << 15_u8 == -32768); 4 | assert!(1_i32 << 31_u8 == -2147483648); 5 | assert!(1_i64 << 63_u8 == -9223372036854775808); 6 | assert!(1_i128 << 127_u8 == -170141183460469231731687303715884105728); 7 | 8 | assert!(1_i8 << 7_u8 == i8::MIN); 9 | assert!(1_i16 << 15_u8 == i16::MIN); 10 | assert!(1_i32 << 31_u8 == i32::MIN); 11 | assert!(1_i64 << 63_u8 == i64::MIN); 12 | assert!(1_i128 << 127_u8 == i128::MIN); 13 | } 14 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/arithmetic/unary.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | 3 | // `not` 4 | let a = 127u8 + 128u8; // 255 5 | let b = !a; // 0 6 | let c = !(-123i8); // 122 7 | let d = !false; // true 8 | 9 | // `neg` 10 | let e = - c; // -122 11 | 12 | // #[allow(arithmetic_overflow)] 13 | // let f = - ((- 64i8) - 64i8); // -128! (overflow error unless optimising) 14 | // TODO currently fails due to https://github.com/runtimeverification/haskell-backend/pull/4095 15 | 16 | // println!("{a}\n{b}\n{c}\n{d}\n{e}\n{f}\n"); 17 | } 18 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/checked_arithmetic.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | checked_add_i32(1,2); 3 | } 4 | 5 | /// If the precondition is not met, the program is not executed (exits cleanly, ex falso quodlibet) 6 | macro_rules! precondition { 7 | ($pre:expr, $block:expr) => { 8 | if $pre { $block } 9 | }; 10 | } 11 | 12 | fn checked_add_i32(a: i32, b: i32) { 13 | 14 | precondition!( 15 | a.checked_add(b).is_some(), 16 | unsafe { 17 | let result = a.unchecked_add(b); 18 | assert!(result as i64 == a as i64 + b as i64) 19 | } 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/allocs/array_nest_compare.rs: -------------------------------------------------------------------------------- 1 | const U16_ARRAY: [u16; 3] = [100, 200, 300]; 2 | const NESTED: [[u16;3];2] = [U16_ARRAY, U16_ARRAY]; 3 | 4 | fn main() { 5 | // the array will be allocated twice, even if the same constant is used 6 | assert_eq!(NESTED, [[100,200,300],[100,200,300]]); 7 | // this uses an inlined array constant instead of the global one 8 | assert!(compare_to_stored(U16_ARRAY)); 9 | assert!(compare_to_stored(NESTED[0])); 10 | // println!("All assertions passed!"); 11 | } 12 | 13 | fn compare_to_stored(array: [u16;3]) -> bool { 14 | NESTED[1] == array 15 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/tuple-empty.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [], 3 | "types": [], 4 | "typeInfo": { 5 | "TupleType": { 6 | "types": [], 7 | "layout": { 8 | "fields": { 9 | "Arbitrary": { 10 | "offsets": [] 11 | } 12 | }, 13 | "variants": { 14 | "Single": { 15 | "index": 0 16 | } 17 | }, 18 | "abi": { 19 | "Aggregate": { 20 | "sized": true 21 | } 22 | }, 23 | "abi_align": 1, 24 | "size": { 25 | "num_bits": 0 26 | } 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /nix/kmir-pyk-pyproject/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | callPackage, 4 | nix-gitignore, 5 | 6 | uv2nix, 7 | }: 8 | let 9 | src = callPackage ../kmir-source { }; 10 | 11 | # load a uv workspace from a workspace root 12 | workspace = uv2nix.lib.workspace.loadWorkspace { workspaceRoot = "${src}/kmir"; }; 13 | 14 | # create overlay 15 | lockFileOverlay = workspace.mkPyprojectOverlay { 16 | # prefer "wheel" over "sdist" due to maintance overhead 17 | # there is no bundled set of overlays for "sdist" in uv2nix, in contrast to poetry2nix 18 | sourcePreference = "wheel"; 19 | }; 20 | in 21 | { 22 | inherit lockFileOverlay workspace; 23 | } 24 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/arrays/array_inlined.rs: -------------------------------------------------------------------------------- 1 | const I8_ARRAY: [i8; 3] = [1, -2, 3]; 2 | const I32_ARRAY: [i32; 4] = [10, -20, 30, -40]; 3 | 4 | fn main() { 5 | 6 | // Product of first two elements 7 | let i8_product = I8_ARRAY[0] * I8_ARRAY[1]; 8 | let i32_product = I32_ARRAY[0] * I32_ARRAY[1]; 9 | 10 | // Assertions 11 | 12 | // these constants get allocated, which is not supported yet 13 | // assert_eq!(i8_product, -2); // 1 * (-2) = -2 14 | // assert_eq!(i32_product, -200); // 10 * -20 = -200 15 | 16 | // therefore using a computation instead of constants 17 | assert_eq!(i8_product as i32 * 100, i32_product); 18 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/offset-u8-fail.rs: -------------------------------------------------------------------------------- 1 | // Copyright Kani Contributors 2 | // SPDX-License-Identifier: Apache-2.0 OR MIT 3 | 4 | // https://github.com/model-checking/kani/blob/main/tests/expected/offset-u8-fail/main.rs 5 | 6 | // Checks that the pointer computed with `offset` causes a failure if it's 7 | // dereferenced outside the object bounds 8 | #![feature(core_intrinsics)] 9 | use std::intrinsics::offset; 10 | 11 | fn main() { 12 | test_offset(); 13 | } 14 | 15 | // #[kani::proof] 16 | fn test_offset() { 17 | let s: &str = "123"; 18 | let ptr: *const u8 = s.as_ptr(); 19 | 20 | unsafe { 21 | let x = *offset(ptr, 3isize) as char; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/call-with-args/closure-call.rs: -------------------------------------------------------------------------------- 1 | fn test_t(x: (u32,)) -> u32 { x.0 } // expects a singleton tuple 2 | 3 | fn main() { 4 | let single: u32 = 32; 5 | let tuple: (u32,) = (single,); 6 | 7 | test_t(tuple); // gets passed a singleton tuple 8 | 9 | let identity = |x| x; // expects a single u32 10 | 11 | identity(single); // gets passed a &closure and a singleton tuple! 12 | 13 | let twice = (single, single); 14 | let is_equal = |a, b| { assert!(a == b); }; // expects and accesses its arguments as locals _2 and _3 (u32) 15 | 16 | // is_equal(twice); // error 17 | is_equal(single, single); // gets passed a &closure and a singleton tuple !!! 18 | } 19 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/closure_access_struct.rs: -------------------------------------------------------------------------------- 1 | struct MyStruct { 2 | data: i32 3 | } 4 | 5 | fn main() { 6 | // List of MyStruct instances 7 | let struct_list = [ 8 | MyStruct { data: 10 }, 9 | MyStruct { data: 20 }, 10 | MyStruct { data: 30 }, 11 | MyStruct { data: 40 }, 12 | MyStruct { data: 50 } 13 | ]; 14 | 15 | // Closure function that takes &MyStruct reference 16 | let get_value = |struct_ref: &MyStruct| { 17 | struct_ref.data 18 | }; 19 | 20 | // Use list call style, passing reference 21 | let result = get_value(&struct_list[2]); 22 | 23 | // Verify result 24 | assert_eq!(result, 30); 25 | } -------------------------------------------------------------------------------- /.cruft.json: -------------------------------------------------------------------------------- 1 | { 2 | "template": "https://github.com/runtimeverification/python-project-template", 3 | "commit": "7a095b4dd0a51916da0a728b8fdd9adf7e469a68", 4 | "checkout": null, 5 | "context": { 6 | "cookiecutter": { 7 | "project_name": "MIR Semantics", 8 | "project_slug": "mir-semantics", 9 | "package_name": "mir_semantics", 10 | "version": "0.1.0", 11 | "description": "", 12 | "author_name": "Runtime Verification, Inc.", 13 | "author_email": "contact@runtimeverification.com", 14 | "_template": "https://github.com/runtimeverification/python-project-template", 15 | "_commit": "7a095b4dd0a51916da0a728b8fdd9adf7e469a68" 16 | } 17 | }, 18 | "directory": null 19 | } 20 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/bitwise-not-shift.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // Integers 3 | assert!(3_u128 & 7_u128 == 3_u128); 4 | assert!(3_u128 | 7_u128 == 7_u128); 5 | assert!(3_u128 ^ 7_u128 == 4_u128); 6 | 7 | // Booleans 8 | assert!(false | false == false); 9 | assert!(true | false == true); 10 | assert!(true & true == true); 11 | assert!(true & false == false); 12 | assert!(true ^ true == false); 13 | assert!(true ^ false == true); 14 | 15 | // Borrows 16 | assert!(&3 & &7 == 3); 17 | assert!(&3 | &7 == 7); 18 | assert!(&3 ^ &7 == 4); 19 | assert!(&false & &false == false); 20 | assert!(&true | &true == true); 21 | assert!(&false ^ &false == false); 22 | } 23 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/transmute-maybe-uninit.rs: -------------------------------------------------------------------------------- 1 | #![feature(core_intrinsics)] 2 | use std::mem::MaybeUninit; 3 | 4 | struct Something([u8; 3]); 5 | 6 | fn main() { 7 | unsafe { 8 | let maybe_signed = std::intrinsics::transmute_unchecked::>(42); 9 | assert!(maybe_signed.assume_init() == 42); 10 | 11 | let maybe_unsigned = std::intrinsics::transmute::>(9999); 12 | assert!(maybe_unsigned.assume_init() == 9999); 13 | 14 | let something = Something([1, 2, 3]); 15 | let maybe_something = std::intrinsics::transmute::>(something); 16 | assert!(maybe_something.assume_init().0 == [1, 2, 3]); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/interior-mut2.rs: -------------------------------------------------------------------------------- 1 | use std::cell::Cell; 2 | 3 | struct Counter { 4 | value: Cell, 5 | } 6 | 7 | impl Counter { 8 | fn new(start: i32) -> Self { 9 | Counter { value: Cell::new(start) } 10 | } 11 | 12 | fn increment(&self) { 13 | self.value.set(self.get() + 1); 14 | } 15 | 16 | fn get(&self) -> i32 { 17 | self.value.get() 18 | } 19 | } 20 | 21 | fn main() { 22 | let counter = Counter::new(0); 23 | // println!("Before: {}", counter.get()); 24 | 25 | // We only have &counter, but can still mutate inside 26 | counter.increment(); 27 | counter.increment(); 28 | 29 | assert!(2 == counter.get()); 30 | // println!("After: {}", counter.get()); 31 | } 32 | -------------------------------------------------------------------------------- /nix/test/package.nix: -------------------------------------------------------------------------------- 1 | { 2 | stdenv, 3 | callPackage, 4 | 5 | which, 6 | 7 | kmir, 8 | rev ? null, 9 | }: 10 | 11 | stdenv.mkDerivation { 12 | pname = "kmir-package-test"; 13 | version = if (rev != null) then rev else "dirty"; 14 | 15 | src = callPackage ../kmir-source { }; 16 | 17 | enableParallelBuilding = true; 18 | 19 | nativeBuildInputs = [ 20 | which 21 | kmir.rust 22 | ]; 23 | 24 | # for package/test-package.sh 25 | postPatch = '' 26 | patchShebangs . 27 | ''; 28 | 29 | buildPhase = '' 30 | runHook preBuild 31 | # cat package/test-package.sh 32 | # bash package/test-package.sh 33 | package/test-package.sh 34 | runHook postBuild 35 | ''; 36 | 37 | installPhase = '' 38 | touch $out 39 | ''; 40 | } 41 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/newtype-pubkey/newtype-pubkey.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | 3 | #[derive(Copy, Clone)] 4 | pub struct Pubkey(pub [u8; 32]); 5 | 6 | const KEY: Pubkey = Pubkey([ 7 | 0, 1, 2, 3, 4, 5, 6, 7, 8 | 8, 9, 10, 11, 12, 13, 14, 15, 9 | 16, 17, 18, 19, 20, 21, 22, 23, 10 | 24, 25, 26, 27, 28, 29, 30, 31, 11 | ]); 12 | 13 | #[inline(never)] 14 | fn use_inner(arr: &[u8; 32]) -> usize { 15 | // Touch the array so MIR keeps the projection 16 | if arr[0] == 0 { 32 } else { 0 } 17 | } 18 | 19 | fn main() { 20 | let pk = KEY; // forces constant decoding of StructType(newtype) 21 | let len = use_inner(&pk.0); // field projection .0; needs StructType decode to Aggregate 22 | core::hint::black_box(len); 23 | } 24 | 25 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/interior-mut-fail.rs: -------------------------------------------------------------------------------- 1 | use std::cell::RefCell; 2 | 3 | struct Counter { 4 | value: RefCell, 5 | } 6 | 7 | impl Counter { 8 | fn new(start: i32) -> Self { 9 | Counter { value: RefCell::new(start) } 10 | } 11 | 12 | fn increment(&self) { 13 | *self.value.borrow_mut() += 1; 14 | } 15 | 16 | fn get(&self) -> i32 { 17 | *self.value.borrow() 18 | } 19 | } 20 | 21 | fn main() { 22 | let counter = Counter::new(0); 23 | // println!("Before: {}", counter.get()); 24 | 25 | // We only have &counter, but can still mutate inside 26 | counter.increment(); 27 | counter.increment(); 28 | 29 | assert!(2 == counter.get()); 30 | // println!("After: {}", counter.get()); 31 | } 32 | -------------------------------------------------------------------------------- /nix/kmir-pyk/build-systems-overlay.nix: -------------------------------------------------------------------------------- 1 | final: prev: 2 | let 3 | inherit (final) resolveBuildSystem; 4 | inherit (builtins) mapAttrs; 5 | 6 | # Build system dependencies specified in the shape expected by resolveBuildSystem 7 | # The empty lists below are lists of optional dependencies. 8 | # 9 | # A package `foo` with specification written as: 10 | # `setuptools-scm[toml]` in pyproject.toml would be written as 11 | # `foo.setuptools-scm = [ "toml" ]` in Nix 12 | buildSystemOverrides = { 13 | # add dependencies here, e.g.: 14 | # pyperclip.setuptools = [ ]; 15 | }; 16 | in 17 | mapAttrs ( 18 | name: spec: 19 | prev.${name}.overrideAttrs (old: { 20 | nativeBuildInputs = old.nativeBuildInputs ++ resolveBuildSystem spec; 21 | }) 22 | ) buildSystemOverrides 23 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/array-u8-const-len.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [ 3 | 0, 4 | 1, 5 | 2, 6 | 3 7 | ], 8 | "types": [ 9 | [ 10 | 0, 11 | { 12 | "PrimitiveType": { 13 | "Uint": "U8" 14 | } 15 | } 16 | ] 17 | ], 18 | "typeInfo": { 19 | "ArrayType": { 20 | "elem_type": 0, 21 | "size": { 22 | "id": 100, 23 | "kind": { 24 | "Value": [ 25 | 0, 26 | { 27 | "bytes": [ 28 | 4 29 | ], 30 | "provenance": { 31 | "ptrs": [] 32 | }, 33 | "align": 1, 34 | "mutability": "Not" 35 | } 36 | ] 37 | } 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /nix/README.md: -------------------------------------------------------------------------------- 1 | ## Notes 2 | #### git submodules 3 | If you use git submodules that are not required for building the project with `nix`, then you should add these directories to the `gitignoreSourcePure` list in `nix/mir-semantics/default.nix`, see the respective left-over `TODO` in the nix file. Otherwise, the nix build that is uploaded to the nix binary cache by CI might not match the version that is requested by `kup`, in case this project is offered as a package by `kup`. This is due to weird behaviour in regards to git submodules by `git` and `nix`, where a submodule directory might exist and be empty or instead not exist, which impacts the resulting nix hash, which is of impartance when offering/downloading cached nix derivations. See [runtimeverification/k/pull/4804](https://github.com/runtimeverification/k/pull/4804) for more information. -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/intrinsic/blackbox_function_tys.expected.json: -------------------------------------------------------------------------------- 1 | { 2 | "<&u32 as std::fmt::Debug>::fmt": -3, 3 | "<() as std::process::Termination>::report": 14, 4 | ">::call_once": 19, 5 | "<{closure@std::rt::lang_start<()>::{closure#0}} as std::ops::FnOnce<()>>::call_once": 30, 6 | "add_one": 43, 7 | "core::fmt::num::::fmt": 21, 8 | "core::panicking::assert_failed::": 45, 9 | "main": -1, 10 | "std::hint::black_box::": 44, 11 | "std::ptr::drop_in_place::<&u32>": -5, 12 | "std::ptr::drop_in_place::<{closure@std::rt::lang_start<()>::{closure#0}}>": -6, 13 | "std::rt::lang_start::<()>": -2, 14 | "std::rt::lang_start::<()>::{closure#0}": 32, 15 | "std::sys::backtrace::__rust_begin_short_backtrace::": 13 16 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/functions/input.json: -------------------------------------------------------------------------------- 1 | [ 2 | [ 3 | 114, 4 | { 5 | "NormalSym": "_ZN4core3ptr42drop_in_place$LT$alloc..string..String$GT$17h1018ac0f9e0b0734E" 6 | } 7 | ], 8 | [ 9 | 102, 10 | { 11 | "NoOpSym": "" 12 | } 13 | ], 14 | [ 15 | 19, 16 | { 17 | "NormalSym": "_ZN4core3ops8function6FnOnce9call_once17ha726c80bc9e6a2adE" 18 | } 19 | ], 20 | [ 21 | 100, 22 | { 23 | "NormalSym": "__rust_dealloc" 24 | } 25 | ], 26 | [ 27 | 78, 28 | { 29 | "IntrinsicSym": "volatile_load" 30 | } 31 | ], 32 | [ 33 | 27, 34 | { 35 | "IntrinsicSym": "ctpop" 36 | } 37 | ], 38 | [ 39 | 109, 40 | { 41 | "NormalSym": "_ZN10mainfoobar3bar17hc9f701b05bebc012E" 42 | } 43 | ] 44 | ] 45 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/two-crate-bin/main-crate/src/main.rs: -------------------------------------------------------------------------------- 1 | use crate1; 2 | use crate1::MyStruct; 3 | 4 | fn main() { 5 | let result = test_crate1_with(Some(42)); 6 | 7 | if let crate1::MyEnum::Bar(result2) = use_unwrap_enum(Some(crate1::MyEnum::Bar(42))) { 8 | assert_eq!(result.int_field, result2); 9 | } 10 | } 11 | 12 | fn test_crate1_with(maybe_i: Option) -> MyStruct { 13 | // let (the_i, the_e) = if let Some(i) = maybe_i { 14 | // (i, Some(crate1::MyEnum::Bar(i))) 15 | // } else { 16 | // (0, None) 17 | // }; 18 | let the_i = maybe_i.unwrap_or(0 + 1 + 2 + 3); 19 | let the_e = maybe_i.map(|i| crate1::MyEnum::Bar(i)); 20 | 21 | MyStruct::new(the_i, the_e) 22 | } 23 | 24 | fn use_unwrap_enum(e: Option) -> crate1::MyEnum { 25 | e.unwrap_or(crate1::MyEnum::Bar(0)) 26 | } 27 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/symbolic-structs-fail.rs: -------------------------------------------------------------------------------- 1 | #[allow(dead_code)] 2 | struct IntStruct{ 3 | field1: i16, 4 | field2: u8, 5 | field3: bool, 6 | } 7 | 8 | #[allow(dead_code)] 9 | struct OtherStruct { 10 | field1: i16, 11 | field2: u8, 12 | } 13 | 14 | #[allow(dead_code)] 15 | #[allow(unused)] 16 | fn eats_struct_args( 17 | x1: i16, 18 | mut x2: IntStruct, 19 | x3: &OtherStruct, 20 | ) -> () { 21 | if (x2.field1 == (*x3).field1) { 22 | x2.field2 = (*x3).field2; 23 | x2.field3 = true; 24 | } else { 25 | x2.field1 = x1; 26 | x2.field3 = false; 27 | } 28 | 29 | assert!(x2.field3 || x2.field2 != (*x3).field2); 30 | } 31 | 32 | fn main () { 33 | let a = IntStruct{ field1: 0, field2: 1, field3: false}; 34 | let b = OtherStruct{field1: 2, field2: 3}; 35 | eats_struct_args(5, a, &b) 36 | } 37 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/transmute-u8-to-enum-changed-discriminant-signed-fail.rs: -------------------------------------------------------------------------------- 1 | #[repr(i8)] 2 | #[derive(Clone, Copy, Debug, PartialEq)] 3 | pub enum AccountState { 4 | Uninitialized = 0, 5 | Initialized = 1, 6 | Frozen = -1, 7 | } 8 | 9 | fn main() { 10 | unsafe { 11 | assert_eq!(core::mem::transmute::(0), AccountState::Uninitialized); 12 | assert_eq!(core::mem::transmute::(0), AccountState::Uninitialized); 13 | 14 | assert_eq!(core::mem::transmute::(1), AccountState::Initialized); 15 | assert_eq!(core::mem::transmute::(1), AccountState::Initialized); 16 | 17 | assert_eq!(core::mem::transmute::(255), AccountState::Frozen); 18 | assert_eq!(core::mem::transmute::(-1), AccountState::Frozen); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /kmir/src/kmir/kprint.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import logging 4 | from typing import TYPE_CHECKING 5 | 6 | from pyk.kast.pretty import PrettyPrinter, indent 7 | 8 | _LOGGER: logging.Logger = logging.getLogger(__name__) 9 | 10 | if TYPE_CHECKING: 11 | from pyk.kast.outer import KDefinition 12 | 13 | 14 | class KMIRPrettyPrinter(PrettyPrinter): 15 | """ 16 | Custom Pretty Printer for improved ListItem display formatting. 17 | Formats ListItem elements with line breaks for better readability. 18 | """ 19 | 20 | def __init__(self, definition: KDefinition) -> None: 21 | """ 22 | Initialize KMIR Pretty Printer 23 | 24 | Args: 25 | definition: K definition 26 | """ 27 | super().__init__(definition) 28 | self.symbol_table['ListItem'] = lambda *args: 'ListItem (' + (indent(', '.join(args))).strip() + ')\n' 29 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/two-crate-bin/crate1/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub fn add(left: u64, right: u64) -> u64 { 2 | left + right 3 | } 4 | 5 | #[derive(Clone, Copy)] 6 | pub struct MyStruct { 7 | pub int_field: isize, 8 | pub enum_field: MyEnum, 9 | pub option_field: Option 10 | } 11 | 12 | impl MyStruct { 13 | pub fn new(i: isize, e: Option) -> Self { 14 | let enum_field = e.unwrap_or(MyEnum::Foo); 15 | MyStruct { int_field: i, enum_field, option_field: e } 16 | } 17 | } 18 | 19 | #[derive(Clone, Copy)] 20 | pub enum MyEnum { 21 | Foo, 22 | Bar(isize) 23 | } 24 | 25 | impl MyEnum { 26 | pub fn default() -> Self { Self::Bar(42) } 27 | } 28 | 29 | #[cfg(test)] 30 | mod tests { 31 | use super::*; 32 | 33 | #[test] 34 | fn it_works() { 35 | let result = add(2, 2); 36 | assert_eq!(result, 4); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/allocs/option_consts.rs: -------------------------------------------------------------------------------- 1 | const OPT_NO_U32: Option = None; 2 | const OPT_A_U64: Option = Some(42); 3 | const OPT_NO_REF: Option<&[u32;3]> = None; 4 | 5 | fn main() { 6 | let a = 1; 7 | let result = sub_(0,a); 8 | assert_eq!(result, OPT_NO_U32); 9 | assert_eq!(OPT_A_U64, Some(41 + a as u64)); 10 | assert!(OPT_NO_REF.is_none()); 11 | let arr0 = [0u32; 3]; 12 | assert_eq!(opt_ref(&arr0), None); 13 | let arr = [a;3]; 14 | assert_eq!(opt_ref(&arr), Some(&arr)); 15 | } 16 | 17 | // basically checked_sub 18 | fn sub_(a:u32, b:u32) -> Option { 19 | if a < b { 20 | None // this becomes an Operand::Constant 21 | } else { 22 | Some(a - b) 23 | } 24 | } 25 | 26 | fn opt_ref(arr: &[u32;3]) -> Option<&[u32;3]> { 27 | if arr[0] == 0 { 28 | None 29 | } else { 30 | Some(arr) 31 | } 32 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/488-support-function-pointer-calls.rs: -------------------------------------------------------------------------------- 1 | use std::convert::TryFrom; 2 | use std::array; 3 | 4 | // inspired by solana-pubkey but very simple code 5 | #[allow(dead_code)] 6 | struct EightBytes([u8;8]); 7 | 8 | impl From<[u8;8]> for EightBytes { 9 | fn from(bytes: [u8;8]) -> Self { Self(bytes) } 10 | } 11 | 12 | // causing problems with the extraction 13 | // the `try_from` and `from` from stdlib are not available in the SMIR 14 | impl TryFrom<&[u8]> for EightBytes { 15 | type Error = array::TryFromSliceError; 16 | fn try_from(bytes: &[u8]) -> Result { 17 | <[u8;8]>::try_from(bytes).map(Self::from) 18 | } 19 | } 20 | 21 | fn main() { 22 | let bytes: [u8;8] = [1,2,3,4,5,6,7,8]; 23 | let slice: &[u8] = &bytes; 24 | let thing: Result = EightBytes::try_from(slice); 25 | assert!(thing.is_ok()); 26 | } 27 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/enum.smir.main.cli-stats-leaves.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ span: src/rust/library/std/src/rt.rs:194 5 | │ 6 | │ (162 steps) 7 | ├─ 3 (terminal) 8 | │ #EndProgram ~> .K 9 | │ function: main 10 | │ 11 | ┊ constraint: true 12 | ┊ subst: ... 13 | └─ 2 (leaf, target, terminal) 14 | #EndProgram ~> .K 15 | 16 | 17 | 18 | 19 | STATISTICS 20 | ----------- 21 | Total nodes: 2 22 | 23 | Node roles (exclusive): 24 | target : 1 ids: 2 25 | terminal: 1 ids: 3 26 | (root nodes omitted from totals: 1) 27 | 28 | Leaf paths from init: 29 | total leaves (non-root): 1 30 | reachable leaves : 1 31 | total steps : 162 32 | 33 | leaf 2: steps 162, path 1 -> 3 -> 2 34 | 35 | LEAF CELLS 36 | --------------- 37 | Node 2: 38 | #EndProgram ~> .K -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/slice-split-at.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | let arr: [u8; 2] = [42, 255]; 3 | let slice = arr.as_slice(); 4 | let (left, right) = slice.split_at(1); 5 | assert!(left == [42]); 6 | assert!(right == [255]); 7 | 8 | let arr: [u8; 3] = [42, 255, 66]; 9 | let slice = arr.as_slice(); 10 | let (left, right) = slice.split_at(1); 11 | assert!(left == [42]); 12 | assert!(right == [255, 66]); 13 | 14 | // Empty Case RHS 15 | let arr: [u8; 3] = [42, 255, 66]; 16 | let slice = arr.as_slice(); 17 | let (left, right) = slice.split_at(3); 18 | assert!(left == [42, 255, 66]); 19 | assert!(right == []); 20 | 21 | // Empty Case LHS 22 | let arr: [u8; 3] = [42, 255, 66]; 23 | let slice = arr.as_slice(); 24 | let (left, right) = slice.split_at(0); 25 | assert!(left == []); 26 | assert!(right == [42, 255, 66]); 27 | } 28 | -------------------------------------------------------------------------------- /kmir/src/kmir/parse/__main__.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import sys 3 | from pathlib import Path 4 | 5 | from ..build import LLVM_DEF_DIR 6 | from ..kmir import KMIR 7 | from .parser import parse_json 8 | 9 | 10 | def parse_args() -> argparse.Namespace: 11 | parser = argparse.ArgumentParser() 12 | parser.add_argument('json', metavar='JSON', help='JSON data to convert') 13 | parser.add_argument('sort', metavar='SORT', help='Expected Sort name for the parsed term', default='pgm') 14 | return parser.parse_args() 15 | 16 | 17 | def main() -> None: 18 | sys.setrecursionlimit(10000000) 19 | args = parse_args() 20 | kmir = KMIR(LLVM_DEF_DIR) 21 | 22 | result = parse_json(kmir.definition, Path(args.json), args.sort) 23 | 24 | if result is None: 25 | print('Parse error!', file=sys.stderr) 26 | sys.exit(1) 27 | 28 | term, _ = result 29 | print(kmir.pretty_print(term)) 30 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/two-crate-dylib/crate1/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub fn add(left: isize, right: isize) -> isize { 2 | left + right 3 | } 4 | 5 | #[derive(Clone, Copy)] 6 | pub struct MyStruct { 7 | pub int_field: isize, 8 | pub enum_field: MyEnum, 9 | pub option_field: Option 10 | } 11 | 12 | impl MyStruct { 13 | pub fn new(i: isize, e: Option) -> Self { 14 | let enum_field = e.unwrap_or(MyEnum::Foo); 15 | MyStruct { int_field: add(i, 0), enum_field, option_field: e } 16 | } 17 | } 18 | 19 | #[derive(Clone, Copy)] 20 | pub enum MyEnum { 21 | Foo, 22 | Bar(isize) 23 | } 24 | 25 | impl MyEnum { 26 | pub fn default() -> Self { Self::Bar(42) } 27 | } 28 | 29 | #[cfg(test)] 30 | mod tests { 31 | use super::*; 32 | 33 | #[test] 34 | fn it_works() { 35 | let result = add(2, 2); 36 | assert_eq!(result, 4); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/struct-multi/struct-multi.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | 3 | // Exercise decoding of a struct whose fields are not stored in declaration order. 4 | // RangeInclusive is known to have such a layout on some platforms. 5 | 6 | use std::ops::RangeInclusive; 7 | 8 | // Force a multi-field StructType constant so decoding happens at runtime. 9 | // Use RangeInclusive::new in a const context to avoid evaluation at run time. 10 | const R: RangeInclusive = RangeInclusive::new(0, 31); 11 | 12 | fn main() { 13 | // Use the constant so MIR emits a Constant->Allocated for a StructType with 2 fields 14 | let r = R; 15 | // Compute a boolean via public API that depends on correct internal layout decoding. 16 | // If decoding is wrong (e.g., ignoring non-ordered offsets), this expression can differ. 17 | let ok = r.contains(&0) && r.contains(&31) && !r.contains(&32); 18 | assert!(ok); 19 | } 20 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/enum/enum.rs: -------------------------------------------------------------------------------- 1 | #![allow(unused)] 2 | #![allow(dead_code)] 3 | enum Letter { 4 | A = 65, 5 | B, 6 | M = 77, 7 | } 8 | 9 | #[repr(u16)] 10 | enum WithData { 11 | X = 88, 12 | Y{y:i32} = 89, 13 | Z{y:i16, z: bool} = 90, 14 | ZZ(i8, i8, bool) = 9090, 15 | } 16 | 17 | fn main() { 18 | let a = Letter::A; 19 | 20 | let x = WithData::X; 21 | let y = WithData::Y { y: 42}; 22 | let z = WithData::Z { y:42, z: false }; 23 | let zz = WithData::ZZ(42, 43, true); 24 | 25 | let mut zzz : WithData; 26 | 27 | if let WithData::Y{y} = x { 28 | let zzz = WithData::Y{y}; 29 | } 30 | 31 | if let Letter::A = a { 32 | let zzz = a; 33 | } 34 | 35 | match zz { 36 | WithData::Y{y:_} => 37 | zzz = y, 38 | WithData::Z{y:_, z} => 39 | zzz = WithData::ZZ(0, 0, z), 40 | _ => 41 | zzz = x, 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /kmir/src/kmir/kdist/mir-semantics/cheatcodes.md: -------------------------------------------------------------------------------- 1 | ## Cheatcodes 2 | 3 | ### Assume 4 | 5 | - Purpose: prune paths by assuming a boolean condition. 6 | - Hook: NonDivergingIntrinsic::Assume. 7 | - Semantics: add a path constraint via ensures (post-condition); false makes the path infeasible; true is a no-op. 8 | - Usage: nightly + `#![feature(core_intrinsics)]`; inside `unsafe` call `std::intrinsics::assume()`, e.g. `unsafe { std::intrinsics::assume(x < 10) }`. 9 | 10 | ```k 11 | module KMIR-CHEATCODES 12 | imports BOOL 13 | imports KMIR-CONTROL-FLOW 14 | 15 | // Driver 16 | syntax KItem ::= #assume ( Evaluation ) [strict(1), symbol(cheatcode_assume)] 17 | 18 | // Hook: intrinsic → cheatcode 19 | rule #execStmt(statement(statementKindIntrinsic(nonDivergingIntrinsicAssume(OP)), _SPAN)) 20 | => #assume(OP) 21 | ... 22 | 23 | 24 | // Post-condition 25 | rule #assume(BoolVal(B)) => .K ... 26 | ensures B 27 | endmodule 28 | ``` 29 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/README.md: -------------------------------------------------------------------------------- 1 | Small tests for MIR execution 2 | ----------------------------- 3 | 4 | The tests below this directory are intended to be run with `kmir run`, comparing the pretty-printed output to an expectation file. 5 | 6 | # To add a new test 7 | 8 | * Write a Rust test program `NAME.rs` 9 | * Generate stable-mir JSON `NAME.smir.json` for the test program (using `deps/stable-mir-pretty`) 10 | * run the program once to generate the expected output state 11 | ``` 12 | /mir-semantics $ poetry -C kmir run -- kmir run path/to/NAME.smir.json > //.run.state 13 | ``` 14 | * check that the output is as expected 15 | * add test to `EXEC_DATA` array in `kmir/src/tests/integration/test_integration.py` 16 | * Several tests can be run from the same `NAME.smir.json` by varying the `--depth` parameter. 17 | 18 | 19 | Ideally, we should also keep the original `NAME.rs` program so we can later update the tests when/if the JSON format changes. 20 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-smir-random/complex-types/test.rs: -------------------------------------------------------------------------------- 1 | pub struct Point { 2 | x: i32, 3 | y: i32, 4 | } 5 | 6 | pub enum Foo { 7 | Bar, 8 | Baz(Point), 9 | Qux(u8, Option), 10 | } 11 | 12 | pub fn test(foo: Foo, bs: [u8; 8], ns: &[i32]) { 13 | match foo { 14 | Foo::Bar => {}, 15 | Foo::Baz(Point { x, y }) => if x >= y { 16 | assert!(x - y >= 0); 17 | } else { 18 | assert!(y - x >= 0); 19 | }, 20 | Foo::Qux(x, Some(y)) => { 21 | assert!(u16::from(x) + u16::from(y) >= u16::from(x + y)); 22 | }, 23 | _ => {}, 24 | } 25 | 26 | let mut sum: u64 = 0; 27 | for b in bs { 28 | let b64 = u64::from(b); 29 | sum += b64; 30 | assert!(sum >= b64); 31 | } 32 | 33 | let mut min: i32 = i32::MAX; 34 | for n in ns { 35 | if *n < min { 36 | min = *n; 37 | } 38 | assert!(min <= *n); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/schema-parse/functions/reference.kmir: -------------------------------------------------------------------------------- 1 | ListItem( 2 | functionName( 3 | ty(114), 4 | functionNormalSym(symbol("_ZN4core3ptr42drop_in_place$LT$alloc..string..String$GT$17h1018ac0f9e0b0734E")) 5 | ) 6 | ) 7 | ListItem( 8 | functionName( 9 | ty(102), 10 | functionNoop(symbol("")) 11 | ) 12 | ) 13 | ListItem( 14 | functionName( 15 | ty(19), 16 | functionNormalSym(symbol("_ZN4core3ops8function6FnOnce9call_once17ha726c80bc9e6a2adE")) 17 | ) 18 | ) 19 | ListItem( 20 | functionName( 21 | ty(100), 22 | functionNormalSym(symbol("__rust_dealloc")) 23 | ) 24 | ) 25 | ListItem( 26 | functionName( 27 | ty(78), 28 | functionIntrinsic(symbol("volatile_load")) 29 | ) 30 | ) 31 | ListItem( 32 | functionName( 33 | ty(27), 34 | functionIntrinsic(symbol("ctpop")) 35 | ) 36 | ) 37 | ListItem( 38 | functionName( 39 | ty(109), 40 | functionNormalSym(symbol("_ZN10mainfoobar3bar17hc9f701b05bebc012E")) 41 | ) 42 | ) 43 | -------------------------------------------------------------------------------- /.github/workflows/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG K_DISTRO=jammy 2 | ARG K_COMMIT 3 | FROM runtimeverificationinc/kframework-k:ubuntu-${K_DISTRO}-${K_COMMIT} 4 | RUN apt-get update \ 5 | && apt-get upgrade --yes \ 6 | && apt-get install --yes \ 7 | curl 8 | 9 | ARG USER=user 10 | ARG GROUP 11 | ARG USER_ID=1000 12 | ARG GROUP_ID=1000 13 | RUN groupadd -g ${GROUP_ID} ${GROUP} && useradd -m -u ${USER_ID} -s /bin/sh -g ${GROUP} ${USER} 14 | USER ${USER}:${GROUP} 15 | 16 | ENV PATH="/home/${USER}/.cargo/bin:${PATH}" 17 | RUN curl https://sh.rustup.rs -sSf | bash -s -- -y 18 | RUN rustup toolchain install nightly-2024-11-29 --component llvm-tools --component rustc-dev --component rust-src 19 | RUN rustup default nightly-2024-11-29-x86_64-unknown-linux-gnu 20 | 21 | RUN mkdir /home/${USER}/workspace 22 | WORKDIR /home/${USER}/workspace 23 | 24 | ARG UV_VERSION 25 | ENV PATH=/home/${USER}/.local/bin:${PATH} 26 | RUN curl -LsSf https://astral.sh/uv/$UV_VERSION/install.sh | sh \ 27 | && uv --version 28 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/cmp.rs: -------------------------------------------------------------------------------- 1 | fn cmp_lt(x: i32, y: i32) -> bool { 2 | x < y 3 | } 4 | 5 | fn cmp_le(x: i32, y: i32) -> bool { 6 | x <= y 7 | } 8 | 9 | fn cmp_gt(x: i32, y: i32) -> bool { 10 | x > y 11 | } 12 | 13 | fn cmp_ge(x: i32, y: i32) -> bool { 14 | x >= y 15 | } 16 | 17 | fn cmp_eq(x: i32, y: i32) -> bool { 18 | x == y 19 | } 20 | 21 | fn cmp_neq(x: i32, y: i32) -> bool { 22 | x != y 23 | } 24 | 25 | fn main() { 26 | assert!( cmp_lt(3, 4)); 27 | assert!(!cmp_lt(4, 3)); 28 | assert!(!cmp_lt(4, 4)); 29 | 30 | assert!( cmp_le(3, 4)); 31 | assert!(!cmp_le(4, 3)); 32 | assert!( cmp_le(4, 4)); 33 | 34 | assert!(!cmp_gt(3, 4)); 35 | assert!( cmp_gt(4, 3)); 36 | assert!(!cmp_gt(4, 4)); 37 | 38 | assert!(!cmp_ge(3, 4)); 39 | assert!( cmp_ge(4, 3)); 40 | assert!( cmp_ge(4, 4)); 41 | 42 | assert!(!cmp_eq(4, 3)); 43 | assert!( cmp_eq(4, 4)); 44 | 45 | assert!( cmp_neq(4, 3)); 46 | assert!(!cmp_neq(4, 4)); 47 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/transmute-u8-to-enum-changed-discriminant.rs: -------------------------------------------------------------------------------- 1 | #[repr(u8)] 2 | #[derive(Clone, Copy, Debug, PartialEq)] 3 | pub enum AccountState { 4 | Uninitialized = 11, 5 | Initialized = 22, 6 | Frozen = 255, 7 | } 8 | 9 | fn main() { 10 | unsafe { 11 | assert_eq!(core::mem::transmute::(11), AccountState::Uninitialized); 12 | assert_eq!(core::mem::transmute::(22), AccountState::Initialized); 13 | assert_eq!(core::mem::transmute::(255), AccountState::Frozen); 14 | 15 | // Compiler rejects transmuting between different width types 16 | // assert_eq!(core::mem::transmute::(-1), AccountState::Frozen); 17 | 18 | // The within the same width the type can be different, here an `-1_i8` is used instead 19 | // of a `255_u8`, but the bit pattern matches it creates the correct type 20 | assert_eq!(core::mem::transmute::(-1), AccountState::Frozen); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/local-raw-fail.main.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ span: 0 5 | │ 6 | │ (106 steps) 7 | ├─ 3 8 | │ #expect ( thunk ( #applyBinOp ( binOpEq , thunk ( #applyBinOp ( binOpBitAnd , th 9 | │ function: main 10 | ┃ 11 | ┃ (1 step) 12 | ┣━━┓ 13 | ┃ │ 14 | ┃ ├─ 4 15 | ┃ │ AssertError ( assertMessageMisalignedPointerDereference ( ... required: operandC 16 | ┃ │ function: main 17 | ┃ │ 18 | ┃ │ (1 step) 19 | ┃ └─ 6 (stuck, leaf) 20 | ┃ #ProgramError ( AssertError ( assertMessageMisalignedPointerDereference ( ... re 21 | ┃ function: main 22 | ┃ 23 | ┗━━┓ 24 | │ 25 | ├─ 5 26 | │ #execBlockIdx ( basicBlockIdx ( 1 ) ) ~> .K 27 | │ function: main 28 | │ 29 | │ (16 steps) 30 | ├─ 7 (terminal) 31 | │ #EndProgram ~> .K 32 | │ function: main 33 | │ 34 | ┊ constraint: true 35 | ┊ subst: ... 36 | └─ 2 (leaf, target, terminal) 37 | #EndProgram ~> .K 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/raw-ptr-cast-fail.main.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ span: 0 5 | │ 6 | │ (120 steps) 7 | ├─ 3 8 | │ #expect ( thunk ( #applyBinOp ( binOpEq , thunk ( #applyBinOp ( binOpBitAnd , th 9 | │ function: main 10 | ┃ 11 | ┃ (1 step) 12 | ┣━━┓ 13 | ┃ │ 14 | ┃ ├─ 4 15 | ┃ │ AssertError ( assertMessageMisalignedPointerDereference ( ... required: operandC 16 | ┃ │ function: main 17 | ┃ │ 18 | ┃ │ (1 step) 19 | ┃ └─ 6 (stuck, leaf) 20 | ┃ #ProgramError ( AssertError ( assertMessageMisalignedPointerDereference ( ... re 21 | ┃ function: main 22 | ┃ 23 | ┗━━┓ 24 | │ 25 | ├─ 5 26 | │ #execBlockIdx ( basicBlockIdx ( 3 ) ) ~> .K 27 | │ function: main 28 | │ 29 | │ (124 steps) 30 | ├─ 7 (terminal) 31 | │ #EndProgram ~> .K 32 | │ function: main 33 | │ 34 | ┊ constraint: true 35 | ┊ subst: ... 36 | └─ 2 (leaf, target, terminal) 37 | #EndProgram ~> .K 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/intrinsics.rs: -------------------------------------------------------------------------------- 1 | #![feature(core_intrinsics)] 2 | use std::intrinsics::{self, assert_inhabited}; 3 | 4 | fn main() { 5 | intrinsics::cold_path(); 6 | let b = true; 7 | intrinsics::likely(b); 8 | intrinsics::unlikely(b); 9 | prefetch(); 10 | assert_inhabited::(); // Up to compiler/CodegenBackend to panic or NOOP 11 | std::hint::black_box( 12 | assert_inhabited::<()>() // Trying to stop being optimised away 13 | ); 14 | } 15 | 16 | fn prefetch() { 17 | let mut data = 11; 18 | let ptr = &data as *const i32; 19 | 20 | unsafe { 21 | intrinsics::prefetch_read_instruction::(ptr, 3); 22 | intrinsics::prefetch_read_data::(ptr, 3); 23 | assert_eq!(11, *ptr); 24 | } 25 | 26 | let ptr_mut = &mut data as *mut i32; 27 | unsafe { 28 | intrinsics::prefetch_write_instruction::(ptr_mut, 3); 29 | intrinsics::prefetch_write_data::(ptr_mut, 3); 30 | // (*ptr_mut) = 44; 31 | // assert_eq!(44, *ptr); // FIXME: fails due to thunks on casts 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/transmute-try-from-symbolic.rs: -------------------------------------------------------------------------------- 1 | use std::convert::TryFrom; 2 | 3 | pub enum ProgramError { 4 | InvalidAccountData 5 | } 6 | 7 | #[repr(u8)] 8 | #[derive(Clone, Copy, Debug, PartialEq)] 9 | pub enum AccountState { 10 | Uninitialized, 11 | Initialized, 12 | Frozen, 13 | } 14 | 15 | impl TryFrom for AccountState { 16 | type Error = ProgramError; 17 | 18 | #[inline(always)] 19 | fn try_from(value: u8) -> Result { 20 | match value { 21 | // SAFETY: `value` is guaranteed to be in the range of the enum variants. 22 | 0..=2 => Ok(unsafe { core::mem::transmute::(value) }), 23 | _ => Err(ProgramError::InvalidAccountData), 24 | } 25 | } 26 | } 27 | 28 | fn main() { 29 | num_into_state(0); 30 | } 31 | 32 | fn num_into_state(arg: u8) { 33 | let state: Result = AccountState::try_from(arg); 34 | 35 | if arg <= 2 { 36 | assert!(state.is_ok()); 37 | } else { 38 | assert!(state.is_err()); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/references/weirdRefs.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug)] 2 | struct MyStruct { 3 | a_value: i8, 4 | another: bool, 5 | a_third: usize, 6 | } 7 | 8 | #[derive(Debug)] 9 | struct Enclosing<'a> { 10 | inner: &'a mut MyStruct 11 | } 12 | 13 | fn main () { 14 | 15 | let mut a = MyStruct { a_value: 32, another: false, a_third: 32}; 16 | 17 | // mutate field through ref and double-ref 18 | let r1 = &mut (a.a_value); 19 | *r1 = 42; 20 | assert!(a.a_value == 42); 21 | let mut r1 = &mut (a.a_value); 22 | let r2 = &mut r1; 23 | **r2 = 43; 24 | assert!(a.a_value == 43); 25 | 26 | // create reference-field chain 27 | let mut e = Enclosing{inner: &mut a}; 28 | let ee = &mut e; 29 | 30 | // read and write values through chain of ref/field projections 31 | let vv = (*(*ee).inner).a_value; 32 | assert!(vv == 43); 33 | 34 | (*(*ee).inner).another = true; 35 | 36 | let r3 = &mut (*ee).inner.a_third; 37 | *r3 = (*(*ee).inner).a_value as usize; 38 | 39 | assert!(a.another); 40 | assert!(a.a_third == 43); 41 | 42 | } 43 | 44 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/intrinsic/raw_eq_simple.rs: -------------------------------------------------------------------------------- 1 | #![feature(core_intrinsics)] 2 | 3 | use std::intrinsics::raw_eq; 4 | 5 | // NOTE: This test demonstrates the raw_eq intrinsic implementation. 6 | // Known issue: Haskell backend produces more verbose symbolic execution output 7 | // compared to LLVM backend due to different handling of symbolic branches. 8 | // Both backends correctly implement the intrinsic but output format differs. 9 | 10 | fn main() { 11 | let a = 42; 12 | let b = 42; 13 | 14 | // Test raw_eq intrinsic with identical values (both variables) 15 | let result = unsafe { raw_eq(&a, &b) }; 16 | assert!(result); 17 | 18 | // TODO: need alloc to be supported in the semantics 19 | // // Test raw_eq with constant and variable (same type, same value) 20 | // let result_const_var = unsafe { raw_eq(&42, &a) }; 21 | // assert!(result_const_var); 22 | 23 | // // Test raw_eq with constant and variable (same type, different value) 24 | // let c = 24; 25 | // let result_const_var_diff = unsafe { raw_eq(&42, &c) }; 26 | // assert!(!result_const_var_diff); 27 | } -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/single-lib/small_test_lib::testing::test_add_in_range.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ 5 | │ (114 steps) 6 | ├─ 3 (split) 7 | │ #selectBlock ( switchTargets ( ... branches: branch ( 0 , basicBlockIdx ( 1 ) ) 8 | ┃ 9 | ┃ (branch) 10 | ┣━━┓ subst: .Subst 11 | ┃ ┃ constraint: 12 | ┃ ┃ notBool ARG_UINT1:Int +Int ARG_UINT2:Int <=Int 18446744073709551615 13 | ┃ │ 14 | ┃ ├─ 4 15 | ┃ │ #selectBlock ( switchTargets ( ... branches: branch ( 0 , basicBlockIdx ( 1 ) ) 16 | ┃ │ 17 | ┃ │ (6 steps) 18 | ┃ └─ 6 (stuck, leaf) 19 | ┃ #setUpCalleeData ( monoItemFn ( ... name: symbol ( "** UNKNOWN FUNCTION **" ) , 20 | ┃ 21 | ┗━━┓ subst: .Subst 22 | ┃ constraint: 23 | ┃ ARG_UINT1:Int +Int ARG_UINT2:Int <=Int 18446744073709551615 24 | │ 25 | ├─ 5 26 | │ #selectBlock ( switchTargets ( ... branches: branch ( 0 , basicBlockIdx ( 1 ) ) 27 | │ 28 | │ (182 steps) 29 | ├─ 7 (terminal) 30 | │ #EndProgram ~> .K 31 | │ 32 | ┊ constraint: true 33 | ┊ subst: ... 34 | └─ 2 (leaf, target, terminal) 35 | #EndProgram ~> .K 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/tuple-bool-u32.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [ 3 | 1, 4 | 0, 5 | 0, 6 | 0, 7 | 120, 8 | 86, 9 | 52, 10 | 18 11 | ], 12 | "types": [ 13 | [ 14 | 1, 15 | { 16 | "PrimitiveType": "Bool" 17 | } 18 | ], 19 | [ 20 | 4, 21 | { 22 | "PrimitiveType": { 23 | "Uint": "U32" 24 | } 25 | } 26 | ] 27 | ], 28 | "typeInfo": { 29 | "TupleType": { 30 | "types": [ 31 | 1, 32 | 4 33 | ], 34 | "layout": { 35 | "fields": { 36 | "Arbitrary": { 37 | "offsets": [ 38 | { 39 | "num_bits": 0 40 | }, 41 | { 42 | "num_bits": 32 43 | } 44 | ] 45 | } 46 | }, 47 | "variants": { 48 | "Single": { 49 | "index": 0 50 | } 51 | }, 52 | "abi": { 53 | "Aggregate": { 54 | "sized": true 55 | } 56 | }, 57 | "abi_align": 4, 58 | "size": { 59 | "num_bits": 64 60 | } 61 | } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/tuple-u8-i32.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [ 3 | 171, 4 | 0, 5 | 0, 6 | 0, 7 | 120, 8 | 86, 9 | 52, 10 | 18 11 | ], 12 | "types": [ 13 | [ 14 | 0, 15 | { 16 | "PrimitiveType": { 17 | "Uint": "U8" 18 | } 19 | } 20 | ], 21 | [ 22 | 3, 23 | { 24 | "PrimitiveType": { 25 | "Int": "I32" 26 | } 27 | } 28 | ] 29 | ], 30 | "typeInfo": { 31 | "TupleType": { 32 | "types": [ 33 | 0, 34 | 3 35 | ], 36 | "layout": { 37 | "fields": { 38 | "Arbitrary": { 39 | "offsets": [ 40 | { 41 | "num_bits": 0 42 | }, 43 | { 44 | "num_bits": 32 45 | } 46 | ] 47 | } 48 | }, 49 | "variants": { 50 | "Single": { 51 | "index": 0 52 | } 53 | }, 54 | "abi": { 55 | "Aggregate": { 56 | "sized": true 57 | } 58 | }, 59 | "abi_align": 4, 60 | "size": { 61 | "num_bits": 64 62 | } 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/pointers/ref_ptr_cases.rs: -------------------------------------------------------------------------------- 1 | fn aliasing_refs_have_same_pointer() { 2 | let value = 42_i32; 3 | let first = &value; 4 | let second = &value; 5 | 6 | assert!((first as *const i32) == (second as *const i32)); 7 | assert!(std::ptr::eq(first, second)); 8 | } 9 | 10 | fn distinct_locals_have_distinct_pointers() { 11 | let left = 10_i32; 12 | let right = 10_i32; 13 | 14 | assert!((&left as *const i32) != (&right as *const i32)); 15 | } 16 | 17 | fn array_element_addresses_are_distinct() { 18 | let items = [3_u8, 5, 7]; 19 | let first = &items[0]; 20 | let first_again = &items[0]; 21 | let second = &items[1]; 22 | 23 | assert!((first as *const u8) == (first_again as *const u8)); 24 | assert!((first as *const u8) != (second as *const u8)); 25 | } 26 | 27 | fn reborrow_mut_pointer_roundtrip() { 28 | let mut byte = 0_u8; 29 | let ptr = &mut byte as *mut u8; 30 | 31 | unsafe { 32 | *ptr = 1; 33 | } 34 | 35 | assert_eq!(byte, 1); 36 | } 37 | 38 | fn main() { 39 | aliasing_refs_have_same_pointer(); 40 | distinct_locals_have_distinct_pointers(); 41 | array_element_addresses_are_distinct(); 42 | reborrow_mut_pointer_roundtrip(); 43 | } 44 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/enum-1-variant-2-fields.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [ 3 | 255, 4 | 0, 5 | 1, 6 | 0 7 | ], 8 | "types": [ 9 | [ 10 | 2, 11 | { 12 | "PrimitiveType": { 13 | "Int": "I16" 14 | } 15 | } 16 | ], 17 | [ 18 | 1, 19 | { 20 | "PrimitiveType": "Bool" 21 | } 22 | ] 23 | ], 24 | "typeInfo": { 25 | "EnumType": { 26 | "name": "Foo", 27 | "adt_def": 1, 28 | "discriminants": [ 29 | 0 30 | ], 31 | "fields": [ 32 | [ 33 | 2, 34 | 1 35 | ] 36 | ], 37 | "layout": { 38 | "fields": { 39 | "Arbitrary": { 40 | "offsets": [ 41 | { 42 | "num_bits": 0 43 | }, 44 | { 45 | "num_bits": 16 46 | } 47 | ] 48 | } 49 | }, 50 | "variants": { 51 | "Single": { 52 | "index": 0 53 | } 54 | }, 55 | "abi": { 56 | "ScalarPair": {} 57 | }, 58 | "abi_align": 2, 59 | "size": { 60 | "num_bits": 32 61 | } 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/pointer-cast.rs: -------------------------------------------------------------------------------- 1 | // example functions producing pointer coercion and PtrToPtr casts 2 | 3 | fn main() { 4 | if test(42) != 42 { 5 | test_unpack_success(42); 6 | }; 7 | } 8 | 9 | // from p-token::processor::unpack_amount, casting a pointer to a slice to an array pointer 10 | const fn unpack_amount(instruction_data: &[u8]) -> u64 { 11 | // expected u64 (8) 12 | assert!(instruction_data.len() >= 8); 13 | // SAFETY: The minimum size of the instruction data is 8 bytes. 14 | unsafe { 15 | u64::from_le_bytes( // the `from_le_bytes` introduces `transmute` (not supported yet) 16 | *(instruction_data.as_ptr() as *const [u8; 8]) 17 | ) 18 | } 19 | } 20 | 21 | fn test_unpack_success(value: u64) { 22 | let bytes: &[u8] = &value.to_le_bytes()[..]; // another `transmute`` 23 | let result = unpack_amount(bytes); 24 | assert!(result == value); 25 | } 26 | 27 | // simple array program performing similar casts as the above 28 | fn slice_to_array_data(data: &[u8]) -> [u8; 8] { 29 | assert!(data.len() >= 8); 30 | unsafe { *(data.as_ptr() as *const [u8;8]) } 31 | } 32 | 33 | fn test(i: u8) -> u8 { 34 | let array = [i; 42]; 35 | let result = slice_to_array_data(&array); 36 | result[7] 37 | } -------------------------------------------------------------------------------- /nix/kmir-pyk/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | callPackage, 4 | 5 | pyproject-nix, 6 | pyproject-build-systems, 7 | kmir-pyk-pyproject, 8 | pyproject-overlays ? [ ], 9 | 10 | python, 11 | }: 12 | let 13 | inherit (kmir-pyk-pyproject) lockFileOverlay workspace; 14 | 15 | pyproject-util = callPackage pyproject-nix.build.util { }; 16 | pyproject-packages = callPackage pyproject-nix.build.packages { inherit python; }; 17 | 18 | buildSystemsOverlay = import ./build-systems-overlay.nix; 19 | 20 | # construct package set 21 | pythonSet = pyproject-packages.overrideScope ( 22 | lib.composeManyExtensions ( 23 | [ 24 | # make build tools available by default as these are not necessarily specified in python lock files 25 | pyproject-build-systems.overlays.default 26 | # include all packages from the python lock file 27 | lockFileOverlay 28 | # add build system overrides to certain python packages 29 | buildSystemsOverlay 30 | ] 31 | ++ pyproject-overlays 32 | ) 33 | ); 34 | in 35 | pyproject-util.mkApplication { 36 | # default dependancy group enables no optional dependencies and no dependency-groups 37 | venv = pythonSet.mkVirtualEnv "kmir-pyk-env" workspace.deps.default; 38 | package = pythonSet.kmir; 39 | } 40 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/single-dylib/small_test_dylib::add.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ 5 | │ (35 steps) 6 | ├─ 3 (split) 7 | │ #expect ( BoolVal ( notBool ARG_UINT1:Int +Int ARG_UINT2:Int &Int 18446744073709 8 | ┃ 9 | ┃ (branch) 10 | ┣━━┓ subst: .Subst 11 | ┃ ┃ constraint: 12 | ┃ ┃ notBool notBool ARG_UINT1:Int +Int ARG_UINT2:Int &Int 18446744073709551615 ==Int ARG_UINT1:Int +Int ARG_UINT2:Int ==Bool false 13 | ┃ │ 14 | ┃ ├─ 4 15 | ┃ │ #expect ( BoolVal ( notBool ARG_UINT1:Int +Int ARG_UINT2:Int &Int 18446744073709 16 | ┃ │ 17 | ┃ │ (2 steps) 18 | ┃ └─ 6 (stuck, leaf) 19 | ┃ #ProgramError ( AssertError ( assertMessageOverflow ( binOpAdd , operandCopy ( p 20 | ┃ 21 | ┗━━┓ subst: .Subst 22 | ┃ constraint: 23 | ┃ notBool ARG_UINT1:Int +Int ARG_UINT2:Int &Int 18446744073709551615 ==Int ARG_UINT1:Int +Int ARG_UINT2:Int ==Bool false 24 | │ 25 | ├─ 5 26 | │ #expect ( BoolVal ( notBool ARG_UINT1:Int +Int ARG_UINT2:Int &Int 18446744073709 27 | │ 28 | │ (16 steps) 29 | ├─ 7 (terminal) 30 | │ #EndProgram ~> .K 31 | │ 32 | ┊ constraint: true 33 | ┊ subst: ... 34 | └─ 2 (leaf, target, terminal) 35 | #EndProgram ~> .K 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/crate-tests/single-bin/single_exe::a_module::twice.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ 5 | │ (44 steps) 6 | ├─ 3 (split) 7 | │ #expect ( BoolVal ( notBool ARG_UINT1:Int +Int ARG_UINT1:Int &Int 18446744073709 8 | ┃ 9 | ┃ (branch) 10 | ┣━━┓ subst: .Subst 11 | ┃ ┃ constraint: 12 | ┃ ┃ notBool notBool ARG_UINT1:Int +Int ARG_UINT1:Int &Int 18446744073709551615 ==Int ARG_UINT1:Int +Int ARG_UINT1:Int ==Bool false 13 | ┃ │ 14 | ┃ ├─ 4 15 | ┃ │ #expect ( BoolVal ( notBool ARG_UINT1:Int +Int ARG_UINT1:Int &Int 18446744073709 16 | ┃ │ 17 | ┃ │ (2 steps) 18 | ┃ └─ 6 (stuck, leaf) 19 | ┃ #ProgramError ( AssertError ( assertMessageOverflow ( binOpAdd , operandCopy ( p 20 | ┃ 21 | ┗━━┓ subst: .Subst 22 | ┃ constraint: 23 | ┃ notBool ARG_UINT1:Int +Int ARG_UINT1:Int &Int 18446744073709551615 ==Int ARG_UINT1:Int +Int ARG_UINT1:Int ==Bool false 24 | │ 25 | ├─ 5 26 | │ #expect ( BoolVal ( notBool ARG_UINT1:Int +Int ARG_UINT1:Int &Int 18446744073709 27 | │ 28 | │ (21 steps) 29 | ├─ 7 (terminal) 30 | │ #EndProgram ~> .K 31 | │ 32 | ┊ constraint: true 33 | ┊ subst: ... 34 | └─ 2 (leaf, target, terminal) 35 | #EndProgram ~> .K 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /kmir/src/kmir/kdist/mir-semantics/target.md: -------------------------------------------------------------------------------- 1 | ```k 2 | requires "ty.md" 3 | 4 | module TARGET 5 | imports INT 6 | imports TYPES 7 | 8 | syntax MachineInfo ::= machineInfo(endian: Endian, pointerWidth: MachineSize) [group(mir---endian--pointer-width)] 9 | syntax Endian ::= "endianLittle" [group(mir-enum), symbol(Endian::Little)] 10 | | "endianBig" [group(mir-enum), symbol(Endian::Big)] 11 | 12 | endmodule 13 | ``` 14 | 15 | ### Index 16 | 17 | #### Internal MIR 18 | - MachineInfo - not present 19 | - [Endian](https://github.com/runtimeverification/rust/blob/85f90a461262f7ca37a6e629933d455fa9c3ee48/compiler/rustc_abi/src/lib.rs#L387-L392) 20 | 21 | #### SMIR (Bridge) 22 | - [MachineInfo](https://github.com/runtimeverification/rust/blob/9131ddf5faba14fab225a7bf8ef5ee5dafe12e3b/compiler/rustc_smir/src/rustc_smir/context.rs#L39-L48) 23 | - [Endian](https://github.com/runtimeverification/rust/blob/9131ddf5faba14fab225a7bf8ef5ee5dafe12e3b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs#L24-L33) 24 | 25 | #### Stable MIR 26 | - [MachineInfo](https://github.com/runtimeverification/rust/blob/9131ddf5faba14fab225a7bf8ef5ee5dafe12e3b/compiler/stable_mir/src/target.rs#L6-L11) 27 | - [Endian](https://github.com/runtimeverification/rust/blob/9131ddf5faba14fab225a7bf8ef5ee5dafe12e3b/compiler/stable_mir/src/target.rs#L27-L31) 28 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/transmute-bytes.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::transmute_bytes_to_bytes)] 2 | #![allow(clippy::unnecessary_transmute)] 3 | 4 | use std::mem::transmute; 5 | 6 | fn bytes_to_u64(bytes: [u8; 8]) -> u64 { 7 | let value = unsafe { transmute::<[u8; 8], u64>(bytes) }; 8 | // prevent round-trip-transmute rule from simplifying this 9 | let enlarged = value as u128; 10 | let original = enlarged as u64; 11 | let roundtrip = unsafe { transmute::(original) }; 12 | assert_eq!(roundtrip, bytes); 13 | value 14 | } 15 | 16 | fn u64_to_bytes(value: u64) -> [u8; 8] { 17 | let mut bytes = unsafe { transmute::(value) }; 18 | let first = bytes[0]; 19 | bytes[0] = 255u8; 20 | bytes[0] = first; 21 | let roundtrip = unsafe { transmute::<[u8; 8], u64>(bytes) }; 22 | assert_eq!(roundtrip, value); 23 | bytes 24 | } 25 | 26 | fn main() { 27 | let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF]; 28 | let int = bytes_to_u64(bytes); 29 | assert_eq!(int, 0xEFCD_AB89_6745_2301); 30 | 31 | let roundtrip = u64_to_bytes(int); 32 | assert_eq!(roundtrip, bytes); 33 | 34 | let value = 0x1020_3040_5060_7080_u64; 35 | let value_roundtrip = bytes_to_u64(u64_to_bytes(value)); 36 | assert_eq!(value_roundtrip, value); 37 | } 38 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/test_functions.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import json 4 | from pathlib import Path 5 | from typing import TYPE_CHECKING 6 | 7 | import pytest 8 | 9 | from kmir.kompile import _functions 10 | from kmir.smir import SMIRInfo 11 | from kmir.testing.fixtures import assert_or_update_show_output 12 | 13 | if TYPE_CHECKING: 14 | from kmir.kmir import KMIR 15 | 16 | # Test data for intrinsic blackbox test 17 | EXEC_DATA_DIR = (Path(__file__).parent / 'data' / 'exec-smir').resolve(strict=True) 18 | INTRINSIC_SMIR_FILE = EXEC_DATA_DIR / 'intrinsic' / 'blackbox.smir.json' 19 | 20 | 21 | @pytest.mark.parametrize('smir_file', [INTRINSIC_SMIR_FILE], ids=['intrinsic_blackbox']) 22 | def test_functions(smir_file: Path, kmir: KMIR, update_expected_output: bool) -> None: 23 | """Test _make_function_map using actual SMIR JSON data.""" 24 | # Given 25 | smir_info = SMIRInfo.from_file(smir_file) 26 | # When 27 | result = _functions(kmir, smir_info) 28 | result_dict = {ty: body.to_dict() for ty, body in result.items()} 29 | # Then 30 | result_str = json.dumps(result_dict, indent=2, sort_keys=True) 31 | expected_file = smir_file.parent / 'blackbox_functions.expected.json' 32 | assert_or_update_show_output(result_str, expected_file, update=update_expected_output) 33 | -------------------------------------------------------------------------------- /kmir/src/kmir/kdist/mir-semantics/kmir-ast.md: -------------------------------------------------------------------------------- 1 | ```k 2 | requires "abi.md" 3 | requires "alloc.md" 4 | requires "body.md" 5 | requires "lib.md" 6 | requires "mono.md" 7 | requires "target.md" 8 | requires "ty.md" 9 | 10 | module KMIR-AST 11 | imports ABI 12 | imports ALLOC 13 | imports BODY 14 | imports LIB 15 | imports MONO 16 | imports TARGET 17 | imports TYPES 18 | 19 | 20 | syntax Pgm ::= Symbol GlobalAllocs FunctionNames MonoItems TypeMappings MachineInfo 21 | [symbol(pgm), group(mir---name--allocs--functions--items--types--machine)] 22 | 23 | syntax FunctionKind ::= functionNormalSym(Symbol) [symbol(FunctionKind::NormalSym), group(mir-enum)] 24 | | functionIntrinsic(Symbol) [symbol(FunctionKind::IntrinsicSym), group(mir-enum)] 25 | | functionNoop(Symbol) [symbol(FunctionKind::NoOpSym), group(mir-enum)] 26 | 27 | syntax FunctionName ::= functionName(Ty, FunctionKind) 28 | [symbol(functionName), group(mir)] 29 | 30 | syntax FunctionNames ::= List [group(mir-klist-FunctionName)] 31 | 32 | syntax TypeMapping ::= TypeMapping( Ty, TypeInfo ) [group(mir)] 33 | 34 | syntax TypeMappings ::= List{TypeMapping, ""} [group(mir-list), symbol(TypeMappings::append), terminator-symbol(TypeMappings::empty)] 35 | 36 | endmodule 37 | ``` 38 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/struct-simple-permuted-fields.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [ 3 | 1, 4 | 15, 5 | 31 6 | ], 7 | "types": [ 8 | [ 9 | 0, 10 | { 11 | "PrimitiveType": { 12 | "Uint": "U8" 13 | } 14 | } 15 | ], 16 | [ 17 | 1, 18 | { 19 | "PrimitiveType": "Bool" 20 | } 21 | ] 22 | ], 23 | "typeInfo": { 24 | "StructType": { 25 | "name": "core::ops::RangeInclusive", 26 | "adt_def": 100, 27 | "fields": [ 28 | 0, 29 | 0, 30 | 1 31 | ], 32 | "layout": { 33 | "fields": { 34 | "Arbitrary": { 35 | "offsets": [ 36 | { 37 | "num_bits": 8 38 | }, 39 | { 40 | "num_bits": 16 41 | }, 42 | { 43 | "num_bits": 0 44 | } 45 | ] 46 | } 47 | }, 48 | "variants": { 49 | "Single": { 50 | "index": 0 51 | } 52 | }, 53 | "abi": { 54 | "Aggregate": { 55 | "sized": true 56 | } 57 | }, 58 | "abi_align": 1, 59 | "size": { 60 | "num_bits": 24 61 | } 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /nix/kmir/default.nix: -------------------------------------------------------------------------------- 1 | { 2 | lib, 3 | stdenv, 4 | runCommand, 5 | makeWrapper, 6 | callPackage, 7 | 8 | k, 9 | which, 10 | stable-mir-json, 11 | stable-mir-json-rust, 12 | 13 | kmir-pyk, 14 | rev ? null, 15 | kmir-rust ? null, 16 | }@args: 17 | 18 | stdenv.mkDerivation { 19 | pname = "kmir"; 20 | version = if (rev != null) then rev else "dirty"; 21 | nativeBuildInputs = [ 22 | k 23 | kmir-pyk 24 | makeWrapper 25 | ]; 26 | 27 | src = callPackage ../kmir-source { }; 28 | 29 | dontUseCmakeConfigure = true; 30 | 31 | enableParallelBuilding = true; 32 | 33 | buildPhase = '' 34 | export XDG_CACHE_HOME=$(pwd) 35 | kmir-kdist -v build -j4 36 | ''; 37 | 38 | installPhase = '' 39 | mkdir -p $out 40 | cp -r ./kdist-*/* $out/ 41 | mkdir -p $out/bin 42 | makeWrapper ${kmir-pyk}/bin/kmir $out/bin/kmir --prefix PATH : ${ 43 | lib.makeBinPath ( 44 | [ 45 | which 46 | k 47 | stable-mir-json 48 | ] 49 | ++ lib.optionals (kmir-rust != null) [ kmir-rust ] 50 | ) 51 | } --set KDIST_DIR $out 52 | ''; 53 | 54 | passthru = 55 | if kmir-rust == null then 56 | { 57 | # list all supported solc versions here 58 | rust = callPackage ./default.nix (args // { kmir-rust = stable-mir-json-rust; }); 59 | } 60 | else 61 | { }; 62 | } 63 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/tuple-i16-bool-u8.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [ 3 | 52, 4 | 18, 5 | 1, 6 | 254 7 | ], 8 | "types": [ 9 | [ 10 | 0, 11 | { 12 | "PrimitiveType": { 13 | "Uint": "U8" 14 | } 15 | } 16 | ], 17 | [ 18 | 1, 19 | { 20 | "PrimitiveType": "Bool" 21 | } 22 | ], 23 | [ 24 | 2, 25 | { 26 | "PrimitiveType": { 27 | "Int": "I16" 28 | } 29 | } 30 | ] 31 | ], 32 | "typeInfo": { 33 | "TupleType": { 34 | "types": [ 35 | 2, 36 | 1, 37 | 0 38 | ], 39 | "layout": { 40 | "fields": { 41 | "Arbitrary": { 42 | "offsets": [ 43 | { 44 | "num_bits": 0 45 | }, 46 | { 47 | "num_bits": 16 48 | }, 49 | { 50 | "num_bits": 24 51 | } 52 | ] 53 | } 54 | }, 55 | "variants": { 56 | "Single": { 57 | "index": 0 58 | } 59 | }, 60 | "abi": { 61 | "Aggregate": { 62 | "sized": true 63 | } 64 | }, 65 | "abi_align": 1, 66 | "size": { 67 | "num_bits": 32 68 | } 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/pointers/pointer-cast-length-test-fail.rs: -------------------------------------------------------------------------------- 1 | #![feature(ptr_metadata)] 2 | // example functions asserting lengths of pointer coercions and PtrToPtr casts 3 | 4 | fn main() { 5 | let a = [42; 8]; 6 | array_cast_test(&a); 7 | } 8 | 9 | fn array_cast_test(arr: &[u8]) { 10 | assert!(arr.len() >= 4); 11 | 12 | let arr4 = unsafe { *(arr.as_ptr() as *const [u8; 4]) }; 13 | assert!(arr4.len() == 4); 14 | // println!("Slice of length {l0} converted to array {arr4:?}"); 15 | 16 | let arr4_mut = arr.as_ptr() as *mut [u8; 4]; 17 | unsafe {(*arr4_mut)[1] = 41}; 18 | let l4 = unsafe { (*arr4_mut).len() }; 19 | 20 | assert!(l4 == 4); 21 | // println!("Mutated array {arr:?} through {arr4_mut:?} with length {l4}"); 22 | 23 | let s4 = &arr4 as &[u8]; 24 | let arr9 = unsafe { *(s4.as_ptr() as *const [u8; 9]) }; // this is undefined behaviour 25 | assert!(arr9.len() == 9); 26 | // println!("Produced array of length 9: {arr9:?}"); 27 | 28 | // println!("Arrays and addresses:"); 29 | // println!("{:?}: {:?}, length {}", arr.as_ptr(), arr, arr.len()); 30 | // println!("{:?}: {:?}, length {}", arr4.as_ptr(), arr4, arr4.len()); 31 | // println!("{:?}: {:?}, length {}", arr4_mut, unsafe { *arr4_mut }, unsafe { *arr4_mut }.len()); 32 | // println!("{:?}: {:?}, length {}", arr9.as_ptr(), arr9, arr9.len()); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /.github/workflows/p-token-release.yml: -------------------------------------------------------------------------------- 1 | name: "Release P-Token KMIR" 2 | 3 | on: 4 | push: 5 | branches: 6 | - feature/p-token 7 | 8 | jobs: 9 | release-docker: 10 | runs-on: [self-hosted, linux, normal] 11 | steps: 12 | - uses: actions/checkout@v4 13 | with: 14 | fetch-depth: 0 15 | submodules: recursive 16 | - name: 'Setup Docker Buildx' 17 | uses: docker/setup-buildx-action@v3.10.0 18 | 19 | - name: 'Login to Docker Hub' 20 | uses: docker/login-action@v3.4.0 21 | with: 22 | username: ${{ vars.DOCKERHUB_USERNAME }} 23 | password: ${{ secrets.DOCKERHUB_PASSWORD }} 24 | 25 | - name: Set Image Name 26 | id: set-image-name 27 | run: | 28 | echo "image-name=runtimeverificationinc/kmir" >> $GITHUB_OUTPUT 29 | echo "k-version=$(cat deps/k_release)" >> $GITHUB_OUTPUT 30 | echo "short-sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT 31 | 32 | - name: Build Kmir Container 33 | uses: docker/build-push-action@v6 34 | with: 35 | context: . 36 | file: Dockerfile.kmir 37 | platforms: linux/amd64 38 | push: true 39 | build-args: | 40 | K_VERSION=${{ steps.set-image-name.outputs.k-version }} 41 | tags: ${{ steps.set-image-name.outputs.image-name }}:p-token-${{ steps.set-image-name.outputs.short-sha }} 42 | 43 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/decode-value/enum-1-variant-1-field.json: -------------------------------------------------------------------------------- 1 | { 2 | "bytes": [ 3 | 255, 4 | 0, 5 | 0, 6 | 0 7 | ], 8 | "types": [ 9 | [ 10 | 3, 11 | { 12 | "PrimitiveType": { 13 | "Int": "I32" 14 | } 15 | } 16 | ] 17 | ], 18 | "typeInfo": { 19 | "EnumType": { 20 | "name": "Foo", 21 | "adt_def": 1, 22 | "discriminants": [ 23 | 0 24 | ], 25 | "fields": [ 26 | [ 27 | 3 28 | ] 29 | ], 30 | "layout": { 31 | "fields": { 32 | "Arbitrary": { 33 | "offsets": [ 34 | { 35 | "num_bits": 0 36 | } 37 | ] 38 | } 39 | }, 40 | "variants": { 41 | "Single": { 42 | "index": 0 43 | } 44 | }, 45 | "abi": { 46 | "Scalar": { 47 | "Initialized": { 48 | "value": { 49 | "Int": { 50 | "length": "I32", 51 | "signed": true 52 | } 53 | }, 54 | "valid_range": { 55 | "start": 0, 56 | "end": 4294967295 57 | } 58 | } 59 | } 60 | }, 61 | "abi_align": 4, 62 | "size": { 63 | "num_bits": 32 64 | } 65 | } 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/symbolic-args-fail.main.cli-stats-leaves.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ span: src/rust/library/std/src/rt.rs:194 5 | │ 6 | │ (566 steps) 7 | └─ 3 (stuck, leaf) 8 | #setUpCalleeData ( monoItemFn ( ... name: symbol ( "** UNKNOWN FUNCTION **" ) , 9 | span: no-location:0 10 | 11 | 12 | ┌─ 2 (root, leaf, target, terminal) 13 | │ #EndProgram ~> .K 14 | 15 | 16 | 17 | STATISTICS 18 | ----------- 19 | Total nodes: 1 20 | 21 | Node roles (exclusive): 22 | failing : 1 ids: 3 23 | (root nodes omitted from totals: 1, 2) 24 | 25 | Leaf paths from init: 26 | total leaves (non-root): 1 27 | reachable leaves : 1 28 | total steps : 566 29 | 30 | leaf 3: steps 566, path 1 -> 3 31 | 32 | LEAF CELLS 33 | --------------- 34 | Node 3: 35 | #setUpCalleeData ( monoItemFn ( ... name: symbol ( "** UNKNOWN FUNCTION **" ) , id: defId ( 38 ) , body: noBody ) , operandConstant ( constOperand ( ... span: span ( 32 ) , userTy: noUserTypeAnnotationIndex , const: mirConst ( ... kind: constantKindAllocated ( allocation ( ... bytes: b"\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x00\x00\x00\x00" , provenance: provenanceMap ( ... ptrs: provenanceMapEntry ( ... offset: 0 , allocId: allocId ( 1 ) ) .ProvenanceMapEntries ) , align: align ( 8 ) , mutability: mutabilityMut ) ) , ty: ty ( 39 ) , id: mirConstId ( 25 ) ) ) ) .Operands ) ~> .K -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/symbolic-args-fail.rs: -------------------------------------------------------------------------------- 1 | #[allow(dead_code)] 2 | struct MyStruct<'a>{ field: &'a MyEnum} 3 | 4 | #[allow(dead_code)] 5 | enum MyEnum { 6 | My1, 7 | My2(i8), 8 | } 9 | 10 | #[allow(dead_code)] 11 | #[allow(unused)] 12 | fn eats_all_args<'a>( 13 | x1: i32, 14 | x2: &mut u16, 15 | x3: bool, 16 | x4: MyStruct<'a>, 17 | x5: MyEnum, 18 | x6: &mut [u8], 19 | x7: &[i8; 3], 20 | x8: &mut [MyStruct<'a>; 2], 21 | x9: *const MyStruct<'a>, 22 | ) -> () { 23 | *x2 = x1 as u16; 24 | if x3 { 25 | x8[0] = x4; 26 | } 27 | else { 28 | x8[0] = unsafe { MyStruct{field: (*x9).field} }; 29 | } 30 | match x5 { 31 | _ => { 32 | if x6.len() > 0 33 | { x6[0] = x7[0] as u8; } 34 | } 35 | } 36 | } 37 | 38 | // we need a `main` function that calls eats_all_args 39 | fn main() { 40 | let e1 = MyEnum::My1; 41 | let e2 = MyEnum::My2(0); 42 | let e3 = MyEnum::My1; 43 | let e4 = MyEnum::My2(0); 44 | let mut x2 = 0; 45 | let my1 = MyStruct{field: &e1}; 46 | let my2 = MyStruct{field: &e2}; 47 | let my3 = MyStruct{field: &e3}; 48 | let my4 = MyStruct{field: &MyEnum::My1}; 49 | let mut a1 = [1, 2, 3]; 50 | let a2 = [1, 2, 3]; 51 | eats_all_args(1, &mut x2, true, my1, e4, &mut a1, &a2, &mut [my2, my3], &my4 as *const MyStruct<'_>); 52 | 53 | assert!(false); // makes the test with main fail, as the other one also fails 54 | } 55 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/main-a-b-c/main-a-b-c.run.state: -------------------------------------------------------------------------------- 1 | 2 | 3 | #EndProgram ~> .K 4 | 5 | 6 | noReturn 7 | 8 | 9 | ty ( -1 ) 10 | 11 | 12 | 13 | ListItem ( basicBlock (... statements: .Statements , terminator: terminator (... kind: terminatorKindCall (... func: operandConstant ( constOperand (... span: span ( 50 ) , userTy: noUserTypeAnnotationIndex , const: mirConst (... kind: constantKindZeroSized , ty: ty ( 25 ) , id: mirConstId ( 9 ) ) ) ) , args: .Operands , destination: place (... local: local ( 0 ) , projection: .ProjectionElems ) , target: someBasicBlockIdx ( basicBlockIdx ( 1 ) ) , unwind: unwindActionContinue ) , span: span ( 51 ) ) ) ) 14 | ListItem ( basicBlock (... statements: .Statements , terminator: terminator (... kind: terminatorKindReturn , span: span ( 52 ) ) ) ) 15 | 16 | 17 | ty ( -1 ) 18 | 19 | 20 | place (... local: local ( 0 ) , projection: .ProjectionElems ) 21 | 22 | 23 | noBasicBlockIdx 24 | 25 | 26 | unwindActionContinue 27 | 28 | 29 | ListItem ( newLocal ( ty ( 1 ) , mutabilityMut ) ) 30 | 31 | 32 | 33 | ListItem ( StackFrame ( ty ( -1 ) , place (... local: local ( -1 ) , projection: .ProjectionElems ) , noBasicBlockIdx , unwindActionUnreachable , .List ) ) 34 | 35 | -------------------------------------------------------------------------------- /kmir/src/tests/unit/test_unit.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from typing import TYPE_CHECKING 4 | 5 | import pytest 6 | 7 | from kmir.smir import compute_closure 8 | 9 | if TYPE_CHECKING: 10 | from kmir.smir import Ty 11 | 12 | # fmt: off 13 | GRAPH_CLOSURE_TESTS = [ 14 | ( 15 | 'Simple Directed Graph', 16 | 0, 17 | {0: [1], 1: [2], 2: [3]}, 18 | {0, 1, 2, 3} 19 | ), 20 | ( 21 | 'Graph with a Cycle', 22 | 0, 23 | {0: [1], 1: [2], 2: [0, 3], 3: [4]}, 24 | {0, 1, 2, 3, 4} 25 | ), 26 | ( 27 | 'Disconnected Node', 28 | 0, 29 | {0: [1, 2], 1: [3], 2: [], 3: [], 4: [0]}, 30 | {0, 1, 2, 3} 31 | ), 32 | ( 33 | 'Start Node with No Outgoing Edges', 34 | 0, 35 | {0: [], 1: [0, 2], 2: [1]}, 36 | {0} 37 | ), 38 | ( 39 | 'Multiple Paths to a Node', 40 | 0, 41 | {0: [1, 2], 1: [3], 2: [3], 3: [4]}, 42 | {0, 1, 2, 3, 4} 43 | ), 44 | ( 45 | 'Self-loop in a node', 46 | 0, 47 | {0: [0, 1], 1: [2]}, 48 | {0, 1, 2} 49 | ), 50 | ] 51 | # fmt: on 52 | 53 | 54 | @pytest.mark.parametrize( 55 | 'test_case', 56 | GRAPH_CLOSURE_TESTS, 57 | ids=[name for name, _, _, _ in GRAPH_CLOSURE_TESTS], 58 | ) 59 | def test_compute_closure(test_case: tuple[str, Ty, dict[Ty, set[Ty]], list[Ty]]) -> None: 60 | _, start, edges, expected = test_case 61 | 62 | result = compute_closure(start, edges) 63 | assert result == expected 64 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/test_offset_from-fail.rs: -------------------------------------------------------------------------------- 1 | #![feature(core_intrinsics)] 2 | use std::intrinsics::ptr_offset_from_unsigned; // core::ptr variant since 1.87.0, not for us 3 | 4 | fn testing(mode: isize) { 5 | let a = [1, 2, 3, 4, 5]; 6 | let b = [6, 7, 8, 9, 10]; 7 | let a_p = &a as *const i32; 8 | let b_p = &b as *const i32; 9 | let a1: *const i32 = &a[1]; 10 | let a3: *const i32 = &a[3]; 11 | let b1: *const i32 = &b[1]; 12 | 13 | match mode { 14 | 0 => unsafe { // correct and expected operation on pointers with offset 15 | let a1_p = a_p.add(1); 16 | assert_eq!(a1_p.offset_from(a_p), 1); 17 | assert_eq!(a_p.offset_from(a1_p), -1); 18 | assert_eq!(ptr_offset_from_unsigned(a1_p, a_p), 1); 19 | }, 20 | 1 => unsafe { // correct and expected operation on addresses within arrays 21 | assert_eq!(a3.offset_from(a1), 2); 22 | assert_eq!(a1.offset_from(a3), -2); 23 | }, 24 | 2 => unsafe { // different allocation 25 | assert_eq!(a1.offset_from(b1), 0xdeadbeef); // UB 26 | }, 27 | 3 => unsafe { 28 | // violating assumption of a3 > a1 29 | assert_eq!(ptr_offset_from_unsigned(a1, a3), 0xdeadbeef); // UB 30 | }, 31 | 4 => unsafe { 32 | let unit_p: *const () = &(); 33 | assert_eq!(unit_p.offset_from(unit_p), 0xdeadbeef); // panics 34 | }, 35 | _ => () 36 | } 37 | } 38 | 39 | 40 | fn main() { 41 | testing(0); 42 | testing(4); 43 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2023 - 2025, Runtime Verification Inc. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | 8 | 1. Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | 2. Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | 3. Neither the name of the copyright holder nor the names of its 16 | contributors may be used to endorse or promote products derived from 17 | this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /kmir/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["hatchling"] 3 | build-backend = "hatchling.build" 4 | 5 | [project] 6 | name = "kmir" 7 | version = "0.3.181" 8 | description = "" 9 | requires-python = ">=3.10" 10 | dependencies = [ 11 | "kframework==v7.1.304", 12 | "rust-demangler==1.0", 13 | ] 14 | 15 | [[project.authors]] 16 | name = "Runtime Verification, Inc." 17 | email = "contact@runtimeverification.com" 18 | 19 | [project.scripts] 20 | parse = "kmir.parse.__main__:main" 21 | kmir = "kmir.__main__:main" 22 | kmir-kdist = "pyk.kdist.__main__:main" 23 | 24 | [project.entry-points.kdist] 25 | mir-semantics = "kmir.kdist.plugin" 26 | 27 | [project.entry-points.pytest11] 28 | pytest-kmir = "kmir.testing.fixtures" 29 | 30 | [dependency-groups] 31 | dev = [ 32 | "autoflake", 33 | "black", 34 | "flake8", 35 | "flake8-bugbear", 36 | "flake8-comprehensions", 37 | "flake8-quotes", 38 | "flake8-type-checking", 39 | "isort", 40 | "mypy", 41 | "pep8-naming", 42 | "pytest", 43 | "pytest-cov", 44 | "pytest-mock", 45 | "pytest-xdist", 46 | "pyupgrade", 47 | ] 48 | 49 | [tool.hatch.metadata] 50 | allow-direct-references = true 51 | 52 | [tool.isort] 53 | profile = "black" 54 | line_length = 120 55 | 56 | [tool.autoflake] 57 | recursive = true 58 | expand-star-imports = true 59 | remove-all-unused-imports = true 60 | ignore-init-module-imports = true 61 | remove-duplicate-keys = true 62 | remove-unused-variables = true 63 | 64 | [tool.black] 65 | line-length = 120 66 | skip-string-normalization = true 67 | 68 | [tool.mypy] 69 | disallow_untyped_defs = true 70 | -------------------------------------------------------------------------------- /.github/actions/with-docker/action.yml: -------------------------------------------------------------------------------- 1 | name: 'With Docker' 2 | description: 'Run a given stage with Docker Image' 3 | inputs: 4 | container-name: 5 | description: 'Docker container name to use' 6 | required: true 7 | runs: 8 | using: 'composite' 9 | steps: 10 | - name: 'Set up Docker' 11 | shell: bash {0} 12 | env: 13 | CONTAINER_NAME: ${{ inputs.container-name }} 14 | run: | 15 | set -euxo pipefail 16 | 17 | TAG=runtimeverificationinc/${CONTAINER_NAME} 18 | K_COMMIT=$(grep -Po '[0-9.]+' ./deps/k_release) 19 | UV_VERSION=$(cat deps/uv_release) 20 | 21 | USER=github-user 22 | GROUP=${USER} 23 | USER_ID=1000 24 | GROUP_ID=${USER_ID} 25 | 26 | docker build . --tag ${TAG} \ 27 | --file .github/workflows/Dockerfile \ 28 | --build-arg K_COMMIT=${K_COMMIT} \ 29 | --build-arg USER=${USER} \ 30 | --build-arg GROUP=${GROUP} \ 31 | --build-arg USER_ID=${USER_ID} \ 32 | --build-arg GROUP_ID=${GROUP_ID} \ 33 | --build-arg UV_VERSION=${UV_VERSION} 34 | 35 | docker run \ 36 | --name ${CONTAINER_NAME} \ 37 | --rm \ 38 | --interactive \ 39 | --tty \ 40 | --detach \ 41 | --workdir /home/${USER}/workspace \ 42 | ${TAG} 43 | 44 | docker cp . ${CONTAINER_NAME}:/home/${USER}/workspace 45 | docker exec --user root ${CONTAINER_NAME} chown -R ${USER}:${GROUP} /home/${USER}/workspace 46 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-smir-random/simple-types/init-0.expected: -------------------------------------------------------------------------------- 1 | 2 | 3 | srandInt ( 0 ) ~> #execTerminator ( terminator (... kind: terminatorKindCall (... func: operandConstant ( constOperand (... span: span ( 0 ) , userTy: noUserTypeAnnotationIndex , const: mirConst (... kind: constantKindZeroSized , ty: ty ( -4 ) , id: mirConstId ( 0 ) ) ) ) , args: operandCopy ( place (... local: local ( 1 ) , projection: .ProjectionElems ) ) operandCopy ( place (... local: local ( 2 ) , projection: .ProjectionElems ) ) operandCopy ( place (... local: local ( 3 ) , projection: .ProjectionElems ) ) .Operands , destination: place (... local: local ( 0 ) , projection: .ProjectionElems ) , target: noBasicBlockIdx , unwind: unwindActionContinue ) , span: span ( 0 ) ) ) ~> .K 4 | 5 | 6 | noReturn 7 | 8 | 9 | ty ( -1 ) 10 | 11 | 12 | 13 | .List 14 | 15 | 16 | ty ( -1 ) 17 | 18 | 19 | place (... local: local ( -1 ) , projection: .ProjectionElems ) 20 | 21 | 22 | noBasicBlockIdx 23 | 24 | 25 | unwindActionUnreachable 26 | 27 | 28 | ListItem ( newLocal ( ty ( 0 ) , mutabilityNot ) ) 29 | ListItem ( typedValue ( BoolVal ( true ) , ty ( 18 ) , mutabilityNot ) ) 30 | ListItem ( typedValue ( Integer ( 197 , 8 , false ) , ty ( 9 ) , mutabilityNot ) ) 31 | ListItem ( typedValue ( Integer ( -341142443 , 32 , true ) , ty ( 8 ) , mutabilityNot ) ) 32 | 33 | 34 | 35 | .List 36 | 37 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-smir-random/simple-types/init-2.expected: -------------------------------------------------------------------------------- 1 | 2 | 3 | srandInt ( 2 ) ~> #execTerminator ( terminator (... kind: terminatorKindCall (... func: operandConstant ( constOperand (... span: span ( 0 ) , userTy: noUserTypeAnnotationIndex , const: mirConst (... kind: constantKindZeroSized , ty: ty ( -4 ) , id: mirConstId ( 0 ) ) ) ) , args: operandCopy ( place (... local: local ( 1 ) , projection: .ProjectionElems ) ) operandCopy ( place (... local: local ( 2 ) , projection: .ProjectionElems ) ) operandCopy ( place (... local: local ( 3 ) , projection: .ProjectionElems ) ) .Operands , destination: place (... local: local ( 0 ) , projection: .ProjectionElems ) , target: noBasicBlockIdx , unwind: unwindActionContinue ) , span: span ( 0 ) ) ) ~> .K 4 | 5 | 6 | noReturn 7 | 8 | 9 | ty ( -1 ) 10 | 11 | 12 | 13 | .List 14 | 15 | 16 | ty ( -1 ) 17 | 18 | 19 | place (... local: local ( -1 ) , projection: .ProjectionElems ) 20 | 21 | 22 | noBasicBlockIdx 23 | 24 | 25 | unwindActionUnreachable 26 | 27 | 28 | ListItem ( newLocal ( ty ( 0 ) , mutabilityNot ) ) 29 | ListItem ( typedValue ( BoolVal ( true ) , ty ( 18 ) , mutabilityNot ) ) 30 | ListItem ( typedValue ( Integer ( 28 , 8 , false ) , ty ( 9 ) , mutabilityNot ) ) 31 | ListItem ( typedValue ( Integer ( -1754129965 , 32 , true ) , ty ( 8 ) , mutabilityNot ) ) 32 | 33 | 34 | 35 | .List 36 | 37 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-smir-random/simple-types/init-3.expected: -------------------------------------------------------------------------------- 1 | 2 | 3 | srandInt ( 3 ) ~> #execTerminator ( terminator (... kind: terminatorKindCall (... func: operandConstant ( constOperand (... span: span ( 0 ) , userTy: noUserTypeAnnotationIndex , const: mirConst (... kind: constantKindZeroSized , ty: ty ( -4 ) , id: mirConstId ( 0 ) ) ) ) , args: operandCopy ( place (... local: local ( 1 ) , projection: .ProjectionElems ) ) operandCopy ( place (... local: local ( 2 ) , projection: .ProjectionElems ) ) operandCopy ( place (... local: local ( 3 ) , projection: .ProjectionElems ) ) .Operands , destination: place (... local: local ( 0 ) , projection: .ProjectionElems ) , target: noBasicBlockIdx , unwind: unwindActionContinue ) , span: span ( 0 ) ) ) ~> .K 4 | 5 | 6 | noReturn 7 | 8 | 9 | ty ( -1 ) 10 | 11 | 12 | 13 | .List 14 | 15 | 16 | ty ( -1 ) 17 | 18 | 19 | place (... local: local ( -1 ) , projection: .ProjectionElems ) 20 | 21 | 22 | noBasicBlockIdx 23 | 24 | 25 | unwindActionUnreachable 26 | 27 | 28 | ListItem ( newLocal ( ty ( 0 ) , mutabilityNot ) ) 29 | ListItem ( typedValue ( BoolVal ( false ) , ty ( 18 ) , mutabilityNot ) ) 30 | ListItem ( typedValue ( Integer ( 66 , 8 , false ) , ty ( 9 ) , mutabilityNot ) ) 31 | ListItem ( typedValue ( Integer ( 446333181 , 32 , true ) , ty ( 8 ) , mutabilityNot ) ) 32 | 33 | 34 | 35 | .List 36 | 37 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-smir-random/simple-types/init-5.expected: -------------------------------------------------------------------------------- 1 | 2 | 3 | srandInt ( 5 ) ~> #execTerminator ( terminator (... kind: terminatorKindCall (... func: operandConstant ( constOperand (... span: span ( 0 ) , userTy: noUserTypeAnnotationIndex , const: mirConst (... kind: constantKindZeroSized , ty: ty ( -4 ) , id: mirConstId ( 0 ) ) ) ) , args: operandCopy ( place (... local: local ( 1 ) , projection: .ProjectionElems ) ) operandCopy ( place (... local: local ( 2 ) , projection: .ProjectionElems ) ) operandCopy ( place (... local: local ( 3 ) , projection: .ProjectionElems ) ) .Operands , destination: place (... local: local ( 0 ) , projection: .ProjectionElems ) , target: noBasicBlockIdx , unwind: unwindActionContinue ) , span: span ( 0 ) ) ) ~> .K 4 | 5 | 6 | noReturn 7 | 8 | 9 | ty ( -1 ) 10 | 11 | 12 | 13 | .List 14 | 15 | 16 | ty ( -1 ) 17 | 18 | 19 | place (... local: local ( -1 ) , projection: .ProjectionElems ) 20 | 21 | 22 | noBasicBlockIdx 23 | 24 | 25 | unwindActionUnreachable 26 | 27 | 28 | ListItem ( newLocal ( ty ( 0 ) , mutabilityNot ) ) 29 | ListItem ( typedValue ( BoolVal ( true ) , ty ( 18 ) , mutabilityNot ) ) 30 | ListItem ( typedValue ( Integer ( 130 , 8 , false ) , ty ( 9 ) , mutabilityNot ) ) 31 | ListItem ( typedValue ( Integer ( 1038467225 , 32 , true ) , ty ( 8 ) , mutabilityNot ) ) 32 | 33 | 34 | 35 | .List 36 | 37 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-smir-random/simple-types/init-6.expected: -------------------------------------------------------------------------------- 1 | 2 | 3 | srandInt ( 6 ) ~> #execTerminator ( terminator (... kind: terminatorKindCall (... func: operandConstant ( constOperand (... span: span ( 0 ) , userTy: noUserTypeAnnotationIndex , const: mirConst (... kind: constantKindZeroSized , ty: ty ( -4 ) , id: mirConstId ( 0 ) ) ) ) , args: operandCopy ( place (... local: local ( 1 ) , projection: .ProjectionElems ) ) operandCopy ( place (... local: local ( 2 ) , projection: .ProjectionElems ) ) operandCopy ( place (... local: local ( 3 ) , projection: .ProjectionElems ) ) .Operands , destination: place (... local: local ( 0 ) , projection: .ProjectionElems ) , target: noBasicBlockIdx , unwind: unwindActionContinue ) , span: span ( 0 ) ) ) ~> .K 4 | 5 | 6 | noReturn 7 | 8 | 9 | ty ( -1 ) 10 | 11 | 12 | 13 | .List 14 | 15 | 16 | ty ( -1 ) 17 | 18 | 19 | place (... local: local ( -1 ) , projection: .ProjectionElems ) 20 | 21 | 22 | noBasicBlockIdx 23 | 24 | 25 | unwindActionUnreachable 26 | 27 | 28 | ListItem ( newLocal ( ty ( 0 ) , mutabilityNot ) ) 29 | ListItem ( typedValue ( BoolVal ( true ) , ty ( 18 ) , mutabilityNot ) ) 30 | ListItem ( typedValue ( Integer ( 41 , 8 , false ) , ty ( 9 ) , mutabilityNot ) ) 31 | ListItem ( typedValue ( Integer ( -1023827911 , 32 , true ) , ty ( 8 ) , mutabilityNot ) ) 32 | 33 | 34 | 35 | .List 36 | 37 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-smir-random/simple-types/init-1.expected: -------------------------------------------------------------------------------- 1 | 2 | 3 | srandInt ( 1 ) ~> #execTerminator ( terminator (... kind: terminatorKindCall (... func: operandConstant ( constOperand (... span: span ( 0 ) , userTy: noUserTypeAnnotationIndex , const: mirConst (... kind: constantKindZeroSized , ty: ty ( -4 ) , id: mirConstId ( 0 ) ) ) ) , args: operandCopy ( place (... local: local ( 1 ) , projection: .ProjectionElems ) ) operandCopy ( place (... local: local ( 2 ) , projection: .ProjectionElems ) ) operandCopy ( place (... local: local ( 3 ) , projection: .ProjectionElems ) ) .Operands , destination: place (... local: local ( 0 ) , projection: .ProjectionElems ) , target: noBasicBlockIdx , unwind: unwindActionContinue ) , span: span ( 0 ) ) ) ~> .K 4 | 5 | 6 | noReturn 7 | 8 | 9 | ty ( -1 ) 10 | 11 | 12 | 13 | .List 14 | 15 | 16 | ty ( -1 ) 17 | 18 | 19 | place (... local: local ( -1 ) , projection: .ProjectionElems ) 20 | 21 | 22 | noBasicBlockIdx 23 | 24 | 25 | unwindActionUnreachable 26 | 27 | 28 | ListItem ( newLocal ( ty ( 0 ) , mutabilityNot ) ) 29 | ListItem ( typedValue ( BoolVal ( false ) , ty ( 18 ) , mutabilityNot ) ) 30 | ListItem ( typedValue ( Integer ( 32 , 8 , false ) , ty ( 9 ) , mutabilityNot ) ) 31 | ListItem ( typedValue ( Integer ( -1051970500 , 32 , true ) , ty ( 8 ) , mutabilityNot ) ) 32 | 33 | 34 | 35 | .List 36 | 37 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-smir-random/simple-types/init-4.expected: -------------------------------------------------------------------------------- 1 | 2 | 3 | srandInt ( 4 ) ~> #execTerminator ( terminator (... kind: terminatorKindCall (... func: operandConstant ( constOperand (... span: span ( 0 ) , userTy: noUserTypeAnnotationIndex , const: mirConst (... kind: constantKindZeroSized , ty: ty ( -4 ) , id: mirConstId ( 0 ) ) ) ) , args: operandCopy ( place (... local: local ( 1 ) , projection: .ProjectionElems ) ) operandCopy ( place (... local: local ( 2 ) , projection: .ProjectionElems ) ) operandCopy ( place (... local: local ( 3 ) , projection: .ProjectionElems ) ) .Operands , destination: place (... local: local ( 0 ) , projection: .ProjectionElems ) , target: noBasicBlockIdx , unwind: unwindActionContinue ) , span: span ( 0 ) ) ) ~> .K 4 | 5 | 6 | noReturn 7 | 8 | 9 | ty ( -1 ) 10 | 11 | 12 | 13 | .List 14 | 15 | 16 | ty ( -1 ) 17 | 18 | 19 | place (... local: local ( -1 ) , projection: .ProjectionElems ) 20 | 21 | 22 | noBasicBlockIdx 23 | 24 | 25 | unwindActionUnreachable 26 | 27 | 28 | ListItem ( newLocal ( ty ( 0 ) , mutabilityNot ) ) 29 | ListItem ( typedValue ( BoolVal ( false ) , ty ( 18 ) , mutabilityNot ) ) 30 | ListItem ( typedValue ( Integer ( 155 , 8 , false ) , ty ( 9 ) , mutabilityNot ) ) 31 | ListItem ( typedValue ( Integer ( -446426455 , 32 , true ) , ty ( 8 ) , mutabilityNot ) ) 32 | 33 | 34 | 35 | .List 36 | 37 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-smir-random/simple-types/init-7.expected: -------------------------------------------------------------------------------- 1 | 2 | 3 | srandInt ( 7 ) ~> #execTerminator ( terminator (... kind: terminatorKindCall (... func: operandConstant ( constOperand (... span: span ( 0 ) , userTy: noUserTypeAnnotationIndex , const: mirConst (... kind: constantKindZeroSized , ty: ty ( -4 ) , id: mirConstId ( 0 ) ) ) ) , args: operandCopy ( place (... local: local ( 1 ) , projection: .ProjectionElems ) ) operandCopy ( place (... local: local ( 2 ) , projection: .ProjectionElems ) ) operandCopy ( place (... local: local ( 3 ) , projection: .ProjectionElems ) ) .Operands , destination: place (... local: local ( 0 ) , projection: .ProjectionElems ) , target: noBasicBlockIdx , unwind: unwindActionContinue ) , span: span ( 0 ) ) ) ~> .K 4 | 5 | 6 | noReturn 7 | 8 | 9 | ty ( -1 ) 10 | 11 | 12 | 13 | .List 14 | 15 | 16 | ty ( -1 ) 17 | 18 | 19 | place (... local: local ( -1 ) , projection: .ProjectionElems ) 20 | 21 | 22 | noBasicBlockIdx 23 | 24 | 25 | unwindActionUnreachable 26 | 27 | 28 | ListItem ( newLocal ( ty ( 0 ) , mutabilityNot ) ) 29 | ListItem ( typedValue ( BoolVal ( false ) , ty ( 18 ) , mutabilityNot ) ) 30 | ListItem ( typedValue ( Integer ( 77 , 8 , false ) , ty ( 9 ) , mutabilityNot ) ) 31 | ListItem ( typedValue ( Integer ( -1940095024 , 32 , true ) , ty ( 8 ) , mutabilityNot ) ) 32 | 33 | 34 | 35 | .List 36 | 37 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-smir-random/simple-types/init-8.expected: -------------------------------------------------------------------------------- 1 | 2 | 3 | srandInt ( 8 ) ~> #execTerminator ( terminator (... kind: terminatorKindCall (... func: operandConstant ( constOperand (... span: span ( 0 ) , userTy: noUserTypeAnnotationIndex , const: mirConst (... kind: constantKindZeroSized , ty: ty ( -4 ) , id: mirConstId ( 0 ) ) ) ) , args: operandCopy ( place (... local: local ( 1 ) , projection: .ProjectionElems ) ) operandCopy ( place (... local: local ( 2 ) , projection: .ProjectionElems ) ) operandCopy ( place (... local: local ( 3 ) , projection: .ProjectionElems ) ) .Operands , destination: place (... local: local ( 0 ) , projection: .ProjectionElems ) , target: noBasicBlockIdx , unwind: unwindActionContinue ) , span: span ( 0 ) ) ) ~> .K 4 | 5 | 6 | noReturn 7 | 8 | 9 | ty ( -1 ) 10 | 11 | 12 | 13 | .List 14 | 15 | 16 | ty ( -1 ) 17 | 18 | 19 | place (... local: local ( -1 ) , projection: .ProjectionElems ) 20 | 21 | 22 | noBasicBlockIdx 23 | 24 | 25 | unwindActionUnreachable 26 | 27 | 28 | ListItem ( newLocal ( ty ( 0 ) , mutabilityNot ) ) 29 | ListItem ( typedValue ( BoolVal ( false ) , ty ( 18 ) , mutabilityNot ) ) 30 | ListItem ( typedValue ( Integer ( 189 , 8 , false ) , ty ( 9 ) , mutabilityNot ) ) 31 | ListItem ( typedValue ( Integer ( 1985542055 , 32 , true ) , ty ( 8 ) , mutabilityNot ) ) 32 | 33 | 34 | 35 | .List 36 | 37 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/run-smir-random/simple-types/init-9.expected: -------------------------------------------------------------------------------- 1 | 2 | 3 | srandInt ( 9 ) ~> #execTerminator ( terminator (... kind: terminatorKindCall (... func: operandConstant ( constOperand (... span: span ( 0 ) , userTy: noUserTypeAnnotationIndex , const: mirConst (... kind: constantKindZeroSized , ty: ty ( -4 ) , id: mirConstId ( 0 ) ) ) ) , args: operandCopy ( place (... local: local ( 1 ) , projection: .ProjectionElems ) ) operandCopy ( place (... local: local ( 2 ) , projection: .ProjectionElems ) ) operandCopy ( place (... local: local ( 3 ) , projection: .ProjectionElems ) ) .Operands , destination: place (... local: local ( 0 ) , projection: .ProjectionElems ) , target: noBasicBlockIdx , unwind: unwindActionContinue ) , span: span ( 0 ) ) ) ~> .K 4 | 5 | 6 | noReturn 7 | 8 | 9 | ty ( -1 ) 10 | 11 | 12 | 13 | .List 14 | 15 | 16 | ty ( -1 ) 17 | 18 | 19 | place (... local: local ( -1 ) , projection: .ProjectionElems ) 20 | 21 | 22 | noBasicBlockIdx 23 | 24 | 25 | unwindActionUnreachable 26 | 27 | 28 | ListItem ( newLocal ( ty ( 0 ) , mutabilityNot ) ) 29 | ListItem ( typedValue ( BoolVal ( false ) , ty ( 18 ) , mutabilityNot ) ) 30 | ListItem ( typedValue ( Integer ( 191 , 8 , false ) , ty ( 9 ) , mutabilityNot ) ) 31 | ListItem ( typedValue ( Integer ( -1000150020 , 32 , true ) , ty ( 8 ) , mutabilityNot ) ) 32 | 33 | 34 | 35 | .List 36 | 37 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/assign-cast/assign-cast.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | 3 | // unsigned to signed 4 | let a: u16 = 32896; // 2^15 + (2^7); 5 | // narrowing 6 | let b = a as i8; // -128 7 | // changing signedness 8 | let c = a as i16; // -32640 = a - 2^16 9 | // widening 10 | let d = a as i32; // == a 11 | 12 | // println!("a: {a}\nb: {b} = a as i8\nc: {c} = a as i16\nd: {d} = a as i32\n"); 13 | 14 | // signed to signed 15 | // widening with sign 16 | let e = b as i16; // -128 17 | let f = d as i64; // 32896 == d 18 | // narrowing with sign 19 | let g = c as i8; // -128 20 | let h = d as i8; // -128 again 21 | 22 | // println!("e: {e} = b as i16\nf: {f} = d as i64\ng: {g} = c as i8\nh: {h} = d as i8\n"); 23 | 24 | // signed to unsigned 25 | // changing signedness to unsigned 26 | let i = c as u16; // == a 27 | let j = d as u32; // == a 28 | // widening with sign 29 | let k = b as u16; // 65408 30 | let l = d as u64; // == a 31 | // narrowing with sign 32 | let m = c as u8; // 128 33 | let n = d as u8; // 128 34 | let o = f as u32; // == a 35 | 36 | // println!("i: {i} = c as u16\nj: {j} = d as u32\nk: {k} = b as u16\nl: {l} = d as u64\nm: {m} = c as u8\nn: {n} = d as u8\no: {o} = f as u32\n"); 37 | 38 | /* OUTPUT: 39 | a: 32896 40 | b: -128 = a as i8 41 | c: -32640 = a as i16 42 | d: 32896 = a as i32 43 | 44 | e: -128 = b as i16 45 | f: 32896 = d as i64 46 | g: -128 = c as i8 47 | h: -128 = d as i8 48 | 49 | i: 32896 = c as u16 50 | j: 32896 = d as u32 51 | k: 65408 = b as u16 52 | l: 32896 = d as u64 53 | m: 128 = c as u8 54 | n: 128 = d as u8 55 | o: 32896 = f as u32 56 | */ 57 | } 58 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/main-a-b-c/main-a-b-c.state: -------------------------------------------------------------------------------- 1 | 2 | 3 | #execTerminator ( terminator (... kind: terminatorKindReturn , span: span ( 65 ) ) ) ~> .K 4 | 5 | 6 | noReturn 7 | 8 | 9 | ty ( 27 ) 10 | 11 | 12 | 13 | ListItem ( basicBlock (... statements: .Statements , terminator: terminator (... kind: terminatorKindReturn , span: span ( 65 ) ) ) ) 14 | 15 | 16 | ty ( 26 ) 17 | 18 | 19 | place (... local: local ( 0 ) , projection: .ProjectionElems ) 20 | 21 | 22 | someBasicBlockIdx ( basicBlockIdx ( 1 ) ) 23 | 24 | 25 | unwindActionContinue 26 | 27 | 28 | ListItem ( newLocal ( ty ( 1 ) , mutabilityMut ) ) 29 | 30 | 31 | 32 | ListItem ( StackFrame ( ty ( 25 ) , place (... local: local ( 0 ) , projection: .ProjectionElems ) , someBasicBlockIdx ( basicBlockIdx ( 1 ) ) , unwindActionContinue , ListItem ( newLocal ( ty ( 1 ) , mutabilityMut ) ) ) ) 33 | ListItem ( StackFrame ( ty ( -1 ) , place (... local: local ( 0 ) , projection: .ProjectionElems ) , someBasicBlockIdx ( basicBlockIdx ( 1 ) ) , unwindActionContinue , ListItem ( newLocal ( ty ( 1 ) , mutabilityMut ) ) ) ) 34 | ListItem ( StackFrame ( ty ( -1 ) , place (... local: local ( 0 ) , projection: .ProjectionElems ) , noBasicBlockIdx , unwindActionContinue , ListItem ( newLocal ( ty ( 1 ) , mutabilityMut ) ) ) ) 35 | ListItem ( StackFrame ( ty ( -1 ) , place (... local: local ( -1 ) , projection: .ProjectionElems ) , noBasicBlockIdx , unwindActionUnreachable , .List ) ) 36 | 37 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/show/interior-mut3-fail.main.expected: -------------------------------------------------------------------------------- 1 | 2 | ┌─ 1 (root, init) 3 | │ #execTerminator ( terminator ( ... kind: terminatorKindCall ( ... func: operandC 4 | │ span: 0 5 | │ 6 | │ (154 steps) 7 | ├─ 3 8 | │ #expect ( thunk ( #applyBinOp ( binOpEq , thunk ( #applyBinOp ( binOpBitAnd , th 9 | │ function: main 10 | ┃ 11 | ┃ (1 step) 12 | ┣━━┓ 13 | ┃ │ 14 | ┃ ├─ 4 15 | ┃ │ AssertError ( assertMessageMisalignedPointerDereference ( ... required: operandC 16 | ┃ │ function: main 17 | ┃ │ 18 | ┃ │ (1 step) 19 | ┃ └─ 6 (stuck, leaf) 20 | ┃ #ProgramError ( AssertError ( assertMessageMisalignedPointerDereference ( ... re 21 | ┃ function: main 22 | ┃ 23 | ┗━━┓ 24 | │ 25 | ├─ 5 26 | │ #execBlockIdx ( basicBlockIdx ( 8 ) ) ~> .K 27 | │ function: main 28 | │ 29 | │ (111 steps) 30 | ├─ 7 31 | │ #expect ( thunk ( #applyBinOp ( binOpEq , thunk ( #applyBinOp ( binOpBitAnd , th 32 | │ function: main 33 | ┃ 34 | ┃ (1 step) 35 | ┣━━┓ 36 | ┃ │ 37 | ┃ ├─ 8 38 | ┃ │ AssertError ( assertMessageMisalignedPointerDereference ( ... required: operandC 39 | ┃ │ function: main 40 | ┃ │ 41 | ┃ │ (1 step) 42 | ┃ └─ 10 (stuck, leaf) 43 | ┃ #ProgramError ( AssertError ( assertMessageMisalignedPointerDereference ( ... re 44 | ┃ function: main 45 | ┃ 46 | ┗━━┓ 47 | │ 48 | ├─ 9 49 | │ #execBlockIdx ( basicBlockIdx ( 7 ) ) ~> .K 50 | │ function: main 51 | │ 52 | │ (17 steps) 53 | └─ 11 (stuck, leaf) 54 | #setLocalValue ( place ( ... local: local ( 1 ) , projection: .ProjectionElems ) 55 | function: main 56 | span: 79 57 | 58 | 59 | ┌─ 2 (root, leaf, target, terminal) 60 | │ #EndProgram ~> .K 61 | 62 | 63 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/prove-rs/bitwise-shift.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // Shl basic 3 | assert!(1_u8 << 3_u8 == 8); 4 | assert!(1_u8 << 3_i8 == 8); // Negative on RHS if in 0..size 5 | assert!(1_i8 << 3_u8 == 8); 6 | assert!(1_i8 << 3_i8 == 8); 7 | assert!(1_i8 << 7_u8 == -128_i8); 8 | 9 | // Shl Overflow 10 | assert!(255_u8 << 1_u8 == 254); 11 | assert!(-127_i8 << 1_u8 == 2); 12 | // assert!(-128_i8 << -1_i8 == 2); // Shift must be in 0..size 13 | // assert!(0_u8 << 8_u8 == 0); // Shift must be in 0..size 14 | 15 | // Shr basic 16 | assert!(24_u8 >> 3_u8 == 3); 17 | assert!(24_u8 >> 3_i8 == 3); // Negative on RHS if in 0..size 18 | assert!(24_i8 >> 3_u8 == 3); 19 | assert!(24_i8 >> 3_i8 == 3); 20 | 21 | // Shr Overflow 22 | assert!(255_u8 >> 1_u8 == 127); 23 | assert!(-127_i8 >> 1_u8 == -64); // Arithmetic shift sign extends 24 | // assert!(-128_i8 >> -1_i8 == 2); // Shift must be in 0..size 25 | // assert!(0_u8 >> 8_u8 == 0); // Shift must be in 0..size 26 | 27 | // ShlUnchecked basic 28 | assert!(1_u8.wrapping_shl(3_u32) == 8_u8); // RHS must be u32 29 | 30 | // ShlUnchecked Overflow 31 | assert!(255_u8.wrapping_shl(1_u32) == 254_u8); 32 | assert!(128_u8.wrapping_shl(1_u32) == 0_u8); 33 | assert!((-128_i8).wrapping_shl(3_u32) == 0_i8); 34 | assert!((-127_i8).wrapping_shl(3_u32) == 8_i8); 35 | 36 | // ShrUnchecked basic 37 | assert!(32_u8.wrapping_shr(2_u32) == 8_u8); // RHS must be u32 38 | 39 | // ShlUnchecked Overflow 40 | assert!(255_u8.wrapping_shr(1_u32) == 127_u8); 41 | assert!(128_u8.wrapping_shr(1_u32) == 64_u8); 42 | assert!((-128_i8).wrapping_shr(3_u32) == -16_i8); 43 | assert!((-127_i8).wrapping_shr(1_u32) == -64_i8); 44 | } -------------------------------------------------------------------------------- /kmir/src/kmir/testing/fixtures.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from difflib import unified_diff 4 | from typing import TYPE_CHECKING 5 | 6 | import pytest 7 | 8 | from kmir.build import HASKELL_DEF_DIR, LLVM_LIB_DIR 9 | from kmir.kmir import KMIR 10 | 11 | if TYPE_CHECKING: 12 | from pathlib import Path 13 | 14 | from pytest import FixtureRequest, Parser 15 | 16 | import sys 17 | 18 | 19 | def pytest_configure(config) -> None: 20 | sys.setrecursionlimit(1000000) 21 | 22 | 23 | def assert_or_update_show_output(actual_text: str, expected_file: Path, *, update: bool) -> None: 24 | if update: 25 | expected_file.write_text(actual_text) 26 | else: 27 | assert expected_file.is_file() 28 | expected_text = expected_file.read_text() 29 | if actual_text != expected_text: 30 | diff = '\n'.join( 31 | unified_diff( 32 | expected_text.splitlines(), 33 | actual_text.splitlines(), 34 | fromfile=str(expected_file), 35 | tofile='actual_text', 36 | lineterm='', 37 | ) 38 | ) 39 | raise AssertionError(f'The actual output does not match the expected output:\n{diff}') 40 | 41 | 42 | def pytest_addoption(parser: Parser) -> None: 43 | parser.addoption( 44 | '--update-expected-output', 45 | action='store_true', 46 | default=False, 47 | help='Write expected output files for proof tests', 48 | ) 49 | 50 | 51 | @pytest.fixture 52 | def update_expected_output(request: FixtureRequest) -> bool: 53 | return request.config.getoption('--update-expected-output') 54 | 55 | 56 | @pytest.fixture 57 | def kmir() -> KMIR: 58 | return KMIR(HASKELL_DEF_DIR, LLVM_LIB_DIR) 59 | -------------------------------------------------------------------------------- /kmir/src/tests/integration/data/exec-smir/call-with-args/main-a-b-with-int.state: -------------------------------------------------------------------------------- 1 | 2 | 3 | #execBlock ( basicBlock (... statements: .Statements , terminator: terminator (... kind: terminatorKindReturn , span: span ( 63 ) ) ) ) ~> .K 4 | 5 | 6 | noReturn 7 | 8 | 9 | ty ( 27 ) 10 | 11 | 12 | 13 | ListItem ( basicBlock (... statements: .Statements , terminator: terminator (... kind: terminatorKindReturn , span: span ( 63 ) ) ) ) 14 | 15 | 16 | ty ( 25 ) 17 | 18 | 19 | place (... local: local ( 0 ) , projection: .ProjectionElems ) 20 | 21 | 22 | someBasicBlockIdx ( basicBlockIdx ( 1 ) ) 23 | 24 | 25 | unwindActionContinue 26 | 27 | 28 | ListItem ( newLocal ( ty ( 1 ) , mutabilityMut ) ) 29 | ListItem ( typedValue ( Integer ( 10 , 64 , false ) , ty ( 26 ) , mutabilityNot ) ) 30 | ListItem ( typedValue ( Integer ( 11 , 16 , true ) , ty ( 28 ) , mutabilityNot ) ) 31 | 32 | 33 | 34 | ListItem ( StackFrame ( ty ( -1 ) , place (... local: local ( 0 ) , projection: .ProjectionElems ) , someBasicBlockIdx ( basicBlockIdx ( 1 ) ) , unwindActionContinue , ListItem ( newLocal ( ty ( 1 ) , mutabilityMut ) ) 35 | ListItem ( typedValue ( Integer ( 10 , 64 , false ) , ty ( 26 ) , mutabilityNot ) ) ) ) 36 | ListItem ( StackFrame ( ty ( -1 ) , place (... local: local ( 0 ) , projection: .ProjectionElems ) , noBasicBlockIdx , unwindActionContinue , ListItem ( newLocal ( ty ( 1 ) , mutabilityMut ) ) ) ) 37 | ListItem ( StackFrame ( ty ( -1 ) , place (... local: local ( -1 ) , projection: .ProjectionElems ) , noBasicBlockIdx , unwindActionUnreachable , .List ) ) 38 | 39 | -------------------------------------------------------------------------------- /kmir/src/kmir/kparse.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from typing import TYPE_CHECKING 4 | 5 | from pyk.ktool.kprint import KPrint 6 | 7 | if TYPE_CHECKING: 8 | from collections.abc import Callable, Iterable 9 | from pathlib import Path 10 | 11 | from pyk.kast.inner import KInner 12 | from pyk.kast.outer import KFlatModule 13 | from pyk.kast.pretty import SymbolTable 14 | from pyk.kore.syntax import Pattern 15 | from pyk.utils import BugReport 16 | 17 | 18 | class KParse(KPrint): 19 | def __init__( 20 | self, 21 | definition_dir: Path, 22 | use_directory: Path | None = None, 23 | bug_report: BugReport | None = None, 24 | extra_unparsing_modules: Iterable[KFlatModule] = (), 25 | patch_symbol_table: Callable[[SymbolTable], None] | None = None, 26 | ): 27 | super().__init__( 28 | definition_dir, 29 | use_directory=use_directory, 30 | bug_report=bug_report, 31 | extra_unparsing_modules=extra_unparsing_modules, 32 | patch_symbol_table=patch_symbol_table, 33 | ) 34 | 35 | def kparse(self, input_file: Path, *, sort: str) -> tuple[int, KInner]: 36 | returncode, kore = self.kparse_into_kore(input_file, sort=sort) 37 | kast = self.kore_to_kast(kore) 38 | return returncode, kast 39 | 40 | def kparse_into_kore(self, input_file: Path, *, sort: str) -> tuple[int, Pattern]: 41 | from pyk.kore.parser import KoreParser 42 | from pyk.ktool.kprint import _kast 43 | 44 | proc_res = _kast( 45 | file=input_file, 46 | definition_dir=self.definition_dir, 47 | sort=sort, 48 | input='rule', 49 | output='kore', 50 | ) 51 | 52 | parser = KoreParser(proc_res.stdout) 53 | pattern = parser.pattern() 54 | assert parser.eof 55 | 56 | return proc_res.returncode, pattern 57 | --------------------------------------------------------------------------------