@@ -8,7 +8,7 @@ use rustc_hir::lang_items::LangItem;
88use rustc_middle:: mir:: { self , AssertKind , InlineAsmMacro , SwitchTargets , UnwindTerminateReason } ;
99use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf , ValidityRequirement } ;
1010use rustc_middle:: ty:: print:: { with_no_trimmed_paths, with_no_visible_paths} ;
11- use rustc_middle:: ty:: { self , Instance , Ty } ;
11+ use rustc_middle:: ty:: { self , Instance , List , Ty } ;
1212use rustc_middle:: { bug, span_bug} ;
1313use rustc_session:: config:: OptLevel ;
1414use rustc_span:: source_map:: Spanned ;
@@ -827,7 +827,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
827827 helper : & TerminatorCodegenHelper < ' tcx > ,
828828 bx : & mut Bx ,
829829 intrinsic : ty:: IntrinsicDef ,
830- instance : Option < Instance < ' tcx > > ,
830+ instance : Instance < ' tcx > ,
831831 source_info : mir:: SourceInfo ,
832832 target : Option < mir:: BasicBlock > ,
833833 unwind : mir:: UnwindAction ,
@@ -837,7 +837,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
837837 // These are intrinsics that compile to panics so that we can get a message
838838 // which mentions the offending type, even from a const context.
839839 if let Some ( requirement) = ValidityRequirement :: from_intrinsic ( intrinsic. name ) {
840- let ty = instance. unwrap ( ) . args . type_at ( 0 ) ;
840+ let ty = instance. args . type_at ( 0 ) ;
841841
842842 let do_panic = !bx
843843 . tcx ( )
@@ -910,35 +910,116 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
910910 let callee = self . codegen_operand ( bx, func) ;
911911
912912 let ( instance, mut llfn) = match * callee. layout . ty . kind ( ) {
913- ty:: FnDef ( def_id, args ) => (
914- Some ( ty:: Instance :: expect_resolve (
913+ ty:: FnDef ( def_id, generic_args ) => {
914+ let instance = ty:: Instance :: expect_resolve (
915915 bx. tcx ( ) ,
916916 bx. typing_env ( ) ,
917917 def_id,
918- args ,
918+ generic_args ,
919919 fn_span,
920- ) ) ,
921- None ,
922- ) ,
920+ ) ;
921+
922+ let instance = match instance. def {
923+ // We don't need AsyncDropGlueCtorShim here because it is not `noop func`,
924+ // it is `func returning noop future`
925+ ty:: InstanceKind :: DropGlue ( _, None ) => {
926+ // Empty drop glue; a no-op.
927+ let target = target. unwrap ( ) ;
928+ return helper. funclet_br ( self , bx, target, mergeable_succ) ;
929+ }
930+ ty:: InstanceKind :: Intrinsic ( def_id) => {
931+ let intrinsic = bx. tcx ( ) . intrinsic ( def_id) . unwrap ( ) ;
932+ if let Some ( merging_succ) = self . codegen_panic_intrinsic (
933+ & helper,
934+ bx,
935+ intrinsic,
936+ instance,
937+ source_info,
938+ target,
939+ unwind,
940+ mergeable_succ,
941+ ) {
942+ return merging_succ;
943+ }
944+
945+ let fn_abi = bx. fn_abi_of_instance ( instance, List :: empty ( ) ) ;
946+
947+ let mut llargs = Vec :: with_capacity ( 1 ) ;
948+ let ret_dest = self . make_return_dest (
949+ bx,
950+ destination,
951+ & fn_abi. ret ,
952+ & mut llargs,
953+ Some ( intrinsic) ,
954+ ) ;
955+ let dest = match ret_dest {
956+ _ if fn_abi. ret . is_indirect ( ) => llargs[ 0 ] ,
957+ ReturnDest :: Nothing => bx. const_undef ( bx. type_ptr ( ) ) ,
958+ ReturnDest :: IndirectOperand ( dst, _) | ReturnDest :: Store ( dst) => {
959+ dst. val . llval
960+ }
961+ ReturnDest :: DirectOperand ( _) => {
962+ bug ! ( "Cannot use direct operand with an intrinsic call" )
963+ }
964+ } ;
965+
966+ let args: Vec < _ > =
967+ args. iter ( ) . map ( |arg| self . codegen_operand ( bx, & arg. node ) ) . collect ( ) ;
968+
969+ if matches ! ( intrinsic, ty:: IntrinsicDef { name: sym:: caller_location, .. } )
970+ {
971+ let location = self . get_caller_location (
972+ bx,
973+ mir:: SourceInfo { span : fn_span, ..source_info } ,
974+ ) ;
975+
976+ assert_eq ! ( llargs, [ ] ) ;
977+ if let ReturnDest :: IndirectOperand ( tmp, _) = ret_dest {
978+ location. val . store ( bx, tmp) ;
979+ }
980+ self . store_return ( bx, ret_dest, & fn_abi. ret , location. immediate ( ) ) ;
981+ return helper. funclet_br ( self , bx, target. unwrap ( ) , mergeable_succ) ;
982+ }
983+
984+ match Self :: codegen_intrinsic_call ( bx, instance, fn_abi, & args, dest, span)
985+ {
986+ Ok ( ( ) ) => {
987+ if let ReturnDest :: IndirectOperand ( dst, _) = ret_dest {
988+ self . store_return ( bx, ret_dest, & fn_abi. ret , dst. val . llval ) ;
989+ }
990+
991+ return if let Some ( target) = target {
992+ helper. funclet_br ( self , bx, target, mergeable_succ)
993+ } else {
994+ bx. unreachable ( ) ;
995+ MergingSucc :: False
996+ } ;
997+ }
998+ Err ( instance) => {
999+ if intrinsic. must_be_overridden {
1000+ span_bug ! (
1001+ span,
1002+ "intrinsic {} must be overridden by codegen backend, but isn't" ,
1003+ intrinsic. name,
1004+ ) ;
1005+ }
1006+ instance
1007+ }
1008+ }
1009+ }
1010+ _ => instance,
1011+ } ;
1012+
1013+ ( Some ( instance) , None )
1014+ }
9231015 ty:: FnPtr ( ..) => ( None , Some ( callee. immediate ( ) ) ) ,
9241016 _ => bug ! ( "{} is not callable" , callee. layout. ty) ,
9251017 } ;
9261018
927- let def = instance. map ( |i| i. def ) ;
928-
929- // We don't need AsyncDropGlueCtorShim here because it is not `noop func`,
930- // it is `func returning noop future`
931- if let Some ( ty:: InstanceKind :: DropGlue ( _, None ) ) = def {
932- // Empty drop glue; a no-op.
933- let target = target. unwrap ( ) ;
934- return helper. funclet_br ( self , bx, target, mergeable_succ) ;
935- }
936-
9371019 // FIXME(eddyb) avoid computing this if possible, when `instance` is
9381020 // available - right now `sig` is only needed for getting the `abi`
9391021 // and figuring out how many extra args were passed to a C-variadic `fn`.
9401022 let sig = callee. layout . ty . fn_sig ( bx. tcx ( ) ) ;
941- let abi = sig. abi ( ) ;
9421023
9431024 let extra_args = & args[ sig. inputs ( ) . skip_binder ( ) . len ( ) ..] ;
9441025 let extra_args = bx. tcx ( ) . mk_type_list_from_iter ( extra_args. iter ( ) . map ( |op_arg| {
@@ -954,83 +1035,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
9541035 // The arguments we'll be passing. Plus one to account for outptr, if used.
9551036 let arg_count = fn_abi. args . len ( ) + fn_abi. ret . is_indirect ( ) as usize ;
9561037
957- let instance = match def {
958- Some ( ty:: InstanceKind :: Intrinsic ( def_id) ) => {
959- let intrinsic = bx. tcx ( ) . intrinsic ( def_id) . unwrap ( ) ;
960- if let Some ( merging_succ) = self . codegen_panic_intrinsic (
961- & helper,
962- bx,
963- intrinsic,
964- instance,
965- source_info,
966- target,
967- unwind,
968- mergeable_succ,
969- ) {
970- return merging_succ;
971- }
972-
973- let mut llargs = Vec :: with_capacity ( 1 ) ;
974- let ret_dest = self . make_return_dest (
975- bx,
976- destination,
977- & fn_abi. ret ,
978- & mut llargs,
979- Some ( intrinsic) ,
980- ) ;
981- let dest = match ret_dest {
982- _ if fn_abi. ret . is_indirect ( ) => llargs[ 0 ] ,
983- ReturnDest :: Nothing => bx. const_undef ( bx. type_ptr ( ) ) ,
984- ReturnDest :: IndirectOperand ( dst, _) | ReturnDest :: Store ( dst) => dst. val . llval ,
985- ReturnDest :: DirectOperand ( _) => {
986- bug ! ( "Cannot use direct operand with an intrinsic call" )
987- }
988- } ;
989-
990- let args: Vec < _ > =
991- args. iter ( ) . map ( |arg| self . codegen_operand ( bx, & arg. node ) ) . collect ( ) ;
992-
993- if matches ! ( intrinsic, ty:: IntrinsicDef { name: sym:: caller_location, .. } ) {
994- let location = self
995- . get_caller_location ( bx, mir:: SourceInfo { span : fn_span, ..source_info } ) ;
996-
997- assert_eq ! ( llargs, [ ] ) ;
998- if let ReturnDest :: IndirectOperand ( tmp, _) = ret_dest {
999- location. val . store ( bx, tmp) ;
1000- }
1001- self . store_return ( bx, ret_dest, & fn_abi. ret , location. immediate ( ) ) ;
1002- return helper. funclet_br ( self , bx, target. unwrap ( ) , mergeable_succ) ;
1003- }
1004-
1005- let instance = * instance. as_ref ( ) . unwrap ( ) ;
1006- match Self :: codegen_intrinsic_call ( bx, instance, fn_abi, & args, dest, span) {
1007- Ok ( ( ) ) => {
1008- if let ReturnDest :: IndirectOperand ( dst, _) = ret_dest {
1009- self . store_return ( bx, ret_dest, & fn_abi. ret , dst. val . llval ) ;
1010- }
1011-
1012- return if let Some ( target) = target {
1013- helper. funclet_br ( self , bx, target, mergeable_succ)
1014- } else {
1015- bx. unreachable ( ) ;
1016- MergingSucc :: False
1017- } ;
1018- }
1019- Err ( instance) => {
1020- if intrinsic. must_be_overridden {
1021- span_bug ! (
1022- span,
1023- "intrinsic {} must be overridden by codegen backend, but isn't" ,
1024- intrinsic. name,
1025- ) ;
1026- }
1027- Some ( instance)
1028- }
1029- }
1030- }
1031- _ => instance,
1032- } ;
1033-
10341038 let mut llargs = Vec :: with_capacity ( arg_count) ;
10351039
10361040 // We still need to call `make_return_dest` even if there's no `target`, since
@@ -1040,7 +1044,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10401044 let destination = target. map ( |target| ( return_dest, target) ) ;
10411045
10421046 // Split the rust-call tupled arguments off.
1043- let ( first_args, untuple) = if abi == ExternAbi :: RustCall
1047+ let ( first_args, untuple) = if sig . abi ( ) == ExternAbi :: RustCall
10441048 && let Some ( ( tup, args) ) = args. split_last ( )
10451049 {
10461050 ( args, Some ( tup) )
@@ -1055,7 +1059,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10551059 ' make_args: for ( i, arg) in first_args. iter ( ) . enumerate ( ) {
10561060 let mut op = self . codegen_operand ( bx, & arg. node ) ;
10571061
1058- if let ( 0 , Some ( ty:: InstanceKind :: Virtual ( _, idx) ) ) = ( i, def) {
1062+ if let ( 0 , Some ( ty:: InstanceKind :: Virtual ( _, idx) ) ) = ( i, instance . map ( |i| i . def ) ) {
10591063 match op. val {
10601064 Pair ( data_ptr, meta) => {
10611065 // In the case of Rc<Self>, we need to explicitly pass a
0 commit comments