@@ -128,7 +128,11 @@ pub enum Scalar<Tag = AllocId> {
128
128
/// A pointer into an `Allocation`. An `Allocation` in the `memory` module has a list of
129
129
/// relocations, but a `Scalar` is only large enough to contain one, so we just represent the
130
130
/// relocation and its associated offset together as a `Pointer` here.
131
- Ptr ( Pointer < Tag > ) ,
131
+ ///
132
+ /// We also store the size of the pointer, such that a `Scalar` always knows how big it is.
133
+ /// The size is always the pointer size of the current target, but this is not information
134
+ /// that we always have readily available.
135
+ Ptr ( Pointer < Tag > , u8 ) ,
132
136
}
133
137
134
138
#[ cfg( all( target_arch = "x86_64" , target_pointer_width = "64" ) ) ]
@@ -139,7 +143,7 @@ pub enum Scalar<Tag = AllocId> {
139
143
impl < Tag : Provenance > fmt:: Debug for Scalar < Tag > {
140
144
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
141
145
match self {
142
- Scalar :: Ptr ( ptr) => write ! ( f, "{:?}" , ptr) ,
146
+ Scalar :: Ptr ( ptr, _size ) => write ! ( f, "{:?}" , ptr) ,
143
147
Scalar :: Int ( int) => write ! ( f, "{:?}" , int) ,
144
148
}
145
149
}
@@ -148,7 +152,7 @@ impl<Tag: Provenance> fmt::Debug for Scalar<Tag> {
148
152
impl < Tag : Provenance > fmt:: Display for Scalar < Tag > {
149
153
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
150
154
match self {
151
- Scalar :: Ptr ( ptr) => write ! ( f, "pointer to {:?}" , ptr) ,
155
+ Scalar :: Ptr ( ptr, _size ) => write ! ( f, "pointer to {:?}" , ptr) ,
152
156
Scalar :: Int ( int) => write ! ( f, "{:?}" , int) ,
153
157
}
154
158
}
@@ -168,13 +172,6 @@ impl<Tag> From<Double> for Scalar<Tag> {
168
172
}
169
173
}
170
174
171
- impl < Tag > From < Pointer < Tag > > for Scalar < Tag > {
172
- #[ inline( always) ]
173
- fn from ( ptr : Pointer < Tag > ) -> Self {
174
- Scalar :: Ptr ( ptr)
175
- }
176
- }
177
-
178
175
impl < Tag > From < ScalarInt > for Scalar < Tag > {
179
176
#[ inline( always) ]
180
177
fn from ( ptr : ScalarInt ) -> Self {
@@ -185,21 +182,26 @@ impl<Tag> From<ScalarInt> for Scalar<Tag> {
185
182
impl < ' tcx , Tag > Scalar < Tag > {
186
183
pub const ZST : Self = Scalar :: Int ( ScalarInt :: ZST ) ;
187
184
188
- #[ inline]
189
- pub fn null_ptr ( cx : & impl HasDataLayout ) -> Self {
190
- Scalar :: Int ( ScalarInt :: null ( cx. data_layout ( ) . pointer_size ) )
185
+ #[ inline( always ) ]
186
+ pub fn from_pointer ( ptr : Pointer < Tag > , cx : & impl HasDataLayout ) -> Self {
187
+ Scalar :: Ptr ( ptr , u8 :: try_from ( cx. pointer_size ( ) . bytes ( ) ) . unwrap ( ) )
191
188
}
192
189
193
190
/// Create a Scalar from a pointer with an `Option<_>` tag (where `None` represents a plain integer).
194
191
pub fn from_maybe_pointer ( ptr : Pointer < Option < Tag > > , cx : & impl HasDataLayout ) -> Self {
195
192
match ptr. into_parts ( ) {
196
- ( Some ( tag) , offset) => Scalar :: Ptr ( Pointer :: new ( tag, offset) ) ,
193
+ ( Some ( tag) , offset) => Scalar :: from_pointer ( Pointer :: new ( tag, offset) , cx ) ,
197
194
( None , offset) => {
198
195
Scalar :: Int ( ScalarInt :: try_from_uint ( offset. bytes ( ) , cx. pointer_size ( ) ) . unwrap ( ) )
199
196
}
200
197
}
201
198
}
202
199
200
+ #[ inline]
201
+ pub fn null_ptr ( cx : & impl HasDataLayout ) -> Self {
202
+ Scalar :: Int ( ScalarInt :: null ( cx. pointer_size ( ) ) )
203
+ }
204
+
203
205
#[ inline( always) ]
204
206
fn ptr_op (
205
207
self ,
@@ -209,7 +211,10 @@ impl<'tcx, Tag> Scalar<Tag> {
209
211
) -> InterpResult < ' tcx , Self > {
210
212
match self {
211
213
Scalar :: Int ( int) => Ok ( Scalar :: Int ( int. ptr_sized_op ( dl, f_int) ?) ) ,
212
- Scalar :: Ptr ( ptr) => Ok ( Scalar :: Ptr ( f_ptr ( ptr) ?) ) ,
214
+ Scalar :: Ptr ( ptr, sz) => {
215
+ debug_assert_eq ! ( u64 :: from( sz) , dl. pointer_size( ) . bytes( ) ) ;
216
+ Ok ( Scalar :: Ptr ( f_ptr ( ptr) ?, sz) )
217
+ }
213
218
}
214
219
}
215
220
@@ -334,59 +339,18 @@ impl<'tcx, Tag> Scalar<Tag> {
334
339
/// This is almost certainly not the method you want! You should dispatch on the type
335
340
/// and use `to_{u8,u16,...}`/`scalar_to_ptr` to perform ptr-to-int / int-to-ptr casts as needed.
336
341
///
337
- /// This method only exists for the benefit of low-level memory operations
338
- /// as well as the implementation of the above methods.
342
+ /// This method only exists for the benefit of low-level memory operations.
339
343
#[ inline]
340
- pub fn to_bits_or_ptr (
341
- self ,
342
- target_size : Size ,
343
- cx : & impl HasDataLayout ,
344
- ) -> Result < u128 , Pointer < Tag > > {
344
+ pub fn to_bits_or_ptr ( self , target_size : Size ) -> Result < u128 , Pointer < Tag > > {
345
345
assert_ne ! ( target_size. bytes( ) , 0 , "you should never look at the bits of a ZST" ) ;
346
346
match self {
347
347
Scalar :: Int ( int) => Ok ( int. assert_bits ( target_size) ) ,
348
- Scalar :: Ptr ( ptr) => {
349
- assert_eq ! ( target_size, cx . data_layout ( ) . pointer_size ) ;
348
+ Scalar :: Ptr ( ptr, sz ) => {
349
+ assert_eq ! ( target_size. bytes ( ) , u64 :: from ( sz ) ) ;
350
350
Err ( ptr)
351
351
}
352
352
}
353
353
}
354
-
355
- /// Do not call this method! It does not do ptr-to-int casts when needed.
356
- #[ inline( always) ]
357
- pub fn assert_bits ( self , target_size : Size ) -> u128 {
358
- self . assert_int ( ) . assert_bits ( target_size)
359
- }
360
-
361
- /// Do not call this method! It does not do ptr-to-int casts when needed.
362
- #[ inline]
363
- pub fn assert_int ( self ) -> ScalarInt {
364
- match self {
365
- Scalar :: Ptr ( _) => bug ! ( "expected an int but got an abstract pointer" ) ,
366
- Scalar :: Int ( int) => int,
367
- }
368
- }
369
-
370
- /// Do not call this method! It does not do int-to-ptr casts when needed.
371
- #[ inline]
372
- pub fn assert_ptr ( self ) -> Pointer < Tag > {
373
- match self {
374
- Scalar :: Ptr ( p) => p,
375
- Scalar :: Int { .. } => bug ! ( "expected a Pointer but got Raw bits" ) ,
376
- }
377
- }
378
-
379
- /// Do not call this method! Dispatch based on the type instead.
380
- #[ inline]
381
- pub fn is_bits ( self ) -> bool {
382
- matches ! ( self , Scalar :: Int { .. } )
383
- }
384
-
385
- /// Do not call this method! Dispatch based on the type instead.
386
- #[ inline]
387
- pub fn is_ptr ( self ) -> bool {
388
- matches ! ( self , Scalar :: Ptr ( _) )
389
- }
390
354
}
391
355
392
356
impl < ' tcx , Tag : Provenance > Scalar < Tag > {
@@ -396,7 +360,7 @@ impl<'tcx, Tag: Provenance> Scalar<Tag> {
396
360
#[ inline]
397
361
pub fn erase_for_fmt ( self ) -> Scalar {
398
362
match self {
399
- Scalar :: Ptr ( ptr) => Scalar :: Ptr ( ptr. erase_for_fmt ( ) ) ,
363
+ Scalar :: Ptr ( ptr, sz ) => Scalar :: Ptr ( ptr. erase_for_fmt ( ) , sz ) ,
400
364
Scalar :: Int ( int) => Scalar :: Int ( int) ,
401
365
}
402
366
}
@@ -405,25 +369,45 @@ impl<'tcx, Tag: Provenance> Scalar<Tag> {
405
369
/// likely want to use instead.
406
370
///
407
371
/// Will perform ptr-to-int casts if needed and possible.
372
+ #[ inline]
373
+ pub fn try_to_int ( self ) -> Option < ScalarInt > {
374
+ match self {
375
+ Scalar :: Int ( int) => Some ( int) ,
376
+ Scalar :: Ptr ( ptr, sz) => {
377
+ if Tag :: OFFSET_IS_ADDR {
378
+ Some (
379
+ ScalarInt :: try_from_uint ( ptr. offset . bytes ( ) , Size :: from_bytes ( sz) ) . unwrap ( ) ,
380
+ )
381
+ } else {
382
+ None
383
+ }
384
+ }
385
+ }
386
+ }
387
+
388
+ #[ inline( always) ]
389
+ pub fn assert_int ( self ) -> ScalarInt {
390
+ self . try_to_int ( ) . unwrap ( )
391
+ }
392
+
408
393
#[ inline]
409
394
pub fn to_bits ( self , target_size : Size ) -> InterpResult < ' tcx , u128 > {
410
395
assert_ne ! ( target_size. bytes( ) , 0 , "you should never look at the bits of a ZST" ) ;
411
- match self {
412
- Scalar :: Int ( int) => int. to_bits ( target_size) . map_err ( |size| {
396
+ self . try_to_int ( )
397
+ . ok_or_else ( || err_unsup ! ( ReadPointerAsBytes ) ) ?
398
+ . to_bits ( target_size)
399
+ . map_err ( |size| {
413
400
err_ub ! ( ScalarSizeMismatch {
414
401
target_size: target_size. bytes( ) ,
415
402
data_size: size. bytes( ) ,
416
403
} )
417
404
. into ( )
418
- } ) ,
419
- Scalar :: Ptr ( ptr) => {
420
- if Tag :: OFFSET_IS_ADDR {
421
- Ok ( ptr. offset . bytes ( ) . into ( ) )
422
- } else {
423
- throw_unsup ! ( ReadPointerAsBytes )
424
- }
425
- }
426
- }
405
+ } )
406
+ }
407
+
408
+ #[ inline( always) ]
409
+ pub fn assert_bits ( self , target_size : Size ) -> u128 {
410
+ self . to_bits ( target_size) . unwrap ( )
427
411
}
428
412
429
413
pub fn to_bool ( self ) -> InterpResult < ' tcx , bool > {
@@ -547,13 +531,6 @@ impl<Tag> From<Scalar<Tag>> for ScalarMaybeUninit<Tag> {
547
531
}
548
532
}
549
533
550
- impl < Tag > From < Pointer < Tag > > for ScalarMaybeUninit < Tag > {
551
- #[ inline( always) ]
552
- fn from ( s : Pointer < Tag > ) -> Self {
553
- ScalarMaybeUninit :: Scalar ( s. into ( ) )
554
- }
555
- }
556
-
557
534
// We want the `Debug` output to be readable as it is used by `derive(Debug)` for
558
535
// all the Miri types.
559
536
impl < Tag : Provenance > fmt:: Debug for ScalarMaybeUninit < Tag > {
@@ -575,6 +552,16 @@ impl<Tag: Provenance> fmt::Display for ScalarMaybeUninit<Tag> {
575
552
}
576
553
577
554
impl < Tag > ScalarMaybeUninit < Tag > {
555
+ #[ inline]
556
+ pub fn from_pointer ( ptr : Pointer < Tag > , cx : & impl HasDataLayout ) -> Self {
557
+ ScalarMaybeUninit :: Scalar ( Scalar :: from_pointer ( ptr, cx) )
558
+ }
559
+
560
+ #[ inline]
561
+ pub fn from_maybe_pointer ( ptr : Pointer < Option < Tag > > , cx : & impl HasDataLayout ) -> Self {
562
+ ScalarMaybeUninit :: Scalar ( Scalar :: from_maybe_pointer ( ptr, cx) )
563
+ }
564
+
578
565
#[ inline]
579
566
pub fn check_init ( self ) -> InterpResult < ' static , Scalar < Tag > > {
580
567
match self {
0 commit comments