@@ -10,12 +10,12 @@ use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
1010use rustc_middle:: ty:: print:: { FmtPrinter , PrettyPrinter } ;
1111use rustc_middle:: ty:: { ConstInt , Ty , TyCtxt } ;
1212use rustc_middle:: { mir, ty} ;
13- use rustc_target:: abi:: { self , Abi , HasDataLayout , Size } ;
13+ use rustc_target:: abi:: { self , Abi , HasDataLayout , Primitive , Size } ;
1414
1515use super :: {
1616 alloc_range, from_known_layout, mir_assign_valid_types, AllocId , Frame , InterpCx , InterpResult ,
17- MPlaceTy , Machine , MemPlace , MemPlaceMeta , OffsetMode , PlaceTy , Pointer , Projectable ,
18- Provenance , Scalar ,
17+ MPlaceTy , Machine , MemPlace , MemPlaceMeta , MemoryKind , OffsetMode , PlaceTy , Pointer ,
18+ Projectable , Provenance , Scalar ,
1919} ;
2020
2121/// An `Immediate` represents a single immediate self-contained Rust value.
@@ -261,12 +261,29 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
261261 {
262262 Immediate :: Uninit
263263 }
264+ (
265+ Immediate :: Scalar ( scalar) ,
266+ Abi :: Vector {
267+ element : abi:: Scalar :: Initialized { value : s @ Primitive :: Int ( ..) , .. } ,
268+ ..
269+ } ,
270+ ) => {
271+ let size = s. size ( cx) ;
272+ assert_eq ! ( size, layout. size) ;
273+ assert ! ( self . layout. size. bytes( ) <= 16 ) ;
274+ let vector_bits: u128 = scalar. to_bits ( self . layout . size ) . unwrap ( ) ;
275+ Immediate :: Scalar ( Scalar :: Int (
276+ ty:: ScalarInt :: try_from_uint ( size. truncate ( vector_bits >> offset. bits ( ) ) , size)
277+ . unwrap ( ) ,
278+ ) )
279+ }
264280 // the field covers the entire type
265281 _ if layout. size == self . layout . size => {
266282 assert_eq ! ( offset. bytes( ) , 0 ) ;
267283 assert ! (
268284 match ( self . layout. abi, layout. abi) {
269285 ( Abi :: Scalar ( ..) , Abi :: Scalar ( ..) ) => true ,
286+ ( Abi :: Aggregate { sized: true } , Abi :: Scalar ( ..) ) => true ,
270287 ( Abi :: ScalarPair ( ..) , Abi :: ScalarPair ( ..) ) => true ,
271288 _ => false ,
272289 } ,
@@ -500,6 +517,21 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
500517 ) ?;
501518 Some ( ImmTy :: from_immediate ( Immediate :: ScalarPair ( a_val, b_val) , mplace. layout ) )
502519 }
520+ Abi :: Vector {
521+ element : abi:: Scalar :: Initialized { value : s @ abi:: Primitive :: Int ( ..) , .. } ,
522+ ..
523+ } => {
524+ let size = s. size ( self ) ;
525+ let stride = size. align_to ( s. align ( self ) . abi ) ;
526+ if mplace. layout . size . bytes ( ) <= 16 {
527+ assert ! ( stride. bytes( ) > 0 ) ;
528+ let vector_scalar =
529+ alloc. read_scalar ( alloc_range ( Size :: ZERO , mplace. layout . size ) , false ) ?;
530+ Some ( ImmTy { imm : Immediate :: Scalar ( vector_scalar) , layout : mplace. layout } )
531+ } else {
532+ None
533+ }
534+ }
503535 _ => {
504536 // Neither a scalar nor scalar pair.
505537 None
@@ -539,12 +571,23 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
539571 & self ,
540572 op : & impl Readable < ' tcx , M :: Provenance > ,
541573 ) -> InterpResult < ' tcx , ImmTy < ' tcx , M :: Provenance > > {
542- if !matches ! (
543- op. layout( ) . abi,
574+ let can_primitive_read = match op. layout ( ) . abi {
544575 Abi :: Scalar ( abi:: Scalar :: Initialized { .. } )
545- | Abi :: ScalarPair ( abi:: Scalar :: Initialized { .. } , abi:: Scalar :: Initialized { .. } )
546- ) {
547- span_bug ! ( self . cur_span( ) , "primitive read not possible for type: {}" , op. layout( ) . ty) ;
576+ | Abi :: ScalarPair ( abi:: Scalar :: Initialized { .. } , abi:: Scalar :: Initialized { .. } ) => {
577+ true
578+ }
579+ Abi :: Vector {
580+ element : abi:: Scalar :: Initialized { value : abi:: Primitive :: Int ( ..) , .. } ,
581+ ..
582+ } => op. layout ( ) . size . bytes ( ) <= 16 ,
583+ _ => false ,
584+ } ;
585+ if !can_primitive_read {
586+ span_bug ! (
587+ self . cur_span( ) ,
588+ "primitive read not possible for type: {:?}" ,
589+ op. layout( ) . ty
590+ ) ;
548591 }
549592 let imm = self . read_immediate_raw ( op) ?. right ( ) . unwrap ( ) ;
550593 if matches ! ( * imm, Immediate :: Uninit ) {
@@ -599,7 +642,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
599642 ///
600643 /// Can (but does not always) trigger UB if `op` is uninitialized.
601644 pub fn operand_to_simd (
602- & self ,
645+ & mut self ,
603646 op : & OpTy < ' tcx , M :: Provenance > ,
604647 ) -> InterpResult < ' tcx , ( MPlaceTy < ' tcx , M :: Provenance > , u64 ) > {
605648 // Basically we just transmute this place into an array following simd_size_and_type.
@@ -612,7 +655,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
612655 throw_ub ! ( InvalidUninitBytes ( None ) )
613656 }
614657 Immediate :: Scalar ( ..) | Immediate :: ScalarPair ( ..) => {
615- bug ! ( "arrays/slices can never have Scalar/ScalarPair layout" )
658+ if let Abi :: Vector {
659+ element : abi:: Scalar :: Initialized { value : abi:: Primitive :: Int ( ..) , .. } , ..
660+ } = op. layout . abi && op. layout . size . bytes ( ) <= 16 {
661+ let mplace = self . allocate ( op. layout , MemoryKind :: Stack ) ?;
662+ self . write_immediate ( imm. imm , & mplace) . unwrap ( ) ;
663+ self . mplace_to_simd ( & mplace)
664+ } else {
665+ bug ! ( "arrays/slices can never have Scalar/ScalarPair layout" )
666+ }
616667 }
617668 } ,
618669 }
0 commit comments