From 24870428a767758de49d20a603d368f68669e54f Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 15 Dec 2016 18:27:47 +0100 Subject: [PATCH 1/5] 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 a91a75454dd93..27d73fb66481d 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 374232c8324c4a5516f7f00d48558fb5775bfe96 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 12 Jan 2017 09:26:22 +0100 Subject: [PATCH 2/5] add memrchr libc function --- src/terminator/mod.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/terminator/mod.rs b/src/terminator/mod.rs index 7107a99e8b5e7..67cd75d4ce2ba 100644 --- a/src/terminator/mod.rs +++ b/src/terminator/mod.rs @@ -405,6 +405,18 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { 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(); + 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::Bytes(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; From 8084d60f5441890742b0ea7a28efc77639ee44c6 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Mon, 19 Dec 2016 18:08:53 +0100 Subject: [PATCH 3/5] 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 fe5beb2e5cfbf..3c541608ed1d1 100644 --- a/src/eval_context.rs +++ b/src/eval_context.rs @@ -517,10 +517,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 0000000000000..9e05a89a4ea37 --- /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 927844ab241fe860dfc09733773bc2d35eba9ae4 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 11 Jan 2017 10:04:17 +0100 Subject: [PATCH 4/5] 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 3c541608ed1d1..be745a805acc5 100644 --- a/src/eval_context.rs +++ b/src/eval_context.rs @@ -688,7 +688,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)) @@ -1011,7 +1011,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 { From e7ef11813804a05f11325859145f24297326bd43 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 12 Jan 2017 09:30:18 +0100 Subject: [PATCH 5/5] fix copy pasted code --- src/terminator/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/terminator/mod.rs b/src/terminator/mod.rs index 67cd75d4ce2ba..cbf9bbda2cf83 100644 --- a/src/terminator/mod.rs +++ b/src/terminator/mod.rs @@ -407,8 +407,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_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::Ptr(new_ptr)), dest, dest_ty)?;