Skip to content

Commit 893a66d

Browse files
committed
Split Call into Call and DivergingCall
DivergingCall is different enough from the regular converging Call to warrant the split. This also inlines CallData struct and creates a new CallTargets enum in order to have a way to differentiate between calls that do not have an associated cleanup block. Note, that this patch still does not produce DivergingCall terminator anywhere. Look for that in the next patches.
1 parent 7312e0a commit 893a66d

File tree

5 files changed

+113
-57
lines changed

5 files changed

+113
-57
lines changed

src/librustc/mir/repr.rs

Lines changed: 65 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -256,13 +256,51 @@ pub enum Terminator<'tcx> {
256256
/// `END_BLOCK`.
257257
Return,
258258

259-
/// block ends with a call; it should have two successors. The
260-
/// first successor indicates normal return. The second indicates
261-
/// unwinding.
259+
/// Block ends with a call of a converging function
262260
Call {
263-
data: CallData<'tcx>,
264-
targets: (BasicBlock, BasicBlock),
261+
/// The function that’s being called
262+
func: Operand<'tcx>,
263+
/// Arguments the function is called with
264+
args: Vec<Operand<'tcx>>,
265+
/// Location to write the return value into
266+
destination: Lvalue<'tcx>,
267+
targets: CallTargets,
265268
},
269+
270+
/// Block ends with a call of a diverging function.
271+
DivergingCall {
272+
/// The function that’s being called
273+
func: Operand<'tcx>,
274+
/// Arguments the function is called with
275+
args: Vec<Operand<'tcx>>,
276+
/// Some, if there’s any cleanup to be done when function unwinds
277+
cleanup: Option<BasicBlock>,
278+
}
279+
}
280+
281+
#[derive(RustcEncodable, RustcDecodable)]
282+
pub enum CallTargets {
283+
/// The only target that should be entered when function returns normally.
284+
Return(BasicBlock),
285+
/// In addition to the normal-return block, function has associated cleanup that should be done
286+
/// when function unwinds.
287+
WithCleanup((BasicBlock, BasicBlock))
288+
}
289+
290+
impl CallTargets {
291+
pub fn as_slice(&self) -> &[BasicBlock] {
292+
match *self {
293+
CallTargets::Return(ref b) => slice::ref_slice(b),
294+
CallTargets::WithCleanup(ref bs) => bs.as_slice()
295+
}
296+
}
297+
298+
pub fn as_mut_slice(&mut self) -> &mut [BasicBlock] {
299+
match *self {
300+
CallTargets::Return(ref mut b) => slice::mut_ref_slice(b),
301+
CallTargets::WithCleanup(ref mut bs) => bs.as_mut_slice()
302+
}
303+
}
266304
}
267305

268306
impl<'tcx> Terminator<'tcx> {
@@ -271,12 +309,17 @@ impl<'tcx> Terminator<'tcx> {
271309
match *self {
272310
Goto { target: ref b } => slice::ref_slice(b),
273311
Panic { target: ref b } => slice::ref_slice(b),
274-
If { cond: _, targets: ref b } => b.as_slice(),
312+
If { targets: ref b, .. } => b.as_slice(),
275313
Switch { targets: ref b, .. } => b,
276314
SwitchInt { targets: ref b, .. } => b,
277315
Diverge => &[],
278316
Return => &[],
279-
Call { data: _, targets: ref b } => b.as_slice(),
317+
Call { targets: ref b, .. } => b.as_slice(),
318+
DivergingCall { cleanup: ref b, .. } => if let Some(b) = b.as_ref() {
319+
slice::ref_slice(b)
320+
} else {
321+
&mut []
322+
},
280323
}
281324
}
282325

@@ -285,28 +328,21 @@ impl<'tcx> Terminator<'tcx> {
285328
match *self {
286329
Goto { target: ref mut b } => slice::mut_ref_slice(b),
287330
Panic { target: ref mut b } => slice::mut_ref_slice(b),
288-
If { cond: _, targets: ref mut b } => b.as_mut_slice(),
331+
If { targets: ref mut b, .. } => b.as_mut_slice(),
289332
Switch { targets: ref mut b, .. } => b,
290333
SwitchInt { targets: ref mut b, .. } => b,
291334
Diverge => &mut [],
292335
Return => &mut [],
293-
Call { data: _, targets: ref mut b } => b.as_mut_slice(),
336+
Call { targets: ref mut b, .. } => b.as_mut_slice(),
337+
DivergingCall { cleanup: ref mut b, .. } => if let Some(b) = b.as_mut() {
338+
slice::mut_ref_slice(b)
339+
} else {
340+
&mut []
341+
},
294342
}
295343
}
296344
}
297345

