@@ -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,36 @@ 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 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) ,
144
156
}
145
157
}
146
158
}
147
159
}
148
160
149
161
fn cast_from_int (
150
162
& self ,
151
- v : u128 ,
163
+ v : u128 , // raw bits
152
164
src_layout : TyLayout < ' tcx > ,
153
165
dest_layout : TyLayout < ' tcx > ,
154
166
) -> InterpResult < ' tcx , Scalar < M :: PointerTag > > {
167
+ // Let's make sure v is sign-extended *if* it has a signed type.
155
168
let signed = src_layout. abi . is_signed ( ) ;
156
169
let v = if signed {
157
170
self . sign_extend ( v, src_layout)
@@ -166,21 +179,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
166
179
Ok ( Scalar :: from_uint ( v, dest_layout. size ) )
167
180
}
168
181
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
172
184
) ) ,
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
176
187
) ) ,
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
180
190
) ) ,
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
184
193
) ) ,
185
194
186
195
Char => {
@@ -194,52 +203,36 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
194
203
}
195
204
}
196
205
197
- fn cast_from_float (
206
+ fn cast_from_float < F > (
198
207
& self ,
199
- bits : u128 ,
200
- fty : FloatTy ,
208
+ f : F ,
201
209
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
+ {
203
213
use rustc:: ty:: TyKind :: * ;
204
- use rustc_apfloat:: FloatConvert ;
205
214
match dest_ty. sty {
206
215
// float -> uint
207
216
Uint ( t) => {
208
217
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 ;
213
219
// This should already fit the bit width
214
220
Ok ( Scalar :: from_uint ( v, Size :: from_bits ( width as u64 ) ) )
215
221
} ,
216
222
// float -> int
217
223
Int ( t) => {
218
224
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 ;
223
226
Ok ( Scalar :: from_int ( v, Size :: from_bits ( width as u64 ) ) )
224
227
} ,
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) ,
243
236
}
244
237
}
245
238
0 commit comments