@@ -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) ;
@@ -221,11 +223,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
221223 let OperandValueKind :: Immediate ( in_scalar) = operand_kind else {
222224 bug ! ( "Found {operand_kind:?} for operand {operand:?}" ) ;
223225 } ;
224- if let OperandValueKind :: Immediate ( out_scalar) = cast_kind {
226+ if let OperandValueKind :: Immediate ( out_scalar) = cast_kind
227+ && in_scalar. size ( self . cx ) == out_scalar. size ( self . cx )
228+ {
225229 let cast_bty = bx. backend_type ( cast) ;
226- Some ( OperandValue :: Immediate ( Self :: transmute_immediate (
227- bx, imm, in_scalar, out_scalar, cast_bty,
228- ) ) )
230+ Some ( OperandValue :: Immediate (
231+ self . transmute_immediate ( bx, imm, in_scalar, out_scalar, cast_bty) ,
232+ ) )
229233 } else {
230234 None
231235 }
@@ -234,12 +238,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
234238 let OperandValueKind :: Pair ( in_a, in_b) = operand_kind else {
235239 bug ! ( "Found {operand_kind:?} for operand {operand:?}" ) ;
236240 } ;
237- if let OperandValueKind :: Pair ( out_a, out_b) = cast_kind {
241+ if let OperandValueKind :: Pair ( out_a, out_b) = cast_kind
242+ && in_a. size ( self . cx ) == out_a. size ( self . cx )
243+ && in_b. size ( self . cx ) == out_b. size ( self . cx )
244+ {
238245 let out_a_ibty = bx. scalar_pair_element_backend_type ( cast, 0 , false ) ;
239246 let out_b_ibty = bx. scalar_pair_element_backend_type ( cast, 1 , false ) ;
240247 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) ,
248+ self . transmute_immediate ( bx, imm_a, in_a, out_a, out_a_ibty) ,
249+ self . transmute_immediate ( bx, imm_b, in_b, out_b, out_b_ibty) ,
243250 ) )
244251 } else {
245252 None
@@ -254,12 +261,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
254261 /// `to_backend_ty` must be the *non*-immediate backend type (so it will be
255262 /// `i8`, not `i1`, for `bool`-like types.)
256263 fn transmute_immediate (
264+ & self ,
257265 bx : & mut Bx ,
258266 mut imm : Bx :: Value ,
259267 from_scalar : abi:: Scalar ,
260268 to_scalar : abi:: Scalar ,
261269 to_backend_ty : Bx :: Type ,
262270 ) -> Bx :: Value {
271+ debug_assert_eq ! ( from_scalar. size( self . cx) , to_scalar. size( self . cx) ) ;
272+
263273 use abi:: Primitive :: * ;
264274 imm = bx. from_immediate ( imm) ;
265275 imm = match ( from_scalar. primitive ( ) , to_scalar. primitive ( ) ) {
@@ -831,14 +841,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
831841 let operand_ty = operand. ty ( self . mir , self . cx . tcx ( ) ) ;
832842 let cast_layout = self . cx . layout_of ( self . monomorphize ( cast_ty) ) ;
833843 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- }
842844
843845 match ( self . value_kind ( operand_layout) , self . value_kind ( cast_layout) ) {
844846 // Can always load from a pointer as needed
@@ -847,9 +849,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
847849 // Need to generate an `alloc` to get a pointer from an immediate
848850 ( OperandValueKind :: Immediate ( ..) | OperandValueKind :: Pair ( ..) , OperandValueKind :: Ref ) => false ,
849851
850- // When we have scalar immediates, we can convert them as needed
851- ( OperandValueKind :: Immediate ( ..) , OperandValueKind :: Immediate ( ..) ) |
852- ( OperandValueKind :: Pair ( ..) , OperandValueKind :: Pair ( ..) ) => true ,
852+ // When we have scalar immediates, we can only convert things
853+ // where the sizes match, to avoid endianness questions.
854+ ( OperandValueKind :: Immediate ( a) , OperandValueKind :: Immediate ( b) ) =>
855+ a. size ( self . cx ) == b. size ( self . cx ) ,
856+ ( OperandValueKind :: Pair ( a0, a1) , OperandValueKind :: Pair ( b0, b1) ) =>
857+ a0. size ( self . cx ) == b0. size ( self . cx ) && a1. size ( self . cx ) == b1. size ( self . cx ) ,
853858
854859 // Send mixings between scalars and pairs through the memory route
855860 // FIXME: Maybe this could use insertvalue/extractvalue instead?
0 commit comments