Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compositional crux-mir support #659

Merged
merged 19 commits into from
Apr 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
efffd2e
crux-mir.cabal: move all module into exposed-modules
spernsteiner Feb 12, 2021
bbc792c
crux-mir: add mainWithExtraOverrides entry point
spernsteiner Feb 12, 2021
a5ec4eb
crux-mir: add MethodSpec and MethodSpecBuilder intrinsics
spernsteiner Feb 13, 2021
57dcde9
crux-mir: TransTy: add isUnsized
spernsteiner Feb 16, 2021
ccc62d9
crux-mir: add functions for manipulating MirRefs within IO/OverrideSi…
spernsteiner Jan 14, 2021
8b10cfc
crux-mir: add mirRef_eqIO
spernsteiner Jan 13, 2021
259e086
crux-mir: pass MIR CollectionState to overrides
spernsteiner Feb 17, 2021
25bab3f
crux-mir: add _Wrapped lens for Substs
spernsteiner Feb 17, 2021
619b365
crux-mir: expose `sym ~ W4.ExprBuilder ...` constraint in BindExtraOv…
spernsteiner Feb 17, 2021
4f42945
add mirFail stubs for construction of MethodSpec{,Builder}
spernsteiner Nov 5, 2020
46aa87f
let test suites override the default mir-json -L search path
spernsteiner Feb 18, 2021
607c33c
crux-mir: add CTyUnsafeCell pattern
spernsteiner Feb 19, 2021
f23e141
update golden test files for line number change
spernsteiner Feb 19, 2021
529f038
crux-mir: add crucible::method_spec::clobber_globals function
spernsteiner Feb 23, 2021
42f151e
Mir.Intrinsics: add mirRef_overlaps
spernsteiner Feb 23, 2021
d29d5aa
minor improvements to mirRef_overlaps
spernsteiner Feb 24, 2021
155fa0f
more doc comments explaining the crux-mir/crux-mir-comp split
spernsteiner Feb 25, 2021
44c8aeb
add mirRef_indexAndLenSim
spernsteiner Feb 25, 2021
c6b5472
don't require Crux.Model personality for mirRef_indexAndLenSim
spernsteiner Feb 26, 2021
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
13 changes: 6 additions & 7 deletions crux-mir/crux-mir.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,12 @@ library
Mir.PP
Mir.Generate
Mir.DefId
other-modules:
Mir.FancyMuxTree
Mir.Intrinsics
Mir.Overrides
Mir.TransTy
Mir.Trans
Mir.TransCustom
Mir.FancyMuxTree
Mir.Intrinsics
Mir.Overrides
Mir.TransTy
Mir.Trans
Mir.TransCustom


executable crux-mir
Expand Down
2 changes: 2 additions & 0 deletions crux-mir/lib/crucible/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#![no_std]
#![feature(core_intrinsics)]
#![feature(crucible_intrinsics)]
#![feature(unboxed_closures)]

pub mod bitvector;
pub mod method_spec;
pub mod sym_bytes;
pub mod symbolic;

Expand Down
83 changes: 83 additions & 0 deletions crux-mir/lib/crucible/method_spec/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
//! Provides the `MethodSpec` type, used for compositional reasoning. Also provides
//! `MethodSpecBuilder`, which is used internally by the compositional reasoning macros to
//! construct a `MethodSpec` from a symbolic test.
//!
//! Note that these types work only when running under `crux-mir-comp`. Trying to use them under
//! ordinary `crux-mir` will produce an error.
use core::fmt;

mod raw;

pub use self::raw::clobber_globals;


/// The specification of a function. This can be used when verifying callers of the function to
/// avoid simulating the entire function itself.
#[derive(Clone, Copy)]
pub struct MethodSpec {
raw: raw::MethodSpec,
}

impl MethodSpec {
/// Enable this `MethodSpec` to be used as an override for its subject function.
pub fn enable(&self) {
raw::spec_enable(self.raw);
}
}

impl fmt::Debug for MethodSpec {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let s = raw::spec_pretty_print(self.raw);
fmt.write_str("MethodSpec {")?;
for (i, chunk) in s.split("\n").enumerate() {
if i > 0 {
fmt.write_str(", ")?;
}
fmt.write_str(chunk);
}
fmt.write_str("}")?;
Ok(())
}
}


/// Helper type used to incrementally construct a `MethodSpec` for a function.
pub struct MethodSpecBuilder {
raw: raw::MethodSpecBuilder,
}

impl fmt::Debug for MethodSpecBuilder {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "MethodSpecBuilder {{ .. }}")
}
}