298-
#[derive(Debug, RustcEncodable, RustcDecodable)]
299-
pub struct CallData<'tcx> {
300-
/// where the return value is written to
301-
pub destination: Lvalue<'tcx>,
302-
303-
/// the fn being called
304-
pub func: Operand<'tcx>,
305-
306-
/// the arguments
307-
pub args: Vec<Operand<'tcx>>,
308-
}
309-
310346
impl<'tcx> BasicBlockData<'tcx> {
311347
pub fn new(terminator: Terminator<'tcx>) -> BasicBlockData<'tcx> {
312348
BasicBlockData {
@@ -357,15 +393,13 @@ impl<'tcx> Terminator<'tcx> {
357393
SwitchInt { discr: ref lv, .. } => write!(fmt, "switchInt({:?})", lv),
358394
Diverge => write!(fmt, "diverge"),
359395
Return => write!(fmt, "return"),
360-
Call { data: ref c, .. } => {
361-
try!(write!(fmt, "{:?} = {:?}(", c.destination, c.func));
362-
for (index, arg) in c.args.iter().enumerate() {
363-
if index > 0 {
364-
try!(write!(fmt, ", "));
365-
}
366-
try!(write!(fmt, "{:?}", arg));
367-
}
368-
write!(fmt, ")")
396+
Call { .. } => {
397+
// the author didn’t bother rebasing this
398+
unimplemented!()
399+
},
400+
DivergingCall { .. } => {
401+
// the author didn’t bother rebasing this
402+
unimplemented!()
369403
}
370404
}
371405
}
@@ -378,6 +412,7 @@ impl<'tcx> Terminator<'tcx> {
378412
Goto { .. } | Panic { .. } => vec!["".into_cow()],
379413
If { .. } => vec!["true".into_cow(), "false".into_cow()],
380414
Call { .. } => vec!["return".into_cow(), "unwind".into_cow()],
415+
DivergingCall { .. } => vec!["unwind".into_cow()],
381416
Switch { ref adt_def, .. } => {
382417
adt_def.variants
383418
.iter()

src/librustc/mir/visit.rs

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -137,16 +137,26 @@ pub trait Visitor<'tcx> {
137137
Terminator::Return => {
138138
}
139139

140-
Terminator::Call { ref data, ref targets } => {
141-
self.visit_lvalue(&data.destination, LvalueContext::Store);
142-
self.visit_operand(&data.func);
143-
for arg in &data.args {
140+
Terminator::Call { ref func, ref args, ref destination, ref targets } => {
141+
self.visit_lvalue(destination, LvalueContext::Store);
142+
self.visit_operand(func);
143+
for arg in args {
144144
self.visit_operand(arg);
145145
}
146146
for &target in targets.as_slice() {
147147
self.visit_branch(block, target);
148148
}
149149
}
150+
151+
Terminator::DivergingCall { ref func, ref args, ref cleanup } => {
152+
self.visit_operand(func);
153+
for arg in args {
154+
self.visit_operand(arg);
155+
}
156+
for &target in cleanup.as_ref() {
157+
self.visit_branch(block, target);
158+
}
159+
}
150160
}
151161
}
152162

@@ -424,16 +434,29 @@ pub trait MutVisitor<'tcx> {
424434
Terminator::Return => {
425435
}
426436

427-
Terminator::Call { ref mut data, ref mut targets } => {
428-
self.visit_lvalue(&mut data.destination, LvalueContext::Store);
429-
self.visit_operand(&mut data.func);
430-
for arg in &mut data.args {
437+
Terminator::Call { ref mut func,
438+
ref mut args,
439+
ref mut destination,
440+
ref mut targets } => {
441+
self.visit_lvalue(destination, LvalueContext::Store);
442+
self.visit_operand(func);
443+
for arg in args {
431444
self.visit_operand(arg);
432445
}
433446
for &target in targets.as_slice() {
434447
self.visit_branch(block, target);
435448
}
436449
}
450+
451+
Terminator::DivergingCall { ref mut func, ref mut args, ref mut cleanup } => {
452+
self.visit_operand(func);
453+
for arg in args {
454+
self.visit_operand(arg);
455+
}
456+
for &target in cleanup.as_ref() {
457+
self.visit_branch(block, target);
458+
}
459+
}
437460
}
438461
}
439462

src/librustc_mir/build/expr/into.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -218,14 +218,13 @@ impl<'a,'tcx> Builder<'a,'tcx> {
218218
.collect();
219219
let success = this.cfg.start_new_block();
220220
let panic = this.diverge_cleanup();
221+
let targets = CallTargets::WithCleanup((success, panic));
221222
this.cfg.terminate(block,
222223
Terminator::Call {
223-
data: CallData {
224-
destination: destination.clone(),
225-
func: fun,
226-
args: args,
227-
},
228-
targets: (success, panic),
224+
func: fun,
225+
args: args,
226+
destination: destination.clone(),
227+
targets: targets
229228
});
230229
success.unit()
231230
}

src/librustc_mir/transform/erase_regions.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -90,28 +90,23 @@ impl<'a, 'tcx> EraseRegions<'a, 'tcx> {
9090
Terminator::Switch { ref mut discr, .. } => {
9191
self.erase_regions_lvalue(discr);
9292
}
93-
Terminator::SwitchInt {
94-
ref mut discr,
95-
ref mut switch_ty,
96-
..
97-
} => {
93+
Terminator::SwitchInt { ref mut discr, ref mut switch_ty, .. } => {
9894
self.erase_regions_lvalue(discr);
9995
*switch_ty = self.tcx.erase_regions(switch_ty);
10096
},
101-
Terminator::Call {
102-
data: CallData {
103-
ref mut destination,
104-
ref mut func,
105-
ref mut args
106-
},
107-
..
108-
} => {
97+
Terminator::Call { ref mut destination, ref mut func, ref mut args, .. } => {
10998
self.erase_regions_lvalue(destination);
11099
self.erase_regions_operand(func);
111100
for arg in &mut *args {
112101
self.erase_regions_operand(arg);
113102
}
114103
}
104+
Terminator::DivergingCall { ref mut func, ref mut args, .. } => {
105+
self.erase_regions_operand(func);
106+
for arg in &mut *args {
107+
self.erase_regions_operand(arg);
108+
}
109+
}
115110
}
116111
}
117112

src/librustc_trans/trans/mir/block.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
164164
}
165165

166166
build::Br(bcx, self.llblock(targets.0), DebugLoc::None)
167+
},
168+
169+
mir::Terminator::DivergingCall { .. } => {
170+
unimplemented!()
167171
}
168172
}
169173
}

0 commit comments

Comments
 (0)