From 2f3440d213af7d46e11d143fc3811b0b0d770abe Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Mon, 13 Mar 2017 19:28:29 -0400 Subject: [PATCH 1/5] implement write_bytes intrinsic --- src/terminator/intrinsic.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/terminator/intrinsic.rs b/src/terminator/intrinsic.rs index ab8539be31..9c7489d145 100644 --- a/src/terminator/intrinsic.rs +++ b/src/terminator/intrinsic.rs @@ -402,6 +402,25 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } } + "write_bytes" => { + let u8 = self.tcx.types.u8; + let ty = substs.type_at(0); + let size = self.type_size(ty)?.expect("write_bytes() type must be sized"); + let val_byte = self.value_to_primval(arg_vals[1], u8)?.to_u128()?; + let mut pattern: u128 = 0; + for ii in 0..size { + pattern |= val_byte << (8 * ii); + } + let val_full = Value::ByVal(PrimVal::from_u128(pattern)); + let mut ptr = arg_vals[0].read_ptr(&self.memory)?; + + let count = self.value_to_primval(arg_vals[2], usize)?.to_u64()?; + for _ in 0..count { + self.write_value_to_ptr(val_full, ptr, ty)?; + ptr = ptr.offset(size); + } + } + name => return Err(EvalError::Unimplemented(format!("unimplemented intrinsic: {}", name))), } From aa2f9988a41144bf29d3538239b40bb12571f36c Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Mon, 13 Mar 2017 19:40:48 -0400 Subject: [PATCH 2/5] add write-bytes test --- tests/run-pass/write-bytes.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tests/run-pass/write-bytes.rs diff --git a/tests/run-pass/write-bytes.rs b/tests/run-pass/write-bytes.rs new file mode 100644 index 0000000000..1df23ab1fe --- /dev/null +++ b/tests/run-pass/write-bytes.rs @@ -0,0 +1,17 @@ +fn main() { + const LENGTH: usize = 10; + let mut v: [u64; LENGTH] = [0; LENGTH]; + + for idx in 0..LENGTH { + assert_eq!(v[idx], 0); + } + + unsafe { + let p = v.as_mut_ptr(); + ::std::ptr::write_bytes(p, 0xab, LENGTH); + } + + for idx in 0..LENGTH { + assert_eq!(v[idx], 0xabababababababab); + } +} From e79ee140ee0809fc23e4d6f148fac228ca669e98 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Mon, 13 Mar 2017 20:32:43 -0400 Subject: [PATCH 3/5] write_bytes(): fix handling of types that are larger than u128 --- src/terminator/intrinsic.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/terminator/intrinsic.rs b/src/terminator/intrinsic.rs index 9c7489d145..56d097289b 100644 --- a/src/terminator/intrinsic.rs +++ b/src/terminator/intrinsic.rs @@ -406,18 +406,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let u8 = self.tcx.types.u8; let ty = substs.type_at(0); let size = self.type_size(ty)?.expect("write_bytes() type must be sized"); - let val_byte = self.value_to_primval(arg_vals[1], u8)?.to_u128()?; - let mut pattern: u128 = 0; - for ii in 0..size { - pattern |= val_byte << (8 * ii); - } - let val_full = Value::ByVal(PrimVal::from_u128(pattern)); let mut ptr = arg_vals[0].read_ptr(&self.memory)?; - let count = self.value_to_primval(arg_vals[2], usize)?.to_u64()?; - for _ in 0..count { - self.write_value_to_ptr(val_full, ptr, ty)?; - ptr = ptr.offset(size); + for _ in 0..(count * size) { + self.write_value_to_ptr(arg_vals[1], ptr, u8)?; + ptr = ptr.offset(1); } } From 4cae50cccbd5b9cf349baaa93178edb8b2ff3b1d Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Mon, 13 Mar 2017 20:33:23 -0400 Subject: [PATCH 4/5] add write_bytes() test for a larger-than-u128 struct --- tests/run-pass/write-bytes.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/run-pass/write-bytes.rs b/tests/run-pass/write-bytes.rs index 1df23ab1fe..7c9a38fca6 100644 --- a/tests/run-pass/write-bytes.rs +++ b/tests/run-pass/write-bytes.rs @@ -1,3 +1,11 @@ +#[repr(C)] +#[derive(Copy, Clone)] +struct Foo { + a: u64, + b: u64, + c: u64, +} + fn main() { const LENGTH: usize = 10; let mut v: [u64; LENGTH] = [0; LENGTH]; @@ -14,4 +22,24 @@ fn main() { for idx in 0..LENGTH { assert_eq!(v[idx], 0xabababababababab); } + + // ----- + + let mut w: [Foo; LENGTH] = [Foo { a: 0, b: 0, c: 0 }; LENGTH]; + for idx in 0..LENGTH { + assert_eq!(w[idx].a, 0); + assert_eq!(w[idx].b, 0); + assert_eq!(w[idx].c, 0); + } + + unsafe { + let p = w.as_mut_ptr(); + ::std::ptr::write_bytes(p, 0xcd, LENGTH); + } + + for idx in 0..LENGTH { + assert_eq!(w[idx].a, 0xcdcdcdcdcdcdcdcd); + assert_eq!(w[idx].b, 0xcdcdcdcdcdcdcdcd); + assert_eq!(w[idx].c, 0xcdcdcdcdcdcdcdcd); + } } From 41c2aa677a0ad0e6ff7e77e738b410d7ed3d2980 Mon Sep 17 00:00:00 2001 From: David Renshaw Date: Mon, 13 Mar 2017 20:47:08 -0400 Subject: [PATCH 5/5] simplify write_bytes() by using memory.write_repeat() --- src/terminator/intrinsic.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/terminator/intrinsic.rs b/src/terminator/intrinsic.rs index 56d097289b..51404e7d13 100644 --- a/src/terminator/intrinsic.rs +++ b/src/terminator/intrinsic.rs @@ -405,13 +405,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "write_bytes" => { let u8 = self.tcx.types.u8; let ty = substs.type_at(0); + let ty_align = self.type_align(ty)?; + let val_byte = self.value_to_primval(arg_vals[1], u8)?.to_u128()? as u8; let size = self.type_size(ty)?.expect("write_bytes() type must be sized"); - let mut ptr = arg_vals[0].read_ptr(&self.memory)?; + let ptr = arg_vals[0].read_ptr(&self.memory)?; let count = self.value_to_primval(arg_vals[2], usize)?.to_u64()?; - for _ in 0..(count * size) { - self.write_value_to_ptr(arg_vals[1], ptr, u8)?; - ptr = ptr.offset(1); - } + self.memory.check_align(ptr, size * count, ty_align)?; + self.memory.write_repeat(ptr, val_byte, size * count)?; } name => return Err(EvalError::Unimplemented(format!("unimplemented intrinsic: {}", name))),