Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions .github/scripts/check-cachix-pin.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#!/usr/bin/env bash
set -euo pipefail

# Kup relies on cachix registry k-framework-binary.
CACHE="k-framework-binary"
OWNER_REPO="${OWNER_REPO:-$(git remote get-url origin | sed -E 's#(git@github.com:|https://github.com/)##; s#\.git$##')}"
REV="${REV:-${GITHUB_SHA:-$(git rev-parse HEAD)}}"
UNAME_S="$(uname -s)"
UNAME_M="$(uname -m)"
case "${UNAME_S}-${UNAME_M}" in
Linux-x86_64) SYSTEM="x86_64-linux" ;;
Linux-aarch64 | Linux-arm64) SYSTEM="aarch64-linux" ;;
Darwin-x86_64) SYSTEM="x86_64-darwin" ;;
Darwin-arm64) SYSTEM="aarch64-darwin" ;;
*)
echo "Unsupported platform: ${UNAME_S}-${UNAME_M}" >&2
exit 1
;;
esac
PIN_API_URL="https://app.cachix.org/api/v1/cache/${CACHE}/pin"
CHECK_PACKAGES=(kmir kmir.rust)

SUMMARY="${GITHUB_STEP_SUMMARY:-/dev/stdout}"

{
echo "## Cachix Publish Summary"
echo "CACHE: $CACHE"
echo "OWNER_REPO: $OWNER_REPO"
echo "REV: $REV"
echo "SYSTEM: $SYSTEM"
echo "PACKAGES: ${CHECK_PACKAGES[*]}"
} >> "$SUMMARY"

# Verify push + pin together for each package. Both can become visible with delay.
PIN_VISIBILITY_TIMEOUT_SECONDS=120 # 2 minutes
PIN_VISIBILITY_INTERVAL_SECONDS=5 # 5 seconds
PIN_VISIBILITY_ATTEMPTS=$((PIN_VISIBILITY_TIMEOUT_SECONDS / PIN_VISIBILITY_INTERVAL_SECONDS))
for i in $(seq 1 "$PIN_VISIBILITY_ATTEMPTS"); do
PIN_JSON="$(curl -fsSL "${PIN_API_URL}?q=${REV}")"
ALL_OK=1

for PKG in "${CHECK_PACKAGES[@]}"; do
KEY="github:${OWNER_REPO}/${REV}#packages.${SYSTEM}.${PKG}"
STORE_PATH="$(
echo "$PIN_JSON" \
| jq -r --arg k "$KEY" 'map(select(.name == $k)) | first | (.lastRevision.storePath // .storePath // .store_path // .path // "")'
)"
if [ -z "$STORE_PATH" ]; then
PIN_STATUS="pin-missing"
PUSH_STATUS="000"
ALL_OK=0
{
echo "key-${PKG}: ${KEY}"
echo "pin-status-${PKG}: ${PIN_STATUS}"
echo "push-http-${PKG}: ${PUSH_STATUS}"
}
continue
fi

PIN_STATUS="pin-ok"
HASH="$(basename "$STORE_PATH" | cut -d- -f1)"
PUSH_NARINFO_URL="https://${CACHE}.cachix.org/${HASH}.narinfo"
PUSH_STATUS="$(curl -sS -o /dev/null -w '%{http_code}' "$PUSH_NARINFO_URL")" || PUSH_STATUS="000"
if [ "$PUSH_STATUS" != "200" ]; then
ALL_OK=0
fi

{
echo "key-${PKG}: ${KEY}"
echo "store-path-${PKG}: ${STORE_PATH}"
echo "pin-status-${PKG}: ${PIN_STATUS}"
echo "push-http-${PKG}: ${PUSH_STATUS}"
}
done

if [ "$ALL_OK" = "1" ]; then
echo "cachix-status: push-and-pin-ok-for-all-packages" >> "$SUMMARY"
exit 0
fi

echo "cachix-check-attempt-${i}: not-ready, retrying in ${PIN_VISIBILITY_INTERVAL_SECONDS}s"
sleep "$PIN_VISIBILITY_INTERVAL_SECONDS"
done

echo "cachix-status: push-or-pin-missing-after-${PIN_VISIBILITY_TIMEOUT_SECONDS}s-for-at-least-one-package" >> "$SUMMARY"
exit 1
9 changes: 7 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,17 @@ jobs:
env:
CACHIX_AUTH_TOKEN: '${{ secrets.CACHIX_PRIVATE_KFB_TOKEN }}'
GC_DONT_GC: '1'
OWNER_REPO: '${{ github.repository }}'
REV: '${{ github.sha }}'
with:
packages: jq
script: |
export PATH="$(nix build github:runtimeverification/kup --no-link --json | jq -r '.[].outputs | to_entries[].value')/bin:$PATH"
kup publish k-framework-binary .#kmir --keep-days 180
kup publish k-framework-binary .#kmir.rust --keep-days 180
kup publish k-framework-binary .#kmir --keep-days 180 || true
kup publish k-framework-binary .#kmir.rust --keep-days 180 || true

