Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Move ReturnDest creation into a method
It's quite a large amount of code, and moving it into a method allowed
for some refactoring to make the logic a little easier to understand
  • Loading branch information
Aatch committed Apr 6, 2016
1 parent e4d4fa3 commit 73790f0
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 65 deletions.
122 changes: 58 additions & 64 deletions src/librustc_trans/mir/block.rs
Expand Up @@ -211,70 +211,13 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
let mut llargs = Vec::with_capacity(arg_count);

// Prepare the return value destination
let ret_dest = if let Some((ref d, _)) = *destination {
match *d {
// Handle temporary lvalues, specifically Operand ones, as
// they don't have allocas
mir::Lvalue::Temp(idx) => {
let lvalue_ty = self.mir.lvalue_ty(bcx.tcx(), d);
let ret_ty = lvalue_ty.to_ty(bcx.tcx());
match self.temps[idx as usize] {
TempRef::Lvalue(dest) => {
if fn_ty.ret.is_indirect() {
llargs.push(dest.llval);
ReturnDest::Nothing
} else if fn_ty.ret.is_ignore() {
ReturnDest::Nothing
} else {
ReturnDest::Store(dest.llval)
}
}
TempRef::Operand(None) => {
let is_intrinsic = if let Intrinsic = callee.data {
true
} else {
false
};

if fn_ty.ret.is_indirect() {
// Odd, but possible, case, we have an operand temporary,
// but the calling convention has an indirect return.
let tmp = bcx.with_block(|bcx| {
base::alloc_ty(bcx, ret_ty, "tmp_ret")
});
llargs.push(tmp);
ReturnDest::IndirectOperand(tmp, idx)
} else if is_intrinsic {
// Currently, intrinsics always need a location to store
// the result. so we create a temporary alloca for the
// result
let tmp = bcx.with_block(|bcx| {
base::alloc_ty(bcx, ret_ty, "tmp_ret")
});
ReturnDest::IndirectOperand(tmp, idx)
} else if fn_ty.ret.is_ignore() {
ReturnDest::Nothing
} else {
ReturnDest::DirectOperand(idx)
}
}
TempRef::Operand(Some(_)) => {
bug!("lvalue temp already assigned to");
}
}
}
_ => {
let dest = self.trans_lvalue(&bcx, d);
if fn_ty.ret.is_indirect() {
llargs.push(dest.llval);
ReturnDest::Nothing
} else if fn_ty.ret.is_ignore() {
ReturnDest::Nothing
} else {
ReturnDest::Store(dest.llval)
}
}
}
let ret_dest = if let Some((ref dest, _)) = *destination {
let is_intrinsic = if let Intrinsic = callee.data {
true
} else {
false
};
self.make_return_dest(&bcx, dest, &fn_ty.ret, &mut llargs, is_intrinsic)
} else {
ReturnDest::Nothing
};
Expand Down Expand Up @@ -601,6 +544,57 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
self.blocks[bb.index()].llbb
}

fn make_return_dest(&mut self, bcx: &BlockAndBuilder<'bcx, 'tcx>,
dest: &mir::Lvalue<'tcx>, fn_ret_ty: &ArgType,
llargs: &mut Vec<ValueRef>, is_intrinsic: bool) -> ReturnDest {
// If the return is ignored, we can just return a do-nothing ReturnDest
if fn_ret_ty.is_ignore() {
return ReturnDest::Nothing;
}
let dest = match *dest {
mir::Lvalue::Temp(idx) => {
let lvalue_ty = self.mir.lvalue_ty(bcx.tcx(), dest);
let ret_ty = lvalue_ty.to_ty(bcx.tcx());
match self.temps[idx as usize] {
TempRef::Lvalue(dest) => dest,
TempRef::Operand(None) => {
// Handle temporary lvalues, specifically Operand ones, as
// they don't have allocas
return if fn_ret_ty.is_indirect() {
// Odd, but possible, case, we have an operand temporary,
// but the calling convention has an indirect return.
let tmp = bcx.with_block(|bcx| {
base::alloc_ty(bcx, ret_ty, "tmp_ret")
});
llargs.push(tmp);
ReturnDest::IndirectOperand(tmp, idx)
} else if is_intrinsic {
// Currently, intrinsics always need a location to store
// the result. so we create a temporary alloca for the
// result
let tmp = bcx.with_block(|bcx| {
base::alloc_ty(bcx, ret_ty, "tmp_ret")
});
ReturnDest::IndirectOperand(tmp, idx)
} else {
ReturnDest::DirectOperand(idx)
};
}
TempRef::Operand(Some(_)) => {
bug!("lvalue temp already assigned to");
}
}
}
_ => self.trans_lvalue(bcx, dest)
};
if fn_ret_ty.is_indirect() {
llargs.push(dest.llval);
ReturnDest::Nothing
} else {
ReturnDest::Store(dest.llval)
}
}

fn trans_transmute(&mut self, bcx: &BlockAndBuilder<'bcx, 'tcx>,
src: &mir::Operand<'tcx>, dst: LvalueRef<'tcx>) {
let mut val = self.trans_operand(bcx, src);
Expand Down
4 changes: 3 additions & 1 deletion src/librustc_trans/mir/lvalue.rs
Expand Up @@ -220,7 +220,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
TempRef::Lvalue(lvalue) => f(self, lvalue),
TempRef::Operand(None) => {
let lvalue_ty = self.mir.lvalue_ty(bcx.tcx(), lvalue);
let lvalue = LvalueRef::alloca(bcx, lvalue_ty.to_ty(bcx.tcx()), "lvalue_temp");
let lvalue = LvalueRef::alloca(bcx,
lvalue_ty.to_ty(bcx.tcx()),
"lvalue_temp");
let ret = f(self, lvalue);
let op = self.trans_load(bcx, lvalue.llval, lvalue_ty.to_ty(bcx.tcx()));
self.temps[idx as usize] = TempRef::Operand(Some(op));
Expand Down

0 comments on commit 73790f0

Please sign in to comment.