about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_incremental/lib.rs1
-rw-r--r--src/librustc_trans/base.rs14
-rw-r--r--src/librustc_trans/context.rs7
-rw-r--r--src/librustc_trans/partitioning.rs28
-rw-r--r--src/test/incremental/change_symbol_export_status.rs42
5 files changed, 79 insertions, 13 deletions
diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs
index b72766bccea..3cb5244413b 100644
--- a/src/librustc_incremental/lib.rs
+++ b/src/librustc_incremental/lib.rs
@@ -48,6 +48,7 @@ pub mod ich;
 pub use assert_dep_graph::assert_dep_graph;
 pub use calculate_svh::compute_incremental_hashes_map;
 pub use calculate_svh::IncrementalHashesMap;
+pub use calculate_svh::hasher::IchHasher;
 pub use persist::load_dep_graph;
 pub use persist::save_dep_graph;
 pub use persist::save_trans_partition;
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index 5b79f040d0f..f70c24c3ccb 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -1610,7 +1610,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     let symbol_map = Rc::new(symbol_map);
 
-    let previous_work_products = trans_reuse_previous_work_products(tcx,
+    let previous_work_products = trans_reuse_previous_work_products(&shared_ccx,
                                                                     &codegen_units,
                                                                     &symbol_map);
 
@@ -1630,7 +1630,9 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
             ModuleTranslation {
                 name: String::from(ccx.codegen_unit().name()),
-                symbol_name_hash: ccx.codegen_unit().compute_symbol_name_hash(tcx, &symbol_map),
+                symbol_name_hash: ccx.codegen_unit()
+                                     .compute_symbol_name_hash(&shared_ccx,
+                                                               &symbol_map),
                 source: source,
             }
         })
@@ -1962,7 +1964,7 @@ fn gather_type_sizes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
 
 /// For each CGU, identify if we can reuse an existing object file (or
 /// maybe other context).