# Cachix has not been responding to 'cachix pin' requests made under the hood by kup. So we need to manually verify the push and pin.
.github/scripts/check-cachix-pin.sh

- name: 'On failure, delete drafted release'
if: failure()
Expand Down
28 changes: 28 additions & 0 deletions .github/workflows/test-cachix-pin.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: 'Test Cachix Pin'

on:
workflow_dispatch:
inputs:
ref:
description: 'Git ref (tag or SHA) of an existing release to verify'
required: true
type: string

jobs:
verify-cachix-pin:
name: 'Verify Cachix Pin'
runs-on: [self-hosted, linux, normal]
steps:
- name: 'Check out code'
uses: actions/checkout@v4

- name: 'Verify cachix publish and pin'
uses: workflow/nix-shell-action@v3
env:
CACHIX_AUTH_TOKEN: '${{ secrets.CACHIX_PRIVATE_KFB_TOKEN }}'
GC_DONT_GC: '1'
OWNER_REPO: '${{ github.repository }}'
REV: '${{ inputs.ref }}'
with:
packages: jq
script: bash .github/scripts/check-cachix-pin.sh
4 changes: 3 additions & 1 deletion .github/workflows/update-dependencies.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ jobs:
git checkout "${VERSION}"
cd ../..
sed -i 's!__smir_version__: Final = '"'[0-9a-f]*'"'!__smir_version__: Final = '"'${VERSION}'"'!' kmir/src/kmir/__init__.py
git add deps/stable-mir-json kmir/src/kmir/__init__.py
CHANNEL=$(grep '^channel' deps/stable-mir-json/rust-toolchain.toml | sed 's!channel = "\(.*\)"!\1!')
sed -i 's!^channel = ".*"!channel = "'"${CHANNEL}"'"!' rust-toolchain.toml
git add deps/stable-mir-json kmir/src/kmir/__init__.py rust-toolchain.toml
git commit -m "deps/stable-mir-json: sync submodule ${VERSION}" || true
- name: 'Update Nix flake inputs'
run: |
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ test: test-unit test-integration smir-parse-tests
stable-mir-json: CARGO_BUILD_OPTS =
stable-mir-json:
cd deps/stable-mir-json && cargo build ${CARGO_BUILD_OPTS}
cd deps/stable-mir-json && cargo build --release ${CARGO_BUILD_OPTS}
cd deps/stable-mir-json && cargo run --bin cargo_stable_mir_json -- ${TOP_DIR}/deps/stable-mir-json ${TOP_DIR}/deps
${TOP_DIR}/deps/.stable-mir-json/release.sh --version || ${TOP_DIR}/deps/.stable-mir-json/debug.sh --version

