@@ -5,11 +5,11 @@ use syntax::ast::{FloatTy, IntTy, UintTy};
55use syntax:: symbol:: sym;
66
77use rustc_apfloat:: ieee:: { Single , Double } ;
8+ use rustc_apfloat:: { Float , FloatConvert } ;
89use rustc:: mir:: interpret:: {
910 Scalar , InterpResult , Pointer , PointerArithmetic , InterpError ,
1011} ;
1112use rustc:: mir:: CastKind ;
12- use rustc_apfloat:: Float ;
1313
1414use super :: { InterpretCx , Machine , PlaceTy , OpTy , Immediate } ;
1515
@@ -126,7 +126,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
126126 Ok ( ( ) )
127127 }
128128
129- pub ( super ) fn cast_scalar (
129+ fn cast_scalar (
130130 & self ,
131131 val : Scalar < M :: PointerTag > ,
132132 src_layout : TyLayout < ' tcx > ,
@@ -135,23 +135,36 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
135135 use rustc:: ty:: TyKind :: * ;
136136 trace ! ( "Casting {:?}: {:?} to {:?}" , val, src_layout. ty, dest_layout. ty) ;
137137
138- match val. to_bits_or_ptr ( src_layout. size , self ) {
139- Err ( ptr) => self . cast_from_ptr ( ptr, dest_layout. ty ) ,
140- Ok ( data) => {
141- match src_layout. ty . sty {
142- Float ( fty) => self . cast_from_float ( data, fty, dest_layout. ty ) ,
143- _ => self . cast_from_int ( data, src_layout, dest_layout) ,
138+ match src_layout. ty . sty {
139+ // 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+ _ => {
146+ 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, dest_layout. ty ) ,
155+ Ok ( data) => self . cast_from_int ( data, src_layout, dest_layout) ,
144156 }
145157 }
146158 }
147159 }
148160
149161 fn cast_from_int (
150162 & self ,
151- v : u128 ,
163+ v : u128 , // raw bits
152164 src_layout : TyLayout < ' tcx > ,
153165 dest_layout : TyLayout < ' tcx > ,
154166 ) -> InterpResult < ' tcx , Scalar < M :: PointerTag > > {
167+ // Let's make sure v is sign-extended *if* it has a signed type.
155168 let signed = src_layout. abi . is_signed ( ) ;
156169 let v = if signed {
157170 self . sign_extend ( v, src_layout)
@@ -166,21 +179,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
166179 Ok ( Scalar :: from_uint ( v, dest_layout. size ) )
167180 }
168181
169- Float ( FloatTy :: F32 ) if signed => Ok ( Scalar :: from_uint (
170- Single :: from_i128 ( v as i128 ) . value . to_bits ( ) ,
171- Size :: from_bits ( 32 )
182+ Float ( FloatTy :: F32 ) if signed => Ok ( Scalar :: from_f32 (
183+ Single :: from_i128 ( v as i128 ) . value
172184 ) ) ,
173- Float ( FloatTy :: F64 ) if signed => Ok ( Scalar :: from_uint (
174- Double :: from_i128 ( v as i128 ) . value . to_bits ( ) ,
175- Size :: from_bits ( 64 )
185+ Float ( FloatTy :: F64 ) if signed => Ok ( Scalar :: from_f64 (
186+ Double :: from_i128 ( v as i128 ) . value
176187 ) ) ,
177- Float ( FloatTy :: F32 ) => Ok ( Scalar :: from_uint (
178- Single :: from_u128 ( v) . value . to_bits ( ) ,
179- Size :: from_bits ( 32 )
188+ Float ( FloatTy :: F32 ) => Ok ( Scalar :: from_f32 (
189+ Single :: from_u128 ( v) . value
180190 ) ) ,
181- Float ( FloatTy :: F64 ) => Ok ( Scalar :: from_uint (
182- Double :: from_u128 ( v) . value . to_bits ( ) ,
183- Size :: from_bits ( 64 )
191+ Float ( FloatTy :: F64 ) => Ok ( Scalar :: from_f64 (
192+ Double :: from_u128 ( v) . value
184193 ) ) ,
185194
186195 Char => {
@@ -194,52 +203,36 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
194203 }
195204 }
196205
197- fn cast_from_float (
206+ fn cast_from_float < F > (
198207 & self ,
199- bits : u128 ,
200- fty : FloatTy ,
208+ f : F ,
201209 dest_ty : Ty < ' tcx >
202- ) -> InterpResult < ' tcx , Scalar < M :: PointerTag > > {
210+ ) -> InterpResult < ' tcx , Scalar < M :: PointerTag > >
211+ where F : Float + Into < Scalar < M :: PointerTag > > + FloatConvert < Single > + FloatConvert < Double >
212+ {
203213 use rustc:: ty:: TyKind :: * ;
204- use rustc_apfloat:: FloatConvert ;
205214 match dest_ty. sty {
206215 // float -> uint
207216 Uint ( t) => {
208217 let width = t. bit_width ( ) . unwrap_or_else ( || self . pointer_size ( ) . bits ( ) as usize ) ;
209- let v = match fty {
210- FloatTy :: F32 => Single :: from_bits ( bits) . to_u128 ( width) . value ,
211- FloatTy :: F64 => Double :: from_bits ( bits) . to_u128 ( width) . value ,
212- } ;
218+ let v = f. to_u128 ( width) . value ;
213219 // This should already fit the bit width
214220 Ok ( Scalar :: from_uint ( v, Size :: from_bits ( width as u64 ) ) )
215221 } ,
216222 // float -> int
217223 Int ( t) => {
218224 let width = t. bit_width ( ) . unwrap_or_else ( || self . pointer_size ( ) . bits ( ) as usize ) ;
219- let v = match fty {
220- FloatTy :: F32 => Single :: from_bits ( bits) . to_i128 ( width) . value ,
221- FloatTy :: F64 => Double :: from_bits ( bits) . to_i128 ( width) . value ,
222- } ;
225+ let v = f. to_i128 ( width) . value ;
223226 Ok ( Scalar :: from_int ( v, Size :: from_bits ( width as u64 ) ) )
224227 } ,
225- // f64 -> f32
226- Float ( FloatTy :: F32 ) if fty == FloatTy :: F64 => {
227- Ok ( Scalar :: from_uint (
228- Single :: to_bits ( Double :: from_bits ( bits) . convert ( & mut false ) . value ) ,
229- Size :: from_bits ( 32 ) ,
230- ) )
231- } ,
232- // f32 -> f64
233- Float ( FloatTy :: F64 ) if fty == FloatTy :: F32 => {
234- Ok ( Scalar :: from_uint (
235- Double :: to_bits ( Single :: from_bits ( bits) . convert ( & mut false ) . value ) ,
236- Size :: from_bits ( 64 ) ,
237- ) )
238- } ,
239- // identity cast
240- Float ( FloatTy :: F64 ) => Ok ( Scalar :: from_uint ( bits, Size :: from_bits ( 64 ) ) ) ,
241- Float ( FloatTy :: F32 ) => Ok ( Scalar :: from_uint ( bits, Size :: from_bits ( 32 ) ) ) ,
242- _ => err ! ( Unimplemented ( format!( "float to {:?} cast" , dest_ty) ) ) ,
228+ // float -> f32
229+ Float ( FloatTy :: F32 ) =>
230+ Ok ( Scalar :: from_f32 ( f. convert ( & mut false ) . value ) ) ,
231+ // float -> f64
232+ Float ( FloatTy :: F64 ) =>
233+ Ok ( Scalar :: from_f64 ( f. convert ( & mut false ) . value ) ) ,
234+ // That's it.
235+ _ => bug ! ( "invalid float to {:?} cast" , dest_ty) ,
243236 }
244237 }
245238
0 commit comments