@@ -18,6 +18,7 @@ macro_rules! err {
1818mod error;
1919mod value;
2020mod allocation;
21+ mod pointer;
2122
2223pub use self :: error:: {
2324 EvalError , EvalResult , EvalErrorKind , AssertMessage , ConstEvalErr , struct_error,
@@ -31,11 +32,13 @@ pub use self::allocation::{
3132 Relocations , UndefMask ,
3233} ;
3334
35+ pub use self :: pointer:: { Pointer , PointerArithmetic } ;
36+
3437use std:: fmt;
3538use mir;
3639use hir:: def_id:: DefId ;
3740use ty:: { self , TyCtxt , Instance } ;
38- use ty:: layout:: { self , HasDataLayout , Size } ;
41+ use ty:: layout:: { self , Size } ;
3942use middle:: region;
4043use std:: io;
4144use std:: hash:: Hash ;
@@ -80,145 +83,6 @@ pub struct GlobalId<'tcx> {
8083 pub promoted : Option < mir:: Promoted > ,
8184}
8285
83- ////////////////////////////////////////////////////////////////////////////////
84- // Pointer arithmetic
85- ////////////////////////////////////////////////////////////////////////////////
86-
87- pub trait PointerArithmetic : layout:: HasDataLayout {
88- // These are not supposed to be overridden.
89-
90- #[ inline( always) ]
91- fn pointer_size ( self ) -> Size {
92- self . data_layout ( ) . pointer_size
93- }
94-
95- //// Trunace the given value to the pointer size; also return whether there was an overflow
96- fn truncate_to_ptr ( self , val : u128 ) -> ( u64 , bool ) {
97- let max_ptr_plus_1 = 1u128 << self . pointer_size ( ) . bits ( ) ;
98- ( ( val % max_ptr_plus_1) as u64 , val >= max_ptr_plus_1)
99- }
100-
101- // Overflow checking only works properly on the range from -u64 to +u64.
102- fn overflowing_signed_offset ( self , val : u64 , i : i128 ) -> ( u64 , bool ) {
103- // FIXME: is it possible to over/underflow here?
104- if i < 0 {
105- // trickery to ensure that i64::min_value() works fine
106- // this formula only works for true negative values, it panics for zero!
107- let n = u64:: max_value ( ) - ( i as u64 ) + 1 ;
108- val. overflowing_sub ( n)
109- } else {
110- self . overflowing_offset ( val, i as u64 )
111- }
112- }
113-
114- fn overflowing_offset ( self , val : u64 , i : u64 ) -> ( u64 , bool ) {
115- let ( res, over1) = val. overflowing_add ( i) ;
116- let ( res, over2) = self . truncate_to_ptr ( res as u128 ) ;
117- ( res, over1 || over2)
118- }
119-
120- fn signed_offset < ' tcx > ( self , val : u64 , i : i64 ) -> EvalResult < ' tcx , u64 > {
121- let ( res, over) = self . overflowing_signed_offset ( val, i as i128 ) ;
122- if over { err ! ( Overflow ( mir:: BinOp :: Add ) ) } else { Ok ( res) }
123- }
124-
125- fn offset < ' tcx > ( self , val : u64 , i : u64 ) -> EvalResult < ' tcx , u64 > {
126- let ( res, over) = self . overflowing_offset ( val, i) ;
127- if over { err ! ( Overflow ( mir:: BinOp :: Add ) ) } else { Ok ( res) }
128- }
129-
130- fn wrapping_signed_offset ( self , val : u64 , i : i64 ) -> u64 {
131- self . overflowing_signed_offset ( val, i as i128 ) . 0
132- }
133- }
134-
135- impl < T : layout:: HasDataLayout > PointerArithmetic for T { }
136-
137-
138- /// Pointer is generic over the type that represents a reference to Allocations,
139- /// thus making it possible for the most convenient representation to be used in
140- /// each context.
141- ///
142- /// Defaults to the index based and loosely coupled AllocId.
143- ///
144- /// Pointer is also generic over the `Tag` associated with each pointer,
145- /// which is used to do provenance tracking during execution.
146- #[ derive( Copy , Clone , Debug , Eq , PartialEq , Ord , PartialOrd , RustcEncodable , RustcDecodable , Hash ) ]
147- pub struct Pointer < Tag =( ) , Id =AllocId > {
148- pub alloc_id : Id ,
149- pub offset : Size ,
150- pub tag : Tag ,
151- }
152-
153- /// Produces a `Pointer` which points to the beginning of the Allocation
154- impl From < AllocId > for Pointer {
155- #[ inline( always) ]
156- fn from ( alloc_id : AllocId ) -> Self {
157- Pointer :: new ( alloc_id, Size :: ZERO )
158- }
159- }
160-
161- impl < ' tcx > Pointer < ( ) > {
162- #[ inline( always) ]
163- pub fn new ( alloc_id : AllocId , offset : Size ) -> Self {
164- Pointer { alloc_id, offset, tag : ( ) }
165- }
166-
167- #[ inline( always) ]
168- pub fn with_default_tag < Tag > ( self ) -> Pointer < Tag >
169- where Tag : Default
170- {
171- Pointer :: new_with_tag ( self . alloc_id , self . offset , Default :: default ( ) )
172- }
173- }
174-
175- impl < ' tcx , Tag > Pointer < Tag > {
176- #[ inline( always) ]
177- pub fn new_with_tag ( alloc_id : AllocId , offset : Size , tag : Tag ) -> Self {
178- Pointer { alloc_id, offset, tag }
179- }
180-
181- pub fn wrapping_signed_offset ( self , i : i64 , cx : impl HasDataLayout ) -> Self {
182- Pointer :: new_with_tag (
183- self . alloc_id ,
184- Size :: from_bytes ( cx. data_layout ( ) . wrapping_signed_offset ( self . offset . bytes ( ) , i) ) ,
185- self . tag ,
186- )
187- }
188-
189- pub fn overflowing_signed_offset ( self , i : i128 , cx : impl HasDataLayout ) -> ( Self , bool ) {
190- let ( res, over) = cx. data_layout ( ) . overflowing_signed_offset ( self . offset . bytes ( ) , i) ;
191- ( Pointer :: new_with_tag ( self . alloc_id , Size :: from_bytes ( res) , self . tag ) , over)
192- }
193-
194- pub fn signed_offset ( self , i : i64 , cx : impl HasDataLayout ) -> EvalResult < ' tcx , Self > {
195- Ok ( Pointer :: new_with_tag (
196- self . alloc_id ,
197- Size :: from_bytes ( cx. data_layout ( ) . signed_offset ( self . offset . bytes ( ) , i) ?) ,
198- self . tag ,
199- ) )
200- }
201-
202- pub fn overflowing_offset ( self , i : Size , cx : impl HasDataLayout ) -> ( Self , bool ) {
203- let ( res, over) = cx. data_layout ( ) . overflowing_offset ( self . offset . bytes ( ) , i. bytes ( ) ) ;
204- ( Pointer :: new_with_tag ( self . alloc_id , Size :: from_bytes ( res) , self . tag ) , over)
205- }
206-
207- pub fn offset ( self , i : Size , cx : impl HasDataLayout ) -> EvalResult < ' tcx , Self > {
208- Ok ( Pointer :: new_with_tag (
209- self . alloc_id ,
210- Size :: from_bytes ( cx. data_layout ( ) . offset ( self . offset . bytes ( ) , i. bytes ( ) ) ?) ,
211- self . tag
212- ) )
213- }
214-
215- #[ inline]
216- pub fn erase_tag ( self ) -> Pointer {
217- Pointer { alloc_id : self . alloc_id , offset : self . offset , tag : ( ) }
218- }
219- }
220-
221-
22286#[ derive( Copy , Clone , Eq , Hash , Ord , PartialEq , PartialOrd , Debug ) ]
22387pub struct AllocId ( pub u64 ) ;
22488
0 commit comments