Expand Down
2 changes: 1 addition & 1 deletion deps/stable-mir-json
Submodule stable-mir-json updated 58 files
+86 −0 .github/scripts/check-cachix-pin.sh
+3 −1 .github/workflows/master.yml
+28 −0 .github/workflows/test-cachix-pin.yml
+2 −1 .gitignore
+91 −0 CHANGELOG.md
+1 −1 Cargo.lock
+2 −2 Cargo.toml
+13 −10 Makefile
+58 −0 docs/adr/001-index-first-graph-architecture.md
+54 −0 docs/adr/002-declarative-pipeline-with-allocmap-coherence.md
+33 −7 src/mk_graph/index.rs
+0 −3 src/mk_graph/output/d2.rs
+1 −5 src/mk_graph/output/dot.rs
+0 −1,473 src/printer.rs
+259 −0 src/printer/collect.rs
+237 −0 src/printer/items.rs
+107 −0 src/printer/link_map.rs
+494 −0 src/printer/mir_visitor.rs
+83 −0 src/printer/mod.rs
+495 −0 src/printer/schema.rs
+131 −0 src/printer/ty_visitor.rs
+168 −0 src/printer/types.rs
+64 −0 src/printer/util.rs
+2 −0 tests/integration/normalise-filter.jq
+25 −0 tests/integration/programs/assert_eq.smir.json.expected
+14 −0 tests/integration/programs/binop.smir.json.expected
+14 −0 tests/integration/programs/char-trivial.smir.json.expected
+20 −0 tests/integration/programs/closure-args.smir.json.expected
+20 −0 tests/integration/programs/closure-no-args.smir.json.expected
+14 −0 tests/integration/programs/const-arithm-simple.smir.json.expected
+14 −0 tests/integration/programs/div.smir.json.expected
+16 −0 tests/integration/programs/double-ref-deref.smir.json.expected
+12 −0 tests/integration/programs/enum.smir.json.expected
+14 −0 tests/integration/programs/fibonacci.smir.json.expected
+14 −0 tests/integration/programs/float.smir.json.expected
+28 −0 tests/integration/programs/fn-ptr-in-arg.smir.json.expected
+14 −0 tests/integration/programs/modulo.smir.json.expected
+14 −0 tests/integration/programs/mutual_recursion.smir.json.expected
+14 −0 tests/integration/programs/option-construction.smir.json.expected
+19 −0 tests/integration/programs/param_types.smir.json.expected
+14 −0 tests/integration/programs/primitive-type-bounds.smir.json.expected
+14 −0 tests/integration/programs/recursion-simple-match.smir.json.expected
+14 −0 tests/integration/programs/recursion-simple.smir.json.expected
+15 −0 tests/integration/programs/ref-deref.smir.json.expected
+14 −0 tests/integration/programs/shl_min.smir.json.expected
+21 −0 tests/integration/programs/slice.smir.json.expected
+9 −0 tests/integration/programs/static-vtable-nonbuiltin-deref.rs
+3,527 −0 tests/integration/programs/static-vtable-nonbuiltin-deref.smir.json.expected
+16 −0 tests/integration/programs/strange-ref-deref.smir.json.expected
+14 −0 tests/integration/programs/struct.smir.json.expected
+14 −0 tests/integration/programs/sum-to-n.smir.json.expected
+16 −0 tests/integration/programs/tuple-eq.smir.json.expected
+14 −0 tests/integration/programs/tuples-simple.smir.json.expected
+19 −0 tests/integration/programs/weirdRefs.smir.json.expected
+1 −30 tests/ui/failing.tsv
+30 −1 tests/ui/passing.tsv
+39 −1 tests/ui/remake_ui_tests.sh
+240 −47 tests/ui/run_ui_tests.sh
2 changes: 1 addition & 1 deletion deps/stable-mir-json_release
Original file line number Diff line number Diff line change
@@ -1 +1 @@
a5b714d89d0c12c7f4b00602a95ad2d3a34530f0
047ca6ac01786e1b616e13a216d70268b9785e17
14 changes: 7 additions & 7 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

flake-utils.url = "github:numtide/flake-utils";

stable-mir-json-flake.url = "github:runtimeverification/stable-mir-json/a5b714d89d0c12c7f4b00602a95ad2d3a34530f0";
stable-mir-json-flake.url = "github:runtimeverification/stable-mir-json/047ca6ac01786e1b616e13a216d70268b9785e17";
stable-mir-json-flake = {
inputs.nixpkgs.follows = "nixpkgs";
inputs.flake-utils.follows = "flake-utils";
Expand Down
2 changes: 1 addition & 1 deletion kmir/src/kmir/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
from typing import Final

__version__: Final = version('kmir')
__smir_version__: Final = 'a5b714d89d0c12c7f4b00602a95ad2d3a34530f0'
__smir_version__: Final = '047ca6ac01786e1b616e13a216d70268b9785e17'
10 changes: 9 additions & 1 deletion kmir/src/kmir/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def _kmir_show(opts: ShowOpts) -> None:
if opts.leaves:
if lines and lines[-1] != '':
lines.append('')
lines.extend(render_leaf_k_cells(proof, node_printer.cterm_show))
lines.extend(render_leaf_k_cells(proof, node_printer.cterm_show, smir_info=node_printer.smir_info))

# Handle --to-module output
if opts.to_module:
Expand Down Expand Up @@ -410,6 +410,13 @@ def _arg_parser() -> ArgumentParser:
action='store_true',
help='Break on every MIR step (statements and terminators)',
)
prove_args.add_argument(
'--break-on-function',
dest='break_on_function',
action='append',
default=None,
help='Break when calling functions / intrinsics matching this name (repeatable)',
)

