@@ -3,7 +3,7 @@ use crate::ty::{
3
3
AdtDef, ClosureDef, Const, CoroutineDef, GenericArgs, Movability, Region, RigidTy, Ty, TyKind,
4
4
};
5
5
use crate::{Error, Opaque, Span, Symbol};
6
- use std::{io, slice} ;
6
+ use std::io ;
7
7
/// The SMIR representation of a single function.
8
8
#[derive(Clone, Debug)]
9
9
pub struct Body {
@@ -23,6 +23,8 @@ pub struct Body {
23
23
pub(super) var_debug_info: Vec<VarDebugInfo>,
24
24
}
25
25
26
+ pub type BasicBlockIdx = usize;
27
+
26
28
impl Body {
27
29
/// Constructs a `Body`.
28
30
///
@@ -114,66 +116,64 @@ pub struct Terminator {
114
116
}
115
117
116
118
impl Terminator {
117
- pub fn successors(&self) -> Successors<'_> {
119
+ pub fn successors(&self) -> Successors {
118
120
self.kind.successors()
119
121
}
120
122
}
121
123
122
- pub type Successors<'a> = impl Iterator<Item = usize> + 'a ;
124
+ pub type Successors = Vec<BasicBlockIdx> ;
123
125
124
126
#[derive(Clone, Debug, Eq, PartialEq)]
125
127
pub enum TerminatorKind {
126
128
Goto {
127
- target: usize ,
129
+ target: BasicBlockIdx ,
128
130
},
129
131
SwitchInt {
130
132
discr: Operand,
131
133
targets: SwitchTargets,
132
- otherwise: usize,
133
134
},
134
135
Resume,
135
136
Abort,
136
137
Return,
137
138
Unreachable,
138
139
Drop {
139
140
place: Place,
140
- target: usize ,
141
+ target: BasicBlockIdx ,
141
142
unwind: UnwindAction,
142
143
},
143
144
Call {
144
145
func: Operand,
145
146
args: Vec<Operand>,
146
147
destination: Place,
147
- target: Option<usize >,
148
+ target: Option<BasicBlockIdx >,
148
149
unwind: UnwindAction,
149
150
},
150
151
Assert {
151
152
cond: Operand,
152
153
expected: bool,
153
154
msg: AssertMessage,
154
- target: usize ,
155
+ target: BasicBlockIdx ,
155
156
unwind: UnwindAction,
156
157
},
157
- CoroutineDrop,
158
158
InlineAsm {
159
159
template: String,
160
160
operands: Vec<InlineAsmOperand>,
161
161
options: String,
162
162
line_spans: String,
163
- destination: Option<usize >,
163
+ destination: Option<BasicBlockIdx >,
164
164
unwind: UnwindAction,
165
165
},
166
166
}
167
167
168
168
impl TerminatorKind {
169
- pub fn successors(&self) -> Successors<'_> {
169
+ pub fn successors(&self) -> Successors {
170
170
use self::TerminatorKind::*;
171
171
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]
177
177
}
178
178
Goto { target: t }
179
179
| Call { target: None, unwind: UnwindAction::Cleanup(t), .. }
@@ -182,21 +182,18 @@ impl TerminatorKind {
182
182
| Assert { target: t, unwind: _, .. }
183
183
| InlineAsm { destination: None, unwind: UnwindAction::Cleanup(t), .. }
184
184
| InlineAsm { destination: Some(t), unwind: _, .. } => {
185
- Some(t).into_iter().chain((&[]).into_iter().copied())
185
+ vec![t]
186
186
}
187
187
188
- CoroutineDrop
189
- | Return
188
+ Return
190
189
| Resume
191
190
| Abort
192
191
| Unreachable
193
192
| Call { target: None, unwind: _, .. }
194
193
| 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![]
199
195
}
196
+ SwitchInt { ref targets, .. } => targets.all_targets(),
200
197
}
201
198
}
202
199
@@ -205,7 +202,6 @@ impl TerminatorKind {
205
202
TerminatorKind::Goto { .. }
206
203
| TerminatorKind::Return
207
204
| TerminatorKind::Unreachable
208
- | TerminatorKind::CoroutineDrop
209
205
| TerminatorKind::Resume
210
206
| TerminatorKind::Abort
211
207
| TerminatorKind::SwitchInt { .. } => None,
@@ -231,7 +227,7 @@ pub enum UnwindAction {
231
227
Continue,
232
228
Unreachable,
233
229
Terminate,
234
- Cleanup(usize ),
230
+ Cleanup(BasicBlockIdx ),
235
231
}
236
232
237
233
#[derive(Clone, Debug, Eq, PartialEq)]
@@ -662,10 +658,42 @@ pub struct Constant {
662
658
pub literal: Const,
663
659
}
664
660
661
+ /// The possible branch sites of a [TerminatorKind::SwitchInt].
665
662
#[derive(Clone, Debug, Eq, PartialEq)]
666
663
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
+ }
669
697
}
670
698
671
699
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
0 commit comments