commit
8127440014
@ -199,7 +199,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
|
||||
self.write_null(dest, dest_ty)?;
|
||||
} else {
|
||||
let align = self.tcx.data_layout.pointer_align;
|
||||
let ptr = self.memory.allocate(Size::from_bytes(size), align, Some(MemoryKind::C.into()))?;
|
||||
let ptr = self.memory.allocate(Size::from_bytes(size), align, MemoryKind::C.into())?;
|
||||
self.write_scalar(dest, Scalar::Ptr(ptr), dest_ty)?;
|
||||
}
|
||||
}
|
||||
@ -268,7 +268,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
|
||||
)?;
|
||||
let mut args = self.frame().mir.args_iter();
|
||||
|
||||
let arg_local = args.next().ok_or(
|
||||
let arg_local = args.next().ok_or_else(||
|
||||
EvalErrorKind::AbiViolation(
|
||||
"Argument to __rust_maybe_catch_panic does not take enough arguments."
|
||||
.to_owned(),
|
||||
@ -395,7 +395,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
|
||||
let value_copy = self.memory.allocate(
|
||||
Size::from_bytes((value.len() + 1) as u64),
|
||||
Align::from_bytes(1, 1).unwrap(),
|
||||
Some(MemoryKind::Env.into()),
|
||||
MemoryKind::Env.into(),
|
||||
)?;
|
||||
self.memory.write_bytes(value_copy.into(), &value)?;
|
||||
let trailing_zero_ptr = value_copy.offset(Size::from_bytes(value.len() as u64), &self)?.into();
|
||||
@ -504,7 +504,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
|
||||
|
||||
// Figure out how large a pthread TLS key actually is. This is libc::pthread_key_t.
|
||||
let key_type = args[0].ty.builtin_deref(true)
|
||||
.ok_or(EvalErrorKind::AbiViolation("Wrong signature used for pthread_key_create: First argument must be a raw pointer.".to_owned()))?.ty;
|
||||
.ok_or_else(|| EvalErrorKind::AbiViolation("Wrong signature used for pthread_key_create: First argument must be a raw pointer.".to_owned()))?.ty;
|
||||
let key_size = self.layout_of(key_type)?.size;
|
||||
|
||||
// Create key and write it into the memory where key_ptr wants it
|
||||
@ -656,7 +656,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
|
||||
}
|
||||
let ptr = self.memory.allocate(Size::from_bytes(size),
|
||||
Align::from_bytes(align, align).unwrap(),
|
||||
Some(MemoryKind::Rust.into()))?;
|
||||
MemoryKind::Rust.into())?;
|
||||
self.write_scalar(dest, Scalar::Ptr(ptr), dest_ty)?;
|
||||
}
|
||||
"alloc::alloc::::__rust_alloc_zeroed" => {
|
||||
@ -670,7 +670,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
|
||||
}
|
||||
let ptr = self.memory.allocate(Size::from_bytes(size),
|
||||
Align::from_bytes(align, align).unwrap(),
|
||||
Some(MemoryKind::Rust.into()))?;
|
||||
MemoryKind::Rust.into())?;
|
||||
self.memory.write_repeat(ptr.into(), 0, Size::from_bytes(size))?;
|
||||
self.write_scalar(dest, Scalar::Ptr(ptr), dest_ty)?;
|
||||
}
|
||||
@ -747,7 +747,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
|
||||
// current frame.
|
||||
self.dump_local(dest);
|
||||
self.goto_block(dest_block);
|
||||
return Ok(());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_null(&mut self, dest: Place, dest_ty: Ty<'tcx>) -> EvalResult<'tcx> {
|
||||
|
@ -75,7 +75,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
|
||||
}
|
||||
// FIXME: assuming here that type size is < i64::max_value()
|
||||
let pointee_size = self.layout_of(pointee_ty)?.size.bytes() as i64;
|
||||
return if let Some(offset) = offset.checked_mul(pointee_size) {
|
||||
if let Some(offset) = offset.checked_mul(pointee_size) {
|
||||
let ptr = ptr.ptr_signed_offset(offset, self)?;
|
||||
// Do not do bounds-checking for integers; they can never alias a normal pointer anyway.
|
||||
if let Scalar::Ptr(ptr) = ptr {
|
||||
@ -87,7 +87,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
|
||||
Ok(ptr)
|
||||
} else {
|
||||
err!(Overflow(mir::BinOp::Mul))
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn value_to_isize(
|
||||
|
26
src/lib.rs
26
src/lib.rs
@ -5,6 +5,8 @@
|
||||
inclusive_range_methods,
|
||||
)]
|
||||
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless))]
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
@ -24,7 +26,6 @@ use rustc::ty::layout::{TyLayout, LayoutOf, Size};
|
||||
use rustc::ty::subst::Subst;
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::mir;
|
||||
use rustc::middle::const_val;
|
||||
|
||||
use syntax::ast::Mutability;
|
||||
use syntax::codemap::Span;
|
||||
@ -172,7 +173,7 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
|
||||
// Return value
|
||||
let size = ecx.tcx.data_layout.pointer_size;
|
||||
let align = ecx.tcx.data_layout.pointer_align;
|
||||
let ret_ptr = ecx.memory_mut().allocate(size, align, Some(MemoryKind::Stack))?;
|
||||
let ret_ptr = ecx.memory_mut().allocate(size, align, MemoryKind::Stack)?;
|
||||
cleanup_ptr = Some(ret_ptr);
|
||||
|
||||
// Push our stack frame
|
||||
@ -211,7 +212,7 @@ pub fn create_ecx<'a, 'mir: 'a, 'tcx: 'mir>(
|
||||
let foo = ecx.memory.allocate_bytes(b"foo\0");
|
||||
let ptr_size = ecx.memory.pointer_size();
|
||||
let ptr_align = ecx.tcx.data_layout.pointer_align;
|
||||
let foo_ptr = ecx.memory.allocate(ptr_size, ptr_align, None)?;
|
||||
let foo_ptr = ecx.memory.allocate(ptr_size, ptr_align, MemoryKind::Stack)?;
|
||||
ecx.memory.write_scalar(foo_ptr.into(), ptr_align, Scalar::Ptr(foo), ptr_size, false)?;
|
||||
ecx.memory.mark_static_initialized(foo_ptr.alloc_id, Mutability::Immutable)?;
|
||||
ecx.write_ptr(dest, foo_ptr.into(), ty)?;
|
||||
@ -270,10 +271,10 @@ pub fn eval_main<'a, 'tcx: 'a>(
|
||||
block.terminator().source_info.span
|
||||
};
|
||||
|
||||
let mut err = const_val::struct_error(ecx.tcx.tcx.at(span), "constant evaluation error");
|
||||
let mut err = struct_error(ecx.tcx.tcx.at(span), "constant evaluation error");
|
||||
let (frames, span) = ecx.generate_stacktrace(None);
|
||||
err.span_label(span, e.to_string());
|
||||
for const_val::FrameInfo { span, location, .. } in frames {
|
||||
for FrameInfo { span, location, .. } in frames {
|
||||
err.span_note(span, &format!("inside call to `{}`", location));
|
||||
}
|
||||
err.emit();
|
||||
@ -405,7 +406,7 @@ impl<'mir, 'tcx: 'mir> Machine<'mir, 'tcx> for Evaluator<'tcx> {
|
||||
let ptr = ecx.memory.allocate(
|
||||
layout.size,
|
||||
layout.align,
|
||||
None,
|
||||
MemoryKind::Stack,
|
||||
)?;
|
||||
|
||||
// Step 4: Cache allocation id for recursive statics
|
||||
@ -428,14 +429,11 @@ impl<'mir, 'tcx: 'mir> Machine<'mir, 'tcx> for Evaluator<'tcx> {
|
||||
let frame = ecx.frame_mut();
|
||||
let bb = &frame.mir.basic_blocks()[frame.block];
|
||||
if bb.statements.len() == frame.stmt && !bb.is_cleanup {
|
||||
match bb.terminator().kind {
|
||||
::rustc::mir::TerminatorKind::Return => {
|
||||
for (local, _local_decl) in mir.local_decls.iter_enumerated().skip(1) {
|
||||
// Don't deallocate locals, because the return value might reference them
|
||||
frame.storage_dead(local);
|
||||
}
|
||||
if let ::rustc::mir::TerminatorKind::Return = bb.terminator().kind {
|
||||
for (local, _local_decl) in mir.local_decls.iter_enumerated().skip(1) {
|
||||
// Don't deallocate locals, because the return value might reference them
|
||||
frame.storage_dead(local);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -479,7 +477,7 @@ impl<'mir, 'tcx: 'mir> Machine<'mir, 'tcx> for Evaluator<'tcx> {
|
||||
value: Value::Scalar(Scalar::from_u128(match layout.size.bytes() {
|
||||
0 => 1 as u128,
|
||||
size => size as u128,
|
||||
}.into())),
|
||||
})),
|
||||
ty: usize,
|
||||
},
|
||||
dest,
|
||||
|
10
src/locks.rs
10
src/locks.rs
@ -241,11 +241,9 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> MemoryExt<'tcx> for Memory<'a, 'mir, 'tcx, Evalu
|
||||
// All is well
|
||||
continue 'locks;
|
||||
}
|
||||
} else {
|
||||
if !is_our_lock {
|
||||
// All is well.
|
||||
continue 'locks;
|
||||
}
|
||||
} else if !is_our_lock {
|
||||
// All is well.
|
||||
continue 'locks;
|
||||
}
|
||||
// If we get here, releasing this is an error except for NoLock.
|
||||
if lock.active != NoLock {
|
||||
@ -377,7 +375,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> MemoryExt<'tcx> for Memory<'a, 'mir, 'tcx, Evalu
|
||||
}
|
||||
// Clean up the map
|
||||
alloc_locks.retain(|lock| match lock.active {
|
||||
NoLock => lock.suspended.len() > 0,
|
||||
NoLock => !lock.suspended.is_empty(),
|
||||
_ => true,
|
||||
});
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super:
|
||||
.expect("Offset called on non-ptr type")
|
||||
.ty;
|
||||
let ptr = self.pointer_offset(
|
||||
left.into(),
|
||||
left,
|
||||
pointee_ty,
|
||||
right.to_bits(self.memory.pointer_size())? as i64,
|
||||
)?;
|
||||
|
@ -19,7 +19,7 @@ pub struct RangeMap<T> {
|
||||
// At the same time the `end` is irrelevant for the sorting and range searching, but used for the check.
|
||||
// This kind of search breaks, if `end < start`, so don't do that!
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
|
||||
struct Range {
|
||||
pub struct Range {
|
||||
start: u64,
|
||||
end: u64, // Invariant: end > start
|
||||
}
|
||||
@ -189,7 +189,7 @@ impl<T> RangeMap<T> {
|
||||
F: FnMut(&T) -> bool,
|
||||
{
|
||||
let mut remove = Vec::new();
|
||||
for (range, data) in self.map.iter() {
|
||||
for (range, data) in &self.map {
|
||||
if !f(data) {
|
||||
remove.push(*range);
|
||||
}
|
||||
|
20
src/tls.rs
20
src/tls.rs
@ -30,38 +30,38 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> MemoryExt<'tcx> for Memory<'a, 'mir, 'tcx, Evalu
|
||||
},
|
||||
);
|
||||
trace!("New TLS key allocated: {} with dtor {:?}", new_key, dtor);
|
||||
return new_key;
|
||||
new_key
|
||||
}
|
||||
|
||||
fn delete_tls_key(&mut self, key: TlsKey) -> EvalResult<'tcx> {
|
||||
return match self.data.thread_local.remove(&key) {
|
||||
match self.data.thread_local.remove(&key) {
|
||||
Some(_) => {
|
||||
trace!("TLS key {} removed", key);
|
||||
Ok(())
|
||||
}
|
||||
None => err!(TlsOutOfBounds),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn load_tls(&mut self, key: TlsKey) -> EvalResult<'tcx, Scalar> {
|
||||
return match self.data.thread_local.get(&key) {
|
||||
match self.data.thread_local.get(&key) {
|
||||
Some(&TlsEntry { data, .. }) => {
|
||||
trace!("TLS key {} loaded: {:?}", key, data);
|
||||
Ok(data)
|
||||
}
|
||||
None => err!(TlsOutOfBounds),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn store_tls(&mut self, key: TlsKey, new_data: Scalar) -> EvalResult<'tcx> {
|
||||
return match self.data.thread_local.get_mut(&key) {
|
||||
match self.data.thread_local.get_mut(&key) {
|
||||
Some(&mut TlsEntry { ref mut data, .. }) => {
|
||||
trace!("TLS key {} stored: {:?}", key, new_data);
|
||||
*data = new_data;
|
||||
Ok(())
|
||||
}
|
||||
None => err!(TlsOutOfBounds),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a dtor, its argument and its index, if one is supposed to run
|
||||
@ -104,7 +104,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> MemoryExt<'tcx> for Memory<'a, 'mir, 'tcx, Evalu
|
||||
}
|
||||
}
|
||||
}
|
||||
return Ok(None);
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
@ -124,8 +124,8 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
|
||||
Place::undef(),
|
||||
StackPopCleanup::None,
|
||||
)?;
|
||||
let arg_local = self.frame().mir.args_iter().next().ok_or(
|
||||
EvalErrorKind::AbiViolation("TLS dtor does not take enough arguments.".to_owned()),
|
||||
let arg_local = self.frame().mir.args_iter().next().ok_or_else(
|
||||
|| EvalErrorKind::AbiViolation("TLS dtor does not take enough arguments.".to_owned()),
|
||||
)?;
|
||||
let dest = self.eval_place(&mir::Place::Local(arg_local))?;
|
||||
let ty = self.tcx.mk_mut_ptr(self.tcx.types.u8);
|
||||
|
@ -8,7 +8,7 @@ use rustc::ty::subst::{Substs, Subst};
|
||||
use rustc::traits::{self, TraitEngine};
|
||||
use rustc::infer::InferCtxt;
|
||||
use rustc::middle::region;
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc::mir::interpret::{ConstValue};
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc_mir::interpret::HasMemory;
|
||||
|
||||
@ -135,10 +135,10 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
|
||||
}
|
||||
|
||||
fn abstract_place(&self, place: &mir::Place<'tcx>) -> EvalResult<'tcx, AbsPlace<'tcx>> {
|
||||
Ok(match place {
|
||||
&mir::Place::Local(l) => AbsPlace::Local(l),
|
||||
&mir::Place::Static(ref s) => AbsPlace::Static(s.def_id),
|
||||
&mir::Place::Projection(ref p) =>
|
||||
Ok(match *place {
|
||||
mir::Place::Local(l) => AbsPlace::Local(l),
|
||||
mir::Place::Static(ref s) => AbsPlace::Static(s.def_id),
|
||||
mir::Place::Projection(ref p) =>
|
||||
AbsPlace::Projection(Box::new(self.abstract_place_projection(&*p)?)),
|
||||
})
|
||||
}
|
||||
@ -378,11 +378,8 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
|
||||
mut layout: ty::layout::TyLayout<'tcx>,
|
||||
i: usize,
|
||||
) -> EvalResult<'tcx, Ty<'tcx>> {
|
||||
match base {
|
||||
Place::Ptr { extra: PlaceExtra::DowncastVariant(variant_index), .. } => {
|
||||
layout = layout.for_variant(&self, variant_index);
|
||||
}
|
||||
_ => {}
|
||||
if let Place::Ptr { extra: PlaceExtra::DowncastVariant(variant_index), .. } = base {
|
||||
layout = layout.for_variant(&self, variant_index);
|
||||
}
|
||||
let tcx = self.tcx.tcx;
|
||||
Ok(match layout.ty.sty {
|
||||
@ -667,12 +664,11 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
|
||||
// Inner lifetimes *outlive* outer ones, so only if we have no lifetime restriction yet,
|
||||
// we record the region of this borrow to the context.
|
||||
if query.re == None {
|
||||
match *region {
|
||||
ReScope(scope) => query.re = Some(scope),
|
||||
// It is possible for us to encounter erased lifetimes here because the lifetimes in
|
||||
// this functions' Subst will be erased.
|
||||
_ => {}
|
||||
if let ReScope(scope) = *region {
|
||||
query.re = Some(scope);
|
||||
}
|
||||
// It is possible for us to encounter erased lifetimes here because the lifetimes in
|
||||
// this functions' Subst will be erased.
|
||||
}
|
||||
self.validate_ptr(val, query.place.0, pointee_ty, query.re, query.mutbl, mode)?;
|
||||
}
|
||||
@ -719,14 +715,14 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
|
||||
}
|
||||
TyArray(elem_ty, len) => {
|
||||
let len = match len.val {
|
||||
ConstVal::Unevaluated(def_id, substs) => {
|
||||
ConstValue::Unevaluated(def_id, substs) => {
|
||||
self.tcx.const_eval(self.tcx.param_env(def_id).and(GlobalId {
|
||||
instance: Instance::new(def_id, substs),
|
||||
promoted: None,
|
||||
}))
|
||||
.map_err(|_err|EvalErrorKind::MachineError("<already reported>".to_string()))?
|
||||
}
|
||||
ConstVal::Value(_) => len,
|
||||
_ => len,
|
||||
};
|
||||
let len = len.unwrap_usize(self.tcx.tcx);
|
||||
for i in 0..len {
|
||||
@ -772,7 +768,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, '
|
||||
let variant_idx = self.read_discriminant_as_variant_index(query.place.1, query.ty)?;
|
||||
let variant = &adt.variants[variant_idx];
|
||||
|
||||
if variant.fields.len() > 0 {
|
||||
if !variant.fields.is_empty() {
|
||||
// Downcast to this variant, if needed
|
||||
let place = if adt.is_enum() {
|
||||
(
|
||||
|
Loading…
x
Reference in New Issue
Block a user