Skip to content

Commit 3e0b2fa

Browse files
committed
Change SwitchTarget representation
The new structure encodes its invariant, which reduces the likelihood of having an inconsistent representation. It is also more intuitive and user friendly. I encapsulated the structure for now in case we decide to change it back.
1 parent 07921b5 commit 3e0b2fa

File tree

4 files changed

+72
-44
lines changed

4 files changed

+72
-44
lines changed

compiler/rustc_smir/src/rustc_smir/convert/mir.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -579,13 +579,12 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
579579
mir::TerminatorKind::SwitchInt { discr, targets } => TerminatorKind::SwitchInt {
580580
discr: discr.stable(tables),
581581
targets: {
582-
let (value_vec, mut target_vec): (Vec<_>, Vec<_>) =
583-
targets.iter().map(|(value, target)| (value, target.as_usize())).unzip();
584-
// We need to push otherwise as last element to ensure it's same as in MIR.
585-
target_vec.push(targets.otherwise().as_usize());
586-
stable_mir::mir::SwitchTargets { value: value_vec, targets: target_vec }
582+
let branches = targets.iter().map(|(val, target)| (val, target.as_usize()));
583+
stable_mir::mir::SwitchTargets::new(
584+
branches.collect(),
585+
targets.otherwise().as_usize(),
586+
)
587587
},
588-
otherwise: targets.otherwise().as_usize(),
589588
},
590589
mir::TerminatorKind::UnwindResume => TerminatorKind::Resume,
591590
mir::TerminatorKind::UnwindTerminate(_) => TerminatorKind::Abort,

compiler/stable_mir/src/mir/body.rs

