@@ -4,6 +4,7 @@ use syntax::ast::{FloatTy, IntTy, UintTy};
4
4
use error:: { EvalResult , EvalError } ;
5
5
use eval_context:: EvalContext ;
6
6
use value:: PrimVal ;
7
+ use memory:: { MemoryPointer , PointerArithmetic } ;
7
8
8
9
impl < ' a , ' tcx > EvalContext < ' a , ' tcx > {
9
10
pub ( super ) fn cast_primval (
@@ -12,38 +13,34 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
12
13
src_ty : Ty < ' tcx > ,
13
14
dest_ty : Ty < ' tcx >
14
15
) -> EvalResult < ' tcx , PrimVal > {
15
- let kind = self . ty_to_primval_kind ( src_ty) ?;
16
-
17
- use value:: PrimValKind :: * ;
18
- match kind {
19
- F32 => self . cast_float ( val. to_f32 ( ) ? as f64 , dest_ty) ,
20
- F64 => self . cast_float ( val. to_f64 ( ) ?, dest_ty) ,
21
-
22
- I8 | I16 | I32 | I64 | I128 => {
23
- if val. is_ptr ( ) {
24
- self . cast_ptr ( val, dest_ty)
25
- } else {
26
- self . cast_signed_int ( val. to_i128 ( ) ?, dest_ty)
16
+ let src_kind = self . ty_to_primval_kind ( src_ty) ?;
17
+
18
+ match val {
19
+ PrimVal :: Undef => Ok ( PrimVal :: Undef ) ,
20
+ PrimVal :: Ptr ( ptr) => self . cast_from_ptr ( ptr, dest_ty) ,
21
+ val @ PrimVal :: Bytes ( _) => {
22
+ use value:: PrimValKind :: * ;
23
+ match src_kind {
24
+ F32 => self . cast_from_float ( val. to_f32 ( ) ? as f64 , dest_ty) ,
25
+ F64 => self . cast_from_float ( val. to_f64 ( ) ?, dest_ty) ,
26
+
27
+ I8 | I16 | I32 | I64 | I128 => {
28
+ self . cast_from_signed_int ( val. to_i128 ( ) ?, dest_ty)
29
+ } ,
30
+
31
+ Bool | Char | U8 | U16 | U32 | U64 | U128 | FnPtr | Ptr => {
32
+ self . cast_from_int ( val. to_u128 ( ) ?, dest_ty, false )
33
+ } ,
27
34
}
28
- } ,
29
-
30
- Bool | Char | U8 | U16 | U32 | U64 | U128 => {
31
- if val. is_ptr ( ) {
32
- self . cast_ptr ( val, dest_ty)
33
- } else {
34
- self . cast_int ( val. to_u128 ( ) ?, dest_ty, false )
35
- }
36
- } ,
37
-
38
- FnPtr | Ptr => self . cast_ptr ( val, dest_ty) ,
35
+ }
39
36
}
40
37
}
41
38
42
- fn cast_signed_int ( & self , val : i128 , ty : ty:: Ty < ' tcx > ) -> EvalResult < ' tcx , PrimVal > {
43
- self . cast_int ( val as u128 , ty, val < 0 )
39
+ fn cast_from_signed_int ( & self , val : i128 , ty : ty:: Ty < ' tcx > ) -> EvalResult < ' tcx , PrimVal > {
40
+ self . cast_from_int ( val as u128 , ty, val < 0 )
44
41
}
45
42
46
- fn cast_int ( & self , v : u128 , ty : ty:: Ty < ' tcx > , negative : bool ) -> EvalResult < ' tcx , PrimVal > {
43
+ fn cast_from_int ( & self , v : u128 , ty : ty:: Ty < ' tcx > , negative : bool ) -> EvalResult < ' tcx , PrimVal > {
47
44
use rustc:: ty:: TypeVariants :: * ;
48
45
match ty. sty {
49
46
// Casts to bool are not permitted by rustc, no need to handle them here.
@@ -63,13 +60,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
63
60
TyInt ( IntTy :: Is ) => {
64
61
let int_ty = self . tcx . sess . target . int_type ;
65
62
let ty = self . tcx . mk_mach_int ( int_ty) ;
66
- self . cast_int ( v, ty, negative)
63
+ self . cast_from_int ( v, ty, negative)
67
64
}
68
65
69
66
TyUint ( UintTy :: Us ) => {
70
67
let uint_ty = self . tcx . sess . target . uint_type ;
71
68
let ty = self . tcx . mk_mach_uint ( uint_ty) ;
72
- self . cast_int ( v, ty, negative)
69
+ self . cast_from_int ( v, ty, negative)
73
70
}
74
71
75
72
TyFloat ( FloatTy :: F64 ) if negative => Ok ( PrimVal :: from_f64 ( v as i128 as f64 ) ) ,
@@ -80,34 +77,34 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
80
77
TyChar if v as u8 as u128 == v => Ok ( PrimVal :: Bytes ( v) ) ,
81
78
TyChar => Err ( EvalError :: InvalidChar ( v) ) ,
82
79
83
- // No alignment check needed for raw pointers
84
- TyRawPtr ( _) => Ok ( PrimVal :: Bytes ( v % ( 1 << self . memory . pointer_size ( ) ) ) ) ,
80
+ // No alignment check needed for raw pointers. But we have to truncate to target ptr size.
81
+ TyRawPtr ( _) => Ok ( PrimVal :: Bytes ( self . memory . truncate_to_ptr ( v ) . 0 as u128 ) ) ,
85
82
86
83
_ => Err ( EvalError :: Unimplemented ( format ! ( "int to {:?} cast" , ty) ) ) ,
87
84
}
88
85
}
89
86
90
- fn cast_float ( & self , val : f64 , ty : Ty < ' tcx > ) -> EvalResult < ' tcx , PrimVal > {
87
+ fn cast_from_float ( & self , val : f64 , ty : Ty < ' tcx > ) -> EvalResult < ' tcx , PrimVal > {
91
88
use rustc:: ty:: TypeVariants :: * ;
92
89
match ty. sty {
93
90
// Casting negative floats to unsigned integers yields zero.
94
- TyUint ( _) if val < 0.0 => self . cast_int ( 0 , ty, false ) ,
95
- TyInt ( _) if val < 0.0 => self . cast_int ( val as i128 as u128 , ty, true ) ,
91
+ TyUint ( _) if val < 0.0 => self . cast_from_int ( 0 , ty, false ) ,
92
+ TyInt ( _) if val < 0.0 => self . cast_from_int ( val as i128 as u128 , ty, true ) ,
96
93
97
- TyInt ( _) | ty:: TyUint ( _) => self . cast_int ( val as u128 , ty, false ) ,
94
+ TyInt ( _) | ty:: TyUint ( _) => self . cast_from_int ( val as u128 , ty, false ) ,
98
95
99
96
TyFloat ( FloatTy :: F64 ) => Ok ( PrimVal :: from_f64 ( val) ) ,
100
97
TyFloat ( FloatTy :: F32 ) => Ok ( PrimVal :: from_f32 ( val as f32 ) ) ,
101
98
_ => Err ( EvalError :: Unimplemented ( format ! ( "float to {:?} cast" , ty) ) ) ,
102
99
}
103
100
}
104
101
105
- fn cast_ptr ( & self , ptr : PrimVal , ty : Ty < ' tcx > ) -> EvalResult < ' tcx , PrimVal > {
102
+ fn cast_from_ptr ( & self , ptr : MemoryPointer , ty : Ty < ' tcx > ) -> EvalResult < ' tcx , PrimVal > {
106
103
use rustc:: ty:: TypeVariants :: * ;
107
104
match ty. sty {
108
105
// Casting to a reference or fn pointer is not permitted by rustc, no need to support it here.
109
106
TyRawPtr ( _) | TyInt ( IntTy :: Is ) | TyUint ( UintTy :: Us ) =>
110
- Ok ( ptr) ,
107
+ Ok ( PrimVal :: Ptr ( ptr) ) ,
111
108
TyInt ( _) | TyUint ( _) => Err ( EvalError :: ReadPointerAsBytes ) ,
112
109
_ => Err ( EvalError :: Unimplemented ( format ! ( "ptr to {:?} cast" , ty) ) ) ,
113
110
}
0 commit comments