Skip to content

Commit 3ebe058

Browse files
committed
Make ConstAnalysis::ecx a RefCell.
Of the many dataflow analyses, `ConstAnalysis` is the only one that requires the analysis be mutabile when used with `ResultsVisitor`. It's needed because of the `ecx` field -- `ecx.intern_with_temp_alloc` is called during visiting and it takes `&mut self`. This commit changes `ConstAnalysis` to use interior mutability for the `ecx` field. This is a bit annoying for `ConstAnalysis`, but it will allow more immutability in `ResultsVisitor`, as seen in the next commit.
1 parent f977dfc commit 3ebe058

File tree

1 file changed

+48
-22
lines changed

1 file changed

+48
-22
lines changed

compiler/rustc_mir_transform/src/dataflow_const_prop.rs

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
//! Currently, this pass only propagates scalar values.
44
55
use std::assert_matches::assert_matches;
6+
use std::cell::RefCell;
67
use std::fmt::Formatter;
78

89
use rustc_abi::{BackendRepr, FIRST_VARIANT, FieldIdx, Size, VariantIdx};
@@ -85,7 +86,7 @@ struct ConstAnalysis<'a, 'tcx> {
8586
map: Map<'tcx>,
8687
tcx: TyCtxt<'tcx>,
8788
local_decls: &'a LocalDecls<'tcx>,
88-
ecx: InterpCx<'tcx, DummyMachine>,
89+
ecx: RefCell<InterpCx<'tcx, DummyMachine>>,
8990
typing_env: ty::TypingEnv<'tcx>,
9091
}
9192

