2 use syntax
::ast
::{FloatTy, IntTy, UintTy}
;
4 use rustc_const_math
::ConstFloat
;
5 use super::{EvalContext, Machine}
;
6 use rustc
::mir
::interpret
::{PrimVal, EvalResult, MemoryPointer, PointerArithmetic}
;
7 use rustc_apfloat
::ieee
::{Single, Double}
;
8 use rustc_apfloat
::Float
;
10 impl<'a
, 'tcx
, M
: Machine
<'tcx
>> EvalContext
<'a
, 'tcx
, M
> {
11 pub(super) fn cast_primval(
16 ) -> EvalResult
<'tcx
, PrimVal
> {
17 trace
!("Casting {:?}: {:?} to {:?}", val
, src_ty
, dest_ty
);
18 let src_kind
= self.ty_to_primval_kind(src_ty
)?
;
21 PrimVal
::Undef
=> Ok(PrimVal
::Undef
),
22 PrimVal
::Ptr(ptr
) => self.cast_from_ptr(ptr
, dest_ty
),
23 val @ PrimVal
::Bytes(_
) => {
24 use rustc
::mir
::interpret
::PrimValKind
::*;
26 F32
=> self.cast_from_float(val
.to_f32()?
, dest_ty
),
27 F64
=> self.cast_from_float(val
.to_f64()?
, dest_ty
),
29 I8
| I16
| I32
| I64
| I128
=> {
30 self.cast_from_signed_int(val
.to_i128()?
, dest_ty
)
33 Bool
| Char
| U8
| U16
| U32
| U64
| U128
| FnPtr
| Ptr
=> {
34 self.cast_from_int(val
.to_u128()?
, dest_ty
, false)
41 fn cast_from_signed_int(&self, val
: i128
, ty
: Ty
<'tcx
>) -> EvalResult
<'tcx
, PrimVal
> {
42 self.cast_from_int(val
as u128
, ty
, val
< 0)
45 fn int_to_int(&self, v
: i128
, ty
: IntTy
) -> u128
{
47 IntTy
::I8
=> v
as i8 as u128
,
48 IntTy
::I16
=> v
as i16 as u128
,
49 IntTy
::I32
=> v
as i32 as u128
,
50 IntTy
::I64
=> v
as i64 as u128
,
51 IntTy
::I128
=> v
as u128
,
53 let ty
= self.tcx
.sess
.target
.isize_ty
;
54 self.int_to_int(v
, ty
)
58 fn int_to_uint(&self, v
: u128
, ty
: UintTy
) -> u128
{
60 UintTy
::U8
=> v
as u8 as u128
,
61 UintTy
::U16
=> v
as u16 as u128
,
62 UintTy
::U32
=> v
as u32 as u128
,
63 UintTy
::U64
=> v
as u64 as u128
,
66 let ty
= self.tcx
.sess
.target
.usize_ty
;
67 self.int_to_uint(v
, ty
)
77 ) -> EvalResult
<'tcx
, PrimVal
> {
78 trace
!("cast_from_int: {}, {}, {}", v
, ty
, negative
);
79 use rustc
::ty
::TypeVariants
::*;
81 // Casts to bool are not permitted by rustc, no need to handle them here.
82 TyInt(ty
) => Ok(PrimVal
::Bytes(self.int_to_int(v
as i128
, ty
))),
83 TyUint(ty
) => Ok(PrimVal
::Bytes(self.int_to_uint(v
, ty
))),
85 TyFloat(fty
) if negative
=> Ok(PrimVal
::Bytes(ConstFloat
::from_i128(v
as i128
, fty
).bits
)),
86 TyFloat(fty
) => Ok(PrimVal
::Bytes(ConstFloat
::from_u128(v
, fty
).bits
)),
88 TyChar
if v
as u8 as u128
== v
=> Ok(PrimVal
::Bytes(v
)),
89 TyChar
=> err
!(InvalidChar(v
)),
91 // No alignment check needed for raw pointers. But we have to truncate to target ptr size.
92 TyRawPtr(_
) => Ok(PrimVal
::Bytes(self.memory
.truncate_to_ptr(v
).0 as u128
)),
94 _
=> err
!(Unimplemented(format
!("int to {:?} cast", ty
))),
98 fn cast_from_float(&self, val
: ConstFloat
, ty
: Ty
<'tcx
>) -> EvalResult
<'tcx
, PrimVal
> {
99 use rustc
::ty
::TypeVariants
::*;
102 let width
= t
.bit_width().unwrap_or(self.memory
.pointer_size() as usize * 8);
104 FloatTy
::F32
=> Ok(PrimVal
::Bytes(Single
::from_bits(val
.bits
).to_u128(width
).value
)),
105 FloatTy
::F64
=> Ok(PrimVal
::Bytes(Double
::from_bits(val
.bits
).to_u128(width
).value
)),
110 let width
= t
.bit_width().unwrap_or(self.memory
.pointer_size() as usize * 8);
112 FloatTy
::F32
=> Ok(PrimVal
::from_i128(Single
::from_bits(val
.bits
).to_i128(width
).value
)),
113 FloatTy
::F64
=> Ok(PrimVal
::from_i128(Double
::from_bits(val
.bits
).to_i128(width
).value
)),
117 TyFloat(fty
) => Ok(PrimVal
::from_float(val
.convert(fty
))),
118 _
=> err
!(Unimplemented(format
!("float to {:?} cast", ty
))),
122 fn cast_from_ptr(&self, ptr
: MemoryPointer
, ty
: Ty
<'tcx
>) -> EvalResult
<'tcx
, PrimVal
> {
123 use rustc
::ty
::TypeVariants
::*;
125 // Casting to a reference or fn pointer is not permitted by rustc, no need to support it here.
127 TyInt(IntTy
::Isize
) |
128 TyUint(UintTy
::Usize
) => Ok(PrimVal
::Ptr(ptr
)),
129 TyInt(_
) | TyUint(_
) => err
!(ReadPointerAsBytes
),
130 _
=> err
!(Unimplemented(format
!("ptr to {:?} cast", ty
))),