1
1
#![ allow( unknown_lints) ]
2
2
3
- use ty:: layout:: { Align , HasDataLayout , Size } ;
4
- use ty;
3
+ use ty:: layout:: { HasDataLayout , Size } ;
5
4
use ty:: subst:: Substs ;
6
5
use hir:: def_id:: DefId ;
7
6
8
7
use super :: { EvalResult , Pointer , PointerArithmetic , Allocation } ;
9
8
10
9
/// Represents a constant value in Rust. Scalar and ScalarPair are optimizations which
11
- /// matches Value's optimizations for easy conversions between these two types
10
+ /// matches the LocalValue optimizations for easy conversions between Value and ConstValue.
12
11
#[ derive( Copy , Clone , Debug , Eq , PartialEq , PartialOrd , Ord , RustcEncodable , RustcDecodable , Hash ) ]
13
12
pub enum ConstValue < ' tcx > {
14
13
/// Never returned from the `const_eval` query, but the HIR contains these frequently in order
15
14
/// to allow HIR creation to happen for everything before needing to be able to run constant
16
15
/// evaluation
17
16
Unevaluated ( DefId , & ' tcx Substs < ' tcx > ) ,
18
17
/// Used only for types with layout::abi::Scalar ABI and ZSTs
18
+ ///
19
+ /// Not using the enum `Value` to encode that this must not be `Undef`
19
20
Scalar ( Scalar ) ,
20
21
/// Used only for types with layout::abi::ScalarPair
21
22
///
@@ -26,25 +27,6 @@ pub enum ConstValue<'tcx> {
26
27
}
27
28
28
29
impl < ' tcx > ConstValue < ' tcx > {
29
- #[ inline]
30
- pub fn from_byval_value ( val : Value ) -> EvalResult < ' static , Self > {
31
- Ok ( match val {
32
- Value :: ByRef ( ..) => bug ! ( ) ,
33
- Value :: ScalarPair ( a, b) => ConstValue :: ScalarPair ( a. unwrap_or_err ( ) ?, b) ,
34
- Value :: Scalar ( val) => ConstValue :: Scalar ( val. unwrap_or_err ( ) ?) ,
35
- } )
36
- }
37
-
38
- #[ inline]
39
- pub fn to_byval_value ( & self ) -> Option < Value > {
40
- match * self {
41
- ConstValue :: Unevaluated ( ..) |
42
- ConstValue :: ByRef ( ..) => None ,
43
- ConstValue :: ScalarPair ( a, b) => Some ( Value :: ScalarPair ( a. into ( ) , b) ) ,
44
- ConstValue :: Scalar ( val) => Some ( Value :: Scalar ( val. into ( ) ) ) ,
45
- }
46
- }
47
-
48
30
#[ inline]
49
31
pub fn try_to_scalar ( & self ) -> Option < Scalar > {
50
32
match * self {
@@ -56,58 +38,44 @@ impl<'tcx> ConstValue<'tcx> {
56
38
}
57
39
58
40
#[ inline]
59
- pub fn to_bits ( & self , size : Size ) -> Option < u128 > {
41
+ pub fn try_to_bits ( & self , size : Size ) -> Option < u128 > {
60
42
self . try_to_scalar ( ) ?. to_bits ( size) . ok ( )
61
43
}
62
44
63
45
#[ inline]
64
- pub fn to_ptr ( & self ) -> Option < Pointer > {
46
+ pub fn try_to_ptr ( & self ) -> Option < Pointer > {
65
47
self . try_to_scalar ( ) ?. to_ptr ( ) . ok ( )
66
48
}
67
- }
68
-
69
- /// A `Value` represents a single self-contained Rust value.
70
- ///
71
- /// A `Value` can either refer to a block of memory inside an allocation (`ByRef`) or to a primitive
72
- /// value held directly, outside of any allocation (`Scalar`). For `ByRef`-values, we remember
73
- /// whether the pointer is supposed to be aligned or not (also see Place).
74
- ///
75
- /// For optimization of a few very common cases, there is also a representation for a pair of
76
- /// primitive values (`ScalarPair`). It allows Miri to avoid making allocations for checked binary
77
- /// operations and fat pointers. This idea was taken from rustc's codegen.
78
- #[ derive( Clone , Copy , Debug , Eq , PartialEq , Ord , PartialOrd , RustcEncodable , RustcDecodable , Hash ) ]
79
- pub enum Value {
80
- ByRef ( Scalar , Align ) ,
81
- Scalar ( ScalarMaybeUndef ) ,
82
- ScalarPair ( ScalarMaybeUndef , ScalarMaybeUndef ) ,
83
- }
84
49
85
- impl < ' tcx > ty:: TypeFoldable < ' tcx > for Value {
86
- fn super_fold_with < ' gcx : ' tcx , F : ty:: fold:: TypeFolder < ' gcx , ' tcx > > ( & self , _: & mut F ) -> Self {
87
- * self
50
+ pub fn new_slice (
51
+ val : Scalar ,
52
+ len : u64 ,
53
+ cx : impl HasDataLayout
54
+ ) -> Self {
55
+ ConstValue :: ScalarPair ( val, Scalar :: Bits {
56
+ bits : len as u128 ,
57
+ size : cx. data_layout ( ) . pointer_size . bytes ( ) as u8 ,
58
+ } . into ( ) )
88
59
}
89
- fn super_visit_with < V : ty:: fold:: TypeVisitor < ' tcx > > ( & self , _: & mut V ) -> bool {
90
- false
60
+
61
+ pub fn new_dyn_trait ( val : Scalar , vtable : Pointer ) -> Self {
62
+ ConstValue :: ScalarPair ( val, Scalar :: Ptr ( vtable) . into ( ) )
91
63
}
92
64
}
93
65
94
66
impl < ' tcx > Scalar {
95
- pub fn ptr_null < C : HasDataLayout > ( cx : C ) -> Self {
67
+ pub fn ptr_null ( cx : impl HasDataLayout ) -> Self {
96
68
Scalar :: Bits {
97
69
bits : 0 ,
98
70
size : cx. data_layout ( ) . pointer_size . bytes ( ) as u8 ,
99
71
}
100
72
}
101
73
102
- pub fn to_value_with_len < C : HasDataLayout > ( self , len : u64 , cx : C ) -> Value {
103
- ScalarMaybeUndef :: Scalar ( self ) . to_value_with_len ( len, cx)
104
- }
105
-
106
- pub fn to_value_with_vtable ( self , vtable : Pointer ) -> Value {
107
- ScalarMaybeUndef :: Scalar ( self ) . to_value_with_vtable ( vtable)
74
+ pub fn zst ( ) -> Self {
75
+ Scalar :: Bits { bits : 0 , size : 0 }
108
76
}
109
77
110
- pub fn ptr_signed_offset < C : HasDataLayout > ( self , i : i64 , cx : C ) -> EvalResult < ' tcx , Self > {
78
+ pub fn ptr_signed_offset ( self , i : i64 , cx : impl HasDataLayout ) -> EvalResult < ' tcx , Self > {
111
79
let layout = cx. data_layout ( ) ;
112
80
match self {
113
81
Scalar :: Bits { bits, size } => {
@@ -121,7 +89,7 @@ impl<'tcx> Scalar {
121
89
}
122
90
}
123
91
124
- pub fn ptr_offset < C : HasDataLayout > ( self , i : Size , cx : C ) -> EvalResult < ' tcx , Self > {
92
+ pub fn ptr_offset ( self , i : Size , cx : impl HasDataLayout ) -> EvalResult < ' tcx , Self > {
125
93
let layout = cx. data_layout ( ) ;
126
94
match self {
127
95
Scalar :: Bits { bits, size } => {
@@ -135,7 +103,7 @@ impl<'tcx> Scalar {
135
103
}
136
104
}
137
105
138
- pub fn ptr_wrapping_signed_offset < C : HasDataLayout > ( self , i : i64 , cx : C ) -> Self {
106
+ pub fn ptr_wrapping_signed_offset ( self , i : i64 , cx : impl HasDataLayout ) -> Self {
139
107
let layout = cx. data_layout ( ) ;
140
108
match self {
141
109
Scalar :: Bits { bits, size } => {
@@ -149,7 +117,7 @@ impl<'tcx> Scalar {
149
117
}
150
118
}
151
119
152
- pub fn is_null_ptr < C : HasDataLayout > ( self , cx : C ) -> bool {
120
+ pub fn is_null_ptr ( self , cx : impl HasDataLayout ) -> bool {
153
121
match self {
154
122
Scalar :: Bits { bits, size } => {
155
123
assert_eq ! ( size as u64 , cx. data_layout( ) . pointer_size. bytes( ) ) ;
@@ -159,8 +127,52 @@ impl<'tcx> Scalar {
159
127
}
160
128
}
161
129
162
- pub fn to_value ( self ) -> Value {
163
- Value :: Scalar ( ScalarMaybeUndef :: Scalar ( self ) )
130
+ pub fn from_bool ( b : bool ) -> Self {
131
+ Scalar :: Bits { bits : b as u128 , size : 1 }
132
+ }
133
+
134
+ pub fn from_char ( c : char ) -> Self {
135
+ Scalar :: Bits { bits : c as u128 , size : 4 }
136
+ }
137
+
138
+ pub fn to_bits ( self , target_size : Size ) -> EvalResult < ' tcx , u128 > {
139
+ match self {
140
+ Scalar :: Bits { bits, size } => {
141
+ assert_eq ! ( target_size. bytes( ) , size as u64 ) ;
142
+ assert_ne ! ( size, 0 , "to_bits cannot be used with zsts" ) ;
143
+ Ok ( bits)
144
+ }
145
+ Scalar :: Ptr ( _) => err ! ( ReadPointerAsBytes ) ,
146
+ }
147
+ }
148
+
149
+ pub fn to_ptr ( self ) -> EvalResult < ' tcx , Pointer > {
150
+ match self {
151
+ Scalar :: Bits { ..} => err ! ( ReadBytesAsPointer ) ,
152
+ Scalar :: Ptr ( p) => Ok ( p) ,
153
+ }
154
+ }
155
+
156
+ pub fn is_bits ( self ) -> bool {
157
+ match self {
158
+ Scalar :: Bits { .. } => true ,
159
+ _ => false ,
160
+ }
161
+ }
162
+
163
+ pub fn is_ptr ( self ) -> bool {
164
+ match self {
165
+ Scalar :: Ptr ( _) => true ,
166
+ _ => false ,
167
+ }
168
+ }
169
+
170
+ pub fn to_bool ( self ) -> EvalResult < ' tcx , bool > {
171
+ match self {
172
+ Scalar :: Bits { bits : 0 , size : 1 } => Ok ( false ) ,
173
+ Scalar :: Bits { bits : 1 , size : 1 } => Ok ( true ) ,
174
+ _ => err ! ( InvalidBool ) ,
175
+ }
164
176
}
165
177
}
166
178
@@ -202,81 +214,23 @@ impl From<Scalar> for ScalarMaybeUndef {
202
214
}
203
215
}
204
216
205
- impl ScalarMaybeUndef {
206
- pub fn unwrap_or_err ( self ) -> EvalResult < ' static , Scalar > {
217
+ impl < ' tcx > ScalarMaybeUndef {
218
+ pub fn not_undef ( self ) -> EvalResult < ' static , Scalar > {
207
219
match self {
208
220
ScalarMaybeUndef :: Scalar ( scalar) => Ok ( scalar) ,
209
221
ScalarMaybeUndef :: Undef => err ! ( ReadUndefBytes ) ,
210
222
}
211
223
}
212
224
213
- pub fn to_value_with_len < C : HasDataLayout > ( self , len : u64 , cx : C ) -> Value {
214
- Value :: ScalarPair ( self , Scalar :: Bits {
215
- bits : len as u128 ,
216
- size : cx. data_layout ( ) . pointer_size . bytes ( ) as u8 ,
217
- } . into ( ) )
218
- }
219
-
220
- pub fn to_value_with_vtable ( self , vtable : Pointer ) -> Value {
221
- Value :: ScalarPair ( self , Scalar :: Ptr ( vtable) . into ( ) )
222
- }
223
-
224
- pub fn ptr_offset < C : HasDataLayout > ( self , i : Size , cx : C ) -> EvalResult < ' tcx , Self > {
225
- match self {
226
- ScalarMaybeUndef :: Scalar ( scalar) => {
227
- scalar. ptr_offset ( i, cx) . map ( ScalarMaybeUndef :: Scalar )
228
- } ,
229
- ScalarMaybeUndef :: Undef => Ok ( ScalarMaybeUndef :: Undef )
230
- }
231
- }
232
- }
233
-
234
- impl < ' tcx > Scalar {
235
- pub fn from_bool ( b : bool ) -> Self {
236
- Scalar :: Bits { bits : b as u128 , size : 1 }
237
- }
238
-
239
- pub fn from_char ( c : char ) -> Self {
240
- Scalar :: Bits { bits : c as u128 , size : 4 }
241
- }
242
-
243
- pub fn to_bits ( self , target_size : Size ) -> EvalResult < ' tcx , u128 > {
244
- match self {
245
- Scalar :: Bits { bits, size } => {
246
- assert_eq ! ( target_size. bytes( ) , size as u64 ) ;
247
- assert_ne ! ( size, 0 , "to_bits cannot be used with zsts" ) ;
248
- Ok ( bits)
249
- }
250
- Scalar :: Ptr ( _) => err ! ( ReadPointerAsBytes ) ,
251
- }
252
- }
253
-
254
225
pub fn to_ptr ( self ) -> EvalResult < ' tcx , Pointer > {
255
- match self {
256
- Scalar :: Bits { ..} => err ! ( ReadBytesAsPointer ) ,
257
- Scalar :: Ptr ( p) => Ok ( p) ,
258
- }
259
- }
260
-
261
- pub fn is_bits ( self ) -> bool {
262
- match self {
263
- Scalar :: Bits { .. } => true ,
264
- _ => false ,
265
- }
226
+ self . not_undef ( ) ?. to_ptr ( )
266
227
}
267
228
268
- pub fn is_ptr ( self ) -> bool {
269
- match self {
270
- Scalar :: Ptr ( _) => true ,
271
- _ => false ,
272
- }
229
+ pub fn to_bits ( self , target_size : Size ) -> EvalResult < ' tcx , u128 > {
230
+ self . not_undef ( ) ?. to_bits ( target_size)
273
231
}
274
232
275
233
pub fn to_bool ( self ) -> EvalResult < ' tcx , bool > {
276
- match self {
277
- Scalar :: Bits { bits : 0 , size : 1 } => Ok ( false ) ,
278
- Scalar :: Bits { bits : 1 , size : 1 } => Ok ( true ) ,
279
- _ => err ! ( InvalidBool ) ,
280
- }
234
+ self . not_undef ( ) ?. to_bool ( )
281
235
}
282
236
}
0 commit comments