Tidying up, fix some minor linkage bugs, use ty flags to avoid caching closure types.

This commit is contained in:
Nick Cameron 2015-06-03 11:31:23 +12:00
parent 8f9f2fe97e
commit e9db5fb202
13 changed files with 75 additions and 79 deletions

View File

@ -50,9 +50,6 @@ pub enum DefIdSource {
// Identifies a type alias (`type X = ...`).
TypeWithId,
// Identifies a type parameter (`fn foo<X>() { ... }`).
TypeParameter,
// Identifies a region parameter (`fn foo<'X>() { ... }`).
RegionParameter,
@ -193,7 +190,7 @@ pub fn parse_substs_data<'tcx, F>(data: &[u8], crate_num: ast::CrateNum, pos: us
tcx: &ty::ctxt<'tcx>, conv: F) -> subst::Substs<'tcx> where
F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
{
debug!("parse_substs_data {}", data_log_string(data, pos));
debug!("parse_substs_data{}", data_log_string(data, pos));
let mut st = parse_state_from_data(data, crate_num, pos, tcx);
parse_substs(&mut st, conv)
}
@ -542,7 +539,14 @@ fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> w
len: len };
match tcx.rcache.borrow().get(&key).cloned() {
Some(tt) => return tt,
Some(tt) => {
// If there is a closure buried in the type some where, then we
// need to re-convert any def ids (see case 'k', below). That means
// we can't reuse the cached version.
if !ty::type_has_ty_closure(tt) {
return tt;
}
}
None => {}
}
let mut ps = PState {

View File

@ -20,7 +20,7 @@ use middle::def;
use metadata::encoder as e;
use middle::region;
use metadata::tydecode;
use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter};
use metadata::tydecode::{DefIdSource, NominalType, TypeWithId};
use metadata::tydecode::{RegionParameter, ClosureSource};
use metadata::tyencode;
use middle::cast;
@ -346,13 +346,6 @@ impl<D:serialize::Decoder> def_id_decoder_helpers for D
// ______________________________________________________________________
// Encoding and decoding the AST itself
//
// The hard work is done by an autogenerated module astencode_gen. To
// regenerate astencode_gen, run src/etc/gen-astencode. It will
// replace astencode_gen with a dummy file and regenerate its
// contents. If you get compile errors, the dummy file
// remains---resolve the errors and then rerun astencode_gen.
// Annoying, I know, but hopefully only temporary.
//
// When decoding, we have to renumber the AST so that the node ids that
// appear within are disjoint from the node ids in our existing ASTs.
// We also have to adjust the spans: for now we just insert a dummy span,
@ -656,35 +649,6 @@ impl<'a, 'tcx> read_method_callee_helper<'tcx> for reader::Decoder<'a> {
}
}
impl<'tcx> tr for MethodOrigin<'tcx> {
fn tr(&self, dcx: &DecodeContext) -> MethodOrigin<'tcx> {
match *self {
ty::MethodStatic(did) => ty::MethodStatic(did.tr(dcx)),
ty::MethodStaticClosure(did) => {
ty::MethodStaticClosure(did.tr(dcx))
}
ty::MethodTypeParam(ref mp) => {
ty::MethodTypeParam(
ty::MethodParam {
// def-id is already translated when we read it out
trait_ref: mp.trait_ref.clone(),
method_num: mp.method_num,
impl_def_id: mp.impl_def_id.tr(dcx),
}
)
}
ty::MethodTraitObject(ref mo) => {
ty::MethodTraitObject(
ty::MethodObject {
trait_ref: mo.trait_ref.clone(),
.. *mo
}
)
}
}
}
}
pub fn encode_closure_kind(ebml_w: &mut Encoder, kind: ty::ClosureKind) {
kind.encode(ebml_w).unwrap();
}
@ -1473,10 +1437,10 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
-> subst::Substs<'tcx> {
self.read_opaque(|this, doc| {
Ok(tydecode::parse_substs_data(doc.data,
dcx.cdata.cnum,
doc.start,
dcx.tcx,
|s, a| this.convert_def_id(dcx, s, a)))
dcx.cdata.cnum,
doc.start,
dcx.tcx,
|s, a| this.convert_def_id(dcx, s, a)))
}).unwrap()
}
@ -1617,7 +1581,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
-> ast::DefId {
let r = match source {
NominalType | TypeWithId | RegionParameter => dcx.tr_def_id(did),
TypeParameter | ClosureSource => dcx.tr_intern_def_id(did)
ClosureSource => dcx.tr_intern_def_id(did)
};
debug!("convert_def_id(source={:?}, did={:?})={:?}", source, did, r);
return r;

View File

@ -814,6 +814,7 @@ bitflags! {
const HAS_REGIONS = 1 << 5,
const HAS_TY_ERR = 1 << 6,
const HAS_PROJECTION = 1 << 7,
const HAS_TY_CLOSURE = 1 << 8,
const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits |
TypeFlags::HAS_SELF.bits |
TypeFlags::HAS_REGIONS.bits,
@ -985,6 +986,9 @@ pub fn type_needs_infer(ty: Ty) -> bool {
pub fn type_has_projection(ty: Ty) -> bool {
ty.flags.get().intersects(TypeFlags::HAS_PROJECTION)
}
pub fn type_has_ty_closure(ty: Ty) -> bool {
ty.flags.intersects(TypeFlags::HAS_TY_CLOSURE)
}
pub fn type_has_late_bound_regions(ty: Ty) -> bool {
ty.flags.get().intersects(TypeFlags::HAS_RE_LATE_BOUND)
@ -2960,6 +2964,7 @@ impl FlagComputation {
}
&ty_closure(_, substs) => {
self.add_flags(TypeFlags::HAS_TY_CLOSURE);
self.add_substs(substs);
}

View File

@ -304,11 +304,14 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
s
}
fn closure_to_string<'tcx>(cx: &ctxt<'tcx>, cty: &ty::ClosureTy<'tcx>) -> String {
fn closure_to_string<'tcx>(cx: &ctxt<'tcx>,
cty: &ty::ClosureTy<'tcx>,
did: &ast::DefId)
-> String {
let mut s = String::new();
s.push_str("[closure");
push_sig_to_string(cx, &mut s, '(', ')', &cty.sig);
s.push(']');
s.push_str(&format!(" id={:?}]", did));
s
}
@ -407,13 +410,13 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
ty_closure(ref did, substs) => {
let closure_tys = cx.closure_tys.borrow();
closure_tys.get(did).map(|closure_type| {
closure_to_string(cx, &closure_type.subst(cx, substs))
closure_to_string(cx, &closure_type.subst(cx, substs), did)
}).unwrap_or_else(|| {
if did.krate == ast::LOCAL_CRATE {
let span = cx.map.span(did.node);
format!("[closure {}]", span.repr(cx))
format!("[closure {} id={:?}]", span.repr(cx), did)
} else {
format!("[closure]")
format!("[closure id={:?}]", did)
}
})
}

View File

@ -117,9 +117,8 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
_ => {
bcx.tcx().sess.span_bug(
expr.span,
&format!("type of callee is neither bare-fn nor closure: \
{}",
bcx.ty_to_string(datum.ty)));
&format!("type of callee is neither bare-fn nor closure: {}",
bcx.ty_to_string(datum.ty)));
}
}
}
@ -506,6 +505,9 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
false
};
debug!("trans_fn_ref_with_substs({}) must_monomorphise: {}",
def_id.repr(tcx), must_monomorphise);
// Create a monomorphic version of generic functions
if must_monomorphise {
// Should be either intra-crate or inlined.

View File

@ -153,7 +153,8 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc
match ccx.closure_vals().borrow().get(&mono_id) {
Some(&llfn) => {
debug!("get_or_create_declaration_if_closure(): found closure");
debug!("get_or_create_declaration_if_closure(): found closure {:?}: {:?}",
mono_id, ccx.tn().val_to_string(llfn));
return Some(Datum::new(llfn, function_type, Rvalue::new(ByValue)))
}
None => {}
@ -173,9 +174,10 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc
attributes::inline(llfn, attributes::InlineAttr::Hint);
debug!("get_or_create_declaration_if_closure(): inserting new \
closure {:?} (type {})",
closure {:?} (type {}): {:?}",
mono_id,
ccx.tn().type_to_string(val_ty(llfn)));
ccx.tn().type_to_string(val_ty(llfn)),
ccx.tn().val_to_string(llfn));
ccx.closure_vals().borrow_mut().insert(mono_id, llfn);
Some(Datum::new(llfn, function_type, Rvalue::new(ByValue)))
@ -198,9 +200,9 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
Dest::Ignore(ccx) => ccx
};
let tcx = ccx.tcx();
let _icx = push_ctxt("closure::trans_closure");
let _icx = push_ctxt("closure::trans_closure_expr");
debug!("trans_closure()");
debug!("trans_closure_expr()");
let closure_id = ast_util::local_def(id);
let llfn = get_or_create_declaration_if_closure(
@ -230,7 +232,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
&[],
sig.output,
function_type.abi,
ClosureEnv::Closure(&freevars[..]));
ClosureEnv::Closure(&freevars));
// Don't hoist this to the top of the function. It's perfectly legitimate
// to have a zero-size closure (in which case dest will be `Ignore`) and
@ -238,7 +240,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
let (mut bcx, dest_addr) = match dest {
Dest::SaveIn(bcx, p) => (bcx, p),
Dest::Ignore(_) => {
debug!("trans_closure() ignoring result");
debug!("trans_closure_expr() ignoring result");
return None;
}
};

