@@ -7,22 +7,13 @@ use syntax::symbol::sym;
7
7
use rustc_apfloat:: ieee:: { Single , Double } ;
8
8
use rustc_apfloat:: { Float , FloatConvert } ;
9
9
use rustc:: mir:: interpret:: {
10
- Scalar , InterpResult , Pointer , PointerArithmetic ,
10
+ Scalar , InterpResult , PointerArithmetic ,
11
11
} ;
12
12
use rustc:: mir:: CastKind ;
13
13
14
- use super :: { InterpCx , Machine , PlaceTy , OpTy , Immediate , FnVal } ;
14
+ use super :: { InterpCx , Machine , PlaceTy , OpTy , ImmTy , Immediate , FnVal } ;
15
15
16
16
impl < ' mir , ' tcx , M : Machine < ' mir , ' tcx > > InterpCx < ' mir , ' tcx , M > {
17
- fn type_is_fat_ptr ( & self , ty : Ty < ' tcx > ) -> bool {
18
- match ty. sty {
19
- ty:: RawPtr ( ty:: TypeAndMut { ty, .. } ) |
20
- ty:: Ref ( _, ty, _) => !self . type_is_sized ( ty) ,
21
- ty:: Adt ( def, _) if def. is_box ( ) => !self . type_is_sized ( ty. boxed_ty ( ) ) ,
22
- _ => false ,
23
- }
24
- }
25
-
26
17
pub fn cast (
27
18
& mut self ,
28
19
src : OpTy < ' tcx , M :: PointerTag > ,
@@ -37,40 +28,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
37
28
38
29
Misc | Pointer ( PointerCast :: MutToConstPointer ) => {
39
30
let src = self . read_immediate ( src) ?;
40
-
41
- if self . type_is_fat_ptr ( src. layout . ty ) {
42
- match ( * src, self . type_is_fat_ptr ( dest. layout . ty ) ) {
43
- // pointers to extern types
44
- ( Immediate :: Scalar ( _) , _) |
45
- // slices and trait objects to other slices/trait objects
46
- ( Immediate :: ScalarPair ( ..) , true ) => {
47
- // No change to immediate
48
- self . write_immediate ( * src, dest) ?;
49
- }
50
- // slices and trait objects to thin pointers (dropping the metadata)
51
- ( Immediate :: ScalarPair ( data, _) , false ) => {
52
- self . write_scalar ( data, dest) ?;
53
- }
54
- }
55
- } else {
56
- match src. layout . variants {
57
- layout:: Variants :: Single { index } => {
58
- if let Some ( discr) =
59
- src. layout . ty . discriminant_for_variant ( * self . tcx , index)
60
- {
61
- // Cast from a univariant enum
62
- assert ! ( src. layout. is_zst( ) ) ;
63
- return self . write_scalar (
64
- Scalar :: from_uint ( discr. val , dest. layout . size ) ,
65
- dest) ;
66
- }
67
- }
68
- layout:: Variants :: Multiple { .. } => { } ,
69
- }
70
-
71
- let dest_val = self . cast_scalar ( src. to_scalar ( ) ?, src. layout , dest. layout ) ?;
72
- self . write_scalar ( dest_val, dest) ?;
73
- }
31
+ let res = self . cast_immediate ( src, dest. layout ) ?;
32
+ self . write_immediate ( res, dest) ?;
74
33
}
75
34
76
35
Pointer ( PointerCast :: ReifyFnPointer ) => {
@@ -126,36 +85,76 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
126
85
Ok ( ( ) )
127
86
}
128
87
129
- fn cast_scalar (
88
+ fn cast_immediate (
130
89
& self ,
131
- val : Scalar < M :: PointerTag > ,
132
- src_layout : TyLayout < ' tcx > ,
90
+ src : ImmTy < ' tcx , M :: PointerTag > ,
133
91
dest_layout : TyLayout < ' tcx > ,
134
- ) -> InterpResult < ' tcx , Scalar < M :: PointerTag > > {
92
+ ) -> InterpResult < ' tcx , Immediate < M :: PointerTag > > {
135
93
use rustc:: ty:: TyKind :: * ;
136
- trace ! ( "Casting {:?}: {:?} to {:?}" , val , src_layout . ty, dest_layout. ty) ;
94
+ trace ! ( "Casting {:?}: {:?} to {:?}" , * src , src . layout . ty, dest_layout. ty) ;
137
95
138
- match src_layout . ty . sty {
96
+ match src . layout . ty . sty {
139
97
// Floating point
140
- Float ( FloatTy :: F32 ) => self . cast_from_float ( val. to_f32 ( ) ?, dest_layout. ty ) ,
141
- Float ( FloatTy :: F64 ) => self . cast_from_float ( val. to_f64 ( ) ?, dest_layout. ty ) ,
142
- // Integer(-like), including fn ptr casts and casts from enums that
143
- // are represented as integers (this excludes univariant enums, which
144
- // are handled in `cast` directly).
145
- _ => {
98
+ Float ( FloatTy :: F32 ) =>
99
+ return Ok ( self . cast_from_float ( src. to_scalar ( ) ?. to_f32 ( ) ?, dest_layout. ty ) ?. into ( ) ) ,
100
+ Float ( FloatTy :: F64 ) =>
101
+ return Ok ( self . cast_from_float ( src. to_scalar ( ) ?. to_f64 ( ) ?, dest_layout. ty ) ?. into ( ) ) ,
102
+ // The rest is integer/pointer-"like", including fn ptr casts and casts from enums that
103
+ // are represented as integers.
104
+ _ =>
146
105
assert ! (
147
- src_layout. ty. is_bool( ) || src_layout. ty. is_char( ) ||
148
- src_layout. ty. is_enum( ) || src_layout. ty. is_integral( ) ||
149
- src_layout. ty. is_unsafe_ptr( ) || src_layout. ty. is_fn_ptr( ) ||
150
- src_layout. ty. is_region_ptr( ) ,
151
- "Unexpected cast from type {:?}" , src_layout. ty
152
- ) ;
153
- match val. to_bits_or_ptr ( src_layout. size , self ) {
154
- Err ( ptr) => self . cast_from_ptr ( ptr, src_layout, dest_layout) ,
155
- Ok ( data) => self . cast_from_int ( data, src_layout, dest_layout) ,
106
+ src. layout. ty. is_bool( ) || src. layout. ty. is_char( ) ||
107
+ src. layout. ty. is_enum( ) || src. layout. ty. is_integral( ) ||
108
+ src. layout. ty. is_any_ptr( ) ,
109
+ "Unexpected cast from type {:?}" , src. layout. ty
110
+ )
111
+ }
112
+
113
+ // Handle cast from a univariant (ZST) enum.
114
+ match src. layout . variants {
115
+ layout:: Variants :: Single { index } => {
116
+ if let Some ( discr) =
117
+ src. layout . ty . discriminant_for_variant ( * self . tcx , index)
118
+ {
119
+ assert ! ( src. layout. is_zst( ) ) ;
120
+ return Ok ( Scalar :: from_uint ( discr. val , dest_layout. size ) . into ( ) ) ;
156
121
}
157
122
}
123
+ layout:: Variants :: Multiple { .. } => { } ,
124
+ }
125
+
126
+ // Handle casting the metadata away from a fat pointer.
127
+ if src. layout . ty . is_unsafe_ptr ( ) && dest_layout. ty . is_unsafe_ptr ( ) &&
128
+ dest_layout. size != src. layout . size
129
+ {
130
+ assert_eq ! ( src. layout. size, 2 * self . memory. pointer_size( ) ) ;
131
+ assert_eq ! ( dest_layout. size, self . memory. pointer_size( ) ) ;
132
+ assert ! ( dest_layout. ty. is_unsafe_ptr( ) ) ;
133
+ match * src {
134
+ Immediate :: ScalarPair ( data, _) =>
135
+ return Ok ( data. into ( ) ) ,
136
+ Immediate :: Scalar ( ..) =>
137
+ bug ! (
138
+ "{:?} input to a fat-to-thin cast ({:?} -> {:?})" ,
139
+ * src, src. layout. ty, dest_layout. ty
140
+ ) ,
141
+ } ;
142
+ }
143
+
144
+ // Handle casting any ptr to raw ptr (might be a fat ptr).
145
+ if src. layout . ty . is_any_ptr ( ) && dest_layout. ty . is_unsafe_ptr ( )
146
+ {
147
+ // The only possible size-unequal case was handled above.
148
+ assert_eq ! ( src. layout. size, dest_layout. size) ;
149
+ return Ok ( * src) ;
158
150
}
151
+
152
+ // For all remaining casts, we either
153
+ // (a) cast a raw ptr to usize, or
154
+ // (b) cast from an integer-like (including bool, char, enums).
155
+ // In both cases we want the bits.
156
+ let bits = self . force_bits ( src. to_scalar ( ) ?, src. layout . size ) ?;
157
+ Ok ( self . cast_from_int ( bits, src. layout , dest_layout) ?. into ( ) )
159
158
}
160
159
161
160
fn cast_from_int (
@@ -236,31 +235,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
236
235
}
237
236
}
238
237
239
- fn cast_from_ptr (
240
- & self ,
241
- ptr : Pointer < M :: PointerTag > ,
242
- src_layout : TyLayout < ' tcx > ,
243
- dest_layout : TyLayout < ' tcx > ,
244
- ) -> InterpResult < ' tcx , Scalar < M :: PointerTag > > {
245
- use rustc:: ty:: TyKind :: * ;
246
-
247
- match dest_layout. ty . sty {
248
- // Casting to a reference or fn pointer is not permitted by rustc,
249
- // no need to support it here.
250
- RawPtr ( _) => Ok ( ptr. into ( ) ) ,
251
- Int ( _) | Uint ( _) => {
252
- let size = self . memory . pointer_size ( ) ;
253
-
254
- match self . force_bits ( Scalar :: Ptr ( ptr) , size) {
255
- Ok ( bits) => self . cast_from_int ( bits, src_layout, dest_layout) ,
256
- Err ( _) if dest_layout. size == size => Ok ( ptr. into ( ) ) ,
257
- Err ( e) => Err ( e) ,
258
- }
259
- }
260
- _ => bug ! ( "invalid MIR: ptr to {:?} cast" , dest_layout. ty)
261
- }
262
- }
263
-
264
238
fn unsize_into_ptr (
265
239
& mut self ,
266
240
src : OpTy < ' tcx , M :: PointerTag > ,
0 commit comments