Skip to content

Commit 6d4a436

Browse files
committed
Allow machines to create new memory kinds
1 parent 2bde423 commit 6d4a436

File tree

11 files changed

+115
-64
lines changed

11 files changed

+115
-64
lines changed

miri/fn_call.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ use super::{
1515
MemoryExt,
1616
};
1717

18+
use super::memory::Kind;
19+
1820
pub trait EvalContextExt<'tcx> {
1921
fn call_c_abi(
2022
&mut self,
@@ -110,15 +112,15 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
110112
self.write_null(dest, dest_ty)?;
111113
} else {
112114
let align = self.memory.pointer_size();
113-
let ptr = self.memory.allocate(size, align, Kind::C)?;
115+
let ptr = self.memory.allocate(size, align, Kind::C.into())?;
114116
self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
115117
}
116118
}
117119

118120
"free" => {
119121
let ptr = args[0].into_ptr(&mut self.memory)?;
120122
if !ptr.is_null()? {
121-
self.memory.deallocate(ptr.to_ptr()?, None, Kind::C)?;
123+
self.memory.deallocate(ptr.to_ptr()?, None, Kind::C.into())?;
122124
}
123125
}
124126

@@ -242,7 +244,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
242244
}
243245
if let Some(old) = success {
244246
if let Some(var) = old {
245-
self.memory.deallocate(var, None, Kind::Env)?;
247+
self.memory.deallocate(var, None, Kind::Env.into())?;
246248
}
247249
self.write_null(dest, dest_ty)?;
248250
} else {
@@ -265,12 +267,12 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
265267
}
266268
if let Some((name, value)) = new {
267269
// +1 for the null terminator
268-
let value_copy = self.memory.allocate((value.len() + 1) as u64, 1, Kind::Env)?;
270+
let value_copy = self.memory.allocate((value.len() + 1) as u64, 1, Kind::Env.into())?;
269271
self.memory.write_bytes(value_copy.into(), &value)?;
270272
let trailing_zero_ptr = value_copy.offset(value.len() as u64, &self)?.into();
271273
self.memory.write_bytes(trailing_zero_ptr, &[0])?;
272274
if let Some(var) = self.machine_data.env_vars.insert(name.to_owned(), value_copy) {
273-
self.memory.deallocate(var, None, Kind::Env)?;
275+
self.memory.deallocate(var, None, Kind::Env.into())?;
274276
}
275277
self.write_null(dest, dest_ty)?;
276278
} else {
@@ -491,7 +493,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
491493
if !align.is_power_of_two() {
492494
return Err(EvalError::HeapAllocNonPowerOfTwoAlignment(align));
493495
}
494-
let ptr = self.memory.allocate(size, align, Kind::Rust)?;
496+
let ptr = self.memory.allocate(size, align, Kind::Rust.into())?;
495497
self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
496498
}
497499
"alloc::heap::::__rust_alloc_zeroed" => {
@@ -503,7 +505,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
503505
if !align.is_power_of_two() {
504506
return Err(EvalError::HeapAllocNonPowerOfTwoAlignment(align));
505507
}
506-
let ptr = self.memory.allocate(size, align, Kind::Rust)?;
508+
let ptr = self.memory.allocate(size, align, Kind::Rust.into())?;
507509
self.memory.write_repeat(ptr.into(), 0, size)?;
508510
self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
509511
}
@@ -517,7 +519,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
517519
if !align.is_power_of_two() {
518520
return Err(EvalError::HeapAllocNonPowerOfTwoAlignment(align));
519521
}
520-
self.memory.deallocate(ptr, Some((old_size, align)), Kind::Rust)?;
522+
self.memory.deallocate(ptr, Some((old_size, align)), Kind::Rust.into())?;
521523
}
522524
"alloc::heap::::__rust_realloc" => {
523525
let ptr = args[0].into_ptr(&mut self.memory)?.to_ptr()?;
@@ -534,7 +536,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
534536
if !new_align.is_power_of_two() {
535537
return Err(EvalError::HeapAllocNonPowerOfTwoAlignment(new_align));
536538
}
537-
let new_ptr = self.memory.reallocate(ptr, old_size, old_align, new_size, new_align, Kind::Rust)?;
539+
let new_ptr = self.memory.reallocate(ptr, old_size, old_align, new_size, new_align, Kind::Rust.into())?;
538540
self.write_primval(dest, PrimVal::Ptr(new_ptr), dest_ty)?;
539541
}
540542

miri/helpers.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use rustc_miri::interpret::{
66
};
77

88
use rustc::ty::Ty;
9-
use rustc::ty::layout::Layout;
109

1110
pub trait EvalContextExt<'tcx> {
1211
fn wrapping_pointer_offset(

miri/intrinsic.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use rustc_miri::interpret::{
88
Lvalue, LvalueExtra,
99
PrimVal, PrimValKind, Value, Pointer,
1010
HasMemory,
11-
Machine,
1211
EvalContext,
1312
};
1413

miri/lib.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ mod fn_call;
3232
mod operator;
3333
mod intrinsic;
3434
mod helpers;
35+
mod memory;
3536

3637
use fn_call::EvalContextExt as MissingFnsEvalContextExt;
3738
use operator::EvalContextExt as OperatorEvalContextExt;
@@ -278,6 +279,7 @@ impl<'a, 'tcx: 'a> MemoryExt<'tcx> for Memory<'a, 'tcx, Evaluator> {
278279
impl<'tcx> Machine<'tcx> for Evaluator {
279280
type Data = EvaluatorData;
280281
type MemoryData = MemoryData<'tcx>;
282+
type MemoryKinds = memory::Kind;
281283

282284
/// Returns Ok() when the function was handled, fail otherwise
283285
fn eval_fn_call<'a>(
@@ -313,4 +315,28 @@ impl<'tcx> Machine<'tcx> for Evaluator {
313315
) -> EvalResult<'tcx, Option<(PrimVal, bool)>> {
314316
ecx.ptr_op(bin_op, left, left_ty, right, right_ty)
315317
}
318+
319+
fn mark_static_initialized(m: memory::Kind) -> EvalResult<'tcx> {
320+
use memory::Kind::*;
321+
match m {
322+
// FIXME: This could be allowed, but not for env vars set during miri execution
323+
Env => Err(EvalError::Unimplemented("statics can't refer to env vars".to_owned())),
324+
_ => Ok(()),
325+
}
326+
}
327+
328+
fn box_alloc<'a>(
329+
ecx: &mut EvalContext<'a, 'tcx, Self>,
330+
ty: ty::Ty<'tcx>,
331+
) -> EvalResult<'tcx, PrimVal> {
332+
let size = ecx.type_size(ty)?.expect("box only works with sized types");
333+
let align = ecx.type_align(ty)?;
334+
if size == 0 {
335+
Ok(PrimVal::Bytes(align.into()))
336+
} else {
337+
ecx.memory
338+
.allocate(size, align, Kind::Machine(memory::Kind::Rust))
339+
.map(PrimVal::Ptr)
340+
}
341+
}
316342
}

src/librustc_mir/interpret/const_eval.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ impl Error for ConstEvalError {
128128
impl<'tcx> super::Machine<'tcx> for CompileTimeFunctionEvaluator {
129129
type Data = ();
130130
type MemoryData = ();
131+
type MemoryKinds = !;
131132
fn eval_fn_call<'a>(
132133
ecx: &mut EvalContext<'a, 'tcx, Self>,
133134
instance: ty::Instance<'tcx>,
@@ -185,4 +186,15 @@ impl<'tcx> super::Machine<'tcx> for CompileTimeFunctionEvaluator {
185186
) -> EvalResult<'tcx, Option<(PrimVal, bool)>> {
186187
Err(ConstEvalError::NeedsRfc("Pointer arithmetic or comparison".to_string()).into())
187188
}
189+
190+
fn mark_static_initialized(m: !) -> EvalResult<'tcx> {
191+
m
192+
}
193+
194+
fn box_alloc<'a>(
195+
_ecx: &mut EvalContext<'a, 'tcx, Self>,
196+
_ty: ty::Ty<'tcx>,
197+
) -> EvalResult<'tcx, PrimVal> {
198+
Err(ConstEvalError::NeedsRfc("Heap allocations via `box` keyword".to_string()).into())
199+
}
188200
}

src/librustc_mir/interpret/error.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc::mir;
44
use rustc::ty::{FnSig, Ty, layout};
55

66
use super::{
7-
MemoryPointer, Kind, LockInfo, AccessKind
7+
MemoryPointer, LockInfo, AccessKind
88
};
99

1010
use rustc_const_math::ConstMathErr;
@@ -88,8 +88,8 @@ pub enum EvalError<'tcx> {
8888
AssumptionNotHeld,
8989
InlineAsm,
9090
TypeNotPrimitive(Ty<'tcx>),
91-
ReallocatedWrongMemoryKind(Kind, Kind),
92-
DeallocatedWrongMemoryKind(Kind, Kind),
91+
ReallocatedWrongMemoryKind(String, String),
92+
DeallocatedWrongMemoryKind(String, String),
9393
ReallocateNonBasePtr,
9494
DeallocateNonBasePtr,
9595
IncorrectAllocationInformation,
@@ -262,10 +262,10 @@ impl<'tcx> fmt::Display for EvalError<'tcx> {
262262
write!(f, "tried to call a function with sig {} through a function pointer of type {}", sig, got),
263263
ArrayIndexOutOfBounds(span, len, index) =>
264264
write!(f, "index out of bounds: the len is {} but the index is {} at {:?}", len, index, span),
265-
ReallocatedWrongMemoryKind(old, new) =>
266-
write!(f, "tried to reallocate memory from {:?} to {:?}", old, new),
267-
DeallocatedWrongMemoryKind(old, new) =>
268-
write!(f, "tried to deallocate {:?} memory but gave {:?} as the kind", old, new),
265+
ReallocatedWrongMemoryKind(ref old, ref new) =>
266+
write!(f, "tried to reallocate memory from {} to {}", old, new),
267+
DeallocatedWrongMemoryKind(ref old, ref new) =>
268+
write!(f, "tried to deallocate {} memory but gave {} as the kind", old, new),
269269
Math(span, ref err) =>
270270
write!(f, "{:?} at {:?}", err, span),
271271
Intrinsic(ref err) =>

src/librustc_mir/interpret/eval_context.rs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -776,17 +776,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
776776
}
777777

778778
NullaryOp(mir::NullOp::Box, ty) => {
779-
// FIXME(CTFE): don't allow heap allocations in const eval
780-
// FIXME: call the `exchange_malloc` lang item if available
781-
let size = self.type_size(ty)?.expect("box only works with sized types");
782-
if size == 0 {
783-
let align = self.type_align(ty)?;
784-
self.write_primval(dest, PrimVal::Bytes(align.into()), dest_ty)?;
785-
} else {
786-
let align = self.type_align(ty)?;
787-
let ptr = self.memory.allocate(size, align, MemoryKind::Rust)?;
788-
self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
789-
}
779+
let ptr = M::box_alloc(self, ty)?;
780+
self.write_primval(dest, ptr, dest_ty)?;
790781
}
791782

792783
NullaryOp(mir::NullOp::SizeOf, ty) => {

src/librustc_mir/interpret/machine.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ pub trait Machine<'tcx>: Sized {
2121
/// Additional data that can be accessed via the Memory
2222
type MemoryData;
2323

24+
/// Additional memory kinds a machine wishes to distinguish from the builtin ones
25+
type MemoryKinds: ::std::fmt::Debug + PartialEq + Copy + Clone;
26+
2427
/// Entry point to all function calls.
2528
///
2629
/// Returns Ok(true) when the function was handled completely
@@ -61,5 +64,16 @@ pub trait Machine<'tcx>: Sized {
6164
right: PrimVal,
6265
right_ty: ty::Ty<'tcx>,
6366
) -> EvalResult<'tcx, Option<(PrimVal, bool)>>;
67+
68+
/// Called when trying to mark machine defined `MemoryKinds` as static
69+
fn mark_static_initialized(m: Self::MemoryKinds) -> EvalResult<'tcx>;
70+
71+
/// Heap allocations via the `box` keyword
72+
///
73+
/// Returns a pointer to the allocated memory
74+
fn box_alloc<'a>(
75+
ecx: &mut EvalContext<'a, 'tcx, Self>,
76+
ty: ty::Ty<'tcx>,
77+
) -> EvalResult<'tcx, PrimVal>;
6478
}
6579

0 commit comments

Comments
 (0)