Skip to content

Commit ea6f607

Browse files
committed
Use PrimVal instead of Pointer where applicable
1 parent a6734cd commit ea6f607

File tree

6 files changed

+125
-31
lines changed

6 files changed

+125
-31
lines changed

src/eval_context.rs

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
637637
let value = self.eval_operand(operand)?;
638638

639639
// FIXME(solson)
640-
let dest = self.force_allocation(dest)?.to_ptr()?;
640+
let dest = PrimVal::Ptr(self.force_allocation(dest)?.to_ptr()?);
641641

642642
for i in 0..length {
643643
let elem_dest = dest.offset(i * elem_size, self.memory.layout)?;
@@ -893,6 +893,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
893893
}
894894
// FIXME: assuming here that type size is < i64::max_value()
895895
let pointee_size = self.type_size(pointee_ty)?.expect("cannot offset a pointer to an unsized type") as i64;
896+
if pointee_size == 0 {
897+
// rustc relies on offsetting pointers to zsts to be a nop
898+
return Ok(ptr);
899+
}
896900
return if let Some(offset) = offset.checked_mul(pointee_size) {
897901
let ptr = ptr.signed_offset(offset, self.memory.layout)?;
898902
self.memory.check_bounds(ptr.to_ptr()?, false)?;
@@ -943,7 +947,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
943947
self.monomorphize(operand.ty(self.mir(), self.tcx), self.substs())
944948
}
945949

