X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fshims%2Fintrinsics.rs;h=5ef7fba7f59083b093902b40a094b4b2fe851d95;hb=cf9340113efcf5c7bea4a143f42c8ea47da4550e;hp=4e957f792b7513721902d334d126f742c76d28d8;hpb=1f504ea7be76c55bb3ba8d79599f161d65f5bb51;p=rust.git diff --git a/src/shims/intrinsics.rs b/src/shims/intrinsics.rs index 4e957f792b7..5ef7fba7f59 100644 --- a/src/shims/intrinsics.rs +++ b/src/shims/intrinsics.rs @@ -1,3 +1,5 @@ +use std::iter; + use rustc_apfloat::Float; use rustc::mir; use rustc::mir::interpret::{InterpResult, PointerArithmetic}; @@ -5,7 +7,7 @@ use rustc::ty; use crate::{ - PlaceTy, OpTy, ImmTy, Immediate, Scalar, Tag, + PlaceTy, OpTy, Immediate, Scalar, Tag, OperatorEvalContextExt }; @@ -28,8 +30,8 @@ fn call_intrinsic( // (as opposed to through a place), we have to remember to erase any tag // that might still hang around! - let intrinsic_name = this.tcx.item_name(instance.def_id()).as_str(); - match intrinsic_name.get() { + let intrinsic_name = &*tcx.item_name(instance.def_id()).as_str(); + match intrinsic_name { "arith_offset" => { let offset = this.read_scalar(args[1])?.to_isize(this)?; let ptr = this.read_scalar(args[0])?.not_undef()?; @@ -68,7 +70,7 @@ fn call_intrinsic( // even if the type they wrap would be less aligned (e.g. AtomicU64 on 32bit must // be 8-aligned). let align = Align::from_bytes(place.layout.size.bytes()).unwrap(); - this.memory().check_ptr_access(place.ptr, place.layout.size, align)?; + this.memory.check_ptr_access(place.ptr, place.layout.size, align)?; this.write_scalar(val, dest)?; } @@ -83,12 +85,15 @@ fn call_intrinsic( // even if the type they wrap would be less aligned (e.g. AtomicU64 on 32bit must // be 8-aligned). let align = Align::from_bytes(place.layout.size.bytes()).unwrap(); - this.memory().check_ptr_access(place.ptr, place.layout.size, align)?; + this.memory.check_ptr_access(place.ptr, place.layout.size, align)?; this.write_scalar(val, place.into())?; } - "atomic_fence_acq" => { + "atomic_fence_acq" | + "atomic_fence_rel" | + "atomic_fence_acqrel" | + "atomic_fence" => { // we are inherently singlethreaded and singlecored, this is a nop } @@ -101,7 +106,7 @@ fn call_intrinsic( // even if the type they wrap would be less aligned (e.g. AtomicU64 on 32bit must // be 8-aligned). let align = Align::from_bytes(place.layout.size.bytes()).unwrap(); - this.memory().check_ptr_access(place.ptr, place.layout.size, align)?; + this.memory.check_ptr_access(place.ptr, place.layout.size, align)?; this.write_scalar(old, dest)?; // old value is returned this.write_scalar(new, place.into())?; @@ -117,10 +122,10 @@ fn call_intrinsic( // even if the type they wrap would be less aligned (e.g. AtomicU64 on 32bit must // be 8-aligned). let align = Align::from_bytes(place.layout.size.bytes()).unwrap(); - this.memory().check_ptr_access(place.ptr, place.layout.size, align)?; + this.memory.check_ptr_access(place.ptr, place.layout.size, align)?; // binary_op will bail if either of them is not a scalar - let (eq, _) = this.binary_op(mir::BinOp::Eq, old, expect_old)?; + let eq = this.overflowing_binary_op(mir::BinOp::Eq, old, expect_old)?.0; let res = Immediate::ScalarPair(old.to_scalar_or_undef(), eq.into()); this.write_immediate(res, dest)?; // old value is returned // update ptr depending on comparison @@ -170,7 +175,7 @@ fn call_intrinsic( // even if the type they wrap would be less aligned (e.g. AtomicU64 on 32bit must // be 8-aligned). let align = Align::from_bytes(place.layout.size.bytes()).unwrap(); - this.memory().check_ptr_access(place.ptr, place.layout.size, align)?; + this.memory.check_ptr_access(place.ptr, place.layout.size, align)?; this.write_immediate(*old, dest)?; // old value is returned let (op, neg) = match intrinsic_name.split('_').nth(1).unwrap() { @@ -183,13 +188,13 @@ fn call_intrinsic( _ => bug!(), }; // Atomics wrap around on overflow. - let (val, _overflowed) = this.binary_op(op, old, rhs)?; + let val = this.binary_op(op, old, rhs)?; let val = if neg { - this.unary_op(mir::UnOp::Not, ImmTy::from_scalar(val, old.layout))? + this.unary_op(mir::UnOp::Not, val)? } else { val }; - this.write_scalar(val, place.into())?; + this.write_immediate(*val, place.into())?; } "breakpoint" => unimplemented!(), // halt miri @@ -204,12 +209,12 @@ fn call_intrinsic( let size = Size::from_bytes(count * elem_size); let src = this.read_scalar(args[0])?.not_undef()?; - let src = this.memory().check_ptr_access(src, size, elem_align)?; + let src = this.memory.check_ptr_access(src, size, elem_align)?; let dest = this.read_scalar(args[1])?.not_undef()?; - let dest = this.memory().check_ptr_access(dest, size, elem_align)?; + let dest = this.memory.check_ptr_access(dest, size, elem_align)?; if let (Some(src), Some(dest)) = (src, dest) { - this.memory_mut().copy( + this.memory.copy( src, dest, size, @@ -228,7 +233,7 @@ fn call_intrinsic( "log10f32" | "log2f32" | "floorf32" | "ceilf32" | "truncf32" | "roundf32" => { // FIXME: Using host floats. let f = f32::from_bits(this.read_scalar(args[0])?.to_u32()?); - let f = match intrinsic_name.get() { + let f = match intrinsic_name { "sinf32" => f.sin(), "fabsf32" => f.abs(), "cosf32" => f.cos(), @@ -251,7 +256,7 @@ fn call_intrinsic( "log10f64" | "log2f64" | "floorf64" | "ceilf64" | "truncf64" | "roundf64" => { // FIXME: Using host floats. let f = f64::from_bits(this.read_scalar(args[0])?.to_u64()?); - let f = match intrinsic_name.get() { + let f = match intrinsic_name { "sinf64" => f.sin(), "fabsf64" => f.abs(), "cosf64" => f.cos(), @@ -273,7 +278,7 @@ fn call_intrinsic( "fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => { let a = this.read_immediate(args[0])?; let b = this.read_immediate(args[1])?; - let op = match intrinsic_name.get() { + let op = match intrinsic_name { "fadd_fast" => mir::BinOp::Add, "fsub_fast" => mir::BinOp::Sub, "fmul_fast" => mir::BinOp::Mul, @@ -287,7 +292,7 @@ fn call_intrinsic( "minnumf32" | "maxnumf32" => { let a = this.read_scalar(args[0])?.to_f32()?; let b = this.read_scalar(args[1])?.to_f32()?; - let res = if intrinsic_name.get().starts_with("min") { + let res = if intrinsic_name.starts_with("min") { a.min(b) } else { a.max(b) @@ -298,7 +303,7 @@ fn call_intrinsic( "minnumf64" | "maxnumf64" => { let a = this.read_scalar(args[0])?.to_f64()?; let b = this.read_scalar(args[1])?.to_f64()?; - let res = if intrinsic_name.get().starts_with("min") { + let res = if intrinsic_name.starts_with("min") { a.min(b) } else { a.max(b) @@ -312,7 +317,7 @@ fn call_intrinsic( let a = this.read_immediate(args[0])?; let b = this.read_immediate(args[1])?; // check x % y != 0 - if this.binary_op(mir::BinOp::Rem, a, b)?.0.to_bits(dest.layout.size)? != 0 { + if this.overflowing_binary_op(mir::BinOp::Rem, a, b)?.0.to_bits(dest.layout.size)? != 0 { // Check if `b` is -1, which is the "min_value / -1" case. let minus1 = Scalar::from_int(-1, dest.layout.size); return Err(if b.to_scalar().unwrap() == minus1 { @@ -353,10 +358,8 @@ fn call_intrinsic( _ => { // Do it in memory let mplace = this.force_allocation(dest)?; - assert!(mplace.meta.is_none()); - // not a zst, must be valid pointer - let ptr = mplace.ptr.to_ptr()?; - this.memory_mut().get_mut(ptr.alloc_id)?.write_repeat(tcx, ptr, 0, dest.layout.size)?; + mplace.meta.unwrap_none(); // must be sized + this.memory.write_bytes(mplace.ptr, iter::repeat(0u8).take(dest.layout.size.bytes() as usize))?; } } } @@ -509,15 +512,15 @@ fn call_intrinsic( "unchecked_add" | "unchecked_sub" | "unchecked_mul" => { let l = this.read_immediate(args[0])?; let r = this.read_immediate(args[1])?; - let op = match intrinsic_name.get() { + let op = match intrinsic_name { "unchecked_add" => mir::BinOp::Add, "unchecked_sub" => mir::BinOp::Sub, "unchecked_mul" => mir::BinOp::Mul, _ => bug!(), }; - let (res, overflowed) = this.binary_op(op, l, r)?; + let (res, overflowed, _ty) = this.overflowing_binary_op(op, l, r)?; if overflowed { - throw_ub_format!("Overflowing arithmetic in {}", intrinsic_name.get()); + throw_ub_format!("Overflowing arithmetic in {}", intrinsic_name); } this.write_scalar(res, dest)?; } @@ -543,9 +546,10 @@ fn call_intrinsic( _ => { // Do it in memory let mplace = this.force_allocation(dest)?; - assert!(mplace.meta.is_none()); + mplace.meta.unwrap_none(); let ptr = mplace.ptr.to_ptr()?; - this.memory_mut() + // We know the return place is in-bounds + this.memory .get_mut(ptr.alloc_id)? .mark_definedness(ptr, dest.layout.size, false); } @@ -560,16 +564,7 @@ fn call_intrinsic( let ptr = this.read_scalar(args[0])?.not_undef()?; let count = this.read_scalar(args[2])?.to_usize(this)?; let byte_count = ty_layout.size * count; - match this.memory().check_ptr_access(ptr, byte_count, ty_layout.align.abi)? { - Some(ptr) => { - this.memory_mut() - .get_mut(ptr.alloc_id)? - .write_repeat(tcx, ptr, val_byte, byte_count)?; - } - None => { - // Size is 0, nothing to do. - } - } + this.memory.write_bytes(ptr, iter::repeat(val_byte).take(byte_count.bytes() as usize))?; } name => throw_unsup_format!("unimplemented intrinsic: {}", name),