@@ -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,145 +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
- 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
-
222
86
#[ derive( Copy , Clone , Eq , Hash , Ord , PartialEq , PartialOrd , Debug ) ]
223
87
pub struct AllocId ( pub u64 ) ;
224
88
0 commit comments