Merge pull request #510 from solson/rustup
rustup: value -> immediate, by-value HasLayout, edition 2018
This commit is contained in:
commit
0e9e0f2d82
@ -9,6 +9,7 @@ repository = "https://github.com/solson/miri"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
default-run = "miri"
|
default-run = "miri"
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
test = true # we have unit tests
|
test = true # we have unit tests
|
||||||
|
@ -1 +1 @@
|
|||||||
nightly-2018-11-04
|
nightly-2018-11-05
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#![feature(rustc_private)]
|
#![feature(rustc_private, extern_crate_item_prelude)]
|
||||||
extern crate miri;
|
extern crate miri;
|
||||||
extern crate getopts;
|
extern crate getopts;
|
||||||
extern crate rustc;
|
extern crate rustc;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#![feature(rustc_private)]
|
#![feature(rustc_private, extern_crate_item_prelude)]
|
||||||
|
|
||||||
extern crate getopts;
|
extern crate getopts;
|
||||||
extern crate miri;
|
extern crate miri;
|
||||||
|
@ -120,7 +120,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
|
|||||||
|
|
||||||
match &link_name[..] {
|
match &link_name[..] {
|
||||||
"malloc" => {
|
"malloc" => {
|
||||||
let size = self.read_scalar(args[0])?.to_usize(&self)?;
|
let size = self.read_scalar(args[0])?.to_usize(self)?;
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
self.write_null(dest)?;
|
self.write_null(dest)?;
|
||||||
} else {
|
} else {
|
||||||
@ -132,7 +132,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
|
|||||||
|
|
||||||
"free" => {
|
"free" => {
|
||||||
let ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation, no tag
|
let ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation, no tag
|
||||||
if !ptr.is_null_ptr(&self) {
|
if !ptr.is_null_ptr(self) {
|
||||||
self.memory_mut().deallocate(
|
self.memory_mut().deallocate(
|
||||||
ptr.to_ptr()?.with_default_tag(),
|
ptr.to_ptr()?.with_default_tag(),
|
||||||
None,
|
None,
|
||||||
@ -142,8 +142,8 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
"__rust_alloc" => {
|
"__rust_alloc" => {
|
||||||
let size = self.read_scalar(args[0])?.to_usize(&self)?;
|
let size = self.read_scalar(args[0])?.to_usize(self)?;
|
||||||
let align = self.read_scalar(args[1])?.to_usize(&self)?;
|
let align = self.read_scalar(args[1])?.to_usize(self)?;
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
return err!(HeapAllocZeroBytes);
|
return err!(HeapAllocZeroBytes);
|
||||||
}
|
}
|
||||||
@ -160,8 +160,8 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
|
|||||||
self.write_scalar(Scalar::Ptr(ptr), dest)?;
|
self.write_scalar(Scalar::Ptr(ptr), dest)?;
|
||||||
}
|
}
|
||||||
"__rust_alloc_zeroed" => {
|
"__rust_alloc_zeroed" => {
|
||||||
let size = self.read_scalar(args[0])?.to_usize(&self)?;
|
let size = self.read_scalar(args[0])?.to_usize(self)?;
|
||||||
let align = self.read_scalar(args[1])?.to_usize(&self)?;
|
let align = self.read_scalar(args[1])?.to_usize(self)?;
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
return err!(HeapAllocZeroBytes);
|
return err!(HeapAllocZeroBytes);
|
||||||
}
|
}
|
||||||
@ -180,8 +180,8 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
|
|||||||
}
|
}
|
||||||
"__rust_dealloc" => {
|
"__rust_dealloc" => {
|
||||||
let ptr = self.read_scalar(args[0])?.to_ptr()?.erase_tag(); // raw ptr operation, no tag
|
let ptr = self.read_scalar(args[0])?.to_ptr()?.erase_tag(); // raw ptr operation, no tag
|
||||||
let old_size = self.read_scalar(args[1])?.to_usize(&self)?;
|
let old_size = self.read_scalar(args[1])?.to_usize(self)?;
|
||||||
let align = self.read_scalar(args[2])?.to_usize(&self)?;
|
let align = self.read_scalar(args[2])?.to_usize(self)?;
|
||||||
if old_size == 0 {
|
if old_size == 0 {
|
||||||
return err!(HeapAllocZeroBytes);
|
return err!(HeapAllocZeroBytes);
|
||||||
}
|
}
|
||||||
@ -196,9 +196,9 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
|
|||||||
}
|
}
|
||||||
"__rust_realloc" => {
|
"__rust_realloc" => {
|
||||||
let ptr = self.read_scalar(args[0])?.to_ptr()?.erase_tag(); // raw ptr operation, no tag
|
let ptr = self.read_scalar(args[0])?.to_ptr()?.erase_tag(); // raw ptr operation, no tag
|
||||||
let old_size = self.read_scalar(args[1])?.to_usize(&self)?;
|
let old_size = self.read_scalar(args[1])?.to_usize(self)?;
|
||||||
let align = self.read_scalar(args[2])?.to_usize(&self)?;
|
let align = self.read_scalar(args[2])?.to_usize(self)?;
|
||||||
let new_size = self.read_scalar(args[3])?.to_usize(&self)?;
|
let new_size = self.read_scalar(args[3])?.to_usize(self)?;
|
||||||
if old_size == 0 || new_size == 0 {
|
if old_size == 0 || new_size == 0 {
|
||||||
return err!(HeapAllocZeroBytes);
|
return err!(HeapAllocZeroBytes);
|
||||||
}
|
}
|
||||||
@ -222,7 +222,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
|
|||||||
//
|
//
|
||||||
// libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)
|
// libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK)
|
||||||
// is called if a `HashMap` is created the regular way.
|
// is called if a `HashMap` is created the regular way.
|
||||||
match self.read_scalar(args[0])?.to_usize(&self)? {
|
match self.read_scalar(args[0])?.to_usize(self)? {
|
||||||
318 | 511 => {
|
318 | 511 => {
|
||||||
return err!(Unimplemented(
|
return err!(Unimplemented(
|
||||||
"miri does not support random number generators".to_owned(),
|
"miri does not support random number generators".to_owned(),
|
||||||
@ -260,7 +260,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
|
|||||||
// Now we make a function call. TODO: Consider making this re-usable? EvalContext::step does sth. similar for the TLS dtors,
|
// Now we make a function call. TODO: Consider making this re-usable? EvalContext::step does sth. similar for the TLS dtors,
|
||||||
// and of course eval_main.
|
// and of course eval_main.
|
||||||
let mir = self.load_mir(f_instance.def)?;
|
let mir = self.load_mir(f_instance.def)?;
|
||||||
let ret_place = MPlaceTy::dangling(self.layout_of(self.tcx.mk_unit())?, &self).into();
|
let ret_place = MPlaceTy::dangling(self.layout_of(self.tcx.mk_unit())?, self).into();
|
||||||
self.push_stack_frame(
|
self.push_stack_frame(
|
||||||
f_instance,
|
f_instance,
|
||||||
mir.span,
|
mir.span,
|
||||||
@ -294,7 +294,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
|
|||||||
"memcmp" => {
|
"memcmp" => {
|
||||||
let left = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation
|
let left = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation
|
||||||
let right = self.read_scalar(args[1])?.not_undef()?.erase_tag(); // raw ptr operation
|
let right = self.read_scalar(args[1])?.not_undef()?.erase_tag(); // raw ptr operation
|
||||||
let n = Size::from_bytes(self.read_scalar(args[2])?.to_usize(&self)?);
|
let n = Size::from_bytes(self.read_scalar(args[2])?.to_usize(self)?);
|
||||||
|
|
||||||
let result = {
|
let result = {
|
||||||
let left_bytes = self.memory().read_bytes(left.with_default_tag(), n)?;
|
let left_bytes = self.memory().read_bytes(left.with_default_tag(), n)?;
|
||||||
@ -318,11 +318,11 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
|
|||||||
let ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation
|
let ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation
|
||||||
let ptr = ptr.with_default_tag();
|
let ptr = ptr.with_default_tag();
|
||||||
let val = self.read_scalar(args[1])?.to_bytes()? as u8;
|
let val = self.read_scalar(args[1])?.to_bytes()? as u8;
|
||||||
let num = self.read_scalar(args[2])?.to_usize(&self)?;
|
let num = self.read_scalar(args[2])?.to_usize(self)?;
|
||||||
if let Some(idx) = self.memory().read_bytes(ptr, Size::from_bytes(num))?
|
if let Some(idx) = self.memory().read_bytes(ptr, Size::from_bytes(num))?
|
||||||
.iter().rev().position(|&c| c == val)
|
.iter().rev().position(|&c| c == val)
|
||||||
{
|
{
|
||||||
let new_ptr = ptr.ptr_offset(Size::from_bytes(num - idx as u64 - 1), &self)?;
|
let new_ptr = ptr.ptr_offset(Size::from_bytes(num - idx as u64 - 1), self)?;
|
||||||
self.write_scalar(new_ptr, dest)?;
|
self.write_scalar(new_ptr, dest)?;
|
||||||
} else {
|
} else {
|
||||||
self.write_null(dest)?;
|
self.write_null(dest)?;
|
||||||
@ -333,12 +333,12 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
|
|||||||
let ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation
|
let ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation
|
||||||
let ptr = ptr.with_default_tag();
|
let ptr = ptr.with_default_tag();
|
||||||
let val = self.read_scalar(args[1])?.to_bytes()? as u8;
|
let val = self.read_scalar(args[1])?.to_bytes()? as u8;
|
||||||
let num = self.read_scalar(args[2])?.to_usize(&self)?;
|
let num = self.read_scalar(args[2])?.to_usize(self)?;
|
||||||
if let Some(idx) = self.memory().read_bytes(ptr, Size::from_bytes(num))?.iter().position(
|
if let Some(idx) = self.memory().read_bytes(ptr, Size::from_bytes(num))?.iter().position(
|
||||||
|&c| c == val,
|
|&c| c == val,
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
let new_ptr = ptr.ptr_offset(Size::from_bytes(idx as u64), &self)?;
|
let new_ptr = ptr.ptr_offset(Size::from_bytes(idx as u64), self)?;
|
||||||
self.write_scalar(new_ptr, dest)?;
|
self.write_scalar(new_ptr, dest)?;
|
||||||
} else {
|
} else {
|
||||||
self.write_null(dest)?;
|
self.write_null(dest)?;
|
||||||
@ -351,7 +351,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
|
|||||||
let name = self.memory().read_c_str(name_ptr.with_default_tag())?;
|
let name = self.memory().read_c_str(name_ptr.with_default_tag())?;
|
||||||
match self.machine.env_vars.get(name) {
|
match self.machine.env_vars.get(name) {
|
||||||
Some(&var) => Scalar::Ptr(var),
|
Some(&var) => Scalar::Ptr(var),
|
||||||
None => Scalar::ptr_null(*self.tcx),
|
None => Scalar::ptr_null(&*self.tcx),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.write_scalar(result, dest)?;
|
self.write_scalar(result, dest)?;
|
||||||
@ -361,7 +361,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
|
|||||||
let mut success = None;
|
let mut success = None;
|
||||||
{
|
{
|
||||||
let name_ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation
|
let name_ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation
|
||||||
if !name_ptr.is_null_ptr(&self) {
|
if !name_ptr.is_null_ptr(self) {
|
||||||
let name = self.memory().read_c_str(name_ptr.to_ptr()?
|
let name = self.memory().read_c_str(name_ptr.to_ptr()?
|
||||||
.with_default_tag())?.to_owned();
|
.with_default_tag())?.to_owned();
|
||||||
if !name.is_empty() && !name.contains(&b'=') {
|
if !name.is_empty() && !name.contains(&b'=') {
|
||||||
@ -385,7 +385,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
|
|||||||
let name_ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation
|
let name_ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag(); // raw ptr operation
|
||||||
let value_ptr = self.read_scalar(args[1])?.to_ptr()?.erase_tag(); // raw ptr operation
|
let value_ptr = self.read_scalar(args[1])?.to_ptr()?.erase_tag(); // raw ptr operation
|
||||||
let value = self.memory().read_c_str(value_ptr.with_default_tag())?;
|
let value = self.memory().read_c_str(value_ptr.with_default_tag())?;
|
||||||
if !name_ptr.is_null_ptr(&self) {
|
if !name_ptr.is_null_ptr(self) {
|
||||||
let name = self.memory().read_c_str(name_ptr.to_ptr()?.with_default_tag())?;
|
let name = self.memory().read_c_str(name_ptr.to_ptr()?.with_default_tag())?;
|
||||||
if !name.is_empty() && !name.contains(&b'=') {
|
if !name.is_empty() && !name.contains(&b'=') {
|
||||||
new = Some((name.to_owned(), value.to_owned()));
|
new = Some((name.to_owned(), value.to_owned()));
|
||||||
@ -400,7 +400,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
|
|||||||
MiriMemoryKind::Env.into(),
|
MiriMemoryKind::Env.into(),
|
||||||
)?.with_default_tag();
|
)?.with_default_tag();
|
||||||
self.memory_mut().write_bytes(value_copy.into(), &value)?;
|
self.memory_mut().write_bytes(value_copy.into(), &value)?;
|
||||||
let trailing_zero_ptr = value_copy.offset(Size::from_bytes(value.len() as u64), &self)?.into();
|
let trailing_zero_ptr = value_copy.offset(Size::from_bytes(value.len() as u64), self)?.into();
|
||||||
self.memory_mut().write_bytes(trailing_zero_ptr, &[0])?;
|
self.memory_mut().write_bytes(trailing_zero_ptr, &[0])?;
|
||||||
if let Some(var) = self.machine.env_vars.insert(
|
if let Some(var) = self.machine.env_vars.insert(
|
||||||
name.to_owned(),
|
name.to_owned(),
|
||||||
@ -510,7 +510,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
|
|||||||
let key_layout = self.layout_of(key_type)?;
|
let key_layout = self.layout_of(key_type)?;
|
||||||
|
|
||||||
// Create key and write it into the memory where key_ptr wants it
|
// Create key and write it into the memory where key_ptr wants it
|
||||||
let key = self.machine.tls.create_tls_key(dtor, *self.tcx) as u128;
|
let key = self.machine.tls.create_tls_key(dtor, &*self.tcx) as u128;
|
||||||
if key_layout.size.bits() < 128 && key >= (1u128 << key_layout.size.bits() as u128) {
|
if key_layout.size.bits() < 128 && key >= (1u128 << key_layout.size.bits() as u128) {
|
||||||
return err!(OutOfTls);
|
return err!(OutOfTls);
|
||||||
}
|
}
|
||||||
@ -555,7 +555,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
|
|||||||
}
|
}
|
||||||
"pthread_attr_getstack" => {
|
"pthread_attr_getstack" => {
|
||||||
// second argument is where we are supposed to write the stack size
|
// second argument is where we are supposed to write the stack size
|
||||||
let ptr = self.ref_to_mplace(self.read_value(args[1])?)?;
|
let ptr = self.ref_to_mplace(self.read_immediate(args[1])?)?;
|
||||||
let stackaddr = Scalar::from_int(0x80000, args[1].layout.size); // just any address
|
let stackaddr = Scalar::from_int(0x80000, args[1].layout.size); // just any address
|
||||||
self.write_scalar(stackaddr, ptr.into())?;
|
self.write_scalar(stackaddr, ptr.into())?;
|
||||||
// return 0
|
// return 0
|
||||||
@ -613,7 +613,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
|
|||||||
// This just creates a key; Windows does not natively support TLS dtors.
|
// This just creates a key; Windows does not natively support TLS dtors.
|
||||||
|
|
||||||
// Create key and return it
|
// Create key and return it
|
||||||
let key = self.machine.tls.create_tls_key(None, *self.tcx) as u128;
|
let key = self.machine.tls.create_tls_key(None, &*self.tcx) as u128;
|
||||||
|
|
||||||
// Figure out how large a TLS key actually is. This is c::DWORD.
|
// Figure out how large a TLS key actually is. This is c::DWORD.
|
||||||
if dest.layout.size.bits() < 128 && key >= (1u128 << dest.layout.size.bits() as u128) {
|
if dest.layout.size.bits() < 128 && key >= (1u128 << dest.layout.size.bits() as u128) {
|
||||||
|
@ -5,7 +5,7 @@ use rustc::ty;
|
|||||||
use rustc::mir::interpret::{EvalResult, PointerArithmetic};
|
use rustc::mir::interpret::{EvalResult, PointerArithmetic};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
PlaceTy, OpTy, Value, Scalar, ScalarMaybeUndef, Borrow,
|
PlaceTy, OpTy, Immediate, Scalar, ScalarMaybeUndef, Borrow,
|
||||||
ScalarExt, OperatorEvalContextExt
|
ScalarExt, OperatorEvalContextExt
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -38,13 +38,13 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
|
|||||||
let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..];
|
let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..];
|
||||||
match intrinsic_name {
|
match intrinsic_name {
|
||||||
"arith_offset" => {
|
"arith_offset" => {
|
||||||
let offset = self.read_scalar(args[1])?.to_isize(&self)?;
|
let offset = self.read_scalar(args[1])?.to_isize(self)?;
|
||||||
let ptr = self.read_scalar(args[0])?.not_undef()?;
|
let ptr = self.read_scalar(args[0])?.not_undef()?;
|
||||||
|
|
||||||
let pointee_ty = substs.type_at(0);
|
let pointee_ty = substs.type_at(0);
|
||||||
let pointee_size = self.layout_of(pointee_ty)?.size.bytes() as i64;
|
let pointee_size = self.layout_of(pointee_ty)?.size.bytes() as i64;
|
||||||
let offset = offset.overflowing_mul(pointee_size).0;
|
let offset = offset.overflowing_mul(pointee_size).0;
|
||||||
let result_ptr = ptr.ptr_wrapping_signed_offset(offset, &self);
|
let result_ptr = ptr.ptr_wrapping_signed_offset(offset, self);
|
||||||
self.write_scalar(result_ptr, dest)?;
|
self.write_scalar(result_ptr, dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
|
|||||||
"atomic_load_relaxed" |
|
"atomic_load_relaxed" |
|
||||||
"atomic_load_acq" |
|
"atomic_load_acq" |
|
||||||
"volatile_load" => {
|
"volatile_load" => {
|
||||||
let ptr = self.ref_to_mplace(self.read_value(args[0])?)?;
|
let ptr = self.ref_to_mplace(self.read_immediate(args[0])?)?;
|
||||||
let val = self.read_scalar(ptr.into())?; // make sure it fits into a scalar; otherwise it cannot be atomic
|
let val = self.read_scalar(ptr.into())?; // make sure it fits into a scalar; otherwise it cannot be atomic
|
||||||
self.write_scalar(val, dest)?;
|
self.write_scalar(val, dest)?;
|
||||||
}
|
}
|
||||||
@ -68,7 +68,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
|
|||||||
"atomic_store_relaxed" |
|
"atomic_store_relaxed" |
|
||||||
"atomic_store_rel" |
|
"atomic_store_rel" |
|
||||||
"volatile_store" => {
|
"volatile_store" => {
|
||||||
let ptr = self.ref_to_mplace(self.read_value(args[0])?)?;
|
let ptr = self.ref_to_mplace(self.read_immediate(args[0])?)?;
|
||||||
let val = self.read_scalar(args[1])?; // make sure it fits into a scalar; otherwise it cannot be atomic
|
let val = self.read_scalar(args[1])?; // make sure it fits into a scalar; otherwise it cannot be atomic
|
||||||
self.write_scalar(val, ptr.into())?;
|
self.write_scalar(val, ptr.into())?;
|
||||||
}
|
}
|
||||||
@ -78,7 +78,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
|
|||||||
}
|
}
|
||||||
|
|
||||||
_ if intrinsic_name.starts_with("atomic_xchg") => {
|
_ if intrinsic_name.starts_with("atomic_xchg") => {
|
||||||
let ptr = self.ref_to_mplace(self.read_value(args[0])?)?;
|
let ptr = self.ref_to_mplace(self.read_immediate(args[0])?)?;
|
||||||
let new = self.read_scalar(args[1])?;
|
let new = self.read_scalar(args[1])?;
|
||||||
let old = self.read_scalar(ptr.into())?;
|
let old = self.read_scalar(ptr.into())?;
|
||||||
self.write_scalar(old, dest)?; // old value is returned
|
self.write_scalar(old, dest)?; // old value is returned
|
||||||
@ -86,14 +86,14 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
|
|||||||
}
|
}
|
||||||
|
|
||||||
_ if intrinsic_name.starts_with("atomic_cxchg") => {
|
_ if intrinsic_name.starts_with("atomic_cxchg") => {
|
||||||
let ptr = self.ref_to_mplace(self.read_value(args[0])?)?;
|
let ptr = self.ref_to_mplace(self.read_immediate(args[0])?)?;
|
||||||
let expect_old = self.read_value(args[1])?; // read as value for the sake of `binary_op_val()`
|
let expect_old = self.read_immediate(args[1])?; // read as value for the sake of `binary_op_val()`
|
||||||
let new = self.read_scalar(args[2])?;
|
let new = self.read_scalar(args[2])?;
|
||||||
let old = self.read_value(ptr.into())?; // read as value for the sake of `binary_op_val()`
|
let old = self.read_immediate(ptr.into())?; // read as value for the sake of `binary_op_val()`
|
||||||
// binary_op_val will bail if either of them is not a scalar
|
// binary_op_val will bail if either of them is not a scalar
|
||||||
let (eq, _) = self.binary_op_val(mir::BinOp::Eq, old, expect_old)?;
|
let (eq, _) = self.binary_op_val(mir::BinOp::Eq, old, expect_old)?;
|
||||||
let res = Value::ScalarPair(old.to_scalar_or_undef(), eq.into());
|
let res = Immediate::ScalarPair(old.to_scalar_or_undef(), eq.into());
|
||||||
self.write_value(res, dest)?; // old value is returned
|
self.write_immediate(res, dest)?; // old value is returned
|
||||||
// update ptr depending on comparison
|
// update ptr depending on comparison
|
||||||
if eq.to_bool()? {
|
if eq.to_bool()? {
|
||||||
self.write_scalar(new, ptr.into())?;
|
self.write_scalar(new, ptr.into())?;
|
||||||
@ -125,13 +125,13 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
|
|||||||
"atomic_xsub_rel" |
|
"atomic_xsub_rel" |
|
||||||
"atomic_xsub_acqrel" |
|
"atomic_xsub_acqrel" |
|
||||||
"atomic_xsub_relaxed" => {
|
"atomic_xsub_relaxed" => {
|
||||||
let ptr = self.ref_to_mplace(self.read_value(args[0])?)?;
|
let ptr = self.ref_to_mplace(self.read_immediate(args[0])?)?;
|
||||||
if !ptr.layout.ty.is_integral() {
|
if !ptr.layout.ty.is_integral() {
|
||||||
return err!(Unimplemented(format!("Atomic arithmetic operations only work on integer types")));
|
return err!(Unimplemented(format!("Atomic arithmetic operations only work on integer types")));
|
||||||
}
|
}
|
||||||
let rhs = self.read_value(args[1])?;
|
let rhs = self.read_immediate(args[1])?;
|
||||||
let old = self.read_value(ptr.into())?;
|
let old = self.read_immediate(ptr.into())?;
|
||||||
self.write_value(*old, dest)?; // old value is returned
|
self.write_immediate(*old, dest)?; // old value is returned
|
||||||
let op = match intrinsic_name.split('_').nth(1).unwrap() {
|
let op = match intrinsic_name.split('_').nth(1).unwrap() {
|
||||||
"or" => mir::BinOp::BitOr,
|
"or" => mir::BinOp::BitOr,
|
||||||
"xor" => mir::BinOp::BitXor,
|
"xor" => mir::BinOp::BitXor,
|
||||||
@ -151,7 +151,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
|
|||||||
let elem_ty = substs.type_at(0);
|
let elem_ty = substs.type_at(0);
|
||||||
let elem_layout = self.layout_of(elem_ty)?;
|
let elem_layout = self.layout_of(elem_ty)?;
|
||||||
let elem_size = elem_layout.size.bytes();
|
let elem_size = elem_layout.size.bytes();
|
||||||
let count = self.read_scalar(args[2])?.to_usize(&self)?;
|
let count = self.read_scalar(args[2])?.to_usize(self)?;
|
||||||
let elem_align = elem_layout.align;
|
let elem_align = elem_layout.align;
|
||||||
// erase tags: this is a raw ptr operation
|
// erase tags: this is a raw ptr operation
|
||||||
let src = self.read_scalar(args[0])?.not_undef()?.erase_tag();
|
let src = self.read_scalar(args[0])?.not_undef()?.erase_tag();
|
||||||
@ -167,7 +167,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
|
|||||||
}
|
}
|
||||||
|
|
||||||
"discriminant_value" => {
|
"discriminant_value" => {
|
||||||
let place = self.ref_to_mplace(self.read_value(args[0])?)?;
|
let place = self.ref_to_mplace(self.read_immediate(args[0])?)?;
|
||||||
let discr_val = self.read_discriminant(place.into())?.0;
|
let discr_val = self.read_discriminant(place.into())?.0;
|
||||||
self.write_scalar(Scalar::from_uint(discr_val, dest.layout.size), dest)?;
|
self.write_scalar(Scalar::from_uint(discr_val, dest.layout.size), dest)?;
|
||||||
}
|
}
|
||||||
@ -215,8 +215,8 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
|
|||||||
}
|
}
|
||||||
|
|
||||||
"fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => {
|
"fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => {
|
||||||
let a = self.read_value(args[0])?;
|
let a = self.read_immediate(args[0])?;
|
||||||
let b = self.read_value(args[1])?;
|
let b = self.read_immediate(args[1])?;
|
||||||
let op = match intrinsic_name {
|
let op = match intrinsic_name {
|
||||||
"fadd_fast" => mir::BinOp::Add,
|
"fadd_fast" => mir::BinOp::Add,
|
||||||
"fsub_fast" => mir::BinOp::Sub,
|
"fsub_fast" => mir::BinOp::Sub,
|
||||||
@ -231,8 +231,8 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
|
|||||||
"exact_div" => {
|
"exact_div" => {
|
||||||
// Performs an exact division, resulting in undefined behavior where
|
// Performs an exact division, resulting in undefined behavior where
|
||||||
// `x % y != 0` or `y == 0` or `x == T::min_value() && y == -1`
|
// `x % y != 0` or `y == 0` or `x == T::min_value() && y == -1`
|
||||||
let a = self.read_value(args[0])?;
|
let a = self.read_immediate(args[0])?;
|
||||||
let b = self.read_value(args[1])?;
|
let b = self.read_immediate(args[1])?;
|
||||||
// check x % y != 0
|
// check x % y != 0
|
||||||
if self.binary_op_val(mir::BinOp::Rem, a, b)?.0.to_bytes()? != 0 {
|
if self.binary_op_val(mir::BinOp::Rem, a, b)?.0.to_bytes()? != 0 {
|
||||||
return err!(ValidationFailure(format!("exact_div: {:?} cannot be divided by {:?}", a, b)));
|
return err!(ValidationFailure(format!("exact_div: {:?} cannot be divided by {:?}", a, b)));
|
||||||
@ -251,13 +251,13 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
|
|||||||
if !dest.layout.is_zst() { // nothing to do for ZST
|
if !dest.layout.is_zst() { // nothing to do for ZST
|
||||||
match dest.layout.abi {
|
match dest.layout.abi {
|
||||||
layout::Abi::Scalar(ref s) => {
|
layout::Abi::Scalar(ref s) => {
|
||||||
let x = Scalar::from_int(0, s.value.size(&self));
|
let x = Scalar::from_int(0, s.value.size(self));
|
||||||
self.write_value(Value::Scalar(x.into()), dest)?;
|
self.write_immediate(Immediate::Scalar(x.into()), dest)?;
|
||||||
}
|
}
|
||||||
layout::Abi::ScalarPair(ref s1, ref s2) => {
|
layout::Abi::ScalarPair(ref s1, ref s2) => {
|
||||||
let x = Scalar::from_int(0, s1.value.size(&self));
|
let x = Scalar::from_int(0, s1.value.size(self));
|
||||||
let y = Scalar::from_int(0, s2.value.size(&self));
|
let y = Scalar::from_int(0, s2.value.size(self));
|
||||||
self.write_value(Value::ScalarPair(x.into(), y.into()), dest)?;
|
self.write_immediate(Immediate::ScalarPair(x.into(), y.into()), dest)?;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// Do it in memory
|
// Do it in memory
|
||||||
@ -279,12 +279,12 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
|
|||||||
}
|
}
|
||||||
|
|
||||||
"move_val_init" => {
|
"move_val_init" => {
|
||||||
let ptr = self.ref_to_mplace(self.read_value(args[0])?)?;
|
let ptr = self.ref_to_mplace(self.read_immediate(args[0])?)?;
|
||||||
self.copy_op(args[1], ptr.into())?;
|
self.copy_op(args[1], ptr.into())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
"offset" => {
|
"offset" => {
|
||||||
let offset = self.read_scalar(args[1])?.to_isize(&self)?;
|
let offset = self.read_scalar(args[1])?.to_isize(self)?;
|
||||||
let ptr = self.read_scalar(args[0])?.not_undef()?;
|
let ptr = self.read_scalar(args[0])?.not_undef()?;
|
||||||
let result_ptr = self.pointer_offset_inbounds(ptr, substs.type_at(0), offset)?;
|
let result_ptr = self.pointer_offset_inbounds(ptr, substs.type_at(0), offset)?;
|
||||||
self.write_scalar(result_ptr, dest)?;
|
self.write_scalar(result_ptr, dest)?;
|
||||||
@ -347,7 +347,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
|
|||||||
}
|
}
|
||||||
|
|
||||||
"size_of_val" => {
|
"size_of_val" => {
|
||||||
let mplace = self.ref_to_mplace(self.read_value(args[0])?)?;
|
let mplace = self.ref_to_mplace(self.read_immediate(args[0])?)?;
|
||||||
let (size, _) = self.size_and_align_of_mplace(mplace)?
|
let (size, _) = self.size_and_align_of_mplace(mplace)?
|
||||||
.expect("size_of_val called on extern type");
|
.expect("size_of_val called on extern type");
|
||||||
let ptr_size = self.pointer_size();
|
let ptr_size = self.pointer_size();
|
||||||
@ -359,7 +359,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
|
|||||||
|
|
||||||
"min_align_of_val" |
|
"min_align_of_val" |
|
||||||
"align_of_val" => {
|
"align_of_val" => {
|
||||||
let mplace = self.ref_to_mplace(self.read_value(args[0])?)?;
|
let mplace = self.ref_to_mplace(self.read_immediate(args[0])?)?;
|
||||||
let (_, align) = self.size_and_align_of_mplace(mplace)?
|
let (_, align) = self.size_and_align_of_mplace(mplace)?
|
||||||
.expect("size_of_val called on extern type");
|
.expect("size_of_val called on extern type");
|
||||||
let ptr_size = self.pointer_size();
|
let ptr_size = self.pointer_size();
|
||||||
@ -372,13 +372,13 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
|
|||||||
"type_name" => {
|
"type_name" => {
|
||||||
let ty = substs.type_at(0);
|
let ty = substs.type_at(0);
|
||||||
let ty_name = ty.to_string();
|
let ty_name = ty.to_string();
|
||||||
let value = self.str_to_value(&ty_name)?;
|
let value = self.str_to_immediate(&ty_name)?;
|
||||||
self.write_value(value, dest)?;
|
self.write_immediate(value, dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
"unchecked_div" => {
|
"unchecked_div" => {
|
||||||
let l = self.read_value(args[0])?;
|
let l = self.read_immediate(args[0])?;
|
||||||
let r = self.read_value(args[1])?;
|
let r = self.read_immediate(args[1])?;
|
||||||
let rval = r.to_scalar()?.to_bytes()?;
|
let rval = r.to_scalar()?.to_bytes()?;
|
||||||
if rval == 0 {
|
if rval == 0 {
|
||||||
return err!(Intrinsic(format!("Division by 0 in unchecked_div")));
|
return err!(Intrinsic(format!("Division by 0 in unchecked_div")));
|
||||||
@ -392,8 +392,8 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
|
|||||||
}
|
}
|
||||||
|
|
||||||
"unchecked_rem" => {
|
"unchecked_rem" => {
|
||||||
let l = self.read_value(args[0])?;
|
let l = self.read_immediate(args[0])?;
|
||||||
let r = self.read_value(args[1])?;
|
let r = self.read_immediate(args[1])?;
|
||||||
let rval = r.to_scalar()?.to_bytes()?;
|
let rval = r.to_scalar()?.to_bytes()?;
|
||||||
if rval == 0 {
|
if rval == 0 {
|
||||||
return err!(Intrinsic(format!("Division by 0 in unchecked_rem")));
|
return err!(Intrinsic(format!("Division by 0 in unchecked_rem")));
|
||||||
@ -416,11 +416,11 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
|
|||||||
match dest.layout.abi {
|
match dest.layout.abi {
|
||||||
layout::Abi::Scalar(..) => {
|
layout::Abi::Scalar(..) => {
|
||||||
let x = ScalarMaybeUndef::Undef;
|
let x = ScalarMaybeUndef::Undef;
|
||||||
self.write_value(Value::Scalar(x), dest)?;
|
self.write_immediate(Immediate::Scalar(x), dest)?;
|
||||||
}
|
}
|
||||||
layout::Abi::ScalarPair(..) => {
|
layout::Abi::ScalarPair(..) => {
|
||||||
let x = ScalarMaybeUndef::Undef;
|
let x = ScalarMaybeUndef::Undef;
|
||||||
self.write_value(Value::ScalarPair(x, x), dest)?;
|
self.write_immediate(Immediate::ScalarPair(x, x), dest)?;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// Do it in memory
|
// Do it in memory
|
||||||
@ -437,7 +437,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
|
|||||||
let ty_layout = self.layout_of(ty)?;
|
let ty_layout = self.layout_of(ty)?;
|
||||||
let val_byte = self.read_scalar(args[1])?.to_u8()?;
|
let val_byte = self.read_scalar(args[1])?.to_u8()?;
|
||||||
let ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag().with_default_tag();
|
let ptr = self.read_scalar(args[0])?.not_undef()?.erase_tag().with_default_tag();
|
||||||
let count = self.read_scalar(args[2])?.to_usize(&self)?;
|
let count = self.read_scalar(args[2])?.to_usize(self)?;
|
||||||
self.memory().check_align(ptr, ty_layout.align)?;
|
self.memory().check_align(ptr, ty_layout.align)?;
|
||||||
self.memory_mut().write_repeat(ptr, val_byte, ty_layout.size * count)?;
|
self.memory_mut().write_repeat(ptr, val_byte, ty_layout.size * count)?;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#![feature(rustc_private)]
|
#![feature(rustc_private, extern_crate_item_prelude)]
|
||||||
|
|
||||||
#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless))]
|
#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless))]
|
||||||
|
|
||||||
@ -253,7 +253,7 @@ impl Into<MemoryKind<MiriMemoryKind>> for MiriMemoryKind {
|
|||||||
impl MayLeak for MiriMemoryKind {
|
impl MayLeak for MiriMemoryKind {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn may_leak(self) -> bool {
|
fn may_leak(self) -> bool {
|
||||||
use MiriMemoryKind::*;
|
use self::MiriMemoryKind::*;
|
||||||
match self {
|
match self {
|
||||||
Rust | C => false,
|
Rust | C => false,
|
||||||
Env | MutStatic => true,
|
Env | MutStatic => true,
|
||||||
|
@ -539,12 +539,12 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
|
|||||||
// above. First deref, which will call `tag_dereference`.
|
// above. First deref, which will call `tag_dereference`.
|
||||||
// (This is somewhat redundant because validation already did the same thing,
|
// (This is somewhat redundant because validation already did the same thing,
|
||||||
// but what can you do.)
|
// but what can you do.)
|
||||||
let val = self.read_value(self.place_to_op(place)?)?;
|
let val = self.read_immediate(self.place_to_op(place)?)?;
|
||||||
let dest = self.ref_to_mplace(val)?;
|
let dest = self.ref_to_mplace(val)?;
|
||||||
// Now put a new ref into the old place, which will call `tag_reference`.
|
// Now put a new ref into the old place, which will call `tag_reference`.
|
||||||
// FIXME: Honor `fn_entry`!
|
// FIXME: Honor `fn_entry`!
|
||||||
let val = self.create_ref(dest, Some(mutbl))?;
|
let val = self.create_ref(dest, Some(mutbl))?;
|
||||||
self.write_value(val, place)?;
|
self.write_immediate(val, place)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
12
src/tls.rs
12
src/tls.rs
@ -42,7 +42,7 @@ impl<'tcx> TlsData<'tcx> {
|
|||||||
pub fn create_tls_key(
|
pub fn create_tls_key(
|
||||||
&mut self,
|
&mut self,
|
||||||
dtor: Option<ty::Instance<'tcx>>,
|
dtor: Option<ty::Instance<'tcx>>,
|
||||||
cx: impl HasDataLayout,
|
cx: &impl HasDataLayout,
|
||||||
) -> TlsKey {
|
) -> TlsKey {
|
||||||
let new_key = self.next_key;
|
let new_key = self.next_key;
|
||||||
self.next_key += 1;
|
self.next_key += 1;
|
||||||
@ -109,7 +109,7 @@ impl<'tcx> TlsData<'tcx> {
|
|||||||
fn fetch_tls_dtor(
|
fn fetch_tls_dtor(
|
||||||
&mut self,
|
&mut self,
|
||||||
key: Option<TlsKey>,
|
key: Option<TlsKey>,
|
||||||
cx: impl HasDataLayout,
|
cx: &impl HasDataLayout,
|
||||||
) -> Option<(ty::Instance<'tcx>, Scalar<Borrow>, TlsKey)> {
|
) -> Option<(ty::Instance<'tcx>, Scalar<Borrow>, TlsKey)> {
|
||||||
use std::collections::Bound::*;
|
use std::collections::Bound::*;
|
||||||
|
|
||||||
@ -135,14 +135,14 @@ impl<'tcx> TlsData<'tcx> {
|
|||||||
|
|
||||||
impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, 'tcx> {
|
impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, 'tcx> {
|
||||||
fn run_tls_dtors(&mut self) -> EvalResult<'tcx> {
|
fn run_tls_dtors(&mut self) -> EvalResult<'tcx> {
|
||||||
let mut dtor = self.machine.tls.fetch_tls_dtor(None, *self.tcx);
|
let mut dtor = self.machine.tls.fetch_tls_dtor(None, &*self.tcx);
|
||||||
// FIXME: replace loop by some structure that works with stepping
|
// FIXME: replace loop by some structure that works with stepping
|
||||||
while let Some((instance, ptr, key)) = dtor {
|
while let Some((instance, ptr, key)) = dtor {
|
||||||
trace!("Running TLS dtor {:?} on {:?}", instance, ptr);
|
trace!("Running TLS dtor {:?} on {:?}", instance, ptr);
|
||||||
// TODO: Potentially, this has to support all the other possible instances?
|
// TODO: Potentially, this has to support all the other possible instances?
|
||||||
// See eval_fn_call in interpret/terminator/mod.rs
|
// See eval_fn_call in interpret/terminator/mod.rs
|
||||||
let mir = self.load_mir(instance.def)?;
|
let mir = self.load_mir(instance.def)?;
|
||||||
let ret_place = MPlaceTy::dangling(self.layout_of(self.tcx.mk_unit())?, &self).into();
|
let ret_place = MPlaceTy::dangling(self.layout_of(self.tcx.mk_unit())?, self).into();
|
||||||
self.push_stack_frame(
|
self.push_stack_frame(
|
||||||
instance,
|
instance,
|
||||||
mir.span,
|
mir.span,
|
||||||
@ -159,9 +159,9 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for super::MiriEvalContext<
|
|||||||
// step until out of stackframes
|
// step until out of stackframes
|
||||||
self.run()?;
|
self.run()?;
|
||||||
|
|
||||||
dtor = match self.machine.tls.fetch_tls_dtor(Some(key), *self.tcx) {
|
dtor = match self.machine.tls.fetch_tls_dtor(Some(key), &*self.tcx) {
|
||||||
dtor @ Some(_) => dtor,
|
dtor @ Some(_) => dtor,
|
||||||
None => self.machine.tls.fetch_tls_dtor(None, *self.tcx),
|
None => self.machine.tls.fetch_tls_dtor(None, &*self.tcx),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
// FIXME: On a windows target, call `unsafe extern "system" fn on_tls_callback`.
|
// FIXME: On a windows target, call `unsafe extern "system" fn on_tls_callback`.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user