@@ -342,102 +342,6 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
342342
343343/// Codegen implementations for some terminator variants.
344344impl < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > FunctionCx < ' a , ' tcx , Bx > {
345- fn codegen_tail_call_terminator (
346- & mut self ,
347- bx : & mut Bx ,
348- func : & mir:: Operand < ' tcx > ,
349- args : & [ Spanned < mir:: Operand < ' tcx > > ] ,
350- fn_span : Span ,
351- mergeable_succ : bool ,
352- ) -> MergingSucc {
353- // We don't need source_info as we already have fn_span for diagnostics
354- let func = self . codegen_operand ( bx, func) ;
355- let fn_ty = func. layout . ty ;
356-
357- // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
358- let ( fn_ptr, fn_abi, instance) = match * fn_ty. kind ( ) {
359- ty:: FnDef ( def_id, substs) => {
360- let instance = ty:: Instance :: expect_resolve (
361- bx. tcx ( ) ,
362- bx. typing_env ( ) ,
363- def_id,
364- substs,
365- fn_span,
366- ) ;
367- let fn_ptr = bx. get_fn_addr ( instance) ;
368- let fn_abi = bx. fn_abi_of_instance ( instance, ty:: List :: empty ( ) ) ;
369- ( fn_ptr, fn_abi, Some ( instance) )
370- }
371- ty:: FnPtr ( ..) => {
372- let sig = fn_ty. fn_sig ( bx. tcx ( ) ) ;
373- let extra_args = bx. tcx ( ) . mk_type_list ( & [ ] ) ;
374- let fn_ptr = func. immediate ( ) ;
375- let fn_abi = bx. fn_abi_of_fn_ptr ( sig, extra_args) ;
376- ( fn_ptr, fn_abi, None )
377- }
378- _ => bug ! ( "{} is not callable" , func. layout. ty) ,
379- } ;
380-
381- let mut llargs = Vec :: with_capacity ( args. len ( ) ) ;
382- let mut lifetime_ends_after_call = Vec :: new ( ) ;
383-
384- // Process arguments
385- for arg in args {
386- let op = self . codegen_operand ( bx, & arg. node ) ;
387- let arg_idx = llargs. len ( ) ;
388-
389- if arg_idx < fn_abi. args . len ( ) {
390- self . codegen_argument (
391- bx,
392- op,
393- & mut llargs,
394- & fn_abi. args [ arg_idx] ,
395- & mut lifetime_ends_after_call,
396- ) ;
397- } else {
398- // This can happen in case of C-variadic functions
399- let is_immediate = match op. val {
400- Immediate ( _) => true ,
401- _ => false ,
402- } ;
403-
404- if is_immediate {
405- llargs. push ( op. immediate ( ) ) ;
406- } else {
407- let temp = PlaceRef :: alloca ( bx, op. layout ) ;
408- op. val . store ( bx, temp) ;
409- llargs. push ( bx. load (
410- bx. backend_type ( op. layout ) ,
411- temp. val . llval ,
412- temp. val . align ,
413- ) ) ;
414- }
415- }
416- }
417-
418- // Call the function
419- let fn_ty = bx. fn_decl_backend_type ( fn_abi) ;
420- let fn_attrs = if let Some ( instance) = instance
421- && bx. tcx ( ) . def_kind ( instance. def_id ( ) ) . has_codegen_attrs ( )
422- {
423- Some ( bx. tcx ( ) . codegen_fn_attrs ( instance. def_id ( ) ) )
424- } else {
425- None
426- } ;
427-
428- // Perform the actual function call
429- let llret = bx. call ( fn_ty, fn_attrs, Some ( fn_abi) , fn_ptr, & llargs, None , instance) ;
430-
431- // Mark as tail call - this is the critical part
432- bx. set_tail_call ( llret) ;
433-
434- // Return the result - musttail requires ret immediately after the call
435- bx. ret ( llret) ;
436-
437- assert_eq ! ( mergeable_succ, false ) ;
438- MergingSucc :: False
439- }
440-
441345 /// Generates code for a `Resume` terminator.
442346 fn codegen_resume_terminator ( & mut self , helper : TerminatorCodegenHelper < ' tcx > , bx : & mut Bx ) {
443347 if let Some ( funclet) = helper. funclet ( self ) {
@@ -1247,6 +1151,102 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
12471151 )
12481152 }
12491153
1154+ fn codegen_tail_call_terminator (
1155+ & mut self ,
1156+ bx : & mut Bx ,
1157+ func : & mir:: Operand < ' tcx > ,
1158+ args : & [ Spanned < mir:: Operand < ' tcx > > ] ,
1159+ fn_span : Span ,
1160+ mergeable_succ : bool ,
1161+ ) -> MergingSucc {
1162+ // We don't need source_info as we already have fn_span for diagnostics
1163+ let func = self . codegen_operand ( bx, func) ;
1164+ let fn_ty = func. layout . ty ;
1165+
1166+ // Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
1167+ let ( fn_ptr, fn_abi, instance) = match * fn_ty. kind ( ) {
1168+ ty:: FnDef ( def_id, substs) => {
1169+ let instance = ty:: Instance :: expect_resolve (
1170+ bx. tcx ( ) ,
1171+ bx. typing_env ( ) ,
1172+ def_id,
1173+ substs,
1174+ fn_span,
1175+ ) ;
1176+ let fn_ptr = bx. get_fn_addr ( instance) ;
1177+ let fn_abi = bx. fn_abi_of_instance ( instance, ty:: List :: empty ( ) ) ;
1178+ ( fn_ptr, fn_abi, Some ( instance) )
1179+ }
1180+ ty:: FnPtr ( ..) => {
1181+ let sig = fn_ty. fn_sig ( bx. tcx ( ) ) ;
1182+ let extra_args = bx. tcx ( ) . mk_type_list ( & [ ] ) ;
1183+ let fn_ptr = func. immediate ( ) ;
1184+ let fn_abi = bx. fn_abi_of_fn_ptr ( sig, extra_args) ;
1185+ ( fn_ptr, fn_abi, None )
1186+ }
1187+ _ => bug ! ( "{} is not callable" , func. layout. ty) ,
1188+ } ;
1189+
1190+ let mut llargs = Vec :: with_capacity ( args. len ( ) ) ;
1191+ let mut lifetime_ends_after_call = Vec :: new ( ) ;
1192+
1193+ // Process arguments
1194+ for arg in args {
1195+ let op = self . codegen_operand ( bx, & arg. node ) ;
1196+ let arg_idx = llargs. len ( ) ;
1197+
1198+ if arg_idx < fn_abi. args . len ( ) {
1199+ self . codegen_argument (
1200+ bx,
1201+ op,
1202+ & mut llargs,
1203+ & fn_abi. args [ arg_idx] ,
1204+ & mut lifetime_ends_after_call,
1205+ ) ;
1206+ } else {
1207+ // This can happen in case of C-variadic functions
1208+ let is_immediate = match op. val {
1209+ Immediate ( _) => true ,
1210+ _ => false ,
1211+ } ;
1212+
1213+ if is_immediate {
1214+ llargs. push ( op. immediate ( ) ) ;
1215+ } else {
1216+ let temp = PlaceRef :: alloca ( bx, op. layout ) ;
1217+ op. val . store ( bx, temp) ;
1218+ llargs. push ( bx. load (
1219+ bx. backend_type ( op. layout ) ,
1220+ temp. val . llval ,
1221+ temp. val . align ,
1222+ ) ) ;
1223+ }
1224+ }
1225+ }
1226+
1227+ // Call the function
1228+ let fn_ty = bx. fn_decl_backend_type ( fn_abi) ;
1229+ let fn_attrs = if let Some ( instance) = instance
1230+ && bx. tcx ( ) . def_kind ( instance. def_id ( ) ) . has_codegen_attrs ( )
1231+ {
1232+ Some ( bx. tcx ( ) . codegen_fn_attrs ( instance. def_id ( ) ) )
1233+ } else {
1234+ None
1235+ } ;
1236+
1237+ // Perform the actual function call
1238+ let llret = bx. call ( fn_ty, fn_attrs, Some ( fn_abi) , fn_ptr, & llargs, None , instance) ;
1239+
1240+ // Mark as tail call - this is the critical part
1241+ bx. set_tail_call ( llret) ;
1242+
1243+ // Return the result - musttail requires ret immediately after the call
1244+ bx. ret ( llret) ;
1245+
1246+ assert_eq ! ( mergeable_succ, false ) ;
1247+ MergingSucc :: False
1248+ }
1249+
12501250 fn codegen_asm_terminator (
12511251 & mut self ,
12521252 helper : TerminatorCodegenHelper < ' tcx > ,
0 commit comments