Move some code around in codegen_call_terminator
This commit is contained in:
@@ -8,7 +8,7 @@ use rustc_hir::lang_items::LangItem;
|
|||||||
use rustc_middle::mir::{self, AssertKind, InlineAsmMacro, SwitchTargets, UnwindTerminateReason};
|
use rustc_middle::mir::{self, AssertKind, InlineAsmMacro, SwitchTargets, UnwindTerminateReason};
|
||||||
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
|
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement};
|
||||||
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths};
|
||||||
use rustc_middle::ty::{self, Instance, Ty};
|
use rustc_middle::ty::{self, Instance, List, Ty};
|
||||||
use rustc_middle::{bug, span_bug};
|
use rustc_middle::{bug, span_bug};
|
||||||
use rustc_session::config::OptLevel;
|
use rustc_session::config::OptLevel;
|
||||||
use rustc_span::source_map::Spanned;
|
use rustc_span::source_map::Spanned;
|
||||||
@@ -827,7 +827,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
helper: &TerminatorCodegenHelper<'tcx>,
|
helper: &TerminatorCodegenHelper<'tcx>,
|
||||||
bx: &mut Bx,
|
bx: &mut Bx,
|
||||||
intrinsic: ty::IntrinsicDef,
|
intrinsic: ty::IntrinsicDef,
|
||||||
instance: Option<Instance<'tcx>>,
|
instance: Instance<'tcx>,
|
||||||
source_info: mir::SourceInfo,
|
source_info: mir::SourceInfo,
|
||||||
target: Option<mir::BasicBlock>,
|
target: Option<mir::BasicBlock>,
|
||||||
unwind: mir::UnwindAction,
|
unwind: mir::UnwindAction,
|
||||||
@@ -837,7 +837,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
// These are intrinsics that compile to panics so that we can get a message
|
// These are intrinsics that compile to panics so that we can get a message
|
||||||
// which mentions the offending type, even from a const context.
|
// which mentions the offending type, even from a const context.
|
||||||
if let Some(requirement) = ValidityRequirement::from_intrinsic(intrinsic.name) {
|
if let Some(requirement) = ValidityRequirement::from_intrinsic(intrinsic.name) {
|
||||||
let ty = instance.unwrap().args.type_at(0);
|
let ty = instance.args.type_at(0);
|
||||||
|
|
||||||
let do_panic = !bx
|
let do_panic = !bx
|
||||||
.tcx()
|
.tcx()
|
||||||
@@ -910,52 +910,24 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
let callee = self.codegen_operand(bx, func);
|
let callee = self.codegen_operand(bx, func);
|
||||||
|
|
||||||
let (instance, mut llfn) = match *callee.layout.ty.kind() {
|
let (instance, mut llfn) = match *callee.layout.ty.kind() {
|
||||||
ty::FnDef(def_id, args) => (
|
ty::FnDef(def_id, generic_args) => {
|
||||||
Some(ty::Instance::expect_resolve(
|
let instance = ty::Instance::expect_resolve(
|
||||||
bx.tcx(),
|
bx.tcx(),
|
||||||
bx.typing_env(),
|
bx.typing_env(),
|
||||||
def_id,
|
def_id,
|
||||||
args,
|
generic_args,
|
||||||
fn_span,
|
fn_span,
|
||||||
)),
|
);
|
||||||
None,
|
|
||||||
),
|
|
||||||
ty::FnPtr(..) => (None, Some(callee.immediate())),
|
|
||||||
_ => bug!("{} is not callable", callee.layout.ty),
|
|
||||||
};
|
|
||||||
|
|
||||||
let def = instance.map(|i| i.def);
|
|
||||||
|
|
||||||
|
let instance = match instance.def {
|
||||||
// We don't need AsyncDropGlueCtorShim here because it is not `noop func`,
|
// We don't need AsyncDropGlueCtorShim here because it is not `noop func`,
|
||||||
// it is `func returning noop future`
|
// it is `func returning noop future`
|
||||||
if let Some(ty::InstanceKind::DropGlue(_, None)) = def {
|
ty::InstanceKind::DropGlue(_, None) => {
|
||||||
// Empty drop glue; a no-op.
|
// Empty drop glue; a no-op.
|
||||||
let target = target.unwrap();
|
let target = target.unwrap();
|
||||||
return helper.funclet_br(self, bx, target, mergeable_succ);
|
return helper.funclet_br(self, bx, target, mergeable_succ);
|
||||||
}
|
}
|
||||||
|
ty::InstanceKind::Intrinsic(def_id) => {
|
||||||
// FIXME(eddyb) avoid computing this if possible, when `instance` is
|
|
||||||
// available - right now `sig` is only needed for getting the `abi`
|
|
||||||
// and figuring out how many extra args were passed to a C-variadic `fn`.
|
|
||||||
let sig = callee.layout.ty.fn_sig(bx.tcx());
|
|
||||||
let abi = sig.abi();
|
|
||||||
|
|
||||||
let extra_args = &args[sig.inputs().skip_binder().len()..];
|
|
||||||
let extra_args = bx.tcx().mk_type_list_from_iter(extra_args.iter().map(|op_arg| {
|
|
||||||
let op_ty = op_arg.node.ty(self.mir, bx.tcx());
|
|
||||||
self.monomorphize(op_ty)
|
|
||||||
}));
|
|
||||||
|
|
||||||
let fn_abi = match instance {
|
|
||||||
Some(instance) => bx.fn_abi_of_instance(instance, extra_args),
|
|
||||||
None => bx.fn_abi_of_fn_ptr(sig, extra_args),
|
|
||||||
};
|
|
||||||
|
|
||||||
// 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 instance = match def {
|
|
||||||
Some(ty::InstanceKind::Intrinsic(def_id)) => {
|
|
||||||
let intrinsic = bx.tcx().intrinsic(def_id).unwrap();
|
let intrinsic = bx.tcx().intrinsic(def_id).unwrap();
|
||||||
if let Some(merging_succ) = self.codegen_panic_intrinsic(
|
if let Some(merging_succ) = self.codegen_panic_intrinsic(
|
||||||
&helper,
|
&helper,
|
||||||
@@ -970,6 +942,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
return merging_succ;
|
return merging_succ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let fn_abi = bx.fn_abi_of_instance(instance, List::empty());
|
||||||
|
|
||||||
let mut llargs = Vec::with_capacity(1);
|
let mut llargs = Vec::with_capacity(1);
|
||||||
let ret_dest = self.make_return_dest(
|
let ret_dest = self.make_return_dest(
|
||||||
bx,
|
bx,
|
||||||
@@ -981,7 +955,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
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()),
|
||||||
ReturnDest::IndirectOperand(dst, _) | ReturnDest::Store(dst) => dst.val.llval,
|
ReturnDest::IndirectOperand(dst, _) | ReturnDest::Store(dst) => {
|
||||||
|
dst.val.llval
|
||||||
|
}
|
||||||
ReturnDest::DirectOperand(_) => {
|
ReturnDest::DirectOperand(_) => {
|
||||||
bug!("Cannot use direct operand with an intrinsic call")
|
bug!("Cannot use direct operand with an intrinsic call")
|
||||||
}
|
}
|
||||||
@@ -990,9 +966,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
let args: Vec<_> =
|
let args: Vec<_> =
|
||||||
args.iter().map(|arg| self.codegen_operand(bx, &arg.node)).collect();
|
args.iter().map(|arg| self.codegen_operand(bx, &arg.node)).collect();
|
||||||
|
|
||||||
if matches!(intrinsic, ty::IntrinsicDef { name: sym::caller_location, .. }) {
|
if matches!(intrinsic, ty::IntrinsicDef { name: sym::caller_location, .. })
|
||||||
let location = self
|
{
|
||||||
.get_caller_location(bx, mir::SourceInfo { span: fn_span, ..source_info });
|
let location = self.get_caller_location(
|
||||||
|
bx,
|
||||||
|
mir::SourceInfo { span: fn_span, ..source_info },
|
||||||
|
);
|
||||||
|
|
||||||
assert_eq!(llargs, []);
|
assert_eq!(llargs, []);
|
||||||
if let ReturnDest::IndirectOperand(tmp, _) = ret_dest {
|
if let ReturnDest::IndirectOperand(tmp, _) = ret_dest {
|
||||||
@@ -1002,8 +981,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
return helper.funclet_br(self, bx, target.unwrap(), mergeable_succ);
|
return helper.funclet_br(self, bx, target.unwrap(), mergeable_succ);
|
||||||
}
|
}
|
||||||
|
|
||||||
let instance = *instance.as_ref().unwrap();
|
match Self::codegen_intrinsic_call(bx, instance, fn_abi, &args, dest, span)
|
||||||
match Self::codegen_intrinsic_call(bx, instance, fn_abi, &args, dest, span) {
|
{
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
|
if let ReturnDest::IndirectOperand(dst, _) = ret_dest {
|
||||||
self.store_return(bx, ret_dest, &fn_abi.ret, dst.val.llval);
|
self.store_return(bx, ret_dest, &fn_abi.ret, dst.val.llval);
|
||||||
@@ -1024,13 +1003,38 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
intrinsic.name,
|
intrinsic.name,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Some(instance)
|
instance
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => instance,
|
_ => instance,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
(Some(instance), None)
|
||||||
|
}
|
||||||
|
ty::FnPtr(..) => (None, Some(callee.immediate())),
|
||||||
|
_ => bug!("{} is not callable", callee.layout.ty),
|
||||||
|
};
|
||||||
|
|
||||||
|
// FIXME(eddyb) avoid computing this if possible, when `instance` is
|
||||||
|
// available - right now `sig` is only needed for getting the `abi`
|
||||||
|
// and figuring out how many extra args were passed to a C-variadic `fn`.
|
||||||
|
let sig = callee.layout.ty.fn_sig(bx.tcx());
|
||||||
|
|
||||||
|
let extra_args = &args[sig.inputs().skip_binder().len()..];
|
||||||
|
let extra_args = bx.tcx().mk_type_list_from_iter(extra_args.iter().map(|op_arg| {
|
||||||
|
let op_ty = op_arg.node.ty(self.mir, bx.tcx());
|
||||||
|
self.monomorphize(op_ty)
|
||||||
|
}));
|
||||||
|
|
||||||
|
let fn_abi = match instance {
|
||||||
|
Some(instance) => bx.fn_abi_of_instance(instance, extra_args),
|
||||||
|
None => bx.fn_abi_of_fn_ptr(sig, extra_args),
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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 mut llargs = Vec::with_capacity(arg_count);
|
let mut llargs = Vec::with_capacity(arg_count);
|
||||||
|
|
||||||
// We still need to call `make_return_dest` even if there's no `target`, since
|
// We still need to call `make_return_dest` even if there's no `target`, since
|
||||||
@@ -1040,7 +1044,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
let destination = target.map(|target| (return_dest, target));
|
let destination = target.map(|target| (return_dest, target));
|
||||||
|
|
||||||
// Split the rust-call tupled arguments off.
|
// Split the rust-call tupled arguments off.
|
||||||
let (first_args, untuple) = if abi == ExternAbi::RustCall
|
let (first_args, untuple) = if sig.abi() == ExternAbi::RustCall
|
||||||
&& let Some((tup, args)) = args.split_last()
|
&& let Some((tup, args)) = args.split_last()
|
||||||
{
|
{
|
||||||
(args, Some(tup))
|
(args, Some(tup))
|
||||||
@@ -1055,7 +1059,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
'make_args: for (i, arg) in first_args.iter().enumerate() {
|
'make_args: for (i, arg) in first_args.iter().enumerate() {
|
||||||
let mut op = self.codegen_operand(bx, &arg.node);
|
let mut op = self.codegen_operand(bx, &arg.node);
|
||||||
|
|
||||||
if let (0, Some(ty::InstanceKind::Virtual(_, idx))) = (i, def) {
|
if let (0, Some(ty::InstanceKind::Virtual(_, idx))) = (i, instance.map(|i| i.def)) {
|
||||||
match op.val {
|
match op.val {
|
||||||
Pair(data_ptr, meta) => {
|
Pair(data_ptr, meta) => {
|
||||||
// In the case of Rc<Self>, we need to explicitly pass a
|
// In the case of Rc<Self>, we need to explicitly pass a
|
||||||
|
|||||||
Reference in New Issue
Block a user