11#![ allow( unknown_lints) ]
22
3- use ty:: layout:: { Align , HasDataLayout , Size } ;
4- use ty;
3+ use ty:: layout:: { HasDataLayout , Size } ;
54use ty:: subst:: Substs ;
65use hir:: def_id:: DefId ;
76
87use super :: { EvalResult , Pointer , PointerArithmetic , Allocation } ;
98
109/// 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.
1211#[ derive( Copy , Clone , Debug , Eq , PartialEq , PartialOrd , Ord , RustcEncodable , RustcDecodable , Hash ) ]
1312pub enum ConstValue < ' tcx > {
1413 /// Never returned from the `const_eval` query, but the HIR contains these frequently in order
1514 /// to allow HIR creation to happen for everything before needing to be able to run constant
1615 /// evaluation
1716 Unevaluated ( DefId , & ' tcx Substs < ' tcx > ) ,
1817 /// 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`
1920 Scalar ( Scalar ) ,
2021 /// Used only for types with layout::abi::ScalarPair
2122 ///
@@ -26,25 +27,6 @@ pub enum ConstValue<'tcx> {
2627}
2728
2829impl < ' 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-
4830 #[ inline]
4931 pub fn try_to_scalar ( & self ) -> Option < Scalar > {
5032 match * self {
@@ -56,58 +38,44 @@ impl<'tcx> ConstValue<'tcx> {
5638 }
5739
5840 #[ inline]
59- pub fn to_bits ( & self , size : Size ) -> Option < u128 > {
41+ pub fn try_to_bits ( & self , size : Size ) -> Option < u128 > {
6042 self . try_to_scalar ( ) ?. to_bits ( size) . ok ( )
6143 }
6244
6345 #[ inline]
64- pub fn to_ptr ( & self ) -> Option < Pointer > {
46+ pub fn try_to_ptr ( & self ) -> Option < Pointer > {
6547 self . try_to_scalar ( ) ?. to_ptr ( ) . ok ( )
6648 }
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- }
8449
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 ( ) )
8859 }
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 ( ) )
9163 }
9264}
9365
9466impl < ' tcx > Scalar {
95- pub fn ptr_null < C : HasDataLayout > ( cx : C ) -> Self {
67+ pub fn ptr_null ( cx : impl HasDataLayout ) -> Self {
9668 Scalar :: Bits {
9769 bits : 0 ,
9870 size : cx. data_layout ( ) . pointer_size . bytes ( ) as u8 ,
9971 }
10072 }
10173
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 }
10876 }
10977
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 > {
11179 let layout = cx. data_layout ( ) ;
11280 match self {
11381 Scalar :: Bits { bits, size } => {
@@ -121,7 +89,7 @@ impl<'tcx> Scalar {
12189 }
12290 }
12391
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 > {
12593 let layout = cx. data_layout ( ) ;
12694 match self {
12795 Scalar :: Bits { bits, size } => {
@@ -135,7 +103,7 @@ impl<'tcx> Scalar {
135103 }
136104 }
137105
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 {
139107 let layout = cx. data_layout ( ) ;
140108 match self {
141109 Scalar :: Bits { bits, size } => {
@@ -149,7 +117,7 @@ impl<'tcx> Scalar {
149117 }
150118 }
151119
152- pub fn is_null_ptr < C : HasDataLayout > ( self , cx : C ) -> bool {
120+ pub fn is_null_ptr ( self , cx : impl HasDataLayout ) -> bool {
153121 match self {
154122 Scalar :: Bits { bits, size } => {
155123 assert_eq ! ( size as u64 , cx. data_layout( ) . pointer_size. bytes( ) ) ;
@@ -159,8 +127,52 @@ impl<'tcx> Scalar {
159127 }
160128 }
161129
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+ }
164176 }
165177}
166178
@@ -202,81 +214,23 @@ impl From<Scalar> for ScalarMaybeUndef {
202214 }
203215}
204216
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 > {
207219 match self {
208220 ScalarMaybeUndef :: Scalar ( scalar) => Ok ( scalar) ,
209221 ScalarMaybeUndef :: Undef => err ! ( ReadUndefBytes ) ,
210222 }
211223 }
212224
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-
254225 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 ( )
266227 }
267228
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)
273231 }
274232
275233 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 ( )
281235 }
282236}
0 commit comments