@@ -84,14 +84,18 @@ impl<'tcx, Tag: Provenance> Immediate<Tag> {
84
84
}
85
85
86
86
#[ inline]
87
- pub fn to_scalar_pair ( self ) -> InterpResult < ' tcx , ( Scalar < Tag > , Scalar < Tag > ) > {
87
+ pub fn to_scalar_or_uninit_pair ( self ) -> ( ScalarMaybeUninit < Tag > , ScalarMaybeUninit < Tag > ) {
88
88
match self {
89
- Immediate :: ScalarPair ( val1, val2) => Ok ( ( val1. check_init ( ) ?, val2. check_init ( ) ?) ) ,
90
- Immediate :: Scalar ( ..) => {
91
- bug ! ( "Got a scalar where a scalar pair was expected" )
92
- }
89
+ Immediate :: ScalarPair ( val1, val2) => ( val1, val2) ,
90
+ Immediate :: Scalar ( ..) => bug ! ( "Got a scalar where a scalar pair was expected" ) ,
93
91
}
94
92
}
93
+
94
+ #[ inline]
95
+ pub fn to_scalar_pair ( self ) -> InterpResult < ' tcx , ( Scalar < Tag > , Scalar < Tag > ) > {
96
+ let ( val1, val2) = self . to_scalar_or_uninit_pair ( ) ;
97
+ Ok ( ( val1. check_init ( ) ?, val2. check_init ( ) ?) )
98
+ }
95
99
}
96
100
97
101
// ScalarPair needs a type to interpret, so we often have an immediate and a type together
@@ -248,9 +252,12 @@ impl<'tcx, Tag: Provenance> ImmTy<'tcx, Tag> {
248
252
impl < ' mir , ' tcx : ' mir , M : Machine < ' mir , ' tcx > > InterpCx < ' mir , ' tcx , M > {
249
253
/// Try reading an immediate in memory; this is interesting particularly for `ScalarPair`.
250
254
/// Returns `None` if the layout does not permit loading this as a value.
251
- fn try_read_immediate_from_mplace (
255
+ ///
256
+ /// This is an internal function; call `read_immediate` instead.
257
+ fn read_immediate_from_mplace_raw (
252
258
& self ,
253
259
mplace : & MPlaceTy < ' tcx , M :: PointerTag > ,
260
+ force : bool ,
254
261
) -> InterpResult < ' tcx , Option < ImmTy < ' tcx , M :: PointerTag > > > {
255
262
if mplace. layout . is_unsized ( ) {
256
263
// Don't touch unsized
@@ -271,42 +278,61 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
271
278
// case where some of the bytes are initialized and others are not. So, we need an extra
272
279
// check that walks over the type of `mplace` to make sure it is truly correct to treat this
273
280
// like a `Scalar` (or `ScalarPair`).
274
- match mplace. layout . abi {
275
- Abi :: Scalar ( abi:: Scalar :: Initialized { .. } ) => {
276
- let scalar = alloc. read_scalar ( alloc_range ( Size :: ZERO , mplace. layout . size ) ) ?;
277
- Ok ( Some ( ImmTy { imm : scalar. into ( ) , layout : mplace. layout } ) )
278
- }
281
+ let scalar_layout = match mplace. layout . abi {
282
+ // `if` does not work nested inside patterns, making this a bit awkward to express.
283
+ Abi :: Scalar ( abi:: Scalar :: Initialized { value : s, .. } ) => Some ( s) ,
284
+ Abi :: Scalar ( s) if force => Some ( s. primitive ( ) ) ,
285
+ _ => None ,
286
+ } ;
287
+ if let Some ( _) = scalar_layout {
288
+ let scalar = alloc. read_scalar ( alloc_range ( Size :: ZERO , mplace. layout . size ) ) ?;
289
+ return Ok ( Some ( ImmTy { imm : scalar. into ( ) , layout : mplace. layout } ) ) ;
290
+ }
291
+ let scalar_pair_layout = match mplace. layout . abi {
279
292
Abi :: ScalarPair (
280
293
abi:: Scalar :: Initialized { value : a, .. } ,
281
294
abi:: Scalar :: Initialized { value : b, .. } ,
282
- ) => {
283
- // We checked `ptr_align` above, so all fields will have the alignment they need.
284
- // We would anyway check against `ptr_align.restrict_for_offset(b_offset)`,
285
- // which `ptr.offset(b_offset)` cannot possibly fail to satisfy.
286
- let ( a_size, b_size) = ( a. size ( self ) , b. size ( self ) ) ;
287
- let b_offset = a_size. align_to ( b. align ( self ) . abi ) ;
288
- assert ! ( b_offset. bytes( ) > 0 ) ; // we later use the offset to tell apart the fields
289
- let a_val = alloc. read_scalar ( alloc_range ( Size :: ZERO , a_size) ) ?;
290
- let b_val = alloc. read_scalar ( alloc_range ( b_offset, b_size) ) ?;
291
- Ok ( Some ( ImmTy { imm : Immediate :: ScalarPair ( a_val, b_val) , layout : mplace. layout } ) )
292
- }
293
- _ => Ok ( None ) ,
295
+ ) => Some ( ( a, b) ) ,
296
+ Abi :: ScalarPair ( a, b) if force => Some ( ( a. primitive ( ) , b. primitive ( ) ) ) ,
297
+ _ => None ,
298
+ } ;
299
+ if let Some ( ( a, b) ) = scalar_pair_layout {
300
+ // We checked `ptr_align` above, so all fields will have the alignment they need.
301
+ // We would anyway check against `ptr_align.restrict_for_offset(b_offset)`,
302
+ // which `ptr.offset(b_offset)` cannot possibly fail to satisfy.
303
+ let ( a_size, b_size) = ( a. size ( self ) , b. size ( self ) ) ;
304
+ let b_offset = a_size. align_to ( b. align ( self ) . abi ) ;
305
+ assert ! ( b_offset. bytes( ) > 0 ) ; // we later use the offset to tell apart the fields
306
+ let a_val = alloc. read_scalar ( alloc_range ( Size :: ZERO , a_size) ) ?;
307
+ let b_val = alloc. read_scalar ( alloc_range ( b_offset, b_size) ) ?;
308
+ return Ok ( Some ( ImmTy {
309
+ imm : Immediate :: ScalarPair ( a_val, b_val) ,
310
+ layout : mplace. layout ,
311
+ } ) ) ;
294
312
}
313
+ // Neither a scalar nor scalar pair.
314
+ return Ok ( None ) ;
295
315
}
296
316
297
- /// Try returning an immediate for the operand.
298
- /// If the layout does not permit loading this as an immediate, return where in memory
299
- /// we can find the data.
317
+ /// Try returning an immediate for the operand. If the layout does not permit loading this as an
318
+ /// immediate, return where in memory we can find the data.
300
319
/// Note that for a given layout, this operation will either always fail or always
301
320
/// succeed! Whether it succeeds depends on whether the layout can be represented
302
321
/// in an `Immediate`, not on which data is stored there currently.
303
- pub fn try_read_immediate (
322
+ ///
323
+ /// If `force` is `true`, then even scalars with fields that can be ununit will be
324
+ /// read. This means the load is lossy and should not be written back!
325
+ /// This flag exists only for validity checking.
326
+ ///
327
+ /// This is an internal function that should not usually be used; call `read_immediate` instead.
328
+ pub fn read_immediate_raw (
304
329
& self ,
305
330
src : & OpTy < ' tcx , M :: PointerTag > ,
331
+ force : bool ,
306
332
) -> InterpResult < ' tcx , Result < ImmTy < ' tcx , M :: PointerTag > , MPlaceTy < ' tcx , M :: PointerTag > > > {
307
333
Ok ( match src. try_as_mplace ( ) {
308
334
Ok ( ref mplace) => {
309
- if let Some ( val) = self . try_read_immediate_from_mplace ( mplace) ? {
335
+ if let Some ( val) = self . read_immediate_from_mplace_raw ( mplace, force ) ? {
310
336
Ok ( val)
311
337
} else {
312
338
Err ( * mplace)
@@ -322,7 +348,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
322
348
& self ,
323
349
op : & OpTy < ' tcx , M :: PointerTag > ,
324
350
) -> InterpResult < ' tcx , ImmTy < ' tcx , M :: PointerTag > > {
325
- if let Ok ( imm) = self . try_read_immediate ( op) ? {
351
+ if let Ok ( imm) = self . read_immediate_raw ( op, /*force*/ false ) ? {
326
352
Ok ( imm)
327
353
} else {
328
354
span_bug ! ( self . cur_span( ) , "primitive read failed for type: {:?}" , op. layout. ty) ;
0 commit comments