@@ -19,9 +19,9 @@ use rustc_macros::HashStable;
1919use rustc_serialize:: { Decodable , Decoder , Encodable , Encoder } ;
2020
2121use super :: {
22- AllocId , BadBytesAccess , CtfeProvenance , InterpErrorKind , InterpResult , Pointer ,
23- PointerArithmetic , Provenance , ResourceExhaustionInfo , Scalar , ScalarSizeMismatch ,
24- UndefinedBehaviorInfo , UnsupportedOpInfo , interp_ok, read_target_uint, write_target_uint,
22+ AllocId , BadBytesAccess , CtfeProvenance , InterpErrorKind , InterpResult , Pointer , Provenance ,
23+ ResourceExhaustionInfo , Scalar , ScalarSizeMismatch , UndefinedBehaviorInfo , UnsupportedOpInfo ,
24+ interp_ok, read_target_uint, write_target_uint,
2525} ;
2626use crate :: ty;
2727
@@ -601,14 +601,13 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
601601 } ) ?;
602602 if !Prov :: OFFSET_IS_ADDR && !self . provenance . range_empty ( range, cx) {
603603 // Find the provenance.
604- let ( offset , _prov) = self
604+ let ( prov_range , _prov) = self
605605 . provenance
606- . range_ptrs_get ( range, cx)
607- . first ( )
608- . copied ( )
606+ . get_range ( range, cx)
607+ . next ( )
609608 . expect ( "there must be provenance somewhere here" ) ;
610- let start = offset . max ( range. start ) ; // the pointer might begin before `range`!
611- let end = ( offset + cx . pointer_size ( ) ) . min ( range. end ( ) ) ; // the pointer might end after `range`!
609+ let start = prov_range . start . max ( range. start ) ; // the pointer might begin before `range`!
610+ let end = prov_range . end ( ) . min ( range. end ( ) ) ; // the pointer might end after `range`!
612611 return Err ( AllocError :: ReadPointerAsInt ( Some ( BadBytesAccess {
613612 access : range,
614613 bad : AllocRange :: from ( start..end) ,
@@ -630,7 +629,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
630629 range : AllocRange ,
631630 ) -> & mut [ u8 ] {
632631 self . mark_init ( range, true ) ;
633- self . provenance . clear ( range, cx) ;
632+ self . provenance . clear ( range, & self . bytes , cx) ;
634633
635634 & mut self . bytes [ range. start . bytes_usize ( ) ..range. end ( ) . bytes_usize ( ) ]
636635 }
@@ -643,7 +642,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
643642 range : AllocRange ,
644643 ) -> * mut [ u8 ] {
645644 self . mark_init ( range, true ) ;
646- self . provenance . clear ( range, cx) ;
645+ self . provenance . clear ( range, & self . bytes , cx) ;
647646
648647 assert ! ( range. end( ) . bytes_usize( ) <= self . bytes. len( ) ) ; // need to do our own bounds-check
649648 // Crucially, we go via `AllocBytes::as_mut_ptr`, not `AllocBytes::deref_mut`.
@@ -711,57 +710,14 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
711710 if read_provenance {
712711 assert_eq ! ( range. size, cx. data_layout( ) . pointer_size( ) ) ;
713712
714- // When reading data with provenance, the easy case is finding provenance exactly where we
715- // are reading, then we can put data and provenance back together and return that.
716- if let Some ( prov) = self . provenance . get_ptr ( range. start ) {
717- // Now we can return the bits, with their appropriate provenance.
713+ if let Some ( prov) = self . provenance . read_ptr ( range. start , cx) ? {
714+ // Assemble the bits with their provenance.
718715 let ptr = Pointer :: new ( prov, Size :: from_bytes ( bits) ) ;
719- return Ok ( Scalar :: from_pointer ( ptr, cx) ) ;
716+ Ok ( Scalar :: from_pointer ( ptr, cx) )
717+ } else {
718+ // Return raw bits without provenance.
719+ Ok ( Scalar :: from_uint ( bits, range. size ) )
720720 }
721- // The other easy case is total absence of provenance.
722- if self . provenance . range_empty ( range, cx) {
723- return Ok ( Scalar :: from_uint ( bits, range. size ) ) ;
724- }
725- // If we get here, we have to check per-byte provenance, and join them together.
726- let prov = ' prov: {
727- if !Prov :: OFFSET_IS_ADDR {
728- // FIXME(#146291): We need to ensure that we don't mix different pointers with
729- // the same provenance.
730- return Err ( AllocError :: ReadPartialPointer ( range. start ) ) ;
731- }
732- // Initialize with first fragment. Must have index 0.
733- let Some ( ( mut joint_prov, 0 ) ) = self . provenance . get_byte ( range. start , cx) else {
734- break ' prov None ;
735- } ;
736- // Update with the remaining fragments.
737- for offset in Size :: from_bytes ( 1 ) ..range. size {
738- // Ensure there is provenance here and it has the right index.
739- let Some ( ( frag_prov, frag_idx) ) =
740- self . provenance . get_byte ( range. start + offset, cx)
741- else {
742- break ' prov None ;
743- } ;
744- // Wildcard provenance is allowed to come with any index (this is needed
745- // for Miri's native-lib mode to work).
746- if u64:: from ( frag_idx) != offset. bytes ( ) && Some ( frag_prov) != Prov :: WILDCARD {
747- break ' prov None ;
748- }
749- // Merge this byte's provenance with the previous ones.
750- joint_prov = match Prov :: join ( joint_prov, frag_prov) {
751- Some ( prov) => prov,
752- None => break ' prov None ,
753- } ;
754- }
755- break ' prov Some ( joint_prov) ;
756- } ;
757- if prov. is_none ( ) && !Prov :: OFFSET_IS_ADDR {
758- // There are some bytes with provenance here but overall the provenance does not add up.
759- // We need `OFFSET_IS_ADDR` to fall back to no-provenance here; without that option, we must error.
760- return Err ( AllocError :: ReadPartialPointer ( range. start ) ) ;
761- }
762- // We can use this provenance.
763- let ptr = Pointer :: new ( prov, Size :: from_bytes ( bits) ) ;
764- return Ok ( Scalar :: from_maybe_pointer ( ptr, cx) ) ;
765721 } else {
766722 // We are *not* reading a pointer.
767723 // If we can just ignore provenance or there is none, that's easy.
@@ -816,7 +772,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
816772 /// Write "uninit" to the given memory range.
817773 pub fn write_uninit ( & mut self , cx : & impl HasDataLayout , range : AllocRange ) {
818774 self . mark_init ( range, false ) ;
819- self . provenance . clear ( range, cx) ;
775+ self . provenance . clear ( range, & self . bytes , cx) ;
820776 }
821777
822778 /// Mark all bytes in the given range as initialised and reset the provenance
@@ -831,21 +787,28 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
831787 size : Size :: from_bytes ( self . len ( ) ) ,
832788 } ) ;
833789 self . mark_init ( range, true ) ;
834- self . provenance . write_wildcards ( cx, range) ;
790+ self . provenance . write_wildcards ( cx, & self . bytes , range) ;
835791 }
836792
837793 /// Remove all provenance in the given memory range.
838794 pub fn clear_provenance ( & mut self , cx : & impl HasDataLayout , range : AllocRange ) {
839- self . provenance . clear ( range, cx) ;
795+ self . provenance . clear ( range, & self . bytes , cx) ;
840796 }
841797
842798 pub fn provenance_merge_bytes ( & mut self , cx : & impl HasDataLayout ) -> bool {
843799 self . provenance . merge_bytes ( cx)
844800 }
845801
802+ pub fn provenance_prepare_copy (
803+ & self ,
804+ range : AllocRange ,
805+ cx : & impl HasDataLayout ,
806+ ) -> ProvenanceCopy < Prov > {
807+ self . provenance . prepare_copy ( range, & self . bytes , cx)
808+ }
809+
846810 /// Applies a previously prepared provenance copy.
847- /// The affected range, as defined in the parameters to `provenance().prepare_copy` is expected
848- /// to be clear of provenance.
811+ /// The affected range is expected to be clear of provenance.
849812 ///
850813 /// This is dangerous to use as it can violate internal `Allocation` invariants!
851814 /// It only exists to support an efficient implementation of `mem_copy_repeatedly`.
0 commit comments