Introduce the CallTarget enum
This commit is contained in:
parent
02db151b00
commit
050b417a74
1 changed files with 31 additions and 21 deletions
|
@ -9,7 +9,7 @@ use rustc_middle::ty::layout::FnAbiExt;
|
||||||
use rustc_target::abi::call::{Conv, FnAbi};
|
use rustc_target::abi::call::{Conv, FnAbi};
|
||||||
use rustc_target::spec::abi::Abi;
|
use rustc_target::spec::abi::Abi;
|
||||||
|
|
||||||
use cranelift_codegen::ir::AbiParam;
|
use cranelift_codegen::ir::{AbiParam, SigRef};
|
||||||
use smallvec::smallvec;
|
use smallvec::smallvec;
|
||||||
|
|
||||||
use self::pass_mode::*;
|
use self::pass_mode::*;
|
||||||
|
@ -380,9 +380,11 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
||||||
args.iter().map(|arg| codegen_operand(fx, arg)).collect::<Vec<_>>()
|
args.iter().map(|arg| codegen_operand(fx, arg)).collect::<Vec<_>>()
|
||||||
};
|
};
|
||||||
|
|
||||||
// | indirect call target
|
enum CallTarget {
|
||||||
// | | the first argument to be passed
|
Direct(FuncRef),
|
||||||
// v v
|
Indirect(SigRef, Value),
|
||||||
|
}
|
||||||
|
|
||||||
let (func_ref, first_arg) = match instance {
|
let (func_ref, first_arg) = match instance {
|
||||||
// Trait object call
|
// Trait object call
|
||||||
Some(Instance { def: InstanceDef::Virtual(_, idx), .. }) => {
|
Some(Instance { def: InstanceDef::Virtual(_, idx), .. }) => {
|
||||||
|
@ -390,20 +392,27 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
||||||
let nop_inst = fx.bcx.ins().nop();
|
let nop_inst = fx.bcx.ins().nop();
|
||||||
fx.add_comment(
|
fx.add_comment(
|
||||||
nop_inst,
|
nop_inst,
|
||||||
format!("virtual call; self arg pass mode: {:?}", &fn_abi.args[0],),
|
format!("virtual call; self arg pass mode: {:?}", &fn_abi.args[0]),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (ptr, method) = crate::vtable::get_ptr_and_method_ref(fx, args[0], idx);
|
let (ptr, method) = crate::vtable::get_ptr_and_method_ref(fx, args[0], idx);
|
||||||
(Some(method), smallvec![ptr])
|
let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi);
|
||||||
|
let sig = fx.bcx.import_signature(sig);
|
||||||
|
|
||||||
|
(CallTarget::Indirect(sig, method), smallvec![ptr])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normal call
|
// Normal call
|
||||||
Some(_) => (
|
Some(instance) => {
|
||||||
None,
|
let func_ref = fx.get_function_ref(instance);
|
||||||
|
(
|
||||||
|
CallTarget::Direct(func_ref),
|
||||||
args.get(0)
|
args.get(0)
|
||||||
.map(|arg| adjust_arg_for_abi(fx, *arg, &fn_abi.args[0]))
|
.map(|arg| adjust_arg_for_abi(fx, *arg, &fn_abi.args[0]))
|
||||||
.unwrap_or(smallvec![]),
|
.unwrap_or(smallvec![]),
|
||||||
),
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Indirect call
|
// Indirect call
|
||||||
None => {
|
None => {
|
||||||
|
@ -411,9 +420,13 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
||||||
let nop_inst = fx.bcx.ins().nop();
|
let nop_inst = fx.bcx.ins().nop();
|
||||||
fx.add_comment(nop_inst, "indirect call");
|
fx.add_comment(nop_inst, "indirect call");
|
||||||
}
|
}
|
||||||
|
|
||||||
let func = codegen_operand(fx, func).load_scalar(fx);
|
let func = codegen_operand(fx, func).load_scalar(fx);
|
||||||
|
let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi);
|
||||||
|
let sig = fx.bcx.import_signature(sig);
|
||||||
|
|
||||||
(
|
(
|
||||||
Some(func),
|
CallTarget::Indirect(sig, func),
|
||||||
args.get(0)
|
args.get(0)
|
||||||
.map(|arg| adjust_arg_for_abi(fx, *arg, &fn_abi.args[0]))
|
.map(|arg| adjust_arg_for_abi(fx, *arg, &fn_abi.args[0]))
|
||||||
.unwrap_or(smallvec![]),
|
.unwrap_or(smallvec![]),
|
||||||
|
@ -452,14 +465,11 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
||||||
assert_eq!(fn_abi.args.len(), regular_args_count);
|
assert_eq!(fn_abi.args.len(), regular_args_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
let call_inst = if let Some(func_ref) = func_ref {
|
let call_inst = match func_ref {
|
||||||
let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi);
|
CallTarget::Direct(func_ref) => fx.bcx.ins().call(func_ref, &call_args),
|
||||||
let sig = fx.bcx.import_signature(sig);
|
CallTarget::Indirect(sig, func_ptr) => {
|
||||||
fx.bcx.ins().call_indirect(sig, func_ref, &call_args)
|
fx.bcx.ins().call_indirect(sig, func_ptr, &call_args)
|
||||||
} else {
|
}
|
||||||
let func_ref =
|
|
||||||
fx.get_function_ref(instance.expect("non-indirect call on non-FnDef type"));
|
|
||||||
fx.bcx.ins().call(func_ref, &call_args)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
(call_inst, call_args)
|
(call_inst, call_args)
|
||||||
|
|
Loading…
Reference in a new issue