@@ -15,41 +15,38 @@ pub enum ConstValue<'tcx> {
15
15
/// to allow HIR creation to happen for everything before needing to be able to run constant
16
16
/// evaluation
17
17
Unevaluated ( DefId , & ' tcx Substs < ' tcx > ) ,
18
- /// Used only for types with layout::abi::Scalar ABI and ZSTs which use Scalar::undef()
18
+ /// Used only for types with layout::abi::Scalar ABI and ZSTs
19
19
Scalar ( Scalar ) ,
20
20
/// Used only for types with layout::abi::ScalarPair
21
- ScalarPair ( Scalar , Scalar ) ,
21
+ ///
22
+ /// The second field may be undef in case of `Option<usize>::None`
23
+ ScalarPair ( Scalar , ScalarMaybeUndef ) ,
22
24
/// Used only for the remaining cases. An allocation + offset into the allocation
23
25
ByRef ( & ' tcx Allocation , Size ) ,
24
26
}
25
27
26
28
impl < ' tcx > ConstValue < ' tcx > {
27
29
#[ inline]
28
- pub fn from_byval_value ( val : Value ) -> Self {
29
- match val {
30
+ pub fn from_byval_value ( val : Value ) -> EvalResult < ' static , Self > {
31
+ Ok ( match val {
30
32
Value :: ByRef ( ..) => bug ! ( ) ,
31
- Value :: ScalarPair ( a, b) => ConstValue :: ScalarPair ( a, b) ,
32
- Value :: Scalar ( val) => ConstValue :: Scalar ( val) ,
33
- }
33
+ Value :: ScalarPair ( a, b) => ConstValue :: ScalarPair ( a. unwrap_or_err ( ) ? , b) ,
34
+ Value :: Scalar ( val) => ConstValue :: Scalar ( val. unwrap_or_err ( ) ? ) ,
35
+ } )
34
36
}
35
37
36
38
#[ inline]
37
39
pub fn to_byval_value ( & self ) -> Option < Value > {
38
40
match * self {
39
41
ConstValue :: Unevaluated ( ..) |
40
42
ConstValue :: ByRef ( ..) => None ,
41
- ConstValue :: ScalarPair ( a, b) => Some ( Value :: ScalarPair ( a, b) ) ,
42
- ConstValue :: Scalar ( val) => Some ( Value :: Scalar ( val) ) ,
43
+ ConstValue :: ScalarPair ( a, b) => Some ( Value :: ScalarPair ( a. into ( ) , b) ) ,
44
+ ConstValue :: Scalar ( val) => Some ( Value :: Scalar ( val. into ( ) ) ) ,
43
45
}
44
46
}
45
47
46
48
#[ inline]
47
- pub fn from_scalar ( val : Scalar ) -> Self {
48
- ConstValue :: Scalar ( val)
49
- }
50
-
51
- #[ inline]
52
- pub fn to_scalar ( & self ) -> Option < Scalar > {
49
+ pub fn try_to_scalar ( & self ) -> Option < Scalar > {
53
50
match * self {
54
51
ConstValue :: Unevaluated ( ..) |
55
52
ConstValue :: ByRef ( ..) |
@@ -60,12 +57,12 @@ impl<'tcx> ConstValue<'tcx> {
60
57
61
58
#[ inline]
62
59
pub fn to_bits ( & self , size : Size ) -> Option < u128 > {
63
- self . to_scalar ( ) ?. to_bits ( size) . ok ( )
60
+ self . try_to_scalar ( ) ?. to_bits ( size) . ok ( )
64
61
}
65
62
66
63
#[ inline]
67
64
pub fn to_ptr ( & self ) -> Option < Pointer > {
68
- self . to_scalar ( ) ?. to_ptr ( ) . ok ( )
65
+ self . try_to_scalar ( ) ?. to_ptr ( ) . ok ( )
69
66
}
70
67
}
71
68
@@ -81,8 +78,8 @@ impl<'tcx> ConstValue<'tcx> {
81
78
#[ derive( Clone , Copy , Debug , Eq , PartialEq , Ord , PartialOrd , RustcEncodable , RustcDecodable , Hash ) ]
82
79
pub enum Value {
83
80
ByRef ( Scalar , Align ) ,
84
- Scalar ( Scalar ) ,
85
- ScalarPair ( Scalar , Scalar ) ,
81
+ Scalar ( ScalarMaybeUndef ) ,
82
+ ScalarPair ( ScalarMaybeUndef , ScalarMaybeUndef ) ,
86
83
}
87
84
88
85
impl < ' tcx > ty:: TypeFoldable < ' tcx > for Value {
@@ -98,23 +95,27 @@ impl<'tcx> Scalar {
98
95
pub fn ptr_null < C : HasDataLayout > ( cx : C ) -> Self {
99
96
Scalar :: Bits {
100
97
bits : 0 ,
101
- defined : cx. data_layout ( ) . pointer_size . bits ( ) as u8 ,
98
+ size : cx. data_layout ( ) . pointer_size . bytes ( ) as u8 ,
102
99
}
103
100
}
104
101
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)
108
+ }
109
+
105
110
pub fn ptr_signed_offset < C : HasDataLayout > ( self , i : i64 , cx : C ) -> EvalResult < ' tcx , Self > {
106
111
let layout = cx. data_layout ( ) ;
107
112
match self {
108
- Scalar :: Bits { bits, defined } => {
109
- let pointer_size = layout. pointer_size . bits ( ) as u8 ;
110
- if defined < pointer_size {
111
- err ! ( ReadUndefBytes )
112
- } else {
113
- Ok ( Scalar :: Bits {
114
- bits : layout. signed_offset ( bits as u64 , i) ? as u128 ,
115
- defined : pointer_size,
116
- } )
117
- }
113
+ Scalar :: Bits { bits, size } => {
114
+ assert_eq ! ( size as u64 , layout. pointer_size. bytes( ) ) ;
115
+ Ok ( Scalar :: Bits {
116
+ bits : layout. signed_offset ( bits as u64 , i) ? as u128 ,
117
+ size,
118
+ } )
118
119
}
119
120
Scalar :: Ptr ( ptr) => ptr. signed_offset ( i, layout) . map ( Scalar :: Ptr ) ,
120
121
}
@@ -123,65 +124,43 @@ impl<'tcx> Scalar {
123
124
pub fn ptr_offset < C : HasDataLayout > ( self , i : Size , cx : C ) -> EvalResult < ' tcx , Self > {
124
125
let layout = cx. data_layout ( ) ;
125
126
match self {
126
- Scalar :: Bits { bits, defined } => {
127
- let pointer_size = layout. pointer_size . bits ( ) as u8 ;
128
- if defined < pointer_size {
129
- err ! ( ReadUndefBytes )
130
- } else {
131
- Ok ( Scalar :: Bits {
132
- bits : layout. offset ( bits as u64 , i. bytes ( ) ) ? as u128 ,
133
- defined : pointer_size,
134
- } )
135
- }
127
+ Scalar :: Bits { bits, size } => {
128
+ assert_eq ! ( size as u64 , layout. pointer_size. bytes( ) ) ;
129
+ Ok ( Scalar :: Bits {
130
+ bits : layout. offset ( bits as u64 , i. bytes ( ) ) ? as u128 ,
131
+ size,
132
+ } )
136
133
}
137
134
Scalar :: Ptr ( ptr) => ptr. offset ( i, layout) . map ( Scalar :: Ptr ) ,
138
135
}
139
136
}
140
137
141
- pub fn ptr_wrapping_signed_offset < C : HasDataLayout > ( self , i : i64 , cx : C ) -> EvalResult < ' tcx , Self > {
138
+ pub fn ptr_wrapping_signed_offset < C : HasDataLayout > ( self , i : i64 , cx : C ) -> Self {
142
139
let layout = cx. data_layout ( ) ;
143
140
match self {
144
- Scalar :: Bits { bits, defined } => {
145
- let pointer_size = layout. pointer_size . bits ( ) as u8 ;
146
- if defined < pointer_size {
147
- err ! ( ReadUndefBytes )
148
- } else {
149
- Ok ( Scalar :: Bits {
150
- bits : layout. wrapping_signed_offset ( bits as u64 , i) as u128 ,
151
- defined : pointer_size,
152
- } )
153
- }
141
+ Scalar :: Bits { bits, size } => {
142
+ assert_eq ! ( size as u64 , layout. pointer_size. bytes( ) ) ;
143
+ Scalar :: Bits {
144
+ bits : layout. wrapping_signed_offset ( bits as u64 , i) as u128 ,
145
+ size,
146
+ }
154
147
}
155
- Scalar :: Ptr ( ptr) => Ok ( Scalar :: Ptr ( ptr. wrapping_signed_offset ( i, layout) ) ) ,
148
+ Scalar :: Ptr ( ptr) => Scalar :: Ptr ( ptr. wrapping_signed_offset ( i, layout) ) ,
156
149
}
157
150
}
158
151
159
- pub fn is_null_ptr < C : HasDataLayout > ( self , cx : C ) -> EvalResult < ' tcx , bool > {
152
+ pub fn is_null_ptr < C : HasDataLayout > ( self , cx : C ) -> bool {
160
153
match self {
161
- Scalar :: Bits {
162
- bits, defined,
163
- } => if defined < cx. data_layout ( ) . pointer_size . bits ( ) as u8 {
164
- err ! ( ReadUndefBytes )
165
- } else {
166
- Ok ( bits == 0 )
154
+ Scalar :: Bits { bits, size } => {
155
+ assert_eq ! ( size as u64 , cx. data_layout( ) . pointer_size. bytes( ) ) ;
156
+ bits == 0
167
157
} ,
168
- Scalar :: Ptr ( _) => Ok ( false ) ,
158
+ Scalar :: Ptr ( _) => false ,
169
159
}
170
160
}
171
161
172
- pub fn to_value_with_len < C : HasDataLayout > ( self , len : u64 , cx : C ) -> Value {
173
- Value :: ScalarPair ( self , Scalar :: Bits {
174
- bits : len as u128 ,
175
- defined : cx. data_layout ( ) . pointer_size . bits ( ) as u8 ,
176
- } )
177
- }
178
-
179
- pub fn to_value_with_vtable ( self , vtable : Pointer ) -> Value {
180
- Value :: ScalarPair ( self , Scalar :: Ptr ( vtable) )
181
- }
182
-
183
162
pub fn to_value ( self ) -> Value {
184
- Value :: Scalar ( self )
163
+ Value :: Scalar ( ScalarMaybeUndef :: Scalar ( self ) )
185
164
}
186
165
}
187
166
@@ -199,8 +178,9 @@ impl From<Pointer> for Scalar {
199
178
pub enum Scalar {
200
179
/// The raw bytes of a simple value.
201
180
Bits {
202
- /// The first `defined` number of bits are valid
203
- defined : u8 ,
181
+ /// The first `size` bytes are the value.
182
+ /// Do not try to read less or more bytes that that
183
+ size : u8 ,
204
184
bits : u128 ,
205
185
} ,
206
186
@@ -210,25 +190,63 @@ pub enum Scalar {
210
190
Ptr ( Pointer ) ,
211
191
}
212
192
213
- impl < ' tcx > Scalar {
214
- pub fn undef ( ) -> Self {
215
- Scalar :: Bits { bits : 0 , defined : 0 }
193
+ #[ derive( Clone , Copy , Debug , Eq , PartialEq , Ord , PartialOrd , RustcEncodable , RustcDecodable , Hash ) ]
194
+ pub enum ScalarMaybeUndef {
195
+ Scalar ( Scalar ) ,
196
+ Undef ,
197
+ }
198
+
199
+ impl From < Scalar > for ScalarMaybeUndef {
200
+ fn from ( s : Scalar ) -> Self {
201
+ ScalarMaybeUndef :: Scalar ( s)
202
+ }
203
+ }
204
+
205
+ impl ScalarMaybeUndef {
206
+ pub fn unwrap_or_err ( self ) -> EvalResult < ' static , Scalar > {
207
+ match self {
208
+ ScalarMaybeUndef :: Scalar ( scalar) => Ok ( scalar) ,
209
+ ScalarMaybeUndef :: Undef => err ! ( ReadUndefBytes ) ,
210
+ }
211
+ }
212
+
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 ( ) )
216
218
}
217
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 {
218
235
pub fn from_bool ( b : bool ) -> Self {
219
- // FIXME: can we make defined `1`?
220
- Scalar :: Bits { bits : b as u128 , defined : 8 }
236
+ Scalar :: Bits { bits : b as u128 , size : 1 }
221
237
}
222
238
223
239
pub fn from_char ( c : char ) -> Self {
224
- Scalar :: Bits { bits : c as u128 , defined : 32 }
240
+ Scalar :: Bits { bits : c as u128 , size : 4 }
225
241
}
226
242
227
- pub fn to_bits ( self , size : Size ) -> EvalResult < ' tcx , u128 > {
243
+ pub fn to_bits ( self , target_size : Size ) -> EvalResult < ' tcx , u128 > {
228
244
match self {
229
- Scalar :: Bits { .. } if size. bits ( ) == 0 => bug ! ( "to_bits cannot be used with zsts" ) ,
230
- Scalar :: Bits { bits, defined } if size. bits ( ) <= defined as u64 => Ok ( bits) ,
231
- Scalar :: Bits { .. } => err ! ( ReadUndefBytes ) ,
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
+ }
232
250
Scalar :: Ptr ( _) => err ! ( ReadPointerAsBytes ) ,
233
251
}
234
252
}
@@ -256,8 +274,8 @@ impl<'tcx> Scalar {
256
274
257
275
pub fn to_bool ( self ) -> EvalResult < ' tcx , bool > {
258
276
match self {
259
- Scalar :: Bits { bits : 0 , defined : 8 } => Ok ( false ) ,
260
- Scalar :: Bits { bits : 1 , defined : 8 } => Ok ( true ) ,
277
+ Scalar :: Bits { bits : 0 , size : 1 } => Ok ( false ) ,
278
+ Scalar :: Bits { bits : 1 , size : 1 } => Ok ( true ) ,
261
279
_ => err ! ( InvalidBool ) ,
262
280
}
263
281
}
0 commit comments