From 050b417a74a5f55a91ae25f0b841a6d04219ce34 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 26 Jul 2021 14:40:27 +0200 Subject: [PATCH] Introduce the CallTarget enum --- src/abi/mod.rs | 52 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/src/abi/mod.rs b/src/abi/mod.rs index 54c8fb0e7b8..a8596707c8e 100644 --- a/src/abi/mod.rs +++ b/src/abi/mod.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::layout::FnAbiExt; use rustc_target::abi::call::{Conv, FnAbi}; use rustc_target::spec::abi::Abi; -use cranelift_codegen::ir::AbiParam; +use cranelift_codegen::ir::{AbiParam, SigRef}; use smallvec::smallvec; use self::pass_mode::*; @@ -380,9 +380,11 @@ pub(crate) fn codegen_terminator_call<'tcx>( args.iter().map(|arg| codegen_operand(fx, arg)).collect::>() }; - // | indirect call target - // | | the first argument to be passed - // v v + enum CallTarget { + Direct(FuncRef), + Indirect(SigRef, Value), + } + let (func_ref, first_arg) = match instance { // Trait object call Some(Instance { def: InstanceDef::Virtual(_, idx), .. }) => { @@ -390,20 +392,27 @@ pub(crate) fn codegen_terminator_call<'tcx>( let nop_inst = fx.bcx.ins().nop(); fx.add_comment( 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); - (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 - Some(_) => ( - None, - args.get(0) - .map(|arg| adjust_arg_for_abi(fx, *arg, &fn_abi.args[0])) - .unwrap_or(smallvec![]), - ), + Some(instance) => { + let func_ref = fx.get_function_ref(instance); + ( + CallTarget::Direct(func_ref), + args.get(0) + .map(|arg| adjust_arg_for_abi(fx, *arg, &fn_abi.args[0])) + .unwrap_or(smallvec![]), + ) + } // Indirect call None => { @@ -411,9 +420,13 @@ pub(crate) fn codegen_terminator_call<'tcx>( let nop_inst = fx.bcx.ins().nop(); fx.add_comment(nop_inst, "indirect call"); } + 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) .map(|arg| adjust_arg_for_abi(fx, *arg, &fn_abi.args[0])) .unwrap_or(smallvec![]), @@ -452,14 +465,11 @@ pub(crate) fn codegen_terminator_call<'tcx>( assert_eq!(fn_abi.args.len(), regular_args_count); } - let call_inst = if let Some(func_ref) = func_ref { - let sig = clif_sig_from_fn_abi(fx.tcx, fx.triple(), &fn_abi); - let sig = fx.bcx.import_signature(sig); - fx.bcx.ins().call_indirect(sig, func_ref, &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) + let call_inst = match func_ref { + CallTarget::Direct(func_ref) => fx.bcx.ins().call(func_ref, &call_args), + CallTarget::Indirect(sig, func_ptr) => { + fx.bcx.ins().call_indirect(sig, func_ptr, &call_args) + } }; (call_inst, call_args)