use llvm::{ValueRef, True, IntEQ, IntNE};
use rustc::ty::layout;
use rustc::ty::{self, Ty, AdtKind};
+use rustc::mir::tcx::LvalueTy;
use mir::lvalue::LvalueRef;
use common::*;
use builder::Builder;
pub fn trans_field_ptr<'a, 'tcx>(
bcx: &Builder<'a, 'tcx>,
val: LvalueRef<'tcx>,
- discr: Disr,
- ix: usize
+ ix: usize,
) -> ValueRef {
+ let discr = match val.ty {
+ LvalueTy::Ty { .. } => 0,
+ LvalueTy::Downcast { variant_index, .. } => variant_index,
+ };
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
// decide to do some kind of cdr-coding-like non-unique repr
// someday), it will need to return a possibly-new bcx as well.
match *l {
layout::Univariant { ref variant, .. } => {
- assert_eq!(discr, Disr(0));
+ assert_eq!(discr, 0);
struct_field_ptr(bcx, &variant,
&compute_fields(bcx.ccx, t, 0, false),
val, ix, false)
}
layout::Vector { count, .. } => {
- assert_eq!(discr.0, 0);
+ assert_eq!(discr, 0);
assert!((ix as u64) < count);
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);
+ let mut fields = compute_fields(bcx.ccx, t, discr, false);
fields.insert(0, d.to_ty(&bcx.tcx(), false));
- struct_field_ptr(bcx, &variants[discr.0 as usize],
+ struct_field_ptr(bcx, &variants[discr],
&fields,
val, ix + 1, true)
}
bcx.pointercast(val.llval, ty.ptr_to())
}
layout::RawNullablePointer { nndiscr, .. } |
- layout::StructWrappedNullablePointer { nndiscr, .. } if discr.0 != nndiscr => {
+ layout::StructWrappedNullablePointer { nndiscr, .. } if discr as u64 != nndiscr => {
let nullfields = compute_fields(bcx.ccx, t, (1-nndiscr) as usize, false);
// The unit-like case might have a nonzero number of unit-like fields.
// (e.d., Result of Either with (), as one side.)
layout::RawNullablePointer { nndiscr, .. } => {
let nnty = compute_fields(bcx.ccx, t, nndiscr as usize, false)[0];
assert_eq!(ix, 0);
- assert_eq!(discr.0, nndiscr);
+ assert_eq!(discr as u64, nndiscr);
let ty = type_of::type_of(bcx.ccx, nnty);
bcx.pointercast(val.llval, ty.ptr_to())
}
layout::StructWrappedNullablePointer { ref nonnull, nndiscr, .. } => {
- assert_eq!(discr.0, nndiscr);
+ assert_eq!(discr as u64, nndiscr);
struct_field_ptr(bcx, &nonnull,
- &compute_fields(bcx.ccx, t, discr.0 as usize, false),
+ &compute_fields(bcx.ccx, t, discr, false),
val, ix, false)
}
_ => bug!("element access in type without elements: {} represented as {:#?}", t, l)
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use middle::lang_items::StartFnLangItem;
use rustc::ty::subst::Substs;
+use rustc::mir::tcx::LvalueTy;
use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::adjustment::CustomCoerceUnsized;
continue;
}
- let src_f = adt::trans_field_ptr(bcx, src, Disr(0), i);
- let dst_f = adt::trans_field_ptr(bcx, dst, Disr(0), i);
+ let src_f = adt::trans_field_ptr(bcx, src, i);
+ let dst_f = adt::trans_field_ptr(bcx, dst, i);
if src_fty == dst_fty {
memcpy_ty(bcx, dst_f, src_f, src_fty, None);
} else {
bcx.alloca(fn_ty.ret.memory_ty(ccx), "sret_slot")
};
// Can return unsized value
- let dest_val = LvalueRef::new_sized_ty(dest, sig.output());
+ let mut dest_val = LvalueRef::new_sized_ty(dest, sig.output());
+ dest_val.ty = LvalueTy::Downcast {
+ adt_def: sig.output().ty_adt_def().unwrap(),
+ substs: substs,
+ variant_index: disr.0 as usize,
+ };
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, dest_val, Disr::from(disr), i);
+ let lldestptr = adt::trans_field_ptr(&bcx, dest_val, i);
let arg = &fn_ty.args[arg_idx];
arg_idx += 1;
if common::type_is_fat_ptr(bcx.ccx, arg_ty) {
use middle::lang_items::BoxFreeFnLangItem;
use rustc::ty::subst::{Substs};
use rustc::traits;
-use rustc::ty::{self, AdtKind, Ty, TypeFoldable};
+use rustc::ty::{self, AdtDef, AdtKind, Ty, TypeFoldable};
use rustc::ty::subst::Kind;
+use rustc::mir::tcx::LvalueTy;
use mir::lvalue::LvalueRef;
use adt;
use base::*;
// Iterates through the elements of a structural type, dropping them.
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>,
+ fn iter_variant<'a, 'tcx>(cx: &'a Builder<'a, 'tcx>,
av: LvalueRef<'tcx>,
- variant: &'tcx ty::VariantDef,
- substs: &Substs<'tcx>) {
+ adt_def: &'tcx AdtDef,
+ variant_index: usize,
+ substs: &'tcx Substs<'tcx>) {
+ let variant = &adt_def.variants[variant_index];
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, av, Disr::from(variant.disr_val), i);
+ let mut av = av.clone();
+ av.ty = LvalueTy::Downcast {
+ adt_def: adt_def,
+ substs: substs,
+ variant_index: variant_index,
+ };
+ let field_ptr = adt::trans_field_ptr(&cx, av, i);
drop_ty(&cx, LvalueRef::new_sized_ty(field_ptr, arg));
}
}
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, ptr, Disr(0), i);
+ let llupvar = adt::trans_field_ptr(&cx, ptr, i);
drop_ty(&cx, LvalueRef::new_sized_ty(llupvar, upvar_ty));
}
}
}
ty::TyTuple(ref args) => {
for (i, arg) in args.iter().enumerate() {
- let llfld_a = adt::trans_field_ptr(&cx, ptr, Disr(0), i);
+ let llfld_a = adt::trans_field_ptr(&cx, ptr, i);
drop_ty(&cx, LvalueRef::new_sized_ty(llfld_a, *arg));
}
}
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, ptr, Disr::from(discr), i);
+ let mut ptr = ptr.clone();
+ ptr.ty = LvalueTy::Downcast {
+ adt_def: adt,
+ substs: substs,
+ variant_index: Disr::from(discr).0 as usize,
+ };
+ let llfld_a = adt::trans_field_ptr(&cx, ptr, i);
let ptr = if cx.ccx.shared().type_is_sized(field_ty) {
LvalueRef::new_sized_ty(llfld_a, field_ty)
} else {
(adt::BranchKind::Single, None) => {
if n_variants != 0 {
assert!(n_variants == 1);
- iter_variant(&cx, ptr, &adt.variants[0], substs);
+ iter_variant(&cx, ptr, &adt, 0, substs);
}
}
(adt::BranchKind::Switch, Some(lldiscrim_a)) => {
let llswitch = cx.switch(lldiscrim_a, ret_void_cx.llbb(), n_variants);
let next_cx = cx.build_new_block("enum-iter-next");
- for variant in &adt.variants {
+ for (i, variant) in adt.variants.iter().enumerate() {
let variant_cx_name = format!("enum-iter-variant-{}",
&variant.disr_val.to_string());
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, ptr, variant, substs);
+ iter_variant(&variant_cx, ptr, &adt, i, substs);
variant_cx.br(next_cx.llbb());
}
cx = next_cx;
use machine;
use type_::Type;
use rustc::ty::{self, Ty};
-use Disr;
use rustc::hir;
use syntax::ast;
use syntax::symbol::Symbol;
let arg = LvalueRef::new_sized_ty(llarg, arg_type);
(0..contents.len())
.map(|i| {
- bcx.load(adt::trans_field_ptr(bcx, arg, Disr(0), i))
+ bcx.load(adt::trans_field_ptr(bcx, arg, i))
})
.collect()
}
Ref(llval) => {
for (n, &ty) in arg_types.iter().enumerate() {
let ptr = adt::trans_field_ptr(
- bcx, LvalueRef::new_sized_ty(llval, tuple.ty), Disr(0), n
+ bcx, LvalueRef::new_sized_ty(llval, tuple.ty), n
);
let val = if common::type_is_fat_ptr(bcx.ccx, ty) {
let (lldata, llextra) = base::load_fat_ptr(bcx, ptr, ty);
use machine;
use type_of::type_of;
use type_of;
-use Disr;
use std::ptr;
LvalueRef::new_sized(llval, LvalueTy::from_ty(ty))
}
+ pub fn new_unsized(llval: ValueRef, llextra: ValueRef, ty: LvalueTy<'tcx>) -> LvalueRef<'tcx> {
+ LvalueRef {
+ llval: llval,
+ llextra: llextra,
+ ty: ty,
+ }
+ }
pub fn new_unsized_ty(llval: ValueRef, llextra: ValueRef, ty: Ty<'tcx>) -> LvalueRef<'tcx> {
LvalueRef {
llval: llval,
let (llprojected, llextra) = match projection.elem {
mir::ProjectionElem::Deref => bug!(),
mir::ProjectionElem::Field(ref field, _) => {
- let base_ty = tr_base.ty.to_ty(tcx);
- let discr = match tr_base.ty {
- LvalueTy::Ty { .. } => 0,
- LvalueTy::Downcast { adt_def: _, substs: _, variant_index: v } => v,
- };
- let discr = discr as u64;
let is_sized = self.ccx.shared().type_is_sized(projected_ty.to_ty(tcx));
let base = if is_sized {
- LvalueRef::new_sized_ty(tr_base.llval, base_ty)
- } else {
- LvalueRef::new_unsized_ty(tr_base.llval, tr_base.llextra, base_ty)
- };
- let llprojected = adt::trans_field_ptr(bcx, base, Disr(discr),
- field.index());
- let llextra = if is_sized {
- ptr::null_mut()
+ LvalueRef::new_sized(tr_base.llval, tr_base.ty)
} else {
- tr_base.llextra
+ LvalueRef::new_unsized(tr_base.llval, tr_base.llextra, tr_base.ty)
};
- (llprojected, llextra)
+ let llprojected = adt::trans_field_ptr(bcx, base, field.index());
+ (llprojected, base.llextra)
}
mir::ProjectionElem::Index(ref index) => {
let index = self.trans_operand(bcx, index);
use rustc::ty::{self, Ty};
use rustc::ty::cast::{CastTy, IntTy};
use rustc::ty::layout::Layout;
+use rustc::mir::tcx::LvalueTy;
use rustc::mir;
use middle::lang_items::ExchangeMallocFnLangItem;
mir::Rvalue::Aggregate(ref kind, ref operands) => {
match *kind {
- mir::AggregateKind::Adt(adt_def, variant_index, _, active_field_index) => {
+ mir::AggregateKind::Adt(adt_def, variant_index, substs, active_field_index) => {
let disr = Disr::from(adt_def.variants[variant_index].disr_val);
let dest_ty = dest.ty.to_ty(bcx.tcx());
adt::trans_set_discr(&bcx, dest_ty, dest.llval, Disr::from(disr));
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 = LvalueRef::new_sized_ty(dest.llval, dest_ty);
+ let mut val = LvalueRef::new_sized(dest.llval, dest.ty);
let field_index = active_field_index.unwrap_or(i);
- let lldest_i = adt::trans_field_ptr(&bcx, val, disr, field_index);
+ val.ty = LvalueTy::Downcast {
+ adt_def: adt_def,
+ substs: self.monomorphize(&substs),
+ variant_index: disr.0 as usize,
+ };
+ let lldest_i = adt::trans_field_ptr(&bcx, val, field_index);
self.store_operand(&bcx, lldest_i, op, None);
}
}