@@ -158,17 +158,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
158
158
debug_assert ! ( src. layout. is_sized( ) ) ;
159
159
debug_assert ! ( dst. layout. is_sized( ) ) ;
160
160
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
-
172
161
if let Some ( val) = self . codegen_transmute_operand ( bx, src, dst. layout ) {
173
162
val. store ( bx, dst) ;
174
163
return ;
@@ -202,8 +191,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
202
191
operand : OperandRef < ' tcx , Bx :: Value > ,
203
192
cast : TyAndLayout < ' tcx > ,
204
193
) -> 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
+ }
207
209
208
210
let operand_kind = self . value_kind ( operand. layout ) ;
209
211
let cast_kind = self . value_kind ( cast) ;
@@ -221,11 +223,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
221
223
let OperandValueKind :: Immediate ( in_scalar) = operand_kind else {
222
224
bug ! ( "Found {operand_kind:?} for operand {operand:?}" ) ;
223
225
} ;
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
+ {
225
229
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
+ ) )
229
233
} else {
230
234
None
231
235
}
@@ -234,12 +238,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
234
238
let OperandValueKind :: Pair ( in_a, in_b) = operand_kind else {
235
239
bug ! ( "Found {operand_kind:?} for operand {operand:?}" ) ;
236
240
} ;
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
+ {
238
245
let out_a_ibty = bx. scalar_pair_element_backend_type ( cast, 0 , false ) ;
239
246
let out_b_ibty = bx. scalar_pair_element_backend_type ( cast, 1 , false ) ;
240
247
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) ,
243
250
) )
244
251
} else {
245
252
None
@@ -254,12 +261,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
254
261
/// `to_backend_ty` must be the *non*-immediate backend type (so it will be
255
262
/// `i8`, not `i1`, for `bool`-like types.)
256
263
fn transmute_immediate (
264
+ & self ,
257
265
bx : & mut Bx ,
258
266
mut imm : Bx :: Value ,
259
267
from_scalar : abi:: Scalar ,
260
268
to_scalar : abi:: Scalar ,
261
269
to_backend_ty : Bx :: Type ,
262
270
) -> Bx :: Value {
271
+ debug_assert_eq ! ( from_scalar. size( self . cx) , to_scalar. size( self . cx) ) ;
272
+
263
273
use abi:: Primitive :: * ;
264
274
imm = bx. from_immediate ( imm) ;
265
275
imm = match ( from_scalar. primitive ( ) , to_scalar. primitive ( ) ) {
@@ -831,14 +841,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
831
841
let operand_ty = operand. ty ( self . mir , self . cx . tcx ( ) ) ;
832
842
let cast_layout = self . cx . layout_of ( self . monomorphize ( cast_ty) ) ;
833
843
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
- }
842
844
843
845
match ( self . value_kind ( operand_layout) , self . value_kind ( cast_layout) ) {
844
846
// Can always load from a pointer as needed
@@ -847,9 +849,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
847
849
// Need to generate an `alloc` to get a pointer from an immediate
848
850
( OperandValueKind :: Immediate ( ..) | OperandValueKind :: Pair ( ..) , OperandValueKind :: Ref ) => false ,
849
851
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 ) ,
853
858
854
859
// Send mixings between scalars and pairs through the memory route
855
860
// FIXME: Maybe this could use insertvalue/extractvalue instead?
0 commit comments