trans: Get rid of the last potential on-demand creation of non-closure functions.

This commit is contained in:
Michael Woerister 2016-05-13 18:14:47 -04:00
parent 6717106947
commit 5f3fefc77d
3 changed files with 11 additions and 91 deletions

View File

@ -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 {

View File

@ -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

View File

@ -17,7 +17,6 @@ use rustc::ty::subst::{Subst, Substs};
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::util::ppaux;
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(_) => {