Auto merge of #36151 - camlorn:struct_layout_optimization, r=eddyb

refactor to remove trans::adt and make rustc::ty::layout authoritative

I asked on IRC about optimizing struct layout by reordering fields from most-aligned to least-aligned and somehow ended up getting talked into doing this.  The goal here is to make `layout` authoritative and to remove `adt`.  The former has been accomplished by reimplementing `represent_type_uncached` and the latter is in progress.  @eddyb thought I should make the PR now.

My plan is to reserve the actual optimization for a second PR, as this work is useful by itself.
This commit is contained in:
bors 2016-09-25 18:47:00 -07:00 committed by GitHub
commit 9966397b61
21 changed files with 536 additions and 1004 deletions

View File

@ -489,6 +489,9 @@ pub struct GlobalCtxt<'tcx> {
/// Cache for layouts computed from types. /// Cache for layouts computed from types.
pub layout_cache: RefCell<FnvHashMap<Ty<'tcx>, &'tcx Layout>>, pub layout_cache: RefCell<FnvHashMap<Ty<'tcx>, &'tcx Layout>>,
/// Used to prevent layout from recursing too deeply.
pub layout_depth: Cell<usize>,
/// Map from function to the `#[derive]` mode that it's defining. Only used /// Map from function to the `#[derive]` mode that it's defining. Only used
/// by `rustc-macro` crates. /// by `rustc-macro` crates.
pub derive_macros: RefCell<NodeMap<token::InternedString>>, pub derive_macros: RefCell<NodeMap<token::InternedString>>,
@ -760,6 +763,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
crate_name: token::intern_and_get_ident(crate_name), crate_name: token::intern_and_get_ident(crate_name),
data_layout: data_layout, data_layout: data_layout,
layout_cache: RefCell::new(FnvHashMap()), layout_cache: RefCell::new(FnvHashMap()),
layout_depth: Cell::new(0),
derive_macros: RefCell::new(NodeMap()), derive_macros: RefCell::new(NodeMap()),
}, f) }, f)
} }

View File

@ -328,6 +328,42 @@ pub enum Integer {
} }
impl Integer { impl Integer {
pub fn size(&self) -> Size {
match *self {
I1 => Size::from_bits(1),
I8 => Size::from_bytes(1),
I16 => Size::from_bytes(2),
I32 => Size::from_bytes(4),
I64 => Size::from_bytes(8),
}
}
pub fn align(&self, dl: &TargetDataLayout)-> Align {
match *self {
I1 => dl.i1_align,
I8 => dl.i8_align,
I16 => dl.i16_align,
I32 => dl.i32_align,
I64 => dl.i64_align,
}
}
pub fn to_ty<'a, 'tcx>(&self, tcx: &ty::TyCtxt<'a, 'tcx, 'tcx>,
signed: bool) -> Ty<'tcx> {
match (*self, signed) {
(I1, false) => tcx.types.u8,
(I8, false) => tcx.types.u8,
(I16, false) => tcx.types.u16,
(I32, false) => tcx.types.u32,
(I64, false) => tcx.types.u64,
(I1, true) => tcx.types.i8,
(I8, true) => tcx.types.i8,
(I16, true) => tcx.types.i16,
(I32, true) => tcx.types.i32,
(I64, true) => tcx.types.i64,
}
}
/// Find the smallest Integer type which can represent the signed value. /// Find the smallest Integer type which can represent the signed value.
pub fn fit_signed(x: i64) -> Integer { pub fn fit_signed(x: i64) -> Integer {
match x { match x {
@ -350,6 +386,18 @@ impl Integer {
} }
} }
/// Find the smallest integer with the given alignment.
pub fn for_abi_align(dl: &TargetDataLayout, align: Align) -> Option<Integer> {
let wanted = align.abi();
for &candidate in &[I8, I16, I32, I64] {
let ty = Int(candidate);
if wanted == ty.align(dl).abi() && wanted == ty.size(dl).bytes() {
return Some(candidate);
}
}
None
}
/// 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(dl: &TargetDataLayout, ity: attr::IntType) -> Integer {
match ity { match ity {
@ -623,6 +671,15 @@ impl<'a, 'gcx, 'tcx> Struct {
} }
Ok(None) Ok(None)
} }
pub fn offset_of_field(&self, index: usize) -> Size {
assert!(index < self.offset_after_field.len());
if index == 0 {
Size::from_bytes(0)
} else {
self.offset_after_field[index-1]
}
}
} }
/// An untagged union. /// An untagged union.
@ -912,7 +969,7 @@ impl<'a, 'gcx, 'tcx> Layout {
Univariant { variant: unit, non_zero: false } Univariant { variant: unit, non_zero: false }
} }
// Tuples. // Tuples and closures.
ty::TyClosure(_, ty::ClosureSubsts { upvar_tys: tys, .. }) | ty::TyClosure(_, ty::ClosureSubsts { upvar_tys: tys, .. }) |
ty::TyTuple(tys) => { ty::TyTuple(tys) => {
let mut st = Struct::new(dl, false); let mut st = Struct::new(dl, false);
@ -972,10 +1029,10 @@ impl<'a, 'gcx, 'tcx> Layout {
}); });
} }
if def.variants.len() == 1 { if !def.is_enum() || def.variants.len() == 1 && hint == attr::ReprAny {
// Struct, or union, or univariant enum equivalent to a struct. // Struct, or union, or univariant enum equivalent to a struct.
// (Typechecking will reject discriminant-sizing attrs.) // (Typechecking will reject discriminant-sizing attrs.)
assert!(!def.is_enum() || hint == attr::ReprAny);
let fields = def.variants[0].fields.iter().map(|field| { let fields = def.variants[0].fields.iter().map(|field| {
field.ty(tcx, substs).layout(infcx) field.ty(tcx, substs).layout(infcx)
}); });
@ -1103,20 +1160,7 @@ impl<'a, 'gcx, 'tcx> Layout {
// won't be so conservative. // won't be so conservative.
// Use the initial field alignment // Use the initial field alignment
let wanted = start_align.abi(); let mut ity = Integer::for_abi_align(dl, start_align).unwrap_or(min_ity);
let mut ity = min_ity;
for &candidate in &[I16, I32, I64] {
let ty = Int(candidate);
if wanted == ty.align(dl).abi() && wanted == ty.size(dl).bytes() {
ity = candidate;
break;
}
}
// FIXME(eddyb) conservative only to avoid diverging from trans::adt.
if align.abi() != start_align.abi() {
ity = min_ity;
}
// If the alignment is not larger than the chosen discriminant size, // If the alignment is not larger than the chosen discriminant size,
// don't use the alignment as the final size. // don't use the alignment as the final size.

View File

@ -608,10 +608,19 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
} }
} }
let rec_limit = tcx.sess.recursion_limit.get();
let depth = tcx.layout_depth.get();
if depth > rec_limit {
tcx.sess.fatal(
&format!("overflow representing the type `{}`", self));
}
tcx.layout_depth.set(depth+1);
let layout = Layout::compute_uncached(self, infcx)?; let layout = Layout::compute_uncached(self, infcx)?;
if can_cache { if can_cache {
tcx.layout_cache.borrow_mut().insert(self, layout); tcx.layout_cache.borrow_mut().insert(self, layout);
} }
tcx.layout_depth.set(depth);
Ok(layout) Ok(layout)
} }

View File

