@@ -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