@@ -10,12 +10,12 @@ use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
10
10
use rustc_middle:: ty:: print:: { FmtPrinter , PrettyPrinter } ;
11
11
use rustc_middle:: ty:: { ConstInt , Ty , TyCtxt } ;
12
12
use rustc_middle:: { mir, ty} ;
13
- use rustc_target:: abi:: { self , Abi , HasDataLayout , Size } ;
13
+ use rustc_target:: abi:: { self , Abi , HasDataLayout , Primitive , Size } ;
14
14
15
15
use super :: {
16
16
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 ,
19
19
} ;
20
20
21
21
/// An `Immediate` represents a single immediate self-contained Rust value.
@@ -261,12 +261,29 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
261
261
{
262
262
Immediate :: Uninit
263
263
}
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
+ }
264
280
// the field covers the entire type
265
281
_ if layout. size == self . layout . size => {
266
282
assert_eq ! ( offset. bytes( ) , 0 ) ;
267
283
assert ! (
268
284
match ( self . layout. abi, layout. abi) {
269
285
( Abi :: Scalar ( ..) , Abi :: Scalar ( ..) ) => true ,
286
+ ( Abi :: Aggregate { sized: true } , Abi :: Scalar ( ..) ) => true ,
270
287
( Abi :: ScalarPair ( ..) , Abi :: ScalarPair ( ..) ) => true ,
271
288
_ => false ,
272
289
} ,
@@ -500,6 +517,21 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
500
517
) ?;
501
518
Some ( ImmTy :: from_immediate ( Immediate :: ScalarPair ( a_val, b_val) , mplace. layout ) )
502
519
}
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
+ }
503
535
_ => {
504
536
// Neither a scalar nor scalar pair.
505
537
None
@@ -539,12 +571,23 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
539
571
& self ,
540
572
op : & impl Readable < ' tcx , M :: Provenance > ,
541
573
) -> InterpResult < ' tcx , ImmTy < ' tcx , M :: Provenance > > {
542
- if !matches ! (
543
- op. layout( ) . abi,
574
+ let can_primitive_read = match op. layout ( ) . abi {
544
575
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
+ ) ;
548
591
}
549
592
let imm = self . read_immediate_raw ( op) ?. right ( ) . unwrap ( ) ;
550
593
if matches ! ( * imm, Immediate :: Uninit ) {
@@ -599,7 +642,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
599
642
///
600
643
/// Can (but does not always) trigger UB if `op` is uninitialized.
601
644
pub fn operand_to_simd (
602
- & self ,
645
+ & mut self ,
603
646
op : & OpTy < ' tcx , M :: Provenance > ,
604
647
) -> InterpResult < ' tcx , ( MPlaceTy < ' tcx , M :: Provenance > , u64 ) > {
605
648
// 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> {
612
655
throw_ub ! ( InvalidUninitBytes ( None ) )
613
656
}
614
657
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
+ }
616
667
}
617
668
} ,
618
669
}
0 commit comments