@@ -9,7 +9,6 @@ use crate::MemFlags;
99
1010use rustc_hir as hir;
1111use rustc_middle:: mir:: { self , AggregateKind , Operand } ;
12- use rustc_middle:: ty:: cast:: { CastTy , IntTy } ;
1312use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf , TyAndLayout } ;
1413use rustc_middle:: ty:: { self , adjustment:: PointerCoercion , Instance , Ty , TyCtxt } ;
1514use rustc_middle:: { bug, span_bug} ;
@@ -237,21 +236,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
237236 }
238237 }
239238 OperandValue :: Immediate ( imm) => {
240- let OperandValueKind :: Immediate ( in_scalar ) = operand_kind else {
239+ let OperandValueKind :: Immediate ( from_scalar ) = operand_kind else {
241240 bug ! ( "Found {operand_kind:?} for operand {operand:?}" ) ;
242241 } ;
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 )
245244 {
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) ;
248247 Some ( OperandValue :: Immediate ( self . transmute_immediate (
249248 bx,
250249 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 ,
255254 ) ) )
256255 } else {
257256 None
@@ -280,6 +279,60 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
280279 }
281280 }
282281
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+ imm = bx. to_immediate_scalar ( imm, to_scalar) ;
333+ Some ( imm)
334+ }
335+
283336 /// Transmutes one of the immediates from an [`OperandValue::Immediate`]
284337 /// or an [`OperandValue::Pair`] to an immediate of the target type.
285338 ///
@@ -508,62 +561,33 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
508561 | mir:: CastKind :: IntToFloat
509562 | mir:: CastKind :: PtrToPtr
510563 | mir:: CastKind :: FnPtrToPtr
511-
512564 // Since int2ptr can have arbitrary integer types as input (so we have to do
513565 // sign extension and all that), it is currently best handled in the same code
514566 // path as the other integer-to-X casts.
515567 | mir:: CastKind :: PointerWithExposedProvenance => {
568+ let imm = operand. immediate ( ) ;
569+ let operand_kind = self . value_kind ( operand. layout ) ;
570+ let OperandValueKind :: Immediate ( from_scalar) = operand_kind else {
571+ bug ! ( "Found {operand_kind:?} for operand {operand:?}" ) ;
572+ } ;
573+ let from_backend_ty = bx. cx ( ) . immediate_backend_type ( operand. layout ) ;
574+
516575 assert ! ( bx. cx( ) . is_backend_immediate( cast) ) ;
517- let ll_t_out = bx. cx ( ) . immediate_backend_type ( cast) ;
576+ let to_backend_ty = bx. cx ( ) . immediate_backend_type ( cast) ;
518577 if operand. layout . abi . is_uninhabited ( ) {
519- let val = OperandValue :: Immediate ( bx. cx ( ) . const_poison ( ll_t_out ) ) ;
578+ let val = OperandValue :: Immediate ( bx. cx ( ) . const_poison ( to_backend_ty ) ) ;
520579 return OperandRef { val, layout : cast } ;
521580 }
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) ,
581+ let cast_kind = self . value_kind ( cast) ;
582+ let OperandValueKind :: Immediate ( to_scalar) = cast_kind else {
583+ bug ! ( "Found {cast_kind:?} for operand {cast:?}" ) ;
565584 } ;
566- OperandValue :: Immediate ( newval)
585+
586+ self . cast_immediate ( bx, imm, from_scalar, from_backend_ty, to_scalar, to_backend_ty)
587+ . map ( OperandValue :: Immediate )
588+ . unwrap_or_else ( || {
589+ bug ! ( "Unsupported cast of {operand:?} to {cast:?}" ) ;
590+ } )
567591 }
568592 mir:: CastKind :: Transmute => {
569593 self . codegen_transmute_operand ( bx, operand, cast) . unwrap_or_else ( || {
0 commit comments