rustc: add some abstractions to ty::layout for a more concise API.
This commit is contained in:
parent
c977daf97c
commit
43b227f3bd
17 changed files with 188 additions and 80 deletions
|
@ -89,7 +89,7 @@ impl<'a, 'gcx, 'tcx> ExprVisitor<'a, 'gcx, 'tcx> {
|
||||||
let from = unpack_option_like(self.infcx.tcx.global_tcx(), from);
|
let from = unpack_option_like(self.infcx.tcx.global_tcx(), from);
|
||||||
match (&from.sty, sk_to) {
|
match (&from.sty, sk_to) {
|
||||||
(&ty::TyFnDef(..), SizeSkeleton::Known(size_to))
|
(&ty::TyFnDef(..), SizeSkeleton::Known(size_to))
|
||||||
if size_to == Pointer.size(&self.infcx.tcx.data_layout) => {
|
if size_to == Pointer.size(self.infcx) => {
|
||||||
struct_span_err!(self.infcx.tcx.sess, span, E0591,
|
struct_span_err!(self.infcx.tcx.sess, span, E0591,
|
||||||
"`{}` is zero-sized and can't be transmuted to `{}`",
|
"`{}` is zero-sized and can't be transmuted to `{}`",
|
||||||
from, to)
|
from, to)
|
||||||
|
|
|
@ -202,6 +202,16 @@ impl TargetDataLayout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait HasDataLayout: Copy {
|
||||||
|
fn data_layout(&self) -> &TargetDataLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> HasDataLayout for &'a TargetDataLayout {
|
||||||
|
fn data_layout(&self) -> &TargetDataLayout {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Endianness of the target, which must match cfg(target-endian).
|
/// Endianness of the target, which must match cfg(target-endian).
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum Endian {
|
pub enum Endian {
|
||||||
|
@ -242,7 +252,9 @@ impl Size {
|
||||||
Size::from_bytes((self.bytes() + mask) & !mask)
|
Size::from_bytes((self.bytes() + mask) & !mask)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn checked_add(self, offset: Size, dl: &TargetDataLayout) -> Option<Size> {
|
pub fn checked_add<C: HasDataLayout>(self, offset: Size, cx: C) -> Option<Size> {
|
||||||
|
let dl = cx.data_layout();
|
||||||
|
|
||||||
// Each Size is less than dl.obj_size_bound(), so the sum is
|
// Each Size is less than dl.obj_size_bound(), so the sum is
|
||||||
// also less than 1 << 62 (and therefore can't overflow).
|
// also less than 1 << 62 (and therefore can't overflow).
|
||||||
let bytes = self.bytes() + offset.bytes();
|
let bytes = self.bytes() + offset.bytes();
|
||||||
|
@ -254,7 +266,9 @@ impl Size {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn checked_mul(self, count: u64, dl: &TargetDataLayout) -> Option<Size> {
|
pub fn checked_mul<C: HasDataLayout>(self, count: u64, cx: C) -> Option<Size> {
|
||||||
|
let dl = cx.data_layout();
|
||||||
|
|
||||||
// Each Size is less than dl.obj_size_bound(), so the sum is
|
// Each Size is less than dl.obj_size_bound(), so the sum is
|
||||||
// also less than 1 << 62 (and therefore can't overflow).
|
// also less than 1 << 62 (and therefore can't overflow).
|
||||||
match self.bytes().checked_mul(count) {
|
match self.bytes().checked_mul(count) {
|
||||||
|
@ -354,7 +368,9 @@ impl Integer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn align(&self, dl: &TargetDataLayout)-> Align {
|
pub fn align<C: HasDataLayout>(&self, cx: C) -> Align {
|
||||||
|
let dl = cx.data_layout();
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
I1 => dl.i1_align,
|
I1 => dl.i1_align,
|
||||||
I8 => dl.i8_align,
|
I8 => dl.i8_align,
|
||||||
|
@ -408,7 +424,9 @@ impl Integer {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find the smallest integer with the given alignment.
|
/// Find the smallest integer with the given alignment.
|
||||||
pub fn for_abi_align(dl: &TargetDataLayout, align: Align) -> Option<Integer> {
|
pub fn for_abi_align<C: HasDataLayout>(cx: C, align: Align) -> Option<Integer> {
|
||||||
|
let dl = cx.data_layout();
|
||||||
|
|
||||||
let wanted = align.abi();
|
let wanted = align.abi();
|
||||||
for &candidate in &[I8, I16, I32, I64] {
|
for &candidate in &[I8, I16, I32, I64] {
|
||||||
let ty = Int(candidate);
|
let ty = Int(candidate);
|
||||||
|
@ -420,7 +438,9 @@ impl Integer {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the Integer type from an attr::IntType.
|
/// Get the Integer type from an attr::IntType.
|
||||||
pub fn from_attr(dl: &TargetDataLayout, ity: attr::IntType) -> Integer {
|
pub fn from_attr<C: HasDataLayout>(cx: C, ity: attr::IntType) -> Integer {
|
||||||
|
let dl = cx.data_layout();
|
||||||
|
|
||||||
match ity {
|
match ity {
|
||||||
attr::SignedInt(IntTy::I8) | attr::UnsignedInt(UintTy::U8) => I8,
|
attr::SignedInt(IntTy::I8) | attr::UnsignedInt(UintTy::U8) => I8,
|
||||||
attr::SignedInt(IntTy::I16) | attr::UnsignedInt(UintTy::U16) => I16,
|
attr::SignedInt(IntTy::I16) | attr::UnsignedInt(UintTy::U16) => I16,
|
||||||
|
@ -450,7 +470,7 @@ impl Integer {
|
||||||
let min_default = I8;
|
let min_default = I8;
|
||||||
|
|
||||||
if let Some(ity) = repr.int {
|
if let Some(ity) = repr.int {
|
||||||
let discr = Integer::from_attr(&tcx.data_layout, ity);
|
let discr = Integer::from_attr(tcx, ity);
|
||||||
let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
|
let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
|
||||||
if discr < fit {
|
if discr < fit {
|
||||||
bug!("Integer::repr_discr: `#[repr]` hint too small for \
|
bug!("Integer::repr_discr: `#[repr]` hint too small for \
|
||||||
|
@ -491,7 +511,9 @@ pub enum Primitive {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Primitive {
|
impl Primitive {
|
||||||
pub fn size(self, dl: &TargetDataLayout) -> Size {
|
pub fn size<C: HasDataLayout>(self, cx: C) -> Size {
|
||||||
|
let dl = cx.data_layout();
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Int(I1) | Int(I8) => Size::from_bits(8),
|
Int(I1) | Int(I8) => Size::from_bits(8),
|
||||||
Int(I16) => Size::from_bits(16),
|
Int(I16) => Size::from_bits(16),
|
||||||
|
@ -502,7 +524,9 @@ impl Primitive {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn align(self, dl: &TargetDataLayout) -> Align {
|
pub fn align<C: HasDataLayout>(self, cx: C) -> Align {
|
||||||
|
let dl = cx.data_layout();
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Int(I1) => dl.i1_align,
|
Int(I1) => dl.i1_align,
|
||||||
Int(I8) => dl.i8_align,
|
Int(I8) => dl.i8_align,
|
||||||
|
@ -682,8 +706,8 @@ impl<'a, 'gcx, 'tcx> Struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determine whether a structure would be zero-sized, given its fields.
|
/// Determine whether a structure would be zero-sized, given its fields.
|
||||||
pub fn would_be_zero_sized<I>(dl: &TargetDataLayout, fields: I)
|
fn would_be_zero_sized<I>(dl: &TargetDataLayout, fields: I)
|
||||||
-> Result<bool, LayoutError<'gcx>>
|
-> Result<bool, LayoutError<'gcx>>
|
||||||
where I: Iterator<Item=Result<&'a Layout, LayoutError<'gcx>>> {
|
where I: Iterator<Item=Result<&'a Layout, LayoutError<'gcx>>> {
|
||||||
for field in fields {
|
for field in fields {
|
||||||
let field = field?;
|
let field = field?;
|
||||||
|
@ -831,7 +855,7 @@ pub struct Union {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> Union {
|
impl<'a, 'gcx, 'tcx> Union {
|
||||||
pub fn new(dl: &TargetDataLayout, packed: bool) -> Union {
|
fn new(dl: &TargetDataLayout, packed: bool) -> Union {
|
||||||
Union {
|
Union {
|
||||||
align: if packed { dl.i8_align } else { dl.aggregate_align },
|
align: if packed { dl.i8_align } else { dl.aggregate_align },
|
||||||
min_size: Size::from_bytes(0),
|
min_size: Size::from_bytes(0),
|
||||||
|
@ -840,10 +864,10 @@ impl<'a, 'gcx, 'tcx> Union {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extend the Struct with more fields.
|
/// Extend the Struct with more fields.
|
||||||
pub fn extend<I>(&mut self, dl: &TargetDataLayout,
|
fn extend<I>(&mut self, dl: &TargetDataLayout,
|
||||||
fields: I,
|
fields: I,
|
||||||
scapegoat: Ty<'gcx>)
|
scapegoat: Ty<'gcx>)
|
||||||
-> Result<(), LayoutError<'gcx>>
|
-> Result<(), LayoutError<'gcx>>
|
||||||
where I: Iterator<Item=Result<&'a Layout, LayoutError<'gcx>>> {
|
where I: Iterator<Item=Result<&'a Layout, LayoutError<'gcx>>> {
|
||||||
for (index, field) in fields.enumerate() {
|
for (index, field) in fields.enumerate() {
|
||||||
let field = field?;
|
let field = field?;
|
||||||
|
@ -1452,7 +1476,9 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn size(&self, dl: &TargetDataLayout) -> Size {
|
pub fn size<C: HasDataLayout>(&self, cx: C) -> Size {
|
||||||
|
let dl = cx.data_layout();
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Scalar { value, .. } | RawNullablePointer { value, .. } => {
|
Scalar { value, .. } | RawNullablePointer { value, .. } => {
|
||||||
value.size(dl)
|
value.size(dl)
|
||||||
|
@ -1494,7 +1520,9 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn align(&self, dl: &TargetDataLayout) -> Align {
|
pub fn align<C: HasDataLayout>(&self, cx: C) -> Align {
|
||||||
|
let dl = cx.data_layout();
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Scalar { value, .. } | RawNullablePointer { value, .. } => {
|
Scalar { value, .. } | RawNullablePointer { value, .. } => {
|
||||||
value.align(dl)
|
value.align(dl)
|
||||||
|
@ -1534,11 +1562,13 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn field_offset(&self,
|
pub fn field_offset<C: HasDataLayout>(&self,
|
||||||
dl: &TargetDataLayout,
|
cx: C,
|
||||||
i: usize,
|
i: usize,
|
||||||
variant_index: Option<usize>)
|
variant_index: Option<usize>)
|
||||||
-> Size {
|
-> Size {
|
||||||
|
let dl = cx.data_layout();
|
||||||
|
|
||||||
match *self {
|
match *self {
|
||||||
Scalar { .. } |
|
Scalar { .. } |
|
||||||
CEnum { .. } |
|
CEnum { .. } |
|
||||||
|
@ -1617,7 +1647,7 @@ impl<'a, 'gcx, 'tcx> SizeSkeleton<'gcx> {
|
||||||
// First try computing a static layout.
|
// First try computing a static layout.
|
||||||
let err = match ty.layout(infcx) {
|
let err = match ty.layout(infcx) {
|
||||||
Ok(layout) => {
|
Ok(layout) => {
|
||||||
return Ok(SizeSkeleton::Known(layout.size(&tcx.data_layout)));
|
return Ok(SizeSkeleton::Known(layout.size(tcx)));
|
||||||
}
|
}
|
||||||
Err(err) => err
|
Err(err) => err
|
||||||
};
|
};
|
||||||
|
@ -1748,18 +1778,55 @@ impl<'tcx> Deref for TyLayout<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'gcx, 'tcx> TyLayout<'gcx> {
|
pub trait HasTyCtxt<'tcx>: HasDataLayout {
|
||||||
pub fn of(infcx: &InferCtxt<'a, 'gcx, 'tcx>, ty: Ty<'gcx>)
|
fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>;
|
||||||
-> Result<Self, LayoutError<'gcx>> {
|
}
|
||||||
let ty = normalize_associated_type(infcx, ty);
|
|
||||||
|
impl<'a, 'gcx, 'tcx> HasDataLayout for TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
fn data_layout(&self) -> &TargetDataLayout {
|
||||||
|
&self.data_layout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'gcx, 'tcx> HasTyCtxt<'gcx> for TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'gcx> {
|
||||||
|
self.global_tcx()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'gcx, 'tcx> HasDataLayout for &'a InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
fn data_layout(&self) -> &TargetDataLayout {
|
||||||
|
&self.tcx.data_layout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'gcx, 'tcx> HasTyCtxt<'gcx> for &'a InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'gcx> {
|
||||||
|
self.tcx.global_tcx()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait LayoutTyper<'tcx>: HasTyCtxt<'tcx> {
|
||||||
|
type TyLayout;
|
||||||
|
|
||||||
|
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'gcx, 'tcx> LayoutTyper<'gcx> for &'a InferCtxt<'a, 'gcx, 'tcx> {
|
||||||
|
type TyLayout = Result<TyLayout<'gcx>, LayoutError<'gcx>>;
|
||||||
|
|
||||||
|
fn layout_of(self, ty: Ty<'gcx>) -> Self::TyLayout {
|
||||||
|
let ty = normalize_associated_type(self, ty);
|
||||||
|
|
||||||
Ok(TyLayout {
|
Ok(TyLayout {
|
||||||
ty: ty,
|
ty: ty,
|
||||||
layout: ty.layout(infcx)?,
|
layout: ty.layout(self)?,
|
||||||
variant_index: None
|
variant_index: None
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> TyLayout<'tcx> {
|
||||||
pub fn for_variant(&self, variant_index: usize) -> Self {
|
pub fn for_variant(&self, variant_index: usize) -> Self {
|
||||||
TyLayout {
|
TyLayout {
|
||||||
variant_index: Some(variant_index),
|
variant_index: Some(variant_index),
|
||||||
|
@ -1767,8 +1834,8 @@ impl<'a, 'gcx, 'tcx> TyLayout<'gcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn field_offset(&self, dl: &TargetDataLayout, i: usize) -> Size {
|
pub fn field_offset<C: HasDataLayout>(&self, cx: C, i: usize) -> Size {
|
||||||
self.layout.field_offset(dl, i, self.variant_index)
|
self.layout.field_offset(cx, i, self.variant_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn field_count(&self) -> usize {
|
pub fn field_count(&self) -> usize {
|
||||||
|
@ -1808,9 +1875,11 @@ impl<'a, 'gcx, 'tcx> TyLayout<'gcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn field_type(&self, tcx: TyCtxt<'a, 'gcx, 'gcx>, i: usize) -> Ty<'gcx> {
|
pub fn field_type<C: HasTyCtxt<'tcx>>(&self, cx: C, i: usize) -> Ty<'tcx> {
|
||||||
let ptr_field_type = |pointee: Ty<'gcx>| {
|
let tcx = cx.tcx();
|
||||||
let slice = |element: Ty<'gcx>| {
|
|
||||||
|
let ptr_field_type = |pointee: Ty<'tcx>| {
|
||||||
|
let slice = |element: Ty<'tcx>| {
|
||||||
assert!(i < 2);
|
assert!(i < 2);
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
tcx.mk_mut_ptr(element)
|
tcx.mk_mut_ptr(element)
|
||||||
|
@ -1877,8 +1946,7 @@ impl<'a, 'gcx, 'tcx> TyLayout<'gcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn field(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>, i: usize)
|
pub fn field<C: LayoutTyper<'tcx>>(&self, cx: C, i: usize) -> C::TyLayout {
|
||||||
-> Result<Self, LayoutError<'gcx>> {
|
cx.layout_of(self.field_type(cx, i))
|
||||||
TyLayout::of(infcx, self.field_type(infcx.tcx.global_tcx(), i))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -733,7 +733,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Layout::General { ref variants, ref size, discr, .. } = *layout {
|
if let Layout::General { ref variants, ref size, discr, .. } = *layout {
|
||||||
let discr_size = Primitive::Int(discr).size(&cx.tcx.data_layout).bytes();
|
let discr_size = Primitive::Int(discr).size(cx.tcx).bytes();
|
||||||
|
|
||||||
debug!("enum `{}` is {} bytes large with layout:\n{:#?}",
|
debug!("enum `{}` is {} bytes large with layout:\n{:#?}",
|
||||||
t, size.bytes(), layout);
|
t, size.bytes(), layout);
|
||||||
|
|
|
@ -35,13 +35,13 @@ use type_of;
|
||||||
|
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
use rustc::ty::{self, Ty};
|
use rustc::ty::{self, Ty};
|
||||||
|
use rustc::ty::layout::{Layout, LayoutTyper};
|
||||||
|
|
||||||
use libc::c_uint;
|
use libc::c_uint;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
|
||||||
pub use syntax::abi::Abi;
|
pub use syntax::abi::Abi;
|
||||||
pub use rustc::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
|
pub use rustc::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
|
||||||
use rustc::ty::layout::Layout;
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||||
enum ArgKind {
|
enum ArgKind {
|
||||||
|
|
|
@ -46,8 +46,8 @@ use super::Disr;
|
||||||
use std;
|
use std;
|
||||||
|
|
||||||
use llvm::{ValueRef, True, IntEQ, IntNE};
|
use llvm::{ValueRef, True, IntEQ, IntNE};
|
||||||
use rustc::ty::layout;
|
|
||||||
use rustc::ty::{self, Ty};
|
use rustc::ty::{self, Ty};
|
||||||
|
use rustc::ty::layout::{self, LayoutTyper};
|
||||||
use common::*;
|
use common::*;
|
||||||
use builder::Builder;
|
use builder::Builder;
|
||||||
use base;
|
use base;
|
||||||
|
@ -246,9 +246,8 @@ fn union_fill(cx: &CrateContext, size: u64, align: u64) -> Type {
|
||||||
assert_eq!(size%align, 0);
|
assert_eq!(size%align, 0);
|
||||||
assert_eq!(align.count_ones(), 1, "Alignment must be a power fof 2. Got {}", align);
|
assert_eq!(align.count_ones(), 1, "Alignment must be a power fof 2. Got {}", align);
|
||||||
let align_units = size/align;
|
let align_units = size/align;
|
||||||
let dl = &cx.tcx().data_layout;
|
|
||||||
let layout_align = layout::Align::from_bytes(align, align).unwrap();
|
let layout_align = layout::Align::from_bytes(align, align).unwrap();
|
||||||
if let Some(ity) = layout::Integer::for_abi_align(dl, layout_align) {
|
if let Some(ity) = layout::Integer::for_abi_align(cx, layout_align) {
|
||||||
Type::array(&Type::from_integer(cx, ity), align_units)
|
Type::array(&Type::from_integer(cx, ity), align_units)
|
||||||
} else {
|
} else {
|
||||||
Type::array(&Type::vector(&Type::i32(cx), align/4),
|
Type::array(&Type::vector(&Type::i32(cx), align/4),
|
||||||
|
|
|
@ -1295,8 +1295,8 @@ fn gather_type_sizes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||||
// (delay format until we actually need it)
|
// (delay format until we actually need it)
|
||||||
let record = |kind, opt_discr_size, variants| {
|
let record = |kind, opt_discr_size, variants| {
|
||||||
let type_desc = format!("{:?}", ty);
|
let type_desc = format!("{:?}", ty);
|
||||||
let overall_size = layout.size(&tcx.data_layout);
|
let overall_size = layout.size(tcx);
|
||||||
let align = layout.align(&tcx.data_layout);
|
let align = layout.align(tcx);
|
||||||
tcx.sess.code_stats.borrow_mut().record_type_size(kind,
|
tcx.sess.code_stats.borrow_mut().record_type_size(kind,
|
||||||
type_desc,
|
type_desc,
|
||||||
align,
|
align,
|
||||||
|
@ -1332,8 +1332,8 @@ fn gather_type_sizes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||||
session::FieldInfo {
|
session::FieldInfo {
|
||||||
name: field_name.to_string(),
|
name: field_name.to_string(),
|
||||||
offset: offset.bytes(),
|
offset: offset.bytes(),
|
||||||
size: field_layout.size(&tcx.data_layout).bytes(),
|
size: field_layout.size(tcx).bytes(),
|
||||||
align: field_layout.align(&tcx.data_layout).abi(),
|
align: field_layout.align(tcx).abi(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1343,8 +1343,8 @@ fn gather_type_sizes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||||
session::VariantInfo {
|
session::VariantInfo {
|
||||||
name: Some(name.to_string()),
|
name: Some(name.to_string()),
|
||||||
kind: session::SizeKind::Exact,
|
kind: session::SizeKind::Exact,
|
||||||
align: value.align(&tcx.data_layout).abi(),
|
align: value.align(tcx).abi(),
|
||||||
size: value.size(&tcx.data_layout).bytes(),
|
size: value.size(tcx).bytes(),
|
||||||
fields: vec![],
|
fields: vec![],
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,7 +27,7 @@ use monomorphize;
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
use value::Value;
|
use value::Value;
|
||||||
use rustc::ty::{self, Ty, TyCtxt};
|
use rustc::ty::{self, Ty, TyCtxt};
|
||||||
use rustc::ty::layout::Layout;
|
use rustc::ty::layout::{Layout, LayoutTyper};
|
||||||
use rustc::ty::subst::{Subst, Substs};
|
use rustc::ty::subst::{Subst, Substs};
|
||||||
use rustc::hir;
|
use rustc::hir;
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -
|
||||||
Layout::UntaggedUnion { .. } |
|
Layout::UntaggedUnion { .. } |
|
||||||
Layout::RawNullablePointer { .. } |
|
Layout::RawNullablePointer { .. } |
|
||||||
Layout::StructWrappedNullablePointer { .. } => {
|
Layout::StructWrappedNullablePointer { .. } => {
|
||||||
!layout.is_unsized() && layout.size(&ccx.tcx().data_layout).bytes() == 0
|
!layout.is_unsized() && layout.size(ccx).bytes() == 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@ pub fn type_is_imm_pair<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>)
|
||||||
/// Identify types which have size zero at runtime.
|
/// Identify types which have size zero at runtime.
|
||||||
pub fn type_is_zero_size<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
|
pub fn type_is_zero_size<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
|
||||||
let layout = ccx.layout_of(ty);
|
let layout = ccx.layout_of(ty);
|
||||||
!layout.is_unsized() && layout.size(&ccx.tcx().data_layout).bytes() == 0
|
!layout.is_unsized() && layout.size(ccx).bytes() == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -28,6 +28,7 @@ use type_::Type;
|
||||||
use rustc_data_structures::base_n;
|
use rustc_data_structures::base_n;
|
||||||
use rustc::ty::subst::Substs;
|
use rustc::ty::subst::Substs;
|
||||||
use rustc::ty::{self, Ty, TyCtxt};
|
use rustc::ty::{self, Ty, TyCtxt};
|
||||||
|
use rustc::ty::layout::{LayoutTyper, TyLayout};
|
||||||
use session::config::NoDebugInfo;
|
use session::config::NoDebugInfo;
|
||||||
use session::Session;
|
use session::Session;
|
||||||
use session::config;
|
use session::config;
|
||||||
|
@ -828,18 +829,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
|
||||||
TypeOfDepthLock(self.local())
|
TypeOfDepthLock(self.local())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layout_of(&self, ty: Ty<'tcx>) -> ty::layout::TyLayout<'tcx> {
|
|
||||||
self.tcx().infer_ctxt((), traits::Reveal::All).enter(|infcx| {
|
|
||||||
ty::layout::TyLayout::of(&infcx, ty).unwrap_or_else(|e| {
|
|
||||||
match e {
|
|
||||||
ty::layout::LayoutError::SizeOverflow(_) =>
|
|
||||||
self.sess().fatal(&e.to_string()),
|
|
||||||
_ => bug!("failed to get layout for `{}`: {}", ty, e)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn check_overflow(&self) -> bool {
|
pub fn check_overflow(&self) -> bool {
|
||||||
self.shared.check_overflow
|
self.shared.check_overflow
|
||||||
}
|
}
|
||||||
|
@ -951,6 +940,54 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> ty::layout::HasDataLayout for &'a SharedCrateContext<'a, 'tcx> {
|
||||||
|
fn data_layout(&self) -> &ty::layout::TargetDataLayout {
|
||||||
|
&self.tcx.data_layout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> ty::layout::HasTyCtxt<'tcx> for &'a SharedCrateContext<'a, 'tcx> {
|
||||||
|
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
|
||||||
|
self.tcx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> ty::layout::HasDataLayout for &'a CrateContext<'a, 'tcx> {
|
||||||
|
fn data_layout(&self) -> &ty::layout::TargetDataLayout {
|
||||||
|
&self.shared.tcx.data_layout
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> ty::layout::HasTyCtxt<'tcx> for &'a CrateContext<'a, 'tcx> {
|
||||||
|
fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
|
||||||
|
self.shared.tcx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> LayoutTyper<'tcx> for &'a SharedCrateContext<'a, 'tcx> {
|
||||||
|
type TyLayout = TyLayout<'tcx>;
|
||||||
|
|
||||||
|
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
|
||||||
|
self.tcx().infer_ctxt((), traits::Reveal::All).enter(|infcx| {
|
||||||
|
infcx.layout_of(ty).unwrap_or_else(|e| {
|
||||||
|
match e {
|
||||||
|
ty::layout::LayoutError::SizeOverflow(_) =>
|
||||||
|
self.sess().fatal(&e.to_string()),
|
||||||
|
_ => bug!("failed to get layout for `{}`: {}", ty, e)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'tcx> LayoutTyper<'tcx> for &'a CrateContext<'a, 'tcx> {
|
||||||
|
type TyLayout = TyLayout<'tcx>;
|
||||||
|
|
||||||
|
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
|
||||||
|
self.shared.layout_of(ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'tcx>);
|
pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'tcx>);
|
||||||
|
|
||||||
impl<'a, 'tcx> Drop for TypeOfDepthLock<'a, 'tcx> {
|
impl<'a, 'tcx> Drop for TypeOfDepthLock<'a, 'tcx> {
|
||||||
|
|
|
@ -35,7 +35,8 @@ use rustc_data_structures::ToHex;
|
||||||
use {type_of, machine, monomorphize};
|
use {type_of, machine, monomorphize};
|
||||||
use common::{self, CrateContext};
|
use common::{self, CrateContext};
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
use rustc::ty::{self, AdtKind, Ty, layout};
|
use rustc::ty::{self, AdtKind, Ty};
|
||||||
|
use rustc::ty::layout::{self, LayoutTyper};
|
||||||
use session::config;
|
use session::config;
|
||||||
use util::nodemap::FxHashMap;
|
use util::nodemap::FxHashMap;
|
||||||
use util::common::path2cstr;
|
use util::common::path2cstr;
|
||||||
|
@ -900,7 +901,7 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> {
|
||||||
let offsets = match *layout {
|
let offsets = match *layout {
|
||||||
layout::Univariant { ref variant, .. } => &variant.offsets,
|
layout::Univariant { ref variant, .. } => &variant.offsets,
|
||||||
layout::Vector { element, count } => {
|
layout::Vector { element, count } => {
|
||||||
let element_size = element.size(&cx.tcx().data_layout).bytes();
|
let element_size = element.size(cx).bytes();
|
||||||
tmp = (0..count).
|
tmp = (0..count).
|
||||||
map(|i| layout::Size::from_bytes(i*element_size))
|
map(|i| layout::Size::from_bytes(i*element_size))
|
||||||
.collect::<Vec<layout::Size>>();
|
.collect::<Vec<layout::Size>>();
|
||||||
|
|
|
@ -18,6 +18,7 @@ use llvm;
|
||||||
use llvm::{ValueRef};
|
use llvm::{ValueRef};
|
||||||
use rustc::traits;
|
use rustc::traits;
|
||||||
use rustc::ty::{self, Ty, TypeFoldable};
|
use rustc::ty::{self, Ty, TypeFoldable};
|
||||||
|
use rustc::ty::layout::LayoutTyper;
|
||||||
use common::*;
|
use common::*;
|
||||||
use meth;
|
use meth;
|
||||||
use monomorphize;
|
use monomorphize;
|
||||||
|
@ -47,7 +48,7 @@ pub fn needs_drop_glue<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, t: Ty<'tcx>
|
||||||
if !scx.type_needs_drop(typ) && scx.type_is_sized(typ) {
|
if !scx.type_needs_drop(typ) && scx.type_is_sized(typ) {
|
||||||
scx.tcx().infer_ctxt((), traits::Reveal::All).enter(|infcx| {
|
scx.tcx().infer_ctxt((), traits::Reveal::All).enter(|infcx| {
|
||||||
let layout = t.layout(&infcx).unwrap();
|
let layout = t.layout(&infcx).unwrap();
|
||||||
if layout.size(&scx.tcx().data_layout).bytes() == 0 {
|
if layout.size(scx).bytes() == 0 {
|
||||||
// `Box<ZeroSizeType>` does not allocate.
|
// `Box<ZeroSizeType>` does not allocate.
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -12,7 +12,8 @@ use llvm::{self, ValueRef, BasicBlockRef};
|
||||||
use rustc_const_eval::{ErrKind, ConstEvalErr, note_const_eval_err};
|
use rustc_const_eval::{ErrKind, ConstEvalErr, note_const_eval_err};
|
||||||
use rustc::middle::lang_items;
|
use rustc::middle::lang_items;
|
||||||
use rustc::middle::const_val::ConstInt;
|
use rustc::middle::const_val::ConstInt;
|
||||||
use rustc::ty::{self, layout, TypeFoldable};
|
use rustc::ty::{self, TypeFoldable};
|
||||||
|
use rustc::ty::layout::{self, LayoutTyper};
|
||||||
use rustc::mir;
|
use rustc::mir;
|
||||||
use abi::{Abi, FnType, ArgType};
|
use abi::{Abi, FnType, ArgType};
|
||||||
use base::{self, Lifetime};
|
use base::{self, Lifetime};
|
||||||
|
|
|
@ -18,7 +18,8 @@ use rustc::hir::def_id::DefId;
|
||||||
use rustc::infer::TransNormalize;
|
use rustc::infer::TransNormalize;
|
||||||
use rustc::mir;
|
use rustc::mir;
|
||||||
use rustc::mir::tcx::LvalueTy;
|
use rustc::mir::tcx::LvalueTy;
|
||||||
use rustc::ty::{self, layout, Ty, TyCtxt, TypeFoldable};
|
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||||
|
use rustc::ty::layout::{self, LayoutTyper};
|
||||||
use rustc::ty::cast::{CastTy, IntTy};
|
use rustc::ty::cast::{CastTy, IntTy};
|
||||||
use rustc::ty::subst::{Kind, Substs, Subst};
|
use rustc::ty::subst::{Kind, Substs, Subst};
|
||||||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||||
|
@ -979,7 +980,6 @@ fn trans_const<'a, 'tcx>(
|
||||||
vals: &[ValueRef]
|
vals: &[ValueRef]
|
||||||
) -> ValueRef {
|
) -> ValueRef {
|
||||||
let l = ccx.layout_of(t);
|
let l = ccx.layout_of(t);
|
||||||
let dl = &ccx.tcx().data_layout;
|
|
||||||
let variant_index = match *kind {
|
let variant_index = match *kind {
|
||||||
mir::AggregateKind::Adt(_, index, _, _) => index,
|
mir::AggregateKind::Adt(_, index, _, _) => index,
|
||||||
_ => 0,
|
_ => 0,
|
||||||
|
@ -1002,7 +1002,7 @@ fn trans_const<'a, 'tcx>(
|
||||||
let mut vals_with_discr = vec![lldiscr];
|
let mut vals_with_discr = vec![lldiscr];
|
||||||
vals_with_discr.extend_from_slice(vals);
|
vals_with_discr.extend_from_slice(vals);
|
||||||
let mut contents = build_const_struct(ccx, &variant, &vals_with_discr[..]);
|
let mut contents = build_const_struct(ccx, &variant, &vals_with_discr[..]);
|
||||||
let needed_padding = l.size(dl).bytes() - variant.stride().bytes();
|
let needed_padding = l.size(ccx).bytes() - variant.stride().bytes();
|
||||||
if needed_padding > 0 {
|
if needed_padding > 0 {
|
||||||
contents.push(padding(ccx, needed_padding));
|
contents.push(padding(ccx, needed_padding));
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use llvm::ValueRef;
|
use llvm::ValueRef;
|
||||||
use rustc::ty::{self, layout, Ty, TypeFoldable};
|
use rustc::ty::{self, Ty, TypeFoldable};
|
||||||
|
use rustc::ty::layout::{self, LayoutTyper};
|
||||||
use rustc::mir;
|
use rustc::mir;
|
||||||
use rustc::mir::tcx::LvalueTy;
|
use rustc::mir::tcx::LvalueTy;
|
||||||
use rustc_data_structures::indexed_vec::Idx;
|
use rustc_data_structures::indexed_vec::Idx;
|
||||||
|
|
|
@ -11,7 +11,8 @@
|
||||||
use libc::c_uint;
|
use libc::c_uint;
|
||||||
use llvm::{self, ValueRef, BasicBlockRef};
|
use llvm::{self, ValueRef, BasicBlockRef};
|
||||||
use llvm::debuginfo::DIScope;
|
use llvm::debuginfo::DIScope;
|
||||||
use rustc::ty::{self, layout};
|
use rustc::ty;
|
||||||
|
use rustc::ty::layout::{self, LayoutTyper};
|
||||||
use rustc::mir::{self, Mir};
|
use rustc::mir::{self, Mir};
|
||||||
use rustc::mir::tcx::LvalueTy;
|
use rustc::mir::tcx::LvalueTy;
|
||||||
use rustc::ty::subst::Substs;
|
use rustc::ty::subst::Substs;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
use llvm::ValueRef;
|
use llvm::ValueRef;
|
||||||
use rustc::ty::{self, Ty};
|
use rustc::ty::{self, Ty};
|
||||||
use rustc::ty::layout::Layout;
|
use rustc::ty::layout::{Layout, LayoutTyper};
|
||||||
use rustc::mir;
|
use rustc::mir;
|
||||||
use rustc::mir::tcx::LvalueTy;
|
use rustc::mir::tcx::LvalueTy;
|
||||||
use rustc_data_structures::indexed_vec::Idx;
|
use rustc_data_structures::indexed_vec::Idx;
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
use llvm::{self, ValueRef};
|
use llvm::{self, ValueRef};
|
||||||
use rustc::ty::{self, Ty};
|
use rustc::ty::{self, Ty};
|
||||||
use rustc::ty::cast::{CastTy, IntTy};
|
use rustc::ty::cast::{CastTy, IntTy};
|
||||||
use rustc::ty::layout::Layout;
|
use rustc::ty::layout::{Layout, LayoutTyper};
|
||||||
use rustc::mir::tcx::LvalueTy;
|
use rustc::mir::tcx::LvalueTy;
|
||||||
use rustc::mir;
|
use rustc::mir;
|
||||||
use middle::lang_items::ExchangeMallocFnLangItem;
|
use middle::lang_items::ExchangeMallocFnLangItem;
|
||||||
|
|
|
@ -13,6 +13,7 @@ use adt;
|
||||||
use common::*;
|
use common::*;
|
||||||
use machine;
|
use machine;
|
||||||
use rustc::ty::{self, Ty, TypeFoldable};
|
use rustc::ty::{self, Ty, TypeFoldable};
|
||||||
|
use rustc::ty::layout::LayoutTyper;
|
||||||
use trans_item::DefPathBasedNames;
|
use trans_item::DefPathBasedNames;
|
||||||
use type_::Type;
|
use type_::Type;
|
||||||
|
|
||||||
|
@ -117,14 +118,14 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
|
||||||
return llsizingty;
|
return llsizingty;
|
||||||
}
|
}
|
||||||
|
|
||||||
let r = layout.size(&cx.tcx().data_layout).bytes();
|
let r = layout.size(cx).bytes();
|
||||||
let l = machine::llsize_of_alloc(cx, llsizingty);
|
let l = machine::llsize_of_alloc(cx, llsizingty);
|
||||||
if r != l {
|
if r != l {
|
||||||
bug!("size differs (rustc: {}, llvm: {}) for type `{}` / {:#?}",
|
bug!("size differs (rustc: {}, llvm: {}) for type `{}` / {:#?}",
|
||||||
r, l, t, layout);
|
r, l, t, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
let r = layout.align(&cx.tcx().data_layout).abi();
|
let r = layout.align(cx).abi();
|
||||||
let l = machine::llalign_of_min(cx, llsizingty) as u64;
|
let l = machine::llalign_of_min(cx, llsizingty) as u64;
|
||||||
if r != l {
|
if r != l {
|
||||||
bug!("align differs (rustc: {}, llvm: {}) for type `{}` / {:#?}",
|
bug!("align differs (rustc: {}, llvm: {}) for type `{}` / {:#?}",
|
||||||
|
@ -324,13 +325,11 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
|
||||||
|
|
||||||
impl<'a, 'tcx> CrateContext<'a, 'tcx> {
|
impl<'a, 'tcx> CrateContext<'a, 'tcx> {
|
||||||
pub fn align_of(&self, ty: Ty<'tcx>) -> machine::llalign {
|
pub fn align_of(&self, ty: Ty<'tcx>) -> machine::llalign {
|
||||||
let layout = self.layout_of(ty);
|
self.layout_of(ty).align(self).abi() as machine::llalign
|
||||||
layout.align(&self.tcx().data_layout).abi() as machine::llalign
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn size_of(&self, ty: Ty<'tcx>) -> machine::llsize {
|
pub fn size_of(&self, ty: Ty<'tcx>) -> machine::llsize {
|
||||||
let layout = self.layout_of(ty);
|
self.layout_of(ty).size(self).bytes() as machine::llsize
|
||||||
layout.size(&self.tcx().data_layout).bytes() as machine::llsize
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue