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:
commit
9966397b61
@ -489,6 +489,9 @@ pub struct GlobalCtxt<'tcx> {
|
||||
/// Cache for layouts computed from types.
|
||||
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
|
||||
/// by `rustc-macro` crates.
|
||||
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),
|
||||
data_layout: data_layout,
|
||||
layout_cache: RefCell::new(FnvHashMap()),
|
||||
layout_depth: Cell::new(0),
|
||||
derive_macros: RefCell::new(NodeMap()),
|
||||
}, f)
|
||||
}
|
||||
|
@ -328,6 +328,42 @@ pub enum 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.
|
||||
pub fn fit_signed(x: i64) -> Integer {
|
||||
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.
|
||||
pub fn from_attr(dl: &TargetDataLayout, ity: attr::IntType) -> Integer {
|
||||
match ity {
|
||||
@ -623,6 +671,15 @@ impl<'a, 'gcx, 'tcx> Struct {
|
||||
}
|
||||
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.
|
||||
@ -912,7 +969,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||
Univariant { variant: unit, non_zero: false }
|
||||
}
|
||||
|
||||
// Tuples.
|
||||
// Tuples and closures.
|
||||
ty::TyClosure(_, ty::ClosureSubsts { upvar_tys: tys, .. }) |
|
||||
ty::TyTuple(tys) => {
|
||||
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.
|
||||
// (Typechecking will reject discriminant-sizing attrs.)
|
||||
assert!(!def.is_enum() || hint == attr::ReprAny);
|
||||
|
||||
let fields = def.variants[0].fields.iter().map(|field| {
|
||||
field.ty(tcx, substs).layout(infcx)
|
||||
});
|
||||
@ -1103,20 +1160,7 @@ impl<'a, 'gcx, 'tcx> Layout {
|
||||
// won't be so conservative.
|
||||
|
||||
// Use the initial field alignment
|
||||
let wanted = start_align.abi();
|
||||
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;
|
||||
}
|
||||
let mut ity = Integer::for_abi_align(dl, start_align).unwrap_or(min_ity);
|
||||
|
||||
// If the alignment is not larger than the chosen discriminant size,
|
||||
// don't use the alignment as the final size.
|
||||
|
@ -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)?;
|
||||
if can_cache {
|
||||
tcx.layout_cache.borrow_mut().insert(self, layout);
|
||||
}
|
||||
tcx.layout_depth.set(depth);
|
||||
Ok(layout)
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ use cabi_s390x;
|
||||
use cabi_mips;
|
||||
use cabi_mips64;
|
||||
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_of;
|
||||
|
||||
@ -102,7 +102,7 @@ impl ArgType {
|
||||
// Wipe old attributes, likely not valid through indirection.
|
||||
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
|
||||
// the value on the stack, so there are no aliases. It's also
|
||||
@ -200,7 +200,7 @@ impl ArgType {
|
||||
base::call_memcpy(bcx,
|
||||
bcx.pointercast(dst, 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),
|
||||
llalign_of_min(ccx, ty)) as u32);
|
||||
|
||||
@ -327,7 +327,7 @@ impl FnType {
|
||||
if let Layout::CEnum { signed, .. } = *ccx.layout_of(ty) {
|
||||
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
|
||||
// doesn't ignore zero-sized struct arguments.
|
||||
// The same is true for s390x-unknown-linux-gnu.
|
||||
@ -358,7 +358,7 @@ impl FnType {
|
||||
ty::TyRef(_, ty::TypeAndMut { ty, .. }) |
|
||||
ty::TyBox(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);
|
||||
}
|
||||
_ => {}
|
||||
@ -427,7 +427,7 @@ impl FnType {
|
||||
} else {
|
||||
if let Some(inner) = rust_ptr_attrs(ty, &mut arg) {
|
||||
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);
|
||||
}
|
||||
args.push(arg);
|
||||
@ -469,8 +469,8 @@ impl FnType {
|
||||
return;
|
||||
}
|
||||
|
||||
let size = llsize_of_real(ccx, llty);
|
||||
if size > llsize_of_real(ccx, ccx.int_type()) {
|
||||
let size = llsize_of_alloc(ccx, llty);
|
||||
if size > llsize_of_alloc(ccx, ccx.int_type()) {
|
||||
arg.make_indirect(ccx);
|
||||
} else if size > 0 {
|
||||
// We want to pass small aggregates as immediates, but using
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -466,32 +466,27 @@ pub fn coerce_unsized_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
store_fat_ptr(bcx, base, info, dst, dst_ty);
|
||||
}
|
||||
|
||||
// This can be extended to enums and tuples in the future.
|
||||
(&ty::TyAdt(def_a, _), &ty::TyAdt(def_b, _)) => {
|
||||
(&ty::TyAdt(def_a, substs_a), &ty::TyAdt(def_b, substs_b)) => {
|
||||
assert_eq!(def_a, def_b);
|
||||
|
||||
let src_repr = adt::represent_type(bcx.ccx(), src_ty);
|
||||
let src_fields = match &*src_repr {
|
||||
&adt::Repr::Univariant(ref s) => &s.fields,
|
||||
_ => bug!("struct has non-univariant repr"),
|
||||
};
|
||||
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_fields = def_a.variants[0].fields.iter().map(|f| {
|
||||
monomorphize::field_ty(bcx.tcx(), substs_a, f)
|
||||
});
|
||||
let dst_fields = def_b.variants[0].fields.iter().map(|f| {
|
||||
monomorphize::field_ty(bcx.tcx(), substs_b, f)
|
||||
});
|
||||
|
||||
let src = adt::MaybeSizedValue::sized(src);
|
||||
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 {
|
||||
if type_is_zero_size(bcx.ccx(), dst_fty) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let src_f = adt::trans_field_ptr(bcx, &src_repr, src, Disr(0), i);
|
||||
let dst_f = adt::trans_field_ptr(bcx, &dst_repr, dst, 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_ty, dst, Disr(0), i);
|
||||
if src_fty == dst_fty {
|
||||
memcpy_ty(bcx, dst_f, src_f, src_fty);
|
||||
} else {
|
||||
@ -1164,11 +1159,10 @@ pub fn trans_ctor_shim<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
if !fcx.fn_ty.ret.is_ignore() {
|
||||
let dest = fcx.llretslotptr.get().unwrap();
|
||||
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 arg_idx = 0;
|
||||
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];
|
||||
arg_idx += 1;
|
||||
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);
|
||||
}
|
||||
}
|
||||
adt::trans_set_discr(bcx, &repr, dest, disr);
|
||||
adt::trans_set_discr(bcx, sig.output, dest, disr);
|
||||
}
|
||||
|
||||
fcx.finish(bcx, DebugLoc::None);
|
||||
|
@ -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 {
|
||||
unsafe {
|
||||
llvm::LLVMConstIntGetZExtValue(v)
|
||||
|
@ -17,7 +17,6 @@ use rustc::hir::def_id::DefId;
|
||||
use rustc::traits;
|
||||
use rustc::mir::mir_map::MirMap;
|
||||
use rustc::mir::repr as mir;
|
||||
use adt;
|
||||
use base;
|
||||
use builder::Builder;
|
||||
use common::BuilderRef_res;
|
||||
@ -142,7 +141,6 @@ pub struct LocalCrateContext<'tcx> {
|
||||
|
||||
lltypes: 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>>,
|
||||
int_type: Type,
|
||||
opaque_vec_type: Type,
|
||||
@ -677,7 +675,6 @@ impl<'tcx> LocalCrateContext<'tcx> {
|
||||
statics_to_rauw: RefCell::new(Vec::new()),
|
||||
lltypes: RefCell::new(FnvHashMap()),
|
||||
llsizingtypes: RefCell::new(FnvHashMap()),
|
||||
adt_reprs: RefCell::new(FnvHashMap()),
|
||||
type_hashcodes: RefCell::new(FnvHashMap()),
|
||||
int_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
|
||||
}
|
||||
|
||||
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> {
|
||||
&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 {
|
||||
self.tcx().infer_ctxt(None, None, traits::Reveal::All).enter(|infcx| {
|
||||
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)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -27,10 +27,10 @@ use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType, DI
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::hir;
|
||||
use {type_of, adt, machine, monomorphize};
|
||||
use {type_of, machine, monomorphize};
|
||||
use common::CrateContext;
|
||||
use type_::Type;
|
||||
use rustc::ty::{self, AdtKind, Ty};
|
||||
use rustc::ty::{self, AdtKind, Ty, layout};
|
||||
use session::config;
|
||||
use util::nodemap::FnvHashMap;
|
||||
use util::common::path2cstr;
|
||||
@ -40,7 +40,6 @@ use std::ffi::CString;
|
||||
use std::path::Path;
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
use syntax;
|
||||
use syntax::util::interner::Interner;
|
||||
use syntax::ast;
|
||||
use syntax::parse::token;
|
||||
@ -1281,7 +1280,7 @@ fn prepare_union_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
// offset of zero bytes).
|
||||
struct EnumMemberDescriptionFactory<'tcx> {
|
||||
enum_type: Ty<'tcx>,
|
||||
type_rep: Rc<adt::Repr<'tcx>>,
|
||||
type_rep: &'tcx layout::Layout,
|
||||
discriminant_type_metadata: Option<DIType>,
|
||||
containing_scope: DIScope,
|
||||
file_metadata: DIFile,
|
||||
@ -1292,11 +1291,15 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
||||
fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
|
||||
-> Vec<MemberDescription> {
|
||||
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 {
|
||||
adt::General(_, ref struct_defs) => {
|
||||
layout::General { ref variants, .. } => {
|
||||
let discriminant_info = RegularDiscriminant(self.discriminant_type_metadata
|
||||
.expect(""));
|
||||
struct_defs
|
||||
variants
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, struct_def)| {
|
||||
@ -1327,7 +1330,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
||||
}
|
||||
}).collect()
|
||||
},
|
||||
adt::Univariant(ref struct_def) => {
|
||||
layout::Univariant{ ref variant, .. } => {
|
||||
assert!(adt.variants.len() <= 1);
|
||||
|
||||
if adt.variants.is_empty() {
|
||||
@ -1338,7 +1341,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
||||
member_description_factory) =
|
||||
describe_enum_variant(cx,
|
||||
self.enum_type,
|
||||
struct_def,
|
||||
variant,
|
||||
&adt.variants[0],
|
||||
NoDiscriminant,
|
||||
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
|
||||
// represents is still wrapped in a struct. This is to make the
|
||||
// DWARF representation of enums uniform.
|
||||
|
||||
// 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();
|
||||
|
||||
// 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_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
|
||||
// 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 union_member_name = format!("RUST$ENCODED$ENUM${}${}",
|
||||
0,
|
||||
@ -1434,7 +1438,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
||||
}
|
||||
]
|
||||
},
|
||||
adt::StructWrappedNullablePointer { nonnull: ref struct_def,
|
||||
layout::StructWrappedNullablePointer { nonnull: ref struct_def,
|
||||
nndiscr,
|
||||
ref discrfield, ..} => {
|
||||
// Create a description of the non-null variant
|
||||
@ -1442,7 +1446,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
||||
describe_enum_variant(cx,
|
||||
self.enum_type,
|
||||
struct_def,
|
||||
&adt.variants[nndiscr.0 as usize],
|
||||
&adt.variants[nndiscr as usize],
|
||||
OptimizedDiscriminant,
|
||||
self.containing_scope,
|
||||
self.span);
|
||||
@ -1457,7 +1461,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
||||
|
||||
// Encode the information about the null variant in the union
|
||||
// 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 discrfield = discrfield.iter()
|
||||
.skip(1)
|
||||
@ -1478,9 +1482,8 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
||||
}
|
||||
]
|
||||
},
|
||||
adt::CEnum(..) | adt::UntaggedUnion(..) => {
|
||||
span_bug!(self.span, "This should be unreachable.")
|
||||
}
|
||||
layout::CEnum { .. } => span_bug!(self.span, "This should be unreachable."),
|
||||
ref l @ _ => bug!("Not an enum layout: {:#?}", l)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1523,16 +1526,39 @@ enum EnumDiscriminantInfo {
|
||||
// full RecursiveTypeDescription.
|
||||
fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
enum_type: Ty<'tcx>,
|
||||
struct_def: &adt::Struct<'tcx>,
|
||||
struct_def: &layout::Struct,
|
||||
variant: ty::VariantDef<'tcx>,
|
||||
discriminant_info: EnumDiscriminantInfo,
|
||||
containing_scope: DIScope,
|
||||
span: Span)
|
||||
-> (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 =
|
||||
Type::struct_(cx, &struct_def.fields
|
||||
Type::struct_(cx, &field_tys
|
||||
.iter()
|
||||
.map(|&t| type_of::type_of(cx, t))
|
||||
.map(|t| type_of::type_of(cx, t))
|
||||
.collect::<Vec<_>>()
|
||||
,
|
||||
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.
|
||||
let args: Vec<(String, Ty)> = arg_names.iter()
|
||||
.zip(&struct_def.fields)
|
||||
.zip(field_tys.iter())
|
||||
.map(|(s, &t)| (s.to_string(), t))
|
||||
.collect();
|
||||
|
||||
@ -1615,7 +1641,6 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
let file_metadata = unknown_file_metadata(cx);
|
||||
|
||||
let variants = &enum_type.ty_adt_def().unwrap().variants;
|
||||
|
||||
let enumerators_metadata: Vec<DIDescriptor> = variants
|
||||
.iter()
|
||||
.map(|v| {
|
||||
@ -1630,7 +1655,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
})
|
||||
.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 cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types
|
||||
.borrow()
|
||||
@ -1638,12 +1663,12 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
match cached_discriminant_type_metadata {
|
||||
Some(discriminant_type_metadata) => discriminant_type_metadata,
|
||||
None => {
|
||||
let discriminant_llvm_type = adt::ll_inttype(cx, inttype);
|
||||
let discriminant_llvm_type = Type::from_integer(cx, inttype);
|
||||
let (discriminant_size, discriminant_align) =
|
||||
size_and_align_of(cx, discriminant_llvm_type);
|
||||
let discriminant_base_type_metadata =
|
||||
type_metadata(cx,
|
||||
adt::ty_of_inttype(cx.tcx(), inttype),
|
||||
inttype.to_ty(&cx.tcx(), signed),
|
||||
syntax_pos::DUMMY_SP);
|
||||
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 {
|
||||
adt::CEnum(inttype, ..) => {
|
||||
return FinalMetadata(discriminant_type_metadata(inttype))
|
||||
layout::CEnum { discr, signed, .. } => {
|
||||
return FinalMetadata(discriminant_type_metadata(discr, signed))
|
||||
},
|
||||
adt::RawNullablePointer { .. } |
|
||||
adt::StructWrappedNullablePointer { .. } |
|
||||
adt::Univariant(..) | adt::UntaggedUnion(..) => None,
|
||||
adt::General(inttype, _) => Some(discriminant_type_metadata(inttype)),
|
||||
layout::RawNullablePointer { .. } |
|
||||
layout::StructWrappedNullablePointer { .. } |
|
||||
layout::Univariant { .. } => None,
|
||||
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);
|
||||
@ -1715,7 +1741,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
enum_llvm_type,
|
||||
EnumMDF(EnumMemberDescriptionFactory {
|
||||
enum_type: enum_type,
|
||||
type_rep: type_rep.clone(),
|
||||
type_rep: type_rep,
|
||||
discriminant_type_metadata: discriminant_type_metadata,
|
||||
containing_scope: containing_scope,
|
||||
file_metadata: file_metadata,
|
||||
|
@ -43,7 +43,7 @@ use std::ptr;
|
||||
|
||||
use syntax_pos::{self, Span, Pos};
|
||||
use syntax::ast;
|
||||
use syntax::attr::IntType;
|
||||
use rustc::ty::layout;
|
||||
|
||||
pub mod gdb;
|
||||
mod utils;
|
||||
@ -69,7 +69,7 @@ pub struct CrateDebugContext<'tcx> {
|
||||
builder: DIBuilderRef,
|
||||
current_debug_location: Cell<InternalDebugLocation>,
|
||||
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>>,
|
||||
namespace_map: RefCell<DefIdMap<DIScope>>,
|
||||
|
@ -513,7 +513,7 @@ fn drop_structural_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
|
||||
let _icx = push_ctxt("drop_structural_ty");
|
||||
|
||||
fn iter_variant<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
|
||||
repr: &adt::Repr<'tcx>,
|
||||
t: Ty<'tcx>,
|
||||
av: adt::MaybeSizedValue,
|
||||
variant: ty::VariantDef<'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() {
|
||||
let arg = monomorphize::field_ty(tcx, substs, field);
|
||||
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);
|
||||
}
|
||||
return cx;
|
||||
@ -543,9 +543,8 @@ fn drop_structural_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
|
||||
let mut cx = cx;
|
||||
match t.sty {
|
||||
ty::TyClosure(_, ref substs) => {
|
||||
let repr = adt::represent_type(cx.ccx(), t);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -562,18 +561,16 @@ fn drop_structural_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
|
||||
|bb, vv| drop_ty(bb, vv, unit_ty, DebugLoc::None));
|
||||
}
|
||||
ty::TyTuple(ref args) => {
|
||||
let repr = adt::represent_type(cx.ccx(), t);
|
||||
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);
|
||||
}
|
||||
}
|
||||
ty::TyAdt(adt, substs) => match adt.adt_kind() {
|
||||
AdtKind::Struct => {
|
||||
let repr = adt::represent_type(cx.ccx(), t);
|
||||
let VariantInfo { fields, discr } = VariantInfo::from_ty(cx.tcx(), t, None);
|
||||
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) {
|
||||
llfld_a
|
||||
@ -593,18 +590,16 @@ fn drop_structural_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
|
||||
AdtKind::Enum => {
|
||||
let fcx = cx.fcx;
|
||||
let ccx = fcx.ccx;
|
||||
|
||||
let repr = adt::represent_type(ccx, t);
|
||||
let n_variants = adt.variants.len();
|
||||
|
||||
// NB: we must hit the discriminant first so that structural
|
||||
// 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) => {
|
||||
if n_variants != 0 {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -633,10 +628,10 @@ fn drop_structural_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
|
||||
let variant_cx = fcx.new_block(&format!("enum-iter-variant-{}",
|
||||
&variant.disr_val
|
||||
.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);
|
||||
let variant_cx = iter_variant(variant_cx,
|
||||
&repr,
|
||||
t,
|
||||
value,
|
||||
variant,
|
||||
substs);
|
||||
|
@ -418,8 +418,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||
let val_ty = substs.type_at(0);
|
||||
match val_ty.sty {
|
||||
ty::TyAdt(adt, ..) if adt.is_enum() => {
|
||||
let repr = adt::represent_type(ccx, val_ty);
|
||||
adt::trans_get_discr(bcx, &repr, llargs[0],
|
||||
adt::trans_get_discr(bcx, val_ty, llargs[0],
|
||||
Some(llret_ty), true)
|
||||
}
|
||||
_ => 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
|
||||
// etc.
|
||||
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);
|
||||
(0..contents.len())
|
||||
.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()
|
||||
}
|
||||
|
@ -24,13 +24,6 @@ pub type llalign = u32;
|
||||
// ______________________________________________________________________
|
||||
// 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
|
||||
// array of T. This is the "ABI" size. It includes any ABI-mandated padding.
|
||||
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.
|
||||
pub fn llbitsize_of_real(cx: &CrateContext, ty: Type) -> llbits {
|
||||
unsafe {
|
||||
|
@ -139,9 +139,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
mir::TerminatorKind::Switch { ref discr, ref adt_def, ref targets } => {
|
||||
let discr_lvalue = self.trans_lvalue(&bcx, discr);
|
||||
let ty = discr_lvalue.ty.to_ty(bcx.tcx());
|
||||
let repr = adt::represent_type(bcx.ccx(), ty);
|
||||
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();
|
||||
@ -167,7 +166,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
if default_bb != Some(target) {
|
||||
let llbb = llblock(self, target);
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -701,10 +700,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
// Handle both by-ref and immediate tuples.
|
||||
match tuple.val {
|
||||
Ref(llval) => {
|
||||
let base_repr = adt::represent_type(bcx.ccx(), tuple.ty);
|
||||
let base = adt::MaybeSizedValue::sized(llval);
|
||||
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 (lldata, llextra) = load_fat_ptr(bcx, ptr);
|
||||
Pair(lldata, llextra)
|
||||
|
@ -23,9 +23,9 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc::ty::cast::{CastTy, IntTy};
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
|
||||
use {abi, adt, base, Disr};
|
||||
use {abi, adt, base, Disr, machine};
|
||||
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_null, C_struct, C_str_slice, C_undef, C_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, _) => {
|
||||
let base_repr = adt::represent_type(self.ccx, tr_base.ty);
|
||||
let llprojected = adt::const_get_field(&base_repr, base.llval,
|
||||
let llprojected = adt::const_get_field(self.ccx, tr_base.ty, base.llval,
|
||||
Disr(0), field.index());
|
||||
let llextra = if is_sized {
|
||||
ptr::null_mut()
|
||||
@ -585,9 +584,8 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||
}
|
||||
_ => Disr(0)
|
||||
};
|
||||
let repr = adt::represent_type(self.ccx, dest_ty);
|
||||
Const::new(
|
||||
adt::trans_const(self.ccx, &repr, disr, &fields),
|
||||
adt::trans_const(self.ccx, dest_ty, disr, &fields),
|
||||
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 llval = operand.llval;
|
||||
let signed = if let CastTy::Int(IntTy::CEnum) = r_t_in {
|
||||
let repr = adt::represent_type(self.ccx, operand.ty);
|
||||
adt::is_discr_signed(&repr)
|
||||
let l = self.ccx.layout_of(operand.ty);
|
||||
adt::is_discr_signed(&l)
|
||||
} else {
|
||||
operand.ty.is_signed()
|
||||
};
|
||||
@ -735,7 +733,12 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
|
||||
|
||||
let base = match tr_lvalue.base {
|
||||
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 {
|
||||
consts::addr_of_mut(self.ccx, llval, align, "ref_mut")
|
||||
} else {
|
||||
|
@ -152,7 +152,6 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
mir::ProjectionElem::Deref => bug!(),
|
||||
mir::ProjectionElem::Field(ref field, _) => {
|
||||
let base_ty = tr_base.ty.to_ty(tcx);
|
||||
let base_repr = adt::represent_type(ccx, base_ty);
|
||||
let discr = match tr_base.ty {
|
||||
LvalueTy::Ty { .. } => 0,
|
||||
LvalueTy::Downcast { adt_def: _, substs: _, variant_index: v } => v,
|
||||
@ -164,7 +163,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
} else {
|
||||
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());
|
||||
let llextra = if is_sized {
|
||||
ptr::null_mut()
|
||||
|
@ -111,10 +111,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
mir::Rvalue::Aggregate(ref kind, ref operands) => {
|
||||
match *kind {
|
||||
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);
|
||||
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() {
|
||||
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) {
|
||||
let val = adt::MaybeSizedValue::sized(dest.llval);
|
||||
let field_index = active_field_index.unwrap_or(i);
|
||||
let lldest_i = adt::trans_field_ptr_builder(&bcx, &repr, val,
|
||||
disr, field_index);
|
||||
let lldest_i = adt::trans_field_ptr_builder(&bcx,
|
||||
dest.ty.to_ty(bcx.tcx()),
|
||||
val, disr, field_index);
|
||||
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_out = type_of::immediate_type_of(bcx.ccx(), cast_ty);
|
||||
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 {
|
||||
OperandValue::Immediate(llval) => llval,
|
||||
OperandValue::Ref(llptr) => {
|
||||
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")
|
||||
};
|
||||
(discr, adt::is_discr_signed(&repr))
|
||||
(discr, adt::is_discr_signed(&l))
|
||||
} else {
|
||||
(operand.immediate(), operand.ty.is_signed())
|
||||
};
|
||||
|
@ -62,11 +62,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
||||
}
|
||||
mir::StatementKind::SetDiscriminant{ref lvalue, variant_index} => {
|
||||
let ty = self.monomorphized_lvalue_ty(lvalue);
|
||||
let repr = adt::represent_type(bcx.ccx(), ty);
|
||||
let lvalue_transed = self.trans_lvalue(&bcx, lvalue);
|
||||
bcx.with_block(|bcx|
|
||||
adt::trans_set_discr(bcx,
|
||||
&repr,
|
||||
ty,
|
||||
lvalue_transed.llval,
|
||||
Disr::from(variant_index))
|
||||
);
|
||||
|
@ -18,6 +18,7 @@ use context::CrateContext;
|
||||
use util::nodemap::FnvHashMap;
|
||||
|
||||
use syntax::ast;
|
||||
use rustc::ty::layout;
|
||||
|
||||
use std::ffi::CString;
|
||||
use std::fmt;
|
||||
@ -299,6 +300,26 @@ impl Type {
|
||||
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. */
|
||||
|
@ -22,17 +22,6 @@ use type_::Type;
|
||||
|
||||
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
|
||||
// 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) => {
|
||||
let llty = sizing_type_of(cx, ty);
|
||||
let size = size as u64;
|
||||
ensure_array_fits_in_address_space(cx, llty, size, t);
|
||||
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 n = t.simd_size(cx.tcx()) as u64;
|
||||
ensure_array_fits_in_address_space(cx, llet, n, t);
|
||||
Type::vector(&llet, n)
|
||||
}
|
||||
|
||||
ty::TyTuple(..) | ty::TyAdt(..) | ty::TyClosure(..) => {
|
||||
let repr = adt::represent_type(cx, t);
|
||||
adt::sizing_type_of(cx, &repr, false)
|
||||
adt::sizing_type_of(cx, t, false)
|
||||
}
|
||||
|
||||
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(..) => {
|
||||
// Only create the named struct, but don't fill it in. We
|
||||
// fill it in *after* placing it into the type cache.
|
||||
let repr = adt::represent_type(cx, t);
|
||||
adt::incomplete_type_of(cx, &repr, "closure")
|
||||
adt::incomplete_type_of(cx, t, "closure")
|
||||
}
|
||||
|
||||
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) => {
|
||||
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);
|
||||
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(..) => {
|
||||
let repr = adt::represent_type(cx, t);
|
||||
adt::type_of(cx, &repr)
|
||||
adt::type_of(cx, t)
|
||||
}
|
||||
ty::TyAdt(..) if t.is_simd() => {
|
||||
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 n = t.simd_size(cx.tcx()) as u64;
|
||||
ensure_array_fits_in_address_space(cx, llet, n, t);
|
||||
Type::vector(&llet, n)
|
||||
}
|
||||
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
|
||||
// avoids creating more than one copy of the enum when one
|
||||
// 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);
|
||||
adt::incomplete_type_of(cx, &repr, &name[..])
|
||||
adt::incomplete_type_of(cx, t, &name[..])
|
||||
}
|
||||
|
||||
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.
|
||||
match t.sty {
|
||||
ty::TyAdt(..) | ty::TyClosure(..) if !t.is_simd() => {
|
||||
let repr = adt::represent_type(cx, t);
|
||||
adt::finish_type_of(cx, &repr, &mut llty);
|
||||
adt::finish_type_of(cx, t, &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>)
|
||||
-> machine::llalign {
|
||||
let llty = sizing_type_of(cx, t);
|
||||
machine::llalign_of_min(cx, llty)
|
||||
let layout = cx.layout_of(t);
|
||||
layout.align(&cx.tcx().data_layout).abi() as machine::llalign
|
||||
}
|
||||
|
||||
fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||
|
@ -22,12 +22,12 @@ pub enum E {
|
||||
B(f32)
|
||||
}
|
||||
|
||||
// CHECK: @VAR2 = constant {{.*}} { i32 0, i32 666, {{.*}} }, section ".test_two"
|
||||
// CHECK: @VAR2 = constant {{.*}} { i32 0, i32 666 }, section ".test_two"
|
||||
#[no_mangle]
|
||||
#[link_section = ".test_two"]
|
||||
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]
|
||||
#[link_section = ".test_three"]
|
||||
pub static VAR3: E = E::B(1.);
|
||||
|
Loading…
Reference in New Issue
Block a user