Skip to content

Commit 330be77

Browse files
committed
Represent PrimVals as "bitbags".
Now instead of holding a native type based on the tag, all PrimVals store a u64 (the `bits`), along with a `kind` corresponding to the variant as it would be in the old PrimVal representation. This commit makes no major optimizations and attempts to not change any behaviour. There will be commits to follow that make use of this representation to eliminate unnecessary allocation hacks like in `value_to_primval`. A number of places could be even more cleaned up after this commit, particularly in `cast.rs`.
1 parent d6b4e1a commit 330be77

File tree

7 files changed

+601
-502
lines changed

7 files changed

+601
-502
lines changed

src/interpreter/cast.rs

Lines changed: 80 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -8,96 +8,107 @@ use primval::PrimVal;
88
use memory::Pointer;
99

1010
use rustc::ty::Ty;
11-
use syntax::ast::{self, IntTy, UintTy};
11+
use syntax::ast::{FloatTy, IntTy, UintTy};
1212

1313
impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1414
pub(super) fn cast_primval(&self, val: PrimVal, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
15-
use primval::PrimVal::*;
16-
match val {
17-
Bool(b) => self.cast_const_int(b as u64, ty, false),
18-
F32(f) => self.cast_const_float(f as f64, ty),
19-
F64(f) => self.cast_const_float(f, ty),
20-
I8(i) => self.cast_signed_int(i as i64, ty),
21-
I16(i) => self.cast_signed_int(i as i64, ty),
22-
I32(i) => self.cast_signed_int(i as i64, ty),
23-
I64(i) => self.cast_signed_int(i, ty),
24-
U8(u) => self.cast_const_int(u as u64, ty, false),
25-
U16(u) => self.cast_const_int(u as u64, ty, false),
26-
U32(u) => self.cast_const_int(u as u64, ty, false),
27-
Char(c) => self.cast_const_int(c as u64, ty, false),
28-
U64(u) => self.cast_const_int(u, ty, false),
29-
FnPtr(ptr) |
30-
Ptr(ptr) => self.cast_ptr(ptr, ty),
31-
}
32-
}
15+
use primval::PrimValKind::*;
16+
match val.kind {
17+
F32 => self.cast_float(val.to_f32() as f64, ty),
18+
F64 => self.cast_float(val.to_f64(), ty),
3319

34-
fn cast_ptr(&self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
35-
use primval::PrimVal::*;
36-
match ty.sty {
37-
ty::TyRef(..) |
38-
ty::TyRawPtr(_) => Ok(Ptr(ptr)),
39-
ty::TyFnPtr(_) => Ok(FnPtr(ptr)),
40-
ty::TyInt(IntTy::I8) => Ok(I8(ptr.to_int()? as i8)),
41-
ty::TyInt(IntTy::I16) => Ok(I16(ptr.to_int()? as i16)),
42-
ty::TyInt(IntTy::I32) => Ok(I32(ptr.to_int()? as i32)),
43-
ty::TyInt(IntTy::I64) => Ok(I64(ptr.to_int()? as i64)),
44-
ty::TyUint(UintTy::U8) => Ok(U8(ptr.to_int()? as u8)),
45-
ty::TyUint(UintTy::U16) => Ok(U16(ptr.to_int()? as u16)),
46-
ty::TyUint(UintTy::U32) => Ok(U32(ptr.to_int()? as u32)),
47-
ty::TyUint(UintTy::U64) => Ok(U64(ptr.to_int()? as u64)),
48-
_ => Err(EvalError::Unimplemented(format!("ptr to {:?} cast", ty))),
20+
I8 | I16 | I32 | I64 => self.cast_signed_int(val.bits as i64, ty),
21+
22+
Bool | Char | U8 | U16 | U32 | U64 => self.cast_int(val.bits, ty, false),
23+
24+
FnPtr(alloc) | Ptr(alloc) => {
25+
let ptr = Pointer::new(alloc, val.bits as usize);
26+
self.cast_ptr(ptr, ty)
27+
}
4928
}
5029
}
5130

5231
fn cast_signed_int(&self, val: i64, ty: ty::Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
53-
self.cast_const_int(val as u64, ty, val < 0)
32+
self.cast_int(val as u64, ty, val < 0)
5433
}
5534

56-
fn cast_const_int(&self, v: u64, ty: ty::Ty<'tcx>, negative: bool) -> EvalResult<'tcx, PrimVal> {
57-
use primval::PrimVal::*;
35+
fn cast_int(&self, v: u64, ty: ty::Ty<'tcx>, negative: bool) -> EvalResult<'tcx, PrimVal> {
36+
use primval::PrimValKind::*;
37+
use rustc::ty::TypeVariants::*;
5838
match ty.sty {
59-
ty::TyBool if v == 0 => Ok(Bool(false)),
60-
ty::TyBool if v == 1 => Ok(Bool(true)),
61-
ty::TyBool => Err(EvalError::InvalidBool),
62-
ty::TyInt(ast::IntTy::I8) => Ok(I8(v as i64 as i8)),
63-
ty::TyInt(ast::IntTy::I16) => Ok(I16(v as i64 as i16)),
64-
ty::TyInt(ast::IntTy::I32) => Ok(I32(v as i64 as i32)),
65-
ty::TyInt(ast::IntTy::I64) => Ok(I64(v as i64)),
66-
ty::TyInt(ast::IntTy::Is) => {
39+
TyBool if v == 0 => Ok(PrimVal::from_bool(false)),
40+
TyBool if v == 1 => Ok(PrimVal::from_bool(true)),
41+
TyBool => Err(EvalError::InvalidBool),
42+
43+
TyInt(IntTy::I8) => Ok(PrimVal::new(v as i64 as i8 as u64, I8)),
44+
TyInt(IntTy::I16) => Ok(PrimVal::new(v as i64 as i16 as u64, I16)),
45+
TyInt(IntTy::I32) => Ok(PrimVal::new(v as i64 as i32 as u64, I32)),
46+
TyInt(IntTy::I64) => Ok(PrimVal::new(v as i64 as i64 as u64, I64)),
47+
48+
TyUint(UintTy::U8) => Ok(PrimVal::new(v as u8 as u64, U8)),
49+
TyUint(UintTy::U16) => Ok(PrimVal::new(v as u16 as u64, U16)),
50+
TyUint(UintTy::U32) => Ok(PrimVal::new(v as u32 as u64, U32)),
51+
TyUint(UintTy::U64) => Ok(PrimVal::new(v, U64)),
52+
53+
TyInt(IntTy::Is) => {
6754
let int_ty = self.tcx.sess.target.int_type;
6855
let ty = self.tcx.mk_mach_int(int_ty);
69-
self.cast_const_int(v, ty, negative)
70-
},
71-
ty::TyUint(ast::UintTy::U8) => Ok(U8(v as u8)),
72-
ty::TyUint(ast::UintTy::U16) => Ok(U16(v as u16)),
73-
ty::TyUint(ast::UintTy::U32) => Ok(U32(v as u32)),
74-
ty::TyUint(ast::UintTy::U64) => Ok(U64(v)),
75-
ty::TyUint(ast::UintTy::Us) => {
56+
self.cast_int(v, ty, negative)
57+
}
58+
59+
TyUint(UintTy::Us) => {
7660
let uint_ty = self.tcx.sess.target.uint_type;
7761
let ty = self.tcx.mk_mach_uint(uint_ty);
78-
self.cast_const_int(v, ty, negative)
79-
},
80-
ty::TyFloat(ast::FloatTy::F64) if negative => Ok(F64(v as i64 as f64)),
81-
ty::TyFloat(ast::FloatTy::F64) => Ok(F64(v as f64)),
82-
ty::TyFloat(ast::FloatTy::F32) if negative => Ok(F32(v as i64 as f32)),
83-
ty::TyFloat(ast::FloatTy::F32) => Ok(F32(v as f32)),
84-
ty::TyRawPtr(_) => Ok(Ptr(Pointer::from_int(v as usize))),
85-
ty::TyChar if v as u8 as u64 == v => Ok(Char(v as u8 as char)),
86-
ty::TyChar => Err(EvalError::InvalidChar(v)),
62+
self.cast_int(v, ty, negative)
63+
}
64+
65+
TyFloat(FloatTy::F64) if negative => Ok(PrimVal::from_f64(v as i64 as f64)),
66+
TyFloat(FloatTy::F64) => Ok(PrimVal::from_f64(v as f64)),
67+
TyFloat(FloatTy::F32) if negative => Ok(PrimVal::from_f32(v as i64 as f32)),
68+
TyFloat(FloatTy::F32) => Ok(PrimVal::from_f32(v as f32)),
69+
70+
TyChar if v as u8 as u64 == v => Ok(PrimVal::new(v, Char)),
71+
TyChar => Err(EvalError::InvalidChar(v)),
72+
73+
TyRawPtr(_) => Ok(PrimVal::from_ptr(Pointer::from_int(v as usize))),
74+
8775
_ => Err(EvalError::Unimplemented(format!("int to {:?} cast", ty))),
8876
}
8977
}
9078

91-
fn cast_const_float(&self, val: f64, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
92-
use primval::PrimVal::*;
79+
fn cast_float(&self, val: f64, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
80+
use rustc::ty::TypeVariants::*;
9381
match ty.sty {
94-
// casting negative floats to unsigned integers yields zero
95-
ty::TyUint(_) if val < 0.0 => self.cast_const_int(0, ty, false),
96-
ty::TyInt(_) if val < 0.0 => self.cast_const_int(val as i64 as u64, ty, true),
97-
ty::TyInt(_) | ty::TyUint(_) => self.cast_const_int(val as u64, ty, false),
98-
ty::TyFloat(ast::FloatTy::F64) => Ok(F64(val)),
99-
ty::TyFloat(ast::FloatTy::F32) => Ok(F32(val as f32)),
82+
// Casting negative floats to unsigned integers yields zero.
83+
TyUint(_) if val < 0.0 => self.cast_int(0, ty, false),
84+
TyInt(_) if val < 0.0 => self.cast_int(val as i64 as u64, ty, true),
85+
86+
TyInt(_) | ty::TyUint(_) => self.cast_int(val as u64, ty, false),
87+
88+
TyFloat(FloatTy::F64) => Ok(PrimVal::from_f64(val)),
89+
TyFloat(FloatTy::F32) => Ok(PrimVal::from_f32(val as f32)),
10090
_ => Err(EvalError::Unimplemented(format!("float to {:?} cast", ty))),
10191
}
10292
}
93+
94+
fn cast_ptr(&self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
95+
use primval::PrimValKind::*;
96+
use rustc::ty::TypeVariants::*;
97+
match ty.sty {
98+
TyRef(..) | TyRawPtr(_) => Ok(PrimVal::from_ptr(ptr)),
99+
TyFnPtr(_) => Ok(PrimVal::from_fn_ptr(ptr)),
100+
101+
TyInt(IntTy::I8) => Ok(PrimVal::new(ptr.to_int()? as u64, I8)),
102+
TyInt(IntTy::I16) => Ok(PrimVal::new(ptr.to_int()? as u64, I16)),
103+
TyInt(IntTy::I32) => Ok(PrimVal::new(ptr.to_int()? as u64, I32)),
104+
TyInt(IntTy::I64) => Ok(PrimVal::new(ptr.to_int()? as u64, I64)),
105+
106+
TyUint(UintTy::U8) => Ok(PrimVal::new(ptr.to_int()? as u64, U8)),
107+
TyUint(UintTy::U16) => Ok(PrimVal::new(ptr.to_int()? as u64, U16)),
108+
TyUint(UintTy::U32) => Ok(PrimVal::new(ptr.to_int()? as u64, U32)),
109+
TyUint(UintTy::U64) => Ok(PrimVal::new(ptr.to_int()? as u64, U64)),
110+
111+
_ => Err(EvalError::Unimplemented(format!("ptr to {:?} cast", ty))),
112+
}
113+
}
103114
}

0 commit comments

Comments
 (0)