Skip to content

Commit

Permalink
Merge pull request rust-lang#108 from oli-obk/packd
Browse files Browse the repository at this point in the history
implement packed struct field access
  • Loading branch information
solson authored Feb 3, 2017
2 parents 29afc84 + 74d1a9a commit 0451b74
Show file tree
Hide file tree
Showing 8 changed files with 191 additions and 70 deletions.
101 changes: 46 additions & 55 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions src/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
match *dest_layout {
Univariant { ref variant, .. } => {
let offsets = variant.offsets.iter().map(|s| s.bytes());
if variant.packed {
let ptr = self.force_allocation(dest)?.to_ptr_and_extra().0;
self.memory.mark_packed(ptr, variant.stride().bytes());
}
self.assign_fields(dest, offsets, operands)?;
}

Expand All @@ -460,6 +464,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
if let mir::AggregateKind::Adt(adt_def, variant, _, _) = *kind {
let discr_val = adt_def.variants[variant].disr_val.to_u128_unchecked();
let discr_size = discr.size().bytes();
if variants[variant].packed {
let ptr = self.force_allocation(dest)?.to_ptr_and_extra().0;
self.memory.mark_packed(ptr, variants[variant].stride().bytes());
}

self.assign_discr_and_fields(
dest,
Expand Down Expand Up @@ -496,6 +504,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {

StructWrappedNullablePointer { nndiscr, ref nonnull, ref discrfield, .. } => {
if let mir::AggregateKind::Adt(_, variant, _, _) = *kind {
if nonnull.packed {
let ptr = self.force_allocation(dest)?.to_ptr_and_extra().0;
self.memory.mark_packed(ptr, nonnull.stride().bytes());
}
if nndiscr == variant as u64 {
let offsets = nonnull.offsets.iter().map(|s| s.bytes());
self.assign_fields(dest, offsets, operands)?;
Expand Down
18 changes: 13 additions & 5 deletions src/lvalue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,13 +173,15 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
let field = field.index();

use rustc::ty::layout::Layout::*;
let offset = match *base_layout {
Univariant { ref variant, .. } => variant.offsets[field],
let (offset, packed) = match *base_layout {
Univariant { ref variant, .. } => {
(variant.offsets[field], variant.packed)
},

General { ref variants, .. } => {
if let LvalueExtra::DowncastVariant(variant_idx) = base_extra {
// +1 for the discriminant, which is field 0
variants[variant_idx].offsets[field + 1]
(variants[variant_idx].offsets[field + 1], variants[variant_idx].packed)
} else {
bug!("field access on enum had no variant index");
}
Expand All @@ -191,7 +193,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
}

StructWrappedNullablePointer { ref nonnull, .. } => {
nonnull.offsets[field]
(nonnull.offsets[field], nonnull.packed)
}

UntaggedUnion { .. } => return Ok(base),
Expand All @@ -200,13 +202,19 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
let field = field as u64;
assert!(field < count);
let elem_size = element.size(&self.tcx.data_layout).bytes();
Size::from_bytes(field * elem_size)
(Size::from_bytes(field * elem_size), false)
}

_ => bug!("field access on non-product type: {:?}", base_layout),
};

let ptr = base_ptr.offset(offset.bytes());

if packed {
let size = self.type_size(field_ty)?.expect("packed struct must be sized");
self.memory.mark_packed(ptr, size);
}

let extra = if self.type_is_sized(field_ty) {
LvalueExtra::None
} else {
Expand Down
Loading

0 comments on commit 0451b74

Please sign in to comment.