@@ -342,102 +342,6 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
342
342
343
343
/// Codegen implementations for some terminator variants.
344
344
impl < ' 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
-
441
345
/// Generates code for a `Resume` terminator.
442
346
fn codegen_resume_terminator ( & mut self , helper : TerminatorCodegenHelper < ' tcx > , bx : & mut Bx ) {
443
347
if let Some ( funclet) = helper. funclet ( self ) {
@@ -1247,6 +1151,102 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1247
1151
)
1248
1152
}
1249
1153
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
+
1250
1250
fn codegen_asm_terminator (
1251
1251
& mut self ,
1252
1252
helper : TerminatorCodegenHelper < ' tcx > ,
0 commit comments