proof_args = ArgumentParser(add_help=False)
proof_args.add_argument('id', metavar='PROOF_ID', help='The id of the proof to view')
Expand Down Expand Up @@ -638,6 +645,7 @@ def _parse_args(ns: Namespace) -> KMirOpts:
break_every_step=ns.break_every_step,
terminate_on_thunk=ns.terminate_on_thunk,
add_module=ns.add_module,
break_on_function=ns.break_on_function or [],
)
case 'link':
return LinkOpts(
Expand Down
7 changes: 7 additions & 0 deletions kmir/src/kmir/_prove.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ def _prove_rs(opts: ProveRSOpts, target_path: Path, label: str) -> APRProof:
symbolic=True,
haskell_target=opts.haskell_target,
llvm_lib_target=opts.llvm_lib_target,
break_on_function=opts.break_on_function or None,
)
else:
_LOGGER.info(f'Constructing initial proof: {label}')
Expand Down Expand Up @@ -92,6 +93,7 @@ def _prove_rs(opts: ProveRSOpts, target_path: Path, label: str) -> APRProof:
symbolic=True,
haskell_target=opts.haskell_target,
llvm_lib_target=opts.llvm_lib_target,
break_on_function=opts.break_on_function or None,
)

proof = apr_proof_from_smir(
Expand Down Expand Up @@ -122,6 +124,7 @@ def _prove_rs(opts: ProveRSOpts, target_path: Path, label: str) -> APRProof:
break_on_terminator_unreachable=opts.break_on_terminator_unreachable,
break_every_terminator=opts.break_every_terminator,
break_every_step=opts.break_every_step,
break_on_function=opts.break_on_function,
)

if opts.max_workers and opts.max_workers > 1:
Expand Down Expand Up @@ -251,6 +254,7 @@ def _cut_point_rules(
break_on_terminator_unreachable: bool,
break_every_terminator: bool,
break_every_step: bool,
break_on_function: list[str] | None = None,
) -> list[str]:
cut_point_rules = []
if break_on_thunk:
Expand Down Expand Up @@ -291,6 +295,9 @@ def _cut_point_rules(
or break_every_step
):
cut_point_rules.append('KMIR-CONTROL-FLOW.termCallFunction')
if break_on_function:
cut_point_rules.append('KMIR-CONTROL-FLOW.termCallFunctionFilter')
cut_point_rules.append('KMIR-CONTROL-FLOW.termCallIntrinsicFilter')
if break_on_terminator_assert or break_every_terminator or break_every_step:
cut_point_rules.append('KMIR-CONTROL-FLOW.termAssert')
if break_on_terminator_drop or break_every_terminator or break_every_step:
Expand Down
26 changes: 13 additions & 13 deletions kmir/src/kmir/kdist/mir-semantics/intrinsics.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ its argument to the destination without modification.

```k
// Black box intrinsic implementation - identity function
rule <k> #execIntrinsic(IntrinsicFunction(symbol("black_box")), ARG:Operand .Operands, DEST)
rule <k> #execIntrinsic(IntrinsicFunction(symbol("black_box")), ARG:Operand .Operands, DEST, _SPAN)
=> #setLocalValue(DEST, ARG)
... </k>
```
Expand All @@ -36,7 +36,7 @@ a NO OP for program semantics. `std::intrinsics::likely` and `std::intrinsics::u
"normal" `MonoItemFn`s that call the `cold_path` intrinsic.

```k
rule <k> #execIntrinsic(IntrinsicFunction(symbol("cold_path")), .Operands, _DEST) => .K ... </k>
rule <k> #execIntrinsic(IntrinsicFunction(symbol("cold_path")), .Operands, _DEST, _SPAN) => .K ... </k>
```

#### Prefetch (`std::intrinsics::prefetch_*`)
Expand All @@ -46,11 +46,11 @@ intrinsics in Rust are performance hints that request the CPU to load or prepare
before it's used. They have no effect on program semantics, and are implemented as a NO OP in this semantics.

```k
rule <k> #execIntrinsic(IntrinsicFunction(symbol("prefetch_read_data")), _ARG1:Operand _ARG2:Operand .Operands, _DEST) => .K ... </k>
rule <k> #execIntrinsic(IntrinsicFunction(symbol("prefetch_write_data")), _ARG1:Operand _ARG2:Operand .Operands, _DEST) => .K ... </k>
rule <k> #execIntrinsic(IntrinsicFunction(symbol("prefetch_read_data")), _ARG1:Operand _ARG2:Operand .Operands, _DEST, _SPAN) => .K ... </k>
rule <k> #execIntrinsic(IntrinsicFunction(symbol("prefetch_write_data")), _ARG1:Operand _ARG2:Operand .Operands, _DEST, _SPAN) => .K ... </k>

