Skip to content

Commit 43d9f38

Browse files
committed
Auto merge of #96098 - JakobDegen:always-return-place, r=oli-obk
Refactor call terminator to always include destination place In #71117 people seemed to agree that call terminators should always have a destination place, even if the call was guaranteed to diverge. This implements that. Unsurprisingly, the diff touches a lot of code, but thankfully I had to do almost nothing interesting. The only interesting thing came up in const prop, where the stack frame having no return place was also used to indicate that the layout could not be computed (or similar). I replaced this with a ZST allocation, which should continue to do the right things. cc `@RalfJung` `@eddyb` who were involved in the original conversation r? rust-lang/mir-opt
2 parents acb5c16 + 09b0936 commit 43d9f38

File tree

67 files changed

+422
-412
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+422
-412
lines changed

compiler/rustc_borrowck/src/constraint_generation.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,7 @@ impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> {
140140
// A `Call` terminator's return value can be a local which has borrows,
141141
// so we need to record those as `killed` as well.
142142
if let TerminatorKind::Call { destination, .. } = terminator.kind {
143-
if let Some((place, _)) = destination {
144-
self.record_killed_borrows_for_place(place, location);
145-
}
143+
self.record_killed_borrows_for_place(destination, location);
146144
}
147145

148146
self.super_terminator(terminator, location);

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2198,10 +2198,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
21982198
"annotate_argument_and_return_for_borrow: target={:?} terminator={:?}",
21992199
target, terminator
22002200
);
2201-
if let TerminatorKind::Call { destination: Some((place, _)), args, .. } =
2201+
if let TerminatorKind::Call { destination, target: Some(_), args, .. } =
22022202
&terminator.kind
22032203
{
2204-
if let Some(assigned_to) = place.as_local() {
2204+
if let Some(assigned_to) = destination.as_local() {
22052205
debug!(
22062206
"annotate_argument_and_return_for_borrow: assigned_to={:?} args={:?}",
22072207
assigned_to, args

compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -705,10 +705,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
705705
let terminator = block.terminator();
706706
debug!("was_captured_by_trait_object: terminator={:?}", terminator);
707707

708-
if let TerminatorKind::Call { destination: Some((place, block)), args, .. } =
708+
if let TerminatorKind::Call { destination, target: Some(block), args, .. } =
709709
&terminator.kind
710710
{
711-
if let Some(dest) = place.as_local() {
711+
if let Some(dest) = destination.as_local() {
712712
debug!(
713713
"was_captured_by_trait_object: target={:?} dest={:?} args={:?}",
714714
target, dest, args

compiler/rustc_borrowck/src/invalidation.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
124124
ref func,
125125
ref args,
126126
destination,
127+
target: _,
127128
cleanup: _,
128129
from_hir_call: _,
129130
fn_span: _,
@@ -132,9 +133,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
132133
for arg in args {
133134
self.consume_operand(location, arg);
134135
}
135-
if let Some((dest, _ /*bb*/)) = destination {
136-
self.mutate_place(location, *dest, Deep);
137-
}
136+
self.mutate_place(location, *destination, Deep);
138137
}
139138
TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => {
140139
self.consume_operand(location, cond);

compiler/rustc_borrowck/src/lib.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,8 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
661661
TerminatorKind::Call {
662662
ref func,
663663
ref args,
664-
ref destination,
664+
destination,
665+
target: _,
665666
cleanup: _,
666667
from_hir_call: _,
667668
fn_span: _,
@@ -670,9 +671,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
670671
for arg in args {
671672
self.consume_operand(loc, (arg, span), flow_state);
672673
}
673-
if let Some((dest, _ /*bb*/)) = *destination {
674-
self.mutate_place(loc, (dest, span), Deep, flow_state);
675-
}
674+
self.mutate_place(loc, (destination, span), Deep, flow_state);
676675
}
677676
TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => {
678677
self.consume_operand(loc, (cond, span), flow_state);

compiler/rustc_borrowck/src/type_check/mod.rs

+12-9
Original file line numberDiff line numberDiff line change
@@ -1403,7 +1403,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
14031403
}
14041404
// FIXME: check the values
14051405
}
1406-
TerminatorKind::Call { ref func, ref args, ref destination, from_hir_call, .. } => {
1406+
TerminatorKind::Call {
1407+
ref func, ref args, destination, target, from_hir_call, ..
1408+
} => {
14071409
self.check_operand(func, term_location);
14081410
for arg in args {
14091411
self.check_operand(arg, term_location);
@@ -1424,7 +1426,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
14241426
sig,
14251427
);
14261428
let sig = self.normalize(sig, term_location);
1427-
self.check_call_dest(body, term, &sig, destination, term_location);
1429+
self.check_call_dest(body, term, &sig, destination, target, term_location);
14281430

14291431
self.prove_predicates(
14301432
sig.inputs_and_output
@@ -1502,15 +1504,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
15021504
body: &Body<'tcx>,
15031505
term: &Terminator<'tcx>,
15041506
sig: &ty::FnSig<'tcx>,
1505-
destination: &Option<(Place<'tcx>, BasicBlock)>,
1507+
destination: Place<'tcx>,
1508+
target: Option<BasicBlock>,
15061509
term_location: Location,
15071510
) {
15081511
let tcx = self.tcx();
1509-
match *destination {
1510-
Some((ref dest, _target_block)) => {
1511-
let dest_ty = dest.ty(body, tcx).ty;
1512+
match target {
1513+
Some(_) => {
1514+
let dest_ty = destination.ty(body, tcx).ty;
15121515
let dest_ty = self.normalize(dest_ty, term_location);
1513-
let category = match dest.as_local() {
1516+
let category = match destination.as_local() {
15141517
Some(RETURN_PLACE) => {
15151518
if let BorrowCheckContext {
15161519
universal_regions:
@@ -1659,8 +1662,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
16591662
self.assert_iscleanup(body, block_data, unwind, true);
16601663
}
16611664
}
1662-
TerminatorKind::Call { ref destination, cleanup, .. } => {
1663-
if let &Some((_, target)) = destination {
1665+
TerminatorKind::Call { ref target, cleanup, .. } => {
1666+
if let &Some(target) = target {
16641667
self.assert_iscleanup(body, block_data, target, is_cleanup);
16651668
}
16661669
if let Some(cleanup) = cleanup {

compiler/rustc_borrowck/src/used_muts.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ impl<'visit, 'cx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'tc
6666
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
6767
debug!("visit_terminator: terminator={:?}", terminator);
6868
match &terminator.kind {
69-
TerminatorKind::Call { destination: Some((into, _)), .. } => {
70-
self.remove_never_initialized_mut_locals(*into);
69+
TerminatorKind::Call { destination, .. } => {
70+
self.remove_never_initialized_mut_locals(*destination);
7171
}
7272
TerminatorKind::DropAndReplace { place, .. } => {
7373
self.remove_never_initialized_mut_locals(*place);

compiler/rustc_codegen_cranelift/src/abi/mod.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -312,13 +312,14 @@ pub(crate) fn codegen_terminator_call<'tcx>(
312312
source_info: mir::SourceInfo,
313313
func: &Operand<'tcx>,
314314
args: &[Operand<'tcx>],
315-
mir_dest: Option<(Place<'tcx>, BasicBlock)>,
315+
destination: Place<'tcx>,
316+
target: Option<BasicBlock>,
316317
) {
317318
let fn_ty = fx.monomorphize(func.ty(fx.mir, fx.tcx));
318319
let fn_sig =
319320
fx.tcx.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), fn_ty.fn_sig(fx.tcx));
320321

321-
let destination = mir_dest.map(|(place, bb)| (codegen_place(fx, place), bb));
322+
let ret_place = codegen_place(fx, destination);
322323

323324
// Handle special calls like instrinsics and empty drop glue.
324325
let instance = if let ty::FnDef(def_id, substs) = *fn_ty.kind() {
@@ -333,7 +334,8 @@ pub(crate) fn codegen_terminator_call<'tcx>(
333334
&fx.tcx.symbol_name(instance).name,
334335
substs,
335336
args,
336-
destination,
337+
ret_place,
338+
target,
337339
);
338340
return;
339341
}
@@ -344,14 +346,15 @@ pub(crate) fn codegen_terminator_call<'tcx>(
344346
fx,
345347
instance,
346348
args,
347-
destination,
349+
ret_place,
350+
target,
348351
source_info,
349352
);
350353
return;
351354
}
352355
InstanceDef::DropGlue(_, None) => {
353356
// empty drop glue - a nop.
354-
let (_, dest) = destination.expect("Non terminating drop_in_place_real???");
357+
let dest = target.expect("Non terminating drop_in_place_real???");
355358
let ret_block = fx.get_block(dest);
356359
fx.bcx.ins().jump(ret_block, &[]);
357360
return;
@@ -377,7 +380,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
377380
.unwrap_or(false);
378381
if is_cold {
379382
fx.bcx.set_cold_block(fx.bcx.current_block().unwrap());
380-
if let Some((_place, destination_block)) = destination {
383+
if let Some(destination_block) = target {
381384
fx.bcx.set_cold_block(fx.get_block(destination_block));
382385
}
383386
}
@@ -459,7 +462,6 @@ pub(crate) fn codegen_terminator_call<'tcx>(
459462
}
460463
};
461464

462-
let ret_place = destination.map(|(place, _)| place);
463465
self::returning::codegen_with_call_return_arg(fx, &fn_abi.ret, ret_place, |fx, return_ptr| {
464466
let call_args = return_ptr
465467
.into_iter()
@@ -511,7 +513,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
511513
call_inst
512514
});
513515

514-
if let Some((_, dest)) = destination {
516+
if let Some(dest) = target {
515517
let ret_block = fx.get_block(dest);
516518
fx.bcx.ins().jump(ret_block, &[]);
517519
} else {

compiler/rustc_codegen_cranelift/src/abi/returning.rs

+18-33
Original file line numberDiff line numberDiff line change
@@ -56,23 +56,22 @@ pub(super) fn codegen_return_param<'tcx>(
5656
pub(super) fn codegen_with_call_return_arg<'tcx>(
5757
fx: &mut FunctionCx<'_, '_, 'tcx>,
5858
ret_arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
59-
ret_place: Option<CPlace<'tcx>>,
59+
ret_place: CPlace<'tcx>,
6060
f: impl FnOnce(&mut FunctionCx<'_, '_, 'tcx>, Option<Value>) -> Inst,
6161
) {
6262
let (ret_temp_place, return_ptr) = match ret_arg_abi.mode {
6363
PassMode::Ignore => (None, None),
64-
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => match ret_place {
65-
Some(ret_place) if matches!(ret_place.inner(), CPlaceInner::Addr(_, None)) => {
64+
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => {
65+
if matches!(ret_place.inner(), CPlaceInner::Addr(_, None)) {
6666
// This is an optimization to prevent unnecessary copies of the return value when
6767
// the return place is already a memory place as opposed to a register.
6868
// This match arm can be safely removed.
6969
(None, Some(ret_place.to_ptr().get_addr(fx)))
70-
}
71-
_ => {
70+
} else {
7271
let place = CPlace::new_stack_slot(fx, ret_arg_abi.layout);
7372
(Some(place), Some(place.to_ptr().get_addr(fx)))
7473
}
75-
},
74+
}
7675
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => {
7776
unreachable!("unsized return value")
7877
}
@@ -84,39 +83,25 @@ pub(super) fn codegen_with_call_return_arg<'tcx>(
8483
match ret_arg_abi.mode {
8584
PassMode::Ignore => {}
8685
PassMode::Direct(_) => {
87-
if let Some(ret_place) = ret_place {
88-
let ret_val = fx.bcx.inst_results(call_inst)[0];
89-
ret_place.write_cvalue(fx, CValue::by_val(ret_val, ret_arg_abi.layout));
90-
}
86+
let ret_val = fx.bcx.inst_results(call_inst)[0];
87+
ret_place.write_cvalue(fx, CValue::by_val(ret_val, ret_arg_abi.layout));
9188
}
9289
PassMode::Pair(_, _) => {
93-
if let Some(ret_place) = ret_place {
94-
let ret_val_a = fx.bcx.inst_results(call_inst)[0];
95-
let ret_val_b = fx.bcx.inst_results(call_inst)[1];
96-
ret_place.write_cvalue(
97-
fx,
98-
CValue::by_val_pair(ret_val_a, ret_val_b, ret_arg_abi.layout),
99-
);
100-
}
90+
let ret_val_a = fx.bcx.inst_results(call_inst)[0];
91+
let ret_val_b = fx.bcx.inst_results(call_inst)[1];
92+
ret_place
93+
.write_cvalue(fx, CValue::by_val_pair(ret_val_a, ret_val_b, ret_arg_abi.layout));
10194
}
10295
PassMode::Cast(cast) => {
103-
if let Some(ret_place) = ret_place {
104-
let results = fx
105-
.bcx
106-
.inst_results(call_inst)
107-
.iter()
108-
.copied()
109-
.collect::<SmallVec<[Value; 2]>>();
110-
let result =
111-
super::pass_mode::from_casted_value(fx, &results, ret_place.layout(), cast);
112-
ret_place.write_cvalue(fx, result);
113-
}
96+
let results =
97+
fx.bcx.inst_results(call_inst).iter().copied().collect::<SmallVec<[Value; 2]>>();
98+
let result =
99+
super::pass_mode::from_casted_value(fx, &results, ret_place.layout(), cast);
100+
ret_place.write_cvalue(fx, result);
114101
}
115102
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => {
116-
if let (Some(ret_place), Some(ret_temp_place)) = (ret_place, ret_temp_place) {
117-
// Both ret_place and ret_temp_place must be Some. If ret_place is None, this is
118-
// a non-returning call. If ret_temp_place is None, it is not necessary to copy the
119-
// return value.
103+
if let Some(ret_temp_place) = ret_temp_place {
104+
// If ret_temp_place is None, it is not necessary to copy the return value.
120105
let ret_temp_value = ret_temp_place.to_cvalue(fx);
121106
ret_place.write_cvalue(fx, ret_temp_value);
122107
}

compiler/rustc_codegen_cranelift/src/base.rs

+2
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,7 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
393393
func,
394394
args,
395395
destination,
396+
target,
396397
fn_span,
397398
cleanup: _,
398399
from_hir_call: _,
@@ -404,6 +405,7 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
404405
func,
405406
args,
406407
*destination,
408+
*target,
407409
)
408410
});
409411
}

compiler/rustc_codegen_cranelift/src/constant.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -542,8 +542,8 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
542542
| TerminatorKind::FalseEdge { .. }
543543
| TerminatorKind::FalseUnwind { .. } => unreachable!(),
544544
TerminatorKind::InlineAsm { .. } => return None,
545-
TerminatorKind::Call { destination: Some((call_place, _)), .. }
546-
if call_place == place =>
545+
TerminatorKind::Call { destination, target: Some(_), .. }
546+
if destination == place =>
547547
{
548548
return None;
549549
}

compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
1010
intrinsic: &str,
1111
_substs: SubstsRef<'tcx>,
1212
args: &[mir::Operand<'tcx>],
13-
destination: Option<(CPlace<'tcx>, BasicBlock)>,
13+
ret: CPlace<'tcx>,
14+
target: Option<BasicBlock>,
1415
) {
15-
let ret = destination.unwrap().0;
16-
1716
intrinsic_match! {
1817
fx, intrinsic, args,
1918
_ => {
@@ -126,7 +125,7 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
126125
};
127126
}
128127

129-
let dest = destination.expect("all llvm intrinsics used by stdlib should return").1;
128+
let dest = target.expect("all llvm intrinsics used by stdlib should return");
130129
let ret_block = fx.get_block(dest);
131130
fx.bcx.ins().jump(ret_block, &[]);
132131
}

0 commit comments

Comments
 (0)