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