Skip to content

Commit 7cf04de

Browse files
committed
Get rid of the integer allocation
1 parent 4566058 commit 7cf04de

16 files changed

+240
-241
lines changed

src/cast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
7171
TyChar if v as u8 as u128 == v => Ok(PrimVal::Bytes(v)),
7272
TyChar => Err(EvalError::InvalidChar(v)),
7373

74-
TyRawPtr(_) => Ok(PrimVal::Ptr(Pointer::from_int(v as u64))),
74+
TyRawPtr(_) => Ok(PrimVal::Bytes(v % (1 << self.memory.pointer_size()))),
7575

7676
_ => Err(EvalError::Unimplemented(format!("int to {:?} cast", ty))),
7777
}

src/error.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub enum EvalError<'tcx> {
2222
allocation_size: u64,
2323
},
2424
ReadPointerAsBytes,
25+
ReadBytesAsPointer,
2526
InvalidPointerMath,
2627
ReadUndefBytes,
2728
DeadLocal,
@@ -81,6 +82,8 @@ impl<'tcx> Error for EvalError<'tcx> {
8182
"pointer offset outside bounds of allocation",
8283
EvalError::ReadPointerAsBytes =>
8384
"a raw memory access tried to access part of a pointer value as raw bytes",
85+
EvalError::ReadBytesAsPointer =>
86+
"a memory access tried to interpret some bytes as a pointer",
8487
EvalError::InvalidPointerMath =>
8588
"attempted to do math or a comparison on pointers into different allocations",
8689
EvalError::ReadUndefBytes =>

src/eval_context.rs

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ pub struct Frame<'tcx> {
6666
pub return_to_block: StackPopCleanup,
6767

6868
/// The location where the result of the current stack frame should be written to.
69-
pub return_lvalue: Lvalue<'tcx>,
69+
/// None if the function is a diverging function
70+
pub return_lvalue: Option<Lvalue<'tcx>>,
7071

7172
/// The list of locals for this stack frame, stored in order as
7273
/// `[arguments..., variables..., temporaries...]`. The locals are stored as `Option<Value>`s.
@@ -266,7 +267,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
266267
instance: ty::Instance<'tcx>,
267268
span: codemap::Span,
268269
mir: &'tcx mir::Mir<'tcx>,
269-
return_lvalue: Lvalue<'tcx>,
270+
return_lvalue: Option<Lvalue<'tcx>>,
270271
return_to_block: StackPopCleanup,
271272
) -> EvalResult<'tcx> {
272273
::log_settings::settings().indentation += 1;
@@ -323,7 +324,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
323324
::log_settings::settings().indentation -= 1;
324325
let frame = self.stack.pop().expect("tried to pop a stack frame, but there were none");
325326
match frame.return_to_block {
326-
StackPopCleanup::MarkStatic(mutable) => if let Lvalue::Global(id) = frame.return_lvalue {
327+
StackPopCleanup::MarkStatic(mutable) => if let Lvalue::Global(id) = frame.return_lvalue.expect("diverging static") {
327328
let global_value = self.globals.get_mut(&id)
328329
.expect("global should have been cached (static)");
329330
match global_value.value {
@@ -389,13 +390,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
389390
where J::IntoIter: ExactSizeIterator,
390391
{
391392
// FIXME(solson)
392-
let dest_ptr = self.force_allocation(dest)?.to_ptr();
393+
let dest_ptr = self.force_allocation(dest)?.to_ptr()?;
393394

394395
let discr_dest = dest_ptr.offset(discr_offset, self.memory.layout)?;
395396
self.memory.write_uint(discr_dest, discr_val, discr_size)?;
396397

397398
let dest = Lvalue::Ptr {
398-
ptr: dest_ptr,
399+
ptr: PrimVal::Ptr(dest_ptr),
399400
extra: LvalueExtra::DowncastVariant(variant_idx),
400401
};
401402

@@ -481,7 +482,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
481482
match *dest_layout {
482483
Univariant { ref variant, .. } => {
483484
if variant.packed {
484-
let ptr = self.force_allocation(dest)?.to_ptr_and_extra().0;
485+
let ptr = self.force_allocation(dest)?.to_ptr_and_extra().0.to_ptr()?;
485486
self.memory.mark_packed(ptr, variant.stride().bytes());
486487
}
487488
self.assign_fields(dest, dest_ty, operands)?;
@@ -499,7 +500,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
499500
.to_u128_unchecked();
500501
let discr_size = discr.size().bytes();
501502
if variants[variant].packed {
502-
let ptr = self.force_allocation(dest)?.to_ptr_and_extra().0;
503+
let ptr = self.force_allocation(dest)?.to_ptr_and_extra().0.to_ptr()?;
503504
self.memory.mark_packed(ptr, variants[variant].stride().bytes());
504505
}
505506

@@ -541,7 +542,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
541542
StructWrappedNullablePointer { nndiscr, ref nonnull, ref discrfield, .. } => {
542543
if let mir::AggregateKind::Adt(_, variant, _, _) = **kind {
543544
if nonnull.packed {
544-
let ptr = self.force_allocation(dest)?.to_ptr_and_extra().0;
545+
let ptr = self.force_allocation(dest)?.to_ptr_and_extra().0.to_ptr()?;
545546
self.memory.mark_packed(ptr, nonnull.stride().bytes());
546547
}
547548
if nndiscr == variant as u64 {
@@ -554,7 +555,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
554555
let (offset, ty) = self.nonnull_offset_and_ty(dest_ty, nndiscr, discrfield)?;
555556

556557
// FIXME(solson)
557-
let dest = self.force_allocation(dest)?.to_ptr();
558+
let dest = self.force_allocation(dest)?.to_ptr()?;
558559

559560
let dest = dest.offset(offset.bytes(), self.memory.layout)?;
560561
let dest_size = self.type_size(ty)?
@@ -613,7 +614,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
613614
let value = self.eval_operand(operand)?;
614615

615616
// FIXME(solson)
616-
let dest = self.force_allocation(dest)?.to_ptr();
617+
let dest = self.force_allocation(dest)?.to_ptr()?;
617618

618619
for i in 0..length {
619620
let elem_dest = dest.offset(i * elem_size, self.memory.layout)?;
@@ -630,8 +631,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
630631

631632
Ref(_, _, ref lvalue) => {
632633
let src = self.eval_lvalue(lvalue)?;
633-
let (raw_ptr, extra) = self.force_allocation(src)?.to_ptr_and_extra();
634-
let ptr = PrimVal::Ptr(raw_ptr);
634+
let (ptr, extra) = self.force_allocation(src)?.to_ptr_and_extra();
635635

636636
let val = match extra {
637637
LvalueExtra::None => Value::ByVal(ptr),
@@ -726,7 +726,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
726726
Discriminant(ref lvalue) => {
727727
let lval = self.eval_lvalue(lvalue)?;
728728
let ty = self.lvalue_ty(lvalue);
729-
let ptr = self.force_allocation(lval)?.to_ptr();
729+
let ptr = self.force_allocation(lval)?.to_ptr()?;
730730
let discr_val = self.read_discriminant_value(ptr, ty)?;
731731
if let ty::TyAdt(adt_def, _) = ty.sty {
732732
if adt_def.discriminants(self.tcx).all(|v| discr_val != v.to_u128_unchecked()) {
@@ -856,14 +856,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
856856
}
857857
}
858858

859-
pub(super) fn wrapping_pointer_offset(&self, ptr: Pointer, pointee_ty: Ty<'tcx>, offset: i64) -> EvalResult<'tcx, Pointer> {
859+
pub(super) fn wrapping_pointer_offset(&self, ptr: PrimVal, pointee_ty: Ty<'tcx>, offset: i64) -> EvalResult<'tcx, PrimVal> {
860860
// FIXME: assuming here that type size is < i64::max_value()
861861
let pointee_size = self.type_size(pointee_ty)?.expect("cannot offset a pointer to an unsized type") as i64;
862862
let offset = offset.overflowing_mul(pointee_size).0;
863-
Ok(ptr.wrapping_signed_offset(offset, self.memory.layout))
863+
ptr.wrapping_signed_offset(offset, self.memory.layout)
864864
}
865865

866-
pub(super) fn pointer_offset(&self, ptr: Pointer, pointee_ty: Ty<'tcx>, offset: i64) -> EvalResult<'tcx, Pointer> {
866+
pub(super) fn pointer_offset(&self, ptr: PrimVal, pointee_ty: Ty<'tcx>, offset: i64) -> EvalResult<'tcx, PrimVal> {
867867
if offset == 0 {
868868
// rustc relies on Offset-by-0 to be well-defined even for "bad" pointers like Unique::empty().
869869
return Ok(ptr);
@@ -872,7 +872,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
872872
let pointee_size = self.type_size(pointee_ty)?.expect("cannot offset a pointer to an unsized type") as i64;
873873
return if let Some(offset) = offset.checked_mul(pointee_size) {
874874
let ptr = ptr.signed_offset(offset, self.memory.layout)?;
875-
self.memory.check_bounds(ptr, false)?;
875+
self.memory.check_bounds(ptr.to_ptr()?, false)?;
876876
Ok(ptr)
877877
} else {
878878
Err(EvalError::OverflowingMath)
@@ -1036,7 +1036,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
10361036

10371037
Lvalue::Ptr { ptr, extra } => {
10381038
assert_eq!(extra, LvalueExtra::None);
1039-
self.write_value_to_ptr(src_val, ptr, dest_ty)
1039+
self.write_value_to_ptr(src_val, ptr.to_ptr()?, dest_ty)
10401040
}
10411041

10421042
Lvalue::Local { frame, local, field } => {
@@ -1242,20 +1242,20 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
12421242
}
12431243
}
12441244

1245-
fn read_ptr(&mut self, ptr: Pointer, pointee_ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
1245+
pub(crate) fn read_ptr(&self, ptr: Pointer, pointee_ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
12461246
let p = self.memory.read_ptr(ptr)?;
12471247
if self.type_is_sized(pointee_ty) {
1248-
Ok(Value::ByVal(PrimVal::Ptr(p)))
1248+
Ok(Value::ByVal(p))
12491249
} else {
12501250
trace!("reading fat pointer extra of type {}", pointee_ty);
12511251
let extra = ptr.offset(self.memory.pointer_size(), self.memory.layout)?;
12521252
let extra = match self.tcx.struct_tail(pointee_ty).sty {
1253-
ty::TyDynamic(..) => PrimVal::Ptr(self.memory.read_ptr(extra)?),
1253+
ty::TyDynamic(..) => self.memory.read_ptr(extra)?,
12541254
ty::TySlice(..) |
12551255
ty::TyStr => PrimVal::from_u128(self.memory.read_usize(extra)? as u128),
12561256
_ => bug!("unsized primval ptr read from {:?}", pointee_ty),
12571257
};
1258-
Ok(Value::ByValPair(PrimVal::Ptr(p), extra))
1258+
Ok(Value::ByValPair(p, extra))
12591259
}
12601260
}
12611261

@@ -1301,7 +1301,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
13011301
ty::TyFloat(FloatTy::F32) => PrimVal::from_f32(self.memory.read_f32(ptr)?),
13021302
ty::TyFloat(FloatTy::F64) => PrimVal::from_f64(self.memory.read_f64(ptr)?),
13031303

1304-
ty::TyFnPtr(_) => self.memory.read_ptr(ptr).map(PrimVal::Ptr)?,
1304+
ty::TyFnPtr(_) => self.memory.read_ptr(ptr)?,
13051305
ty::TyRef(_, ref tam) |
13061306
ty::TyRawPtr(ref tam) => return self.read_ptr(ptr, tam.ty).map(Some),
13071307

@@ -1360,7 +1360,6 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
13601360
(&ty::TyArray(_, length), &ty::TySlice(_)) => {
13611361
let ptr = src.read_ptr(&self.memory)?;
13621362
let len = PrimVal::from_u128(length as u128);
1363-
let ptr = PrimVal::Ptr(ptr);
13641363
self.write_value(Value::ByValPair(ptr, len), dest, dest_ty)
13651364
}
13661365
(&ty::TyDynamic(..), &ty::TyDynamic(..)) => {
@@ -1374,7 +1373,6 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
13741373
let trait_ref = self.tcx.erase_regions(&trait_ref);
13751374
let vtable = self.get_vtable(src_pointee_ty, trait_ref)?;
13761375
let ptr = src.read_ptr(&self.memory)?;
1377-
let ptr = PrimVal::Ptr(ptr);
13781376
let extra = PrimVal::Ptr(vtable);
13791377
self.write_value(Value::ByValPair(ptr, extra), dest, dest_ty)
13801378
},
@@ -1423,7 +1421,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
14231421
};
14241422

14251423
// FIXME(solson)
1426-
let dest = self.force_allocation(dest)?.to_ptr();
1424+
let dest = self.force_allocation(dest)?.to_ptr()?;
14271425
let iter = src_fields.zip(dst_fields).enumerate();
14281426
for (i, (src_f, dst_f)) in iter {
14291427
let src_fty = monomorphize_field_ty(self.tcx, src_f, substs_a);
@@ -1632,7 +1630,7 @@ pub fn eval_main<'a, 'tcx: 'a>(
16321630
start_instance,
16331631
start_mir.span,
16341632
start_mir,
1635-
Lvalue::from_ptr(ret_ptr),
1633+
Some(Lvalue::from_ptr(ret_ptr)),
16361634
StackPopCleanup::None,
16371635
)?;
16381636

@@ -1659,7 +1657,7 @@ pub fn eval_main<'a, 'tcx: 'a>(
16591657
main_instance,
16601658
main_mir.span,
16611659
main_mir,
1662-
Lvalue::from_ptr(Pointer::zst_ptr()),
1660+
Some(Lvalue::zst()),
16631661
StackPopCleanup::None,
16641662
)?;
16651663
}

src/lvalue.rs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ use value::{PrimVal, Value};
1212
pub enum Lvalue<'tcx> {
1313
/// An lvalue referring to a value allocated in the `Memory` system.
1414
Ptr {
15-
ptr: Pointer,
15+
/// An lvalue may have an invalid (integral or undef) pointer,
16+
/// since it might be turned back into a reference
17+
/// before ever being dereferenced.
18+
ptr: PrimVal,
1619
extra: LvalueExtra,
1720
},
1821

@@ -61,22 +64,26 @@ pub struct Global<'tcx> {
6164
}
6265

6366
impl<'tcx> Lvalue<'tcx> {
67+
pub fn zst() -> Self {
68+
Self::from_ptr(Pointer::zst_ptr())
69+
}
70+
6471
pub fn from_ptr(ptr: Pointer) -> Self {
65-
Lvalue::Ptr { ptr, extra: LvalueExtra::None }
72+
Lvalue::Ptr { ptr: PrimVal::Ptr(ptr), extra: LvalueExtra::None }
6673
}
6774

68-
pub(super) fn to_ptr_and_extra(self) -> (Pointer, LvalueExtra) {
75+
pub(super) fn to_ptr_and_extra(self) -> (PrimVal, LvalueExtra) {
6976
match self {
7077
Lvalue::Ptr { ptr, extra } => (ptr, extra),
7178
_ => bug!("to_ptr_and_extra: expected Lvalue::Ptr, got {:?}", self),
7279

7380
}
7481
}
7582

76-
pub(super) fn to_ptr(self) -> Pointer {
83+
pub(super) fn to_ptr(self) -> EvalResult<'tcx, Pointer> {
7784
let (ptr, extra) = self.to_ptr_and_extra();
7885
assert_eq!(extra, LvalueExtra::None);
79-
ptr
86+
ptr.to_ptr()
8087
}
8188

8289
pub(super) fn elem_ty_and_len(self, ty: Ty<'tcx>) -> (Ty<'tcx>, u64) {
@@ -127,7 +134,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
127134
match lvalue {
128135
Lvalue::Ptr { ptr, extra } => {
129136
assert_eq!(extra, LvalueExtra::None);
130-
Ok(Value::ByRef(ptr))
137+
Ok(Value::ByRef(ptr.to_ptr()?))
131138
}
132139
Lvalue::Local { frame, local, field } => {
133140
self.stack[frame].get_local(local, field.map(|(i, _)| i))
@@ -141,7 +148,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
141148
pub(super) fn eval_lvalue(&mut self, mir_lvalue: &mir::Lvalue<'tcx>) -> EvalResult<'tcx, Lvalue<'tcx>> {
142149
use rustc::mir::Lvalue::*;
143150
let lvalue = match *mir_lvalue {
144-
Local(mir::RETURN_POINTER) => self.frame().return_lvalue,
151+
Local(mir::RETURN_POINTER) => self.frame().return_lvalue.expect("diverging function returned"),
145152
Local(local) => Lvalue::Local { frame: self.stack.len() - 1, local, field: None },
146153

147154
Static(ref static_) => {
@@ -229,14 +236,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
229236
Lvalue::Local { frame, local, field } => match self.stack[frame].get_local(local, field.map(|(i, _)| i))? {
230237
Value::ByRef(ptr) => {
231238
assert!(field.is_none(), "local can't be ByRef and have a field offset");
232-
(ptr, LvalueExtra::None)
239+
(PrimVal::Ptr(ptr), LvalueExtra::None)
233240
},
234241
Value::ByVal(PrimVal::Undef) => {
235242
// FIXME: allocate in fewer cases
236243
if self.ty_to_primval_kind(base_ty).is_ok() {
237244
return Ok(base);
238245
} else {
239-
(self.force_allocation(base)?.to_ptr(), LvalueExtra::None)
246+
(PrimVal::Ptr(self.force_allocation(base)?.to_ptr()?), LvalueExtra::None)
240247
}
241248
},
242249
Value::ByVal(_) => {
@@ -264,7 +271,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
264271

265272
let offset = match base_extra {
266273
LvalueExtra::Vtable(tab) => {
267-
let (_, align) = self.size_and_align_of_dst(base_ty, Value::ByValPair(PrimVal::Ptr(base_ptr), PrimVal::Ptr(tab)))?;
274+
let (_, align) = self.size_and_align_of_dst(base_ty, Value::ByValPair(base_ptr, PrimVal::Ptr(tab)))?;
268275
offset.abi_align(Align::from_bytes(align, align).unwrap()).bytes()
269276
}
270277
_ => offset.bytes(),
@@ -276,7 +283,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
276283

277284
if packed {
278285
let size = self.type_size(field_ty)?.expect("packed struct must be sized");
279-
self.memory.mark_packed(ptr, size);
286+
self.memory.mark_packed(ptr.to_ptr()?, size);
280287
}
281288

282289
let extra = if self.type_is_sized(field_ty) {

0 commit comments

Comments
 (0)