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