Skip to content

Commit 10ab168

Browse files
authored
Merge pull request rust-lang#60 from oli-obk/dst
some more cleanups getting rid of intermediate allocations and bad fat ptr assumptions
2 parents 1e3659e + 7e29392 commit 10ab168

File tree

9 files changed

+431
-203
lines changed

9 files changed

+431
-203
lines changed

src/interpreter/cast.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use primval::PrimVal;
88
use memory::Pointer;
99

1010
use rustc::ty::Ty;
11-
use syntax::ast;
11+
use syntax::ast::{self, 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> {
@@ -37,6 +37,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
3737
ty::TyRef(..) |
3838
ty::TyRawPtr(_) => Ok(Ptr(ptr)),
3939
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)),
4048
_ => Err(EvalError::Unimplemented(format!("ptr to {:?} cast", ty))),
4149
}
4250
}

src/interpreter/mod.rs

Lines changed: 135 additions & 138 deletions
Large diffs are not rendered by default.

src/interpreter/terminator/intrinsics.rs

Lines changed: 59 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ use rustc::hir::def_id::DefId;
22
use rustc::mir::repr as mir;
33
use rustc::ty::layout::Layout;
44
use rustc::ty::subst::Substs;
5-
use rustc::ty;
5+
use rustc::ty::{self, Ty};
66

77
use error::{EvalError, EvalResult};
88
use memory::Pointer;
99
use interpreter::EvalContext;
10-
use primval;
10+
use primval::{self, PrimVal};
11+
use interpreter::value::Value;
1112

