Remove type_size and type_align calls

This commit is contained in:
Oliver Schneider 2017-12-06 15:03:24 +01:00
parent dd630a2a26
commit eccf680b5d
4 changed files with 30 additions and 48 deletions

View file

@ -1,4 +1,5 @@
use rustc::ty::{self, Ty};
use rustc::ty::layout::LayoutOf;
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
use rustc::mir;
use syntax::attr;
@ -261,7 +262,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
let result = {
let name_ptr = args[0].into_ptr(&mut self.memory)?.to_ptr()?;
let name = self.memory.read_c_str(name_ptr)?;
match self.machine_data.env_vars.get(name) {
match self.machine.env_vars.get(name) {
Some(&var) => PrimVal::Ptr(var),
None => PrimVal::Bytes(0),
}
@ -276,7 +277,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
if !name_ptr.is_null()? {
let name = self.memory.read_c_str(name_ptr.to_ptr()?)?;
if !name.is_empty() && !name.contains(&b'=') {
success = Some(self.machine_data.env_vars.remove(name));
success = Some(self.machine.env_vars.remove(name));
}
}
}
@ -313,7 +314,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
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(
if let Some(var) = self.machine.env_vars.insert(
name.to_owned(),
value_copy,
)
@ -416,9 +417,9 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
};
// 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, ty::PlacePreference::NoPreference)
let key_type = args[0].ty.builtin_deref(true, ty::LvaluePreference::NoPreference)
.ok_or(EvalErrorKind::AbiViolation("Wrong signature used for pthread_key_create: First argument must be a raw pointer.".to_owned()))?.ty;
let key_size = self.type_layout(key_type)?.size;
let key_size = self.layout_of(key_type)?.size;
// Create key and write it into the memory where key_ptr wants it
let key = self.memory.create_tls_key(dtor) as u128;

View file

@ -1,6 +1,7 @@
use rustc::mir::interpret::{Pointer, EvalResult, PrimVal, EvalContext};
use rustc::ty::Ty;
use rustc::ty::layout::LayoutOf;
pub trait EvalContextExt<'tcx> {
fn wrapping_pointer_offset(
@ -26,9 +27,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
offset: i64,
) -> EvalResult<'tcx, Pointer> {
// FIXME: assuming here that type size is < i64::max_value()
let pointee_size = self.type_size(pointee_ty)?.expect(
"cannot offset a pointer to an unsized type",
) as i64;
let pointee_size = self.layout_of(pointee_ty)?.size.bytes() as i64;
let offset = offset.overflowing_mul(pointee_size).0;
ptr.wrapping_signed_offset(offset, self)
}
@ -53,9 +52,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
};
}
// FIXME: assuming here that type size is < i64::max_value()
let pointee_size = self.type_size(pointee_ty)?.expect(
"cannot offset a pointer to an unsized type",
) as i64;
let pointee_size = self.layout_of(pointee_ty)?.size.bytes() as i64;
return if let Some(offset) = offset.checked_mul(pointee_size) {
let ptr = ptr.signed_offset(offset, self)?;
// Do not do bounds-checking for integers; they can never alias a normal pointer anyway.

View file

@ -1,6 +1,6 @@
use rustc::mir;
use rustc::traits::Reveal;
use rustc::ty::layout::TyLayout;
use rustc::ty::layout::{TyLayout, LayoutOf};
use rustc::ty;
use rustc::mir::interpret::{EvalResult, Place, PlaceExtra, PrimVal, PrimValKind, Value, Pointer,
@ -204,12 +204,13 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
"copy" |
"copy_nonoverlapping" => {
let elem_ty = substs.type_at(0);
let elem_size = self.type_size(elem_ty)?.expect("cannot copy unsized value");
let elem_layout = self.layout_of(elem_ty)?;
let elem_size = elem_layout.size.bytes();
let count = self.value_to_primval(args[2])?.to_u64()?;
if count * elem_size != 0 {
// TODO: We do not even validate alignment for the 0-bytes case. libstd relies on this in vec::IntoIter::next.
// Also see the write_bytes intrinsic.
let elem_align = self.type_align(elem_ty)?;
let elem_align = elem_layout.align.abi();
let src = args[0].into_ptr(&self.memory)?;
let dest = args[1].into_ptr(&self.memory)?;
self.memory.copy(
@ -308,7 +309,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
"likely" | "unlikely" | "forget" => {}
"init" => {
let size = self.type_size(dest_layout.ty)?.expect("cannot zero unsized value");
let size = dest_layout.size.bytes();
let init = |this: &mut Self, val: Value| {
let zero_val = match val {
Value::ByRef(PtrAndAlign { ptr, .. }) => {
@ -321,7 +322,8 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
match this.ty_to_primval_kind(dest_layout.ty) {
Ok(_) => Value::ByVal(PrimVal::Bytes(0)),
Err(_) => {
let ptr = this.alloc_ptr_with_substs(dest_layout.ty, substs)?;
// FIXME(oli-obk): pass TyLayout to alloc_ptr instead of Ty
let ptr = this.alloc_ptr(dest_layout.ty)?;
let ptr = Pointer::from(PrimVal::Ptr(ptr));
this.memory.write_repeat(ptr, 0, size)?;
Value::by_ref(ptr)
@ -349,14 +351,14 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
"min_align_of" => {
let elem_ty = substs.type_at(0);
let elem_align = self.type_align(elem_ty)?;
let elem_align = self.layout_of(elem_ty)?.align.abi();
let align_val = PrimVal::from_u128(elem_align as u128);
self.write_primval(dest, align_val, dest_layout.ty)?;
}
"pref_align_of" => {
let ty = substs.type_at(0);
let layout = self.type_layout(ty)?;
let layout = self.layout_of(ty)?;
let align = layout.align.pref();
let align_val = PrimVal::from_u128(align as u128);
self.write_primval(dest, align_val, dest_layout.ty)?;
@ -492,9 +494,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
"size_of" => {
let ty = substs.type_at(0);
let size = self.type_size(ty)?.expect(
"size_of intrinsic called on unsized value",
) as u128;
let size = self.layout_of(ty)?.size.bytes().into();
self.write_primval(dest, PrimVal::from_u128(size), dest_layout.ty)?;
}
@ -544,9 +544,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
}
"unchecked_shl" => {
let bits = self.type_size(dest_layout.ty)?.expect(
"intrinsic can't be called on unsized type",
) as u128 * 8;
let bits = dest_layout.size.bytes() as u128 * 8;
let rhs = self.value_to_primval(args[1])?
.to_bytes()?;
if rhs >= bits {
@ -564,9 +562,7 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
}
"unchecked_shr" => {
let bits = self.type_size(dest_layout.ty)?.expect(
"intrinsic can't be called on unsized type",
) as u128 * 8;
let bits = dest_layout.size.bytes() as u128 * 8;
let rhs = self.value_to_primval(args[1])?
.to_bytes()?;
if rhs >= bits {
@ -636,18 +632,15 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
"write_bytes" => {
let ty = substs.type_at(0);
let ty_align = self.type_align(ty)?;
let ty_layout = self.layout_of(ty)?;
let val_byte = self.value_to_primval(args[1])?.to_u128()? as u8;
let size = self.type_size(ty)?.expect(
"write_bytes() type must be sized",
);
let ptr = args[0].into_ptr(&self.memory)?;
let count = self.value_to_primval(args[2])?.to_u64()?;
if count > 0 {
// HashMap relies on write_bytes on a NULL ptr with count == 0 to work
// TODO: Should we, at least, validate the alignment? (Also see the copy intrinsic)
self.memory.check_align(ptr, ty_align, Some(AccessKind::Write))?;
self.memory.write_repeat(ptr, val_byte, size * count)?;
self.memory.check_align(ptr, ty_layout.align.abi(), Some(AccessKind::Write))?;
self.memory.write_repeat(ptr, val_byte, ty_layout.size.bytes() * count)?;
}
}

View file

@ -11,7 +11,7 @@ extern crate rustc;
extern crate syntax;
use rustc::ty::{self, TyCtxt};
use rustc::ty::layout::TyLayout;
use rustc::ty::layout::{TyLayout, LayoutOf};
use rustc::hir::def_id::DefId;
use rustc::mir;
use rustc::traits;
@ -141,7 +141,7 @@ pub fn eval_main<'a, 'tcx: 'a>(
Ok(())
}
let mut ecx = EvalContext::new(tcx, limits, Default::default(), Default::default());
let mut ecx = EvalContext::new(tcx, ty::ParamEnv::empty(traits::Reveal::All), limits, Default::default(), Default::default());
match run_main(&mut ecx, main_id, start_wrapper) {
Ok(()) => {
let leaks = ecx.memory().leak_report();
@ -155,9 +155,8 @@ pub fn eval_main<'a, 'tcx: 'a>(
}
}
pub struct Evaluator;
#[derive(Default)]
pub struct EvaluatorData {
pub struct Evaluator {
/// Environment variables set by `setenv`
/// Miri does not expose env vars from the host to the emulated program
pub(crate) env_vars: HashMap<Vec<u8>, MemoryPointer>,
@ -181,16 +180,9 @@ pub struct MemoryData<'tcx> {
}
impl<'tcx> Machine<'tcx> for Evaluator {
type Data = EvaluatorData;
type MemoryData = MemoryData<'tcx>;
type MemoryKinds = memory::MemoryKind;
fn param_env<'a>(
_: &EvalContext<'a, 'tcx, Self>,
) -> ty::ParamEnv<'tcx> {
ty::ParamEnv::empty(traits::Reveal::All)
}
/// Returns Ok() when the function was handled, fail otherwise
fn eval_fn_call<'a>(
ecx: &mut EvalContext<'a, 'tcx, Self>,
@ -239,8 +231,7 @@ impl<'tcx> Machine<'tcx> for Evaluator {
ty: ty::Ty<'tcx>,
dest: Place,
) -> EvalResult<'tcx> {
let size = ecx.type_size(ty)?.expect("box only works with sized types");
let align = ecx.type_align(ty)?;
let layout = ecx.layout_of(ty)?;
// Call the `exchange_malloc` lang item
let malloc = ecx.tcx.lang_items().exchange_malloc_fn().unwrap();
@ -264,7 +255,7 @@ impl<'tcx> Machine<'tcx> for Evaluator {
let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?;
ecx.write_value(
ValTy {
value: Value::ByVal(PrimVal::Bytes(size as u128)),
value: Value::ByVal(PrimVal::Bytes(layout.size.bytes().into())),
ty: usize,
},
dest,
@ -274,7 +265,7 @@ impl<'tcx> Machine<'tcx> for Evaluator {
let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?;
ecx.write_value(
ValTy {
value: Value::ByVal(PrimVal::Bytes(align as u128)),
value: Value::ByVal(PrimVal::Bytes(layout.align.abi().into())),
ty: usize,
},
dest,