@@ -20,7 +20,7 @@ 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:: { Conv , 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;
@@ -518,12 +518,6 @@ pub(crate) fn codegen_terminator_call<'tcx>(
518
518
let args = args;
519
519
assert_eq ! ( fn_abi. args. len( ) , args. len( ) ) ;
520
520
521
- #[ derive( Copy , Clone ) ]
522
- enum CallTarget {
523
- Direct ( FuncRef ) ,
524
- Indirect ( SigRef , Value ) ,
525
- }
526
-
527
521
let ( func_ref, first_arg_override) = match instance {
528
522
// Trait object call
529
523
Some ( Instance { def : InstanceKind :: Virtual ( _, idx) , .. } ) => {
@@ -590,81 +584,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
590
584
with_no_trimmed_paths ! ( fx. add_comment( nop_inst, format!( "abi: {:?}" , fn_abi) ) ) ;
591
585
}
592
586
593
- let sig_ref = match func_ref {
594
- CallTarget :: Direct ( func_ref) => fx. bcx . func . dfg . ext_funcs [ func_ref] . signature ,
595
- CallTarget :: Indirect ( sig_ref, _func_ptr) => sig_ref,
596
- } ;
597
-
598
- match unwind {
599
- // FIXME abort on unreachable and terminate unwinds
600
- UnwindAction :: Continue | UnwindAction :: Unreachable | UnwindAction :: Terminate ( _) => {
601
- let call_inst = match func_ref {
602
- CallTarget :: Direct ( func_ref) => fx. bcx . ins ( ) . call ( func_ref, & call_args) ,
603
- CallTarget :: Indirect ( sig, func_ptr) => {
604
- fx. bcx . ins ( ) . call_indirect ( sig, func_ptr, & call_args)
605
- }
606
- } ;
607
-
608
- fx. bcx
609
- . func
610
- . dfg
611
- . inst_results ( call_inst)
612
- . iter ( )
613
- . copied ( )
614
- . collect :: < SmallVec < [ Value ; 2 ] > > ( )
615
- }
616
- UnwindAction :: Cleanup ( cleanup) => {
617
- let returns_types = fx. bcx . func . dfg . signatures [ sig_ref]
618
- . returns
619
- . iter ( )
620
- . map ( |return_param| return_param. value_type )
621
- . collect :: < Vec < _ > > ( ) ;
622
-
623
- let fallthrough_block = fx. bcx . create_block ( ) ;
624
- let fallthrough_block_call_args = returns_types
625
- . iter ( )
626
- . enumerate ( )
627
- . map ( |( i, _) | BlockArg :: TryCallRet ( i. try_into ( ) . unwrap ( ) ) )
628
- . collect :: < Vec < _ > > ( ) ;
629
- let fallthrough_block_call =
630
- fx. bcx . func . dfg . block_call ( fallthrough_block, & fallthrough_block_call_args) ;
631
- let pre_cleanup_block = fx. bcx . create_block ( ) ;
632
- let pre_cleanup_block_call =
633
- fx. bcx . func . dfg . block_call ( pre_cleanup_block, & [ BlockArg :: TryCallExn ( 0 ) ] ) ;
634
- let exception_table =
635
- fx. bcx . func . dfg . exception_tables . push ( ExceptionTableData :: new (
636
- sig_ref,
637
- fallthrough_block_call,
638
- [ ( Some ( ExceptionTag :: with_number ( 0 ) . unwrap ( ) ) , pre_cleanup_block_call) ] ,
639
- ) ) ;
640
-
641
- match func_ref {
642
- CallTarget :: Direct ( func_ref) => {
643
- fx. bcx . ins ( ) . try_call ( func_ref, & call_args, exception_table) ;
644
- }
645
- CallTarget :: Indirect ( _sig, func_ptr) => {
646
- fx. bcx . ins ( ) . try_call_indirect ( func_ptr, & call_args, exception_table) ;
647
- }
648
- }
649
-
650
- fx. bcx . seal_block ( pre_cleanup_block) ;
651
- fx. bcx . switch_to_block ( pre_cleanup_block) ;
652
- fx. bcx . set_cold_block ( pre_cleanup_block) ;
653
- let exception_ptr = fx. bcx . append_block_param ( pre_cleanup_block, fx. pointer_type ) ;
654
- fx. bcx . def_var ( fx. exception_slot , exception_ptr) ;
655
- let cleanup_block = fx. get_block ( cleanup) ;
656
- fx. bcx . ins ( ) . jump ( cleanup_block, & [ ] ) ;
657
-
658
- fx. bcx . seal_block ( fallthrough_block) ;
659
- fx. bcx . switch_to_block ( fallthrough_block) ;
660
- let returns = returns_types
661
- . into_iter ( )
662
- . map ( |ty| fx. bcx . append_block_param ( fallthrough_block, ty) )
663
- . collect ( ) ;
664
- fx. bcx . ins ( ) . nop ( ) ;
665
- returns
666
- }
667
- }
587
+ codegen_call_with_unwind_action ( fx, func_ref, unwind, & call_args, None )
668
588
} ) ;
669
589
670
590
if let Some ( dest) = target {
@@ -821,44 +741,13 @@ pub(crate) fn codegen_drop<'tcx>(
821
741
822
742
let sig = clif_sig_from_fn_abi ( fx. tcx , fx. target_config . default_call_conv , & fn_abi) ;
823
743
let sig = fx. bcx . import_signature ( sig) ;
824
- match unwind {
825
- // FIXME abort on unreachable and terminate unwinds
826
- UnwindAction :: Continue
827
- | UnwindAction :: Unreachable
828
- | UnwindAction :: Terminate ( _) => {
829
- fx. bcx . ins ( ) . call_indirect ( sig, drop_fn, & [ ptr] ) ;
830
- fx. bcx . ins ( ) . jump ( ret_block, & [ ] ) ;
831
- }
832
- UnwindAction :: Cleanup ( cleanup) => {
833
- let ret_block_call = fx. bcx . func . dfg . block_call ( ret_block, & [ ] ) ;
834
- let pre_cleanup_block = fx. bcx . create_block ( ) ;
835
- let pre_cleanup_block_call = fx
836
- . bcx
837
- . func
838
- . dfg
839
- . block_call ( pre_cleanup_block, & [ BlockArg :: TryCallExn ( 0 ) ] ) ;
840
- let exception_table =
841
- fx. bcx . func . dfg . exception_tables . push ( ExceptionTableData :: new (
842
- sig,
843
- ret_block_call,
844
- [ (
845
- Some ( ExceptionTag :: with_number ( 0 ) . unwrap ( ) ) ,
846
- pre_cleanup_block_call,
847
- ) ] ,
848
- ) ) ;
849
-
850
- fx. bcx . ins ( ) . try_call_indirect ( drop_fn, & [ ptr] , exception_table) ;
851
-
852
- fx. bcx . seal_block ( pre_cleanup_block) ;
853
- fx. bcx . switch_to_block ( pre_cleanup_block) ;
854
- fx. bcx . set_cold_block ( pre_cleanup_block) ;
855
- let exception_ptr =
856
- fx. bcx . append_block_param ( pre_cleanup_block, fx. pointer_type ) ;
857
- fx. bcx . def_var ( fx. exception_slot , exception_ptr) ;
858
- let cleanup_block = fx. get_block ( cleanup) ;
859
- fx. bcx . ins ( ) . jump ( cleanup_block, & [ ] ) ;
860
- }
861
- }
744
+ codegen_call_with_unwind_action (
745
+ fx,
746
+ CallTarget :: Indirect ( sig, drop_fn) ,
747
+ unwind,
748
+ & [ ptr] ,
749
+ Some ( ret_block) ,
750
+ ) ;
862
751
}
863
752
ty:: Dynamic ( _, _, ty:: DynStar ) => {
864
753
// IN THIS ARM, WE HAVE:
@@ -901,44 +790,13 @@ pub(crate) fn codegen_drop<'tcx>(
901
790
902
791
let sig = clif_sig_from_fn_abi ( fx. tcx , fx. target_config . default_call_conv , & fn_abi) ;
903
792
let sig = fx. bcx . import_signature ( sig) ;
904
- match unwind {
905
- // FIXME abort on unreachable and terminate unwinds
906
- UnwindAction :: Continue
907
- | UnwindAction :: Unreachable
908
- | UnwindAction :: Terminate ( _) => {
909
- fx. bcx . ins ( ) . call_indirect ( sig, drop_fn, & [ data] ) ;
910
- fx. bcx . ins ( ) . jump ( ret_block, & [ ] ) ;
911
- }
912
- UnwindAction :: Cleanup ( cleanup) => {
913
- let ret_block_call = fx. bcx . func . dfg . block_call ( ret_block, & [ ] ) ;
914
- let pre_cleanup_block = fx. bcx . create_block ( ) ;
915
- let pre_cleanup_block_call = fx
916
- . bcx
917
- . func
918
- . dfg
919
- . block_call ( pre_cleanup_block, & [ BlockArg :: TryCallExn ( 0 ) ] ) ;
920
- let exception_table =
921
- fx. bcx . func . dfg . exception_tables . push ( ExceptionTableData :: new (
922
- sig,
923
- ret_block_call,
924
- [ (
925
- Some ( ExceptionTag :: with_number ( 0 ) . unwrap ( ) ) ,
926
- pre_cleanup_block_call,
927
- ) ] ,
928
- ) ) ;
929
-
930
- fx. bcx . ins ( ) . try_call_indirect ( drop_fn, & [ data] , exception_table) ;
931
-
932
- fx. bcx . seal_block ( pre_cleanup_block) ;
933
- fx. bcx . switch_to_block ( pre_cleanup_block) ;
934
- fx. bcx . set_cold_block ( pre_cleanup_block) ;
935
- let exception_ptr =
936
- fx. bcx . append_block_param ( pre_cleanup_block, fx. pointer_type ) ;
937
- fx. bcx . def_var ( fx. exception_slot , exception_ptr) ;
938
- let cleanup_block = fx. get_block ( cleanup) ;
939
- fx. bcx . ins ( ) . jump ( cleanup_block, & [ ] ) ;
940
- }
941
- }
793
+ codegen_call_with_unwind_action (
794
+ fx,
795
+ CallTarget :: Indirect ( sig, drop_fn) ,
796
+ unwind,
797
+ & [ data] ,
798
+ Some ( ret_block) ,
799
+ ) ;
942
800
}
943
801
_ => {
944
802
assert ! ( !matches!( drop_instance. def, InstanceKind :: Virtual ( _, _) ) ) ;
@@ -963,45 +821,117 @@ pub(crate) fn codegen_drop<'tcx>(
963
821
}
964
822
965
823
let func_ref = fx. get_function_ref ( drop_instance) ;
966
- let sig_ref = fx. bcx . func . dfg . ext_funcs [ func_ref] . signature ;
967
- match unwind {
968
- // FIXME abort on unreachable and terminate unwinds
969
- UnwindAction :: Continue
970
- | UnwindAction :: Unreachable
971
- | UnwindAction :: Terminate ( _) => {
972
- fx. bcx . ins ( ) . call ( func_ref, & call_args) ;
973
- fx. bcx . ins ( ) . jump ( ret_block, & [ ] ) ;
974
- }
975
- UnwindAction :: Cleanup ( cleanup) => {
976
- let ret_block_call = fx. bcx . func . dfg . block_call ( ret_block, & [ ] ) ;
977
- let pre_cleanup_block = fx. bcx . create_block ( ) ;
978
- let pre_cleanup_block_call = fx
979
- . bcx
980
- . func
981
- . dfg
982
- . block_call ( pre_cleanup_block, & [ BlockArg :: TryCallExn ( 0 ) ] ) ;
983
- let exception_table =
984
- fx. bcx . func . dfg . exception_tables . push ( ExceptionTableData :: new (
985
- sig_ref,
986
- ret_block_call,
987
- [ (
988
- Some ( ExceptionTag :: with_number ( 0 ) . unwrap ( ) ) ,
989
- pre_cleanup_block_call,
990
- ) ] ,
991
- ) ) ;
992
-
993
- fx. bcx . ins ( ) . try_call ( func_ref, & call_args, exception_table) ;
994
-
995
- fx. bcx . seal_block ( pre_cleanup_block) ;
996
- fx. bcx . switch_to_block ( pre_cleanup_block) ;
997
- fx. bcx . set_cold_block ( pre_cleanup_block) ;
998
- let exception_ptr =
999
- fx. bcx . append_block_param ( pre_cleanup_block, fx. pointer_type ) ;
1000
- fx. bcx . def_var ( fx. exception_slot , exception_ptr) ;
1001
- let cleanup_block = fx. get_block ( cleanup) ;
1002
- fx. bcx . ins ( ) . jump ( cleanup_block, & [ ] ) ;
1003
- }
824
+ codegen_call_with_unwind_action (
825
+ fx,
826
+ CallTarget :: Direct ( func_ref) ,
827
+ unwind,
828
+ & call_args,
829
+ Some ( ret_block) ,
830
+ ) ;
831
+ }
832
+ }
833
+ }
834
+ }
835
+
836
+ #[ derive( Copy , Clone ) ]
837
+ pub ( crate ) enum CallTarget {
838
+ Direct ( FuncRef ) ,
839
+ Indirect ( SigRef , Value ) ,
840
+ }
841
+
842
+ pub ( crate ) fn codegen_call_with_unwind_action (
843
+ fx : & mut FunctionCx < ' _ , ' _ , ' _ > ,
844
+ func_ref : CallTarget ,
845
+ unwind : UnwindAction ,
846
+ call_args : & [ Value ] ,
847
+ target_block : Option < Block > ,
848
+ ) -> SmallVec < [ Value ; 2 ] > {
849
+ let sig_ref = match func_ref {
850
+ CallTarget :: Direct ( func_ref) => fx. bcx . func . dfg . ext_funcs [ func_ref] . signature ,
851
+ CallTarget :: Indirect ( sig_ref, _func_ptr) => sig_ref,
852
+ } ;
853
+
854
+ if target_block. is_some ( ) {
855
+ assert ! ( fx. bcx. func. dfg. signatures[ sig_ref] . returns. is_empty( ) ) ;
856
+ }
857
+
858
+ match unwind {
859
+ // FIXME abort on unreachable and terminate unwinds
860
+ UnwindAction :: Continue | UnwindAction :: Unreachable | UnwindAction :: Terminate ( _) => {
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)
1004
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 ( cleanup) => {
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
+ [ ( Some ( ExceptionTag :: with_number ( 0 ) . unwrap ( ) ) , pre_cleanup_block_call) ] ,
905
+ ) ) ;
906
+
907
+ match func_ref {
908
+ CallTarget :: Direct ( func_ref) => {
909
+ fx. bcx . ins ( ) . try_call ( func_ref, & call_args, exception_table) ;
910
+ }
911
+ CallTarget :: Indirect ( _sig, func_ptr) => {
912
+ fx. bcx . ins ( ) . try_call_indirect ( func_ptr, & call_args, exception_table) ;
913
+ }
914
+ }
915
+
916
+ fx. bcx . seal_block ( pre_cleanup_block) ;
917
+ fx. bcx . switch_to_block ( pre_cleanup_block) ;
918
+ fx. bcx . set_cold_block ( pre_cleanup_block) ;
919
+ let exception_ptr = fx. bcx . append_block_param ( pre_cleanup_block, fx. pointer_type ) ;
920
+ fx. bcx . def_var ( fx. exception_slot , exception_ptr) ;
921
+ let cleanup_block = fx. get_block ( cleanup) ;
922
+ fx. bcx . ins ( ) . jump ( cleanup_block, & [ ] ) ;
923
+
924
+ if target_block. is_none ( ) {
925
+ fx. bcx . seal_block ( fallthrough_block) ;
926
+ fx. bcx . switch_to_block ( fallthrough_block) ;
927
+ let returns = returns_types
928
+ . into_iter ( )
929
+ . map ( |ty| fx. bcx . append_block_param ( fallthrough_block, ty) )
930
+ . collect ( ) ;
931
+ fx. bcx . ins ( ) . nop ( ) ;
932
+ returns
933
+ } else {
934
+ smallvec ! [ ]
1005
935
}
1006
936
}
1007
937
}
0 commit comments