Skip to content

Commit 7dc79cc

Browse files
committed
miri: pass pointer alignments directly instead of contextually.
1 parent 08646c6 commit 7dc79cc

File tree

7 files changed

+137
-195
lines changed

7 files changed

+137
-195
lines changed

src/librustc/mir/interpret/mod.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,10 @@ pub use self::error::{EvalError, EvalResult, EvalErrorKind};
1313
pub use self::value::{PrimVal, PrimValKind, Value, Pointer, bytes_to_f32, bytes_to_f64};
1414

1515
use std::collections::BTreeMap;
16-
use ty::layout::HasDataLayout;
1716
use std::fmt;
18-
use ty::layout;
1917
use mir;
2018
use ty;
19+
use ty::layout::{self, Align, HasDataLayout};
2120
use middle::region;
2221
use std::iter;
2322

@@ -166,7 +165,7 @@ pub struct Allocation {
166165
/// Denotes undefined memory. Reading from undefined memory is forbidden in miri
167166
pub undef_mask: UndefMask,
168167
/// The alignment of the allocation to detect unaligned reads.
169-
pub align: u64,
168+
pub align: Align,
170169
}
171170

172171
impl Allocation {
@@ -177,7 +176,7 @@ impl Allocation {
177176
bytes: slice.to_owned(),
178177
relocations: BTreeMap::new(),
179178
undef_mask,
180-
align: 1,
179+
align: Align::from_bytes(1, 1).unwrap(),
181180
}
182181
}
183182
}

src/librustc_mir/interpret/const_eval.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ pub fn eval_body<'a, 'tcx>(
6666
assert!(!layout.is_unsized());
6767
let ptr = ecx.memory.allocate(
6868
layout.size.bytes(),
69-
layout.align.abi(),
69+
layout.align,
7070
None,
7171
)?;
7272
tcx.interpret_interner.borrow_mut().cache(cid, ptr.into());
@@ -95,7 +95,7 @@ pub fn eval_body_as_integer<'a, 'tcx>(
9595
let ptr_ty = eval_body(tcx, instance, param_env);
9696
let (ptr, ty) = ptr_ty?;
9797
let ecx = mk_eval_cx(tcx, instance, param_env)?;
98-
let prim = match ecx.try_read_value(ptr, ty)? {
98+
let prim = match ecx.try_read_value(ptr, ecx.layout_of(ty)?.align, ty)? {
9999
Some(Value::ByVal(prim)) => prim.to_bytes()?,
100100
_ => return err!(TypeNotPrimitive(ty)),
101101
};

src/librustc_mir/interpret/eval_context.rs

+44-57
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
211211
assert!(!layout.is_unsized(), "cannot alloc memory for unsized type");
212212

213213
let size = layout.size.bytes();
214-
let align = layout.align.abi();
215-
self.memory.allocate(size, align, Some(MemoryKind::Stack))
214+
self.memory.allocate(size, layout.align, Some(MemoryKind::Stack))
216215
}
217216

218217
pub fn memory(&self) -> &Memory<'a, 'tcx, M> {
@@ -612,12 +611,12 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
612611
let elem_size = self.layout_of(elem_ty)?.size.bytes();
613612
let value = self.eval_operand(operand)?.value;
614613

615-
let dest = Pointer::from(self.force_allocation(dest)?.to_ptr()?);
614+
let (dest, dest_align) = self.force_allocation(dest)?.to_ptr_align();
616615

617616
// FIXME: speed up repeat filling
618617
for i in 0..length {
619618
let elem_dest = dest.offset(i * elem_size, &self)?;
620-
self.write_value_to_ptr(value, elem_dest, elem_ty)?;
619+
self.write_value_to_ptr(value, elem_dest, dest_align, elem_ty)?;
621620
}
622621
}
623622

@@ -955,15 +954,6 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
955954
layout.align)
956955
}
957956

