Skip to content

Commit 24c1a07

Browse files
committed
refactor trans::mir::block to trans all calls through the same code
1 parent 9da2aac commit 24c1a07

File tree

2 files changed

+84
-67
lines changed

2 files changed

+84
-67
lines changed

src/librustc_trans/abi.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use llvm::{self, ValueRef, AttributePlace};
1212
use base;
1313
use builder::Builder;
14-
use common::{type_is_fat_ptr, C_uint};
14+
use common::{instance_ty, ty_fn_sig, type_is_fat_ptr, C_uint};
1515
use context::CrateContext;
1616
use cabi_x86;
1717
use cabi_x86_64;
@@ -610,6 +610,14 @@ pub struct FnType<'tcx> {
610610
}
611611

612612
impl<'a, 'tcx> FnType<'tcx> {
613+
pub fn of_instance(ccx: &CrateContext<'a, 'tcx>, instance: &ty::Instance<'tcx>)
614+
-> Self {
615+
let fn_ty = instance_ty(ccx.shared(), &instance);
616+
let sig = ty_fn_sig(ccx, fn_ty);
617+
let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&sig);
618+
Self::new(ccx, sig, &[])
619+
}
620+
613621
pub fn new(ccx: &CrateContext<'a, 'tcx>,
614622
sig: ty::FnSig<'tcx>,
615623
extra_args: &[Ty<'tcx>]) -> FnType<'tcx> {
@@ -631,6 +639,8 @@ impl<'a, 'tcx> FnType<'tcx> {
631639
pub fn unadjusted(ccx: &CrateContext<'a, 'tcx>,
632640
sig: ty::FnSig<'tcx>,
633641
extra_args: &[Ty<'tcx>]) -> FnType<'tcx> {
642+
debug!("FnType::unadjusted({:?}, {:?})", sig, extra_args);
643+
634644
use self::Abi::*;
635645
let cconv = match ccx.sess().target.target.adjust_abi(sig.abi) {
636646
RustIntrinsic | PlatformIntrinsic |

src/librustc_trans/mir/block.rs

+73-66
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,23 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
5353
_ => funclets[bb].as_ref(),
5454
};
5555

56+
for statement in &data.statements {
57+
bcx = self.trans_statement(bcx, statement);
58+
}
59+
60+
self.trans_terminator(bcx, bb, data.terminator(), funclet);
61+
}
62+
63+
fn trans_terminator(&mut self,
64+
mut bcx: Builder<'a, 'tcx>,
65+
bb: mir::BasicBlock,
66+
terminator: &mir::Terminator<'tcx>,
67+
funclet: Option<&Funclet>)
68+
{
69+
debug!("trans_terminator: {:?}", terminator);
70+
5671
// Create the cleanup bundle, if needed.
72+
let tcx = bcx.tcx();
5773
let cleanup_pad = funclet.map(|lp| lp.cleanuppad());
5874
let cleanup_bundle = funclet.map(|l| l.bundle());
5975

@@ -104,12 +120,53 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
104120
}
105121
};
106122

107-
for statement in &data.statements {
108-
bcx = self.trans_statement(bcx, statement);
109-
}
123+
let do_call = |
124+
this: &mut Self,
125+
bcx: Builder<'a, 'tcx>,
126+
fn_ty: FnType<'tcx>,
127+
fn_ptr: ValueRef,
128+
llargs: &[ValueRef],
129+
destination: Option<(ReturnDest, ty::Ty<'tcx>, mir::BasicBlock)>,
130+
cleanup: Option<mir::BasicBlock>
131+
| {
132+
if let Some(cleanup) = cleanup {
133+
let ret_bcx = if let Some((_, _, target)) = destination {
134+
this.blocks[target]
135+
} else {
136+
this.unreachable_block()
137+
};
138+
let invokeret = bcx.invoke(fn_ptr,
139+
&llargs,
140+
ret_bcx,
141+
llblock(this, cleanup),
142+
cleanup_bundle);
143+
fn_ty.apply_attrs_callsite(invokeret);
144+
145+
if let Some((ret_dest, ret_ty, target)) = destination {
146+
let ret_bcx = this.get_builder(target);
147+
this.set_debug_loc(&ret_bcx, terminator.source_info);
148+
let op = OperandRef {
149+
val: Immediate(invokeret),
150+
ty: ret_ty,
151+
};
152+
this.store_return(&ret_bcx, ret_dest, &fn_ty.ret, op);
153+
}
154+
} else {
155+
let llret = bcx.call(fn_ptr, &llargs, cleanup_bundle);
156+
fn_ty.apply_attrs_callsite(llret);
110157

111-
let terminator = data.terminator();
112-
debug!("trans_block: terminator: {:?}", terminator);
158+
if let Some((ret_dest, ret_ty, target)) = destination {
159+
let op = OperandRef {
160+
val: Immediate(llret),
161+
ty: ret_ty,
162+
};
163+
this.store_return(&bcx, ret_dest, &fn_ty.ret, op);
164+
funclet_br(this, bcx, target);
165+
} else {
166+
bcx.unreachable();
167+
}
168+
}
169+
};
113170

114171
let span = terminator.source_info.span;
115172
self.set_debug_loc(&bcx, terminator.source_info);
@@ -218,24 +275,16 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
218275
}
219276

220277
let lvalue = self.trans_lvalue(&bcx, location);
278+
let fn_ty = FnType::of_instance(bcx.ccx, &drop_fn);
221279
let (drop_fn, need_extra) = match ty.sty {
222280
ty::TyDynamic(..) => (meth::DESTRUCTOR.get_fn(&bcx, lvalue.llextra),
223281
false),
224282
_ => (callee::get_fn(bcx.ccx, drop_fn), lvalue.has_extra())
225283
};
226284
let args = &[lvalue.llval, lvalue.llextra][..1 + need_extra as usize];
227-
if let Some(unwind) = unwind {
228-
bcx.invoke(
229-
drop_fn,
230-
args,
231-
self.blocks[target],
232-
llblock(self, unwind),
233-
cleanup_bundle
234-
);
235-
} else {
236-
bcx.call(drop_fn, args, cleanup_bundle);
237-
funclet_br(self, bcx, target);
238-
}
285+
do_call(self, bcx, fn_ty, drop_fn, args,
286+
Some((ReturnDest::Nothing, tcx.mk_nil(), target)),
287+
unwind);
239288
}
240289

241290
mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => {
@@ -342,26 +391,18 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
342391
// Obtain the panic entry point.
343392
let def_id = common::langcall(bcx.tcx(), Some(span), "", lang_item);
344393
let instance = ty::Instance::mono(bcx.tcx(), def_id);
394+
let fn_ty = FnType::of_instance(bcx.ccx, &instance);
345395
let llfn = callee::get_fn(bcx.ccx, instance);
346396

347397
// Translate the actual panic invoke/call.
348-
if let Some(unwind) = cleanup {
349-
bcx.invoke(llfn,
350-
&args,
351-
self.unreachable_block(),
352-
llblock(self, unwind),
353-
cleanup_bundle);
354-
} else {
355-
bcx.call(llfn, &args, cleanup_bundle);
356-
bcx.unreachable();
357-
}
398+
do_call(self, bcx, fn_ty, llfn, &args, None, cleanup);
358399
}
359400

360401
mir::TerminatorKind::DropAndReplace { .. } => {
361-
bug!("undesugared DropAndReplace in trans: {:?}", data);
402+
bug!("undesugared DropAndReplace in trans: {:?}", terminator);
362403
}
363404

364-
mir::TerminatorKind::Call { ref func, ref args, ref destination, ref cleanup } => {
405+
mir::TerminatorKind::Call { ref func, ref args, ref destination, cleanup } => {
365406
// Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
366407
let callee = self.trans_operand(&bcx, func);
367408

@@ -514,43 +555,9 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
514555
_ => span_bug!(span, "no llfn for call"),
515556
};
516557

517-
// Many different ways to call a function handled here
518-
if let &Some(cleanup) = cleanup {
519-
let ret_bcx = if let Some((_, target)) = *destination {
520-
self.blocks[target]
521-
} else {
522-
self.unreachable_block()
523-
};
524-
let invokeret = bcx.invoke(fn_ptr,
525-
&llargs,
526-
ret_bcx,
527-
llblock(self, cleanup),
528-
cleanup_bundle);
529-
fn_ty.apply_attrs_callsite(invokeret);
530-
531-
if let Some((_, target)) = *destination {
532-
let ret_bcx = self.get_builder(target);
533-
self.set_debug_loc(&ret_bcx, terminator.source_info);
534-
let op = OperandRef {
535-
val: Immediate(invokeret),
536-
ty: sig.output(),
537-
};
538-
self.store_return(&ret_bcx, ret_dest, &fn_ty.ret, op);
539-
}
540-
} else {
541-
let llret = bcx.call(fn_ptr, &llargs, cleanup_bundle);
542-
fn_ty.apply_attrs_callsite(llret);
543-
if let Some((_, target)) = *destination {
544-
let op = OperandRef {
545-
val: Immediate(llret),
546-
ty: sig.output(),
547-
};
548-
self.store_return(&bcx, ret_dest, &fn_ty.ret, op);
549-
funclet_br(self, bcx, target);
550-
} else {
551-
bcx.unreachable();
552-
}
553-
}
558+
do_call(self, bcx, fn_ty, fn_ptr, &llargs,
559+
destination.as_ref().map(|&(_, target)| (ret_dest, sig.output(), target)),
560+
cleanup);
554561
}
555562
}
556563
}

0 commit comments

Comments
 (0)