Skip to content

Commit ab6a5ec

Browse files
authored
Add zero-init, and put it behind an unsound feature flag (rust-lang#1521)
1 parent d53296a commit ab6a5ec

File tree

24 files changed

+278
-23
lines changed

24 files changed

+278
-23
lines changed

.github/workflows/kani.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,25 @@ jobs:
3333
- name: Execute Kani regression
3434
run: ./scripts/kani-regression.sh
3535

36+
experimental-features-regression:
37+
runs-on: ubuntu-20.04
38+
env:
39+
KANI_ENABLE_UNSOUND_EXPERIMENTS: 1
40+
steps:
41+
- name: Checkout Kani
42+
uses: actions/checkout@v2
43+
44+
- name: Setup Kani Dependencies
45+
uses: ./.github/actions/setup
46+
with:
47+
os: ubuntu-20.04
48+
49+
- name: Build Kani
50+
run: cargo build
51+
52+
- name: Execute Kani regression
53+
run: ./scripts/kani-regression.sh
54+
3655
perf:
3756
runs-on: ubuntu-20.04
3857
steps:

cprover_bindings/src/goto_program/typ.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,13 +185,13 @@ impl DatatypeComponent {
185185
}
186186

187187
pub fn field<T: Into<InternedString>>(name: T, typ: Type) -> Self {
188+
let name = name.into();
188189
assert!(
189190
Self::typecheck_datatype_field(&typ),
190191
"Illegal field.\n\tName: {}\n\tType: {:?}",
191-
name.into(),
192+
name,
192193
typ
193194
);
194-
let name = name.into();
195195
Field { name, typ }
196196
}
197197

kani-compiler/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ tracing-tree = "0.2.0"
3535
default = ['cprover']
3636
cprover = ['ar', 'bitflags', 'cbmc', 'kani_metadata', 'libc', 'num', 'object', 'rustc-demangle', 'serde',
3737
'serde_json', "strum", "strum_macros"]
38+
unsound_experiments = ["kani_queries/unsound_experiments"]
3839

3940
[package.metadata.rust-analyzer]
4041
# This package uses rustc crates.

kani-compiler/kani_queries/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,8 @@ edition = "2021"
88
license = "MIT OR Apache-2.0"
99
publish = false
1010

11+
[features]
12+
unsound_experiments = []
13+
1114
[dependencies]
1215
tracing = {version = "0.1"}

kani-compiler/kani_queries/src/lib.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,15 @@
33

44
use std::sync::atomic::{AtomicBool, Ordering};
55

6+
#[cfg(feature = "unsound_experiments")]
7+
mod unsound_experiments;
8+
9+
#[cfg(feature = "unsound_experiments")]
10+
use {
11+
crate::unsound_experiments::UnsoundExperiments,
12+
std::sync::{Arc, Mutex},
13+
};
14+
615
pub trait UserInput {
716
fn set_symbol_table_passes(&mut self, passes: Vec<String>);
817
fn get_symbol_table_passes(&self) -> Vec<String>;
@@ -18,6 +27,9 @@ pub trait UserInput {
1827

1928
fn set_ignore_global_asm(&mut self, global_asm: bool);
2029
fn get_ignore_global_asm(&self) -> bool;
30+
31+
#[cfg(feature = "unsound_experiments")]
32+
fn get_unsound_experiments(&self) -> Arc<Mutex<UnsoundExperiments>>;
2133
}
2234

2335
#[derive(Debug, Default)]
@@ -27,6 +39,8 @@ pub struct QueryDb {
2739
symbol_table_passes: Vec<String>,
2840
json_pretty_print: AtomicBool,
2941
ignore_global_asm: AtomicBool,
42+
#[cfg(feature = "unsound_experiments")]
43+
unsound_experiments: Arc<Mutex<UnsoundExperiments>>,
3044
}
3145

3246
impl UserInput for QueryDb {
@@ -69,4 +83,9 @@ impl UserInput for QueryDb {
6983
fn get_ignore_global_asm(&self) -> bool {
7084
self.ignore_global_asm.load(Ordering::Relaxed)
7185
}
86+
87+
#[cfg(feature = "unsound_experiments")]
88+
fn get_unsound_experiments(&self) -> Arc<Mutex<UnsoundExperiments>> {
89+
self.unsound_experiments.clone()
90+
}
7291
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Copyright Kani Contributors
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
#![cfg(feature = "unsound_experiments")]
5+
6+
#[derive(Debug, Default)]
7+
pub struct UnsoundExperiments {
8+
/// Zero initilize variables.
9+
/// This is useful for experiments to see whether assigning constant values produces better
10+
/// performance by allowing CBMC to do more constant propegation.
11+
/// Unfortunatly, it is unsafe to use for production code, since it may unsoundly hide bugs.
12+
pub zero_init_vars: bool,
13+
}

kani-compiler/src/codegen_cprover_gotoc/codegen/function.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ impl<'tcx> GotocCtx<'tcx> {
7777
// Index 0 represents the return value, which does not need to be
7878
// declared in the first block
7979
if lc.index() < 1 || lc.index() > mir.arg_count {
80-
self.current_fn_mut().push_onto_block(Stmt::decl(sym_e, None, loc));
80+
let init = self.codegen_default_initializer(&sym_e);
81+
self.current_fn_mut().push_onto_block(Stmt::decl(sym_e, init, loc));
8182
}
8283
});
8384
}

kani-compiler/src/codegen_cprover_gotoc/codegen/statement.rs

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -56,23 +56,7 @@ impl<'tcx> GotocCtx<'tcx> {
5656
.assign(self.codegen_rvalue(r, location), location)
5757
}
5858
}
59-
StatementKind::Deinit(place) => {
60-
// From rustc doc: "This writes `uninit` bytes to the entire place."
61-
// Our model of GotoC has a similar statement, which is later lowered
62-
// to assigning a Nondet in CBMC, with a comment specifying that it
63-
// corresponds to a Deinit.
64-
let dst_mir_ty = self.place_ty(place);
65-
let dst_type = self.codegen_ty(dst_mir_ty);
66-
let layout = self.layout_of(dst_mir_ty);
67-
if layout.is_zst() || dst_type.sizeof_in_bits(&self.symbol_table) == 0 {
68-
// We ignore assignment for all zero size types
69-
Stmt::skip(location)
70-
} else {
71-
unwrap_or_return_codegen_unimplemented_stmt!(self, self.codegen_place(place))
72-
.goto_expr
73-
.deinit(location)
74-
}
75-
}
59+
StatementKind::Deinit(place) => self.codegen_deinit(place, location),
7660
StatementKind::SetDiscriminant { place, variant_index } => {
7761
// this requires place points to an enum type.
7862
let pt = self.place_ty(place);
@@ -277,6 +261,25 @@ impl<'tcx> GotocCtx<'tcx> {
277261
}
278262
}
279263

264+
/// From rustc doc: "This writes `uninit` bytes to the entire place."
265+
/// Our model of GotoC has a similar statement, which is later lowered
266+
/// to assigning a Nondet in CBMC, with a comment specifying that it
267+
/// corresponds to a Deinit.
268+
#[cfg(not(feature = "unsound_experiments"))]
269+
fn codegen_deinit(&mut self, place: &Place<'tcx>, loc: Location) -> Stmt {
270+
let dst_mir_ty = self.place_ty(place);
271+
let dst_type = self.codegen_ty(dst_mir_ty);
272+
let layout = self.layout_of(dst_mir_ty);
273+
if layout.is_zst() || dst_type.sizeof_in_bits(&self.symbol_table) == 0 {
274+
// We ignore assignment for all zero size types
275+
Stmt::skip(loc)
276+
} else {
277+
unwrap_or_return_codegen_unimplemented_stmt!(self, self.codegen_place(place))
278+
.goto_expr
279+
.deinit(loc)
280+
}
281+
}
282+
280283
/// A special case handler to codegen `return ();`
281284
fn codegen_ret_unit(&mut self) -> Stmt {
282285
let is_file_local = false;

kani-compiler/src/codegen_cprover_gotoc/codegen/typ.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,15 @@ impl<'tcx> GotocCtx<'tcx> {
676676
Type::struct_tag(name)
677677
}
678678

679+
/// Codegens the an initalizer for variables without one.
680+
/// By default, returns `None` which leaves the variable uninitilized.
681+
/// In CBMC, this translates to a NONDET value.
682+
/// In the future, we might want to replace this with `Poison`.
683+
#[cfg(not(feature = "unsound_experiments"))]
684+
pub fn codegen_default_initializer(&self, _e: &Expr) -> Option<Expr> {
685+
None
686+
}
687+
679688
/// The unit type in Rust is an empty struct in gotoc
680689
pub fn codegen_ty_unit(&mut self) -> Type {
681690
self.ensure_struct(UNIT_TYPE_EMPTY_STRUCT_NAME, "()", |_, _| vec![])

kani-compiler/src/codegen_cprover_gotoc/context/goto_ctx.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ impl<'tcx> GotocCtx<'tcx> {
161161
let c = self.current_fn_mut().get_and_incr_counter();
162162
let var =
163163
self.gen_stack_variable(c, &self.current_fn().name(), "temp", t, loc, false).to_expr();
164+
let value = value.or_else(|| self.codegen_default_initializer(&var));
164165
let decl = Stmt::decl(var.clone(), value, loc);
165166
(var, decl)
166167
}

0 commit comments

Comments
 (0)