2 use rustc
::ty
::layout
::LayoutOf
;
3 use syntax
::ast
::{FloatTy, IntTy, UintTy}
;
5 use rustc_const_math
::ConstFloat
;
6 use super::{EvalContext, Machine}
;
7 use rustc
::mir
::interpret
::{PrimVal, EvalResult, MemoryPointer, PointerArithmetic}
;
8 use rustc_apfloat
::ieee
::{Single, Double}
;
9 use rustc_apfloat
::Float
;
11 impl<'a
, 'mir
, 'tcx
, M
: Machine
<'mir
, 'tcx
>> EvalContext
<'a
, 'mir
, 'tcx
, M
> {
12 pub(super) fn cast_primval(
17 ) -> EvalResult
<'tcx
, PrimVal
> {
18 use rustc
::ty
::TypeVariants
::*;
19 trace
!("Casting {:?}: {:?} to {:?}", val
, src_ty
, dest_ty
);
22 PrimVal
::Undef
=> Ok(PrimVal
::Undef
),
23 PrimVal
::Ptr(ptr
) => self.cast_from_ptr(ptr
, dest_ty
),
24 PrimVal
::Bytes(b
) => {
26 TyFloat(fty
) => self.cast_from_float(b
, fty
, dest_ty
),
27 _
=> self.cast_from_int(b
, src_ty
, dest_ty
),
38 ) -> EvalResult
<'tcx
, PrimVal
> {
39 let signed
= self.layout_of(src_ty
)?
.abi
.is_signed();
41 self.sign_extend(v
, src_ty
)?
45 trace
!("cast_from_int: {}, {}, {}", v
, src_ty
, dest_ty
);
46 use rustc
::ty
::TypeVariants
::*;
48 TyInt(_
) | TyUint(_
) => {
49 let v
= self.truncate(v
, dest_ty
)?
;
53 TyFloat(fty
) if signed
=> Ok(PrimVal
::Bytes(ConstFloat
::from_i128(v
as i128
, fty
).bits
)),
54 TyFloat(fty
) => Ok(PrimVal
::Bytes(ConstFloat
::from_u128(v
, fty
).bits
)),
56 TyChar
if v
as u8 as u128
== v
=> Ok(PrimVal
::Bytes(v
)),
57 TyChar
=> err
!(InvalidChar(v
)),
59 // No alignment check needed for raw pointers. But we have to truncate to target ptr size.
61 Ok(PrimVal
::Bytes(self.memory
.truncate_to_ptr(v
).0 as u128
))
64 // Casts to bool are not permitted by rustc, no need to handle them here.
65 _
=> err
!(Unimplemented(format
!("int to {:?} cast", dest_ty
))),
69 fn cast_from_float(&self, bits
: u128
, fty
: FloatTy
, dest_ty
: Ty
<'tcx
>) -> EvalResult
<'tcx
, PrimVal
> {
70 use rustc
::ty
::TypeVariants
::*;
71 use rustc_apfloat
::FloatConvert
;
75 let width
= t
.bit_width().unwrap_or(self.memory
.pointer_size() as usize * 8);
77 FloatTy
::F32
=> Ok(PrimVal
::Bytes(Single
::from_bits(bits
).to_u128(width
).value
)),
78 FloatTy
::F64
=> Ok(PrimVal
::Bytes(Double
::from_bits(bits
).to_u128(width
).value
)),
83 let width
= t
.bit_width().unwrap_or(self.memory
.pointer_size() as usize * 8);
85 FloatTy
::F32
=> Ok(PrimVal
::from_i128(Single
::from_bits(bits
).to_i128(width
).value
)),
86 FloatTy
::F64
=> Ok(PrimVal
::from_i128(Double
::from_bits(bits
).to_i128(width
).value
)),
90 TyFloat(FloatTy
::F32
) if fty
== FloatTy
::F64
=> {
91 Ok(PrimVal
::Bytes(Single
::to_bits(Double
::from_bits(bits
).convert(&mut false).value
)))
94 TyFloat(FloatTy
::F64
) if fty
== FloatTy
::F32
=> {
95 Ok(PrimVal
::Bytes(Double
::to_bits(Single
::from_bits(bits
).convert(&mut false).value
)))
98 TyFloat(_
) => Ok(PrimVal
::Bytes(bits
)),
99 _
=> err
!(Unimplemented(format
!("float to {:?} cast", dest_ty
))),
103 fn cast_from_ptr(&self, ptr
: MemoryPointer
, ty
: Ty
<'tcx
>) -> EvalResult
<'tcx
, PrimVal
> {
104 use rustc
::ty
::TypeVariants
::*;
106 // Casting to a reference or fn pointer is not permitted by rustc, no need to support it here.
108 TyInt(IntTy
::Isize
) |
109 TyUint(UintTy
::Usize
) => Ok(PrimVal
::Ptr(ptr
)),
110 TyInt(_
) | TyUint(_
) => err
!(ReadPointerAsBytes
),
111 _
=> err
!(Unimplemented(format
!("ptr to {:?} cast", ty
))),