Merge pull request #98 from oli-obk/rustup

rustup (i128)
This commit is contained in:
Scott Olson 2017-01-11 23:40:37 -08:00 committed by GitHub
commit 57b983862e
14 changed files with 193 additions and 148 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@
tex/*/out
*.dot
*.mir
*.rs.bk

8
Cargo.lock generated
View File

@ -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)" = "<none>"
"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"

View File

@ -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"

View File

@ -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"),
}

View File

@ -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)),

View File

@ -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,

View File

@ -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),
}
}
}

View File

@ -4,6 +4,7 @@
collections_bound,
pub_restricted,
rustc_private,
i128_type,
)]
// From rustc.

View File

@ -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::<LittleEndian>(data, len),
layout::Endian::Big => target.write_uint::<BigEndian>(data, len),
layout::Endian::Little => target.write_uint128::<LittleEndian>(data, len),
layout::Endian::Big => target.write_uint128::<BigEndian>(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::<LittleEndian>(data, len),
layout::Endian::Big => target.write_int::<BigEndian>(data, len),
layout::Endian::Little => target.write_int128::<LittleEndian>(data, len),
layout::Endian::Big => target.write_int128::<BigEndian>(data, len),
}
}
fn read_target_uint(endianess: layout::Endian, mut source: &[u8]) -> Result<u64, byteorder::Error> {
fn read_target_uint(endianess: layout::Endian, mut source: &[u8]) -> Result<u128, io::Error> {
match endianess {
layout::Endian::Little => source.read_uint::<LittleEndian>(source.len()),
layout::Endian::Big => source.read_uint::<BigEndian>(source.len()),
layout::Endian::Little => source.read_uint128::<LittleEndian>(source.len()),
layout::Endian::Big => source.read_uint128::<BigEndian>(source.len()),
}
}
fn read_target_int(endianess: layout::Endian, mut source: &[u8]) -> Result<i64, byteorder::Error> {
fn read_target_int(endianess: layout::Endian, mut source: &[u8]) -> Result<i128, io::Error> {
match endianess {
layout::Endian::Little => source.read_int::<LittleEndian>(source.len()),
layout::Endian::Big => source.read_int::<BigEndian>(source.len()),
layout::Endian::Little => source.read_int128::<LittleEndian>(source.len()),
layout::Endian::Big => source.read_int128::<BigEndian>(source.len()),
}
}
@ -833,26 +837,26 @@ fn read_target_int(endianess: layout::Endian, mut source: &[u8]) -> Result<i64,
// Methods to access floats in the target endianess
////////////////////////////////////////////////////////////////////////////////
fn write_target_f32(endianess: layout::Endian, mut target: &mut [u8], data: f32) -> 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::<LittleEndian>(data),
layout::Endian::Big => target.write_f32::<BigEndian>(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::<LittleEndian>(data),
layout::Endian::Big => target.write_f64::<BigEndian>(data),
}
}
fn read_target_f32(endianess: layout::Endian, mut source: &[u8]) -> Result<f32, byteorder::Error> {
fn read_target_f32(endianess: layout::Endian, mut source: &[u8]) -> Result<f32, io::Error> {
match endianess {
layout::Endian::Little => source.read_f32::<LittleEndian>(),
layout::Endian::Big => source.read_f32::<BigEndian>(),
}
}
fn read_target_f64(endianess: layout::Endian, mut source: &[u8]) -> Result<f64, byteorder::Error> {
fn read_target_f64(endianess: layout::Endian, mut source: &[u8]) -> Result<f64, io::Error> {
match endianess {
layout::Endian::Little => source.read_f64::<LittleEndian>(),
layout::Endian::Big => source.read_f64::<BigEndian>(),

View File

@ -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)),

View File

@ -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, .. } => {

View File

@ -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),
};

View File

@ -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);

View File

@ -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::<u32, f32>(bytes as u32) }
}
pub(super) fn bytes_to_f64(bytes: u64) -> f64 {
unsafe { transmute::<u64, f64>(bytes) }
pub(super) fn bytes_to_f64(bytes: u128) -> f64 {
unsafe { transmute::<u64, f64>(bytes as u64) }
}
pub(super) fn f32_to_bytes(f: f32) -> u64 {
unsafe { transmute::<f32, u32>(f) as u64 }
pub(super) fn f32_to_bytes(f: f32) -> u128 {
unsafe { transmute::<f32, u32>(f) as u128 }
}
pub(super) fn f64_to_bytes(f: f64) -> u64 {
unsafe { transmute::<f64, u64>(f) }
pub(super) fn f64_to_bytes(f: f64) -> u128 {
unsafe { transmute::<f64, u64>(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),
}
}