Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
rustc_mir: implement visit_local instead/along visit_lvalue where pos…
…sible.
  • Loading branch information
eddyb committed Sep 3, 2017
1 parent 2f2b8b3 commit c911925
Show file tree
Hide file tree
Showing 10 changed files with 217 additions and 235 deletions.
6 changes: 4 additions & 2 deletions src/librustc/mir/visit.rs
Expand Up @@ -256,7 +256,9 @@ macro_rules! make_mir_visitor {
}

fn visit_local(&mut self,
_local: & $($mutability)* Local) {
_local: & $($mutability)* Local,
_context: LvalueContext<'tcx>,
_location: Location) {
}

fn visit_visibility_scope(&mut self,
Expand Down Expand Up @@ -610,7 +612,7 @@ macro_rules! make_mir_visitor {
location: Location) {
match *lvalue {
Lvalue::Local(ref $($mutability)* local) => {
self.visit_local(local);
self.visit_local(local, context, location);
}
Lvalue::Static(ref $($mutability)* static_) => {
self.visit_static(static_, context, location);
Expand Down
3 changes: 1 addition & 2 deletions src/librustc_mir/transform/copy_prop.rs
Expand Up @@ -236,8 +236,7 @@ impl<'tcx> Action<'tcx> {
}

// Replace all uses of the destination local with the source local.
let src_lvalue = Lvalue::Local(src_local);
def_use_analysis.replace_all_defs_and_uses_with(dest_local, mir, src_lvalue);
def_use_analysis.replace_all_defs_and_uses_with(dest_local, mir, src_local);

// Finally, zap the now-useless assignment instruction.
debug!(" Deleting assignment");
Expand Down
18 changes: 17 additions & 1 deletion src/librustc_mir/transform/generator.rs
Expand Up @@ -88,7 +88,9 @@ struct RenameLocalVisitor {

impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor {
fn visit_local(&mut self,
local: &mut Local) {
local: &mut Local,
_: LvalueContext<'tcx>,
_: Location) {
if *local == self.from {
*local = self.to;
}
Expand All @@ -98,6 +100,13 @@ impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor {
struct DerefArgVisitor;

impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor {
fn visit_local(&mut self,
local: &mut Local,
_: LvalueContext<'tcx>,
_: Location) {
assert_ne!(*local, self_arg());
}

fn visit_lvalue(&mut self,
lvalue: &mut Lvalue<'tcx>,
context: LvalueContext<'tcx>,
Expand Down Expand Up @@ -177,6 +186,13 @@ impl<'a, 'tcx> TransformVisitor<'a, 'tcx> {
}

impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> {
fn visit_local(&mut self,
local: &mut Local,
_: LvalueContext<'tcx>,
_: Location) {
assert_eq!(self.remap.get(local), None);
}

fn visit_lvalue(&mut self,
lvalue: &mut Lvalue<'tcx>,
context: LvalueContext<'tcx>,
Expand Down
55 changes: 24 additions & 31 deletions src/librustc_mir/transform/inline.rs
Expand Up @@ -589,16 +589,6 @@ impl<'a, 'tcx> Integrator<'a, 'tcx> {
new
}

fn update_local(&self, local: Local) -> Option<Local> {
let idx = local.index();
if idx < (self.args.len() + 1) {
return None;
}
let idx = idx - (self.args.len() + 1);
let local = Local::new(idx);
self.local_map.get(local).cloned()
}

fn arg_index(&self, arg: Local) -> Option<usize> {
let idx = arg.index();
if idx > 0 && idx <= self.args.len() {
Expand All @@ -610,32 +600,35 @@ impl<'a, 'tcx> Integrator<'a, 'tcx> {
}

impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
fn visit_local(&mut self,
local: &mut Local,
_ctxt: LvalueContext<'tcx>,
_location: Location) {
if *local == RETURN_POINTER {
match self.destination {
Lvalue::Local(l) => *local = l,
ref lval => bug!("Return lvalue is {:?}, not local", lval)
}
}
let idx = local.index() - 1;
if idx < self.args.len() {
match self.args[idx] {
Operand::Consume(Lvalue::Local(l)) => *local = l,
ref op => bug!("Arg operand `{:?}` is {:?}, not local", idx, op)
}
}
*local = self.local_map[Local::new(idx - self.args.len())];
}

fn visit_lvalue(&mut self,
lvalue: &mut Lvalue<'tcx>,
_ctxt: LvalueContext<'tcx>,
_location: Location) {
if let Lvalue::Local(ref mut local) = *lvalue {
if let Some(l) = self.update_local(*local) {
// Temp or Var; update the local reference
*local = l;
return;
}
}
if let Lvalue::Local(local) = *lvalue {
if local == RETURN_POINTER {
// Return pointer; update the lvalue itself
*lvalue = self.destination.clone();
} else if local.index() < (self.args.len() + 1) {
// Argument, once again update the the lvalue itself
let idx = local.index() - 1;
if let Operand::Consume(ref lval) = self.args[idx] {
*lvalue = lval.clone();
} else {
bug!("Arg operand `{:?}` is not an Lvalue use.", idx)
}
}
if let Lvalue::Local(RETURN_POINTER) = *lvalue {
// Return pointer; update the lvalue itself
*lvalue = self.destination.clone();
} else {
self.super_lvalue(lvalue, _ctxt, _location)
self.super_lvalue(lvalue, _ctxt, _location);
}
}

Expand Down
92 changes: 43 additions & 49 deletions src/librustc_mir/transform/promote_consts.rs
Expand Up @@ -83,52 +83,49 @@ struct TempCollector<'tcx> {
}

impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> {
fn visit_lvalue(&mut self,
lvalue: &Lvalue<'tcx>,
context: LvalueContext<'tcx>,
location: Location) {
self.super_lvalue(lvalue, context, location);
if let Lvalue::Local(index) = *lvalue {
// We're only interested in temporaries
if self.mir.local_kind(index) != LocalKind::Temp {
return;
}
fn visit_local(&mut self,
&index: &Local,
context: LvalueContext<'tcx>,
location: Location) {
// We're only interested in temporaries
if self.mir.local_kind(index) != LocalKind::Temp {
return;
}

// Ignore drops, if the temp gets promoted,
// then it's constant and thus drop is noop.
// Storage live ranges are also irrelevant.
if context.is_drop() || context.is_storage_marker() {
return;
}
// Ignore drops, if the temp gets promoted,
// then it's constant and thus drop is noop.
// Storage live ranges are also irrelevant.
if context.is_drop() || context.is_storage_marker() {
return;
}

let temp = &mut self.temps[index];
if *temp == TempState::Undefined {
match context {
LvalueContext::Store |
LvalueContext::Call => {
*temp = TempState::Defined {
location,
uses: 0
};
return;
}
_ => { /* mark as unpromotable below */ }
}
} else if let TempState::Defined { ref mut uses, .. } = *temp {
// We always allow borrows, even mutable ones, as we need
// to promote mutable borrows of some ZSTs e.g. `&mut []`.
let allowed_use = match context {
LvalueContext::Borrow {..} => true,
_ => context.is_nonmutating_use()
};
if allowed_use {
*uses += 1;
let temp = &mut self.temps[index];
if *temp == TempState::Undefined {
match context {
LvalueContext::Store |
LvalueContext::Call => {
*temp = TempState::Defined {
location,
uses: 0
};
return;
}
/* mark as unpromotable below */
_ => { /* mark as unpromotable below */ }
}
*temp = TempState::Unpromotable;
} else if let TempState::Defined { ref mut uses, .. } = *temp {
// We always allow borrows, even mutable ones, as we need
// to promote mutable borrows of some ZSTs e.g. `&mut []`.
let allowed_use = match context {
LvalueContext::Borrow {..} => true,
_ => context.is_nonmutating_use()
};
if allowed_use {
*uses += 1;
return;
}
/* mark as unpromotable below */
}
*temp = TempState::Unpromotable;
}

fn visit_source_info(&mut self, source_info: &SourceInfo) {
Expand Down Expand Up @@ -326,16 +323,13 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {

/// Replaces all temporaries with their promoted counterparts.
impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> {
fn visit_lvalue(&mut self,
lvalue: &mut Lvalue<'tcx>,
context: LvalueContext<'tcx>,
location: Location) {
if let Lvalue::Local(ref mut temp) = *lvalue {
if self.source.local_kind(*temp) == LocalKind::Temp {
*temp = self.promote_temp(*temp);
}
fn visit_local(&mut self,
local: &mut Local,
_: LvalueContext<'tcx>,
_: Location) {
if self.source.local_kind(*local) == LocalKind::Temp {
*local = self.promote_temp(*local);
}
self.super_lvalue(lvalue, context, location);
}
}

Expand Down
51 changes: 29 additions & 22 deletions src/librustc_mir/transform/qualify_consts.rs
Expand Up @@ -499,33 +499,40 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
/// For functions (constant or not), it also records
/// candidates for promotion in promotion_candidates.
impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
fn visit_local(&mut self,
&local: &Local,
_: LvalueContext<'tcx>,
_: Location) {
match self.mir.local_kind(local) {
LocalKind::ReturnPointer => {
self.not_const();
}
LocalKind::Arg => {
self.add(Qualif::FN_ARGUMENT);
}
LocalKind::Var => {
self.add(Qualif::NOT_CONST);
}
LocalKind::Temp => {
if !self.temp_promotion_state[local].is_promotable() {
self.add(Qualif::NOT_PROMOTABLE);
}

if let Some(qualif) = self.temp_qualif[local] {
self.add(qualif);
} else {
self.not_const();
}
}
}
}

fn visit_lvalue(&mut self,
lvalue: &Lvalue<'tcx>,
context: LvalueContext<'tcx>,
location: Location) {
match *lvalue {
Lvalue::Local(local) => match self.mir.local_kind(local) {
LocalKind::ReturnPointer => {
self.not_const();
}
LocalKind::Arg => {
self.add(Qualif::FN_ARGUMENT);
}
LocalKind::Var => {
self.add(Qualif::NOT_CONST);
}
LocalKind::Temp => {
if !self.temp_promotion_state[local].is_promotable() {
self.add(Qualif::NOT_PROMOTABLE);
}

if let Some(qualif) = self.temp_qualif[local] {
self.add(qualif);
} else {
self.not_const();
}
}
},
Lvalue::Local(ref local) => self.visit_local(local, context, location),
Lvalue::Static(ref global) => {
self.add(Qualif::STATIC);

Expand Down
20 changes: 6 additions & 14 deletions src/librustc_mir/transform/simplify.rs
Expand Up @@ -352,15 +352,11 @@ struct DeclMarker {
}

impl<'tcx> Visitor<'tcx> for DeclMarker {
fn visit_lvalue(&mut self, lval: &Lvalue<'tcx>, ctx: LvalueContext<'tcx>, loc: Location) {
if ctx == LvalueContext::StorageLive || ctx == LvalueContext::StorageDead {
// ignore these altogether, they get removed along with their otherwise unused decls.
return;
fn visit_local(&mut self, local: &Local, ctx: LvalueContext<'tcx>, _: Location) {
// ignore these altogether, they get removed along with their otherwise unused decls.
if ctx != LvalueContext::StorageLive && ctx != LvalueContext::StorageDead {
self.locals.insert(local.index());
}
if let Lvalue::Local(ref v) = *lval {
self.locals.insert(v.index());
}
self.super_lvalue(lval, ctx, loc);
}
}

Expand All @@ -384,11 +380,7 @@ impl<'tcx> MutVisitor<'tcx> for LocalUpdater {
});
self.super_basic_block_data(block, data);
}
fn visit_lvalue(&mut self, lval: &mut Lvalue<'tcx>, ctx: LvalueContext<'tcx>, loc: Location) {
match *lval {
Lvalue::Local(ref mut l) => *l = Local::new(self.map[l.index()]),
_ => (),
};
self.super_lvalue(lval, ctx, loc);
fn visit_local(&mut self, l: &mut Local, _: LvalueContext<'tcx>, _: Location) {
*l = Local::new(self.map[l.index()]);
}
}

0 comments on commit c911925

Please sign in to comment.