RootInlinedParent(parent) => match *parent {
InlinedItem::Item(def_id, _) |
InlinedItem::TraitItem(def_id, _) |
- InlinedItem::ImplItem(def_id, _) |
- InlinedItem::Foreign(def_id, _) =>
+ InlinedItem::ImplItem(def_id, _) =>
return DepNode::MetaData(def_id)
},
II::ImplItem(fld.fold_ops.new_def_id(d),
ii.map(|ii| fld.fold_impl_item(ii)))
}
- II::Foreign(d, i) => II::Foreign(fld.fold_ops.new_def_id(d),
- i.map(|i| fld.fold_foreign_item(i)))
};
let ii = map.forest.inlined_items.alloc(ii);
pub enum InlinedItem {
Item(DefId /* def-id in source crate */, P<hir::Item>),
TraitItem(DefId /* impl id */, P<hir::TraitItem>),
- ImplItem(DefId /* impl id */, P<hir::ImplItem>),
- Foreign(DefId /* extern item */, P<hir::ForeignItem>),
+ ImplItem(DefId /* impl id */, P<hir::ImplItem>)
}
/// A borrowed version of `hir::InlinedItem`.
pub enum InlinedItemRef<'a> {
Item(DefId, &'a hir::Item),
TraitItem(DefId, &'a hir::TraitItem),
- ImplItem(DefId, &'a hir::ImplItem),
- Foreign(DefId, &'a hir::ForeignItem)
+ ImplItem(DefId, &'a hir::ImplItem)
}
/// Item definitions in the currently-compiled crate would have the CrateNum
{
match *self {
InlinedItem::Item(_, ref i) => visitor.visit_item(&i),
- InlinedItem::Foreign(_, ref i) => visitor.visit_foreign_item(&i),
InlinedItem::TraitItem(_, ref ti) => visitor.visit_trait_item(ti),
InlinedItem::ImplItem(_, ref ii) => visitor.visit_impl_item(ii),
}
ii: InlinedItemRef) {
let id = match ii {
InlinedItemRef::Item(_, i) => i.id,
- InlinedItemRef::Foreign(_, i) => i.id,
InlinedItemRef::TraitItem(_, ti) => ti.id,
InlinedItemRef::ImplItem(_, ii) => ii.id,
};
dcx);
let name = match *ii {
InlinedItem::Item(_, ref i) => i.name,
- InlinedItem::Foreign(_, ref i) => i.name,
InlinedItem::TraitItem(_, ref ti) => ti.name,
InlinedItem::ImplItem(_, ref ii) => ii.name
};
InlinedItemRef::ImplItem(d, ii) => {
InlinedItem::ImplItem(d, P(fold::noop_fold_impl_item(ii.clone(), &mut fld)))
}
- InlinedItemRef::Foreign(d, i) => {
- InlinedItem::Foreign(d, P(fold::noop_fold_foreign_item(i.clone(), &mut fld)))
- }
};
(ii, fld.id_range)
let item_node_id = match ii {
&InlinedItem::Item(_, ref i) => i.id,
&InlinedItem::TraitItem(_, ref ti) => ti.id,
- &InlinedItem::ImplItem(_, ref ii) => ii.id,
- &InlinedItem::Foreign(_, ref fi) => fi.id
+ &InlinedItem::ImplItem(_, ref ii) => ii.id
};
copy_item_type(dcx, item_node_id, orig_did);
let inlined_root_node_id = find_inlined_item_root(item.id);
cache_inlined_item(def_id, item.id, inlined_root_node_id);
}
- decoder::FoundAst::Found(&InlinedItem::Foreign(d, ref item)) => {
- assert_eq!(d, def_id);
- let inlined_root_node_id = find_inlined_item_root(item.id);
- cache_inlined_item(def_id, item.id, inlined_root_node_id);
- }
decoder::FoundAst::FoundParent(parent_did, item) => {
let inlined_root_node_id = find_inlined_item_root(item.id);
cache_inlined_item(parent_did, item.id, inlined_root_node_id);
use std::io::{Cursor, SeekFrom};
use std::rc::Rc;
use std::u32;
-use syntax::abi::Abi;
use syntax::ast::{self, NodeId, Name, CRATE_NODE_ID, CrateNum};
use syntax::attr::{self,AttrMetaMethods,AttributeMethods};
use errors::Handler;
if body.is_some() {
encode_item_sort(self.rbml_w, 'p');
- encode_inlined_item(ecx,
- self.rbml_w,
- InlinedItemRef::TraitItem(
- trait_def_id,
- trait_item));
self.encode_mir(trait_item.id);
} else {
encode_item_sort(self.rbml_w, 'r');
let types = generics.parent_types as usize + generics.types.len();
let needs_inline = types > 0 || is_default_impl ||
attr::requests_inline(&impl_item.attrs);
- if needs_inline || sig.constness == hir::Constness::Const {
+ if sig.constness == hir::Constness::Const {
encode_inlined_item(
ecx,
self.rbml_w,
InlinedItemRef::ImplItem(ecx.tcx.map.local_def_id(parent_id),
impl_item));
+ }
+ if needs_inline || sig.constness == hir::Constness::Const {
self.encode_mir(impl_item.id);
}
encode_constness(self.rbml_w, sig.constness);
encode_name(self.rbml_w, item.name);
encode_attributes(self.rbml_w, &item.attrs);
let needs_inline = tps_len > 0 || attr::requests_inline(&item.attrs);
- if needs_inline || constness == hir::Constness::Const {
+ if constness == hir::Constness::Const {
encode_inlined_item(ecx, self.rbml_w, InlinedItemRef::Item(def_id, item));
+ }
+ if needs_inline || constness == hir::Constness::Const {
self.encode_mir(item.id);
}
encode_constness(self.rbml_w, constness);
for v in &enum_definition.variants {
encode_variant_id(self.rbml_w, ecx.tcx.map.local_def_id(v.node.data.id()));
}
- encode_inlined_item(ecx, self.rbml_w, InlinedItemRef::Item(def_id, item));
- self.encode_mir(item.id);
// Encode inherent implementations for self enumeration.
encode_inherent_implementations(ecx, self.rbml_w, def_id);
needs to know*/
self.encode_struct_fields(variant);
- encode_inlined_item(ecx, self.rbml_w, InlinedItemRef::Item(def_id, item));
- self.encode_mir(item.id);
-
// Encode inherent implementations for self structure.
encode_inherent_implementations(ecx, self.rbml_w, def_id);
let ecx = self.ecx();
debug!("writing foreign item {}", ecx.tcx.node_path_str(nitem.id));
- let abi = ecx.tcx.map.get_foreign_abi(nitem.id);
encode_def_id_and_key(ecx, self.rbml_w, def_id);
let parent_id = ecx.tcx.map.get_parent(nitem.id);
encode_family(self.rbml_w, FN_FAMILY);
self.encode_bounds_and_type_for_item(nitem.id);
encode_name(self.rbml_w, nitem.name);
- if abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic {
- encode_inlined_item(ecx,
- self.rbml_w,
- InlinedItemRef::Foreign(def_id, nitem));
- self.encode_mir(nitem.id);
- }
encode_attributes(self.rbml_w, &nitem.attrs);
let stab = ecx.tcx.lookup_stability(ecx.tcx.map.local_def_id(nitem.id));
let depr = ecx.tcx.lookup_deprecation(ecx.tcx.map.local_def_id(nitem.id));
use context::{SharedCrateContext, CrateContextList};
use debuginfo::{self, DebugLoc};
use declare;
-use inline;
use machine;
use machine::{llalign_of_min, llsize_of};
use meth;
false
};
- let debug_context = if let (false, Some((instance, sig, abi))) = (no_debug, definition) {
- debuginfo::create_function_debug_context(ccx, instance, sig, abi, llfndecl)
+ let mir = def_id.and_then(|id| ccx.get_mir(id));
+
+ let debug_context = if let (false, Some((instance, sig, abi)), &Some(ref mir)) =
+ (no_debug, definition, &mir) {
+ debuginfo::create_function_debug_context(ccx, instance, sig, abi, llfndecl, mir)
} else {
debuginfo::empty_function_debug_context(ccx)
};
FunctionContext {
- mir: def_id.and_then(|id| ccx.get_mir(id)),
+ mir: mir,
llfn: llfndecl,
llretslotptr: Cell::new(None),
param_env: ccx.tcx().empty_parameter_environment(),
let sig = ccx.tcx().normalize_associated_type(&sig);
let abi = fn_ty.fn_abi();
- let local_instance = inline::maybe_inline_instance(ccx, instance);
- let lldecl = match ccx.instances().borrow().get(&local_instance) {
+ let lldecl = match ccx.instances().borrow().get(&instance) {
Some(&val) => val,
None => bug!("Instance `{:?}` not already declared", instance)
};
}
pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
- ctor_id: ast::NodeId,
+ def_id: DefId,
+ substs: &'tcx Substs<'tcx>,
disr: Disr,
- param_substs: &'tcx Substs<'tcx>,
llfndecl: ValueRef) {
- let ctor_ty = ccx.tcx().node_id_to_type(ctor_id);
- let ctor_ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &ctor_ty);
+ attributes::inline(llfndecl, attributes::InlineAttr::Hint);
+ attributes::set_frame_pointer_elimination(ccx, llfndecl);
+
+ let ctor_ty = ccx.tcx().lookup_item_type(def_id).ty;
+ let ctor_ty = monomorphize::apply_param_substs(ccx.tcx(), substs, &ctor_ty);
let sig = ccx.tcx().erase_late_bound_regions(&ctor_ty.fn_sig());
let sig = ccx.tcx().normalize_associated_type(&sig);
println!("n_null_glues: {}", stats.n_null_glues.get());
println!("n_real_glues: {}", stats.n_real_glues.get());
- println!("n_fallback_instantiations: {}", stats.n_fallback_instantiations.get());
-
println!("n_fns: {}", stats.n_fns.get());
- println!("n_monos: {}", stats.n_monos.get());
println!("n_inlines: {}", stats.n_inlines.get());
println!("n_closures: {}", stats.n_closures.get());
println!("fn stats:");
use arena::TypedArena;
use back::symbol_names;
-use llvm::{ValueRef, get_params};
-use middle::cstore::LOCAL_CRATE;
+use llvm::{self, ValueRef, get_params};
use rustc::hir::def_id::DefId;
use rustc::ty::subst::Substs;
use rustc::traits;
-use rustc::hir::map as hir_map;
use abi::{Abi, FnType};
use attributes;
use base;
use consts;
use debuginfo::DebugLoc;
use declare;
-use inline;
use meth;
use monomorphize::{self, Instance};
use trans_item::TransItem;
use type_of;
-use value::Value;
use Disr;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::hir;
use syntax_pos::DUMMY_SP;
-use errors;
#[derive(Debug)]
pub enum CalleeData {
return Callee::trait_method(ccx, trait_id, def_id, substs);
}
- let maybe_node_id = inline::get_local_instance(ccx, def_id)
- .and_then(|def_id| tcx.map.as_local_node_id(def_id));
- let maybe_ast_node = maybe_node_id.and_then(|node_id| {
- tcx.map.find(node_id)
- });
-
- let data = match maybe_ast_node {
- Some(hir_map::NodeStructCtor(_)) => {
- NamedTupleConstructor(Disr(0))
- }
- Some(hir_map::NodeVariant(_)) => {
- let vinfo = common::inlined_variant_def(ccx, maybe_node_id.unwrap());
- NamedTupleConstructor(Disr::from(vinfo.disr_val))
- }
- Some(hir_map::NodeForeignItem(fi)) if {
- let abi = tcx.map.get_foreign_abi(fi.id);
- abi == Abi::RustIntrinsic || abi == Abi::PlatformIntrinsic
- } => Intrinsic,
-
- _ => {
- let (llfn, ty) = get_fn(ccx, def_id, substs);
- return Callee::ptr(llfn, ty);
+ let fn_ty = def_ty(tcx, def_id, substs);
+ if let ty::TyFnDef(_, _, f) = fn_ty.sty {
+ if f.abi == Abi::RustIntrinsic || f.abi == Abi::PlatformIntrinsic {
+ return Callee {
+ data: Intrinsic,
+ ty: fn_ty
+ };
}
- };
+ }
- Callee {
- data: data,
- ty: def_ty(tcx, def_id, substs)
+ // FIXME(eddyb) Detect ADT constructors more efficiently.
+ if let Some(adt_def) = fn_ty.fn_ret().skip_binder().ty_adt_def() {
+ if let Some(v) = adt_def.variants.iter().find(|v| def_id == v.did) {
+ return Callee {
+ data: NamedTupleConstructor(Disr::from(v.disr_val)),
+ ty: fn_ty
+ };
+ }
}
+
+ let (llfn, ty) = get_fn(ccx, def_id, substs);
+ Callee::ptr(llfn, ty)
}
/// Trait method, which has to be resolved to an impl method.
trait_closure_kind);
let method_ty = def_ty(tcx, def_id, substs);
- let fn_ptr_ty = match method_ty.sty {
- ty::TyFnDef(_, _, fty) => tcx.mk_fn_ptr(fty),
- _ => bug!("expected fn item type, found {}",
- method_ty)
- };
- Callee::ptr(llfn, fn_ptr_ty)
+ Callee::ptr(llfn, method_ty)
}
traits::VtableFnPointer(vtable_fn_pointer) => {
let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_id).unwrap();
let llfn = trans_fn_pointer_shim(ccx, trait_closure_kind, vtable_fn_pointer.fn_ty);
let method_ty = def_ty(tcx, def_id, substs);
- let fn_ptr_ty = match method_ty.sty {
- ty::TyFnDef(_, _, fty) => tcx.mk_fn_ptr(fty),
- _ => bug!("expected fn item type, found {}",
- method_ty)
- };
- Callee::ptr(llfn, fn_ptr_ty)
+ Callee::ptr(llfn, method_ty)
}
traits::VtableObject(ref data) => {
Callee {
Virtual(idx) => {
meth::trans_object_shim(ccx, self.ty, idx)
}
- NamedTupleConstructor(_) => match self.ty.sty {
+ NamedTupleConstructor(disr) => match self.ty.sty {
ty::TyFnDef(def_id, substs, _) => {
- return get_fn(ccx, def_id, substs).0;
+ let instance = Instance::new(def_id, substs);
+ if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
+ return llfn;
+ }
+
+ let sym = ccx.symbol_map().get_or_compute(ccx.shared(),
+ TransItem::Fn(instance));
+ assert!(!ccx.codegen_unit().contains_item(&TransItem::Fn(instance)));
+ let lldecl = declare::define_internal_fn(ccx, &sym, self.ty);
+ base::trans_ctor_shim(ccx, def_id, substs, disr, lldecl);
+ ccx.instances().borrow_mut().insert(instance, lldecl);
+
+ lldecl
}
_ => bug!("expected fn item type, found {}", self.ty)
},
assert!(!substs.types.needs_infer());
assert!(!substs.types.has_escaping_regions());
+ assert!(!substs.types.has_param_types());
- // Check whether this fn has an inlined copy and, if so, redirect
- // def_id to the local id of the inlined copy.
- let def_id = inline::maybe_instantiate_inline(ccx, def_id);
-
- fn is_named_tuple_constructor(tcx: TyCtxt, def_id: DefId) -> bool {
- let node_id = match tcx.map.as_local_node_id(def_id) {
- Some(n) => n,
- None => { return false; }
- };
- let map_node = errors::expect(
- &tcx.sess.diagnostic(),
- tcx.map.find(node_id),
- || "local item should be in ast map".to_string());
-
- match map_node {
- hir_map::NodeVariant(v) => {
- v.node.data.is_tuple()
- }
- hir_map::NodeStructCtor(_) => true,
- _ => false
- }
- }
- let must_monomorphise =
- !substs.types.is_empty() || is_named_tuple_constructor(tcx, def_id);
-
- debug!("get_fn({:?}) must_monomorphise: {}",
- def_id, must_monomorphise);
-
- // Create a monomorphic version of generic functions
- if must_monomorphise {
- // Should be either intra-crate or inlined.
- assert_eq!(def_id.krate, LOCAL_CRATE);
-
- let substs = tcx.normalize_associated_type(&substs);
- let (val, fn_ty) = monomorphize::monomorphic_fn(ccx, def_id, substs);
- let fn_ptr_ty = match fn_ty.sty {
- ty::TyFnDef(_, _, fty) => {
- // Create a fn pointer with the substituted signature.
- tcx.mk_fn_ptr(fty)
- }
- _ => bug!("expected fn item type, found {}", fn_ty)
- };
- assert_eq!(type_of::type_of(ccx, fn_ptr_ty), common::val_ty(val));
- return (val, fn_ptr_ty);
- }
-
- // Find the actual function pointer.
- let ty = ccx.tcx().lookup_item_type(def_id).ty;
- let fn_ptr_ty = match ty.sty {
- ty::TyFnDef(_, _, ref fty) => {
- // Create a fn pointer with the normalized signature.
- tcx.mk_fn_ptr(tcx.normalize_associated_type(fty))
- }
- _ => bug!("expected fn item type, found {}", ty)
- };
+ let substs = tcx.normalize_associated_type(&substs);
+ let instance = Instance::new(def_id, substs);
+ let item_ty = ccx.tcx().lookup_item_type(def_id).ty;
+ let fn_ty = monomorphize::apply_param_substs(ccx.tcx(), substs, &item_ty);
- let instance = Instance::mono(ccx.shared(), def_id);
if let Some(&llfn) = ccx.instances().borrow().get(&instance) {
- return (llfn, fn_ptr_ty);
+ return (llfn, fn_ty);
}
- let local_id = ccx.tcx().map.as_local_node_id(def_id);
- let local_item = match local_id.and_then(|id| tcx.map.find(id)) {
- Some(hir_map::NodeItem(&hir::Item {
- span, node: hir::ItemFn(..), ..
- })) |
- Some(hir_map::NodeTraitItem(&hir::TraitItem {
- span, node: hir::MethodTraitItem(_, Some(_)), ..
- })) |
- Some(hir_map::NodeImplItem(&hir::ImplItem {
- span, node: hir::ImplItemKind::Method(..), ..
- })) => {
- Some(span)
- }
- _ => None
- };
+ let sym = ccx.symbol_map().get_or_compute(ccx.shared(),
+ TransItem::Fn(instance));
+ debug!("get_fn({:?}: {:?}) => {}", instance, fn_ty, sym);
// This is subtle and surprising, but sometimes we have to bitcast
// the resulting fn pointer. The reason has to do with external
// reference. It also occurs when testing libcore and in some
// other weird situations. Annoying.
- let sym = ccx.symbol_map().get_or_compute(ccx.shared(),
- TransItem::Fn(instance));
-
- let llptrty = type_of::type_of(ccx, fn_ptr_ty);
- let llfn = if let Some(llfn) = declare::get_declared_value(ccx, &sym) {
- if let Some(span) = local_item {
- if declare::get_defined_value(ccx, &sym).is_some() {
- ccx.sess().span_fatal(span,
- &format!("symbol `{}` is already defined", &sym));
- }
+ let fn_ptr_ty = match fn_ty.sty {
+ ty::TyFnDef(_, _, fty) => {
+ // Create a fn pointer with the substituted signature.
+ tcx.mk_fn_ptr(fty)
}
+ _ => bug!("expected fn item type, found {}", fn_ty)
+ };
+ let llptrty = type_of::type_of(ccx, fn_ptr_ty);
+ let llfn = if let Some(llfn) = declare::get_declared_value(ccx, &sym) {
if common::val_ty(llfn) != llptrty {
- if local_item.is_some() {
- bug!("symbol `{}` previously declared as {:?}, now wanted as {:?}",
- sym, Value(llfn), llptrty);
- }
debug!("get_fn: casting {:?} to {:?}", llfn, llptrty);
consts::ptrcast(llfn, llptrty)
} else {
llfn
}
} else {
- let llfn = declare::declare_fn(ccx, &sym, ty);
+ let llfn = declare::declare_fn(ccx, &sym, fn_ty);
assert_eq!(common::val_ty(llfn), llptrty);
debug!("get_fn: not casting pointer!");
let attrs = ccx.tcx().get_attrs(def_id);
attributes::from_fn_attrs(ccx, &attrs, llfn);
- if local_item.is_some() {
+
+ 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.
attributes::unwind(llfn, true);
+ unsafe {
+ llvm::LLVMSetLinkage(llfn, llvm::ExternalLinkage);
+ }
}
llfn
ccx.instances().borrow_mut().insert(instance, llfn);
- (llfn, fn_ptr_ty)
+ (llfn, fn_ty)
}
// ______________________________________________________________________
use Disr;
-#[derive(Copy, Clone)]
-pub struct NodeIdAndSpan {
- pub id: ast::NodeId,
- pub span: Span,
-}
-
/// The concrete version of ty::FieldDef. The name is the field index if
/// the field is numeric.
pub struct Field<'tcx>(pub ast::Name, pub Ty<'tcx>);
}
}
-/// Return the VariantDef corresponding to an inlined variant node
-pub fn inlined_variant_def<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
- inlined_vid: ast::NodeId)
- -> ty::VariantDef<'tcx>
-{
- let ctor_ty = ccx.tcx().node_id_to_type(inlined_vid);
- debug!("inlined_variant_def: ctor_ty={:?} inlined_vid={:?}", ctor_ty,
- inlined_vid);
- let adt_def = match ctor_ty.sty {
- ty::TyFnDef(_, _, &ty::BareFnTy { sig: ty::Binder(ty::FnSig {
- output, ..
- }), ..}) => output,
- _ => ctor_ty
- }.ty_adt_def().unwrap();
- let variant_def_id = if ccx.tcx().map.is_inlined_node_id(inlined_vid) {
- ccx.defid_for_inlined_node(inlined_vid).unwrap()
- } else {
- ccx.tcx().map.local_def_id(inlined_vid)
- };
-
- adt_def.variants
- .iter()
- .find(|v| variant_def_id == v.did)
- .unwrap_or_else(|| {
- bug!("no variant for {:?}::{}", adt_def, inlined_vid)
- })
-}
-
// To avoid UB from LLVM, these two functions mask RHS with an
// appropriate mask unconditionally (i.e. the fallback behavior for
// all shifts). For 32- and 64-bit types, this matches the semantics
let defined_in_current_codegen_unit = ccx.codegen_unit()
.items()
.contains_key(&TransItem::Static(id));
- if defined_in_current_codegen_unit {
- if declare::get_declared_value(ccx, sym).is_none() {
- span_bug!(span, "trans: Static not properly pre-defined?");
- }
- } else {
- if declare::get_declared_value(ccx, sym).is_some() {
- span_bug!(span, "trans: Conflicting symbol names for static?");
- }
+ assert!(!defined_in_current_codegen_unit);
+
+ if declare::get_declared_value(ccx, sym).is_some() {
+ span_bug!(span, "trans: Conflicting symbol names for static?");
}
let g = declare::define_global(ccx, sym, llty).unwrap();
pub n_glues_created: Cell<usize>,
pub n_null_glues: Cell<usize>,
pub n_real_glues: Cell<usize>,
- pub n_fallback_instantiations: Cell<usize>,
pub n_fns: Cell<usize>,
- pub n_monos: Cell<usize>,
pub n_inlines: Cell<usize>,
pub n_closures: Cell<usize>,
pub n_llvm_insns: Cell<usize>,
drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, (ValueRef, FnType)>>,
/// Cache instances of monomorphic and polymorphic items
instances: RefCell<FnvHashMap<Instance<'tcx>, ValueRef>>,
- monomorphizing: RefCell<DefIdMap<usize>>,
/// Cache generated vtables
vtables: RefCell<FnvHashMap<ty::PolyTraitRef<'tcx>, ValueRef>>,
/// Cache of constant strings,
n_glues_created: Cell::new(0),
n_null_glues: Cell::new(0),
n_real_glues: Cell::new(0),
- n_fallback_instantiations: Cell::new(0),
n_fns: Cell::new(0),
- n_monos: Cell::new(0),
n_inlines: Cell::new(0),
n_closures: Cell::new(0),
n_llvm_insns: Cell::new(0),
fn_pointer_shims: RefCell::new(FnvHashMap()),
drop_glues: RefCell::new(FnvHashMap()),
instances: RefCell::new(FnvHashMap()),
- monomorphizing: RefCell::new(DefIdMap()),
vtables: RefCell::new(FnvHashMap()),
const_cstr_cache: RefCell::new(FnvHashMap()),
const_unsized: RefCell::new(FnvHashMap()),
&self.local().instances
}
- pub fn monomorphizing<'a>(&'a self) -> &'a RefCell<DefIdMap<usize>> {
- &self.local().monomorphizing
- }
-
pub fn vtables<'a>(&'a self) -> &'a RefCell<FnvHashMap<ty::PolyTraitRef<'tcx>, ValueRef>> {
&self.local().vtables
}
use rustc::ty::subst::Substs;
use rustc::hir;
use {type_of, adt, machine, monomorphize};
-use common::{CrateContext, FunctionContext};
+use common::CrateContext;
use type_::Type;
use rustc::ty::{self, Ty};
use session::config;
file_metadata
}
-/// Finds the scope metadata node for the given AST node.
-pub fn scope_metadata(fcx: &FunctionContext,
- node_id: ast::NodeId,
- error_reporting_span: Span)
- -> DIScope {
- let scope_map = &fcx.debug_context
- .get_ref(error_reporting_span)
- .scope_map;
- match scope_map.borrow().get(&node_id).cloned() {
- Some(scope_metadata) => scope_metadata,
- None => {
- let node = fcx.ccx.tcx().map.get(node_id);
-
- span_bug!(error_reporting_span,
- "debuginfo: Could not find scope info for node {:?}",
- node);
- }
- }
-}
-
fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
t: Ty<'tcx>) -> DIType {
use rustc::hir::def_id::DefId;
use rustc::hir::map::DefPathData;
use rustc::ty::subst::Substs;
-use rustc::hir;
use abi::Abi;
-use common::{NodeIdAndSpan, CrateContext, FunctionContext, Block, BlockAndBuilder};
-use inline;
+use common::{CrateContext, FunctionContext, Block, BlockAndBuilder};
use monomorphize::{self, Instance};
use rustc::ty::{self, Ty};
+use rustc::mir::repr as mir;
use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
-use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet};
+use util::nodemap::{DefIdMap, FnvHashMap, FnvHashSet};
use libc::c_uint;
use std::cell::{Cell, RefCell};
}
pub struct FunctionDebugContextData {
- scope_map: RefCell<NodeMap<DIScope>>,
fn_metadata: DISubprogram,
source_locations_enabled: Cell<bool>,
source_location_override: Cell<bool>,
instance: Instance<'tcx>,
sig: &ty::FnSig<'tcx>,
abi: Abi,
- llfn: ValueRef) -> FunctionDebugContext {
+ llfn: ValueRef,
+ mir: &mir::Mir) -> FunctionDebugContext {
if cx.sess().opts.debuginfo == NoDebugInfo {
return FunctionDebugContext::DebugInfoDisabled;
}
// Do this here already, in case we do an early exit from this function.
source_loc::set_debug_location(cx, None, UnknownLocation);
- let instance = inline::maybe_inline_instance(cx, instance);
- let (containing_scope, span) = get_containing_scope_and_span(cx, instance);
+ let containing_scope = get_containing_scope(cx, instance);
+ let span = mir.span;
// This can be the case for functions inlined from another crate
if span == syntax_pos::DUMMY_SP {
// Initialize fn debug context (including scope map and namespace map)
let fn_debug_context = box FunctionDebugContextData {
- scope_map: RefCell::new(NodeMap()),
fn_metadata: fn_metadata,
source_locations_enabled: Cell::new(false),
source_location_override: Cell::new(false),
names
}
- fn get_containing_scope_and_span<'ccx, 'tcx>(cx: &CrateContext<'ccx, 'tcx>,
- instance: Instance<'tcx>)
- -> (DIScope, Span) {
+ fn get_containing_scope<'ccx, 'tcx>(cx: &CrateContext<'ccx, 'tcx>,
+ instance: Instance<'tcx>)
+ -> DIScope {
// First, let's see if this is a method within an inherent impl. Because
// if yes, we want to make the result subroutine DIE a child of the
// subroutine's self-type.
}
});
- let containing_scope = self_type.unwrap_or_else(|| {
+ self_type.unwrap_or_else(|| {
namespace::item_namespace(cx, DefId {
krate: instance.def.krate,
index: cx.tcx()
.def_key(instance.def)
.parent
- .expect("get_containing_scope_and_span: missing parent?")
+ .expect("get_containing_scope: missing parent?")
})
- });
-
- // Try to get some span information, if we have an inlined item.
- let definition_span = cx.tcx()
- .map
- .def_id_span(instance.def, syntax_pos::DUMMY_SP);
-
- (containing_scope, definition_span)
+ })
}
}
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum DebugLoc {
- At(ast::NodeId, Span),
ScopeAt(DIScope, Span),
None
}
source_loc::set_source_location(bcx.fcx(), Some(bcx), self);
}
}
-
-pub trait ToDebugLoc {
- fn debug_loc(&self) -> DebugLoc;
-}
-
-impl ToDebugLoc for hir::Expr {
- fn debug_loc(&self) -> DebugLoc {
- DebugLoc::At(self.id, self.span)
- }
-}
-
-impl ToDebugLoc for NodeIdAndSpan {
- fn debug_loc(&self) -> DebugLoc {
- DebugLoc::At(self.id, self.span)
- }
-}
-
-impl ToDebugLoc for Option<NodeIdAndSpan> {
- fn debug_loc(&self) -> DebugLoc {
- match *self {
- Some(NodeIdAndSpan { id, span }) => DebugLoc::At(id, span),
- None => DebugLoc::None
- }
- }
-}
use self::InternalDebugLocation::*;
use super::utils::{debug_context, span_start};
-use super::metadata::{scope_metadata,UNKNOWN_COLUMN_NUMBER};
+use super::metadata::{UNKNOWN_COLUMN_NUMBER};
use super::{FunctionDebugContext, DebugLoc};
use llvm;
let dbg_loc = if function_debug_context.source_locations_enabled.get() {
let (scope, span) = match debug_loc {
- DebugLoc::At(node_id, span) => {
- (scope_metadata(fcx, node_id, span), span)
- }
DebugLoc::ScopeAt(scope, span) => (scope, span),
DebugLoc::None => {
set_debug_location(fcx.ccx, builder, UnknownLocation);
g,
TransItem::DropGlue(g).to_raw_string(),
ccx.codegen_unit().name());
-
- ccx.stats().n_fallback_instantiations.set(ccx.stats()
- .n_fallback_instantiations
- .get() + 1);
}
}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use rustc::hir::def_id::DefId;
-use base::push_ctxt;
-use common::*;
-use monomorphize::Instance;
-
-use rustc::dep_graph::DepNode;
-
-fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> Option<DefId> {
- debug!("instantiate_inline({:?})", fn_id);
- let _icx = push_ctxt("instantiate_inline");
- let tcx = ccx.tcx();
- let _task = tcx.dep_graph.in_task(DepNode::TransInlinedItem(fn_id));
-
- tcx.sess
- .cstore
- .maybe_get_item_ast(tcx, fn_id)
- .map(|(_, inline_id)| {
- tcx.map.local_def_id(inline_id)
- })
-}
-
-pub fn get_local_instance(ccx: &CrateContext, fn_id: DefId)
- -> Option<DefId> {
- if let Some(_) = ccx.tcx().map.as_local_node_id(fn_id) {
- Some(fn_id)
- } else {
- instantiate_inline(ccx, fn_id)
- }
-}
-
-pub fn maybe_instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> DefId {
- get_local_instance(ccx, fn_id).unwrap_or(fn_id)
-}
-
-pub fn maybe_inline_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
- instance: Instance<'tcx>) -> Instance<'tcx> {
- let def_id = maybe_instantiate_inline(ccx, instance.def);
- Instance {
- def: def_id,
- substs: instance.substs
- }
-}
let name = tcx.item_name(def_id).as_str();
let span = match call_debug_location {
- DebugLoc::At(_, span) | DebugLoc::ScopeAt(_, span) => span,
+ DebugLoc::ScopeAt(_, span) => span,
DebugLoc::None => {
span_bug!(fcx.span.unwrap_or(DUMMY_SP),
"intrinsic `{}` called with missing span", name);
mod declare;
mod disr;
mod glue;
-mod inline;
mod intrinsic;
mod machine;
mod meth;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use llvm::ValueRef;
-use llvm;
use rustc::hir::def_id::DefId;
use rustc::infer::TransNormalize;
use rustc::ty::subst::{Subst, Substs};
-use rustc::ty::{self, Ty, TypeFoldable, TyCtxt};
-use attributes;
-use base::{push_ctxt};
-use base;
+use rustc::ty::{self, Ty, TyCtxt};
use common::*;
-use declare;
-use Disr;
-use rustc::hir::map as hir_map;
use rustc::util::ppaux;
-use rustc::hir;
-
-use errors;
-
use std::fmt;
-use trans_item::TransItem;
-
-pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
- fn_id: DefId,
- psubsts: &'tcx Substs<'tcx>)
- -> (ValueRef, Ty<'tcx>) {
- debug!("monomorphic_fn(fn_id={:?}, real_substs={:?})", fn_id, psubsts);
- assert!(!psubsts.types.needs_infer() && !psubsts.types.has_param_types());
-
- let _icx = push_ctxt("monomorphic_fn");
-
- let instance = Instance::new(fn_id, psubsts);
-
- let item_ty = ccx.tcx().lookup_item_type(fn_id).ty;
-
- debug!("monomorphic_fn about to subst into {:?}", item_ty);
- let mono_ty = apply_param_substs(ccx.tcx(), psubsts, &item_ty);
- debug!("mono_ty = {:?} (post-substitution)", mono_ty);
-
- if let Some(&val) = ccx.instances().borrow().get(&instance) {
- debug!("leaving monomorphic fn {:?}", instance);
- return (val, mono_ty);
- } else {
- assert!(!ccx.codegen_unit().contains_item(&TransItem::Fn(instance)));
- }
-
- debug!("monomorphic_fn({:?})", instance);
-
- ccx.stats().n_monos.set(ccx.stats().n_monos.get() + 1);
-
- let depth;
- {
- let mut monomorphizing = ccx.monomorphizing().borrow_mut();
- depth = match monomorphizing.get(&fn_id) {
- Some(&d) => d, None => 0
- };
-
- debug!("monomorphic_fn: depth for fn_id={:?} is {:?}", fn_id, depth+1);
-
- // Random cut-off -- code that needs to instantiate the same function
- // recursively more than thirty times can probably safely be assumed
- // to be causing an infinite expansion.
- if depth > ccx.sess().recursion_limit.get() {
- let error = format!("reached the recursion limit while instantiating `{}`",
- instance);
- if let Some(id) = ccx.tcx().map.as_local_node_id(fn_id) {
- ccx.sess().span_fatal(ccx.tcx().map.span(id), &error);
- } else {
- ccx.sess().fatal(&error);
- }
- }
-
- monomorphizing.insert(fn_id, depth + 1);
- }
-
- let symbol = ccx.symbol_map().get_or_compute(ccx.shared(),
- TransItem::Fn(instance));
-
- debug!("monomorphize_fn mangled to {}", &symbol);
- assert!(declare::get_defined_value(ccx, &symbol).is_none());
-
- // FIXME(nagisa): perhaps needs a more fine grained selection?
- let lldecl = declare::define_internal_fn(ccx, &symbol, mono_ty);
- // FIXME(eddyb) Doubt all extern fn should allow unwinding.
- attributes::unwind(lldecl, true);
-
- ccx.instances().borrow_mut().insert(instance, lldecl);
-
- // we can only monomorphize things in this crate (or inlined into it)
- let fn_node_id = ccx.tcx().map.as_local_node_id(fn_id).unwrap();
- let map_node = errors::expect(
- ccx.sess().diagnostic(),
- ccx.tcx().map.find(fn_node_id),
- || {
- format!("while instantiating `{}`, couldn't find it in \
- the item map (may have attempted to monomorphize \
- an item defined in a different crate?)",
- instance)
- });
- match map_node {
- hir_map::NodeItem(&hir::Item {
- ref attrs,
- node: hir::ItemFn(..), ..
- }) |
- hir_map::NodeImplItem(&hir::ImplItem {
- ref attrs, node: hir::ImplItemKind::Method(
- hir::MethodSig { .. }, _), ..
- }) |
- hir_map::NodeTraitItem(&hir::TraitItem {
- ref attrs, node: hir::MethodTraitItem(
- hir::MethodSig { .. }, Some(_)), ..
- }) => {
- let trans_item = TransItem::Fn(instance);
-
- if ccx.shared().translation_items().borrow().contains(&trans_item) {
- attributes::from_fn_attrs(ccx, attrs, lldecl);
- unsafe {
- llvm::LLVMSetLinkage(lldecl, llvm::ExternalLinkage);
- }
- } else {
- // FIXME: #34151
- // Normally, getting here would indicate a bug in trans::collector,
- // since it seems to have missed a translation item. When we are
- // translating with non-MIR based trans, however, the results of
- // the collector are not entirely reliable since it bases its
- // analysis on MIR. Thus, we'll instantiate the missing function
- // privately in this codegen unit, so that things keep working.
- ccx.stats().n_fallback_instantiations.set(ccx.stats()
- .n_fallback_instantiations
- .get() + 1);
- trans_item.predefine(ccx, llvm::InternalLinkage);
- trans_item.define(ccx);
- }
- }
-
- hir_map::NodeVariant(_) | hir_map::NodeStructCtor(_) => {
- let disr = match map_node {
- hir_map::NodeVariant(_) => {
- Disr::from(inlined_variant_def(ccx, fn_node_id).disr_val)
- }
- hir_map::NodeStructCtor(_) => Disr(0),
- _ => bug!()
- };
- attributes::inline(lldecl, attributes::InlineAttr::Hint);
- attributes::set_frame_pointer_elimination(ccx, lldecl);
- base::trans_ctor_shim(ccx, fn_node_id, disr, psubsts, lldecl);
- }
-
- _ => bug!("can't monomorphize a {:?}", map_node)
- };
-
- ccx.monomorphizing().borrow_mut().insert(fn_id, depth);
-
- debug!("leaving monomorphic fn {}", ccx.tcx().item_path_str(fn_id));
- (lldecl, mono_ty)
-}
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct Instance<'tcx> {
use glue::DropGlueKind;
use llvm;
use monomorphize::{self, Instance};
-use inline;
use rustc::dep_graph::DepNode;
use rustc::hir;
-use rustc::hir::map as hir_map;
use rustc::hir::def_id::DefId;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::ty::subst::Substs;
use rustc_const_eval::fatal_const_eval_err;
use std::hash::{Hash, Hasher};
use syntax::ast::{self, NodeId};
-use syntax::{attr,errors};
+use syntax::attr;
use type_of;
use glue;
use abi::{Abi, FnType};
let ty = ccx.tcx().lookup_item_type(def_id).ty;
let llty = type_of::type_of(ccx, ty);
- match ccx.tcx().map.get(node_id) {
- hir::map::NodeItem(&hir::Item {
- span, node: hir::ItemStatic(..), ..
- }) => {
- let g = declare::define_global(ccx, symbol_name, llty).unwrap_or_else(|| {
- ccx.sess().span_fatal(span,
- &format!("symbol `{}` is already defined", symbol_name))
- });
+ let g = declare::define_global(ccx, symbol_name, llty).unwrap_or_else(|| {
+ ccx.sess().span_fatal(ccx.tcx().map.span(node_id),
+ &format!("symbol `{}` is already defined", symbol_name))
+ });
- unsafe { llvm::LLVMSetLinkage(g, linkage) };
- }
+ unsafe { llvm::LLVMSetLinkage(g, linkage) };
- item => bug!("predefine_static: expected static, found {:?}", item)
- }
+ let instance = Instance::mono(ccx.shared(), def_id);
+ ccx.instances().borrow_mut().insert(instance, g);
+ ccx.statics().borrow_mut().insert(g, def_id);
}
fn predefine_fn(ccx: &CrateContext<'a, 'tcx>,
assert!(!instance.substs.types.needs_infer() &&
!instance.substs.types.has_param_types());
- let instance = inline::maybe_inline_instance(ccx, instance);
-
let item_ty = ccx.tcx().lookup_item_type(instance.def).ty;
let item_ty = ccx.tcx().erase_regions(&item_ty);
let mono_ty = monomorphize::apply_param_substs(ccx.tcx(), instance.substs, &item_ty);
- let fn_node_id = ccx.tcx().map.as_local_node_id(instance.def).unwrap();
- let map_node = errors::expect(
- ccx.sess().diagnostic(),
- ccx.tcx().map.find(fn_node_id),
- || {
- format!("while instantiating `{}`, couldn't find it in \
- the item map (may have attempted to monomorphize \
- an item defined in a different crate?)",
- instance)
- });
-
- match map_node {
- hir_map::NodeItem(&hir::Item {
- ref attrs, node: hir::ItemFn(..), ..
- }) |
- hir_map::NodeTraitItem(&hir::TraitItem {
- ref attrs, node: hir::MethodTraitItem(..), ..
- }) |
- hir_map::NodeImplItem(&hir::ImplItem {
- ref attrs, node: hir::ImplItemKind::Method(..), ..
- }) => {
- let lldecl = declare::declare_fn(ccx, symbol_name, mono_ty);
- unsafe { llvm::LLVMSetLinkage(lldecl, linkage) };
- base::set_link_section(ccx, lldecl, attrs);
- if linkage == llvm::LinkOnceODRLinkage ||
- linkage == llvm::WeakODRLinkage {
- llvm::SetUniqueComdat(ccx.llmod(), lldecl);
- }
+ let attrs = ccx.tcx().get_attrs(instance.def);
+ let lldecl = declare::declare_fn(ccx, symbol_name, mono_ty);
+ unsafe { llvm::LLVMSetLinkage(lldecl, linkage) };
+ base::set_link_section(ccx, lldecl, &attrs);
+ if linkage == llvm::LinkOnceODRLinkage ||
+ linkage == llvm::WeakODRLinkage {
+ llvm::SetUniqueComdat(ccx.llmod(), lldecl);
+ }
- attributes::from_fn_attrs(ccx, attrs, lldecl);
- ccx.instances().borrow_mut().insert(instance, lldecl);
- }
- _ => bug!("Invalid item for TransItem::Fn: `{:?}`", map_node)
- };
+ attributes::from_fn_attrs(ccx, &attrs, lldecl);
+ ccx.instances().borrow_mut().insert(instance, lldecl);
}
fn predefine_drop_glue(ccx: &CrateContext<'a, 'tcx>,