]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_trans/context.rs
Refactor determining of relocation model into methods
[rust.git] / src / librustc_trans / context.rs
index bfcb1ae33b3019f000314b4e25005f23f1a839aa..d8b3089bc998e5edd5b07abbd9f922962dffa525 100644 (file)
@@ -10,7 +10,7 @@
 
 use llvm;
 use llvm::{ContextRef, ModuleRef, ValueRef, BuilderRef};
-use rustc::dep_graph::{DepNode, DepTrackingMap, DepTrackingMapConfig};
+use rustc::dep_graph::{DepNode, DepTrackingMap, DepTrackingMapConfig, WorkProduct};
 use middle::cstore::LinkMeta;
 use rustc::hir::def::ExportMap;
 use rustc::hir::def_id::DefId;
 use monomorphize::Instance;
 
 use partitioning::CodegenUnit;
-use collector::TransItemState;
 use trans_item::TransItem;
 use type_::{Type, TypeNames};
 use rustc::ty::subst::{Substs, VecPerParamSpace};
 use rustc::ty::{self, Ty, TyCtxt};
 use session::config::NoDebugInfo;
 use session::Session;
+use session::config;
+use symbol_map::SymbolMap;
 use util::sha2::Sha256;
 use util::nodemap::{NodeMap, NodeSet, DefIdMap, FnvHashMap, FnvHashSet};
 
 use std::str;
 use syntax::ast;
 use syntax::parse::token::InternedString;
+use abi::FnType;
 
 pub struct Stats {
     pub n_glues_created: Cell<usize>,
     pub n_null_glues: Cell<usize>,
     pub n_real_glues: Cell<usize>,
+    pub n_fallback_instantiations: Cell<usize>,
     pub n_fns: Cell<usize>,
     pub n_monos: Cell<usize>,
     pub n_inlines: Cell<usize>,
@@ -80,11 +83,9 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
     mir_map: &'a MirMap<'tcx>,
     mir_cache: RefCell<DefIdMap<Rc<mir::Mir<'tcx>>>>,
 
-    available_monomorphizations: RefCell<FnvHashSet<String>>,
-    available_drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, String>>,
     use_dll_storage_attrs: bool,
 
-    translation_items: RefCell<FnvHashMap<TransItem<'tcx>, TransItemState>>,
+    translation_items: RefCell<FnvHashSet<TransItem<'tcx>>>,
     trait_cache: RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>>,
 }
 
@@ -95,11 +96,12 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
 pub struct LocalCrateContext<'tcx> {
     llmod: ModuleRef,
     llcx: ContextRef,
+    previous_work_product: Option<WorkProduct>,
     tn: TypeNames, // FIXME: This seems to be largely unused.
     codegen_unit: CodegenUnit<'tcx>,
     needs_unwind_cleanup_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
     fn_pointer_shims: RefCell<FnvHashMap<Ty<'tcx>, ValueRef>>,
-    drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, ValueRef>>,
+    drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, (ValueRef, FnType)>>,
     /// Track mapping of external ids to local items imported for inlining
     external: RefCell<DefIdMap<Option<ast::NodeId>>>,
     /// Backwards version of the `external` map (inlined items to where they
@@ -172,6 +174,8 @@ pub struct LocalCrateContext<'tcx> {
 
     /// Depth of the current type-of computation - used to bail out
     type_of_depth: Cell<usize>,
+
+    symbol_map: Rc<SymbolMap<'tcx>>,
 }
 
 // Implement DepTrackingMapConfig for `trait_cache`