@@ -153,7 +154,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
153154
map,
154155
tcx,
155156
local_decls: &body.local_decls,
156-
ecx: InterpCx::new(tcx, DUMMY_SP, typing_env, DummyMachine),
157+
ecx: RefCell::new(InterpCx::new(tcx, DUMMY_SP, typing_env, DummyMachine)),
157158
typing_env,
158159
}
159160
}
@@ -410,6 +411,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
410411
match self.eval_operand(operand, state) {
411412
FlatSet::Elem(op) => self
412413
.ecx
414+
.borrow()
413415
.int_to_int_or_float(&op, layout)
414416
.discard_err()
415417
.map_or(FlatSet::Top, |result| self.wrap_immediate(*result)),
@@ -424,6 +426,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
424426
match self.eval_operand(operand, state) {
425427
FlatSet::Elem(op) => self
426428
.ecx
429+
.borrow()
427430
.float_to_float_or_int(&op, layout)
428431
.discard_err()
429432
.map_or(FlatSet::Top, |result| self.wrap_immediate(*result)),
@@ -454,6 +457,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
454457
match self.eval_operand(operand, state) {
455458
FlatSet::Elem(value) => self
456459
.ecx
460+
.borrow()
457461
.unary_op(*op, &value)
458462
.discard_err()
459463
.map_or(FlatSet::Top, |val| self.wrap_immediate(*val)),
@@ -468,6 +472,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
468472
let val = match null_op {
469473
NullOp::OffsetOf(fields) => self
470474
.ecx
475+
.borrow()
471476
.tcx
472477
.offset_of_subfield(self.typing_env, layout, fields.iter())
473478
.bytes(),
@@ -556,8 +561,11 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
556561
}
557562
}
558563
Operand::Constant(box constant) => {
559-
if let Some(constant) =
560-
self.ecx.eval_mir_constant(&constant.const_, constant.span, None).discard_err()
564+
if let Some(constant) = self
565+
.ecx
566+
.borrow()
567+
.eval_mir_constant(&constant.const_, constant.span, None)
568+
.discard_err()
561569
{
562570
self.assign_constant(state, place, constant, &[]);
563571
}
@@ -587,7 +595,9 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
587595
return;
588596
}
589597
}
590-
operand = if let Some(operand) = self.ecx.project(&operand, proj_elem).discard_err() {
598+
operand = if let Some(operand) =
599+
self.ecx.borrow().project(&operand, proj_elem).discard_err()
600+
{
591601
operand
592602
} else {
593603
return;
@@ -598,17 +608,22 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
598608
place,
599609
operand,
600610
&mut |elem, op| match elem {
601-
TrackElem::Field(idx) => self.ecx.project_field(op, idx).discard_err(),
602-
TrackElem::Variant(idx) => self.ecx.project_downcast(op, idx).discard_err(),
611+
TrackElem::Field(idx) => self.ecx.borrow().project_field(op, idx).discard_err(),
612+
TrackElem::Variant(idx) => {
613+
self.ecx.borrow().project_downcast(op, idx).discard_err()
614+
}
603615
TrackElem::Discriminant => {
604-
let variant = self.ecx.read_discriminant(op).discard_err()?;
605-
let discr_value =
606-
self.ecx.discriminant_for_variant(op.layout.ty, variant).discard_err()?;
616+
let variant = self.ecx.borrow().read_discriminant(op).discard_err()?;
617+
let discr_value = self
618+
.ecx
619+
.borrow()
620+
.discriminant_for_variant(op.layout.ty, variant)
621+
.discard_err()?;
607622
Some(discr_value.into())
608623
}
609624
TrackElem::DerefLen => {
610-
let op: OpTy<'_> = self.ecx.deref_pointer(op).discard_err()?.into();
611-
let len_usize = op.len(&self.ecx).discard_err()?;
625+
let op: OpTy<'_> = self.ecx.borrow().deref_pointer(op).discard_err()?.into();
626+
let len_usize = op.len(&self.ecx.borrow()).discard_err()?;
612627
let layout = self
613628
.tcx
614629
.layout_of(self.typing_env.as_query_input(self.tcx.types.usize))
@@ -617,7 +632,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
617632
}
618633
},
619634
&mut |place, op| {
620-
if let Some(imm) = self.ecx.read_immediate_raw(op).discard_err()
635+
if let Some(imm) = self.ecx.borrow().read_immediate_raw(op).discard_err()
621636
&& let Some(imm) = imm.right()
622637
{
623638
let elem = self.wrap_immediate(*imm);
@@ -641,7 +656,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
641656
(FlatSet::Bottom, _) | (_, FlatSet::Bottom) => (FlatSet::Bottom, FlatSet::Bottom),
642657
// Both sides are known, do the actual computation.
643658
(FlatSet::Elem(left), FlatSet::Elem(right)) => {
644-
match self.ecx.binary_op(op, &left, &right).discard_err() {
659+
match self.ecx.borrow().binary_op(op, &left, &right).discard_err() {
645660
// Ideally this would return an Immediate, since it's sometimes
646661
// a pair and sometimes not. But as a hack we always return a pair
647662
// and just make the 2nd component `Bottom` when it does not exist.
@@ -714,8 +729,11 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
714729
return None;
715730
}
716731
let enum_ty_layout = self.tcx.layout_of(self.typing_env.as_query_input(enum_ty)).ok()?;
717-
let discr_value =
718-
self.ecx.discriminant_for_variant(enum_ty_layout.ty, variant_index).discard_err()?;
732+
let discr_value = self
733+
.ecx
734+
.borrow()
735+
.discriminant_for_variant(enum_ty_layout.ty, variant_index)
736+
.discard_err()?;
719737
Some(discr_value.to_scalar())
720738
}
721739

@@ -956,7 +974,7 @@ impl<'tcx> ResultsVisitor<'tcx, ConstAnalysis<'_, 'tcx>> for Collector<'_, 'tcx>
956974
OperandCollector {
957975
state,
958976
visitor: self,
959-
ecx: &mut analysis.ecx,
977+
ecx: &mut analysis.ecx.borrow_mut(),
960978
map: &analysis.map,
961979
}
962980
.visit_rvalue(rvalue, location);
@@ -978,9 +996,12 @@ impl<'tcx> ResultsVisitor<'tcx, ConstAnalysis<'_, 'tcx>> for Collector<'_, 'tcx>
978996
// Don't overwrite the assignment if it already uses a constant (to keep the span).
979997
}
980998
StatementKind::Assign(box (place, _)) => {
981-
if let Some(value) =
982-
self.try_make_constant(&mut analysis.ecx, place, state, &analysis.map)
983-
{
999+
if let Some(value) = self.try_make_constant(
1000+
&mut analysis.ecx.borrow_mut(),
1001+
place,
1002+
state,
1003+
&analysis.map,
1004+
) {
9841005
self.patch.assignments.insert(location, value);
9851006
}
9861007
}
@@ -995,8 +1016,13 @@ impl<'tcx> ResultsVisitor<'tcx, ConstAnalysis<'_, 'tcx>> for Collector<'_, 'tcx>
9951016
terminator: &Terminator<'tcx>,
9961017
location: Location,
9971018
) {
998-
OperandCollector { state, visitor: self, ecx: &mut analysis.ecx, map: &analysis.map }
999-
.visit_terminator(terminator, location);
1019+
OperandCollector {
1020+
state,
1021+
visitor: self,
1022+
ecx: &mut analysis.ecx.borrow_mut(),
1023+
map: &analysis.map,
1024+
}
1025+
.visit_terminator(terminator, location);
10001026
}
10011027
}
10021028

0 commit comments

Comments
 (0)