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 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};
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>>,
}
impl<'a, 'tcx: 'a> CrateContextList<'a, 'tcx> {
-
pub fn new(shared_ccx: &'a SharedCrateContext<'a, '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, symbol_map.clone())
+ 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,
}
}
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);
+ }
}
}
}
}
+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();
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)
}
impl<'tcx> LocalCrateContext<'tcx> {
fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>,
codegen_unit: CodegenUnit<'tcx>,
+ previous_work_product: Option<WorkProduct>,
symbol_map: Rc<SymbolMap<'tcx>>)
-> LocalCrateContext<'tcx> {
unsafe {
// 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
};
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()),
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
}