@@ -196,31 +200,39 @@ pub struct CrateContextList<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx: 'a> CrateContextList<'a, 'tcx> {
-
     pub fn new(shared_ccx: &'a SharedCrateContext<'a, 'tcx>,
-               codegen_units: Vec<CodegenUnit<'tcx>>)
+               codegen_units: Vec<CodegenUnit<'tcx>>,
+               previous_work_products: Vec<Option<WorkProduct>>,
+               symbol_map: Rc<SymbolMap<'tcx>>)
                -> CrateContextList<'a, 'tcx> {
         CrateContextList {
             shared: shared_ccx,
-            local_ccxs: codegen_units.into_iter().map(|codegen_unit| {
-                LocalCrateContext::new(shared_ccx, codegen_unit)
+            local_ccxs: codegen_units.into_iter().zip(previous_work_products).map(|(cgu, wp)| {
+                LocalCrateContext::new(shared_ccx, cgu, wp, symbol_map.clone())
             }).collect()
         }
     }
 
-    pub fn iter<'b>(&'b self) -> CrateContextIterator<'b, 'tcx> {
+    /// Iterate over all crate contexts, whether or not they need
+    /// translation.  That is, whether or not a `.o` file is available
+    /// for re-use from a previous incr. comp.).
+    pub fn iter_all<'b>(&'b self) -> CrateContextIterator<'b, 'tcx> {
         CrateContextIterator {
             shared: self.shared,
             index: 0,
-            local_ccxs: &self.local_ccxs[..]
+            local_ccxs: &self.local_ccxs[..],
+            filter_to_previous_work_product_unavail: false,
         }
     }
 
-    pub fn get_ccx<'b>(&'b self, index: usize) -> CrateContext<'b, 'tcx> {
-        CrateContext {
+    /// Iterator over all CCX that need translation (cannot reuse results from
+    /// previous incr. comp.).
+    pub fn iter_need_trans<'b>(&'b self) -> CrateContextIterator<'b, 'tcx> {
+        CrateContextIterator {
             shared: self.shared,
-            index: index,
+            index: 0,
             local_ccxs: &self.local_ccxs[..],
+            filter_to_previous_work_product_unavail: true,
         }
     }
 
@@ -244,24 +256,38 @@ pub struct CrateContextIterator<'a, 'tcx: 'a> {
     shared: &'a SharedCrateContext<'a, 'tcx>,
     local_ccxs: &'a [LocalCrateContext<'tcx>],
     index: usize,
+
+    /// if true, only return results where `previous_work_product` is none
+    filter_to_previous_work_product_unavail: bool,
 }
 
 impl<'a, 'tcx> Iterator for CrateContextIterator<'a,'tcx> {
     type Item = CrateContext<'a, 'tcx>;
 
     fn next(&mut self) -> Option<CrateContext<'a, 'tcx>> {
-        if self.index >= self.local_ccxs.len() {
-            return None;
-        }
+        loop {
+            if self.index >= self.local_ccxs.len() {
+                return None;
+            }
 
-        let index = self.index;
-        self.index += 1;
+            let index = self.index;
+            self.index += 1;
 
-        Some(CrateContext {
-            shared: self.shared,
-            index: index,
-            local_ccxs: self.local_ccxs,
-        })
+            let ccx = CrateContext {
+                shared: self.shared,
+                index: index,
+                local_ccxs: self.local_ccxs,
+            };
+
+            if
+                self.filter_to_previous_work_product_unavail &&
+                ccx.previous_work_product().is_some()
+            {
+                continue;
+            }
+
+            return Some(ccx);
+        }
     }
 }
 
@@ -297,6 +323,38 @@ fn next(&mut self) -> Option<(CrateContext<'a, 'tcx>, bool)> {
     }
 }
 
+pub fn get_reloc_model(sess: &Session) -> llvm::RelocMode {
+    let reloc_model_arg = match sess.opts.cg.relocation_model {
+        Some(ref s) => &s[..],
+        None => &sess.target.target.options.relocation_model[..],
+    };
+
+    match reloc_model_arg {
+        "pic" => llvm::RelocPIC,
+        "static" => llvm::RelocStatic,
+        "default" => llvm::RelocDefault,
+        "dynamic-no-pic" => llvm::RelocDynamicNoPic,
+        _ => {
+            sess.err(&format!("{:?} is not a valid relocation mode",
+                             sess.opts
+                                 .cg
+                                 .relocation_model));
+            sess.abort_if_errors();
+            bug!();
+        }
+    }
+}
+
+fn is_any_library(sess: &Session) -> bool {
+    sess.crate_types.borrow().iter().any(|ty| {
+        *ty != config::CrateTypeExecutable
+    })
+}
+
+pub fn is_pie_binary(sess: &Session) -> bool {
+    !is_any_library(sess) && get_reloc_model(sess) == llvm::RelocPIC
+}
+
 unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
     let llcx = llvm::LLVMContextCreate();
     let mod_name = CString::new(mod_name).unwrap();
@@ -327,6 +385,11 @@ unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextR
     let llvm_target = sess.target.target.llvm_target.as_bytes();
     let llvm_target = CString::new(llvm_target).unwrap();
     llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
+
+    if is_pie_binary(sess) {
+        llvm::LLVMRustSetModulePIELevel(llmod);
+    }
+
     (llcx, llmod)
 }
 
@@ -403,6 +466,7 @@ pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>,
                 n_glues_created: Cell::new(0),
                 n_null_glues: Cell::new(0),
                 n_real_glues: Cell::new(0),
+                n_fallback_instantiations: Cell::new(0),
                 n_fns: Cell::new(0),
                 n_monos: Cell::new(0),
                 n_inlines: Cell::new(0),
@@ -413,10 +477,8 @@ pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>,
             },
             check_overflow: check_overflow,
             check_drop_flag_for_sanity: check_drop_flag_for_sanity,
-            available_monomorphizations: RefCell::new(FnvHashSet()),
-            available_drop_glues: RefCell::new(FnvHashMap()),
             use_dll_storage_attrs: use_dll_storage_attrs,
-            translation_items: RefCell::new(FnvHashMap()),
+            translation_items: RefCell::new(FnvHashSet()),
             trait_cache: RefCell::new(DepTrackingMap::new(tcx.dep_graph.clone())),
         }
     }
@@ -479,7 +541,7 @@ pub fn get_mir(&self, def_id: DefId) -> Option<CachedMir<'b, 'tcx>> {
         }
     }
 
