Support structs and single-variant enums.
This commit is contained in:
parent
fd10ec9278
commit
8a0b95bc8b
3 changed files with 61 additions and 47 deletions
|
@ -5,7 +5,7 @@ use rustc::mir::repr as mir;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use memory::{Memory, Pointer, Repr};
|
use memory::{FieldRepr, Memory, Pointer, Repr};
|
||||||
|
|
||||||
const TRACE_EXECUTION: bool = true;
|
const TRACE_EXECUTION: bool = true;
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
|
||||||
let mut locals = Vec::with_capacity(num_args + num_vars + num_temps);
|
let mut locals = Vec::with_capacity(num_args + num_vars + num_temps);
|
||||||
|
|
||||||
for (arg_decl, arg_operand) in mir.arg_decls.iter().zip(args) {
|
for (arg_decl, arg_operand) in mir.arg_decls.iter().zip(args) {
|
||||||
let repr = Repr::from_ty(arg_decl.ty);
|
let repr = self.ty_to_repr(arg_decl.ty);
|
||||||
let dest = self.memory.allocate(repr.size());
|
let dest = self.memory.allocate(repr.size());
|
||||||
let src = try!(self.operand_to_ptr(arg_operand));
|
let src = try!(self.operand_to_ptr(arg_operand));
|
||||||
try!(self.memory.copy(src, dest, repr.size()));
|
try!(self.memory.copy(src, dest, repr.size()));
|
||||||
|
@ -117,7 +117,8 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
|
||||||
let var_tys = mir.var_decls.iter().map(|v| v.ty);
|
let var_tys = mir.var_decls.iter().map(|v| v.ty);
|
||||||
let temp_tys = mir.temp_decls.iter().map(|t| t.ty);
|
let temp_tys = mir.temp_decls.iter().map(|t| t.ty);
|
||||||
locals.extend(var_tys.chain(temp_tys).map(|ty| {
|
locals.extend(var_tys.chain(temp_tys).map(|ty| {
|
||||||
self.memory.allocate(Repr::from_ty(ty).size())
|
let repr = self.ty_to_repr(ty).size();
|
||||||
|
self.memory.allocate(repr)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
self.stack.push(Frame {
|
self.stack.push(Frame {
|
||||||
|
@ -273,7 +274,7 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
|
||||||
{
|
{
|
||||||
let dest = try!(self.lvalue_to_ptr(lvalue));
|
let dest = try!(self.lvalue_to_ptr(lvalue));
|
||||||
let dest_ty = self.current_frame().mir.lvalue_ty(self.tcx, lvalue).to_ty(self.tcx);
|
let dest_ty = self.current_frame().mir.lvalue_ty(self.tcx, lvalue).to_ty(self.tcx);
|
||||||
let dest_repr = Repr::from_ty(dest_ty);
|
let dest_repr = self.ty_to_repr(dest_ty);
|
||||||
|
|
||||||
use rustc::mir::repr::Rvalue::*;
|
use rustc::mir::repr::Rvalue::*;
|
||||||
match *rvalue {
|
match *rvalue {
|
||||||
|
@ -297,7 +298,21 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
|
||||||
self.memory.write_int(dest, n)
|
self.memory.write_int(dest, n)
|
||||||
}
|
}
|
||||||
|
|
||||||
Aggregate(mir::AggregateKind::Tuple, ref operands) => {
|
Aggregate(ref _kind, ref operands) => {
|
||||||
|
// TODO(tsion): Handle different `kind` variants.
|
||||||
|
|
||||||
|
// let max_fields = adt_def.variants
|
||||||
|
// .iter()
|
||||||
|
// .map(|v| v.fields.len())
|
||||||
|
// .max()
|
||||||
|
// .unwrap_or(0);
|
||||||
|
// let ptr = self.allocate_aggregate(max_fields);
|
||||||
|
// for (i, operand) in operands.iter().enumerate() {
|
||||||
|
// let val = self.operand_to_ptr(operand);
|
||||||
|
// self.write_pointer(ptr.offset(i), val);
|
||||||
|
// }
|
||||||
|
// Value::Adt { variant: variant, data_ptr: ptr }
|
||||||
|
|
||||||
match dest_repr {
|
match dest_repr {
|
||||||
Repr::Aggregate { ref fields, .. } => {
|
Repr::Aggregate { ref fields, .. } => {
|
||||||
for (field, operand) in fields.iter().zip(operands) {
|
for (field, operand) in fields.iter().zip(operands) {
|
||||||
|
@ -316,24 +331,6 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
|
||||||
// Value::Pointer(self.lvalue_to_ptr(lvalue))
|
// Value::Pointer(self.lvalue_to_ptr(lvalue))
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// Aggregate(mir::AggregateKind::Adt(ref adt_def, variant, _substs),
|
|
||||||
// ref operands) => {
|
|
||||||
// let max_fields = adt_def.variants
|
|
||||||
// .iter()
|
|
||||||
// .map(|v| v.fields.len())
|
|
||||||
// .max()
|
|
||||||
// .unwrap_or(0);
|
|
||||||
|
|
||||||
// let ptr = self.allocate_aggregate(max_fields);
|
|
||||||
|
|
||||||
// for (i, operand) in operands.iter().enumerate() {
|
|
||||||
// let val = self.operand_to_ptr(operand);
|
|
||||||
// self.write_pointer(ptr.offset(i), val);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Value::Adt { variant: variant, data_ptr: ptr }
|
|
||||||
// }
|
|
||||||
|
|
||||||
ref r => panic!("can't handle rvalue: {:?}", r),
|
ref r => panic!("can't handle rvalue: {:?}", r),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -433,6 +430,36 @@ impl<'a, 'tcx: 'a> Interpreter<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn make_aggregate_repr<I>(&self, iter: I) -> Repr where I: IntoIterator<Item = ty::Ty<'tcx>> {
|
||||||
|
let mut size = 0;
|
||||||
|
let fields = iter.into_iter().map(|ty| {
|
||||||
|
let repr = self.ty_to_repr(ty);
|
||||||
|
let old_size = size;
|
||||||
|
size += repr.size();
|
||||||
|
FieldRepr { offset: old_size, repr: repr }
|
||||||
|
}).collect();
|
||||||
|
Repr::Aggregate { size: size, fields: fields }
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(tsion): Cache these outputs.
|
||||||
|
fn ty_to_repr(&self, ty: ty::Ty<'tcx>) -> Repr {
|
||||||
|
match ty.sty {
|
||||||
|
ty::TyBool => Repr::Bool,
|
||||||
|
ty::TyInt(_) => Repr::Int,
|
||||||
|
ty::TyTuple(ref fields) => self.make_aggregate_repr(fields.iter().cloned()),
|
||||||
|
|
||||||
|
ty::TyEnum(adt_def, ref subst) | ty::TyStruct(adt_def, ref subst) => {
|
||||||
|
// TODO(tsion): Support multi-variant enums.
|
||||||
|
assert!(adt_def.variants.len() == 1);
|
||||||
|
let field_tys = adt_def.variants[0].fields.iter().map(|f| f.ty(self.tcx, subst));
|
||||||
|
self.make_aggregate_repr(field_tys)
|
||||||
|
}
|
||||||
|
|
||||||
|
ref t => panic!("can't convert type to repr: {:?}", t),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fn current_frame(&self) -> &Frame<'a, 'tcx> {
|
fn current_frame(&self) -> &Frame<'a, 'tcx> {
|
||||||
self.stack.last().expect("no call frames exist")
|
self.stack.last().expect("no call frames exist")
|
||||||
}
|
}
|
||||||
|
@ -449,7 +476,10 @@ pub fn interpret_start_points<'tcx>(tcx: &TyCtxt<'tcx>, mir_map: &MirMap<'tcx>)
|
||||||
|
|
||||||
let mut miri = Interpreter::new(tcx, mir_map);
|
let mut miri = Interpreter::new(tcx, mir_map);
|
||||||
let return_ptr = match mir.return_ty {
|
let return_ptr = match mir.return_ty {
|
||||||
ty::FnConverging(ty) => Some(miri.memory.allocate(Repr::from_ty(ty).size())),
|
ty::FnConverging(ty) => {
|
||||||
|
let repr = miri.ty_to_repr(ty).size();
|
||||||
|
Some(miri.memory.allocate(repr))
|
||||||
|
}
|
||||||
ty::FnDiverging => None,
|
ty::FnDiverging => None,
|
||||||
};
|
};
|
||||||
miri.call(mir, &[], return_ptr).unwrap();
|
miri.call(mir, &[], return_ptr).unwrap();
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use byteorder::{self, ByteOrder};
|
use byteorder::{self, ByteOrder};
|
||||||
use rustc::middle::ty;
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
@ -141,28 +140,6 @@ impl Pointer {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Repr {
|
impl Repr {
|
||||||
// TODO(tsion): Cache these outputs.
|
|
||||||
pub fn from_ty(ty: ty::Ty) -> Self {
|
|
||||||
match ty.sty {
|
|
||||||
ty::TyBool => Repr::Bool,
|
|
||||||
|
|
||||||
ty::TyInt(_) => Repr::Int,
|
|
||||||
|
|
||||||
ty::TyTuple(ref fields) => {
|
|
||||||
let mut size = 0;
|
|
||||||
let fields = fields.iter().map(|ty| {
|
|
||||||
let repr = Repr::from_ty(ty);
|
|
||||||
let old_size = size;
|
|
||||||
size += repr.size();
|
|
||||||
FieldRepr { offset: old_size, repr: repr }
|
|
||||||
}).collect();
|
|
||||||
Repr::Aggregate { size: size, fields: fields }
|
|
||||||
},
|
|
||||||
|
|
||||||
ref t => panic!("can't convert type to repr: {:?}", t),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn size(&self) -> usize {
|
pub fn size(&self) -> usize {
|
||||||
match *self {
|
match *self {
|
||||||
Repr::Bool => 1,
|
Repr::Bool => 1,
|
||||||
|
|
|
@ -61,6 +61,13 @@ fn if_true() -> i32 {
|
||||||
if true { 1 } else { 0 }
|
if true { 1 } else { 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Pair { x: i64, y: i64 }
|
||||||
|
|
||||||
|
#[miri_run]
|
||||||
|
fn pair() -> Pair {
|
||||||
|
Pair { x: 10, y: 20 }
|
||||||
|
}
|
||||||
|
|
||||||
// #[miri_run(expected = "Int(2)")]
|
// #[miri_run(expected = "Int(2)")]
|
||||||
// fn call() -> i32 {
|
// fn call() -> i32 {
|
||||||
// fn increment(x: i32) -> i32 {
|
// fn increment(x: i32) -> i32 {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue