]> git.lizzy.rs Git - rust.git/blob - src/helpers.rs
rustup for big refactor; kill most of validation
[rust.git] / src / helpers.rs
1 use rustc::ty::layout::{Size, HasDataLayout};
2
3 use super::{Scalar, ScalarMaybeUndef, EvalResult};
4 use rustc_mir::interpret::sign_extend;
5
6 pub trait ScalarExt {
7     fn null(size: Size) -> Self;
8     fn from_i32(i: i32) -> Self;
9     fn from_uint(i: impl Into<u128>, ptr_size: Size) -> Self;
10     fn from_int(i: impl Into<i128>, ptr_size: Size) -> Self;
11     fn from_f32(f: f32) -> Self;
12     fn from_f64(f: f64) -> Self;
13     fn is_null(self) -> bool;
14 }
15
16 pub trait FalibleScalarExt {
17     fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'static, u64>;
18     fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'static, i64>;
19     fn to_i32(self) -> EvalResult<'static, i32>;
20     fn to_u8(self) -> EvalResult<'static, u8>;
21
22     /// HACK: this function just extracts all bits if `defined != 0`
23     /// Mainly used for args of C-functions and we should totally correctly fetch the size
24     /// of their arguments
25     fn to_bytes(self) -> EvalResult<'static, u128>;
26 }
27
28 impl ScalarExt for Scalar {
29     fn null(size: Size) -> Self {
30         Scalar::Bits { bits: 0, size: size.bytes() as u8 }
31     }
32
33     fn from_i32(i: i32) -> Self {
34         Scalar::Bits { bits: i as u32 as u128, size: 4 }
35     }
36
37     fn from_uint(i: impl Into<u128>, size: Size) -> Self {
38         Scalar::Bits { bits: i.into(), size: size.bytes() as u8 }
39     }
40
41     fn from_int(i: impl Into<i128>, size: Size) -> Self {
42         Scalar::Bits { bits: i.into() as u128, size: size.bytes() as u8 }
43     }
44
45     fn from_f32(f: f32) -> Self {
46         Scalar::Bits { bits: f.to_bits() as u128, size: 4 }
47     }
48
49     fn from_f64(f: f64) -> Self {
50         Scalar::Bits { bits: f.to_bits() as u128, size: 8 }
51     }
52
53     fn is_null(self) -> bool {
54         match self {
55             Scalar::Bits { bits, .. } => bits == 0,
56             Scalar::Ptr(_) => false
57         }
58     }
59 }
60
61 impl FalibleScalarExt for Scalar {
62     fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'static, u64> {
63         let b = self.to_bits(cx.data_layout().pointer_size)?;
64         assert_eq!(b as u64 as u128, b);
65         Ok(b as u64)
66     }
67
68     fn to_u8(self) -> EvalResult<'static, u8> {
69         let sz = Size::from_bits(8);
70         let b = self.to_bits(sz)?;
71         assert_eq!(b as u8 as u128, b);
72         Ok(b as u8)
73     }
74
75     fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'static, i64> {
76         let b = self.to_bits(cx.data_layout().pointer_size)?;
77         let b = sign_extend(b, cx.data_layout().pointer_size) as i128;
78         assert_eq!(b as i64 as i128, b);
79         Ok(b as i64)
80     }
81
82     fn to_i32(self) -> EvalResult<'static, i32> {
83         let sz = Size::from_bits(32);
84         let b = self.to_bits(sz)?;
85         let b = sign_extend(b, sz) as i128;
86         assert_eq!(b as i32 as i128, b);
87         Ok(b as i32)
88     }
89
90     fn to_bytes(self) -> EvalResult<'static, u128> {
91         match self {
92             Scalar::Bits { bits, size } => {
93                 assert_ne!(size, 0);
94                 Ok(bits)
95             },
96             Scalar::Ptr(_) => err!(ReadPointerAsBytes),
97         }
98     }
99 }
100
101 impl FalibleScalarExt for ScalarMaybeUndef {
102     fn to_usize(self, cx: impl HasDataLayout) -> EvalResult<'static, u64> {
103         self.not_undef()?.to_usize(cx)
104     }
105
106     fn to_u8(self) -> EvalResult<'static, u8> {
107         self.not_undef()?.to_u8()
108     }
109
110     fn to_isize(self, cx: impl HasDataLayout) -> EvalResult<'static, i64> {
111         self.not_undef()?.to_isize(cx)
112     }
113
114     fn to_i32(self) -> EvalResult<'static, i32> {
115         self.not_undef()?.to_i32()
116     }
117
118     fn to_bytes(self) -> EvalResult<'static, u128> {
119         self.not_undef()?.to_bytes()
120     }
121 }