-    pub fn translation_items(&self) -> &RefCell<FnvHashMap<TransItem<'tcx>, TransItemState>> {
+    pub fn translation_items(&self) -> &RefCell<FnvHashSet<TransItem<'tcx>>> {
         &self.translation_items
     }
 
@@ -515,7 +577,9 @@ pub fn metadata_symbol_name(&self) -> String {
 
 impl<'tcx> LocalCrateContext<'tcx> {
     fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>,
-               codegen_unit: CodegenUnit<'tcx>)
+               codegen_unit: CodegenUnit<'tcx>,
+               previous_work_product: Option<WorkProduct>,
+               symbol_map: Rc<SymbolMap<'tcx>>)
            -> LocalCrateContext<'tcx> {
         unsafe {
             // Append ".rs" to LLVM module identifier.
@@ -526,13 +590,15 @@ fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>,
             // crashes if the module identifier is same as other symbols
             // such as a function name in the module.
             // 1. http://llvm.org/bugs/show_bug.cgi?id=11479
-            let llmod_id = format!("{}.rs", codegen_unit.name);
+            let llmod_id = format!("{}.rs", codegen_unit.name());
 
             let (llcx, llmod) = create_context_and_module(&shared.tcx.sess,
                                                           &llmod_id[..]);
 
             let dbg_cx = if shared.tcx.sess.opts.debuginfo != NoDebugInfo {
-                Some(debuginfo::CrateDebugContext::new(llmod))
+                let dctx = debuginfo::CrateDebugContext::new(llmod);
+                debuginfo::metadata::compile_unit_metadata(shared, &dctx, shared.tcx.sess);
+                Some(dctx)
             } else {
                 None
             };
@@ -540,6 +606,7 @@ fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>,
             let local_ccx = LocalCrateContext {
                 llmod: llmod,
                 llcx: llcx,
+                previous_work_product: previous_work_product,
                 codegen_unit: codegen_unit,
                 tn: TypeNames::new(),
                 needs_unwind_cleanup_cache: RefCell::new(FnvHashMap()),
@@ -574,6 +641,7 @@ fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>,
                 intrinsics: RefCell::new(FnvHashMap()),
                 n_llvm_insns: Cell::new(0),
                 type_of_depth: Cell::new(0),
+                symbol_map: symbol_map,
             };
 
             let (int_type, opaque_vec_type, str_slice_ty, mut local_ccx) = {
@@ -698,6 +766,10 @@ pub fn llcx(&self) -> ContextRef {
         self.local().llcx
     }
 
+    pub fn previous_work_product(&self) -> Option<&WorkProduct> {
+        self.local().previous_work_product.as_ref()
+    }
+
     pub fn codegen_unit(&self) -> &CodegenUnit<'tcx> {
         &self.local().codegen_unit
     }
@@ -730,7 +802,8 @@ pub fn fn_pointer_shims(&self) -> &RefCell<FnvHashMap<Ty<'tcx>, ValueRef>> {
         &self.local().fn_pointer_shims
     }
 
-    pub fn drop_glues<'a>(&'a self) -> &'a RefCell<FnvHashMap<DropGlueKind<'tcx>, ValueRef>> {
+    pub fn drop_glues<'a>(&'a self)
+                          -> &'a RefCell<FnvHashMap<DropGlueKind<'tcx>, (ValueRef, FnType)>> {
         &self.local().drop_glues
     }
 
@@ -816,14 +889,6 @@ pub fn stats<'a>(&'a self) -> &'a Stats {
         &self.shared.stats
     }
 
-    pub fn available_monomorphizations<'a>(&'a self) -> &'a RefCell<FnvHashSet<String>> {
-        &self.shared.available_monomorphizations
-    }
-
-    pub fn available_drop_glues(&self) -> &RefCell<FnvHashMap<DropGlueKind<'tcx>, String>> {
-        &self.shared.available_drop_glues
-    }
-
     pub fn int_type(&self) -> Type {
         self.local().int_type
     }
@@ -900,22 +965,12 @@ pub fn get_mir(&self, def_id: DefId) -> Option<CachedMir<'b, 'tcx>> {
         self.shared.get_mir(def_id)
     }
 
-    pub fn translation_items(&self) -> &RefCell<FnvHashMap<TransItem<'tcx>, TransItemState>> {
-        &self.shared.translation_items
+    pub fn symbol_map(&self) -> &SymbolMap<'tcx> {
+        &*self.local().symbol_map
     }
 
-    pub fn record_translation_item_as_generated(&self, cgi: TransItem<'tcx>) {
-        if self.sess().opts.debugging_opts.print_trans_items.is_none() {
-            return;
-        }
-
-        let mut codegen_items = self.translation_items().borrow_mut();
-
-        if codegen_items.contains_key(&cgi) {
-            codegen_items.insert(cgi, TransItemState::PredictedAndGenerated);
-        } else {
-            codegen_items.insert(cgi, TransItemState::NotPredictedButGenerated);
-        }
+    pub fn translation_items(&self) -> &RefCell<FnvHashSet<TransItem<'tcx>>> {
+        &self.shared.translation_items
     }
 
     /// Given the def-id of some item that has no type parameters, make