@@ -160,6 +160,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
160
160
mut unwind : mir:: UnwindAction ,
161
161
lifetime_ends_after_call : & [ ( Bx :: Value , Size ) ] ,
162
162
instance : Option < Instance < ' tcx > > ,
163
+ tail : bool ,
163
164
mergeable_succ : bool ,
164
165
) -> MergingSucc {
165
166
let tcx = bx. tcx ( ) ;
@@ -221,6 +222,15 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
221
222
}
222
223
} ;
223
224
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
+
224
234
if let Some ( unwind_block) = unwind_block {
225
235
let ret_llbb = if let Some ( ( _, target) ) = destination {
226
236
fx. llbb ( target)
@@ -659,6 +669,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
659
669
unwind,
660
670
& [ ] ,
661
671
Some ( drop_instance) ,
672
+ false ,
662
673
!maybe_null && mergeable_succ,
663
674
)
664
675
}
@@ -747,8 +758,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
747
758
let ( fn_abi, llfn, instance) = common:: build_langcall ( bx, span, lang_item) ;
748
759
749
760
// 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
+ ) ;
752
774
assert_eq ! ( merging_succ, MergingSucc :: False ) ;
753
775
MergingSucc :: False
754
776
}
@@ -778,6 +800,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
778
800
& [ ] ,
779
801
Some ( instance) ,
780
802
false ,
803
+ false ,
781
804
) ;
782
805
assert_eq ! ( merging_succ, MergingSucc :: False ) ;
783
806
}
@@ -845,6 +868,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
845
868
unwind,
846
869
& [ ] ,
847
870
Some ( instance) ,
871
+ false ,
848
872
mergeable_succ,
849
873
) )
850
874
}
@@ -860,6 +884,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
860
884
target : Option < mir:: BasicBlock > ,
861
885
unwind : mir:: UnwindAction ,
862
886
fn_span : Span ,
887
+ tail : bool ,
863
888
mergeable_succ : bool ,
864
889
) -> MergingSucc {
865
890
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> {
1003
1028
// We still need to call `make_return_dest` even if there's no `target`, since
1004
1029
// `fn_abi.ret` could be `PassMode::Indirect`, even if it is uninhabited,
1005
1030
// 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
+ } ;
1008
1037
1009
1038
// Split the rust-call tupled arguments off.
1010
1039
let ( first_args, untuple) = if sig. abi ( ) == ExternAbi :: RustCall
@@ -1147,6 +1176,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1147
1176
unwind,
1148
1177
& lifetime_ends_after_call,
1149
1178
instance,
1179
+ tail,
1150
1180
mergeable_succ,
1151
1181
)
1152
1182
}
@@ -1388,15 +1418,23 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1388
1418
target,
1389
1419
unwind,
1390
1420
fn_span,
1421
+ false ,
1391
1422
mergeable_succ ( ) ,
1392
1423
) ,
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
+ ) ,
1400
1438
mir:: TerminatorKind :: CoroutineDrop | mir:: TerminatorKind :: Yield { .. } => {
1401
1439
bug ! ( "coroutine ops in codegen" )
1402
1440
}
0 commit comments