//! Global machine state as well as implementation of the interpreter engine
//! `Machine` trait.
-use std::rc::Rc;
use std::borrow::Cow;
use std::cell::RefCell;
+use std::rc::Rc;
use rand::rngs::StdRng;
-use syntax::attr;
-use syntax::symbol::sym;
use rustc::hir::def_id::DefId;
-use rustc::ty::{self, Ty, TyCtxt, layout::{Size, LayoutOf}};
use rustc::mir;
+use rustc::ty::{
+ self,
+ layout::{LayoutOf, Size},
+ Ty, TyCtxt,
+};
+use syntax::attr;
+use syntax::symbol::sym;
use crate::*;
// Some global facts about the emulated machine.
-pub const PAGE_SIZE: u64 = 4*1024; // FIXME: adjust to target architecture
-pub const STACK_ADDR: u64 = 32*PAGE_SIZE; // not really about the "stack", but where we start assigning integer addresses to allocations
-pub const STACK_SIZE: u64 = 16*PAGE_SIZE; // whatever
+pub const PAGE_SIZE: u64 = 4 * 1024; // FIXME: adjust to target architecture
+pub const STACK_ADDR: u64 = 32 * PAGE_SIZE; // not really about the "stack", but where we start assigning integer addresses to allocations
+pub const STACK_SIZE: u64 = 16 * PAGE_SIZE; // whatever
pub const NUM_CPUS: u64 = 1;
/// Extra memory kinds
pub(crate) argv: Option<Pointer<Tag>>,
pub(crate) cmd_line: Option<Pointer<Tag>>,
- /// Last OS error.
- pub(crate) last_error: u32,
+ /// Last OS error location in memory. It is a 32-bit integer.
+ pub(crate) last_error: Option<MPlaceTy<'tcx, Tag>>,
/// TLS state.
pub(crate) tls: TlsData<'tcx>,
/// If enabled, the `env_vars` field is populated with the host env vars during initialization
/// and random number generation is delegated to the host.
pub(crate) communicate: bool,
+
+ pub(crate) file_handler: FileHandler,
}
impl<'tcx> Evaluator<'tcx> {
argc: None,
argv: None,
cmd_line: None,
- last_error: 0,
+ last_error: None,
tls: TlsData::default(),
communicate,
+ file_handler: Default::default(),
}
}
}
type PointerTag = Tag;
type ExtraFnVal = Dlsym;
- type MemoryMap = MonoHashMap<AllocId, (MemoryKind<MiriMemoryKind>, Allocation<Tag, Self::AllocExtra>)>;
+ type MemoryMap = MonoHashMap<
+ AllocId,
+ (
+ MemoryKind<MiriMemoryKind>,
+ Allocation<Tag, Self::AllocExtra>,
+ ),
+ >;
const STATIC_KIND: Option<MiriMemoryKind> = Some(MiriMemoryKind::Static);
#[inline(always)]
fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool {
- ecx.memory().extra.validate
+ ecx.memory.extra.validate
}
#[inline(always)]
ecx.write_scalar(Scalar::from_uint(align, arg.layout.size), arg)?;
// No more arguments.
- assert!(
- args.next().is_none(),
- "`exchange_malloc` lang item has more arguments than expected"
- );
+ args.next().expect_none("`exchange_malloc` lang item has more arguments than expected");
Ok(())
}
None => tcx.item_name(def_id).as_str(),
};
- let alloc = match link_name.get() {
+ let alloc = match &*link_name {
"__cxa_thread_atexit_impl" => {
// This should be all-zero, pointer-sized.
let size = tcx.data_layout.pointer_size;
}
#[inline(always)]
- fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>
- {
+ fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
// We are not interested in detecting loops.
Ok(())
}
id: AllocId,
alloc: Cow<'b, Allocation>,
kind: Option<MemoryKind<Self::MemoryKinds>>,
- ) -> (Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>>, Self::PointerTag) {
+ ) -> (
+ Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>>,
+ Self::PointerTag,
+ ) {
let kind = kind.expect("we set our STATIC_KIND so this cannot be None");
let alloc = alloc.into_owned();
let (stacks, base_tag) = if !memory_extra.validate {
} else {
let (stacks, base_tag) = Stacks::new_allocation(
id,
- Size::from_bytes(alloc.bytes.len() as u64),
+ alloc.size,
Rc::clone(&memory_extra.stacked_borrows),
kind,
);
(Some(stacks), base_tag)
};
- if kind != MiriMemoryKind::Static.into() {
- assert!(alloc.relocations.is_empty(), "Only statics can come initialized with inner pointers");
- // Now we can rely on the inner pointers being static, too.
- }
let mut stacked_borrows = memory_extra.stacked_borrows.borrow_mut();
- let alloc: Allocation<Tag, Self::AllocExtra> = Allocation {
- bytes: alloc.bytes,
- relocations: Relocations::from_presorted(
- alloc.relocations.iter()
- // The allocations in the relocations (pointers stored *inside* this allocation)
- // all get the base pointer tag.
- .map(|&(offset, ((), alloc))| {
- let tag = if !memory_extra.validate {
- Tag::Untagged
- } else {
- stacked_borrows.static_base_ptr(alloc)
- };
- (offset, (tag, alloc))
- })
- .collect()
- ),
- undef_mask: alloc.undef_mask,
- align: alloc.align,
- mutability: alloc.mutability,
- extra: AllocExtra {
+ let alloc: Allocation<Tag, Self::AllocExtra> = alloc.with_tags_and_extra(
+ |alloc| {
+ if !memory_extra.validate {
+ Tag::Untagged
+ } else {
+ // Only statics may already contain pointers at this point
+ assert_eq!(kind, MiriMemoryKind::Static.into());
+ stacked_borrows.static_base_ptr(alloc)
+ }
+ },
+ AllocExtra {
stacked_borrows: stacks,
},
- };
+ );
(Cow::Owned(alloc), base_tag)
}
#[inline(always)]
- fn tag_static_base_pointer(
- memory_extra: &MemoryExtra,
- id: AllocId,
- ) -> Self::PointerTag {
+ fn tag_static_base_pointer(memory_extra: &MemoryExtra, id: AllocId) -> Self::PointerTag {
if !memory_extra.validate {
Tag::Untagged
} else {
- memory_extra.stacked_borrows.borrow_mut().static_base_ptr(id)
+ memory_extra
+ .stacked_borrows
+ .borrow_mut()
+ .static_base_ptr(id)
}
}
) -> InterpResult<'tcx> {
if !Self::enforce_validity(ecx) {
// No tracking.
- Ok(())
+ Ok(())
} else {
ecx.retag(kind, place)
}
fn stack_push(
ecx: &mut InterpCx<'mir, 'tcx, Self>,
) -> InterpResult<'tcx, stacked_borrows::CallId> {
- Ok(ecx.memory().extra.stacked_borrows.borrow_mut().new_call())
+ Ok(ecx.memory.extra.stacked_borrows.borrow_mut().new_call())
}
#[inline(always)]
ecx: &mut InterpCx<'mir, 'tcx, Self>,
extra: stacked_borrows::CallId,
) -> InterpResult<'tcx> {
- Ok(ecx.memory().extra.stacked_borrows.borrow_mut().end_call(extra))
+ Ok(ecx
+ .memory
+ .extra
+ .stacked_borrows
+ .borrow_mut()
+ .end_call(extra))
}
#[inline(always)]