Skip to content

Commit

Permalink
Cast eval result to return type
Browse files Browse the repository at this point in the history
  • Loading branch information
k0aki committed Sep 17, 2023
1 parent 810c12e commit 0f058c6
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 38 deletions.
2 changes: 1 addition & 1 deletion crates/interpreter/src/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use cranelift_entity::SecondaryMap;

use sonatina_ir::{module::ModuleCtx, DataFlowGraph, Type, Value, I256};

use crate::{types, value::EvalValue, ProgramCounter};
use crate::{types, EvalValue, ProgramCounter};

pub struct Frame {
pub ret_addr: ProgramCounter,
Expand Down
1 change: 1 addition & 0 deletions crates/interpreter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ pub mod value;
pub use frame::Frame;
pub use pc::ProgramCounter;
pub use state::State;
pub use value::{EvalResult, EvalValue};
66 changes: 34 additions & 32 deletions crates/interpreter/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ use std::{
use sonatina_ir::{
insn::{BinaryOp, CastOp, UnaryOp},
module::FuncRef,
Block, DataLocationKind, Immediate, InsnData, Module, I256,
Block, DataLocationKind, Immediate, InsnData, Module,
};

use crate::{types, Frame, ProgramCounter};
use crate::{types, EvalResult, Frame, ProgramCounter};

pub struct State {
module: Module,
Expand All @@ -34,15 +34,15 @@ impl State {
}
}

pub fn run(mut self) -> Option<I256> {
pub fn run(mut self) -> EvalResult {
loop {
if let Some(arg) = self.step() {
return arg;
}
}
}

pub fn step(&mut self) -> Option<Option<I256>> {
pub fn step(&mut self) -> Option<EvalResult> {
let frame = self.frames.last_mut().unwrap();
let insn = self.pc.insn;
let ctx = &self.module.ctx;
Expand Down Expand Up @@ -205,25 +205,32 @@ impl State {
None
}
Return { args } => {
let arg = args.map(|arg| frame.load(ctx, arg, dfg));
let mut frame = self.frames.pop().unwrap(); // pop returning frame

let frame = self.frames.pop().unwrap(); // pop returning frame
match self.frames.last_mut() {
Some(caller_frame) => {
// Function epilogue

self.pc.resume_frame_at(frame.ret_addr);

let caller = &self.module.funcs[self.pc.func_ref];
if let Some(lit) = arg {
if let Some(arg) = *args {
let arg_literal = frame.load(ctx, arg, dfg);
let v = caller.dfg.insn_result(self.pc.insn).unwrap();
caller_frame.map(lit, v);
caller_frame.map(arg_literal, v);
}

self.pc.next_insn(&caller.layout);
None
}
None => Some(arg),
None => {
let Some(arg) = *args else {
return Some(EvalResult::Void);
};
let arg_literal = frame.load(ctx, arg, dfg);
let ty = dfg.value_ty(arg);
Some(EvalResult::from_i256(ctx, arg_literal, ty))
}
}
}
Gep { args } => {
Expand Down Expand Up @@ -259,7 +266,6 @@ impl State {

#[cfg(test)]
mod test {
use sonatina_ir::I256;
use sonatina_parser::parser::Parser;

use super::*;
Expand Down Expand Up @@ -288,7 +294,7 @@ mod test {

let result = state.run();

assert_eq!(result.unwrap(), I256::all_one().neg());
assert_eq!(result.into_i32(), 1i32);
}

#[test]
Expand All @@ -309,7 +315,7 @@ mod test {

let result = state.run();

assert_eq!(result.unwrap(), (-3).into());
assert_eq!(result.into_i16(), -3i16);
}

#[test]
Expand All @@ -327,9 +333,7 @@ mod test {

let result = state.run();

const NEG_128: i16 = i16::from_be_bytes([0xff, 0x80]);

assert_eq!(result.unwrap(), NEG_128.into());
assert_eq!(result.into_i16(), -128i16);
}

#[test]
Expand All @@ -347,9 +351,7 @@ mod test {

let elem_ptr = state.run();

let result = i16::from_be_bytes([0x0, 0x80]);

assert_eq!(elem_ptr.unwrap(), result.into());
assert_eq!(elem_ptr.into_i16(), 128i16);
}

#[test]
Expand All @@ -369,7 +371,7 @@ mod test {

let data = state.run();

assert_eq!(data.unwrap(), 1.into());
assert_eq!(data.into_i32(), 1i32);
}

#[test]
Expand All @@ -396,7 +398,7 @@ mod test {

let data = state.run();

assert_eq!(data.unwrap(), 0.into());
assert_eq!(data.into_i8(), 0i8);
}

#[test]
Expand All @@ -415,9 +417,9 @@ mod test {

let state = parse_module_make_state(input);

let boolean = state.run().unwrap();
let boolean = state.run();

assert_eq!(boolean, I256::zero())
assert!(!boolean.into_bool())
}

#[test]
Expand All @@ -436,9 +438,9 @@ mod test {

let state = parse_module_make_state(input);

let result = state.run().unwrap();
let result = state.run();

assert_eq!(result, 1.into());
assert_eq!(result.into_i8(), 1i8);
}

#[test]
Expand All @@ -459,9 +461,9 @@ mod test {

let state = parse_module_make_state(input);

let result = state.run().unwrap();
let result = state.run();

assert_eq!(result, 2.into());
assert_eq!(result.into_i64(), 2i64);
}

#[test]
Expand All @@ -481,9 +483,9 @@ mod test {

let state = parse_module_make_state(input);

let result = state.run().unwrap();
let result = state.run();

assert_eq!(result, (-1).into());
assert_eq!(result.into_i8(), -1i8);
}

#[test]
Expand All @@ -504,7 +506,7 @@ mod test {

let elem_ptr = state.run();

assert_eq!(elem_ptr.unwrap(), 12.into());
assert_eq!(elem_ptr.into_usize(), 12usize);
}

#[test]
Expand All @@ -523,7 +525,7 @@ mod test {

let arg = state.run();

assert!(arg.is_none());
arg.into_void();
}

#[cfg(target_arch = "aarch64")]
Expand All @@ -543,7 +545,7 @@ mod test {

let elem_ptr = state.run();

assert_eq!(elem_ptr.unwrap(), 16.into());
assert_eq!(elem_ptr.into_usize(), 16usize);
}

#[test]
Expand All @@ -564,6 +566,6 @@ mod test {

let elem_ptr = state.run();

assert_eq!(elem_ptr.unwrap(), 11.into());
assert_eq!(elem_ptr.into_usize(), 11usize);
}
}
102 changes: 98 additions & 4 deletions crates/interpreter/src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ impl EvalValue {
}

pub fn i256(&self) -> I256 {
match self {
Self::Literal(i256) => *i256,
_ => panic!(),
}
let Self::Literal(i256) = *self else {
panic!("undefined");
};
i256
}

pub fn deserialize(ctx: &ModuleCtx, ty: Type, b: Vec<u8>) -> Option<Self> {
Expand Down Expand Up @@ -64,3 +64,97 @@ impl EvalValue {
}
}
}

pub enum EvalResult {
I1(bool),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
I128(i128),
I256(I256),
Void,
Addr(usize),
}

impl EvalResult {
pub fn from_i256(ctx: &ModuleCtx, i256: I256, ty: Type) -> Self {
use EvalResult::*;
match ty {
Type::I1 => I1(i256.trunc_to_i1()),
Type::I8 => I8(i256.trunc_to_i8()),
Type::I16 => I16(i256.trunc_to_i16()),
Type::I32 => I32(i256.trunc_to_i32()),
Type::I64 => I64(i256.trunc_to_i64()),
Type::I128 => I128(i256.trunc_to_i128()),
Type::I256 => I256(i256),
Type::Compound(_) => {
debug_assert!(ctx.with_ty_store(|s| s.is_ptr(ty)));
Addr(i256.to_u256().as_usize())
}
_ => unreachable!(),
}
}

pub fn into_bool(self) -> bool {
let Self::I1(boolean) = self else {
panic!("not a boolean")
};
boolean
}

pub fn into_i8(self) -> i8 {
let Self::I8(i8) = self else {
panic!("not an i8")
};
i8
}

pub fn into_i16(self) -> i16 {
let Self::I16(i16) = self else {
panic!("not an i16")
};
i16
}

pub fn into_i32(self) -> i32 {
let Self::I32(i32) = self else {
panic!("not an i32")
};
i32
}

pub fn into_i64(self) -> i64 {
let Self::I64(i64) = self else {
panic!("not an i64")
};
i64
}

pub fn into_i128(self) -> i128 {
let Self::I128(i128) = self else {
panic!("not an i128")
};
i128
}

pub fn into_i256(self) -> I256 {
let Self::I256(i256) = self else {
panic!("not an i256")
};
i256
}

pub fn into_void(self) {
let Self::Void = self else {
panic!("not a void")
};
}

pub fn into_usize(self) -> usize {
let Self::Addr(usize) = self else {
panic!("not a memory address")
};
usize
}
}
1 change: 0 additions & 1 deletion crates/ir/src/bigint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ impl I256 {
}

pub fn trunc_to_i8(self) -> i8 {
println!("{:?}", self.to_u256().low_u32() as i8);
self.to_u256().low_u32() as i8
}

Expand Down

0 comments on commit 0f058c6

Please sign in to comment.