Skip to content

Commit dc04fc7

Browse files
celinvaltedinski
authored andcommitted
Revert change to rustc SwitchTargets type. (rust-lang#710)
We have changed the visibility of one of the members of SwitchTargets to have access to their values during codegen. I re-wrote the code to use standard API so we don't need to keep using a forked version of the compiler. Issue rust-lang#42. The only changes left are the ones to enable rmc codegen and a a few options we enabled. Those should be handled once we have a new driver.
1 parent 380d917 commit dc04fc7

File tree

3 files changed

+66
-54
lines changed

3 files changed

+66
-54
lines changed

compiler/rustc_codegen_rmc/src/codegen/statement.rs

Lines changed: 36 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,9 @@ impl<'tcx> GotocCtx<'tcx> {
4040
TerminatorKind::Goto { target } => {
4141
Stmt::goto(self.current_fn().find_label(target), loc)
4242
}
43-
TerminatorKind::SwitchInt { discr, switch_ty, targets } => match targets {
44-
SwitchTargets { values, .. } => {
45-
let all_targets = targets.all_targets();
46-
self.codegen_switch_int(discr, switch_ty, values, all_targets)
47-
}
48-
},
43+
TerminatorKind::SwitchInt { discr, switch_ty, targets } => {
44+
self.codegen_switch_int(discr, switch_ty, targets)
45+
}
4946
TerminatorKind::Resume => Stmt::assert_false("resume instruction", loc),
5047
TerminatorKind::Abort => Stmt::assert_false("abort instruction", loc),
5148
TerminatorKind::Return => {
@@ -206,62 +203,48 @@ impl<'tcx> GotocCtx<'tcx> {
206203
&mut self,
207204
discr: &Operand<'tcx>,
208205
switch_ty: Ty<'tcx>,
209-
values: &SmallVec<[u128; 1]>,
210-
targets: &[BasicBlock],
206+
targets: &SwitchTargets,
211207
) -> Stmt {
212-
assert_eq!(targets.len(), values.len() + 1);
213-
214208
let v = self.codegen_operand(discr);
215209
let switch_ty = self.monomorphize(switch_ty);
216-
match switch_ty.kind() {
217-
//TODO, can replace with guarded goto
218-
ty::Bool => {
219-
let jmp: usize = values[0].try_into().unwrap();
220-
let jmp2 = if jmp == 0 { 1 } else { 0 };
221-
Stmt::block(
222-
vec![
223-
v.cast_to(Type::bool()).if_then_else(
210+
if targets.all_targets().len() == 1 {
211+
// Translate to a guarded goto
212+
let first_target = targets.iter().next().unwrap();
213+
Stmt::block(
214+
vec![
215+
v.eq(Expr::int_constant(first_target.0, self.codegen_ty(switch_ty)))
216+
.if_then_else(
224217
Stmt::goto(
225-
self.current_fn().labels()[targets[jmp2].index()].clone(),
218+
self.current_fn().labels()[first_target.1.index()].clone(),
226219
Location::none(),
227220
),
228221
None,
229222
Location::none(),
230223
),
231-
Stmt::goto(
232-
self.current_fn().labels()[targets[jmp].index()].clone(),
233-
Location::none(),
234-
),
235-
],
236-
Location::none(),
237-
)
238-
}
239-
ty::Char | ty::Int(_) | ty::Uint(_) => {
240-
let cases = values
241-
.iter()
242-
.enumerate()
243-
.map(|(i, idx)| {
244-
let bb = &targets[i];
245-
Expr::int_constant(*idx, self.codegen_ty(switch_ty)).switch_case(
246-
Stmt::goto(
247-
self.current_fn().labels()[bb.index()].clone(),
248-
Location::none(),
249-
),
250-
)
251-
})
252-
.collect();
253-
let default = Stmt::goto(
254-
self.current_fn().labels()[targets[values.len()].index()].clone(),
255-
Location::none(),
256-
);
257-
v.switch(cases, Some(default), Location::none())
258-
}
259-
x => {
260-
unreachable!(
261-
"Unexpected switch_ty {:?}\n{:?}\n{:?}\n{:?}\n{:?}\n{:?}",
262-
discr, switch_ty, values, targets, v, x
263-
)
264-
}
224+
Stmt::goto(
225+
self.current_fn().labels()[targets.otherwise().index()].clone(),
226+
Location::none(),
227+
),
228+
],
229+
Location::none(),
230+
)
231+
} else {
232+
// Switches with empty targets should've been eliminated already.
233+
assert!(targets.all_targets().len() > 1);
234+
let cases = targets
235+
.iter()
236+
.map(|(c, bb)| {
237+
Expr::int_constant(c, self.codegen_ty(switch_ty)).switch_case(Stmt::goto(
238+
self.current_fn().labels()[bb.index()].clone(),
239+
Location::none(),
240+
))
241+
})
242+
.collect();
243+
let default = Stmt::goto(
244+
self.current_fn().labels()[targets.otherwise().index()].clone(),
245+
Location::none(),
246+
);
247+
v.switch(cases, Some(default), Location::none())
265248
}
266249
}
267250

compiler/rustc_middle/src/mir/terminator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub use super::query::*;
2121
pub struct SwitchTargets {
2222
/// Possible values. The locations to branch to in each case
2323
/// are found in the corresponding indices from the `targets` vector.
24-
pub values: SmallVec<[u128; 1]>,
24+
values: SmallVec<[u128; 1]>,
2525

2626
/// Possible branch sites. The last element of this vector is used
2727
/// for the otherwise branch, so targets.len() == values.len() + 1

src/test/rmc/Match/match_bool.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
// compile-flags: --crate-type lib
4+
// rmc-flags: --function match_bool
5+
6+
#[rmc::proof]
7+
pub fn match_bool() {
8+
let arg: bool = rmc::nondet();
9+
let var = match arg {
10+
true => !arg,
11+
_ => arg,
12+
};
13+
14+
let var2 = match arg {
15+
_ => false,
16+
};
17+
18+
assert!(var == var2);
19+
20+
let mut i = 0;
21+
22+
match arg {
23+
true => i = 1,
24+
false => i = 2,
25+
_ => i = 3,
26+
}
27+
28+
assert!(i == 1 || i == 2);
29+
}

0 commit comments

Comments
 (0)