Add helpful logging statements.

This commit adds logging statements to `promote_consts` and
`qualify_consts` to make it easier to understand what it is doing.
This commit is contained in:
David Wood 2018-10-26 12:11:19 +02:00
parent 42c11de47b
commit 9169f817b3
No known key found for this signature in database
GPG Key ID: 01760B4F9F53F154
2 changed files with 29 additions and 1 deletions

View File

@ -53,6 +53,7 @@ pub enum TempState {
impl TempState {
pub fn is_promotable(&self) -> bool {
debug!("is_promotable: self={:?}", self);
if let TempState::Defined { uses, .. } = *self {
uses > 0
} else {
@ -88,6 +89,7 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> {
&index: &Local,
context: PlaceContext<'tcx>,
location: Location) {
debug!("visit_local: index={:?} context={:?} location={:?}", index, context, location);
// We're only interested in temporaries
if self.mir.local_kind(index) != LocalKind::Temp {
return;
@ -97,10 +99,15 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> {
// then it's constant and thus drop is noop.
// Storage live ranges are also irrelevant.
if context.is_drop() || context.is_storage_marker() {
debug!(
"visit_local: context.is_drop={:?} context.is_storage_marker={:?}",
context.is_drop(), context.is_storage_marker(),
);
return;
}
let temp = &mut self.temps[index];
debug!("visit_local: temp={:?}", temp);
if *temp == TempState::Undefined {
match context {
PlaceContext::Store |
@ -121,6 +128,7 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> {
PlaceContext::Borrow {..} => true,
_ => context.is_nonmutating_use()
};
debug!("visit_local: allowed_use={:?}", allowed_use);
if allowed_use {
*uses += 1;
return;

View File

@ -84,7 +84,7 @@ impl<'a, 'tcx> Qualif {
}
/// What kind of item we are in.
#[derive(Copy, Clone, PartialEq, Eq)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum Mode {
Const,
Static,
@ -383,6 +383,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
// Collect all the temps we need to promote.
let mut promoted_temps = BitSet::new_empty(self.temp_promotion_state.len());
debug!("qualify_const: promotion_candidates={:?}", self.promotion_candidates);
for candidate in &self.promotion_candidates {
match *candidate {
Candidate::Ref(Location { block: bb, statement_index: stmt_idx }) => {
@ -414,6 +415,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
&local: &Local,
_: PlaceContext<'tcx>,
_: Location) {
debug!("visit_local: local={:?}", local);
let kind = self.mir.local_kind(local);
match kind {
LocalKind::ReturnPointer => {
@ -435,6 +437,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
}
if !self.temp_promotion_state[local].is_promotable() {
debug!("visit_local: (not promotable) local={:?}", local);
self.add(Qualif::NOT_PROMOTABLE);
}
@ -451,6 +454,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
place: &Place<'tcx>,
context: PlaceContext<'tcx>,
location: Location) {
debug!("visit_place: place={:?} context={:?} location={:?}", place, context, location);
match *place {
Place::Local(ref local) => self.visit_local(local, context, location),
Place::Promoted(_) => bug!("promoting already promoted MIR"),
@ -557,6 +561,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
}
fn visit_operand(&mut self, operand: &Operand<'tcx>, location: Location) {
debug!("visit_operand: operand={:?} location={:?}", operand, location);
self.super_operand(operand, location);
match *operand {
@ -591,6 +596,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
}
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
debug!("visit_rvalue: rvalue={:?} location={:?}", rvalue, location);
// Recurse through operands and places.
if let Rvalue::Ref(region, kind, ref place) = *rvalue {
let mut is_reborrow = false;
@ -696,6 +702,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
}
}
debug!("visit_rvalue: forbidden_mut={:?}", forbidden_mut);
if forbidden_mut {
self.add(Qualif::NOT_CONST);
} else {
@ -709,15 +716,19 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
}
place = &proj.base;
}
debug!("visit_rvalue: place={:?}", place);
if let Place::Local(local) = *place {
if self.mir.local_kind(local) == LocalKind::Temp {
debug!("visit_rvalue: local={:?}", local);
if let Some(qualif) = self.local_qualif[local] {
// `forbidden_mut` is false, so we can safely ignore
// `MUTABLE_INTERIOR` from the local's qualifications.
// This allows borrowing fields which don't have
// `MUTABLE_INTERIOR`, from a type that does, e.g.:
// `let _: &'static _ = &(Cell::new(1), 2).1;`
debug!("visit_rvalue: qualif={:?}", qualif);
if (qualif - Qualif::MUTABLE_INTERIOR).is_empty() {
debug!("visit_rvalue: candidate={:?}", candidate);
self.promotion_candidates.push(candidate);
}
}
@ -815,6 +826,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
bb: BasicBlock,
kind: &TerminatorKind<'tcx>,
location: Location) {
debug!("visit_terminator_kind: bb={:?} kind={:?} location={:?}", bb, kind, location);
if let TerminatorKind::Call { ref func, ref args, ref destination, .. } = *kind {
self.visit_operand(func, location);
@ -972,6 +984,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
let candidate = Candidate::Argument { bb, index: i };
if is_shuffle && i == 2 {
if this.qualif.is_empty() {
debug!("visit_terminator_kind: candidate={:?}", candidate);
this.promotion_candidates.push(candidate);
} else {
span_err!(this.tcx.sess, this.span, E0526,
@ -998,6 +1011,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
// We can error out with a hard error if the argument is not
// constant here.
if (this.qualif - Qualif::NOT_PROMOTABLE).is_empty() {
debug!("visit_terminator_kind: candidate={:?}", candidate);
this.promotion_candidates.push(candidate);
} else {
this.tcx.sess.span_err(this.span,
@ -1075,6 +1089,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
dest: &Place<'tcx>,
rvalue: &Rvalue<'tcx>,
location: Location) {
debug!("visit_assign: dest={:?} rvalue={:?} location={:?}", dest, rvalue, location);
self.visit_rvalue(rvalue, location);
// Check the allowed const fn argument forms.
@ -1123,10 +1138,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
}
fn visit_source_info(&mut self, source_info: &SourceInfo) {
debug!("visit_source_info: source_info={:?}", source_info);
self.span = source_info.span;
}
fn visit_statement(&mut self, bb: BasicBlock, statement: &Statement<'tcx>, location: Location) {
debug!("visit_statement: bb={:?} statement={:?} location={:?}", bb, statement, location);
self.nest(|this| {
this.visit_source_info(&statement.source_info);
match statement.kind {
@ -1150,6 +1167,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
bb: BasicBlock,
terminator: &Terminator<'tcx>,
location: Location) {
debug!("visit_terminator: bb={:?} terminator={:?} location={:?}", bb, terminator, location);
self.nest(|this| this.super_terminator(bb, terminator, location));
}
}
@ -1216,6 +1234,7 @@ impl MirPass for QualifyAndPromoteConstants {
hir::BodyOwnerKind::Static(hir::MutMutable) => Mode::StaticMut,
};
debug!("run_pass: mode={:?}", mode);
if mode == Mode::Fn || mode == Mode::ConstFn {
// This is ugly because Qualifier holds onto mir,
// which can't be mutated until its scope ends.
@ -1258,6 +1277,7 @@ impl MirPass for QualifyAndPromoteConstants {
// In `const` and `static` everything without `StorageDead`
// is `'static`, we don't have to create promoted MIR fragments,
// just remove `Drop` and `StorageDead` on "promoted" locals.
debug!("run_pass: promoted_temps={:?}", promoted_temps);
for block in mir.basic_blocks_mut() {
block.statements.retain(|statement| {
match statement.kind {