mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-27 09:14:20 +00:00
Auto merge of #76123 - tmiasko:inline-args-storage, r=wesleywiser
inliner: Emit storage markers for introduced arg temporaries When introducing argument temporaries during inlining, emit storage marker statements just before the assignment and in the beginning of the return block. This ensures that such temporaries will not be considered live across yield points after inlining inside a generator. Fixes #71793.
This commit is contained in:
commit
0b65a3d0a6
@ -506,7 +506,7 @@ impl Inliner<'tcx> {
|
||||
let return_block = destination.1;
|
||||
|
||||
// Copy the arguments if needed.
|
||||
let args: Vec<_> = self.make_call_args(args, &callsite, caller_body);
|
||||
let args: Vec<_> = self.make_call_args(args, &callsite, caller_body, return_block);
|
||||
|
||||
let bb_len = caller_body.basic_blocks().len();
|
||||
let mut integrator = Integrator {
|
||||
@ -553,6 +553,7 @@ impl Inliner<'tcx> {
|
||||
args: Vec<Operand<'tcx>>,
|
||||
callsite: &CallSite<'tcx>,
|
||||
caller_body: &mut Body<'tcx>,
|
||||
return_block: BasicBlock,
|
||||
) -> Vec<Local> {
|
||||
let tcx = self.tcx;
|
||||
|
||||
@ -581,8 +582,18 @@ impl Inliner<'tcx> {
|
||||
// and the vector is `[closure_ref, tmp0, tmp1, tmp2]`.
|
||||
if tcx.is_closure(callsite.callee) {
|
||||
let mut args = args.into_iter();
|
||||
let self_ = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body);
|
||||
let tuple = self.create_temp_if_necessary(args.next().unwrap(), callsite, caller_body);
|
||||
let self_ = self.create_temp_if_necessary(
|
||||
args.next().unwrap(),
|
||||
callsite,
|
||||
caller_body,
|
||||
return_block,
|
||||
);
|
||||
let tuple = self.create_temp_if_necessary(
|
||||
args.next().unwrap(),
|
||||
callsite,
|
||||
caller_body,
|
||||
return_block,
|
||||
);
|
||||
assert!(args.next().is_none());
|
||||
|
||||
let tuple = Place::from(tuple);
|
||||
@ -602,13 +613,13 @@ impl Inliner<'tcx> {
|
||||
Operand::Move(tcx.mk_place_field(tuple, Field::new(i), ty.expect_ty()));
|
||||
|
||||
// Spill to a local to make e.g., `tmp0`.
|
||||
self.create_temp_if_necessary(tuple_field, callsite, caller_body)
|
||||
self.create_temp_if_necessary(tuple_field, callsite, caller_body, return_block)
|
||||
});
|
||||
|
||||
closure_ref_arg.chain(tuple_tmp_args).collect()
|
||||
} else {
|
||||
args.into_iter()
|
||||
.map(|a| self.create_temp_if_necessary(a, callsite, caller_body))
|
||||
.map(|a| self.create_temp_if_necessary(a, callsite, caller_body, return_block))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
@ -620,6 +631,7 @@ impl Inliner<'tcx> {
|
||||
arg: Operand<'tcx>,
|
||||
callsite: &CallSite<'tcx>,
|
||||
caller_body: &mut Body<'tcx>,
|
||||
return_block: BasicBlock,
|
||||
) -> Local {
|
||||
// FIXME: Analysis of the usage of the arguments to avoid
|
||||
// unnecessary temporaries.
|
||||
@ -642,11 +654,19 @@ impl Inliner<'tcx> {
|
||||
let arg_tmp = LocalDecl::new(ty, callsite.location.span);
|
||||
let arg_tmp = caller_body.local_decls.push(arg_tmp);
|
||||
|
||||
let stmt = Statement {
|
||||
caller_body[callsite.bb].statements.push(Statement {
|
||||
source_info: callsite.location,
|
||||
kind: StatementKind::StorageLive(arg_tmp),
|
||||
});
|
||||
caller_body[callsite.bb].statements.push(Statement {
|
||||
source_info: callsite.location,
|
||||
kind: StatementKind::Assign(box (Place::from(arg_tmp), arg)),
|
||||
};
|
||||
caller_body[callsite.bb].statements.push(stmt);
|
||||
});
|
||||
caller_body[return_block].statements.insert(
|
||||
0,
|
||||
Statement { source_info: callsite.location, kind: StatementKind::StorageDead(arg_tmp) },
|
||||
);
|
||||
|
||||
arg_tmp
|
||||
}
|
||||
}
|
||||
|
@ -22,9 +22,13 @@ fn bar() -> bool {
|
||||
// + literal: Const { ty: fn(i32, i32) -> bool {foo}, val: Value(Scalar(<ZST>)) }
|
||||
StorageLive(_2); // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:6
|
||||
_2 = _1; // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:6
|
||||
StorageLive(_3); // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:13
|
||||
_3 = const 1_i32; // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:13
|
||||
StorageLive(_4); // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:13
|
||||
_4 = const -1_i32; // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:13
|
||||
_0 = Eq(move _3, move _4); // scope 2 at $DIR/inline-any-operand.rs:17:5: 17:11
|
||||
StorageDead(_4); // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:13
|
||||
StorageDead(_3); // scope 1 at $DIR/inline-any-operand.rs:12:5: 12:13
|
||||
StorageDead(_2); // scope 1 at $DIR/inline-any-operand.rs:12:12: 12:13
|
||||
StorageDead(_1); // scope 0 at $DIR/inline-any-operand.rs:13:1: 13:2
|
||||
return; // scope 0 at $DIR/inline-any-operand.rs:13:2: 13:2
|
||||
|
@ -30,9 +30,13 @@ fn foo(_1: T, _2: i32) -> i32 {
|
||||
_7 = _2; // scope 1 at $DIR/inline-closure.rs:12:10: 12:11
|
||||
(_5.0: i32) = move _6; // scope 1 at $DIR/inline-closure.rs:12:5: 12:12
|
||||
(_5.1: i32) = move _7; // scope 1 at $DIR/inline-closure.rs:12:5: 12:12
|
||||
StorageLive(_8); // scope 1 at $DIR/inline-closure.rs:12:5: 12:12
|
||||
_8 = move (_5.0: i32); // scope 1 at $DIR/inline-closure.rs:12:5: 12:12
|
||||
StorageLive(_9); // scope 1 at $DIR/inline-closure.rs:12:5: 12:12
|
||||
_9 = move (_5.1: i32); // scope 1 at $DIR/inline-closure.rs:12:5: 12:12
|
||||
_0 = _8; // scope 2 at $DIR/inline-closure.rs:11:22: 11:24
|
||||
StorageDead(_9); // scope 1 at $DIR/inline-closure.rs:12:5: 12:12
|
||||
StorageDead(_8); // scope 1 at $DIR/inline-closure.rs:12:5: 12:12
|
||||
StorageDead(_7); // scope 1 at $DIR/inline-closure.rs:12:11: 12:12
|
||||
StorageDead(_6); // scope 1 at $DIR/inline-closure.rs:12:11: 12:12
|
||||
StorageDead(_5); // scope 1 at $DIR/inline-closure.rs:12:11: 12:12
|
||||
|
@ -33,9 +33,13 @@ fn foo(_1: T, _2: &i32) -> i32 {
|
||||
_7 = &(*_2); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:10: 16:11
|
||||
(_5.0: &i32) = move _6; // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
|
||||
(_5.1: &i32) = move _7; // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
|
||||
StorageLive(_8); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
|
||||
_8 = move (_5.0: &i32); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
|
||||
StorageLive(_9); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
|
||||
_9 = move (_5.1: &i32); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
|
||||
_0 = (*_8); // scope 3 at $DIR/inline-closure-borrows-arg.rs:14:9: 14:18
|
||||
StorageDead(_9); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
|
||||
StorageDead(_8); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:5: 16:12
|
||||
StorageDead(_7); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:11: 16:12
|
||||
StorageDead(_6); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:11: 16:12
|
||||
StorageDead(_5); // scope 1 at $DIR/inline-closure-borrows-arg.rs:16:11: 16:12
|
||||
|
@ -38,6 +38,7 @@ fn foo(_1: T, _2: i32) -> (i32, T) {
|
||||
StorageLive(_8); // scope 1 at $DIR/inline-closure-captures.rs:12:7: 12:8
|
||||
_8 = _2; // scope 1 at $DIR/inline-closure-captures.rs:12:7: 12:8
|
||||
(_7.0: i32) = move _8; // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
||||
StorageLive(_11); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
||||
_11 = move (_7.0: i32); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
||||
StorageLive(_9); // scope 2 at $DIR/inline-closure-captures.rs:11:19: 11:20
|
||||
_9 = (*((*_6).0: &i32)); // scope 2 at $DIR/inline-closure-captures.rs:11:19: 11:20
|
||||
@ -47,6 +48,7 @@ fn foo(_1: T, _2: i32) -> (i32, T) {
|
||||
(_0.1: T) = move _10; // scope 2 at $DIR/inline-closure-captures.rs:11:18: 11:24
|
||||
StorageDead(_10); // scope 2 at $DIR/inline-closure-captures.rs:11:23: 11:24
|
||||
StorageDead(_9); // scope 2 at $DIR/inline-closure-captures.rs:11:23: 11:24
|
||||
StorageDead(_11); // scope 1 at $DIR/inline-closure-captures.rs:12:5: 12:9
|
||||
StorageDead(_8); // scope 1 at $DIR/inline-closure-captures.rs:12:8: 12:9
|
||||
StorageDead(_7); // scope 1 at $DIR/inline-closure-captures.rs:12:8: 12:9
|
||||
StorageDead(_6); // scope 1 at $DIR/inline-closure-captures.rs:12:8: 12:9
|
||||
|
16
src/test/ui/mir/issue-71793-inline-args-storage.rs
Normal file
16
src/test/ui/mir/issue-71793-inline-args-storage.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// Verifies that inliner emits StorageLive & StorageDead when introducing
|
||||
// temporaries for arguments, so that they don't become part of the generator.
|
||||
// Regression test for #71793.
|
||||
//
|
||||
// check-pass
|
||||
// edition:2018
|
||||
// compile-args: -Zmir-opt-level=2
|
||||
|
||||
#![crate_type = "lib"]
|
||||
|
||||
pub async fn connect() {}
|
||||
|
||||
pub async fn connect_many() {
|
||||
Vec::<String>::new().first().ok_or("").unwrap();
|
||||
connect().await;
|
||||
}
|
Loading…
Reference in New Issue
Block a user