impl MethodSpecBuilder {
pub fn new<Args, F: Fn<Args>>(f: F) -> MethodSpecBuilder {
MethodSpecBuilder {
raw: raw::builder_new::<F>(),
}
}

pub fn add_arg<T>(&mut self, x: &T) {
self.raw = raw::builder_add_arg(self.raw, x);
}

pub fn gather_assumes(&mut self) {
self.raw = raw::builder_gather_assumes(self.raw);
}

pub fn set_return<T>(&mut self, x: &T) {
self.raw = raw::builder_set_return(self.raw, x);
}

pub fn gather_asserts(&mut self) {
self.raw = raw::builder_gather_asserts(self.raw);
}

pub fn finish(self) -> MethodSpec {
MethodSpec {
raw: raw::builder_finish(self.raw),
}
}
}
73 changes: 73 additions & 0 deletions crux-mir/lib/crucible/method_spec/raw.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//! Bindings for low-level MethodSpec APIs.
//!
//! Like most functions in the `crucible` crate, these functions are left unimplemented in Rust
//! and are replaced by a real implementation via the Crucible override mechanism. However, unlike
//! most other functions, the necessary overrides are not provided by `crux-mir`; instead, they are
//! provided by the `crux-mir-comp` package in the `saw-script` repository, which extends ordinary
//! `crux-mir` with additional overrides using `crux-mir`'s new `mainWithExtraOverrides` entry
//! point. Trying to use these APIs under ordinary `crux-mir` will produce an error.

/// Crucible `MethodSpecType`, exposed to Rust.
///
/// As usual for Crucible types, this implements `Copy`, since it's backed by a boxed,
/// garbage-collected Haskell value. It contains a dummy field to ensure the Rust compiler sees it
/// as having non-zero size. The representation is overridden within `crux-mir`, so the field
/// should not be accessed when running symbolically.
#[derive(Clone, Copy)]
pub struct MethodSpec(u8);

// We only have `libcore` available, so we can't return `String` here. Instead, the override for
// this function within `crux-mir` will construct and leak a `str`.
pub fn spec_pretty_print(ms: MethodSpec) -> &'static str {
"(unknown MethodSpec)"
}

/// Enable using `ms` in place of calls to the actual function. The function to override is
/// determined by the `F` type parameter of `builder_new` during the construction of the
/// `MethodSpec`.
pub fn spec_enable(ms: MethodSpec) {
}


/// Crucible `MethodSpecBuilderType`, exposed to Rust.
#[derive(Clone, Copy)]
pub struct MethodSpecBuilder(u8);

pub fn builder_new<F>() -> MethodSpecBuilder {
// If the program is running under ordinary `crux-mir` instead of `crux-mir-comp`, then the
// override for this function will be missing. We could provide a dummy implementation for
// that case, but it's better to fail early. Otherwise users will get cryptic errors when
// invoking their spec functions, as `builder_finish` won't have its usual effect of discarding
// any new goals added by the spec function.
unimplemented!("MethodSpecBuilder is not supported on this version of crux-mir")
}

pub fn builder_add_arg<T>(msb: MethodSpecBuilder, x: &T) -> MethodSpecBuilder {
let _ = x;
msb
}

pub fn builder_gather_assumes(msb: MethodSpecBuilder) -> MethodSpecBuilder {
msb
}

pub fn builder_set_return<T>(msb: MethodSpecBuilder, x: &T) -> MethodSpecBuilder {
let _ = x;
msb
}

pub fn builder_gather_asserts(msb: MethodSpecBuilder) -> MethodSpecBuilder {
msb
}

pub fn builder_finish(msb: MethodSpecBuilder) -> MethodSpec {
let _ = msb;
MethodSpec(0)
}


/// Replace all mutable global data with arbitrary values. This is used at the start of tests to
/// ensure that the property holds in any context.
pub fn clobber_globals() {
unimplemented!("MethodSpecBuilder is not supported on this version of crux-mir")
}
10 changes: 5 additions & 5 deletions crux-mir/src/Mir/Generate.hs
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,10 @@ needsRebuild output inputs = do
mirJsonOutFile :: FilePath -> FilePath
mirJsonOutFile rustFile = rustFile -<.> "mir"

getRlibsDir :: IO FilePath
getRlibsDir = maybe "rlibs" id <$> lookupEnv "CRUX_RUST_LIBRARY_PATH"
getRlibsDir :: (?defaultRlibsDir :: FilePath) => IO FilePath
getRlibsDir = maybe ?defaultRlibsDir id <$> lookupEnv "CRUX_RUST_LIBRARY_PATH"

compileMirJson :: Bool -> Bool -> FilePath -> IO ()
compileMirJson :: (?defaultRlibsDir :: FilePath) => Bool -> Bool -> FilePath -> IO ()
compileMirJson keepRlib quiet rustFile = do
let outFile = rustFile -<.> "bin"

Expand All @@ -103,7 +103,7 @@ compileMirJson keepRlib quiet rustFile = do
True -> removeFile outFile
False -> return ()

maybeCompileMirJson :: Bool -> Bool -> FilePath -> IO ()
maybeCompileMirJson :: (?defaultRlibsDir :: FilePath) => Bool -> Bool -> FilePath -> IO ()
maybeCompileMirJson keepRlib quiet rustFile = do
build <- needsRebuild (mirJsonOutFile rustFile) [rustFile]
when build $ compileMirJson keepRlib quiet rustFile
Expand Down Expand Up @@ -159,7 +159,7 @@ libJsonFiles =
-- NOTE: If the rust file has not been modified since the
-- last .mir file was created, this function does nothing
-- This function uses 'failIO' if any error occurs
generateMIR :: (HasCallStack, ?debug::Int) =>
generateMIR :: (HasCallStack, ?debug::Int, ?defaultRlibsDir :: FilePath) =>
FilePath -- ^ location of input file
-> Bool -- ^ `True` to keep the generated .rlib
-> IO Collection
Expand Down
Loading