Skip to content

Commit ba23b87

Browse files
authored
Merge pull request #34 from oli-obk/alignment
use ty::layout::Size and ty::layout::TargetDataLayout
2 parents 0c720f6 + 4c7aae7 commit ba23b87

File tree

6 files changed

+72
-55
lines changed

6 files changed

+72
-55
lines changed

src/interpreter/mod.rs

+11-15
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ pub struct EvalContext<'a, 'tcx: 'a> {
3535
mir_cache: RefCell<DefIdMap<Rc<mir::Mir<'tcx>>>>,
3636

3737
/// The virtual memory system.
38-
memory: Memory<'tcx>,
38+
memory: Memory<'a, 'tcx>,
3939

4040
/// Precomputed statics, constants and promoteds.
4141
statics: HashMap<ConstantId<'tcx>, Pointer>,
@@ -138,11 +138,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
138138
tcx: tcx,
139139
mir_map: mir_map,
140140
mir_cache: RefCell::new(DefIdMap()),
141-
memory: Memory::new(tcx.sess
142-
.target
143-
.uint_type
144-
.bit_width()
145-
.expect("Session::target::uint_type was usize")/8),
141+
memory: Memory::new(&tcx.data_layout),
146142
statics: HashMap::new(),
147143
stack: Vec::new(),
148144
}
@@ -162,7 +158,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
162158
&self.memory
163159
}
164160

165-
pub fn memory_mut(&mut self) -> &mut Memory<'tcx> {
161+
pub fn memory_mut(&mut self) -> &mut Memory<'a, 'tcx> {
166162
&mut self.memory
167163
}
168164