+58-27
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::ty::{
33
AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, RigidTy, Ty, TyKind,
44
};
55
use crate::{Error, Opaque, Span, Symbol};
6-
use std::{io, slice};
6+
use std::io;
77
/// The SMIR representation of a single function.
88
#[derive(Clone, Debug)]
99
pub struct Body {
@@ -23,6 +23,8 @@ pub struct Body {
2323
pub(super) var_debug_info: Vec<VarDebugInfo>,
2424
}
2525

26+
pub type BasicBlockIdx = usize;
27+
2628
impl Body {
2729
/// Constructs a `Body`.
2830
///
@@ -114,66 +116,64 @@ pub struct Terminator {
114116
}
115117

116118
impl Terminator {
117-
pub fn successors(&self) -> Successors<'_> {
119+
pub fn successors(&self) -> Successors {
118120
self.kind.successors()
119121
}
120122
}
121123

122-
pub type Successors<'a> = impl Iterator<Item = usize> + 'a;
124+
pub type Successors = Vec<BasicBlockIdx>;
123125

124126
#[derive(Clone, Debug, Eq, PartialEq)]
125127
pub enum TerminatorKind {
126128
Goto {
127-
target: usize,
129+
target: BasicBlockIdx,
128130
},
129131
SwitchInt {
130132
discr: Operand,
131133
targets: SwitchTargets,
132-
otherwise: usize,
133134
},
134135
Resume,
135136
Abort,
136137
Return,
137138
Unreachable,
138139
Drop {
139140
place: Place,
140-
target: usize,
141+
target: BasicBlockIdx,
141142
unwind: UnwindAction,
142143
},
143144
Call {
144145
func: Operand,
145146
args: Vec<Operand>,
146147
destination: Place,
147-
target: Option<usize>,
148+
target: Option<BasicBlockIdx>,
148149
unwind: UnwindAction,
149150
},
150151
Assert {
151152
cond: Operand,
152153
expected: bool,
153154
msg: AssertMessage,
154-
target: usize,
155+
target: BasicBlockIdx,
155156
unwind: UnwindAction,
156157
},
157-
CoroutineDrop,
158158
InlineAsm {
159159
template: String,
160160
operands: Vec<InlineAsmOperand>,
161161
options: String,
162162
line_spans: String,
163-
destination: Option<usize>,
163+
destination: Option<BasicBlockIdx>,
164164
unwind: UnwindAction,
165165
},
166166
}
167167

168168
impl TerminatorKind {
169-
pub fn successors(&self) -> Successors<'_> {
169+
pub fn successors(&self) -> Successors {
170170
use self::TerminatorKind::*;
171171
match *self {
172-
Call { target: Some(t), unwind: UnwindAction::Cleanup(ref u), .. }
173-
| Drop { target: t, unwind: UnwindAction::Cleanup(ref u), .. }
174-
| Assert { target: t, unwind: UnwindAction::Cleanup(ref u), .. }
175-
| InlineAsm { destination: Some(t), unwind: UnwindAction::Cleanup(ref u), .. } => {
176-
Some(t).into_iter().chain(slice::from_ref(u).into_iter().copied())
172+
Call { target: Some(t), unwind: UnwindAction::Cleanup(u), .. }
173+
| Drop { target: t, unwind: UnwindAction::Cleanup(u), .. }
174+
| Assert { target: t, unwind: UnwindAction::Cleanup(u), .. }
175+
| InlineAsm { destination: Some(t), unwind: UnwindAction::Cleanup(u), .. } => {
176+
vec![t, u]
177177
}
178178
Goto { target: t }
179179
| Call { target: None, unwind: UnwindAction::Cleanup(t), .. }
@@ -182,21 +182,18 @@ impl TerminatorKind {
182182
| Assert { target: t, unwind: _, .. }
183183
| InlineAsm { destination: None, unwind: UnwindAction::Cleanup(t), .. }
184184
| InlineAsm { destination: Some(t), unwind: _, .. } => {
185-
Some(t).into_iter().chain((&[]).into_iter().copied())
185+
vec![t]
186186
}
187187

188-
CoroutineDrop
189-
| Return
188+
Return
190189
| Resume
191190
| Abort
192191
| Unreachable
193192
| Call { target: None, unwind: _, .. }
194193
| InlineAsm { destination: None, unwind: _, .. } => {
195-
None.into_iter().chain((&[]).into_iter().copied())
196-
}
197-
SwitchInt { ref targets, .. } => {
198-
None.into_iter().chain(targets.targets.iter().copied())
194+
vec![]
199195
}
196+
SwitchInt { ref targets, .. } => targets.all_targets(),
200197
}
201198
}
202199

@@ -205,7 +202,6 @@ impl TerminatorKind {
205202
TerminatorKind::Goto { .. }
206203
| TerminatorKind::Return
207204
| TerminatorKind::Unreachable
208-
| TerminatorKind::CoroutineDrop
209205
| TerminatorKind::Resume
210206
| TerminatorKind::Abort
211207
| TerminatorKind::SwitchInt { .. } => None,
@@ -231,7 +227,7 @@ pub enum UnwindAction {
231227
Continue,
232228
Unreachable,
233229
Terminate,
234-
Cleanup(usize),
230+
Cleanup(BasicBlockIdx),
235231
}
236232

237233
#[derive(Clone, Debug, Eq, PartialEq)]
@@ -662,10 +658,45 @@ pub struct Constant {
662658
pub literal: Const,
663659
}
664660

661+
/// The possible branch sites of a [TerminatorKind::SwitchInt].
665662
#[derive(Clone, Debug, Eq, PartialEq)]
666663
pub struct SwitchTargets {
667-
pub value: Vec<u128>,
668-
pub targets: Vec<usize>,
664+
/// The conditional branches where the first element represents the value that guards this
665+
/// branch, and the second element is the branch target.
666+
branches: Vec<(u128, BasicBlockIdx)>,
667+
/// The `otherwise` branch which will be taken in case none of the conditional branches are
668+
/// satisfied.
669+
otherwise: BasicBlockIdx,
670+
}
671+
672+
impl SwitchTargets {
673+
/// All possible targets including the `otherwise` target.
674+
pub fn all_targets(&self) -> Successors {
675+
Some(self.otherwise)
676+
.into_iter()
677+
.chain(self.branches.iter().map(|(_, target)| *target))
678+
.collect()
679+
}
680+
681+
/// The `otherwise` branch target.
682+
pub fn otherwise(&self) -> BasicBlockIdx {
683+
self.otherwise
684+
}
685+
686+
/// The conditional targets which are only taken if the pattern matches the given value.
687+
pub fn branches(&self) -> impl Iterator<Item = (u128, BasicBlockIdx)> + '_ {
688+
self.branches.iter().copied()
689+
}
690+
691+
/// The number of targets including `otherwise`.
692+
pub fn len(&self) -> usize {
693+
self.branches.len() + 1
694+
}
695+
696+
/// Create a new SwitchTargets from the given branches and `otherwise` target.
697+
pub fn new(branches: Vec<(u128, BasicBlockIdx)>, otherwise: BasicBlockIdx) -> SwitchTargets {
698+
SwitchTargets { branches, otherwise }
699+
}
669700
}
670701

671702
#[derive(Copy, Clone, Debug, Eq, PartialEq)]

compiler/stable_mir/src/mir/pretty.rs

+7-8
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,8 @@ pub fn pretty_statement(statement: &StatementKind) -> String {
7676

7777
pub fn pretty_terminator<W: io::Write>(terminator: &TerminatorKind, w: &mut W) -> io::Result<()> {
7878
write!(w, "{}", pretty_terminator_head(terminator))?;
79-
let successor_count = terminator.successors().count();
79+
let successors = terminator.successors();
80+
let successor_count = successors.len();
8081
let labels = pretty_successor_labels(terminator);
8182

8283
let show_unwind = !matches!(terminator.unwind(), None | Some(UnwindAction::Cleanup(_)));
@@ -98,12 +99,12 @@ pub fn pretty_terminator<W: io::Write>(terminator: &TerminatorKind, w: &mut W) -
9899
Ok(())
99100
}
100101
(1, false) => {
101-
write!(w, " -> {:?}", terminator.successors().next().unwrap())?;
102+
write!(w, " -> {:?}", successors[0])?;
102103
Ok(())
103104
}
104105
_ => {
105106
write!(w, " -> [")?;
106-
for (i, target) in terminator.successors().enumerate() {
107+
for (i, target) in successors.iter().enumerate() {
107108
if i > 0 {
108109
write!(w, ", ")?;
109110
}
@@ -157,20 +158,18 @@ pub fn pretty_terminator_head(terminator: &TerminatorKind) -> String {
157158
pretty.push_str(")");
158159
pretty
159160
}
160-
CoroutineDrop => format!(" coroutine_drop"),
161161
InlineAsm { .. } => todo!(),
162162
}
163163
}
164164

165165
pub fn pretty_successor_labels(terminator: &TerminatorKind) -> Vec<String> {
166166
use self::TerminatorKind::*;
167167
match terminator {
168-
Resume | Abort | Return | Unreachable | CoroutineDrop => vec![],
168+
Resume | Abort | Return | Unreachable => vec![],
169169
Goto { .. } => vec!["".to_string()],
170170
SwitchInt { targets, .. } => targets
171-
.value
172-
.iter()
173-
.map(|target| format!("{}", target))
171+
.branches()
172+
.map(|(val, _target)| format!("{val}"))
174173
.chain(iter::once("otherwise".into()))
175174
.collect(),
176175
Drop { unwind: UnwindAction::Cleanup(_), .. } => vec!["return".into(), "unwind".into()],

compiler/stable_mir/src/mir/visit.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -237,8 +237,7 @@ pub trait MirVisitor {
237237
TerminatorKind::Goto { .. }
238238
| TerminatorKind::Resume
239239
| TerminatorKind::Abort
240-
| TerminatorKind::Unreachable
241-
| TerminatorKind::CoroutineDrop => {}
240+
| TerminatorKind::Unreachable => {}
242241
TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => {
243242
self.visit_operand(cond, location);
244243
self.visit_assert_msg(msg, location);
@@ -268,7 +267,7 @@ pub trait MirVisitor {
268267
let local = RETURN_LOCAL;
269268
self.visit_local(&local, PlaceContext::NON_MUTATING, location);
270269
}
271-
TerminatorKind::SwitchInt { discr, targets: _, otherwise: _ } => {
270+
TerminatorKind::SwitchInt { discr, targets: _ } => {
272271
self.visit_operand(discr, location);
273272
}
274273
}

0 commit comments

Comments
 (0)