1
Fork 0

introduce is_foreign_item query

This may seem like overkill, but it's exactly what we want/need for
incremental compilation I think. In particular, while generating code
for some codegen unit X, we can wind up querying about any number of
external items, and we only want to be forced to rebuild X is some of
those changed from a foreign item to otherwise. Factoring this into a
query means we would re-run only if some `false` became `true` (or vice
versa).
This commit is contained in:
Niko Matsakis 2017-04-14 10:51:22 -04:00
parent 1785bca513
commit 8289e5a73e
5 changed files with 30 additions and 10 deletions

View file

@ -88,6 +88,7 @@ pub enum DepNode<D: Clone + Debug> {
// predicates for an item wind up in `ItemSignature`).
AssociatedItems(D),
ItemSignature(D),
IsForeignItem(D),
TypeParamPredicates((D, D)),
SizedConstraint(D),
AdtDestructor(D),
@ -171,6 +172,7 @@ impl<D: Clone + Debug> DepNode<D> {
TransCrateItem,
AssociatedItems,
ItemSignature,
IsForeignItem,
AssociatedItemDefIds,
InherentImpls,
TypeckTables,
@ -221,6 +223,7 @@ impl<D: Clone + Debug> DepNode<D> {
TransInlinedItem(ref d) => op(d).map(TransInlinedItem),
AssociatedItems(ref d) => op(d).map(AssociatedItems),
ItemSignature(ref d) => op(d).map(ItemSignature),
IsForeignItem(ref d) => op(d).map(IsForeignItem),
TypeParamPredicates((ref item, ref param)) => {
Some(TypeParamPredicates((try_opt!(op(item)), try_opt!(op(param)))))
}

View file

@ -380,6 +380,9 @@ define_maps! { <'tcx>
pub adt_destructor: AdtDestructor(DefId) -> Option<ty::Destructor>,
pub adt_sized_constraint: SizedConstraint(DefId) -> Ty<'tcx>,
/// True if this is a foreign item (i.e., linked via `extern { ... }`).
pub is_foreign_item: IsForeignItem(DefId) -> bool,
/// Maps from def-id of a type or region parameter to its
/// (inferred) variance.
pub variances: ItemSignature(DefId) -> Rc<Vec<ty::Variance>>,

View file

@ -111,6 +111,7 @@ provide! { <'tcx> tcx, def_id, cdata
closure_kind => { cdata.closure_kind(def_id.index) }
closure_type => { cdata.closure_ty(def_id.index, tcx) }
inherent_impls => { Rc::new(cdata.get_inherent_implementations_for_type(def_id.index)) }
is_foreign_item => { cdata.is_foreign_item(def_id.index) }
}
impl CrateStore for cstore::CStore {

View file

@ -14,18 +14,18 @@
//! and methods are represented as just a fn ptr and not a full
//! closure.
use llvm::{self, ValueRef};
use rustc::hir::def_id::DefId;
use rustc::ty::subst::Substs;
use attributes;
use common::{self, CrateContext};
use monomorphize;
use consts;
use declare;
use monomorphize::Instance;
use llvm::{self, ValueRef};
use monomorphize::{self, Instance};
use rustc::hir::def_id::DefId;
use rustc::ty::{self, TypeFoldable};
use rustc::ty::subst::Substs;
use syntax_pos::DUMMY_SP;
use trans_item::TransItem;
use type_of;
use rustc::ty::TypeFoldable;
/// Translates a reference to a fn/method item, monomorphizing and
/// inlining as it goes.
@ -102,15 +102,17 @@ pub fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
let attrs = instance.def.attrs(ccx.tcx());
attributes::from_fn_attrs(ccx, &attrs, llfn);
let is_local_def = ccx.shared().translation_items().borrow()
.contains(&TransItem::Fn(instance));
if is_local_def {
// FIXME(eddyb) Doubt all extern fn should allow unwinding.
// Perhaps questionable, but we assume that anything defined
// *in Rust code* may unwind. Foreign items like `extern "C" {
// fn foo(); }` are assumed not to unwind **unless** they have
// a `#[unwind]` attribute.
if !ty::queries::is_foreign_item::get(tcx, DUMMY_SP, instance.def_id()) {
attributes::unwind(llfn, true);
unsafe {
llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::ExternalLinkage);
}
}
if ccx.use_dll_storage_attrs() &&
ccx.sess().cstore.is_dllimport_foreign_item(instance.def_id())
{

View file

@ -99,6 +99,7 @@ pub fn provide(providers: &mut Providers) {
trait_def,
adt_def,
impl_trait_ref,
is_foreign_item,
..*providers
};
}
@ -1530,3 +1531,13 @@ fn compute_type_of_foreign_fn_decl<'a, 'tcx>(
let substs = Substs::identity_for_item(tcx, def_id);
tcx.mk_fn_def(def_id, substs, fty)
}
fn is_foreign_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
-> bool {
match tcx.hir.get_if_local(def_id) {
Some(hir_map::NodeForeignItem(..)) => true,
Some(_) => false,
_ => bug!("is_foreign_item applied to non-local def-id {:?}", def_id)
}
}