@@ -182,7 +178,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
182178
Ok(ptr)
183179
}
184180
Str(ref s) => {
185-
let psize = self.memory.pointer_size;
181+
let psize = self.memory.pointer_size();
186182
let static_ptr = self.memory.allocate(s.len());
187183
let ptr = self.memory.allocate(psize * 2);
188184
self.memory.write_bytes(static_ptr, s.as_bytes())?;
@@ -191,7 +187,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
191187
Ok(ptr)
192188
}
193189
ByteStr(ref bs) => {
194-
let psize = self.memory.pointer_size;
190+
let psize = self.memory.pointer_size();
195191
let static_ptr = self.memory.allocate(bs.len());
196192
let ptr = self.memory.allocate(psize);
197193
self.memory.write_bytes(static_ptr, bs)?;
@@ -515,7 +511,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
515511
match lv.extra {
516512
LvalueExtra::None => {},
517513
LvalueExtra::Length(len) => {
518-
let len_ptr = dest.offset(self.memory.pointer_size as isize);
514+
let len_ptr = dest.offset(self.memory.pointer_size() as isize);
519515
self.memory.write_usize(len_ptr, len)?;
520516
}
521517
LvalueExtra::DowncastVariant(..) =>
@@ -541,7 +537,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
541537

542538
match (&src_pointee_ty.sty, &dest_pointee_ty.sty) {
543539
(&ty::TyArray(_, length), &ty::TySlice(_)) => {
544-
let len_ptr = dest.offset(self.memory.pointer_size as isize);
540+
let len_ptr = dest.offset(self.memory.pointer_size() as isize);
545541
self.memory.write_usize(len_ptr, length as u64)?;
546542
}
547543

@@ -655,7 +651,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
655651
Ok(Size::from_bytes(0))
656652
}
657653
FatPointer { .. } => {
658-
let bytes = layout::FAT_PTR_ADDR * self.memory.pointer_size;
654+
let bytes = layout::FAT_PTR_ADDR * self.memory.pointer_size();
659655
Ok(Size::from_bytes(bytes as u64))
660656
}
661657
_ => Err(EvalError::Unimplemented(format!("can't handle type: {:?}, with layout: {:?}", ty, layout))),
@@ -766,7 +762,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
766762
let ptr = self.memory.read_ptr(base.ptr)?;
767763
let extra = match pointee_ty.sty {
768764
ty::TySlice(_) | ty::TyStr => {
769-
let len_ptr = base.ptr.offset(self.memory.pointer_size as isize);
765+
let len_ptr = base.ptr.offset(self.memory.pointer_size() as isize);
770766
let len = self.memory.read_usize(len_ptr)?;
771767
LvalueExtra::Length(len)
772768
}
@@ -815,7 +811,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
815811

816812
pub fn read_primval(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
817813
use syntax::ast::{IntTy, UintTy};
818-
let val = match (self.memory.pointer_size, &ty.sty) {
814+
let val = match (self.memory.pointer_size(), &ty.sty) {
819815
(_, &ty::TyBool) => PrimVal::Bool(self.memory.read_bool(ptr)?),
820816
(_, &ty::TyChar) => {
821817
let c = self.memory.read_uint(ptr, 4)? as u32;
@@ -923,7 +919,7 @@ pub fn eval_main<'a, 'tcx: 'a>(
923919

924920
if mir.arg_decls.len() == 2 {
925921
// start function
926-
let ptr_size = ecx.memory().pointer_size;
922+
let ptr_size = ecx.memory().pointer_size();
927923
let nargs = ecx.memory_mut().allocate(ptr_size);
928924
ecx.memory_mut().write_usize(nargs, 0).unwrap();
929925
let args = ecx.memory_mut().allocate(ptr_size);

src/interpreter/terminator.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
277277
.collect();
278278
let args_ptrs = args_res?;
279279

280-
let pointer_size = self.memory.pointer_size;
280+
let pointer_size = self.memory.pointer_size();
281281

282282
match name {
283283
"add_with_overflow" => self.intrinsic_with_overflow(mir::BinOp::Add, &args[0], &args[1], dest, dest_layout)?,
@@ -368,7 +368,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
368368
ty::TySlice(_) | ty::TyStr => {
369369
let elem_ty = ty.sequence_element_type(self.tcx);
370370
let elem_size = self.type_size(elem_ty) as u64;
371-
let ptr_size = self.memory.pointer_size as isize;
371+
let ptr_size = self.memory.pointer_size() as isize;
372372
let n = self.memory.read_usize(args_ptrs[0].offset(ptr_size))?;
373373
self.memory.write_uint(dest, n * elem_size, pointer_size)?;
374374
}
@@ -557,7 +557,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
557557
self.memory.deallocate(contents_ptr)?;
558558
}
559559
Err(EvalError::ReadBytesAsPointer) => {
560-
let size = self.memory.pointer_size;
560+
let size = self.memory.pointer_size();
561561
let possible_drop_fill = self.memory.read_bytes(ptr, size)?;
562562
if possible_drop_fill.iter().all(|&b| b == mem::POST_DROP_U8) {
563563
return Ok(());

src/memory.rs

+35-36
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use std::{fmt, iter, mem, ptr};
66
use rustc::hir::def_id::DefId;
77
use rustc::ty::BareFnTy;
88
use rustc::ty::subst::Substs;
9+
use rustc::ty::layout::TargetDataLayout;
910

1011
use error::{EvalError, EvalResult};
1112
use primval::PrimVal;
@@ -53,7 +54,7 @@ pub struct FunctionDefinition<'tcx> {
5354
// Top-level interpreter memory
5455
////////////////////////////////////////////////////////////////////////////////
5556

56-
pub struct Memory<'tcx> {
57+
pub struct Memory<'a, 'tcx> {
5758
/// Actual memory allocations (arbitrary bytes, may contain pointers into other allocations)
5859
alloc_map: HashMap<AllocId, Allocation>,
5960
/// Function "allocations". They exist solely so pointers have something to point to, and
@@ -62,18 +63,17 @@ pub struct Memory<'tcx> {
6263
/// Inverse map of `functions` so we don't allocate a new pointer every time we need one
6364
function_alloc_cache: HashMap<FunctionDefinition<'tcx>, AllocId>,
6465
next_id: AllocId,
65-
pub pointer_size: usize,
66+
pub layout: &'a TargetDataLayout,
6667
}
6768

68-
impl<'tcx> Memory<'tcx> {
69-
// FIXME: pass tcx.data_layout (This would also allow it to use primitive type alignments to diagnose unaligned memory accesses.)
70-
pub fn new(pointer_size: usize) -> Self {
69+
impl<'a, 'tcx> Memory<'a, 'tcx> {
70+
pub fn new(layout: &'a TargetDataLayout) -> Self {
7171
Memory {
7272
alloc_map: HashMap::new(),
7373
functions: HashMap::new(),
7474
function_alloc_cache: HashMap::new(),
7575
next_id: AllocId(0),
76-
pointer_size: pointer_size,
76+
layout: layout,
7777
}
7878
}
7979

@@ -156,10 +156,13 @@ impl<'tcx> Memory<'tcx> {
156156
Ok(())
157157
}
158158

159-
////////////////////////////////////////////////////////////////////////////////
160-
// Allocation accessors
161-
////////////////////////////////////////////////////////////////////////////////
159+
pub fn pointer_size(&self) -> usize {
160+
self.layout.pointer_size.bytes() as usize
161+
}
162+
}
162163

164+
/// Allocation accessors
165+
impl<'a, 'tcx> Memory<'a, 'tcx> {
163166
pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation> {
164167
match self.alloc_map.get(&id) {
165168
Some(alloc) => Ok(alloc),
@@ -235,21 +238,20 @@ impl<'tcx> Memory<'tcx> {
235238
if !relocations.is_empty() {
236239
print!("{:1$}", "", prefix.len()); // Print spaces.
237240
let mut pos = 0;
238-
let relocation_width = (self.pointer_size - 1) * 3;
241+
let relocation_width = (self.pointer_size() - 1) * 3;
239242
for (i, target_id) in relocations {
240243
print!("{:1$}", "", (i - pos) * 3);
241244
print!("└{0:─^1$}┘ ", format!("({})", target_id), relocation_width);
242-
pos = i + self.pointer_size;
245+
pos = i + self.pointer_size();
243246
}
244247
println!("");
245248
}
246249
}
247250
}
251+
}
248252

249-
////////////////////////////////////////////////////////////////////////////////
250-
// Byte accessors
251-
////////////////////////////////////////////////////////////////////////////////
252-
253+
/// Byte accessors
254+
impl<'a, 'tcx> Memory<'a, 'tcx> {
253255
fn get_bytes_unchecked(&self, ptr: Pointer, size: usize) -> EvalResult<'tcx, &[u8]> {
254256
let alloc = self.get(ptr.alloc_id)?;
255257
if ptr.offset + size > alloc.bytes.len() {
@@ -287,11 +289,10 @@ impl<'tcx> Memory<'tcx> {
287289
self.mark_definedness(ptr, size, true)?;
288290
self.get_bytes_unchecked_mut(ptr, size)
289291
}
292+
}
290293

291-
////////////////////////////////////////////////////////////////////////////////
292-
// Reading and writing
293-
////////////////////////////////////////////////////////////////////////////////
294-
294+
/// Reading and writing
295+
impl<'a, 'tcx> Memory<'a, 'tcx> {
295296
pub fn copy(&mut self, src: Pointer, dest: Pointer, size: usize) -> EvalResult<'tcx, ()> {
296297
self.check_relocation_edges(src, size)?;
297298

@@ -336,7 +337,7 @@ impl<'tcx> Memory<'tcx> {
336337
}
337338

338339
pub fn read_ptr(&self, ptr: Pointer) -> EvalResult<'tcx, Pointer> {
339-
let size = self.pointer_size;
340+
let size = self.pointer_size();
340341
self.check_defined(ptr, size)?;
341342
let offset = self.get_bytes_unchecked(ptr, size)?
342343
.read_uint::<NativeEndian>(size).unwrap() as usize;
@@ -349,7 +350,7 @@ impl<'tcx> Memory<'tcx> {
349350

350351
pub fn write_ptr(&mut self, dest: Pointer, ptr: Pointer) -> EvalResult<'tcx, ()> {
351352
{
352-
let size = self.pointer_size;
353+
let size = self.pointer_size();
353354
let mut bytes = self.get_bytes_mut(dest, size)?;
354355
bytes.write_uint::<NativeEndian>(ptr.offset as u64, size).unwrap();
355356
}
@@ -358,7 +359,7 @@ impl<'tcx> Memory<'tcx> {
358359
}
359360

360361
pub fn write_primval(&mut self, ptr: Pointer, val: PrimVal) -> EvalResult<'tcx, ()> {
361-
let pointer_size = self.pointer_size;
362+
let pointer_size = self.pointer_size();
362363
match val {
363364
PrimVal::Bool(b) => self.write_bool(ptr, b),
364365
PrimVal::I8(n) => self.write_int(ptr, n as i64, 1),
@@ -406,31 +407,30 @@ impl<'tcx> Memory<'tcx> {
406407
}
407408

408409
pub fn read_isize(&self, ptr: Pointer) -> EvalResult<'tcx, i64> {
409-
self.read_int(ptr, self.pointer_size)
410+
self.read_int(ptr, self.pointer_size())
410411
}
411412

412413
pub fn write_isize(&mut self, ptr: Pointer, n: i64) -> EvalResult<'tcx, ()> {
413-
let size = self.pointer_size;
414+
let size = self.pointer_size();
414415
self.write_int(ptr, n, size)
415416
}
416417

417418
pub fn read_usize(&self, ptr: Pointer) -> EvalResult<'tcx, u64> {
418-
self.read_uint(ptr, self.pointer_size)
419+
self.read_uint(ptr, self.pointer_size())
419420
}
420421

421422
pub fn write_usize(&mut self, ptr: Pointer, n: u64) -> EvalResult<'tcx, ()> {
422-
let size = self.pointer_size;
423+
let size = self.pointer_size();
423424
self.write_uint(ptr, n, size)
424425
}
426+
}
425427

426-
////////////////////////////////////////////////////////////////////////////////
427-
// Relocations
428-
////////////////////////////////////////////////////////////////////////////////
429-
428+
/// Relocations
429+
impl<'a, 'tcx> Memory<'a, 'tcx> {
430430
fn relocations(&self, ptr: Pointer, size: usize)
431431
-> EvalResult<'tcx, btree_map::Range<usize, AllocId>>
432432
{
433-
let start = ptr.offset.saturating_sub(self.pointer_size - 1);
433+
let start = ptr.offset.saturating_sub(self.pointer_size() - 1);
434434
let end = ptr.offset + size;
435435
Ok(self.get(ptr.alloc_id)?.relocations.range(Included(&start), Excluded(&end)))
436436
}
@@ -444,7 +444,7 @@ impl<'tcx> Memory<'tcx> {
444444
let start = ptr.offset;
445445
let end = start + size;
446446
let first = *keys.first().unwrap();
447-
let last = *keys.last().unwrap() + self.pointer_size;
447+
let last = *keys.last().unwrap() + self.pointer_size();
448448

449449
let alloc = self.get_mut(ptr.alloc_id)?;
450450

@@ -478,11 +478,10 @@ impl<'tcx> Memory<'tcx> {
478478
self.get_mut(dest.alloc_id)?.relocations.extend(relocations);
479479
Ok(())
480480
}
481+
}
481482

482-
////////////////////////////////////////////////////////////////////////////////
483-
// Undefined bytes
484-
////////////////////////////////////////////////////////////////////////////////
485-
483+
/// Undefined bytes
484+
impl<'a, 'tcx> Memory<'a, 'tcx> {
486485
// FIXME(solson): This is a very naive, slow version.
487486
fn copy_undef_mask(&mut self, src: Pointer, dest: Pointer, size: usize) -> EvalResult<'tcx, ()> {
488487
// The bits have to be saved locally before writing to dest in case src and dest overlap.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#[repr(C)]
2+
pub enum Foo {
3+
A, B, C, D
4+
}
5+
6+
fn main() {
7+
let f = unsafe { std::mem::transmute::<i32, Foo>(42) };
8+
match f {
9+
Foo::A => {}, //~ ERROR invalid enum discriminant value read
10+
Foo::B => {},
11+
Foo::C => {},
12+
Foo::D => {},
13+
}
14+
}

tests/compile-fail/match_char.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fn main() {
2+
assert!(std::char::from_u32(-1_i32 as u32).is_none());
3+
match unsafe { std::mem::transmute::<i32, char>(-1) } {
4+
'a' => {}, //~ERROR tried to interpret an invalid 32-bit value as a char: 4294967295
5+
'b' => {},
6+
_ => {},
7+
}
8+
}

tests/compiletest.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ fn compile_test() {
7777
match cmd.output() {
7878
Ok(ref output) if output.status.success() => writeln!(stderr.lock(), "ok").unwrap(),
7979
Ok(output) => {
80-
writeln!(stderr.lock(), "FAILED with exit code {}", output.status.code().unwrap_or(0)).unwrap();
80+
writeln!(stderr.lock(), "FAILED with exit code {:?}", output.status.code()).unwrap();
8181
writeln!(stderr.lock(), "stdout: \n {}", std::str::from_utf8(&output.stdout).unwrap()).unwrap();
8282
writeln!(stderr.lock(), "stderr: \n {}", std::str::from_utf8(&output.stderr).unwrap()).unwrap();
8383
panic!("some tests failed");

0 commit comments

Comments
 (0)