@@ -9,7 +9,6 @@ use crate::MemFlags;
9
9
10
10
use rustc_hir as hir;
11
11
use rustc_middle:: mir:: { self , AggregateKind , Operand } ;
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} ;
@@ -237,21 +236,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
237
236
}
238
237
}
239
238
OperandValue :: Immediate ( imm) => {
240
- let OperandValueKind :: Immediate ( in_scalar ) = operand_kind else {
239
+ let OperandValueKind :: Immediate ( from_scalar ) = operand_kind else {
241
240
bug ! ( "Found {operand_kind:?} for operand {operand:?}" ) ;
242
241
} ;
243
- if let OperandValueKind :: Immediate ( out_scalar ) = cast_kind
244
- && in_scalar . size ( self . cx ) == out_scalar . size ( self . cx )
242
+ if let OperandValueKind :: Immediate ( to_scalar ) = cast_kind
243
+ && from_scalar . size ( self . cx ) == to_scalar . size ( self . cx )
245
244
{
246
- let operand_bty = bx. backend_type ( operand. layout ) ;
247
- let cast_bty = bx. backend_type ( cast) ;
245
+ let from_backend_ty = bx. backend_type ( operand. layout ) ;
246
+ let to_backend_ty = bx. backend_type ( cast) ;
248
247
Some ( OperandValue :: Immediate ( self . transmute_immediate (
249
248
bx,
250
249
imm,
251
- in_scalar ,
252
- operand_bty ,
253
- out_scalar ,
254
- cast_bty ,
250
+ from_scalar ,
251
+ from_backend_ty ,
252
+ to_scalar ,
253
+ to_backend_ty ,
255
254
) ) )
256
255
} else {
257
256
None
@@ -280,6 +279,59 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
280
279
}
281
280
}
282
281
282
+ /// Cast one of the immediates from an [`OperandValue::Immediate`]
283
+ /// or an [`OperandValue::Pair`] to an immediate of the target type.
284
+ fn cast_immediate (
285
+ & self ,
286
+ bx : & mut Bx ,
287
+ mut imm : Bx :: Value ,
288
+ from_scalar : abi:: Scalar ,
289
+ from_backend_ty : Bx :: Type ,
290
+ to_scalar : abi:: Scalar ,
291
+ to_backend_ty : Bx :: Type ,
292
+ ) -> Option < Bx :: Value > {
293
+ use abi:: Primitive :: * ;
294
+
295
+ // When scalars are passed by value, there's no metadata recording their
296
+ // valid ranges. For example, `char`s are passed as just `i32`, with no
297
+ // way for LLVM to know that they're 0x10FFFF at most. Thus we assume
298
+ // the range of the input value too, not just the output range.
299
+ self . assume_scalar_range ( bx, imm, from_scalar, from_backend_ty) ;
300
+
301
+ imm = match ( from_scalar. primitive ( ) , to_scalar. primitive ( ) ) {
302
+ ( Int ( _, is_signed) , Int ( ..) ) => bx. intcast ( imm, to_backend_ty, is_signed) ,
303
+ ( F16 | F32 | F64 | F128 , F16 | F32 | F64 | F128 ) => {
304
+ let srcsz = bx. cx ( ) . float_width ( from_backend_ty) ;
305
+ let dstsz = bx. cx ( ) . float_width ( to_backend_ty) ;
306
+ if dstsz > srcsz {
307
+ bx. fpext ( imm, to_backend_ty)
308
+ } else if srcsz > dstsz {
309
+ bx. fptrunc ( imm, to_backend_ty)
310
+ } else {
311
+ imm
312
+ }
313
+ }
314
+ ( Int ( _, is_signed) , F16 | F32 | F64 | F128 ) => {
315
+ if is_signed {
316
+ bx. sitofp ( imm, to_backend_ty)
317
+ } else {
318
+ bx. uitofp ( imm, to_backend_ty)
319
+ }
320
+ }
321
+ ( Pointer ( ..) , Pointer ( ..) ) => bx. pointercast ( imm, to_backend_ty) ,
322
+ ( Int ( _, is_signed) , Pointer ( ..) ) => {
323
+ let usize_imm = bx. intcast ( imm, bx. cx ( ) . type_isize ( ) , is_signed) ;
324
+ bx. inttoptr ( usize_imm, to_backend_ty)
325
+ }
326
+ ( F16 | F32 | F64 | F128 , Int ( _, is_signed) ) => {
327
+ bx. cast_float_to_int ( is_signed, imm, to_backend_ty)
328
+ }
329
+ _ => return None ,
330
+ } ;
331
+ self . assume_scalar_range ( bx, imm, to_scalar, to_backend_ty) ;
332
+ Some ( imm)
333
+ }
334
+
283
335
/// Transmutes one of the immediates from an [`OperandValue::Immediate`]
284
336
/// or an [`OperandValue::Pair`] to an immediate of the target type.
285
337
///
@@ -508,62 +560,33 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
508
560
| mir:: CastKind :: IntToFloat
509
561
| mir:: CastKind :: PtrToPtr
510
562
| mir:: CastKind :: FnPtrToPtr
511
-
512
563
// Since int2ptr can have arbitrary integer types as input (so we have to do
513
564
// sign extension and all that), it is currently best handled in the same code
514
565
// path as the other integer-to-X casts.
515
566
| mir:: CastKind :: PointerWithExposedProvenance => {
567
+ let imm = operand. immediate ( ) ;
568
+ let operand_kind = self . value_kind ( operand. layout ) ;
569
+ let OperandValueKind :: Immediate ( from_scalar) = operand_kind else {
570
+ bug ! ( "Found {operand_kind:?} for operand {operand:?}" ) ;
571
+ } ;
572
+ let from_backend_ty = bx. cx ( ) . immediate_backend_type ( operand. layout ) ;
573
+
516
574
assert ! ( bx. cx( ) . is_backend_immediate( cast) ) ;
517
- let ll_t_out = bx. cx ( ) . immediate_backend_type ( cast) ;
575
+ let to_backend_ty = bx. cx ( ) . immediate_backend_type ( cast) ;
518
576
if operand. layout . abi . is_uninhabited ( ) {
519
- let val = OperandValue :: Immediate ( bx. cx ( ) . const_poison ( ll_t_out ) ) ;
577
+ let val = OperandValue :: Immediate ( bx. cx ( ) . const_poison ( to_backend_ty ) ) ;
520
578
return OperandRef { val, layout : cast } ;
521
579
}
522
- let r_t_in =
523
- CastTy :: from_ty ( operand. layout . ty ) . expect ( "bad input type for cast" ) ;
524
- let r_t_out = CastTy :: from_ty ( cast. ty ) . expect ( "bad output type for cast" ) ;
525
- let ll_t_in = bx. cx ( ) . immediate_backend_type ( operand. layout ) ;
526
- let llval = operand. immediate ( ) ;
527
-
528
- let newval = match ( r_t_in, r_t_out) {
529
- ( CastTy :: Int ( i) , CastTy :: Int ( _) ) => {
530
- bx. intcast ( llval, ll_t_out, i. is_signed ( ) )
531
- }
532
- ( CastTy :: Float , CastTy :: Float ) => {
533
- let srcsz = bx. cx ( ) . float_width ( ll_t_in) ;
534
- let dstsz = bx. cx ( ) . float_width ( ll_t_out) ;
535
- if dstsz > srcsz {
536
- bx. fpext ( llval, ll_t_out)
537
- } else if srcsz > dstsz {
538
- bx. fptrunc ( llval, ll_t_out)
539
- } else {
540
- llval
541
- }
542
- }
543
- ( CastTy :: Int ( i) , CastTy :: Float ) => {
544
- if i. is_signed ( ) {
545
- bx. sitofp ( llval, ll_t_out)
546
- } else {
547
- bx. uitofp ( llval, ll_t_out)
548
- }
549
- }
550
- ( CastTy :: Ptr ( _) | CastTy :: FnPtr , CastTy :: Ptr ( _) ) => {
551
- bx. pointercast ( llval, ll_t_out)
552
- }
553
- ( CastTy :: Int ( i) , CastTy :: Ptr ( _) ) => {
554
- let usize_llval =
555
- bx. intcast ( llval, bx. cx ( ) . type_isize ( ) , i. is_signed ( ) ) ;
556
- bx. inttoptr ( usize_llval, ll_t_out)
557
- }
558
- ( CastTy :: Float , CastTy :: Int ( IntTy :: I ) ) => {
559
- bx. cast_float_to_int ( true , llval, ll_t_out)
560
- }
561
- ( CastTy :: Float , CastTy :: Int ( _) ) => {
562
- bx. cast_float_to_int ( false , llval, ll_t_out)
563
- }
564
- _ => bug ! ( "unsupported cast: {:?} to {:?}" , operand. layout. ty, cast. ty) ,
580
+ let cast_kind = self . value_kind ( cast) ;
581
+ let OperandValueKind :: Immediate ( to_scalar) = cast_kind else {
582
+ bug ! ( "Found {cast_kind:?} for operand {cast:?}" ) ;
565
583
} ;
566
- OperandValue :: Immediate ( newval)
584
+
585
+ self . cast_immediate ( bx, imm, from_scalar, from_backend_ty, to_scalar, to_backend_ty)
586
+ . map ( OperandValue :: Immediate )
587
+ . unwrap_or_else ( || {
588
+ bug ! ( "Unsupported cast of {operand:?} to {cast:?}" ) ;
589
+ } )
567
590
}
568
591
mir:: CastKind :: Transmute => {
569
592
self . codegen_transmute_operand ( bx, operand, cast) . unwrap_or_else ( || {
0 commit comments