]> git.lizzy.rs Git - rust.git/commitdiff
add location table
authorNiko Matsakis <niko@alum.mit.edu>
Tue, 1 May 2018 14:03:36 +0000 (10:03 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Sat, 5 May 2018 09:03:56 +0000 (05:03 -0400)
This will be used in fact generation.

src/librustc_mir/borrow_check/location.rs [new file with mode: 0644]
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/borrow_check/nll/mod.rs

diff --git a/src/librustc_mir/borrow_check/location.rs b/src/librustc_mir/borrow_check/location.rs
new file mode 100644 (file)
index 0000000..e09f0ee
--- /dev/null
@@ -0,0 +1,126 @@
+// Copyright 2017 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.
+
+#![allow(dead_code)] // TODO -- will be used in a later commit, remove then
+
+use rustc::mir::{BasicBlock, Location, Mir};
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+
+/// Maps between a MIR Location, which identifies the a particular
+/// statement within a basic block, to a "rich location", which
+/// identifies at a finer granularity. In particular, we distinguish
+/// the *start* of a statement and the *mid-point*. The mid-point is
+/// the point *just* before the statement takes effect; in particular,
+/// for an assignment `A = B`, it is the point where B is about to be
+/// written into A. This mid-point is a kind of hack to work around
+/// our inability to track the position information at sufficient
+/// granularity through outlives relations; however, the rich location
+/// table serves another purpose: it compresses locations from
+/// multiple words into a single u32.
+crate struct LocationTable {
+    num_points: usize,
+    statements_before_block: IndexVec<BasicBlock, usize>,
+}
+
+newtype_index!(LocationIndex { DEBUG_FORMAT = "LocationIndex({})" });
+
+#[derive(Copy, Clone, Debug)]
+crate enum RichLocation {
+    Start(Location),
+    Mid(Location),
+}
+
+impl LocationTable {
+    crate fn new(mir: &Mir<'_>) -> Self {
+        let mut num_points = 0;
+        let statements_before_block = mir.basic_blocks()
+            .iter()
+            .map(|block_data| {
+                let v = num_points;
+                num_points += (block_data.statements.len() + 1) * 2;
+                v
+            })
+            .collect();
+
+        debug!(
+            "LocationTable(statements_before_block={:#?})",
+            statements_before_block
+        );
+        debug!("LocationTable: num_points={:#?}", num_points);
+
+        Self {
+            num_points,
+            statements_before_block,
+        }
+    }
+
+    #[allow(dead_code)] // TODO
+    crate fn all_points(&self) -> impl Iterator<Item = LocationIndex> {
+        (0..self.num_points).map(LocationIndex::new)
+    }
+
+    crate fn start_index(&self, location: Location) -> LocationIndex {
+        let Location {
+            block,
+            statement_index,
+        } = location;
+        let start_index = self.statements_before_block[block];
+        LocationIndex::new(start_index + statement_index * 2)
+    }
+
+    crate fn mid_index(&self, location: Location) -> LocationIndex {
+        let Location {
+            block,
+            statement_index,
+        } = location;
+        let start_index = self.statements_before_block[block];
+        LocationIndex::new(start_index + statement_index * 2 + 1)
+    }
+
+    crate fn to_location(&self, index: LocationIndex) -> RichLocation {
+        let point_index = index.index();
+
+        // Find the basic block. We have a vector with the
+        // starting index of the statement in each block. Imagine
+        // we have statement #22, and we have a vector like:
+        //
+        // [0, 10, 20]
+        //
+        // In that case, this represents point_index 2 of
+        // basic block BB2. We know this because BB0 accounts for
+        // 0..10, BB1 accounts for 11..20, and BB2 accounts for
+        // 20...
+        //
+        // To compute this, we could do a binary search, but
+        // because I am lazy we instead iterate through to find
+        // the last point where the "first index" (0, 10, or 20)
+        // was less than the statement index (22). In our case, this will
+        // be (BB2, 20).
+        let (block, &first_index) = self.statements_before_block
+            .iter_enumerated()
+            .filter(|(_, first_index)| **first_index <= point_index)
+            .last()
+            .unwrap();
+
+        let statement_index = (point_index - first_index) / 2;
+        if index.is_start() {
+            RichLocation::Start(Location { block, statement_index })
+        } else {
+            RichLocation::Mid(Location { block, statement_index })
+        }
+    }
+}
+
+impl LocationIndex {
+    fn is_start(&self) -> bool {
+        // even indices are start points; odd indices are mid points
+        (self.index() % 2) == 0
+    }
+}
index c619f350f58de10da593624a17a31ce56eb50591..3e3f510e308c330b82fbd16e524aa2e033c2ce2a 100644 (file)
 
 use self::borrow_set::{BorrowSet, BorrowData};
 use self::flows::Flows;
+use self::location::LocationTable;
 use self::prefixes::PrefixSet;
 use self::MutateMode::{JustWrite, WriteAndRead};
 
 crate mod borrow_set;
 mod error_reporting;
 mod flows;
+mod location;
 crate mod place_ext;
 mod prefixes;
 
@@ -110,6 +112,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
     let mut mir: Mir<'tcx> = input_mir.clone();
     let free_regions = nll::replace_regions_in_mir(infcx, def_id, param_env, &mut mir);
     let mir = &mir; // no further changes
+    let location_table = &LocationTable::new(mir);
 
     let move_data: MoveData<'tcx> = match MoveData::gather_moves(mir, tcx) {
         Ok(move_data) => move_data,
@@ -199,6 +202,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
         def_id,
         free_regions,
         mir,
+        location_table,
         param_env,
         &mut flow_inits,
         &mdpe.move_data,
index 411bf5b55ed6b3de70cbad768fcb99116ff132ee..80ad3ecb9f85ffc1e150e5856fc7dec8d37a94ea 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use borrow_check::borrow_set::BorrowSet;
+use borrow_check::location::LocationTable;
 use rustc::hir::def_id::DefId;
 use rustc::mir::{ClosureRegionRequirements, ClosureOutlivesSubject, Mir};
 use rustc::infer::InferCtxt;
@@ -70,6 +71,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>(
     def_id: DefId,
     universal_regions: UniversalRegions<'tcx>,
     mir: &Mir<'tcx>,
+    _location_table: &LocationTable,
     param_env: ty::ParamEnv<'gcx>,
     flow_inits: &mut FlowAtLocation<MaybeInitializedPlaces<'cx, 'gcx, 'tcx>>,
     move_data: &MoveData<'tcx>,