Drive function item translation from collector
Functions and method are declared ahead-of-time, including generic ones. Closures are not considered trans items anymore, instead they are translated on demands.
This commit is contained in:
parent
891c2a082f
commit
6717106947
|
@ -75,6 +75,7 @@ use debuginfo::{self, DebugLoc, ToDebugLoc};
|
|||
use declare;
|
||||
use expr;
|
||||
use glue;
|
||||
use inline;
|
||||
use machine;
|
||||
use machine::{llalign_of_min, llsize_of, llsize_of_real};
|
||||
use meth;
|
||||
|
@ -1948,6 +1949,49 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
closure::ClosureEnv::NotClosure);
|
||||
}
|
||||
|
||||
pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance<'tcx>) {
|
||||
let instance = inline::maybe_inline_instance(ccx, instance);
|
||||
|
||||
let fn_node_id = ccx.tcx().map.as_local_node_id(instance.def).unwrap();
|
||||
|
||||
let _s = StatRecorder::new(ccx, ccx.tcx().node_path_str(fn_node_id));
|
||||
debug!("trans_instance(instance={:?})", instance);
|
||||
let _icx = push_ctxt("trans_instance");
|
||||
|
||||
let item = ccx.tcx().map.find(fn_node_id).unwrap();
|
||||
|
||||
let fn_ty = ccx.tcx().lookup_item_type(instance.def).ty;
|
||||
let fn_ty = ccx.tcx().erase_regions(&fn_ty);
|
||||
let fn_ty = monomorphize::apply_param_substs(ccx.tcx(), instance.substs, &fn_ty);
|
||||
|
||||
let sig = ccx.tcx().erase_late_bound_regions(fn_ty.fn_sig());
|
||||
let sig = ccx.tcx().normalize_associated_type(&sig);
|
||||
let abi = fn_ty.fn_abi();
|
||||
|
||||
let lldecl = match ccx.instances().borrow().get(&instance) {
|
||||
Some(&val) => val,
|
||||
None => bug!("Instance `{:?}` not already declared", instance)
|
||||
};
|
||||
|
||||
match item {
|
||||
hir_map::NodeItem(&hir::Item {
|
||||
node: hir::ItemFn(ref decl, _, _, _, _, ref body), ..
|
||||
}) |
|
||||
hir_map::NodeTraitItem(&hir::TraitItem {
|
||||
node: hir::MethodTraitItem(
|
||||
hir::MethodSig { ref decl, .. }, Some(ref body)), ..
|
||||
}) |
|
||||
hir_map::NodeImplItem(&hir::ImplItem {
|
||||
node: hir::ImplItemKind::Method(
|
||||
hir::MethodSig { ref decl, .. }, ref body), ..
|
||||
}) => {
|
||||
trans_closure(ccx, decl, body, lldecl, instance,
|
||||
fn_node_id, &sig, abi, closure::ClosureEnv::NotClosure);
|
||||
}
|
||||
_ => bug!("Instance is a {:?}?", item)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||
ctor_ty: Ty<'tcx>,
|
||||
disr: Disr,
|
||||
|
@ -2267,70 +2311,23 @@ pub fn trans_item(ccx: &CrateContext, item: &hir::Item) {
|
|||
let _icx = push_ctxt("trans_item");
|
||||
|
||||
let tcx = ccx.tcx();
|
||||
let from_external = ccx.external_srcs().borrow().contains_key(&item.id);
|
||||
|
||||
match item.node {
|
||||
hir::ItemFn(ref decl, _, _, _, ref generics, ref body) => {
|
||||
if !generics.is_type_parameterized() {
|
||||
let trans_everywhere = attr::requests_inline(&item.attrs);
|
||||
// Ignore `trans_everywhere` for cross-crate inlined items
|
||||
// (`from_external`). `trans_item` will be called once for each
|
||||
// compilation unit that references the item, so it will still get
|
||||
// translated everywhere it's needed.
|
||||
for (ref ccx, is_origin) in ccx.maybe_iter(!from_external && trans_everywhere) {
|
||||
hir::ItemFn(_, _, _, _, _, _) => {
|
||||
let def_id = tcx.map.local_def_id(item.id);
|
||||
let empty_substs = ccx.empty_substs_for_def_id(def_id);
|
||||
let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
|
||||
trans_fn(ccx, &decl, &body, llfn, empty_substs, item.id);
|
||||
set_link_section(ccx, llfn, &item.attrs);
|
||||
update_linkage(ccx,
|
||||
llfn,
|
||||
Some(item.id),
|
||||
if is_origin {
|
||||
OriginalTranslation
|
||||
} else {
|
||||
InlinedCopy
|
||||
});
|
||||
|
||||
if is_entry_fn(ccx.sess(), item.id) {
|
||||
create_entry_wrapper(ccx, item.span, llfn);
|
||||
// check for the #[rustc_error] annotation, which forces an
|
||||
// error in trans. This is used to write compile-fail tests
|
||||
// that actually test that compilation succeeds without
|
||||
// reporting an error.
|
||||
if is_entry_fn(ccx.sess(), item.id) {
|
||||
let empty_substs = ccx.empty_substs_for_def_id(def_id);
|
||||
let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
|
||||
create_entry_wrapper(ccx, item.span, llfn);
|
||||
if tcx.has_attr(def_id, "rustc_error") {
|
||||
tcx.sess.span_fatal(item.span, "compilation successful");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
hir::ItemImpl(_, _, ref generics, _, _, ref impl_items) => {
|
||||
// Both here and below with generic methods, be sure to recurse and look for
|
||||
// items that we need to translate.
|
||||
if !generics.ty_params.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
for impl_item in impl_items {
|
||||
if let hir::ImplItemKind::Method(ref sig, ref body) = impl_item.node {
|
||||
if sig.generics.ty_params.is_empty() {
|
||||
let trans_everywhere = attr::requests_inline(&impl_item.attrs);
|
||||
for (ref ccx, is_origin) in ccx.maybe_iter(trans_everywhere) {
|
||||
let def_id = tcx.map.local_def_id(impl_item.id);
|
||||
let empty_substs = ccx.empty_substs_for_def_id(def_id);
|
||||
let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
|
||||
trans_fn(ccx, &sig.decl, body, llfn, empty_substs, impl_item.id);
|
||||
update_linkage(ccx, llfn, Some(impl_item.id),
|
||||
if is_origin {
|
||||
OriginalTranslation
|
||||
} else {
|
||||
InlinedCopy
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Function is actually translated in trans_instance
|
||||
}
|
||||
hir::ItemEnum(ref enum_definition, ref gens) => {
|
||||
if gens.ty_params.is_empty() {
|
||||
|
@ -2338,8 +2335,9 @@ pub fn trans_item(ccx: &CrateContext, item: &hir::Item) {
|
|||
enum_variant_size_lint(ccx, enum_definition, item.span, item.id);
|
||||
}
|
||||
}
|
||||
hir::ItemImpl(..) |
|
||||
hir::ItemStatic(..) => {
|
||||
// Don't do anything here. Translation of statics has been moved to
|
||||
// Don't do anything here. Translation has been moved to
|
||||
// being "collector-driven".
|
||||
}
|
||||
_ => {}
|
||||
|
@ -2482,17 +2480,17 @@ fn internalize_symbols(cx: &CrateContextList, reachable: &HashSet<&str>) {
|
|||
let linkage = llvm::LLVMGetLinkage(val);
|
||||
// We only care about external declarations (not definitions)
|
||||
// and available_externally definitions.
|
||||
if !(linkage == llvm::ExternalLinkage as c_uint &&
|
||||
llvm::LLVMIsDeclaration(val) != 0) &&
|
||||
!(linkage == llvm::AvailableExternallyLinkage as c_uint) {
|
||||
continue;
|
||||
}
|
||||
let is_available_externally = linkage == llvm::AvailableExternallyLinkage as c_uint;
|
||||
let is_decl = llvm::LLVMIsDeclaration(val) != 0;
|
||||
|
||||
if is_decl || is_available_externally {
|
||||
let name = CStr::from_ptr(llvm::LLVMGetValueName(val))
|
||||
.to_bytes()
|
||||
.to_vec();
|
||||
declared.insert(name);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Examine each external definition. If the definition is not used in
|
||||
|
@ -2501,22 +2499,28 @@ fn internalize_symbols(cx: &CrateContextList, reachable: &HashSet<&str>) {
|
|||
for ccx in cx.iter() {
|
||||
for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
|
||||
let linkage = llvm::LLVMGetLinkage(val);
|
||||
|
||||
let is_external = linkage == llvm::ExternalLinkage as c_uint;
|
||||
let is_weak_odr = linkage == llvm::WeakODRLinkage as c_uint;
|
||||
let is_decl = llvm::LLVMIsDeclaration(val) != 0;
|
||||
|
||||
// We only care about external definitions.
|
||||
if !((linkage == llvm::ExternalLinkage as c_uint ||
|
||||
linkage == llvm::WeakODRLinkage as c_uint) &&
|
||||
llvm::LLVMIsDeclaration(val) == 0) {
|
||||
continue;
|
||||
}
|
||||
if (is_external || is_weak_odr) && !is_decl {
|
||||
|
||||
let name = CStr::from_ptr(llvm::LLVMGetValueName(val))
|
||||
.to_bytes()
|
||||
.to_vec();
|
||||
if !declared.contains(&name) &&
|
||||
!reachable.contains(str::from_utf8(&name).unwrap()) {
|
||||
|
||||
let is_declared = declared.contains(&name);
|
||||
let reachable = reachable.contains(str::from_utf8(&name).unwrap());
|
||||
|
||||
if !is_declared && !reachable {
|
||||
llvm::SetLinkage(val, llvm::InternalLinkage);
|
||||
llvm::SetDLLStorageClass(val, llvm::DefaultStorageClass);
|
||||
llvm::UnsetComdat(val);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2744,6 +2748,9 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
|||
span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
|
||||
}
|
||||
}
|
||||
TransItem::Fn(instance) => {
|
||||
trans_instance(&ccx, instance);
|
||||
}
|
||||
_ => { }
|
||||
}
|
||||
}
|
||||
|
@ -2980,7 +2987,7 @@ fn collect_and_partition_translation_items<'a, 'tcx>(scx: &SharedCrateContext<'a
|
|||
let mut item_keys: Vec<_> = items
|
||||
.iter()
|
||||
.map(|i| {
|
||||
let mut output = i.to_string(scx.tcx());
|
||||
let mut output = i.to_string(scx);
|
||||
output.push_str(" @@");
|
||||
let mut empty = Vec::new();
|
||||
let mut cgus = item_to_cgus.get_mut(i).unwrap_or(&mut empty);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
use arena::TypedArena;
|
||||
use back::symbol_names;
|
||||
use llvm::{ValueRef, get_param, get_params};
|
||||
use llvm::{self, ValueRef, get_param, get_params};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use abi::{Abi, FnType};
|
||||
use adt;
|
||||
|
@ -167,7 +167,7 @@ fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
variadic: false
|
||||
})
|
||||
}));
|
||||
let llfn = declare::define_internal_fn(ccx, &symbol, function_type);
|
||||
let llfn = declare::declare_fn(ccx, &symbol, function_type);
|
||||
|
||||
// set an inline hint for all closures
|
||||
attributes::inline(llfn, attributes::InlineAttr::Hint);
|
||||
|
@ -211,6 +211,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
|
|||
id, closure_def_id, closure_substs);
|
||||
|
||||
let llfn = get_or_create_closure_declaration(ccx, closure_def_id, closure_substs);
|
||||
llvm::SetLinkage(llfn, llvm::WeakODRLinkage);
|
||||
|
||||
// Get the type of this closure. Use the current `param_substs` as
|
||||
// the closure substitutions. This makes sense because the closure
|
||||
|
@ -377,7 +378,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
|
|||
// Create the by-value helper.
|
||||
let function_name =
|
||||
symbol_names::internal_name_from_type_and_suffix(ccx, llonce_fn_ty, "once_shim");
|
||||
let lloncefn = declare::define_internal_fn(ccx, &function_name, llonce_fn_ty);
|
||||
let lloncefn = declare::declare_fn(ccx, &function_name, llonce_fn_ty);
|
||||
attributes::set_frame_pointer_elimination(ccx, lloncefn);
|
||||
|
||||
let (block_arena, fcx): (TypedArena<_>, FunctionContext);
|
||||
|
|
|
@ -325,7 +325,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
|
|||
// We've been here already, no need to search again.
|
||||
return;
|
||||
}
|
||||
debug!("BEGIN collect_items_rec({})", starting_point.to_string(scx.tcx()));
|
||||
debug!("BEGIN collect_items_rec({})", starting_point.to_string(scx));
|
||||
|
||||
let mut neighbors = Vec::new();
|
||||
let recursion_depth_reset;
|
||||
|
@ -396,7 +396,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
|
|||
recursion_depths.insert(def_id, depth);
|
||||
}
|
||||
|
||||
debug!("END collect_items_rec({})", starting_point.to_string(scx.tcx()));
|
||||
debug!("END collect_items_rec({})", starting_point.to_string(scx));
|
||||
}
|
||||
|
||||
fn record_inlining_canditates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
@ -456,12 +456,25 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
|
|||
match *rvalue {
|
||||
mir::Rvalue::Aggregate(mir::AggregateKind::Closure(def_id,
|
||||
ref substs), _) => {
|
||||
assert!(can_have_local_instance(self.scx.tcx(), def_id));
|
||||
let trans_item = create_fn_trans_item(self.scx.tcx(),
|
||||
def_id,
|
||||
substs.func_substs,
|
||||
self.param_substs);
|
||||
self.output.push(trans_item);
|
||||
let mir = errors::expect(self.scx.sess().diagnostic(), self.scx.get_mir(def_id),
|
||||
|| format!("Could not find MIR for closure: {:?}", def_id));
|
||||
|
||||
let concrete_substs = monomorphize::apply_param_substs(self.scx.tcx(),
|
||||
self.param_substs,
|
||||
&substs.func_substs);
|
||||
let concrete_substs = self.scx.tcx().erase_regions(&concrete_substs);
|
||||
|
||||
let mut visitor = MirNeighborCollector {
|
||||
scx: self.scx,
|
||||
mir: &mir,
|
||||
output: self.output,
|
||||
param_substs: concrete_substs
|
||||
};
|
||||
|
||||
visitor.visit_mir(&mir);
|
||||
for promoted in &mir.promoted {
|
||||
visitor.visit_mir(promoted);
|
||||
}
|
||||
}
|
||||
// When doing an cast from a regular pointer to a fat pointer, we
|
||||
// have to instantiate all methods of the trait being cast to, so we
|
||||
|
@ -1107,9 +1120,8 @@ impl<'b, 'a, 'v> hir_visit::Visitor<'v> for RootCollector<'b, 'a, 'v> {
|
|||
self.scx.tcx().map.local_def_id(item.id)));
|
||||
self.output.push(TransItem::Static(item.id));
|
||||
}
|
||||
hir::ItemFn(_, _, constness, _, ref generics, _) => {
|
||||
if !generics.is_type_parameterized() &&
|
||||
constness == hir::Constness::NotConst {
|
||||
hir::ItemFn(_, _, _, _, ref generics, _) => {
|
||||
if !generics.is_type_parameterized() {
|
||||
let def_id = self.scx.tcx().map.local_def_id(item.id);
|
||||
|
||||
debug!("RootCollector: ItemFn({})",
|
||||
|
@ -1129,9 +1141,8 @@ impl<'b, 'a, 'v> hir_visit::Visitor<'v> for RootCollector<'b, 'a, 'v> {
|
|||
match ii.node {
|
||||
hir::ImplItemKind::Method(hir::MethodSig {
|
||||
ref generics,
|
||||
constness,
|
||||
..
|
||||
}, _) if constness == hir::Constness::NotConst => {
|
||||
}, _) => {
|
||||
let hir_map = &self.scx.tcx().map;
|
||||
let parent_node_id = hir_map.get_parent_node(ii.id);
|
||||
let is_impl_generic = match hir_map.expect_item(parent_node_id) {
|
||||
|
@ -1260,7 +1271,7 @@ pub fn print_collection_results<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>) {
|
|||
let mut item_keys = FnvHashMap();
|
||||
|
||||
for (item, item_state) in trans_items.iter() {
|
||||
let k = item.to_string(scx.tcx());
|
||||
let k = item.to_string(scx);
|
||||
|
||||
if item_keys.contains_key(&k) {
|
||||
let prev: (TransItem, TransItemState) = item_keys[&k];
|
||||
|
@ -1288,7 +1299,7 @@ pub fn print_collection_results<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>) {
|
|||
let mut generated = FnvHashSet();
|
||||
|
||||
for (item, item_state) in trans_items.iter() {
|
||||
let item_key = item.to_string(scx.tcx());
|
||||
let item_key = item.to_string(scx);
|
||||
|
||||
match *item_state {
|
||||
TransItemState::PredictedAndGenerated => {
|
||||
|
|
|
@ -8,13 +8,11 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use llvm::{AvailableExternallyLinkage, InternalLinkage, SetLinkage};
|
||||
use middle::cstore::{FoundAst, InlinedItem};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::ty::subst::Substs;
|
||||
use base::{push_ctxt, trans_item, trans_fn};
|
||||
use callee::Callee;
|
||||
use base::push_ctxt;
|
||||
use common::*;
|
||||
use monomorphize::Instance;
|
||||
|
||||
use rustc::dep_graph::DepNode;
|
||||
use rustc::hir;
|
||||
|
@ -52,30 +50,6 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> Option<DefId> {
|
|||
ccx.external_srcs().borrow_mut().insert(item.id, fn_id);
|
||||
|
||||
ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
|
||||
trans_item(ccx, item);
|
||||
|
||||
if let hir::ItemFn(_, _, _, _, ref generics, _) = item.node {
|
||||
// Generics have no symbol, so they can't be given any linkage.
|
||||
if !generics.is_type_parameterized() {
|
||||
let linkage = if ccx.sess().opts.cg.codegen_units == 1 {
|
||||
// We could use AvailableExternallyLinkage here,
|
||||
// but InternalLinkage allows LLVM to optimize more
|
||||
// aggressively (at the cost of sometimes
|
||||
// duplicating code).
|
||||
InternalLinkage
|
||||
} else {
|
||||
// With multiple compilation units, duplicated code
|
||||
// is more of a problem. Also, `codegen_units > 1`
|
||||
// means the user is okay with losing some
|
||||
// performance.
|
||||
AvailableExternallyLinkage
|
||||
};
|
||||
let empty_substs = tcx.mk_substs(Substs::empty());
|
||||
let def_id = tcx.map.local_def_id(item.id);
|
||||
let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
|
||||
SetLinkage(llfn, linkage);
|
||||
}
|
||||
}
|
||||
|
||||
item.id
|
||||
}
|
||||
|
@ -135,35 +109,12 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> Option<DefId> {
|
|||
// don't.
|
||||
trait_item.id
|
||||
}
|
||||
FoundAst::Found(&InlinedItem::ImplItem(impl_did, ref impl_item)) => {
|
||||
FoundAst::Found(&InlinedItem::ImplItem(_, ref impl_item)) => {
|
||||
ccx.external().borrow_mut().insert(fn_id, Some(impl_item.id));
|
||||
ccx.external_srcs().borrow_mut().insert(impl_item.id, fn_id);
|
||||
|
||||
ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
|
||||
|
||||
// Translate monomorphic impl methods immediately.
|
||||
if let hir::ImplItemKind::Method(ref sig, ref body) = impl_item.node {
|
||||
let impl_tpt = tcx.lookup_item_type(impl_did);
|
||||
if impl_tpt.generics.types.is_empty() &&
|
||||
sig.generics.ty_params.is_empty() {
|
||||
let def_id = tcx.map.local_def_id(impl_item.id);
|
||||
let empty_substs = ccx.empty_substs_for_def_id(def_id);
|
||||
let llfn = Callee::def(ccx, def_id, empty_substs).reify(ccx).val;
|
||||
trans_fn(ccx,
|
||||
&sig.decl,
|
||||
body,
|
||||
llfn,
|
||||
empty_substs,
|
||||
impl_item.id);
|
||||
// See linkage comments on items.
|
||||
if ccx.sess().opts.cg.codegen_units == 1 {
|
||||
SetLinkage(llfn, InternalLinkage);
|
||||
} else {
|
||||
SetLinkage(llfn, AvailableExternallyLinkage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_item.id
|
||||
}
|
||||
};
|
||||
|
@ -184,3 +135,12 @@ pub fn get_local_instance(ccx: &CrateContext, fn_id: DefId)
|
|||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,15 +109,16 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
|||
});
|
||||
match map_node {
|
||||
hir_map::NodeItem(&hir::Item {
|
||||
ref attrs, node: hir::ItemFn(ref decl, _, _, _, _, ref body), ..
|
||||
}) |
|
||||
hir_map::NodeTraitItem(&hir::TraitItem {
|
||||
ref attrs, node: hir::MethodTraitItem(
|
||||
hir::MethodSig { ref decl, .. }, Some(ref body)), ..
|
||||
ref attrs,
|
||||
node: hir::ItemFn(ref decl, _, _, _, _, ref body), ..
|
||||
}) |
|
||||
hir_map::NodeImplItem(&hir::ImplItem {
|
||||
ref attrs, node: hir::ImplItemKind::Method(
|
||||
hir::MethodSig { ref decl, .. }, ref body), ..
|
||||
}) |
|
||||
hir_map::NodeTraitItem(&hir::TraitItem {
|
||||
ref attrs, node: hir::MethodTraitItem(
|
||||
hir::MethodSig { ref decl, .. }, Some(ref body)), ..
|
||||
}) => {
|
||||
attributes::from_fn_attrs(ccx, attrs, lldecl);
|
||||
|
||||
|
|
|
@ -14,19 +14,22 @@
|
|||
//! item-path. This is used for unit testing the code that generates
|
||||
//! paths etc in all kinds of annoying scenarios.
|
||||
|
||||
use attributes;
|
||||
use base;
|
||||
use context::CrateContext;
|
||||
use context::{SharedCrateContext, CrateContext};
|
||||
use declare;
|
||||
use glue::DropGlueKind;
|
||||
use llvm;
|
||||
use monomorphize::Instance;
|
||||
use monomorphize::{self, Instance};
|
||||
use inline;
|
||||
use rustc::hir;
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::ty::{self, Ty, TyCtxt};
|
||||
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc::ty::subst;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use syntax::ast::{self, NodeId};
|
||||
use syntax::attr;
|
||||
use syntax::{attr,errors};
|
||||
use syntax::parse::token;
|
||||
use type_of;
|
||||
|
||||
|
@ -59,22 +62,25 @@ impl<'tcx> Hash for TransItem<'tcx> {
|
|||
}
|
||||
|
||||
|
||||
impl<'tcx> TransItem<'tcx> {
|
||||
impl<'a, 'tcx> TransItem<'tcx> {
|
||||
|
||||
pub fn predefine<'ccx>(&self,
|
||||
ccx: &CrateContext<'ccx, 'tcx>,
|
||||
pub fn predefine(&self,
|
||||
ccx: &CrateContext<'a, 'tcx>,
|
||||
linkage: llvm::Linkage) {
|
||||
match *self {
|
||||
TransItem::Static(node_id) => {
|
||||
TransItem::predefine_static(ccx, node_id, linkage);
|
||||
}
|
||||
TransItem::Fn(instance) => {
|
||||
TransItem::predefine_fn(ccx, instance, linkage);
|
||||
}
|
||||
_ => {
|
||||
// Not yet implemented
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn predefine_static<'a>(ccx: &CrateContext<'a, 'tcx>,
|
||||
fn predefine_static(ccx: &CrateContext<'a, 'tcx>,
|
||||
node_id: ast::NodeId,
|
||||
linkage: llvm::Linkage) {
|
||||
let def_id = ccx.tcx().map.local_def_id(node_id);
|
||||
|
@ -101,7 +107,57 @@ impl<'tcx> TransItem<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn requests_inline<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
|
||||
fn predefine_fn(ccx: &CrateContext<'a, 'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
linkage: llvm::Linkage) {
|
||||
let unit = ccx.codegen_unit();
|
||||
debug!("predefine_fn[cg={}](instance={:?})", &unit.name[..], instance);
|
||||
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 symbol = instance.symbol_name(ccx.shared());
|
||||
let lldecl = declare::declare_fn(ccx, &symbol, mono_ty);
|
||||
|
||||
attributes::from_fn_attrs(ccx, attrs, lldecl);
|
||||
llvm::SetLinkage(lldecl, linkage);
|
||||
base::set_link_section(ccx, lldecl, attrs);
|
||||
|
||||
ccx.instances().borrow_mut().insert(instance, lldecl);
|
||||
}
|
||||
_ => bug!("Invalid item for TransItem::Fn: `{:?}`", map_node)
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
pub fn requests_inline(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
|
||||
match *self {
|
||||
TransItem::Fn(ref instance) => {
|
||||
let attributes = tcx.get_attrs(instance.def);
|
||||
|
@ -128,7 +184,7 @@ impl<'tcx> TransItem<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn explicit_linkage<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<llvm::Linkage> {
|
||||
pub fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<llvm::Linkage> {
|
||||
let def_id = match *self {
|
||||
TransItem::Fn(ref instance) => instance.def,
|
||||
TransItem::Static(node_id) => tcx.map.local_def_id(node_id),
|
||||
|
@ -152,7 +208,8 @@ impl<'tcx> TransItem<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn to_string<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
|
||||
pub fn to_string(&self, scx: &SharedCrateContext<'a, 'tcx>) -> String {
|
||||
let tcx = scx.tcx();
|
||||
let hir_map = &tcx.map;
|
||||
|
||||
return match *self {
|
||||
|
@ -170,13 +227,12 @@ impl<'tcx> TransItem<'tcx> {
|
|||
},
|
||||
TransItem::Static(node_id) => {
|
||||
let def_id = hir_map.local_def_id(node_id);
|
||||
let instance = Instance::new(def_id,
|
||||
tcx.mk_substs(subst::Substs::empty()));
|
||||
let instance = Instance::mono(scx, def_id);
|
||||
to_string_internal(tcx, "static ", instance)
|
||||
},
|
||||
};
|
||||
|
||||
fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx,'tcx>,
|
||||
fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
prefix: &str,
|
||||
instance: Instance<'tcx>)
|
||||
-> String {
|
||||
|
|
Loading…
Reference in New Issue