Skip to content

Commit 90c2470

Browse files
authored
Merge pull request #44 from oli-obk/alignment
Alignment
2 parents 0948e2d + f8cfc38 commit 90c2470

File tree

6 files changed

+143
-57
lines changed

6 files changed

+143
-57
lines changed

src/error.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ pub enum EvalError<'tcx> {
3636
},
3737
ExecutionTimeLimitReached,
3838
StackFrameLimitReached,
39+
AlignmentCheckFailed {
40+
required: usize,
41+
has: usize,
42+
},
3943
}
4044

4145
pub type EvalResult<'tcx, T> = Result<T, EvalError<'tcx>>;
@@ -82,6 +86,8 @@ impl<'tcx> Error for EvalError<'tcx> {
8286
"reached the configured maximum execution time",
8387
EvalError::StackFrameLimitReached =>
8488
"reached the configured maximum number of stack frames",
89+
EvalError::AlignmentCheckFailed{..} =>
90+
"tried to execute a misaligned read or write",
8591
}
8692
}
8793

@@ -106,6 +112,9 @@ impl<'tcx> fmt::Display for EvalError<'tcx> {
106112
EvalError::OutOfMemory { allocation_size, memory_size, memory_usage } =>
107113
write!(f, "tried to allocate {} more bytes, but only {} bytes are free of the {} byte memory",
108114
allocation_size, memory_size - memory_usage, memory_size),
115+
EvalError::AlignmentCheckFailed { required, has } =>
116+
write!(f, "tried to access memory with alignment {}, but alignment {} is required",
117+
has, required),
109118
_ => write!(f, "{}", self.description()),
110119
}
111120
}

src/interpreter/mod.rs

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
152152
match output_ty {
153153
ty::FnConverging(ty) => {
154154
let size = self.type_size_with_substs(ty, substs);
155-
self.memory.allocate(size).map(Some)
155+
let align = self.type_align_with_substs(ty, substs);
156+
self.memory.allocate(size, align).map(Some)
156157
}
157158
ty::FnDiverging => Ok(None),
158159
}
@@ -176,19 +177,19 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
176177
use rustc_const_math::{ConstInt, ConstIsize, ConstUsize, ConstFloat};
177178
macro_rules! i2p {
178179
($i:ident, $n:expr) => {{
179-
let ptr = self.memory.allocate($n)?;
180+
let ptr = self.memory.allocate($n, $n)?;
180181
self.memory.write_int(ptr, $i as i64, $n)?;
181182
Ok(ptr)
182183
}}
183184
}
184185
match *const_val {
185186
Float(ConstFloat::F32(f)) => {
186-
let ptr = self.memory.allocate(4)?;
187+
let ptr = self.memory.allocate(4, 4)?;
187188
self.memory.write_f32(ptr, f)?;
188189
Ok(ptr)
189190
},
190191
Float(ConstFloat::F64(f)) => {
191-
let ptr = self.memory.allocate(8)?;
192+
let ptr = self.memory.allocate(8, 8)?;
192193
self.memory.write_f64(ptr, f)?;
193194
Ok(ptr)
194195
},
@@ -197,42 +198,42 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
197198
Integral(ConstInt::InferSigned(_)) => unreachable!(),
198199
Integral(ConstInt::I8(i)) => i2p!(i, 1),
199200
Integral(ConstInt::U8(i)) => i2p!(i, 1),
201+
Integral(ConstInt::Isize(ConstIsize::Is16(i))) |
200202
Integral(ConstInt::I16(i)) => i2p!(i, 2),
203+
Integral(ConstInt::Usize(ConstUsize::Us16(i))) |
201204
Integral(ConstInt::U16(i)) => i2p!(i, 2),
205+
Integral(ConstInt::Isize(ConstIsize::Is32(i))) |
202206
Integral(ConstInt::I32(i)) => i2p!(i, 4),
207+
Integral(ConstInt::Usize(ConstUsize::Us32(i))) |
203208
Integral(ConstInt::U32(i)) => i2p!(i, 4),
209+
Integral(ConstInt::Isize(ConstIsize::Is64(i))) |
204210
Integral(ConstInt::I64(i)) => i2p!(i, 8),
211+
Integral(ConstInt::Usize(ConstUsize::Us64(i))) |
205212
Integral(ConstInt::U64(i)) => i2p!(i, 8),
206-
Integral(ConstInt::Isize(ConstIsize::Is16(i))) => i2p!(i, 2),
207-
Integral(ConstInt::Isize(ConstIsize::Is32(i))) => i2p!(i, 4),
208-
Integral(ConstInt::Isize(ConstIsize::Is64(i))) => i2p!(i, 8),
209-
Integral(ConstInt::Usize(ConstUsize::Us16(i))) => i2p!(i, 2),
210-
Integral(ConstInt::Usize(ConstUsize::Us32(i))) => i2p!(i, 4),
211-
Integral(ConstInt::Usize(ConstUsize::Us64(i))) => i2p!(i, 8),
212213
Str(ref s) => {
213214
let psize = self.memory.pointer_size();
214-
let static_ptr = self.memory.allocate(s.len())?;
215-
let ptr = self.memory.allocate(psize * 2)?;
215+
let static_ptr = self.memory.allocate(s.len(), 1)?;
216+
let ptr = self.memory.allocate(psize * 2, psize)?;
216217
self.memory.write_bytes(static_ptr, s.as_bytes())?;
217218
self.memory.write_ptr(ptr, static_ptr)?;
218219
self.memory.write_usize(ptr.offset(psize as isize), s.len() as u64)?;
219220
Ok(ptr)
220221
}
221222
ByteStr(ref bs) => {
222223
let psize = self.memory.pointer_size();
223-
let static_ptr = self.memory.allocate(bs.len())?;
224-
let ptr = self.memory.allocate(psize)?;
224+
let static_ptr = self.memory.allocate(bs.len(), 1)?;
225+
let ptr = self.memory.allocate(psize, psize)?;
225226
self.memory.write_bytes(static_ptr, bs)?;
226227
self.memory.write_ptr(ptr, static_ptr)?;
227228
Ok(ptr)
228229
}
229230
Bool(b) => {
230-
let ptr = self.memory.allocate(1)?;
231+
let ptr = self.memory.allocate(1, 1)?;
231232
self.memory.write_bool(ptr, b)?;
232233
Ok(ptr)
233234
}
234235
Char(c) => {
235-
let ptr = self.memory.allocate(4)?;
236+
let ptr = self.memory.allocate(4, 4)?;
236237
self.memory.write_uint(ptr, c as u64, 4)?;
237238
Ok(ptr)
238239
},
@@ -278,10 +279,18 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
278279
self.type_size_with_substs(ty, self.substs())
279280
}
280281

