Skip to content

Commit c263ccf

Browse files
committed
Auto merge of #118461 - celinval:smir-switch-targets, r=ouz-a
Change `SwitchTarget` representation in StableMIR 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. ### Notes: 1. I had to change the `Successors` type, since there's a conflict on the iterator type. We could potentially implement an iterator here, but I would prefer keeping it simple for now, and add a `successors_iter()` method if needed. 2. I removed `CoroutineDrop` for now since it we never create it. We can add it when we add support to other MIR stages.
2 parents 1d726a2 + 9d2c923 commit c263ccf

File tree

4 files changed

+69
-44
lines changed

4 files changed

+69
-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

+55-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,42 @@ 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+
self.branches.iter().map(|(_, target)| *target).chain(Some(self.otherwise)).collect()
676+
}
677+
678+
/// The `otherwise` branch target.
679+
pub fn otherwise(&self) -> BasicBlockIdx {
680+
self.otherwise
681+
}
682+
683+
/// The conditional targets which are only taken if the pattern matches the given value.
684+
pub fn branches(&self) -> impl Iterator<Item = (u128, BasicBlockIdx)> + '_ {
685+
self.branches.iter().copied()
686+
}
687+
688+
/// The number of targets including `otherwise`.
689+
pub fn len(&self) -> usize {
690+
self.branches.len() + 1
691+
}
692+
693+
/// Create a new SwitchTargets from the given branches and `otherwise` target.
694+
pub fn new(branches: Vec<(u128, BasicBlockIdx)>, otherwise: BasicBlockIdx) -> SwitchTargets {
695+
SwitchTargets { branches, otherwise }
696+
}
669697
}
670698

671699
#[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)