Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup: Avoid repeating signatures, get rid of to_bytes hack #568

Merged
merged 3 commits into from
Dec 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
337 changes: 160 additions & 177 deletions src/fn_call.rs

Large diffs are not rendered by default.

70 changes: 18 additions & 52 deletions src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,68 +5,31 @@ use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};

use crate::*;

pub trait ScalarExt {
/// HACK: this function just extracts all bits if `defined != 0`
/// Mainly used for args of C-functions and we should totally correctly fetch the size
/// of their arguments
fn to_bytes(self) -> EvalResult<'static, u128>;
}

impl<Tag> ScalarExt for Scalar<Tag> {
fn to_bytes(self) -> EvalResult<'static, u128> {
match self {
Scalar::Bits { bits, size } => {
assert_ne!(size, 0);
Ok(bits)
},
Scalar::Ptr(_) => err!(ReadPointerAsBytes),
}
}
}

impl<Tag> ScalarExt for ScalarMaybeUndef<Tag> {
fn to_bytes(self) -> EvalResult<'static, u128> {
self.not_undef()?.to_bytes()
}
}

pub trait EvalContextExt<'tcx> {
fn resolve_path(&self, path: &[&str]) -> EvalResult<'tcx, ty::Instance<'tcx>>;

/// Visit the memory covered by `place`, sensitive to freezing: The 3rd parameter
/// will be true if this is frozen, false if this is in an `UnsafeCell`.
fn visit_freeze_sensitive(
&self,
place: MPlaceTy<'tcx, Borrow>,
size: Size,
action: impl FnMut(Pointer<Borrow>, Size, bool) -> EvalResult<'tcx>,
) -> EvalResult<'tcx>;
}


impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super::Evaluator<'tcx>> {
impl<'a, 'mir, 'tcx> EvalContextExt<'a, 'mir, 'tcx> for crate::MiriEvalContext<'a, 'mir, 'tcx> {}
pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, 'mir, 'tcx> {
/// Get an instance for a path.
fn resolve_path(&self, path: &[&str]) -> EvalResult<'tcx, ty::Instance<'tcx>> {
self.tcx
let this = self.eval_context_ref();
this.tcx
.crates()
.iter()
.find(|&&krate| self.tcx.original_crate_name(krate) == path[0])
.find(|&&krate| this.tcx.original_crate_name(krate) == path[0])
.and_then(|krate| {
let krate = DefId {
krate: *krate,
index: CRATE_DEF_INDEX,
};
let mut items = self.tcx.item_children(krate);
let mut items = this.tcx.item_children(krate);
let mut path_it = path.iter().skip(1).peekable();

while let Some(segment) = path_it.next() {
for item in mem::replace(&mut items, Default::default()).iter() {
if item.ident.name == *segment {
if path_it.peek().is_none() {
return Some(ty::Instance::mono(self.tcx.tcx, item.def.def_id()));
return Some(ty::Instance::mono(this.tcx.tcx, item.def.def_id()));
}

items = self.tcx.item_children(item.def.def_id());
items = this.tcx.item_children(item.def.def_id());
break;
}
}
Expand All @@ -79,15 +42,18 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
})
}

/// Visit the memory covered by `place`, sensitive to freezing: The 3rd parameter
/// will be true if this is frozen, false if this is in an `UnsafeCell`.
fn visit_freeze_sensitive(
&self,
place: MPlaceTy<'tcx, Borrow>,
size: Size,
mut action: impl FnMut(Pointer<Borrow>, Size, bool) -> EvalResult<'tcx>,
) -> EvalResult<'tcx> {
let this = self.eval_context_ref();
trace!("visit_frozen(place={:?}, size={:?})", *place, size);
debug_assert_eq!(size,
self.size_and_align_of_mplace(place)?
this.size_and_align_of_mplace(place)?
.map(|(size, _)| size)
.unwrap_or_else(|| place.layout.size)
);
Expand All @@ -106,8 +72,8 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
}
// We assume that we are given the fields in increasing offset order,
// and nothing else changes.
let unsafe_cell_offset = unsafe_cell_ptr.get_ptr_offset(self);
let end_offset = end_ptr.get_ptr_offset(self);
let unsafe_cell_offset = unsafe_cell_ptr.get_ptr_offset(this);
let end_offset = end_ptr.get_ptr_offset(this);
assert!(unsafe_cell_offset >= end_offset);
let frozen_size = unsafe_cell_offset - end_offset;
// Everything between the end_ptr and this `UnsafeCell` is frozen.
Expand All @@ -119,18 +85,18 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
action(unsafe_cell_ptr.to_ptr()?, unsafe_cell_size, /*frozen*/false)?;
}
// Update end end_ptr.
end_ptr = unsafe_cell_ptr.ptr_wrapping_offset(unsafe_cell_size, self);
end_ptr = unsafe_cell_ptr.ptr_wrapping_offset(unsafe_cell_size, this);
// Done
Ok(())
};
// Run a visitor
{
let mut visitor = UnsafeCellVisitor {
ecx: self,
ecx: this,
unsafe_cell_action: |place| {
trace!("unsafe_cell_action on {:?}", place.ptr);
// We need a size to go on.
let unsafe_cell_size = self.size_and_align_of_mplace(place)?
let unsafe_cell_size = this.size_and_align_of_mplace(place)?
.map(|(size, _)| size)
// for extern types, just cover what we can
.unwrap_or_else(|| place.layout.size);
Expand All @@ -146,7 +112,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
}
// The part between the end_ptr and the end of the place is also frozen.
// So pretend there is a 0-sized `UnsafeCell` at the end.
unsafe_cell_action(place.ptr.ptr_wrapping_offset(size, self), Size::ZERO)?;
unsafe_cell_action(place.ptr.ptr_wrapping_offset(size, this), Size::ZERO)?;
// Done!
return Ok(());

Expand Down
Loading