Auto merge of #33473 - michaelwoerister:split-cratecontext, r=nikomatsakis

Preparatory refactorings for collector-driven trans.

This is a set of refactorings that allows to do translation item collection and partitioning before LocalCrateContext instances or LLVM modules are generated. As a consequence we can now create LocalCrateContexts already with knowledge of the codegen unit it will be used for. This is a preparation step for driving trans by the results of codegen unit partitioning.
This commit is contained in:
bors 2016-05-09 23:50:10 -07:00
commit 1939b76903
13 changed files with 538 additions and 492 deletions

View file

@ -639,7 +639,8 @@ pub fn run_passes(sess: &Session,
}
// Sanity check
assert!(trans.modules.len() == sess.opts.cg.codegen_units);
assert!(trans.modules.len() == sess.opts.cg.codegen_units ||
sess.opts.debugging_opts.incremental.is_some());
let tm = create_target_machine(sess);

View file

@ -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};
@ -81,7 +81,7 @@ use machine::{llalign_of_min, llsize_of, llsize_of_real};
use meth;
use mir;
use monomorphize::{self, Instance};
use partitioning::{self, PartitioningStrategy, InstantiationMode};
use partitioning::{self, PartitioningStrategy, InstantiationMode, CodegenUnit};
use symbol_names_test;
use tvec;
use type_::Type;
@ -664,7 +664,7 @@ pub fn coerce_unsized_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
}
}
pub fn custom_coerce_unsize_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
pub fn custom_coerce_unsize_info<'scx, 'tcx>(scx: &SharedCrateContext<'scx, 'tcx>,
source_ty: Ty<'tcx>,
target_ty: Ty<'tcx>)
-> CustomCoerceUnsized {
@ -674,13 +674,13 @@ pub fn custom_coerce_unsize_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
subst::VecPerParamSpace::empty());
let trait_ref = ty::Binder(ty::TraitRef {
def_id: ccx.tcx().lang_items.coerce_unsized_trait().unwrap(),
substs: ccx.tcx().mk_substs(trait_substs)
def_id: scx.tcx().lang_items.coerce_unsized_trait().unwrap(),
substs: scx.tcx().mk_substs(trait_substs)
});
match fulfill_obligation(ccx, DUMMY_SP, trait_ref) {
match fulfill_obligation(scx, DUMMY_SP, trait_ref) {
traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => {
ccx.tcx().custom_coerce_unsized_kind(impl_def_id)
scx.tcx().custom_coerce_unsized_kind(impl_def_id)
}
vtable => {
bug!("invalid CoerceUnsized vtable: {:?}", vtable);
@ -1824,7 +1824,7 @@ pub fn trans_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
closure_env: closure::ClosureEnv) {
ccx.stats().n_closures.set(ccx.stats().n_closures.get() + 1);
if collector::collecting_debug_information(ccx) {
if collector::collecting_debug_information(ccx.shared()) {
ccx.record_translation_item_as_generated(TransItem::Fn(instance));
}
@ -2188,7 +2188,8 @@ pub fn update_linkage(ccx: &CrateContext,
// `llval` is a translation of an item defined in a separate
// compilation unit. This only makes sense if there are at least
// two compilation units.
assert!(ccx.sess().opts.cg.codegen_units > 1);
assert!(ccx.sess().opts.cg.codegen_units > 1 ||
ccx.sess().opts.debugging_opts.incremental.is_some());
// `llval` is a copy of something defined elsewhere, so use
// `AvailableExternallyLinkage` to avoid duplicating code in the
// output.
@ -2524,7 +2525,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();
@ -2579,12 +2580,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_"
@ -2661,10 +2662,10 @@ fn iter_functions(llmod: llvm::ModuleRef) -> ValueIter {
///
/// This list is later used by linkers to determine the set of symbols needed to
/// be exposed from a dynamic library and it's also encoded into the metadata.
pub fn filter_reachable_ids(ccx: &SharedCrateContext) -> NodeSet {
ccx.reachable().iter().map(|x| *x).filter(|id| {
pub fn filter_reachable_ids(scx: &SharedCrateContext) -> NodeSet {
scx.reachable().iter().map(|x| *x).filter(|id| {
// First, only worry about nodes which have a symbol name
ccx.item_symbols().borrow().contains_key(id)
scx.item_symbols().borrow().contains_key(id)
}).filter(|&id| {
// Next, we want to ignore some FFI functions that are not exposed from
// this crate. Reachable FFI functions can be lumped into two
@ -2679,9 +2680,9 @@ pub fn filter_reachable_ids(ccx: &SharedCrateContext) -> NodeSet {
//
// As a result, if this id is an FFI item (foreign item) then we only
// let it through if it's included statically.
match ccx.tcx().map.get(id) {
match scx.tcx().map.get(id) {
hir_map::NodeForeignItem(..) => {
ccx.sess().cstore.is_statically_included_foreign_item(id)
scx.sess().cstore.is_statically_included_foreign_item(id)
}
_ => true,
}
@ -2716,10 +2717,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(),
@ -2728,9 +2726,15 @@ pub fn trans_crate<'tcx>(tcx: &TyCtxt<'tcx>,
check_overflow,
check_dropflag);
let codegen_units = collect_and_partition_translation_items(&shared_ccx);
let codegen_unit_count = codegen_units.len();
assert!(tcx.sess.opts.cg.codegen_units == codegen_unit_count ||
tcx.sess.opts.debugging_opts.incremental.is_some());
let crate_context_list = CrateContextList::new(&shared_ccx, codegen_units);
{
let ccx = shared_ccx.get_ccx(0);
collect_translation_items(&ccx);
let ccx = crate_context_list.get_ccx(0);
// Translate all items. See `TransModVisitor` for
// details on why we walk in this particular way.
@ -2740,12 +2744,12 @@ pub fn trans_crate<'tcx>(tcx: &TyCtxt<'tcx>,
krate.visit_all_items(&mut TransModVisitor { ccx: &ccx });
}
collector::print_collection_results(&ccx);
collector::print_collection_results(ccx.shared());
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);
}
@ -2794,7 +2798,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();
@ -2820,14 +2824,14 @@ pub fn trans_crate<'tcx>(tcx: &TyCtxt<'tcx>,
}
}
if codegen_units > 1 {
internalize_symbols(&shared_ccx,
if codegen_unit_count > 1 {
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 {
@ -2912,10 +2916,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TransItemsWithinModVisitor<'a, 'tcx> {
}
}
fn collect_translation_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>) {
let time_passes = ccx.sess().time_passes();
fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>)
-> Vec<CodegenUnit<'tcx>> {
let time_passes = scx.sess().time_passes();
let collection_mode = match ccx.sess().opts.debugging_opts.print_trans_items {
let collection_mode = match scx.sess().opts.debugging_opts.print_trans_items {
Some(ref s) => {
let mode_string = s.to_lowercase();
let mode_string = mode_string.trim();
@ -2926,7 +2931,7 @@ fn collect_translation_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>) {
let message = format!("Unknown codegen-item collection mode '{}'. \
Falling back to 'lazy' mode.",
mode_string);
ccx.sess().warn(&message);
scx.sess().warn(&message);
}
TransItemCollectionMode::Lazy
@ -2936,27 +2941,27 @@ fn collect_translation_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>) {
};
let (items, reference_map) = time(time_passes, "translation item collection", || {
collector::collect_crate_translation_items(&ccx, collection_mode)
collector::collect_crate_translation_items(scx, collection_mode)
});
let strategy = if ccx.sess().opts.debugging_opts.incremental.is_some() {
let strategy = if scx.sess().opts.debugging_opts.incremental.is_some() {
PartitioningStrategy::PerModule
} else {
PartitioningStrategy::FixedUnitCount(ccx.sess().opts.cg.codegen_units)
PartitioningStrategy::FixedUnitCount(scx.sess().opts.cg.codegen_units)
};
let codegen_units = time(time_passes, "codegen unit partitioning", || {
partitioning::partition(ccx.tcx(),
partitioning::partition(scx.tcx(),
items.iter().cloned(),
strategy,
&reference_map)
});
if ccx.sess().opts.debugging_opts.print_trans_items.is_some() {
if scx.sess().opts.debugging_opts.print_trans_items.is_some() {
let mut item_to_cgus = HashMap::new();
for cgu in codegen_units {
for (trans_item, linkage) in cgu.items {
for cgu in &codegen_units {
for (&trans_item, &linkage) in &cgu.items {
item_to_cgus.entry(trans_item)
.or_insert(Vec::new())
.push((cgu.name.clone(), linkage));
@ -2966,7 +2971,7 @@ fn collect_translation_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>) {
let mut item_keys: Vec<_> = items
.iter()
.map(|i| {
let mut output = i.to_string(ccx);
let mut output = i.to_string(scx.tcx());
output.push_str(" @@");
let mut empty = Vec::new();
let mut cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
@ -3005,10 +3010,12 @@ fn collect_translation_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>) {
println!("TRANS_ITEM {}", item);
}
let mut ccx_map = ccx.translation_items().borrow_mut();
let mut ccx_map = scx.translation_items().borrow_mut();
for cgi in items {
ccx_map.insert(cgi, TransItemState::PredictedButNotGenerated);
}
}
codegen_units
}

View file

@ -156,7 +156,7 @@ impl<'tcx> Callee<'tcx> {
let trait_id = method_item.container().id();
let trait_ref = ty::Binder(substs.to_trait_ref(tcx, trait_id));
let trait_ref = infer::normalize_associated_type(tcx, &trait_ref);
match common::fulfill_obligation(ccx, DUMMY_SP, trait_ref) {
match common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref) {
traits::VtableImpl(vtable_impl) => {
let impl_did = vtable_impl.impl_def_id;
let mname = tcx.item_name(def_id);

File diff suppressed because it is too large Load diff

View file

@ -20,6 +20,7 @@ use rustc::cfg;
use rustc::hir::def::Def;
use rustc::hir::def_id::DefId;
use rustc::infer;
use rustc::util::common::MemoizationMap;
use middle::lang_items::LangItem;
use rustc::ty::subst::Substs;
use abi::{Abi, FnType};
@ -54,7 +55,7 @@ use syntax::codemap::{DUMMY_SP, Span};
use syntax::parse::token::InternedString;
use syntax::parse::token;
pub use context::CrateContext;
pub use context::{CrateContext, SharedCrateContext};
/// Is the type's representation size known at compile time?
pub fn type_is_sized<'tcx>(tcx: &TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
@ -1049,92 +1050,86 @@ pub fn expr_ty_adjusted<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, ex: &hir::Expr) ->
/// Attempts to resolve an obligation. The result is a shallow vtable resolution -- meaning that we
/// do not (necessarily) resolve all nested obligations on the impl. Note that type check should
/// guarantee to us that all nested obligations *could be* resolved if we wanted to.
pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
pub fn fulfill_obligation<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
span: Span,
trait_ref: ty::PolyTraitRef<'tcx>)
-> traits::Vtable<'tcx, ()>
{
let tcx = ccx.tcx();
let tcx = scx.tcx();
// Remove any references to regions; this helps improve caching.
let trait_ref = tcx.erase_regions(&trait_ref);
// First check the cache.
match ccx.trait_cache().borrow().get(&trait_ref) {
Some(vtable) => {
info!("Cache hit: {:?}", trait_ref);
return (*vtable).clone();
}
None => { }
}
scx.trait_cache().memoize(trait_ref, || {
debug!("trans fulfill_obligation: trait_ref={:?} def_id={:?}",
trait_ref, trait_ref.def_id());
debug!("trans fulfill_obligation: trait_ref={:?} def_id={:?}",
trait_ref, trait_ref.def_id());
// Do the initial selection for the obligation. This yields the
// shallow result we are looking for -- that is, what specific impl.
let infcx = infer::normalizing_infer_ctxt(tcx,
&tcx.tables,
ProjectionMode::Any);
let mut selcx = SelectionContext::new(&infcx);
let obligation_cause = traits::ObligationCause::misc(span,
ast::DUMMY_NODE_ID);
let obligation = traits::Obligation::new(obligation_cause,
trait_ref.to_poly_trait_predicate());
// Do the initial selection for the obligation. This yields the
// shallow result we are looking for -- that is, what specific impl.
let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables, ProjectionMode::Any);
let mut selcx = SelectionContext::new(&infcx);
let selection = match selcx.select(&obligation) {
Ok(Some(selection)) => selection,
Ok(None) => {
// Ambiguity can happen when monomorphizing during trans
// expands to some humongo type that never occurred
// statically -- this humongo type can then overflow,
// leading to an ambiguous result. So report this as an
// overflow bug, since I believe this is the only case
// where ambiguity can result.
debug!("Encountered ambiguity selecting `{:?}` during trans, \
presuming due to overflow",
trait_ref);
tcx.sess.span_fatal(
span,
"reached the recursion limit during monomorphization \
(selection ambiguity)");
}
Err(e) => {
span_bug!(
span,
"Encountered error `{:?}` selecting `{:?}` during trans",
e,
trait_ref)
}
};
let obligation =
traits::Obligation::new(traits::ObligationCause::misc(span, ast::DUMMY_NODE_ID),
trait_ref.to_poly_trait_predicate());
let selection = match selcx.select(&obligation) {
Ok(Some(selection)) => selection,
Ok(None) => {
// Ambiguity can happen when monomorphizing during trans
// expands to some humongo type that never occurred
// statically -- this humongo type can then overflow,
// leading to an ambiguous result. So report this as an
// overflow bug, since I believe this is the only case
// where ambiguity can result.
debug!("Encountered ambiguity selecting `{:?}` during trans, \
presuming due to overflow",
trait_ref);
ccx.sess().span_fatal(
span,
"reached the recursion limit during monomorphization (selection ambiguity)");
}
Err(e) => {
span_bug!(
span,
"Encountered error `{:?}` selecting `{:?}` during trans",
e,
trait_ref)
}
};
// Currently, we use a fulfillment context to completely resolve
// all nested obligations. This is because they can inform the
// inference of the impl's type parameters.
let mut fulfill_cx = traits::FulfillmentContext::new();
let vtable = selection.map(|predicate| {
fulfill_cx.register_predicate_obligation(&infcx, predicate);
});
let vtable = infer::drain_fulfillment_cx_or_panic(
span, &infcx, &mut fulfill_cx, &vtable
);
// Currently, we use a fulfillment context to completely resolve
// all nested obligations. This is because they can inform the
// inference of the impl's type parameters.
let mut fulfill_cx = traits::FulfillmentContext::new();
let vtable = selection.map(|predicate| {
fulfill_cx.register_predicate_obligation(&infcx, predicate);
});
let vtable = infer::drain_fulfillment_cx_or_panic(
span, &infcx, &mut fulfill_cx, &vtable
);
info!("Cache miss: {:?} => {:?}", trait_ref, vtable);
info!("Cache miss: {:?} => {:?}", trait_ref, vtable);
ccx.trait_cache().borrow_mut().insert(trait_ref, vtable.clone());
vtable
vtable
})
}
/// Normalizes the predicates and checks whether they hold. If this
/// returns false, then either normalize encountered an error or one
/// of the predicates did not hold. Used when creating vtables to
/// check for unsatisfiable methods.
pub fn normalize_and_test_predicates<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
predicates: Vec<ty::Predicate<'tcx>>)
-> bool
pub fn normalize_and_test_predicates<'tcx>(tcx: &TyCtxt<'tcx>,
predicates: Vec<ty::Predicate<'tcx>>)
-> bool
{
debug!("normalize_and_test_predicates(predicates={:?})",
predicates);
let tcx = ccx.tcx();
let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables, ProjectionMode::Any);
let mut selcx = SelectionContext::new(&infcx);
let mut fulfill_cx = traits::FulfillmentContext::new();

View file

@ -1133,7 +1133,7 @@ pub fn trans_static(ccx: &CrateContext,
attrs: &[ast::Attribute])
-> Result<ValueRef, ConstEvalErr> {
if collector::collecting_debug_information(ccx) {
if collector::collecting_debug_information(ccx.shared()) {
ccx.record_translation_item_as_generated(TransItem::Static(id));
}

View file

@ -28,6 +28,7 @@ use mir::CachedMir;
use monomorphize::Instance;
use collector::{TransItem, TransItemState};
use partitioning::CodegenUnit;
use type_::{Type, TypeNames};
use rustc::ty::subst::{Substs, VecPerParamSpace};
use rustc::ty::{self, Ty, TyCtxt};
@ -64,8 +65,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<LocalCrateContext<'tcx>>,
metadata_llmod: ModuleRef,
metadata_llcx: ContextRef,
@ -86,6 +85,7 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
use_dll_storage_attrs: bool,
translation_items: RefCell<FnvHashMap<TransItem<'tcx>, TransItemState>>,
trait_cache: RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>>,
}
/// The local portion of a `CrateContext`. There is one `LocalCrateContext`
@ -95,7 +95,8 @@ 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.
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>>,
@ -171,8 +172,6 @@ pub struct LocalCrateContext<'tcx> {
/// Depth of the current type-of computation - used to bail out
type_of_depth: Cell<usize>,
trait_cache: RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>>,
}
// Implement DepTrackingMapConfig for `trait_cache`
@ -184,23 +183,66 @@ impl<'tcx> DepTrackingMapConfig for TraitSelectionCache<'tcx> {
type Key = ty::PolyTraitRef<'tcx>;
type Value = traits::Vtable<'tcx, ()>;
fn to_dep_node(key: &ty::PolyTraitRef<'tcx>) -> DepNode<DefId> {
ty::tls::with(|tcx| {
let lifted_key = tcx.lift(key).unwrap();
lifted_key.to_poly_trait_predicate().dep_node()
})
key.to_poly_trait_predicate().dep_node()
}
}
/// This list owns a number of LocalCrateContexts and binds them to their common
/// SharedCrateContext. This type just exists as a convenience, something to
/// pass around all LocalCrateContexts with and get an iterator over them.
pub struct CrateContextList<'a, 'tcx: 'a> {
shared: &'a SharedCrateContext<'a, 'tcx>,
local_ccxs: Vec<LocalCrateContext<'tcx>>,
}
impl<'a, 'tcx: 'a> CrateContextList<'a, 'tcx> {
pub fn new(shared_ccx: &'a SharedCrateContext<'a, 'tcx>,
codegen_units: Vec<CodegenUnit<'tcx>>)
-> CrateContextList<'a, 'tcx> {
CrateContextList {
shared: shared_ccx,
local_ccxs: codegen_units.into_iter().map(|codegen_unit| {
LocalCrateContext::new(shared_ccx, codegen_unit)
}).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
}
}
/// A CrateContext value binds together one LocalCrateContext with the
/// SharedCrateContext. It exists as a convenience wrapper, so we don't have to
/// pass around (SharedCrateContext, LocalCrateContext) tuples all over trans.
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 +250,7 @@ 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.shared.local_ccxs.len() {
if self.index >= self.local_ccxs.len() {
return None;
}
@ -217,8 +259,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 +268,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 +278,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 +331,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 +389,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 +418,10 @@ 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,
trait_cache: RefCell::new(DepTrackingMap::new(tcx.dep_graph.clone())),
}
}
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
}
@ -447,6 +442,10 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
&self.item_symbols
}
pub fn trait_cache(&self) -> &RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>> {
&self.trait_cache
}
pub fn link_meta<'a>(&'a self) -> &'a LinkMeta {
&self.link_meta
}
@ -466,14 +465,47 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
pub fn use_dll_storage_attrs(&self) -> bool {
self.use_dll_storage_attrs
}
pub fn get_mir(&self, def_id: DefId) -> Option<CachedMir<'b, 'tcx>> {
if def_id.is_local() {
let node_id = self.tcx.map.as_local_node_id(def_id).unwrap();
self.mir_map.map.get(&node_id).map(CachedMir::Ref)
} else {
if let Some(mir) = self.mir_cache.borrow().get(&def_id).cloned() {
return Some(CachedMir::Owned(mir));
}
let mir = self.sess().cstore.maybe_get_item_mir(self.tcx, def_id);
let cached = mir.map(Rc::new);
if let Some(ref mir) = cached {
self.mir_cache.borrow_mut().insert(def_id, mir.clone());
}
cached.map(CachedMir::Owned)
}
}
pub fn translation_items(&self) -> &RefCell<FnvHashMap<TransItem<'tcx>, TransItemState>> {
&self.translation_items
}
}
impl<'tcx> LocalCrateContext<'tcx> {
fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>,
name: &str)
codegen_unit: CodegenUnit<'tcx>)
-> LocalCrateContext<'tcx> {
unsafe {
let (llcx, llmod) = create_context_and_module(&shared.tcx.sess, name);
// Append ".rs" to 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", 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))
@ -481,9 +513,10 @@ impl<'tcx> LocalCrateContext<'tcx> {
None
};
let mut local_ccx = LocalCrateContext {
let local_ccx = LocalCrateContext {
llmod: llmod,
llcx: llcx,
codegen_unit: codegen_unit,
tn: TypeNames::new(),
needs_unwind_cleanup_cache: RefCell::new(FnvHashMap()),
fn_pointer_shims: RefCell::new(FnvHashMap()),
@ -517,26 +550,30 @@ impl<'tcx> LocalCrateContext<'tcx> {
intrinsics: RefCell::new(FnvHashMap()),
n_llvm_insns: Cell::new(0),
type_of_depth: Cell::new(0),
trait_cache: RefCell::new(DepTrackingMap::new(shared.tcx
.dep_graph
.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 +582,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 +605,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 +636,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 +653,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 +667,15 @@ 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 codegen_unit(&self) -> &CodegenUnit<'tcx> {
&self.local().codegen_unit
}
pub fn td(&self) -> llvm::TargetDataRef {
@ -631,7 +683,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,85 +703,85 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
}
pub fn needs_unwind_cleanup_cache(&self) -> &RefCell<FnvHashMap<Ty<'tcx>, bool>> {
&self.local.needs_unwind_cleanup_cache
&self.local().needs_unwind_cleanup_cache
}
pub fn fn_pointer_shims(&self) -> &RefCell<FnvHashMap<Ty<'tcx>, ValueRef>> {
&self.local.fn_pointer_shims
&self.local().fn_pointer_shims
}
pub fn drop_glues<'a>(&'a self) -> &'a RefCell<FnvHashMap<DropGlueKind<'tcx>, ValueRef>> {
&self.local.drop_glues
&self.local().drop_glues
}
pub fn external<'a>(&'a self) -> &'a RefCell<DefIdMap<Option<ast::NodeId>>> {
&self.local.external
&self.local().external
}
pub fn external_srcs<'a>(&'a self) -> &'a RefCell<NodeMap<DefId>> {
&self.local.external_srcs
&self.local().external_srcs
}
pub fn instances<'a>(&'a self) -> &'a RefCell<FnvHashMap<Instance<'tcx>, ValueRef>> {
&self.local.instances
&self.local().instances
}
pub fn monomorphizing<'a>(&'a self) -> &'a RefCell<DefIdMap<usize>> {
&self.local.monomorphizing
&self.local().monomorphizing
}
pub fn vtables<'a>(&'a self) -> &'a RefCell<FnvHashMap<ty::PolyTraitRef<'tcx>, ValueRef>> {
&self.local.vtables
&self.local().vtables
}
pub fn const_cstr_cache<'a>(&'a self) -> &'a RefCell<FnvHashMap<InternedString, ValueRef>> {
&self.local.const_cstr_cache
&self.local().const_cstr_cache
}
pub fn const_unsized<'a>(&'a self) -> &'a RefCell<FnvHashMap<ValueRef, ValueRef>> {
&self.local.const_unsized
&self.local().const_unsized
}
pub fn const_globals<'a>(&'a self) -> &'a RefCell<FnvHashMap<ValueRef, ValueRef>> {
&self.local.const_globals
&self.local().const_globals
}
pub fn const_values<'a>(&'a self) -> &'a RefCell<FnvHashMap<(ast::NodeId, &'tcx Substs<'tcx>),
ValueRef>> {
&self.local.const_values
&self.local().const_values
}
pub fn extern_const_values<'a>(&'a self) -> &'a RefCell<DefIdMap<ValueRef>> {
&self.local.extern_const_values
&self.local().extern_const_values
}
pub fn statics<'a>(&'a self) -> &'a RefCell<FnvHashMap<ValueRef, DefId>> {
&self.local.statics
&self.local().statics
}
pub fn impl_method_cache<'a>(&'a self)
-> &'a RefCell<FnvHashMap<(DefId, ast::Name), DefId>> {
&self.local.impl_method_cache
&self.local().impl_method_cache
}
pub fn closure_bare_wrapper_cache<'a>(&'a self) -> &'a RefCell<FnvHashMap<ValueRef, ValueRef>> {
&self.local.closure_bare_wrapper_cache
&self.local().closure_bare_wrapper_cache
}
pub fn statics_to_rauw<'a>(&'a self) -> &'a RefCell<Vec<(ValueRef, ValueRef)>> {
&self.local.statics_to_rauw
&self.local().statics_to_rauw
}
pub fn lltypes<'a>(&'a self) -> &'a RefCell<FnvHashMap<Ty<'tcx>, Type>> {
&self.local.lltypes
&self.local().lltypes
}
pub fn llsizingtypes<'a>(&'a self) -> &'a RefCell<FnvHashMap<Ty<'tcx>, Type>> {
&self.local.llsizingtypes
&self.local().llsizingtypes
}
pub fn adt_reprs<'a>(&'a self) -> &'a RefCell<FnvHashMap<Ty<'tcx>, Rc<adt::Repr<'tcx>>>> {
&self.local.adt_reprs
&self.local().adt_reprs
}
pub fn symbol_hasher<'a>(&'a self) -> &'a RefCell<Sha256> {
@ -737,7 +789,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
}
pub fn type_hashcodes<'a>(&'a self) -> &'a RefCell<FnvHashMap<Ty<'tcx>, String>> {
&self.local.type_hashcodes
&self.local().type_hashcodes
}
pub fn stats<'a>(&'a self) -> &'a Stats {
@ -753,43 +805,39 @@ 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<FnvHashMap<Instance<'tcx>, ValueRef>> {
&self.local.closure_vals
&self.local().closure_vals
}
pub fn dbg_cx<'a>(&'a self) -> &'a Option<debuginfo::CrateDebugContext<'tcx>> {
&self.local.dbg_cx
&self.local().dbg_cx
}
pub fn eh_personality<'a>(&'a self) -> &'a Cell<Option<ValueRef>> {
&self.local.eh_personality
&self.local().eh_personality
}
pub fn eh_unwind_resume<'a>(&'a self) -> &'a Cell<Option<ValueRef>> {
&self.local.eh_unwind_resume
&self.local().eh_unwind_resume
}
pub fn rust_try_fn<'a>(&'a self) -> &'a Cell<Option<ValueRef>> {
&self.local.rust_try_fn
&self.local().rust_try_fn
}
fn intrinsics<'a>(&'a self) -> &'a RefCell<FnvHashMap<&'static str, ValueRef>> {
&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);
}
pub fn trait_cache(&self) -> &RefCell<DepTrackingMap<TraitSelectionCache<'tcx>>> {
&self.local.trait_cache
self.local().n_llvm_insns.set(self.local().n_llvm_insns.get() + 1);
}
pub fn obj_size_bound(&self) -> u64 {
@ -803,14 +851,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 {
@ -829,21 +877,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
}
pub fn get_mir(&self, def_id: DefId) -> Option<CachedMir<'b, 'tcx>> {
if def_id.is_local() {
let node_id = self.tcx().map.as_local_node_id(def_id).unwrap();
self.shared.mir_map.map.get(&node_id).map(CachedMir::Ref)
} else {
if let Some(mir) = self.shared.mir_cache.borrow().get(&def_id).cloned() {
return Some(CachedMir::Owned(mir));
}
let mir = self.sess().cstore.maybe_get_item_mir(self.tcx(), def_id);
let cached = mir.map(Rc::new);
if let Some(ref mir) = cached {
self.shared.mir_cache.borrow_mut().insert(def_id, mir.clone());
}
cached.map(CachedMir::Owned)
}
self.shared.get_mir(def_id)
}
pub fn translation_items(&self) -> &RefCell<FnvHashMap<TransItem<'tcx>, TransItemState>> {

View file

@ -510,7 +510,9 @@ fn coerce_unsized<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let source = unpack_datum!(bcx, source.to_ref_datum(bcx));
assert!(target.kind.is_by_ref());
let kind = custom_coerce_unsize_info(bcx.ccx(), source.ty, target.ty);
let kind = custom_coerce_unsize_info(bcx.ccx().shared(),
source.ty,
target.ty);
let repr_source = adt::represent_type(bcx.ccx(), source.ty);
let src_fields = match &*repr_source {

View file

@ -19,7 +19,7 @@ use llvm;
use llvm::{ValueRef, get_param};
use middle::lang_items::ExchangeFreeFnLangItem;
use rustc::ty::subst::{Substs};
use rustc::traits;
use rustc::{infer, traits};
use rustc::ty::{self, Ty, TyCtxt};
use abi::{Abi, FnType};
use adt;
@ -92,13 +92,12 @@ pub fn type_needs_drop<'tcx>(tcx: &TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
tcx.type_needs_drop_given_env(ty, &tcx.empty_parameter_environment())
}
pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
t: Ty<'tcx>) -> Ty<'tcx> {
let tcx = ccx.tcx();
pub fn get_drop_glue_type<'tcx>(tcx: &TyCtxt<'tcx>,
t: Ty<'tcx>) -> Ty<'tcx> {
// Even if there is no dtor for t, there might be one deeper down and we
// might need to pass in the vtable ptr.
if !type_is_sized(tcx, t) {
return ccx.tcx().erase_regions(&t);
return tcx.erase_regions(&t);
}
// FIXME (#22815): note that type_needs_drop conservatively
@ -116,15 +115,18 @@ pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
match t.sty {
ty::TyBox(typ) if !type_needs_drop(&tcx, typ)
&& type_is_sized(tcx, typ) => {
let llty = sizing_type_of(ccx, typ);
// `Box<ZeroSizeType>` does not allocate.
if llsize_of_alloc(ccx, llty) == 0 {
let infcx = infer::normalizing_infer_ctxt(tcx,
&tcx.tables,
traits::ProjectionMode::Any);
let layout = t.layout(&infcx).unwrap();
if layout.size(&tcx.data_layout).bytes() == 0 {
// `Box<ZeroSizeType>` does not allocate.
tcx.types.i8
} else {
ccx.tcx().erase_regions(&t)
tcx.erase_regions(&t)
}
}
_ => ccx.tcx().erase_regions(&t)
_ => tcx.erase_regions(&t)
}
}
@ -154,7 +156,7 @@ pub fn drop_ty_core<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
DropGlueKind::Ty(t)
};
let glue = get_drop_glue_core(ccx, g);
let glue_type = get_drop_glue_type(ccx, t);
let glue_type = get_drop_glue_type(ccx.tcx(), t);
let ptr = if glue_type != t {
PointerCast(bcx, v, type_of(ccx, glue_type).ptr_to())
} else {
@ -231,7 +233,7 @@ impl<'tcx> DropGlueKind<'tcx> {
fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
g: DropGlueKind<'tcx>) -> ValueRef {
debug!("make drop glue for {:?}", g);
let g = g.map_ty(|t| get_drop_glue_type(ccx, t));
let g = g.map_ty(|t| get_drop_glue_type(ccx.tcx(), t));
debug!("drop glue type {:?}", g);
match ccx.drop_glues().borrow().get(&g) {
Some(&glue) => return glue,
@ -364,7 +366,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
def_id: tcx.lang_items.drop_trait().unwrap(),
substs: tcx.mk_substs(Substs::empty().with_self_ty(t))
});
let vtbl = match fulfill_obligation(bcx.ccx(), DUMMY_SP, trait_ref) {
let vtbl = match fulfill_obligation(bcx.ccx().shared(), DUMMY_SP, trait_ref) {
traits::VtableImpl(data) => data,
_ => bug!("dtor for {:?} is not an impl???", t)
};
@ -487,7 +489,7 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, g: DropGlueKind<'tcx>)
-> Block<'blk, 'tcx> {
if collector::collecting_debug_information(bcx.ccx()) {
if collector::collecting_debug_information(bcx.ccx().shared()) {
bcx.ccx()
.record_translation_item_as_generated(TransItem::DropGlue(g));
}

View file

@ -144,7 +144,7 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
// Not in the cache. Build it.
let methods = traits::supertraits(tcx, trait_ref.clone()).flat_map(|trait_ref| {
let vtable = fulfill_obligation(ccx, DUMMY_SP, trait_ref.clone());
let vtable = fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref.clone());
match vtable {
// Should default trait error here?
traits::VtableDefaultImpl(_) |
@ -157,7 +157,7 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
substs,
nested: _ }) => {
let nullptr = C_null(Type::nil(ccx).ptr_to());
get_vtable_methods(ccx, id, substs)
get_vtable_methods(tcx, id, substs)
.into_iter()
.map(|opt_mth| opt_mth.map_or(nullptr, |mth| {
Callee::def(ccx, mth.method.def_id, &mth.substs).reify(ccx).val
@ -215,13 +215,11 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
vtable
}
pub fn get_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
impl_id: DefId,
substs: &'tcx subst::Substs<'tcx>)
-> Vec<Option<ImplMethod<'tcx>>>
pub fn get_vtable_methods<'tcx>(tcx: &TyCtxt<'tcx>,
impl_id: DefId,
substs: &'tcx subst::Substs<'tcx>)
-> Vec<Option<ImplMethod<'tcx>>>
{
let tcx = ccx.tcx();
debug!("get_vtable_methods(impl_id={:?}, substs={:?}", impl_id, substs);
let trt_id = match tcx.impl_trait_ref(impl_id) {
@ -287,7 +285,7 @@ pub fn get_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
// try and trans it, in that case. Issue #23435.
if mth.is_provided {
let predicates = mth.method.predicates.predicates.subst(tcx, &mth.substs);
if !normalize_and_test_predicates(ccx, predicates.into_vec()) {
if !normalize_and_test_predicates(tcx, predicates.into_vec()) {
debug!("get_vtable_methods: predicates do not hold");
return None;
}

View file

@ -136,7 +136,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
return;
}
let drop_fn = glue::get_drop_glue(bcx.ccx(), ty);
let drop_ty = glue::get_drop_glue_type(bcx.ccx(), ty);
let drop_ty = glue::get_drop_glue_type(bcx.tcx(), ty);
let llvalue = if drop_ty != ty {
bcx.pointercast(lvalue.llval, type_of::type_of(bcx.ccx(), drop_ty).ptr_to())
} else {

View file

@ -233,7 +233,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
let trait_id = trait_item.container().id();
let substs = instance.substs;
let trait_ref = ty::Binder(substs.to_trait_ref(ccx.tcx(), trait_id));
let vtable = common::fulfill_obligation(ccx, DUMMY_SP, trait_ref);
let vtable = common::fulfill_obligation(ccx.shared(), DUMMY_SP, trait_ref);
if let traits::VtableImpl(vtable_impl) = vtable {
let name = ccx.tcx().item_name(instance.def);
for ac in ccx.tcx().associated_consts(vtable_impl.impl_def_id) {

View file

@ -256,10 +256,6 @@ fn place_root_translation_items<'tcx, I>(tcx: &TyCtxt<'tcx>,
fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning<'tcx>,
target_cgu_count: usize,
crate_name: &str) {
if target_cgu_count >= initial_partitioning.codegen_units.len() {
return;
}
assert!(target_cgu_count >= 1);
let codegen_units = &mut initial_partitioning.codegen_units;
@ -278,7 +274,22 @@ fn merge_codegen_units<'tcx>(initial_partitioning: &mut PreInliningPartitioning<
}
for (index, cgu) in codegen_units.iter_mut().enumerate() {
cgu.name = token::intern_and_get_ident(&format!("{}.{}", crate_name, index)[..]);
cgu.name = numbered_codegen_unit_name(crate_name, index);
}
// If the initial partitioning contained less than target_cgu_count to begin
// with, we won't have enough codegen units here, so add a empty units until
// we reach the target count
while codegen_units.len() < target_cgu_count {
let index = codegen_units.len();
codegen_units.push(CodegenUnit {
name: numbered_codegen_unit_name(crate_name, index),
items: FnvHashMap()
});
}
fn numbered_codegen_unit_name(crate_name: &str, index: usize) -> InternedString {
token::intern_and_get_ident(&format!("{}.{}", crate_name, index)[..])
}
}