@@ -9,7 +9,7 @@ use rustc_middle::ty::layout::FnAbiExt;
99use rustc_target:: abi:: call:: { Conv , FnAbi } ;
1010use rustc_target:: spec:: abi:: Abi ;
1111
12- use cranelift_codegen:: ir:: AbiParam ;
12+ use cranelift_codegen:: ir:: { AbiParam , SigRef } ;
1313use smallvec:: smallvec;
1414
1515use self :: pass_mode:: * ;
@@ -380,40 +380,53 @@ pub(crate) fn codegen_terminator_call<'tcx>(
380380 args. iter ( ) . map ( |arg| codegen_operand ( fx, arg) ) . collect :: < Vec < _ > > ( )
381381 } ;
382382
383- // | indirect call target
384- // | | the first argument to be passed
385- // v v
383+ enum CallTarget {
384+ Direct ( FuncRef ) ,
385+ Indirect ( SigRef , Value ) ,
386+ }
387+
386388 let ( func_ref, first_arg) = match instance {
387389 // Trait object call
388390 Some ( Instance { def : InstanceDef :: Virtual ( _, idx) , .. } ) => {
389391 if fx. clif_comments . enabled ( ) {
390392 let nop_inst = fx. bcx . ins ( ) . nop ( ) ;
391393 fx. add_comment (
392394 nop_inst,
393- format ! ( "virtual call; self arg pass mode: {:?}" , & fn_abi. args[ 0 ] , ) ,
395+ format ! ( "virtual call; self arg pass mode: {:?}" , & fn_abi. args[ 0 ] ) ,
394396 ) ;
395397 }
398+
396399 let ( ptr, method) = crate :: vtable:: get_ptr_and_method_ref ( fx, args[ 0 ] , idx) ;
397- ( Some ( method) , smallvec ! [ ptr] )
400+ let sig = clif_sig_from_fn_abi ( fx. tcx , fx. triple ( ) , & fn_abi) ;
401+ let sig = fx. bcx . import_signature ( sig) ;
402+
403+ ( CallTarget :: Indirect ( sig, method) , smallvec ! [ ptr] )
398404 }
399405
400406 // Normal call
401- Some ( _) => (
402- None ,
403- args. get ( 0 )
404- . map ( |arg| adjust_arg_for_abi ( fx, * arg, & fn_abi. args [ 0 ] ) )
405- . unwrap_or ( smallvec ! [ ] ) ,
406- ) ,
407+ Some ( instance) => {
408+ let func_ref = fx. get_function_ref ( instance) ;
409+ (
410+ CallTarget :: Direct ( func_ref) ,
411+ args. get ( 0 )
412+ . map ( |arg| adjust_arg_for_abi ( fx, * arg, & fn_abi. args [ 0 ] ) )
413+ . unwrap_or ( smallvec ! [ ] ) ,
414+ )
415+ }
407416
408417 // Indirect call
409418 None => {
410419 if fx. clif_comments . enabled ( ) {
411420 let nop_inst = fx. bcx . ins ( ) . nop ( ) ;
412421 fx. add_comment ( nop_inst, "indirect call" ) ;
413422 }
423+
414424 let func = codegen_operand ( fx, func) . load_scalar ( fx) ;
425+ let sig = clif_sig_from_fn_abi ( fx. tcx , fx. triple ( ) , & fn_abi) ;
426+ let sig = fx. bcx . import_signature ( sig) ;
427+
415428 (
416- Some ( func) ,
429+ CallTarget :: Indirect ( sig , func) ,
417430 args. get ( 0 )
418431 . map ( |arg| adjust_arg_for_abi ( fx, * arg, & fn_abi. args [ 0 ] ) )
419432 . unwrap_or ( smallvec ! [ ] ) ,
@@ -452,14 +465,11 @@ pub(crate) fn codegen_terminator_call<'tcx>(
452465 assert_eq ! ( fn_abi. args. len( ) , regular_args_count) ;
453466 }
454467
455- let call_inst = if let Some ( func_ref) = func_ref {
456- let sig = clif_sig_from_fn_abi ( fx. tcx , fx. triple ( ) , & fn_abi) ;
457- let sig = fx. bcx . import_signature ( sig) ;
458- fx. bcx . ins ( ) . call_indirect ( sig, func_ref, & call_args)
459- } else {
460- let func_ref =
461- fx. get_function_ref ( instance. expect ( "non-indirect call on non-FnDef type" ) ) ;
462- fx. bcx . ins ( ) . call ( func_ref, & call_args)
468+ let call_inst = match func_ref {
469+ CallTarget :: Direct ( func_ref) => fx. bcx . ins ( ) . call ( func_ref, & call_args) ,
470+ CallTarget :: Indirect ( sig, func_ptr) => {
471+ fx. bcx . ins ( ) . call_indirect ( sig, func_ptr, & call_args)
472+ }
463473 } ;
464474
465475 ( call_inst, call_args)
0 commit comments