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> {
158158llargs : & [ Bx :: Value ] ,
159159destination : Option < ( ReturnDest < ' tcx , Bx :: Value > , mir:: BasicBlock ) > ,
160160mut unwind : mir:: UnwindAction ,
161- copied_constant_arguments : & [ PlaceRef < ' tcx , < Bx as BackendTypes > :: Value > ] ,
161+ lifetime_ends_after_call : & [ ( Bx :: Value , Size ) ] ,
162162instance : Option < Instance < ' tcx > > ,
163163mergeable_succ : bool ,
164164) -> MergingSucc {
@@ -245,8 +245,8 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
245245if 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 tmpin 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
261261if let Some ( ( ret_dest, target) ) = destination {
262- for tmpin 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) ;
266266self . 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 ( ) {
10531056let 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}
11461155let num_untupled = untuple. map ( |tup| {
11471156self . 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
11751185let 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
11791195let 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> {
14801496op : OperandRef < ' tcx , Bx :: Value > ,
14811497llargs : & mut Vec < Bx :: Value > ,
14821498arg : & ArgAbi < ' tcx , Ty < ' tcx > > ,
1499+ lifetime_ends_after_call : & mut Vec < ( Bx :: Value , Size ) > ,
14831500) {
14841501match arg. mode {
14851502PassMode :: Ignore => return ,
@@ -1518,7 +1535,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
15181535None => arg. layout . align . abi ,
15191536} ;
15201537let 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}
15241543PassMode :: 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.
15411560let 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> {
16211642operand : & mir:: Operand < ' tcx > ,
16221643llargs : & mut Vec < Bx :: Value > ,
16231644args : & [ ArgAbi < ' tcx , Ty < ' tcx > > ] ,
1645+ lifetime_ends_after_call : & mut Vec < ( Bx :: Value , Size ) > ,
16241646) -> usize {
16251647let tuple = self . codegen_operand ( bx, operand) ;
16261648
@@ -1633,13 +1655,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
16331655for i in 0 ..tuple. layout . fields . count ( ) {
16341656let field_ptr = tuple_ptr. project_field ( bx, i) ;
16351657let 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.
16401662for i in 0 ..tuple. layout . fields . count ( ) {
16411663let 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