@@ -158,17 +158,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
158158        debug_assert ! ( src. layout. is_sized( ) ) ; 
159159        debug_assert ! ( dst. layout. is_sized( ) ) ; 
160160
161-         if  src. layout . size  != dst. layout . size 
162-             || src. layout . abi . is_uninhabited ( ) 
163-             || dst. layout . abi . is_uninhabited ( ) 
164-         { 
165-             // In all of these cases it's UB to run this transmute, but that's 
166-             // known statically so might as well trap for it, rather than just 
167-             // making it unreachable. 
168-             bx. abort ( ) ; 
169-             return ; 
170-         } 
171- 
172161        if  let  Some ( val)  = self . codegen_transmute_operand ( bx,  src,  dst. layout )  { 
173162            val. store ( bx,  dst) ; 
174163            return ; 
@@ -202,8 +191,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
202191        operand :  OperandRef < ' tcx ,  Bx :: Value > , 
203192        cast :  TyAndLayout < ' tcx > , 
204193    )  -> Option < OperandValue < Bx :: Value > >  { 
205-         // Callers already checked that the layout sizes match 
206-         debug_assert_eq ! ( operand. layout. size,  cast. size) ; 
194+         // Check for transmutes that are always UB. 
195+         if  operand. layout . size  != cast. size 
196+             || operand. layout . abi . is_uninhabited ( ) 
197+             || cast. abi . is_uninhabited ( ) 
198+         { 
199+             if  !operand. layout . abi . is_uninhabited ( )  { 
200+                 // Since this is known statically and the input could have existed 
201+                 // without already having hit UB, might as well trap for it. 
202+                 bx. abort ( ) ; 
203+             } 
204+ 
205+             // Because this transmute is UB, return something easy to generate, 
206+             // since it's fine that later uses of the value are probably UB. 
207+             return  Some ( OperandValue :: poison ( bx,  cast) ) ; 
208+         } 
207209
208210        let  operand_kind = self . value_kind ( operand. layout ) ; 
209211        let  cast_kind = self . value_kind ( cast) ; 
@@ -222,10 +224,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
222224                    bug ! ( "Found {operand_kind:?} for operand {operand:?}" ) ; 
223225                } ; 
224226                if  let  OperandValueKind :: Immediate ( out_scalar)  = cast_kind { 
225-                     let  cast_bty = bx. backend_type ( cast) ; 
226-                     Some ( OperandValue :: Immediate ( Self :: transmute_immediate ( 
227-                         bx,  imm,  in_scalar,  out_scalar,  cast_bty, 
228-                     ) ) ) 
227+                     match  ( in_scalar,  out_scalar)  { 
228+                         ( ScalarOrZst :: Zst ,  ScalarOrZst :: Zst )  => { 
229+                             Some ( OperandRef :: new_zst ( bx,  cast) . val ) 
230+                         } 
231+                         ( ScalarOrZst :: Scalar ( in_scalar) ,  ScalarOrZst :: Scalar ( out_scalar) ) 
232+                             if  in_scalar. size ( self . cx )  == out_scalar. size ( self . cx )  =>
233+                         { 
234+                             let  cast_bty = bx. backend_type ( cast) ; 
235+                             Some ( OperandValue :: Immediate ( 
236+                                 self . transmute_immediate ( bx,  imm,  in_scalar,  out_scalar,  cast_bty) , 
237+                             ) ) 
238+                         } 
239+                         _ => None , 
240+                     } 
229241                }  else  { 
230242                    None 
231243                } 
@@ -234,12 +246,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
234246                let  OperandValueKind :: Pair ( in_a,  in_b)  = operand_kind else  { 
235247                    bug ! ( "Found {operand_kind:?} for operand {operand:?}" ) ; 
236248                } ; 
237-                 if  let  OperandValueKind :: Pair ( out_a,  out_b)  = cast_kind { 
249+                 if  let  OperandValueKind :: Pair ( out_a,  out_b)  = cast_kind
250+                     && in_a. size ( self . cx )  == out_a. size ( self . cx ) 
251+                     && in_b. size ( self . cx )  == out_b. size ( self . cx ) 
252+                 { 
238253                    let  out_a_ibty = bx. scalar_pair_element_backend_type ( cast,  0 ,  false ) ; 
239254                    let  out_b_ibty = bx. scalar_pair_element_backend_type ( cast,  1 ,  false ) ; 
240255                    Some ( OperandValue :: Pair ( 
241-                         Self :: transmute_immediate ( bx,  imm_a,  in_a,  out_a,  out_a_ibty) , 
242-                         Self :: transmute_immediate ( bx,  imm_b,  in_b,  out_b,  out_b_ibty) , 
256+                         self . transmute_immediate ( bx,  imm_a,  in_a,  out_a,  out_a_ibty) , 
257+                         self . transmute_immediate ( bx,  imm_b,  in_b,  out_b,  out_b_ibty) , 
243258                    ) ) 
244259                }  else  { 
245260                    None 
@@ -254,12 +269,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
254269/// `to_backend_ty` must be the *non*-immediate backend type (so it will be 
255270/// `i8`, not `i1`, for `bool`-like types.) 
256271fn  transmute_immediate ( 
272+         & self , 
257273        bx :  & mut  Bx , 
258274        mut  imm :  Bx :: Value , 
259275        from_scalar :  abi:: Scalar , 
260276        to_scalar :  abi:: Scalar , 
261277        to_backend_ty :  Bx :: Type , 
262278    )  -> Bx :: Value  { 
279+         debug_assert_eq ! ( from_scalar. size( self . cx) ,  to_scalar. size( self . cx) ) ; 
280+ 
263281        use  abi:: Primitive :: * ; 
264282        imm = bx. from_immediate ( imm) ; 
265283        imm = match  ( from_scalar. primitive ( ) ,  to_scalar. primitive ( ) )  { 
@@ -831,14 +849,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
831849                let  operand_ty = operand. ty ( self . mir ,  self . cx . tcx ( ) ) ; 
832850                let  cast_layout = self . cx . layout_of ( self . monomorphize ( cast_ty) ) ; 
833851                let  operand_layout = self . cx . layout_of ( self . monomorphize ( operand_ty) ) ; 
834-                 if  operand_layout. size  != cast_layout. size 
835-                     || operand_layout. abi . is_uninhabited ( ) 
836-                     || cast_layout. abi . is_uninhabited ( ) 
837-                 { 
838-                     // Send UB cases to the full form so the operand version can 
839-                     // `bitcast` without worrying about malformed IR. 
840-                     return  false ; 
841-                 } 
842852
843853                match  ( self . value_kind ( operand_layout) ,  self . value_kind ( cast_layout) )  { 
844854                    // Can always load from a pointer as needed 
@@ -847,9 +857,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
847857                    // Need to generate an `alloc` to get a pointer from an immediate 
848858                    ( OperandValueKind :: Immediate ( ..)  | OperandValueKind :: Pair ( ..) ,  OperandValueKind :: Ref )  => false , 
849859
850-                     // When we have scalar immediates, we can convert them as needed 
851-                     ( OperandValueKind :: Immediate ( ..) ,  OperandValueKind :: Immediate ( ..) )  |
852-                     ( OperandValueKind :: Pair ( ..) ,  OperandValueKind :: Pair ( ..) )  => true , 
860+                     // When we have scalar immediates, we can only convert things 
861+                     // where the sizes match, to avoid endianness questions. 
862+                     ( OperandValueKind :: Immediate ( a) ,  OperandValueKind :: Immediate ( b) )  =>
863+                         a. size ( self . cx )  == b. size ( self . cx ) , 
864+                     ( OperandValueKind :: Pair ( a0,  a1) ,  OperandValueKind :: Pair ( b0,  b1) )  =>
865+                         a0. size ( self . cx )  == b0. size ( self . cx )  && a1. size ( self . cx )  == b1. size ( self . cx ) , 
853866
854867                    // Send mixings between scalars and pairs through the memory route 
855868                    // FIXME: Maybe this could use insertvalue/extractvalue instead? 
@@ -887,13 +900,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
887900        if  self . cx . is_backend_immediate ( layout)  { 
888901            debug_assert ! ( !self . cx. is_backend_scalar_pair( layout) ) ; 
889902            OperandValueKind :: Immediate ( match  layout. abi  { 
890-                 abi:: Abi :: Scalar ( s)  => s, 
891-                 abi:: Abi :: Vector  {  element,  .. }  => element, 
892-                 x => bug ! ( "Couldn't translate {x:?} as backend immediate" ) , 
903+                 abi:: Abi :: Scalar ( s)  => ScalarOrZst :: Scalar ( s) , 
904+                 abi:: Abi :: Vector  {  element,  .. }  => ScalarOrZst :: Scalar ( element) , 
905+                 _ if  layout. is_zst ( )  => ScalarOrZst :: Zst , 
906+                 x => span_bug ! ( self . mir. span,  "Couldn't translate {x:?} as backend immediate" ) , 
893907            } ) 
894908        }  else  if  self . cx . is_backend_scalar_pair ( layout)  { 
895909            let  abi:: Abi :: ScalarPair ( s1,  s2)  = layout. abi  else  { 
896-                 bug ! ( "Couldn't translate {:?} as backend scalar pair" ,  layout. abi) 
910+                 span_bug ! ( 
911+                     self . mir. span, 
912+                     "Couldn't translate {:?} as backend scalar pair" , 
913+                     layout. abi, 
914+                 ) ; 
897915            } ; 
898916            OperandValueKind :: Pair ( s1,  s2) 
899917        }  else  { 
@@ -902,9 +920,26 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
902920    } 
903921} 
904922
923+ /// The variants of this match [`OperandValue`], giving details about the 
924+ /// backend values that will be held in that other type. 
905925#[ derive( Debug ,  Copy ,  Clone ) ]  
906926enum  OperandValueKind  { 
907927    Ref , 
908-     Immediate ( abi :: Scalar ) , 
928+     Immediate ( ScalarOrZst ) , 
909929    Pair ( abi:: Scalar ,  abi:: Scalar ) , 
910930} 
931+ 
932+ #[ derive( Debug ,  Copy ,  Clone ) ]  
933+ enum  ScalarOrZst  { 
934+     Zst , 
935+     Scalar ( abi:: Scalar ) , 
936+ } 
937+ 
938+ impl  ScalarOrZst  { 
939+     pub  fn  size ( self ,  cx :  & impl  abi:: HasDataLayout )  -> abi:: Size  { 
940+         match  self  { 
941+             ScalarOrZst :: Zst  => abi:: Size :: ZERO , 
942+             ScalarOrZst :: Scalar ( s)  => s. size ( cx) , 
943+         } 
944+     } 
945+ } 
0 commit comments