|  | 
| 1 | 1 | use std::convert::TryFrom; | 
|  | 2 | +use std::fmt; | 
| 2 | 3 | 
 | 
| 3 | 4 | use rustc_apfloat::{ | 
| 4 | 5 |     ieee::{Double, Single}, | 
| 5 | 6 |     Float, | 
| 6 | 7 | }; | 
| 7 | 8 | use rustc_macros::HashStable; | 
| 8 |  | -use std::fmt; | 
|  | 9 | +use rustc_target::abi::TargetDataLayout; | 
| 9 | 10 | 
 | 
| 10 | 11 | use crate::ty::{ | 
| 11 | 12 |     layout::{HasDataLayout, Size}, | 
| @@ -200,68 +201,54 @@ impl<'tcx, Tag> Scalar<Tag> { | 
| 200 | 201 |         Scalar::Raw { data: 0, size: 0 } | 
| 201 | 202 |     } | 
| 202 | 203 | 
 | 
| 203 |  | -    #[inline] | 
| 204 |  | -    pub fn ptr_offset(self, i: Size, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> { | 
| 205 |  | -        let dl = cx.data_layout(); | 
|  | 204 | +    #[inline(always)] | 
|  | 205 | +    fn ptr_op( | 
|  | 206 | +        self, | 
|  | 207 | +        dl: &TargetDataLayout, | 
|  | 208 | +        f_int: impl FnOnce(u64) -> InterpResult<'tcx, u64>, | 
|  | 209 | +        f_ptr: impl FnOnce(Pointer<Tag>) -> InterpResult<'tcx, Pointer<Tag>>, | 
|  | 210 | +    ) -> InterpResult<'tcx, Self> { | 
| 206 | 211 |         match self { | 
| 207 | 212 |             Scalar::Raw { data, size } => { | 
| 208 | 213 |                 assert_eq!(u64::from(size), dl.pointer_size.bytes()); | 
| 209 |  | -                Ok(Scalar::Raw { | 
| 210 |  | -                    data: u128::from(dl.offset(u64::try_from(data).unwrap(), i.bytes())?), | 
| 211 |  | -                    size, | 
| 212 |  | -                }) | 
|  | 214 | +                Ok(Scalar::Raw { data: u128::from(f_int(u64::try_from(data).unwrap())?), size }) | 
| 213 | 215 |             } | 
| 214 |  | -            Scalar::Ptr(ptr) => ptr.offset(i, dl).map(Scalar::Ptr), | 
|  | 216 | +            Scalar::Ptr(ptr) => Ok(Scalar::Ptr(f_ptr(ptr)?)), | 
| 215 | 217 |         } | 
| 216 | 218 |     } | 
| 217 | 219 | 
 | 
|  | 220 | +    #[inline] | 
|  | 221 | +    pub fn ptr_offset(self, i: Size, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> { | 
|  | 222 | +        let dl = cx.data_layout(); | 
|  | 223 | +        self.ptr_op(dl, |int| dl.offset(int, i.bytes()), |ptr| ptr.offset(i, dl)) | 
|  | 224 | +    } | 
|  | 225 | + | 
| 218 | 226 |     #[inline] | 
| 219 | 227 |     pub fn ptr_wrapping_offset(self, i: Size, cx: &impl HasDataLayout) -> Self { | 
| 220 | 228 |         let dl = cx.data_layout(); | 
| 221 |  | -        match self { | 
| 222 |  | -            Scalar::Raw { data, size } => { | 
| 223 |  | -                assert_eq!(u64::from(size), dl.pointer_size.bytes()); | 
| 224 |  | -                Scalar::Raw { | 
| 225 |  | -                    data: u128::from( | 
| 226 |  | -                        dl.overflowing_offset(u64::try_from(data).unwrap(), i.bytes()).0, | 
| 227 |  | -                    ), | 
| 228 |  | -                    size, | 
| 229 |  | -                } | 
| 230 |  | -            } | 
| 231 |  | -            Scalar::Ptr(ptr) => Scalar::Ptr(ptr.wrapping_offset(i, dl)), | 
| 232 |  | -        } | 
|  | 229 | +        self.ptr_op( | 
|  | 230 | +            dl, | 
|  | 231 | +            |int| Ok(dl.overflowing_offset(int, i.bytes()).0), | 
|  | 232 | +            |ptr| Ok(ptr.wrapping_offset(i, dl)), | 
|  | 233 | +        ) | 
|  | 234 | +        .unwrap() | 
| 233 | 235 |     } | 
| 234 | 236 | 
 | 
| 235 | 237 |     #[inline] | 
| 236 | 238 |     pub fn ptr_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> InterpResult<'tcx, Self> { | 
| 237 | 239 |         let dl = cx.data_layout(); | 
| 238 |  | -        match self { | 
| 239 |  | -            Scalar::Raw { data, size } => { | 
| 240 |  | -                assert_eq!(u64::from(size), dl.pointer_size.bytes()); | 
| 241 |  | -                Ok(Scalar::Raw { | 
| 242 |  | -                    data: u128::from(dl.signed_offset(u64::try_from(data).unwrap(), i)?), | 
| 243 |  | -                    size, | 
| 244 |  | -                }) | 
| 245 |  | -            } | 
| 246 |  | -            Scalar::Ptr(ptr) => ptr.signed_offset(i, dl).map(Scalar::Ptr), | 
| 247 |  | -        } | 
|  | 240 | +        self.ptr_op(dl, |int| dl.signed_offset(int, i), |ptr| ptr.signed_offset(i, dl)) | 
| 248 | 241 |     } | 
| 249 | 242 | 
 | 
| 250 | 243 |     #[inline] | 
| 251 | 244 |     pub fn ptr_wrapping_signed_offset(self, i: i64, cx: &impl HasDataLayout) -> Self { | 
| 252 | 245 |         let dl = cx.data_layout(); | 
| 253 |  | -        match self { | 
| 254 |  | -            Scalar::Raw { data, size } => { | 
| 255 |  | -                assert_eq!(u64::from(size), dl.pointer_size.bytes()); | 
| 256 |  | -                Scalar::Raw { | 
| 257 |  | -                    data: u128::from( | 
| 258 |  | -                        dl.overflowing_signed_offset(u64::try_from(data).unwrap(), i128::from(i)).0, | 
| 259 |  | -                    ), | 
| 260 |  | -                    size, | 
| 261 |  | -                } | 
| 262 |  | -            } | 
| 263 |  | -            Scalar::Ptr(ptr) => Scalar::Ptr(ptr.wrapping_signed_offset(i, dl)), | 
| 264 |  | -        } | 
|  | 246 | +        self.ptr_op( | 
|  | 247 | +            dl, | 
|  | 248 | +            |int| Ok(dl.overflowing_signed_offset(int, i).0), | 
|  | 249 | +            |ptr| Ok(ptr.wrapping_signed_offset(i, dl)), | 
|  | 250 | +        ) | 
|  | 251 | +        .unwrap() | 
| 265 | 252 |     } | 
| 266 | 253 | 
 | 
| 267 | 254 |     #[inline] | 
|  | 
0 commit comments