@@ -7,7 +7,7 @@ mod returning;
7
7
use std:: borrow:: Cow ;
8
8
use std:: mem;
9
9
10
- use cranelift_codegen:: ir:: { ArgumentPurpose , SigRef } ;
10
+ use cranelift_codegen:: ir:: { ArgumentPurpose , BlockArg , ExceptionTableData , ExceptionTag , SigRef } ;
11
11
use cranelift_codegen:: isa:: CallConv ;
12
12
use cranelift_module:: ModuleError ;
13
13
use rustc_abi:: { CanonAbi , ExternAbi , X86Call } ;
@@ -20,10 +20,12 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
20
20
use rustc_session:: Session ;
21
21
use rustc_span:: source_map:: Spanned ;
22
22
use rustc_target:: callconv:: { FnAbi , PassMode } ;
23
- use smallvec:: SmallVec ;
23
+ use smallvec:: { SmallVec , smallvec } ;
24
24
25
25
use self :: pass_mode:: * ;
26
26
pub ( crate ) use self :: returning:: codegen_return;
27
+ use crate :: base:: codegen_unwind_terminate;
28
+ use crate :: debuginfo:: EXCEPTION_HANDLER_CLEANUP ;
27
29
use crate :: prelude:: * ;
28
30
29
31
fn clif_sig_from_fn_abi < ' tcx > (
@@ -380,7 +382,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
380
382
args : & [ Spanned < Operand < ' tcx > > ] ,
381
383
destination : Place < ' tcx > ,
382
384
target : Option < BasicBlock > ,
383
- _unwind : UnwindAction ,
385
+ unwind : UnwindAction ,
384
386
) {
385
387
let func = codegen_operand ( fx, func) ;
386
388
let fn_sig = func. layout ( ) . ty . fn_sig ( fx. tcx ) ;
@@ -515,12 +517,6 @@ pub(crate) fn codegen_terminator_call<'tcx>(
515
517
let args = args;
516
518
assert_eq ! ( fn_abi. args. len( ) , args. len( ) ) ;
517
519
518
- #[ derive( Copy , Clone ) ]
519
- enum CallTarget {
520
- Direct ( FuncRef ) ,
521
- Indirect ( SigRef , Value ) ,
522
- }
523
-
524
520
let ( func_ref, first_arg_override) = match instance {
525
521
// Trait object call
526
522
Some ( Instance { def : InstanceKind :: Virtual ( _, idx) , .. } ) => {
@@ -582,18 +578,12 @@ pub(crate) fn codegen_terminator_call<'tcx>(
582
578
adjust_call_for_c_variadic ( fx, & fn_abi, source_info, func_ref, & mut call_args) ;
583
579
}
584
580
585
- let call_inst = match func_ref {
586
- CallTarget :: Direct ( func_ref) => fx. bcx . ins ( ) . call ( func_ref, & call_args) ,
587
- CallTarget :: Indirect ( sig, func_ptr) => {
588
- fx. bcx . ins ( ) . call_indirect ( sig, func_ptr, & call_args)
589
- }
590
- } ;
591
-
592
581
if fx. clif_comments . enabled ( ) {
593
- with_no_trimmed_paths ! ( fx. add_comment( call_inst, format!( "abi: {:?}" , fn_abi) ) ) ;
582
+ let nop_inst = fx. bcx . ins ( ) . nop ( ) ;
583
+ with_no_trimmed_paths ! ( fx. add_post_comment( nop_inst, format!( "abi: {:?}" , fn_abi) ) ) ;
594
584
}
595
585
596
- fx . bcx . func . dfg . inst_results ( call_inst ) . iter ( ) . copied ( ) . collect :: < SmallVec < [ Value ; 2 ] > > ( )
586
+ codegen_call_with_unwind_action ( fx , source_info . span , func_ref , unwind , & call_args , None )
597
587
} ) ;
598
588
599
589
if let Some ( dest) = target {
@@ -703,7 +693,7 @@ pub(crate) fn codegen_drop<'tcx>(
703
693
source_info : mir:: SourceInfo ,
704
694
drop_place : CPlace < ' tcx > ,
705
695
target : BasicBlock ,
706
- _unwind : UnwindAction ,
696
+ unwind : UnwindAction ,
707
697
) {
708
698
let ty = drop_place. layout ( ) . ty ;
709
699
let drop_instance = Instance :: resolve_drop_in_place ( fx. tcx , ty) ;
@@ -749,9 +739,14 @@ pub(crate) fn codegen_drop<'tcx>(
749
739
750
740
let sig = clif_sig_from_fn_abi ( fx. tcx , fx. target_config . default_call_conv , & fn_abi) ;
751
741
let sig = fx. bcx . import_signature ( sig) ;
752
- // FIXME implement cleanup on exceptions
753
- fx. bcx . ins ( ) . call_indirect ( sig, drop_fn, & [ ptr] ) ;
754
- fx. bcx . ins ( ) . jump ( ret_block, & [ ] ) ;
742
+ codegen_call_with_unwind_action (
743
+ fx,
744
+ source_info. span ,
745
+ CallTarget :: Indirect ( sig, drop_fn) ,
746
+ unwind,
747
+ & [ ptr] ,
748
+ Some ( ret_block) ,
749
+ ) ;
755
750
}
756
751
ty:: Dynamic ( _, _, ty:: DynStar ) => {
757
752
// IN THIS ARM, WE HAVE:
@@ -794,9 +789,14 @@ pub(crate) fn codegen_drop<'tcx>(
794
789
795
790
let sig = clif_sig_from_fn_abi ( fx. tcx , fx. target_config . default_call_conv , & fn_abi) ;
796
791
let sig = fx. bcx . import_signature ( sig) ;
797
- fx. bcx . ins ( ) . call_indirect ( sig, drop_fn, & [ data] ) ;
798
- // FIXME implement cleanup on exceptions
799
- fx. bcx . ins ( ) . jump ( ret_block, & [ ] ) ;
792
+ codegen_call_with_unwind_action (
793
+ fx,
794
+ source_info. span ,
795
+ CallTarget :: Indirect ( sig, drop_fn) ,
796
+ unwind,
797
+ & [ data] ,
798
+ Some ( ret_block) ,
799
+ ) ;
800
800
}
801
801
_ => {
802
802
assert ! ( !matches!( drop_instance. def, InstanceKind :: Virtual ( _, _) ) ) ;
@@ -821,9 +821,132 @@ pub(crate) fn codegen_drop<'tcx>(
821
821
}
822
822
823
823
let func_ref = fx. get_function_ref ( drop_instance) ;
824
- fx. bcx . ins ( ) . call ( func_ref, & call_args) ;
825
- // FIXME implement cleanup on exceptions
826
- fx. bcx . ins ( ) . jump ( ret_block, & [ ] ) ;
824
+ codegen_call_with_unwind_action (
825
+ fx,
826
+ source_info. span ,
827
+ CallTarget :: Direct ( func_ref) ,
828
+ unwind,
829
+ & call_args,
830
+ Some ( ret_block) ,
831
+ ) ;
832
+ }
833
+ }
834
+ }
835
+ }
836
+
837
+ #[ derive( Copy , Clone ) ]
838
+ pub ( crate ) enum CallTarget {
839
+ Direct ( FuncRef ) ,
840
+ Indirect ( SigRef , Value ) ,
841
+ }
842
+
843
+ pub ( crate ) fn codegen_call_with_unwind_action (
844
+ fx : & mut FunctionCx < ' _ , ' _ , ' _ > ,
845
+ span : Span ,
846
+ func_ref : CallTarget ,
847
+ unwind : UnwindAction ,
848
+ call_args : & [ Value ] ,
849
+ target_block : Option < Block > ,
850
+ ) -> SmallVec < [ Value ; 2 ] > {
851
+ let sig_ref = match func_ref {
852
+ CallTarget :: Direct ( func_ref) => fx. bcx . func . dfg . ext_funcs [ func_ref] . signature ,
853
+ CallTarget :: Indirect ( sig_ref, _func_ptr) => sig_ref,
854
+ } ;
855
+
856
+ if target_block. is_some ( ) {
857
+ assert ! ( fx. bcx. func. dfg. signatures[ sig_ref] . returns. is_empty( ) ) ;
858
+ }
859
+ match unwind {
860
+ UnwindAction :: Continue | UnwindAction :: Unreachable => {
861
+ let call_inst = match func_ref {
862
+ CallTarget :: Direct ( func_ref) => fx. bcx . ins ( ) . call ( func_ref, & call_args) ,
863
+ CallTarget :: Indirect ( sig, func_ptr) => {
864
+ fx. bcx . ins ( ) . call_indirect ( sig, func_ptr, & call_args)
865
+ }
866
+ } ;
867
+
868
+ if let Some ( target_block) = target_block {
869
+ fx. bcx . ins ( ) . jump ( target_block, & [ ] ) ;
870
+ smallvec ! [ ]
871
+ } else {
872
+ fx. bcx
873
+ . func
874
+ . dfg
875
+ . inst_results ( call_inst)
876
+ . iter ( )
877
+ . copied ( )
878
+ . collect :: < SmallVec < [ Value ; 2 ] > > ( )
879
+ }
880
+ }
881
+ UnwindAction :: Cleanup ( _) | UnwindAction :: Terminate ( _) => {
882
+ let returns_types = fx. bcx . func . dfg . signatures [ sig_ref]
883
+ . returns
884
+ . iter ( )
885
+ . map ( |return_param| return_param. value_type )
886
+ . collect :: < Vec < _ > > ( ) ;
887
+
888
+ let fallthrough_block = fx. bcx . create_block ( ) ;
889
+ let fallthrough_block_call_args = returns_types
890
+ . iter ( )
891
+ . enumerate ( )
892
+ . map ( |( i, _) | BlockArg :: TryCallRet ( i. try_into ( ) . unwrap ( ) ) )
893
+ . collect :: < Vec < _ > > ( ) ;
894
+ let fallthrough_block_call = fx. bcx . func . dfg . block_call (
895
+ target_block. unwrap_or ( fallthrough_block) ,
896
+ & fallthrough_block_call_args,
897
+ ) ;
898
+ let pre_cleanup_block = fx. bcx . create_block ( ) ;
899
+ let pre_cleanup_block_call =
900
+ fx. bcx . func . dfg . block_call ( pre_cleanup_block, & [ BlockArg :: TryCallExn ( 0 ) ] ) ;
901
+ let exception_table = fx. bcx . func . dfg . exception_tables . push ( ExceptionTableData :: new (
902
+ sig_ref,
903
+ fallthrough_block_call,
904
+ [ (
905
+ Some ( ExceptionTag :: with_number ( EXCEPTION_HANDLER_CLEANUP ) . unwrap ( ) ) ,
906
+ pre_cleanup_block_call,
907
+ ) ] ,
908
+ ) ) ;
909
+
910
+ match func_ref {
911
+ CallTarget :: Direct ( func_ref) => {
912
+ fx. bcx . ins ( ) . try_call ( func_ref, & call_args, exception_table) ;
913
+ }
914
+ CallTarget :: Indirect ( _sig, func_ptr) => {
915
+ fx. bcx . ins ( ) . try_call_indirect ( func_ptr, & call_args, exception_table) ;
916
+ }
917
+ }
918
+
919
+ fx. bcx . seal_block ( pre_cleanup_block) ;
920
+ fx. bcx . switch_to_block ( pre_cleanup_block) ;
921
+ fx. bcx . set_cold_block ( pre_cleanup_block) ;
922
+ match unwind {
923
+ UnwindAction :: Continue | UnwindAction :: Unreachable => unreachable ! ( ) ,
924
+ UnwindAction :: Cleanup ( cleanup) => {
925
+ let exception_ptr =
926
+ fx. bcx . append_block_param ( pre_cleanup_block, fx. pointer_type ) ;
927
+ fx. bcx . def_var ( fx. exception_slot , exception_ptr) ;
928
+ let cleanup_block = fx. get_block ( cleanup) ;
929
+ fx. bcx . ins ( ) . jump ( cleanup_block, & [ ] ) ;
930
+ }
931
+ UnwindAction :: Terminate ( reason) => {
932
+ // FIXME dedup terminate blocks
933
+ fx. bcx . append_block_param ( pre_cleanup_block, fx. pointer_type ) ;
934
+
935
+ codegen_unwind_terminate ( fx, span, reason) ;
936
+ }
937
+ }
938
+
939
+ if target_block. is_none ( ) {
940
+ fx. bcx . seal_block ( fallthrough_block) ;
941
+ fx. bcx . switch_to_block ( fallthrough_block) ;
942
+ let returns = returns_types
943
+ . into_iter ( )
944
+ . map ( |ty| fx. bcx . append_block_param ( fallthrough_block, ty) )
945
+ . collect ( ) ;
946
+ fx. bcx . ins ( ) . nop ( ) ;
947
+ returns
948
+ } else {
949
+ smallvec ! [ ]
827
950
}
828
951
}
829
952
}
0 commit comments