From 3a658e09e88ad999fe1f5dbc4ac7a14c0d38c90f Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 12 Jan 2017 08:28:42 +0100 Subject: [PATCH] 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 | 33 +++++++++-------- src/lib.rs | 1 + src/memory.rs | 64 +++++++++++++++++---------------- src/operator.rs | 38 +++++++++++--------- src/step.rs | 2 +- src/terminator/intrinsic.rs | 42 +++++++++++----------- src/terminator/mod.rs | 28 +++++++-------- src/value.rs | 71 +++++++++++++++++++++++++------------ 14 files changed, 193 insertions(+), 148 deletions(-) diff --git a/.gitignore b/.gitignore index d9940aa58b5..a51553a8c5e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ tex/*/out *.dot *.mir +*.rs.bk diff --git a/Cargo.lock b/Cargo.lock index b63b557f071..94611529c5d 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 1d5de26f007..ada46a794cb 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 24a0b7ba00b..379f25ef757 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; @@ -51,7 +51,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"), @@ -64,8 +64,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 2b3194a5994..413c9b6ba82 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 9b532e01375..bf01ae27d2a 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 adbb0db5914..7a0264665e5 100644 --- a/src/eval_context.rs +++ b/src/eval_context.rs @@ -169,7 +169,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> { @@ -177,7 +177,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), @@ -429,7 +429,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(); let discr_offset = variants[variant].offsets[0].bytes(); @@ -497,7 +497,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); @@ -556,7 +556,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) => { @@ -566,7 +566,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"), @@ -1028,6 +1028,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) @@ -1040,6 +1041,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) @@ -1092,7 +1094,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(()), } @@ -1115,7 +1117,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)), } } @@ -1126,9 +1128,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) => { @@ -1138,9 +1141,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)?), @@ -1159,7 +1163,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))); @@ -1171,9 +1175,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); @@ -1220,7 +1224,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)?; } @@ -1454,6 +1458,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 8965384e162..418ccfa549f 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/memory.rs b/src/memory.rs index 2825f55eab4..5be28f27712 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 2e1ac075294..417e7047ec0 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, Bool) => !bytes_to_bool(bytes) as u128, - (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, 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 u64, - (Not, I16) => !(bytes as i16) as u64, - (Not, I32) => !(bytes as i32) as u64, - (Not, I64) => !(bytes as i64) as u64, + (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 u64, - (Neg, I16) => -(bytes as i16) as u64, - (Neg, I32) => -(bytes as i32) as u64, - (Neg, I64) => -(bytes as i64) as u64, + (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 527df96a18b..109631327b1 100644 --- a/src/step.rs +++ b/src/step.rs @@ -101,7 +101,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, .. } => { diff --git a/src/terminator/intrinsic.rs b/src/terminator/intrinsic.rs index 193abd21389..a91a75454dd 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)?; } @@ -260,7 +260,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)?; } @@ -268,7 +268,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)?; } @@ -289,7 +289,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); @@ -310,13 +310,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)?; } @@ -336,21 +336,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" => { @@ -362,7 +362,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" => { @@ -514,14 +514,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 d74458a87cd..6959da650b4 100644 --- a/src/terminator/mod.rs +++ b/src/terminator/mod.rs @@ -71,7 +71,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]), @@ -262,7 +262,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); @@ -275,13 +275,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, .. } => { @@ -290,7 +290,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. @@ -301,7 +301,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, @@ -366,13 +366,13 @@ 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)?; } "memchr" => { @@ -641,8 +641,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), @@ -650,8 +650,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 @@ -660,8 +660,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 ddffdd01ee8..8d153528d4f 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,56 @@ 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_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| b as 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> { @@ -186,7 +209,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 +220,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 +231,7 @@ impl PrimValKind { 2 => PrimValKind::I16, 4 => PrimValKind::I32, 8 => PrimValKind::I64, + 16 => PrimValKind::I128, _ => bug!("can't make int with size {}", size), } }