282+
fn type_align(&self, ty: Ty<'tcx>) -> usize {
283+
self.type_align_with_substs(ty, self.substs())
284+
}
285+
281286
fn type_size_with_substs(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> usize {
282287
self.type_layout_with_substs(ty, substs).size(&self.tcx.data_layout).bytes() as usize
283288
}
284289

290+
fn type_align_with_substs(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> usize {
291+
self.type_layout_with_substs(ty, substs).align(&self.tcx.data_layout).abi() as usize
292+
}
293+
285294
fn type_layout(&self, ty: Ty<'tcx>) -> &'tcx Layout {
286295
self.type_layout_with_substs(ty, self.substs())
287296
}
@@ -315,7 +324,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
315324

316325
let locals: EvalResult<'tcx, Vec<Pointer>> = arg_tys.chain(var_tys).chain(temp_tys).map(|ty| {
317326
let size = self.type_size_with_substs(ty, substs);
318-
self.memory.allocate(size)
327+
let align = self.type_align_with_substs(ty, substs);
328+
self.memory.allocate(size, align)
319329
}).collect();
320330

321331
self.stack.push(Frame {
@@ -519,15 +529,15 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
519529
}
520530

521531
Repeat(ref operand, _) => {
522-
let (elem_size, length) = match dest_ty.sty {
523-
ty::TyArray(elem_ty, n) => (self.type_size(elem_ty), n),
532+
let (elem_size, elem_align, length) = match dest_ty.sty {
533+
ty::TyArray(elem_ty, n) => (self.type_size(elem_ty), self.type_align(elem_ty), n),
524534
_ => panic!("tried to assign array-repeat to non-array type {:?}", dest_ty),
525535
};
526536

527537
let src = self.eval_operand(operand)?;
528538
for i in 0..length {
529539
let elem_dest = dest.offset((i * elem_size) as isize);
530-
self.memory.copy(src, elem_dest, elem_size)?;
540+
self.memory.copy(src, elem_dest, elem_size, elem_align)?;
531541
}
532542
}
533543

@@ -562,7 +572,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
562572

563573
Box(ty) => {
564574
let size = self.type_size(ty);
565-
let ptr = self.memory.allocate(size)?;
575+
let align = self.type_align(ty);
576+
let ptr = self.memory.allocate(size, align)?;
566577
self.memory.write_ptr(dest, ptr)?;
567578
}
568579

@@ -593,13 +604,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
593604
warn!("misc cast from {:?} to {:?}", src_ty, dest_ty);
594605
let dest_size = self.type_size(dest_ty);
595606
let src_size = self.type_size(src_ty);
607+
let dest_align = self.type_align(dest_ty);
596608

597609
// Hack to support fat pointer -> thin pointer casts to keep tests for
598610
// other things passing for now.
599611
let is_fat_ptr_cast = pointee_type(src_ty).map_or(false, |ty| !self.type_is_sized(ty));
600612

601613
if dest_size == src_size || is_fat_ptr_cast {
602-
self.memory.copy(src, dest, dest_size)?;
614+
self.memory.copy(src, dest, dest_size, dest_align)?;
603615
} else {
604616
return Err(EvalError::Unimplemented(format!("can't handle cast: {:?}", rvalue)));
605617
}
@@ -710,7 +722,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
710722
Item { def_id, substs } => {
711723
if let ty::TyFnDef(..) = ty.sty {
712724
// function items are zero sized
713-
Ok(self.memory.allocate(0)?)
725+
Ok(self.memory.allocate(0, 0)?)
714726
} else {
715727
let cid = ConstantId {
716728
def_id: def_id,
@@ -843,7 +855,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
843855

844856
fn move_(&mut self, src: Pointer, dest: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, ()> {
845857
let size = self.type_size(ty);
846-
self.memory.copy(src, dest, size)?;
858+
let align = self.type_align(ty);
859+
self.memory.copy(src, dest, size, align)?;
847860
Ok(())
848861
}
849862

@@ -967,9 +980,9 @@ pub fn eval_main<'a, 'tcx: 'a>(
967980
if mir.arg_decls.len() == 2 {
968981
// start function
969982
let ptr_size = ecx.memory().pointer_size();
970-
let nargs = ecx.memory_mut().allocate(ptr_size).expect("can't allocate memory for nargs");
983+
let nargs = ecx.memory_mut().allocate(ptr_size, ptr_size).expect("can't allocate memory for nargs");
971984
ecx.memory_mut().write_usize(nargs, 0).unwrap();
972-
let args = ecx.memory_mut().allocate(ptr_size).expect("can't allocate memory for arg pointer");
985+
let args = ecx.memory_mut().allocate(ptr_size, ptr_size).expect("can't allocate memory for arg pointer");
973986
ecx.memory_mut().write_usize(args, 0).unwrap();
974987
ecx.frame_mut().locals[0] = nargs;
975988
ecx.frame_mut().locals[1] = args;

src/interpreter/terminator.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
8888
match func_ty.sty {
8989
ty::TyFnPtr(bare_fn_ty) => {
9090
let ptr = self.eval_operand(func)?;
91-
assert_eq!(ptr.offset, 0);
9291
let fn_ptr = self.memory.read_ptr(ptr)?;
9392
let FunctionDefinition { def_id, substs, fn_ty } = self.memory.get_fn(fn_ptr.alloc_id)?;
9493
if fn_ty != bare_fn_ty {
@@ -290,10 +289,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
290289
"copy_nonoverlapping" => {
291290
let elem_ty = *substs.types.get(subst::FnSpace, 0);
292291
let elem_size = self.type_size(elem_ty);
292+
let elem_align = self.type_align(elem_ty);
293293
let src = self.memory.read_ptr(args_ptrs[0])?;
294294
let dest = self.memory.read_ptr(args_ptrs[1])?;
295295
let count = self.memory.read_isize(args_ptrs[2])?;
296-
self.memory.copy(src, dest, count as usize * elem_size)?;
296+
self.memory.copy(src, dest, count as usize * elem_size, elem_align)?;
297297
}
298298

299299
"discriminant_value" => {
@@ -308,8 +308,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
308308
"init" => self.memory.write_repeat(dest, 0, dest_layout.size(&self.tcx.data_layout).bytes() as usize)?,
309309

310310
"min_align_of" => {
311-
// FIXME: use correct value
312-
self.memory.write_int(dest, 1, pointer_size)?;
311+
let elem_ty = *substs.types.get(subst::FnSpace, 0);
312+
let elem_align = self.type_align(elem_ty);
313+
self.memory.write_uint(dest, elem_align as u64, pointer_size)?;
313314
}
314315

315316
"move_val_init" => {
@@ -416,14 +417,16 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
416417
match &link_name[..] {
417418
"__rust_allocate" => {
418419
let size = self.memory.read_usize(args[0])?;
419-
let ptr = self.memory.allocate(size as usize)?;
420+
let align = self.memory.read_usize(args[1])?;
421+
let ptr = self.memory.allocate(size as usize, align as usize)?;
420422
self.memory.write_ptr(dest, ptr)?;
421423
}
422424

423425
"__rust_reallocate" => {
424426
let ptr = self.memory.read_ptr(args[0])?;
425427
let size = self.memory.read_usize(args[2])?;
426-
let new_ptr = self.memory.reallocate(ptr, size as usize)?;
428+
let align = self.memory.read_usize(args[3])?;
429+
let new_ptr = self.memory.reallocate(ptr, size as usize, align as usize)?;
427430
self.memory.write_ptr(dest, new_ptr)?;
428431
}
429432

0 commit comments

Comments
 (0)