@@ -7,22 +7,13 @@ use syntax::symbol::sym;
77use rustc_apfloat:: ieee:: { Single , Double } ;
88use rustc_apfloat:: { Float , FloatConvert } ;
99use rustc:: mir:: interpret:: {
10- Scalar , InterpResult , Pointer , PointerArithmetic ,
10+ Scalar , InterpResult , PointerArithmetic ,
1111} ;
1212use rustc:: mir:: CastKind ;
1313
14- use super :: { InterpCx , Machine , PlaceTy , OpTy , Immediate , FnVal } ;
14+ use super :: { InterpCx , Machine , PlaceTy , OpTy , ImmTy , Immediate , FnVal } ;
1515
1616impl < ' 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-
2617 pub fn cast (
2718 & mut self ,
2819 src : OpTy < ' tcx , M :: PointerTag > ,
@@ -37,40 +28,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
3728
3829 Misc | Pointer ( PointerCast :: MutToConstPointer ) => {
3930 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) ?;
7433 }
7534
7635 Pointer ( PointerCast :: ReifyFnPointer ) => {
@@ -126,36 +85,76 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
12685 Ok ( ( ) )
12786 }
12887
129- fn cast_scalar (
88+ fn cast_immediate (
13089 & self ,
131- val : Scalar < M :: PointerTag > ,
132- src_layout : TyLayout < ' tcx > ,
90+ src : ImmTy < ' tcx , M :: PointerTag > ,
13391 dest_layout : TyLayout < ' tcx > ,
134- ) -> InterpResult < ' tcx , Scalar < M :: PointerTag > > {
92+ ) -> InterpResult < ' tcx , Immediate < M :: PointerTag > > {
13593 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) ;
13795
138- match src_layout . ty . sty {
96+ match src . layout . ty . sty {
13997 // 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+ _ =>
146105 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 ( ) ) ;
156121 }
157122 }
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) ;
158150 }
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 ( ) )
159158 }
160159
161160 fn cast_from_int (
@@ -236,31 +235,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
236235 }
237236 }
238237
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-
264238 fn unsize_into_ptr (
265239 & mut self ,
266240 src : OpTy < ' tcx , M :: PointerTag > ,
0 commit comments