Skip to content

Commit

Permalink
Add test for gep instruction
Browse files Browse the repository at this point in the history
  • Loading branch information
k0aki committed Sep 8, 2023
1 parent 974590b commit 2f19d71
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 24 deletions.
32 changes: 17 additions & 15 deletions crates/interpreter/src/frame.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ impl Frame {
let addr = self.alloca_region.len();

let size_of_data = byte_size_of_ty(ctx, ty);

for _ in 0..size_of_data {
self.alloca_region.push(0u8);
}
Expand All @@ -76,17 +77,18 @@ impl Frame {
debug_assert!(ctx.with_ty_store(|s| s.is_ptr(ptr_ty)));

let pointee_ty = ctx.with_ty_store(|s| s.deref(ptr_ty)).unwrap();
debug_assert!(!pointee_ty.is_integral() && !ctx.with_ty_store(|s| s.is_ptr(ptr_ty)));

debug_assert!(!pointee_ty.is_integral() && !ctx.with_ty_store(|s| s.is_ptr(pointee_ty)));
let mut cmpd_ty = to_cmpd_ty(pointee_ty);

let mut offset = 0usize;

for arg in &args[1..] {
let index = self.load(*arg, dfg).as_usize();

ctx.with_ty_store(|s| match s.resolve_compound(cmpd_ty.unwrap()) {
let cmpd_ty_data = ctx.with_ty_store(|s| s.resolve_compound(cmpd_ty.unwrap()).clone());
match cmpd_ty_data {
CompoundTypeData::Array { elem, .. } => {
offset += index * byte_size_of_ty(ctx, *elem);
cmpd_ty = to_cmpd_ty(*elem);
offset += index * byte_size_of_ty(ctx, elem);
cmpd_ty = to_cmpd_ty(elem);
}
CompoundTypeData::Struct(data) => {
for ty in &data.fields[..index] {
Expand All @@ -95,7 +97,7 @@ impl Frame {
cmpd_ty = to_cmpd_ty(data.fields[index]);
}
_ => unreachable!(),
})
}
}
Literal::from_usize(base_addr + offset)
}
Expand Down Expand Up @@ -153,16 +155,16 @@ pub fn byte_size_of_ty(ctx: &ModuleCtx, ty: Type) -> usize {
Type::I64 => mem::size_of::<i64>(),
Type::I128 => mem::size_of::<i128>(),
Type::I256 => mem::size_of::<I256>(),
Type::Compound(ty) => {
Type::Compound(cmpd_ty) => {
use CompoundTypeData::*;
ctx.with_ty_store(|s| match s.resolve_compound(ty) {
Array { len, elem } => len * byte_size_of_ty(ctx, *elem),
let cmpd_ty_data = ctx.with_ty_store(|s| s.resolve_compound(cmpd_ty).clone());
match cmpd_ty_data {
Array { len, elem } => len * byte_size_of_ty(ctx, elem),
Ptr(_) => mem::size_of::<usize>(),
Struct(data) => data
.fields
.iter()
.fold(0usize, |acc, ty| acc + byte_size_of_ty(ctx, *ty)),
})
Struct(data) => data.fields.iter().fold(0usize, |acc, field_ty| {
acc + byte_size_of_ty(ctx, *field_ty)
}),
}
}
Type::Void => mem::size_of::<()>(),
}
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 @@ -5,4 +5,5 @@ pub mod value;

pub use frame::Frame;
pub use pc::ProgramCounter;
pub use state::State;
pub use value::Literal;
4 changes: 2 additions & 2 deletions crates/interpreter/src/pc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use sonatina_ir::{module::FuncRef, Block, Insn, Layout};

#[derive(Clone, Copy)]
#[derive(Clone, Copy, Debug)]
pub struct ProgramCounter {
pub func_ref: FuncRef,
pub insn: Insn,
Expand All @@ -18,7 +18,7 @@ impl ProgramCounter {
}

pub fn call(&mut self, callee_ref: FuncRef, callee_layout: &Layout) {
*self = ProgramCounter::new(callee_ref, &callee_layout)
*self = ProgramCounter::new(callee_ref, callee_layout)
}

pub fn next_insn(&mut self, layout: &Layout) {
Expand Down
84 changes: 78 additions & 6 deletions crates/interpreter/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use sonatina_ir::{

use crate::{Frame, Literal, ProgramCounter};

struct State {
pub struct State {
module: Module,
frames: Vec<Frame>,
pc: ProgramCounter,
Expand Down Expand Up @@ -144,7 +144,7 @@ impl State {
let mut literal_args = Vec::with_capacity(args.len());
for arg in args {
let arg = frame.load(*arg, dfg);
literal_args.push(arg.clone())
literal_args.push(arg)
}

// Function prologue
Expand Down Expand Up @@ -201,7 +201,7 @@ impl State {
None
}
Return { args } => {
let arg = args.map(|arg| frame.load(arg, dfg).clone());
let arg = args.map(|arg| frame.load(arg, dfg));

let frame = self.frames.pop().unwrap(); // pop returning frame
match self.frames.last_mut() {
Expand All @@ -218,11 +218,11 @@ impl State {
self.pc.next_insn(&caller.layout);
None
}
None => return Some(arg),
None => Some(arg),
}
}
Gep { args } => {
let ptr = frame.gep(ctx, &args, dfg);
let ptr = frame.gep(ctx, args, dfg);

frame.map(ptr, insn, dfg);

Expand All @@ -234,7 +234,7 @@ impl State {
let prev_block = self.prev_block.unwrap();
for (v, block) in values.iter().zip(blocks.iter()) {
if prev_block == *block {
let lit = frame.load(*v, dfg).clone();
let lit = frame.load(*v, dfg);
frame.map(lit, insn, dfg);
break;
}
Expand All @@ -244,3 +244,75 @@ impl State {
}
}
}

#[cfg(test)]
mod test {
use sonatina_ir::{builder::test_util::TestModuleBuilder, Type};

use super::*;

#[test]
fn gep() {
let mut test_module_builder = TestModuleBuilder::new();
let mut builder = test_module_builder.func_builder(&[], Type::I256);

let b = builder.append_block();
builder.switch_to_block(b);

let name = "";
let fields = [Type::I32, Type::I64, Type::I1]; // offset to fields[2] is 4 + 8
let ty = builder.declare_struct_type(name, &fields, false);

let p = builder.alloca(ty);

let idx = builder.make_imm_value(2);

let addr = builder.gep(&[p, idx]);
builder.ret(addr);

builder.seal_all();
let func_ref = builder.finish();
let module = test_module_builder.build();

let state = State::new(module, func_ref);

let elem_ptr = state.repl();

assert_eq!(elem_ptr.unwrap().as_usize(), 12);
}

#[test]
fn gep_nested_aggr_ty() {
let mut test_module_builder = TestModuleBuilder::new();
let mut builder = test_module_builder.func_builder(&[], Type::I256);

let b = builder.append_block();
builder.switch_to_block(b);

let arr_ty0 = builder.declare_array_type(Type::I16, 3);
let arr_ty1 = builder.declare_array_type(Type::I8, 2);

// offset to fields[2][1] is 4 + 2 * 3 + 1
let fields = [Type::I32, arr_ty0, arr_ty1];
let name = "";
let struct_ty = builder.declare_struct_type(name, &fields, false);

let p = builder.alloca(struct_ty);

let idx0 = builder.make_imm_value(2);
let idx1 = builder.make_imm_value(1);

let addr = builder.gep(&[p, idx0, idx1]);
builder.ret(addr);

builder.seal_all();
let func_ref = builder.finish();
let module = test_module_builder.build();

let state = State::new(module, func_ref);

let elem_ptr = state.repl();

assert_eq!(elem_ptr.unwrap().as_usize(), 11);
}
}
2 changes: 1 addition & 1 deletion crates/interpreter/src/value.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use sonatina_ir::{module::ModuleCtx, Type, I256, U256};

#[derive(Clone, Copy, PartialEq, Eq)]
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Literal(pub I256);

impl Default for Literal {
Expand Down
9 changes: 9 additions & 0 deletions crates/ir/src/builder/func_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ impl<'a> FunctionBuilder<'a> {
self.func_mut().dfg.make_global_value(gv)
}

pub fn declare_array_type(&mut self, elem: Type, len: usize) -> Type {
self.module_builder.declare_array_type(elem, len)
}

pub fn declare_struct_type(&mut self, name: &str, fields: &[Type], packed: bool) -> Type {
self.module_builder
.declare_struct_type(name, fields, packed)
Expand Down Expand Up @@ -244,6 +248,11 @@ impl<'a> FunctionBuilder<'a> {
self.insert_insn(insn_data);
}

pub fn gep(&mut self, args: &[Value]) -> Option<Value> {
let insn_data = InsnData::Gep { args: args.into() };
self.insert_insn(insn_data)
}

pub fn phi(&mut self, args: &[(Value, Block)]) -> Value {
let ty = self.func().dfg.value_ty(args[0].0);
let insn_data = InsnData::Phi {
Expand Down
4 changes: 4 additions & 0 deletions crates/ir/src/builder/module_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ impl ModuleBuilder {
.with_ty_store_mut(|s| s.make_struct(name, fields, packed))
}

pub fn declare_array_type(&mut self, elem: Type, len: usize) -> Type {
self.ctx.with_ty_store_mut(|s| s.make_array(elem, len))
}

pub fn get_func_ref(&self, name: &str) -> Option<FuncRef> {
self.declared_funcs.get(name).copied()
}
Expand Down

0 comments on commit 2f19d71

Please sign in to comment.