Skip to content

Commit 3bcee26

Browse files
committed
Handle immediate tuples in trans_arguments_untupled
Use either getelementptr or extractvalue depending on whether or not the tuple is immediate or not.
1 parent 0e3b37a commit 3bcee26

File tree

1 file changed

+36
-36
lines changed

1 file changed

+36
-36
lines changed

src/librustc_trans/mir/block.rs

+36-36
Original file line numberDiff line numberDiff line change
@@ -436,47 +436,47 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
436436
fn_ty: &FnType,
437437
next_idx: &mut usize,
438438
callee: &mut CalleeData) {
439-
// FIXME: consider having some optimization to avoid tupling/untupling
440-
// (and storing/loading in the case of immediates)
441-
442-
// avoid trans_operand for pointless copying
443-
let lv = match *operand {
444-
mir::Operand::Consume(ref lvalue) => self.trans_lvalue(bcx, lvalue),
445-
mir::Operand::Constant(ref constant) => {
446-
// FIXME: consider being less pessimized
447-
if constant.ty.is_nil() {
448-
return;
449-
}
450-
451-
let ty = bcx.monomorphize(&constant.ty);
452-
let lv = LvalueRef::alloca(bcx, ty, "__untuple_alloca");
453-
let constant = self.trans_constant(bcx, constant);
454-
self.store_operand(bcx, lv.llval, constant);
455-
lv
456-
}
457-
};
439+
let tuple = self.trans_operand(bcx, operand);
458440

459-
let lv_ty = lv.ty.to_ty(bcx.tcx());
460-
let result_types = match lv_ty.sty {
441+
let arg_types = match tuple.ty.sty {
461442
ty::TyTuple(ref tys) => tys,
462-
_ => span_bug!(
463-
self.mir.span,
464-
"bad final argument to \"rust-call\" fn {:?}", lv_ty)
443+
_ => span_bug!(self.mir.span,
444+
"bad final argument to \"rust-call\" fn {:?}", tuple.ty)
465445
};
466446

467-
let base_repr = adt::represent_type(bcx.ccx(), lv_ty);
468-
let base = adt::MaybeSizedValue::sized(lv.llval);
469-
for (n, &ty) in result_types.iter().enumerate() {
470-
let ptr = adt::trans_field_ptr_builder(bcx, &base_repr, base, Disr(0), n);
471-
let val = if common::type_is_fat_ptr(bcx.tcx(), ty) {
472-
let (lldata, llextra) = load_fat_ptr(bcx, ptr);
473-
FatPtr(lldata, llextra)
474-
} else {
475-
// Don't bother loading the value, trans_argument will.
476-
Ref(ptr)
477-
};
478-
self.trans_argument(bcx, val, llargs, fn_ty, next_idx, callee);
447+
// Handle both by-ref and immediate tuples. This gives us the option of
448+
match tuple.val {
449+
Ref(llval) => {
450+
let base_repr = adt::represent_type(bcx.ccx(), tuple.ty);
451+
let base = adt::MaybeSizedValue::sized(llval);
452+
for (n, &ty) in arg_types.iter().enumerate() {
453+
let ptr = adt::trans_field_ptr_builder(bcx, &base_repr, base, Disr(0), n);
454+
let val = if common::type_is_fat_ptr(bcx.tcx(), ty) {
455+
let (lldata, llextra) = load_fat_ptr(bcx, ptr);
456+
FatPtr(lldata, llextra)
457+
} else {
458+
// trans_argument will load this if it needs to
459+
Ref(ptr)
460+
};
461+
self.trans_argument(bcx, val, llargs, fn_ty, next_idx, callee);
462+
}
463+
464+
}
465+
Immediate(llval) => {
466+
for (n, &ty) in arg_types.iter().enumerate() {
467+
let mut elem = bcx.extract_value(llval, n);
468+
// Truncate bools to i1, if needed
469+
if ty.is_bool() && common::val_ty(elem) != Type::i1(bcx.ccx()) {
470+
elem = bcx.trunc(elem, Type::i1(bcx.ccx()));
471+
}
472+
// If the tuple is immediate, the elements are as well
473+
let val = Immediate(elem);
474+
self.trans_argument(bcx, val, llargs, fn_ty, next_idx, callee);
475+
}
476+
}
477+
FatPtr(_, _) => bug!("tuple is a fat pointer?!")
479478
}
479+
480480
}
481481

482482
fn get_personality_slot(&mut self, bcx: &BlockAndBuilder<'bcx, 'tcx>) -> ValueRef {

0 commit comments

Comments
 (0)