958-
fn copy(&mut self, src: Pointer, dest: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx> {
959-
let layout = self.layout_of(ty)?;
960-
assert!(!layout.is_unsized(), "cannot copy from an unsized type");
961-
let size = layout.size.bytes();
962-
let align = layout.align.abi();
963-
self.memory.copy(src, dest, size, align, false)?;
964-
Ok(())
965-
}
966-
967957
pub fn force_allocation(&mut self, place: Place) -> EvalResult<'tcx, Place> {
968958
let new_place = match place {
969959
Place::Local { frame, local } => {
@@ -984,8 +974,9 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
984974
let ptr = self.alloc_ptr(ty)?;
985975
self.stack[frame].locals[local.index() - 1] =
986976
Some(Value::ByRef(ptr.into(), layout.align)); // it stays live
987-
self.write_value_to_ptr(val, ptr.into(), ty)?;
988-
Place::from_ptr(ptr, layout.align)
977+
let place = Place::from_ptr(ptr, layout.align);
978+
self.write_value(ValTy { value: val, ty }, place)?;
979+
place
989980
}
990981
}
991982
}
@@ -1002,7 +993,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
1002993
) -> EvalResult<'tcx, Value> {
1003994
match value {
1004995
Value::ByRef(ptr, align) => {
1005-
self.read_with_align(align, |ectx| ectx.read_value(ptr, ty))
996+
self.read_value(ptr, align, ty)
1006997
}
1007998
other => Ok(other),
1008999
}
@@ -1059,8 +1050,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
10591050
match dest {
10601051
Place::Ptr { ptr, align, extra } => {
10611052
assert_eq!(extra, PlaceExtra::None);
1062-
self.write_with_align_mut(align,
1063-
|ectx| ectx.write_value_to_ptr(src_val, ptr, dest_ty))
1053+
self.write_value_to_ptr(src_val, ptr, align, dest_ty)
10641054
}
10651055

10661056
Place::Local { frame, local } => {
@@ -1091,10 +1081,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
10911081
//
10921082
// Thus, it would be an error to replace the `ByRef` with a `ByVal`, unless we
10931083
// knew for certain that there were no outstanding pointers to this allocation.
1094-
self.write_with_align_mut(align, |ectx| {
1095-
ectx.write_value_to_ptr(src_val, dest_ptr, dest_ty)
1096-
})?;
1097-
1084+
self.write_value_to_ptr(src_val, dest_ptr, align, dest_ty)?;
10981085
} else if let Value::ByRef(src_ptr, align) = src_val {
10991086
// If the value is not `ByRef`, then we know there are no pointers to it
11001087
// and we can simply overwrite the `Value` in the locals array directly.
@@ -1107,18 +1094,14 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
11071094
// It is a valid optimization to attempt reading a primitive value out of the
11081095
// source and write that into the destination without making an allocation, so
11091096
// we do so here.
1110-
self.read_with_align_mut(align, |ectx| {
1111-
if let Ok(Some(src_val)) = ectx.try_read_value(src_ptr, dest_ty) {
1112-
write_dest(ectx, src_val)?;
1113-
} else {
1114-
let dest_ptr = ectx.alloc_ptr(dest_ty)?.into();
1115-
ectx.copy(src_ptr, dest_ptr, dest_ty)?;
1116-
let layout = ectx.layout_of(dest_ty)?;
1117-
write_dest(ectx, Value::ByRef(dest_ptr, layout.align))?;
1118-
}
1119-
Ok(())
1120-
})?;
1121-
1097+
if let Ok(Some(src_val)) = self.try_read_value(src_ptr, align, dest_ty) {
1098+
write_dest(self, src_val)?;
1099+
} else {
1100+
let dest_ptr = self.alloc_ptr(dest_ty)?.into();
1101+
let layout = self.layout_of(dest_ty)?;
1102+
self.memory.copy(src_ptr, align.min(layout.align), dest_ptr, layout.align, layout.size.bytes(), false)?;
1103+
write_dest(self, Value::ByRef(dest_ptr, layout.align))?;
1104+
}
11221105
} else {
11231106
// Finally, we have the simple case where neither source nor destination are
11241107
// `ByRef`. We may simply copy the source value over the the destintion.
@@ -1131,26 +1114,26 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
11311114
&mut self,
11321115
value: Value,
11331116
dest: Pointer,
1117+
dest_align: Align,
11341118
dest_ty: Ty<'tcx>,
11351119
) -> EvalResult<'tcx> {
11361120
trace!("write_value_to_ptr: {:#?}", value);
1121+
let layout = self.layout_of(dest_ty)?;
11371122
match value {
11381123
Value::ByRef(ptr, align) => {
1139-
self.read_with_align_mut(align, |ectx| ectx.copy(ptr, dest, dest_ty))
1124+
self.memory.copy(ptr, align.min(layout.align), dest, dest_align.min(layout.align), layout.size.bytes(), false)
11401125
}
11411126
Value::ByVal(primval) => {
1142-
let layout = self.layout_of(dest_ty)?;
11431127
match layout.abi {
11441128
layout::Abi::Scalar(_) => {}
11451129
_ if primval.is_undef() => {}
11461130
_ => bug!("write_value_to_ptr: invalid ByVal layout: {:#?}", layout)
11471131
}
11481132
// TODO: Do we need signedness?
1149-
self.memory.write_primval(dest.to_ptr()?, primval, layout.size.bytes(), false)
1133+
self.memory.write_primval(dest.to_ptr()?, dest_align, primval, layout.size.bytes(), false)
11501134
}
11511135
Value::ByValPair(a_val, b_val) => {
11521136
let ptr = dest.to_ptr()?;
1153-
let mut layout = self.layout_of(dest_ty)?;
11541137
trace!("write_value_to_ptr valpair: {:#?}", layout);
11551138
let (a, b) = match layout.abi {
11561139
layout::Abi::ScalarPair(ref a, ref b) => (&a.value, &b.value),
@@ -1161,9 +1144,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
11611144
let b_offset = a_size.abi_align(b.align(&self));
11621145
let b_ptr = ptr.offset(b_offset.bytes(), &self)?.into();
11631146
// TODO: What about signedess?
1164-
self.memory.write_primval(a_ptr, a_val, a_size.bytes(), false)?;
1165-
self.memory.write_primval(b_ptr, b_val, b_size.bytes(), false)?;
1166-
Ok(())
1147+
self.memory.write_primval(a_ptr, dest_align, a_val, a_size.bytes(), false)?;
1148+
self.memory.write_primval(b_ptr, dest_align, b_val, b_size.bytes(), false)
11671149
}
11681150
}
11691151
}
@@ -1246,8 +1228,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
12461228
}
12471229
}
12481230

