@@ -11,7 +11,10 @@ use rustc::mir::interpret::{
11
11
ConstValue , Pointer , Scalar ,
12
12
EvalResult , EvalErrorKind ,
13
13
} ;
14
- use super :: { EvalContext , Machine , MemPlace , MPlaceTy , MemoryKind } ;
14
+ use super :: {
15
+ EvalContext , Machine , AllocMap , Allocation , AllocationExtra ,
16
+ MemPlace , MPlaceTy , PlaceTy , Place , MemoryKind ,
17
+ } ;
15
18
pub use rustc:: mir:: interpret:: ScalarMaybeUndef ;
16
19
17
20
/// A `Value` represents a single immediate self-contained Rust value.
@@ -41,6 +44,11 @@ impl Immediate {
41
44
}
42
45
43
46
impl < ' tcx , Tag > Immediate < Tag > {
47
+ #[ inline]
48
+ pub fn from_scalar ( val : Scalar < Tag > ) -> Self {
49
+ Immediate :: Scalar ( ScalarMaybeUndef :: Scalar ( val) )
50
+ }
51
+
44
52
#[ inline]
45
53
pub fn erase_tag ( self ) -> Immediate
46
54
{
@@ -112,15 +120,15 @@ impl<'tcx, Tag> Immediate<Tag> {
112
120
// as input for binary and cast operations.
113
121
#[ derive( Copy , Clone , Debug ) ]
114
122
pub struct ImmTy < ' tcx , Tag =( ) > {
115
- immediate : Immediate < Tag > ,
123
+ pub imm : Immediate < Tag > ,
116
124
pub layout : TyLayout < ' tcx > ,
117
125
}
118
126
119
127
impl < ' tcx , Tag > :: std:: ops:: Deref for ImmTy < ' tcx , Tag > {
120
128
type Target = Immediate < Tag > ;
121
129
#[ inline( always) ]
122
130
fn deref ( & self ) -> & Immediate < Tag > {
123
- & self . immediate
131
+ & self . imm
124
132
}
125
133
}
126
134
@@ -180,7 +188,7 @@ impl<Tag> Operand<Tag> {
180
188
181
189
#[ derive( Copy , Clone , Debug , Hash , PartialEq , Eq ) ]
182
190
pub struct OpTy < ' tcx , Tag =( ) > {
183
- crate op : Operand < Tag > , // ideally we'd make this private, but const_prop needs this
191
+ op : Operand < Tag > ,
184
192
pub layout : TyLayout < ' tcx > ,
185
193
}
186
194
@@ -206,12 +214,25 @@ impl<'tcx, Tag> From<ImmTy<'tcx, Tag>> for OpTy<'tcx, Tag> {
206
214
#[ inline( always) ]
207
215
fn from ( val : ImmTy < ' tcx , Tag > ) -> Self {
208
216
OpTy {
209
- op : Operand :: Immediate ( val. immediate ) ,
217
+ op : Operand :: Immediate ( val. imm ) ,
210
218
layout : val. layout
211
219
}
212
220
}
213
221
}
214
222
223
+ impl < ' tcx , Tag : Copy > ImmTy < ' tcx , Tag >
224
+ {
225
+ #[ inline]
226
+ pub fn from_scalar ( val : Scalar < Tag > , layout : TyLayout < ' tcx > ) -> Self {
227
+ ImmTy { imm : Immediate :: from_scalar ( val) , layout }
228
+ }
229
+
230
+ #[ inline]
231
+ pub fn to_bits ( self ) -> EvalResult < ' tcx , u128 > {
232
+ self . to_scalar ( ) ?. to_bits ( self . layout . size )
233
+ }
234
+ }
235
+
215
236
impl < ' tcx , Tag > OpTy < ' tcx , Tag >
216
237
{
217
238
#[ inline]
@@ -324,8 +345,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
324
345
& self ,
325
346
op : OpTy < ' tcx , M :: PointerTag >
326
347
) -> EvalResult < ' tcx , ImmTy < ' tcx , M :: PointerTag > > {
327
- if let Ok ( immediate ) = self . try_read_immediate ( op) ? {
328
- Ok ( ImmTy { immediate , layout : op. layout } )
348
+ if let Ok ( imm ) = self . try_read_immediate ( op) ? {
349
+ Ok ( ImmTy { imm , layout : op. layout } )
329
350
} else {
330
351
bug ! ( "primitive read failed for type: {:?}" , op. layout. ty) ;
331
352
}
@@ -469,6 +490,22 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
469
490
Ok ( OpTy { op, layout } )
470
491
}
471
492
493
+ /// Every place can be read from, so we can turm them into an operand
494
+ #[ inline( always) ]
495
+ pub fn place_to_op (
496
+ & self ,
497
+ place : PlaceTy < ' tcx , M :: PointerTag >
498
+ ) -> EvalResult < ' tcx , OpTy < ' tcx , M :: PointerTag > > {
499
+ let op = match * place {
500
+ Place :: Ptr ( mplace) => {
501
+ Operand :: Indirect ( mplace)
502
+ }
503
+ Place :: Local { frame, local } =>
504
+ * self . stack [ frame] . locals [ local] . access ( ) ?
505
+ } ;
506
+ Ok ( OpTy { op, layout : place. layout } )
507
+ }
508
+
472
509
// Evaluate a place with the goal of reading from it. This lets us sometimes
473
510
// avoid allocations.
474
511
fn eval_place_to_op (
@@ -531,10 +568,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
531
568
. collect ( )
532
569
}
533
570
534
- // Used when miri runs into a constant, and by CTFE.
535
- // FIXME: CTFE should use allocations, then we can make this private (embed it into
536
- // `eval_operand`, ideally).
537
- pub ( crate ) fn const_value_to_op (
571
+ // Used when Miri runs into a constant, and (indirectly through lazy_const_to_op) by CTFE.
572
+ fn const_value_to_op (
538
573
& self ,
539
574
val : ty:: LazyConst < ' tcx > ,
540
575
) -> EvalResult < ' tcx , Operand < M :: PointerTag > > {
@@ -666,3 +701,21 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
666
701
}
667
702
668
703
}
704
+
705
+ impl < ' a , ' mir , ' tcx , M > EvalContext < ' a , ' mir , ' tcx , M >
706
+ where
707
+ M : Machine < ' a , ' mir , ' tcx , PointerTag =( ) > ,
708
+ // FIXME: Working around https://github.com/rust-lang/rust/issues/24159
709
+ M :: MemoryMap : AllocMap < AllocId , ( MemoryKind < M :: MemoryKinds > , Allocation < ( ) , M :: AllocExtra > ) > ,
710
+ M :: AllocExtra : AllocationExtra < ( ) , M :: MemoryExtra > ,
711
+ {
712
+ // FIXME: CTFE should use allocations, then we can remove this.
713
+ pub ( crate ) fn lazy_const_to_op (
714
+ & self ,
715
+ cnst : ty:: LazyConst < ' tcx > ,
716
+ ty : ty:: Ty < ' tcx > ,
717
+ ) -> EvalResult < ' tcx , OpTy < ' tcx > > {
718
+ let op = self . const_value_to_op ( cnst) ?;
719
+ Ok ( OpTy { op, layout : self . layout_of ( ty) ? } )
720
+ }
721
+ }
0 commit comments