Skip to content

Commit

Permalink
Impl Interpret for InsertValue/ExtractValue
Browse files Browse the repository at this point in the history
  • Loading branch information
Y-Nak committed Nov 19, 2024
1 parent ad7df8a commit f7720a4
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 8 deletions.
24 changes: 24 additions & 0 deletions crates/interpreter/test_files/insert_value.sntn
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
target = "evm-ethereum-london"

type @s1 = {i32, i64, i1};

#[(3.i32, 2.i64, 1.i1) -> 6.i64]
func private %insert_value_basic(v0.i32, v1.i64, v2.i1) -> i64 {
block0:
v3.@s1 = insert_value undef.@s1 0.i256 v0;
v4.@s1 = insert_value v3 1.i256 v1;
v5.@s1 = insert_value v4 2.i256 v2;

v6.i32 = extract_value v5 0.i256;
v7.i64 = extract_value v5 1.i256;
v8.i1 = extract_value v5 2.i256;

v9.i64 = sext v6 i64;
v10.i64 = zext v8 i64;

v11.i64 = add v7 v9;
v12.i64 = add v11 v10;

return v12;
}

1 change: 1 addition & 0 deletions crates/interpreter/tests/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ fn parse_func_cases(module: &ParsedModule, func_ref: FuncRef) -> Result<Vec<Test
.collect()
}

