@@ -128,7 +128,11 @@ pub enum Scalar<Tag = AllocId> {
128128 /// A pointer into an `Allocation`. An `Allocation` in the `memory` module has a list of
129129 /// relocations, but a `Scalar` is only large enough to contain one, so we just represent the
130130 /// 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 ) ,
132136}
133137
134138#[ cfg( all( target_arch = "x86_64" , target_pointer_width = "64" ) ) ]
@@ -139,7 +143,7 @@ pub enum Scalar<Tag = AllocId> {
139143impl < Tag : Provenance > fmt:: Debug for Scalar < Tag > {
140144 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
141145 match self {
142- Scalar :: Ptr ( ptr) => write ! ( f, "{:?}" , ptr) ,
146+ Scalar :: Ptr ( ptr, _size ) => write ! ( f, "{:?}" , ptr) ,
143147 Scalar :: Int ( int) => write ! ( f, "{:?}" , int) ,
144148 }
145149 }
@@ -148,7 +152,7 @@ impl<Tag: Provenance> fmt::Debug for Scalar<Tag> {
148152impl < Tag : Provenance > fmt:: Display for Scalar < Tag > {
149153 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
150154 match self {
151- Scalar :: Ptr ( ptr) => write ! ( f, "pointer to {:?}" , ptr) ,
155+ Scalar :: Ptr ( ptr, _size ) => write ! ( f, "pointer to {:?}" , ptr) ,
152156 Scalar :: Int ( int) => write ! ( f, "{:?}" , int) ,
153157 }
154158 }
@@ -168,13 +172,6 @@ impl<Tag> From<Double> for Scalar<Tag> {
168172 }
169173}
170174
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-
178175impl < Tag > From < ScalarInt > for Scalar < Tag > {
179176 #[ inline( always) ]
180177 fn from ( ptr : ScalarInt ) -> Self {
@@ -185,21 +182,26 @@ impl<Tag> From<ScalarInt> for Scalar<Tag> {
185182impl < ' tcx , Tag > Scalar < Tag > {
186183 pub const ZST : Self = Scalar :: Int ( ScalarInt :: ZST ) ;
187184
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 ( ) )
191188 }
192189
193190 /// Create a Scalar from a pointer with an `Option<_>` tag (where `None` represents a plain integer).
194191 pub fn from_maybe_pointer ( ptr : Pointer < Option < Tag > > , cx : & impl HasDataLayout ) -> Self {
195192 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 ) ,
197194 ( None , offset) => {
198195 Scalar :: Int ( ScalarInt :: try_from_uint ( offset. bytes ( ) , cx. pointer_size ( ) ) . unwrap ( ) )
199196 }
200197 }
201198 }
202199
200+ #[ inline]
201+ pub fn null_ptr ( cx : & impl HasDataLayout ) -> Self {
202+ Scalar :: Int ( ScalarInt :: null ( cx. pointer_size ( ) ) )
203+ }
204+
203205 #[ inline( always) ]
204206 fn ptr_op (
205207 self ,
@@ -209,7 +211,10 @@ impl<'tcx, Tag> Scalar<Tag> {
209211 ) -> InterpResult < ' tcx , Self > {
210212 match self {
211213 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+ }
213218 }
214219 }
215220
@@ -334,59 +339,18 @@ impl<'tcx, Tag> Scalar<Tag> {
334339 /// This is almost certainly not the method you want! You should dispatch on the type
335340 /// and use `to_{u8,u16,...}`/`scalar_to_ptr` to perform ptr-to-int / int-to-ptr casts as needed.
336341 ///
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.
339343 #[ 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 > > {
345345 assert_ne ! ( target_size. bytes( ) , 0 , "you should never look at the bits of a ZST" ) ;
346346 match self {
347347 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 ) ) ;
350350 Err ( ptr)
351351 }
352352 }
353353 }
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- }
390354}
391355
392356impl < ' tcx , Tag : Provenance > Scalar < Tag > {
@@ -396,7 +360,7 @@ impl<'tcx, Tag: Provenance> Scalar<Tag> {
396360 #[ inline]
397361 pub fn erase_for_fmt ( self ) -> Scalar {
398362 match self {
399- Scalar :: Ptr ( ptr) => Scalar :: Ptr ( ptr. erase_for_fmt ( ) ) ,
363+ Scalar :: Ptr ( ptr, sz ) => Scalar :: Ptr ( ptr. erase_for_fmt ( ) , sz ) ,
400364 Scalar :: Int ( int) => Scalar :: Int ( int) ,
401365 }
402366 }
@@ -405,25 +369,45 @@ impl<'tcx, Tag: Provenance> Scalar<Tag> {
405369 /// likely want to use instead.
406370 ///
407371 /// 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+
408393 #[ inline]
409394 pub fn to_bits ( self , target_size : Size ) -> InterpResult < ' tcx , u128 > {
410395 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| {
413400 err_ub ! ( ScalarSizeMismatch {
414401 target_size: target_size. bytes( ) ,
415402 data_size: size. bytes( ) ,
416403 } )
417404 . 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 ( )
427411 }
428412
429413 pub fn to_bool ( self ) -> InterpResult < ' tcx , bool > {
@@ -547,13 +531,6 @@ impl<Tag> From<Scalar<Tag>> for ScalarMaybeUninit<Tag> {
547531 }
548532}
549533
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-
557534// We want the `Debug` output to be readable as it is used by `derive(Debug)` for
558535// all the Miri types.
559536impl < Tag : Provenance > fmt:: Debug for ScalarMaybeUninit < Tag > {
@@ -575,6 +552,16 @@ impl<Tag: Provenance> fmt::Display for ScalarMaybeUninit<Tag> {
575552}
576553
577554impl < 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+
578565 #[ inline]
579566 pub fn check_init ( self ) -> InterpResult < ' static , Scalar < Tag > > {
580567 match self {
0 commit comments