Skip to content

Commit df5e122

Browse files
committed
Merge remote-tracking branch 'miri/upstream' into miri
2 parents 0253d98 + f835974 commit df5e122

File tree

17 files changed

+8266
-0
lines changed

17 files changed

+8266
-0
lines changed

.editorconfig

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# EditorConfig helps developers define and maintain consistent
2+
# coding styles between different editors and IDEs
3+
# editorconfig.org
4+
5+
root = true
6+
7+
8+
[*]
9+
end_of_line = lf
10+
charset = utf-8
11+
trim_trailing_whitespace = true
12+
insert_final_newline = true
13+
indent_style = space
14+
indent_size = 4
15+
16+
[*.rs]
17+
indent_style = space
18+
indent_size = 4
19+
20+
[*.toml]
21+
indent_style = space
22+
indent_size = 4
23+
24+
[*.md]
25+
trim_trailing_whitespace = false

src/librustc/mir/interpret/cast.rs

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
use rustc::ty::{self, Ty};
2+
use syntax::ast::{FloatTy, IntTy, UintTy};
3+
4+
use super::{PrimVal, EvalContext, EvalResult, MemoryPointer, PointerArithmetic, Machine};
5+
6+
impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
7+
pub(super) fn cast_primval(
8+
&self,
9+
val: PrimVal,
10+
src_ty: Ty<'tcx>,
11+
dest_ty: Ty<'tcx>,
12+
) -> EvalResult<'tcx, PrimVal> {
13+
trace!("Casting {:?}: {:?} to {:?}", val, src_ty, dest_ty);
14+
let src_kind = self.ty_to_primval_kind(src_ty)?;
15+
16+
match val {
17+
PrimVal::Undef => Ok(PrimVal::Undef),
18+
PrimVal::Ptr(ptr) => self.cast_from_ptr(ptr, dest_ty),
19+
val @ PrimVal::Bytes(_) => {
20+
use super::PrimValKind::*;
21+
match src_kind {
22+
F32 => self.cast_from_float(val.to_f32()? as f64, dest_ty),
23+
F64 => self.cast_from_float(val.to_f64()?, dest_ty),
24+
25+
I8 | I16 | I32 | I64 | I128 => {
26+
self.cast_from_signed_int(val.to_i128()?, dest_ty)
27+
}
28+
29+
Bool | Char | U8 | U16 | U32 | U64 | U128 | FnPtr | Ptr => {
30+
self.cast_from_int(val.to_u128()?, dest_ty, false)
31+
}
32+
}
33+
}
34+
}
35+
}
36+
37+
fn cast_from_signed_int(&self, val: i128, ty: ty::Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
38+
self.cast_from_int(val as u128, ty, val < 0)
39+
}
40+
41+
fn int_to_int(&self, v: i128, ty: IntTy) -> u128 {
42+
match ty {
43+
IntTy::I8 => v as i8 as u128,
44+
IntTy::I16 => v as i16 as u128,
45+
IntTy::I32 => v as i32 as u128,
46+
IntTy::I64 => v as i64 as u128,
47+
IntTy::I128 => v as u128,
48+
IntTy::Is => {
49+
let ty = self.tcx.sess.target.isize_ty;
50+
self.int_to_int(v, ty)
51+
}
52+
}
53+
}
54+
fn int_to_uint(&self, v: u128, ty: UintTy) -> u128 {
55+
match ty {
56+
UintTy::U8 => v as u8 as u128,
57+
UintTy::U16 => v as u16 as u128,
58+
UintTy::U32 => v as u32 as u128,
59+
UintTy::U64 => v as u64 as u128,
60+
UintTy::U128 => v,
61+
UintTy::Us => {
62+
let ty = self.tcx.sess.target.usize_ty;
63+
self.int_to_uint(v, ty)
64+
}
65+
}
66+
}
67+
68+
fn cast_from_int(
69+
&self,
70+
v: u128,
71+
ty: ty::Ty<'tcx>,
72+
negative: bool,
73+
) -> EvalResult<'tcx, PrimVal> {
74+
trace!("cast_from_int: {}, {}, {}", v, ty, negative);
75+
use rustc::ty::TypeVariants::*;
76+
match ty.sty {
77+
// Casts to bool are not permitted by rustc, no need to handle them here.
78+
TyInt(ty) => Ok(PrimVal::Bytes(self.int_to_int(v as i128, ty))),
79+
TyUint(ty) => Ok(PrimVal::Bytes(self.int_to_uint(v, ty))),
80+
81+
TyFloat(FloatTy::F64) if negative => Ok(PrimVal::from_f64(v as i128 as f64)),
82+
TyFloat(FloatTy::F64) => Ok(PrimVal::from_f64(v as f64)),
83+
TyFloat(FloatTy::F32) if negative => Ok(PrimVal::from_f32(v as i128 as f32)),
84+
TyFloat(FloatTy::F32) => Ok(PrimVal::from_f32(v as f32)),
85+
86+
TyChar if v as u8 as u128 == v => Ok(PrimVal::Bytes(v)),
87+
TyChar => err!(InvalidChar(v)),
88+
89+
// No alignment check needed for raw pointers. But we have to truncate to target ptr size.
90+
TyRawPtr(_) => Ok(PrimVal::Bytes(self.memory.truncate_to_ptr(v).0 as u128)),
91+
92+
_ => err!(Unimplemented(format!("int to {:?} cast", ty))),
93+
}
94+
}
95+
96+
fn cast_from_float(&self, val: f64, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
97+
use rustc::ty::TypeVariants::*;
98+
match ty.sty {
99+
// Casting negative floats to unsigned integers yields zero.
100+
TyUint(_) if val < 0.0 => self.cast_from_int(0, ty, false),
101+
TyInt(_) if val < 0.0 => self.cast_from_int(val as i128 as u128, ty, true),
102+
103+
TyInt(_) | ty::TyUint(_) => self.cast_from_int(val as u128, ty, false),
104+
105+
TyFloat(FloatTy::F64) => Ok(PrimVal::from_f64(val)),
106+
TyFloat(FloatTy::F32) => Ok(PrimVal::from_f32(val as f32)),
107+
_ => err!(Unimplemented(format!("float to {:?} cast", ty))),
108+
}
109+
}
110+
111+
fn cast_from_ptr(&self, ptr: MemoryPointer, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
112+
use rustc::ty::TypeVariants::*;
113+
match ty.sty {
114+
// Casting to a reference or fn pointer is not permitted by rustc, no need to support it here.
115+
TyRawPtr(_) |
116+
TyInt(IntTy::Is) |
117+
TyUint(UintTy::Us) => Ok(PrimVal::Ptr(ptr)),
118+
TyInt(_) | TyUint(_) => err!(ReadPointerAsBytes),
119+
_ => err!(Unimplemented(format!("ptr to {:?} cast", ty))),
120+
}
121+
}
122+
}

0 commit comments

Comments
 (0)