don't duplicate field access logic, always go through lvalue_field
This commit is contained in:
parent
a727ceb7e9
commit
ac71d6f345
3 changed files with 46 additions and 38 deletions
|
@ -358,45 +358,45 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assign_discr_and_fields<
|
pub fn assign_discr_and_fields<
|
||||||
I: IntoIterator<Item = u64>,
|
|
||||||
V: IntoValTyPair<'tcx>,
|
V: IntoValTyPair<'tcx>,
|
||||||
J: IntoIterator<Item = V>,
|
J: IntoIterator<Item = V>,
|
||||||
>(
|
>(
|
||||||
&mut self,
|
&mut self,
|
||||||
dest: Lvalue<'tcx>,
|
dest: Lvalue<'tcx>,
|
||||||
offsets: I,
|
dest_ty: Ty<'tcx>,
|
||||||
|
discr_offset: u64,
|
||||||
operands: J,
|
operands: J,
|
||||||
discr_val: u128,
|
discr_val: u128,
|
||||||
|
variant_idx: usize,
|
||||||
discr_size: u64,
|
discr_size: u64,
|
||||||
) -> EvalResult<'tcx> {
|
) -> EvalResult<'tcx> {
|
||||||
// FIXME(solson)
|
// FIXME(solson)
|
||||||
let dest_ptr = self.force_allocation(dest)?.to_ptr();
|
let dest_ptr = self.force_allocation(dest)?.to_ptr();
|
||||||
|
|
||||||
let mut offsets = offsets.into_iter();
|
|
||||||
let discr_offset = offsets.next().unwrap();
|
|
||||||
let discr_dest = dest_ptr.offset(discr_offset);
|
let discr_dest = dest_ptr.offset(discr_offset);
|
||||||
self.memory.write_uint(discr_dest, discr_val, discr_size)?;
|
self.memory.write_uint(discr_dest, discr_val, discr_size)?;
|
||||||
|
|
||||||
self.assign_fields(dest, offsets, operands)
|
let dest = Lvalue::Ptr {
|
||||||
|
ptr: dest_ptr,
|
||||||
|
extra: LvalueExtra::DowncastVariant(variant_idx),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.assign_fields(dest, dest_ty, operands)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assign_fields<
|
pub fn assign_fields<
|
||||||
I: IntoIterator<Item = u64>,
|
|
||||||
V: IntoValTyPair<'tcx>,
|
V: IntoValTyPair<'tcx>,
|
||||||
J: IntoIterator<Item = V>,
|
J: IntoIterator<Item = V>,
|
||||||
>(
|
>(
|
||||||
&mut self,
|
&mut self,
|
||||||
dest: Lvalue<'tcx>,
|
dest: Lvalue<'tcx>,
|
||||||
offsets: I,
|
dest_ty: Ty<'tcx>,
|
||||||
operands: J,
|
operands: J,
|
||||||
) -> EvalResult<'tcx> {
|
) -> EvalResult<'tcx> {
|
||||||
// FIXME(solson)
|
for (field_index, operand) in operands.into_iter().enumerate() {
|
||||||
let dest = self.force_allocation(dest)?.to_ptr();
|
|
||||||
|
|
||||||
for (offset, operand) in offsets.into_iter().zip(operands) {
|
|
||||||
let (value, value_ty) = operand.into_val_ty_pair(self)?;
|
let (value, value_ty) = operand.into_val_ty_pair(self)?;
|
||||||
let field_dest = dest.offset(offset);
|
let field_dest = self.lvalue_field(dest, field_index, dest_ty, value_ty)?;
|
||||||
self.write_value_to_ptr(value, field_dest, value_ty)?;
|
self.write_value(value, field_dest, value_ty)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -444,22 +444,15 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
use rustc::ty::layout::Layout::*;
|
use rustc::ty::layout::Layout::*;
|
||||||
match *dest_layout {
|
match *dest_layout {
|
||||||
Univariant { ref variant, .. } => {
|
Univariant { ref variant, .. } => {
|
||||||
let offsets = variant.offsets.iter().map(|s| s.bytes());
|
|
||||||
if variant.packed {
|
if variant.packed {
|
||||||
let ptr = self.force_allocation(dest)?.to_ptr_and_extra().0;
|
let ptr = self.force_allocation(dest)?.to_ptr_and_extra().0;
|
||||||
self.memory.mark_packed(ptr, variant.stride().bytes());
|
self.memory.mark_packed(ptr, variant.stride().bytes());
|
||||||
}
|
}
|
||||||
self.assign_fields(dest, offsets, operands)?;
|
self.assign_fields(dest, dest_ty, operands)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Array { .. } => {
|
Array { .. } => {
|
||||||
let elem_size = match dest_ty.sty {
|
self.assign_fields(dest, dest_ty, operands)?;
|
||||||
ty::TyArray(elem_ty, _) => self.type_size(elem_ty)?
|
|
||||||
.expect("array elements are sized") as u64,
|
|
||||||
_ => bug!("tried to assign {:?} to non-array type {:?}", kind, dest_ty),
|
|
||||||
};
|
|
||||||
let offsets = (0..).map(|i| i * elem_size);
|
|
||||||
self.assign_fields(dest, offsets, operands)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
General { discr, ref variants, .. } => {
|
General { discr, ref variants, .. } => {
|
||||||
|
@ -473,9 +466,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
|
|
||||||
self.assign_discr_and_fields(
|
self.assign_discr_and_fields(
|
||||||
dest,
|
dest,
|
||||||
variants[variant].offsets.iter().cloned().map(Size::bytes),
|
dest_ty,
|
||||||
|
variants[variant].offsets[0].bytes(),
|
||||||
operands,
|
operands,
|
||||||
discr_val,
|
discr_val,
|
||||||
|
variant,
|
||||||
discr_size,
|
discr_size,
|
||||||
)?;
|
)?;
|
||||||
} else {
|
} else {
|
||||||
|
@ -511,8 +506,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
self.memory.mark_packed(ptr, nonnull.stride().bytes());
|
self.memory.mark_packed(ptr, nonnull.stride().bytes());
|
||||||
}
|
}
|
||||||
if nndiscr == variant as u64 {
|
if nndiscr == variant as u64 {
|
||||||
let offsets = nonnull.offsets.iter().map(|s| s.bytes());
|
self.assign_fields(dest, dest_ty, operands)?;
|
||||||
self.assign_fields(dest, offsets, operands)?;
|
|
||||||
} else {
|
} else {
|
||||||
for operand in operands {
|
for operand in operands {
|
||||||
let operand_ty = self.operand_ty(operand);
|
let operand_ty = self.operand_ty(operand);
|
||||||
|
@ -543,11 +537,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector { element, count } => {
|
Vector { count, .. } => {
|
||||||
let elem_size = element.size(&self.tcx.data_layout).bytes();
|
|
||||||
debug_assert_eq!(count, operands.len() as u64);
|
debug_assert_eq!(count, operands.len() as u64);
|
||||||
let offsets = (0..).map(|i| i * elem_size);
|
self.assign_fields(dest, dest_ty, operands)?;
|
||||||
self.assign_fields(dest, offsets, operands)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UntaggedUnion { .. } => {
|
UntaggedUnion { .. } => {
|
||||||
|
|
|
@ -195,6 +195,19 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
(Size::from_bytes(field * elem_size), false)
|
(Size::from_bytes(field * elem_size), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We treat arrays + fixed sized indexing like field accesses
|
||||||
|
Array { .. } => {
|
||||||
|
let field = field_index as u64;
|
||||||
|
let elem_size = match base_ty.sty {
|
||||||
|
ty::TyArray(elem_ty, n) => {
|
||||||
|
assert!(field < n as u64);
|
||||||
|
self.type_size(elem_ty)?.expect("array elements are sized") as u64
|
||||||
|
},
|
||||||
|
_ => bug!("lvalue_field: got Array layout but non-array type {:?}", base_ty),
|
||||||
|
};
|
||||||
|
(Size::from_bytes(field * elem_size), false)
|
||||||
|
}
|
||||||
|
|
||||||
_ => bug!("field access on non-product type: {:?}", base_layout),
|
_ => bug!("field access on non-product type: {:?}", base_layout),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -205,6 +218,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
assert!(field.is_none(), "local can't be ByRef and have a field offset");
|
assert!(field.is_none(), "local can't be ByRef and have a field offset");
|
||||||
(ptr, LvalueExtra::None)
|
(ptr, LvalueExtra::None)
|
||||||
},
|
},
|
||||||
|
Value::ByVal(PrimVal::Undef) => {
|
||||||
|
// FIXME: add some logic for when to not allocate
|
||||||
|
(self.force_allocation(base)?.to_ptr(), LvalueExtra::None)
|
||||||
|
},
|
||||||
Value::ByVal(_) => {
|
Value::ByVal(_) => {
|
||||||
assert_eq!(offset.bytes(), 0, "ByVal can only have 1 non zst field with offset 0");
|
assert_eq!(offset.bytes(), 0, "ByVal can only have 1 non zst field with offset 0");
|
||||||
return Ok(base);
|
return Ok(base);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::mir;
|
use rustc::mir;
|
||||||
use rustc::ty::layout::{Layout, Size};
|
use rustc::ty::layout::Layout;
|
||||||
use rustc::ty::subst::Substs;
|
use rustc::ty::subst::Substs;
|
||||||
use rustc::ty::{self, Ty, BareFnTy};
|
use rustc::ty::{self, Ty, BareFnTy};
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
|
@ -215,29 +215,28 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||||
let dest_layout = self.type_layout(dest_ty)?;
|
let dest_layout = self.type_layout(dest_ty)?;
|
||||||
trace!("layout({:?}) = {:#?}", dest_ty, dest_layout);
|
trace!("layout({:?}) = {:#?}", dest_ty, dest_layout);
|
||||||
match *dest_layout {
|
match *dest_layout {
|
||||||
Layout::Univariant { ref variant, .. } => {
|
Layout::Univariant { .. } => {
|
||||||
let disr_val = v.disr_val.to_u128_unchecked();
|
let disr_val = v.disr_val.to_u128_unchecked();
|
||||||
assert_eq!(disr_val, 0);
|
assert_eq!(disr_val, 0);
|
||||||
let offsets = variant.offsets.iter().map(|s| s.bytes());
|
self.assign_fields(lvalue, dest_ty, args)?;
|
||||||
|
|
||||||
self.assign_fields(lvalue, offsets, args)?;
|
|
||||||
},
|
},
|
||||||
Layout::General { discr, ref variants, .. } => {
|
Layout::General { discr, ref variants, .. } => {
|
||||||
let disr_val = v.disr_val.to_u128_unchecked();
|
let disr_val = v.disr_val.to_u128_unchecked();
|
||||||
let discr_size = discr.size().bytes();
|
let discr_size = discr.size().bytes();
|
||||||
self.assign_discr_and_fields(
|
self.assign_discr_and_fields(
|
||||||
lvalue,
|
lvalue,
|
||||||
variants[disr_val as usize].offsets.iter().cloned().map(Size::bytes),
|
dest_ty,
|
||||||
|
variants[disr_val as usize].offsets[0].bytes(),
|
||||||
args,
|
args,
|
||||||
disr_val,
|
disr_val,
|
||||||
|
disr_val as usize,
|
||||||
discr_size,
|
discr_size,
|
||||||
)?;
|
)?;
|
||||||
},
|
},
|
||||||
Layout::StructWrappedNullablePointer { nndiscr, ref nonnull, ref discrfield, .. } => {
|
Layout::StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => {
|
||||||
let disr_val = v.disr_val.to_u128_unchecked();
|
let disr_val = v.disr_val.to_u128_unchecked();
|
||||||
if nndiscr as u128 == disr_val {
|
if nndiscr as u128 == disr_val {
|
||||||
let offsets = nonnull.offsets.iter().map(|s| s.bytes());
|
self.assign_fields(lvalue, dest_ty, args)?;
|
||||||
self.assign_fields(lvalue, offsets, args)?;
|
|
||||||
} else {
|
} else {
|
||||||
for (_, ty) in args {
|
for (_, ty) in args {
|
||||||
assert_eq!(self.type_size(ty)?, Some(0));
|
assert_eq!(self.type_size(ty)?, Some(0));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue