Allow machines to create new memory kinds
This commit is contained in:
parent
7ed706d09c
commit
adfea61665
10 changed files with 131 additions and 62 deletions
|
@ -15,6 +15,8 @@ use super::{
|
|||
MemoryExt,
|
||||
};
|
||||
|
||||
use super::memory::Kind;
|
||||
|
||||
pub trait EvalContextExt<'tcx> {
|
||||
fn call_c_abi(
|
||||
&mut self,
|
||||
|
@ -110,7 +112,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
|
|||
self.write_null(dest, dest_ty)?;
|
||||
} else {
|
||||
let align = self.memory.pointer_size();
|
||||
let ptr = self.memory.allocate(size, align, Kind::C)?;
|
||||
let ptr = self.memory.allocate(size, align, Kind::C.into())?;
|
||||
self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
|
||||
}
|
||||
}
|
||||
|
@ -118,7 +120,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
|
|||
"free" => {
|
||||
let ptr = args[0].into_ptr(&mut self.memory)?;
|
||||
if !ptr.is_null()? {
|
||||
self.memory.deallocate(ptr.to_ptr()?, None, Kind::C)?;
|
||||
self.memory.deallocate(ptr.to_ptr()?, None, Kind::C.into())?;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,7 +244,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
|
|||
}
|
||||
if let Some(old) = success {
|
||||
if let Some(var) = old {
|
||||
self.memory.deallocate(var, None, Kind::Env)?;
|
||||
self.memory.deallocate(var, None, Kind::Env.into())?;
|
||||
}
|
||||
self.write_null(dest, dest_ty)?;
|
||||
} else {
|
||||
|
@ -265,12 +267,12 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
|
|||
}
|
||||
if let Some((name, value)) = new {
|
||||
// +1 for the null terminator
|
||||
let value_copy = self.memory.allocate((value.len() + 1) as u64, 1, Kind::Env)?;
|
||||
let value_copy = self.memory.allocate((value.len() + 1) as u64, 1, Kind::Env.into())?;
|
||||
self.memory.write_bytes(value_copy.into(), &value)?;
|
||||
let trailing_zero_ptr = value_copy.offset(value.len() as u64, &self)?.into();
|
||||
self.memory.write_bytes(trailing_zero_ptr, &[0])?;
|
||||
if let Some(var) = self.machine_data.env_vars.insert(name.to_owned(), value_copy) {
|
||||
self.memory.deallocate(var, None, Kind::Env)?;
|
||||
self.memory.deallocate(var, None, Kind::Env.into())?;
|
||||
}
|
||||
self.write_null(dest, dest_ty)?;
|
||||
} else {
|
||||
|
@ -491,7 +493,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
|
|||
if !align.is_power_of_two() {
|
||||
return Err(EvalError::HeapAllocNonPowerOfTwoAlignment(align));
|
||||
}
|
||||
let ptr = self.memory.allocate(size, align, Kind::Rust)?;
|
||||
let ptr = self.memory.allocate(size, align, Kind::Rust.into())?;
|
||||
self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
|
||||
}
|
||||
"alloc::heap::::__rust_alloc_zeroed" => {
|
||||
|
@ -503,7 +505,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
|
|||
if !align.is_power_of_two() {
|
||||
return Err(EvalError::HeapAllocNonPowerOfTwoAlignment(align));
|
||||
}
|
||||
let ptr = self.memory.allocate(size, align, Kind::Rust)?;
|
||||
let ptr = self.memory.allocate(size, align, Kind::Rust.into())?;
|
||||
self.memory.write_repeat(ptr.into(), 0, size)?;
|
||||
self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
|
||||
}
|
||||
|
@ -517,7 +519,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
|
|||
if !align.is_power_of_two() {
|
||||
return Err(EvalError::HeapAllocNonPowerOfTwoAlignment(align));
|
||||
}
|
||||
self.memory.deallocate(ptr, Some((old_size, align)), Kind::Rust)?;
|
||||
self.memory.deallocate(ptr, Some((old_size, align)), Kind::Rust.into())?;
|
||||
}
|
||||
"alloc::heap::::__rust_realloc" => {
|
||||
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>
|
|||
if !new_align.is_power_of_two() {
|
||||
return Err(EvalError::HeapAllocNonPowerOfTwoAlignment(new_align));
|
||||
}
|
||||
let new_ptr = self.memory.reallocate(ptr, old_size, old_align, new_size, new_align, Kind::Rust)?;
|
||||
let new_ptr = self.memory.reallocate(ptr, old_size, old_align, new_size, new_align, Kind::Rust.into())?;
|
||||
self.write_primval(dest, PrimVal::Ptr(new_ptr), dest_ty)?;
|
||||
}
|
||||
|
||||
|
|
26
miri/lib.rs
26
miri/lib.rs
|
@ -32,6 +32,7 @@ mod fn_call;
|
|||
mod operator;
|
||||
mod intrinsic;
|
||||
mod helpers;
|
||||
mod memory;
|
||||
|
||||
use fn_call::EvalContextExt as MissingFnsEvalContextExt;
|
||||
use operator::EvalContextExt as OperatorEvalContextExt;
|
||||
|
@ -278,6 +279,7 @@ impl<'a, 'tcx: 'a> MemoryExt<'tcx> for Memory<'a, 'tcx, Evaluator> {
|
|||
impl<'tcx> Machine<'tcx> for Evaluator {
|
||||
type Data = EvaluatorData;
|
||||
type MemoryData = MemoryData<'tcx>;
|
||||
type MemoryKinds = memory::Kind;
|
||||
|
||||
/// Returns Ok() when the function was handled, fail otherwise
|
||||
fn eval_fn_call<'a>(
|
||||
|
@ -313,4 +315,28 @@ impl<'tcx> Machine<'tcx> for Evaluator {
|
|||
) -> EvalResult<'tcx, Option<(PrimVal, bool)>> {
|
||||
ecx.ptr_op(bin_op, left, left_ty, right, right_ty)
|
||||
}
|
||||
|
||||
fn mark_static_initialized(m: memory::Kind) -> EvalResult<'tcx> {
|
||||
use memory::Kind::*;
|
||||
match m {
|
||||
// FIXME: This could be allowed, but not for env vars set during miri execution
|
||||
Env => Err(EvalError::Unimplemented("statics can't refer to env vars".to_owned())),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
fn box_alloc<'a>(
|
||||
ecx: &mut EvalContext<'a, 'tcx, Self>,
|
||||
ty: ty::Ty<'tcx>,
|
||||
) -> EvalResult<'tcx, PrimVal> {
|
||||
let size = ecx.type_size(ty)?.expect("box only works with sized types");
|
||||
let align = ecx.type_align(ty)?;
|
||||
if size == 0 {
|
||||
Ok(PrimVal::Bytes(align.into()))
|
||||
} else {
|
||||
ecx.memory
|
||||
.allocate(size, align, Kind::Machine(memory::Kind::Rust))
|
||||
.map(PrimVal::Ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
16
miri/memory.rs
Normal file
16
miri/memory.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
|
||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
pub enum Kind {
|
||||
/// Error if deallocated any other way than `rust_deallocate`
|
||||
Rust,
|
||||
/// Error if deallocated any other way than `free`
|
||||
C,
|
||||
/// Part of env var emulation
|
||||
Env,
|
||||
}
|
||||
|
||||
impl Into<::rustc_miri::interpret::Kind<Kind>> for Kind {
|
||||
fn into(self) -> ::rustc_miri::interpret::Kind<Kind> {
|
||||
::rustc_miri::interpret::Kind::Machine(self)
|
||||
}
|
||||
}
|
|
@ -128,6 +128,7 @@ impl Error for ConstEvalError {
|
|||
impl<'tcx> super::Machine<'tcx> for CompileTimeFunctionEvaluator {
|
||||
type Data = ();
|
||||
type MemoryData = ();
|
||||
type MemoryKinds = !;
|
||||
fn eval_fn_call<'a>(
|
||||
ecx: &mut EvalContext<'a, 'tcx, Self>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
|
@ -185,4 +186,15 @@ impl<'tcx> super::Machine<'tcx> for CompileTimeFunctionEvaluator {
|
|||
) -> EvalResult<'tcx, Option<(PrimVal, bool)>> {
|
||||
Err(ConstEvalError::NeedsRfc("Pointer arithmetic or comparison".to_string()).into())
|
||||
}
|
||||
|
||||
fn mark_static_initialized(m: !) -> EvalResult<'tcx> {
|
||||
m
|
||||
}
|
||||
|
||||
fn box_alloc<'a>(
|
||||
_ecx: &mut EvalContext<'a, 'tcx, Self>,
|
||||
_ty: ty::Ty<'tcx>,
|
||||
) -> EvalResult<'tcx, PrimVal> {
|
||||
Err(ConstEvalError::NeedsRfc("Heap allocations via `box` keyword".to_string()).into())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use rustc::mir;
|
|||
use rustc::ty::{FnSig, Ty, layout};
|
||||
|
||||
use super::{
|
||||
MemoryPointer, Kind, LockInfo, AccessKind
|
||||
MemoryPointer, LockInfo, AccessKind
|
||||
};
|
||||
|
||||
use rustc_const_math::ConstMathErr;
|
||||
|
@ -88,8 +88,8 @@ pub enum EvalError<'tcx> {
|
|||
AssumptionNotHeld,
|
||||
InlineAsm,
|
||||
TypeNotPrimitive(Ty<'tcx>),
|
||||
ReallocatedWrongMemoryKind(Kind, Kind),
|
||||
DeallocatedWrongMemoryKind(Kind, Kind),
|
||||
ReallocatedWrongMemoryKind(String, String),
|
||||
DeallocatedWrongMemoryKind(String, String),
|
||||
ReallocateNonBasePtr,
|
||||
DeallocateNonBasePtr,
|
||||
IncorrectAllocationInformation,
|
||||
|
@ -262,10 +262,10 @@ impl<'tcx> fmt::Display for EvalError<'tcx> {
|
|||
write!(f, "tried to call a function with sig {} through a function pointer of type {}", sig, got),
|
||||
ArrayIndexOutOfBounds(span, len, index) =>
|
||||
write!(f, "index out of bounds: the len is {} but the index is {} at {:?}", len, index, span),
|
||||
ReallocatedWrongMemoryKind(old, new) =>
|
||||
write!(f, "tried to reallocate memory from {:?} to {:?}", old, new),
|
||||
DeallocatedWrongMemoryKind(old, new) =>
|
||||
write!(f, "tried to deallocate {:?} memory but gave {:?} as the kind", old, new),
|
||||
ReallocatedWrongMemoryKind(ref old, ref new) =>
|
||||
write!(f, "tried to reallocate memory from {} to {}", old, new),
|
||||
DeallocatedWrongMemoryKind(ref old, ref new) =>
|
||||
write!(f, "tried to deallocate {} memory but gave {} as the kind", old, new),
|
||||
Math(span, ref err) =>
|
||||
write!(f, "{:?} at {:?}", err, span),
|
||||
Intrinsic(ref err) =>
|
||||
|
|
|
@ -782,17 +782,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
|
|||
}
|
||||
|
||||
NullaryOp(mir::NullOp::Box, ty) => {
|
||||
// FIXME(CTFE): don't allow heap allocations in const eval
|
||||
// FIXME: call the `exchange_malloc` lang item if available
|
||||
let size = self.type_size(ty)?.expect("box only works with sized types");
|
||||
if size == 0 {
|
||||
let align = self.type_align(ty)?;
|
||||
self.write_primval(dest, PrimVal::Bytes(align.into()), dest_ty)?;
|
||||
} else {
|
||||
let align = self.type_align(ty)?;
|
||||
let ptr = self.memory.allocate(size, align, MemoryKind::Rust)?;
|
||||
self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
|
||||
}
|
||||
let ptr = M::box_alloc(self, ty)?;
|
||||
self.write_primval(dest, ptr, dest_ty)?;
|
||||
}
|
||||
|
||||
NullaryOp(mir::NullOp::SizeOf, ty) => {
|
||||
|
|
|
@ -21,6 +21,9 @@ pub trait Machine<'tcx>: Sized {
|
|||
/// Additional data that can be accessed via the Memory
|
||||
type MemoryData;
|
||||
|
||||
/// Additional memory kinds a machine wishes to distinguish from the builtin ones
|
||||
type MemoryKinds: ::std::fmt::Debug + PartialEq + Copy + Clone;
|
||||
|
||||
/// Entry point to all function calls.
|
||||
///
|
||||
/// Returns Ok(true) when the function was handled completely
|
||||
|
@ -61,5 +64,16 @@ pub trait Machine<'tcx>: Sized {
|
|||
right: PrimVal,
|
||||
right_ty: ty::Ty<'tcx>,
|
||||
) -> EvalResult<'tcx, Option<(PrimVal, bool)>>;
|
||||
|
||||
/// Called when trying to mark machine defined `MemoryKinds` as static
|
||||
fn mark_static_initialized(m: Self::MemoryKinds) -> EvalResult<'tcx>;
|
||||
|
||||
/// Heap allocations via the `box` keyword
|
||||
///
|
||||
/// Returns a pointer to the allocated memory
|
||||
fn box_alloc<'a>(
|
||||
ecx: &mut EvalContext<'a, 'tcx, Self>,
|
||||
ty: ty::Ty<'tcx>,
|
||||
) -> EvalResult<'tcx, PrimVal>;
|
||||
}
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ impl fmt::Display for AllocId {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Allocation {
|
||||
pub struct Allocation<M> {
|
||||
/// The actual bytes of the allocation.
|
||||
/// Note that the bytes of a pointer represent the offset of the pointer
|
||||
pub bytes: Vec<u8>,
|
||||
|
@ -132,12 +132,12 @@ pub struct Allocation {
|
|||
/// Use the `mark_static_initalized` method of `Memory` to ensure that an error occurs, if the memory of this
|
||||
/// allocation is modified or deallocated in the future.
|
||||
/// Helps guarantee that stack allocations aren't deallocated via `rust_deallocate`
|
||||
pub kind: Kind,
|
||||
pub kind: Kind<M>,
|
||||
/// Memory regions that are locked by some function
|
||||
locks: BTreeMap<MemoryRange, LockInfo>,
|
||||
}
|
||||
|
||||
impl Allocation {
|
||||
impl<M> Allocation<M> {
|
||||
fn iter_locks<'a>(&'a self, offset: u64, len: u64) -> impl Iterator<Item=(&'a MemoryRange, &'a LockInfo)> + 'a {
|
||||
self.locks.range(MemoryRange::range(offset, len))
|
||||
.filter(move |&(range, _)| range.overlaps(offset, len))
|
||||
|
@ -165,11 +165,7 @@ impl Allocation {
|
|||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||
pub enum Kind {
|
||||
/// Error if deallocated any other way than `rust_deallocate`
|
||||
Rust,
|
||||
/// Error if deallocated any other way than `free`
|
||||
C,
|
||||
pub enum Kind<T> {
|
||||
/// Error if deallocated except during a stack pop
|
||||
Stack,
|
||||
/// Static in the process of being initialized.
|
||||
|
@ -179,8 +175,8 @@ pub enum Kind {
|
|||
UninitializedStatic,
|
||||
/// May never be deallocated
|
||||
Static,
|
||||
/// Part of env var emulation
|
||||
Env,
|
||||
/// Additional memory kinds a machine wishes to distinguish from the builtin ones
|
||||
Machine(T),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
|
@ -226,7 +222,7 @@ pub struct Memory<'a, 'tcx, M: Machine<'tcx>> {
|
|||
pub data: M::MemoryData,
|
||||
|
||||
/// Actual memory allocations (arbitrary bytes, may contain pointers into other allocations).
|
||||
alloc_map: HashMap<AllocId, Allocation>,
|
||||
alloc_map: HashMap<AllocId, Allocation<M::MemoryKinds>>,
|
||||
|
||||
/// The AllocId to assign to the next new allocation. Always incremented, never gets smaller.
|
||||
next_id: AllocId,
|
||||
|
@ -285,7 +281,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn allocations(&self) -> ::std::collections::hash_map::Iter<AllocId, Allocation> {
|
||||
pub fn allocations(&self) -> ::std::collections::hash_map::Iter<AllocId, Allocation<M::MemoryKinds>> {
|
||||
self.alloc_map.iter()
|
||||
}
|
||||
|
||||
|
@ -313,7 +309,12 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
|
|||
Ok(ptr)
|
||||
}
|
||||
|
||||
pub fn allocate(&mut self, size: u64, align: u64, kind: Kind) -> EvalResult<'tcx, MemoryPointer> {
|
||||
pub fn allocate(
|
||||
&mut self,
|
||||
size: u64,
|
||||
align: u64,
|
||||
kind: Kind<M::MemoryKinds>,
|
||||
) -> EvalResult<'tcx, MemoryPointer> {
|
||||
assert_ne!(align, 0);
|
||||
assert!(align.is_power_of_two());
|
||||
|
||||
|
@ -341,7 +342,15 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
|
|||
Ok(MemoryPointer::new(id, 0))
|
||||
}
|
||||
|
||||
pub fn reallocate(&mut self, ptr: MemoryPointer, old_size: u64, old_align: u64, new_size: u64, new_align: u64, kind: Kind) -> EvalResult<'tcx, MemoryPointer> {
|
||||
pub fn reallocate(
|
||||
&mut self,
|
||||
ptr: MemoryPointer,
|
||||
old_size: u64,
|
||||
old_align: u64,
|
||||
new_size: u64,
|
||||
new_align: u64,
|
||||
kind: Kind<M::MemoryKinds>,
|
||||
) -> EvalResult<'tcx, MemoryPointer> {
|
||||
use std::cmp::min;
|
||||
|
||||
if ptr.offset != 0 {
|
||||
|
@ -349,7 +358,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
|
|||
}
|
||||
if let Ok(alloc) = self.get(ptr.alloc_id) {
|
||||
if alloc.kind != kind {
|
||||
return Err(EvalError::ReallocatedWrongMemoryKind(alloc.kind, kind));
|
||||
return Err(EvalError::ReallocatedWrongMemoryKind(format!("{:?}", alloc.kind), format!("{:?}", kind)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -361,7 +370,12 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
|
|||
Ok(new_ptr)
|
||||
}
|
||||
|
||||
pub fn deallocate(&mut self, ptr: MemoryPointer, size_and_align: Option<(u64, u64)>, kind: Kind) -> EvalResult<'tcx> {
|
||||
pub fn deallocate(
|
||||
&mut self,
|
||||
ptr: MemoryPointer,
|
||||
size_and_align: Option<(u64, u64)>,
|
||||
kind: Kind<M::MemoryKinds>,
|
||||
) -> EvalResult<'tcx> {
|
||||
if ptr.offset != 0 {
|
||||
return Err(EvalError::DeallocateNonBasePtr);
|
||||
}
|
||||
|
@ -380,7 +394,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
|
|||
.map_err(|lock| EvalError::DeallocatedLockedMemory { ptr, lock })?;
|
||||
|
||||
if alloc.kind != kind {
|
||||
return Err(EvalError::DeallocatedWrongMemoryKind(alloc.kind, kind));
|
||||
return Err(EvalError::DeallocatedWrongMemoryKind(format!("{:?}", alloc.kind), format!("{:?}", kind)));
|
||||
}
|
||||
if let Some((size, align)) = size_and_align {
|
||||
if size != alloc.bytes.len() as u64 || align != alloc.align {
|
||||
|
@ -573,7 +587,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
|
|||
|
||||
/// Allocation accessors
|
||||
impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
|
||||
pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation> {
|
||||
pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation<M::MemoryKinds>> {
|
||||
match self.alloc_map.get(&id) {
|
||||
Some(alloc) => Ok(alloc),
|
||||
None => match self.functions.get(&id) {
|
||||
|
@ -583,7 +597,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_mut_unchecked(&mut self, id: AllocId) -> EvalResult<'tcx, &mut Allocation> {
|
||||
fn get_mut_unchecked(&mut self, id: AllocId) -> EvalResult<'tcx, &mut Allocation<M::MemoryKinds>> {
|
||||
match self.alloc_map.get_mut(&id) {
|
||||
Some(alloc) => Ok(alloc),
|
||||
None => match self.functions.get(&id) {
|
||||
|
@ -593,7 +607,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_mut(&mut self, id: AllocId) -> EvalResult<'tcx, &mut Allocation> {
|
||||
pub fn get_mut(&mut self, id: AllocId) -> EvalResult<'tcx, &mut Allocation<M::MemoryKinds>> {
|
||||
let alloc = self.get_mut_unchecked(id)?;
|
||||
if alloc.mutable == Mutability::Mutable {
|
||||
Ok(alloc)
|
||||
|
@ -663,13 +677,11 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
|
|||
}
|
||||
|
||||
let immutable = match (alloc.kind, alloc.mutable) {
|
||||
(Kind::UninitializedStatic, _) => " (static in the process of initialization)",
|
||||
(Kind::Static, Mutability::Mutable) => " (static mut)",
|
||||
(Kind::Static, Mutability::Immutable) => " (immutable)",
|
||||
(Kind::Env, _) => " (env var)",
|
||||
(Kind::C, _) => " (malloc)",
|
||||
(Kind::Rust, _) => " (heap)",
|
||||
(Kind::Stack, _) => " (stack)",
|
||||
(Kind::UninitializedStatic, _) => " (static in the process of initialization)".to_owned(),
|
||||
(Kind::Static, Mutability::Mutable) => " (static mut)".to_owned(),
|
||||
(Kind::Static, Mutability::Immutable) => " (immutable)".to_owned(),
|
||||
(Kind::Machine(m), _) => format!(" ({:?})", m),
|
||||
(Kind::Stack, _) => " (stack)".to_owned(),
|
||||
};
|
||||
trace!("{}({} bytes, alignment {}){}", msg, alloc.bytes.len(), alloc.align, immutable);
|
||||
|
||||
|
@ -793,17 +805,12 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
|
|||
// E.g. `const Foo: &u32 = &1;` refers to the temp local that stores the `1`
|
||||
Kind::Stack |
|
||||
// The entire point of this function
|
||||
Kind::UninitializedStatic |
|
||||
// In the future const eval will allow heap allocations so we'll need to protect them
|
||||
// from deallocation, too
|
||||
Kind::Rust |
|
||||
Kind::C => {},
|
||||
Kind::UninitializedStatic => {},
|
||||
Kind::Machine(m) => M::mark_static_initialized(m)?,
|
||||
Kind::Static => {
|
||||
trace!("mark_static_initalized: skipping already initialized static referred to by static currently being initialized");
|
||||
return Ok(());
|
||||
},
|
||||
// FIXME: This could be allowed, but not for env vars set during miri execution
|
||||
Kind::Env => return Err(EvalError::Unimplemented("statics can't refer to env vars".to_owned())),
|
||||
}
|
||||
*kind = Kind::Static;
|
||||
*mutable = mutability;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
i128_type,
|
||||
rustc_private,
|
||||
conservative_impl_trait,
|
||||
never_type,
|
||||
)]
|
||||
|
||||
// From rustc.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// error-pattern: tried to deallocate Stack memory but gave Rust as the kind
|
||||
// error-pattern: tried to deallocate Stack memory but gave Machine(Rust) as the kind
|
||||
|
||||
fn main() {
|
||||
let x = 42;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue