@@ -2,7 +2,7 @@ use std::fmt;
22
33use rustc_abi as abi;
44use rustc_abi:: {
5- Align , BackendRepr , FIRST_VARIANT , FieldIdx , Primitive , Size , TagEncoding , Variants ,
5+ Align , BackendRepr , FIRST_VARIANT , FieldIdx , Primitive , Size , TagEncoding , VariantIdx , Variants ,
66} ;
77use rustc_middle:: mir:: interpret:: { Pointer , Scalar , alloc_range} ;
88use rustc_middle:: mir:: { self , ConstValue } ;
@@ -545,67 +545,109 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
545545 } ;
546546 OperandRef { val, layout }
547547 }
548+
549+ pub ( crate ) fn supports_builder ( layout : TyAndLayout < ' tcx > ) -> bool {
550+ match layout. backend_repr {
551+ BackendRepr :: Memory { .. } if layout. is_zst ( ) => true ,
552+ BackendRepr :: Scalar ( _) | BackendRepr :: ScalarPair ( _, _) => true ,
553+ _ => false ,
554+ }
555+ }
548556}
549557
550558impl < ' a , ' tcx , V : CodegenObject > OperandRef < ' tcx , Result < V , abi:: Scalar > > {
551559 pub ( crate ) fn insert_field < Bx : BuilderMethods < ' a , ' tcx , Value = V > > (
552560 & mut self ,
553561 bx : & mut Bx ,
562+ v : VariantIdx ,
554563 f : FieldIdx ,
555564 operand : OperandRef < ' tcx , V > ,
556565 ) {
557- let field_layout = self . layout . field ( bx. cx ( ) , f. as_usize ( ) ) ;
558- let field_offset = self . layout . fields . offset ( f. as_usize ( ) ) ;
566+ let ( expect_zst, is_zero_offset) = if let abi:: FieldsShape :: Primitive = self . layout . fields {
567+ // Don't ask for field layout for primitives, because that will panic.
568+ if !self . layout . uninhabited {
569+ // Real primitives only have one variant, but weird types like
570+ // `Result<!, !>` turn out to also be "Primitive", and dead code
571+ // like `Err(never)` needs to not ICE.
572+ assert_eq ! ( v, FIRST_VARIANT ) ;
573+ }
574+ let first_field = f == FieldIdx :: ZERO ;
575+ ( self . layout . is_zst ( ) || !first_field, first_field)
576+ } else {
577+ let variant_layout = self . layout . for_variant ( bx. cx ( ) , v) ;
578+ let field_layout = variant_layout. field ( bx. cx ( ) , f. as_usize ( ) ) ;
579+ let field_offset = variant_layout. fields . offset ( f. as_usize ( ) ) ;
580+ ( field_layout. is_zst ( ) , field_offset == Size :: ZERO )
581+ } ;
559582
560583 let mut update = |tgt : & mut Result < V , abi:: Scalar > , src, from_scalar| {
561584 let from_bty = bx. cx ( ) . type_from_scalar ( from_scalar) ;
562585 let to_scalar = tgt. unwrap_err ( ) ;
563586 let to_bty = bx. cx ( ) . type_from_scalar ( to_scalar) ;
564- let v = transmute_immediate ( bx, src, from_scalar, from_bty, to_scalar, to_bty) ;
565- * tgt = Ok ( v ) ;
587+ let imm = transmute_immediate ( bx, src, from_scalar, from_bty, to_scalar, to_bty) ;
588+ * tgt = Ok ( imm ) ;
566589 } ;
567590
568591 match ( operand. val , operand. layout . backend_repr ) {
569- ( OperandValue :: ZeroSized , _) => {
570- debug_assert_eq ! ( field_layout. size, Size :: ZERO ) ;
571- }
592+ ( OperandValue :: ZeroSized , _) if expect_zst => { }
572593 ( OperandValue :: Immediate ( v) , BackendRepr :: Scalar ( from_scalar) ) => match & mut self . val {
573- OperandValue :: Immediate ( val @ Err ( _) ) => {
574- debug_assert_eq ! ( field_offset, Size :: ZERO ) ;
594+ OperandValue :: Immediate ( val @ Err ( _) ) if is_zero_offset => {
575595 update ( val, v, from_scalar) ;
576- //*val = Ok(v);
577596 }
578- OperandValue :: Pair ( fst @ Err ( _) , _) if field_offset == Size :: ZERO => {
597+ OperandValue :: Pair ( fst @ Err ( _) , _) if is_zero_offset => {
579598 update ( fst, v, from_scalar) ;
580- //*fst = Ok(v);
581599 }
582- OperandValue :: Pair ( _, snd @ Err ( _) ) if field_offset != Size :: ZERO => {
600+ OperandValue :: Pair ( _, snd @ Err ( _) ) if !is_zero_offset => {
583601 update ( snd, v, from_scalar) ;
584- //*snd = Ok(v);
585602 }
586- _ => bug ! ( "Tried to insert {operand:?} into field {f:?} of {self:?}" ) ,
603+ _ => bug ! ( "Tried to insert {operand:?} into {v:?}. {f:?} of {self:?}" ) ,
587604 } ,
588605 ( OperandValue :: Pair ( a, b) , BackendRepr :: ScalarPair ( from_sa, from_sb) ) => {
589606 match & mut self . val {
590607 OperandValue :: Pair ( fst @ Err ( _) , snd @ Err ( _) ) => {
591608 update ( fst, a, from_sa) ;
592- //*fst = Ok(a);
593609 update ( snd, b, from_sb) ;
594- //*snd = Ok(b);
595610 }
596- _ => bug ! ( "Tried to insert {operand:?} into field {f:?} of {self:?}" ) ,
611+ _ => bug ! ( "Tried to insert {operand:?} into {v:?}. {f:?} of {self:?}" ) ,
597612 }
598613 }
599- _ => bug ! ( "Unsupported operand {operand:?} inserting into field {f:?} of {self:?}" ) ,
614+ _ => bug ! ( "Unsupported operand {operand:?} inserting into {v:?}.{f:?} of {self:?}" ) ,
615+ }
616+ }
617+
618+ pub ( super ) fn insert_imm ( & mut self , f : FieldIdx , imm : V ) {
619+ let field_offset = self . layout . fields . offset ( f. as_usize ( ) ) ;
620+ let is_zero_offset = field_offset == Size :: ZERO ;
621+ match & mut self . val {
622+ OperandValue :: Immediate ( val @ Err ( _) ) if is_zero_offset => {
623+ * val = Ok ( imm) ;
624+ }
625+ OperandValue :: Pair ( fst @ Err ( _) , _) if is_zero_offset => {
626+ * fst = Ok ( imm) ;
627+ }
628+ OperandValue :: Pair ( _, snd @ Err ( _) ) if !is_zero_offset => {
629+ * snd = Ok ( imm) ;
630+ }
631+ _ => bug ! ( "Tried to insert {imm:?} into field {f:?} of {self:?}" ) ,
600632 }
601633 }
602634
603- pub fn finalize ( self ) -> OperandRef < ' tcx , V > {
604- let OperandRef { val, layout } = self ;
635+ pub fn finalize ( & self , cx : & impl CodegenMethods < ' tcx , Value = V > ) -> OperandRef < ' tcx , V > {
636+ let OperandRef { val, layout } = * self ;
637+
638+ let unwrap = |r : Result < V , abi:: Scalar > | match r {
639+ Ok ( v) => v,
640+ Err ( s) if s. is_uninit_valid ( ) => {
641+ let bty = cx. type_from_scalar ( s) ;
642+ cx. const_undef ( bty)
643+ }
644+ Err ( _) => bug ! ( "OperandRef::finalize called while fields are missing {self:?}" ) ,
645+ } ;
646+
605647 let val = match val {
606648 OperandValue :: ZeroSized => OperandValue :: ZeroSized ,
607- OperandValue :: Immediate ( v) => OperandValue :: Immediate ( v . unwrap ( ) ) ,
608- OperandValue :: Pair ( a, b) => OperandValue :: Pair ( a . unwrap ( ) , b . unwrap ( ) ) ,
649+ OperandValue :: Immediate ( v) => OperandValue :: Immediate ( unwrap ( v ) ) ,
650+ OperandValue :: Pair ( a, b) => OperandValue :: Pair ( unwrap ( a ) , unwrap ( b ) ) ,
609651 OperandValue :: Ref ( _) => bug ! ( ) ,
610652 } ;
611653 OperandRef { val, layout }
0 commit comments