1213
impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1314
pub(super) fn call_intrinsic(
@@ -16,29 +17,35 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1617
substs: &'tcx Substs<'tcx>,
1718
args: &[mir::Operand<'tcx>],
1819
dest: Pointer,
20+
dest_ty: Ty<'tcx>,
1921
dest_layout: &'tcx Layout,
2022
) -> EvalResult<'tcx, ()> {
21-
// TODO(solson): We can probably remove this _to_ptr easily.
22-
let args_res: EvalResult<Vec<Pointer>> = args.iter()
23-
.map(|arg| self.eval_operand_to_ptr(arg))
23+
let args_ptrs: EvalResult<Vec<Value>> = args.iter()
24+
.map(|arg| self.eval_operand(arg))
2425
.collect();
25-
let args_ptrs = args_res?;
26+
let args_ptrs = args_ptrs?;
2627
let pointer_size = self.memory.pointer_size();
28+
let i32 = self.tcx.types.i32;
29+
let isize = self.tcx.types.isize;
30+
let usize = self.tcx.types.usize;
31+
let f32 = self.tcx.types.f32;
32+
let f64 = self.tcx.types.f64;
2733

2834
match &self.tcx.item_name(def_id).as_str()[..] {
2935
"add_with_overflow" => self.intrinsic_with_overflow(mir::BinOp::Add, &args[0], &args[1], dest, dest_layout)?,
3036
"sub_with_overflow" => self.intrinsic_with_overflow(mir::BinOp::Sub, &args[0], &args[1], dest, dest_layout)?,
3137
"mul_with_overflow" => self.intrinsic_with_overflow(mir::BinOp::Mul, &args[0], &args[1], dest, dest_layout)?,
3238

3339
"arith_offset" => {
34-
let ptr = self.memory.read_ptr(args_ptrs[0])?;
35-
let offset = self.memory.read_int(args_ptrs[1], pointer_size)?;
40+
let ptr = args_ptrs[0].read_ptr(&self.memory)?;
41+
let offset = self.value_to_primval(args_ptrs[1], isize)?.expect_int("arith_offset second arg not isize");
3642
let new_ptr = ptr.offset(offset as isize);
3743
self.memory.write_ptr(dest, new_ptr)?;
3844
}
3945

4046
"assume" => {
41-
if !self.memory.read_bool(args_ptrs[0])? {
47+
let bool = self.tcx.types.bool;
48+
if !self.value_to_primval(args_ptrs[0], bool)?.expect_bool("assume arg not bool") {
4249
return Err(EvalError::AssumptionNotHeld);
4350
}
4451
}
@@ -51,47 +58,59 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
5158
let elem_ty = substs.type_at(0);
5259
let elem_size = self.type_size(elem_ty);
5360
let elem_align = self.type_align(elem_ty);
54-
let src = self.memory.read_ptr(args_ptrs[0])?;
55-
let dest = self.memory.read_ptr(args_ptrs[1])?;
56-
let count = self.memory.read_isize(args_ptrs[2])?;
61+
let src = args_ptrs[0].read_ptr(&self.memory)?;
62+
let dest = args_ptrs[1].read_ptr(&self.memory)?;
63+
let count = self.value_to_primval(args_ptrs[2], usize)?.expect_uint("arith_offset second arg not isize");
5764
self.memory.copy(src, dest, count as usize * elem_size, elem_align)?;
5865
}
5966

6067
"ctpop" => {
6168
let elem_ty = substs.type_at(0);
6269
let elem_size = self.type_size(elem_ty);
63-
let num = self.memory.read_uint(args_ptrs[0], elem_size)?.count_ones();
70+
let num = self.value_to_primval(args_ptrs[2], elem_ty)?.expect_int("ctpop second arg not integral");
71+
let num = num.count_ones();
6472
self.memory.write_uint(dest, num.into(), elem_size)?;
6573
}
6674

6775
"ctlz" => {
6876
let elem_ty = substs.type_at(0);
6977
let elem_size = self.type_size(elem_ty);
70-
let num = self.memory.read_uint(args_ptrs[0], elem_size)?.leading_zeros();
78+
let num = self.value_to_primval(args_ptrs[2], elem_ty)?;
79+
let num = match num {
80+
PrimVal::I8(i) => i.leading_zeros(),
81+
PrimVal::U8(i) => i.leading_zeros(),
82+
PrimVal::I16(i) => i.leading_zeros(),
83+
PrimVal::U16(i) => i.leading_zeros(),
84+
PrimVal::I32(i) => i.leading_zeros(),
85+
PrimVal::U32(i) => i.leading_zeros(),
86+
PrimVal::I64(i) => i.leading_zeros(),
87+
PrimVal::U64(i) => i.leading_zeros(),
88+
_ => bug!("ctlz called with non-integer type"),
89+
};
7190
self.memory.write_uint(dest, num.into(), elem_size)?;
7291
}
7392

7493
"discriminant_value" => {
7594
let ty = substs.type_at(0);
76-
let adt_ptr = self.memory.read_ptr(args_ptrs[0])?;
95+
let adt_ptr = args_ptrs[0].read_ptr(&self.memory)?;
7796
let discr_val = self.read_discriminant_value(adt_ptr, ty)?;
7897
self.memory.write_uint(dest, discr_val, 8)?;
7998
}
8099

81100
"fabsf32" => {
82-
let f = self.memory.read_f32(args_ptrs[0])?;
101+
let f = self.value_to_primval(args_ptrs[2], f32)?.expect_f32("fabsf32 read non f32");
83102
self.memory.write_f32(dest, f.abs())?;
84103
}
85104

86105
"fabsf64" => {
87-
let f = self.memory.read_f64(args_ptrs[0])?;
106+
let f = self.value_to_primval(args_ptrs[2], f64)?.expect_f64("fabsf64 read non f64");
88107
self.memory.write_f64(dest, f.abs())?;
89108
}
90109

91110
"fadd_fast" => {
92111
let ty = substs.type_at(0);
93-
let a = self.read_primval(args_ptrs[0], ty)?;
94-
let b = self.read_primval(args_ptrs[0], ty)?;
112+
let a = self.value_to_primval(args_ptrs[0], ty)?;
113+
let b = self.value_to_primval(args_ptrs[0], ty)?;
95114
let result = primval::binary_op(mir::BinOp::Add, a, b)?;
96115
self.memory.write_primval(dest, result.0)?;
97116
}
@@ -117,8 +136,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
117136

118137
"move_val_init" => {
119138
let ty = substs.type_at(0);
120-
let ptr = self.memory.read_ptr(args_ptrs[0])?;
121-
self.move_(args_ptrs[1], ptr, ty)?;
139+
let ptr = args_ptrs[0].read_ptr(&self.memory)?;
140+
self.write_value(args_ptrs[1], ptr, ty)?;
122141
}
123142

124143
"needs_drop" => {
@@ -129,10 +148,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
129148
"offset" => {
130149
let pointee_ty = substs.type_at(0);
131150
let pointee_size = self.type_size(pointee_ty) as isize;
132-
let ptr_arg = args_ptrs[0];
133-
let offset = self.memory.read_isize(args_ptrs[1])?;
151+
let offset = self.value_to_primval(args_ptrs[1], isize)?.expect_int("offset second arg not isize");
134152

135-
let ptr = self.memory.read_ptr(ptr_arg)?;
153+
let ptr = args_ptrs[0].read_ptr(&self.memory)?;
136154
let result_ptr = ptr.offset(offset as isize * pointee_size);
137155
self.memory.write_ptr(dest, result_ptr)?;
138156
}
@@ -150,24 +168,24 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
150168
}
151169

152170
"powif32" => {
153-
let f = self.memory.read_f32(args_ptrs[0])?;
154-
let i = self.memory.read_int(args_ptrs[1], 4)?;
171+
let f = self.value_to_primval(args_ptrs[0], f32)?.expect_f32("powif32 first arg not f32");
172+
let i = self.value_to_primval(args_ptrs[1], i32)?.expect_int("powif32 second arg not i32");
155173
self.memory.write_f32(dest, f.powi(i as i32))?;
156174
}
157175

158176
"powif64" => {
159-
let f = self.memory.read_f32(args_ptrs[0])?;
160-
let i = self.memory.read_int(args_ptrs[1], 4)?;
161-
self.memory.write_f32(dest, f.powi(i as i32))?;
177+
let f = self.value_to_primval(args_ptrs[0], f64)?.expect_f64("powif64 first arg not f64");
178+
let i = self.value_to_primval(args_ptrs[1], i32)?.expect_int("powif64 second arg not i32");
179+
self.memory.write_f64(dest, f.powi(i as i32))?;
162180
}
163181

164182
"sqrtf32" => {
165-
let f = self.memory.read_f32(args_ptrs[0])?;
183+
let f = self.value_to_primval(args_ptrs[0], f32)?.expect_f32("sqrtf32 first arg not f32");
166184
self.memory.write_f32(dest, f.sqrt())?;
167185
}
168186

169187
"sqrtf64" => {
170-
let f = self.memory.read_f64(args_ptrs[0])?;
188+
let f = self.value_to_primval(args_ptrs[0], f64)?.expect_f64("sqrtf64 first arg not f64");
171189
self.memory.write_f64(dest, f.sqrt())?;
172190
}
173191

@@ -182,14 +200,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
182200
let (size, _) = self.size_and_align_of_dst(ty, args_ptrs[0])?;
183201
self.memory.write_uint(dest, size, pointer_size)?;
184202
}
185-
// FIXME: wait for eval_operand_to_ptr to be gone
186-
/*
187203
"type_name" => {
188204
let ty = substs.type_at(0);
189205
let ty_name = ty.to_string();
190206
let s = self.str_to_value(&ty_name)?;
191-
self.memory.write_ptr(dest, s)?;
192-
}*/
207+
self.write_value(s, dest, dest_ty)?;
208+
}
193209
"type_id" => {
194210
let ty = substs.type_at(0);
195211
let n = self.tcx.type_id_hash(ty);
@@ -198,7 +214,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
198214

199215
"transmute" => {
200216
let ty = substs.type_at(0);
201-
self.move_(args_ptrs[0], dest, ty)?;
217+
self.write_value(args_ptrs[0], dest, ty)?;
202218
}
203219

204220
"try" => unimplemented!(),
@@ -207,14 +223,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
207223

208224
"volatile_load" => {
209225
let ty = substs.type_at(0);
210-
let ptr = self.memory.read_ptr(args_ptrs[0])?;
226+
let ptr = args_ptrs[0].read_ptr(&self.memory)?;
211227
self.move_(ptr, dest, ty)?;
212228
}
213229

214230
"volatile_store" => {
215231
let ty = substs.type_at(0);
216-
let dest = self.memory.read_ptr(args_ptrs[0])?;
217-
self.move_(args_ptrs[1], dest, ty)?;
232+
let dest = args_ptrs[0].read_ptr(&self.memory)?;
233+
self.write_value(args_ptrs[1], dest, ty)?;
218234
}
219235

220236
name => return Err(EvalError::Unimplemented(format!("unimplemented intrinsic: {}", name))),
@@ -229,7 +245,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
229245
fn size_and_align_of_dst(
230246
&self,
231247
ty: ty::Ty<'tcx>,
232-
value: Pointer,
248+
value: Value,
233249
) -> EvalResult<'tcx, (u64, u64)> {
234250
let pointer_size = self.memory.pointer_size();
235251
if self.type_is_sized(ty) {
@@ -306,8 +322,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
306322
}
307323
}
308324
ty::TyTrait(..) => {
309-
let (_, vtable) = self.get_fat_ptr(value);
310-
let vtable = self.memory.read_ptr(vtable)?;
325+
let vtable = value.expect_vtable(&self.memory)?;
311326
// the second entry in the vtable is the dynamic size of the object.
312327
let size = self.memory.read_usize(vtable.offset(pointer_size as isize))?;
313328
let align = self.memory.read_usize(vtable.offset(pointer_size as isize * 2))?;
@@ -317,10 +332,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
317332
ty::TySlice(_) | ty::TyStr => {
318333
let elem_ty = ty.sequence_element_type(self.tcx);
319334
let elem_size = self.type_size(elem_ty) as u64;
320-
let (_, len_ptr) = self.get_fat_ptr(value);
321-
let n = self.memory.read_usize(len_ptr)?;
335+
let len = value.expect_slice_len(&self.memory)?;
322336
let align = self.type_align(elem_ty);
323-
Ok((n * elem_size, align as u64))
337+
Ok((len * elem_size, align as u64))
324338
}
325339

326340
_ => bug!("size_of_val::<{:?}>", ty),

src/interpreter/terminator/mod.rs

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ use syntax::{ast, attr};
1414
use error::{EvalError, EvalResult};
1515
use memory::Pointer;
1616
use primval::PrimVal;
17-
use super::{EvalContext, IntegerExt, StackPopCleanup, Value};
17+
use super::{EvalContext, IntegerExt, StackPopCleanup};
18+
use super::value::Value;
1819

1920
mod intrinsics;
2021

@@ -164,7 +165,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
164165
let ty = fn_ty.sig.0.output;
165166
let layout = self.type_layout(ty);
166167
let (ret, target) = destination.unwrap();
167-
self.call_intrinsic(def_id, substs, arg_operands, ret, layout)?;
168+
self.call_intrinsic(def_id, substs, arg_operands, ret, ty, layout)?;
168169
self.goto_block(target);
169170
Ok(())
170171
}
@@ -265,9 +266,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
265266
None => name.as_str(),
266267
};
267268