@ -24,7 +24,7 @@ use cabi_s390x;
use cabi_mips; use cabi_mips;
use cabi_mips64; use cabi_mips64;
use cabi_asmjs; use cabi_asmjs;
use machine::{llalign_of_min, llsize_of, llsize_of_real, llsize_of_store}; use machine::{llalign_of_min, llsize_of, llsize_of_alloc};
use type_::Type; use type_::Type;
use type_of; use type_of;
@ -102,7 +102,7 @@ impl ArgType {
// Wipe old attributes, likely not valid through indirection. // Wipe old attributes, likely not valid through indirection.
self.attrs = llvm::Attributes::default(); self.attrs = llvm::Attributes::default();
let llarg_sz = llsize_of_real(ccx, self.ty); let llarg_sz = llsize_of_alloc(ccx, self.ty);
// For non-immediate arguments the callee gets its own copy of // For non-immediate arguments the callee gets its own copy of
// the value on the stack, so there are no aliases. It's also // the value on the stack, so there are no aliases. It's also
@ -200,7 +200,7 @@ impl ArgType {
base::call_memcpy(bcx, base::call_memcpy(bcx,
bcx.pointercast(dst, Type::i8p(ccx)), bcx.pointercast(dst, Type::i8p(ccx)),
bcx.pointercast(llscratch, Type::i8p(ccx)), bcx.pointercast(llscratch, Type::i8p(ccx)),
C_uint(ccx, llsize_of_store(ccx, self.ty)), C_uint(ccx, llsize_of_alloc(ccx, self.ty)),
cmp::min(llalign_of_min(ccx, self.ty), cmp::min(llalign_of_min(ccx, self.ty),
llalign_of_min(ccx, ty)) as u32); llalign_of_min(ccx, ty)) as u32);
@ -327,7 +327,7 @@ impl FnType {
if let Layout::CEnum { signed, .. } = *ccx.layout_of(ty) { if let Layout::CEnum { signed, .. } = *ccx.layout_of(ty) {
arg.signedness = Some(signed); arg.signedness = Some(signed);
} }
if llsize_of_real(ccx, arg.ty) == 0 { if llsize_of_alloc(ccx, arg.ty) == 0 {
// For some forsaken reason, x86_64-pc-windows-gnu // For some forsaken reason, x86_64-pc-windows-gnu
// doesn't ignore zero-sized struct arguments. // doesn't ignore zero-sized struct arguments.
// The same is true for s390x-unknown-linux-gnu. // The same is true for s390x-unknown-linux-gnu.
@ -358,7 +358,7 @@ impl FnType {
ty::TyRef(_, ty::TypeAndMut { ty, .. }) | ty::TyRef(_, ty::TypeAndMut { ty, .. }) |
ty::TyBox(ty) => { ty::TyBox(ty) => {
let llty = type_of::sizing_type_of(ccx, ty); let llty = type_of::sizing_type_of(ccx, ty);
let llsz = llsize_of_real(ccx, llty); let llsz = llsize_of_alloc(ccx, llty);
ret.attrs.set_dereferenceable(llsz); ret.attrs.set_dereferenceable(llsz);
} }
_ => {} _ => {}
@ -427,7 +427,7 @@ impl FnType {
} else { } else {
if let Some(inner) = rust_ptr_attrs(ty, &mut arg) { if let Some(inner) = rust_ptr_attrs(ty, &mut arg) {
let llty = type_of::sizing_type_of(ccx, inner); let llty = type_of::sizing_type_of(ccx, inner);
let llsz = llsize_of_real(ccx, llty); let llsz = llsize_of_alloc(ccx, llty);
arg.attrs.set_dereferenceable(llsz); arg.attrs.set_dereferenceable(llsz);
} }
args.push(arg); args.push(arg);
@ -469,8 +469,8 @@ impl FnType {
return; return;
} }
let size = llsize_of_real(ccx, llty); let size = llsize_of_alloc(ccx, llty);
if size > llsize_of_real(ccx, ccx.int_type()) { if size > llsize_of_alloc(ccx, ccx.int_type()) {
arg.make_indirect(ccx); arg.make_indirect(ccx);
} else if size > 0 { } else if size > 0 {
// We want to pass small aggregates as immediates, but using // We want to pass small aggregates as immediates, but using

File diff suppressed because it is too large Load Diff

View File

@ -466,32 +466,27 @@ pub fn coerce_unsized_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
store_fat_ptr(bcx, base, info, dst, dst_ty); store_fat_ptr(bcx, base, info, dst, dst_ty);
} }
// This can be extended to enums and tuples in the future. (&ty::TyAdt(def_a, substs_a), &ty::TyAdt(def_b, substs_b)) => {
(&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) => {
assert_eq!(def_a, def_b); assert_eq!(def_a, def_b);
let src_repr = adt::represent_type(bcx.ccx(), src_ty); let src_fields = def_a.variants[0].fields.iter().map(|f| {
let src_fields = match &*src_repr { monomorphize::field_ty(bcx.tcx(), substs_a, f)
&adt::Repr::Univariant(ref s) => &s.fields, });
_ => bug!("struct has non-univariant repr"), let dst_fields = def_b.variants[0].fields.iter().map(|f| {
}; monomorphize::field_ty(bcx.tcx(), substs_b, f)
let dst_repr = adt::represent_type(bcx.ccx(), dst_ty); });
let dst_fields = match &*dst_repr {
&adt::Repr::Univariant(ref s) => &s.fields,
_ => bug!("struct has non-univariant repr"),
};
let src = adt::MaybeSizedValue::sized(src); let src = adt::MaybeSizedValue::sized(src);
let dst = adt::MaybeSizedValue::sized(dst); let dst = adt::MaybeSizedValue::sized(dst);
let iter = src_fields.iter().zip(dst_fields).enumerate(); let iter = src_fields.zip(dst_fields).enumerate();
for (i, (src_fty, dst_fty)) in iter { for (i, (src_fty, dst_fty)) in iter {
if type_is_zero_size(bcx.ccx(), dst_fty) { if type_is_zero_size(bcx.ccx(), dst_fty) {
continue; continue;
} }
let src_f = adt::trans_field_ptr(bcx, &src_repr, src, Disr(0), i); let src_f = adt::trans_field_ptr(bcx, src_ty, src, Disr(0), i);
let dst_f = adt::trans_field_ptr(bcx, &dst_repr, dst, Disr(0), i); let dst_f = adt::trans_field_ptr(bcx, dst_ty, dst, Disr(0), i);
if src_fty == dst_fty { if src_fty == dst_fty {
memcpy_ty(bcx, dst_f, src_f, src_fty); memcpy_ty(bcx, dst_f, src_f, src_fty);
} else { } else {
@ -1164,11 +1159,10 @@ pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
if !fcx.fn_ty.ret.is_ignore() { if !fcx.fn_ty.ret.is_ignore() {
let dest = fcx.llretslotptr.get().unwrap(); let dest = fcx.llretslotptr.get().unwrap();
let dest_val = adt::MaybeSizedValue::sized(dest); // Can return unsized value let dest_val = adt::MaybeSizedValue::sized(dest); // Can return unsized value
let repr = adt::represent_type(ccx, sig.output);
let mut llarg_idx = fcx.fn_ty.ret.is_indirect() as usize; let mut llarg_idx = fcx.fn_ty.ret.is_indirect() as usize;
let mut arg_idx = 0; let mut arg_idx = 0;
for (i, arg_ty) in sig.inputs.into_iter().enumerate() { for (i, arg_ty) in sig.inputs.into_iter().enumerate() {
let lldestptr = adt::trans_field_ptr(bcx, &repr, dest_val, Disr::from(disr), i); let lldestptr = adt::trans_field_ptr(bcx, sig.output, dest_val, Disr::from(disr), i);
let arg = &fcx.fn_ty.args[arg_idx]; let arg = &fcx.fn_ty.args[arg_idx];
arg_idx += 1; arg_idx += 1;
let b = &bcx.build(); let b = &bcx.build();
@ -1181,7 +1175,7 @@ pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
arg.store_fn_arg(b, &mut llarg_idx, lldestptr); arg.store_fn_arg(b, &mut llarg_idx, lldestptr);
} }
} }
adt::trans_set_discr(bcx, &repr, dest, disr); adt::trans_set_discr(bcx, sig.output, dest, disr);
} }
fcx.finish(bcx, DebugLoc::None); fcx.finish(bcx, DebugLoc::None);

View File

@ -875,12 +875,6 @@ pub fn const_get_elt(v: ValueRef, us: &[c_uint])
} }
} }
pub fn const_to_int(v: ValueRef) -> i64 {
unsafe {
llvm::LLVMConstIntGetSExtValue(v)
}
}
pub fn const_to_uint(v: ValueRef) -> u64 { pub fn const_to_uint(v: ValueRef) -> u64 {
unsafe { unsafe {
llvm::LLVMConstIntGetZExtValue(v) llvm::LLVMConstIntGetZExtValue(v)

View File

@ -17,7 +17,6 @@ use rustc::hir::def_id::DefId;
use rustc::traits; use rustc::traits;
use rustc::mir::mir_map::MirMap; use rustc::mir::mir_map::MirMap;
use rustc::mir::repr as mir; use rustc::mir::repr as mir;
use adt;
use base; use base;
use builder::Builder; use builder::Builder;
use common::BuilderRef_res; use common::BuilderRef_res;
@ -142,7 +141,6 @@ pub struct LocalCrateContext<'tcx> {
lltypes: RefCell<FnvHashMap<Ty<'tcx>, Type>>, lltypes: RefCell<FnvHashMap<Ty<'tcx>, Type>>,
llsizingtypes: RefCell<FnvHashMap<Ty<'tcx>, Type>>, llsizingtypes: RefCell<FnvHashMap<Ty<'tcx>, Type>>,
adt_reprs: RefCell<FnvHashMap<Ty<'tcx>, Rc<adt::Repr<'tcx>>>>,
type_hashcodes: RefCell<FnvHashMap<Ty<'tcx>, String>>, type_hashcodes: RefCell<FnvHashMap<Ty<'tcx>, String>>,
int_type: Type, int_type: Type,
opaque_vec_type: Type, opaque_vec_type: Type,
@ -677,7 +675,6 @@ impl<'tcx> LocalCrateContext<'tcx> {
statics_to_rauw: RefCell::new(Vec::new()), statics_to_rauw: RefCell::new(Vec::new()),
lltypes: RefCell::new(FnvHashMap()), lltypes: RefCell::new(FnvHashMap()),
llsizingtypes: RefCell::new(FnvHashMap()), llsizingtypes: RefCell::new(FnvHashMap()),
adt_reprs: RefCell::new(FnvHashMap()),
type_hashcodes: RefCell::new(FnvHashMap()), type_hashcodes: RefCell::new(FnvHashMap()),
int_type: Type::from_ref(ptr::null_mut()), int_type: Type::from_ref(ptr::null_mut()),
opaque_vec_type: Type::from_ref(ptr::null_mut()), opaque_vec_type: Type::from_ref(ptr::null_mut()),
@ -918,10 +915,6 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
&self.local().llsizingtypes &self.local().llsizingtypes
} }
pub fn adt_reprs<'a>(&'a self) -> &'a RefCell<FnvHashMap<Ty<'tcx>, Rc<adt::Repr<'tcx>>>> {
&self.local().adt_reprs
}
pub fn symbol_hasher<'a>(&'a self) -> &'a RefCell<Sha256> { pub fn symbol_hasher<'a>(&'a self) -> &'a RefCell<Sha256> {
&self.shared.symbol_hasher &self.shared.symbol_hasher
} }
@ -994,7 +987,11 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
pub fn layout_of(&self, ty: Ty<'tcx>) -> &'tcx ty::layout::Layout { pub fn layout_of(&self, ty: Ty<'tcx>) -> &'tcx ty::layout::Layout {
self.tcx().infer_ctxt(None, None, traits::Reveal::All).enter(|infcx| { self.tcx().infer_ctxt(None, None, traits::Reveal::All).enter(|infcx| {
ty.layout(&infcx).unwrap_or_else(|e| { ty.layout(&infcx).unwrap_or_else(|e| {
bug!("failed to get layout for `{}`: {}", ty, e); match e {
ty::layout::LayoutError::SizeOverflow(_) =>
self.sess().fatal(&e.to_string()),
_ => bug!("failed to get layout for `{}`: {}", ty, e)
}
}) })
}) })
} }

View File

@ -27,10 +27,10 @@ use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType, DI
use rustc::hir::def_id::DefId; use rustc::hir::def_id::DefId;
use rustc::ty::subst::Substs; use rustc::ty::subst::Substs;
use rustc::hir; use rustc::hir;
use {type_of, adt, machine, monomorphize}; use {type_of, machine, monomorphize};
use common::CrateContext; use common::CrateContext;
use type_::Type; use type_::Type;
use rustc::ty::{self, AdtKind, Ty}; use rustc::ty::{self, AdtKind, Ty, layout};
use session::config; use session::config;
use util::nodemap::FnvHashMap; use util::nodemap::FnvHashMap;
use util::common::path2cstr; use util::common::path2cstr;
@ -40,7 +40,6 @@ use std::ffi::CString;
use std::path::Path; use std::path::Path;
use std::ptr; use std::ptr;
use std::rc::Rc; use std::rc::Rc;
use syntax;
use syntax::util::interner::Interner; use syntax::util::interner::Interner;
use syntax::ast; use syntax::ast;
use syntax::parse::token; use syntax::parse::token;
@ -1281,7 +1280,7 @@ fn prepare_union_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
// offset of zero bytes). // offset of zero bytes).
struct EnumMemberDescriptionFactory<'tcx> { struct EnumMemberDescriptionFactory<'tcx> {
enum_type: Ty<'tcx>, enum_type: Ty<'tcx>,
type_rep: Rc<adt::Repr<'tcx>>, type_rep: &'tcx layout::Layout,
discriminant_type_metadata: Option<DIType>, discriminant_type_metadata: Option<DIType>,
containing_scope: DIScope, containing_scope: DIScope,
file_metadata: DIFile, file_metadata: DIFile,
@ -1292,11 +1291,15 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>) fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
-> Vec<MemberDescription> { -> Vec<MemberDescription> {
let adt = &self.enum_type.ty_adt_def().unwrap(); let adt = &self.enum_type.ty_adt_def().unwrap();
let substs = match self.enum_type.sty {
ty::TyAdt(def, ref s) if def.adt_kind() == AdtKind::Enum => s,
_ => bug!("{} is not an enum", self.enum_type)
};
match *self.type_rep { match *self.type_rep {
adt::General(_, ref struct_defs) => { layout::General { ref variants, .. } => {
let discriminant_info = RegularDiscriminant(self.discriminant_type_metadata let discriminant_info = RegularDiscriminant(self.discriminant_type_metadata
.expect("")); .expect(""));
struct_defs variants
.iter() .iter()
.enumerate() .enumerate()
.map(|(i, struct_def)| { .map(|(i, struct_def)| {
@ -1327,7 +1330,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
} }
}).collect() }).collect()
}, },
adt::Univariant(ref struct_def) => { layout::Univariant{ ref variant, .. } => {
assert!(adt.variants.len() <= 1); assert!(adt.variants.len() <= 1);
if adt.variants.is_empty() { if adt.variants.is_empty() {
@ -1338,7 +1341,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
member_description_factory) = member_description_factory) =
describe_enum_variant(cx, describe_enum_variant(cx,
self.enum_type, self.enum_type,
struct_def, variant,
&adt.variants[0], &adt.variants[0],
NoDiscriminant, NoDiscriminant,
self.containing_scope, self.containing_scope,
@ -1362,16 +1365,17 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
] ]
} }
} }
adt::RawNullablePointer { nndiscr: non_null_variant_index, nnty, .. } => { layout::RawNullablePointer { nndiscr: non_null_variant_index, .. } => {
// As far as debuginfo is concerned, the pointer this enum // As far as debuginfo is concerned, the pointer this enum
// represents is still wrapped in a struct. This is to make the // represents is still wrapped in a struct. This is to make the
// DWARF representation of enums uniform. // DWARF representation of enums uniform.
// First create a description of the artificial wrapper struct: // First create a description of the artificial wrapper struct:
let non_null_variant = &adt.variants[non_null_variant_index.0 as usize]; let non_null_variant = &adt.variants[non_null_variant_index as usize];
let non_null_variant_name = non_null_variant.name.as_str(); let non_null_variant_name = non_null_variant.name.as_str();
// The llvm type and metadata of the pointer // The llvm type and metadata of the pointer
let nnty = monomorphize::field_ty(cx.tcx(), &substs, &non_null_variant.fields[0] );
let non_null_llvm_type = type_of::type_of(cx, nnty); let non_null_llvm_type = type_of::type_of(cx, nnty);
let non_null_type_metadata = type_metadata(cx, nnty, self.span); let non_null_type_metadata = type_metadata(cx, nnty, self.span);
@ -1416,7 +1420,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
// Encode the information about the null variant in the union // Encode the information about the null variant in the union
// member's name. // member's name.
let null_variant_index = (1 - non_null_variant_index.0) as usize; let null_variant_index = (1 - non_null_variant_index) as usize;
let null_variant_name = adt.variants[null_variant_index].name; let null_variant_name = adt.variants[null_variant_index].name;
let union_member_name = format!("RUST$ENCODED$ENUM${}${}", let union_member_name = format!("RUST$ENCODED$ENUM${}${}",
0, 0,
@ -1434,7 +1438,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
} }
] ]
}, },
adt::StructWrappedNullablePointer { nonnull: ref struct_def, layout::StructWrappedNullablePointer { nonnull: ref struct_def,
nndiscr, nndiscr,
ref discrfield, ..} => { ref discrfield, ..} => {
// Create a description of the non-null variant // Create a description of the non-null variant
@ -1442,7 +1446,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
describe_enum_variant(cx, describe_enum_variant(cx,
self.enum_type, self.enum_type,
struct_def, struct_def,
&adt.variants[nndiscr.0 as usize], &adt.variants[nndiscr as usize],
OptimizedDiscriminant, OptimizedDiscriminant,
self.containing_scope, self.containing_scope,
self.span); self.span);
@ -1457,7 +1461,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
// Encode the information about the null variant in the union // Encode the information about the null variant in the union
// member's name. // member's name.
let null_variant_index = (1 - nndiscr.0) as usize; let null_variant_index = (1 - nndiscr) as usize;
let null_variant_name = adt.variants[null_variant_index].name; let null_variant_name = adt.variants[null_variant_index].name;
let discrfield = discrfield.iter() let discrfield = discrfield.iter()
.skip(1) .skip(1)
@ -1478,9 +1482,8 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
} }
] ]
}, },
adt::CEnum(..) | adt::UntaggedUnion(..) => { layout::CEnum { .. } => span_bug!(self.span, "This should be unreachable."),
span_bug!(self.span, "This should be unreachable.") ref l @ _ => bug!("Not an enum layout: {:#?}", l)
}
} }
} }
} }
@ -1523,16 +1526,39 @@ enum EnumDiscriminantInfo {
// full RecursiveTypeDescription. // full RecursiveTypeDescription.
fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
enum_type: Ty<'tcx>, enum_type: Ty<'tcx>,
struct_def: &adt::Struct<'tcx>, struct_def: &layout::Struct,
variant: ty::VariantDef<'tcx>, variant: ty::VariantDef<'tcx>,
discriminant_info: EnumDiscriminantInfo, discriminant_info: EnumDiscriminantInfo,
containing_scope: DIScope, containing_scope: DIScope,
span: Span) span: Span)
-> (DICompositeType, Type, MemberDescriptionFactory<'tcx>) { -> (DICompositeType, Type, MemberDescriptionFactory<'tcx>) {
let substs = match enum_type.sty {
ty::TyAdt(def, s) if def.adt_kind() == AdtKind::Enum => s,
ref t @ _ => bug!("{:#?} is not an enum", t)
};
let maybe_discr_and_signed: Option<(layout::Integer, bool)> = match *cx.layout_of(enum_type) {
layout::CEnum {discr, ..} => Some((discr, true)),
layout::General{discr, ..} => Some((discr, false)),
layout::Univariant { .. }
| layout::RawNullablePointer { .. }
| layout::StructWrappedNullablePointer { .. } => None,
ref l @ _ => bug!("This should be unreachable. Type is {:#?} layout is {:#?}", enum_type, l)
};
let mut field_tys = variant.fields.iter().map(|f: ty::FieldDef<'tcx>| {
monomorphize::field_ty(cx.tcx(), &substs, f)
}).collect::<Vec<_>>();
if let Some((discr, signed)) = maybe_discr_and_signed {
field_tys.insert(0, discr.to_ty(&cx.tcx(), signed));
}
let variant_llvm_type = let variant_llvm_type =
Type::struct_(cx, &struct_def.fields Type::struct_(cx, &field_tys
.iter() .iter()
.map(|&t| type_of::type_of(cx, t)) .map(|t| type_of::type_of(cx, t))
.collect::<Vec<_>>() .collect::<Vec<_>>()
, ,
struct_def.packed); struct_def.packed);
@ -1578,7 +1604,7 @@ fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
// Build an array of (field name, field type) pairs to be captured in the factory closure. // Build an array of (field name, field type) pairs to be captured in the factory closure.
let args: Vec<(String, Ty)> = arg_names.iter() let args: Vec<(String, Ty)> = arg_names.iter()
.zip(&struct_def.fields) .zip(field_tys.iter())
.map(|(s, &t)| (s.to_string(), t)) .map(|(s, &t)| (s.to_string(), t))
.collect(); .collect();
@ -1615,7 +1641,6 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
let file_metadata = unknown_file_metadata(cx); let file_metadata = unknown_file_metadata(cx);
let variants = &enum_type.ty_adt_def().unwrap().variants; let variants = &enum_type.ty_adt_def().unwrap().variants;
let enumerators_metadata: Vec<DIDescriptor> = variants let enumerators_metadata: Vec<DIDescriptor> = variants
.iter() .iter()
.map(|v| { .map(|v| {
@ -1630,7 +1655,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
}) })
.collect(); .collect();
let discriminant_type_metadata = |inttype: syntax::attr::IntType| { let discriminant_type_metadata = |inttype: layout::Integer, signed: bool| {
let disr_type_key = (enum_def_id, inttype); let disr_type_key = (enum_def_id, inttype);
let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types
.borrow() .borrow()
@ -1638,12 +1663,12 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
match cached_discriminant_type_metadata { match cached_discriminant_type_metadata {
Some(discriminant_type_metadata) => discriminant_type_metadata, Some(discriminant_type_metadata) => discriminant_type_metadata,
None => { None => {
let discriminant_llvm_type = adt::ll_inttype(cx, inttype); let discriminant_llvm_type = Type::from_integer(cx, inttype);
let (discriminant_size, discriminant_align) = let (discriminant_size, discriminant_align) =
size_and_align_of(cx, discriminant_llvm_type); size_and_align_of(cx, discriminant_llvm_type);
let discriminant_base_type_metadata = let discriminant_base_type_metadata =
type_metadata(cx, type_metadata(cx,
adt::ty_of_inttype(cx.tcx(), inttype), inttype.to_ty(&cx.tcx(), signed),
syntax_pos::DUMMY_SP); syntax_pos::DUMMY_SP);
let discriminant_name = get_enum_discriminant_name(cx, enum_def_id); let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
@ -1670,16 +1695,17 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
} }
}; };
let type_rep = adt::represent_type(cx, enum_type); let type_rep = cx.layout_of(enum_type);
let discriminant_type_metadata = match *type_rep { let discriminant_type_metadata = match *type_rep {
adt::CEnum(inttype, ..) => { layout::CEnum { discr, signed, .. } => {
return FinalMetadata(discriminant_type_metadata(inttype)) return FinalMetadata(discriminant_type_metadata(discr, signed))
}, },
adt::RawNullablePointer { .. } | layout::RawNullablePointer { .. } |
adt::StructWrappedNullablePointer { .. } | layout::StructWrappedNullablePointer { .. } |
adt::Univariant(..) | adt::UntaggedUnion(..) => None, layout::Univariant { .. } => None,
adt::General(inttype, _) => Some(discriminant_type_metadata(inttype)), layout::General { discr, .. } => Some(discriminant_type_metadata(discr, false)),
ref l @ _ => bug!("Not an enum layout: {:#?}", l)
}; };
let enum_llvm_type = type_of::type_of(cx, enum_type); let enum_llvm_type = type_of::type_of(cx, enum_type);
@ -1715,7 +1741,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
enum_llvm_type, enum_llvm_type,
EnumMDF(EnumMemberDescriptionFactory { EnumMDF(EnumMemberDescriptionFactory {
enum_type: enum_type, enum_type: enum_type,
type_rep: type_rep.clone(), type_rep: type_rep,
discriminant_type_metadata: discriminant_type_metadata, discriminant_type_metadata: discriminant_type_metadata,
containing_scope: containing_scope, containing_scope: containing_scope,
file_metadata: file_metadata, file_metadata: file_metadata,

View File

@ -43,7 +43,7 @@ use std::ptr;
use syntax_pos::{self, Span, Pos}; use syntax_pos::{self, Span, Pos};
use syntax::ast; use syntax::ast;
use syntax::attr::IntType; use rustc::ty::layout;
pub mod gdb; pub mod gdb;
mod utils; mod utils;
@ -69,7 +69,7 @@ pub struct CrateDebugContext<'tcx> {
builder: DIBuilderRef, builder: DIBuilderRef,
current_debug_location: Cell<InternalDebugLocation>, current_debug_location: Cell<InternalDebugLocation>,
created_files: RefCell<FnvHashMap<String, DIFile>>, created_files: RefCell<FnvHashMap<String, DIFile>>,
created_enum_disr_types: RefCell<FnvHashMap<(DefId, IntType), DIType>>, created_enum_disr_types: RefCell<FnvHashMap<(DefId, layout::Integer), DIType>>,
type_map: RefCell<TypeMap<'tcx>>, type_map: RefCell<TypeMap<'tcx>>,
namespace_map: RefCell<DefIdMap<DIScope>>, namespace_map: RefCell<DefIdMap<DIScope>>,

View File

@ -513,7 +513,7 @@ fn drop_structural_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
let _icx = push_ctxt("drop_structural_ty"); let _icx = push_ctxt("drop_structural_ty");
fn iter_variant<'blk, 'tcx>(cx: Block<'blk, 'tcx>, fn iter_variant<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
repr: &adt::Repr<'tcx>, t: Ty<'tcx>,
av: adt::MaybeSizedValue, av: adt::MaybeSizedValue,
variant: ty::VariantDef<'tcx>, variant: ty::VariantDef<'tcx>,
substs: &Substs<'tcx>) substs: &Substs<'tcx>)
@ -525,7 +525,7 @@ fn drop_structural_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
for (i, field) in variant.fields.iter().enumerate() { for (i, field) in variant.fields.iter().enumerate() {
let arg = monomorphize::field_ty(tcx, substs, field); let arg = monomorphize::field_ty(tcx, substs, field);
cx = drop_ty(cx, cx = drop_ty(cx,
adt::trans_field_ptr(cx, repr, av, Disr::from(variant.disr_val), i), adt::trans_field_ptr(cx, t, av, Disr::from(variant.disr_val), i),
arg, DebugLoc::None); arg, DebugLoc::None);
} }
return cx; return cx;
@ -543,9 +543,8 @@ fn drop_structural_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
let mut cx = cx; let mut cx = cx;
match t.sty { match t.sty {
ty::TyClosure(_, ref substs) => { ty::TyClosure(_, ref substs) => {
let repr = adt::represent_type(cx.ccx(), t);
for (i, upvar_ty) in substs.upvar_tys.iter().enumerate() { for (i, upvar_ty) in substs.upvar_tys.iter().enumerate() {
let llupvar = adt::trans_field_ptr(cx, &repr, value, Disr(0), i); let llupvar = adt::trans_field_ptr(cx, t, value, Disr(0), i);
cx = drop_ty(cx, llupvar, upvar_ty, DebugLoc::None); cx = drop_ty(cx, llupvar, upvar_ty, DebugLoc::None);
} }
} }
@ -562,18 +561,16 @@ fn drop_structural_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
|bb, vv| drop_ty(bb, vv, unit_ty, DebugLoc::None)); |bb, vv| drop_ty(bb, vv, unit_ty, DebugLoc::None));
} }
ty::TyTuple(ref args) => { ty::TyTuple(ref args) => {
let repr = adt::represent_type(cx.ccx(), t);
for (i, arg) in args.iter().enumerate() { for (i, arg) in args.iter().enumerate() {
let llfld_a = adt::trans_field_ptr(cx, &repr, value, Disr(0), i); let llfld_a = adt::trans_field_ptr(cx, t, value, Disr(0), i);
cx = drop_ty(cx, llfld_a, *arg, DebugLoc::None); cx = drop_ty(cx, llfld_a, *arg, DebugLoc::None);
} }
} }
ty::TyAdt(adt, substs) => match adt.adt_kind() { ty::TyAdt(adt, substs) => match adt.adt_kind() {
AdtKind::Struct => { AdtKind::Struct => {
let repr = adt::represent_type(cx.ccx(), t);
let VariantInfo { fields, discr } = VariantInfo::from_ty(cx.tcx(), t, None); let VariantInfo { fields, discr } = VariantInfo::from_ty(cx.tcx(), t, None);
for (i, &Field(_, field_ty)) in fields.iter().enumerate() { for (i, &Field(_, field_ty)) in fields.iter().enumerate() {
let llfld_a = adt::trans_field_ptr(cx, &repr, value, Disr::from(discr), i); let llfld_a = adt::trans_field_ptr(cx, t, value, Disr::from(discr), i);
let val = if type_is_sized(cx.tcx(), field_ty) { let val = if type_is_sized(cx.tcx(), field_ty) {
llfld_a llfld_a
@ -593,18 +590,16 @@ fn drop_structural_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
AdtKind::Enum => { AdtKind::Enum => {
let fcx = cx.fcx; let fcx = cx.fcx;
let ccx = fcx.ccx; let ccx = fcx.ccx;
let repr = adt::represent_type(ccx, t);
let n_variants = adt.variants.len(); let n_variants = adt.variants.len();
// NB: we must hit the discriminant first so that structural // NB: we must hit the discriminant first so that structural
// comparison know not to proceed when the discriminants differ. // comparison know not to proceed when the discriminants differ.
match adt::trans_switch(cx, &repr, av, false) { match adt::trans_switch(cx, t, av, false) {
(adt::BranchKind::Single, None) => { (adt::BranchKind::Single, None) => {
if n_variants != 0 { if n_variants != 0 {
assert!(n_variants == 1); assert!(n_variants == 1);
cx = iter_variant(cx, &repr, adt::MaybeSizedValue::sized(av), cx = iter_variant(cx, t, adt::MaybeSizedValue::sized(av),
&adt.variants[0], substs); &adt.variants[0], substs);
} }
} }
@ -633,10 +628,10 @@ fn drop_structural_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
let variant_cx = fcx.new_block(&format!("enum-iter-variant-{}", let variant_cx = fcx.new_block(&format!("enum-iter-variant-{}",
&variant.disr_val &variant.disr_val
.to_string())); .to_string()));
let case_val = adt::trans_case(cx, &repr, Disr::from(variant.disr_val)); let case_val = adt::trans_case(cx, t, Disr::from(variant.disr_val));
AddCase(llswitch, case_val, variant_cx.llbb); AddCase(llswitch, case_val, variant_cx.llbb);
let variant_cx = iter_variant(variant_cx, let variant_cx = iter_variant(variant_cx,
&repr, t,
value, value,
variant, variant,
substs); substs);

View File

@ -418,8 +418,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
let val_ty = substs.type_at(0); let val_ty = substs.type_at(0);
match val_ty.sty { match val_ty.sty {
ty::TyAdt(adt, ..) if adt.is_enum() => { ty::TyAdt(adt, ..) if adt.is_enum() => {
let repr = adt::represent_type(ccx, val_ty); adt::trans_get_discr(bcx, val_ty, llargs[0],
adt::trans_get_discr(bcx, &repr, llargs[0],
Some(llret_ty), true) Some(llret_ty), true)
} }
_ => C_null(llret_ty) _ => C_null(llret_ty)
@ -629,13 +628,10 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
// destructors, and the contents are SIMD // destructors, and the contents are SIMD
// etc. // etc.
assert!(!bcx.fcx.type_needs_drop(arg_type)); assert!(!bcx.fcx.type_needs_drop(arg_type));
let repr = adt::represent_type(bcx.ccx(), arg_type);
let repr_ptr = &repr;
let arg = adt::MaybeSizedValue::sized(llarg); let arg = adt::MaybeSizedValue::sized(llarg);
(0..contents.len()) (0..contents.len())
.map(|i| { .map(|i| {
Load(bcx, adt::trans_field_ptr(bcx, repr_ptr, arg, Disr(0), i)) Load(bcx, adt::trans_field_ptr(bcx, arg_type, arg, Disr(0), i))
}) })
.collect() .collect()
} }

View File

@ -24,13 +24,6 @@ pub type llalign = u32;
// ______________________________________________________________________ // ______________________________________________________________________
// compute sizeof / alignof // compute sizeof / alignof
// Returns the number of bytes clobbered by a Store to this type.
pub fn llsize_of_store(cx: &CrateContext, ty: Type) -> llsize {
unsafe {
return llvm::LLVMStoreSizeOfType(cx.td(), ty.to_ref());
}
}
// Returns the number of bytes between successive elements of type T in an // Returns the number of bytes between successive elements of type T in an
// array of T. This is the "ABI" size. It includes any ABI-mandated padding. // array of T. This is the "ABI" size. It includes any ABI-mandated padding.
pub fn llsize_of_alloc(cx: &CrateContext, ty: Type) -> llsize { pub fn llsize_of_alloc(cx: &CrateContext, ty: Type) -> llsize {
@ -39,28 +32,6 @@ pub fn llsize_of_alloc(cx: &CrateContext, ty: Type) -> llsize {
} }
} }
// Returns, as near as we can figure, the "real" size of a type. As in, the
// bits in this number of bytes actually carry data related to the datum
// with the type. Not junk, accidentally-damaged words, or whatever.
// Note that padding of the type will be included for structs, but not for the
// other types (i.e. SIMD types).
// Rounds up to the nearest byte though, so if you have a 1-bit
// value, we return 1 here, not 0. Most of rustc works in bytes. Be warned
// that LLVM *does* distinguish between e.g. a 1-bit value and an 8-bit value
// at the codegen level! In general you should prefer `llbitsize_of_real`
// below.
pub fn llsize_of_real(cx: &CrateContext, ty: Type) -> llsize {
unsafe {
let nbits = llvm::LLVMSizeOfTypeInBits(cx.td(), ty.to_ref());
if nbits & 7 != 0 {
// Not an even number of bytes, spills into "next" byte.
1 + (nbits >> 3)
} else {
nbits >> 3
}
}
}
/// Returns the "real" size of the type in bits. /// Returns the "real" size of the type in bits.
pub fn llbitsize_of_real(cx: &CrateContext, ty: Type) -> llbits { pub fn llbitsize_of_real(cx: &CrateContext, ty: Type) -> llbits {
unsafe { unsafe {

View File

@ -139,9 +139,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
mir::TerminatorKind::Switch { ref discr, ref adt_def, ref targets } => { mir::TerminatorKind::Switch { ref discr, ref adt_def, ref targets } => {
let discr_lvalue = self.trans_lvalue(&bcx, discr); let discr_lvalue = self.trans_lvalue(&bcx, discr);
let ty = discr_lvalue.ty.to_ty(bcx.tcx()); let ty = discr_lvalue.ty.to_ty(bcx.tcx());
let repr = adt::represent_type(bcx.ccx(), ty);
let discr = bcx.with_block(|bcx| let discr = bcx.with_block(|bcx|
adt::trans_get_discr(bcx, &repr, discr_lvalue.llval, None, true) adt::trans_get_discr(bcx, ty, discr_lvalue.llval, None, true)
); );
let mut bb_hist = FnvHashMap(); let mut bb_hist = FnvHashMap();
@ -167,7 +166,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
if default_bb != Some(target) { if default_bb != Some(target) {
let llbb = llblock(self, target); let llbb = llblock(self, target);
let llval = bcx.with_block(|bcx| adt::trans_case( let llval = bcx.with_block(|bcx| adt::trans_case(
bcx, &repr, Disr::from(adt_variant.disr_val))); bcx, ty, Disr::from(adt_variant.disr_val)));
build::AddCase(switch, llval, llbb) build::AddCase(switch, llval, llbb)
} }
} }
@ -701,10 +700,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
// Handle both by-ref and immediate tuples. // Handle both by-ref and immediate tuples.
match tuple.val { match tuple.val {
Ref(llval) => { Ref(llval) => {
let base_repr = adt::represent_type(bcx.ccx(), tuple.ty);
let base = adt::MaybeSizedValue::sized(llval); let base = adt::MaybeSizedValue::sized(llval);
for (n, &ty) in arg_types.iter().enumerate() { for (n, &ty) in arg_types.iter().enumerate() {
let ptr = adt::trans_field_ptr_builder(bcx, &base_repr, base, Disr(0), n); let ptr = adt::trans_field_ptr_builder(bcx, tuple.ty, base, Disr(0), n);
let val = if common::type_is_fat_ptr(bcx.tcx(), ty) { let val = if common::type_is_fat_ptr(bcx.tcx(), ty) {
let (lldata, llextra) = load_fat_ptr(bcx, ptr); let (lldata, llextra) = load_fat_ptr(bcx, ptr);
Pair(lldata, llextra) Pair(lldata, llextra)

View File

@ -23,9 +23,9 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::ty::cast::{CastTy, IntTy}; use rustc::ty::cast::{CastTy, IntTy};
use rustc::ty::subst::Substs; use rustc::ty::subst::Substs;
use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use {abi, adt, base, Disr}; use {abi, adt, base, Disr, machine};
use callee::Callee; use callee::Callee;
use common::{self, BlockAndBuilder, CrateContext, const_get_elt, val_ty}; use common::{self, BlockAndBuilder, CrateContext, const_get_elt, val_ty, type_is_sized};
use common::{C_array, C_bool, C_bytes, C_floating_f64, C_integral}; use common::{C_array, C_bool, C_bytes, C_floating_f64, C_integral};
use common::{C_null, C_struct, C_str_slice, C_undef, C_uint}; use common::{C_null, C_struct, C_str_slice, C_undef, C_uint};
use common::{const_to_opt_int, const_to_opt_uint}; use common::{const_to_opt_int, const_to_opt_uint};
@ -441,8 +441,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
} }
} }
mir::ProjectionElem::Field(ref field, _) => { mir::ProjectionElem::Field(ref field, _) => {
let base_repr = adt::represent_type(self.ccx, tr_base.ty); let llprojected = adt::const_get_field(self.ccx, tr_base.ty, base.llval,
let llprojected = adt::const_get_field(&base_repr, base.llval,
Disr(0), field.index()); Disr(0), field.index());
let llextra = if is_sized { let llextra = if is_sized {
ptr::null_mut() ptr::null_mut()
@ -585,9 +584,8 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
} }
_ => Disr(0) _ => Disr(0)
}; };
let repr = adt::represent_type(self.ccx, dest_ty);
Const::new( Const::new(
adt::trans_const(self.ccx, &repr, disr, &fields), adt::trans_const(self.ccx, dest_ty, disr, &fields),
dest_ty dest_ty
) )
} }
@ -658,8 +656,8 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
let ll_t_out = type_of::immediate_type_of(self.ccx, cast_ty); let ll_t_out = type_of::immediate_type_of(self.ccx, cast_ty);
let llval = operand.llval; let llval = operand.llval;
let signed = if let CastTy::Int(IntTy::CEnum) = r_t_in { let signed = if let CastTy::Int(IntTy::CEnum) = r_t_in {
let repr = adt::represent_type(self.ccx, operand.ty); let l = self.ccx.layout_of(operand.ty);
adt::is_discr_signed(&repr) adt::is_discr_signed(&l)
} else { } else {
operand.ty.is_signed() operand.ty.is_signed()
}; };
@ -735,7 +733,12 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
let base = match tr_lvalue.base { let base = match tr_lvalue.base {
Base::Value(llval) => { Base::Value(llval) => {
let align = type_of::align_of(self.ccx, ty); // FIXME: may be wrong for &*(&simd_vec as &fmt::Debug)
let align = if type_is_sized(self.ccx.tcx(), ty) {
type_of::align_of(self.ccx, ty)
} else {
self.ccx.tcx().data_layout.pointer_align.abi() as machine::llalign
};
if bk == mir::BorrowKind::Mut { if bk == mir::BorrowKind::Mut {
consts::addr_of_mut(self.ccx, llval, align, "ref_mut") consts::addr_of_mut(self.ccx, llval, align, "ref_mut")
} else { } else {

View File

@ -152,7 +152,6 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
mir::ProjectionElem::Deref => bug!(), mir::ProjectionElem::Deref => bug!(),
mir::ProjectionElem::Field(ref field, _) => { mir::ProjectionElem::Field(ref field, _) => {
let base_ty = tr_base.ty.to_ty(tcx); let base_ty = tr_base.ty.to_ty(tcx);
let base_repr = adt::represent_type(ccx, base_ty);
let discr = match tr_base.ty { let discr = match tr_base.ty {
LvalueTy::Ty { .. } => 0, LvalueTy::Ty { .. } => 0,
LvalueTy::Downcast { adt_def: _, substs: _, variant_index: v } => v, LvalueTy::Downcast { adt_def: _, substs: _, variant_index: v } => v,
@ -164,7 +163,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
} else { } else {
adt::MaybeSizedValue::unsized_(tr_base.llval, tr_base.llextra) adt::MaybeSizedValue::unsized_(tr_base.llval, tr_base.llextra)
}; };
let llprojected = adt::trans_field_ptr_builder(bcx, &base_repr, base, let llprojected = adt::trans_field_ptr_builder(bcx, base_ty, base,
Disr(discr), field.index()); Disr(discr), field.index());
let llextra = if is_sized { let llextra = if is_sized {
ptr::null_mut() ptr::null_mut()

View File

@ -111,10 +111,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
mir::Rvalue::Aggregate(ref kind, ref operands) => { mir::Rvalue::Aggregate(ref kind, ref operands) => {
match *kind { match *kind {
mir::AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => { mir::AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => {
let repr = adt::represent_type(bcx.ccx(), dest.ty.to_ty(bcx.tcx()));
let disr = Disr::from(adt_def.variants[variant_index].disr_val); let disr = Disr::from(adt_def.variants[variant_index].disr_val);
bcx.with_block(|bcx| { bcx.with_block(|bcx| {
adt::trans_set_discr(bcx, &repr, dest.llval, Disr::from(disr)); adt::trans_set_discr(bcx,
dest.ty.to_ty(bcx.tcx()), dest.llval, Disr::from(disr));
}); });
for (i, operand) in operands.iter().enumerate() { for (i, operand) in operands.iter().enumerate() {
let op = self.trans_operand(&bcx, operand); let op = self.trans_operand(&bcx, operand);
@ -122,8 +122,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
if !common::type_is_zero_size(bcx.ccx(), op.ty) { if !common::type_is_zero_size(bcx.ccx(), op.ty) {
let val = adt::MaybeSizedValue::sized(dest.llval); let val = adt::MaybeSizedValue::sized(dest.llval);
let field_index = active_field_index.unwrap_or(i); let field_index = active_field_index.unwrap_or(i);
let lldest_i = adt::trans_field_ptr_builder(&bcx, &repr, val, let lldest_i = adt::trans_field_ptr_builder(&bcx,
disr, field_index); dest.ty.to_ty(bcx.tcx()),
val, disr, field_index);
self.store_operand(&bcx, lldest_i, op); self.store_operand(&bcx, lldest_i, op);
} }
} }
@ -270,17 +271,17 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
let ll_t_in = type_of::immediate_type_of(bcx.ccx(), operand.ty); let ll_t_in = type_of::immediate_type_of(bcx.ccx(), operand.ty);
let ll_t_out = type_of::immediate_type_of(bcx.ccx(), cast_ty); let ll_t_out = type_of::immediate_type_of(bcx.ccx(), cast_ty);
let (llval, signed) = if let CastTy::Int(IntTy::CEnum) = r_t_in { let (llval, signed) = if let CastTy::Int(IntTy::CEnum) = r_t_in {
let repr = adt::represent_type(bcx.ccx(), operand.ty); let l = bcx.ccx().layout_of(operand.ty);
let discr = match operand.val { let discr = match operand.val {
OperandValue::Immediate(llval) => llval, OperandValue::Immediate(llval) => llval,
OperandValue::Ref(llptr) => { OperandValue::Ref(llptr) => {
bcx.with_block(|bcx| { bcx.with_block(|bcx| {
adt::trans_get_discr(bcx, &repr, llptr, None, true) adt::trans_get_discr(bcx, operand.ty, llptr, None, true)
}) })
} }
OperandValue::Pair(..) => bug!("Unexpected Pair operand") OperandValue::Pair(..) => bug!("Unexpected Pair operand")
}; };
(discr, adt::is_discr_signed(&repr)) (discr, adt::is_discr_signed(&l))
} else { } else {
(operand.immediate(), operand.ty.is_signed()) (operand.immediate(), operand.ty.is_signed())
}; };

View File

@ -62,11 +62,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
} }
mir::StatementKind::SetDiscriminant{ref lvalue, variant_index} => { mir::StatementKind::SetDiscriminant{ref lvalue, variant_index} => {
let ty = self.monomorphized_lvalue_ty(lvalue); let ty = self.monomorphized_lvalue_ty(lvalue);
let repr = adt::represent_type(bcx.ccx(), ty);
let lvalue_transed = self.trans_lvalue(&bcx, lvalue); let lvalue_transed = self.trans_lvalue(&bcx, lvalue);
bcx.with_block(|bcx| bcx.with_block(|bcx|
adt::trans_set_discr(bcx, adt::trans_set_discr(bcx,
&repr, ty,
lvalue_transed.llval, lvalue_transed.llval,
Disr::from(variant_index)) Disr::from(variant_index))
); );

View File

@ -18,6 +18,7 @@ use context::CrateContext;
use util::nodemap::FnvHashMap; use util::nodemap::FnvHashMap;
use syntax::ast; use syntax::ast;
use rustc::ty::layout;
use std::ffi::CString; use std::ffi::CString;
use std::fmt; use std::fmt;
@ -299,6 +300,26 @@ impl Type {
llvm::LLVMGetIntTypeWidth(self.to_ref()) as u64 llvm::LLVMGetIntTypeWidth(self.to_ref()) as u64
} }
} }
pub fn from_integer(cx: &CrateContext, i: layout::Integer) -> Type {
use rustc::ty::layout::Integer::*;
match i {
I1 => Type::i1(cx),
I8 => Type::i8(cx),
I16 => Type::i16(cx),
I32 => Type::i32(cx),
I64 => Type::i64(cx),
}
}
pub fn from_primitive(ccx: &CrateContext, p: layout::Primitive) -> Type {
match p {
layout::Int(i) => Type::from_integer(ccx, i),
layout::F32 => Type::f32(ccx),
layout::F64 => Type::f64(ccx),
layout::Pointer => bug!("It is not possible to convert Pointer directly to Type.")
}
}
} }
/* Memory-managed object interface to type handles. */ /* Memory-managed object interface to type handles. */

View File

@ -22,17 +22,6 @@ use type_::Type;
use syntax::ast; use syntax::ast;
// LLVM doesn't like objects that are too big. Issue #17913
fn ensure_array_fits_in_address_space<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
llet: Type,
size: machine::llsize,
scapegoat: Ty<'tcx>) {
let esz = machine::llsize_of_alloc(ccx, llet);
match esz.checked_mul(size) {
Some(n) if n < ccx.obj_size_bound() => {}
_ => { ccx.report_overbig_object(scapegoat) }
}
}
// A "sizing type" is an LLVM type, the size and alignment of which are // A "sizing type" is an LLVM type, the size and alignment of which are
// guaranteed to be equivalent to what you would get out of `type_of()`. It's // guaranteed to be equivalent to what you would get out of `type_of()`. It's
@ -81,7 +70,6 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
ty::TyArray(ty, size) => { ty::TyArray(ty, size) => {
let llty = sizing_type_of(cx, ty); let llty = sizing_type_of(cx, ty);
let size = size as u64; let size = size as u64;
ensure_array_fits_in_address_space(cx, llty, size, t);
Type::array(&llty, size) Type::array(&llty, size)
} }
@ -98,13 +86,11 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
} }
let llet = type_of(cx, e); let llet = type_of(cx, e);
let n = t.simd_size(cx.tcx()) as u64; let n = t.simd_size(cx.tcx()) as u64;
ensure_array_fits_in_address_space(cx, llet, n, t);
Type::vector(&llet, n) Type::vector(&llet, n)
} }
ty::TyTuple(..) | ty::TyAdt(..) | ty::TyClosure(..) => { ty::TyTuple(..) | ty::TyAdt(..) | ty::TyClosure(..) => {
let repr = adt::represent_type(cx, t); adt::sizing_type_of(cx, t, false)
adt::sizing_type_of(cx, &repr, false)
} }
ty::TyProjection(..) | ty::TyInfer(..) | ty::TyParam(..) | ty::TyProjection(..) | ty::TyInfer(..) | ty::TyParam(..) |
@ -242,8 +228,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
ty::TyClosure(..) => { ty::TyClosure(..) => {
// Only create the named struct, but don't fill it in. We // Only create the named struct, but don't fill it in. We
// fill it in *after* placing it into the type cache. // fill it in *after* placing it into the type cache.
let repr = adt::represent_type(cx, t); adt::incomplete_type_of(cx, t, "closure")
adt::incomplete_type_of(cx, &repr, "closure")
} }
ty::TyBox(ty) | ty::TyBox(ty) |
@ -266,11 +251,6 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
ty::TyArray(ty, size) => { ty::TyArray(ty, size) => {
let size = size as u64; let size = size as u64;
// we must use `sizing_type_of` here as the type may
// not be fully initialized.
let szty = sizing_type_of(cx, ty);
ensure_array_fits_in_address_space(cx, szty, size, t);
let llty = in_memory_type_of(cx, ty); let llty = in_memory_type_of(cx, ty);
Type::array(&llty, size) Type::array(&llty, size)
} }
@ -290,8 +270,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
} }
ty::TyTuple(ref tys) if tys.is_empty() => Type::nil(cx), ty::TyTuple(ref tys) if tys.is_empty() => Type::nil(cx),
ty::TyTuple(..) => { ty::TyTuple(..) => {
let repr = adt::represent_type(cx, t); adt::type_of(cx, t)
adt::type_of(cx, &repr)
} }
ty::TyAdt(..) if t.is_simd() => { ty::TyAdt(..) if t.is_simd() => {
let e = t.simd_type(cx.tcx()); let e = t.simd_type(cx.tcx());
@ -302,7 +281,6 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
} }
let llet = in_memory_type_of(cx, e); let llet = in_memory_type_of(cx, e);
let n = t.simd_size(cx.tcx()) as u64; let n = t.simd_size(cx.tcx()) as u64;
ensure_array_fits_in_address_space(cx, llet, n, t);
Type::vector(&llet, n) Type::vector(&llet, n)
} }
ty::TyAdt(def, substs) => { ty::TyAdt(def, substs) => {
@ -310,9 +288,8 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
// fill it in *after* placing it into the type cache. This // fill it in *after* placing it into the type cache. This
// avoids creating more than one copy of the enum when one // avoids creating more than one copy of the enum when one
// of the enum's variants refers to the enum itself. // of the enum's variants refers to the enum itself.
let repr = adt::represent_type(cx, t);
let name = llvm_type_name(cx, def.did, substs); let name = llvm_type_name(cx, def.did, substs);
adt::incomplete_type_of(cx, &repr, &name[..]) adt::incomplete_type_of(cx, t, &name[..])
} }
ty::TyInfer(..) | ty::TyInfer(..) |
@ -329,8 +306,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
// If this was an enum or struct, fill in the type now. // If this was an enum or struct, fill in the type now.
match t.sty { match t.sty {
ty::TyAdt(..) | ty::TyClosure(..) if !t.is_simd() => { ty::TyAdt(..) | ty::TyClosure(..) if !t.is_simd() => {
let repr = adt::represent_type(cx, t); adt::finish_type_of(cx, t, &mut llty);
adt::finish_type_of(cx, &repr, &mut llty);
} }
_ => () _ => ()
} }
@ -340,8 +316,8 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
pub fn align_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) pub fn align_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
-> machine::llalign { -> machine::llalign {
let llty = sizing_type_of(cx, t); let layout = cx.layout_of(t);
machine::llalign_of_min(cx, llty) layout.align(&cx.tcx().data_layout).abi() as machine::llalign
} }
fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,

View File

@ -22,12 +22,12 @@ pub enum E {
B(f32) B(f32)
} }
// CHECK: @VAR2 = constant {{.*}} { i32 0, i32 666, {{.*}} }, section ".test_two" // CHECK: @VAR2 = constant {{.*}} { i32 0, i32 666 }, section ".test_two"
#[no_mangle] #[no_mangle]
#[link_section = ".test_two"] #[link_section = ".test_two"]
pub static VAR2: E = E::A(666); pub static VAR2: E = E::A(666);
// CHECK: @VAR3 = constant {{.*}} { i32 1, float 1.000000e+00, {{.*}} }, section ".test_three" // CHECK: @VAR3 = constant {{.*}} { i32 1, float 1.000000e+00 }, section ".test_three"
#[no_mangle] #[no_mangle]
#[link_section = ".test_three"] #[link_section = ".test_three"]
pub static VAR3: E = E::B(1.); pub static VAR3: E = E::B(1.);