@@ -160,6 +160,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
160160 mut unwind : mir:: UnwindAction ,
161161 lifetime_ends_after_call : & [ ( Bx :: Value , Size ) ] ,
162162 instance : Option < Instance < ' tcx > > ,
163+ tail : bool ,
163164 mergeable_succ : bool ,
164165 ) -> MergingSucc {
165166 let tcx = bx. tcx ( ) ;
@@ -221,6 +222,15 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
221222 }
222223 } ;
223224
225+ if tail {
226+ bx. tail_call ( fn_ty, fn_attrs, fn_abi, fn_ptr, llargs, self . funclet ( fx) , instance) ;
227+ for & ( tmp, size) in lifetime_ends_after_call {
228+ bx. lifetime_end ( tmp, size) ;
229+ }
230+
231+ return MergingSucc :: False ;
232+ }
233+
224234 if let Some ( unwind_block) = unwind_block {
225235 let ret_llbb = if let Some ( ( _, target) ) = destination {
226236 fx. llbb ( target)
@@ -659,6 +669,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
659669 unwind,
660670 & [ ] ,
661671 Some ( drop_instance) ,
672+ false ,
662673 !maybe_null && mergeable_succ,
663674 )
664675 }
@@ -747,8 +758,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
747758 let ( fn_abi, llfn, instance) = common:: build_langcall ( bx, span, lang_item) ;
748759
749760 // Codegen the actual panic invoke/call.
750- let merging_succ =
751- helper. do_call ( self , bx, fn_abi, llfn, & args, None , unwind, & [ ] , Some ( instance) , false ) ;
761+ let merging_succ = helper. do_call (
762+ self ,
763+ bx,
764+ fn_abi,
765+ llfn,
766+ & args,
767+ None ,
768+ unwind,
769+ & [ ] ,
770+ Some ( instance) ,
771+ false ,
772+ false ,
773+ ) ;
752774 assert_eq ! ( merging_succ, MergingSucc :: False ) ;
753775 MergingSucc :: False
754776 }
@@ -778,6 +800,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
778800 & [ ] ,
779801 Some ( instance) ,
780802 false ,
803+ false ,
781804 ) ;
782805 assert_eq ! ( merging_succ, MergingSucc :: False ) ;
783806 }
@@ -845,6 +868,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
845868 unwind,
846869 & [ ] ,
847870 Some ( instance) ,
871+ false ,
848872 mergeable_succ,
849873 ) )
850874 }
@@ -860,6 +884,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
860884 target : Option < mir:: BasicBlock > ,
861885 unwind : mir:: UnwindAction ,
862886 fn_span : Span ,
887+ tail : bool ,
863888 mergeable_succ : bool ,
864889 ) -> MergingSucc {
865890 let source_info = mir:: SourceInfo { span : fn_span, ..terminator. source_info } ;
@@ -1003,8 +1028,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10031028 // We still need to call `make_return_dest` even if there's no `target`, since
10041029 // `fn_abi.ret` could be `PassMode::Indirect`, even if it is uninhabited,
10051030 // and `make_return_dest` adds the return-place indirect pointer to `llargs`.
1006- let return_dest = self . make_return_dest ( bx, destination, & fn_abi. ret , & mut llargs) ;
1007- let destination = target. map ( |target| ( return_dest, target) ) ;
1031+ let destination = if !tail {
1032+ let return_dest = self . make_return_dest ( bx, destination, & fn_abi. ret , & mut llargs) ;
1033+ target. map ( |target| ( return_dest, target) )
1034+ } else {
1035+ None
1036+ } ;
10081037
10091038 // Split the rust-call tupled arguments off.
10101039 let ( first_args, untuple) = if sig. abi ( ) == ExternAbi :: RustCall
@@ -1147,6 +1176,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
11471176 unwind,
11481177 & lifetime_ends_after_call,
11491178 instance,
1179+ tail,
11501180 mergeable_succ,
11511181 )
11521182 }
@@ -1388,15 +1418,23 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
13881418 target,
13891419 unwind,
13901420 fn_span,
1421+ false ,
13911422 mergeable_succ ( ) ,
13921423 ) ,
1393- mir:: TerminatorKind :: TailCall { .. } => {
1394- // FIXME(explicit_tail_calls): implement tail calls in ssa backend
1395- span_bug ! (
1396- terminator. source_info. span,
1397- "`TailCall` terminator is not yet supported by `rustc_codegen_ssa`"
1398- )
1399- }
1424+ mir:: TerminatorKind :: TailCall { ref func, ref args, fn_span } => self
1425+ . codegen_call_terminator (
1426+ helper,
1427+ bx,
1428+ terminator,
1429+ func,
1430+ args,
1431+ mir:: Place :: from ( mir:: RETURN_PLACE ) ,
1432+ None ,
1433+ mir:: UnwindAction :: Unreachable ,
1434+ fn_span,
1435+ true ,
1436+ mergeable_succ ( ) ,
1437+ ) ,
14001438 mir:: TerminatorKind :: CoroutineDrop | mir:: TerminatorKind :: Yield { .. } => {
14011439 bug ! ( "coroutine ops in codegen" )
14021440 }
0 commit comments