@@ -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,152 +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- #[ inline]
97- fn truncate_to_ptr ( & self , val : u128 ) -> ( u64 , bool ) {
98- let max_ptr_plus_1 = 1u128 << self . pointer_size ( ) . bits ( ) ;
99- ( ( val % max_ptr_plus_1) as u64 , val >= max_ptr_plus_1)
100- }
101-
102- #[ inline]
103- fn offset < ' tcx > ( & self , val : u64 , i : u64 ) -> EvalResult < ' tcx , u64 > {
104- let ( res, over) = self . overflowing_offset ( val, i) ;
105- if over { err ! ( Overflow ( mir:: BinOp :: Add ) ) } else { Ok ( res) }
106- }
107-
108- #[ inline]
109- fn overflowing_offset ( & self , val : u64 , i : u64 ) -> ( u64 , bool ) {
110- let ( res, over1) = val. overflowing_add ( i) ;
111- let ( res, over2) = self . truncate_to_ptr ( u128:: from ( res) ) ;
112- ( res, over1 || over2)
113- }
114-
115- #[ inline]
116- fn signed_offset < ' tcx > ( & self , val : u64 , i : i64 ) -> EvalResult < ' tcx , u64 > {
117- let ( res, over) = self . overflowing_signed_offset ( val, i128:: from ( i) ) ;
118- if over { err ! ( Overflow ( mir:: BinOp :: Add ) ) } else { Ok ( res) }
119- }
120-
121- // Overflow checking only works properly on the range from -u64 to +u64.
122- #[ inline]
123- fn overflowing_signed_offset ( & self , val : u64 , i : i128 ) -> ( u64 , bool ) {
124- // FIXME: is it possible to over/underflow here?
125- if i < 0 {
126- // trickery to ensure that i64::min_value() works fine
127- // this formula only works for true negative values, it panics for zero!
128- let n = u64:: max_value ( ) - ( i as u64 ) + 1 ;
129- val. overflowing_sub ( n)
130- } else {
131- self . overflowing_offset ( val, i as u64 )
132- }
133- }
134- }
135-
136- impl < T : layout:: HasDataLayout > PointerArithmetic for T { }
137-
138-
139- /// Pointer is generic over the type that represents a reference to Allocations,
140- /// thus making it possible for the most convenient representation to be used in
141- /// each context.
142- ///
143- /// Defaults to the index based and loosely coupled AllocId.
144- ///
145- /// Pointer is also generic over the `Tag` associated with each pointer,
146- /// which is used to do provenance tracking during execution.
147- #[ derive( Copy , Clone , Debug , Eq , PartialEq , Ord , PartialOrd , RustcEncodable , RustcDecodable , Hash ) ]
148- pub struct Pointer < Tag =( ) , Id =AllocId > {
149- pub alloc_id : Id ,
150- pub offset : Size ,
151- pub tag : Tag ,
152- }
153-
154- /// Produces a `Pointer` which points to the beginning of the Allocation
155- impl From < AllocId > for Pointer {
156- #[ inline( always) ]
157- fn from ( alloc_id : AllocId ) -> Self {
158- Pointer :: new ( alloc_id, Size :: ZERO )
159- }
160- }
161-
162- impl < ' tcx > Pointer < ( ) > {
163- #[ inline( always) ]
164- pub fn new ( alloc_id : AllocId , offset : Size ) -> Self {
165- Pointer { alloc_id, offset, tag : ( ) }
166- }
167-
168- #[ inline( always) ]
169- pub fn with_default_tag < Tag > ( self ) -> Pointer < Tag >
170- where Tag : Default
171- {
172- Pointer :: new_with_tag ( self . alloc_id , self . offset , Default :: default ( ) )
173- }
174- }
175-
176- impl < ' tcx , Tag > Pointer < Tag > {
177- #[ inline( always) ]
178- pub fn new_with_tag ( alloc_id : AllocId , offset : Size , tag : Tag ) -> Self {
179- Pointer { alloc_id, offset, tag }
180- }
181-
182- #[ inline]
183- pub fn offset ( self , i : Size , cx : & impl HasDataLayout ) -> EvalResult < ' tcx , Self > {
184- Ok ( Pointer :: new_with_tag (
185- self . alloc_id ,
186- Size :: from_bytes ( cx. data_layout ( ) . offset ( self . offset . bytes ( ) , i. bytes ( ) ) ?) ,
187- self . tag
188- ) )
189- }
190-
191- #[ inline]
192- pub fn overflowing_offset ( self , i : Size , cx : & impl HasDataLayout ) -> ( Self , bool ) {
193- let ( res, over) = cx. data_layout ( ) . overflowing_offset ( self . offset . bytes ( ) , i. bytes ( ) ) ;
194- ( Pointer :: new_with_tag ( self . alloc_id , Size :: from_bytes ( res) , self . tag ) , over)
195- }
196-
197- #[ inline( always) ]
198- pub fn wrapping_offset ( self , i : Size , cx : & impl HasDataLayout ) -> Self {
199- self . overflowing_offset ( i, cx) . 0
200- }
201-
202- #[ inline]
203- pub fn signed_offset ( self , i : i64 , cx : & impl HasDataLayout ) -> EvalResult < ' tcx , Self > {
204- Ok ( Pointer :: new_with_tag (
205- self . alloc_id ,
206- Size :: from_bytes ( cx. data_layout ( ) . signed_offset ( self . offset . bytes ( ) , i) ?) ,
207- self . tag ,
208- ) )
209- }
210-
211- #[ inline]
212- pub fn overflowing_signed_offset ( self , i : i128 , cx : & impl HasDataLayout ) -> ( Self , bool ) {
213- let ( res, over) = cx. data_layout ( ) . overflowing_signed_offset ( self . offset . bytes ( ) , i) ;
214- ( Pointer :: new_with_tag ( self . alloc_id , Size :: from_bytes ( res) , self . tag ) , over)
215- }
216-
217- #[ inline( always) ]
218- pub fn wrapping_signed_offset ( self , i : i64 , cx : & impl HasDataLayout ) -> Self {
219- self . overflowing_signed_offset ( i128:: from ( i) , cx) . 0
220- }
221-
222- #[ inline( always) ]
223- pub fn erase_tag ( self ) -> Pointer {
224- Pointer { alloc_id : self . alloc_id , offset : self . offset , tag : ( ) }
225- }
226- }
227-
228-
22986#[ derive( Copy , Clone , Eq , Hash , Ord , PartialEq , PartialOrd , Debug ) ]
23087pub struct AllocId ( pub u64 ) ;
23188
0 commit comments