From 574aa3bc42a02348ee8b7bd61fbea480f48c01d5 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 13 May 2018 13:14:26 +0200 Subject: [PATCH 01/16] Rustup to rustc 1.27.0-nightly (ff2ac35db 2018-05-12) --- src/fn_call.rs | 2 +- src/validation.rs | 15 +++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/fn_call.rs b/src/fn_call.rs index 2b4e7b73662..272c27e4021 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -459,7 +459,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' promoted: None, }; let const_val = self.const_eval(cid)?; - let value = const_val.val.unwrap_u64(); + let value = const_val.unwrap_usize(self.tcx.tcx); if value == name { result = Some(path_value); break; diff --git a/src/validation.rs b/src/validation.rs index b274b465015..deb1c5d5bc0 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -10,7 +10,7 @@ use rustc::infer::InferCtxt; use rustc::middle::region; use rustc::middle::const_val::ConstVal; use rustc_data_structures::indexed_vec::Idx; -use rustc_mir::interpret::{HasMemory, eval_body}; +use rustc_mir::interpret::HasMemory; use super::{EvalContext, Place, PlaceExtra, ValTy}; use rustc::mir::interpret::{DynamicLifetime, AccessKind, EvalErrorKind, Value, EvalError, EvalResult}; @@ -718,18 +718,17 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' } } TyArray(elem_ty, len) => { - let len_val = match len.val { + let len = match len.val { ConstVal::Unevaluated(def_id, substs) => { - eval_body(self.tcx.tcx, GlobalId { + self.tcx.const_eval(self.tcx.param_env(def_id).and(GlobalId { instance: Instance::new(def_id, substs), promoted: None, - }, ty::ParamEnv::reveal_all()) - .ok_or_else(||EvalErrorKind::MachineError("".to_string()))? - .0 + })) + .map_err(|_err|EvalErrorKind::MachineError("".to_string()))? } - ConstVal::Value(val) => val, + ConstVal::Value(_) => len, }; - let len = ConstVal::Value(len_val).unwrap_u64(); + let len = len.unwrap_usize(self.tcx.tcx); for i in 0..len { let inner_place = self.place_index(query.place.1, query.ty, i as u64)?; self.validate( From c8ff634f828b62290a5ee9798687bca2ec300f71 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 13 May 2018 15:32:35 +0200 Subject: [PATCH 02/16] Enable backtraces for tests --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6a987f93748..9aa632da05e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,7 @@ script: - | # Test plain miri cargo build --release --all-features && - cargo test --release --all-features --all && + RUST_BACKTRACE=1 cargo test --release --all-features --all && cargo install --all-features --force - | # Test cargo miri From b906ce84ec0635e2033b94415f6ad3ef938c7489 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 19 May 2018 12:14:13 +0200 Subject: [PATCH 03/16] Rustup to rustc 1.28.0-nightly (952f344cd 2018-05-18) --- src/bin/miri.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bin/miri.rs b/src/bin/miri.rs index 4e0be7bd320..5ae9626f01f 100644 --- a/src/bin/miri.rs +++ b/src/bin/miri.rs @@ -5,7 +5,7 @@ extern crate miri; extern crate rustc; extern crate rustc_driver; extern crate rustc_errors; -extern crate rustc_trans_utils; +extern crate rustc_codegen_utils; extern crate env_logger; extern crate log_settings; extern crate syntax; @@ -18,7 +18,7 @@ use rustc_driver::driver::{CompileState, CompileController}; use rustc::session::config::{self, Input, ErrorOutputType}; use rustc::hir::{self, itemlikevisit}; use rustc::ty::TyCtxt; -use rustc_trans_utils::trans_crate::TransCrate; +use rustc_codegen_utils::codegen_backend::CodegenBackend; use syntax::ast; use std::path::PathBuf; @@ -67,7 +67,7 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls { } fn late_callback( &mut self, - trans: &TransCrate, + trans: &CodegenBackend, matches: &getopts::Matches, sess: &Session, cstore: &CrateStore, From 601673d06fd2ddee44dfb437f56afeee36f0e96f Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sat, 19 May 2018 14:09:29 +0200 Subject: [PATCH 04/16] trans -> codegen_backend --- src/bin/miri.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin/miri.rs b/src/bin/miri.rs index 5ae9626f01f..8d80135cde3 100644 --- a/src/bin/miri.rs +++ b/src/bin/miri.rs @@ -67,7 +67,7 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls { } fn late_callback( &mut self, - trans: &CodegenBackend, + codegen_backend: &CodegenBackend, matches: &getopts::Matches, sess: &Session, cstore: &CrateStore, @@ -75,7 +75,7 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls { odir: &Option, ofile: &Option, ) -> Compilation { - self.default.late_callback(trans, matches, sess, cstore, input, odir, ofile) + self.default.late_callback(codegen_backend, matches, sess, cstore, input, odir, ofile) } fn build_controller( &mut self, From 98802769a1d3df9b106ad89221679aef0e8aede1 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 20 May 2018 11:26:40 +0200 Subject: [PATCH 05/16] Rustup to rustc 1.28.0-nightly (a3085756e 2018-05-19) --- src/fn_call.rs | 34 +++++++++++++++++----------------- src/intrinsic.rs | 12 ++++++------ src/lib.rs | 16 ++++++++-------- src/locks.rs | 11 ++++++----- src/operator.rs | 10 +++++----- 5 files changed, 42 insertions(+), 41 deletions(-) diff --git a/src/fn_call.rs b/src/fn_call.rs index 272c27e4021..e7250eca949 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -1,5 +1,5 @@ use rustc::ty::{self, Ty}; -use rustc::ty::layout::{self, Align, LayoutOf}; +use rustc::ty::layout::{self, Align, LayoutOf, Size}; use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc::mir; use rustc_data_structures::indexed_vec::Idx; @@ -187,7 +187,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, align, Some(MemoryKind::C.into()))?; + let ptr = self.memory.allocate(Size::from_bytes(size), align, Some(MemoryKind::C.into()))?; self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?; } } @@ -281,7 +281,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' "memcmp" => { let left = self.into_ptr(args[0].value)?; let right = self.into_ptr(args[1].value)?; - let n = self.value_to_primval(args[2])?.to_u64()?; + let n = Size::from_bytes(self.value_to_primval(args[2])?.to_u64()?); let result = { let left_bytes = self.memory.read_bytes(left, n)?; @@ -306,11 +306,11 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' let ptr = self.into_ptr(args[0].value)?; let val = self.value_to_primval(args[1])?.to_u64()? as u8; let num = self.value_to_primval(args[2])?.to_u64()?; - if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().rev().position( + if let Some(idx) = self.memory.read_bytes(ptr, Size::from_bytes(num))?.iter().rev().position( |&c| c == val, ) { - let new_ptr = ptr.offset(num - idx as u64 - 1, &self)?; + let new_ptr = ptr.offset(Size::from_bytes(num - idx as u64 - 1), &self)?; self.write_ptr(dest, new_ptr, dest_ty)?; } else { self.write_null(dest, dest_ty)?; @@ -321,11 +321,11 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' let ptr = self.into_ptr(args[0].value)?; let val = self.value_to_primval(args[1])?.to_u64()? as u8; let num = self.value_to_primval(args[2])?.to_u64()?; - if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().position( + if let Some(idx) = self.memory.read_bytes(ptr, Size::from_bytes(num))?.iter().position( |&c| c == val, ) { - let new_ptr = ptr.offset(idx as u64, &self)?; + let new_ptr = ptr.offset(Size::from_bytes(idx as u64), &self)?; self.write_ptr(dest, new_ptr, dest_ty)?; } else { self.write_null(dest, dest_ty)?; @@ -381,12 +381,12 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' if let Some((name, value)) = new { // +1 for the null terminator let value_copy = self.memory.allocate( - (value.len() + 1) as u64, + Size::from_bytes((value.len() + 1) as u64), Align::from_bytes(1, 1).unwrap(), Some(MemoryKind::Env.into()), )?; self.memory.write_bytes(value_copy.into(), &value)?; - let trailing_zero_ptr = value_copy.offset(value.len() as u64, &self)?.into(); + let trailing_zero_ptr = value_copy.offset(Size::from_bytes(value.len() as u64), &self)?.into(); self.memory.write_bytes(trailing_zero_ptr, &[0])?; if let Some(var) = self.machine.env_vars.insert( name.to_owned(), @@ -410,7 +410,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' // stdout/stderr use std::io::{self, Write}; - let buf_cont = self.memory.read_bytes(buf, n)?; + let buf_cont = self.memory.read_bytes(buf, Size::from_bytes(n))?; let res = if fd == 1 { io::stdout().write(buf_cont) } else { @@ -502,7 +502,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' key_ptr, key_align, PrimVal::Bytes(key), - key_size.bytes(), + key_size, false, )?; @@ -643,7 +643,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' if !align.is_power_of_two() { return err!(HeapAllocNonPowerOfTwoAlignment(align)); } - let ptr = self.memory.allocate(size, + let ptr = self.memory.allocate(Size::from_bytes(size), Align::from_bytes(align, align).unwrap(), Some(MemoryKind::Rust.into()))?; self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?; @@ -657,10 +657,10 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' if !align.is_power_of_two() { return err!(HeapAllocNonPowerOfTwoAlignment(align)); } - let ptr = self.memory.allocate(size, + let ptr = self.memory.allocate(Size::from_bytes(size), Align::from_bytes(align, align).unwrap(), Some(MemoryKind::Rust.into()))?; - self.memory.write_repeat(ptr.into(), 0, size)?; + self.memory.write_repeat(ptr.into(), 0, Size::from_bytes(size))?; self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?; } "alloc::alloc::::__rust_dealloc" => { @@ -675,7 +675,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' } self.memory.deallocate( ptr, - Some((old_size, Align::from_bytes(align, align).unwrap())), + Some((Size::from_bytes(old_size), Align::from_bytes(align, align).unwrap())), MemoryKind::Rust.into(), )?; } @@ -692,9 +692,9 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' } let new_ptr = self.memory.reallocate( ptr, - old_size, + Size::from_bytes(old_size), Align::from_bytes(align, align).unwrap(), - new_size, + Size::from_bytes(new_size), Align::from_bytes(align, align).unwrap(), MemoryKind::Rust.into(), )?; diff --git a/src/intrinsic.rs b/src/intrinsic.rs index 234d1ee7848..30de1c68ca6 100644 --- a/src/intrinsic.rs +++ b/src/intrinsic.rs @@ -1,5 +1,5 @@ use rustc::mir; -use rustc::ty::layout::{TyLayout, LayoutOf}; +use rustc::ty::layout::{TyLayout, LayoutOf, Size}; use rustc::ty; use rustc::mir::interpret::{EvalResult, PrimVal, PrimValKind, Value, Pointer}; @@ -35,7 +35,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: // FIXME: return a real value in case the target allocation has an // alignment bigger than the one requested let n = u128::max_value(); - let amt = 128 - self.memory.pointer_size() * 8; + let amt = 128 - self.memory.pointer_size().bytes() * 8; self.write_primval(dest, PrimVal::Bytes((n << amt) >> amt), dest_layout.ty)?; }, @@ -225,7 +225,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: elem_align, dest, elem_align, - count * elem_size, + Size::from_bytes(count * elem_size), intrinsic_name.ends_with("_nonoverlapping"), )?; } @@ -332,7 +332,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: "likely" | "unlikely" | "forget" => {} "init" => { - let size = dest_layout.size.bytes(); + let size = dest_layout.size; let init = |this: &mut Self, val: Value| { let zero_val = match val { Value::ByRef(ptr, _) => { @@ -631,7 +631,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: } "uninit" => { - let size = dest_layout.size.bytes(); + let size = dest_layout.size; let uninit = |this: &mut Self, val: Value| match val { Value::ByRef(ptr, _) => { this.memory.mark_definedness(ptr, size, false)?; @@ -662,7 +662,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: // 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_layout.align)?; - self.memory.write_repeat(ptr, val_byte, ty_layout.size.bytes() * count)?; + self.memory.write_repeat(ptr, val_byte, ty_layout.size * count)?; } } diff --git a/src/lib.rs b/src/lib.rs index dce31c4ed33..66ad6377e32 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,7 +20,7 @@ extern crate regex; extern crate lazy_static; use rustc::ty::{self, TyCtxt}; -use rustc::ty::layout::{TyLayout, LayoutOf}; +use rustc::ty::layout::{TyLayout, LayoutOf, Size}; use rustc::ty::subst::Subst; use rustc::hir::def_id::DefId; use rustc::mir; @@ -93,7 +93,7 @@ pub fn eval_main<'a, 'tcx: 'a>( } // Return value - let size = ecx.tcx.data_layout.pointer_size.bytes(); + 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))?; cleanup_ptr = Some(ret_ptr); @@ -299,7 +299,7 @@ impl<'mir, 'tcx: 'mir> Machine<'mir, 'tcx> for Evaluator<'tcx> { let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?; assert!(!layout.is_unsized()); let ptr = ecx.memory.allocate( - layout.size.bytes(), + layout.size, layout.align, None, )?; @@ -373,8 +373,8 @@ impl<'mir, 'tcx: 'mir> Machine<'mir, 'tcx> for Evaluator<'tcx> { ecx.write_value( ValTy { value: Value::ByVal(PrimVal::Bytes(match layout.size.bytes() { - 0 => 1, - size => size, + 0 => 1 as u128, + size => size as u128, }.into())), ty: usize, }, @@ -407,10 +407,10 @@ impl<'mir, 'tcx: 'mir> Machine<'mir, 'tcx> for Evaluator<'tcx> { fn check_locks<'a>( mem: &Memory<'a, 'mir, 'tcx, Self>, ptr: MemoryPointer, - size: u64, + size: Size, access: AccessKind, ) -> EvalResult<'tcx> { - mem.check_locks(ptr, size, access) + mem.check_locks(ptr, size.bytes(), access) } fn add_lock<'a>( @@ -439,7 +439,7 @@ impl<'mir, 'tcx: 'mir> Machine<'mir, 'tcx> for Evaluator<'tcx> { //ptr, FIXME ptr: MemoryPointer { alloc_id: AllocId(0), - offset: 0, + offset: Size::from_bytes(0), }, lock: lock.active, }.into() diff --git a/src/locks.rs b/src/locks.rs index 677b0454a54..9efbabc7171 100644 --- a/src/locks.rs +++ b/src/locks.rs @@ -1,5 +1,6 @@ use super::*; use rustc::middle::region; +use rustc::ty::layout::Size; //////////////////////////////////////////////////////////////////////////////// // Locks @@ -116,7 +117,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> MemoryExt<'tcx> for Memory<'a, 'mir, 'tcx, Evalu }; let frame = self.cur_frame; locks - .check(Some(frame), ptr.offset, len, access) + .check(Some(frame), ptr.offset.bytes(), len, access) .map_err(|lock| { EvalErrorKind::MemoryLockViolation { ptr, @@ -146,7 +147,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> MemoryExt<'tcx> for Memory<'a, 'mir, 'tcx, Evalu len, region ); - self.check_bounds(ptr.offset(len, &*self)?, true)?; // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow) + self.check_bounds(ptr.offset(Size::from_bytes(len), &*self)?, true)?; // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow) let locks = match self.data.locks.get_mut(&ptr.alloc_id) { Some(locks) => locks, @@ -157,7 +158,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> MemoryExt<'tcx> for Memory<'a, 'mir, 'tcx, Evalu // Iterate over our range and acquire the lock. If the range is already split into pieces, // we have to manipulate all of them. let lifetime = DynamicLifetime { frame, region }; - for lock in locks.iter_mut(ptr.offset, len) { + for lock in locks.iter_mut(ptr.offset.bytes(), len) { if !lock.access_permitted(None, kind) { return err!(MemoryAcquireConflict { ptr, @@ -203,7 +204,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> MemoryExt<'tcx> for Memory<'a, 'mir, 'tcx, Evalu None => return Ok(()), }; - 'locks: for lock in locks.iter_mut(ptr.offset, len) { + 'locks: for lock in locks.iter_mut(ptr.offset.bytes(), len) { let is_our_lock = match lock.active { WriteLock(lft) => // Double-check that we are holding the lock. @@ -281,7 +282,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> MemoryExt<'tcx> for Memory<'a, 'mir, 'tcx, Evalu None => return Ok(()), }; - for lock in locks.iter_mut(ptr.offset, len) { + for lock in locks.iter_mut(ptr.offset.bytes(), len) { // Check if we have a suspension here let (got_the_lock, remove_suspension) = match lock.suspended.get_mut(&lock_id) { None => { diff --git a/src/operator.rs b/src/operator.rs index 220f8f9acd5..557e07975d7 100644 --- a/src/operator.rs +++ b/src/operator.rs @@ -89,9 +89,9 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: Sub => { return self.binary_op( Sub, - PrimVal::Bytes(left.offset as u128), + PrimVal::Bytes(left.offset.bytes() as u128), self.tcx.types.usize, - PrimVal::Bytes(right.offset as u128), + PrimVal::Bytes(right.offset.bytes() as u128), self.tcx.types.usize, ).map(Some) } @@ -150,17 +150,17 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: Add if signed => map_to_primval(left.overflowing_signed_offset(right, self)), Add if !signed => - map_to_primval(left.overflowing_offset(right as u64, self)), + map_to_primval(left.overflowing_offset(Size::from_bytes(right as u64), self)), BitAnd if !signed => { let base_mask : u64 = !(self.memory.get(left.alloc_id)?.align.abi() - 1); let right = right as u64; if right & base_mask == base_mask { // Case 1: The base address bits are all preserved, i.e., right is all-1 there - (PrimVal::Ptr(MemoryPointer::new(left.alloc_id, left.offset & right)), false) + (PrimVal::Ptr(MemoryPointer::new(left.alloc_id, Size::from_bytes(left.offset.bytes() & right))), false) } else if right & base_mask == 0 { // Case 2: The base address bits are all taken away, i.e., right is all-0 there - (PrimVal::from_u128((left.offset & right) as u128), false) + (PrimVal::from_u128((left.offset.bytes() & right) as u128), false) } else { return err!(ReadPointerAsBytes); } From 1437a975d64b0e04f807abfbca78deb4c93f928e Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Fri, 25 May 2018 14:37:12 +0200 Subject: [PATCH 06/16] s/allocate_cached/allocate_bytes --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 66ad6377e32..f8119245b48 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -131,7 +131,7 @@ pub fn eval_main<'a, 'tcx: 'a>( // Third argument (argv): &[b"foo"] let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?; let ty = ecx.tcx.mk_imm_ptr(ecx.tcx.mk_imm_ptr(ecx.tcx.types.u8)); - let foo = ecx.memory.allocate_cached(b"foo\0"); + 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)?; From 4143922d1d613154ad2c3369b3e2c6a6fd4ef35e Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sat, 26 May 2018 17:07:34 +0200 Subject: [PATCH 07/16] Partial rustup --- benches/helpers/miri_helper.rs | 9 +- src/fn_call.rs | 114 +++++++++--------- src/helpers.rs | 34 +++--- src/intrinsic.rs | 206 +++++++++++++++++---------------- src/lib.rs | 104 ++++++++++++++--- src/locks.rs | 16 +-- src/operator.rs | 101 +++++++++------- src/tls.rs | 24 ++-- src/validation.rs | 6 +- 9 files changed, 358 insertions(+), 256 deletions(-) diff --git a/benches/helpers/miri_helper.rs b/benches/helpers/miri_helper.rs index 6657ba11997..2bf78b0a71c 100644 --- a/benches/helpers/miri_helper.rs +++ b/benches/helpers/miri_helper.rs @@ -55,16 +55,13 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls<'a> { state.session.abort_if_errors(); let tcx = state.tcx.unwrap(); - let (entry_node_id, _) = state.session.entry_fn.borrow().expect( + let (entry_node_id, _, _) = state.session.entry_fn.borrow().expect( "no main or start function found", ); - let entry_def_id = tcx.map.local_def_id(entry_node_id); + let entry_def_id = tcx.hir.local_def_id(entry_node_id); - let memory_size = 100 * 1024 * 1024; // 100MB - let step_limit = 1000_000; - let stack_limit = 100; bencher.borrow_mut().iter(|| { - eval_main(tcx, entry_def_id, memory_size, step_limit, stack_limit); + eval_main(tcx, entry_def_id, None); }); state.session.abort_if_errors(); diff --git a/src/fn_call.rs b/src/fn_call.rs index e7250eca949..ea0c5eb8b26 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -38,7 +38,7 @@ fn write_discriminant_value<'a, 'mir, 'tcx: 'a + 'mir>( .val; let (discr_dest, discr) = ecx.place_field(dest, mir::Field::new(0), layout)?; - ecx.write_primval(discr_dest, PrimVal::Bytes(discr_val), discr.ty)?; + ecx.write_scalar(discr_dest, Scalar::from_u128(discr_val), discr.ty)?; } layout::Variants::NicheFilling { dataful_variant, @@ -51,7 +51,7 @@ fn write_discriminant_value<'a, 'mir, 'tcx: 'a + 'mir>( ecx.place_field(dest, mir::Field::new(0), layout)?; let niche_value = ((variant_index - niche_variants.start()) as u128) .wrapping_add(niche_start); - ecx.write_primval(niche_dest, PrimVal::Bytes(niche_value), niche.ty)?; + ecx.write_scalar(niche_dest, Scalar::from_u128(niche_value), niche.ty)?; } } } @@ -182,13 +182,13 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' match &link_name[..] { "malloc" => { - let size = self.value_to_primval(args[0])?.to_u64()?; + let size = self.value_to_scalar(args[0])?.to_u64()?; if size == 0 { 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()))?; - self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?; + self.write_scalar(dest, Scalar::Ptr(ptr), dest_ty)?; } } @@ -209,7 +209,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' // // libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK) // is called if a `HashMap` is created the regular way. - match self.value_to_primval(args[0])?.to_u64()? { + match self.value_to_scalar(args[0])?.to_u64()? { 318 | 511 => { return err!(Unimplemented( "miri does not support random number generators".to_owned(), @@ -281,7 +281,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' "memcmp" => { let left = self.into_ptr(args[0].value)?; let right = self.into_ptr(args[1].value)?; - let n = Size::from_bytes(self.value_to_primval(args[2])?.to_u64()?); + let n = Size::from_bytes(self.value_to_scalar(args[2])?.to_u64()?); let result = { let left_bytes = self.memory.read_bytes(left, n)?; @@ -295,22 +295,22 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' } }; - self.write_primval( + self.write_scalar( dest, - PrimVal::Bytes(result as u128), + Scalar::from_i8(result), dest_ty, )?; } "memrchr" => { let ptr = self.into_ptr(args[0].value)?; - let val = self.value_to_primval(args[1])?.to_u64()? as u8; - let num = self.value_to_primval(args[2])?.to_u64()?; + let val = self.value_to_scalar(args[1])?.to_u64()? as u8; + let num = self.value_to_scalar(args[2])?.to_u64()?; if let Some(idx) = self.memory.read_bytes(ptr, Size::from_bytes(num))?.iter().rev().position( |&c| c == val, ) { - let new_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_ptr(dest, new_ptr, dest_ty)?; } else { self.write_null(dest, dest_ty)?; @@ -319,13 +319,13 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' "memchr" => { let ptr = self.into_ptr(args[0].value)?; - let val = self.value_to_primval(args[1])?.to_u64()? as u8; - let num = self.value_to_primval(args[2])?.to_u64()?; + let val = self.value_to_scalar(args[1])?.to_u64()? as u8; + let num = self.value_to_scalar(args[2])?.to_u64()?; if let Some(idx) = self.memory.read_bytes(ptr, Size::from_bytes(num))?.iter().position( |&c| c == val, ) { - let new_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_ptr(dest, new_ptr, dest_ty)?; } else { self.write_null(dest, dest_ty)?; @@ -337,11 +337,11 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' let name_ptr = self.into_ptr(args[0].value)?.to_ptr()?; let name = self.memory.read_c_str(name_ptr)?; match self.machine.env_vars.get(name) { - Some(&var) => PrimVal::Ptr(var), - None => PrimVal::Bytes(0), + Some(&var) => Scalar::Ptr(var), + None => Scalar::null(), } }; - self.write_primval(dest, result, dest_ty)?; + self.write_scalar(dest, result, dest_ty)?; } "unsetenv" => { @@ -361,7 +361,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' } self.write_null(dest, dest_ty)?; } else { - self.write_primval(dest, PrimVal::from_i128(-1), dest_ty)?; + self.write_scalar(dest, Scalar::from_i128(-1), dest_ty)?; } } @@ -397,14 +397,14 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' } self.write_null(dest, dest_ty)?; } else { - self.write_primval(dest, PrimVal::from_i128(-1), dest_ty)?; + self.write_scalar(dest, Scalar::from_i128(-1), dest_ty)?; } } "write" => { - let fd = self.value_to_primval(args[0])?.to_u64()?; + let fd = self.value_to_scalar(args[0])?.to_u64()?; let buf = self.into_ptr(args[1].value)?; - let n = self.value_to_primval(args[2])?.to_u64()?; + let n = self.value_to_scalar(args[2])?.to_u64()?; trace!("Called write({:?}, {:?}, {:?})", fd, buf, n); let result = if fd == 1 || fd == 2 { // stdout/stderr @@ -417,16 +417,17 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' io::stderr().write(buf_cont) }; match res { - Ok(n) => n as isize, + Ok(n) => n as i64, Err(_) => -1, } } else { warn!("Ignored output to FD {}", fd); - n as isize // pretend it all went well + n as i64 // pretend it all went well }; // now result is the value we return back to the program - self.write_primval( + let ptr_size = self.memory.pointer_size(); + self.write_scalar( dest, - PrimVal::Bytes(result as u128), + Scalar::from_isize(result, ptr_size), dest_ty, )?; } @@ -434,22 +435,23 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' "strlen" => { let ptr = self.into_ptr(args[0].value)?.to_ptr()?; let n = self.memory.read_c_str(ptr)?.len(); - self.write_primval(dest, PrimVal::Bytes(n as u128), dest_ty)?; + let ptr_size = self.memory.pointer_size(); + self.write_scalar(dest, Scalar::from_usize(n as u64, ptr_size), dest_ty)?; } // Some things needed for sys::thread initialization to go through "signal" | "sigaction" | "sigaltstack" => { - self.write_primval(dest, PrimVal::Bytes(0), dest_ty)?; + self.write_scalar(dest, Scalar::null(), dest_ty)?; } "sysconf" => { - let name = self.value_to_primval(args[0])?.to_u64()?; + let name = self.value_to_scalar(args[0])?.to_u64()?; trace!("sysconf() called with name {}", name); // cache the sysconf integers via miri's global cache let paths = &[ - (&["libc", "_SC_PAGESIZE"], PrimVal::Bytes(4096)), - (&["libc", "_SC_GETPW_R_SIZE_MAX"], PrimVal::from_i128(-1)), + (&["libc", "_SC_PAGESIZE"], Scalar::from_i128(4096)), + (&["libc", "_SC_GETPW_R_SIZE_MAX"], Scalar::from_i128(-1)), ]; let mut result = None; for &(path, path_value) in paths { @@ -467,7 +469,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' } } if let Some(result) = result { - self.write_primval(dest, result, dest_ty)?; + self.write_scalar(dest, result, dest_ty)?; } else { return err!(Unimplemented( format!("Unimplemented sysconf name: {}", name), @@ -481,11 +483,11 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' let key_align = self.layout_of(args[0].ty)?.align; // Extract the function type out of the signature (that seems easier than constructing it ourselves...) - let dtor = match self.into_ptr(args[1].value)?.into_inner_primval() { - PrimVal::Ptr(dtor_ptr) => Some(self.memory.get_fn(dtor_ptr)?), - PrimVal::Bytes(0) => None, - PrimVal::Bytes(_) => return err!(ReadBytesAsPointer), - PrimVal::Undef => return err!(ReadUndefBytes), + let dtor = match self.into_ptr(args[1].value)? { + Scalar::Ptr(dtor_ptr) => Some(self.memory.get_fn(dtor_ptr)?), + Scalar::Bits { defined: 0, .. } => return err!(ReadUndefBytes), + Scalar::Bits { bits: 0, .. } => None, + Scalar::Bits { .. } => return err!(ReadBytesAsPointer), }; // Figure out how large a pthread TLS key actually is. This is libc::pthread_key_t. @@ -498,10 +500,10 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' if key_size.bits() < 128 && key >= (1u128 << key_size.bits() as u128) { return err!(OutOfTls); } - self.memory.write_primval( + self.memory.write_scalar( key_ptr, key_align, - PrimVal::Bytes(key), + Scalar::from_u128(key), key_size, false, )?; @@ -511,20 +513,20 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' } "pthread_key_delete" => { // The conversion into TlsKey here is a little fishy, but should work as long as usize >= libc::pthread_key_t - let key = self.value_to_primval(args[0])?.to_u64()? as TlsKey; + let key = self.value_to_scalar(args[0])?.to_u64()? as TlsKey; self.memory.delete_tls_key(key)?; // Return success (0) self.write_null(dest, dest_ty)?; } "pthread_getspecific" => { // The conversion into TlsKey here is a little fishy, but should work as long as usize >= libc::pthread_key_t - let key = self.value_to_primval(args[0])?.to_u64()? as TlsKey; + let key = self.value_to_scalar(args[0])?.to_u64()? as TlsKey; let ptr = self.memory.load_tls(key)?; self.write_ptr(dest, ptr, dest_ty)?; } "pthread_setspecific" => { // The conversion into TlsKey here is a little fishy, but should work as long as usize >= libc::pthread_key_t - let key = self.value_to_primval(args[0])?.to_u64()? as TlsKey; + let key = self.value_to_scalar(args[0])?.to_u64()? as TlsKey; let new_ptr = self.into_ptr(args[1].value)?; self.memory.store_tls(key, new_ptr)?; @@ -635,8 +637,8 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' match &path[..] { // Allocators are magic. They have no MIR, even when the rest of libstd does. "alloc::alloc::::__rust_alloc" => { - let size = self.value_to_primval(args[0])?.to_u64()?; - let align = self.value_to_primval(args[1])?.to_u64()?; + let size = self.value_to_scalar(args[0])?.to_u64()?; + let align = self.value_to_scalar(args[1])?.to_u64()?; if size == 0 { return err!(HeapAllocZeroBytes); } @@ -646,11 +648,11 @@ 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()))?; - self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?; + self.write_scalar(dest, Scalar::Ptr(ptr), dest_ty)?; } "alloc::alloc::::__rust_alloc_zeroed" => { - let size = self.value_to_primval(args[0])?.to_u64()?; - let align = self.value_to_primval(args[1])?.to_u64()?; + let size = self.value_to_scalar(args[0])?.to_u64()?; + let align = self.value_to_scalar(args[1])?.to_u64()?; if size == 0 { return err!(HeapAllocZeroBytes); } @@ -661,12 +663,12 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' Align::from_bytes(align, align).unwrap(), Some(MemoryKind::Rust.into()))?; self.memory.write_repeat(ptr.into(), 0, Size::from_bytes(size))?; - self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?; + self.write_scalar(dest, Scalar::Ptr(ptr), dest_ty)?; } "alloc::alloc::::__rust_dealloc" => { let ptr = self.into_ptr(args[0].value)?.to_ptr()?; - let old_size = self.value_to_primval(args[1])?.to_u64()?; - let align = self.value_to_primval(args[2])?.to_u64()?; + let old_size = self.value_to_scalar(args[1])?.to_u64()?; + let align = self.value_to_scalar(args[2])?.to_u64()?; if old_size == 0 { return err!(HeapAllocZeroBytes); } @@ -681,9 +683,9 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' } "alloc::alloc::::__rust_realloc" => { let ptr = self.into_ptr(args[0].value)?.to_ptr()?; - let old_size = self.value_to_primval(args[1])?.to_u64()?; - let align = self.value_to_primval(args[2])?.to_u64()?; - let new_size = self.value_to_primval(args[3])?.to_u64()?; + let old_size = self.value_to_scalar(args[1])?.to_u64()?; + let align = self.value_to_scalar(args[2])?.to_u64()?; + let new_size = self.value_to_scalar(args[3])?.to_u64()?; if old_size == 0 || new_size == 0 { return err!(HeapAllocZeroBytes); } @@ -698,7 +700,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' Align::from_bytes(align, align).unwrap(), MemoryKind::Rust.into(), )?; - self.write_primval(dest, PrimVal::Ptr(new_ptr), dest_ty)?; + self.write_scalar(dest, Scalar::Ptr(new_ptr), dest_ty)?; } // A Rust function is missing, which means we are running with MIR missing for libstd (or other dependencies). @@ -720,13 +722,13 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' "std::rt::panicking" => { // we abort on panic -> `std::rt::panicking` always returns false let bool = self.tcx.types.bool; - self.write_primval(dest, PrimVal::from_bool(false), bool)?; + self.write_scalar(dest, Scalar::from_bool(false), bool)?; } "std::sys::imp::c::::AddVectoredExceptionHandler" | "std::sys::imp::c::::SetThreadStackGuarantee" => { let usize = self.tcx.types.usize; // any non zero value works for the stdlib. This is just used for stackoverflows anyway - self.write_primval(dest, PrimVal::Bytes(1), usize)?; + self.write_scalar(dest, Scalar::from_u128(1), usize)?; }, _ => return err!(NoMirFor(path)), } @@ -740,6 +742,6 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' } fn write_null(&mut self, dest: Place, dest_ty: Ty<'tcx>) -> EvalResult<'tcx> { - self.write_primval(dest, PrimVal::Bytes(0), dest_ty) + self.write_scalar(dest, Scalar::null(), dest_ty) } } diff --git a/src/helpers.rs b/src/helpers.rs index a7b94a656da..d881d5c2711 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -1,24 +1,24 @@ use mir; use rustc::ty::Ty; -use rustc::ty::layout::LayoutOf; +use rustc::ty::layout::{LayoutOf, Size}; -use super::{Pointer, EvalResult, PrimVal, EvalContext, ValTy}; +use super::{Scalar, ScalarExt, EvalResult, EvalContext, ValTy}; use rustc_mir::interpret::sign_extend; pub trait EvalContextExt<'tcx> { fn wrapping_pointer_offset( &self, - ptr: Pointer, + ptr: Scalar, pointee_ty: Ty<'tcx>, offset: i64, - ) -> EvalResult<'tcx, Pointer>; + ) -> EvalResult<'tcx, Scalar>; fn pointer_offset( &self, - ptr: Pointer, + ptr: Scalar, pointee_ty: Ty<'tcx>, offset: i64, - ) -> EvalResult<'tcx, Pointer>; + ) -> EvalResult<'tcx, Scalar>; fn value_to_isize( &self, @@ -44,22 +44,22 @@ pub trait EvalContextExt<'tcx> { impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super::Evaluator<'tcx>> { fn wrapping_pointer_offset( &self, - ptr: Pointer, + ptr: Scalar, pointee_ty: Ty<'tcx>, offset: i64, - ) -> EvalResult<'tcx, Pointer> { + ) -> EvalResult<'tcx, Scalar> { // FIXME: assuming here that type size is < i64::max_value() 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) + ptr.ptr_wrapping_signed_offset(offset, self) } fn pointer_offset( &self, - ptr: Pointer, + ptr: Scalar, pointee_ty: Ty<'tcx>, offset: i64, - ) -> EvalResult<'tcx, Pointer> { + ) -> EvalResult<'tcx, Scalar> { // This function raises an error if the offset moves the pointer outside of its allocation. We consider // ZSTs their own huge allocation that doesn't overlap with anything (and nothing moves in there because the size is 0). // We also consider the NULL pointer its own separate allocation, and all the remaining integers pointers their own @@ -76,9 +76,9 @@ 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) { - let ptr = ptr.signed_offset(offset, self)?; + 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 PrimVal::Ptr(ptr) = ptr.into_inner_primval() { + if let Scalar::Ptr(ptr) = ptr { self.memory.check_bounds(ptr, false)?; } else if ptr.is_null()? { // We moved *to* a NULL pointer. That seems wrong, LLVM considers the NULL pointer its own small allocation. Reject this, for now. @@ -95,7 +95,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: value: ValTy<'tcx>, ) -> EvalResult<'tcx, i64> { assert_eq!(value.ty, self.tcx.types.isize); - let raw = self.value_to_primval(value)?.to_bytes()?; + let raw = self.value_to_scalar(value)?.to_bits(self.memory.pointer_size())?; let raw = sign_extend(self.tcx.tcx, raw, self.tcx.types.isize)?; Ok(raw as i64) } @@ -105,7 +105,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: value: ValTy<'tcx>, ) -> EvalResult<'tcx, u64> { assert_eq!(value.ty, self.tcx.types.usize); - self.value_to_primval(value)?.to_bytes().map(|v| v as u64) + self.value_to_scalar(value)?.to_bits(self.memory.pointer_size()).map(|v| v as u64) } fn value_to_i32( @@ -113,7 +113,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: value: ValTy<'tcx>, ) -> EvalResult<'tcx, i32> { assert_eq!(value.ty, self.tcx.types.i32); - let raw = self.value_to_primval(value)?.to_bytes()?; + let raw = self.value_to_scalar(value)?.to_bits(Size::from_bits(32))?; let raw = sign_extend(self.tcx.tcx, raw, self.tcx.types.i32)?; Ok(raw as i32) } @@ -123,6 +123,6 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: value: ValTy<'tcx>, ) -> EvalResult<'tcx, u8> { assert_eq!(value.ty, self.tcx.types.u8); - self.value_to_primval(value)?.to_bytes().map(|v| v as u8) + self.value_to_scalar(value)?.to_bits(Size::from_bits(8)).map(|v| v as u8) } } diff --git a/src/intrinsic.rs b/src/intrinsic.rs index 30de1c68ca6..3d537ea629c 100644 --- a/src/intrinsic.rs +++ b/src/intrinsic.rs @@ -1,12 +1,14 @@ use rustc::mir; -use rustc::ty::layout::{TyLayout, LayoutOf, Size}; +use rustc::ty::layout::{TyLayout, LayoutOf, Size, Primitive, Integer::*}; use rustc::ty; -use rustc::mir::interpret::{EvalResult, PrimVal, PrimValKind, Value, Pointer}; +use rustc::mir::interpret::{EvalResult, Scalar, Value}; use rustc_mir::interpret::{Place, PlaceExtra, HasMemory, EvalContext, ValTy}; use helpers::EvalContextExt as HelperEvalContextExt; +use super::ScalarExt; + pub trait EvalContextExt<'tcx> { fn call_intrinsic( &mut self, @@ -36,7 +38,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: // alignment bigger than the one requested let n = u128::max_value(); let amt = 128 - self.memory.pointer_size().bytes() * 8; - self.write_primval(dest, PrimVal::Bytes((n << amt) >> amt), dest_layout.ty)?; + self.write_scalar(dest, Scalar::from_u128((n << amt) >> amt), dest_layout.ty)?; }, "add_with_overflow" => { @@ -77,7 +79,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: } "assume" => { - let cond = self.value_to_primval(args[0])?.to_bool()?; + let cond = self.value_to_scalar(args[0])?.to_bool()?; if !cond { return err!(AssumptionNotHeld); } @@ -115,16 +117,16 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: let ty = substs.type_at(0); let align = self.layout_of(ty)?.align; let ptr = self.into_ptr(args[0].value)?; - let change = self.value_to_primval(args[1])?; + let change = self.value_to_scalar(args[1])?; let old = self.read_value(ptr, align, ty)?; let old = match old { - Value::ByVal(val) => val, + Value::Scalar(val) => val, Value::ByRef { .. } => bug!("just read the value, can't be byref"), - Value::ByValPair(..) => bug!("atomic_xchg doesn't work with nonprimitives"), + Value::ScalarPair(..) => bug!("atomic_xchg doesn't work with nonprimitives"), }; - self.write_primval(dest, old, ty)?; - self.write_primval( - Place::from_primval_ptr(ptr, align), + self.write_scalar(dest, old, ty)?; + self.write_scalar( + Place::from_scalar_ptr(ptr, align), change, ty, )?; @@ -134,22 +136,22 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: let ty = substs.type_at(0); let align = self.layout_of(ty)?.align; let ptr = self.into_ptr(args[0].value)?; - let expect_old = self.value_to_primval(args[1])?; - let change = self.value_to_primval(args[2])?; + let expect_old = self.value_to_scalar(args[1])?; + let change = self.value_to_scalar(args[2])?; let old = self.read_value(ptr, align, ty)?; let old = match old { - Value::ByVal(val) => val, + Value::Scalar(val) => val, Value::ByRef { .. } => bug!("just read the value, can't be byref"), - Value::ByValPair(..) => bug!("atomic_cxchg doesn't work with nonprimitives"), + Value::ScalarPair(..) => bug!("atomic_cxchg doesn't work with nonprimitives"), }; let (val, _) = self.binary_op(mir::BinOp::Eq, old, ty, expect_old, ty)?; let valty = ValTy { - value: Value::ByValPair(old, val), + value: Value::ScalarPair(old, val), ty: dest_layout.ty, }; self.write_value(valty, dest)?; - self.write_primval( - Place::from_primval_ptr(ptr, dest_layout.align), + self.write_scalar( + Place::from_scalar_ptr(ptr, dest_layout.align), change, ty, )?; @@ -183,16 +185,16 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: let ty = substs.type_at(0); let align = self.layout_of(ty)?.align; let ptr = self.into_ptr(args[0].value)?; - let change = self.value_to_primval(args[1])?; + let change = self.value_to_scalar(args[1])?; let old = self.read_value(ptr, align, ty)?; let old = match old { - Value::ByVal(val) => val, + Value::Scalar(val) => val, Value::ByRef { .. } => bug!("just read the value, can't be byref"), - Value::ByValPair(..) => { + Value::ScalarPair(..) => { bug!("atomic_xadd_relaxed doesn't work with nonprimitives") } }; - self.write_primval(dest, old, ty)?; + self.write_scalar(dest, old, ty)?; let op = match intrinsic_name.split('_').nth(1).unwrap() { "or" => mir::BinOp::BitOr, "xor" => mir::BinOp::BitXor, @@ -203,7 +205,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: }; // FIXME: what do atomics do on overflow? let (val, _) = self.binary_op(op, old, ty, change, ty)?; - self.write_primval(Place::from_primval_ptr(ptr, dest_layout.align), val, ty)?; + self.write_scalar(Place::from_scalar_ptr(ptr, dest_layout.align), val, ty)?; } "breakpoint" => unimplemented!(), // halt miri @@ -233,8 +235,11 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: "ctpop" | "cttz" | "cttz_nonzero" | "ctlz" | "ctlz_nonzero" | "bswap" => { let ty = substs.type_at(0); - let num = self.value_to_primval(args[0])?.to_bytes()?; - let kind = self.ty_to_primval_kind(ty)?; + let num = self.value_to_scalar(args[0])?.to_bytes()?; + let kind = match self.layout_of(ty)?.abi { + ty::layout::Abi::Scalar(ref scalar) => scalar.value, + _ => Err(::rustc::mir::interpret::EvalErrorKind::TypeNotPrimitive(ty))?, + }; let num = if intrinsic_name.ends_with("_nonzero") { if num == 0 { return err!(Intrinsic(format!("{} called on 0", intrinsic_name))); @@ -243,21 +248,21 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: } else { numeric_intrinsic(intrinsic_name, num, kind)? }; - self.write_primval(dest, num, ty)?; + self.write_scalar(dest, num, ty)?; } "discriminant_value" => { let ty = substs.type_at(0); let adt_ptr = self.into_ptr(args[0].value)?; let adt_align = self.layout_of(args[0].ty)?.align; - let place = Place::from_primval_ptr(adt_ptr, adt_align); + let place = Place::from_scalar_ptr(adt_ptr, adt_align); let discr_val = self.read_discriminant_value(place, ty)?; - self.write_primval(dest, PrimVal::Bytes(discr_val), dest_layout.ty)?; + self.write_scalar(dest, Scalar::from_u128(discr_val), dest_layout.ty)?; } "sinf32" | "fabsf32" | "cosf32" | "sqrtf32" | "expf32" | "exp2f32" | "logf32" | "log10f32" | "log2f32" | "floorf32" | "ceilf32" | "truncf32" => { - let f = self.value_to_primval(args[0])?.to_bytes()?; + let f = self.value_to_scalar(args[0])?.to_bytes()?; let f = f32::from_bits(f as u32); let f = match intrinsic_name { "sinf32" => f.sin(), @@ -274,12 +279,12 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: "truncf32" => f.trunc(), _ => bug!(), }; - self.write_primval(dest, PrimVal::Bytes(f.to_bits() as u128), dest_layout.ty)?; + self.write_scalar(dest, Scalar::from_f32(f), dest_layout.ty)?; } "sinf64" | "fabsf64" | "cosf64" | "sqrtf64" | "expf64" | "exp2f64" | "logf64" | "log10f64" | "log2f64" | "floorf64" | "ceilf64" | "truncf64" => { - let f = self.value_to_primval(args[0])?.to_bytes()?; + let f = self.value_to_scalar(args[0])?.to_bytes()?; let f = f64::from_bits(f as u64); let f = match intrinsic_name { "sinf64" => f.sin(), @@ -296,13 +301,13 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: "truncf64" => f.trunc(), _ => bug!(), }; - self.write_primval(dest, PrimVal::Bytes(f.to_bits() as u128), dest_layout.ty)?; + self.write_scalar(dest, Scalar::from_f64(f), dest_layout.ty)?; } "fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => { let ty = substs.type_at(0); - let a = self.value_to_primval(args[0])?; - let b = self.value_to_primval(args[1])?; + let a = self.value_to_scalar(args[0])?; + let b = self.value_to_scalar(args[1])?; let op = match intrinsic_name { "fadd_fast" => mir::BinOp::Add, "fsub_fast" => mir::BinOp::Sub, @@ -312,21 +317,21 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: _ => bug!(), }; let result = self.binary_op(op, a, ty, b, ty)?; - self.write_primval(dest, result.0, dest_layout.ty)?; + self.write_scalar(dest, result.0, dest_layout.ty)?; } "exact_div" => { // Performs an exact division, resulting in undefined behavior where // `x % y != 0` or `y == 0` or `x == T::min_value() && y == -1` let ty = substs.type_at(0); - let a = self.value_to_primval(args[0])?; - let b = self.value_to_primval(args[1])?; + let a = self.value_to_scalar(args[0])?; + let b = self.value_to_scalar(args[1])?; // check x % y != 0 - if self.binary_op(mir::BinOp::Rem, a, ty, b, ty)?.0 != PrimVal::Bytes(0) { + if self.binary_op(mir::BinOp::Rem, a, ty, b, ty)?.0 != Scalar::null() { return err!(ValidationFailure(format!("exact_div: {:?} cannot be divided by {:?}", a, b))); } let result = self.binary_op(mir::BinOp::Div, a, ty, b, ty)?; - self.write_primval(dest, result.0, dest_layout.ty)?; + self.write_scalar(dest, result.0, dest_layout.ty)?; }, "likely" | "unlikely" | "forget" => {} @@ -341,21 +346,21 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: val } // TODO(solson): Revisit this, it's fishy to check for Undef here. - Value::ByVal(PrimVal::Undef) => { - match this.ty_to_primval_kind(dest_layout.ty) { - Ok(_) => Value::ByVal(PrimVal::Bytes(0)), - Err(_) => { + Value::Scalar(Scalar::Bits { defined: 0, .. }) => { + match this.layout_of(dest_layout.ty)?.abi { + ty::layout::Abi::Scalar(_) => Value::Scalar(Scalar::null()), + _ => { // 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)); + let ptr = Scalar::Ptr(ptr); this.memory.write_repeat(ptr, 0, size)?; Value::ByRef(ptr, dest_layout.align) } } } - Value::ByVal(_) => Value::ByVal(PrimVal::Bytes(0)), - Value::ByValPair(..) => { - Value::ByValPair(PrimVal::Bytes(0), PrimVal::Bytes(0)) + Value::Scalar(_) => Value::Scalar(Scalar::null()), + Value::ScalarPair(..) => { + Value::ScalarPair(Scalar::null(), Scalar::null()) } }; Ok(zero_val) @@ -376,16 +381,16 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: "min_align_of" => { let elem_ty = substs.type_at(0); 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)?; + let align_val = Scalar::from_u128(elem_align as u128); + self.write_scalar(dest, align_val, dest_layout.ty)?; } "pref_align_of" => { let ty = substs.type_at(0); 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)?; + let align_val = Scalar::from_u128(align as u128); + self.write_scalar(dest, align_val, dest_layout.ty)?; } "move_val_init" => { @@ -399,9 +404,9 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: let ty = substs.type_at(0); let env = ty::ParamEnv::reveal_all(); let needs_drop = ty.needs_drop(self.tcx.tcx, env); - self.write_primval( + self.write_scalar( dest, - PrimVal::from_bool(needs_drop), + Scalar::from_bool(needs_drop), dest_layout.ty, )?; } @@ -444,75 +449,75 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: } "powf32" => { - let f = self.value_to_primval(args[0])?.to_bytes()?; + let f = self.value_to_scalar(args[0])?.to_bits(Size::from_bits(32))?; let f = f32::from_bits(f as u32); - let f2 = self.value_to_primval(args[1])?.to_bytes()?; + let f2 = self.value_to_scalar(args[1])?.to_bits(Size::from_bits(32))?; let f2 = f32::from_bits(f2 as u32); - self.write_primval( + self.write_scalar( dest, - PrimVal::Bytes(f.powf(f2).to_bits() as u128), + Scalar::from_f32(f.powf(f2)), dest_layout.ty, )?; } "powf64" => { - let f = self.value_to_primval(args[0])?.to_bytes()?; + let f = self.value_to_scalar(args[0])?.to_bits(Size::from_bits(64))?; let f = f64::from_bits(f as u64); - let f2 = self.value_to_primval(args[1])?.to_bytes()?; + let f2 = self.value_to_scalar(args[1])?.to_bits(Size::from_bits(64))?; let f2 = f64::from_bits(f2 as u64); - self.write_primval( + self.write_scalar( dest, - PrimVal::Bytes(f.powf(f2).to_bits() as u128), + Scalar::from_f64(f.powf(f2)), dest_layout.ty, )?; } "fmaf32" => { - let a = self.value_to_primval(args[0])?.to_bytes()?; + let a = self.value_to_scalar(args[0])?.to_bits(Size::from_bits(32))?; let a = f32::from_bits(a as u32); - let b = self.value_to_primval(args[1])?.to_bytes()?; + let b = self.value_to_scalar(args[1])?.to_bits(Size::from_bits(32))?; let b = f32::from_bits(b as u32); - let c = self.value_to_primval(args[2])?.to_bytes()?; + let c = self.value_to_scalar(args[2])?.to_bits(Size::from_bits(32))?; let c = f32::from_bits(c as u32); - self.write_primval( + self.write_scalar( dest, - PrimVal::Bytes((a * b + c).to_bits() as u128), + Scalar::from_f32(a * b + c), dest_layout.ty, )?; } "fmaf64" => { - let a = self.value_to_primval(args[0])?.to_bytes()?; + let a = self.value_to_scalar(args[0])?.to_bits(Size::from_bits(64))?; let a = f64::from_bits(a as u64); - let b = self.value_to_primval(args[1])?.to_bytes()?; + let b = self.value_to_scalar(args[1])?.to_bits(Size::from_bits(64))?; let b = f64::from_bits(b as u64); - let c = self.value_to_primval(args[2])?.to_bytes()?; + let c = self.value_to_scalar(args[2])?.to_bits(Size::from_bits(64))?; let c = f64::from_bits(c as u64); - self.write_primval( + self.write_scalar( dest, - PrimVal::Bytes((a * b + c).to_bits() as u128), + Scalar::from_f64(a * b + c), dest_layout.ty, )?; } "powif32" => { - let f = self.value_to_primval(args[0])?.to_bytes()?; + let f = self.value_to_scalar(args[0])?.to_bits(Size::from_bits(32))?; let f = f32::from_bits(f as u32); let i = self.value_to_i32(args[1])?; - self.write_primval( + self.write_scalar( dest, - PrimVal::Bytes(f.powi(i).to_bits() as u128), + Scalar::from_f32(f.powi(i)), dest_layout.ty, )?; } "powif64" => { - let f = self.value_to_primval(args[0])?.to_bytes()?; + let f = self.value_to_scalar(args[0])?.to_bits(Size::from_bits(64))?; let f = f64::from_bits(f as u64); let i = self.value_to_i32(args[1])?; - self.write_primval( + self.write_scalar( dest, - PrimVal::Bytes(f.powi(i).to_bits() as u128), + Scalar::from_f64(f.powi(i)), dest_layout.ty, )?; } @@ -520,15 +525,15 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: "size_of" => { let ty = substs.type_at(0); let size = self.layout_of(ty)?.size.bytes().into(); - self.write_primval(dest, PrimVal::from_u128(size), dest_layout.ty)?; + self.write_scalar(dest, Scalar::from_u128(size), dest_layout.ty)?; } "size_of_val" => { let ty = substs.type_at(0); let (size, _) = self.size_and_align_of_dst(ty, args[0].value)?; - self.write_primval( + self.write_scalar( dest, - PrimVal::from_u128(size.bytes() as u128), + Scalar::from_u128(size.bytes() as u128), dest_layout.ty, )?; } @@ -537,9 +542,9 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: "align_of_val" => { let ty = substs.type_at(0); let (_, align) = self.size_and_align_of_dst(ty, args[0].value)?; - self.write_primval( + self.write_scalar( dest, - PrimVal::from_u128(align.abi() as u128), + Scalar::from_u128(align.abi() as u128), dest_layout.ty, )?; } @@ -553,7 +558,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: "type_id" => { let ty = substs.type_at(0); let n = self.tcx.type_id_hash(ty); - self.write_primval(dest, PrimVal::Bytes(n as u128), dest_layout.ty)?; + self.write_scalar(dest, Scalar::Bits { bits: n as u128, defined: 64 }, dest_layout.ty)?; } "transmute" => { @@ -566,7 +571,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: "unchecked_shl" => { let bits = dest_layout.size.bytes() as u128 * 8; - let rhs = self.value_to_primval(args[1])? + let rhs = self.value_to_scalar(args[1])? .to_bytes()?; if rhs >= bits { return err!(Intrinsic( @@ -584,7 +589,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: "unchecked_shr" => { let bits = dest_layout.size.bytes() as u128 * 8; - let rhs = self.value_to_primval(args[1])? + let rhs = self.value_to_scalar(args[1])? .to_bytes()?; if rhs >= bits { return err!(Intrinsic( @@ -601,7 +606,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: } "unchecked_div" => { - let rhs = self.value_to_primval(args[1])? + let rhs = self.value_to_scalar(args[1])? .to_bytes()?; if rhs == 0 { return err!(Intrinsic(format!("Division by 0 in unchecked_div"))); @@ -616,7 +621,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: } "unchecked_rem" => { - let rhs = self.value_to_primval(args[1])? + let rhs = self.value_to_scalar(args[1])? .to_bytes()?; if rhs == 0 { return err!(Intrinsic(format!("Division by 0 in unchecked_rem"))); @@ -637,7 +642,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: this.memory.mark_definedness(ptr, size, false)?; Ok(val) } - _ => Ok(Value::ByVal(PrimVal::Undef)), + _ => Ok(Value::Scalar(Scalar::undef())), }; match dest { Place::Local { frame, local } => self.modify_local(frame, local, uninit)?, @@ -681,26 +686,25 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: fn numeric_intrinsic<'tcx>( name: &str, bytes: u128, - kind: PrimValKind, -) -> EvalResult<'tcx, PrimVal> { + kind: Primitive, +) -> EvalResult<'tcx, Scalar> { macro_rules! integer_intrinsic { ($method:ident) => ({ - use rustc::mir::interpret::PrimValKind::*; let result_bytes = match kind { - I8 => (bytes as i8).$method() as u128, - U8 => (bytes as u8).$method() as u128, - I16 => (bytes as i16).$method() as u128, - U16 => (bytes as u16).$method() as u128, - I32 => (bytes as i32).$method() as u128, - U32 => (bytes as u32).$method() as u128, - I64 => (bytes as i64).$method() as u128, - U64 => (bytes as u64).$method() as u128, - I128 => (bytes as i128).$method() as u128, - U128 => bytes.$method() as u128, + Primitive::Int(I8, true) => (bytes as i8).$method() as u128, + Primitive::Int(I8, false) => (bytes as u8).$method() as u128, + Primitive::Int(I16, true) => (bytes as i16).$method() as u128, + Primitive::Int(I16, false) => (bytes as u16).$method() as u128, + Primitive::Int(I32, true) => (bytes as i32).$method() as u128, + Primitive::Int(I32, false) => (bytes as u32).$method() as u128, + Primitive::Int(I64, true) => (bytes as i64).$method() as u128, + Primitive::Int(I64, false) => (bytes as u64).$method() as u128, + Primitive::Int(I128, true) => (bytes as i128).$method() as u128, + Primitive::Int(I128, false) => bytes.$method() as u128, _ => bug!("invalid `{}` argument: {:?}", name, bytes), }; - PrimVal::Bytes(result_bytes) + Scalar::from_u128(result_bytes) }); } diff --git a/src/lib.rs b/src/lib.rs index f8119245b48..e3c83c284db 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -53,6 +53,81 @@ use validation::EvalContextExt as ValidationEvalContextExt; use range_map::RangeMap; use validation::{ValidationQuery, AbsPlace}; +pub trait ScalarExt { + fn null() -> Self; + fn from_i8(i: i8) -> Self; + fn from_u128(i: u128) -> Self; + fn from_i128(i: i128) -> Self; + fn from_usize(i: u64, ptr_size: Size) -> Self; + fn from_isize(i: i64, ptr_size: Size) -> Self; + fn from_f32(f: f32) -> Self; + fn from_f64(f: f64) -> Self; + fn to_u64(self) -> EvalResult<'static, u64>; + fn is_null(self) -> EvalResult<'static, bool>; + fn to_bytes(self) -> EvalResult<'static, u128>; +} + +impl ScalarExt for Scalar { + fn null() -> Self { + Scalar::Bits { bits: 0, defined: 128 } + } + + fn from_i8(i: i8) -> Self { + Scalar::Bits { bits: i as i128 as u128, defined: 8 } + } + + fn from_u128(i: u128) -> Self { + Scalar::Bits { bits: i, defined: 128 } + } + + fn from_i128(i: i128) -> Self { + Scalar::Bits { bits: i as u128, defined: 128 } + } + + fn from_usize(i: u64, ptr_size: Size) -> Self { + Scalar::Bits { bits: i as u128, defined: ptr_size.bits() as u8 } + } + + fn from_isize(i: i64, ptr_size: Size) -> Self { + Scalar::Bits { bits: i as i128 as u128, defined: ptr_size.bits() as u8 } + } + + fn from_f32(f: f32) -> Self { + Scalar::Bits { bits: f.to_bits() as u128, defined: 32 } + } + + fn from_f64(f: f64) -> Self { + Scalar::Bits { bits: f.to_bits() as u128, defined: 64 } + } + + fn to_u64(self) -> EvalResult<'static, u64> { + let b = self.to_bits(Size::from_bits(64))?; + assert_eq!(b as u64 as u128, b); + Ok(b as u64) + } + + fn is_null(self) -> EvalResult<'static, bool> { + match self { + Scalar::Bits { bits, defined } => { + if defined > 0 { + Ok(bits == 0) + } else { + err!(ReadUndefBytes) + } + } + Scalar::Ptr(_) => Ok(false) + } + } + + fn to_bytes(self) -> EvalResult<'static, u128> { + match self { + Scalar::Bits { defined: 0, .. } => err!(ReadUndefBytes), + Scalar::Bits { bits, .. } => Ok(bits), + Scalar::Ptr(_) => err!(ReadPointerAsBytes), + } + } +} + pub fn eval_main<'a, 'tcx: 'a>( tcx: TyCtxt<'a, 'tcx, 'tcx>, main_id: DefId, @@ -65,7 +140,7 @@ pub fn eval_main<'a, 'tcx: 'a>( ) -> EvalResult<'tcx> { let main_instance = ty::Instance::mono(ecx.tcx.tcx, main_id); let main_mir = ecx.load_mir(main_instance.def)?; - let mut cleanup_ptr = None; // Pointer to be deallocated when we are done + let mut cleanup_ptr = None; // Scalar to be deallocated when we are done if !main_mir.return_ty().is_nil() || main_mir.arg_count != 0 { return err!(Unimplemented( @@ -116,7 +191,7 @@ pub fn eval_main<'a, 'tcx: 'a>( let main_ptr_ty = ecx.tcx.mk_fn_ptr(main_ty.fn_sig(ecx.tcx.tcx)); ecx.write_value( ValTy { - value: Value::ByVal(PrimVal::Ptr(main_ptr)), + value: Value::Scalar(Scalar::Ptr(main_ptr)), ty: main_ptr_ty, }, dest, @@ -125,7 +200,7 @@ pub fn eval_main<'a, 'tcx: 'a>( // Second argument (argc): 1 let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?; let ty = ecx.tcx.types.isize; - ecx.write_primval(dest, PrimVal::Bytes(1), ty)?; + ecx.write_scalar(dest, Scalar::from_u128(1), ty)?; // FIXME: extract main source file path // Third argument (argv): &[b"foo"] @@ -135,7 +210,7 @@ pub fn eval_main<'a, 'tcx: 'a>( 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)?; - ecx.memory.write_primval(foo_ptr.into(), ptr_align, PrimVal::Ptr(foo.into()), ptr_size, false)?; + 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)?; @@ -145,7 +220,7 @@ pub fn eval_main<'a, 'tcx: 'a>( main_instance, main_mir.span, main_mir, - Place::from_primval_ptr(PrimVal::Bytes(1).into(), ty::layout::Align::from_bytes(1, 1).unwrap()), + Place::from_scalar_ptr(Scalar::from_u128(1), ty::layout::Align::from_bytes(1, 1).unwrap()), StackPopCleanup::None, )?; @@ -187,6 +262,7 @@ pub fn eval_main<'a, 'tcx: 'a>( } } } + ::std::process::exit(1); } } } @@ -195,7 +271,7 @@ pub fn eval_main<'a, 'tcx: 'a>( pub struct Evaluator<'tcx> { /// Environment variables set by `setenv` /// Miri does not expose env vars from the host to the emulated program - pub(crate) env_vars: HashMap, MemoryPointer>, + pub(crate) env_vars: HashMap, Pointer>, /// Places that were suspended by the validation subsystem, and will be recovered later pub(crate) suspended: HashMap>>, @@ -205,7 +281,7 @@ pub type TlsKey = usize; #[derive(Copy, Clone, Debug)] pub struct TlsEntry<'tcx> { - data: Pointer, // Will eventually become a map from thread IDs to `Pointer`s, if we ever support more than one thread. + data: Scalar, // Will eventually become a map from thread IDs to `Scalar`s, if we ever support more than one thread. dtor: Option>, } @@ -256,11 +332,11 @@ impl<'mir, 'tcx: 'mir> Machine<'mir, 'tcx> for Evaluator<'tcx> { fn try_ptr_op<'a>( ecx: &rustc_mir::interpret::EvalContext<'a, 'mir, 'tcx, Self>, bin_op: mir::BinOp, - left: PrimVal, + left: Scalar, left_ty: ty::Ty<'tcx>, - right: PrimVal, + right: Scalar, right_ty: ty::Ty<'tcx>, - ) -> EvalResult<'tcx, Option<(PrimVal, bool)>> { + ) -> EvalResult<'tcx, Option<(Scalar, bool)>> { ecx.ptr_op(bin_op, left, left_ty, right, right_ty) } @@ -372,7 +448,7 @@ impl<'mir, 'tcx: 'mir> Machine<'mir, 'tcx> for Evaluator<'tcx> { let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?; ecx.write_value( ValTy { - value: Value::ByVal(PrimVal::Bytes(match layout.size.bytes() { + value: Value::Scalar(Scalar::from_u128(match layout.size.bytes() { 0 => 1 as u128, size => size as u128, }.into())), @@ -385,7 +461,7 @@ impl<'mir, 'tcx: 'mir> Machine<'mir, 'tcx> for Evaluator<'tcx> { let dest = ecx.eval_place(&mir::Place::Local(args.next().unwrap()))?; ecx.write_value( ValTy { - value: Value::ByVal(PrimVal::Bytes(layout.align.abi().into())), + value: Value::Scalar(Scalar::from_u128(layout.align.abi().into())), ty: usize, }, dest, @@ -406,7 +482,7 @@ impl<'mir, 'tcx: 'mir> Machine<'mir, 'tcx> for Evaluator<'tcx> { fn check_locks<'a>( mem: &Memory<'a, 'mir, 'tcx, Self>, - ptr: MemoryPointer, + ptr: Pointer, size: Size, access: AccessKind, ) -> EvalResult<'tcx> { @@ -437,7 +513,7 @@ impl<'mir, 'tcx: 'mir> Machine<'mir, 'tcx> for Evaluator<'tcx> { .map_err(|lock| { EvalErrorKind::DeallocatedLockedMemory { //ptr, FIXME - ptr: MemoryPointer { + ptr: Pointer { alloc_id: AllocId(0), offset: Size::from_bytes(0), }, diff --git a/src/locks.rs b/src/locks.rs index 9efbabc7171..a463f8ba575 100644 --- a/src/locks.rs +++ b/src/locks.rs @@ -70,27 +70,27 @@ impl<'tcx> LockInfo<'tcx> { pub trait MemoryExt<'tcx> { fn check_locks( &self, - ptr: MemoryPointer, + ptr: Pointer, len: u64, access: AccessKind, ) -> EvalResult<'tcx>; fn acquire_lock( &mut self, - ptr: MemoryPointer, + ptr: Pointer, len: u64, region: Option, kind: AccessKind, ) -> EvalResult<'tcx>; fn suspend_write_lock( &mut self, - ptr: MemoryPointer, + ptr: Pointer, len: u64, lock_path: &AbsPlace<'tcx>, suspend: Option, ) -> EvalResult<'tcx>; fn recover_write_lock( &mut self, - ptr: MemoryPointer, + ptr: Pointer, len: u64, lock_path: &AbsPlace<'tcx>, lock_region: Option, @@ -103,7 +103,7 @@ pub trait MemoryExt<'tcx> { impl<'a, 'mir, 'tcx: 'mir + 'a> MemoryExt<'tcx> for Memory<'a, 'mir, 'tcx, Evaluator<'tcx>> { fn check_locks( &self, - ptr: MemoryPointer, + ptr: Pointer, len: u64, access: AccessKind, ) -> EvalResult<'tcx> { @@ -132,7 +132,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> MemoryExt<'tcx> for Memory<'a, 'mir, 'tcx, Evalu /// Acquire the lock for the given lifetime fn acquire_lock( &mut self, - ptr: MemoryPointer, + ptr: Pointer, len: u64, region: Option, kind: AccessKind, @@ -191,7 +191,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> MemoryExt<'tcx> for Memory<'a, 'mir, 'tcx, Evalu /// When suspending, the same cases are fine; we just register an additional suspension. fn suspend_write_lock( &mut self, - ptr: MemoryPointer, + ptr: Pointer, len: u64, lock_path: &AbsPlace<'tcx>, suspend: Option, @@ -264,7 +264,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> MemoryExt<'tcx> for Memory<'a, 'mir, 'tcx, Evalu /// Release a suspension from the write lock. If this is the last suspension or if there is no suspension, acquire the lock. fn recover_write_lock( &mut self, - ptr: MemoryPointer, + ptr: Pointer, len: u64, lock_path: &AbsPlace<'tcx>, lock_region: Option, diff --git a/src/operator.rs b/src/operator.rs index 557e07975d7..721b4f0bfdd 100644 --- a/src/operator.rs +++ b/src/operator.rs @@ -1,4 +1,5 @@ use rustc::ty; +use rustc::ty::layout::Primitive; use rustc::mir; use super::*; @@ -9,38 +10,58 @@ pub trait EvalContextExt<'tcx> { fn ptr_op( &self, bin_op: mir::BinOp, - left: PrimVal, + left: Scalar, left_ty: ty::Ty<'tcx>, - right: PrimVal, + right: Scalar, right_ty: ty::Ty<'tcx>, - ) -> EvalResult<'tcx, Option<(PrimVal, bool)>>; + ) -> EvalResult<'tcx, Option<(Scalar, bool)>>; fn ptr_int_arithmetic( &self, bin_op: mir::BinOp, - left: MemoryPointer, + left: Pointer, right: i128, signed: bool, - ) -> EvalResult<'tcx, (PrimVal, bool)>; + ) -> EvalResult<'tcx, (Scalar, bool)>; } impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super::Evaluator<'tcx>> { fn ptr_op( &self, bin_op: mir::BinOp, - left: PrimVal, + left: Scalar, left_ty: ty::Ty<'tcx>, - right: PrimVal, + right: Scalar, right_ty: ty::Ty<'tcx>, - ) -> EvalResult<'tcx, Option<(PrimVal, bool)>> { - use rustc::mir::interpret::PrimValKind::*; + ) -> EvalResult<'tcx, Option<(Scalar, bool)>> { use rustc::mir::BinOp::*; - let usize = PrimValKind::from_uint_size(self.memory.pointer_size()); - let isize = PrimValKind::from_int_size(self.memory.pointer_size()); - let left_kind = self.ty_to_primval_kind(left_ty)?; - let right_kind = self.ty_to_primval_kind(right_ty)?; + use rustc::ty::layout::Integer::*; + let usize = Primitive::Int(match self.memory.pointer_size().bytes() { + 1 => I8, + 2 => I16, + 4 => I32, + 8 => I64, + 16 => I128, + _ => unreachable!(), + }, false); + let isize = Primitive::Int(match self.memory.pointer_size().bytes() { + 1 => I8, + 2 => I16, + 4 => I32, + 8 => I64, + 16 => I128, + _ => unreachable!(), + }, true); + let left_kind = match self.layout_of(left_ty)?.abi { + ty::layout::Abi::Scalar(ref scalar) => scalar.value, + _ => Err(EvalErrorKind::TypeNotPrimitive(left_ty))?, + }; + let right_kind = match self.layout_of(right_ty)?.abi { + ty::layout::Abi::Scalar(ref scalar) => scalar.value, + _ => Err(EvalErrorKind::TypeNotPrimitive(right_ty))?, + }; match bin_op { - Offset if left_kind == Ptr && right_kind == usize => { + Offset if left_kind == Primitive::Pointer && right_kind == usize => { let pointee_ty = left_ty .builtin_deref(true) .expect("Offset called on non-ptr type") @@ -48,35 +69,35 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: let ptr = self.pointer_offset( left.into(), pointee_ty, - right.to_bytes()? as i64, + right.to_bits(self.memory.pointer_size())? as i64, )?; - Ok(Some((ptr.into_inner_primval(), false))) + Ok(Some((ptr, false))) } // These work on anything Eq if left_kind == right_kind => { let result = match (left, right) { - (PrimVal::Bytes(left), PrimVal::Bytes(right)) => left == right, - (PrimVal::Ptr(left), PrimVal::Ptr(right)) => left == right, - (PrimVal::Undef, _) | - (_, PrimVal::Undef) => return err!(ReadUndefBytes), + (Scalar::Bits { .. }, Scalar::Bits { .. }) => { + left.to_bits(self.memory.pointer_size())? == right.to_bits(self.memory.pointer_size())? + }, + (Scalar::Ptr(left), Scalar::Ptr(right)) => left == right, _ => false, }; - Ok(Some((PrimVal::from_bool(result), false))) + Ok(Some((Scalar::from_bool(result), false))) } Ne if left_kind == right_kind => { let result = match (left, right) { - (PrimVal::Bytes(left), PrimVal::Bytes(right)) => left != right, - (PrimVal::Ptr(left), PrimVal::Ptr(right)) => left != right, - (PrimVal::Undef, _) | - (_, PrimVal::Undef) => return err!(ReadUndefBytes), + (Scalar::Bits { .. }, Scalar::Bits { .. }) => { + left.to_bits(self.memory.pointer_size())? != right.to_bits(self.memory.pointer_size())? + }, + (Scalar::Ptr(left), Scalar::Ptr(right)) => left != right, _ => true, }; - Ok(Some((PrimVal::from_bool(result), false))) + Ok(Some((Scalar::from_bool(result), false))) } // These need both pointers to be in the same allocation Lt | Le | Gt | Ge | Sub if left_kind == right_kind && - (left_kind == Ptr || left_kind == usize || left_kind == isize) && + (left_kind == Primitive::Pointer || left_kind == usize || left_kind == isize) && left.is_ptr() && right.is_ptr() => { let left = left.to_ptr()?; let right = right.to_ptr()?; @@ -89,15 +110,15 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: Sub => { return self.binary_op( Sub, - PrimVal::Bytes(left.offset.bytes() as u128), + Scalar::Bits { bits: left.offset.bytes() as u128, defined: self.memory.pointer_size().bits() as u8 }, self.tcx.types.usize, - PrimVal::Bytes(right.offset.bytes() as u128), + Scalar::Bits { bits: right.offset.bytes() as u128, defined: self.memory.pointer_size().bits() as u8 }, self.tcx.types.usize, ).map(Some) } _ => bug!("We already established it has to be one of these operators."), }; - Ok(Some((PrimVal::from_bool(res), false))) + Ok(Some((Scalar::from_bool(res), false))) } else { // Both are pointers, but from different allocations. err!(InvalidPointerMath) @@ -106,23 +127,23 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: // These work if one operand is a pointer, the other an integer Add | BitAnd | Sub if left_kind == right_kind && (left_kind == usize || left_kind == isize) && - left.is_ptr() && right.is_bytes() => { + left.is_ptr() && right.is_bits() => { // Cast to i128 is fine as we checked the kind to be ptr-sized self.ptr_int_arithmetic( bin_op, left.to_ptr()?, - right.to_bytes()? as i128, + right.to_bits(self.memory.pointer_size())? as i128, left_kind == isize, ).map(Some) } Add | BitAnd if left_kind == right_kind && (left_kind == usize || left_kind == isize) && - left.is_bytes() && right.is_ptr() => { + left.is_bits() && right.is_ptr() => { // This is a commutative operation, just swap the operands self.ptr_int_arithmetic( bin_op, right.to_ptr()?, - left.to_bytes()? as i128, + left.to_bits(self.memory.pointer_size())? as i128, left_kind == isize, ).map(Some) } @@ -133,14 +154,14 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: fn ptr_int_arithmetic( &self, bin_op: mir::BinOp, - left: MemoryPointer, + left: Pointer, right: i128, signed: bool, - ) -> EvalResult<'tcx, (PrimVal, bool)> { + ) -> EvalResult<'tcx, (Scalar, bool)> { use rustc::mir::BinOp::*; - fn map_to_primval((res, over): (MemoryPointer, bool)) -> (PrimVal, bool) { - (PrimVal::Ptr(res), over) + fn map_to_primval((res, over): (Pointer, bool)) -> (Scalar, bool) { + (Scalar::Ptr(res), over) } Ok(match bin_op { @@ -157,10 +178,10 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: let right = right as u64; if right & base_mask == base_mask { // Case 1: The base address bits are all preserved, i.e., right is all-1 there - (PrimVal::Ptr(MemoryPointer::new(left.alloc_id, Size::from_bytes(left.offset.bytes() & right))), false) + (Scalar::Ptr(Pointer::new(left.alloc_id, Size::from_bytes(left.offset.bytes() & right))), false) } else if right & base_mask == 0 { // Case 2: The base address bits are all taken away, i.e., right is all-0 there - (PrimVal::from_u128((left.offset.bytes() & right) as u128), false) + (Scalar::Bits { bits: (left.offset.bytes() & right) as u128, defined: 128 }, false) } else { return err!(ReadPointerAsBytes); } diff --git a/src/tls.rs b/src/tls.rs index e55cbede233..7f49509ef42 100644 --- a/src/tls.rs +++ b/src/tls.rs @@ -1,17 +1,17 @@ use rustc::{ty, mir}; -use super::{TlsKey, TlsEntry, EvalResult, EvalErrorKind, Pointer, Memory, Evaluator, Place, - StackPopCleanup, EvalContext}; +use super::{TlsKey, TlsEntry, EvalResult, EvalErrorKind, Scalar, ScalarExt, Memory, Evaluator, + Place, StackPopCleanup, EvalContext}; pub trait MemoryExt<'tcx> { fn create_tls_key(&mut self, dtor: Option>) -> TlsKey; fn delete_tls_key(&mut self, key: TlsKey) -> EvalResult<'tcx>; - fn load_tls(&mut self, key: TlsKey) -> EvalResult<'tcx, Pointer>; - fn store_tls(&mut self, key: TlsKey, new_data: Pointer) -> EvalResult<'tcx>; + fn load_tls(&mut self, key: TlsKey) -> EvalResult<'tcx, Scalar>; + fn store_tls(&mut self, key: TlsKey, new_data: Scalar) -> EvalResult<'tcx>; fn fetch_tls_dtor( &mut self, key: Option, - ) -> EvalResult<'tcx, Option<(ty::Instance<'tcx>, Pointer, TlsKey)>>; + ) -> EvalResult<'tcx, Option<(ty::Instance<'tcx>, Scalar, TlsKey)>>; } pub trait EvalContextExt<'tcx> { @@ -25,7 +25,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> MemoryExt<'tcx> for Memory<'a, 'mir, 'tcx, Evalu self.data.thread_local.insert( new_key, TlsEntry { - data: Pointer::null(), + data: Scalar::null(), dtor, }, ); @@ -43,7 +43,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> MemoryExt<'tcx> for Memory<'a, 'mir, 'tcx, Evalu }; } - fn load_tls(&mut self, key: TlsKey) -> EvalResult<'tcx, Pointer> { + fn load_tls(&mut self, key: TlsKey) -> EvalResult<'tcx, Scalar> { return match self.data.thread_local.get(&key) { Some(&TlsEntry { data, .. }) => { trace!("TLS key {} loaded: {:?}", key, data); @@ -53,7 +53,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> MemoryExt<'tcx> for Memory<'a, 'mir, 'tcx, Evalu }; } - fn store_tls(&mut self, key: TlsKey, new_data: Pointer) -> EvalResult<'tcx> { + fn store_tls(&mut self, key: TlsKey, new_data: Scalar) -> EvalResult<'tcx> { return match self.data.thread_local.get_mut(&key) { Some(&mut TlsEntry { ref mut data, .. }) => { trace!("TLS key {} stored: {:?}", key, new_data); @@ -85,19 +85,21 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> MemoryExt<'tcx> for Memory<'a, 'mir, 'tcx, Evalu fn fetch_tls_dtor( &mut self, key: Option, - ) -> EvalResult<'tcx, Option<(ty::Instance<'tcx>, Pointer, TlsKey)>> { + ) -> EvalResult<'tcx, Option<(ty::Instance<'tcx>, Scalar, TlsKey)>> { use std::collections::Bound::*; + + let thread_local = &mut self.data.thread_local; let start = match key { Some(key) => Excluded(key), None => Unbounded, }; for (&key, &mut TlsEntry { ref mut data, dtor }) in - self.data.thread_local.range_mut((start, Unbounded)) + thread_local.range_mut((start, Unbounded)) { if !data.is_null()? { if let Some(dtor) = dtor { let ret = Some((dtor, *data, key)); - *data = Pointer::null(); + *data = Scalar::null(); return Ok(ret); } } diff --git a/src/validation.rs b/src/validation.rs index deb1c5d5bc0..24ddffee9de 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -12,7 +12,7 @@ use rustc::middle::const_val::ConstVal; use rustc_data_structures::indexed_vec::Idx; use rustc_mir::interpret::HasMemory; -use super::{EvalContext, Place, PlaceExtra, ValTy}; +use super::{EvalContext, Place, PlaceExtra, ValTy, ScalarExt}; use rustc::mir::interpret::{DynamicLifetime, AccessKind, EvalErrorKind, Value, EvalError, EvalResult}; use locks::MemoryExt; @@ -119,7 +119,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' Index(v) => { let value = self.frame().get_local(v)?; let ty = self.tcx.tcx.types.usize; - let n = self.value_to_primval(ValTy { value, ty })?.to_u64()?; + let n = self.value_to_scalar(ValTy { value, ty })?.to_u64()?; Index(n) }, ConstantIndex { offset, min_length, from_end } => @@ -652,7 +652,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' TyBool | TyFloat(_) | TyChar => { if mode.acquiring() { let val = self.read_place(query.place.1)?; - let val = self.value_to_primval(ValTy { value: val, ty: query.ty })?; + let val = self.value_to_scalar(ValTy { value: val, ty: query.ty })?; val.to_bytes()?; // TODO: Check if these are valid bool/float/codepoint/UTF-8 } From 1bd088a96c03ae38ccea15403487da6a10d978f3 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 30 May 2018 14:29:32 +0200 Subject: [PATCH 08/16] `memcmp` returns `i32` --- src/fn_call.rs | 4 ++-- src/lib.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/fn_call.rs b/src/fn_call.rs index ea0c5eb8b26..6a2255e5777 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -289,7 +289,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' use std::cmp::Ordering::*; match left_bytes.cmp(right_bytes) { - Less => -1i8, + Less => -1i32, Equal => 0, Greater => 1, } @@ -297,7 +297,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' self.write_scalar( dest, - Scalar::from_i8(result), + Scalar::from_i32(result), dest_ty, )?; } diff --git a/src/lib.rs b/src/lib.rs index e3c83c284db..079560c0ca9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,7 +55,7 @@ use validation::{ValidationQuery, AbsPlace}; pub trait ScalarExt { fn null() -> Self; - fn from_i8(i: i8) -> Self; + fn from_i32(i: i32) -> Self; fn from_u128(i: u128) -> Self; fn from_i128(i: i128) -> Self; fn from_usize(i: u64, ptr_size: Size) -> Self; @@ -72,8 +72,8 @@ impl ScalarExt for Scalar { Scalar::Bits { bits: 0, defined: 128 } } - fn from_i8(i: i8) -> Self { - Scalar::Bits { bits: i as i128 as u128, defined: 8 } + fn from_i32(i: i32) -> Self { + Scalar::Bits { bits: i as u32 as u128, defined: 32 } } fn from_u128(i: u128) -> Self { From 9655aaf3aa74e948935b1749fbdff2f8f774226b Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 30 May 2018 14:29:54 +0200 Subject: [PATCH 09/16] Comparing Scalar's with differend `defined` values is false --- src/intrinsic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/intrinsic.rs b/src/intrinsic.rs index 3d537ea629c..1e8090dc189 100644 --- a/src/intrinsic.rs +++ b/src/intrinsic.rs @@ -327,7 +327,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: let a = self.value_to_scalar(args[0])?; let b = self.value_to_scalar(args[1])?; // check x % y != 0 - if self.binary_op(mir::BinOp::Rem, a, ty, b, ty)?.0 != Scalar::null() { + if !self.binary_op(mir::BinOp::Rem, a, ty, b, ty)?.0.is_null()? { return err!(ValidationFailure(format!("exact_div: {:?} cannot be divided by {:?}", a, b))); } let result = self.binary_op(mir::BinOp::Div, a, ty, b, ty)?; From 062be7c047fa6c276b48c7b024725e90d3a93c25 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 30 May 2018 14:30:15 +0200 Subject: [PATCH 10/16] Comparing non-pointer-size types should be possible --- src/operator.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/operator.rs b/src/operator.rs index 721b4f0bfdd..f36e749dc92 100644 --- a/src/operator.rs +++ b/src/operator.rs @@ -52,11 +52,13 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: 16 => I128, _ => unreachable!(), }, true); - let left_kind = match self.layout_of(left_ty)?.abi { + let left_layout = self.layout_of(left_ty)?; + let left_kind = match left_layout.abi { ty::layout::Abi::Scalar(ref scalar) => scalar.value, _ => Err(EvalErrorKind::TypeNotPrimitive(left_ty))?, }; - let right_kind = match self.layout_of(right_ty)?.abi { + let right_layout = self.layout_of(right_ty)?; + let right_kind = match right_layout.abi { ty::layout::Abi::Scalar(ref scalar) => scalar.value, _ => Err(EvalErrorKind::TypeNotPrimitive(right_ty))?, }; @@ -77,7 +79,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: Eq if left_kind == right_kind => { let result = match (left, right) { (Scalar::Bits { .. }, Scalar::Bits { .. }) => { - left.to_bits(self.memory.pointer_size())? == right.to_bits(self.memory.pointer_size())? + left.to_bits(left_layout.size)? == right.to_bits(right_layout.size)? }, (Scalar::Ptr(left), Scalar::Ptr(right)) => left == right, _ => false, @@ -87,7 +89,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: Ne if left_kind == right_kind => { let result = match (left, right) { (Scalar::Bits { .. }, Scalar::Bits { .. }) => { - left.to_bits(self.memory.pointer_size())? != right.to_bits(self.memory.pointer_size())? + left.to_bits(left_layout.size)? != right.to_bits(right_layout.size)? }, (Scalar::Ptr(left), Scalar::Ptr(right)) => left != right, _ => true, From 1d9c56ddf40fd43231c3caa167465167738ebfda Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 30 May 2018 15:59:04 +0200 Subject: [PATCH 11/16] TlsKey is messy because it changes types between systems --- src/fn_call.rs | 9 +++------ src/lib.rs | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/fn_call.rs b/src/fn_call.rs index 6a2255e5777..d1a483d2e80 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -512,21 +512,18 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' self.write_null(dest, dest_ty)?; } "pthread_key_delete" => { - // The conversion into TlsKey here is a little fishy, but should work as long as usize >= libc::pthread_key_t - let key = self.value_to_scalar(args[0])?.to_u64()? as TlsKey; + let key = self.value_to_scalar(args[0])?.to_bytes()?; self.memory.delete_tls_key(key)?; // Return success (0) self.write_null(dest, dest_ty)?; } "pthread_getspecific" => { - // The conversion into TlsKey here is a little fishy, but should work as long as usize >= libc::pthread_key_t - let key = self.value_to_scalar(args[0])?.to_u64()? as TlsKey; + let key = self.value_to_scalar(args[0])?.to_bytes()?; let ptr = self.memory.load_tls(key)?; self.write_ptr(dest, ptr, dest_ty)?; } "pthread_setspecific" => { - // The conversion into TlsKey here is a little fishy, but should work as long as usize >= libc::pthread_key_t - let key = self.value_to_scalar(args[0])?.to_u64()? as TlsKey; + let key = self.value_to_scalar(args[0])?.to_bytes()?; let new_ptr = self.into_ptr(args[1].value)?; self.memory.store_tls(key, new_ptr)?; diff --git a/src/lib.rs b/src/lib.rs index 079560c0ca9..6d7c0b05f80 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -277,7 +277,7 @@ pub struct Evaluator<'tcx> { pub(crate) suspended: HashMap>>, } -pub type TlsKey = usize; +pub type TlsKey = u128; #[derive(Copy, Clone, Debug)] pub struct TlsEntry<'tcx> { From 77c8582031ca4084651d2cf365f81f19bbd50fcc Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 30 May 2018 17:43:27 +0200 Subject: [PATCH 12/16] `align_offset` intrinsic is now a lang item --- src/fn_call.rs | 12 ++++++++++++ src/intrinsic.rs | 8 -------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/fn_call.rs b/src/fn_call.rs index d1a483d2e80..fdaa819c08f 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -135,6 +135,18 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' _ => {} } + if self.tcx.lang_items().align_offset_fn() == Some(instance.def.def_id()) { + // FIXME: return a real value in case the target allocation has an + // alignment bigger than the one requested + let n = u128::max_value(); + let amt = 128 - self.memory.pointer_size().bytes() * 8; + let (dest, return_to_block) = destination.unwrap(); + let ty = self.tcx.types.usize; + self.write_scalar(dest, Scalar::from_u128((n << amt) >> amt), ty)?; + self.goto_block(return_to_block); + return Ok(true); + } + let mir = match self.load_mir(instance.def) { Ok(mir) => mir, Err(EvalError { kind: EvalErrorKind::NoMirFor(path), .. }) => { diff --git a/src/intrinsic.rs b/src/intrinsic.rs index 1e8090dc189..cee2f1ab768 100644 --- a/src/intrinsic.rs +++ b/src/intrinsic.rs @@ -33,14 +33,6 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'mir, 'tcx, super: let intrinsic_name = &self.tcx.item_name(instance.def_id()).as_str()[..]; match intrinsic_name { - "align_offset" => { - // FIXME: return a real value in case the target allocation has an - // alignment bigger than the one requested - let n = u128::max_value(); - let amt = 128 - self.memory.pointer_size().bytes() * 8; - self.write_scalar(dest, Scalar::from_u128((n << amt) >> amt), dest_layout.ty)?; - }, - "add_with_overflow" => { self.intrinsic_with_overflow( mir::BinOp::Add, From 8284b4e912baf72473c3696ce9e46cc334da18e4 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 30 May 2018 17:43:54 +0200 Subject: [PATCH 13/16] `to_u64` and `to_bytes` are horribly easy to use wrongly. --- src/fn_call.rs | 8 ++++---- src/lib.rs | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/fn_call.rs b/src/fn_call.rs index fdaa819c08f..72efcd6ede0 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -316,7 +316,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' "memrchr" => { let ptr = self.into_ptr(args[0].value)?; - let val = self.value_to_scalar(args[1])?.to_u64()? as u8; + let val = self.value_to_scalar(args[1])?.to_bytes()? as u8; let num = self.value_to_scalar(args[2])?.to_u64()?; if let Some(idx) = self.memory.read_bytes(ptr, Size::from_bytes(num))?.iter().rev().position( |&c| c == val, @@ -331,7 +331,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' "memchr" => { let ptr = self.into_ptr(args[0].value)?; - let val = self.value_to_scalar(args[1])?.to_u64()? as u8; + let val = self.value_to_scalar(args[1])?.to_bytes()? as u8; let num = self.value_to_scalar(args[2])?.to_u64()?; if let Some(idx) = self.memory.read_bytes(ptr, Size::from_bytes(num))?.iter().position( |&c| c == val, @@ -414,9 +414,9 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' } "write" => { - let fd = self.value_to_scalar(args[0])?.to_u64()?; + let fd = self.value_to_scalar(args[0])?.to_bytes()?; let buf = self.into_ptr(args[1].value)?; - let n = self.value_to_scalar(args[2])?.to_u64()?; + let n = self.value_to_scalar(args[2])?.to_bytes()? as u64; trace!("Called write({:?}, {:?}, {:?})", fd, buf, n); let result = if fd == 1 || fd == 2 { // stdout/stderr diff --git a/src/lib.rs b/src/lib.rs index 6d7c0b05f80..550965573cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -64,6 +64,9 @@ pub trait ScalarExt { fn from_f64(f: f64) -> Self; fn to_u64(self) -> EvalResult<'static, u64>; fn is_null(self) -> EvalResult<'static, bool>; + /// 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>; } From cec51f8513bc1fa6344b702a4e5036c4961fda04 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 3 Jun 2018 11:54:17 +0200 Subject: [PATCH 14/16] Use correct bit size when reading usize values --- src/fn_call.rs | 30 +++++++++++++++--------------- src/lib.rs | 6 +++--- src/validation.rs | 2 +- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/fn_call.rs b/src/fn_call.rs index 72efcd6ede0..36cc29a2b5b 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -194,7 +194,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' match &link_name[..] { "malloc" => { - let size = self.value_to_scalar(args[0])?.to_u64()?; + let size = self.value_to_scalar(args[0])?.to_usize(self)?; if size == 0 { self.write_null(dest, dest_ty)?; } else { @@ -221,7 +221,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' // // libc::syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), GRND_NONBLOCK) // is called if a `HashMap` is created the regular way. - match self.value_to_scalar(args[0])?.to_u64()? { + match self.value_to_scalar(args[0])?.to_usize(self)? { 318 | 511 => { return err!(Unimplemented( "miri does not support random number generators".to_owned(), @@ -293,7 +293,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' "memcmp" => { let left = self.into_ptr(args[0].value)?; let right = self.into_ptr(args[1].value)?; - let n = Size::from_bytes(self.value_to_scalar(args[2])?.to_u64()?); + let n = Size::from_bytes(self.value_to_scalar(args[2])?.to_usize(self)?); let result = { let left_bytes = self.memory.read_bytes(left, n)?; @@ -317,7 +317,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' "memrchr" => { let ptr = self.into_ptr(args[0].value)?; let val = self.value_to_scalar(args[1])?.to_bytes()? as u8; - let num = self.value_to_scalar(args[2])?.to_u64()?; + let num = self.value_to_scalar(args[2])?.to_usize(self)?; if let Some(idx) = self.memory.read_bytes(ptr, Size::from_bytes(num))?.iter().rev().position( |&c| c == val, ) @@ -332,7 +332,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' "memchr" => { let ptr = self.into_ptr(args[0].value)?; let val = self.value_to_scalar(args[1])?.to_bytes()? as u8; - let num = self.value_to_scalar(args[2])?.to_u64()?; + let num = self.value_to_scalar(args[2])?.to_usize(self)?; if let Some(idx) = self.memory.read_bytes(ptr, Size::from_bytes(num))?.iter().position( |&c| c == val, ) @@ -457,7 +457,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' } "sysconf" => { - let name = self.value_to_scalar(args[0])?.to_u64()?; + let name = self.value_to_scalar(args[0])?.to_usize(self)?; trace!("sysconf() called with name {}", name); // cache the sysconf integers via miri's global cache @@ -646,8 +646,8 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' match &path[..] { // Allocators are magic. They have no MIR, even when the rest of libstd does. "alloc::alloc::::__rust_alloc" => { - let size = self.value_to_scalar(args[0])?.to_u64()?; - let align = self.value_to_scalar(args[1])?.to_u64()?; + let size = self.value_to_scalar(args[0])?.to_usize(self)?; + let align = self.value_to_scalar(args[1])?.to_usize(self)?; if size == 0 { return err!(HeapAllocZeroBytes); } @@ -660,8 +660,8 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' self.write_scalar(dest, Scalar::Ptr(ptr), dest_ty)?; } "alloc::alloc::::__rust_alloc_zeroed" => { - let size = self.value_to_scalar(args[0])?.to_u64()?; - let align = self.value_to_scalar(args[1])?.to_u64()?; + let size = self.value_to_scalar(args[0])?.to_usize(self)?; + let align = self.value_to_scalar(args[1])?.to_usize(self)?; if size == 0 { return err!(HeapAllocZeroBytes); } @@ -676,8 +676,8 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' } "alloc::alloc::::__rust_dealloc" => { let ptr = self.into_ptr(args[0].value)?.to_ptr()?; - let old_size = self.value_to_scalar(args[1])?.to_u64()?; - let align = self.value_to_scalar(args[2])?.to_u64()?; + let old_size = self.value_to_scalar(args[1])?.to_usize(self)?; + let align = self.value_to_scalar(args[2])?.to_usize(self)?; if old_size == 0 { return err!(HeapAllocZeroBytes); } @@ -692,9 +692,9 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' } "alloc::alloc::::__rust_realloc" => { let ptr = self.into_ptr(args[0].value)?.to_ptr()?; - let old_size = self.value_to_scalar(args[1])?.to_u64()?; - let align = self.value_to_scalar(args[2])?.to_u64()?; - let new_size = self.value_to_scalar(args[3])?.to_u64()?; + let old_size = self.value_to_scalar(args[1])?.to_usize(self)?; + let align = self.value_to_scalar(args[2])?.to_usize(self)?; + let new_size = self.value_to_scalar(args[3])?.to_usize(self)?; if old_size == 0 || new_size == 0 { return err!(HeapAllocZeroBytes); } diff --git a/src/lib.rs b/src/lib.rs index 550965573cb..a29211df996 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -62,7 +62,7 @@ pub trait ScalarExt { fn from_isize(i: i64, ptr_size: Size) -> Self; fn from_f32(f: f32) -> Self; fn from_f64(f: f64) -> Self; - fn to_u64(self) -> EvalResult<'static, u64>; + fn to_usize<'a, 'mir, 'tcx>(self, ecx: &rustc_mir::interpret::EvalContext<'a, 'mir, 'tcx, Evaluator<'tcx>>) -> EvalResult<'static, u64>; fn is_null(self) -> EvalResult<'static, bool>; /// 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 @@ -103,8 +103,8 @@ impl ScalarExt for Scalar { Scalar::Bits { bits: f.to_bits() as u128, defined: 64 } } - fn to_u64(self) -> EvalResult<'static, u64> { - let b = self.to_bits(Size::from_bits(64))?; + fn to_usize<'a, 'mir, 'tcx>(self, ecx: &rustc_mir::interpret::EvalContext<'a, 'mir, 'tcx, Evaluator<'tcx>>) -> EvalResult<'static, u64> { + let b = self.to_bits(ecx.memory.pointer_size())?; assert_eq!(b as u64 as u128, b); Ok(b as u64) } diff --git a/src/validation.rs b/src/validation.rs index 24ddffee9de..d82a345c251 100644 --- a/src/validation.rs +++ b/src/validation.rs @@ -119,7 +119,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx> for EvalContext<'a, 'mir, ' Index(v) => { let value = self.frame().get_local(v)?; let ty = self.tcx.tcx.types.usize; - let n = self.value_to_scalar(ValTy { value, ty })?.to_u64()?; + let n = self.value_to_scalar(ValTy { value, ty })?.to_usize(self)?; Index(n) }, ConstantIndex { offset, min_length, from_end } => From 675587280f5cee0ea99ebb4c4f70043e89aa1aed Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 3 Jun 2018 12:13:30 +0200 Subject: [PATCH 15/16] Update cargo-miri --- cargo-miri-test/Cargo.lock | 12 ++++++------ src/bin/cargo-miri.rs | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cargo-miri-test/Cargo.lock b/cargo-miri-test/Cargo.lock index 8b2387fa641..85c3c08dba0 100644 --- a/cargo-miri-test/Cargo.lock +++ b/cargo-miri-test/Cargo.lock @@ -1,14 +1,14 @@ -[root] +[[package]] +name = "byteorder" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "cargo-miri-test" version = "0.1.0" dependencies = [ "byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "byteorder" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [metadata] "checksum byteorder 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c40977b0ee6b9885c9013cd41d9feffdd22deb3bb4dc3a71d901cc7a77de18c8" diff --git a/src/bin/cargo-miri.rs b/src/bin/cargo-miri.rs index 39a41583a39..010f25e8152 100644 --- a/src/bin/cargo-miri.rs +++ b/src/bin/cargo-miri.rs @@ -154,7 +154,7 @@ fn main() { // this check ensures that dependencies are built but not interpreted and the final crate is // interpreted but not built - let miri_enabled = std::env::args().any(|s| s == "-Zno-trans"); + let miri_enabled = std::env::args().any(|s| s == "--emit=dep-info,metadata"); let mut command = if miri_enabled { let mut path = std::env::current_exe().expect("current executable path invalid"); @@ -193,7 +193,7 @@ where if !found_dashes { args.push("--".to_owned()); } - args.push("-Zno-trans".to_owned()); + args.push("--emit=dep-info,metadata".to_owned()); args.push("--cfg".to_owned()); args.push(r#"feature="cargo-miri""#.to_owned()); From e1734470e780e05a3366a2f74cfa25ea88a518a5 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Sun, 3 Jun 2018 12:54:43 +0200 Subject: [PATCH 16/16] Reenable the rustc tester --- rustc_tests/Cargo.lock | 209 +++++++++++++++++++++++++--------------- rustc_tests/src/main.rs | 10 +- src/lib.rs | 1 - 3 files changed, 134 insertions(+), 86 deletions(-) diff --git a/rustc_tests/Cargo.lock b/rustc_tests/Cargo.lock index a1e273a96bd..9cf4fe0d134 100644 --- a/rustc_tests/Cargo.lock +++ b/rustc_tests/Cargo.lock @@ -1,10 +1,3 @@ -[root] -name = "rustc_tests" -version = "0.1.0" -dependencies = [ - "miri 0.1.0", -] - [[package]] name = "aho-corasick" version = "0.6.3" @@ -14,26 +7,13 @@ dependencies = [ ] [[package]] -name = "backtrace" -version = "0.3.3" +name = "atty" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "backtrace-sys" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -46,36 +26,24 @@ name = "cfg-if" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "dbghelp-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "env_logger" -version = "0.4.3" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "gcc" -version = "0.3.53" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "kernel32-sys" -version = "0.2.2" +name = "humantime" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -83,6 +51,11 @@ name = "lazy_static" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "lazy_static" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "libc" version = "0.2.30" @@ -90,15 +63,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "log" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "log_settings" -version = "0.1.1" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -109,15 +77,41 @@ dependencies = [ "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "memchr" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "miri" version = "0.1.0" dependencies = [ "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_miri 0.1.0", + "env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quick-error" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "redox_syscall" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "redox_termios" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -132,26 +126,54 @@ dependencies = [ "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "regex" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "regex-syntax" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "rustc-demangle" -version = "0.1.5" +name = "regex-syntax" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] -name = "rustc_miri" +name = "rustc_tests" version = "0.1.0" dependencies = [ - "backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "miri 0.1.0", +] + +[[package]] +name = "termcolor" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "termion" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -163,6 +185,11 @@ dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ucd-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unreachable" version = "1.0.0" @@ -183,35 +210,59 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.2.8" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "winapi-build" -version = "0.1.1" +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "wincolor" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [metadata] "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" -"checksum backtrace 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "99f2ce94e22b8e664d95c57fff45b98a966c2252b60691d0b7aeeccd88d70983" -"checksum backtrace-sys 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "afccc5772ba333abccdf60d55200fa3406f8c59dcf54d5f7998c9107d3799c7c" +"checksum atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2fc4a1aa4c24c0718a250f0681885c1af91419d242f29eb8f2ab28502d80dbd1" "checksum byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff81738b726f5d099632ceaffe7fb65b90212e8dce59d518729e7e8634032d3d" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" -"checksum dbghelp-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97590ba53bcb8ac28279161ca943a924d1fd4a8fb3fa63302591647c4fc5b850" -"checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" -"checksum gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)" = "e8310f7e9c890398b0e80e301c4f474e9918d2b27fca8f48486ca775fa9ffc5a" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum env_logger 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "0e6e40ebb0e66918a37b38c7acab4e10d299e0463fe2af5d29b9cc86710cfd2a" +"checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" +"checksum lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e6412c5e2ad9584b0b8e979393122026cdd6d2a80b933f890dcd694ddbe73739" "checksum libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)" = "2370ca07ec338939e356443dac2296f581453c35fe1e3a3ed06023c49435f915" -"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" -"checksum log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d382732ea0fbc09790c4899db3255bdea0fc78b54bf234bd18a63bb603915b6" +"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" +"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" +"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" +"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" +"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" +"checksum regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75ecf88252dce580404a22444fc7d626c01815debba56a7f4f536772a5ff19d3" "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" -"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" +"checksum regex-syntax 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1ac0f60d675cc6cf13a20ec076568254472551051ad5dd050364d70671bf6b" +"checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83" +"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" +"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum wincolor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eeb06499a3a4d44302791052df005d5232b927ed1a9658146d842165c4de7767" diff --git a/rustc_tests/src/main.rs b/rustc_tests/src/main.rs index 77e4a3df406..ecc5287c727 100644 --- a/rustc_tests/src/main.rs +++ b/rustc_tests/src/main.rs @@ -4,7 +4,7 @@ extern crate getopts; extern crate rustc; extern crate rustc_driver; extern crate rustc_errors; -extern crate rustc_trans_utils; +extern crate rustc_codegen_utils; extern crate syntax; use std::path::{PathBuf, Path}; @@ -19,7 +19,7 @@ use rustc_driver::{Compilation, CompilerCalls, RustcDefaultCalls}; use rustc_driver::driver::{CompileState, CompileController}; use rustc::session::config::{self, Input, ErrorOutputType}; use rustc::hir::{self, itemlikevisit}; -use rustc_trans_utils::trans_crate::TransCrate; +use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc::ty::TyCtxt; use syntax::ast; @@ -53,7 +53,7 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls { } fn late_callback( &mut self, - trans: &TransCrate, + trans: &CodegenBackend, matches: &getopts::Matches, sess: &Session, cstore: &CrateStore, @@ -104,9 +104,7 @@ fn after_analysis<'a, 'tcx>(state: &mut CompileState<'a, 'tcx>) { state.hir_crate.unwrap().visit_all_item_likes(&mut Visitor(tcx, state)); } else if let Some((entry_node_id, _, _)) = *state.session.entry_fn.borrow() { let entry_def_id = tcx.hir.local_def_id(entry_node_id); - let start_wrapper = tcx.lang_items().start_fn().and_then(|start_fn| - if tcx.is_mir_available(start_fn) { Some(start_fn) } else { None }); - miri::eval_main(tcx, entry_def_id, start_wrapper); + miri::eval_main(tcx, entry_def_id, None); state.session.abort_if_errors(); } else { diff --git a/src/lib.rs b/src/lib.rs index a29211df996..1ba763349aa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -265,7 +265,6 @@ pub fn eval_main<'a, 'tcx: 'a>( } } } - ::std::process::exit(1); } } }