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:
commit
1939b76903
13 changed files with 538 additions and 492 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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>> {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)[..])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue