@@ -18,6 +18,7 @@ use std::iter;
18
18
use mir;
19
19
use std:: ops:: { Deref , DerefMut } ;
20
20
use rustc_data_structures:: sorted_map:: SortedMap ;
21
+ use rustc_target:: abi:: HasDataLayout ;
21
22
22
23
/// Used by `check_bounds` to indicate whether the pointer needs to be just inbounds
23
24
/// or also inbounds of a *live* allocation.
@@ -76,16 +77,17 @@ impl<'tcx, Tag, Extra> Allocation<Tag, Extra> {
76
77
#[ inline( always) ]
77
78
pub fn check_bounds (
78
79
& self ,
80
+ cx : & impl HasDataLayout ,
79
81
ptr : Pointer < Tag > ,
80
82
size : Size ,
81
83
) -> EvalResult < ' tcx > {
82
84
// if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
83
- self . check_bounds_ptr ( ptr. offset ( size, & * self ) ?)
85
+ self . check_bounds_ptr ( ptr. offset ( size, cx ) ?)
84
86
}
85
87
}
86
88
87
89
/// Byte accessors
88
- impl < ' tcx , Tag , Extra : AllocationExtra < Tag > > Allocation < Tag , Extra > {
90
+ impl < ' tcx , Tag : Copy , Extra : AllocationExtra < Tag > > Allocation < Tag , Extra > {
89
91
/// The last argument controls whether we error out when there are undefined
90
92
/// or pointer bytes. You should never call this, call `get_bytes` or
91
93
/// `get_bytes_with_undef_and_ptr` instead,
@@ -95,21 +97,22 @@ impl<'tcx, Tag, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
95
97
/// on that.
96
98
fn get_bytes_internal (
97
99
& self ,
100
+ cx : & impl HasDataLayout ,
98
101
ptr : Pointer < Tag > ,
99
102
size : Size ,
100
103
align : Align ,
101
104
check_defined_and_ptr : bool ,
102
105
) -> EvalResult < ' tcx , & [ u8 ] > {
103
106
assert_ne ! ( size. bytes( ) , 0 , "0-sized accesses should never even get a `Pointer`" ) ;
104
107
self . check_align ( ptr. into ( ) , align) ?;
105
- self . check_bounds ( ptr , size , InboundsCheck :: Live ) ?;
108
+ self . check_bounds ( cx , ptr , size ) ?;
106
109
107
110
if check_defined_and_ptr {
108
111
self . check_defined ( ptr, size) ?;
109
- self . check_relocations ( ptr, size) ?;
112
+ self . check_relocations ( cx , ptr, size) ?;
110
113
} else {
111
114
// We still don't want relocations on the *edges*
112
- self . check_relocation_edges ( ptr, size) ?;
115
+ self . check_relocation_edges ( cx , ptr, size) ?;
113
116
}
114
117
115
118
AllocationExtra :: memory_read ( self , ptr, size) ?;
@@ -123,39 +126,42 @@ impl<'tcx, Tag, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
123
126
#[ inline]
124
127
fn get_bytes (
125
128
& self ,
129
+ cx : & impl HasDataLayout ,
126
130
ptr : Pointer < Tag > ,
127
131
size : Size ,
128
132
align : Align
129
133
) -> EvalResult < ' tcx , & [ u8 ] > {
130
- self . get_bytes_internal ( ptr, size, align, true )
134
+ self . get_bytes_internal ( cx , ptr, size, align, true )
131
135
}
132
136
133
137
/// It is the caller's responsibility to handle undefined and pointer bytes.
134
138
/// However, this still checks that there are no relocations on the *edges*.
135
139
#[ inline]
136
140
fn get_bytes_with_undef_and_ptr (
137
141
& self ,
142
+ cx : & impl HasDataLayout ,
138
143
ptr : Pointer < Tag > ,
139
144
size : Size ,
140
145
align : Align
141
146
) -> EvalResult < ' tcx , & [ u8 ] > {
142
- self . get_bytes_internal ( ptr, size, align, false )
147
+ self . get_bytes_internal ( cx , ptr, size, align, false )
143
148
}
144
149
145
150
/// Just calling this already marks everything as defined and removes relocations,
146
151
/// so be sure to actually put data there!
147
152
fn get_bytes_mut (
148
153
& mut self ,
154
+ cx : & impl HasDataLayout ,
149
155
ptr : Pointer < Tag > ,
150
156
size : Size ,
151
157
align : Align ,
152
158
) -> EvalResult < ' tcx , & mut [ u8 ] > {
153
159
assert_ne ! ( size. bytes( ) , 0 , "0-sized accesses should never even get a `Pointer`" ) ;
154
160
self . check_align ( ptr. into ( ) , align) ?;
155
- self . check_bounds ( ptr , size , InboundsCheck :: Live ) ?;
161
+ self . check_bounds ( cx , ptr , size ) ?;
156
162
157
163
self . mark_definedness ( ptr, size, true ) ?;
158
- self . clear_relocations ( ptr, size) ?;
164
+ self . clear_relocations ( cx , ptr, size) ?;
159
165
160
166
AllocationExtra :: memory_written ( self , ptr, size) ?;
161
167
@@ -167,24 +173,30 @@ impl<'tcx, Tag, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
167
173
}
168
174
169
175
/// Relocations
170
- impl < ' tcx , Tag , Extra > Allocation < Tag , Extra > {
176
+ impl < ' tcx , Tag : Copy , Extra > Allocation < Tag , Extra > {
171
177
/// Return all relocations overlapping with the given ptr-offset pair.
172
178
fn relocations (
173
179
& self ,
180
+ cx : & impl HasDataLayout ,
174
181
ptr : Pointer < Tag > ,
175
182
size : Size ,
176
183
) -> EvalResult < ' tcx , & [ ( Size , ( Tag , AllocId ) ) ] > {
177
184
// We have to go back `pointer_size - 1` bytes, as that one would still overlap with
178
185
// the beginning of this range.
179
- let start = ptr. offset . bytes ( ) . saturating_sub ( self . pointer_size ( ) . bytes ( ) - 1 ) ;
186
+ let start = ptr. offset . bytes ( ) . saturating_sub ( cx . data_layout ( ) . pointer_size . bytes ( ) - 1 ) ;
180
187
let end = ptr. offset + size; // this does overflow checking
181
188
Ok ( self . relocations . range ( Size :: from_bytes ( start) ..end) )
182
189
}
183
190
184
191
/// Check that there ar eno relocations overlapping with the given range.
185
192
#[ inline( always) ]
186
- fn check_relocations ( & self , ptr : Pointer < Tag > , size : Size ) -> EvalResult < ' tcx > {
187
- if self . relocations ( ptr, size) ?. len ( ) != 0 {
193
+ fn check_relocations (
194
+ & self ,
195
+ cx : & impl HasDataLayout ,
196
+ ptr : Pointer < Tag > ,
197
+ size : Size ,
198
+ ) -> EvalResult < ' tcx > {
199
+ if self . relocations ( cx, ptr, size) ?. len ( ) != 0 {
188
200
err ! ( ReadPointerAsBytes )
189
201
} else {
190
202
Ok ( ( ) )
@@ -197,17 +209,22 @@ impl<'tcx, Tag, Extra> Allocation<Tag, Extra> {
197
209
/// uninitialized. This is a somewhat odd "spooky action at a distance",
198
210
/// but it allows strictly more code to run than if we would just error
199
211
/// immediately in that case.
200
- fn clear_relocations ( & mut self , ptr : Pointer < Tag > , size : Size ) -> EvalResult < ' tcx > {
212
+ fn clear_relocations (
213
+ & mut self ,
214
+ cx : & impl HasDataLayout ,
215
+ ptr : Pointer < Tag > ,
216
+ size : Size ,
217
+ ) -> EvalResult < ' tcx > {
201
218
// Find the start and end of the given range and its outermost relocations.
202
219
let ( first, last) = {
203
220
// Find all relocations overlapping the given range.
204
- let relocations = self . relocations ( ptr, size) ?;
221
+ let relocations = self . relocations ( cx , ptr, size) ?;
205
222
if relocations. is_empty ( ) {
206
223
return Ok ( ( ) ) ;
207
224
}
208
225
209
226
( relocations. first ( ) . unwrap ( ) . 0 ,
210
- relocations. last ( ) . unwrap ( ) . 0 + self . pointer_size ( ) )
227
+ relocations. last ( ) . unwrap ( ) . 0 + cx . data_layout ( ) . pointer_size )
211
228
} ;
212
229
let start = ptr. offset ;
213
230
let end = start + size;
@@ -230,9 +247,14 @@ impl<'tcx, Tag, Extra> Allocation<Tag, Extra> {
230
247
/// Error if there are relocations overlapping with the edges of the
231
248
/// given memory range.
232
249
#[ inline]
233
- fn check_relocation_edges ( & self , ptr : Pointer < Tag > , size : Size ) -> EvalResult < ' tcx > {
234
- self . check_relocations ( ptr, Size :: ZERO ) ?;
235
- self . check_relocations ( ptr. offset ( size, self ) ?, Size :: ZERO ) ?;
250
+ fn check_relocation_edges (
251
+ & self ,
252
+ cx : & impl HasDataLayout ,
253
+ ptr : Pointer < Tag > ,
254
+ size : Size ,
255
+ ) -> EvalResult < ' tcx > {
256
+ self . check_relocations ( cx, ptr, Size :: ZERO ) ?;
257
+ self . check_relocations ( cx, ptr. offset ( size, cx) ?, Size :: ZERO ) ?;
236
258
Ok ( ( ) )
237
259
}
238
260
}
0 commit comments