@@ -14,7 +14,7 @@ use ty::layout::{HasDataLayout, Size};
14
14
use ty:: subst:: Substs ;
15
15
use hir:: def_id:: DefId ;
16
16
17
- use super :: { EvalResult , Pointer , PointerArithmetic , Allocation , AllocId , sign_extend} ;
17
+ use super :: { EvalResult , Pointer , PointerArithmetic , Allocation , AllocId , sign_extend, truncate } ;
18
18
19
19
/// Represents a constant value in Rust. Scalar and ScalarPair are optimizations which
20
20
/// matches the LocalValue optimizations for easy conversions between Value and ConstValue.
@@ -58,6 +58,7 @@ impl<'tcx> ConstValue<'tcx> {
58
58
self . try_to_scalar ( ) ?. to_ptr ( ) . ok ( )
59
59
}
60
60
61
+ #[ inline]
61
62
pub fn new_slice (
62
63
val : Scalar ,
63
64
len : u64 ,
@@ -69,23 +70,27 @@ impl<'tcx> ConstValue<'tcx> {
69
70
} . into ( ) )
70
71
}
71
72
73
+ #[ inline]
72
74
pub fn new_dyn_trait ( val : Scalar , vtable : Pointer ) -> Self {
73
75
ConstValue :: ScalarPair ( val, Scalar :: Ptr ( vtable) . into ( ) )
74
76
}
75
77
}
76
78
77
79
impl < ' tcx > Scalar {
80
+ #[ inline]
78
81
pub fn ptr_null ( cx : impl HasDataLayout ) -> Self {
79
82
Scalar :: Bits {
80
83
bits : 0 ,
81
84
size : cx. data_layout ( ) . pointer_size . bytes ( ) as u8 ,
82
85
}
83
86
}
84
87
88
+ #[ inline]
85
89
pub fn zst ( ) -> Self {
86
90
Scalar :: Bits { bits : 0 , size : 0 }
87
91
}
88
92
93
+ #[ inline]
89
94
pub fn ptr_signed_offset ( self , i : i64 , cx : impl HasDataLayout ) -> EvalResult < ' tcx , Self > {
90
95
let layout = cx. data_layout ( ) ;
91
96
match self {
@@ -100,6 +105,7 @@ impl<'tcx> Scalar {
100
105
}
101
106
}
102
107
108
+ #[ inline]
103
109
pub fn ptr_offset ( self , i : Size , cx : impl HasDataLayout ) -> EvalResult < ' tcx , Self > {
104
110
let layout = cx. data_layout ( ) ;
105
111
match self {
@@ -114,6 +120,7 @@ impl<'tcx> Scalar {
114
120
}
115
121
}
116
122
123
+ #[ inline]
117
124
pub fn ptr_wrapping_signed_offset ( self , i : i64 , cx : impl HasDataLayout ) -> Self {
118
125
let layout = cx. data_layout ( ) ;
119
126
match self {
@@ -128,6 +135,7 @@ impl<'tcx> Scalar {
128
135
}
129
136
}
130
137
138
+ #[ inline]
131
139
pub fn is_null_ptr ( self , cx : impl HasDataLayout ) -> bool {
132
140
match self {
133
141
Scalar :: Bits { bits, size } => {
@@ -138,14 +146,53 @@ impl<'tcx> Scalar {
138
146
}
139
147
}
140
148
149
+ #[ inline]
150
+ pub fn is_null ( self ) -> bool {
151
+ match self {
152
+ Scalar :: Bits { bits, .. } => bits == 0 ,
153
+ Scalar :: Ptr ( _) => false
154
+ }
155
+ }
156
+
157
+ #[ inline]
141
158
pub fn from_bool ( b : bool ) -> Self {
142
159
Scalar :: Bits { bits : b as u128 , size : 1 }
143
160
}
144
161
162
+ #[ inline]
145
163
pub fn from_char ( c : char ) -> Self {
146
164
Scalar :: Bits { bits : c as u128 , size : 4 }
147
165
}
148
166
167
+ #[ inline]
168
+ pub fn from_uint ( i : impl Into < u128 > , size : Size ) -> Self {
169
+ let i = i. into ( ) ;
170
+ debug_assert_eq ! ( truncate( i, size) , i,
171
+ "Unsigned value {} does not fit in {} bits" , i, size. bits( ) ) ;
172
+ Scalar :: Bits { bits : i, size : size. bytes ( ) as u8 }
173
+ }
174
+
175
+ #[ inline]
176
+ pub fn from_int ( i : impl Into < i128 > , size : Size ) -> Self {
177
+ let i = i. into ( ) ;
178
+ // `into` performed sign extension, we have to truncate
179
+ let truncated = truncate ( i as u128 , size) ;
180
+ debug_assert_eq ! ( sign_extend( truncated, size) as i128 , i,
181
+ "Signed value {} does not fit in {} bits" , i, size. bits( ) ) ;
182
+ Scalar :: Bits { bits : truncated, size : size. bytes ( ) as u8 }
183
+ }
184
+
185
+ #[ inline]
186
+ pub fn from_f32 ( f : f32 ) -> Self {
187
+ Scalar :: Bits { bits : f. to_bits ( ) as u128 , size : 4 }
188
+ }
189
+
190
+ #[ inline]
191
+ pub fn from_f64 ( f : f64 ) -> Self {
192
+ Scalar :: Bits { bits : f. to_bits ( ) as u128 , size : 8 }
193
+ }
194
+
195
+ #[ inline]
149
196
pub fn to_bits ( self , target_size : Size ) -> EvalResult < ' tcx , u128 > {
150
197
match self {
151
198
Scalar :: Bits { bits, size } => {
@@ -157,6 +204,7 @@ impl<'tcx> Scalar {
157
204
}
158
205
}
159
206
207
+ #[ inline]
160
208
pub fn to_ptr ( self ) -> EvalResult < ' tcx , Pointer > {
161
209
match self {
162
210
Scalar :: Bits { bits : 0 , .. } => err ! ( InvalidNullPointerUsage ) ,
@@ -165,13 +213,15 @@ impl<'tcx> Scalar {
165
213
}
166
214
}
167
215
216
+ #[ inline]
168
217
pub fn is_bits ( self ) -> bool {
169
218
match self {
170
219
Scalar :: Bits { .. } => true ,
171
220
_ => false ,
172
221
}
173
222
}
174
223
224
+ #[ inline]
175
225
pub fn is_ptr ( self ) -> bool {
176
226
match self {
177
227
Scalar :: Ptr ( _) => true ,
@@ -209,6 +259,13 @@ impl<'tcx> Scalar {
209
259
Ok ( b as u32 )
210
260
}
211
261
262
+ pub fn to_u64 ( self ) -> EvalResult < ' static , u64 > {
263
+ let sz = Size :: from_bits ( 64 ) ;
264
+ let b = self . to_bits ( sz) ?;
265
+ assert_eq ! ( b as u64 as u128 , b) ;
266
+ Ok ( b as u64 )
267
+ }
268
+
212
269
pub fn to_usize ( self , cx : impl HasDataLayout ) -> EvalResult < ' static , u64 > {
213
270
let b = self . to_bits ( cx. data_layout ( ) . pointer_size ) ?;
214
271
assert_eq ! ( b as u64 as u128 , b) ;
@@ -231,12 +288,30 @@ impl<'tcx> Scalar {
231
288
Ok ( b as i32 )
232
289
}
233
290
291
+ pub fn to_i64 ( self ) -> EvalResult < ' static , i64 > {
292
+ let sz = Size :: from_bits ( 64 ) ;
293
+ let b = self . to_bits ( sz) ?;
294
+ let b = sign_extend ( b, sz) as i128 ;
295
+ assert_eq ! ( b as i64 as i128 , b) ;
296
+ Ok ( b as i64 )
297
+ }
298
+
234
299
pub fn to_isize ( self , cx : impl HasDataLayout ) -> EvalResult < ' static , i64 > {
235
300
let b = self . to_bits ( cx. data_layout ( ) . pointer_size ) ?;
236
301
let b = sign_extend ( b, cx. data_layout ( ) . pointer_size ) as i128 ;
237
302
assert_eq ! ( b as i64 as i128 , b) ;
238
303
Ok ( b as i64 )
239
304
}
305
+
306
+ #[ inline]
307
+ pub fn to_f32 ( self ) -> EvalResult < ' static , f32 > {
308
+ Ok ( f32:: from_bits ( self . to_u32 ( ) ?) )
309
+ }
310
+
311
+ #[ inline]
312
+ pub fn to_f64 ( self ) -> EvalResult < ' static , f64 > {
313
+ Ok ( f64:: from_bits ( self . to_u64 ( ) ?) )
314
+ }
240
315
}
241
316
242
317
impl From < Pointer > for Scalar {
@@ -308,6 +383,16 @@ impl<'tcx> ScalarMaybeUndef {
308
383
self . not_undef ( ) ?. to_char ( )
309
384
}
310
385
386
+ #[ inline( always) ]
387
+ pub fn to_f32 ( self ) -> EvalResult < ' tcx , f32 > {
388
+ self . not_undef ( ) ?. to_f32 ( )
389
+ }
390
+
391
+ #[ inline( always) ]
392
+ pub fn to_f64 ( self ) -> EvalResult < ' tcx , f64 > {
393
+ self . not_undef ( ) ?. to_f64 ( )
394
+ }
395
+
311
396
#[ inline( always) ]
312
397
pub fn to_u8 ( self ) -> EvalResult < ' tcx , u8 > {
313
398
self . not_undef ( ) ?. to_u8 ( )
@@ -318,6 +403,11 @@ impl<'tcx> ScalarMaybeUndef {
318
403
self . not_undef ( ) ?. to_u32 ( )
319
404
}
320
405
406
+ #[ inline( always) ]
407
+ pub fn to_u64 ( self ) -> EvalResult < ' tcx , u64 > {
408
+ self . not_undef ( ) ?. to_u64 ( )
409
+ }
410
+
321
411
#[ inline( always) ]
322
412
pub fn to_usize ( self , cx : impl HasDataLayout ) -> EvalResult < ' tcx , u64 > {
323
413
self . not_undef ( ) ?. to_usize ( cx)
@@ -333,6 +423,11 @@ impl<'tcx> ScalarMaybeUndef {
333
423
self . not_undef ( ) ?. to_i32 ( )
334
424
}
335
425
426
+ #[ inline( always) ]
427
+ pub fn to_i64 ( self ) -> EvalResult < ' tcx , i64 > {
428
+ self . not_undef ( ) ?. to_i64 ( )
429
+ }
430
+
336
431
#[ inline( always) ]
337
432
pub fn to_isize ( self , cx : impl HasDataLayout ) -> EvalResult < ' tcx , i64 > {
338
433
self . not_undef ( ) ?. to_isize ( cx)
0 commit comments