]> git.lizzy.rs Git - rust.git/blob - src/interpreter.rs
4ab2413e0ffe2b70097dc6abb27e913e6ec6ee17
[rust.git] / src / interpreter.rs
1 use rustc::infer;
2 use rustc::middle::const_val;
3 use rustc::hir::def_id::DefId;
4 use rustc::mir::mir_map::MirMap;
5 use rustc::mir::repr as mir;
6 use rustc::traits::{self, ProjectionMode};
7 use rustc::ty::fold::TypeFoldable;
8 use rustc::ty::layout::{self, Layout, Size};
9 use rustc::ty::subst::{self, Subst, Substs};
10 use rustc::ty::{self, TyCtxt};
11 use rustc::util::nodemap::DefIdMap;
12 use std::cell::RefCell;
13 use std::ops::Deref;
14 use std::rc::Rc;
15 use std::{iter, mem};
16 use syntax::ast;
17 use syntax::attr;
18 use syntax::codemap::{self, DUMMY_SP};
19
20 use error::{EvalError, EvalResult};
21 use memory::{Memory, Pointer};
22 use primval::{self, PrimVal};
23
24 const TRACE_EXECUTION: bool = false;
25
26 struct Interpreter<'a, 'tcx: 'a> {
27     /// The results of the type checker, from rustc.
28     tcx: &'a TyCtxt<'tcx>,
29
30     /// A mapping from NodeIds to Mir, from rustc. Only contains MIR for crate-local items.
31     mir_map: &'a MirMap<'tcx>,
32
33     /// A local cache from DefIds to Mir for non-crate-local items.
34     mir_cache: RefCell<DefIdMap<Rc<mir::Mir<'tcx>>>>,
35
36     /// The virtual memory system.
37     memory: Memory,
38
39     /// The virtual call stack.
40     stack: Vec<Frame<'a, 'tcx>>,
41
42     /// Another stack containing the type substitutions for the current function invocation. It
43     /// exists separately from `stack` because it must contain the `Substs` for a function while
44     /// *creating* the `Frame` for that same function.
45     substs_stack: Vec<&'tcx Substs<'tcx>>,
46
47     // TODO(tsion): Merge with `substs_stack`. Also try restructuring `Frame` to accomodate.
48     /// A stack of the things necessary to print good strack traces:
49     ///   * Function DefIds and Substs to print proper substituted function names.
50     ///   * Spans pointing to specific function calls in the source.
51     name_stack: Vec<(DefId, &'tcx Substs<'tcx>, codemap::Span)>,
52 }
53
54 /// A stack frame.
55 struct Frame<'a, 'tcx: 'a> {
56     /// The MIR for the function called on this frame.
57     mir: CachedMir<'a, 'tcx>,
58
59     /// The block this frame will execute when a function call returns back to this frame.
60     next_block: mir::BasicBlock,
61
62     /// A pointer for writing the return value of the current call if it's not a diverging call.
63     return_ptr: Option<Pointer>,
64
65     /// The list of locals for the current function, stored in order as
66     /// `[arguments..., variables..., temporaries...]`. The variables begin at `self.var_offset`
67     /// and the temporaries at `self.temp_offset`.
68     locals: Vec<Pointer>,
69
70     /// The offset of the first variable in `self.locals`.
71     var_offset: usize,
72
73     /// The offset of the first temporary in `self.locals`.
74     temp_offset: usize,
75 }
76
77 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
78 struct Lvalue {
79     ptr: Pointer,
80     extra: LvalueExtra,
81 }
82
83 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
84 enum LvalueExtra {
85     None,
86     Length(u64),
87     // TODO(tsion): Vtable(memory::AllocId),
88     DowncastVariant(usize),
89 }
90
91 #[derive(Clone)]
92 enum CachedMir<'mir, 'tcx: 'mir> {
93     Ref(&'mir mir::Mir<'tcx>),
94     Owned(Rc<mir::Mir<'tcx>>)
95 }
96
97 /// Represents the action to be taken in the main loop as a result of executing a terminator.
98 enum TerminatorTarget {
99     /// Make a local jump to the given block.
100     Block(mir::BasicBlock),
101
102     /// Start executing from the new current frame. (For function calls.)
103     Call,
104
105     /// Stop executing the current frame and resume the previous frame.
106     Return,
107 }
108
109 impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
110     fn new(tcx: &'a TyCtxt<'tcx>, mir_map: &'a MirMap<'tcx>) -> Self {
111         Interpreter {
112             tcx: tcx,
113             mir_map: mir_map,
114             mir_cache: RefCell::new(DefIdMap()),
115             memory: Memory::new(),
116             stack: Vec::new(),
117             substs_stack: Vec::new(),
118             name_stack: Vec::new(),
119         }
120     }
121
122     fn maybe_report<T>(&self, span: codemap::Span, r: EvalResult<T>) -> EvalResult<T> {
123         if let Err(ref e) = r {
124             let mut err = self.tcx.sess.struct_span_err(span, &e.to_string());
125             for &(def_id, substs, span) in self.name_stack.iter().rev() {
126                 // FIXME(tsion): Find a way to do this without this Display impl hack.
127                 use rustc::util::ppaux;
128                 use std::fmt;
129                 struct Instance<'tcx>(DefId, &'tcx Substs<'tcx>);
130                 impl<'tcx> fmt::Display for Instance<'tcx> {
131                     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
132                         ppaux::parameterized(f, self.1, self.0, ppaux::Ns::Value, &[],
133                             |tcx| tcx.lookup_item_type(self.0).generics)
134                     }
135                 }
136                 err.span_note(span, &format!("inside call to {}", Instance(def_id, substs)));
137             }
138             err.emit();
139         }
140         r
141     }
142
143     fn log<F>(&self, extra_indent: usize, f: F) where F: FnOnce() {
144         let indent = self.stack.len() + extra_indent;
145         if !TRACE_EXECUTION { return; }
146         for _ in 0..indent { print!("    "); }
147         f();
148         println!("");
149     }
150
151     fn run(&mut self) -> EvalResult<()> {
152         'outer: while !self.stack.is_empty() {
153             let mut current_block = self.frame().next_block;
154
155             loop {
156                 self.log(0, || print!("// {:?}", current_block));
157                 let current_mir = self.mir().clone(); // Cloning a reference.
158                 let block_data = current_mir.basic_block_data(current_block);
159
160                 for stmt in &block_data.statements {
161                     self.log(0, || print!("{:?}", stmt));
162                     let mir::StatementKind::Assign(ref lvalue, ref rvalue) = stmt.kind;
163                     let result = self.eval_assignment(lvalue, rvalue);
164                     try!(self.maybe_report(stmt.span, result));
165                 }
166
167                 let terminator = block_data.terminator();
168                 self.log(0, || print!("{:?}", terminator.kind));
169
170                 let result = self.eval_terminator(terminator);
171                 match try!(self.maybe_report(terminator.span, result)) {
172                     TerminatorTarget::Block(block) => current_block = block,
173                     TerminatorTarget::Return => {
174                         self.pop_stack_frame();
175                         self.name_stack.pop();
176                         continue 'outer;
177                     }
178                     TerminatorTarget::Call => continue 'outer,
179                 }
180             }
181         }
182
183         Ok(())
184     }
185
186     fn push_stack_frame(&mut self, mir: CachedMir<'a, 'tcx>, substs: &'tcx Substs<'tcx>,
187         return_ptr: Option<Pointer>)
188     {
189         self.substs_stack.push(substs);
190
191         let arg_tys = mir.arg_decls.iter().map(|a| a.ty);
192         let var_tys = mir.var_decls.iter().map(|v| v.ty);
193         let temp_tys = mir.temp_decls.iter().map(|t| t.ty);
194
195         let locals: Vec<Pointer> = arg_tys.chain(var_tys).chain(temp_tys).map(|ty| {
196             let size = self.type_size(ty);
197             self.memory.allocate(size)
198         }).collect();
199
200         let num_args = mir.arg_decls.len();
201         let num_vars = mir.var_decls.len();
202
203         self.stack.push(Frame {
204             mir: mir.clone(),
205             next_block: mir::START_BLOCK,
206             return_ptr: return_ptr,
207             locals: locals,
208             var_offset: num_args,
209             temp_offset: num_args + num_vars,
210         });
211     }
212
213     fn pop_stack_frame(&mut self) {
214         let _frame = self.stack.pop().expect("tried to pop a stack frame, but there were none");
215         // TODO(tsion): Deallocate local variables.
216         self.substs_stack.pop();
217     }
218
219     fn eval_terminator(&mut self, terminator: &mir::Terminator<'tcx>)
220             -> EvalResult<TerminatorTarget> {
221         use rustc::mir::repr::TerminatorKind::*;
222         let target = match terminator.kind {
223             Return => TerminatorTarget::Return,
224
225             Goto { target } => TerminatorTarget::Block(target),
226
227             If { ref cond, targets: (then_target, else_target) } => {
228                 let cond_ptr = try!(self.eval_operand(cond));
229                 let cond_val = try!(self.memory.read_bool(cond_ptr));
230                 TerminatorTarget::Block(if cond_val { then_target } else { else_target })
231             }
232
233             SwitchInt { ref discr, ref values, ref targets, .. } => {
234                 let discr_ptr = try!(self.eval_lvalue(discr)).to_ptr();
235                 let discr_size = self
236                     .type_layout(self.lvalue_ty(discr))
237                     .size(&self.tcx.data_layout)
238                     .bytes() as usize;
239                 let discr_val = try!(self.memory.read_uint(discr_ptr, discr_size));
240
241                 // Branch to the `otherwise` case by default, if no match is found.
242                 let mut target_block = targets[targets.len() - 1];
243
244                 for (index, val_const) in values.iter().enumerate() {
245                     let ptr = try!(self.const_to_ptr(val_const));
246                     let val = try!(self.memory.read_uint(ptr, discr_size));
247                     if discr_val == val {
248                         target_block = targets[index];
249                         break;
250                     }
251                 }
252
253                 TerminatorTarget::Block(target_block)
254             }
255
256             Switch { ref discr, ref targets, adt_def } => {
257                 let adt_ptr = try!(self.eval_lvalue(discr)).to_ptr();
258                 let adt_layout = self.type_layout(self.lvalue_ty(discr));
259
260                  match *adt_layout {
261                     Layout::General { discr, .. } => {
262                         let discr_size = discr.size().bytes();
263                         let discr_val = try!(self.memory.read_uint(adt_ptr, discr_size as usize));
264
265                         let matching = adt_def.variants.iter()
266                             .position(|v| discr_val == v.disr_val.to_u64_unchecked());
267
268                         match matching {
269                             Some(i) => TerminatorTarget::Block(targets[i]),
270                             None => return Err(EvalError::InvalidDiscriminant),
271                         }
272                     }
273
274                     Layout::RawNullablePointer { nndiscr, .. } => {
275                         let is_null = match self.memory.read_usize(adt_ptr) {
276                             Ok(0) => true,
277                             Ok(_) | Err(EvalError::ReadPointerAsBytes) => false,
278                             Err(e) => return Err(e),
279                         };
280
281                         assert!(nndiscr == 0 || nndiscr == 1);
282                         let target = if is_null { 1 - nndiscr } else { nndiscr };
283                         TerminatorTarget::Block(targets[target as usize])
284                     }
285
286                     _ => panic!("attmpted to switch on non-aggregate type"),
287                 }
288             }
289
290             Call { ref func, ref args, ref destination, .. } => {
291                 let mut return_ptr = None;
292                 if let Some((ref lv, target)) = *destination {
293                     self.frame_mut().next_block = target;
294                     return_ptr = Some(try!(self.eval_lvalue(lv)).to_ptr());
295                 }
296
297                 let func_ty = self.operand_ty(func);
298                 match func_ty.sty {
299                     ty::TyFnDef(def_id, substs, fn_ty) => {
300                         use syntax::abi::Abi;
301                         match fn_ty.abi {
302                             Abi::RustIntrinsic => {
303                                 let name = self.tcx.item_name(def_id).as_str();
304                                 match fn_ty.sig.0.output {
305                                     ty::FnConverging(ty) => {
306                                         let size = self.type_size(ty);
307                                         try!(self.call_intrinsic(&name, substs, args,
308                                             return_ptr.unwrap(), size))
309                                     }
310                                     ty::FnDiverging => unimplemented!(),
311                                 }
312                             }
313
314                             Abi::C =>
315                                 try!(self.call_c_abi(def_id, args, return_ptr.unwrap())),
316
317                             Abi::Rust | Abi::RustCall => {
318                                 // TODO(tsion): Adjust the first argument when calling a Fn or
319                                 // FnMut closure via FnOnce::call_once.
320
321                                 // Only trait methods can have a Self parameter.
322                                 let (resolved_def_id, resolved_substs) = if substs.self_ty().is_some() {
323                                     self.trait_method(def_id, substs)
324                                 } else {
325                                     (def_id, substs)
326                                 };
327
328                                 let mut arg_srcs = Vec::new();
329                                 for arg in args {
330                                     let src = try!(self.eval_operand(arg));
331                                     let src_ty = self.operand_ty(arg);
332                                     arg_srcs.push((src, src_ty));
333                                 }
334
335                                 if fn_ty.abi == Abi::RustCall && !args.is_empty() {
336                                     arg_srcs.pop();
337                                     let last_arg = args.last().unwrap();
338                                     let last = try!(self.eval_operand(last_arg));
339                                     let last_ty = self.operand_ty(last_arg);
340                                     let last_layout = self.type_layout(last_ty);
341                                     match (&last_ty.sty, last_layout) {
342                                         (&ty::TyTuple(ref fields),
343                                          &Layout::Univariant { ref variant, .. }) => {
344                                             let offsets = iter::once(0)
345                                                 .chain(variant.offset_after_field.iter()
346                                                     .map(|s| s.bytes()));
347                                             for (offset, ty) in offsets.zip(fields) {
348                                                 let src = last.offset(offset as isize);
349                                                 arg_srcs.push((src, ty));
350                                             }
351                                         }
352                                         ty => panic!("expected tuple as last argument in function with 'rust-call' ABI, got {:?}", ty),
353                                     }
354                                 }
355
356                                 let mir = self.load_mir(resolved_def_id);
357                                 self.name_stack.push((def_id, substs, terminator.span));
358                                 self.push_stack_frame(mir, resolved_substs, return_ptr);
359
360                                 for (i, (src, src_ty)) in arg_srcs.into_iter().enumerate() {
361                                     let dest = self.frame().locals[i];
362                                     try!(self.move_(src, dest, src_ty));
363                                 }
364
365                                 TerminatorTarget::Call
366                             }
367
368                             abi => panic!("can't handle function with {:?} ABI", abi),
369                         }
370                     }
371
372                     _ => panic!("can't handle callee of type {:?}", func_ty),
373                 }
374             }
375
376             Drop { ref value, target, .. } => {
377                 let ptr = try!(self.eval_lvalue(value)).to_ptr();
378                 let ty = self.lvalue_ty(value);
379                 try!(self.drop(ptr, ty));
380                 TerminatorTarget::Block(target)
381             }
382
383             Resume => unimplemented!(),
384         };
385
386         Ok(target)
387     }
388
389     fn drop(&mut self, ptr: Pointer, ty: ty::Ty<'tcx>) -> EvalResult<()> {
390         if !self.type_needs_drop(ty) {
391             self.log(1, || print!("no need to drop {:?}", ty));
392             return Ok(());
393         }
394         self.log(1, || print!("need to drop {:?}", ty));
395
396         // TODO(tsion): Call user-defined Drop::drop impls.
397
398         match ty.sty {
399             ty::TyBox(contents_ty) => {
400                 match self.memory.read_ptr(ptr) {
401                     Ok(contents_ptr) => {
402                         try!(self.drop(contents_ptr, contents_ty));
403                         self.log(1, || print!("deallocating box"));
404                         try!(self.memory.deallocate(contents_ptr));
405                     }
406                     Err(EvalError::ReadBytesAsPointer) => {
407                         let size = self.memory.pointer_size;
408                         let possible_drop_fill = try!(self.memory.read_bytes(ptr, size));
409                         if possible_drop_fill.iter().all(|&b| b == mem::POST_DROP_U8) {
410                             return Ok(());
411                         } else {
412                             return Err(EvalError::ReadBytesAsPointer);
413                         }
414                     }
415                     Err(e) => return Err(e),
416                 }
417             }
418
419             // TODO(tsion): Implement drop for other relevant types (e.g. aggregates).
420             _ => {}
421         }
422
423         // Filling drop.
424         // FIXME(tsion): Trait objects (with no static size) probably get filled, too.
425         let size = self.type_size(ty);
426         try!(self.memory.drop_fill(ptr, size));
427
428         Ok(())
429     }
430
431     fn call_intrinsic(
432         &mut self,
433         name: &str,
434         substs: &'tcx Substs<'tcx>,
435         args: &[mir::Operand<'tcx>],
436         dest: Pointer,
437         dest_size: usize
438     ) -> EvalResult<TerminatorTarget> {
439         let args_res: EvalResult<Vec<Pointer>> = args.iter()
440             .map(|arg| self.eval_operand(arg))
441             .collect();
442         let args = try!(args_res);
443
444         match name {
445             "assume" => {}
446
447             "copy_nonoverlapping" => {
448                 let elem_ty = *substs.types.get(subst::FnSpace, 0);
449                 let elem_size = self.type_size(elem_ty);
450                 let src = try!(self.memory.read_ptr(args[0]));
451                 let dest = try!(self.memory.read_ptr(args[1]));
452                 let count = try!(self.memory.read_isize(args[2]));
453                 try!(self.memory.copy(src, dest, count as usize * elem_size));
454             }
455
456             "forget" => {
457                 let arg_ty = *substs.types.get(subst::FnSpace, 0);
458                 let arg_size = self.type_size(arg_ty);
459                 try!(self.memory.drop_fill(args[0], arg_size));
460             }
461
462             "init" => try!(self.memory.write_repeat(dest, 0, dest_size)),
463
464             "min_align_of" => {
465                 try!(self.memory.write_int(dest, 1, dest_size));
466             }
467
468             "move_val_init" => {
469                 let ty = *substs.types.get(subst::FnSpace, 0);
470                 let ptr = try!(self.memory.read_ptr(args[0]));
471                 try!(self.move_(args[1], ptr, ty));
472             }
473
474             // FIXME(tsion): Handle different integer types correctly.
475             "add_with_overflow" => {
476                 let ty = *substs.types.get(subst::FnSpace, 0);
477                 let size = self.type_size(ty);
478                 let left = try!(self.memory.read_int(args[0], size));
479                 let right = try!(self.memory.read_int(args[1], size));
480                 let (n, overflowed) = unsafe {
481                     ::std::intrinsics::add_with_overflow::<i64>(left, right)
482                 };
483                 try!(self.memory.write_int(dest, n, size));
484                 try!(self.memory.write_bool(dest.offset(size as isize), overflowed));
485             }
486
487             // FIXME(tsion): Handle different integer types correctly.
488             "mul_with_overflow" => {
489                 let ty = *substs.types.get(subst::FnSpace, 0);
490                 let size = self.type_size(ty);
491                 let left = try!(self.memory.read_int(args[0], size));
492                 let right = try!(self.memory.read_int(args[1], size));
493                 let (n, overflowed) = unsafe {
494                     ::std::intrinsics::mul_with_overflow::<i64>(left, right)
495                 };
496                 try!(self.memory.write_int(dest, n, size));
497                 try!(self.memory.write_bool(dest.offset(size as isize), overflowed));
498             }
499
500             "offset" => {
501                 let pointee_ty = *substs.types.get(subst::FnSpace, 0);
502                 let pointee_size = self.type_size(pointee_ty) as isize;
503                 let ptr_arg = args[0];
504                 let offset = try!(self.memory.read_isize(args[1]));
505
506                 match self.memory.read_ptr(ptr_arg) {
507                     Ok(ptr) => {
508                         let result_ptr = ptr.offset(offset as isize * pointee_size);
509                         try!(self.memory.write_ptr(dest, result_ptr));
510                     }
511                     Err(EvalError::ReadBytesAsPointer) => {
512                         let addr = try!(self.memory.read_isize(ptr_arg));
513                         let result_addr = addr + offset * pointee_size as i64;
514                         try!(self.memory.write_isize(dest, result_addr));
515                     }
516                     Err(e) => return Err(e),
517                 }
518             }
519
520             // FIXME(tsion): Handle different integer types correctly. Use primvals?
521             "overflowing_sub" => {
522                 let ty = *substs.types.get(subst::FnSpace, 0);
523                 let size = self.type_size(ty);
524                 let left = try!(self.memory.read_int(args[0], size));
525                 let right = try!(self.memory.read_int(args[1], size));
526                 let n = left.wrapping_sub(right);
527                 try!(self.memory.write_int(dest, n, size));
528             }
529
530             "size_of" => {
531                 let ty = *substs.types.get(subst::FnSpace, 0);
532                 let size = self.type_size(ty) as u64;
533                 try!(self.memory.write_uint(dest, size, dest_size));
534             }
535
536             "transmute" => {
537                 let ty = *substs.types.get(subst::FnSpace, 0);
538                 try!(self.move_(args[0], dest, ty));
539             }
540             "uninit" => try!(self.memory.mark_definedness(dest, dest_size, false)),
541
542             name => panic!("can't handle intrinsic: {}", name),
543         }
544
545         // Since we pushed no stack frame, the main loop will act
546         // as if the call just completed and it's returning to the
547         // current frame.
548         Ok(TerminatorTarget::Call)
549     }
550
551     fn call_c_abi(
552         &mut self,
553         def_id: DefId,
554         args: &[mir::Operand<'tcx>],
555         dest: Pointer
556     ) -> EvalResult<TerminatorTarget> {
557         let name = self.tcx.item_name(def_id);
558         let attrs = self.tcx.get_attrs(def_id);
559         let link_name = match attr::first_attr_value_str_by_name(&attrs, "link_name") {
560             Some(ln) => ln.clone(),
561             None => name.as_str(),
562         };
563
564         let args_res: EvalResult<Vec<Pointer>> = args.iter()
565             .map(|arg| self.eval_operand(arg))
566             .collect();
567         let args = try!(args_res);
568
569         match &link_name[..] {
570             "__rust_allocate" => {
571                 let size = try!(self.memory.read_usize(args[0]));
572                 let ptr = self.memory.allocate(size as usize);
573                 try!(self.memory.write_ptr(dest, ptr));
574             }
575
576             "__rust_reallocate" => {
577                 let ptr = try!(self.memory.read_ptr(args[0]));
578                 let size = try!(self.memory.read_usize(args[2]));
579                 try!(self.memory.reallocate(ptr, size as usize));
580                 try!(self.memory.write_ptr(dest, ptr));
581             }
582
583             _ => panic!("can't call C ABI function: {}", link_name),
584         }
585
586         // Since we pushed no stack frame, the main loop will act
587         // as if the call just completed and it's returning to the
588         // current frame.
589         Ok(TerminatorTarget::Call)
590     }
591
592     fn assign_fields<I: IntoIterator<Item = u64>>(
593         &mut self,
594         dest: Pointer,
595         offsets: I,
596         operands: &[mir::Operand<'tcx>],
597     ) -> EvalResult<()> {
598         for (offset, operand) in offsets.into_iter().zip(operands) {
599             let src = try!(self.eval_operand(operand));
600             let src_ty = self.operand_ty(operand);
601             let field_dest = dest.offset(offset as isize);
602             try!(self.move_(src, field_dest, src_ty));
603         }
604         Ok(())
605     }
606
607     fn eval_assignment(&mut self, lvalue: &mir::Lvalue<'tcx>, rvalue: &mir::Rvalue<'tcx>)
608         -> EvalResult<()>
609     {
610         let dest = try!(self.eval_lvalue(lvalue)).to_ptr();
611         let dest_ty = self.lvalue_ty(lvalue);
612         let dest_layout = self.type_layout(dest_ty);
613
614         use rustc::mir::repr::Rvalue::*;
615         match *rvalue {
616             Use(ref operand) => {
617                 let src = try!(self.eval_operand(operand));
618                 try!(self.move_(src, dest, dest_ty));
619             }
620
621             BinaryOp(bin_op, ref left, ref right) => {
622                 let left_ptr = try!(self.eval_operand(left));
623                 let left_ty = self.operand_ty(left);
624                 let left_val = try!(self.read_primval(left_ptr, left_ty));
625
626                 let right_ptr = try!(self.eval_operand(right));
627                 let right_ty = self.operand_ty(right);
628                 let right_val = try!(self.read_primval(right_ptr, right_ty));
629
630                 let val = try!(primval::binary_op(bin_op, left_val, right_val));
631                 try!(self.memory.write_primval(dest, val));
632             }
633
634             UnaryOp(un_op, ref operand) => {
635                 let ptr = try!(self.eval_operand(operand));
636                 let ty = self.operand_ty(operand);
637                 let val = try!(self.read_primval(ptr, ty));
638                 try!(self.memory.write_primval(dest, primval::unary_op(un_op, val)));
639             }
640
641             Aggregate(ref kind, ref operands) => {
642                 match *dest_layout {
643                     Layout::Univariant { ref variant, .. } => {
644                         let offsets = iter::once(0)
645                             .chain(variant.offset_after_field.iter().map(|s| s.bytes()));
646                         try!(self.assign_fields(dest, offsets, operands));
647                     }
648
649                     Layout::Array { .. } => {
650                         let elem_size = match dest_ty.sty {
651                             ty::TyArray(elem_ty, _) => self.type_size(elem_ty) as u64,
652                             _ => panic!("tried to assign {:?} to non-array type {:?}",
653                                         kind, dest_ty),
654                         };
655                         let offsets = (0..).map(|i| i * elem_size);
656                         try!(self.assign_fields(dest, offsets, operands));
657                     }
658
659                     Layout::General { discr, ref variants, .. } => {
660                         if let mir::AggregateKind::Adt(adt_def, variant, _) = *kind {
661                             let discr_val = adt_def.variants[variant].disr_val.to_u64_unchecked();
662                             let discr_size = discr.size().bytes() as usize;
663                             try!(self.memory.write_uint(dest, discr_val, discr_size));
664
665                             let offsets = variants[variant].offset_after_field.iter()
666                                 .map(|s| s.bytes());
667                             try!(self.assign_fields(dest, offsets, operands));
668                         } else {
669                             panic!("tried to assign {:?} to Layout::General", kind);
670                         }
671                     }
672
673                     Layout::RawNullablePointer { nndiscr, .. } => {
674                         if let mir::AggregateKind::Adt(_, variant, _) = *kind {
675                             if nndiscr == variant as u64 {
676                                 assert_eq!(operands.len(), 1);
677                                 let operand = &operands[0];
678                                 let src = try!(self.eval_operand(operand));
679                                 let src_ty = self.operand_ty(operand);
680                                 try!(self.move_(src, dest, src_ty));
681                             } else {
682                                 assert_eq!(operands.len(), 0);
683                                 try!(self.memory.write_isize(dest, 0));
684                             }
685                         } else {
686                             panic!("tried to assign {:?} to Layout::RawNullablePointer", kind);
687                         }
688                     }
689
690                     _ => panic!("can't handle destination layout {:?} when assigning {:?}",
691                                 dest_layout, kind),
692                 }
693             }
694
695             Repeat(ref operand, _) => {
696                 let (elem_size, length) = match dest_ty.sty {
697                     ty::TyArray(elem_ty, n) => (self.type_size(elem_ty), n),
698                     _ => panic!("tried to assign array-repeat to non-array type {:?}", dest_ty),
699                 };
700
701                 let src = try!(self.eval_operand(operand));
702                 for i in 0..length {
703                     let elem_dest = dest.offset((i * elem_size) as isize);
704                     try!(self.memory.copy(src, elem_dest, elem_size));
705                 }
706             }
707
708             Len(ref lvalue) => {
709                 let src = try!(self.eval_lvalue(lvalue));
710                 let ty = self.lvalue_ty(lvalue);
711                 let len = match ty.sty {
712                     ty::TyArray(_, n) => n as u64,
713                     ty::TySlice(_) => if let LvalueExtra::Length(n) = src.extra {
714                         n
715                     } else {
716                         panic!("Rvalue::Len of a slice given non-slice pointer: {:?}", src);
717                     },
718                     _ => panic!("Rvalue::Len expected array or slice, got {:?}", ty),
719                 };
720                 try!(self.memory.write_usize(dest, len));
721             }
722
723             Ref(_, _, ref lvalue) => {
724                 let lv = try!(self.eval_lvalue(lvalue));
725                 try!(self.memory.write_ptr(dest, lv.ptr));
726                 match lv.extra {
727                     LvalueExtra::None => {},
728                     LvalueExtra::Length(len) => {
729                         let len_ptr = dest.offset(self.memory.pointer_size as isize);
730                         try!(self.memory.write_usize(len_ptr, len));
731                     }
732                     LvalueExtra::DowncastVariant(..) =>
733                         panic!("attempted to take a reference to an enum downcast lvalue"),
734                 }
735             }
736
737             Box(ty) => {
738                 let size = self.type_size(ty);
739                 let ptr = self.memory.allocate(size);
740                 try!(self.memory.write_ptr(dest, ptr));
741             }
742
743             Cast(kind, ref operand, dest_ty) => {
744                 let src = try!(self.eval_operand(operand));
745                 let src_ty = self.operand_ty(operand);
746
747                 use rustc::mir::repr::CastKind::*;
748                 match kind {
749                     Unsize => {
750                         try!(self.move_(src, dest, src_ty));
751                         let src_pointee_ty = pointee_type(src_ty).unwrap();
752                         let dest_pointee_ty = pointee_type(dest_ty).unwrap();
753
754                         match (&src_pointee_ty.sty, &dest_pointee_ty.sty) {
755                             (&ty::TyArray(_, length), &ty::TySlice(_)) => {
756                                 let len_ptr = dest.offset(self.memory.pointer_size as isize);
757                                 try!(self.memory.write_usize(len_ptr, length as u64));
758                             }
759
760                             _ => panic!("can't handle cast: {:?}", rvalue),
761                         }
762                     }
763
764                     Misc => {
765                         // FIXME(tsion): Wrong for almost everything.
766                         let size = dest_layout.size(&self.tcx.data_layout).bytes() as usize;
767                         try!(self.memory.copy(src, dest, size));
768                     }
769
770                     _ => panic!("can't handle cast: {:?}", rvalue),
771                 }
772             }
773
774             Slice { .. } => unimplemented!(),
775             InlineAsm { .. } => unimplemented!(),
776         }
777
778         Ok(())
779     }
780
781     fn eval_operand(&mut self, op: &mir::Operand<'tcx>) -> EvalResult<Pointer> {
782         use rustc::mir::repr::Operand::*;
783         match *op {
784             Consume(ref lvalue) =>
785                 Ok(try!(self.eval_lvalue(lvalue)).to_ptr()),
786             Constant(mir::Constant { ref literal, .. }) => {
787                 use rustc::mir::repr::Literal::*;
788                 match *literal {
789                     Value { ref value } => Ok(try!(self.const_to_ptr(value))),
790                     Item { .. } => unimplemented!(),
791                 }
792             }
793         }
794     }
795
796     fn eval_lvalue(&mut self, lvalue: &mir::Lvalue<'tcx>) -> EvalResult<Lvalue> {
797         use rustc::mir::repr::Lvalue::*;
798         let ptr = match *lvalue {
799             ReturnPointer => self.frame().return_ptr
800                 .expect("ReturnPointer used in a function with no return value"),
801             Arg(i) => self.frame().locals[i as usize],
802             Var(i) => self.frame().locals[self.frame().var_offset + i as usize],
803             Temp(i) => self.frame().locals[self.frame().temp_offset + i as usize],
804
805             Static(_def_id) => unimplemented!(),
806
807             Projection(ref proj) => {
808                 let base = try!(self.eval_lvalue(&proj.base));
809                 let base_ty = self.lvalue_ty(&proj.base);
810                 let base_layout = self.type_layout(base_ty);
811
812                 use rustc::mir::repr::ProjectionElem::*;
813                 match proj.elem {
814                     Field(field, _) => {
815                         let variant = match *base_layout {
816                             Layout::Univariant { ref variant, .. } => variant,
817                             Layout::General { ref variants, .. } => {
818                                 if let LvalueExtra::DowncastVariant(variant_idx) = base.extra {
819                                     &variants[variant_idx]
820                                 } else {
821                                     panic!("field access on enum had no variant index");
822                                 }
823                             }
824                             Layout::RawNullablePointer { .. } => {
825                                 assert_eq!(field.index(), 0);
826                                 return Ok(base);
827                             }
828                             _ => panic!("field access on non-product type: {:?}", base_layout),
829                         };
830
831                         let offset = variant.field_offset(field.index()).bytes();
832                         base.ptr.offset(offset as isize)
833                     },
834
835                     Downcast(_, variant) => match *base_layout {
836                         Layout::General { discr, .. } => {
837                             return Ok(Lvalue {
838                                 ptr: base.ptr.offset(discr.size().bytes() as isize),
839                                 extra: LvalueExtra::DowncastVariant(variant),
840                             });
841                         }
842                         Layout::RawNullablePointer { .. } => return Ok(base),
843                         _ => panic!("variant downcast on non-aggregate type: {:?}", base_layout),
844                     },
845
846                     Deref => {
847                         let pointee_ty = pointee_type(base_ty).expect("Deref of non-pointer");
848                         let ptr = try!(self.memory.read_ptr(base.ptr));
849                         let extra = match pointee_ty.sty {
850                             ty::TySlice(_) | ty::TyStr => {
851                                 let len_ptr = base.ptr.offset(self.memory.pointer_size as isize);
852                                 let len = try!(self.memory.read_usize(len_ptr));
853                                 LvalueExtra::Length(len)
854                             }
855                             ty::TyTrait(_) => unimplemented!(),
856                             _ => LvalueExtra::None,
857                         };
858                         return Ok(Lvalue { ptr: ptr, extra: extra });
859                     }
860
861                     Index(ref operand) => {
862                         let elem_size = match base_ty.sty {
863                             ty::TyArray(elem_ty, _) => self.type_size(elem_ty),
864                             ty::TySlice(elem_ty) => self.type_size(elem_ty),
865                             _ => panic!("indexing expected an array or slice, got {:?}", base_ty),
866                         };
867                         let n_ptr = try!(self.eval_operand(operand));
868                         let n = try!(self.memory.read_usize(n_ptr));
869                         base.ptr.offset(n as isize * elem_size as isize)
870                     }
871
872                     ConstantIndex { .. } => unimplemented!(),
873                 }
874             }
875         };
876
877         Ok(Lvalue { ptr: ptr, extra: LvalueExtra::None })
878     }
879
880     // TODO(tsion): Try making const_to_primval instead.
881     fn const_to_ptr(&mut self, const_val: &const_val::ConstVal) -> EvalResult<Pointer> {
882         use rustc::middle::const_val::ConstVal::*;
883         match *const_val {
884             Float(_f) => unimplemented!(),
885             Integral(int) => {
886                 // TODO(tsion): Check int constant type.
887                 let ptr = self.memory.allocate(8);
888                 try!(self.memory.write_uint(ptr, int.to_u64_unchecked(), 8));
889                 Ok(ptr)
890             }
891             Str(ref s) => {
892                 let psize = self.memory.pointer_size;
893                 let static_ptr = self.memory.allocate(s.len());
894                 let ptr = self.memory.allocate(psize * 2);
895                 try!(self.memory.write_bytes(static_ptr, s.as_bytes()));
896                 try!(self.memory.write_ptr(ptr, static_ptr));
897                 try!(self.memory.write_usize(ptr.offset(psize as isize), s.len() as u64));
898                 Ok(ptr)
899             }
900             ByteStr(ref bs) => {
901                 let psize = self.memory.pointer_size;
902                 let static_ptr = self.memory.allocate(bs.len());
903                 let ptr = self.memory.allocate(psize);
904                 try!(self.memory.write_bytes(static_ptr, bs));
905                 try!(self.memory.write_ptr(ptr, static_ptr));
906                 Ok(ptr)
907             }
908             Bool(b) => {
909                 let ptr = self.memory.allocate(1);
910                 try!(self.memory.write_bool(ptr, b));
911                 Ok(ptr)
912             }
913             Char(_c)          => unimplemented!(),
914             Struct(_node_id)  => unimplemented!(),
915             Tuple(_node_id)   => unimplemented!(),
916             Function(_def_id) => unimplemented!(),
917             Array(_, _)       => unimplemented!(),
918             Repeat(_, _)      => unimplemented!(),
919             Dummy             => unimplemented!(),
920         }
921     }
922
923     fn lvalue_ty(&self, lvalue: &mir::Lvalue<'tcx>) -> ty::Ty<'tcx> {
924         self.monomorphize(self.mir().lvalue_ty(self.tcx, lvalue).to_ty(self.tcx))
925     }
926
927     fn operand_ty(&self, operand: &mir::Operand<'tcx>) -> ty::Ty<'tcx> {
928         self.monomorphize(self.mir().operand_ty(self.tcx, operand))
929     }
930
931     fn monomorphize(&self, ty: ty::Ty<'tcx>) -> ty::Ty<'tcx> {
932         let substituted = ty.subst(self.tcx, self.substs());
933         infer::normalize_associated_type(self.tcx, &substituted)
934     }
935
936     fn type_needs_drop(&self, ty: ty::Ty<'tcx>) -> bool {
937         self.tcx.type_needs_drop_given_env(ty, &self.tcx.empty_parameter_environment())
938     }
939
940     fn move_(&mut self, src: Pointer, dest: Pointer, ty: ty::Ty<'tcx>) -> EvalResult<()> {
941         let size = self.type_size(ty);
942         try!(self.memory.copy(src, dest, size));
943         if self.type_needs_drop(ty) {
944             try!(self.memory.drop_fill(src, size));
945         }
946         Ok(())
947     }
948
949     fn type_is_sized(&self, ty: ty::Ty<'tcx>) -> bool {
950         ty.is_sized(&self.tcx.empty_parameter_environment(), DUMMY_SP)
951     }
952
953     fn type_size(&self, ty: ty::Ty<'tcx>) -> usize {
954         self.type_layout(ty).size(&self.tcx.data_layout).bytes() as usize
955     }
956
957     fn type_layout(&self, ty: ty::Ty<'tcx>) -> &'tcx Layout {
958         // TODO(tsion): Is this inefficient? Needs investigation.
959         let ty = self.monomorphize(ty);
960
961         let infcx = infer::normalizing_infer_ctxt(self.tcx, &self.tcx.tables, ProjectionMode::Any);
962
963         // TODO(tsion): Report this error properly.
964         ty.layout(&infcx).unwrap()
965     }
966
967     pub fn read_primval(&mut self, ptr: Pointer, ty: ty::Ty<'tcx>) -> EvalResult<PrimVal> {
968         use syntax::ast::{IntTy, UintTy};
969         let val = match ty.sty {
970             ty::TyBool              => PrimVal::Bool(try!(self.memory.read_bool(ptr))),
971             ty::TyInt(IntTy::I8)    => PrimVal::I8(try!(self.memory.read_int(ptr, 1)) as i8),
972             ty::TyInt(IntTy::I16)   => PrimVal::I16(try!(self.memory.read_int(ptr, 2)) as i16),
973             ty::TyInt(IntTy::I32)   => PrimVal::I32(try!(self.memory.read_int(ptr, 4)) as i32),
974             ty::TyInt(IntTy::I64)   => PrimVal::I64(try!(self.memory.read_int(ptr, 8)) as i64),
975             ty::TyUint(UintTy::U8)  => PrimVal::U8(try!(self.memory.read_uint(ptr, 1)) as u8),
976             ty::TyUint(UintTy::U16) => PrimVal::U16(try!(self.memory.read_uint(ptr, 2)) as u16),
977             ty::TyUint(UintTy::U32) => PrimVal::U32(try!(self.memory.read_uint(ptr, 4)) as u32),
978             ty::TyUint(UintTy::U64) => PrimVal::U64(try!(self.memory.read_uint(ptr, 8)) as u64),
979
980             // TODO(tsion): Pick the PrimVal dynamically.
981             ty::TyInt(IntTy::Is)   => PrimVal::I64(try!(self.memory.read_isize(ptr))),
982             ty::TyUint(UintTy::Us) => PrimVal::U64(try!(self.memory.read_usize(ptr))),
983
984             ty::TyRef(_, ty::TypeAndMut { ty, .. }) |
985             ty::TyRawPtr(ty::TypeAndMut { ty, .. }) => {
986                 if self.type_is_sized(ty) {
987                     match self.memory.read_ptr(ptr) {
988                         Ok(p) => PrimVal::AbstractPtr(p),
989                         Err(EvalError::ReadBytesAsPointer) => {
990                             let n = try!(self.memory.read_usize(ptr));
991                             PrimVal::IntegerPtr(n)
992                         }
993                         Err(e) => return Err(e),
994                     }
995                 } else {
996                     panic!("unimplemented: primitive read of fat pointer type: {:?}", ty);
997                 }
998             }
999
1000             _ => panic!("primitive read of non-primitive type: {:?}", ty),
1001         };
1002         Ok(val)
1003     }
1004
1005     fn frame(&self) -> &Frame<'a, 'tcx> {
1006         self.stack.last().expect("no call frames exist")
1007     }
1008
1009     fn frame_mut(&mut self) -> &mut Frame<'a, 'tcx> {
1010         self.stack.last_mut().expect("no call frames exist")
1011     }
1012
1013     fn mir(&self) -> &mir::Mir<'tcx> {
1014         &self.frame().mir
1015     }
1016
1017     fn substs(&self) -> &'tcx Substs<'tcx> {
1018         self.substs_stack.last().cloned().unwrap_or_else(|| self.tcx.mk_substs(Substs::empty()))
1019     }
1020
1021     fn load_mir(&self, def_id: DefId) -> CachedMir<'a, 'tcx> {
1022         match self.tcx.map.as_local_node_id(def_id) {
1023             Some(node_id) => CachedMir::Ref(self.mir_map.map.get(&node_id).unwrap()),
1024             None => {
1025                 let mut mir_cache = self.mir_cache.borrow_mut();
1026                 if let Some(mir) = mir_cache.get(&def_id) {
1027                     return CachedMir::Owned(mir.clone());
1028                 }
1029
1030                 use rustc::middle::cstore::CrateStore;
1031                 let cs = &self.tcx.sess.cstore;
1032                 let mir = cs.maybe_get_item_mir(self.tcx, def_id).unwrap_or_else(|| {
1033                     panic!("no mir for {:?}", def_id);
1034                 });
1035                 let cached = Rc::new(mir);
1036                 mir_cache.insert(def_id, cached.clone());
1037                 CachedMir::Owned(cached)
1038             }
1039         }
1040     }
1041
1042     fn fulfill_obligation(&self, trait_ref: ty::PolyTraitRef<'tcx>) -> traits::Vtable<'tcx, ()> {
1043         // Do the initial selection for the obligation. This yields the shallow result we are
1044         // looking for -- that is, what specific impl.
1045         let infcx = infer::normalizing_infer_ctxt(self.tcx, &self.tcx.tables, ProjectionMode::Any);
1046         let mut selcx = traits::SelectionContext::new(&infcx);
1047
1048         let obligation = traits::Obligation::new(
1049             traits::ObligationCause::misc(DUMMY_SP, ast::DUMMY_NODE_ID),
1050             trait_ref.to_poly_trait_predicate(),
1051         );
1052         let selection = selcx.select(&obligation).unwrap().unwrap();
1053
1054         // Currently, we use a fulfillment context to completely resolve all nested obligations.
1055         // This is because they can inform the inference of the impl's type parameters.
1056         let mut fulfill_cx = traits::FulfillmentContext::new();
1057         let vtable = selection.map(|predicate| {
1058             fulfill_cx.register_predicate_obligation(&infcx, predicate);
1059         });
1060         let vtable = infer::drain_fulfillment_cx_or_panic(
1061             DUMMY_SP, &infcx, &mut fulfill_cx, &vtable
1062         );
1063
1064         vtable
1065     }
1066
1067     /// Trait method, which has to be resolved to an impl method.
1068     pub fn trait_method(&self, def_id: DefId, substs: &'tcx Substs<'tcx>)
1069         -> (DefId, &'tcx Substs<'tcx>)
1070     {
1071         let method_item = self.tcx.impl_or_trait_item(def_id);
1072         let trait_id = method_item.container().id();
1073         let trait_ref = ty::Binder(substs.to_trait_ref(self.tcx, trait_id));
1074         match self.fulfill_obligation(trait_ref) {
1075             traits::VtableImpl(vtable_impl) => {
1076                 let impl_did = vtable_impl.impl_def_id;
1077                 let mname = self.tcx.item_name(def_id);
1078                 // Create a concatenated set of substitutions which includes those from the impl
1079                 // and those from the method:
1080                 let impl_substs = vtable_impl.substs.with_method_from(substs);
1081                 let substs = self.tcx.mk_substs(impl_substs);
1082                 let mth = get_impl_method(self.tcx, impl_did, substs, mname);
1083
1084                 (mth.method.def_id, mth.substs)
1085             }
1086
1087             traits::VtableClosure(vtable_closure) =>
1088                 (vtable_closure.closure_def_id, vtable_closure.substs.func_substs),
1089
1090             traits::VtableFnPointer(_fn_ty) => {
1091                 let _trait_closure_kind = self.tcx.lang_items.fn_trait_kind(trait_id).unwrap();
1092                 unimplemented!()
1093                 // let llfn = trans_fn_pointer_shim(ccx, trait_closure_kind, fn_ty);
1094
1095                 // let method_ty = def_ty(tcx, def_id, substs);
1096                 // let fn_ptr_ty = match method_ty.sty {
1097                 //     ty::TyFnDef(_, _, fty) => tcx.mk_ty(ty::TyFnPtr(fty)),
1098                 //     _ => unreachable!("expected fn item type, found {}",
1099                 //                       method_ty)
1100                 // };
1101                 // Callee::ptr(immediate_rvalue(llfn, fn_ptr_ty))
1102             }
1103
1104             traits::VtableObject(ref _data) => {
1105                 unimplemented!()
1106                 // Callee {
1107                 //     data: Virtual(traits::get_vtable_index_of_object_method(
1108                 //                   tcx, data, def_id)),
1109                 //                   ty: def_ty(tcx, def_id, substs)
1110                 // }
1111             }
1112             vtable => unreachable!("resolved vtable bad vtable {:?} in trans", vtable),
1113         }
1114     }
1115 }
1116
1117 fn pointee_type<'tcx>(ptr_ty: ty::Ty<'tcx>) -> Option<ty::Ty<'tcx>> {
1118     match ptr_ty.sty {
1119         ty::TyRef(_, ty::TypeAndMut { ty, .. }) |
1120         ty::TyRawPtr(ty::TypeAndMut { ty, .. }) |
1121         ty::TyBox(ty) => {
1122             Some(ty)
1123         }
1124         _ => None,
1125     }
1126 }
1127
1128 impl Lvalue {
1129     fn to_ptr(self) -> Pointer {
1130         assert_eq!(self.extra, LvalueExtra::None);
1131         self.ptr
1132     }
1133 }
1134
1135 impl<'mir, 'tcx: 'mir> Deref for CachedMir<'mir, 'tcx> {
1136     type Target = mir::Mir<'tcx>;
1137     fn deref(&self) -> &mir::Mir<'tcx> {
1138         match *self {
1139             CachedMir::Ref(r) => r,
1140             CachedMir::Owned(ref rc) => &rc,
1141         }
1142     }
1143 }
1144
1145 #[derive(Debug)]
1146 pub struct ImplMethod<'tcx> {
1147     pub method: Rc<ty::Method<'tcx>>,
1148     pub substs: &'tcx Substs<'tcx>,
1149     pub is_provided: bool,
1150 }
1151
1152 /// Locates the applicable definition of a method, given its name.
1153 pub fn get_impl_method<'tcx>(
1154     tcx: &TyCtxt<'tcx>,
1155     impl_def_id: DefId,
1156     substs: &'tcx Substs<'tcx>,
1157     name: ast::Name,
1158 ) -> ImplMethod<'tcx> {
1159     assert!(!substs.types.needs_infer());
1160
1161     let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap();
1162     let trait_def = tcx.lookup_trait_def(trait_def_id);
1163     let infcx = infer::normalizing_infer_ctxt(tcx, &tcx.tables, ProjectionMode::Any);
1164
1165     match trait_def.ancestors(impl_def_id).fn_defs(tcx, name).next() {
1166         Some(node_item) => {
1167             ImplMethod {
1168                 method: node_item.item,
1169                 substs: traits::translate_substs(&infcx, impl_def_id, substs, node_item.node),
1170                 is_provided: node_item.node.is_from_trait(),
1171             }
1172         }
1173         None => {
1174             bug!("method {:?} not found in {:?}", name, impl_def_id);
1175         }
1176     }
1177 }
1178
1179 pub fn interpret_start_points<'tcx>(tcx: &TyCtxt<'tcx>, mir_map: &MirMap<'tcx>) {
1180     for (&id, mir) in &mir_map.map {
1181         for attr in tcx.map.attrs(id) {
1182             use syntax::attr::AttrMetaMethods;
1183             if attr.check_name("miri_run") {
1184                 let item = tcx.map.expect_item(id);
1185
1186                 println!("Interpreting: {}", item.name);
1187
1188                 let mut miri = Interpreter::new(tcx, mir_map);
1189                 let return_ptr = match mir.return_ty {
1190                     ty::FnConverging(ty) => {
1191                         let size = miri.type_size(ty);
1192                         Some(miri.memory.allocate(size))
1193                     }
1194                     ty::FnDiverging => None,
1195                 };
1196                 let substs = miri.tcx.mk_substs(Substs::empty());
1197                 miri.push_stack_frame(CachedMir::Ref(mir), substs, return_ptr);
1198                 if let Err(_e) = miri.run() {
1199                     // TODO(tsion): Detect whether the error was already reported or not.
1200                     // tcx.sess.err(&e.to_string());
1201                 } else if let Some(ret) = return_ptr {
1202                     miri.memory.dump(ret.alloc_id);
1203                 }
1204                 println!("");
1205             }
1206         }
1207     }
1208 }
1209
1210 // TODO(tsion): Upstream these methods into rustc::ty::layout.
1211
1212 trait IntegerExt {
1213     fn size(self) -> Size;
1214 }
1215
1216 impl IntegerExt for layout::Integer {
1217     fn size(self) -> Size {
1218         use rustc::ty::layout::Integer::*;
1219         match self {
1220             I1 | I8 => Size::from_bits(8),
1221             I16 => Size::from_bits(16),
1222             I32 => Size::from_bits(32),
1223             I64 => Size::from_bits(64),
1224         }
1225     }
1226 }
1227
1228 trait StructExt {
1229     fn field_offset(&self, index: usize) -> Size;
1230 }
1231
1232 impl StructExt for layout::Struct {
1233     fn field_offset(&self, index: usize) -> Size {
1234         if index == 0 {
1235             Size::from_bytes(0)
1236         } else {
1237             self.offset_after_field[index - 1]
1238         }
1239     }
1240 }