Skip to content

Commit 17e336c

Browse files
committed
Merge branch 'master' of https://github.com/tsion/miri
2 parents 145cbf8 + 5b012ed commit 17e336c

File tree

6 files changed

+89
-63
lines changed

6 files changed

+89
-63
lines changed

src/interpreter/cast.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
2828
U64(u) |
2929
IntegerPtr(u) => self.cast_const_int(u, ty, false),
3030
FnPtr(ptr) |
31-
AbstractPtr(ptr) => self.cast_ptr(ptr, ty),
31+
Ptr(ptr) => self.cast_ptr(ptr, ty),
3232
}
3333
}
3434

3535
fn cast_ptr(&self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
3636
use primval::PrimVal::*;
3737
match ty.sty {
3838
ty::TyRef(..) |
39-
ty::TyRawPtr(_) => Ok(AbstractPtr(ptr)),
39+
ty::TyRawPtr(_) => Ok(Ptr(ptr)),
4040
ty::TyFnPtr(_) => Ok(FnPtr(ptr)),
4141
_ => Err(EvalError::Unimplemented(format!("ptr to {:?} cast", ty))),
4242
}

src/interpreter/mod.rs

+33-28
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
246246
self.memory.write_bytes(ptr, s.as_bytes())?;
247247
self.memory.freeze(ptr.alloc_id)?;
248248
Value::ByValPair(
249-
PrimVal::AbstractPtr(ptr),
249+
PrimVal::Ptr(ptr),
250250
self.target_usize_primval(s.len() as u64)
251251
)
252252
}
@@ -255,7 +255,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
255255
let ptr = self.memory.allocate(bs.len(), 1)?;
256256
self.memory.write_bytes(ptr, bs)?;
257257
self.memory.freeze(ptr.alloc_id)?;
258-
Value::ByVal(PrimVal::AbstractPtr(ptr))
258+
Value::ByVal(PrimVal::Ptr(ptr))
259259
}
260260