View File

@ -1000,7 +1000,8 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
None => { }
}
debug!("trans fulfill_obligation: trait_ref={}", trait_ref.repr(ccx.tcx()));
debug!("trans fulfill_obligation: trait_ref={} def_id={:?}",
trait_ref.repr(ccx.tcx()), trait_ref.def_id());
ty::populate_implementations_for_trait_if_necessary(tcx, trait_ref.def_id());
let infcx = infer::new_infer_ctxt(tcx);

View File

@ -221,6 +221,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
qualif: check_const::ConstQualif,
param_substs: &'tcx Substs<'tcx>)
-> ValueRef {
debug!("get_const_expr_as_global: {:?}", expr.id);
// Special-case constants to cache a common global for all uses.
match expr.node {
ast::ExprPath(..) => {
@ -228,6 +229,8 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
match def {
def::DefConst(def_id) | def::DefAssociatedConst(def_id, _) => {
if !ccx.tcx().adjustments.borrow().contains_key(&expr.id) {
debug!("get_const_expr_as_global ({:?}): found const {:?}",
expr.id, def_id);
return get_const_val(ccx, def_id, expr);
}
}
@ -911,7 +914,9 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
}
ast::ExprClosure(_, ref decl, ref body) => {
closure::trans_closure_expr(closure::Dest::Ignore(cx),
&**decl, &**body, e.id,
decl,
body,
e.id,
param_substs);
C_null(type_of::type_of(cx, ety))
}

View File

@ -73,7 +73,6 @@ pub struct SharedCrateContext<'tcx> {
check_overflow: bool,
check_drop_flag_for_sanity: bool,
available_monomorphizations: RefCell<FnvHashSet<String>>,
available_drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, String>>,
use_dll_storage_attrs: bool,
}
@ -100,6 +99,7 @@ pub struct LocalCrateContext<'tcx> {
/// Cache instances of monomorphized functions
monomorphized: RefCell<FnvHashMap<MonoId<'tcx>, ValueRef>>,
monomorphizing: RefCell<DefIdMap<usize>>,
available_monomorphizations: RefCell<FnvHashSet<String>>,
/// Cache generated vtables
vtables: RefCell<FnvHashMap<ty::PolyTraitRef<'tcx>, ValueRef>>,
/// Cache of constant strings,
@ -321,7 +321,6 @@ impl<'tcx> SharedCrateContext<'tcx> {
},
check_overflow: check_overflow,
check_drop_flag_for_sanity: check_drop_flag_for_sanity,
available_monomorphizations: RefCell::new(FnvHashSet()),
available_drop_glues: RefCell::new(FnvHashMap()),
use_dll_storage_attrs: use_dll_storage_attrs,
};
@ -452,6 +451,7 @@ impl<'tcx> LocalCrateContext<'tcx> {
external_srcs: RefCell::new(NodeMap()),
monomorphized: RefCell::new(FnvHashMap()),
monomorphizing: RefCell::new(DefIdMap()),
available_monomorphizations: RefCell::new(FnvHashSet()),
vtables: RefCell::new(FnvHashMap()),
const_cstr_cache: RefCell::new(FnvHashMap()),
const_unsized: RefCell::new(FnvHashMap()),
@ -709,7 +709,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
}
pub fn available_monomorphizations<'a>(&'a self) -> &'a RefCell<FnvHashSet<String>> {
&self.shared.available_monomorphizations
&self.local.available_monomorphizations
}
pub fn available_drop_glues(&self) -> &RefCell<FnvHashMap<DropGlueKind<'tcx>, String>> {

