trans: Get rid of the last potential on-demand creation of non-closure functions.
This commit is contained in:
parent
6717106947
commit
5f3fefc77d
@ -25,8 +25,6 @@
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
pub use self::ValueOrigin::*;
|
||||
|
||||
use super::CrateTranslation;
|
||||
use super::ModuleTranslation;
|
||||
|
||||
@ -1918,37 +1916,6 @@ pub fn trans_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
fcx.finish(bcx, fn_cleanup_debug_loc.debug_loc());
|
||||
}
|
||||
|
||||
/// Creates an LLVM function corresponding to a source language function.
|
||||
pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
decl: &hir::FnDecl,
|
||||
body: &hir::Block,
|
||||
llfndecl: ValueRef,
|
||||
param_substs: &'tcx Substs<'tcx>,
|
||||
id: ast::NodeId) {
|
||||
let _s = StatRecorder::new(ccx, ccx.tcx().node_path_str(id));
|
||||
debug!("trans_fn(param_substs={:?})", param_substs);
|
||||
let _icx = push_ctxt("trans_fn");
|
||||
let def_id = if let Some(&def_id) = ccx.external_srcs().borrow().get(&id) {
|
||||
def_id
|
||||
} else {
|
||||
ccx.tcx().map.local_def_id(id)
|
||||
};
|
||||
let fn_ty = ccx.tcx().lookup_item_type(def_id).ty;
|
||||
let fn_ty = monomorphize::apply_param_substs(ccx.tcx(), param_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();
|
||||
trans_closure(ccx,
|
||||
decl,
|
||||
body,
|
||||
llfndecl,
|
||||
Instance::new(def_id, param_substs),
|
||||
id,
|
||||
&sig,
|
||||
abi,
|
||||
closure::ClosureEnv::NotClosure);
|
||||
}
|
||||
|
||||
pub fn trans_instance<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, instance: Instance<'tcx>) {
|
||||
let instance = inline::maybe_inline_instance(ccx, instance);
|
||||
|
||||
@ -2215,46 +2182,14 @@ pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Enum describing the origin of an LLVM `Value`, for linkage purposes.
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum ValueOrigin {
|
||||
/// The LLVM `Value` is in this context because the corresponding item was
|
||||
/// assigned to the current compilation unit.
|
||||
OriginalTranslation,
|
||||
/// The `Value`'s corresponding item was assigned to some other compilation
|
||||
/// unit, but the `Value` was translated in this context anyway because the
|
||||
/// item is marked `#[inline]`.
|
||||
InlinedCopy,
|
||||
}
|
||||
|
||||
/// Set the appropriate linkage for an LLVM `ValueRef` (function or global).
|
||||
/// If the `llval` is the direct translation of a specific Rust item, `id`
|
||||
/// should be set to the `NodeId` of that item. (This mapping should be
|
||||
/// 1-to-1, so monomorphizations and drop/visit glue should have `id` set to
|
||||
/// `None`.) `llval_origin` indicates whether `llval` is the translation of an
|
||||
/// item assigned to `ccx`'s compilation unit or an inlined copy of an item
|
||||
/// assigned to a different compilation unit.
|
||||
/// `None`.)
|
||||
pub fn update_linkage(ccx: &CrateContext,
|
||||
llval: ValueRef,
|
||||
id: Option<ast::NodeId>,
|
||||
llval_origin: ValueOrigin) {
|
||||
match llval_origin {
|
||||
InlinedCopy => {
|
||||
// `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 ||
|
||||
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.
|
||||
llvm::SetLinkage(llval, llvm::AvailableExternallyLinkage);
|
||||
return;
|
||||
},
|
||||
OriginalTranslation => {},
|
||||
}
|
||||
|
||||
id: Option<ast::NodeId>) {
|
||||
if let Some(id) = id {
|
||||
let item = ccx.tcx().map.get(id);
|
||||
if let hir_map::NodeItem(i) = item {
|
||||
|
@ -285,7 +285,7 @@ fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
|
||||
let bcx = fcx.init(false, None);
|
||||
|
||||
update_linkage(ccx, llfn, None, OriginalTranslation);
|
||||
update_linkage(ccx, llfn, None);
|
||||
|
||||
ccx.stats().n_glues_created.set(ccx.stats().n_glues_created.get() + 1);
|
||||
// All glue functions take values passed *by alias*; this is a
|
||||
|
@ -17,7 +17,6 @@
|
||||
use rustc::ty::{self, Ty, TypeFoldable, TyCtxt};
|
||||
use attributes;
|
||||
use base::{push_ctxt};
|
||||
use base::trans_fn;
|
||||
use base;
|
||||
use common::*;
|
||||
use declare;
|
||||
@ -27,17 +26,16 @@
|
||||
|
||||
use rustc::hir;
|
||||
|
||||
use syntax::attr;
|
||||
use errors;
|
||||
|
||||
use std::fmt;
|
||||
use trans_item::TransItem;
|
||||
|
||||
pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
fn_id: DefId,
|
||||
psubsts: &'tcx subst::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");
|
||||
@ -53,6 +51,8 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
if let Some(&val) = ccx.instances().borrow().get(&instance) {
|
||||
debug!("leaving monomorphic fn {:?}", instance);
|
||||
return (val, mono_ty);
|
||||
} else {
|
||||
assert!(!ccx.codegen_unit().items.contains_key(&TransItem::Fn(instance)));
|
||||
}
|
||||
|
||||
debug!("monomorphic_fn({:?})", instance);
|
||||
@ -96,6 +96,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
|
||||
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(
|
||||
@ -110,34 +111,18 @@ 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), ..
|
||||
node: hir::ItemFn(..), ..
|
||||
}) |
|
||||
hir_map::NodeImplItem(&hir::ImplItem {
|
||||
ref attrs, node: hir::ImplItemKind::Method(
|
||||
hir::MethodSig { ref decl, .. }, ref body), ..
|
||||
hir::MethodSig { .. }, _), ..
|
||||
}) |
|
||||
hir_map::NodeTraitItem(&hir::TraitItem {
|
||||
ref attrs, node: hir::MethodTraitItem(
|
||||
hir::MethodSig { ref decl, .. }, Some(ref body)), ..
|
||||
hir::MethodSig { .. }, Some(_)), ..
|
||||
}) => {
|
||||
attributes::from_fn_attrs(ccx, attrs, lldecl);
|
||||
|
||||
let is_first = !ccx.available_monomorphizations().borrow()
|
||||
.contains(&symbol);
|
||||
if is_first {
|
||||
ccx.available_monomorphizations().borrow_mut().insert(symbol.clone());
|
||||
}
|
||||
|
||||
let trans_everywhere = attr::requests_inline(attrs);
|
||||
if trans_everywhere || is_first {
|
||||
let origin = if is_first { base::OriginalTranslation } else { base::InlinedCopy };
|
||||
base::update_linkage(ccx, lldecl, None, origin);
|
||||
trans_fn(ccx, decl, body, lldecl, psubsts, fn_node_id);
|
||||
} else {
|
||||
// We marked the value as using internal linkage earlier, but that is illegal for
|
||||
// declarations, so switch back to external linkage.
|
||||
llvm::SetLinkage(lldecl, llvm::ExternalLinkage);
|
||||
}
|
||||
llvm::SetLinkage(lldecl, llvm::ExternalLinkage);
|
||||
}
|
||||
|
||||
hir_map::NodeVariant(_) | hir_map::NodeStructCtor(_) => {
|
||||
|
Loading…
Reference in New Issue
Block a user