@@ -9,7 +9,6 @@ use crate::MemFlags;
9
9
10
10
use rustc_hir as hir;
11
11
use rustc_middle:: mir;
12
- use rustc_middle:: ty:: cast:: { CastTy , IntTy } ;
13
12
use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf , TyAndLayout } ;
14
13
use rustc_middle:: ty:: { self , adjustment:: PointerCoercion , Instance , Ty , TyCtxt } ;
15
14
use rustc_middle:: { bug, span_bug} ;
@@ -234,21 +233,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
234
233
}
235
234
}
236
235
OperandValue :: Immediate ( imm) => {
237
- let OperandValueKind :: Immediate ( in_scalar ) = operand_kind else {
236
+ let OperandValueKind :: Immediate ( from_scalar ) = operand_kind else {
238
237
bug ! ( "Found {operand_kind:?} for operand {operand:?}" ) ;
239
238
} ;
240
- if let OperandValueKind :: Immediate ( out_scalar ) = cast_kind
241
- && in_scalar . size ( self . cx ) == out_scalar . size ( self . cx )
239
+ if let OperandValueKind :: Immediate ( to_scalar ) = cast_kind
240
+ && from_scalar . size ( self . cx ) == to_scalar . size ( self . cx )
242
241
{
243
- let operand_bty = bx. backend_type ( operand. layout ) ;
244
- let cast_bty = bx. backend_type ( cast) ;
242
+ let from_backend_ty = bx. backend_type ( operand. layout ) ;
243
+ let to_backend_ty = bx. backend_type ( cast) ;
245
244
Some ( OperandValue :: Immediate ( self . transmute_immediate (
246
245
bx,
247
246
imm,
248
- in_scalar ,
249
- operand_bty ,
250
- out_scalar ,
251
- cast_bty ,
247
+ from_scalar ,
248
+ from_backend_ty ,
249
+ to_scalar ,
250
+ to_backend_ty ,
252
251
) ) )
253
252
} else {
254
253
None
@@ -277,6 +276,57 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
277
276
}
278
277
}
279
278
279
+ /// Cast one of the immediates from an [`OperandValue::Immediate`]
280
+ /// or an [`OperandValue::Pair`] to an immediate of the target type.
281
+ fn cast_immediate (
282
+ & self ,
283
+ bx : & mut Bx ,
284
+ mut imm : Bx :: Value ,
285
+ from_scalar : abi:: Scalar ,
286
+ from_backend_ty : Bx :: Type ,
287
+ to_scalar : abi:: Scalar ,
288
+ to_backend_ty : Bx :: Type ,
289
+ ) -> Option < Bx :: Value > {
290
+ use abi:: Primitive :: * ;
291
+
292
+ // When scalars are passed by value, there's no metadata recording their
293
+ // valid ranges. For example, `char`s are passed as just `i32`, with no
294
+ // way for LLVM to know that they're 0x10FFFF at most. Thus we assume
295
+ // the range of the input value too, not just the output range.
296
+ self . assume_scalar_range ( bx, imm, from_scalar, from_backend_ty) ;
297
+
298
+ imm = match ( from_scalar. primitive ( ) , to_scalar. primitive ( ) ) {
299
+ ( Int ( _, is_signed) , Int ( ..) ) => bx. intcast ( imm, to_backend_ty, is_signed) ,
300
+ ( Float ( _) , Float ( _) ) => {
301
+ let srcsz = bx. cx ( ) . float_width ( from_backend_ty) ;
302
+ let dstsz = bx. cx ( ) . float_width ( to_backend_ty) ;
303
+ if dstsz > srcsz {
304
+ bx. fpext ( imm, to_backend_ty)
305
+ } else if srcsz > dstsz {
306
+ bx. fptrunc ( imm, to_backend_ty)
307
+ } else {
308
+ imm
309
+ }
310
+ }
311
+ ( Int ( _, is_signed) , Float ( _) ) => {
312
+ if is_signed {
313
+ bx. sitofp ( imm, to_backend_ty)
314
+ } else {
315
+ bx. uitofp ( imm, to_backend_ty)
316
+ }
317
+ }
318
+ ( Pointer ( ..) , Pointer ( ..) ) => bx. pointercast ( imm, to_backend_ty) ,
319
+ ( Int ( _, is_signed) , Pointer ( ..) ) => {
320
+ let usize_imm = bx. intcast ( imm, bx. cx ( ) . type_isize ( ) , is_signed) ;
321
+ bx. inttoptr ( usize_imm, to_backend_ty)
322
+ }
323
+ ( Float ( _) , Int ( _, is_signed) ) => bx. cast_float_to_int ( is_signed, imm, to_backend_ty) ,
324
+ _ => return None ,
325
+ } ;
326
+ self . assume_scalar_range ( bx, imm, to_scalar, to_backend_ty) ;
327
+ Some ( imm)
328
+ }
329
+
280
330
/// Transmutes one of the immediates from an [`OperandValue::Immediate`]
281
331
/// or an [`OperandValue::Pair`] to an immediate of the target type.
282
332
///
@@ -482,62 +532,33 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
482
532
| mir:: CastKind :: IntToFloat
483
533
| mir:: CastKind :: PtrToPtr
484
534
| mir:: CastKind :: FnPtrToPtr
485
-
486
535
// Since int2ptr can have arbitrary integer types as input (so we have to do
487
536
// sign extension and all that), it is currently best handled in the same code
488
537
// path as the other integer-to-X casts.
489
538
| mir:: CastKind :: PointerWithExposedProvenance => {
539
+ let imm = operand. immediate ( ) ;
540
+ let operand_kind = self . value_kind ( operand. layout ) ;
541
+ let OperandValueKind :: Immediate ( from_scalar) = operand_kind else {
542
+ bug ! ( "Found {operand_kind:?} for operand {operand:?}" ) ;
543
+ } ;
544
+ let from_backend_ty = bx. cx ( ) . immediate_backend_type ( operand. layout ) ;
545
+
490
546
assert ! ( bx. cx( ) . is_backend_immediate( cast) ) ;
491
- let ll_t_out = bx. cx ( ) . immediate_backend_type ( cast) ;
547
+ let to_backend_ty = bx. cx ( ) . immediate_backend_type ( cast) ;
492
548
if operand. layout . abi . is_uninhabited ( ) {
493
- let val = OperandValue :: Immediate ( bx. cx ( ) . const_poison ( ll_t_out ) ) ;
549
+ let val = OperandValue :: Immediate ( bx. cx ( ) . const_poison ( to_backend_ty ) ) ;
494
550
return OperandRef { val, layout : cast } ;
495
551
}
496
- let r_t_in =
497
- CastTy :: from_ty ( operand. layout . ty ) . expect ( "bad input type for cast" ) ;
498
- let r_t_out = CastTy :: from_ty ( cast. ty ) . expect ( "bad output type for cast" ) ;
499
- let ll_t_in = bx. cx ( ) . immediate_backend_type ( operand. layout ) ;
500
- let llval = operand. immediate ( ) ;
501
-
502
- let newval = match ( r_t_in, r_t_out) {
503
- ( CastTy :: Int ( i) , CastTy :: Int ( _) ) => {
504
- bx. intcast ( llval, ll_t_out, i. is_signed ( ) )
505
- }
506
- ( CastTy :: Float , CastTy :: Float ) => {
507
- let srcsz = bx. cx ( ) . float_width ( ll_t_in) ;
508
- let dstsz = bx. cx ( ) . float_width ( ll_t_out) ;
509
- if dstsz > srcsz {
510
- bx. fpext ( llval, ll_t_out)
511
- } else if srcsz > dstsz {
512
- bx. fptrunc ( llval, ll_t_out)
513
- } else {
514
- llval
515
- }
516
- }
517
- ( CastTy :: Int ( i) , CastTy :: Float ) => {
518
- if i. is_signed ( ) {
519
- bx. sitofp ( llval, ll_t_out)
520
- } else {
521
- bx. uitofp ( llval, ll_t_out)
522
- }
523
- }
524
- ( CastTy :: Ptr ( _) | CastTy :: FnPtr , CastTy :: Ptr ( _) ) => {
525
- bx. pointercast ( llval, ll_t_out)
526
- }
527
- ( CastTy :: Int ( i) , CastTy :: Ptr ( _) ) => {
528
- let usize_llval =
529
- bx. intcast ( llval, bx. cx ( ) . type_isize ( ) , i. is_signed ( ) ) ;
530
- bx. inttoptr ( usize_llval, ll_t_out)
531
- }
532
- ( CastTy :: Float , CastTy :: Int ( IntTy :: I ) ) => {
533
- bx. cast_float_to_int ( true , llval, ll_t_out)
534
- }
535
- ( CastTy :: Float , CastTy :: Int ( _) ) => {
536
- bx. cast_float_to_int ( false , llval, ll_t_out)
537
- }
538
- _ => bug ! ( "unsupported cast: {:?} to {:?}" , operand. layout. ty, cast. ty) ,
552
+ let cast_kind = self . value_kind ( cast) ;
553
+ let OperandValueKind :: Immediate ( to_scalar) = cast_kind else {
554
+ bug ! ( "Found {cast_kind:?} for operand {cast:?}" ) ;
539
555
} ;
540
- OperandValue :: Immediate ( newval)
556
+
557
+ self . cast_immediate ( bx, imm, from_scalar, from_backend_ty, to_scalar, to_backend_ty)
558
+ . map ( OperandValue :: Immediate )
559
+ . unwrap_or_else ( || {
560
+ bug ! ( "Unsupported cast of {operand:?} to {cast:?}" ) ;
561
+ } )
541
562
}
542
563
mir:: CastKind :: Transmute => {
543
564
self . codegen_transmute_operand ( bx, operand, cast) . unwrap_or_else ( || {
0 commit comments