From e1e95a83861271e144f65903c652ab9fa9bd64b8 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Wed, 26 Jun 2019 18:50:20 -0500 Subject: [PATCH 1/5] Use force_bits when casting from a pointer --- src/librustc_mir/interpret/cast.rs | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index fbacdf6cd93bb..bd012d4c2bf57 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -242,14 +242,31 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> { ty: Ty<'tcx> ) -> InterpResult<'tcx, Scalar> { use rustc::ty::TyKind::*; - match ty.sty { + + let size = match ty.sty { // Casting to a reference or fn pointer is not permitted by rustc, // no need to support it here. - RawPtr(_) | - Int(IntTy::Isize) | - Uint(UintTy::Usize) => Ok(ptr.into()), - Int(_) | Uint(_) => err!(ReadPointerAsBytes), - _ => err!(Unimplemented(format!("ptr to {:?} cast", ty))), + RawPtr(_) => return Ok(ptr.into()), + Int(IntTy::Isize) | Uint(UintTy::Usize) => { + let size = self.memory.pointer_size(); + if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), size) { + return Ok(Scalar::from_uint(bits, size)); + } + return Ok(ptr.into()); + } + // If the target type is a sized integer, we need the its size to perform the pointer cast + Int(i) => i.bit_width().unwrap(), + Uint(i) => i.bit_width().unwrap(), + // Casting to any other type is not implemented + _ => return err!(Unimplemented(format!("ptr to {:?} cast", ty))), + }; + + let size = Size::from_bits(size as u64); + + if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), size) { + Ok(Scalar::from_uint(bits, size)) + } else { + err!(ReadPointerAsBytes) } } From 7f1e160e02112d4d23a72e52b2ab23860e6a956f Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Fri, 28 Jun 2019 14:25:33 -0500 Subject: [PATCH 2/5] Reorganize code for readabilty and fixed problem with type sizes --- src/librustc_mir/interpret/cast.rs | 47 ++++++++++++++++++------------ 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index bd012d4c2bf57..e8bca0c712399 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -151,7 +151,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> { "Unexpected cast from type {:?}", src_layout.ty ); match val.to_bits_or_ptr(src_layout.size, self) { - Err(ptr) => self.cast_from_ptr(ptr, dest_layout.ty), + Err(ptr) => self.cast_from_ptr(ptr, src_layout, dest_layout), Ok(data) => self.cast_from_int(data, src_layout, dest_layout), } } @@ -239,34 +239,43 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> { fn cast_from_ptr( &self, ptr: Pointer, - ty: Ty<'tcx> + src_layout: TyLayout<'tcx>, + dest_layout: TyLayout<'tcx>, ) -> InterpResult<'tcx, Scalar> { use rustc::ty::TyKind::*; - let size = match ty.sty { + fn int_size<'tcx>(layout: TyLayout<'tcx>) -> Option { + match layout.ty.sty { + Int(i) => i.bit_width(), + Uint(i) => i.bit_width(), + _ => bug!("Not an integer"), + } + } + + match dest_layout.ty.sty { // Casting to a reference or fn pointer is not permitted by rustc, // no need to support it here. - RawPtr(_) => return Ok(ptr.into()), + RawPtr(_) => Ok(ptr.into()), Int(IntTy::Isize) | Uint(UintTy::Usize) => { let size = self.memory.pointer_size(); + if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), size) { - return Ok(Scalar::from_uint(bits, size)); - } - return Ok(ptr.into()); + self.cast_from_int(bits, src_layout, dest_layout) + } else { + Ok(ptr.into()) + } } - // If the target type is a sized integer, we need the its size to perform the pointer cast - Int(i) => i.bit_width().unwrap(), - Uint(i) => i.bit_width().unwrap(), + Int(_) | Uint(_) => { + let size = Size::from_bits(int_size(dest_layout).unwrap() as u64); + + if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), size) { + self.cast_from_int(bits, src_layout, dest_layout) + } else { + err!(ReadPointerAsBytes) + } + }, // Casting to any other type is not implemented - _ => return err!(Unimplemented(format!("ptr to {:?} cast", ty))), - }; - - let size = Size::from_bits(size as u64); - - if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), size) { - Ok(Scalar::from_uint(bits, size)) - } else { - err!(ReadPointerAsBytes) + _ => return err!(Unimplemented(format!("ptr to {:?} cast", dest_layout.ty))), } } From 95bc72052c65e22cbf23f80bfa314528abcb981b Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Sat, 29 Jun 2019 07:59:45 -0500 Subject: [PATCH 3/5] Use pointer size as the source size --- src/librustc_mir/interpret/cast.rs | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index e8bca0c712399..73ef0bd6dacb6 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -244,37 +244,24 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx, Scalar> { use rustc::ty::TyKind::*; - fn int_size<'tcx>(layout: TyLayout<'tcx>) -> Option { - match layout.ty.sty { - Int(i) => i.bit_width(), - Uint(i) => i.bit_width(), - _ => bug!("Not an integer"), - } - } - match dest_layout.ty.sty { // Casting to a reference or fn pointer is not permitted by rustc, // no need to support it here. RawPtr(_) => Ok(ptr.into()), Int(IntTy::Isize) | Uint(UintTy::Usize) => { - let size = self.memory.pointer_size(); - - if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), size) { + if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), self.memory.pointer_size()) { self.cast_from_int(bits, src_layout, dest_layout) } else { Ok(ptr.into()) } } Int(_) | Uint(_) => { - let size = Size::from_bits(int_size(dest_layout).unwrap() as u64); - - if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), size) { + if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), self.memory.pointer_size()) { self.cast_from_int(bits, src_layout, dest_layout) } else { err!(ReadPointerAsBytes) } - }, - // Casting to any other type is not implemented + } _ => return err!(Unimplemented(format!("ptr to {:?} cast", dest_layout.ty))), } } From 51793bd318a162752def38a6ae1ec9292861d0cc Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Sat, 29 Jun 2019 13:19:37 -0500 Subject: [PATCH 4/5] Simplify control flow --- src/librustc_mir/interpret/cast.rs | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 73ef0bd6dacb6..2777ada14f9ad 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -1,7 +1,7 @@ use rustc::ty::{self, Ty, TypeAndMut}; use rustc::ty::layout::{self, TyLayout, Size}; use rustc::ty::adjustment::{PointerCast}; -use syntax::ast::{FloatTy, IntTy, UintTy}; +use syntax::ast::FloatTy; use syntax::symbol::sym; use rustc_apfloat::ieee::{Single, Double}; @@ -248,18 +248,13 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> { // Casting to a reference or fn pointer is not permitted by rustc, // no need to support it here. RawPtr(_) => Ok(ptr.into()), - Int(IntTy::Isize) | Uint(UintTy::Usize) => { - if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), self.memory.pointer_size()) { - self.cast_from_int(bits, src_layout, dest_layout) - } else { - Ok(ptr.into()) - } - } Int(_) | Uint(_) => { - if let Ok(bits) = self.force_bits(Scalar::Ptr(ptr), self.memory.pointer_size()) { - self.cast_from_int(bits, src_layout, dest_layout) - } else { - err!(ReadPointerAsBytes) + let size = self.memory.pointer_size(); + + match self.force_bits(Scalar::Ptr(ptr), size) { + Ok(bits) => self.cast_from_int(bits, src_layout, dest_layout), + Err(_) if dest_layout.size == size => Ok(ptr.into()), + Err(e) => Err(e), } } _ => return err!(Unimplemented(format!("ptr to {:?} cast", dest_layout.ty))), From 92c28bfabcbbbbf864308cd71750d4b20f306b37 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Sat, 29 Jun 2019 22:50:37 -0500 Subject: [PATCH 5/5] Replace error by bug macro --- src/librustc_mir/interpret/cast.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 2777ada14f9ad..e6c9d9f5c79d8 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -257,7 +257,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> { Err(e) => Err(e), } } - _ => return err!(Unimplemented(format!("ptr to {:?} cast", dest_layout.ty))), + _ => bug!("invalid MIR: ptr to {:?} cast", dest_layout.ty) } }