@@ -45,6 +45,14 @@ pub enum OperandValue<V> {
4545 /// as returned by [`LayoutTypeMethods::scalar_pair_element_backend_type`]
4646 /// with `immediate: true`.
4747 Pair ( V , V ) ,
48+ /// A value taking no bytes, and which therefore needs no LLVM value at all.
49+ ///
50+ /// If you ever need a `V` to pass to something, get a fresh poison value
51+ /// from [`ConstMethods::const_poison`].
52+ ///
53+ /// An `OperandValue` *must* be this variant for any type for which
54+ /// `is_zst` on its `Layout` returns `true`.
55+ ZeroSized ,
4856}
4957
5058/// An `OperandRef` is an "SSA" reference to a Rust value, along with
@@ -71,15 +79,9 @@ impl<V: CodegenObject> fmt::Debug for OperandRef<'_, V> {
7179}
7280
7381impl < ' a , ' tcx , V : CodegenObject > OperandRef < ' tcx , V > {
74- pub fn new_zst < Bx : BuilderMethods < ' a , ' tcx , Value = V > > (
75- bx : & mut Bx ,
76- layout : TyAndLayout < ' tcx > ,
77- ) -> OperandRef < ' tcx , V > {
82+ pub fn zero_sized ( layout : TyAndLayout < ' tcx > ) -> OperandRef < ' tcx , V > {
7883 assert ! ( layout. is_zst( ) ) ;
79- OperandRef {
80- val : OperandValue :: Immediate ( bx. const_poison ( bx. immediate_backend_type ( layout) ) ) ,
81- layout,
82- }
84+ OperandRef { val : OperandValue :: ZeroSized , layout }
8385 }
8486
8587 pub fn from_const < Bx : BuilderMethods < ' a , ' tcx , Value = V > > (
@@ -97,7 +99,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
9799 let llval = bx. scalar_to_backend ( x, scalar, bx. immediate_backend_type ( layout) ) ;
98100 OperandValue :: Immediate ( llval)
99101 }
100- ConstValue :: ZeroSized => return OperandRef :: new_zst ( bx , layout) ,
102+ ConstValue :: ZeroSized => return OperandRef :: zero_sized ( layout) ,
101103 ConstValue :: Slice { data, start, end } => {
102104 let Abi :: ScalarPair ( a_scalar, _) = layout. abi else {
103105 bug ! ( "from_const: invalid ScalarPair layout: {:#?}" , layout) ;
@@ -178,7 +180,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
178180 ) ;
179181 OperandRef { val : OperandValue :: Pair ( a_val, b_val) , layout }
180182 }
181- _ if layout. is_zst ( ) => OperandRef :: new_zst ( bx , layout) ,
183+ _ if layout. is_zst ( ) => OperandRef :: zero_sized ( layout) ,
182184 _ => {
183185 // Neither a scalar nor scalar pair. Load from a place
184186 let init = bx. const_data_from_alloc ( alloc) ;
@@ -216,6 +218,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
216218 OperandValue :: Immediate ( llptr) => ( llptr, None ) ,
217219 OperandValue :: Pair ( llptr, llextra) => ( llptr, Some ( llextra) ) ,
218220 OperandValue :: Ref ( ..) => bug ! ( "Deref of by-Ref operand {:?}" , self ) ,
221+ OperandValue :: ZeroSized => bug ! ( "Deref of ZST operand {:?}" , self ) ,
219222 } ;
220223 let layout = cx. layout_of ( projected_ty) ;
221224 PlaceRef { llval : llptr, llextra, layout, align : layout. align . abi }
@@ -273,9 +276,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
273276
274277 let mut val = match ( self . val , self . layout . abi ) {
275278 // If the field is ZST, it has no data.
276- _ if field. is_zst ( ) => {
277- return OperandRef :: new_zst ( bx, field) ;
278- }
279+ _ if field. is_zst ( ) => OperandValue :: ZeroSized ,
279280
280281 // Newtype of a scalar, scalar pair or vector.
281282 ( OperandValue :: Immediate ( _) | OperandValue :: Pair ( ..) , _)
@@ -306,6 +307,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
306307 } ;
307308
308309 match ( & mut val, field. abi ) {
310+ ( OperandValue :: ZeroSized , _) => { }
309311 (
310312 OperandValue :: Immediate ( llval) ,
311313 Abi :: Scalar ( _) | Abi :: ScalarPair ( ..) | Abi :: Vector { .. } ,
@@ -359,16 +361,18 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
359361impl < ' a , ' tcx , V : CodegenObject > OperandValue < V > {
360362 /// Returns an `OperandValue` that's generally UB to use in any way.
361363 ///
362- /// Depending on the `layout`, returns an `Immediate` or `Pair` containing
363- /// poison value(s), or a `Ref` containing a poison pointer.
364+ /// Depending on the `layout`, returns `ZeroSized` for ZSTs, an `Immediate` or
365+ /// `Pair` containing poison value(s), or a `Ref` containing a poison pointer.
364366 ///
365367 /// Supports sized types only.
366368 pub fn poison < Bx : BuilderMethods < ' a , ' tcx , Value = V > > (
367369 bx : & mut Bx ,
368370 layout : TyAndLayout < ' tcx > ,
369371 ) -> OperandValue < V > {
370372 assert ! ( layout. is_sized( ) ) ;
371- if bx. cx ( ) . is_backend_immediate ( layout) {
373+ if layout. is_zst ( ) {
374+ OperandValue :: ZeroSized
375+ } else if bx. cx ( ) . is_backend_immediate ( layout) {
372376 let ibty = bx. cx ( ) . immediate_backend_type ( layout) ;
373377 OperandValue :: Immediate ( bx. const_poison ( ibty) )
374378 } else if bx. cx ( ) . is_backend_scalar_pair ( layout) {
@@ -421,12 +425,11 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
421425 flags : MemFlags ,
422426 ) {
423427 debug ! ( "OperandRef::store: operand={:?}, dest={:?}" , self , dest) ;
424- // Avoid generating stores of zero-sized values, because the only way to have a zero-sized
425- // value is through `undef`, and store itself is useless.
426- if dest. layout . is_zst ( ) {
427- return ;
428- }
429428 match self {
429+ OperandValue :: ZeroSized => {
430+ // Avoid generating stores of zero-sized values, because the only way to have a zero-sized
431+ // value is through `undef`/`poison`, and the store itself is useless.
432+ }
430433 OperandValue :: Ref ( r, None , source_align) => {
431434 if flags. contains ( MemFlags :: NONTEMPORAL ) {
432435 // HACK(nox): This is inefficient but there is no nontemporal memcpy.
@@ -527,7 +530,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
527530 // checks in `codegen_consume` and `extract_field`.
528531 let elem = o. layout . field ( bx. cx ( ) , 0 ) ;
529532 if elem. is_zst ( ) {
530- o = OperandRef :: new_zst ( bx , elem) ;
533+ o = OperandRef :: zero_sized ( elem) ;
531534 } else {
532535 return None ;
533536 }
@@ -561,7 +564,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
561564
562565 // ZSTs don't require any actual memory access.
563566 if layout. is_zst ( ) {
564- return OperandRef :: new_zst ( bx , layout) ;
567+ return OperandRef :: zero_sized ( layout) ;
565568 }
566569
567570 if let Some ( o) = self . maybe_codegen_consume_direct ( bx, place_ref) {
0 commit comments