Skip to content

Commit 47c2155

Browse files
celinvaladpaco-aws
andauthored
Migrate function, block and statement modules to StableMIR (rust-lang#2947)
Migrate these modules to use StableMIR except for calls that depend on the function signature and ABI. Note that we shouldn't really be using function signature as captured here: model-checking/kani#1365. So I suggest that we move to using the FnAbi as soon as we add that to StableMIR. --------- Co-authored-by: Adrian Palacios <[email protected]>
1 parent 64232a0 commit 47c2155

20 files changed

+408
-591
lines changed

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
use crate::codegen_cprover_gotoc::GotocCtx;
2222
use cbmc::goto_program::{Expr, Location, Stmt, Type};
2323
use cbmc::InternedString;
24-
use rustc_span::Span;
2524
use stable_mir::ty::Span as SpanStable;
2625
use std::convert::AsRef;
2726
use strum_macros::{AsRefStr, EnumString};
@@ -149,8 +148,8 @@ impl<'tcx> GotocCtx<'tcx> {
149148
}
150149

151150
/// Generate a cover statement for code coverage reports.
152-
pub fn codegen_coverage(&self, span: Span) -> Stmt {
153-
let loc = self.codegen_caller_span(&span);
151+
pub fn codegen_coverage(&self, span: SpanStable) -> Stmt {
152+
let loc = self.codegen_caller_span_stable(span);
154153
// Should use Stmt::cover, but currently this doesn't work with CBMC
155154
// unless it is run with '--cover cover' (see
156155
// https://github.com/diffblue/cbmc/issues/6613). So for now use

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

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0 OR MIT
33

44
use crate::codegen_cprover_gotoc::GotocCtx;
5-
use rustc_middle::mir::{BasicBlock, BasicBlockData};
6-
use stable_mir::mir::BasicBlockIdx;
5+
use stable_mir::mir::{BasicBlock, BasicBlockIdx};
76
use tracing::debug;
87

98
pub fn bb_label(bb: BasicBlockIdx) -> String {
@@ -17,20 +16,20 @@ impl<'tcx> GotocCtx<'tcx> {
1716
///
1817
/// This function does not return a value, but mutates state with
1918
/// `self.current_fn_mut().push_onto_block(...)`
20-
pub fn codegen_block(&mut self, bb: BasicBlock, bbd: &BasicBlockData<'tcx>) {
21-
debug!(?bb, "Codegen basicblock");
22-
let label: String = self.current_fn().find_label(&bb);
19+
pub fn codegen_block(&mut self, bb: BasicBlockIdx, bbd: &BasicBlock) {
20+
debug!(?bb, "codegen_block");
21+
let label = bb_label(bb);
2322
let check_coverage = self.queries.args().check_coverage;
2423
// the first statement should be labelled. if there is no statements, then the
2524
// terminator should be labelled.
2625
match bbd.statements.len() {
2726
0 => {
28-
let term = bbd.terminator();
27+
let term = &bbd.terminator;
2928
let tcode = self.codegen_terminator(term);
3029
// When checking coverage, the `coverage` check should be
3130
// labelled instead.
3231
if check_coverage {
33-
let span = term.source_info.span;
32+
let span = term.span;
3433
let cover = self.codegen_coverage(span);
3534
self.current_fn_mut().push_onto_block(cover.with_label(label));
3635
self.current_fn_mut().push_onto_block(tcode);
@@ -44,7 +43,7 @@ impl<'tcx> GotocCtx<'tcx> {
4443
// When checking coverage, the `coverage` check should be
4544
// labelled instead.
4645
if check_coverage {
47-
let span = stmt.source_info.span;
46+
let span = stmt.span;
4847
let cover = self.codegen_coverage(span);
4948
self.current_fn_mut().push_onto_block(cover.with_label(label));
5049
self.current_fn_mut().push_onto_block(scode);
@@ -54,16 +53,16 @@ impl<'tcx> GotocCtx<'tcx> {
5453

5554
for s in &bbd.statements[1..] {
5655
if check_coverage {
57-
let span = s.source_info.span;
56+
let span = s.span;
5857
let cover = self.codegen_coverage(span);
5958
self.current_fn_mut().push_onto_block(cover);
6059
}
6160
let stmt = self.codegen_statement(s);
6261
self.current_fn_mut().push_onto_block(stmt);
6362
}
64-
let term = bbd.terminator();
63+
let term = &bbd.terminator;
6564
if check_coverage {
66-
let span = term.source_info.span;
65+
let span = term.span;
6766
let cover = self.codegen_coverage(span);
6867
self.current_fn_mut().push_onto_block(cover);
6968
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ impl<'tcx> GotocCtx<'tcx> {
137137
///
138138
/// This will behave like `codegen_unimplemented_stmt` but print a message that includes
139139
/// the name of the function not supported and the calling convention.
140-
pub fn codegen_ffi_unsupported(&mut self, instance: Instance<'tcx>, loc: Location) -> Stmt {
140+
fn codegen_ffi_unsupported(&mut self, instance: Instance<'tcx>, loc: Location) -> Stmt {
141141
let fn_name = &self.symbol_name(instance);
142142
debug!(?fn_name, ?loc, "codegen_ffi_unsupported");
143143

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

Lines changed: 71 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -7,96 +7,85 @@ use crate::codegen_cprover_gotoc::GotocCtx;
77
use cbmc::goto_program::{Expr, Stmt, Symbol};
88
use cbmc::InternString;
99
use rustc_middle::mir::traversal::reverse_postorder;
10-
use rustc_middle::mir::{Body, HasLocalDecls, Local};
11-
use rustc_middle::ty::{self, Instance};
10+
use stable_mir::mir::mono::Instance;
11+
use stable_mir::mir::{Body, Local};
12+
use stable_mir::ty::{RigidTy, TyKind};
13+
use stable_mir::CrateDef;
1214
use std::collections::BTreeMap;
1315
use std::iter::FromIterator;
1416
use tracing::{debug, debug_span};
1517

1618
/// Codegen MIR functions into gotoc
1719
impl<'tcx> GotocCtx<'tcx> {
18-
/// Get the number of parameters that the current function expects.
19-
fn get_params_size(&self) -> usize {
20-
let sig = self.current_fn().sig();
21-
let sig = self.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig);
22-
// we don't call [codegen_function_sig] because we want to get a bit more metainformation.
23-
sig.inputs().len()
24-
}
25-
2620
/// Declare variables according to their index.
2721
/// - Index 0 represents the return value.
2822
/// - Indices [1, N] represent the function parameters where N is the number of parameters.
2923
/// - Indices that are greater than N represent local variables.
30-
fn codegen_declare_variables(&mut self) {
31-
let mir = self.current_fn().body_internal();
32-
let ldecls = mir.local_decls();
33-
let num_args = self.get_params_size();
34-
ldecls.indices().enumerate().for_each(|(idx, lc)| {
35-
if Some(lc) == mir.spread_arg {
24+
fn codegen_declare_variables(&mut self, body: &Body) {
25+
let ldecls = body.local_decls();
26+
let num_args = body.arg_locals().len();
27+
for (lc, ldata) in ldecls {
28+
if Some(lc) == body.spread_arg() {
3629
// We have already added this local in the function prelude, so
3730
// skip adding it again here.
38-
return;
31+
continue;
3932
}
4033
let base_name = self.codegen_var_base_name(&lc);
4134
let name = self.codegen_var_name(&lc);
42-
let ldata = &ldecls[lc];
43-
let var_ty = self.monomorphize(ldata.ty);
44-
let var_type = self.codegen_ty(var_ty);
45-
let loc = self.codegen_span(&ldata.source_info.span);
35+
let var_type = self.codegen_ty_stable(ldata.ty);
36+
let loc = self.codegen_span_stable(ldata.span);
4637
// Indices [1, N] represent the function parameters where N is the number of parameters.
4738
// Except that ZST fields are not included as parameters.
48-
let sym = Symbol::variable(
49-
name,
50-
base_name,
51-
var_type,
52-
self.codegen_span(&ldata.source_info.span),
53-
)
54-
.with_is_hidden(!self.is_user_variable(&lc))
55-
.with_is_parameter((idx > 0 && idx <= num_args) && !self.is_zst(var_ty));
39+
let sym =
40+
Symbol::variable(name, base_name, var_type, self.codegen_span_stable(ldata.span))
41+
.with_is_hidden(!self.is_user_variable(&lc))
42+
.with_is_parameter((lc > 0 && lc <= num_args) && !self.is_zst_stable(ldata.ty));
5643
let sym_e = sym.to_expr();
5744
self.symbol_table.insert(sym);
5845

5946
// Index 0 represents the return value, which does not need to be
6047
// declared in the first block
61-
if lc.index() < 1 || lc.index() > mir.arg_count {
48+
if lc < 1 || lc > body.arg_locals().len() {
6249
let init = self.codegen_default_initializer(&sym_e);
6350
self.current_fn_mut().push_onto_block(Stmt::decl(sym_e, init, loc));
6451
}
65-
});
52+
}
6653
}
6754

68-
pub fn codegen_function(&mut self, instance: Instance<'tcx>) {
69-
self.set_current_fn(instance);
70-
let name = self.current_fn().name();
55+
pub fn codegen_function(&mut self, instance: Instance) {
56+
let name = self.symbol_name_stable(instance);
7157
let old_sym = self.symbol_table.lookup(&name).unwrap();
7258

73-
let _trace_span =
74-
debug_span!("CodegenFunction", name = self.current_fn().readable_name()).entered();
59+
let _trace_span = debug_span!("CodegenFunction", name = instance.name()).entered();
7560
if old_sym.is_function_definition() {
7661
debug!("Double codegen of {:?}", old_sym);
7762
} else {
7863
assert!(old_sym.is_function());
79-
let mir = self.current_fn().body_internal();
80-
self.print_instance(instance, mir);
81-
self.codegen_function_prelude();
82-
self.codegen_declare_variables();
83-
84-
reverse_postorder(mir).for_each(|(bb, bbd)| self.codegen_block(bb, bbd));
85-
86-
let loc = self.codegen_span(&mir.span);
64+
let body = instance.body().unwrap();
65+
self.set_current_fn(instance, &body);
66+
self.print_instance(instance, &body);
67+
self.codegen_function_prelude(&body);
68+
self.codegen_declare_variables(&body);
69+
70+
// Get the order from internal body for now.
71+
let internal_body = self.current_fn().body_internal();
72+
reverse_postorder(internal_body)
73+
.for_each(|(bb, _)| self.codegen_block(bb.index(), &body.blocks[bb.index()]));
74+
75+
let loc = self.codegen_span_stable(instance.def.span());
8776
let stmts = self.current_fn_mut().extract_block();
88-
let body = Stmt::block(stmts, loc);
89-
self.symbol_table.update_fn_declaration_with_definition(&name, body);
77+
let goto_body = Stmt::block(stmts, loc);
78+
self.symbol_table.update_fn_declaration_with_definition(&name, goto_body);
79+
self.reset_current_fn();
9080
}
91-
self.reset_current_fn();
9281
}
9382

9483
/// Codegen changes required due to the function ABI.
9584
/// We currently untuple arguments for RustCall ABI where the `spread_arg` is set.
96-
fn codegen_function_prelude(&mut self) {
97-
let mir = self.current_fn().body_internal();
98-
if let Some(spread_arg) = mir.spread_arg {
99-
self.codegen_spread_arg(mir, spread_arg);
85+
fn codegen_function_prelude(&mut self, body: &Body) {
86+
debug!(spread_arg=?body.spread_arg(), "codegen_function_prelude");
87+
if let Some(spread_arg) = body.spread_arg() {
88+
self.codegen_spread_arg(body, spread_arg);
10089
}
10190
}
10291

@@ -117,34 +106,27 @@ impl<'tcx> GotocCtx<'tcx> {
117106
///
118107
/// See:
119108
/// <https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/Determine.20untupled.20closure.20args.20from.20Instance.3F>
120-
fn codegen_spread_arg(&mut self, mir: &Body<'tcx>, spread_arg: Local) {
121-
tracing::debug!(current=?self.current_fn, "codegen_spread_arg");
122-
let spread_data = &mir.local_decls()[spread_arg];
123-
let tup_ty = self.monomorphize(spread_data.ty);
124-
if self.is_zst(tup_ty) {
109+
fn codegen_spread_arg(&mut self, body: &Body, spread_arg: Local) {
110+
debug!(current=?self.current_fn().name(), "codegen_spread_arg");
111+
let spread_data = &body.locals()[spread_arg];
112+
let tup_ty = spread_data.ty;
113+
if self.is_zst_stable(tup_ty) {
125114
// No need to spread a ZST since it will be ignored.
126115
return;
127116
}
128117

129-
let loc = self.codegen_span(&spread_data.source_info.span);
118+
let loc = self.codegen_span_stable(spread_data.span);
130119

131120
// Get the function signature from MIR, _before_ we untuple
132-
let fntyp = self.current_fn().instance().ty(self.tcx, ty::ParamEnv::reveal_all());
133-
let sig = match fntyp.kind() {
134-
ty::FnPtr(..) | ty::FnDef(..) => fntyp.fn_sig(self.tcx).skip_binder(),
135-
// Closures themselves will have their arguments already untupled,
136-
// see Zulip link above.
137-
ty::Closure(..) => unreachable!(
138-
"Unexpected `spread arg` set for closure, got: {:?}, {:?}",
139-
fntyp,
140-
self.current_fn().readable_name()
141-
),
142-
_ => unreachable!(
143-
"Expected function type for `spread arg` prelude, got: {:?}, {:?}",
144-
fntyp,
145-
self.current_fn().readable_name()
146-
),
147-
};
121+
let instance = self.current_fn().instance_stable();
122+
// Closures themselves will have their arguments already untupled,
123+
// see Zulip link above.
124+
assert!(
125+
!instance.ty().kind().is_closure(),
126+
"Unexpected spread arg `{}` set for closure `{}`",
127+
spread_arg,
128+
instance.name()
129+
);
148130

149131
// When we codegen the function signature elsewhere, we will codegen the untupled version.
150132
// We then marshall the arguments into a local variable holding the expected tuple.
@@ -166,7 +148,7 @@ impl<'tcx> GotocCtx<'tcx> {
166148
// };
167149
// ```
168150
// Note how the compiler has reordered the fields to improve packing.
169-
let tup_type = self.codegen_ty(tup_ty);
151+
let tup_type = self.codegen_ty_stable(tup_ty);
170152

171153
// We need to marshall the arguments into the tuple
172154
// The arguments themselves have been tacked onto the explicit function paramaters by
@@ -185,21 +167,19 @@ impl<'tcx> GotocCtx<'tcx> {
185167
// }
186168
// ```
187169

188-
let tupe = sig.inputs().last().unwrap();
189-
let args = match tupe.kind() {
190-
ty::Tuple(args) => *args,
191-
_ => unreachable!("a function's spread argument must be a tuple"),
170+
let TyKind::RigidTy(RigidTy::Tuple(args)) = tup_ty.kind() else {
171+
unreachable!("a function's spread argument must be a tuple")
192172
};
193-
let starting_idx = sig.inputs().len();
173+
let starting_idx = spread_arg;
194174
let marshalled_tuple_fields =
195175
BTreeMap::from_iter(args.iter().enumerate().map(|(arg_i, arg_t)| {
196176
// The components come at the end, so offset by the untupled length.
197177
// This follows the naming convention defined in `typ.rs`.
198-
let lc = Local::from_usize(arg_i + starting_idx);
178+
let lc = arg_i + starting_idx;
199179
let (name, base_name) = self.codegen_spread_arg_name(&lc);
200-
let sym = Symbol::variable(name, base_name, self.codegen_ty(arg_t), loc)
180+
let sym = Symbol::variable(name, base_name, self.codegen_ty_stable(*arg_t), loc)
201181
.with_is_hidden(false)
202-
.with_is_parameter(!self.is_zst(arg_t));
182+
.with_is_parameter(!self.is_zst_stable(*arg_t));
203183
// The spread arguments are additional function paramaters that are patched in
204184
// They are to the function signature added in the `fn_typ` function.
205185
// But they were never added to the symbol table, which we currently do here.
@@ -222,19 +202,18 @@ impl<'tcx> GotocCtx<'tcx> {
222202
);
223203
}
224204

225-
pub fn declare_function(&mut self, instance: Instance<'tcx>) {
226-
debug!("declaring {}; {:?}", instance, instance);
227-
self.set_current_fn(instance);
228-
debug!(krate = self.current_fn().krate().as_str());
229-
debug!(is_std = self.current_fn().is_std());
230-
self.ensure(&self.current_fn().name(), |ctx, fname| {
231-
let mir = ctx.current_fn().body_internal();
205+
pub fn declare_function(&mut self, instance: Instance) {
206+
debug!("declaring {}; {:?}", instance.name(), instance);
207+
let body = instance.body().unwrap();
208+
self.set_current_fn(instance, &body);
209+
debug!(krate=?instance.def.krate(), is_std=self.current_fn().is_std(), "declare_function");
210+
self.ensure(&self.symbol_name_stable(instance), |ctx, fname| {
232211
Symbol::function(
233212
fname,
234-
ctx.fn_typ(),
213+
ctx.fn_typ(&body),
235214
None,
236-
ctx.current_fn().readable_name(),
237-
ctx.codegen_span(&mir.span),
215+
instance.name(),
216+
ctx.codegen_span_stable(instance.def.span()),
238217
)
239218
});
240219
self.reset_current_fn();

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ impl<'tcx> GotocCtx<'tcx> {
138138
debug!(?fargs, "codegen_intrinsic");
139139
debug!(?place, "codegen_intrinsic");
140140
debug!(?span, "codegen_intrinsic");
141-
let sig = instance.fn_sig();
141+
let sig = instance.ty().kind().fn_sig().unwrap().skip_binder();
142142
let ret_ty = sig.output();
143143
let farg_types = sig.inputs();
144144
let cbmc_ret_ty = self.codegen_ty_stable(ret_ty);
@@ -414,7 +414,8 @@ impl<'tcx> GotocCtx<'tcx> {
414414
"cttz" => codegen_count_intrinsic!(cttz, true),
415415
"cttz_nonzero" => codegen_count_intrinsic!(cttz, false),
416416
"discriminant_value" => {
417-
let ty = pointee_type_stable(instance.fn_sig().inputs()[0]).unwrap();
417+
let sig = instance.ty().kind().fn_sig().unwrap().skip_binder();
418+
let ty = pointee_type_stable(sig.inputs()[0]).unwrap();
418419
let e = self.codegen_get_discriminant(fargs.remove(0).dereference(), ty, ret_ty);
419420
self.codegen_expr_to_place_stable(place, e)
420421
}

0 commit comments

Comments
 (0)