@@ -20,7 +20,7 @@ use rustc_middle::ty::print::with_no_trimmed_paths;
2020use rustc_session:: Session ;
2121use rustc_span:: source_map:: Spanned ;
2222use rustc_target:: callconv:: { Conv , FnAbi , PassMode } ;
23- use smallvec:: SmallVec ;
23+ use smallvec:: { SmallVec , smallvec } ;
2424
2525use self :: pass_mode:: * ;
2626pub ( crate ) use self :: returning:: codegen_return;
@@ -518,12 +518,6 @@ pub(crate) fn codegen_terminator_call<'tcx>(
518518 let args = args;
519519 assert_eq ! ( fn_abi. args. len( ) , args. len( ) ) ;
520520
521- #[ derive( Copy , Clone ) ]
522- enum CallTarget {
523- Direct ( FuncRef ) ,
524- Indirect ( SigRef , Value ) ,
525- }
526-
527521 let ( func_ref, first_arg_override) = match instance {
528522 // Trait object call
529523 Some ( Instance { def : InstanceKind :: Virtual ( _, idx) , .. } ) => {
@@ -590,81 +584,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
590584 with_no_trimmed_paths ! ( fx. add_comment( nop_inst, format!( "abi: {:?}" , fn_abi) ) ) ;
591585 }
592586
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 )
668588 } ) ;
669589
670590 if let Some ( dest) = target {
@@ -821,44 +741,13 @@ pub(crate) fn codegen_drop<'tcx>(
821741
822742 let sig = clif_sig_from_fn_abi ( fx. tcx , fx. target_config . default_call_conv , & fn_abi) ;
823743 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+ ) ;
862751 }
863752 ty:: Dynamic ( _, _, ty:: DynStar ) => {
864753 // IN THIS ARM, WE HAVE:
@@ -901,44 +790,13 @@ pub(crate) fn codegen_drop<'tcx>(
901790
902791 let sig = clif_sig_from_fn_abi ( fx. tcx , fx. target_config . default_call_conv , & fn_abi) ;
903792 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+ ) ;
942800 }
943801 _ => {
944802 assert ! ( !matches!( drop_instance. def, InstanceKind :: Virtual ( _, _) ) ) ;
@@ -963,45 +821,117 @@ pub(crate) fn codegen_drop<'tcx>(
963821 }
964822
965823 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)
1004865 }
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 ! [ ]
1005935 }
1006936 }
1007937 }
0 commit comments