Skip to content

Commit 73790f0

Browse files
committed
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
1 parent e4d4fa3 commit 73790f0

File tree

2 files changed

+61
-65
lines changed

2 files changed

+61
-65
lines changed

src/librustc_trans/mir/block.rs

Lines changed: 58 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -211,70 +211,13 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
211211
let mut llargs = Vec::with_capacity(arg_count);
212212

213213
// Prepare the return value destination
214-
let ret_dest = if let Some((ref d, _)) = *destination {
215-
match *d {
216-
// Handle temporary lvalues, specifically Operand ones, as
217-
// they don't have allocas
218-
mir::Lvalue::Temp(idx) => {
219-
let lvalue_ty = self.mir.lvalue_ty(bcx.tcx(), d);
220-
let ret_ty = lvalue_ty.to_ty(bcx.tcx());
221-
match self.temps[idx as usize] {
222-
TempRef::Lvalue(dest) => {
223-
if fn_ty.ret.is_indirect() {
224-
llargs.push(dest.llval);
225-
ReturnDest::Nothing
226-
} else if fn_ty.ret.is_ignore() {
227-
ReturnDest::Nothing
228-
} else {
229-
ReturnDest::Store(dest.llval)
230-
}
231-
}
232-
TempRef::Operand(None) => {
233-
let is_intrinsic = if let Intrinsic = callee.data {
234-
true
235-
} else {
236-
false
237-
};
238-
239-
if fn_ty.ret.is_indirect() {
240-
// Odd, but possible, case, we have an operand temporary,
241-
// but the calling convention has an indirect return.
242-
let tmp = bcx.with_block(|bcx| {
243-
base::alloc_ty(bcx, ret_ty, "tmp_ret")
244-
});
245-
llargs.push(tmp);
246-
ReturnDest::IndirectOperand(tmp, idx)
247-
} else if is_intrinsic {
248-
// Currently, intrinsics always need a location to store
249-
// the result. so we create a temporary alloca for the
250-
// result
251-
let tmp = bcx.with_block(|bcx| {
252-
base::alloc_ty(bcx, ret_ty, "tmp_ret")
253-
});
254-
ReturnDest::IndirectOperand(tmp, idx)
255-
} else if fn_ty.ret.is_ignore() {
256-
ReturnDest::Nothing
257-
} else {
258-
ReturnDest::DirectOperand(idx)
259-
}
260-
}
261-
TempRef::Operand(Some(_)) => {
262-
bug!("lvalue temp already assigned to");
263-
}
264-
}
265-
}
266-
_ => {
267-
let dest = self.trans_lvalue(&bcx, d);
268-
if fn_ty.ret.is_indirect() {
269-
llargs.push(dest.llval);
270-
ReturnDest::Nothing
271-
} else if fn_ty.ret.is_ignore() {
272-
ReturnDest::Nothing
273-
} else {
274-
ReturnDest::Store(dest.llval)
275-
}
276-
}
277-
}
214+
let ret_dest = if let Some((ref dest, _)) = *destination {
215+
let is_intrinsic = if let Intrinsic = callee.data {
216+
true
217+
} else {
218+
false
219+
};
220+
self.make_return_dest(&bcx, dest, &fn_ty.ret, &mut llargs, is_intrinsic)
278221
} else {
279222
ReturnDest::Nothing
280223
};
@@ -601,6 +544,57 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
601544
self.blocks[bb.index()].llbb
602545
}
603546

547+
fn make_return_dest(&mut self, bcx: &BlockAndBuilder<'bcx, 'tcx>,
548+
dest: &mir::Lvalue<'tcx>, fn_ret_ty: &ArgType,
549+
llargs: &mut Vec<ValueRef>, is_intrinsic: bool) -> ReturnDest {
550+
// If the return is ignored, we can just return a do-nothing ReturnDest
551+
if fn_ret_ty.is_ignore() {
552+
return ReturnDest::Nothing;
553+
}
554+
let dest = match *dest {
555+
mir::Lvalue::Temp(idx) => {
556+
let lvalue_ty = self.mir.lvalue_ty(bcx.tcx(), dest);
557+
let ret_ty = lvalue_ty.to_ty(bcx.tcx());
558+
match self.temps[idx as usize] {
559+
TempRef::Lvalue(dest) => dest,
560+
TempRef::Operand(None) => {
561+
// Handle temporary lvalues, specifically Operand ones, as
562+
// they don't have allocas
563+
return if fn_ret_ty.is_indirect() {
564+
// Odd, but possible, case, we have an operand temporary,
565+
// but the calling convention has an indirect return.
566+
let tmp = bcx.with_block(|bcx| {
567+
base::alloc_ty(bcx, ret_ty, "tmp_ret")
568+
});
569+
llargs.push(tmp);
570+
ReturnDest::IndirectOperand(tmp, idx)
571+
} else if is_intrinsic {
572+
// Currently, intrinsics always need a location to store
573+
// the result. so we create a temporary alloca for the
574+
// result
575+
let tmp = bcx.with_block(|bcx| {
576+
base::alloc_ty(bcx, ret_ty, "tmp_ret")
577+
});
578+
ReturnDest::IndirectOperand(tmp, idx)
579+
} else {
580+
ReturnDest::DirectOperand(idx)
581+
};
582+
}
583+
TempRef::Operand(Some(_)) => {
584+
bug!("lvalue temp already assigned to");
585+
}
586+
}
587+
}
588+
_ => self.trans_lvalue(bcx, dest)
589+
};
590+
if fn_ret_ty.is_indirect() {
591+
llargs.push(dest.llval);
592+
ReturnDest::Nothing
593+
} else {
594+
ReturnDest::Store(dest.llval)
595+
}
596+
}
597+
604598
fn trans_transmute(&mut self, bcx: &BlockAndBuilder<'bcx, 'tcx>,
605599
src: &mir::Operand<'tcx>, dst: LvalueRef<'tcx>) {
606600
let mut val = self.trans_operand(bcx, src);

src/librustc_trans/mir/lvalue.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
220220
TempRef::Lvalue(lvalue) => f(self, lvalue),
221221
TempRef::Operand(None) => {
222222
let lvalue_ty = self.mir.lvalue_ty(bcx.tcx(), lvalue);
223-
let lvalue = LvalueRef::alloca(bcx, lvalue_ty.to_ty(bcx.tcx()), "lvalue_temp");
223+
let lvalue = LvalueRef::alloca(bcx,
224+
lvalue_ty.to_ty(bcx.tcx()),
225+
"lvalue_temp");
224226
let ret = f(self, lvalue);
225227
let op = self.trans_load(bcx, lvalue.llval, lvalue_ty.to_ty(bcx.tcx()));
226228
self.temps[idx as usize] = TempRef::Operand(Some(op));

0 commit comments

Comments
 (0)