268-
// TODO(solson): We can probably remove this _to_ptr easily.
269-
let args_res: EvalResult<Vec<Pointer>> = args.iter()
270-
.map(|arg| self.eval_operand_to_ptr(arg))
269+
let args_res: EvalResult<Vec<Value>> = args.iter()
270+
.map(|arg| self.eval_operand(arg))
271271
.collect();
272272
let args = args_res?;
273273

@@ -276,26 +276,28 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
276276
return Ok(());
277277
}
278278

279+
let usize = self.tcx.types.usize;
280+
279281
match &link_name[..] {
280282
"__rust_allocate" => {
281-
let size = self.memory.read_usize(args[0])?;
282-
let align = self.memory.read_usize(args[1])?;
283+
let size = self.value_to_primval(args[0], usize)?.expect_uint("__rust_allocate first arg not usize");
284+
let align = self.value_to_primval(args[1], usize)?.expect_uint("__rust_allocate second arg not usize");
283285
let ptr = self.memory.allocate(size as usize, align as usize)?;
284286
self.memory.write_ptr(dest, ptr)?;
285287
}
286288

287289
"__rust_reallocate" => {
288-
let ptr = self.memory.read_ptr(args[0])?;
289-
let size = self.memory.read_usize(args[2])?;
290-
let align = self.memory.read_usize(args[3])?;
290+
let ptr = args[0].read_ptr(&self.memory)?;
291+
let size = self.value_to_primval(args[2], usize)?.expect_uint("__rust_reallocate third arg not usize");
292+
let align = self.value_to_primval(args[3], usize)?.expect_uint("__rust_reallocate fourth arg not usize");
291293
let new_ptr = self.memory.reallocate(ptr, size as usize, align as usize)?;
292294
self.memory.write_ptr(dest, new_ptr)?;
293295
}
294296

295297
"memcmp" => {
296-
let left = self.memory.read_ptr(args[0])?;
297-
let right = self.memory.read_ptr(args[1])?;
298-
let n = self.memory.read_usize(args[2])? as usize;
298+
let left = args[0].read_ptr(&self.memory)?;
299+
let right = args[1].read_ptr(&self.memory)?;
300+
let n = self.value_to_primval(args[2], usize)?.expect_uint("__rust_reallocate first arg not usize") as usize;
299301

300302
let result = {
301303
let left_bytes = self.memory.read_bytes(left, n)?;
@@ -419,7 +421,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
419421
// intermediate function call.
420422
// FIXME: this is a memory leak, should probably add the pointer to the
421423
// current stack.
422-
let first = self.value_to_ptr(args[0].0, args[0].1)?;
424+
let first = self.value_to_ptr_dont_use(args[0].0, args[0].1)?;
423425
args[0].0 = Value::ByVal(PrimVal::Ptr(first));
424426
args[0].1 = self.tcx.mk_mut_ptr(args[0].1);
425427
}
@@ -442,11 +444,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
442444
traits::VtableObject(ref data) => {
443445
let idx = self.tcx.get_vtable_index_of_object_method(data, def_id);
444446
if let Some(&mut(ref mut first_arg, ref mut first_ty)) = args.get_mut(0) {
445-
// FIXME(solson): Remove this allocating hack.
446-
let ptr = self.value_to_ptr(*first_arg, *first_ty)?;
447-
*first_arg = Value::ByRef(ptr);
448-
let (_, vtable) = self.get_fat_ptr(ptr);
449-
let vtable = self.memory.read_ptr(vtable)?;
447+
let vtable = first_arg.expect_vtable(&self.memory)?;
450448
let idx = idx + 3;
451449
let offset = idx * self.memory.pointer_size();
452450
let fn_ptr = self.memory.read_ptr(vtable.offset(offset as isize))?;

0 commit comments

Comments
 (0)