@@ -5,11 +5,11 @@ use syntax::ast::{FloatTy, IntTy, UintTy};
5
5
use syntax:: symbol:: sym;
6
6
7
7
use rustc_apfloat:: ieee:: { Single , Double } ;
8
+ use rustc_apfloat:: { Float , FloatConvert } ;
8
9
use rustc:: mir:: interpret:: {
9
10
Scalar , InterpResult , Pointer , PointerArithmetic , InterpError ,
10
11
} ;
11
12
use rustc:: mir:: CastKind ;
12
- use rustc_apfloat:: Float ;
13
13
14
14
use super :: { InterpretCx , Machine , PlaceTy , OpTy , Immediate } ;
15
15
@@ -126,7 +126,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
126
126
Ok ( ( ) )
127
127
}
128
128
129
- pub ( super ) fn cast_scalar (
129
+ fn cast_scalar (
130
130
& self ,
131
131
val : Scalar < M :: PointerTag > ,
132
132
src_layout : TyLayout < ' tcx > ,
@@ -135,23 +135,33 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
135
135
use rustc:: ty:: TyKind :: * ;
136
136
trace ! ( "Casting {:?}: {:?} to {:?}" , val, src_layout. ty, dest_layout. ty) ;
137
137
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) ,
144
153
}
145
154
}
146
155
}
147
156
}
148
157
149
158
fn cast_from_int (
150
159
& self ,
151
- v : u128 ,
160
+ v : u128 , // raw bits
152
161
src_layout : TyLayout < ' tcx > ,
153
162
dest_layout : TyLayout < ' tcx > ,
154
163
) -> InterpResult < ' tcx , Scalar < M :: PointerTag > > {
164
+ // Let's make sure v is sign-extended *if* it has a signed type.
155
165
let signed = src_layout. abi . is_signed ( ) ;
156
166
let v = if signed {
157
167
self . sign_extend ( v, src_layout)
@@ -190,46 +200,36 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
190
200
}
191
201
}
192
202
193
- fn cast_from_float (
203
+ fn cast_from_float < F > (
194
204
& self ,
195
- bits : u128 ,
196
- fty : FloatTy ,
205
+ f : F ,
197
206
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
+ {
199
210
use rustc:: ty:: TyKind :: * ;
200
- use rustc_apfloat:: FloatConvert ;
201
211
match dest_ty. sty {
202
212
// float -> uint
203
213
Uint ( t) => {
204
214
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 ;
209
216
// This should already fit the bit width
210
217
Ok ( Scalar :: from_uint ( v, Size :: from_bits ( width as u64 ) ) )
211
218
} ,
212
219
// float -> int
213
220
Int ( t) => {
214
221
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 ;
219
223
Ok ( Scalar :: from_int ( v, Size :: from_bits ( width as u64 ) ) )
220
224
} ,
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) ,
233
233
}
234
234
}
235
235
0 commit comments