Skip to content

Commit

Permalink
Call goto-instrument with DFCC only once (#3642)
Browse files Browse the repository at this point in the history
DFCC should be called only once. This PR combined the two DCFF calls
into one.

By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 and MIT licenses.
  • Loading branch information
qinheping authored Oct 25, 2024
1 parent a8a28ee commit ab2cb50
Showing 1 changed file with 40 additions and 40 deletions.
80 changes: 40 additions & 40 deletions kani-driver/src/call_goto_instrument.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,12 @@ impl KaniSession {
self.goto_sanity_check(output)?;
}

self.instrument_contracts(harness, output)?;

if self
let is_loop_contracts_enabled = self
.args
.common_args
.unstable_features
.contains(kani_metadata::UnstableFeature::LoopContracts)
{
self.instrument_loop_contracts(harness, output)?;
}
.contains(kani_metadata::UnstableFeature::LoopContracts);
self.instrument_contracts(harness, is_loop_contracts_enabled, output)?;

if self.args.checks.undefined_function_on() {
self.add_library(output)?;
Expand Down Expand Up @@ -172,42 +168,46 @@ impl KaniSession {
self.call_goto_instrument(args)
}

/// Make CBMC enforce a function contract.
pub fn instrument_contracts(&self, harness: &HarnessMetadata, file: &Path) -> Result<()> {
let Some(assigns) = harness.contract.as_ref() else { return Ok(()) };
/// Apply annotated function contracts and loop contracts with goto-instrument.
pub fn instrument_contracts(
&self,
harness: &HarnessMetadata,
is_loop_contracts_enabled: bool,
file: &Path,
) -> Result<()> {
// Do nothing if neither loop contracts nor function contracts is enabled.
if !is_loop_contracts_enabled && harness.contract.is_none() {
return Ok(());
}

let mut args: Vec<OsString> = vec![
"--dfcc".into(),
(&harness.mangled_name).into(),
"--enforce-contract".into(),
assigns.contracted_function_name.as_str().into(),
"--no-malloc-may-fail".into(),
file.into(),
file.into(),
];
if let Some(tracker) = &assigns.recursion_tracker {
args.push("--nondet-static-exclude".into());
args.push(tracker.as_str().into());
let mut args: Vec<OsString> =
vec!["--dfcc".into(), (&harness.mangled_name).into(), "--no-malloc-may-fail".into()];

if is_loop_contracts_enabled {
args.append(&mut vec![
"--apply-loop-contracts".into(),
"--loop-contracts-no-unwind".into(),
// Because loop contracts now are wrapped in a closure which will be a side-effect expression in CBMC even they
// may not contain side-effect. So we disable the side-effect check for now and will implement a better check
// instead of simply rejecting function calls and statement expressions.
// See issue: diffblue/cbmc#8393
"--disable-loop-contracts-side-effect-check".into(),
]);
}
self.call_goto_instrument(&args)
}

/// Apply annotated loop contracts.
pub fn instrument_loop_contracts(&self, harness: &HarnessMetadata, file: &Path) -> Result<()> {
let args: Vec<OsString> = vec![
"--dfcc".into(),
(&harness.mangled_name).into(),
"--apply-loop-contracts".into(),
"--loop-contracts-no-unwind".into(),
"--no-malloc-may-fail".into(),
// Because loop contracts now are wrapped in a closure which will be a side-effect expression in CBMC even they
// may not contain side-effect. So we disable the side-effect check for now and will implement a better check
// instead of simply rejecting function calls and statement expressions.
// See issue: diffblue/cbmc#8393
"--disable-loop-contracts-side-effect-check".into(),
file.into(),
file.into(),
];
if let Some(assigns) = harness.contract.as_ref() {
args.push("--enforce-contract".into());
args.push(assigns.contracted_function_name.as_str().into());

if let Some(tracker) = &assigns.recursion_tracker {
args.push("--nondet-static-exclude".into());
args.push(tracker.as_str().into());
}
}

args.push(file.into());
args.push(file.into());

self.call_goto_instrument(&args)
}

Expand Down

0 comments on commit ab2cb50

Please sign in to comment.