@@ -9,7 +9,7 @@ use rustc_middle::ty::layout::FnAbiExt;
9
9
use rustc_target:: abi:: call:: { Conv , FnAbi } ;
10
10
use rustc_target:: spec:: abi:: Abi ;
11
11
12
- use cranelift_codegen:: ir:: AbiParam ;
12
+ use cranelift_codegen:: ir:: { AbiParam , SigRef } ;
13
13
use smallvec:: smallvec;
14
14
15
15
use self :: pass_mode:: * ;
@@ -380,40 +380,53 @@ pub(crate) fn codegen_terminator_call<'tcx>(
380
380
args. iter ( ) . map ( |arg| codegen_operand ( fx, arg) ) . collect :: < Vec < _ > > ( )
381
381
} ;
382
382
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
+
386
388
let ( func_ref, first_arg) = match instance {
387
389
// Trait object call
388
390
Some ( Instance { def : InstanceDef :: Virtual ( _, idx) , .. } ) => {
389
391
if fx. clif_comments . enabled ( ) {
390
392
let nop_inst = fx. bcx . ins ( ) . nop ( ) ;
391
393
fx. add_comment (
392
394
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 ] ) ,
394
396
) ;
395
397
}
398
+
396
399
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] )
398
404
}
399
405
400
406
// 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
+ }
407
416
408
417
// Indirect call
409
418
None => {
410
419
if fx. clif_comments . enabled ( ) {
411
420
let nop_inst = fx. bcx . ins ( ) . nop ( ) ;
412
421
fx. add_comment ( nop_inst, "indirect call" ) ;
413
422
}
423
+
414
424
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
+
415
428
(
416
- Some ( func) ,
429
+ CallTarget :: Indirect ( sig , func) ,
417
430
args. get ( 0 )
418
431
. map ( |arg| adjust_arg_for_abi ( fx, * arg, & fn_abi. args [ 0 ] ) )
419
432
. unwrap_or ( smallvec ! [ ] ) ,
@@ -452,14 +465,11 @@ pub(crate) fn codegen_terminator_call<'tcx>(
452
465
assert_eq ! ( fn_abi. args. len( ) , regular_args_count) ;
453
466
}
454
467
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
+ }
463
473
} ;
464
474
465
475
( call_inst, call_args)
0 commit comments