View File

@ -1145,7 +1145,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
SaveIn(lldest) => closure::Dest::SaveIn(bcx, lldest),
Ignore => closure::Dest::Ignore(bcx.ccx())
};
closure::trans_closure_expr(dest, &**decl, &**body, expr.id, bcx.fcx.param_substs)
closure::trans_closure_expr(dest, decl, body, expr.id, bcx.fcx.param_substs)
.unwrap_or(bcx)
}
ast::ExprCall(ref f, ref args) => {
@ -1956,6 +1956,7 @@ fn trans_overloaded_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
args: &'a [P<ast::Expr>],
dest: Option<Dest>)
-> Block<'blk, 'tcx> {
debug!("trans_overloaded_call {}", expr.id);
let method_call = MethodCall::expr(expr.id);
let method_type = bcx.tcx()
.method_map

View File

@ -21,11 +21,13 @@ use syntax::ast_util::local_def;
fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
-> Option<ast::DefId> {
let _icx = push_ctxt("maybe_instantiate_inline");
debug!("instantiate_inline({:?})", fn_id);
let _icx = push_ctxt("instantiate_inline");
match ccx.external().borrow().get(&fn_id) {
Some(&Some(node_id)) => {
// Already inline
debug!("maybe_instantiate_inline({}): already inline as node id {}",
debug!("instantiate_inline({}): already inline as node id {}",
ty::item_path_str(ccx.tcx(), fn_id), node_id);
return Some(local_def(node_id));
}
@ -52,7 +54,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::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);
trans_item(ccx, item);
let linkage = match item.node {
ast::ItemFn(_, _, _, _, ref generics, _) => {
@ -118,7 +120,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
}
}
}
_ => ccx.sess().bug("maybe_instantiate_inline: item has a \
_ => ccx.sess().bug("instantiate_inline: item has a \
non-enum, non-struct parent")
}
trans_item(ccx, &**item);
@ -126,7 +128,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
}
csearch::FoundAst::FoundParent(_, _) => {
ccx.sess().bug("maybe_get_item_ast returned a FoundParent \
with a non-item parent");
with a non-item parent");
}
csearch::FoundAst::Found(&ast::IITraitItem(_, ref trait_item)) => {
ccx.external().borrow_mut().insert(fn_id, Some(trait_item.id));
@ -167,8 +169,12 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
empty_substs,
impl_item.id,
&[]);
// Use InternalLinkage so LLVM can optimize more aggressively.
SetLinkage(llfn, InternalLinkage);
// See linkage comments on items.
if ccx.sess().opts.cg.codegen_units == 1 {
SetLinkage(llfn, InternalLinkage);
} else {
SetLinkage(llfn, AvailableExternallyLinkage);
}
}
}

