Create ret_dest as late as possible in all code paths

This commit is contained in:
Oli Scherer 2024-01-31 20:24:44 +00:00
parent 55200e75da
commit 432635a9ea

View File

@ -817,23 +817,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
// The arguments we'll be passing. Plus one to account for outptr, if used. // The arguments we'll be passing. Plus one to account for outptr, if used.
let arg_count = fn_abi.args.len() + fn_abi.ret.is_indirect() as usize; let arg_count = fn_abi.args.len() + fn_abi.ret.is_indirect() as usize;
let mut llargs = Vec::with_capacity(arg_count);
// Prepare the return value destination
let ret_dest = self.make_return_dest(
bx,
destination,
&fn_abi.ret,
&mut llargs,
intrinsic.is_some(),
target.is_some(),
);
if intrinsic == Some(sym::caller_location) { if intrinsic == Some(sym::caller_location) {
return if let Some(target) = target { return if let Some(target) = target {
let location = let location =
self.get_caller_location(bx, mir::SourceInfo { span: fn_span, ..source_info }); self.get_caller_location(bx, mir::SourceInfo { span: fn_span, ..source_info });
let mut llargs = Vec::with_capacity(arg_count);
let ret_dest =
self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs, true, true);
assert_eq!(llargs, []);
if let ReturnDest::IndirectOperand(tmp, _) = ret_dest { if let ReturnDest::IndirectOperand(tmp, _) = ret_dest {
location.val.store(bx, tmp); location.val.store(bx, tmp);
} }
@ -847,6 +840,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
match intrinsic { match intrinsic {
None | Some(sym::drop_in_place) => {} None | Some(sym::drop_in_place) => {}
Some(intrinsic) => { Some(intrinsic) => {
let mut llargs = Vec::with_capacity(1);
let ret_dest = self.make_return_dest(
bx,
destination,
&fn_abi.ret,
&mut llargs,
true,
target.is_some(),
);
let dest = match ret_dest { let dest = match ret_dest {
_ if fn_abi.ret.is_indirect() => llargs[0], _ if fn_abi.ret.is_indirect() => llargs[0],
ReturnDest::Nothing => bx.const_undef(bx.type_ptr()), ReturnDest::Nothing => bx.const_undef(bx.type_ptr()),
@ -902,6 +904,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
} }
} }
let mut llargs = Vec::with_capacity(arg_count);
let destination = target.as_ref().map(|&target| {
(self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs, false, true), target)
});
// Split the rust-call tupled arguments off. // Split the rust-call tupled arguments off.
let (first_args, untuple) = if abi == Abi::RustCall && !args.is_empty() { let (first_args, untuple) = if abi == Abi::RustCall && !args.is_empty() {
let (tup, args) = args.split_last().unwrap(); let (tup, args) = args.split_last().unwrap();
@ -1042,14 +1049,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
(_, Some(llfn)) => llfn, (_, Some(llfn)) => llfn,
_ => span_bug!(span, "no instance or llfn for call"), _ => span_bug!(span, "no instance or llfn for call"),
}; };
helper.do_call( helper.do_call(
self, self,
bx, bx,
fn_abi, fn_abi,
fn_ptr, fn_ptr,
&llargs, &llargs,
target.as_ref().map(|&target| (ret_dest, target)), destination,
unwind, unwind,
&copied_constant_arguments, &copied_constant_arguments,
mergeable_succ, mergeable_succ,