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