Compute LLVM-agnostic type layouts in rustc.

# Conflicts:
#	src/librustc/ty/layout.rs
This commit is contained in:
Eduard Burtescu 2016-04-19 09:11:46 +03:00
parent efd0ea5b20
commit fe48a4af84
5 changed files with 1006 additions and 37 deletions

View file

@ -31,7 +31,7 @@ use hir::FreevarMap;
use ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, TraitTy};
use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid};
use ty::TypeVariants::*;
use ty::layout::TargetDataLayout;
use ty::layout::{Layout, TargetDataLayout};
use ty::maps;
use util::common::MemoizationMap;
use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};
@ -56,6 +56,7 @@ pub struct CtxtArenas<'tcx> {
bare_fn: TypedArena<BareFnTy<'tcx>>,
region: TypedArena<Region>,
stability: TypedArena<attr::Stability>,
layout: TypedArena<Layout>,
// references
trait_defs: TypedArena<ty::TraitDef<'tcx>>,
@ -70,6 +71,7 @@ impl<'tcx> CtxtArenas<'tcx> {
bare_fn: TypedArena::new(),
region: TypedArena::new(),
stability: TypedArena::new(),
layout: TypedArena::new(),
trait_defs: TypedArena::new(),
adt_defs: TypedArena::new()
@ -230,6 +232,7 @@ pub struct TyCtxt<'tcx> {
bare_fn_interner: RefCell<FnvHashMap<&'tcx BareFnTy<'tcx>, &'tcx BareFnTy<'tcx>>>,
region_interner: RefCell<FnvHashMap<&'tcx Region, &'tcx Region>>,
stability_interner: RefCell<FnvHashMap<&'tcx attr::Stability, &'tcx attr::Stability>>,
layout_interner: RefCell<FnvHashMap<&'tcx Layout, &'tcx Layout>>,
pub dep_graph: DepGraph,
@ -423,6 +426,9 @@ pub struct TyCtxt<'tcx> {
/// Data layout specification for the current target.
pub data_layout: TargetDataLayout,
/// Cache for layouts computed from types.
pub layout_cache: RefCell<FnvHashMap<Ty<'tcx>, &'tcx Layout>>,
}
impl<'tcx> TyCtxt<'tcx> {
@ -504,6 +510,20 @@ impl<'tcx> TyCtxt<'tcx> {
interned
}
pub fn intern_layout(&self, layout: Layout) -> &'tcx Layout {
if let Some(layout) = self.layout_interner.borrow().get(&layout) {
return layout;
}
let interned = self.arenas.layout.alloc(layout);
if let Some(prev) = self.layout_interner
.borrow_mut()
.insert(interned, interned) {
bug!("Tried to overwrite interned Layout: {:?}", prev)
}
interned
}
pub fn store_free_region_map(&self, id: NodeId, map: FreeRegionMap) {
if self.free_region_maps.borrow_mut().insert(id, map).is_some() {
bug!("Tried to overwrite interned FreeRegionMap for NodeId {:?}", id)
@ -547,6 +567,7 @@ impl<'tcx> TyCtxt<'tcx> {
bare_fn_interner: RefCell::new(FnvHashMap()),
region_interner: RefCell::new(FnvHashMap()),
stability_interner: RefCell::new(FnvHashMap()),
layout_interner: RefCell::new(FnvHashMap()),
dep_graph: dep_graph.clone(),
types: common_types,
named_region_map: named_region_map,
@ -595,6 +616,7 @@ impl<'tcx> TyCtxt<'tcx> {
fragment_infos: RefCell::new(DefIdMap()),
crate_name: token::intern_and_get_ident(crate_name),
data_layout: data_layout,
layout_cache: RefCell::new(FnvHashMap()),
}, f)
}
}
@ -768,6 +790,7 @@ impl<'tcx> TyCtxt<'tcx> {
println!("BareFnTy interner: #{}", self.bare_fn_interner.borrow().len());
println!("Region interner: #{}", self.region_interner.borrow().len());
println!("Stability interner: #{}", self.stability_interner.borrow().len());
println!("Layout interner: #{}", self.layout_interner.borrow().len());
}
}

File diff suppressed because it is too large Load diff

View file

@ -18,6 +18,7 @@ use hir::pat_util;
use traits::{self, ProjectionMode};
use ty::{self, Ty, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable};
use ty::{Disr, ParameterEnvironment};
use ty::layout::{Layout, LayoutError};
use ty::TypeVariants::*;
use rustc_const_math::{ConstInt, ConstIsize, ConstUsize};
@ -597,6 +598,24 @@ impl<'tcx> ty::TyS<'tcx> {
result
}
#[inline]
pub fn layout<'a>(&'tcx self, infcx: &infer::InferCtxt<'a, 'tcx>)
-> Result<&'tcx Layout, LayoutError<'tcx>> {
let can_cache = !self.has_param_types() && !self.has_self_ty();
if can_cache {
if let Some(&cached) = infcx.tcx.layout_cache.borrow().get(&self) {
return Ok(cached);
}
}
let layout = Layout::compute_uncached(self, infcx)?;
let layout = infcx.tcx.intern_layout(layout);
if can_cache {
infcx.tcx.layout_cache.borrow_mut().insert(self, layout);
}
Ok(layout)
}
/// Check whether a type is representable. This means it cannot contain unboxed
/// structural recursion. This check is needed for structs and enums.