261261
Struct(_) => unimplemented!(),
@@ -782,31 +782,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
782782
// remove it as soon as PrimVal can represent fat pointers.
783783
fn eval_operand_to_ptr(&mut self, op: &mir::Operand<'tcx>) -> EvalResult<'tcx, Pointer> {
784784
let value = self.eval_operand(op)?;
785-
match value {
786-
Value::ByRef(ptr) => Ok(ptr),
787-
788-
Value::ByVal(primval) => {
789-
let ty = self.operand_ty(op);
790-
let size = self.type_size(ty);
791-
let align = self.type_align(ty);
792-
let ptr = self.memory.allocate(size, align)?;
793-
self.memory.write_primval(ptr, primval)?;
794-
Ok(ptr)
795-
}
796-
797-
Value::ByValPair(primval1, primval2) => {
798-
let ty = self.operand_ty(op);
799-
let size = self.type_size(ty);
800-
let align = self.type_align(ty);
801-
let ptr = self.memory.allocate(size, align)?;
802-
803-
// FIXME(solson): Major dangerous assumptions here. Ideally obliterate this
804-
// function.
805-
self.memory.write_primval(ptr, primval1)?;
806-
self.memory.write_primval(ptr.offset((size / 2) as isize), primval2)?;
807-
Ok(ptr)
808-
}
809-
}
785+
let ty = self.operand_ty(op);
786+
self.value_to_ptr(value, ty)
810787
}
811788

812789
fn eval_operand_to_primval(&mut self, op: &mir::Operand<'tcx>) -> EvalResult<'tcx, PrimVal> {
@@ -992,6 +969,34 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
992969
Ok(())
993970
}
994971

972+
// FIXME(solson): This method unnecessarily allocates and should not be necessary. We can
973+
// remove it as soon as PrimVal can represent fat pointers.
974+
fn value_to_ptr(&mut self, value: Value, ty: Ty<'tcx>) -> EvalResult<'tcx, Pointer> {
975+
match value {
976+
Value::ByRef(ptr) => Ok(ptr),
977+
978+
Value::ByVal(primval) => {
979+
let size = self.type_size(ty);
980+
let align = self.type_align(ty);
981+
let ptr = self.memory.allocate(size, align)?;
982+
self.memory.write_primval(ptr, primval)?;
983+
Ok(ptr)
984+
}
985+
986+
Value::ByValPair(primval1, primval2) => {
987+
let size = self.type_size(ty);
988+
let align = self.type_align(ty);
989+
let ptr = self.memory.allocate(size, align)?;
990+
991+
// FIXME(solson): Major dangerous assumptions here. Ideally obliterate this
992+
// function.
993+
self.memory.write_primval(ptr, primval1)?;
994+
self.memory.write_primval(ptr.offset((size / 2) as isize), primval2)?;
995+
Ok(ptr)
996+
}
997+
}
998+
}
999+
9951000
fn value_to_primval(&mut self, value: Value, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> {
9961001
match value {
9971002
Value::ByRef(ptr) => self.read_primval(ptr, ty),
@@ -1057,7 +1062,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
10571062
&ty::TyRawPtr(ty::TypeAndMut { ty, .. }) => {
10581063
if self.type_is_sized(ty) {
10591064
match self.memory.read_ptr(ptr) {
1060-
Ok(p) => PrimVal::AbstractPtr(p),
1065+
Ok(p) => PrimVal::Ptr(p),
10611066
Err(EvalError::ReadBytesAsPointer) => {
10621067
PrimVal::IntegerPtr(self.memory.read_usize(ptr)?)
10631068
}

src/interpreter/step.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
8282

8383
// Miri can safely ignore these. Only translation needs them.
8484
StorageLive(_) | StorageDead(_) => {}
85+
86+
// Defined to do nothing. These are added by optimization passes, to avoid changing the
87+
// size of MIR constantly.
88+
Nop => {}
8589
}
8690

8791
self.frame_mut().stmt += 1;
@@ -186,12 +190,18 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for ConstantExtractor<'a, 'b, 'tcx> {
186190
}
187191
}
188192

189-
fn visit_lvalue(&mut self, lvalue: &mir::Lvalue<'tcx>, context: LvalueContext, location: mir::Location) {
193+
fn visit_lvalue(
194+
&mut self,
195+
lvalue: &mir::Lvalue<'tcx>,
196+
context: LvalueContext<'tcx>,
197+
location: mir::Location
198+
) {
190199
self.super_lvalue(lvalue, context, location);
191200
if let mir::Lvalue::Static(def_id) = *lvalue {
192201
let substs = subst::Substs::empty(self.ecx.tcx);
193202
let span = self.span;
194-
if let hir::map::Node::NodeItem(&hir::Item { ref node, .. }) = self.ecx.tcx.map.get_if_local(def_id).expect("static not found") {
203+
let node_item = self.ecx.tcx.map.get_if_local(def_id).expect("static not found");
204+
if let hir::map::Node::NodeItem(&hir::Item { ref node, .. }) = node_item {
195205
if let hir::ItemStatic(_, m, _) = *node {
196206
self.global_item(def_id, substs, span, m == hir::MutImmutable);
197207
return;

src/interpreter/terminator/mod.rs

+35-24
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ use syntax::{ast, attr};
1313

1414
use error::{EvalError, EvalResult};
1515
use memory::Pointer;
16-
use super::{EvalContext, IntegerExt, StackPopCleanup};
16+
use primval::PrimVal;
17+
use super::{EvalContext, IntegerExt, StackPopCleanup, Value};
1718

1819
mod intrinsics;
1920

@@ -154,7 +155,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
154155
substs: &'tcx Substs<'tcx>,
155156
fn_ty: &'tcx BareFnTy,
156157
destination: Option<(Pointer, mir::BasicBlock)>,
157-
args: &[mir::Operand<'tcx>],
158+
arg_operands: &[mir::Operand<'tcx>],
158159
span: Span,
159160
) -> EvalResult<'tcx, ()> {
160161
use syntax::abi::Abi;
@@ -163,7 +164,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
163164
let ty = fn_ty.sig.0.output;
164165
let layout = self.type_layout(ty);
165166
let (ret, target) = destination.unwrap();
166-
self.call_intrinsic(def_id, substs, args, ret, layout)?;
167+
self.call_intrinsic(def_id, substs, arg_operands, ret, layout)?;
167168
self.goto_block(target);
168169
Ok(())
169170
}
@@ -172,23 +173,23 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
172173
let ty = fn_ty.sig.0.output;
173174
let size = self.type_size(ty);
174175
let (ret, target) = destination.unwrap();
175-
self.call_c_abi(def_id, args, ret, size)?;
176+
self.call_c_abi(def_id, arg_operands, ret, size)?;
176177
self.goto_block(target);
177178
Ok(())
178179
}
179180

180181
Abi::Rust | Abi::RustCall => {
181-
let mut arg_srcs = Vec::new();
182-
for arg in args {
183-
let src = self.eval_operand_to_ptr(arg)?;
184-
let src_ty = self.operand_ty(arg);
185-
arg_srcs.push((src, src_ty));
182+
let mut args = Vec::new();
183+
for arg in arg_operands {
184+
let arg_val = self.eval_operand(arg)?;
185+
let arg_ty = self.operand_ty(arg);
186+
args.push((arg_val, arg_ty));
186187
}
187188

188189
// Only trait methods can have a Self parameter.
189190
let (resolved_def_id, resolved_substs) =
190191
if let Some(trait_id) = self.tcx.trait_of_item(def_id) {
191-
self.trait_method(trait_id, def_id, substs, &mut arg_srcs)?
192+
self.trait_method(trait_id, def_id, substs, &mut args)?
192193
} else {
193194
(def_id, substs)
194195
};
@@ -200,9 +201,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
200201
};
201202
self.push_stack_frame(resolved_def_id, span, mir, resolved_substs, return_ptr, return_to_block)?;
202203

203-
for (i, (src, src_ty)) in arg_srcs.into_iter().enumerate() {
204+
for (i, (arg_val, arg_ty)) in args.into_iter().enumerate() {
204205
let dest = self.frame().locals[i];
205-
self.move_(src, dest, src_ty)?;
206+
self.write_value(arg_val, dest, arg_ty)?;
206207
}
207208

208209
Ok(())
@@ -344,7 +345,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
344345
})
345346
}
346347

347-
fn unpack_fn_args(&self, args: &mut Vec<(Pointer, Ty<'tcx>)>) {
348+
fn unpack_fn_args(&self, args: &mut Vec<(Value, Ty<'tcx>)>) {
348349
if let Some((last, last_ty)) = args.pop() {
349350
let last_layout = self.type_layout(last_ty);
350351
match (&last_ty.sty, last_layout) {
@@ -353,9 +354,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
353354
let offsets = iter::once(0)
354355
.chain(variant.offset_after_field.iter()
355356
.map(|s| s.bytes()));
357+
let last_ptr = match last {
358+
Value::ByRef(ptr) => ptr,
359+
_ => bug!("rust-call ABI tuple argument wasn't Value::ByRef"),
360+
};
356361
for (offset, ty) in offsets.zip(fields) {
357-
let src = last.offset(offset as isize);
358-
args.push((src, ty));
362+
let arg = Value::ByRef(last_ptr.offset(offset as isize));
363+
args.push((arg, ty));
359364
}
360365
}
361366
ty => bug!("expected tuple as last argument in function with 'rust-call' ABI, got {:?}", ty),
@@ -369,7 +374,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
369374
trait_id: DefId,
370375
def_id: DefId,
371376
substs: &'tcx Substs<'tcx>,
372-
args: &mut Vec<(Pointer, Ty<'tcx>)>,
377+
args: &mut Vec<(Value, Ty<'tcx>)>,
373378
) -> EvalResult<'tcx, (DefId, &'tcx Substs<'tcx>)> {
374379
let trait_ref = ty::TraitRef::from_method(self.tcx, trait_id, substs);
375380
let trait_ref = self.tcx.normalize_associated_type(&ty::Binder(trait_ref));
@@ -398,6 +403,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
398403
(ty::ClosureKind::FnMut, ty::ClosureKind::FnMut) |
399404
(ty::ClosureKind::FnOnce, ty::ClosureKind::FnOnce) |
400405
(ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => {} // No adapter needed.
406+
401407
(ty::ClosureKind::Fn, ty::ClosureKind::FnOnce) |
402408
(ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
403409
// The closure fn is a `fn(&self, ...)` or `fn(&mut self, ...)`.
@@ -409,13 +415,15 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
409415
//
410416
// These are both the same at trans time.
411417

412-
// interpreter magic: insert an intermediate pointer, so we can skip the intermediate function call
413-
// FIXME: this is a memory leak, should probably add the pointer to the current stack
414-
let ptr_size = self.memory.pointer_size();
415-
let first = self.memory.allocate(ptr_size, ptr_size)?;
416-
self.memory.copy(args[0].0, first, ptr_size, ptr_size)?;
417-
self.memory.write_ptr(args[0].0, first)?;
418+
// Interpreter magic: insert an intermediate pointer, so we can skip the
419+
// intermediate function call.
420+
// FIXME: this is a memory leak, should probably add the pointer to the
421+
// current stack.
422+
let first = self.value_to_ptr(args[0].0, args[0].1)?;
423+
args[0].0 = Value::ByVal(PrimVal::Ptr(first));
424+
args[0].1 = self.tcx.mk_mut_ptr(args[0].1);
418425
}
426+
419427
_ => bug!("cannot convert {:?} to {:?}", closure_kind, trait_closure_kind),
420428
}
421429
Ok((vtable_closure.closure_def_id, vtable_closure.substs.func_substs))
@@ -433,8 +441,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
433441

434442
traits::VtableObject(ref data) => {
435443
let idx = self.tcx.get_vtable_index_of_object_method(data, def_id);
436-
if let Some(&mut(first_arg, ref mut first_ty)) = args.get_mut(0) {
437-
let (_, vtable) = self.get_fat_ptr(first_arg);
444+
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);
438449
let vtable = self.memory.read_ptr(vtable)?;
439450
let idx = idx + 3;
440451
let offset = idx * self.memory.pointer_size();

src/memory.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
530530
PrimVal::F32(f) => self.write_f32(ptr, f),
531531
PrimVal::F64(f) => self.write_f64(ptr, f),
532532
PrimVal::FnPtr(p) |
533-
PrimVal::AbstractPtr(p) => self.write_ptr(ptr, p),
533+
PrimVal::Ptr(p) => self.write_ptr(ptr, p),
534534
}
535535
}
536536

src/primval.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub enum PrimVal {
1212
I8(i8), I16(i16), I32(i32), I64(i64),
1313
U8(u8), U16(u16), U32(u32), U64(u64),
1414

15-
AbstractPtr(Pointer),
15+
Ptr(Pointer),
1616
FnPtr(Pointer),
1717
IntegerPtr(u64),
1818
Char(char),
@@ -211,10 +211,10 @@ pub fn binary_op<'tcx>(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> Eva
211211

212212
(IntegerPtr(l), IntegerPtr(r)) => int_binops!(IntegerPtr, l, r),
213213

214-
(AbstractPtr(_), IntegerPtr(_)) |
215-
(IntegerPtr(_), AbstractPtr(_)) |
216-
(FnPtr(_), AbstractPtr(_)) |
217-
(AbstractPtr(_), FnPtr(_)) |
214+
(Ptr(_), IntegerPtr(_)) |
215+
(IntegerPtr(_), Ptr(_)) |
216+
(FnPtr(_), Ptr(_)) |
217+
(Ptr(_), FnPtr(_)) |
218218
(FnPtr(_), IntegerPtr(_)) |
219219
(IntegerPtr(_), FnPtr(_)) =>
220220
unrelated_ptr_ops(bin_op)?,
@@ -225,7 +225,7 @@ pub fn binary_op<'tcx>(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> Eva
225225
_ => return Err(EvalError::Unimplemented(format!("unimplemented fn ptr comparison: {:?}", bin_op))),
226226
},
227227

228-
(AbstractPtr(l_ptr), AbstractPtr(r_ptr)) => {
228+
(Ptr(l_ptr), Ptr(r_ptr)) => {
229229
if l_ptr.alloc_id != r_ptr.alloc_id {
230230
return Ok((unrelated_ptr_ops(bin_op)?, false));
231231
}

0 commit comments

Comments
 (0)