From 0f4bf0d28fa138123ef541e481a4a380b37652c2 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 15 Dec 2016 12:03:58 +0100 Subject: [PATCH 01/19] allow the use of tuple struct constructors as functions --- src/terminator/mod.rs | 28 +++++++++++++++++++ .../run-pass/tuple_like_struct_constructor.rs | 5 ++++ 2 files changed, 33 insertions(+) create mode 100644 tests/run-pass/tuple_like_struct_constructor.rs diff --git a/src/terminator/mod.rs b/src/terminator/mod.rs index d74458a87c..0b2bce7a3b 100644 --- a/src/terminator/mod.rs +++ b/src/terminator/mod.rs @@ -229,6 +229,34 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { (def_id, substs, Vec::new()) }; + // FIXME(eddyb) Detect ADT constructors more efficiently. + if let Some(adt_def) = fn_ty.sig.skip_binder().output().ty_adt_def() { + if let Some(v) = adt_def.variants.iter().find(|v| resolved_def_id == v.did) { + // technically they can diverge, but only if one of their arguments diverges, so it doesn't matter + let (lvalue, target) = destination.expect("tuple struct constructors can't diverge"); + let dest_ty = self.tcx.item_type(adt_def.did); + let dest_layout = self.type_layout(dest_ty)?; + match *dest_layout { + Layout::Univariant { ref variant, .. } => { + assert_eq!(v.disr_val.to_u64_unchecked(), 0); + let offsets = variant.offsets.iter().map(|s| s.bytes()); + + // FIXME: don't allocate for single or dual field structs + let dest = self.force_allocation(lvalue)?.to_ptr(); + + for (offset, (value, value_ty)) in offsets.into_iter().zip(args) { + let field_dest = dest.offset(offset); + self.write_value_to_ptr(value, field_dest, value_ty)?; + } + }, + // FIXME: enum variant constructors + _ => bug!("bad layout for tuple struct constructor: {:?}", dest_layout), + } + self.goto_block(target); + return Ok(()); + } + } + let mir = self.load_mir(resolved_def_id)?; let (return_lvalue, return_to_block) = match destination { Some((lvalue, block)) => (lvalue, StackPopCleanup::Goto(block)), diff --git a/tests/run-pass/tuple_like_struct_constructor.rs b/tests/run-pass/tuple_like_struct_constructor.rs new file mode 100644 index 0000000000..05e8893de1 --- /dev/null +++ b/tests/run-pass/tuple_like_struct_constructor.rs @@ -0,0 +1,5 @@ +fn main() { + #[derive(PartialEq, Eq, Debug)] + struct A(i32); + assert_eq!(Some(42).map(A), Some(A(42))); +} From 0c244d20d7218db471d6a182ccbd1d58a5cf3469 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 15 Dec 2016 14:29:59 +0100 Subject: [PATCH 02/19] abort, panic and print --- src/error.rs | 11 ++++++ src/eval_context.rs | 6 +++ src/step.rs | 42 +++++++++++++++++---- src/terminator/mod.rs | 88 ++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 138 insertions(+), 9 deletions(-) diff --git a/src/error.rs b/src/error.rs index 9b532e0137..ca5ff8356c 100644 --- a/src/error.rs +++ b/src/error.rs @@ -52,6 +52,11 @@ pub enum EvalError<'tcx> { ReallocatedFrozenMemory, DeallocatedFrozenMemory, Layout(layout::LayoutError<'tcx>), + Abort, + Panic { + file: String, + line: u32, + }, } pub type EvalResult<'tcx, T> = Result>; @@ -122,6 +127,10 @@ impl<'tcx> Error for EvalError<'tcx> { "rustc layout computation failed", EvalError::UnterminatedCString(_) => "attempted to get length of a null terminated string, but no null found before end of allocation", + EvalError::Abort => + "`abort` intrinsic reached", + EvalError::Panic { .. } => + "panic!", } } @@ -154,6 +163,8 @@ impl<'tcx> fmt::Display for EvalError<'tcx> { write!(f, "expected primitive type, got {}", ty), EvalError::Layout(ref err) => write!(f, "rustc layout computation failed: {:?}", err), + EvalError::Panic { ref file, line } => + write!(f, "panicked at {}:{}", file, line), _ => write!(f, "{}", self.description()), } } diff --git a/src/eval_context.rs b/src/eval_context.rs index cc3d02d8ce..5cccf2b06c 100644 --- a/src/eval_context.rs +++ b/src/eval_context.rs @@ -43,6 +43,10 @@ pub struct EvalContext<'a, 'tcx: 'a> { /// This prevents infinite loops and huge computations from freezing up const eval. /// Remove once halting problem is solved. pub(super) steps_remaining: u64, + + // FIXME: also add destructors + pub(super) pthread: HashMap, + pub(super) next_pthread_key: i32, } /// A stack frame. @@ -137,6 +141,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { stack: Vec::new(), stack_limit: limits.stack_limit, steps_remaining: limits.step_limit, + pthread: HashMap::new(), + next_pthread_key: 0, } } diff --git a/src/step.rs b/src/step.rs index 527df96a18..a5e72523e4 100644 --- a/src/step.rs +++ b/src/step.rs @@ -15,6 +15,8 @@ use error::{EvalResult, EvalError}; use eval_context::{EvalContext, StackPopCleanup, MirRef}; use lvalue::{Global, GlobalId, Lvalue}; use syntax::codemap::Span; +use syntax::attr; +use value::{Value, PrimVal}; impl<'a, 'tcx> EvalContext<'a, 'tcx> { pub fn inc_step_counter_and_check_limit(&mut self, n: u64) -> EvalResult<'tcx, ()> { @@ -152,6 +154,13 @@ struct ConstantExtractor<'a, 'b: 'a, 'tcx: 'b> { } impl<'a, 'b, 'tcx> ConstantExtractor<'a, 'b, 'tcx> { + fn weak_linkage(&self, def_id: DefId) -> bool { + let attributes = self.ecx.tcx.get_attrs(def_id); + let attr = attr::first_attr_value_str_by_name(&attributes, "linkage"); + trace!("linkage: {:?}", attr); + attr.map_or(false, |name| &*name.as_str() == "weak" || &*name.as_str() == "extern_weak") + } + fn global_item(&mut self, def_id: DefId, substs: &'tcx subst::Substs<'tcx>, span: Span, immutable: bool) { let cid = GlobalId { def_id: def_id, @@ -161,15 +170,34 @@ impl<'a, 'b, 'tcx> ConstantExtractor<'a, 'b, 'tcx> { if self.ecx.globals.contains_key(&cid) { return; } + let ty = self.ecx.tcx.item_type(def_id); + let immutable = immutable && !ty.type_contents(self.ecx.tcx).interior_unsafe(); self.try(|this| { - let mir = this.ecx.load_mir(def_id)?; - this.ecx.globals.insert(cid, Global::uninitialized(mir.return_ty)); - let cleanup = if immutable && !mir.return_ty.type_contents(this.ecx.tcx).interior_unsafe() { - StackPopCleanup::Freeze + if this.weak_linkage(def_id) { + let data = match this.ecx.type_size(ty)?.expect("statics/consts can't be unsized") { + 0...8 => Value::ByVal(PrimVal::new(0)), + n => { + let ptr = this.ecx.memory.allocate(n, 1)?; + this.ecx.memory.write_repeat(ptr, 0, n)?; + Value::ByRef(ptr) + }, + }; + this.ecx.globals.insert(cid, Global { + data: Some(data), + mutable: !immutable, + ty: ty, + }); + Ok(()) } else { - StackPopCleanup::None - }; - this.ecx.push_stack_frame(def_id, span, mir, substs, Lvalue::Global(cid), cleanup, Vec::new()) + this.ecx.globals.insert(cid, Global::uninitialized(ty)); + let cleanup = if immutable { + StackPopCleanup::Freeze + } else { + StackPopCleanup::None + }; + let mir = this.ecx.load_mir(def_id)?; + this.ecx.push_stack_frame(def_id, span, mir, substs, Lvalue::Global(cid), cleanup, Vec::new()) + } }); } fn try EvalResult<'tcx, ()>>(&mut self, f: F) { diff --git a/src/terminator/mod.rs b/src/terminator/mod.rs index 0b2bce7a3b..0207709a56 100644 --- a/src/terminator/mod.rs +++ b/src/terminator/mod.rs @@ -15,6 +15,8 @@ use memory::Pointer; use value::PrimVal; use value::Value; +use std::str::from_utf8; + mod intrinsic; impl<'a, 'tcx> EvalContext<'a, 'tcx> { @@ -200,14 +202,37 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Abi::RustIntrinsic => { let ty = fn_ty.sig.0.output(); let layout = self.type_layout(ty)?; - let (ret, target) = destination.unwrap(); + let (ret, target) = match destination { + Some(dest) => dest, + None => { + assert_eq!(&self.tcx.item_name(def_id).as_str()[..], "abort"); + return Err(EvalError::Abort); + } + }; self.call_intrinsic(def_id, substs, arg_operands, ret, ty, layout, target)?; Ok(()) } Abi::C => { let ty = fn_ty.sig.0.output(); - let (ret, target) = destination.unwrap(); + let (ret, target) = match destination { + Some(dest) => dest, + None => { + assert_eq!(&self.tcx.item_name(def_id).as_str()[..], "panic_impl"); + let args_res: EvalResult> = arg_operands.iter() + .map(|arg| self.eval_operand(arg)?.ok_or(EvalError::ReadUndefBytes)) + .collect(); + let args = args_res?; + // FIXME: process panic text + let file_slice = args[1].expect_slice(&self.memory)?; + let file = from_utf8(self.memory.read_bytes(file_slice.0, file_slice.1)?) + .expect("panic message not utf8") + .to_owned(); + let u32 = self.tcx.types.u32; + let line = self.value_to_primval(args[2], u32)?.to_u64() as u32; + return Err(EvalError::Panic { file: file, line: line }); + } + }; self.call_c_abi(def_id, arg_operands, ret, ty)?; self.goto_block(target); Ok(()) @@ -358,6 +383,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let args = args_res?; let usize = self.tcx.types.usize; + let i32 = self.tcx.types.i32; match &link_name[..] { "__rust_allocate" => { @@ -403,6 +429,18 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { self.write_primval(dest, PrimVal::Bytes(result as u64), dest_ty)?; } + "memrchr" => { + let ptr = args[0].read_ptr(&self.memory)?; + let val = self.value_to_primval(args[1], usize)?.to_u64() as u8; + let num = self.value_to_primval(args[2], usize)?.to_u64(); + if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().rev().position(|&c| c == val) { + let new_ptr = ptr.offset(num - idx as u64 - 1); + self.write_value(Value::ByVal(PrimVal::from_ptr(new_ptr)), dest, dest_ty)?; + } else { + self.write_value(Value::ByVal(PrimVal::new(0)), dest, dest_ty)?; + } + } + "memchr" => { let ptr = args[0].read_ptr(&self.memory)?; let val = self.value_to_primval(args[1], usize)?.to_u64()? as u8; @@ -415,6 +453,27 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } } + "write" => { + // int filedes + let filedes = self.value_to_primval(args[0], usize)?.to_u64(); + // const void* buffer + let buffer = args[1].read_ptr(&self.memory)?; + // size_t size + let size = self.value_to_primval(args[0], usize)?.to_u64(); + + { + let data = self.memory.read_bytes(buffer, size)?; + info!("write to `{:x}`: {:?}", filedes, data); + if filedes == 1 { + for &d in data { + print!("{}", d as char); + } + } + } + + self.write_primval(dest, PrimVal::new(size as u64), dest_ty)?; + } + "getenv" => { { let name_ptr = args[0].read_ptr(&self.memory)?; @@ -423,6 +482,31 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } self.write_value(Value::ByVal(PrimVal::Bytes(0)), dest, dest_ty)?; } + "pthread_key_create" => { + // pthread_key_t* key + let key = args[0].read_ptr(&self.memory)?; + let pthread_key_t = self.tcx.types.i32; + self.next_pthread_key += 1; + let new_key = self.next_pthread_key; + self.write_primval(Lvalue::from_ptr(key), PrimVal::new(new_key as u64), pthread_key_t)?; + self.write_primval(dest, PrimVal::new(0), dest_ty)?; + } + + "pthread_setspecific" => { + let key = self.value_to_primval(args[0], i32)?.to_u64(); + let val = args[1].read_ptr(&self.memory)?; + assert_eq!(key as i32 as u64, key); + self.pthread.insert(key as i32, val); + // FIXME: only keys that were created should exist + self.write_primval(dest, PrimVal::new(0), dest_ty)?; + } + + "pthread_getspecific" => { + let key = self.value_to_primval(args[0], i32)?.to_u64(); + assert_eq!(key as i32 as u64, key); + let val = self.pthread.get(&(key as i32)).map(|&p| p).unwrap_or(Pointer::from_int(0)); + self.write_primval(dest, PrimVal::from_ptr(val), dest_ty)?; + } // unix panic code inside libstd will read the return value of this function "pthread_rwlock_rdlock" => { From 76ea01889b015c8717b109bf6f46d5b825325157 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 15 Dec 2016 18:27:47 +0100 Subject: [PATCH 03/19] more intrinsics --- src/terminator/intrinsic.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/terminator/intrinsic.rs b/src/terminator/intrinsic.rs index 193abd2138..9a56ecab2d 100644 --- a/src/terminator/intrinsic.rs +++ b/src/terminator/intrinsic.rs @@ -66,6 +66,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } "atomic_store" | + "atomic_store_relaxed" | + "atomic_store_rel" | "volatile_store" => { let ty = substs.type_at(0); let dest = arg_vals[0].read_ptr(&self.memory)?; @@ -90,6 +92,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { self.write_primval(Lvalue::from_ptr(ptr), change, ty)?; } + "atomic_cxchg_relaxed" | "atomic_cxchg" => { let ty = substs.type_at(0); let ptr = arg_vals[0].read_ptr(&self.memory)?; @@ -108,6 +111,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { self.write_primval(Lvalue::from_ptr(ptr), change, ty)?; } + "atomic_xadd" | "atomic_xadd_relaxed" => { let ty = substs.type_at(0); let ptr = arg_vals[0].read_ptr(&self.memory)?; From 1ecb2ef9ffc09ed0023971b2774cc383dfee24c0 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 19 Dec 2016 12:33:03 +0100 Subject: [PATCH 04/19] address rebase issues --- src/step.rs | 4 ++-- src/terminator/mod.rs | 30 +++++++++++++++--------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/step.rs b/src/step.rs index a5e72523e4..728026de09 100644 --- a/src/step.rs +++ b/src/step.rs @@ -175,7 +175,7 @@ impl<'a, 'b, 'tcx> ConstantExtractor<'a, 'b, 'tcx> { self.try(|this| { if this.weak_linkage(def_id) { let data = match this.ecx.type_size(ty)?.expect("statics/consts can't be unsized") { - 0...8 => Value::ByVal(PrimVal::new(0)), + 0...8 => Value::ByVal(PrimVal::from_u64(0)), n => { let ptr = this.ecx.memory.allocate(n, 1)?; this.ecx.memory.write_repeat(ptr, 0, n)?; @@ -183,7 +183,7 @@ impl<'a, 'b, 'tcx> ConstantExtractor<'a, 'b, 'tcx> { }, }; this.ecx.globals.insert(cid, Global { - data: Some(data), + value: data, mutable: !immutable, ty: ty, }); diff --git a/src/terminator/mod.rs b/src/terminator/mod.rs index 0207709a56..4059e78a31 100644 --- a/src/terminator/mod.rs +++ b/src/terminator/mod.rs @@ -220,7 +220,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { None => { assert_eq!(&self.tcx.item_name(def_id).as_str()[..], "panic_impl"); let args_res: EvalResult> = arg_operands.iter() - .map(|arg| self.eval_operand(arg)?.ok_or(EvalError::ReadUndefBytes)) + .map(|arg| self.eval_operand(arg)) .collect(); let args = args_res?; // FIXME: process panic text @@ -229,7 +229,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { .expect("panic message not utf8") .to_owned(); let u32 = self.tcx.types.u32; - let line = self.value_to_primval(args[2], u32)?.to_u64() as u32; + let line = self.value_to_primval(args[2], u32)?.to_u64()? as u32; return Err(EvalError::Panic { file: file, line: line }); } }; @@ -431,13 +431,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "memrchr" => { let ptr = args[0].read_ptr(&self.memory)?; - let val = self.value_to_primval(args[1], usize)?.to_u64() as u8; - let num = self.value_to_primval(args[2], usize)?.to_u64(); + let val = self.value_to_primval(args[1], usize)?.to_u64()? as u8; + let num = self.value_to_primval(args[2], usize)?.to_u64()?; if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().rev().position(|&c| c == val) { let new_ptr = ptr.offset(num - idx as u64 - 1); - self.write_value(Value::ByVal(PrimVal::from_ptr(new_ptr)), dest, dest_ty)?; + self.write_value(Value::ByVal(PrimVal::Ptr(new_ptr)), dest, dest_ty)?; } else { - self.write_value(Value::ByVal(PrimVal::new(0)), dest, dest_ty)?; + self.write_value(Value::ByVal(PrimVal::from_u64(0)), dest, dest_ty)?; } } @@ -455,11 +455,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "write" => { // int filedes - let filedes = self.value_to_primval(args[0], usize)?.to_u64(); + let filedes = self.value_to_primval(args[0], usize)?.to_u64()?; // const void* buffer let buffer = args[1].read_ptr(&self.memory)?; // size_t size - let size = self.value_to_primval(args[0], usize)?.to_u64(); + let size = self.value_to_primval(args[0], usize)?.to_u64()?; { let data = self.memory.read_bytes(buffer, size)?; @@ -471,7 +471,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } } - self.write_primval(dest, PrimVal::new(size as u64), dest_ty)?; + self.write_primval(dest, PrimVal::from_u64(size), dest_ty)?; } "getenv" => { @@ -488,24 +488,24 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let pthread_key_t = self.tcx.types.i32; self.next_pthread_key += 1; let new_key = self.next_pthread_key; - self.write_primval(Lvalue::from_ptr(key), PrimVal::new(new_key as u64), pthread_key_t)?; - self.write_primval(dest, PrimVal::new(0), dest_ty)?; + self.write_primval(Lvalue::from_ptr(key), PrimVal::from_u64(new_key as u64), pthread_key_t)?; + self.write_primval(dest, PrimVal::from_u64(0), dest_ty)?; } "pthread_setspecific" => { - let key = self.value_to_primval(args[0], i32)?.to_u64(); + let key = self.value_to_primval(args[0], i32)?.to_u64()?; let val = args[1].read_ptr(&self.memory)?; assert_eq!(key as i32 as u64, key); self.pthread.insert(key as i32, val); // FIXME: only keys that were created should exist - self.write_primval(dest, PrimVal::new(0), dest_ty)?; + self.write_primval(dest, PrimVal::from_u64(0), dest_ty)?; } "pthread_getspecific" => { - let key = self.value_to_primval(args[0], i32)?.to_u64(); + let key = self.value_to_primval(args[0], i32)?.to_u64()?; assert_eq!(key as i32 as u64, key); let val = self.pthread.get(&(key as i32)).map(|&p| p).unwrap_or(Pointer::from_int(0)); - self.write_primval(dest, PrimVal::from_ptr(val), dest_ty)?; + self.write_primval(dest, PrimVal::Ptr(val), dest_ty)?; } // unix panic code inside libstd will read the return value of this function From 1f2966950dcf1099e94850dbfd127715ba62ba2a Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 19 Dec 2016 15:46:03 +0100 Subject: [PATCH 05/19] re-enable auxiliary tests for the host only --- src/bin/miri.rs | 11 ++++++++++- tests/compiletest.rs | 14 +++++++++++--- tests/run-pass/aux_test.rs | 7 +++---- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/bin/miri.rs b/src/bin/miri.rs index 24a0b7ba00..538a036ea7 100644 --- a/src/bin/miri.rs +++ b/src/bin/miri.rs @@ -21,7 +21,10 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls { let mut control = CompileController::basic(); control.after_hir_lowering.callback = Box::new(after_hir_lowering); control.after_analysis.callback = Box::new(after_analysis); - control.after_analysis.stop = Compilation::Stop; + if std::env::var("MIRI_HOST_TARGET") != Ok("yes".to_owned()) { + // only fully compile targets on the host + control.after_analysis.stop = Compilation::Stop; + } control } } @@ -136,6 +139,12 @@ fn main() { args.push(sysroot_flag); args.push(find_sysroot()); } + // we run the optimization passes inside miri + // if we ran them twice we'd get funny failures due to borrowck ElaborateDrops only working on + // unoptimized MIR + // FIXME: add an after-mir-passes hook to rustc driver + args.push("-Zmir-opt-level=0".to_owned()); + // for auxilary builds in unit tests args.push("-Zalways-encode-mir".to_owned()); rustc_driver::run_compiler(&args, &mut MiriCompilerCalls, None, None); diff --git a/tests/compiletest.rs b/tests/compiletest.rs index 50970086ee..90a40d8e39 100644 --- a/tests/compiletest.rs +++ b/tests/compiletest.rs @@ -27,13 +27,20 @@ fn run_pass() { compiletest::run_tests(&config); } -fn miri_pass(path: &str, target: &str) { +fn miri_pass(path: &str, target: &str, host: &str) { let mut config = compiletest::default_config(); config.mode = "mir-opt".parse().expect("Invalid mode"); config.src_base = PathBuf::from(path); config.target = target.to_owned(); config.rustc_path = PathBuf::from("target/debug/miri"); + // don't actually execute the final binary, it might be for other targets and we only care + // about running miri, not the binary. + config.runtool = Some("echo \"\" || ".to_owned()); + if target == host { + std::env::set_var("MIRI_HOST_TARGET", "yes"); + } compiletest::run_tests(&config); + std::env::set_var("MIRI_HOST_TARGET", ""); } fn is_target_dir>(path: P) -> bool { @@ -65,10 +72,11 @@ fn compile_test() { .to_owned(), }; run_pass(); + let host = toolchain.unwrap().splitn(2, '-').skip(1).next().unwrap(); for_all_targets(&sysroot, |target| { - miri_pass("tests/run-pass", &target); + miri_pass("tests/run-pass", &target, host); if let Ok(path) = std::env::var("MIRI_RUSTC_TEST") { - miri_pass(&path, &target); + miri_pass(&path, &target, host); } }); compile_fail(&sysroot); diff --git a/tests/run-pass/aux_test.rs b/tests/run-pass/aux_test.rs index 5510582e87..1b1dbaa683 100644 --- a/tests/run-pass/aux_test.rs +++ b/tests/run-pass/aux_test.rs @@ -1,9 +1,8 @@ // aux-build:dep.rs +// ignore-cross-compile -// FIXME: Auxiliary builds are currently broken. -// extern crate dep; +extern crate dep; fn main() { - // FIXME: Auxiliary builds are currently broken. - // dep::foo(); + dep::foo(); } From 3d431620e625d2f20effdd263f6f8237565fad74 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 19 Dec 2016 15:47:52 +0100 Subject: [PATCH 06/19] msvc has different internals for mutexes and thus fails on a different function --- tests/compile-fail/send-is-not-static-par-for.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/compile-fail/send-is-not-static-par-for.rs b/tests/compile-fail/send-is-not-static-par-for.rs index bee05ecd7f..afb401a919 100644 --- a/tests/compile-fail/send-is-not-static-par-for.rs +++ b/tests/compile-fail/send-is-not-static-par-for.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//error-pattern: no mir for `std::panicking::panicking` +//error-pattern: no mir for `std:: use std::sync::Mutex; From feed3da0a49268fbe004a9b03f96d0d6314fefdf Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 19 Dec 2016 15:59:32 +0100 Subject: [PATCH 07/19] fix travis --- tests/compiletest.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/compiletest.rs b/tests/compiletest.rs index 90a40d8e39..2d0e65c4c0 100644 --- a/tests/compiletest.rs +++ b/tests/compiletest.rs @@ -72,7 +72,14 @@ fn compile_test() { .to_owned(), }; run_pass(); - let host = toolchain.unwrap().splitn(2, '-').skip(1).next().unwrap(); + let host = Path::new(&sysroot).file_name() + .unwrap() + .to_str() + .unwrap() + .splitn(2, '-') + .skip(1) + .next() + .unwrap(); for_all_targets(&sysroot, |target| { miri_pass("tests/run-pass", &target, host); if let Ok(path) = std::env::var("MIRI_RUSTC_TEST") { From 885f1bfa26d06ce80d56daad4028007f75db0197 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 19 Dec 2016 17:26:47 +0100 Subject: [PATCH 08/19] allow using tuple variant names as function handles --- src/eval_context.rs | 70 +++++++++++++++---- src/terminator/mod.rs | 27 ++++--- .../tuple_like_enum_variant_constructor.rs | 3 + 3 files changed, 75 insertions(+), 25 deletions(-) create mode 100644 tests/run-pass/tuple_like_enum_variant_constructor.rs diff --git a/src/eval_context.rs b/src/eval_context.rs index 5cccf2b06c..6669ede3f4 100644 --- a/src/eval_context.rs +++ b/src/eval_context.rs @@ -364,18 +364,44 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Ok(()) } - fn assign_fields>( + pub fn assign_discr_and_fields< + I: IntoIterator, + V: IntoValTyPair<'tcx>, + J: IntoIterator, + >( &mut self, dest: Lvalue<'tcx>, offsets: I, - operands: &[mir::Operand<'tcx>], + operands: J, + discr_val: u64, + discr_size: u64, + ) -> EvalResult<'tcx, ()> { + // FIXME(solson) + let dest_ptr = self.force_allocation(dest)?.to_ptr(); + + let mut offsets = offsets.into_iter(); + let discr_offset = offsets.next().unwrap(); + let discr_dest = dest_ptr.offset(discr_offset); + self.memory.write_uint(discr_dest, discr_val, discr_size)?; + + self.assign_fields(dest, offsets, operands) + } + + pub fn assign_fields< + I: IntoIterator, + V: IntoValTyPair<'tcx>, + J: IntoIterator, + >( + &mut self, + dest: Lvalue<'tcx>, + offsets: I, + operands: J, ) -> EvalResult<'tcx, ()> { // FIXME(solson) let dest = self.force_allocation(dest)?.to_ptr(); for (offset, operand) in offsets.into_iter().zip(operands) { - let value = self.eval_operand(operand)?; - let value_ty = self.operand_ty(operand); + let (value, value_ty) = operand.into_val_ty_pair(self)?; let field_dest = dest.offset(offset); self.write_value_to_ptr(value, field_dest, value_ty)?; } @@ -440,18 +466,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { if let mir::AggregateKind::Adt(adt_def, variant, _, _) = *kind { let discr_val = adt_def.variants[variant].disr_val.to_u64_unchecked(); let discr_size = discr.size().bytes(); - let discr_offset = variants[variant].offsets[0].bytes(); - - // FIXME(solson) - let dest = self.force_allocation(dest)?; - let discr_dest = (dest.to_ptr()).offset(discr_offset); - self.memory.write_uint(discr_dest, discr_val, discr_size)?; - - // Don't include the first offset; it's for the discriminant. - let field_offsets = variants[variant].offsets.iter().skip(1) - .map(|s| s.bytes()); - self.assign_fields(dest, field_offsets, operands)?; + self.assign_discr_and_fields( + dest, + variants[variant].offsets.iter().cloned().map(Size::bytes), + operands, + discr_val, + discr_size, + )?; } else { bug!("tried to assign {:?} to Layout::General", kind); } @@ -1472,3 +1494,21 @@ pub fn monomorphize_field_ty<'a, 'tcx:'a >(tcx: TyCtxt<'a, 'tcx, 'tcx>, f: &ty:: let substituted = &f.ty(tcx, substs); tcx.normalize_associated_type(&substituted) } + +pub trait IntoValTyPair<'tcx> { + fn into_val_ty_pair<'a>(self, ecx: &mut EvalContext<'a, 'tcx>) -> EvalResult<'tcx, (Value, Ty<'tcx>)> where 'tcx: 'a; +} + +impl<'tcx> IntoValTyPair<'tcx> for (Value, Ty<'tcx>) { + fn into_val_ty_pair<'a>(self, _: &mut EvalContext<'a, 'tcx>) -> EvalResult<'tcx, (Value, Ty<'tcx>)> where 'tcx: 'a { + Ok(self) + } +} + +impl<'b, 'tcx: 'b> IntoValTyPair<'tcx> for &'b mir::Operand<'tcx> { + fn into_val_ty_pair<'a>(self, ecx: &mut EvalContext<'a, 'tcx>) -> EvalResult<'tcx, (Value, Ty<'tcx>)> where 'tcx: 'a { + let value = ecx.eval_operand(self)?; + let value_ty = ecx.operand_ty(self); + Ok((value, value_ty)) + } +} diff --git a/src/terminator/mod.rs b/src/terminator/mod.rs index 4059e78a31..5950c775dc 100644 --- a/src/terminator/mod.rs +++ b/src/terminator/mod.rs @@ -2,7 +2,7 @@ use rustc::hir::def_id::DefId; use rustc::mir; use rustc::traits::{self, Reveal}; use rustc::ty::fold::TypeFoldable; -use rustc::ty::layout::Layout; +use rustc::ty::layout::{Layout, Size}; use rustc::ty::subst::{Substs, Kind}; use rustc::ty::{self, Ty, TyCtxt, BareFnTy}; use syntax::codemap::{DUMMY_SP, Span}; @@ -261,20 +261,27 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let (lvalue, target) = destination.expect("tuple struct constructors can't diverge"); let dest_ty = self.tcx.item_type(adt_def.did); let dest_layout = self.type_layout(dest_ty)?; + let disr = v.disr_val.to_u64_unchecked(); match *dest_layout { Layout::Univariant { ref variant, .. } => { - assert_eq!(v.disr_val.to_u64_unchecked(), 0); + assert_eq!(disr, 0); let offsets = variant.offsets.iter().map(|s| s.bytes()); - // FIXME: don't allocate for single or dual field structs - let dest = self.force_allocation(lvalue)?.to_ptr(); - - for (offset, (value, value_ty)) in offsets.into_iter().zip(args) { - let field_dest = dest.offset(offset); - self.write_value_to_ptr(value, field_dest, value_ty)?; - } + self.assign_fields(lvalue, offsets, args)?; + }, + Layout::General { discr, ref variants, .. } => { + // FIXME: report a proper error for invalid discriminants + // right now we simply go into index out of bounds + let discr_size = discr.size().bytes(); + self.assign_discr_and_fields( + lvalue, + variants[disr as usize].offsets.iter().cloned().map(Size::bytes), + args, + disr, + discr_size, + )?; }, - // FIXME: enum variant constructors + // FIXME: raw nullable pointer constructors _ => bug!("bad layout for tuple struct constructor: {:?}", dest_layout), } self.goto_block(target); diff --git a/tests/run-pass/tuple_like_enum_variant_constructor.rs b/tests/run-pass/tuple_like_enum_variant_constructor.rs new file mode 100644 index 0000000000..5cf91b3f4d --- /dev/null +++ b/tests/run-pass/tuple_like_enum_variant_constructor.rs @@ -0,0 +1,3 @@ +fn main() { + assert_eq!(Some(42).map(Some), Some(Some(42))); +} From 1aac50c049ddf8a60c85bc7be91c0d5f80b13f2e Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 19 Dec 2016 17:49:51 +0100 Subject: [PATCH 09/19] allow using tuple variant names as function handles in presence of NonZero optimizations --- src/terminator/mod.rs | 7 ++++++- ...tuple_like_enum_variant_constructor_pointer_opt.rs | 4 ++++ ...ike_enum_variant_constructor_struct_pointer_opt.rs | 11 +++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 tests/run-pass/tuple_like_enum_variant_constructor_pointer_opt.rs create mode 100644 tests/run-pass/tuple_like_enum_variant_constructor_struct_pointer_opt.rs diff --git a/src/terminator/mod.rs b/src/terminator/mod.rs index 5950c775dc..53d31ab6ca 100644 --- a/src/terminator/mod.rs +++ b/src/terminator/mod.rs @@ -281,7 +281,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { discr_size, )?; }, - // FIXME: raw nullable pointer constructors + Layout::StructWrappedNullablePointer { .. } | + Layout::RawNullablePointer { .. } => { + assert_eq!(args.len(), 1); + let (val, ty) = args.pop().unwrap(); + self.write_value(val, lvalue, ty)?; + }, _ => bug!("bad layout for tuple struct constructor: {:?}", dest_layout), } self.goto_block(target); diff --git a/tests/run-pass/tuple_like_enum_variant_constructor_pointer_opt.rs b/tests/run-pass/tuple_like_enum_variant_constructor_pointer_opt.rs new file mode 100644 index 0000000000..fb57d4f4c1 --- /dev/null +++ b/tests/run-pass/tuple_like_enum_variant_constructor_pointer_opt.rs @@ -0,0 +1,4 @@ +fn main() { + let x = 5; + assert_eq!(Some(&x).map(Some), Some(Some(&x))); +} diff --git a/tests/run-pass/tuple_like_enum_variant_constructor_struct_pointer_opt.rs b/tests/run-pass/tuple_like_enum_variant_constructor_struct_pointer_opt.rs new file mode 100644 index 0000000000..e61e4af575 --- /dev/null +++ b/tests/run-pass/tuple_like_enum_variant_constructor_struct_pointer_opt.rs @@ -0,0 +1,11 @@ +#[derive(Copy, Clone, PartialEq, Debug)] +struct A<'a> { + x: i32, + y: &'a i32, +} + +fn main() { + let x = 5; + let a = A { x: 99, y: &x }; + assert_eq!(Some(a).map(Some), Some(Some(a))); +} From 578954b204319ac8a0f4d66af963016a2b6a06f3 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 19 Dec 2016 18:08:53 +0100 Subject: [PATCH 10/19] add test for unions and remove needles forced alloc --- src/eval_context.rs | 4 -- tests/run-pass/union.rs | 88 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 tests/run-pass/union.rs diff --git a/src/eval_context.rs b/src/eval_context.rs index 6669ede3f4..ba1d2dd956 100644 --- a/src/eval_context.rs +++ b/src/eval_context.rs @@ -547,10 +547,6 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let operand = &operands[0]; let value = self.eval_operand(operand)?; let value_ty = self.operand_ty(operand); - - // FIXME(solson) - let dest = self.force_allocation(dest)?; - self.write_value(value, dest, value_ty)?; } diff --git a/tests/run-pass/union.rs b/tests/run-pass/union.rs new file mode 100644 index 0000000000..9e05a89a4e --- /dev/null +++ b/tests/run-pass/union.rs @@ -0,0 +1,88 @@ +#![feature(untagged_unions)] +#![allow(dead_code, unused_variables)] + +fn main() { + a(); + b(); + c(); + d(); +} + +fn a() { + union U { + f1: u32, + f2: f32, + } + let mut u = U { f1: 1 }; + unsafe { + let b1 = &mut u.f1; + *b1 = 5; + } + assert_eq!(unsafe { u.f1 }, 5); +} + +fn b() { + struct S { + x: u32, + y: u32, + } + + union U { + s: S, + both: u64, + } + let mut u = U { s: S { x: 1, y: 2 } }; + unsafe { + let bx = &mut u.s.x; + let by = &mut u.s.y; + *bx = 5; + *by = 10; + } + assert_eq!(unsafe { u.s.x }, 5); + assert_eq!(unsafe { u.s.y }, 10); +} + +fn c() { + #[repr(u32)] + enum Tag { I, F } + + #[repr(C)] + union U { + i: i32, + f: f32, + } + + #[repr(C)] + struct Value { + tag: Tag, + u: U, + } + + fn is_zero(v: Value) -> bool { + unsafe { + match v { + Value { tag: Tag::I, u: U { i: 0 } } => true, + Value { tag: Tag::F, u: U { f: 0.0 } } => true, + _ => false, + } + } + } + assert!(is_zero(Value { tag: Tag::I, u: U { i: 0 }})); + assert!(is_zero(Value { tag: Tag::F, u: U { f: 0.0 }})); + assert!(!is_zero(Value { tag: Tag::I, u: U { i: 1 }})); + assert!(!is_zero(Value { tag: Tag::F, u: U { f: 42.0 }})); +} + +fn d() { + union MyUnion { + f1: u32, + f2: f32, + } + let u = MyUnion { f1: 10 }; + unsafe { + match u { + MyUnion { f1: 10 } => { } + MyUnion { f2 } => { panic!("foo"); } + } + } +} From f734c9d3fc6517b3ce1f25ac4ce2d9e49debed45 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 20 Dec 2016 09:05:46 +0100 Subject: [PATCH 11/19] try to pin down the travis failure --- tests/compiletest.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/compiletest.rs b/tests/compiletest.rs index 2d0e65c4c0..09b31b71bb 100644 --- a/tests/compiletest.rs +++ b/tests/compiletest.rs @@ -73,13 +73,13 @@ fn compile_test() { }; run_pass(); let host = Path::new(&sysroot).file_name() - .unwrap() + .expect("sysroot has no last par") .to_str() - .unwrap() + .expect("sysroot contains non utf8") .splitn(2, '-') .skip(1) .next() - .unwrap(); + .expect("target dir not prefixed"); for_all_targets(&sysroot, |target| { miri_pass("tests/run-pass", &target, host); if let Ok(path) = std::env::var("MIRI_RUSTC_TEST") { From d4f39fd4e0b94640918e3a0723bcbe1d5c77f67d Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 20 Dec 2016 09:32:26 +0100 Subject: [PATCH 12/19] rustup --- Cargo.lock | 32 ++++++++++++++++---------------- src/eval_context.rs | 2 +- src/lib.rs | 1 - 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b63b557f07..4eacf71491 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,7 +28,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -37,7 +37,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -51,12 +51,12 @@ dependencies = [ [[package]] name = "lazy_static" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -69,7 +69,7 @@ name = "log_settings" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -77,29 +77,29 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "0.1.77" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.3.5" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc-serialize" -version = "0.3.19" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -108,7 +108,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -140,14 +140,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum compiletest_rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f3f344389765ad7bec166f64c1b39ed6dd2b54d81c4c5dd8af789169351d380c" "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "49247ec2a285bb3dcb23cbd9c35193c025e7251bfce77c1d5da97e6362dffe7f" -"checksum libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)" = "408014cace30ee0f767b1c4517980646a573ec61a57957aeeabcac8ac0a02e8d" +"checksum lazy_static 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6abe0ee2e758cd6bc8a2cd56726359007748fbf4128da998b65d0b70f881e19b" +"checksum libc 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "a51822fc847e7a8101514d1d44e354ba2ffa7d4c194dcab48870740e327cac70" "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" "checksum log_settings 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3d382732ea0fbc09790c4899db3255bdea0fc78b54bf234bd18a63bb603915b6" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" -"checksum regex 0.1.77 (registry+https://github.com/rust-lang/crates.io-index)" = "64b03446c466d35b42f2a8b203c8e03ed8b91c0f17b56e1f84f7210a257aa665" -"checksum regex-syntax 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279401017ae31cf4e15344aa3f085d0e2e5c1e70067289ef906906fdbe92c8fd" -"checksum rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "6159e4e6e559c81bd706afe9c8fd68f547d3e851ce12e76b1de7914bab61691b" +"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" +"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" +"checksum rustc-serialize 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "237546c689f20bb44980270c73c3b9edd0891c1be49cc1274406134a66d3957b" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" diff --git a/src/eval_context.rs b/src/eval_context.rs index ba1d2dd956..738fff3c9a 100644 --- a/src/eval_context.rs +++ b/src/eval_context.rs @@ -500,7 +500,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } } - StructWrappedNullablePointer { nndiscr, ref nonnull, ref discrfield } => { + StructWrappedNullablePointer { nndiscr, ref nonnull, ref discrfield, .. } => { if let mir::AggregateKind::Adt(_, variant, _, _) = *kind { if nndiscr == variant as u64 { let offsets = nonnull.offsets.iter().map(|s| s.bytes()); diff --git a/src/lib.rs b/src/lib.rs index 1400d63776..d78b2d5cd9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,5 @@ #![feature( btree_range, - cell_extras, collections, collections_bound, pub_restricted, From 71bfaebe842d3e7d87d5af798143c71287880456 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 20 Dec 2016 09:58:41 +0100 Subject: [PATCH 13/19] clamp down on hacks in compiletest --- tests/compiletest.rs | 45 ++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/tests/compiletest.rs b/tests/compiletest.rs index 09b31b71bb..ae55c1adb5 100644 --- a/tests/compiletest.rs +++ b/tests/compiletest.rs @@ -3,9 +3,9 @@ extern crate compiletest_rs as compiletest; use std::path::{PathBuf, Path}; use std::io::Write; -fn compile_fail(sysroot: &str) { - let flags = format!("--sysroot {} -Dwarnings", sysroot); - for_all_targets(sysroot, |target| { +fn compile_fail(sysroot: &Path) { + let flags = format!("--sysroot {} -Dwarnings", sysroot.to_str().expect("non utf8 path")); + for_all_targets(&sysroot, |target| { let mut config = compiletest::default_config(); config.host_rustcflags = Some(flags.clone()); config.mode = "compile-fail".parse().expect("Invalid mode"); @@ -49,8 +49,10 @@ fn is_target_dir>(path: P) -> bool { path.metadata().map(|m| m.is_dir()).unwrap_or(false) } -fn for_all_targets(sysroot: &str, mut f: F) { - for entry in std::fs::read_dir(format!("{}/lib/rustlib/", sysroot)).unwrap() { +fn for_all_targets(sysroot: &Path, mut f: F) { + let target_dir = sysroot.join("lib").join("rustlib"); + println!("target dir: {}", target_dir.to_str().unwrap()); + for entry in std::fs::read_dir(target_dir).expect("invalid sysroot") { let entry = entry.unwrap(); if !is_target_dir(entry.path()) { continue; } let target = entry.file_name().into_string().unwrap(); @@ -62,24 +64,23 @@ fn for_all_targets(sysroot: &str, mut f: F) { #[test] fn compile_test() { - // Taken from https://github.com/Manishearth/rust-clippy/pull/911. - let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); - let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); - let sysroot = match (home, toolchain) { - (Some(home), Some(toolchain)) => format!("{}/toolchains/{}", home, toolchain), - _ => option_env!("RUST_SYSROOT") - .expect("need to specify RUST_SYSROOT env var or use rustup or multirust") - .to_owned(), - }; + let sysroot = std::process::Command::new("rustc") + .arg("--print") + .arg("sysroot") + .output() + .expect("rustc not found") + .stdout; + let sysroot = std::str::from_utf8(&sysroot).expect("sysroot is not utf8").trim(); + let sysroot = &Path::new(&sysroot); + let host = std::process::Command::new("rustc") + .arg("-vV") + .output() + .expect("rustc not found for -vV") + .stdout; + let host = std::str::from_utf8(&host).expect("sysroot is not utf8"); + let host = host.split("\nhost: ").skip(1).next().expect("no host: part in rustc -vV"); + let host = host.split("\n").next().expect("no \n after host"); run_pass(); - let host = Path::new(&sysroot).file_name() - .expect("sysroot has no last par") - .to_str() - .expect("sysroot contains non utf8") - .splitn(2, '-') - .skip(1) - .next() - .expect("target dir not prefixed"); for_all_targets(&sysroot, |target| { miri_pass("tests/run-pass", &target, host); if let Ok(path) = std::env::var("MIRI_RUSTC_TEST") { From c4e58638bbaa51e14f83be46e1530df8a87913a5 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 9 Jan 2017 12:38:06 +0100 Subject: [PATCH 14/19] rustup (i128) --- .gitignore | 1 + Cargo.lock | 8 ++-- Cargo.toml | 3 +- src/bin/miri.rs | 8 ++-- src/cast.rs | 40 +++++++++--------- src/error.rs | 2 +- src/eval_context.rs | 35 +++++++++------- src/lib.rs | 1 + src/lvalue.rs | 5 ++- src/memory.rs | 64 +++++++++++++++-------------- src/operator.rs | 44 +++++++++++--------- src/step.rs | 4 +- src/terminator/intrinsic.rs | 46 +++++++++++---------- src/terminator/mod.rs | 82 ++++++++++++++++++------------------- src/value.rs | 52 ++++++++++++----------- 15 files changed, 211 insertions(+), 184 deletions(-) diff --git a/.gitignore b/.gitignore index d9940aa58b..a51553a8c5 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ tex/*/out *.dot *.mir +*.rs.bk diff --git a/Cargo.lock b/Cargo.lock index 4eacf71491..c257b85329 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,7 +2,7 @@ name = "miri" version = "0.1.0" dependencies = [ - "byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.0.0 (git+https://github.com/quininer/byteorder.git?branch=i128)", "compiletest_rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -19,8 +19,8 @@ dependencies = [ [[package]] name = "byteorder" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +version = "1.0.0" +source = "git+https://github.com/quininer/byteorder.git?branch=i128#ef51df297aa833d0b6639aae328a95597fc07d75" [[package]] name = "compiletest_rs" @@ -136,7 +136,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" -"checksum byteorder 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96c8b41881888cc08af32d47ac4edd52bc7fa27fef774be47a92443756451304" +"checksum byteorder 1.0.0 (git+https://github.com/quininer/byteorder.git?branch=i128)" = "" "checksum compiletest_rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f3f344389765ad7bec166f64c1b39ed6dd2b54d81c4c5dd8af789169351d380c" "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" diff --git a/Cargo.toml b/Cargo.toml index 1d5de26f00..ada46a794c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,8 @@ test = false test = false [dependencies] -byteorder = "0.4.2" +#byteorder = "0.4.2" +byteorder = { git = "https://github.com/quininer/byteorder.git", branch = "i128", features = ["i128"]} env_logger = "0.3.3" log = "0.3.6" log_settings = "0.1.1" diff --git a/src/bin/miri.rs b/src/bin/miri.rs index 538a036ea7..56c2e433d0 100644 --- a/src/bin/miri.rs +++ b/src/bin/miri.rs @@ -1,4 +1,4 @@ -#![feature(rustc_private)] +#![feature(rustc_private, i128_type)] extern crate getopts; extern crate miri; @@ -54,7 +54,7 @@ fn resource_limits_from_attributes(state: &CompileState) -> miri::ResourceLimits let mut limits = miri::ResourceLimits::default(); let krate = state.hir_crate.as_ref().unwrap(); let err_msg = "miri attributes need to be in the form `miri(key = value)`"; - let extract_int = |lit: &syntax::ast::Lit| -> u64 { + let extract_int = |lit: &syntax::ast::Lit| -> u128 { match lit.node { syntax::ast::LitKind::Int(i, _) => i, _ => state.session.span_fatal(lit.span, "expected an integer literal"), @@ -67,8 +67,8 @@ fn resource_limits_from_attributes(state: &CompileState) -> miri::ResourceLimits if let NestedMetaItemKind::MetaItem(ref inner) = item.node { if let MetaItemKind::NameValue(ref value) = inner.node { match &inner.name().as_str()[..] { - "memory_size" => limits.memory_size = extract_int(value), - "step_limit" => limits.step_limit = extract_int(value), + "memory_size" => limits.memory_size = extract_int(value) as u64, + "step_limit" => limits.step_limit = extract_int(value) as u64, "stack_limit" => limits.stack_limit = extract_int(value) as usize, _ => state.session.span_err(item.span, "unknown miri attribute"), } diff --git a/src/cast.rs b/src/cast.rs index 2b3194a599..413c9b6ba8 100644 --- a/src/cast.rs +++ b/src/cast.rs @@ -20,34 +20,36 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { F32 => self.cast_float(val.to_f32()? as f64, dest_ty), F64 => self.cast_float(val.to_f64()?, dest_ty), - I8 | I16 | I32 | I64 => self.cast_signed_int(val.to_i64()?, dest_ty), + I8 | I16 | I32 | I64 | I128 => self.cast_signed_int(val.to_i128()?, dest_ty), - Bool | Char | U8 | U16 | U32 | U64 => self.cast_int(val.to_u64()?, dest_ty, false), + Bool | Char | U8 | U16 | U32 | U64 | U128 => self.cast_int(val.to_u128()?, dest_ty, false), FnPtr | Ptr => self.cast_ptr(val.to_ptr()?, dest_ty), } } - fn cast_signed_int(&self, val: i64, ty: ty::Ty<'tcx>) -> EvalResult<'tcx, PrimVal> { - self.cast_int(val as u64, ty, val < 0) + fn cast_signed_int(&self, val: i128, ty: ty::Ty<'tcx>) -> EvalResult<'tcx, PrimVal> { + self.cast_int(val as u128, ty, val < 0) } - fn cast_int(&self, v: u64, ty: ty::Ty<'tcx>, negative: bool) -> EvalResult<'tcx, PrimVal> { + fn cast_int(&self, v: u128, ty: ty::Ty<'tcx>, negative: bool) -> EvalResult<'tcx, PrimVal> { use rustc::ty::TypeVariants::*; match ty.sty { TyBool if v == 0 => Ok(PrimVal::from_bool(false)), TyBool if v == 1 => Ok(PrimVal::from_bool(true)), TyBool => Err(EvalError::InvalidBool), - TyInt(IntTy::I8) => Ok(PrimVal::Bytes(v as i64 as i8 as u64)), - TyInt(IntTy::I16) => Ok(PrimVal::Bytes(v as i64 as i16 as u64)), - TyInt(IntTy::I32) => Ok(PrimVal::Bytes(v as i64 as i32 as u64)), - TyInt(IntTy::I64) => Ok(PrimVal::Bytes(v as i64 as i64 as u64)), + TyInt(IntTy::I8) => Ok(PrimVal::Bytes(v as i128 as i8 as u128)), + TyInt(IntTy::I16) => Ok(PrimVal::Bytes(v as i128 as i16 as u128)), + TyInt(IntTy::I32) => Ok(PrimVal::Bytes(v as i128 as i32 as u128)), + TyInt(IntTy::I64) => Ok(PrimVal::Bytes(v as i128 as i64 as u128)), + TyInt(IntTy::I128) => Ok(PrimVal::Bytes(v as u128)), - TyUint(UintTy::U8) => Ok(PrimVal::Bytes(v as u8 as u64)), - TyUint(UintTy::U16) => Ok(PrimVal::Bytes(v as u16 as u64)), - TyUint(UintTy::U32) => Ok(PrimVal::Bytes(v as u32 as u64)), - TyUint(UintTy::U64) => Ok(PrimVal::Bytes(v)), + TyUint(UintTy::U8) => Ok(PrimVal::Bytes(v as u8 as u128)), + TyUint(UintTy::U16) => Ok(PrimVal::Bytes(v as u16 as u128)), + TyUint(UintTy::U32) => Ok(PrimVal::Bytes(v as u32 as u128)), + TyUint(UintTy::U64) => Ok(PrimVal::Bytes(v as u64 as u128)), + TyUint(UintTy::U128) => Ok(PrimVal::Bytes(v)), TyInt(IntTy::Is) => { let int_ty = self.tcx.sess.target.int_type; @@ -61,15 +63,15 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { self.cast_int(v, ty, negative) } - TyFloat(FloatTy::F64) if negative => Ok(PrimVal::from_f64(v as i64 as f64)), + TyFloat(FloatTy::F64) if negative => Ok(PrimVal::from_f64(v as i128 as f64)), TyFloat(FloatTy::F64) => Ok(PrimVal::from_f64(v as f64)), - TyFloat(FloatTy::F32) if negative => Ok(PrimVal::from_f32(v as i64 as f32)), + TyFloat(FloatTy::F32) if negative => Ok(PrimVal::from_f32(v as i128 as f32)), TyFloat(FloatTy::F32) => Ok(PrimVal::from_f32(v as f32)), - TyChar if v as u8 as u64 == v => Ok(PrimVal::Bytes(v)), + TyChar if v as u8 as u128 == v => Ok(PrimVal::Bytes(v)), TyChar => Err(EvalError::InvalidChar(v)), - TyRawPtr(_) => Ok(PrimVal::Ptr(Pointer::from_int(v))), + TyRawPtr(_) => Ok(PrimVal::Ptr(Pointer::from_int(v as u64))), _ => Err(EvalError::Unimplemented(format!("int to {:?} cast", ty))), } @@ -80,9 +82,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { match ty.sty { // Casting negative floats to unsigned integers yields zero. TyUint(_) if val < 0.0 => self.cast_int(0, ty, false), - TyInt(_) if val < 0.0 => self.cast_int(val as i64 as u64, ty, true), + TyInt(_) if val < 0.0 => self.cast_int(val as i128 as u128, ty, true), - TyInt(_) | ty::TyUint(_) => self.cast_int(val as u64, ty, false), + TyInt(_) | ty::TyUint(_) => self.cast_int(val as u128, ty, false), TyFloat(FloatTy::F64) => Ok(PrimVal::from_f64(val)), TyFloat(FloatTy::F32) => Ok(PrimVal::from_f32(val as f32)), diff --git a/src/error.rs b/src/error.rs index ca5ff8356c..5d09d2372a 100644 --- a/src/error.rs +++ b/src/error.rs @@ -31,7 +31,7 @@ pub enum EvalError<'tcx> { ExecuteMemory, ArrayIndexOutOfBounds(Span, u64, u64), Math(Span, ConstMathErr), - InvalidChar(u64), + InvalidChar(u128), OutOfMemory { allocation_size: u64, memory_size: u64, diff --git a/src/eval_context.rs b/src/eval_context.rs index b6adde6131..a2a51f6dba 100644 --- a/src/eval_context.rs +++ b/src/eval_context.rs @@ -175,7 +175,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let ptr = self.memory.allocate(s.len() as u64, 1)?; self.memory.write_bytes(ptr, s.as_bytes())?; self.memory.freeze(ptr.alloc_id)?; - Ok(Value::ByValPair(PrimVal::Ptr(ptr), PrimVal::from_u64(s.len() as u64))) + Ok(Value::ByValPair(PrimVal::Ptr(ptr), PrimVal::from_u128(s.len() as u128))) } pub(super) fn const_to_value(&mut self, const_val: &ConstVal) -> EvalResult<'tcx, Value> { @@ -183,7 +183,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { use rustc_const_math::ConstFloat; let primval = match *const_val { - Integral(const_int) => PrimVal::Bytes(const_int.to_u64_unchecked()), + Integral(const_int) => PrimVal::Bytes(const_int.to_u128_unchecked()), Float(ConstFloat::F32(f)) => PrimVal::from_f32(f), Float(ConstFloat::F64(f)) => PrimVal::from_f64(f), @@ -370,7 +370,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { dest: Lvalue<'tcx>, offsets: I, operands: J, - discr_val: u64, + discr_val: u128, discr_size: u64, ) -> EvalResult<'tcx, ()> { // FIXME(solson) @@ -461,7 +461,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { General { discr, ref variants, .. } => { if let mir::AggregateKind::Adt(adt_def, variant, _, _) = *kind { - let discr_val = adt_def.variants[variant].disr_val.to_u64_unchecked(); + let discr_val = adt_def.variants[variant].disr_val.to_u128_unchecked(); let discr_size = discr.size().bytes(); self.assign_discr_and_fields( @@ -525,7 +525,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { CEnum { .. } => { assert_eq!(operands.len(), 0); if let mir::AggregateKind::Adt(adt_def, variant, _, _) = *kind { - let n = adt_def.variants[variant].disr_val.to_u64_unchecked(); + let n = adt_def.variants[variant].disr_val.to_u128_unchecked(); self.write_primval(dest, PrimVal::Bytes(n), dest_ty)?; } else { bug!("tried to assign {:?} to Layout::CEnum", kind); @@ -580,7 +580,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let src = self.eval_lvalue(lvalue)?; let ty = self.lvalue_ty(lvalue); let (_, len) = src.elem_ty_and_len(ty); - self.write_primval(dest, PrimVal::from_u64(len), dest_ty)?; + self.write_primval(dest, PrimVal::from_u128(len as u128), dest_ty)?; } Ref(_, _, ref lvalue) => { @@ -590,7 +590,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let val = match extra { LvalueExtra::None => Value::ByVal(ptr), - LvalueExtra::Length(len) => Value::ByValPair(ptr, PrimVal::from_u64(len)), + LvalueExtra::Length(len) => Value::ByValPair(ptr, PrimVal::from_u128(len as u128)), LvalueExtra::Vtable(vtable) => Value::ByValPair(ptr, PrimVal::Ptr(vtable)), LvalueExtra::DowncastVariant(..) => bug!("attempted to take a reference to an enum downcast lvalue"), @@ -1052,6 +1052,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { I16 => 2, I32 => 4, I64 => 8, + I128 => 16, Is => self.memory.pointer_size(), }; PrimValKind::from_int_size(size) @@ -1064,6 +1065,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { U16 => 2, U32 => 4, U64 => 8, + U128 => 16, Us => self.memory.pointer_size(), }; PrimValKind::from_uint_size(size) @@ -1116,7 +1118,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { ty::TyBool if val.to_bytes()? > 1 => Err(EvalError::InvalidBool), ty::TyChar if ::std::char::from_u32(val.to_bytes()? as u32).is_none() - => Err(EvalError::InvalidChar(val.to_bytes()? as u32 as u64)), + => Err(EvalError::InvalidChar(val.to_bytes()? as u32 as u128)), _ => Ok(()), } @@ -1139,7 +1141,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let c = self.memory.read_uint(ptr, 4)? as u32; match ::std::char::from_u32(c) { Some(ch) => PrimVal::from_char(ch), - None => return Err(EvalError::InvalidChar(c as u64)), + None => return Err(EvalError::InvalidChar(c as u128)), } } @@ -1150,9 +1152,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { I16 => 2, I32 => 4, I64 => 8, + I128 => 16, Is => self.memory.pointer_size(), }; - PrimVal::from_i64(self.memory.read_int(ptr, size)?) + PrimVal::from_i128(self.memory.read_int(ptr, size)?) } ty::TyUint(uint_ty) => { @@ -1162,9 +1165,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { U16 => 2, U32 => 4, U64 => 8, + U128 => 16, Us => self.memory.pointer_size(), }; - PrimVal::from_u64(self.memory.read_uint(ptr, size)?) + PrimVal::from_u128(self.memory.read_uint(ptr, size)?) } ty::TyFloat(FloatTy::F32) => PrimVal::from_f32(self.memory.read_f32(ptr)?), @@ -1183,7 +1187,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let extra = match self.tcx.struct_tail(ty).sty { ty::TyDynamic(..) => PrimVal::Ptr(self.memory.read_ptr(extra)?), ty::TySlice(..) | - ty::TyStr => PrimVal::from_u64(self.memory.read_usize(extra)?), + ty::TyStr => PrimVal::from_u128(self.memory.read_usize(extra)? as u128), _ => bug!("unsized primval ptr read from {:?}", ty), }; return Ok(Some(Value::ByValPair(PrimVal::Ptr(p), extra))); @@ -1195,9 +1199,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { if let CEnum { discr, signed, .. } = *self.type_layout(ty)? { let size = discr.size().bytes(); if signed { - PrimVal::from_i64(self.memory.read_int(ptr, size)?) + PrimVal::from_i128(self.memory.read_int(ptr, size)?) } else { - PrimVal::from_u64(self.memory.read_uint(ptr, size)?) + PrimVal::from_u128(self.memory.read_uint(ptr, size)?) } } else { return Ok(None); @@ -1244,7 +1248,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { match (&src_pointee_ty.sty, &dest_pointee_ty.sty) { (&ty::TyArray(_, length), &ty::TySlice(_)) => { let ptr = src.read_ptr(&self.memory)?; - let len = PrimVal::from_u64(length as u64); + let len = PrimVal::from_u128(length as u128); let ptr = PrimVal::Ptr(ptr); self.write_value(Value::ByValPair(ptr, len), dest, dest_ty)?; } @@ -1478,6 +1482,7 @@ impl IntegerExt for layout::Integer { I16 => Size::from_bits(16), I32 => Size::from_bits(32), I64 => Size::from_bits(64), + I128 => Size::from_bits(128), } } } diff --git a/src/lib.rs b/src/lib.rs index 8965384e16..418ccfa549 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ collections_bound, pub_restricted, rustc_private, + i128_type, )] // From rustc. diff --git a/src/lvalue.rs b/src/lvalue.rs index 966fb65c3c..9ea8b2f148 100644 --- a/src/lvalue.rs +++ b/src/lvalue.rs @@ -282,7 +282,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let elem_size = self.type_size(elem_ty)?.expect("slice element must be sized"); let n_ptr = self.eval_operand(operand)?; let usize = self.tcx.types.usize; - let n = self.value_to_primval(n_ptr, usize)?.to_u64()?; + let n = self.value_to_primval(n_ptr, usize)?.to_u128()?; + // we read a target usize, it can't be 128 bits + assert_eq!(n as u64 as u128, n); + let n = n as u64; assert!(n < len); let ptr = base_ptr.offset(n * elem_size); (ptr, LvalueExtra::None) diff --git a/src/memory.rs b/src/memory.rs index 2825f55eab..5be28f2771 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -1,7 +1,7 @@ -use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian, BigEndian, self}; +use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian, BigEndian}; use std::collections::Bound::{Included, Excluded}; use std::collections::{btree_map, BTreeMap, HashMap, HashSet, VecDeque}; -use std::{fmt, iter, ptr, mem}; +use std::{fmt, iter, ptr, mem, io}; use rustc::hir::def_id::DefId; use rustc::ty::{self, BareFnTy, ClosureTy, ClosureSubsts, TyCtxt}; @@ -567,6 +567,8 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { let endianess = self.endianess(); let bytes = self.get_bytes_unchecked(ptr, size)?; let offset = read_target_uint(endianess, bytes).unwrap(); + assert_eq!(offset as u64 as u128, offset); + let offset = offset as u64; let alloc = self.get(ptr.alloc_id)?; match alloc.relocations.get(&ptr.offset) { Some(&alloc_id) => Ok(Pointer::new(alloc_id, offset)), @@ -596,10 +598,11 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { // We need to mask here, or the byteorder crate can die when given a u64 larger // than fits in an integer of the requested size. let mask = match size { - 1 => 0xff, - 2 => 0xffff, - 4 => 0xffffffff, - 8 => 0xffffffffffffffff, + 1 => !0u8 as u128, + 2 => !0u16 as u128, + 4 => !0u32 as u128, + 8 => !0u64 as u128, + 16 => !0, _ => bug!("unexpected PrimVal::Bytes size"), }; self.write_uint(dest, bytes & mask, size) @@ -630,16 +633,17 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { 2 => Ok(self.layout.i16_align.abi()), 4 => Ok(self.layout.i32_align.abi()), 8 => Ok(self.layout.i64_align.abi()), + 16 => Ok(self.layout.i128_align.abi()), _ => bug!("bad integer size: {}", size), } } - pub fn read_int(&self, ptr: Pointer, size: u64) -> EvalResult<'tcx, i64> { + pub fn read_int(&self, ptr: Pointer, size: u64) -> EvalResult<'tcx, i128> { let align = self.int_align(size)?; self.get_bytes(ptr, size, align).map(|b| read_target_int(self.endianess(), b).unwrap()) } - pub fn write_int(&mut self, ptr: Pointer, n: i64, size: u64) -> EvalResult<'tcx, ()> { + pub fn write_int(&mut self, ptr: Pointer, n: i128, size: u64) -> EvalResult<'tcx, ()> { let align = self.int_align(size)?; let endianess = self.endianess(); let b = self.get_bytes_mut(ptr, size, align)?; @@ -647,12 +651,12 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { Ok(()) } - pub fn read_uint(&self, ptr: Pointer, size: u64) -> EvalResult<'tcx, u64> { + pub fn read_uint(&self, ptr: Pointer, size: u64) -> EvalResult<'tcx, u128> { let align = self.int_align(size)?; self.get_bytes(ptr, size, align).map(|b| read_target_uint(self.endianess(), b).unwrap()) } - pub fn write_uint(&mut self, ptr: Pointer, n: u64, size: u64) -> EvalResult<'tcx, ()> { + pub fn write_uint(&mut self, ptr: Pointer, n: u128, size: u64) -> EvalResult<'tcx, ()> { let align = self.int_align(size)?; let endianess = self.endianess(); let b = self.get_bytes_mut(ptr, size, align)?; @@ -661,21 +665,21 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { } pub fn read_isize(&self, ptr: Pointer) -> EvalResult<'tcx, i64> { - self.read_int(ptr, self.pointer_size()) + self.read_int(ptr, self.pointer_size()).map(|i| i as i64) } pub fn write_isize(&mut self, ptr: Pointer, n: i64) -> EvalResult<'tcx, ()> { let size = self.pointer_size(); - self.write_int(ptr, n, size) + self.write_int(ptr, n as i128, size) } pub fn read_usize(&self, ptr: Pointer) -> EvalResult<'tcx, u64> { - self.read_uint(ptr, self.pointer_size()) + self.read_uint(ptr, self.pointer_size()).map(|i| i as u64) } pub fn write_usize(&mut self, ptr: Pointer, n: u64) -> EvalResult<'tcx, ()> { let size = self.pointer_size(); - self.write_uint(ptr, n, size) + self.write_uint(ptr, n as u128, size) } pub fn write_f32(&mut self, ptr: Pointer, f: f32) -> EvalResult<'tcx, ()> { @@ -801,31 +805,31 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { // Methods to access integers in the target endianess //////////////////////////////////////////////////////////////////////////////// -fn write_target_uint(endianess: layout::Endian, mut target: &mut [u8], data: u64) -> Result<(), byteorder::Error> { +fn write_target_uint(endianess: layout::Endian, mut target: &mut [u8], data: u128) -> Result<(), io::Error> { let len = target.len(); match endianess { - layout::Endian::Little => target.write_uint::(data, len), - layout::Endian::Big => target.write_uint::(data, len), + layout::Endian::Little => target.write_uint128::(data, len), + layout::Endian::Big => target.write_uint128::(data, len), } } -fn write_target_int(endianess: layout::Endian, mut target: &mut [u8], data: i64) -> Result<(), byteorder::Error> { +fn write_target_int(endianess: layout::Endian, mut target: &mut [u8], data: i128) -> Result<(), io::Error> { let len = target.len(); match endianess { - layout::Endian::Little => target.write_int::(data, len), - layout::Endian::Big => target.write_int::(data, len), + layout::Endian::Little => target.write_int128::(data, len), + layout::Endian::Big => target.write_int128::(data, len), } } -fn read_target_uint(endianess: layout::Endian, mut source: &[u8]) -> Result { +fn read_target_uint(endianess: layout::Endian, mut source: &[u8]) -> Result { match endianess { - layout::Endian::Little => source.read_uint::(source.len()), - layout::Endian::Big => source.read_uint::(source.len()), + layout::Endian::Little => source.read_uint128::(source.len()), + layout::Endian::Big => source.read_uint128::(source.len()), } } -fn read_target_int(endianess: layout::Endian, mut source: &[u8]) -> Result { +fn read_target_int(endianess: layout::Endian, mut source: &[u8]) -> Result { match endianess { - layout::Endian::Little => source.read_int::(source.len()), - layout::Endian::Big => source.read_int::(source.len()), + layout::Endian::Little => source.read_int128::(source.len()), + layout::Endian::Big => source.read_int128::(source.len()), } } @@ -833,26 +837,26 @@ fn read_target_int(endianess: layout::Endian, mut source: &[u8]) -> Result Result<(), byteorder::Error> { +fn write_target_f32(endianess: layout::Endian, mut target: &mut [u8], data: f32) -> Result<(), io::Error> { match endianess { layout::Endian::Little => target.write_f32::(data), layout::Endian::Big => target.write_f32::(data), } } -fn write_target_f64(endianess: layout::Endian, mut target: &mut [u8], data: f64) -> Result<(), byteorder::Error> { +fn write_target_f64(endianess: layout::Endian, mut target: &mut [u8], data: f64) -> Result<(), io::Error> { match endianess { layout::Endian::Little => target.write_f64::(data), layout::Endian::Big => target.write_f64::(data), } } -fn read_target_f32(endianess: layout::Endian, mut source: &[u8]) -> Result { +fn read_target_f32(endianess: layout::Endian, mut source: &[u8]) -> Result { match endianess { layout::Endian::Little => source.read_f32::(), layout::Endian::Big => source.read_f32::(), } } -fn read_target_f64(endianess: layout::Endian, mut source: &[u8]) -> Result { +fn read_target_f64(endianess: layout::Endian, mut source: &[u8]) -> Result { match endianess { layout::Endian::Little => source.read_f64::(), layout::Endian::Big => source.read_f64::(), diff --git a/src/operator.rs b/src/operator.rs index 2e1ac07529..417e7047ec 100644 --- a/src/operator.rs +++ b/src/operator.rs @@ -66,7 +66,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { macro_rules! overflow { ($op:ident, $l:expr, $r:expr) => ({ let (val, overflowed) = $l.$op($r); - let primval = PrimVal::Bytes(val as u64); + let primval = PrimVal::Bytes(val as u128); Ok((primval, overflowed)) }) } @@ -144,7 +144,7 @@ pub fn binary_op<'tcx>( fn normalize(val: PrimVal) -> PrimVal { if let PrimVal::Ptr(ptr) = val { if let Ok(bytes) = ptr.to_int() { - return PrimVal::Bytes(bytes); + return PrimVal::Bytes(bytes as u128); } } val @@ -158,7 +158,7 @@ pub fn binary_op<'tcx>( if left_ptr.alloc_id == right_ptr.alloc_id { // If the pointers are into the same allocation, fall through to the more general // match later, which will do comparisons on the pointer offsets. - (left_ptr.offset, right_ptr.offset) + (left_ptr.offset as u128, right_ptr.offset as u128) } else { return Ok((unrelated_ptr_ops(bin_op, left_ptr, right_ptr)?, false)); } @@ -166,7 +166,7 @@ pub fn binary_op<'tcx>( (PrimVal::Ptr(ptr), PrimVal::Bytes(bytes)) | (PrimVal::Bytes(bytes), PrimVal::Ptr(ptr)) => { - return Ok((unrelated_ptr_ops(bin_op, ptr, Pointer::from_int(bytes))?, false)); + return Ok((unrelated_ptr_ops(bin_op, ptr, Pointer::from_int(bytes as u64))?, false)); } (PrimVal::Undef, _) | (_, PrimVal::Undef) => return Err(EvalError::ReadUndefBytes), @@ -182,6 +182,7 @@ pub fn binary_op<'tcx>( I16 | U16 => 16, I32 | U32 => 32, I64 | U64 => 64, + I128 | U128 => 128, _ => bug!("bad MIR: bitshift lhs is not integral"), }; @@ -278,22 +279,25 @@ pub fn unary_op<'tcx>( let bytes = val.to_bytes()?; let result_bytes = match (un_op, val_kind) { - (Not, Bool) => !bytes_to_bool(bytes) as u64, - - (Not, U8) => !(bytes as u8) as u64, - (Not, U16) => !(bytes as u16) as u64, - (Not, U32) => !(bytes as u32) as u64, - (Not, U64) => !bytes, - - (Not, I8) => !(bytes as i8) as u64, - (Not, I16) => !(bytes as i16) as u64, - (Not, I32) => !(bytes as i32) as u64, - (Not, I64) => !(bytes as i64) as u64, - - (Neg, I8) => -(bytes as i8) as u64, - (Neg, I16) => -(bytes as i16) as u64, - (Neg, I32) => -(bytes as i32) as u64, - (Neg, I64) => -(bytes as i64) as u64, + (Not, Bool) => !bytes_to_bool(bytes) as u128, + + (Not, U8) => !(bytes as u8) as u128, + (Not, U16) => !(bytes as u16) as u128, + (Not, U32) => !(bytes as u32) as u128, + (Not, U64) => !(bytes as u64) as u128, + (Not, U128) => !bytes, + + (Not, I8) => !(bytes as i8) as u128, + (Not, I16) => !(bytes as i16) as u128, + (Not, I32) => !(bytes as i32) as u128, + (Not, I64) => !(bytes as i64) as u128, + (Not, I128) => !(bytes as i128) as u128, + + (Neg, I8) => -(bytes as i8) as u128, + (Neg, I16) => -(bytes as i16) as u128, + (Neg, I32) => -(bytes as i32) as u128, + (Neg, I64) => -(bytes as i64) as u128, + (Neg, I128) => -(bytes as i128) as u128, (Neg, F32) => f32_to_bytes(-bytes_to_f32(bytes)), (Neg, F64) => f64_to_bytes(-bytes_to_f64(bytes)), diff --git a/src/step.rs b/src/step.rs index 728026de09..54205ee0b4 100644 --- a/src/step.rs +++ b/src/step.rs @@ -103,7 +103,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let dest = self.force_allocation(dest)?; let discr_dest = (dest.to_ptr()).offset(discr_offset); - self.memory.write_uint(discr_dest, variant_index as u64, discr_size)?; + self.memory.write_uint(discr_dest, variant_index as u128, discr_size)?; } Layout::RawNullablePointer { nndiscr, .. } => { @@ -175,7 +175,7 @@ impl<'a, 'b, 'tcx> ConstantExtractor<'a, 'b, 'tcx> { self.try(|this| { if this.weak_linkage(def_id) { let data = match this.ecx.type_size(ty)?.expect("statics/consts can't be unsized") { - 0...8 => Value::ByVal(PrimVal::from_u64(0)), + 0...8 => Value::ByVal(PrimVal::from_u128(0)), n => { let ptr = this.ecx.memory.allocate(n, 1)?; this.ecx.memory.write_repeat(ptr, 0, n)?; diff --git a/src/terminator/intrinsic.rs b/src/terminator/intrinsic.rs index 9a56ecab2d..971aece77f 100644 --- a/src/terminator/intrinsic.rs +++ b/src/terminator/intrinsic.rs @@ -45,8 +45,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "arith_offset" => { let ptr = arg_vals[0].read_ptr(&self.memory)?; - let offset = self.value_to_primval(arg_vals[1], isize)?.to_i64()?; - let new_ptr = ptr.signed_offset(offset); + let offset = self.value_to_primval(arg_vals[1], isize)?.to_i128()?; + let new_ptr = ptr.signed_offset(offset as i64); self.write_primval(dest, PrimVal::Ptr(new_ptr), dest_ty)?; } @@ -156,7 +156,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let elem_align = self.type_align(elem_ty)?; let src = arg_vals[0].read_ptr(&self.memory)?; let dest = arg_vals[1].read_ptr(&self.memory)?; - let count = self.value_to_primval(arg_vals[2], usize)?.to_u64()?; + let count = self.value_to_primval(arg_vals[2], usize)?.to_u128()? as u64; self.memory.copy(src, dest, count * elem_size, elem_align)?; } @@ -189,7 +189,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { ptr: ptr.to_ptr()?, extra: match self.tcx.struct_tail(ty).sty { ty::TyDynamic(..) => LvalueExtra::Vtable(extra.to_ptr()?), - ty::TyStr | ty::TySlice(_) => LvalueExtra::Length(extra.to_u64()?), + ty::TyStr | ty::TySlice(_) => LvalueExtra::Length(extra.to_u128()? as u64), _ => bug!("invalid fat pointer type: {}", ptr_ty), }, }, @@ -264,7 +264,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "min_align_of" => { let elem_ty = substs.type_at(0); let elem_align = self.type_align(elem_ty)?; - let align_val = PrimVal::from_u64(elem_align as u64); + let align_val = PrimVal::from_u128(elem_align as u128); self.write_primval(dest, align_val, dest_ty)?; } @@ -272,7 +272,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let ty = substs.type_at(0); let layout = self.type_layout(ty)?; let align = layout.align(&self.tcx.data_layout).pref(); - let align_val = PrimVal::from_u64(align); + let align_val = PrimVal::from_u128(align as u128); self.write_primval(dest, align_val, dest_ty)?; } @@ -293,7 +293,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let pointee_ty = substs.type_at(0); // FIXME: assuming here that type size is < i64::max_value() let pointee_size = self.type_size(pointee_ty)?.expect("cannot offset a pointer to an unsized type") as i64; - let offset = self.value_to_primval(arg_vals[1], isize)?.to_i64()?; + let offset = self.value_to_primval(arg_vals[1], isize)?.to_i128()? as i64; let ptr = arg_vals[0].read_ptr(&self.memory)?; let result_ptr = ptr.signed_offset(offset * pointee_size); @@ -314,13 +314,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "powif32" => { let f = self.value_to_primval(arg_vals[0], f32)?.to_f32()?; - let i = self.value_to_primval(arg_vals[1], i32)?.to_i64()?; + let i = self.value_to_primval(arg_vals[1], i32)?.to_i128()?; self.write_primval(dest, PrimVal::from_f32(f.powi(i as i32)), dest_ty)?; } "powif64" => { let f = self.value_to_primval(arg_vals[0], f64)?.to_f64()?; - let i = self.value_to_primval(arg_vals[1], i32)?.to_i64()?; + let i = self.value_to_primval(arg_vals[1], i32)?.to_i128()?; self.write_primval(dest, PrimVal::from_f64(f.powi(i as i32)), dest_ty)?; } @@ -340,21 +340,21 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { // `size_of_val` intrinsic, then change this back to // .expect("size_of intrinsic called on unsized value") // see https://github.com/rust-lang/rust/pull/37708 - let size = self.type_size(ty)?.unwrap_or(!0) as u64; - self.write_primval(dest, PrimVal::from_u64(size), dest_ty)?; + let size = self.type_size(ty)?.unwrap_or(!0) as u128; + self.write_primval(dest, PrimVal::from_u128(size), dest_ty)?; } "size_of_val" => { let ty = substs.type_at(0); let (size, _) = self.size_and_align_of_dst(ty, arg_vals[0])?; - self.write_primval(dest, PrimVal::from_u64(size), dest_ty)?; + self.write_primval(dest, PrimVal::from_u128(size as u128), dest_ty)?; } "min_align_of_val" | "align_of_val" => { let ty = substs.type_at(0); let (_, align) = self.size_and_align_of_dst(ty, arg_vals[0])?; - self.write_primval(dest, PrimVal::from_u64(align), dest_ty)?; + self.write_primval(dest, PrimVal::from_u128(align as u128), dest_ty)?; } "type_name" => { @@ -366,7 +366,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "type_id" => { let ty = substs.type_at(0); let n = self.tcx.type_id_hash(ty); - self.write_primval(dest, PrimVal::Bytes(n), dest_ty)?; + self.write_primval(dest, PrimVal::Bytes(n as u128), dest_ty)?; } "transmute" => { @@ -518,14 +518,16 @@ fn numeric_intrinsic<'tcx>( use value::PrimValKind::*; let result_bytes = match $kind { - I8 => (bytes as i8).$method() as u64, - U8 => (bytes as u8).$method() as u64, - I16 => (bytes as i16).$method() as u64, - U16 => (bytes as u16).$method() as u64, - I32 => (bytes as i32).$method() as u64, - U32 => (bytes as u32).$method() as u64, - I64 => (bytes as i64).$method() as u64, - U64 => bytes.$method() as u64, + 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, _ => bug!("invalid `{}` argument: {:?}", $name, val), }; diff --git a/src/terminator/mod.rs b/src/terminator/mod.rs index 53d31ab6ca..47ebd27abd 100644 --- a/src/terminator/mod.rs +++ b/src/terminator/mod.rs @@ -73,7 +73,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let adt_ty = self.lvalue_ty(discr); let discr_val = self.read_discriminant_value(adt_ptr, adt_ty)?; let matching = adt_def.variants.iter() - .position(|v| discr_val == v.disr_val.to_u64_unchecked()); + .position(|v| discr_val == v.disr_val.to_u128_unchecked()); match matching { Some(i) => self.goto_block(targets[i]), @@ -143,10 +143,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let span = terminator.source_info.span; let len = self.eval_operand_to_primval(len) .expect("can't eval len") - .to_u64()?; + .to_u128()? as u64; let index = self.eval_operand_to_primval(index) .expect("can't eval index") - .to_u64()?; + .to_u128()? as u64; Err(EvalError::ArrayIndexOutOfBounds(span, len, index)) }, mir::AssertMessage::Math(ref err) => @@ -229,7 +229,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { .expect("panic message not utf8") .to_owned(); let u32 = self.tcx.types.u32; - let line = self.value_to_primval(args[2], u32)?.to_u64()? as u32; + let line = self.value_to_primval(args[2], u32)?.to_u128()? as u32; return Err(EvalError::Panic { file: file, line: line }); } }; @@ -261,7 +261,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let (lvalue, target) = destination.expect("tuple struct constructors can't diverge"); let dest_ty = self.tcx.item_type(adt_def.did); let dest_layout = self.type_layout(dest_ty)?; - let disr = v.disr_val.to_u64_unchecked(); + let disr = v.disr_val.to_u128_unchecked(); match *dest_layout { Layout::Univariant { ref variant, .. } => { assert_eq!(disr, 0); @@ -327,7 +327,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } } - fn read_discriminant_value(&self, adt_ptr: Pointer, adt_ty: Ty<'tcx>) -> EvalResult<'tcx, u64> { + fn read_discriminant_value(&self, adt_ptr: Pointer, adt_ty: Ty<'tcx>) -> EvalResult<'tcx, u128> { use rustc::ty::layout::Layout::*; let adt_layout = self.type_layout(adt_ty)?; trace!("read_discriminant_value {:?}", adt_layout); @@ -340,13 +340,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { CEnum { discr, signed: true, .. } => { let discr_size = discr.size().bytes(); - self.memory.read_int(adt_ptr, discr_size)? as u64 + self.memory.read_int(adt_ptr, discr_size)? as u128 } RawNullablePointer { nndiscr, value } => { let discr_size = value.size(&self.tcx.data_layout).bytes(); trace!("rawnullablepointer with size {}", discr_size); - self.read_nonnull_discriminant_value(adt_ptr, nndiscr, discr_size)? + self.read_nonnull_discriminant_value(adt_ptr, nndiscr as u128, discr_size)? } StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => { @@ -355,7 +355,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { trace!("struct wrapped nullable pointer type: {}", ty); // only the pointer part of a fat pointer is used for this space optimization let discr_size = self.type_size(ty)?.expect("bad StructWrappedNullablePointer discrfield"); - self.read_nonnull_discriminant_value(nonnull, nndiscr, discr_size)? + self.read_nonnull_discriminant_value(nonnull, nndiscr as u128, discr_size)? } // The discriminant_value intrinsic returns 0 for non-sum types. @@ -366,7 +366,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Ok(discr_val) } - fn read_nonnull_discriminant_value(&self, ptr: Pointer, nndiscr: u64, discr_size: u64) -> EvalResult<'tcx, u64> { + fn read_nonnull_discriminant_value(&self, ptr: Pointer, nndiscr: u128, discr_size: u64) -> EvalResult<'tcx, u128> { let not_null = match self.memory.read_uint(ptr, discr_size) { Ok(0) => false, Ok(_) | Err(EvalError::ReadPointerAsBytes) => true, @@ -399,8 +399,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { match &link_name[..] { "__rust_allocate" => { - let size = self.value_to_primval(args[0], usize)?.to_u64()?; - let align = self.value_to_primval(args[1], usize)?.to_u64()?; + let size = self.value_to_primval(args[0], usize)?.to_u128()? as u64; + let align = self.value_to_primval(args[1], usize)?.to_u128()? as u64; let ptr = self.memory.allocate(size, align)?; self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?; } @@ -408,15 +408,15 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "__rust_deallocate" => { let ptr = args[0].read_ptr(&self.memory)?; // FIXME: insert sanity check for size and align? - let _old_size = self.value_to_primval(args[1], usize)?.to_u64()?; - let _align = self.value_to_primval(args[2], usize)?.to_u64()?; + let _old_size = self.value_to_primval(args[1], usize)?.to_u128()?; + let _align = self.value_to_primval(args[2], usize)?.to_u128()?; self.memory.deallocate(ptr)?; }, "__rust_reallocate" => { let ptr = args[0].read_ptr(&self.memory)?; - let size = self.value_to_primval(args[2], usize)?.to_u64()?; - let align = self.value_to_primval(args[3], usize)?.to_u64()?; + let size = self.value_to_primval(args[2], usize)?.to_u128()? as u64; + let align = self.value_to_primval(args[3], usize)?.to_u128()? as u64; let new_ptr = self.memory.reallocate(ptr, size, align)?; self.write_primval(dest, PrimVal::Ptr(new_ptr), dest_ty)?; } @@ -424,7 +424,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "memcmp" => { let left = args[0].read_ptr(&self.memory)?; let right = args[1].read_ptr(&self.memory)?; - let n = self.value_to_primval(args[2], usize)?.to_u64()?; + let n = self.value_to_primval(args[2], usize)?.to_u128()? as u64; let result = { let left_bytes = self.memory.read_bytes(left, n)?; @@ -432,31 +432,31 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { use std::cmp::Ordering::*; match left_bytes.cmp(right_bytes) { - Less => -1, + Less => -1i8, Equal => 0, Greater => 1, } }; - self.write_primval(dest, PrimVal::Bytes(result as u64), dest_ty)?; + self.write_primval(dest, PrimVal::Bytes(result as u128), dest_ty)?; } "memrchr" => { let ptr = args[0].read_ptr(&self.memory)?; - let val = self.value_to_primval(args[1], usize)?.to_u64()? as u8; - let num = self.value_to_primval(args[2], usize)?.to_u64()?; + let val = self.value_to_primval(args[1], usize)?.to_u128()? as u8; + let num = self.value_to_primval(args[2], usize)?.to_u128()? as u64; if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().rev().position(|&c| c == val) { let new_ptr = ptr.offset(num - idx as u64 - 1); self.write_value(Value::ByVal(PrimVal::Ptr(new_ptr)), dest, dest_ty)?; } else { - self.write_value(Value::ByVal(PrimVal::from_u64(0)), dest, dest_ty)?; + self.write_value(Value::ByVal(PrimVal::from_u128(0)), dest, dest_ty)?; } } "memchr" => { let ptr = args[0].read_ptr(&self.memory)?; - let val = self.value_to_primval(args[1], usize)?.to_u64()? as u8; - let num = self.value_to_primval(args[2], usize)?.to_u64()?; + let val = self.value_to_primval(args[1], usize)?.to_u128()? as u8; + let num = self.value_to_primval(args[2], usize)?.to_u128()? as u64; if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().position(|&c| c == val) { let new_ptr = ptr.offset(idx as u64); self.write_value(Value::ByVal(PrimVal::Ptr(new_ptr)), dest, dest_ty)?; @@ -467,11 +467,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "write" => { // int filedes - let filedes = self.value_to_primval(args[0], usize)?.to_u64()?; + let filedes = self.value_to_primval(args[0], usize)?.to_u128()?; // const void* buffer let buffer = args[1].read_ptr(&self.memory)?; // size_t size - let size = self.value_to_primval(args[0], usize)?.to_u64()?; + let size = self.value_to_primval(args[0], usize)?.to_u128()? as u64; { let data = self.memory.read_bytes(buffer, size)?; @@ -483,7 +483,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } } - self.write_primval(dest, PrimVal::from_u64(size), dest_ty)?; + self.write_primval(dest, PrimVal::from_u128(size as u128), dest_ty)?; } "getenv" => { @@ -500,22 +500,22 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let pthread_key_t = self.tcx.types.i32; self.next_pthread_key += 1; let new_key = self.next_pthread_key; - self.write_primval(Lvalue::from_ptr(key), PrimVal::from_u64(new_key as u64), pthread_key_t)?; - self.write_primval(dest, PrimVal::from_u64(0), dest_ty)?; + self.write_primval(Lvalue::from_ptr(key), PrimVal::from_u128(new_key as u128), pthread_key_t)?; + self.write_primval(dest, PrimVal::from_u128(0), dest_ty)?; } "pthread_setspecific" => { - let key = self.value_to_primval(args[0], i32)?.to_u64()?; + let key = self.value_to_primval(args[0], i32)?.to_u128()?; let val = args[1].read_ptr(&self.memory)?; - assert_eq!(key as i32 as u64, key); + assert_eq!(key as i32 as u128, key); self.pthread.insert(key as i32, val); // FIXME: only keys that were created should exist - self.write_primval(dest, PrimVal::from_u64(0), dest_ty)?; + self.write_primval(dest, PrimVal::from_u128(0), dest_ty)?; } "pthread_getspecific" => { - let key = self.value_to_primval(args[0], i32)?.to_u64()?; - assert_eq!(key as i32 as u64, key); + let key = self.value_to_primval(args[0], i32)?.to_u128()?; + assert_eq!(key as i32 as u128, key); let val = self.pthread.get(&(key as i32)).map(|&p| p).unwrap_or(Pointer::from_int(0)); self.write_primval(dest, PrimVal::Ptr(val), dest_ty)?; } @@ -725,7 +725,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let ptr = prim_ptr.to_ptr()?; let extra = match self.tcx.struct_tail(contents_ty).sty { ty::TyDynamic(..) => LvalueExtra::Vtable(extra.to_ptr()?), - ty::TyStr | ty::TySlice(_) => LvalueExtra::Length(extra.to_u64()?), + ty::TyStr | ty::TySlice(_) => LvalueExtra::Length(extra.to_u128()? as u64), _ => bug!("invalid fat pointer type: {}", ty), }; self.drop( @@ -765,8 +765,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { adt_def.struct_variant().fields.iter().zip(&variant.offsets) }, Layout::General { ref variants, .. } => { - let discr_val = self.read_discriminant_value(adt_ptr, ty)?; - match adt_def.variants.iter().position(|v| discr_val == v.disr_val.to_u64_unchecked()) { + let discr_val = self.read_discriminant_value(adt_ptr, ty)? as u128; + match adt_def.variants.iter().position(|v| discr_val == v.disr_val.to_u128_unchecked()) { // start at offset 1, to skip over the discriminant Some(i) => adt_def.variants[i].fields.iter().zip(&variants[i].offsets[1..]), None => return Err(EvalError::InvalidDiscriminant), @@ -774,8 +774,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { }, Layout::StructWrappedNullablePointer { nndiscr, ref nonnull, .. } => { let discr = self.read_discriminant_value(adt_ptr, ty)?; - if discr == nndiscr { - assert_eq!(discr as usize as u64, discr); + if discr == nndiscr as u128 { + assert_eq!(discr as usize as u128, discr); adt_def.variants[discr as usize].fields.iter().zip(&nonnull.offsets) } else { // FIXME: the zst variant might contain zst types that impl Drop @@ -784,8 +784,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { }, Layout::RawNullablePointer { nndiscr, .. } => { let discr = self.read_discriminant_value(adt_ptr, ty)?; - if discr == nndiscr { - assert_eq!(discr as usize as u64, discr); + if discr == nndiscr as u128 { + assert_eq!(discr as usize as u128, discr); assert_eq!(adt_def.variants[discr as usize].fields.len(), 1); let field_ty = &adt_def.variants[discr as usize].fields[0]; let field_ty = monomorphize_field_ty(self.tcx, field_ty, substs); diff --git a/src/value.rs b/src/value.rs index ddffdd01ee..ce85b2d35a 100644 --- a/src/value.rs +++ b/src/value.rs @@ -6,23 +6,23 @@ use std::mem::transmute; use error::{EvalError, EvalResult}; use memory::{Memory, Pointer}; -pub(super) fn bytes_to_f32(bytes: u64) -> f32 { +pub(super) fn bytes_to_f32(bytes: u128) -> f32 { unsafe { transmute::(bytes as u32) } } -pub(super) fn bytes_to_f64(bytes: u64) -> f64 { - unsafe { transmute::(bytes) } +pub(super) fn bytes_to_f64(bytes: u128) -> f64 { + unsafe { transmute::(bytes as u64) } } -pub(super) fn f32_to_bytes(f: f32) -> u64 { - unsafe { transmute::(f) as u64 } +pub(super) fn f32_to_bytes(f: f32) -> u128 { + unsafe { transmute::(f) as u128 } } -pub(super) fn f64_to_bytes(f: f64) -> u64 { - unsafe { transmute::(f) } +pub(super) fn f64_to_bytes(f: f64) -> u128 { + unsafe { transmute::(f) as u128 } } -pub(super) fn bytes_to_bool(n: u64) -> bool { +pub(super) fn bytes_to_bool(n: u128) -> bool { // FIXME(solson): Can we reach here due to user error? debug_assert!(n == 0 || n == 1, "bytes interpreted as bool were {}", n); n & 1 == 1 @@ -50,7 +50,7 @@ pub enum Value { #[derive(Clone, Copy, Debug)] pub enum PrimVal { /// The raw bytes of a simple value. - Bytes(u64), + Bytes(u128), /// A pointer into an `Allocation`. An `Allocation` in the `memory` module has a list of /// relocations, but a `PrimVal` is only large enough to contain one, so we just represent the @@ -64,8 +64,8 @@ pub enum PrimVal { #[derive(Clone, Copy, Debug, PartialEq)] pub enum PrimValKind { - I8, I16, I32, I64, - U8, U16, U32, U64, + I8, I16, I32, I64, I128, + U8, U16, U32, U64, U128, F32, F64, Bool, Char, @@ -109,7 +109,9 @@ impl<'a, 'tcx: 'a> Value { Ok((ptr, len)) }, ByValPair(ptr, val) => { - Ok((ptr.to_ptr()?, val.to_u64()?)) + let len = val.to_u128()?; + assert_eq!(len as u64 as u128, len); + Ok((ptr.to_ptr()?, len as u64)) }, _ => unimplemented!(), } @@ -117,12 +119,12 @@ impl<'a, 'tcx: 'a> Value { } impl<'tcx> PrimVal { - pub fn from_u64(n: u64) -> Self { + pub fn from_u128(n: u128) -> Self { PrimVal::Bytes(n) } - pub fn from_i64(n: i64) -> Self { - PrimVal::Bytes(n as u64) + pub fn from_i128(n: i128) -> Self { + PrimVal::Bytes(n as u128) } pub fn from_f32(f: f32) -> Self { @@ -134,35 +136,35 @@ impl<'tcx> PrimVal { } pub fn from_bool(b: bool) -> Self { - PrimVal::Bytes(b as u64) + PrimVal::Bytes(b as u128) } pub fn from_char(c: char) -> Self { - PrimVal::Bytes(c as u64) + PrimVal::Bytes(c as u128) } - pub fn to_bytes(self) -> EvalResult<'tcx, u64> { + pub fn to_bytes(self) -> EvalResult<'tcx, u128> { match self { PrimVal::Bytes(b) => Ok(b), - PrimVal::Ptr(p) => p.to_int(), + PrimVal::Ptr(p) => p.to_int().map(|b| b as u128), PrimVal::Undef => Err(EvalError::ReadUndefBytes), } } pub fn to_ptr(self) -> EvalResult<'tcx, Pointer> { match self { - PrimVal::Bytes(b) => Ok(Pointer::from_int(b)), + PrimVal::Bytes(b) => Ok(Pointer::from_int(b as u64)), PrimVal::Ptr(p) => Ok(p), PrimVal::Undef => Err(EvalError::ReadUndefBytes), } } - pub fn to_u64(self) -> EvalResult<'tcx, u64> { + pub fn to_u128(self) -> EvalResult<'tcx, u128> { self.to_bytes() } - pub fn to_i64(self) -> EvalResult<'tcx, i64> { - self.to_bytes().map(|b| b as i64) + pub fn to_i128(self) -> EvalResult<'tcx, i128> { + self.to_bytes().map(|b| b as i128) } pub fn to_f32(self) -> EvalResult<'tcx, f32> { @@ -186,7 +188,7 @@ impl PrimValKind { pub fn is_int(self) -> bool { use self::PrimValKind::*; match self { - I8 | I16 | I32 | I64 | U8 | U16 | U32 | U64 => true, + I8 | I16 | I32 | I64 | I128 | U8 | U16 | U32 | U64 | U128 => true, _ => false, } } @@ -197,6 +199,7 @@ impl PrimValKind { 2 => PrimValKind::U16, 4 => PrimValKind::U32, 8 => PrimValKind::U64, + 16 => PrimValKind::U128, _ => bug!("can't make uint with size {}", size), } } @@ -207,6 +210,7 @@ impl PrimValKind { 2 => PrimValKind::I16, 4 => PrimValKind::I32, 8 => PrimValKind::I64, + 16 => PrimValKind::I128, _ => bug!("can't make int with size {}", size), } } From d38ab302846766aaff9c48f0d302f64ab0d2933e Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 9 Jan 2017 15:59:43 +0100 Subject: [PATCH 15/19] reintroduce to_u64 and introduce to_i32 --- src/terminator/intrinsic.rs | 4 ++-- src/terminator/mod.rs | 42 ++++++++++++++++++------------------- src/value.rs | 21 +++++++++++++++++++ 3 files changed, 43 insertions(+), 24 deletions(-) diff --git a/src/terminator/intrinsic.rs b/src/terminator/intrinsic.rs index 971aece77f..27d73fb664 100644 --- a/src/terminator/intrinsic.rs +++ b/src/terminator/intrinsic.rs @@ -156,7 +156,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let elem_align = self.type_align(elem_ty)?; let src = arg_vals[0].read_ptr(&self.memory)?; let dest = arg_vals[1].read_ptr(&self.memory)?; - let count = self.value_to_primval(arg_vals[2], usize)?.to_u128()? as u64; + let count = self.value_to_primval(arg_vals[2], usize)?.to_u64()?; self.memory.copy(src, dest, count * elem_size, elem_align)?; } @@ -189,7 +189,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { ptr: ptr.to_ptr()?, extra: match self.tcx.struct_tail(ty).sty { ty::TyDynamic(..) => LvalueExtra::Vtable(extra.to_ptr()?), - ty::TyStr | ty::TySlice(_) => LvalueExtra::Length(extra.to_u128()? as u64), + ty::TyStr | ty::TySlice(_) => LvalueExtra::Length(extra.to_u64()?), _ => bug!("invalid fat pointer type: {}", ptr_ty), }, }, diff --git a/src/terminator/mod.rs b/src/terminator/mod.rs index 47ebd27abd..d3c70f1b31 100644 --- a/src/terminator/mod.rs +++ b/src/terminator/mod.rs @@ -143,10 +143,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let span = terminator.source_info.span; let len = self.eval_operand_to_primval(len) .expect("can't eval len") - .to_u128()? as u64; + .to_u64()?; let index = self.eval_operand_to_primval(index) .expect("can't eval index") - .to_u128()? as u64; + .to_u64()?; Err(EvalError::ArrayIndexOutOfBounds(span, len, index)) }, mir::AssertMessage::Math(ref err) => @@ -399,8 +399,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { match &link_name[..] { "__rust_allocate" => { - let size = self.value_to_primval(args[0], usize)?.to_u128()? as u64; - let align = self.value_to_primval(args[1], usize)?.to_u128()? as u64; + let size = self.value_to_primval(args[0], usize)?.to_u64()?; + let align = self.value_to_primval(args[1], usize)?.to_u64()?; let ptr = self.memory.allocate(size, align)?; self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?; } @@ -408,15 +408,15 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "__rust_deallocate" => { let ptr = args[0].read_ptr(&self.memory)?; // FIXME: insert sanity check for size and align? - let _old_size = self.value_to_primval(args[1], usize)?.to_u128()?; - let _align = self.value_to_primval(args[2], usize)?.to_u128()?; + let _old_size = self.value_to_primval(args[1], usize)?.to_u64()?; + let _align = self.value_to_primval(args[2], usize)?.to_u64()?; self.memory.deallocate(ptr)?; }, "__rust_reallocate" => { let ptr = args[0].read_ptr(&self.memory)?; - let size = self.value_to_primval(args[2], usize)?.to_u128()? as u64; - let align = self.value_to_primval(args[3], usize)?.to_u128()? as u64; + let size = self.value_to_primval(args[2], usize)?.to_u64()?; + let align = self.value_to_primval(args[3], usize)?.to_u64()?; let new_ptr = self.memory.reallocate(ptr, size, align)?; self.write_primval(dest, PrimVal::Ptr(new_ptr), dest_ty)?; } @@ -424,7 +424,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "memcmp" => { let left = args[0].read_ptr(&self.memory)?; let right = args[1].read_ptr(&self.memory)?; - let n = self.value_to_primval(args[2], usize)?.to_u128()? as u64; + let n = self.value_to_primval(args[2], usize)?.to_u64()?; let result = { let left_bytes = self.memory.read_bytes(left, n)?; @@ -443,8 +443,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "memrchr" => { let ptr = args[0].read_ptr(&self.memory)?; - let val = self.value_to_primval(args[1], usize)?.to_u128()? as u8; - let num = self.value_to_primval(args[2], usize)?.to_u128()? as u64; + let val = self.value_to_primval(args[1], usize)?.to_u64()? as u8; + let num = self.value_to_primval(args[2], usize)?.to_u64()?; if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().rev().position(|&c| c == val) { let new_ptr = ptr.offset(num - idx as u64 - 1); self.write_value(Value::ByVal(PrimVal::Ptr(new_ptr)), dest, dest_ty)?; @@ -455,8 +455,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "memchr" => { let ptr = args[0].read_ptr(&self.memory)?; - let val = self.value_to_primval(args[1], usize)?.to_u128()? as u8; - let num = self.value_to_primval(args[2], usize)?.to_u128()? as u64; + let val = self.value_to_primval(args[1], usize)?.to_u64()? as u8; + let num = self.value_to_primval(args[2], usize)?.to_u64()?; if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().position(|&c| c == val) { let new_ptr = ptr.offset(idx as u64); self.write_value(Value::ByVal(PrimVal::Ptr(new_ptr)), dest, dest_ty)?; @@ -467,11 +467,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "write" => { // int filedes - let filedes = self.value_to_primval(args[0], usize)?.to_u128()?; + let filedes = self.value_to_primval(args[0], usize)?.to_u64()?; // const void* buffer let buffer = args[1].read_ptr(&self.memory)?; // size_t size - let size = self.value_to_primval(args[0], usize)?.to_u128()? as u64; + let size = self.value_to_primval(args[0], usize)?.to_u64()?; { let data = self.memory.read_bytes(buffer, size)?; @@ -505,18 +505,16 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } "pthread_setspecific" => { - let key = self.value_to_primval(args[0], i32)?.to_u128()?; + let key = self.value_to_primval(args[0], i32)?.to_i32()?; let val = args[1].read_ptr(&self.memory)?; - assert_eq!(key as i32 as u128, key); - self.pthread.insert(key as i32, val); + self.pthread.insert(key, val); // FIXME: only keys that were created should exist self.write_primval(dest, PrimVal::from_u128(0), dest_ty)?; } "pthread_getspecific" => { - let key = self.value_to_primval(args[0], i32)?.to_u128()?; - assert_eq!(key as i32 as u128, key); - let val = self.pthread.get(&(key as i32)).map(|&p| p).unwrap_or(Pointer::from_int(0)); + let key = self.value_to_primval(args[0], i32)?.to_i32()?; + let val = self.pthread.get(&key).map(|&p| p).unwrap_or(Pointer::from_int(0)); self.write_primval(dest, PrimVal::Ptr(val), dest_ty)?; } @@ -725,7 +723,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let ptr = prim_ptr.to_ptr()?; let extra = match self.tcx.struct_tail(contents_ty).sty { ty::TyDynamic(..) => LvalueExtra::Vtable(extra.to_ptr()?), - ty::TyStr | ty::TySlice(_) => LvalueExtra::Length(extra.to_u128()? as u64), + ty::TyStr | ty::TySlice(_) => LvalueExtra::Length(extra.to_u64()?), _ => bug!("invalid fat pointer type: {}", ty), }; self.drop( diff --git a/src/value.rs b/src/value.rs index ce85b2d35a..8d153528d4 100644 --- a/src/value.rs +++ b/src/value.rs @@ -163,10 +163,31 @@ impl<'tcx> PrimVal { self.to_bytes() } + pub fn to_u64(self) -> EvalResult<'tcx, u64> { + self.to_bytes().map(|b| { + assert_eq!(b as u64 as u128, b); + b as u64 + }) + } + + pub fn to_i32(self) -> EvalResult<'tcx, i32> { + self.to_bytes().map(|b| { + assert_eq!(b as i32 as u128, b); + b as i32 + }) + } + pub fn to_i128(self) -> EvalResult<'tcx, i128> { self.to_bytes().map(|b| b as i128) } + pub fn to_i64(self) -> EvalResult<'tcx, i64> { + self.to_bytes().map(|b| { + assert_eq!(b as i64 as u128, b); + b as i64 + }) + } + pub fn to_f32(self) -> EvalResult<'tcx, f32> { self.to_bytes().map(bytes_to_f32) } From 69ef22977f1a4e0627f530e939662ac31f26f5f4 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 10 Jan 2017 10:04:53 +0100 Subject: [PATCH 16/19] test more targets on travis --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index e76a2f86cf..3aa1b51497 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,9 @@ before_script: - | pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH +- rustup target add i686-unknown-linux-gnu +- rustup target add i686-pc-windows-gnu +- rustup target add i686-pc-windows-msvc script: - | env RUST_SYSROOT=$HOME/rust travis-cargo build && From c18babd07280261fe40ccbcb9723f71f07e347d5 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 10 Jan 2017 10:45:33 +0100 Subject: [PATCH 17/19] analyze travis --- .travis.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3aa1b51497..ed0363dcc9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,9 +5,10 @@ before_script: - | pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH -- rustup target add i686-unknown-linux-gnu -- rustup target add i686-pc-windows-gnu -- rustup target add i686-pc-windows-msvc +- ls -lh ~/rust +- ~/rust/rustup target add i686-unknown-linux-gnu +- ~/rust/rustup target add i686-pc-windows-gnu +- ~/rust/rustup target add i686-pc-windows-msvc script: - | env RUST_SYSROOT=$HOME/rust travis-cargo build && From 8a6b823e1a38ce3776c0a7c41996ed6f5b5113ea Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 10 Jan 2017 12:50:27 +0100 Subject: [PATCH 18/19] travis fix --- .travis.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index ed0363dcc9..fefa37b7fe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,10 +5,9 @@ before_script: - | pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH -- ls -lh ~/rust -- ~/rust/rustup target add i686-unknown-linux-gnu -- ~/rust/rustup target add i686-pc-windows-gnu -- ~/rust/rustup target add i686-pc-windows-msvc +- sh ~/rust-installer/rustup.sh --add-target=i686-unknown-linux-gnu --prefix=/home/travis/rust -y --disable-sudo +- sh ~/rust-installer/rustup.sh --add-target=i686-pc-windows-gnu --prefix=/home/travis/rust -y --disable-sudo +- sh ~/rust-installer/rustup.sh --add-target=i686-pc-windows-msvc --prefix=/home/travis/rust p-y --disable-sudo script: - | env RUST_SYSROOT=$HOME/rust travis-cargo build && From 225973ff7e9fa0e00f0ebbaf01d12e4d04f67d05 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 11 Jan 2017 10:04:17 +0100 Subject: [PATCH 19/19] priroda required functions --- src/eval_context.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/eval_context.rs b/src/eval_context.rs index a2a51f6dba..e3d26f61b6 100644 --- a/src/eval_context.rs +++ b/src/eval_context.rs @@ -715,7 +715,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Ok((offset, ty)) } - fn get_field_ty(&self, ty: Ty<'tcx>, field_index: usize) -> EvalResult<'tcx, Ty<'tcx>> { + pub fn get_field_ty(&self, ty: Ty<'tcx>, field_index: usize) -> EvalResult<'tcx, Ty<'tcx>> { match ty.sty { ty::TyAdt(adt_def, substs) => { Ok(adt_def.struct_variant().fields[field_index].ty(self.tcx, substs)) @@ -1038,7 +1038,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Ok(()) } - pub(super) fn ty_to_primval_kind(&self, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimValKind> { + pub fn ty_to_primval_kind(&self, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimValKind> { use syntax::ast::FloatTy; let kind = match ty.sty {