@@ -84,14 +84,18 @@ impl<'tcx, Tag: Provenance> Immediate<Tag> {
8484    } 
8585
8686    #[ 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 > )  { 
8888        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" ) , 
9391        } 
9492    } 
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+     } 
9599} 
96100
97101// 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> {
248252impl < ' mir ,  ' tcx :  ' mir ,  M :  Machine < ' mir ,  ' tcx > >  InterpCx < ' mir ,  ' tcx ,  M >  { 
249253    /// Try reading an immediate in memory; this is interesting particularly for `ScalarPair`. 
250254/// 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 ( 
252258        & self , 
253259        mplace :  & MPlaceTy < ' tcx ,  M :: PointerTag > , 
260+         force :  bool , 
254261    )  -> InterpResult < ' tcx ,  Option < ImmTy < ' tcx ,  M :: PointerTag > > >  { 
255262        if  mplace. layout . is_unsized ( )  { 
256263            // Don't touch unsized 
@@ -271,42 +278,61 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
271278        // case where some of the bytes are initialized and others are not. So, we need an extra 
272279        // check that walks over the type of `mplace` to make sure it is truly correct to treat this 
273280        // 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  { 
279292            Abi :: ScalarPair ( 
280293                abi:: Scalar :: Initialized  {  value :  a,  .. } , 
281294                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+             } ) ) ; 
294312        } 
313+         // Neither a scalar nor scalar pair. 
314+         return  Ok ( None ) ; 
295315    } 
296316
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. 
300319/// Note that for a given layout, this operation will either always fail or always 
301320/// succeed!  Whether it succeeds depends on whether the layout can be represented 
302321/// 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 ( 
304329        & self , 
305330        src :  & OpTy < ' tcx ,  M :: PointerTag > , 
331+         force :  bool , 
306332    )  -> InterpResult < ' tcx ,  Result < ImmTy < ' tcx ,  M :: PointerTag > ,  MPlaceTy < ' tcx ,  M :: PointerTag > > >  { 
307333        Ok ( match  src. try_as_mplace ( )  { 
308334            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 ) ? { 
310336                    Ok ( val) 
311337                }  else  { 
312338                    Err ( * mplace) 
@@ -322,7 +348,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
322348        & self , 
323349        op :  & OpTy < ' tcx ,  M :: PointerTag > , 
324350    )  -> 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 ) ? { 
326352            Ok ( imm) 
327353        }  else  { 
328354            span_bug ! ( self . cur_span( ) ,  "primitive read failed for type: {:?}" ,  op. layout. ty) ; 
0 commit comments