@@ -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