@@ -9,7 +9,6 @@ use crate::MemFlags;
99
1010use rustc_hir as hir;
1111use rustc_middle:: mir;
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} ;
@@ -234,21 +233,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
234233 }
235234 }
236235 OperandValue :: Immediate ( imm) => {
237- let OperandValueKind :: Immediate ( in_scalar ) = operand_kind else {
236+ let OperandValueKind :: Immediate ( from_scalar ) = operand_kind else {
238237 bug ! ( "Found {operand_kind:?} for operand {operand:?}" ) ;
239238 } ;
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 )
242241 {
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) ;
245244 Some ( OperandValue :: Immediate ( self . transmute_immediate (
246245 bx,
247246 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 ,
252251 ) ) )
253252 } else {
254253 None
@@ -277,6 +276,57 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
277276 }
278277 }
279278
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+
280330 /// Transmutes one of the immediates from an [`OperandValue::Immediate`]
281331 /// or an [`OperandValue::Pair`] to an immediate of the target type.
282332 ///
@@ -482,62 +532,33 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
482532 | mir:: CastKind :: IntToFloat
483533 | mir:: CastKind :: PtrToPtr
484534 | mir:: CastKind :: FnPtrToPtr
485-
486535 // Since int2ptr can have arbitrary integer types as input (so we have to do
487536 // sign extension and all that), it is currently best handled in the same code
488537 // path as the other integer-to-X casts.
489538 | 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+
490546 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) ;
492548 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 ) ) ;
494550 return OperandRef { val, layout : cast } ;
495551 }
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:?}" ) ;
539555 } ;
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+ } )
541562 }
542563 mir:: CastKind :: Transmute => {
543564 self . codegen_transmute_operand ( bx, operand, cast) . unwrap_or_else ( || {
0 commit comments