View File

@ -118,6 +118,7 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
match origin {
ty::MethodStatic(did) |
ty::MethodStaticClosure(did) => {
debug!("trans_method_callee: static, {:?}", did);
Callee {
bcx: bcx,
data: Fn(callee::trans_fn_ref(bcx.ccx(),
@ -134,9 +135,11 @@ pub fn trans_method_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
}) => {
let trait_ref = ty::Binder(bcx.monomorphize(trait_ref));
let span = bcx.tcx().map.span(method_call.expr_id);
debug!("method_call={:?} trait_ref={}",
debug!("method_call={:?} trait_ref={} trait_ref id={:?} substs={:?}",
method_call,
trait_ref.repr(bcx.tcx()));
trait_ref.repr(bcx.tcx()),
trait_ref.0.def_id,
trait_ref.0.substs);
let origin = fulfill_obligation(bcx.ccx(),
span,
trait_ref.clone());

View File

@ -60,6 +60,8 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
};
let item_ty = ty::lookup_item_type(ccx.tcx(), fn_id).ty;
debug!("monomorphic_fn about to subst into {}", item_ty.repr(ccx.tcx()));
let mono_ty = item_ty.subst(ccx.tcx(), psubsts);
match ccx.monomorphized().borrow().get(&hash_id) {
@ -97,8 +99,6 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
}
}
debug!("monomorphic_fn about to subst into {}", item_ty.repr(ccx.tcx()));
debug!("mono_ty = {} (post-substitution)", mono_ty.repr(ccx.tcx()));
let mono_ty = normalize_associated_type(ccx.tcx(), &mono_ty);