946-
fn copy(&mut self, src: Pointer, dest: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx> {
950+
fn copy(&mut self, src: PrimVal, dest: PrimVal, ty: Ty<'tcx>) -> EvalResult<'tcx> {
947951
let size = self.type_size(ty)?.expect("cannot copy from an unsized type");
948952
let align = self.type_align(ty)?;
949953
self.memory.copy(src, dest, size, align)?;
@@ -969,7 +973,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
969973
let substs = self.stack[frame].instance.substs;
970974
let ptr = self.alloc_ptr_with_substs(ty, substs)?;
971975
self.stack[frame].locals[local.index() - 1] = Some(Value::ByRef(ptr)); // it stays live
972-
self.write_value_to_ptr(val, ptr, ty)?;
976+
self.write_value_to_ptr(val, PrimVal::Ptr(ptr), ty)?;
973977
let lval = Lvalue::from_ptr(ptr);
974978
if let Some((field, field_ty)) = field {
975979
self.lvalue_field(lval, field, ty, field_ty)?
@@ -987,7 +991,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
987991
_ => {
988992
let ptr = self.alloc_ptr_with_substs(global_val.ty, cid.instance.substs)?;
989993
self.memory.mark_static(ptr.alloc_id);
990-
self.write_value_to_ptr(global_val.value, ptr, global_val.ty)?;
994+
self.write_value_to_ptr(global_val.value, PrimVal::Ptr(ptr), global_val.ty)?;
991995
// see comment on `initialized` field
992996
if global_val.initialized {
993997
self.memory.mark_static_initalized(ptr.alloc_id, global_val.mutable)?;
@@ -1059,7 +1063,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
10591063

10601064
Lvalue::Ptr { ptr, extra } => {
10611065
assert_eq!(extra, LvalueExtra::None);
1062-
self.write_value_to_ptr(src_val, ptr.to_ptr()?, dest_ty)
1066+
self.write_value_to_ptr(src_val, ptr, dest_ty)
10631067
}
10641068

10651069
Lvalue::Local { frame, local, field } => {
@@ -1090,7 +1094,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
10901094
//
10911095
// Thus, it would be an error to replace the `ByRef` with a `ByVal`, unless we
10921096
// knew for certain that there were no outstanding pointers to this allocation.
1093-
self.write_value_to_ptr(src_val, dest_ptr, dest_ty)?;
1097+
self.write_value_to_ptr(src_val, PrimVal::Ptr(dest_ptr), dest_ty)?;
10941098

10951099
} else if let Value::ByRef(src_ptr) = src_val {
10961100
// If the value is not `ByRef`, then we know there are no pointers to it
@@ -1108,7 +1112,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
11081112
write_dest(self, src_val)?;
11091113
} else {
11101114
let dest_ptr = self.alloc_ptr(dest_ty)?;
1111-
self.copy(src_ptr, dest_ptr, dest_ty)?;
1115+
self.copy(PrimVal::Ptr(src_ptr), PrimVal::Ptr(dest_ptr), dest_ty)?;
11121116
write_dest(self, Value::ByRef(dest_ptr))?;
11131117
}
11141118

@@ -1123,16 +1127,16 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
11231127
pub(super) fn write_value_to_ptr(
11241128
&mut self,
11251129
value: Value,
1126-
dest: Pointer,
1130+
dest: PrimVal,
11271131
dest_ty: Ty<'tcx>,
11281132
) -> EvalResult<'tcx> {
11291133
match value {
1130-
Value::ByRef(ptr) => self.copy(ptr, dest, dest_ty),
1134+
Value::ByRef(ptr) => self.copy(PrimVal::Ptr(ptr), dest, dest_ty),
11311135
Value::ByVal(primval) => {
11321136
let size = self.type_size(dest_ty)?.expect("dest type must be sized");
11331137
self.memory.write_primval(dest, primval, size)
11341138
}
1135-
Value::ByValPair(a, b) => self.write_pair_to_ptr(a, b, dest, dest_ty),
1139+
Value::ByValPair(a, b) => self.write_pair_to_ptr(a, b, dest.to_ptr()?, dest_ty),
11361140
}
11371141
}
11381142

@@ -1153,8 +1157,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
11531157
let field_1_ty = self.get_field_ty(ty, 1)?;
11541158
let field_0_size = self.type_size(field_0_ty)?.expect("pair element type must be sized");
11551159
let field_1_size = self.type_size(field_1_ty)?.expect("pair element type must be sized");
1156-
self.memory.write_primval(ptr.offset(field_0, self.memory.layout)?, a, field_0_size)?;
1157-
self.memory.write_primval(ptr.offset(field_1, self.memory.layout)?, b, field_1_size)?;
1160+
self.memory.write_primval(PrimVal::Ptr(ptr.offset(field_0, self.memory.layout)?), a, field_0_size)?;
1161+
self.memory.write_primval(PrimVal::Ptr(ptr.offset(field_1, self.memory.layout)?), b, field_1_size)?;
11581162
Ok(())
11591163
}
11601164

@@ -1457,7 +1461,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
14571461
let src_f_ptr = src_ptr.offset(src_field_offset, self.memory.layout)?;
14581462
let dst_f_ptr = dest.offset(dst_field_offset, self.memory.layout)?;
14591463
if src_fty == dst_fty {
1460-
self.copy(src_f_ptr, dst_f_ptr, src_fty)?;
1464+
self.copy(PrimVal::Ptr(src_f_ptr), PrimVal::Ptr(dst_f_ptr), src_fty)?;
14611465
} else {
14621466
self.unsize_into(Value::ByRef(src_f_ptr), src_fty, Lvalue::from_ptr(dst_f_ptr), dst_fty)?;
14631467
}

src/lvalue.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,19 @@ pub struct Global<'tcx> {
6666
impl<'tcx> Lvalue<'tcx> {
6767
/// Produces an Lvalue that will error if attempted to be read from
6868
pub fn undef() -> Self {
69-
Lvalue::Ptr {
70-
ptr: PrimVal::Undef,
71-
extra: LvalueExtra::None,
72-
}
69+
Self::from_primval_ptr(PrimVal::Undef)
70+
}
71+
72+
fn from_primval_ptr(ptr: PrimVal) -> Self {
73+
Lvalue::Ptr { ptr, extra: LvalueExtra::None }
7374
}
7475

7576
pub fn zst() -> Self {
7677
Self::from_ptr(Pointer::zst_ptr())
7778
}
7879

7980
pub fn from_ptr(ptr: Pointer) -> Self {
80-
Lvalue::Ptr { ptr: PrimVal::Ptr(ptr), extra: LvalueExtra::None }
81+
Self::from_primval_ptr(PrimVal::Ptr(ptr))
8182
}
8283

8384
pub(super) fn to_ptr_and_extra(self) -> (PrimVal, LvalueExtra) {

src/memory.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
618618
return Ok(&mut []);
619619
}
620620
self.clear_relocations(ptr, size)?;
621-
self.mark_definedness(ptr, size, true)?;
621+
self.mark_definedness(PrimVal::Ptr(ptr), size, true)?;
622622
self.get_bytes_unchecked_mut(ptr, size, align)
623623
}
624624
}
@@ -671,10 +671,12 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
671671
Ok(())
672672
}
673673

674-
pub fn copy(&mut self, src: Pointer, dest: Pointer, size: u64, align: u64) -> EvalResult<'tcx> {
674+
pub fn copy(&mut self, src: PrimVal, dest: PrimVal, size: u64, align: u64) -> EvalResult<'tcx> {
675675
if size == 0 {
676676
return Ok(());
677677
}
678+
let src = src.to_ptr()?;
679+
let dest = dest.to_ptr()?;
678680
self.check_relocation_edges(src, size)?;
679681

680682
let src_bytes = self.get_bytes_unchecked(src, size, align)?.as_ptr();
@@ -755,14 +757,14 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
755757

756758
pub fn write_primval(
757759
&mut self,
758-
dest: Pointer,
760+
dest: PrimVal,
759761
val: PrimVal,
760762
size: u64,
761763
) -> EvalResult<'tcx> {
762764
match val {
763765
PrimVal::Ptr(ptr) => {
764766
assert_eq!(size, self.pointer_size());
765-
self.write_ptr(dest, ptr)
767+
self.write_ptr(dest.to_ptr()?, ptr)
766768
}
767769

768770
PrimVal::Bytes(bytes) => {
@@ -776,7 +778,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
776778
16 => !0,
777779
_ => bug!("unexpected PrimVal::Bytes size"),
778780
};
779-
self.write_uint(dest, bytes & mask, size)
781+
self.write_uint(dest.to_ptr()?, bytes & mask, size)
780782
}
781783

782784
PrimVal::Undef => self.mark_definedness(dest, size, false),
@@ -962,13 +964,14 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
962964

963965
pub fn mark_definedness(
964966
&mut self,
965-
ptr: Pointer,
967+
ptr: PrimVal,
966968
size: u64,
967969
new_state: bool
968970
) -> EvalResult<'tcx> {
969971
if size == 0 {
970972
return Ok(())
971973
}
974+
let ptr = ptr.to_ptr()?;
972975
let mut alloc = self.get_mut(ptr.alloc_id)?;
973976
alloc.undef_mask.set_range(ptr.offset, ptr.offset + size, new_state);
974977
Ok(())

src/terminator/intrinsic.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
6969
"atomic_store_rel" |
7070
"volatile_store" => {
7171
let ty = substs.type_at(0);
72-
let dest = arg_vals[0].read_ptr(&self.memory)?.to_ptr()?;
72+
let dest = arg_vals[0].read_ptr(&self.memory)?;
7373
self.write_value_to_ptr(arg_vals[1], dest, ty)?;
7474
}
7575

@@ -145,8 +145,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
145145
let elem_size = self.type_size(elem_ty)?.expect("cannot copy unsized value");
146146
if elem_size != 0 {
147147
let elem_align = self.type_align(elem_ty)?;
148-
let src = arg_vals[0].read_ptr(&self.memory)?.to_ptr()?;
149-
let dest = arg_vals[1].read_ptr(&self.memory)?.to_ptr()?;
148+
let src = arg_vals[0].read_ptr(&self.memory)?;
149+
let dest = arg_vals[1].read_ptr(&self.memory)?;
150150
let count = self.value_to_primval(arg_vals[2], usize)?.to_u64()?;
151151
self.memory.copy(src, dest, count * elem_size, elem_align)?;
152152
}
@@ -284,7 +284,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
284284

285285
"move_val_init" => {
286286
let ty = substs.type_at(0);
287-
let ptr = arg_vals[0].read_ptr(&self.memory)?.to_ptr()?;
287+
let ptr = arg_vals[0].read_ptr(&self.memory)?;
288288
self.write_value_to_ptr(arg_vals[1], ptr, ty)?;
289289
}
290290

@@ -392,7 +392,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
392392
if dest_align < src_align {
393393
let ptr = self.force_allocation(dest)?.to_ptr()?;
394394
self.memory.mark_packed(ptr, size);
395-
self.write_value_to_ptr(arg_vals[0], ptr, dest_ty)?;
395+
self.write_value_to_ptr(arg_vals[0], PrimVal::Ptr(ptr), dest_ty)?;
396396
} else {
397397
self.write_value(arg_vals[0], dest, dest_ty)?;
398398
}
@@ -403,7 +403,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
403403
let uninit = |this: &mut Self, val: Value| {
404404
match val {
405405
Value::ByRef(ptr) => {
406-
this.memory.mark_definedness(ptr, size, false)?;
406+
this.memory.mark_definedness(PrimVal::Ptr(ptr), size, false)?;
407407
Ok(Value::ByRef(ptr))
408408
},
409409
_ => Ok(Value::ByVal(PrimVal::Undef)),
@@ -412,7 +412,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
412412
match dest {
413413
Lvalue::Local { frame, local, field } => self.modify_local(frame, local, field.map(|(i, _)| i), uninit)?,
414414
Lvalue::Ptr { ptr, extra: LvalueExtra::None } =>
415-
self.memory.mark_definedness(ptr.to_ptr()?, size, false)?,
415+
self.memory.mark_definedness(ptr, size, false)?,
416416
Lvalue::Ptr { .. } => bug!("uninit intrinsic tried to write to fat ptr target"),
417417
Lvalue::Global(cid) => self.modify_global(cid, uninit)?,
418418
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -C debug-assertions
12+
13+
use std::slice;
14+
15+
fn foo<T>(v: &[T]) -> Option<&[T]> {
16+
let mut it = v.iter();
17+
for _ in 0..5 {
18+
let _ = it.next();
19+
}
20+
Some(it.as_slice())
21+
}
22+
23+
fn foo_mut<T>(v: &mut [T]) -> Option<&mut [T]> {
24+
let mut it = v.iter_mut();
25+
for _ in 0..5 {
26+
let _ = it.next();
27+
}
28+
Some(it.into_slice())
29+
}
30+
31+
pub fn main() {
32+
// In a slice of zero-size elements the pointer is meaningless.
33+
// Ensure iteration still works even if the pointer is at the end of the address space.
34+
let slice: &[()] = unsafe { slice::from_raw_parts(-5isize as *const (), 10) };
35+
assert_eq!(slice.len(), 10);
36+
assert_eq!(slice.iter().count(), 10);
37+
38+
// .nth() on the iterator should also behave correctly
39+
let mut it = slice.iter();
40+
assert!(it.nth(5).is_some());
41+
assert_eq!(it.count(), 4);
42+
43+
// Converting Iter to a slice should never have a null pointer
44+
assert!(foo(slice).is_some());
45+
46+
// Test mutable iterators as well
47+
let slice: &mut [()] = unsafe { slice::from_raw_parts_mut(-5isize as *mut (), 10) };
48+
assert_eq!(slice.len(), 10);
49+
assert_eq!(slice.iter_mut().count(), 10);
50+
51+
{
52+
let mut it = slice.iter_mut();
53+
assert!(it.nth(5).is_some());
54+
assert_eq!(it.count(), 4);
55+
}
56+
57+
assert!(foo_mut(slice).is_some())
58+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use std::collections::BinaryHeap;
12+
use std::iter::Iterator;
13+
14+
fn main() {
15+
const N: usize = 8;
16+
17+
for len in 0..N {
18+
let mut tester = BinaryHeap::with_capacity(len);
19+
assert_eq!(tester.len(), 0);
20+
assert!(tester.capacity() >= len);
21+
for _ in 0..len {
22+
tester.push(());
23+
}
24+
assert_eq!(tester.len(), len);
25+
assert_eq!(tester.iter().count(), len);
26+
tester.clear();
27+
}
28+
}

0 commit comments

Comments
 (0)