@@ -18,6 +18,7 @@ macro_rules! err {
18
18
mod error;
19
19
mod value;
20
20
mod allocation;
21
+ mod pointer;
21
22
22
23
pub use self :: error:: {
23
24
EvalError , EvalResult , EvalErrorKind , AssertMessage , ConstEvalErr , struct_error,
@@ -31,11 +32,13 @@ pub use self::allocation::{
31
32
Relocations , UndefMask ,
32
33
} ;
33
34
35
+ pub use self :: pointer:: { Pointer , PointerArithmetic } ;
36
+
34
37
use std:: fmt;
35
38
use mir;
36
39
use hir:: def_id:: DefId ;
37
40
use ty:: { self , TyCtxt , Instance } ;
38
- use ty:: layout:: { self , HasDataLayout , Size } ;
41
+ use ty:: layout:: { self , Size } ;
39
42
use middle:: region;
40
43
use std:: io;
41
44
use std:: hash:: Hash ;
@@ -80,152 +83,6 @@ pub struct GlobalId<'tcx> {
80
83
pub promoted : Option < mir:: Promoted > ,
81
84
}
82
85
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
-
229
86
#[ derive( Copy , Clone , Eq , Hash , Ord , PartialEq , PartialOrd , Debug ) ]
230
87
pub struct AllocId ( pub u64 ) ;
231
88
0 commit comments