-fn trans_reuse_previous_work_products(tcx: TyCtxt,
+fn trans_reuse_previous_work_products(scx: &SharedCrateContext,
                                       codegen_units: &[CodegenUnit],
                                       symbol_map: &SymbolMap)
                                       -> Vec<Option<WorkProduct>> {
@@ -1972,16 +1974,16 @@ fn trans_reuse_previous_work_products(tcx: TyCtxt,
         .map(|cgu| {
             let id = cgu.work_product_id();
 
-            let hash = cgu.compute_symbol_name_hash(tcx, symbol_map);
+            let hash = cgu.compute_symbol_name_hash(scx, symbol_map);
 
             debug!("trans_reuse_previous_work_products: id={:?} hash={}", id, hash);
 
-            if let Some(work_product) = tcx.dep_graph.previous_work_product(&id) {
+            if let Some(work_product) = scx.dep_graph().previous_work_product(&id) {
                 if work_product.input_hash == hash {
                     debug!("trans_reuse_previous_work_products: reusing {:?}", work_product);
                     return Some(work_product);
                 } else {
-                    if tcx.sess.opts.debugging_opts.incremental_info {
+                    if scx.sess().opts.debugging_opts.incremental_info {
                         println!("incremental: CGU `{}` invalidated because of \
                                   changed partitioning hash.",
                                   cgu.name());
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index 262b8362397..8b98eb57814 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -10,7 +10,8 @@
 
 use llvm;
 use llvm::{ContextRef, ModuleRef, ValueRef, BuilderRef};
-use rustc::dep_graph::{DepNode, DepTrackingMap, DepTrackingMapConfig, WorkProduct};
+use rustc::dep_graph::{DepGraph, DepNode, DepTrackingMap, DepTrackingMapConfig,
+                       WorkProduct};
 use middle::cstore::LinkMeta;
 use rustc::hir::def::ExportMap;
 use rustc::hir::def_id::DefId;
@@ -551,6 +552,10 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
         &self.tcx.sess
     }
 
+    pub fn dep_graph<'a>(&'a self) -> &'a DepGraph {
+        &self.tcx.dep_graph
+    }
+
     pub fn stats<'a>(&'a self) -> &'a Stats {
         &self.stats
     }
diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs
index a36960993e4..d93bbec7efa 100644
--- a/src/librustc_trans/partitioning.rs
+++ b/src/librustc_trans/partitioning.rs
@@ -126,10 +126,10 @@ use rustc::hir::map::DefPathData;
 use rustc::session::config::NUMBERED_CODEGEN_UNIT_MARKER;
 use rustc::ty::TyCtxt;
 use rustc::ty::item_path::characteristic_def_id_of_type;
+use rustc_incremental::IchHasher;
 use std::cmp::Ordering;
-use std::hash::{Hash, Hasher};
+use std::hash::Hash;
 use std::sync::Arc;
-use std::collections::hash_map::DefaultHasher;
 use symbol_map::SymbolMap;
 use syntax::ast::NodeId;
 use syntax::symbol::{Symbol, InternedString};
@@ -188,14 +188,30 @@ impl<'tcx> CodegenUnit<'tcx> {
         DepNode::WorkProduct(self.work_product_id())
     }
 
-    pub fn compute_symbol_name_hash(&self, tcx: TyCtxt, symbol_map: &SymbolMap) -> u64 {
-        let mut state = DefaultHasher::new();
-        let all_items = self.items_in_deterministic_order(tcx, symbol_map);
+    pub fn compute_symbol_name_hash(&self,
+                                    scx: &SharedCrateContext,
+                                    symbol_map: &SymbolMap) -> u64 {
+        let mut state = IchHasher::new();
+        let exported_symbols = scx.exported_symbols();
+        let all_items = self.items_in_deterministic_order(scx.tcx(), symbol_map);
         for (item, _) in all_items {
             let symbol_name = symbol_map.get(item).unwrap();
+            symbol_name.len().hash(&mut state);
             symbol_name.hash(&mut state);
+            let exported = match item {
+               TransItem::Fn(ref instance) => {
+                    let node_id = scx.tcx().map.as_local_node_id(instance.def);
+                    node_id.map(|node_id| exported_symbols.contains(&node_id))
+                           .unwrap_or(false)
+               }
+               TransItem::Static(node_id) => {
+                    exported_symbols.contains(&node_id)
+               }
+               TransItem::DropGlue(..) => false,
+            };
+            exported.hash(&mut state);
         }
-        state.finish()
+        state.finish().to_smaller_hash()
     }
 
     pub fn items_in_deterministic_order(&self,
diff --git a/src/test/incremental/change_symbol_export_status.rs b/src/test/incremental/change_symbol_export_status.rs
new file mode 100644
index 00000000000..71f46c641bf
--- /dev/null
+++ b/src/test/incremental/change_symbol_export_status.rs
@@ -0,0 +1,42 @@
+// Copyright 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.
+
+// revisions: rpass1 rpass2
+
+#![feature(rustc_attrs)]
+#![allow(private_no_mangle_fns)]
+
+#![rustc_partition_reused(module="change_symbol_export_status", cfg="rpass2")]
+#![rustc_partition_translated(module="change_symbol_export_status-mod1", cfg="rpass2")]
+
+
+// This test case makes sure that a change in symbol visibility is detected by
+// our dependency tracking. We do this by changing a module's visibility to
+// `private` in rpass2, causing the contained function to go from `default` to
+// `hidden` visibility.
+// The function is marked with #[no_mangle] so it is considered for exporting
+// even from an executable. Plain Rust functions are only exported from Rust
+// libraries, which our test infrastructure does not support.
+
+#[cfg(rpass1)]
+pub mod mod1 {
+    #[no_mangle]
+    pub fn foo() {}
+}
+
+#[cfg(rpass2)]
+mod mod1 {
+    #[no_mangle]
+    pub fn foo() {}
+}
+
+fn main() {
+    mod1::foo();
+}