mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-20 19:52:48 +00:00
Compute LLVM-agnostic type layouts in rustc.
# Conflicts: # src/librustc/ty/layout.rs
This commit is contained in:
parent
efd0ea5b20
commit
fe48a4af84
@ -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
@ -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.
|
||||
|
@ -32,18 +32,7 @@ use rustc::ty::{self, Ty};
|
||||
use libc::c_uint;
|
||||
|
||||
pub use syntax::abi::Abi;
|
||||
|
||||
/// The first half of a fat pointer.
|
||||
/// - For a closure, this is the code address.
|
||||
/// - For an object or trait instance, this is the address of the box.
|
||||
/// - For a slice, this is the base address.
|
||||
pub const FAT_PTR_ADDR: usize = 0;
|
||||
|
||||
/// The second half of a fat pointer.
|
||||
/// - For a closure, this is the address of the environment.
|
||||
/// - For an object or trait instance, this is the address of the vtable.
|
||||
/// - For a slice, this is the length.
|
||||
pub const FAT_PTR_EXTRA: usize = 1;
|
||||
pub use rustc::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||
enum ArgKind {
|
||||
|
@ -784,23 +784,8 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
|
||||
&self.local.trait_cache
|
||||
}
|
||||
|
||||
/// Return exclusive upper bound on object size.
|
||||
///
|
||||
/// The theoretical maximum object size is defined as the maximum positive `int` value. This
|
||||
/// ensures that the `offset` semantics remain well-defined by allowing it to correctly index
|
||||
/// every address within an object along with one byte past the end, along with allowing `int`
|
||||
/// to store the difference between any two pointers into an object.
|
||||
///
|
||||
/// The upper bound on 64-bit currently needs to be lower because LLVM uses a 64-bit integer to
|
||||
/// represent object size in bits. It would need to be 1 << 61 to account for this, but is
|
||||
/// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable
|
||||
/// address space on 64-bit ARMv8 and x86_64.
|
||||
pub fn obj_size_bound(&self) -> u64 {
|
||||
match &self.sess().target.target.target_pointer_width[..] {
|
||||
"32" => 1 << 31,
|
||||
"64" => 1 << 47,
|
||||
_ => bug!() // error handled by config::build_target_config
|
||||
}
|
||||
self.tcx().data_layout.obj_size_bound()
|
||||
}
|
||||
|
||||
pub fn report_overbig_object(&self, obj: Ty<'tcx>) -> ! {
|
||||
|
Loading…
Reference in New Issue
Block a user