11use std:: cmp;
22
3- use rustc_abi:: { BackendRepr , ExternAbi , HasDataLayout , Reg , WrappingRange } ;
3+ use rustc_abi:: { BackendRepr , ExternAbi , HasDataLayout , Reg , Size , WrappingRange } ;
44use rustc_ast as ast;
55use rustc_ast:: { InlineAsmOptions , InlineAsmTemplatePiece } ;
66use rustc_data_structures:: packed:: Pu128 ;
@@ -158,7 +158,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
158158 llargs : & [ Bx :: Value ] ,
159159 destination : Option < ( ReturnDest < ' tcx , Bx :: Value > , mir:: BasicBlock ) > ,
160160 mut unwind : mir:: UnwindAction ,
161- copied_constant_arguments : & [ PlaceRef < ' tcx , < Bx as BackendTypes > :: Value > ] ,
161+ lifetime_ends_after_call : & [ ( Bx :: Value , Size ) ] ,
162162 instance : Option < Instance < ' tcx > > ,
163163 mergeable_succ : bool ,
164164 ) -> MergingSucc {
@@ -245,8 +245,8 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
245245 if let Some ( ( ret_dest, target) ) = destination {
246246 bx. switch_to_block ( fx. llbb ( target) ) ;
247247 fx. set_debug_loc ( bx, self . terminator . source_info ) ;
248- for tmp in copied_constant_arguments {
249- bx. lifetime_end ( tmp. val . llval , tmp . layout . size ) ;
248+ for & ( tmp, size ) in lifetime_ends_after_call {
249+ bx. lifetime_end ( tmp, size) ;
250250 }
251251 fx. store_return ( bx, ret_dest, & fn_abi. ret , invokeret) ;
252252 }
@@ -259,8 +259,8 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
259259 }
260260
261261 if let Some ( ( ret_dest, target) ) = destination {
262- for tmp in copied_constant_arguments {
263- bx. lifetime_end ( tmp. val . llval , tmp . layout . size ) ;
262+ for & ( tmp, size ) in lifetime_ends_after_call {
263+ bx. lifetime_end ( tmp, size) ;
264264 }
265265 fx. store_return ( bx, ret_dest, & fn_abi. ret , llret) ;
266266 self . funclet_br ( fx, bx, target, mergeable_succ)
@@ -1048,7 +1048,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
10481048 ( args, None )
10491049 } ;
10501050
1051- let mut copied_constant_arguments = vec ! [ ] ;
1051+ // When generating arguments we sometimes introduce temporary allocations with lifetime
1052+ // that extend for the duration of a call. Keep track of those allocations and their sizes
1053+ // to generate `lifetime_end` when the call returns.
1054+ let mut lifetime_ends_after_call: Vec < ( Bx :: Value , Size ) > = Vec :: new ( ) ;
10521055 ' make_args: for ( i, arg) in first_args. iter ( ) . enumerate ( ) {
10531056 let mut op = self . codegen_operand ( bx, & arg. node ) ;
10541057
@@ -1136,19 +1139,26 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
11361139 bx. lifetime_start ( tmp. val . llval , tmp. layout . size ) ;
11371140 op. val . store ( bx, tmp) ;
11381141 op. val = Ref ( tmp. val ) ;
1139- copied_constant_arguments . push ( tmp) ;
1142+ lifetime_ends_after_call . push ( ( tmp. val . llval , tmp . layout . size ) ) ;
11401143 }
11411144 _ => { }
11421145 }
11431146
1144- self . codegen_argument ( bx, op, & mut llargs, & fn_abi. args [ i] ) ;
1147+ self . codegen_argument (
1148+ bx,
1149+ op,
1150+ & mut llargs,
1151+ & fn_abi. args [ i] ,
1152+ & mut lifetime_ends_after_call,
1153+ ) ;
11451154 }
11461155 let num_untupled = untuple. map ( |tup| {
11471156 self . codegen_arguments_untupled (
11481157 bx,
11491158 & tup. node ,
11501159 & mut llargs,
11511160 & fn_abi. args [ first_args. len ( ) ..] ,
1161+ & mut lifetime_ends_after_call,
11521162 )
11531163 } ) ;
11541164
@@ -1173,7 +1183,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
11731183 ) ;
11741184
11751185 let last_arg = fn_abi. args . last ( ) . unwrap ( ) ;
1176- self . codegen_argument ( bx, location, & mut llargs, last_arg) ;
1186+ self . codegen_argument (
1187+ bx,
1188+ location,
1189+ & mut llargs,
1190+ last_arg,
1191+ & mut lifetime_ends_after_call,
1192+ ) ;
11771193 }
11781194
11791195 let fn_ptr = match ( instance, llfn) {
@@ -1190,7 +1206,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
11901206 & llargs,
11911207 destination,
11921208 unwind,
1193- & copied_constant_arguments ,
1209+ & lifetime_ends_after_call ,
11941210 instance,
11951211 mergeable_succ,
11961212 )
@@ -1480,6 +1496,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
14801496 op : OperandRef < ' tcx , Bx :: Value > ,
14811497 llargs : & mut Vec < Bx :: Value > ,
14821498 arg : & ArgAbi < ' tcx , Ty < ' tcx > > ,
1499+ lifetime_ends_after_call : & mut Vec < ( Bx :: Value , Size ) > ,
14831500 ) {
14841501 match arg. mode {
14851502 PassMode :: Ignore => return ,
@@ -1518,7 +1535,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
15181535 None => arg. layout . align . abi ,
15191536 } ;
15201537 let scratch = PlaceValue :: alloca ( bx, arg. layout . size , required_align) ;
1538+ bx. lifetime_start ( scratch. llval , arg. layout . size ) ;
15211539 op. val . store ( bx, scratch. with_type ( arg. layout ) ) ;
1540+ lifetime_ends_after_call. push ( ( scratch. llval , arg. layout . size ) ) ;
15221541 ( scratch. llval , scratch. align , true )
15231542 }
15241543 PassMode :: Cast { .. } => {
@@ -1539,7 +1558,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
15391558 // alignment requirements may be higher than the type's alignment, so copy
15401559 // to a higher-aligned alloca.
15411560 let scratch = PlaceValue :: alloca ( bx, arg. layout . size , required_align) ;
1561+ bx. lifetime_start ( scratch. llval , arg. layout . size ) ;
15421562 bx. typed_place_copy ( scratch, op_place_val, op. layout ) ;
1563+ lifetime_ends_after_call. push ( ( scratch. llval , arg. layout . size ) ) ;
15431564 ( scratch. llval , scratch. align , true )
15441565 } else {
15451566 ( op_place_val. llval , op_place_val. align , true )
@@ -1621,6 +1642,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
16211642 operand : & mir:: Operand < ' tcx > ,
16221643 llargs : & mut Vec < Bx :: Value > ,
16231644 args : & [ ArgAbi < ' tcx , Ty < ' tcx > > ] ,
1645+ lifetime_ends_after_call : & mut Vec < ( Bx :: Value , Size ) > ,
16241646 ) -> usize {
16251647 let tuple = self . codegen_operand ( bx, operand) ;
16261648
@@ -1633,13 +1655,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
16331655 for i in 0 ..tuple. layout . fields . count ( ) {
16341656 let field_ptr = tuple_ptr. project_field ( bx, i) ;
16351657 let field = bx. load_operand ( field_ptr) ;
1636- self . codegen_argument ( bx, field, llargs, & args[ i] ) ;
1658+ self . codegen_argument ( bx, field, llargs, & args[ i] , lifetime_ends_after_call ) ;
16371659 }
16381660 } else {
16391661 // If the tuple is immediate, the elements are as well.
16401662 for i in 0 ..tuple. layout . fields . count ( ) {
16411663 let op = tuple. extract_field ( self , bx, i) ;
1642- self . codegen_argument ( bx, op, llargs, & args[ i] ) ;
1664+ self . codegen_argument ( bx, op, llargs, & args[ i] , lifetime_ends_after_call ) ;
16431665 }
16441666 }
16451667 tuple. layout . fields . count ( )
0 commit comments