@@ -67,9 +67,14 @@ pub enum OperandValue<V> {
67
67
/// `is_zst` on its `Layout` returns `true`. Note however that
68
68
/// these values can still require alignment.
69
69
ZeroSized ,
70
+ Uninit ,
70
71
}
71
72
72
73
impl < V : CodegenObject > OperandValue < V > {
74
+ pub ( crate ) fn is_uninit ( & self ) -> bool {
75
+ matches ! ( self , OperandValue :: Uninit )
76
+ }
77
+
73
78
/// Treat this value as a pointer and return the data pointer and
74
79
/// optional metadata as backend values.
75
80
///
@@ -100,6 +105,7 @@ impl<V: CodegenObject> OperandValue<V> {
100
105
ty : TyAndLayout < ' tcx > ,
101
106
) -> bool {
102
107
match self {
108
+ OperandValue :: Uninit => true ,
103
109
OperandValue :: ZeroSized => ty. is_zst ( ) ,
104
110
OperandValue :: Immediate ( _) => cx. is_backend_immediate ( ty) ,
105
111
OperandValue :: Pair ( _, _) => cx. is_backend_scalar_pair ( ty) ,
@@ -144,6 +150,10 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
144
150
) -> Self {
145
151
let layout = bx. layout_of ( ty) ;
146
152
153
+ if val. all_bytes_uninit ( bx. tcx ( ) ) {
154
+ return OperandRef { val : OperandValue :: Uninit , layout } ;
155
+ }
156
+
147
157
let val = match val {
148
158
ConstValue :: Scalar ( x) => {
149
159
let BackendRepr :: Scalar ( scalar) = layout. backend_repr else {
@@ -442,6 +452,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
442
452
443
453
// Read the tag/niche-encoded discriminant from memory.
444
454
let tag_op = match self . val {
455
+ OperandValue :: Uninit => bug ! ( "shouldn't load from uninit" ) ,
445
456
OperandValue :: ZeroSized => bug ! ( ) ,
446
457
OperandValue :: Immediate ( _) | OperandValue :: Pair ( _, _) => {
447
458
self . extract_field ( fx, bx, tag_field. as_usize ( ) )
@@ -591,6 +602,28 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
591
602
}
592
603
593
604
impl < ' a , ' tcx , V : CodegenObject > OperandRef < ' tcx , Result < V , abi:: Scalar > > {
605
+ fn update_uninit < Bx : BuilderMethods < ' a , ' tcx , Value = V > > (
606
+ bx : & mut Bx ,
607
+ tgt : & mut Result < V , abi:: Scalar > ,
608
+ ) {
609
+ let to_scalar = tgt. unwrap_err ( ) ;
610
+ let bty = bx. cx ( ) . type_from_scalar ( to_scalar) ;
611
+ * tgt = Ok ( bx. const_undef ( bty) ) ;
612
+ }
613
+
614
+ fn update < Bx : BuilderMethods < ' a , ' tcx , Value = V > > (
615
+ bx : & mut Bx ,
616
+ tgt : & mut Result < V , abi:: Scalar > ,
617
+ src : V ,
618
+ from_scalar : rustc_abi:: Scalar ,
619
+ ) {
620
+ let from_bty = bx. cx ( ) . type_from_scalar ( from_scalar) ;
621
+ let to_scalar = tgt. unwrap_err ( ) ;
622
+ let to_bty = bx. cx ( ) . type_from_scalar ( to_scalar) ;
623
+ let imm = transmute_immediate ( bx, src, from_scalar, from_bty, to_scalar, to_bty) ;
624
+ * tgt = Ok ( imm) ;
625
+ }
626
+
594
627
pub ( crate ) fn insert_field < Bx : BuilderMethods < ' a , ' tcx , Value = V > > (
595
628
& mut self ,
596
629
bx : & mut Bx ,
@@ -614,37 +647,48 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, Result<V, abi::Scalar>> {
614
647
( field_layout. is_zst ( ) , field_offset == Size :: ZERO )
615
648
} ;
616
649
617
- let mut update = |tgt : & mut Result < V , abi:: Scalar > , src, from_scalar| {
618
- let from_bty = bx. cx ( ) . type_from_scalar ( from_scalar) ;
619
- let to_scalar = tgt. unwrap_err ( ) ;
620
- let to_bty = bx. cx ( ) . type_from_scalar ( to_scalar) ;
621
- let imm = transmute_immediate ( bx, src, from_scalar, from_bty, to_scalar, to_bty) ;
622
- * tgt = Ok ( imm) ;
623
- } ;
624
-
625
650
match ( operand. val , operand. layout . backend_repr ) {
626
651
( OperandValue :: ZeroSized , _) if expect_zst => { }
627
652
( OperandValue :: Immediate ( v) , BackendRepr :: Scalar ( from_scalar) ) => match & mut self . val {
628
653
OperandValue :: Immediate ( val @ Err ( _) ) if is_zero_offset => {
629
- update ( val, v, from_scalar) ;
654
+ Self :: update ( bx , val, v, from_scalar) ;
630
655
}
631
656
OperandValue :: Pair ( fst @ Err ( _) , _) if is_zero_offset => {
632
- update ( fst, v, from_scalar) ;
657
+ Self :: update ( bx , fst, v, from_scalar) ;
633
658
}
634
659
OperandValue :: Pair ( _, snd @ Err ( _) ) if !is_zero_offset => {
635
- update ( snd, v, from_scalar) ;
660
+ Self :: update ( bx, snd, v, from_scalar) ;
661
+ }
662
+ _ => bug ! ( "Tried to insert {operand:?} into {v:?}.{f:?} of {self:?}" ) ,
663
+ } ,
664
+ ( OperandValue :: Uninit , BackendRepr :: Scalar ( _) ) => match & mut self . val {
665
+ OperandValue :: Immediate ( val @ Err ( _) ) if is_zero_offset => {
666
+ Self :: update_uninit ( bx, val) ;
667
+ }
668
+ OperandValue :: Pair ( fst @ Err ( _) , _) if is_zero_offset => {
669
+ Self :: update_uninit ( bx, fst) ;
670
+ }
671
+ OperandValue :: Pair ( _, snd @ Err ( _) ) if !is_zero_offset => {
672
+ Self :: update_uninit ( bx, snd) ;
636
673
}
637
674
_ => bug ! ( "Tried to insert {operand:?} into {v:?}.{f:?} of {self:?}" ) ,
638
675
} ,
639
676
( OperandValue :: Pair ( a, b) , BackendRepr :: ScalarPair ( from_sa, from_sb) ) => {
640
677
match & mut self . val {
641
678
OperandValue :: Pair ( fst @ Err ( _) , snd @ Err ( _) ) => {
642
- update ( fst, a, from_sa) ;
643
- update ( snd, b, from_sb) ;
679
+ Self :: update ( bx , fst, a, from_sa) ;
680
+ Self :: update ( bx , snd, b, from_sb) ;
644
681
}
645
682
_ => bug ! ( "Tried to insert {operand:?} into {v:?}.{f:?} of {self:?}" ) ,
646
683
}
647
684
}
685
+ ( OperandValue :: Uninit , BackendRepr :: ScalarPair ( ..) ) => match & mut self . val {
686
+ OperandValue :: Pair ( fst @ Err ( _) , snd @ Err ( _) ) => {
687
+ Self :: update_uninit ( bx, fst) ;
688
+ Self :: update_uninit ( bx, snd) ;
689
+ }
690
+ _ => bug ! ( "Tried to insert {operand:?} into {v:?}.{f:?} of {self:?}" ) ,
691
+ } ,
648
692
_ => bug ! ( "Unsupported operand {operand:?} inserting into {v:?}.{f:?} of {self:?}" ) ,
649
693
}
650
694
}
@@ -663,6 +707,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, Result<V, abi::Scalar>> {
663
707
} ;
664
708
665
709
let val = match val {
710
+ OperandValue :: Uninit => OperandValue :: Uninit ,
666
711
OperandValue :: ZeroSized => OperandValue :: ZeroSized ,
667
712
OperandValue :: Immediate ( v) => OperandValue :: Immediate ( unwrap ( v) ) ,
668
713
OperandValue :: Pair ( a, b) => OperandValue :: Pair ( unwrap ( a) , unwrap ( b) ) ,
@@ -739,6 +784,13 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
739
784
) {
740
785
debug ! ( "OperandRef::store: operand={:?}, dest={:?}" , self , dest) ;
741
786
match self {
787
+ OperandValue :: Uninit => {
788
+ // Ideally we'd hint to the backend that the destination is deinitialized by the
789
+ // store. But in practice the destination is almost always uninit already because
790
+ // OperandValue::Uninit is pretty much only produced by MaybeUninit::uninit.
791
+ // Attempting to generate a hint by calling memset with undef mostly seems to
792
+ // confuse LLVM.
793
+ }
742
794
OperandValue :: ZeroSized => {
743
795
// Avoid generating stores of zero-sized values, because the only way to have a
744
796
// zero-sized value is through `undef`/`poison`, and the store itself is useless.
0 commit comments