// TODO: Allow Compound value.
fn parse_value(module: &ParsedModule, func_ref: FuncRef, input: &str) -> Result<Immediate, String> {
let value = match Parser::parse(Rule::value, input) {
Ok(mut pairs) => {
Expand Down
4 changes: 4 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 @@ where
self.func.dfg.make_imm_value(imm)
}

pub fn make_undef_value(&mut self, ty: Type) -> ValueId {
self.func.dfg.make_undef_value(ty)
}

/// Return pointer value to the global variable.
pub fn make_global_value(&mut self, gv: GlobalVariable) -> ValueId {
self.func.dfg.make_global_value(gv)
Expand Down
2 changes: 1 addition & 1 deletion crates/ir/src/dfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ impl DataFlowGraph {
value
}

pub fn make_undef(&mut self, ty: Type) -> ValueId {
pub fn make_undef_value(&mut self, ty: Type) -> ValueId {
let value_data = Value::Undef { ty };
self.make_value(value_data)
}
Expand Down
53 changes: 53 additions & 0 deletions crates/ir/src/interpret/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,59 @@ impl Interpret for Alloca {
}
}

impl Interpret for InsertValue {
fn interpret(&self, state: &mut dyn State) -> EvalValue {
state.set_action(Action::Continue);

let dest = state.lookup_val(*self.dest());
let ty = state.dfg().value_ty(*self.dest());

let mut fields = match dest {
EvalValue::Aggregate { fields, .. } => fields.clone(),

EvalValue::Undef => {
let len = match ty.resolve_compound(&state.dfg().ctx).unwrap() {
CompoundTypeData::Array { len, .. } => len,
CompoundTypeData::Struct(s) => s.fields.len(),
CompoundTypeData::Ptr(_) => unreachable!(),
};
vec![EvalValue::Undef; len]
}

EvalValue::Imm(_) => {
unreachable!()
}
};

let idx = state.lookup_val(*self.idx()).as_imm().unwrap().as_usize();
fields[idx] = state.lookup_val(*self.value());

EvalValue::Aggregate { fields, ty }
}
}

impl Interpret for ExtractValue {
fn interpret(&self, state: &mut dyn State) -> EvalValue {
state.set_action(Action::Continue);

let dest = state.lookup_val(*self.dest());
let dest = match dest {
EvalValue::Aggregate { fields, .. } => fields,

EvalValue::Undef => {
return EvalValue::Undef;
}

EvalValue::Imm(_) => {
unreachable!()
}
};

let idx = state.lookup_val(*self.idx()).as_imm().unwrap().as_usize();
dest.into_iter().nth(idx).unwrap()
}
}

fn align_to(offset: usize, alignment: usize) -> usize {
assert!(alignment & (alignment - 1) == 0);
(offset + alignment - 1) & !(alignment - 1)
Expand Down
22 changes: 21 additions & 1 deletion crates/ir/src/interpret/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ pub trait Interpret {
inst::data::Mstore,
inst::data::Gep,
inst::data::Alloca,
inst::data::InsertValue,
inst::data::ExtractValue,
inst::control_flow::Jump,
inst::control_flow::Br,
inst::control_flow::BrTable,
Expand Down Expand Up @@ -119,9 +121,13 @@ pub enum Action {
Return(EvalValue),
}

#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub enum EvalValue {
Imm(Immediate),
Aggregate {
fields: Vec<EvalValue>,
ty: Type,
},
#[default]
Undef,
}
Expand All @@ -134,6 +140,7 @@ impl EvalValue {
{
match self {
EvalValue::Imm(value) => f(value).into(),
EvalValue::Aggregate { .. } => panic!("Type checker needs to handle this!"),
EvalValue::Undef => EvalValue::Undef,
}
}
Expand All @@ -145,6 +152,8 @@ impl EvalValue {
{
match (lhs, rhs) {
(EvalValue::Imm(l), EvalValue::Imm(r)) => f(l, r).into(),
(EvalValue::Aggregate { .. }, _) => panic!("Type checker needs to handle this!"),
(_, EvalValue::Aggregate { .. }) => panic!("Type checker needs to handle this!"),
_ => EvalValue::Undef,
}
}
Expand All @@ -165,6 +174,17 @@ impl fmt::Display for EvalValue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Imm(imm) => write!(f, "{imm}"),
Self::Aggregate { fields, .. } => {
write!(f, "{{ ")?;
let mut fields = fields.iter();
if let Some(field) = fields.next() {
write!(f, "{field} ")?;
}
for field in fields {
write!(f, ",{field} ")?;
}
write!(f, " }}")
}
Self::Undef => write!(f, "undef"),
}
}
Expand Down
20 changes: 14 additions & 6 deletions crates/ir/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,14 @@ impl Type {
pub fn is_pointer(self, ctx: &ModuleCtx) -> bool {
ctx.with_ty_store(|store| store.is_ptr(self))
}

pub fn resolve_compound(self, ctx: &ModuleCtx) -> Option<CompoundTypeData> {
let Self::Compound(cmpd) = self else {
return None;
};

Some(ctx.with_ty_store(|s| s.resolve_compound(cmpd).clone()))
}
}

impl cmp::PartialOrd for Type {
Expand Down Expand Up @@ -183,7 +191,7 @@ impl cmp::PartialOrd for Type {
}

impl WriteWithModule for Type {
fn write(&self, module: &ModuleCtx, w: &mut impl io::Write) -> io::Result<()> {
fn write(&self, ctx: &ModuleCtx, w: &mut impl io::Write) -> io::Result<()> {
match self {
Type::I1 => write!(w, "i1"),
Type::I8 => write!(w, "i8"),
Expand All @@ -192,7 +200,7 @@ impl WriteWithModule for Type {
Type::I64 => write!(w, "i64"),
Type::I128 => write!(w, "i128"),
Type::I256 => write!(w, "i256"),
Type::Compound(cmpd_ty) => cmpd_ty.write(module, w),
Type::Compound(cmpd_ty) => cmpd_ty.write(ctx, w),
Type::Unit => write!(w, "unit"),
}
}
Expand All @@ -204,16 +212,16 @@ pub struct CompoundType(u32);
cranelift_entity::entity_impl!(CompoundType);

impl WriteWithModule for CompoundType {
fn write(&self, module: &ModuleCtx, w: &mut impl io::Write) -> io::Result<()> {
module.with_ty_store(|s| match s.resolve_compound(*self) {
fn write(&self, ctx: &ModuleCtx, w: &mut impl io::Write) -> io::Result<()> {
ctx.with_ty_store(|s| match s.resolve_compound(*self) {
CompoundTypeData::Array { elem: ty, len } => {
write!(w, "[")?;
ty.write(module, &mut *w)?;
ty.write(ctx, &mut *w)?;
write!(w, "; {len}]")
}
CompoundTypeData::Ptr(ty) => {
write!(w, "*")?;
ty.write(module, w)
ty.write(ctx, w)
}
CompoundTypeData::Struct(StructData { name, packed, .. }) => {
if *packed {
Expand Down

0 comments on commit f7720a4

Please sign in to comment.