1
1
use std:: cmp;
2
2
3
- use rustc_abi:: { BackendRepr , ExternAbi , HasDataLayout , Reg , WrappingRange } ;
3
+ use rustc_abi:: { BackendRepr , ExternAbi , HasDataLayout , Reg , Size , WrappingRange } ;
4
4
use rustc_ast as ast;
5
5
use rustc_ast:: { InlineAsmOptions , InlineAsmTemplatePiece } ;
6
6
use rustc_data_structures:: packed:: Pu128 ;
@@ -158,7 +158,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
158
158
llargs : & [ Bx :: Value ] ,
159
159
destination : Option < ( ReturnDest < ' tcx , Bx :: Value > , mir:: BasicBlock ) > ,
160
160
mut unwind : mir:: UnwindAction ,
161
- copied_constant_arguments : & [ PlaceRef < ' tcx , < Bx as BackendTypes > :: Value > ] ,
161
+ lifetime_ends_after_call : & [ ( Bx :: Value , Size ) ] ,
162
162
instance : Option < Instance < ' tcx > > ,
163
163
mergeable_succ : bool ,
164
164
) -> MergingSucc {
@@ -245,8 +245,8 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
245
245
if let Some ( ( ret_dest, target) ) = destination {
246
246
bx. switch_to_block ( fx. llbb ( target) ) ;
247
247
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) ;
250
250
}
251
251
fx. store_return ( bx, ret_dest, & fn_abi. ret , invokeret) ;
252
252
}
@@ -259,8 +259,8 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
259
259
}
260
260
261
261
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) ;
264
264
}
265
265
fx. store_return ( bx, ret_dest, & fn_abi. ret , llret) ;
266
266
self . funclet_br ( fx, bx, target, mergeable_succ)
@@ -1048,7 +1048,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1048
1048
( args, None )
1049
1049
} ;
1050
1050
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 ( ) ;
1052
1055
' make_args: for ( i, arg) in first_args. iter ( ) . enumerate ( ) {
1053
1056
let mut op = self . codegen_operand ( bx, & arg. node ) ;
1054
1057
@@ -1136,19 +1139,26 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1136
1139
bx. lifetime_start ( tmp. val . llval , tmp. layout . size ) ;
1137
1140
op. val . store ( bx, tmp) ;
1138
1141
op. val = Ref ( tmp. val ) ;
1139
- copied_constant_arguments . push ( tmp) ;
1142
+ lifetime_ends_after_call . push ( ( tmp. val . llval , tmp . layout . size ) ) ;
1140
1143
}
1141
1144
_ => { }
1142
1145
}
1143
1146
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
+ ) ;
1145
1154
}
1146
1155
let num_untupled = untuple. map ( |tup| {
1147
1156
self . codegen_arguments_untupled (
1148
1157
bx,
1149
1158
& tup. node ,
1150
1159
& mut llargs,
1151
1160
& fn_abi. args [ first_args. len ( ) ..] ,
1161
+ & mut lifetime_ends_after_call,
1152
1162
)
1153
1163
} ) ;
1154
1164
@@ -1173,7 +1183,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1173
1183
) ;
1174
1184
1175
1185
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
+ ) ;
1177
1193
}
1178
1194
1179
1195
let fn_ptr = match ( instance, llfn) {
@@ -1189,7 +1205,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1189
1205
& llargs,
1190
1206
destination,
1191
1207
unwind,
1192
- & copied_constant_arguments ,
1208
+ & lifetime_ends_after_call ,
1193
1209
instance,
1194
1210
mergeable_succ,
1195
1211
)
@@ -1479,6 +1495,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1479
1495
op : OperandRef < ' tcx , Bx :: Value > ,
1480
1496
llargs : & mut Vec < Bx :: Value > ,
1481
1497
arg : & ArgAbi < ' tcx , Ty < ' tcx > > ,
1498
+ lifetime_ends_after_call : & mut Vec < ( Bx :: Value , Size ) > ,
1482
1499
) {
1483
1500
match arg. mode {
1484
1501
PassMode :: Ignore => return ,
@@ -1517,7 +1534,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1517
1534
None => arg. layout . align . abi ,
1518
1535
} ;
1519
1536
let scratch = PlaceValue :: alloca ( bx, arg. layout . size , required_align) ;
1537
+ bx. lifetime_start ( scratch. llval , arg. layout . size ) ;
1520
1538
op. val . store ( bx, scratch. with_type ( arg. layout ) ) ;
1539
+ lifetime_ends_after_call. push ( ( scratch. llval , arg. layout . size ) ) ;
1521
1540
( scratch. llval , scratch. align , true )
1522
1541
}
1523
1542
PassMode :: Cast { .. } => {
@@ -1538,7 +1557,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1538
1557
// alignment requirements may be higher than the type's alignment, so copy
1539
1558
// to a higher-aligned alloca.
1540
1559
let scratch = PlaceValue :: alloca ( bx, arg. layout . size , required_align) ;
1560
+ bx. lifetime_start ( scratch. llval , arg. layout . size ) ;
1541
1561
bx. typed_place_copy ( scratch, op_place_val, op. layout ) ;
1562
+ lifetime_ends_after_call. push ( ( scratch. llval , arg. layout . size ) ) ;
1542
1563
( scratch. llval , scratch. align , true )
1543
1564
} else {
1544
1565
( op_place_val. llval , op_place_val. align , true )
@@ -1620,6 +1641,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1620
1641
operand : & mir:: Operand < ' tcx > ,
1621
1642
llargs : & mut Vec < Bx :: Value > ,
1622
1643
args : & [ ArgAbi < ' tcx , Ty < ' tcx > > ] ,
1644
+ lifetime_ends_after_call : & mut Vec < ( Bx :: Value , Size ) > ,
1623
1645
) -> usize {
1624
1646
let tuple = self . codegen_operand ( bx, operand) ;
1625
1647
@@ -1632,13 +1654,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1632
1654
for i in 0 ..tuple. layout . fields . count ( ) {
1633
1655
let field_ptr = tuple_ptr. project_field ( bx, i) ;
1634
1656
let field = bx. load_operand ( field_ptr) ;
1635
- self . codegen_argument ( bx, field, llargs, & args[ i] ) ;
1657
+ self . codegen_argument ( bx, field, llargs, & args[ i] , lifetime_ends_after_call ) ;
1636
1658
}
1637
1659
} else {
1638
1660
// If the tuple is immediate, the elements are as well.
1639
1661
for i in 0 ..tuple. layout . fields . count ( ) {
1640
1662
let op = tuple. extract_field ( self , bx, i) ;
1641
- self . codegen_argument ( bx, op, llargs, & args[ i] ) ;
1663
+ self . codegen_argument ( bx, op, llargs, & args[ i] , lifetime_ends_after_call ) ;
1642
1664
}
1643
1665
}
1644
1666
tuple. layout . fields . count ( )
0 commit comments