-
Notifications
You must be signed in to change notification settings - Fork 13k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
emit (via debug!) scary message from `fn borrowck_mir` until basic prototype is in place. Gather children of move paths and set their kill bits in dataflow. (Each node has a link to the child that is first among its siblings.) Hooked in libgraphviz based rendering, including of borrowck dataflow state. doing this well required some refactoring of the code, so I cleaned it up more generally (adding comments to explain what its trying to do and how it is doing it). Update: this newer version addresses most review comments (at least the ones that were largely mechanical changes), but I left the more interesting revisions to separate followup commits (in this same PR).
- Loading branch information
Showing
14 changed files
with
1,777 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
use std::mem; | ||
|
||
/// `BitSlice` provides helper methods for treating a `[usize]` | ||
/// as a bitvector. | ||
pub trait BitSlice { | ||
fn set_bit(&mut self, idx: usize) -> bool; | ||
fn get_bit(&self, idx: usize) -> bool; | ||
} | ||
|
||
impl BitSlice for [usize] { | ||
fn set_bit(&mut self, idx: usize) -> bool { | ||
let words = self; | ||
debug!("set_bit: words={} idx={}", | ||
bits_to_string(words, words.len() * mem::size_of::<usize>()), bit_str(idx)); | ||
let BitLookup { word, bit_in_word, bit_mask } = bit_lookup(idx); | ||
debug!("word={} bit_in_word={} bit_mask={}", word, bit_in_word, bit_mask); | ||
let oldv = words[word]; | ||
let newv = oldv | bit_mask; | ||
words[word] = newv; | ||
oldv != newv | ||
} | ||
|
||
fn get_bit(&self, idx: usize) -> bool { | ||
let words = self; | ||
let BitLookup { word, bit_mask, .. } = bit_lookup(idx); | ||
(words[word] & bit_mask) != 0 | ||
} | ||
} | ||
|
||
struct BitLookup { word: usize, bit_in_word: usize, bit_mask: usize } | ||
|
||
#[inline] | ||
fn bit_lookup(bit: usize) -> BitLookup { | ||
let usize_bits = mem::size_of::<usize>() * 8; | ||
let word = bit / usize_bits; | ||
let bit_in_word = bit % usize_bits; | ||
let bit_mask = 1 << bit_in_word; | ||
BitLookup { word: word, bit_in_word: bit_in_word, bit_mask: bit_mask } | ||
} | ||
|
||
|
||
fn bit_str(bit: usize) -> String { | ||
let byte = bit >> 8; | ||
let lobits = 1 << (bit & 0xFF); | ||
format!("[{}:{}-{:02x}]", bit, byte, lobits) | ||
} | ||
|
||
pub fn bits_to_string(words: &[usize], bytes: usize) -> String { | ||
let mut result = String::new(); | ||
let mut sep = '['; | ||
|
||
// Note: this is a little endian printout of bytes. | ||
|
||
let mut i = 0; | ||
for &word in words.iter() { | ||
let mut v = word; | ||
for _ in 0..mem::size_of::<usize>() { | ||
let byte = v & 0xFF; | ||
if i >= bytes { | ||
assert!(byte == 0); | ||
} else { | ||
result.push(sep); | ||
result.push_str(&format!("{:02x}", byte)); | ||
} | ||
v >>= 8; | ||
i += 1; | ||
sep = '-'; | ||
} | ||
} | ||
result.push(']'); | ||
return result | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// Copyright 2012-2016 The Rust Project Developers. See the COPYRIGHT | ||
// file at the top-level directory of this distribution and at | ||
// http://rust-lang.org/COPYRIGHT. | ||
// | ||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
//! The move-analysis portion of borrowck needs to work in an abstract | ||
//! domain of lifted Lvalues. Most of the Lvalue variants fall into a | ||
//! one-to-one mapping between the concrete and abstract (e.g. a | ||
//! field-deref on a local-variable, `x.field`, has the same meaning | ||
//! in both domains). Indexed-Projections are the exception: `a[x]` | ||
//! needs to be treated as mapping to the same move path as `a[y]` as | ||
//! well as `a[13]`, et cetera. | ||
//! | ||
//! (In theory the analysis could be extended to work with sets of | ||
//! paths, so that `a[0]` and `a[13]` could be kept distinct, while | ||
//! `a[x]` would still overlap them both. But that is not this | ||
//! representation does today.) | ||
use rustc::mir::repr::{Lvalue, LvalueElem}; | ||
use rustc::mir::repr::{Operand, Projection, ProjectionElem}; | ||
|
||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] | ||
pub struct AbstractOperand; | ||
pub type AbstractProjection<'tcx> = | ||
Projection<'tcx, Lvalue<'tcx>, AbstractOperand>; | ||
pub type AbstractElem<'tcx> = | ||
ProjectionElem<'tcx, AbstractOperand>; | ||
|
||
pub trait Lift { | ||
type Abstract; | ||
fn lift(&self) -> Self::Abstract; | ||
} | ||
impl<'tcx> Lift for Operand<'tcx> { | ||
type Abstract = AbstractOperand; | ||
fn lift(&self) -> Self::Abstract { AbstractOperand } | ||
} | ||
impl<'tcx> Lift for LvalueElem<'tcx> { | ||
type Abstract = AbstractElem<'tcx>; | ||
fn lift(&self) -> Self::Abstract { | ||
match *self { | ||
ProjectionElem::Deref => | ||
ProjectionElem::Deref, | ||
ProjectionElem::Field(ref f, ty) => | ||
ProjectionElem::Field(f.clone(), ty.clone()), | ||
ProjectionElem::Index(ref i) => | ||
ProjectionElem::Index(i.lift()), | ||
ProjectionElem::ConstantIndex {offset,min_length,from_end} => | ||
ProjectionElem::ConstantIndex { | ||
offset: offset, | ||
min_length: min_length, | ||
from_end: from_end | ||
}, | ||
ProjectionElem::Downcast(a, u) => | ||
ProjectionElem::Downcast(a.clone(), u.clone()), | ||
} | ||
} | ||
} |
Oops, something went wrong.