1249-
pub fn read_value(&self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
1250-
if let Some(val) = self.try_read_value(ptr, ty)? {
1231+
pub fn read_value(&self, ptr: Pointer, align: Align, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
1232+
if let Some(val) = self.try_read_value(ptr, align, ty)? {
12511233
Ok(val)
12521234
} else {
12531235
bug!("primitive read failed for type: {:?}", ty);
@@ -1257,34 +1239,35 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
12571239
pub(crate) fn read_ptr(
12581240
&self,
12591241
ptr: MemoryPointer,
1242+
ptr_align: Align,
12601243
pointee_ty: Ty<'tcx>,
12611244
) -> EvalResult<'tcx, Value> {
12621245
let ptr_size = self.memory.pointer_size();
1263-
let p : Pointer = self.memory.read_ptr_sized_unsigned(ptr)?.into();
1246+
let p: Pointer = self.memory.read_ptr_sized_unsigned(ptr, ptr_align)?.into();
12641247
if self.type_is_sized(pointee_ty) {
12651248
Ok(p.to_value())
12661249
} else {
12671250
trace!("reading fat pointer extra of type {}", pointee_ty);
12681251
let extra = ptr.offset(ptr_size, self)?;
12691252
match self.tcx.struct_tail(pointee_ty).sty {
12701253
ty::TyDynamic(..) => Ok(p.to_value_with_vtable(
1271-
self.memory.read_ptr_sized_unsigned(extra)?.to_ptr()?,
1254+
self.memory.read_ptr_sized_unsigned(extra, ptr_align)?.to_ptr()?,
12721255
)),
12731256
ty::TySlice(..) | ty::TyStr => Ok(
1274-
p.to_value_with_len(self.memory.read_ptr_sized_unsigned(extra)?.to_bytes()? as u64),
1257+
p.to_value_with_len(self.memory.read_ptr_sized_unsigned(extra, ptr_align)?.to_bytes()? as u64),
12751258
),
12761259
_ => bug!("unsized primval ptr read from {:?}", pointee_ty),
12771260
}
12781261
}
12791262
}
12801263

1281-
pub fn try_read_value(&self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<Value>> {
1264+
pub fn try_read_value(&self, ptr: Pointer, ptr_align: Align, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<Value>> {
12821265
use syntax::ast::FloatTy;
12831266

12841267
let ptr = ptr.to_ptr()?;
12851268
let val = match ty.sty {
12861269
ty::TyBool => {
1287-
let val = self.memory.read_primval(ptr, 1, false)?;
1270+
let val = self.memory.read_primval(ptr, ptr_align, 1, false)?;
12881271
let val = match val {
12891272
PrimVal::Bytes(0) => false,
12901273
PrimVal::Bytes(1) => true,
@@ -1294,7 +1277,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
12941277
PrimVal::from_bool(val)
12951278
}
12961279
ty::TyChar => {
1297-
let c = self.memory.read_primval(ptr, 4, false)?.to_bytes()? as u32;
1280+
let c = self.memory.read_primval(ptr, ptr_align, 4, false)?.to_bytes()? as u32;
12981281
match ::std::char::from_u32(c) {
12991282
Some(ch) => PrimVal::from_char(ch),
13001283
None => return err!(InvalidChar(c as u128)),
@@ -1311,7 +1294,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
13111294
I128 => 16,
13121295
Is => self.memory.pointer_size(),
13131296
};
1314-
self.memory.read_primval(ptr, size, true)?
1297+
self.memory.read_primval(ptr, ptr_align, size, true)?
13151298
}
13161299

13171300
ty::TyUint(uint_ty) => {
@@ -1324,19 +1307,23 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
13241307
U128 => 16,
13251308
Us => self.memory.pointer_size(),
13261309
};
1327-
self.memory.read_primval(ptr, size, false)?
1310+
self.memory.read_primval(ptr, ptr_align, size, false)?
13281311
}
13291312

1330-
ty::TyFloat(FloatTy::F32) => PrimVal::Bytes(self.memory.read_primval(ptr, 4, false)?.to_bytes()?),
1331-
ty::TyFloat(FloatTy::F64) => PrimVal::Bytes(self.memory.read_primval(ptr, 8, false)?.to_bytes()?),
1313+
ty::TyFloat(FloatTy::F32) => {
1314+
PrimVal::Bytes(self.memory.read_primval(ptr, ptr_align, 4, false)?.to_bytes()?)
1315+
}
1316+
ty::TyFloat(FloatTy::F64) => {
1317+
PrimVal::Bytes(self.memory.read_primval(ptr, ptr_align, 8, false)?.to_bytes()?)
1318+
}
13321319

1333-
ty::TyFnPtr(_) => self.memory.read_ptr_sized_unsigned(ptr)?,
1320+
ty::TyFnPtr(_) => self.memory.read_ptr_sized_unsigned(ptr, ptr_align)?,
13341321
ty::TyRef(_, ref tam) |
1335-
ty::TyRawPtr(ref tam) => return self.read_ptr(ptr, tam.ty).map(Some),
1322+
ty::TyRawPtr(ref tam) => return self.read_ptr(ptr, ptr_align, tam.ty).map(Some),
13361323

13371324
ty::TyAdt(def, _) => {
13381325
if def.is_box() {
1339-
return self.read_ptr(ptr, ty.boxed_ty()).map(Some);
1326+
return self.read_ptr(ptr, ptr_align, ty.boxed_ty()).map(Some);
13401327
}
13411328

13421329
if let layout::Abi::Scalar(ref scalar) = self.layout_of(ty)?.abi {
@@ -1345,7 +1332,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
13451332
signed = s;
13461333
}
13471334
let size = scalar.value.size(self).bytes();
1348-
self.memory.read_primval(ptr, size, signed)?
1335+
self.memory.read_primval(ptr, ptr_align, size, signed)?
13491336
} else {
13501337
return Ok(None);
13511338
}

0 commit comments

Comments
 (0)