@@ -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,33 @@ 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
143+ _ => {
144+ assert ! (
145+ src_layout. ty. is_bool( ) || src_layout. ty. is_char( ) ||
146+ src_layout. ty. is_integral( ) || src_layout. ty. is_region_ptr( ) ||
147+ src_layout. ty. is_unsafe_ptr( ) || src_layout. ty. is_fn_ptr( ) ,
148+ "Unexpected cast from type {:?}" , src_layout. ty
149+ ) ;
150+ match val. to_bits_or_ptr ( src_layout. size , self ) {
151+ Err ( ptr) => self . cast_from_ptr ( ptr, dest_layout. ty ) ,
152+ Ok ( data) => self . cast_from_int ( data, src_layout, dest_layout) ,
144153 }
145154 }
146155 }
147156 }
148157
149158 fn cast_from_int (
150159 & self ,
151- v : u128 ,
160+ v : u128 , // raw bits
152161 src_layout : TyLayout < ' tcx > ,
153162 dest_layout : TyLayout < ' tcx > ,
154163 ) -> InterpResult < ' tcx , Scalar < M :: PointerTag > > {
164+ // Let's make sure v is sign-extended *if* it has a signed type.
155165 let signed = src_layout. abi . is_signed ( ) ;
156166 let v = if signed {
157167 self . sign_extend ( v, src_layout)
@@ -190,46 +200,36 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
190200 }
191201 }
192202
193- fn cast_from_float (
203+ fn cast_from_float < F > (
194204 & self ,
195- bits : u128 ,
196- fty : FloatTy ,
205+ f : F ,
197206 dest_ty : Ty < ' tcx >
198- ) -> InterpResult < ' tcx , Scalar < M :: PointerTag > > {
207+ ) -> InterpResult < ' tcx , Scalar < M :: PointerTag > >
208+ where F : Float + Into < Scalar < M :: PointerTag > > + FloatConvert < Single > + FloatConvert < Double >
209+ {
199210 use rustc:: ty:: TyKind :: * ;
200- use rustc_apfloat:: FloatConvert ;
201211 match dest_ty. sty {
202212 // float -> uint
203213 Uint ( t) => {
204214 let width = t. bit_width ( ) . unwrap_or_else ( || self . pointer_size ( ) . bits ( ) as usize ) ;
205- let v = match fty {
206- FloatTy :: F32 => Single :: from_bits ( bits) . to_u128 ( width) . value ,
207- FloatTy :: F64 => Double :: from_bits ( bits) . to_u128 ( width) . value ,
208- } ;
215+ let v = f. to_u128 ( width) . value ;
209216 // This should already fit the bit width
210217 Ok ( Scalar :: from_uint ( v, Size :: from_bits ( width as u64 ) ) )
211218 } ,
212219 // float -> int
213220 Int ( t) => {
214221 let width = t. bit_width ( ) . unwrap_or_else ( || self . pointer_size ( ) . bits ( ) as usize ) ;
215- let v = match fty {
216- FloatTy :: F32 => Single :: from_bits ( bits) . to_i128 ( width) . value ,
217- FloatTy :: F64 => Double :: from_bits ( bits) . to_i128 ( width) . value ,
218- } ;
222+ let v = f. to_i128 ( width) . value ;
219223 Ok ( Scalar :: from_int ( v, Size :: from_bits ( width as u64 ) ) )
220224 } ,
221- // f64 -> f32
222- Float ( FloatTy :: F32 ) if fty == FloatTy :: F64 =>
223- Ok ( Scalar :: from_f32 ( Double :: from_bits ( bits) . convert ( & mut false ) . value ) ) ,
224- // f32 -> f64
225- Float ( FloatTy :: F64 ) if fty == FloatTy :: F32 =>
226- Ok ( Scalar :: from_f64 ( Single :: from_bits ( bits) . convert ( & mut false ) . value ) ) ,
227- // identity cast
228- Float ( FloatTy :: F64 ) if fty == FloatTy :: F64 =>
229- Ok ( Scalar :: from_uint ( bits, Size :: from_bits ( 64 ) ) ) ,
230- Float ( FloatTy :: F32 ) if fty == FloatTy :: F32 =>
231- Ok ( Scalar :: from_uint ( bits, Size :: from_bits ( 32 ) ) ) ,
232- _ => err ! ( Unimplemented ( format!( "float to {:?} cast" , dest_ty) ) ) ,
225+ // float -> f32
226+ Float ( FloatTy :: F32 ) =>
227+ Ok ( Scalar :: from_f32 ( f. convert ( & mut false ) . value ) ) ,
228+ // float -> f64
229+ Float ( FloatTy :: F64 ) =>
230+ Ok ( Scalar :: from_f64 ( f. convert ( & mut false ) . value ) ) ,
231+ // That's it.
232+ _ => bug ! ( "invalid float to {:?} cast" , dest_ty) ,
233233 }
234234 }
235235
0 commit comments