rule <k> #execIntrinsic(IntrinsicFunction(symbol("prefetch_read_instruction")), _ARG1:Operand _ARG2:Operand .Operands, _DEST) => .K ... </k>
rule <k> #execIntrinsic(IntrinsicFunction(symbol("prefetch_write_instruction")), _ARG1:Operand _ARG2:Operand .Operands, _DEST) => .K ... </k>
rule <k> #execIntrinsic(IntrinsicFunction(symbol("prefetch_read_instruction")), _ARG1:Operand _ARG2:Operand .Operands, _DEST, _SPAN) => .K ... </k>
rule <k> #execIntrinsic(IntrinsicFunction(symbol("prefetch_write_instruction")), _ARG1:Operand _ARG2:Operand .Operands, _DEST, _SPAN) => .K ... </k>
```

#### Assert Inhabited (`std::intrinsics::assert_inhabited`)
Expand All @@ -63,13 +63,13 @@ error with `#AssertInhabitedFailure` if we see that following the intrinsic. Oth

```k
syntax MIRError ::= "AssertInhabitedFailure"
rule <k> #execIntrinsic(IntrinsicFunction(symbol("assert_inhabited")), .Operands, _DEST)
rule <k> #execIntrinsic(IntrinsicFunction(symbol("assert_inhabited")), .Operands, _DEST, _SPAN)
~> #continueAt(noBasicBlockIdx)
=> AssertInhabitedFailure
...
</k>

rule <k> #execIntrinsic(IntrinsicFunction(symbol("assert_inhabited")), .Operands, _DEST)
rule <k> #execIntrinsic(IntrinsicFunction(symbol("assert_inhabited")), .Operands, _DEST, _SPAN)
=> .K
...
</k>
Expand All @@ -88,7 +88,7 @@ Execution gets stuck (no matching rule) when operands have different types or un

```k
// Raw eq: dereference operands, extract types, and delegate to typed comparison
rule <k> #execIntrinsic(IntrinsicFunction(symbol("raw_eq")), ARG1:Operand ARG2:Operand .Operands, PLACE)
rule <k> #execIntrinsic(IntrinsicFunction(symbol("raw_eq")), ARG1:Operand ARG2:Operand .Operands, PLACE, _SPAN)
=> #execRawEqTyped(PLACE, #withDeref(ARG1), #extractOperandType(#withDeref(ARG1), LOCALS),
#withDeref(ARG2), #extractOperandType(#withDeref(ARG2), LOCALS))
... </k>
Expand Down Expand Up @@ -134,11 +134,11 @@ through a dereferenced pointer. We extract the place from the pointer operand, a
write the value to that location.

```k
rule <k> #execIntrinsic(IntrinsicFunction(symbol("volatile_store")), operandCopy(place(LOCAL, PROJ)) ARG2:Operand .Operands, _DEST)
rule <k> #execIntrinsic(IntrinsicFunction(symbol("volatile_store")), operandCopy(place(LOCAL, PROJ)) ARG2:Operand .Operands, _DEST, _SPAN)
=> #setLocalValue(place(LOCAL, appendP(PROJ, projectionElemDeref .ProjectionElems)), ARG2)
... </k>

rule <k> #execIntrinsic(IntrinsicFunction(symbol("volatile_store")), operandMove(place(LOCAL, PROJ)) ARG2:Operand .Operands, _DEST)
rule <k> #execIntrinsic(IntrinsicFunction(symbol("volatile_store")), operandMove(place(LOCAL, PROJ)) ARG2:Operand .Operands, _DEST, _SPAN)
=> #setLocalValue(place(LOCAL, appendP(PROJ, projectionElemDeref .ProjectionElems)), ARG2)
... </k>
```
Expand All @@ -153,12 +153,12 @@ the second argument, so the returned difference is always positive.


```k
rule <k> #execIntrinsic(IntrinsicFunction(symbol("ptr_offset_from")), ARG1:Operand ARG2:Operand .Operands, DEST)
rule <k> #execIntrinsic(IntrinsicFunction(symbol("ptr_offset_from")), ARG1:Operand ARG2:Operand .Operands, DEST, _SPAN)
=> #ptrOffsetDiff(ARG1, ARG2, true, DEST)
...
</k>

rule <k> #execIntrinsic(IntrinsicFunction(symbol("ptr_offset_from_unsigned")), ARG1:Operand ARG2:Operand .Operands, DEST)
rule <k> #execIntrinsic(IntrinsicFunction(symbol("ptr_offset_from_unsigned")), ARG1:Operand ARG2:Operand .Operands, DEST, _SPAN)
=> #ptrOffsetDiff(ARG1, ARG2, false, DEST)
...
</k>
Expand Down
Loading
Loading