use llvm::{ValueRef, True, IntEQ, IntNE};
use rustc::ty::layout;
use rustc::ty::{self, Ty, AdtKind};
+use mir::lvalue::LvalueRef;
use common::*;
use builder::Builder;
use glue;
Single
}
-#[derive(Copy, Clone)]
-pub struct MaybeSizedValue {
- pub value: ValueRef,
- pub meta: ValueRef,
-}
-
-impl MaybeSizedValue {
- pub fn sized(value: ValueRef) -> MaybeSizedValue {
- MaybeSizedValue {
- value: value,
- meta: std::ptr::null_mut()
- }
- }
-
- pub fn unsized_(value: ValueRef, meta: ValueRef) -> MaybeSizedValue {
- MaybeSizedValue {
- value: value,
- meta: meta
- }
- }
-
- pub fn has_meta(&self) -> bool {
- !self.meta.is_null()
- }
-}
-
/// Given an enum, struct, closure, or tuple, extracts fields.
/// Treats closures as a struct with one variant.
/// `empty_if_no_variants` is a switch to deal with empty enums.
/// Access a field, at a point when the value's case is known.
pub fn trans_field_ptr<'a, 'tcx>(
bcx: &Builder<'a, 'tcx>,
- t: Ty<'tcx>,
- val: MaybeSizedValue,
+ val: LvalueRef<'tcx>,
discr: Disr,
ix: usize
) -> ValueRef {
+ let t = val.ty.to_ty(bcx.tcx());
let l = bcx.ccx.layout_of(t);
debug!("trans_field_ptr on {} represented as {:#?}", t, l);
// Note: if this ever needs to generate conditionals (e.g., if we
layout::Vector { count, .. } => {
assert_eq!(discr.0, 0);
assert!((ix as u64) < count);
- bcx.struct_gep(val.value, ix)
+ bcx.struct_gep(val.llval, ix)
}
layout::General { discr: d, ref variants, .. } => {
let mut fields = compute_fields(bcx.ccx, t, discr.0 as usize, false);
layout::UntaggedUnion { .. } => {
let fields = compute_fields(bcx.ccx, t, 0, false);
let ty = type_of::in_memory_type_of(bcx.ccx, fields[ix]);
- bcx.pointercast(val.value, ty.ptr_to())
+ bcx.pointercast(val.llval, ty.ptr_to())
}
layout::RawNullablePointer { nndiscr, .. } |
layout::StructWrappedNullablePointer { nndiscr, .. } if discr.0 != nndiscr => {
// (e.d., Result of Either with (), as one side.)
let ty = type_of::type_of(bcx.ccx, nullfields[ix]);
assert_eq!(machine::llsize_of_alloc(bcx.ccx, ty), 0);
- bcx.pointercast(val.value, ty.ptr_to())
+ bcx.pointercast(val.llval, ty.ptr_to())
}
layout::RawNullablePointer { nndiscr, .. } => {
let nnty = compute_fields(bcx.ccx, t, nndiscr as usize, false)[0];
assert_eq!(ix, 0);
assert_eq!(discr.0, nndiscr);
let ty = type_of::type_of(bcx.ccx, nnty);
- bcx.pointercast(val.value, ty.ptr_to())
+ bcx.pointercast(val.llval, ty.ptr_to())
}
layout::StructWrappedNullablePointer { ref nonnull, nndiscr, .. } => {
assert_eq!(discr.0, nndiscr);
bcx: &Builder<'a, 'tcx>,
st: &layout::Struct,
fields: &Vec<Ty<'tcx>>,
- val: MaybeSizedValue,
+ val: LvalueRef,
ix: usize,
needs_cast: bool
) -> ValueRef {
type_of::in_memory_type_of(ccx, fields[i])
}).collect::<Vec<_>>();
let real_ty = Type::struct_(ccx, &fields[..], st.packed);
- bcx.pointercast(val.value, real_ty.ptr_to())
+ bcx.pointercast(val.llval, real_ty.ptr_to())
} else {
- val.value
+ val.llval
};
// Simple case - we can just GEP the field
}
// There's no metadata available, log the case and just do the GEP.
- if !val.has_meta() {
+ if !val.has_extra() {
debug!("Unsized field `{}`, of `{:?}` has no metadata for adjustment",
ix, Value(ptr_val));
return bcx.struct_gep(ptr_val, ix);
// The type Foo<Foo<Trait>> is represented in LLVM as { u16, { u16, u8 }}, meaning that
// the `y` field has 16-bit alignment.
- let meta = val.meta;
+ let meta = val.llextra;
let offset = st.offsets[ix].bytes();
use rustc_incremental::IncrementalHashesMap;
use session::{self, DataTypeKind, Session};
use abi::{self, Abi, FnType};
+use mir::lvalue::LvalueRef;
use adt;
use attributes;
use builder::Builder;
monomorphize::field_ty(bcx.tcx(), substs_b, f)
});
- let src = adt::MaybeSizedValue::sized(src);
- let dst = adt::MaybeSizedValue::sized(dst);
+ let src = LvalueRef::new_sized_ty(src, src_ty);
+ let dst = LvalueRef::new_sized_ty(dst, dst_ty);
let iter = src_fields.zip(dst_fields).enumerate();
for (i, (src_fty, dst_fty)) in iter {
continue;
}
- 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);
+ let src_f = adt::trans_field_ptr(bcx, src, Disr(0), i);
+ let dst_f = adt::trans_field_ptr(bcx, dst, Disr(0), i);
if src_fty == dst_fty {
memcpy_ty(bcx, dst_f, src_f, src_fty, None);
} else {
// final ret value
bcx.alloca(fn_ty.ret.memory_ty(ccx), "sret_slot")
};
- let dest_val = adt::MaybeSizedValue::sized(dest); // Can return unsized value
+ // Can return unsized value
+ let dest_val = LvalueRef::new_sized_ty(dest, sig.output());
let mut llarg_idx = fn_ty.ret.is_indirect() as usize;
let mut arg_idx = 0;
for (i, arg_ty) in sig.inputs().iter().enumerate() {
- let lldestptr = adt::trans_field_ptr(&bcx, sig.output(), dest_val, Disr::from(disr), i);
+ let lldestptr = adt::trans_field_ptr(&bcx, dest_val, Disr::from(disr), i);
let arg = &fn_ty.args[arg_idx];
arg_idx += 1;
if common::type_is_fat_ptr(bcx.ccx, arg_ty) {
use builder::Builder;
use common::{self, CrateContext, SharedCrateContext};
use cleanup::CleanupScope;
-use adt::MaybeSizedValue;
+use mir::lvalue::LvalueRef;
use consts;
use declare;
use value::Value;
// Call the by-ref closure body with `self` in a cleanup scope,
// to drop `self` when the body returns, or in case it unwinds.
let self_scope = CleanupScope::schedule_drop_mem(
- &bcx, MaybeSizedValue::sized(llenv), closure_ty
+ &bcx, LvalueRef::new_sized_ty(llenv, closure_ty)
);
let llfn = callee.reify(bcx.ccx);
use llvm::BasicBlockRef;
use base;
-use adt::MaybeSizedValue;
+use mir::lvalue::LvalueRef;
+use rustc::mir::tcx::LvalueTy;
use builder::Builder;
use common::Funclet;
use glue;
use type_::Type;
-use rustc::ty::Ty;
pub struct CleanupScope<'tcx> {
// Cleanup to run upon scope exit.
#[derive(Copy, Clone)]
pub struct DropValue<'tcx> {
- val: MaybeSizedValue,
- ty: Ty<'tcx>,
+ val: LvalueRef<'tcx>,
skip_dtor: bool,
}
impl<'tcx> DropValue<'tcx> {
fn trans<'a>(&self, funclet: Option<&'a Funclet>, bcx: &Builder<'a, 'tcx>) {
- glue::call_drop_glue(bcx, self.val, self.ty, self.skip_dtor, funclet)
+ glue::call_drop_glue(bcx, self.val, self.skip_dtor, funclet)
}
/// Creates a landing pad for the top scope. The landing pad will perform all cleanups necessary
impl<'a, 'tcx> CleanupScope<'tcx> {
/// Schedules a (deep) drop of `val`, which is a pointer to an instance of `ty`
pub fn schedule_drop_mem(
- bcx: &Builder<'a, 'tcx>, val: MaybeSizedValue, ty: Ty<'tcx>
+ bcx: &Builder<'a, 'tcx>, val: LvalueRef<'tcx>
) -> CleanupScope<'tcx> {
- if !bcx.ccx.shared().type_needs_drop(ty) { return CleanupScope::noop(); }
+ if let LvalueTy::Downcast { .. } = val.ty {
+ bug!("Cannot drop downcast ty yet");
+ }
+ if !bcx.ccx.shared().type_needs_drop(val.ty.to_ty(bcx.tcx())) {
+ return CleanupScope::noop();
+ }
let drop = DropValue {
val: val,
- ty: ty,
skip_dtor: false,
};
/// and dropping the contents associated with that variant
/// *without* executing any associated drop implementation.
pub fn schedule_drop_adt_contents(
- bcx: &Builder<'a, 'tcx>, val: MaybeSizedValue, ty: Ty<'tcx>
+ bcx: &Builder<'a, 'tcx>, val: LvalueRef<'tcx>
) -> CleanupScope<'tcx> {
+ if let LvalueTy::Downcast { .. } = val.ty {
+ bug!("Cannot drop downcast ty yet");
+ }
// `if` below could be "!contents_needs_drop"; skipping drop
// is just an optimization, so sound to be conservative.
- if !bcx.ccx.shared().type_needs_drop(ty) { return CleanupScope::noop(); }
+ if !bcx.ccx.shared().type_needs_drop(val.ty.to_ty(bcx.tcx())) {
+ return CleanupScope::noop();
+ }
let drop = DropValue {
val: val,
- ty: ty,
skip_dtor: true,
};
use rustc::traits;
use rustc::ty::{self, AdtKind, Ty, TypeFoldable};
use rustc::ty::subst::Kind;
-use adt::{self, MaybeSizedValue};
+use mir::lvalue::LvalueRef;
+use adt;
use base::*;
use callee::Callee;
use cleanup::CleanupScope;
use syntax_pos::DUMMY_SP;
-pub fn trans_exchange_free_ty<'a, 'tcx>(
- bcx: &Builder<'a, 'tcx>,
- ptr: MaybeSizedValue,
- content_ty: Ty<'tcx>
-) {
+pub fn trans_exchange_free_ty<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, ptr: LvalueRef<'tcx>) {
+ let content_ty = ptr.ty.to_ty(bcx.tcx());
let def_id = langcall(bcx.tcx(), None, "", BoxFreeFnLangItem);
let substs = bcx.tcx().mk_substs(iter::once(Kind::from(content_ty)));
let callee = Callee::def(bcx.ccx, def_id, substs);
let fn_ty = callee.direct_fn_type(bcx.ccx, &[]);
let llret = bcx.call(callee.reify(bcx.ccx),
- &[ptr.value, ptr.meta][..1 + ptr.has_meta() as usize], None);
+ &[ptr.llval, ptr.llextra][..1 + ptr.has_extra() as usize], None);
fn_ty.apply_attrs_callsite(llret);
}
}
}
-fn drop_ty<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, args: MaybeSizedValue, t: Ty<'tcx>) {
- call_drop_glue(bcx, args, t, false, None)
+fn drop_ty<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, args: LvalueRef<'tcx>) {
+ call_drop_glue(bcx, args, false, None)
}
pub fn call_drop_glue<'a, 'tcx>(
bcx: &Builder<'a, 'tcx>,
- mut args: MaybeSizedValue,
- t: Ty<'tcx>,
+ mut args: LvalueRef<'tcx>,
skip_dtor: bool,
funclet: Option<&'a Funclet>,
) {
+ let t = args.ty.to_ty(bcx.tcx());
// NB: v is an *alias* of type t here, not a direct value.
debug!("call_drop_glue(t={:?}, skip_dtor={})", t, skip_dtor);
if bcx.ccx.shared().type_needs_drop(t) {
let glue = get_drop_glue_core(ccx, g);
let glue_type = get_drop_glue_type(ccx.shared(), t);
if glue_type != t {
- args.value = bcx.pointercast(args.value, type_of(ccx, glue_type).ptr_to());
+ args.llval = bcx.pointercast(args.llval, type_of(ccx, glue_type).ptr_to());
}
// No drop-hint ==> call standard drop glue
- bcx.call(glue, &[args.value, args.meta][..1 + args.has_meta() as usize],
+ bcx.call(glue, &[args.llval, args.llextra][..1 + args.has_extra() as usize],
funclet.map(|b| b.bundle()));
}
}
let value = get_param(llfn, 0);
let ptr = if ccx.shared().type_is_sized(t) {
- MaybeSizedValue::sized(value)
+ LvalueRef::new_sized_ty(value, t)
} else {
- MaybeSizedValue::unsized_(value, get_param(llfn, 1))
+ LvalueRef::new_unsized_ty(value, get_param(llfn, 1), t)
};
let skip_dtor = match g {
// a safe-guard, assert TyBox not used with TyContents.
assert!(!skip_dtor);
let ptr = if !bcx.ccx.shared().type_is_sized(content_ty) {
- let llbox = bcx.load(get_dataptr(&bcx, ptr.value));
- let info = bcx.load(get_meta(&bcx, ptr.value));
- MaybeSizedValue::unsized_(llbox, info)
+ let llbox = bcx.load(get_dataptr(&bcx, ptr.llval));
+ let info = bcx.load(get_meta(&bcx, ptr.llval));
+ LvalueRef::new_unsized_ty(llbox, info, content_ty)
} else {
- MaybeSizedValue::sized(bcx.load(ptr.value))
+ LvalueRef::new_sized_ty(bcx.load(ptr.llval), content_ty)
};
- drop_ty(&bcx, ptr, content_ty);
- trans_exchange_free_ty(&bcx, ptr, content_ty);
+ drop_ty(&bcx, ptr);
+ trans_exchange_free_ty(&bcx, ptr);
bcx
}
ty::TyDynamic(..) => {
// versus without calling Drop::drop. Assert caller is
// okay with always calling the Drop impl, if any.
assert!(!skip_dtor);
- let dtor = bcx.load(ptr.meta);
- bcx.call(dtor, &[ptr.value], None);
+ let dtor = bcx.load(ptr.llextra);
+ bcx.call(dtor, &[ptr.llval], None);
bcx
}
ty::TyAdt(def, ..) if def.dtor_kind().is_present() && !skip_dtor => {
// Issue #23611: schedule cleanup of contents, re-inspecting the
// discriminant (if any) in case of variant swap in drop code.
let contents_scope = if !shallow_drop {
- CleanupScope::schedule_drop_adt_contents(&bcx, ptr, t)
+ CleanupScope::schedule_drop_adt_contents(&bcx, ptr)
} else {
CleanupScope::noop()
};
let callee = Callee::def(bcx.ccx, dtor_did, vtbl.substs);
let fn_ty = callee.direct_fn_type(bcx.ccx, &[]);
let llret;
- let args = &[ptr.value, ptr.meta][..1 + ptr.has_meta() as usize];
+ let args = &[ptr.llval, ptr.llextra][..1 + ptr.has_extra() as usize];
if let Some(landing_pad) = contents_scope.landing_pad {
let normal_bcx = bcx.build_new_block("normal-return");
llret = bcx.invoke(callee.reify(ccx), args, normal_bcx.llbb(), landing_pad, None);
}
_ => {
if bcx.ccx.shared().type_needs_drop(t) {
- drop_structural_ty(bcx, ptr, t)
+ drop_structural_ty(bcx, ptr)
} else {
bcx
}
}
// Iterates through the elements of a structural type, dropping them.
-fn drop_structural_ty<'a, 'tcx>(cx: Builder<'a, 'tcx>,
- ptr: MaybeSizedValue,
- t: Ty<'tcx>)
- -> Builder<'a, 'tcx> {
+fn drop_structural_ty<'a, 'tcx>(cx: Builder<'a, 'tcx>, ptr: LvalueRef<'tcx>) -> Builder<'a, 'tcx> {
fn iter_variant<'a, 'tcx>(cx: &Builder<'a, 'tcx>,
- t: Ty<'tcx>,
- av: adt::MaybeSizedValue,
+ av: LvalueRef<'tcx>,
variant: &'tcx ty::VariantDef,
substs: &Substs<'tcx>) {
let tcx = cx.tcx();
for (i, field) in variant.fields.iter().enumerate() {
let arg = monomorphize::field_ty(tcx, substs, field);
- let field_ptr = adt::trans_field_ptr(&cx, t, av, Disr::from(variant.disr_val), i);
- drop_ty(&cx, MaybeSizedValue::sized(field_ptr), arg);
+ let field_ptr = adt::trans_field_ptr(&cx, av, Disr::from(variant.disr_val), i);
+ drop_ty(&cx, LvalueRef::new_sized_ty(field_ptr, arg));
}
}
let mut cx = cx;
+ let t = ptr.ty.to_ty(cx.tcx());
match t.sty {
ty::TyClosure(def_id, substs) => {
for (i, upvar_ty) in substs.upvar_tys(def_id, cx.tcx()).enumerate() {
- let llupvar = adt::trans_field_ptr(&cx, t, ptr, Disr(0), i);
- drop_ty(&cx, MaybeSizedValue::sized(llupvar), upvar_ty);
+ let llupvar = adt::trans_field_ptr(&cx, ptr, Disr(0), i);
+ drop_ty(&cx, LvalueRef::new_sized_ty(llupvar, upvar_ty));
}
}
ty::TyArray(_, n) => {
- let base = get_dataptr(&cx, ptr.value);
+ let base = get_dataptr(&cx, ptr.llval);
let len = C_uint(cx.ccx, n);
let unit_ty = t.sequence_element_type(cx.tcx());
cx = tvec::slice_for_each(&cx, base, unit_ty, len,
- |bb, vv| drop_ty(bb, MaybeSizedValue::sized(vv), unit_ty));
+ |bb, vv| drop_ty(bb, LvalueRef::new_sized_ty(vv, unit_ty)));
}
ty::TySlice(_) | ty::TyStr => {
let unit_ty = t.sequence_element_type(cx.tcx());
- cx = tvec::slice_for_each(&cx, ptr.value, unit_ty, ptr.meta,
- |bb, vv| drop_ty(bb, MaybeSizedValue::sized(vv), unit_ty));
+ cx = tvec::slice_for_each(&cx, ptr.llval, unit_ty, ptr.llextra,
+ |bb, vv| drop_ty(bb, LvalueRef::new_sized_ty(vv, unit_ty)));
}
ty::TyTuple(ref args) => {
for (i, arg) in args.iter().enumerate() {
- let llfld_a = adt::trans_field_ptr(&cx, t, ptr, Disr(0), i);
- drop_ty(&cx, MaybeSizedValue::sized(llfld_a), *arg);
+ let llfld_a = adt::trans_field_ptr(&cx, ptr, Disr(0), i);
+ drop_ty(&cx, LvalueRef::new_sized_ty(llfld_a, *arg));
}
}
ty::TyAdt(adt, substs) => match adt.adt_kind() {
AdtKind::Struct => {
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, t, ptr, Disr::from(discr), i);
+ let llfld_a = adt::trans_field_ptr(&cx, ptr, Disr::from(discr), i);
let ptr = if cx.ccx.shared().type_is_sized(field_ty) {
- MaybeSizedValue::sized(llfld_a)
+ LvalueRef::new_sized_ty(llfld_a, field_ty)
} else {
- MaybeSizedValue::unsized_(llfld_a, ptr.meta)
+ LvalueRef::new_unsized_ty(llfld_a, ptr.llextra, field_ty)
};
- drop_ty(&cx, ptr, field_ty);
+ drop_ty(&cx, ptr);
}
}
AdtKind::Union => {
// NB: we must hit the discriminant first so that structural
// comparison know not to proceed when the discriminants differ.
- match adt::trans_switch(&cx, t, ptr.value, false) {
+ match adt::trans_switch(&cx, t, ptr.llval, false) {
(adt::BranchKind::Single, None) => {
if n_variants != 0 {
assert!(n_variants == 1);
- iter_variant(&cx, t, ptr, &adt.variants[0], substs);
+ iter_variant(&cx, ptr, &adt.variants[0], substs);
}
}
(adt::BranchKind::Switch, Some(lldiscrim_a)) => {
let tcx = cx.tcx();
- drop_ty(&cx, MaybeSizedValue::sized(lldiscrim_a), tcx.types.isize);
+ drop_ty(&cx, LvalueRef::new_sized_ty(lldiscrim_a, tcx.types.isize));
// Create a fall-through basic block for the "else" case of
// the switch instruction we're about to generate. Note that
let variant_cx = cx.build_new_block(&variant_cx_name);
let case_val = adt::trans_case(&cx, t, Disr::from(variant.disr_val));
variant_cx.add_case(llswitch, case_val, variant_cx.llbb());
- iter_variant(&variant_cx, t, ptr, variant, substs);
+ iter_variant(&variant_cx, ptr, variant, substs);
variant_cx.br(next_cx.llbb());
}
cx = next_cx;
use llvm::{ValueRef};
use abi::{Abi, FnType};
use adt;
+use mir::lvalue::LvalueRef;
use base::*;
use common::*;
use declare;
// destructors, and the contents are SIMD
// etc.
assert!(!bcx.ccx.shared().type_needs_drop(arg_type));
- let arg = adt::MaybeSizedValue::sized(llarg);
+ let arg = LvalueRef::new_sized_ty(llarg, arg_type);
(0..contents.len())
.map(|i| {
- bcx.load(adt::trans_field_ptr(bcx, arg_type, arg, Disr(0), i))
+ bcx.load(adt::trans_field_ptr(bcx, arg, Disr(0), i))
})
.collect()
}
use rustc::ty::{self, layout};
use rustc::mir;
use abi::{Abi, FnType, ArgType};
-use adt::{self, MaybeSizedValue};
+use adt;
use base::{self, Lifetime};
use callee::{Callee, CalleeData, Fn, Intrinsic, NamedTupleConstructor, Virtual};
use builder::Builder;
use super::{MirContext, LocalRef};
use super::analyze::CleanupKind;
use super::constant::Const;
-use super::lvalue::{LvalueRef};
+use super::lvalue::LvalueRef;
use super::operand::OperandRef;
use super::operand::OperandValue::{Pair, Ref, Immediate};
} else {
lvalue.llval
};
- MaybeSizedValue::sized(value)
+ LvalueRef::new_sized_ty(value, ty)
} else {
- MaybeSizedValue::unsized_(lvalue.llval, lvalue.llextra)
+ LvalueRef::new_unsized_ty(lvalue.llval, lvalue.llextra, ty)
};
- let args = &[ptr.value, ptr.meta][..1 + ptr.has_meta() as usize];
+ let args = &[ptr.llval, ptr.llextra][..1 + ptr.has_extra() as usize];
if let Some(unwind) = unwind {
bcx.invoke(
drop_fn,
// Handle both by-ref and immediate tuples.
match tuple.val {
Ref(llval) => {
- let base = adt::MaybeSizedValue::sized(llval);
for (n, &ty) in arg_types.iter().enumerate() {
- let ptr = adt::trans_field_ptr(bcx, tuple.ty, base, Disr(0), n);
+ let ptr = adt::trans_field_ptr(
+ bcx, LvalueRef::new_sized_ty(llval, tuple.ty), Disr(0), n
+ );
let val = if common::type_is_fat_ptr(bcx.ccx, ty) {
let (lldata, llextra) = base::load_fat_ptr(bcx, ptr, ty);
Pair(lldata, llextra)
LvalueRef { llval: llval, llextra: ptr::null_mut(), ty: lvalue_ty }
}
+ pub fn new_sized_ty(llval: ValueRef, ty: Ty<'tcx>) -> LvalueRef<'tcx> {
+ LvalueRef::new_sized(llval, LvalueTy::from_ty(ty))
+ }
+
+ pub fn new_unsized_ty(llval: ValueRef, llextra: ValueRef, ty: Ty<'tcx>) -> LvalueRef<'tcx> {
+ LvalueRef {
+ llval: llval,
+ llextra: llextra,
+ ty: LvalueTy::from_ty(ty),
+ }
+ }
+
pub fn len<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> ValueRef {
let ty = self.ty.to_ty(ccx.tcx());
match ty.sty {
_ => bug!("unexpected type `{}` in LvalueRef::len", ty)
}
}
+
+ pub fn has_extra(&self) -> bool {
+ !self.llextra.is_null()
+ }
}
impl<'a, 'tcx> MirContext<'a, 'tcx> {
let discr = discr as u64;
let is_sized = self.ccx.shared().type_is_sized(projected_ty.to_ty(tcx));
let base = if is_sized {
- adt::MaybeSizedValue::sized(tr_base.llval)
+ LvalueRef::new_sized_ty(tr_base.llval, base_ty)
} else {
- adt::MaybeSizedValue::unsized_(tr_base.llval, tr_base.llextra)
+ LvalueRef::new_unsized_ty(tr_base.llval, tr_base.llextra, base_ty)
};
- let llprojected = adt::trans_field_ptr(bcx, base_ty, base, Disr(discr),
+ let llprojected = adt::trans_field_ptr(bcx, base, Disr(discr),
field.index());
let llextra = if is_sized {
ptr::null_mut()
pub use self::constant::trans_static_initializer;
use self::analyze::CleanupKind;
-use self::lvalue::{LvalueRef};
+use self::lvalue::LvalueRef;
use rustc::mir::traversal;
use self::operand::{OperandRef, OperandValue};
mod analyze;
mod block;
mod constant;
-mod lvalue;
+pub mod lvalue;
mod operand;
mod rvalue;
mod statement;
let op = self.trans_operand(&bcx, operand);
// Do not generate stores and GEPis for zero-sized fields.
if !common::type_is_zero_size(bcx.ccx, op.ty) {
- let val = adt::MaybeSizedValue::sized(dest.llval);
+ let val = LvalueRef::new_sized_ty(dest.llval, dest_ty);
let field_index = active_field_index.unwrap_or(i);
- let lldest_i = adt::trans_field_ptr(&bcx, dest_ty, val, disr,
- field_index);
+ let lldest_i = adt::trans_field_ptr(&bcx, val, disr, field_index);
self.store_operand(&bcx, lldest_i, op, None);
}
}