From b2ea54d2c6277f90312ae6a5de5f9165def99ffe Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 5 May 2016 14:14:41 -0400 Subject: [PATCH] trans: Split LocalCrateContext ownership out of SharedCrateContext. --- src/librustc_trans/base.rs | 26 ++-- src/librustc_trans/context.rs | 259 ++++++++++++++++++---------------- 2 files changed, 151 insertions(+), 134 deletions(-) diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index dd453bf99691..98a84205930f 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -68,7 +68,7 @@ use common::{node_id_type, fulfill_obligation}; use common::{type_is_immediate, type_is_zero_size, val_ty}; use common; use consts; -use context::SharedCrateContext; +use context::{SharedCrateContext, CrateContextList}; use controlflow; use datum; use debuginfo::{self, DebugLoc, ToDebugLoc}; @@ -2522,7 +2522,7 @@ pub fn write_metadata<'a, 'tcx>(cx: &SharedCrateContext<'a, 'tcx>, /// Find any symbols that are defined in one compilation unit, but not declared /// in any other compilation unit. Give these symbols internal linkage. -fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<&str>) { +fn internalize_symbols(cx: &CrateContextList, reachable: &HashSet<&str>) { unsafe { let mut declared = HashSet::new(); @@ -2577,12 +2577,12 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<&str>) { // when using MSVC linker. We do this only for data, as linker can fix up // code references on its own. // See #26591, #27438 -fn create_imps(cx: &SharedCrateContext) { +fn create_imps(cx: &CrateContextList) { // The x86 ABI seems to require that leading underscores are added to symbol // names, so we need an extra underscore on 32-bit. There's also a leading // '\x01' here which disables LLVM's symbol mangling (e.g. no extra // underscores added in front). - let prefix = if cx.sess().target.target.target_pointer_width == "32" { + let prefix = if cx.shared().sess().target.target.target_pointer_width == "32" { "\x01__imp__" } else { "\x01__imp_" @@ -2714,10 +2714,7 @@ pub fn trans_crate<'tcx>(tcx: &TyCtxt<'tcx>, let link_meta = link::build_link_meta(&tcx, name); - let codegen_units = tcx.sess.opts.cg.codegen_units; - let shared_ccx = SharedCrateContext::new(&link_meta.crate_name, - codegen_units, - tcx, + let shared_ccx = SharedCrateContext::new(tcx, &mir_map, export_map, Sha256::new(), @@ -2726,8 +2723,11 @@ pub fn trans_crate<'tcx>(tcx: &TyCtxt<'tcx>, check_overflow, check_dropflag); + let codegen_units = tcx.sess.opts.cg.codegen_units; + let crate_context_list = CrateContextList::new(&shared_ccx, codegen_units); + { - let ccx = shared_ccx.get_ccx(0); + let ccx = crate_context_list.get_ccx(0); collect_translation_items(&ccx); // Translate all items. See `TransModVisitor` for @@ -2743,7 +2743,7 @@ pub fn trans_crate<'tcx>(tcx: &TyCtxt<'tcx>, symbol_names_test::report_symbol_names(&ccx); } - for ccx in shared_ccx.iter() { + for ccx in crate_context_list.iter() { if ccx.sess().opts.debuginfo != NoDebugInfo { debuginfo::finalize(&ccx); } @@ -2792,7 +2792,7 @@ pub fn trans_crate<'tcx>(tcx: &TyCtxt<'tcx>, } } - let modules = shared_ccx.iter() + let modules = crate_context_list.iter() .map(|ccx| ModuleTranslation { llcx: ccx.llcx(), llmod: ccx.llmod() }) .collect(); @@ -2819,13 +2819,13 @@ pub fn trans_crate<'tcx>(tcx: &TyCtxt<'tcx>, } if codegen_units > 1 { - internalize_symbols(&shared_ccx, + internalize_symbols(&crate_context_list, &reachable_symbols.iter().map(|x| &x[..]).collect()); } if sess.target.target.options.is_like_msvc && sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateTypeRlib) { - create_imps(&shared_ccx); + create_imps(&crate_context_list); } let metadata_module = ModuleTranslation { diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 2ee880fa3d85..7db42bb00ee1 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -64,8 +64,6 @@ pub struct Stats { /// crate, so it must not contain references to any LLVM data structures /// (aside from metadata-related ones). pub struct SharedCrateContext<'a, 'tcx: 'a> { - local_ccxs: Vec>, - metadata_llmod: ModuleRef, metadata_llcx: ContextRef, @@ -95,7 +93,7 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> { pub struct LocalCrateContext<'tcx> { llmod: ModuleRef, llcx: ContextRef, - tn: TypeNames, + tn: TypeNames, // FIXME: This seems to be largely unused. needs_unwind_cleanup_cache: RefCell, bool>>, fn_pointer_shims: RefCell, ValueRef>>, drop_glues: RefCell, ValueRef>>, @@ -191,16 +189,65 @@ impl<'tcx> DepTrackingMapConfig for TraitSelectionCache<'tcx> { } } +pub struct CrateContextList<'a, 'tcx: 'a> { + shared: &'a SharedCrateContext<'a, 'tcx>, + local_ccxs: Vec>, +} + +impl<'a, 'tcx: 'a> CrateContextList<'a, 'tcx> { + + pub fn new(shared_ccx: &'a SharedCrateContext<'a, 'tcx>, + local_count: usize) + -> CrateContextList<'a, 'tcx> { + CrateContextList { + shared: shared_ccx, + local_ccxs: (0..local_count).map(|index| { + // Append ".rs" to crate name as LLVM module identifier. + // + // LLVM code generator emits a ".file filename" directive + // for ELF backends. Value of the "filename" is set as the + // LLVM module identifier. Due to a LLVM MC bug[1], LLVM + // 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", shared_ccx.link_meta.crate_name, index); + LocalCrateContext::new(shared_ccx, &llmod_id[..]) + }).collect() + } + } + + pub fn iter<'b>(&'b self) -> CrateContextIterator<'b, 'tcx> { + CrateContextIterator { + shared: self.shared, + index: 0, + local_ccxs: &self.local_ccxs[..] + } + } + + pub fn get_ccx<'b>(&'b self, index: usize) -> CrateContext<'b, 'tcx> { + CrateContext { + shared: self.shared, + index: index, + local_ccxs: &self.local_ccxs[..], + } + } + + pub fn shared(&self) -> &'a SharedCrateContext<'a, 'tcx> { + self.shared + } +} + pub struct CrateContext<'a, 'tcx: 'a> { shared: &'a SharedCrateContext<'a, 'tcx>, - local: &'a LocalCrateContext<'tcx>, - /// The index of `local` in `shared.local_ccxs`. This is used in + local_ccxs: &'a [LocalCrateContext<'tcx>], + /// The index of `local` in `local_ccxs`. This is used in /// `maybe_iter(true)` to identify the original `LocalCrateContext`. index: usize, } pub struct CrateContextIterator<'a, 'tcx: 'a> { shared: &'a SharedCrateContext<'a, 'tcx>, + local_ccxs: &'a [LocalCrateContext<'tcx>], index: usize, } @@ -208,7 +255,7 @@ impl<'a, 'tcx> Iterator for CrateContextIterator<'a,'tcx> { type Item = CrateContext<'a, 'tcx>; fn next(&mut self) -> Option> { - if self.index >= self.shared.local_ccxs.len() { + if self.index >= self.local_ccxs.len() { return None; } @@ -217,8 +264,8 @@ impl<'a, 'tcx> Iterator for CrateContextIterator<'a,'tcx> { Some(CrateContext { shared: self.shared, - local: &self.shared.local_ccxs[index], index: index, + local_ccxs: self.local_ccxs, }) } } @@ -226,6 +273,7 @@ impl<'a, 'tcx> Iterator for CrateContextIterator<'a,'tcx> { /// The iterator produced by `CrateContext::maybe_iter`. pub struct CrateContextMaybeIterator<'a, 'tcx: 'a> { shared: &'a SharedCrateContext<'a, 'tcx>, + local_ccxs: &'a [LocalCrateContext<'tcx>], index: usize, single: bool, origin: usize, @@ -235,20 +283,20 @@ impl<'a, 'tcx> Iterator for CrateContextMaybeIterator<'a, 'tcx> { type Item = (CrateContext<'a, 'tcx>, bool); fn next(&mut self) -> Option<(CrateContext<'a, 'tcx>, bool)> { - if self.index >= self.shared.local_ccxs.len() { + if self.index >= self.local_ccxs.len() { return None; } let index = self.index; self.index += 1; if self.single { - self.index = self.shared.local_ccxs.len(); + self.index = self.local_ccxs.len(); } let ccx = CrateContext { shared: self.shared, - local: &self.shared.local_ccxs[index], index: index, + local_ccxs: self.local_ccxs }; Some((ccx, index == self.origin)) } @@ -288,9 +336,7 @@ unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextR } impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { - pub fn new(crate_name: &str, - local_count: usize, - tcx: &'b TyCtxt<'tcx>, + pub fn new(tcx: &'b TyCtxt<'tcx>, mir_map: &'b MirMap<'tcx>, export_map: ExportMap, symbol_hasher: Sha256, @@ -348,8 +394,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { // start) and then strongly recommending static linkage on MSVC! let use_dll_storage_attrs = tcx.sess.target.target.options.is_like_msvc; - let mut shared_ccx = SharedCrateContext { - local_ccxs: Vec::with_capacity(local_count), + SharedCrateContext { metadata_llmod: metadata_llmod, metadata_llcx: metadata_llcx, export_map: export_map, @@ -378,55 +423,9 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> { available_drop_glues: RefCell::new(FnvHashMap()), use_dll_storage_attrs: use_dll_storage_attrs, translation_items: RefCell::new(FnvHashMap()), - }; - - for i in 0..local_count { - // Append ".rs" to crate name as LLVM module identifier. - // - // LLVM code generator emits a ".file filename" directive - // for ELF backends. Value of the "filename" is set as the - // LLVM module identifier. Due to a LLVM MC bug[1], LLVM - // 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", crate_name, i); - let local_ccx = LocalCrateContext::new(&shared_ccx, &llmod_id[..]); - shared_ccx.local_ccxs.push(local_ccx); - } - - shared_ccx - } - - pub fn iter<'a>(&'a self) -> CrateContextIterator<'a, 'tcx> { - CrateContextIterator { - shared: self, - index: 0, } } - pub fn get_ccx<'a>(&'a self, index: usize) -> CrateContext<'a, 'tcx> { - CrateContext { - shared: self, - local: &self.local_ccxs[index], - index: index, - } - } - - fn get_smallest_ccx<'a>(&'a self) -> CrateContext<'a, 'tcx> { - let (local_ccx, index) = - self.local_ccxs - .iter() - .zip(0..self.local_ccxs.len()) - .min_by_key(|&(local_ccx, _idx)| local_ccx.n_llvm_insns.get()) - .unwrap(); - CrateContext { - shared: self, - local: local_ccx, - index: index, - } - } - - pub fn metadata_llmod(&self) -> ModuleRef { self.metadata_llmod } @@ -481,7 +480,7 @@ impl<'tcx> LocalCrateContext<'tcx> { None }; - let mut local_ccx = LocalCrateContext { + let local_ccx = LocalCrateContext { llmod: llmod, llcx: llcx, tn: TypeNames::new(), @@ -522,21 +521,28 @@ impl<'tcx> LocalCrateContext<'tcx> { .clone())), }; - local_ccx.int_type = Type::int(&local_ccx.dummy_ccx(shared)); - local_ccx.opaque_vec_type = Type::opaque_vec(&local_ccx.dummy_ccx(shared)); + let (int_type, opaque_vec_type, str_slice_ty, mut local_ccx) = { + // Do a little dance to create a dummy CrateContext, so we can + // create some things in the LLVM module of this codegen unit + let mut local_ccxs = vec![local_ccx]; + let (int_type, opaque_vec_type, str_slice_ty) = { + let dummy_ccx = LocalCrateContext::dummy_ccx(shared, + local_ccxs.as_mut_slice()); + let mut str_slice_ty = Type::named_struct(&dummy_ccx, "str_slice"); + str_slice_ty.set_struct_body(&[Type::i8p(&dummy_ccx), + Type::int(&dummy_ccx)], + false); + (Type::int(&dummy_ccx), Type::opaque_vec(&dummy_ccx), str_slice_ty) + }; + (int_type, opaque_vec_type, str_slice_ty, local_ccxs.pop().unwrap()) + }; - // Done mutating local_ccx directly. (The rest of the - // initialization goes through RefCell.) - { - let ccx = local_ccx.dummy_ccx(shared); + local_ccx.int_type = int_type; + local_ccx.opaque_vec_type = opaque_vec_type; + local_ccx.tn.associate_type("str_slice", &str_slice_ty); - let mut str_slice_ty = Type::named_struct(&ccx, "str_slice"); - str_slice_ty.set_struct_body(&[Type::i8p(&ccx), ccx.int_type()], false); - ccx.tn().associate_type("str_slice", &str_slice_ty); - - if ccx.sess().count_llvm_insns() { - base::init_insn_ctxt() - } + if shared.tcx.sess.count_llvm_insns() { + base::init_insn_ctxt() } local_ccx @@ -545,18 +551,19 @@ impl<'tcx> LocalCrateContext<'tcx> { /// Create a dummy `CrateContext` from `self` and the provided /// `SharedCrateContext`. This is somewhat dangerous because `self` may - /// not actually be an element of `shared.local_ccxs`, which can cause some - /// operations to panic unexpectedly. + /// not be fully initialized. /// /// This is used in the `LocalCrateContext` constructor to allow calling /// functions that expect a complete `CrateContext`, even before the local /// portion is fully initialized and attached to the `SharedCrateContext`. - fn dummy_ccx<'a>(&'a self, shared: &'a SharedCrateContext<'a, 'tcx>) + fn dummy_ccx<'a>(shared: &'a SharedCrateContext<'a, 'tcx>, + local_ccxs: &'a [LocalCrateContext<'tcx>]) -> CrateContext<'a, 'tcx> { + assert!(local_ccxs.len() == 1); CrateContext { shared: shared, - local: self, - index: !0 as usize, + index: 0, + local_ccxs: local_ccxs } } } @@ -567,13 +574,23 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { } pub fn local(&self) -> &'b LocalCrateContext<'tcx> { - self.local + &self.local_ccxs[self.index] } /// Get a (possibly) different `CrateContext` from the same /// `SharedCrateContext`. - pub fn rotate(&self) -> CrateContext<'b, 'tcx> { - self.shared.get_smallest_ccx() + pub fn rotate(&'b self) -> CrateContext<'b, 'tcx> { + let (_, index) = + self.local_ccxs + .iter() + .zip(0..self.local_ccxs.len()) + .min_by_key(|&(local_ccx, _idx)| local_ccx.n_llvm_insns.get()) + .unwrap(); + CrateContext { + shared: self.shared, + index: index, + local_ccxs: &self.local_ccxs[..], + } } /// Either iterate over only `self`, or iterate over all `CrateContext`s in @@ -588,10 +605,10 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { index: if iter_all { 0 } else { self.index }, single: !iter_all, origin: self.index, + local_ccxs: self.local_ccxs, } } - pub fn tcx<'a>(&'a self) -> &'a TyCtxt<'tcx> { self.shared.tcx } @@ -605,7 +622,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { } pub fn raw_builder<'a>(&'a self) -> BuilderRef { - self.local.builder.b + self.local().builder.b } pub fn get_intrinsic(&self, key: &str) -> ValueRef { @@ -619,11 +636,11 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { } pub fn llmod(&self) -> ModuleRef { - self.local.llmod + self.local().llmod } pub fn llcx(&self) -> ContextRef { - self.local.llcx + self.local().llcx } pub fn td(&self) -> llvm::TargetDataRef { @@ -631,7 +648,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { } pub fn tn<'a>(&'a self) -> &'a TypeNames { - &self.local.tn + &self.local().tn } pub fn export_map<'a>(&'a self) -> &'a ExportMap { @@ -651,56 +668,56 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { } pub fn needs_unwind_cleanup_cache(&self) -> &RefCell, bool>> { - &self.local.needs_unwind_cleanup_cache + &self.local().needs_unwind_cleanup_cache } pub fn fn_pointer_shims(&self) -> &RefCell, ValueRef>> { - &self.local.fn_pointer_shims + &self.local().fn_pointer_shims } pub fn drop_glues<'a>(&'a self) -> &'a RefCell, ValueRef>> { - &self.local.drop_glues + &self.local().drop_glues } pub fn external<'a>(&'a self) -> &'a RefCell>> { - &self.local.external + &self.local().external } pub fn external_srcs<'a>(&'a self) -> &'a RefCell> { - &self.local.external_srcs + &self.local().external_srcs } pub fn instances<'a>(&'a self) -> &'a RefCell, ValueRef>> { - &self.local.instances + &self.local().instances } pub fn monomorphizing<'a>(&'a self) -> &'a RefCell> { - &self.local.monomorphizing + &self.local().monomorphizing } pub fn vtables<'a>(&'a self) -> &'a RefCell, ValueRef>> { - &self.local.vtables + &self.local().vtables } pub fn const_cstr_cache<'a>(&'a self) -> &'a RefCell> { - &self.local.const_cstr_cache + &self.local().const_cstr_cache } pub fn const_unsized<'a>(&'a self) -> &'a RefCell> { - &self.local.const_unsized + &self.local().const_unsized } pub fn const_globals<'a>(&'a self) -> &'a RefCell> { - &self.local.const_globals + &self.local().const_globals } pub fn const_values<'a>(&'a self) -> &'a RefCell), ValueRef>> { - &self.local.const_values + &self.local().const_values } pub fn extern_const_values<'a>(&'a self) -> &'a RefCell> { - &self.local.extern_const_values + &self.local().extern_const_values } pub fn statics<'a>(&'a self) -> &'a RefCell> { @@ -709,27 +726,27 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { pub fn impl_method_cache<'a>(&'a self) -> &'a RefCell> { - &self.local.impl_method_cache + &self.local().impl_method_cache } pub fn closure_bare_wrapper_cache<'a>(&'a self) -> &'a RefCell> { - &self.local.closure_bare_wrapper_cache + &self.local().closure_bare_wrapper_cache } pub fn statics_to_rauw<'a>(&'a self) -> &'a RefCell> { - &self.local.statics_to_rauw + &self.local().statics_to_rauw } pub fn lltypes<'a>(&'a self) -> &'a RefCell, Type>> { - &self.local.lltypes + &self.local().lltypes } pub fn llsizingtypes<'a>(&'a self) -> &'a RefCell, Type>> { - &self.local.llsizingtypes + &self.local().llsizingtypes } pub fn adt_reprs<'a>(&'a self) -> &'a RefCell, Rc>>> { - &self.local.adt_reprs + &self.local().adt_reprs } pub fn symbol_hasher<'a>(&'a self) -> &'a RefCell { @@ -737,7 +754,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { } pub fn type_hashcodes<'a>(&'a self) -> &'a RefCell, String>> { - &self.local.type_hashcodes + &self.local().type_hashcodes } pub fn stats<'a>(&'a self) -> &'a Stats { @@ -753,43 +770,43 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { } pub fn int_type(&self) -> Type { - self.local.int_type + self.local().int_type } pub fn opaque_vec_type(&self) -> Type { - self.local.opaque_vec_type + self.local().opaque_vec_type } pub fn closure_vals<'a>(&'a self) -> &'a RefCell, ValueRef>> { - &self.local.closure_vals + &self.local().closure_vals } pub fn dbg_cx<'a>(&'a self) -> &'a Option> { - &self.local.dbg_cx + &self.local().dbg_cx } pub fn eh_personality<'a>(&'a self) -> &'a Cell> { - &self.local.eh_personality + &self.local().eh_personality } pub fn eh_unwind_resume<'a>(&'a self) -> &'a Cell> { - &self.local.eh_unwind_resume + &self.local().eh_unwind_resume } pub fn rust_try_fn<'a>(&'a self) -> &'a Cell> { - &self.local.rust_try_fn + &self.local().rust_try_fn } fn intrinsics<'a>(&'a self) -> &'a RefCell> { - &self.local.intrinsics + &self.local().intrinsics } pub fn count_llvm_insn(&self) { - self.local.n_llvm_insns.set(self.local.n_llvm_insns.get() + 1); + self.local().n_llvm_insns.set(self.local().n_llvm_insns.get() + 1); } pub fn trait_cache(&self) -> &RefCell>> { - &self.local.trait_cache + &self.local().trait_cache } pub fn obj_size_bound(&self) -> u64 { @@ -803,14 +820,14 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { } pub fn enter_type_of(&self, ty: Ty<'tcx>) -> TypeOfDepthLock<'b, 'tcx> { - let current_depth = self.local.type_of_depth.get(); + let current_depth = self.local().type_of_depth.get(); debug!("enter_type_of({:?}) at depth {:?}", ty, current_depth); if current_depth > self.sess().recursion_limit.get() { self.sess().fatal( &format!("overflow representing the type `{}`", ty)) } - self.local.type_of_depth.set(current_depth + 1); - TypeOfDepthLock(self.local) + self.local().type_of_depth.set(current_depth + 1); + TypeOfDepthLock(self.local()) } pub fn check_overflow(&self) -> bool {