Skip to content

Commit 65dd5e6

Browse files
committed
Remove the CallKind
We used to have CallKind only because there was a requirement to have all successors in a contiguous memory block. Now that the requirement is gone, remove the CallKind and instead just have the necessary information inline. Awesome!
1 parent 02365fe commit 65dd5e6

File tree

6 files changed

+53
-145
lines changed

6 files changed

+53
-145
lines changed

src/librustc/mir/repr.rs

Lines changed: 20 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -268,71 +268,13 @@ pub enum Terminator<'tcx> {
268268
func: Operand<'tcx>,
269269
/// Arguments the function is called with
270270
args: Vec<Operand<'tcx>>,
271-
/// The kind of call with associated information
272-
kind: CallKind<'tcx>,
271+
/// Destination for the return value. If some, the call is converging.
272+
destination: Option<(Lvalue<'tcx>, BasicBlock)>,
273+
/// Cleanups to be done if the call unwinds.
274+
cleanup: Option<BasicBlock>
273275
},
274276
}
275277

276-
#[derive(Clone, RustcEncodable, RustcDecodable)]
277-
pub enum CallKind<'tcx> {
278-
/// Diverging function without associated cleanup
279-
Diverging,
280-
/// Diverging function with associated cleanup
281-
DivergingCleanup(BasicBlock),
282-
/// Converging function without associated cleanup
283-
Converging {
284-
/// Destination where the call result is written
285-
destination: Lvalue<'tcx>,
286-
/// Block to branch into on successful return
287-
target: BasicBlock,
288-
},
289-
ConvergingCleanup {
290-
/// Destination where the call result is written
291-
destination: Lvalue<'tcx>,
292-
/// First target is branched to on successful return.
293-
/// Second block contains the cleanups to do on unwind.
294-
targets: (BasicBlock, BasicBlock)
295-
}
296-
}
297-
298-
impl<'tcx> CallKind<'tcx> {
299-
pub fn successors(&self) -> &[BasicBlock] {
300-
match *self {
301-
CallKind::Diverging => &[],
302-
CallKind::DivergingCleanup(ref b) |
303-
CallKind::Converging { target: ref b, .. } => slice::ref_slice(b),
304-
CallKind::ConvergingCleanup { ref targets, .. } => targets.as_slice(),
305-
}
306-
}
307-
308-
pub fn successors_mut(&mut self) -> &mut [BasicBlock] {
309-
match *self {
310-
CallKind::Diverging => &mut [],
311-
CallKind::DivergingCleanup(ref mut b) |
312-
CallKind::Converging { target: ref mut b, .. } => slice::mut_ref_slice(b),
313-
CallKind::ConvergingCleanup { ref mut targets, .. } => targets.as_mut_slice(),
314-
}
315-
}
316-
317-
pub fn destination(&self) -> Option<&Lvalue<'tcx>> {
318-
match *self {
319-
CallKind::Converging { ref destination, .. } |
320-
CallKind::ConvergingCleanup { ref destination, .. } => Some(destination),
321-
CallKind::Diverging |
322-
CallKind::DivergingCleanup(_) => None
323-
}
324-
}
325-
326-
pub fn destination_mut(&mut self) -> Option<&mut Lvalue<'tcx>> {
327-
match *self {
328-
CallKind::Converging { ref mut destination, .. } |
329-
CallKind::ConvergingCleanup { ref mut destination, .. } => Some(destination),
330-
CallKind::Diverging |
331-
CallKind::DivergingCleanup(_) => None
332-
}
333-
}
334-
}
335-
336278
impl<'tcx> Terminator<'tcx> {
337279
pub fn successors(&self) -> Cow<[BasicBlock]> {
338280
use self::Terminator::*;
@@ -343,7 +285,11 @@ impl<'tcx> Terminator<'tcx> {
343285
SwitchInt { targets: ref b, .. } => b[..].into_cow(),
344286
Resume => (&[]).into_cow(),
345287
Return => (&[]).into_cow(),
346-
Call { ref kind, .. } => kind.successors()[..].into_cow(),
288+
Call { destination: Some((_, t)), cleanup: Some(c), .. } => vec![t, c].into_cow(),
289+
Call { destination: Some((_, ref t)), cleanup: None, .. } =>
290+
slice::ref_slice(t).into_cow(),
291+
Call { destination: None, cleanup: Some(ref c), .. } => slice::ref_slice(c).into_cow(),
292+
Call { destination: None, cleanup: None, .. } => (&[]).into_cow(),
347293
}
348294
}
349295

@@ -358,7 +304,10 @@ impl<'tcx> Terminator<'tcx> {
358304
SwitchInt { targets: ref mut b, .. } => b.iter_mut().collect(),
359305
Resume => Vec::new(),
360306
Return => Vec::new(),
361-
Call { ref mut kind, .. } => kind.successors_mut().iter_mut().collect(),
307+
Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut c), .. } => vec![t, c],
308+
Call { destination: Some((_, ref mut t)), cleanup: None, .. } => vec![t],
309+
Call { destination: None, cleanup: Some(ref mut c), .. } => vec![c],
310+
Call { destination: None, cleanup: None, .. } => vec![],
362311
}
363312
}
364313
}
@@ -425,8 +374,8 @@ impl<'tcx> Terminator<'tcx> {
425374
SwitchInt { discr: ref lv, .. } => write!(fmt, "switchInt({:?})", lv),
426375
Return => write!(fmt, "return"),
427376
Resume => write!(fmt, "resume"),
428-
Call { ref kind, ref func, ref args } => {
429-
if let Some(destination) = kind.destination() {
377+
Call { ref func, ref args, ref destination, .. } => {
378+
if let Some((ref destination, _)) = *destination {
430379
try!(write!(fmt, "{:?} = ", destination));
431380
}
432381
try!(write!(fmt, "{:?}(", func));
@@ -464,16 +413,11 @@ impl<'tcx> Terminator<'tcx> {
464413
.chain(iter::once(String::from("otherwise").into()))
465414
.collect()
466415
}
467-
Call { ref kind, .. } => match *kind {
468-
CallKind::Diverging =>
469-
vec![],
470-
CallKind::DivergingCleanup(..) =>
471-
vec!["unwind".into_cow()],
472-
CallKind::Converging { .. } =>
473-
vec!["return".into_cow()],
474-
CallKind::ConvergingCleanup { .. } =>
475-
vec!["return".into_cow(), "unwind".into_cow()],
476-
},
416+
Call { destination: Some(_), cleanup: Some(_), .. } =>
417+
vec!["return".into_cow(), "unwind".into_cow()],
418+
Call { destination: Some(_), cleanup: None, .. } => vec!["return".into_cow()],
419+
Call { destination: None, cleanup: Some(_), .. } => vec!["unwind".into_cow()],
420+
Call { destination: None, cleanup: None, .. } => vec![],
477421
}
478422
}
479423
}

src/librustc/mir/visit.rs

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -179,28 +179,17 @@ macro_rules! make_mir_visitor {
179179

180180
Terminator::Call { ref $($mutability)* func,
181181
ref $($mutability)* args,
182-
ref $($mutability)* kind } => {
182+
ref $($mutability)* destination,
183+
ref $($mutability)* cleanup } => {
183184
self.visit_operand(func);
184185
for arg in args {
185186
self.visit_operand(arg);
186187
}
187-
match *kind {
188-
CallKind::Converging {
189-
ref $($mutability)* destination,
190-
..
191-
} |
192-
CallKind::ConvergingCleanup {
193-
ref $($mutability)* destination,
194-
..
195-
} => {
196-
self.visit_lvalue(destination, LvalueContext::Store);
197-
}
198-
CallKind::Diverging |
199-
CallKind::DivergingCleanup(_) => {}
200-
}
201-
for &target in kind.successors() {
188+
if let Some((ref $($mutability)* destination, target)) = *destination {
189+
self.visit_lvalue(destination, LvalueContext::Store);
202190
self.visit_branch(block, target);
203191
}
192+
cleanup.map(|t| self.visit_branch(block, t));
204193
}
205194
}
206195
}

src/librustc_mir/build/expr/into.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -253,17 +253,11 @@ impl<'a,'tcx> Builder<'a,'tcx> {
253253
this.cfg.terminate(block, Terminator::Call {
254254
func: fun,
255255
args: args,
256-
kind: match (cleanup, diverges) {
257-
(None, true) => CallKind::Diverging,
258-
(Some(c), true) => CallKind::DivergingCleanup(c),
259-
(None, false) => CallKind::Converging {
260-
destination: destination.clone(),
261-
target: success
262-
},
263-
(Some(c), false) => CallKind::ConvergingCleanup {
264-
destination: destination.clone(),
265-
targets: (success, c)
266-
}
256+
cleanup: cleanup,
257+
destination: if diverges {
258+
None
259+
} else {
260+
Some ((destination.clone(), success))
267261
}
268262
});
269263
success.unit()

src/librustc_mir/build/scope.rs

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
273273
));
274274
let func = Constant {
275275
span: item.1,
276-
ty: tcx.lookup_item_type(item.0).ty.subst(substs),
276+
ty: tcx.lookup_item_type(item.0).ty,
277277
literal: Literal::Item {
278278
def_id: item.0,
279279
kind: ItemKind::Function,
@@ -285,10 +285,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
285285
self.cfg.terminate(new_block, Terminator::Call {
286286
func: Operand::Constant(func),
287287
args: vec![Operand::Consume(lvalue.clone())],
288-
kind: CallKind::Converging {
289-
target: old_block,
290-
destination: unit_tmp.clone()
291-
}
288+
destination: Some((unit_tmp.clone(), old_block)),
289+
cleanup: None // we’re already doing divergence cleanups
292290
});
293291
terminator = Terminator::Goto { target: new_block };
294292
}
@@ -383,10 +381,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
383381
self.cfg.terminate(block, Terminator::Call {
384382
func: Operand::Constant(func),
385383
args: vec![Operand::Consume(tuple_ref), index, len],
386-
kind: match cleanup {
387-
None => CallKind::Diverging,
388-
Some(c) => CallKind::DivergingCleanup(c)
389-
}
384+
destination: None,
385+
cleanup: cleanup,
390386
});
391387
}
392388

@@ -423,10 +419,8 @@ impl<'a,'tcx> Builder<'a,'tcx> {
423419
self.cfg.terminate(block, Terminator::Call {
424420
func: Operand::Constant(func),
425421
args: vec![Operand::Consume(tuple_ref)],
426-
kind: match cleanup {
427-
None => CallKind::Diverging,
428-
Some(c) => CallKind::DivergingCleanup(c)
429-
}
422+
cleanup: cleanup,
423+
destination: None,
430424
});
431425
}
432426

src/librustc_mir/transform/erase_regions.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ impl<'a, 'tcx> EraseRegions<'a, 'tcx> {
9393
self.erase_regions_lvalue(discr);
9494
*switch_ty = self.tcx.erase_regions(switch_ty);
9595
},
96-
Terminator::Call { ref mut func, ref mut args, ref mut kind } => {
97-
if let Some(destination) = kind.destination_mut() {
96+
Terminator::Call { ref mut func, ref mut args, ref mut destination, .. } => {
97+
if let Some((ref mut destination, _)) = *destination {
9898
self.erase_regions_lvalue(destination);
9999
}
100100
self.erase_regions_operand(func);

src/librustc_trans/trans/mir/block.rs

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
9494
base::build_return_block(bcx.fcx, bcx, return_ty, DebugLoc::None);
9595
}
9696

97-
mir::Terminator::Call { ref func, ref args, ref kind } => {
97+
mir::Terminator::Call { ref func, ref args, ref destination, ref cleanup } => {
9898
// Create the callee. This will always be a fn ptr and hence a kind of scalar.
9999
let callee = self.trans_operand(bcx, func);
100100
let attrs = attributes::from_fn_type(bcx.ccx(), callee.ty);
@@ -115,7 +115,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
115115
};
116116

117117
// Prepare the return value destination
118-
let (ret_dest_ty, must_copy_dest) = if let Some(d) = kind.destination() {
118+
let (ret_dest_ty, must_copy_dest) = if let Some((ref d, _)) = *destination {
119119
let dest = self.trans_lvalue(bcx, d);
120120
let ret_ty = dest.ty.to_ty(bcx.tcx());
121121
if !is_foreign && type_of::return_uses_outptr(bcx.ccx(), ret_ty) {
@@ -144,9 +144,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
144144
}
145145

146146
// Many different ways to call a function handled here
147-
match (is_foreign, base::avoid_invoke(bcx), kind) {
147+
match (is_foreign, base::avoid_invoke(bcx), cleanup, destination) {
148148
// The two cases below are the only ones to use LLVM’s `invoke`.
149-
(false, false, &mir::CallKind::DivergingCleanup(cleanup)) => {
149+
(false, false, &Some(cleanup), &None) => {
150150
let cleanup = self.bcx(cleanup);
151151
let landingpad = self.make_landing_pad(cleanup);
152152
let unreachable_blk = self.unreachable_block();
@@ -158,14 +158,13 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
158158
Some(attrs),
159159
debugloc);
160160
},
161-
(false, false, &mir::CallKind::ConvergingCleanup { ref targets, .. }) => {
162-
let cleanup = self.bcx(targets.1);
161+
(false, false, &Some(cleanup), &Some((_, success))) => {
162+
let cleanup = self.bcx(cleanup);
163163
let landingpad = self.make_landing_pad(cleanup);
164164
let (target, postinvoke) = if must_copy_dest {
165-
(bcx.fcx.new_block("", None),
166-
Some(self.bcx(targets.0)))
165+
(bcx.fcx.new_block("", None), Some(self.bcx(success)))
167166
} else {
168-
(self.bcx(targets.0), None)
167+
(self.bcx(success), None)
169168
};
170169
let invokeret = build::Invoke(bcx,
171170
callee.immediate(),
@@ -205,19 +204,11 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
205204
build::Br(target, postinvoketarget.llbb, debugloc);
206205
}
207206
},
208-
(false, _, &mir::CallKind::DivergingCleanup(_)) |
209-
(false, _, &mir::CallKind::Diverging) => {
207+
(false, _, _, &None) => {
210208
build::Call(bcx, callee.immediate(), &llargs[..], Some(attrs), debugloc);
211209
build::Unreachable(bcx);
212210
}
213-
(false, _, k@&mir::CallKind::ConvergingCleanup { .. }) |
214-
(false, _, k@&mir::CallKind::Converging { .. }) => {
215-
// FIXME: Bug #20046
216-
let target = match *k {
217-
mir::CallKind::ConvergingCleanup { targets, .. } => targets.0,
218-
mir::CallKind::Converging { target, .. } => target,
219-
_ => unreachable!()
220-
};
211+
(false, _, _, &Some((_, target))) => {
221212
let llret = build::Call(bcx,
222213
callee.immediate(),
223214
&llargs[..],
@@ -231,7 +222,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
231222
build::Br(bcx, self.llblock(target), debugloc);
232223
}
233224
// Foreign functions
234-
(true, _, k) => {
225+
(true, _, _, destination) => {
235226
let (dest, _) = ret_dest_ty
236227
.expect("return destination is not set");
237228
bcx = foreign::trans_native_call(bcx,
@@ -241,13 +232,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
241232
&llargs[..],
242233
arg_tys,
243234
debugloc);
244-
match *k {
245-
mir::CallKind::ConvergingCleanup { targets, .. } =>
246-
build::Br(bcx, self.llblock(targets.0), debugloc),
247-
mir::CallKind::Converging { target, .. } =>
248-
build::Br(bcx, self.llblock(target), debugloc),
249-
_ => ()
250-
};
235+
if let Some((_, target)) = *destination {
236+
build::Br(bcx, self.llblock(target), debugloc);
237+
}
251238
},
252239
}
253240
}

0 commit comments

Comments
 (0)