Skip to content

Commit

Permalink
fix(ir): named type problem (maybe fixed)
Browse files Browse the repository at this point in the history
  • Loading branch information
JuniMay committed Feb 22, 2024
1 parent a824d95 commit 2537c30
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 73 deletions.
77 changes: 57 additions & 20 deletions src/ir/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{error::Error, fmt};
use super::{
entities::{BlockData, FunctionData, FunctionKind, ValueData, ValueKind},
module::{DataFlowGraph, Module},
types::Type,
types::{Type, TypeKind},
values::{
Alloc, Binary, BinaryOp, Block, Branch, Call, Function, GetElemPtr, GlobalSlot, Jump, Load,
Return, Store, Unary, UnaryOp, Value,
Expand All @@ -22,11 +22,14 @@ pub enum BuilderErr {
/// The block is not found in the data flow graph.
BlockNotFound,

/// Type not found.
TypeNotFound,

/// Invalid value type.
///
/// This can be used when the value type is not valid for the operation/construction,
/// e.g. a function type provided for zero/bytes/...
InvalidType,
InvalidType(Type),

InvalidKind,

Expand All @@ -48,7 +51,7 @@ pub enum BuilderErr {
IncompatibleArraySize,

/// Incompatible array element type.
IncompatibleArrayElemType,
IncompatibleArrayElemType(Type, Type),

/// Incompatible struct field number.
IncompatibleStructFieldNumber,
Expand All @@ -72,14 +75,19 @@ impl fmt::Display for BuilderErr {
match self {
ValueNotFound => write!(f, "value not found"),
BlockNotFound => write!(f, "block not found"),
InvalidType => write!(f, "invalid value type"),
TypeNotFound => write!(f, "type not found"),
InvalidType(ty) => write!(f, "invalid value type {}", ty),
InvalidKind => write!(f, "invalid value kind"),
InvalidMutability => write!(f, "invalid mutability"),
InvalidGlobalValue => write!(f, "invalid global value"),
InvalidLocalValue => write!(f, "invalid local value"),
IncompatibleType => write!(f, "incompatible value type"),
IncompatibleArraySize => write!(f, "incompatible array size"),
IncompatibleArrayElemType => write!(f, "incompatible array element type"),
IncompatibleArrayElemType(elem_type, value_type) => write!(
f,
"incompatible array element type: {} and {}",
elem_type, value_type
),
IncompatibleStructFieldNumber => {
write!(f, "incompatible struct field number")
}
Expand Down Expand Up @@ -120,11 +128,15 @@ pub trait AddBlock {
fn add_block(&mut self, data: BlockData) -> Result<Block, BuilderErr>;
}

pub trait ConstantBuilder: QueryValueData + AddValue {
pub trait QueryCustomType {
fn custom_type(&self, name: String) -> Result<Type, BuilderErr>;
}

pub trait ConstantBuilder: QueryValueData + AddValue + QueryCustomType {
/// Build a zero constant.
fn zero(&mut self, ty: Type) -> Result<Value, BuilderErr> {
if !ty.is_zero_initializable() {
return Err(BuilderErr::InvalidType);
return Err(BuilderErr::InvalidType(ty.clone()));
}
self.add_value(ValueData::new(ty, ValueKind::Zero))
}
Expand All @@ -137,7 +149,7 @@ pub trait ConstantBuilder: QueryValueData + AddValue {
/// Build a bytes constant.
fn bytes(&mut self, ty: Type, bytes: Vec<u8>) -> Result<Value, BuilderErr> {
if !ty.is_numeric() && !ty.is_ptr() {
return Err(BuilderErr::InvalidType);
return Err(BuilderErr::InvalidType(ty.clone()));
}
self.add_value(ValueData::new(ty, ValueKind::Bytes(bytes)))
}
Expand Down Expand Up @@ -169,15 +181,18 @@ pub trait ConstantBuilder: QueryValueData + AddValue {

/// Build an array constant.
fn array(&mut self, ty: Type, values: Vec<Value>) -> Result<Value, BuilderErr> {
let (size, elem_type) = ty.as_array().ok_or(BuilderErr::InvalidType)?;
let (size, elem_type) = ty.as_array().ok_or(BuilderErr::InvalidType(ty.clone()))?;

if values.len() != size {
return Err(BuilderErr::IncompatibleArraySize);
}

for value in &values {
if self.value_type(*value)? != elem_type.clone() {
return Err(BuilderErr::IncompatibleArrayElemType);
return Err(BuilderErr::IncompatibleArrayElemType(
elem_type.clone(),
self.value_type(*value)?,
));
}
if !self.is_value_const(*value)? {
return Err(BuilderErr::InvalidMutability);
Expand All @@ -189,7 +204,15 @@ pub trait ConstantBuilder: QueryValueData + AddValue {

/// Build a struct constant.
fn struct_(&mut self, ty: Type, values: Vec<Value>) -> Result<Value, BuilderErr> {
let fields = ty.as_struct().ok_or(BuilderErr::InvalidType)?;
let actual_ty = match ty.kind() {
TypeKind::Struct(_) => ty.clone(),
TypeKind::Type(name) => self.custom_type(name.clone())?,
_ => return Err(BuilderErr::InvalidType(ty.clone())),
};

let fields = actual_ty
.as_struct()
.ok_or(BuilderErr::InvalidType(ty.clone()))?;

if fields.len() != values.len() {
return Err(BuilderErr::IncompatibleStructFieldNumber);
Expand Down Expand Up @@ -222,15 +245,15 @@ pub trait LocalValueBuilder: QueryDfgData + AddValue + ConstantBuilder {
/// Build a load instruction.
fn load(&mut self, ty: Type, ptr: Value) -> Result<Value, BuilderErr> {
if !self.value_type(ptr)?.is_ptr() {
return Err(BuilderErr::InvalidType);
return Err(BuilderErr::InvalidType(ty.clone()));
}
self.add_value(Load::new_value_data(ty, ptr))
}

/// Build a store instruction.
fn store(&mut self, val: Value, ptr: Value) -> Result<Value, BuilderErr> {
if !self.value_type(ptr)?.is_ptr() {
return Err(BuilderErr::InvalidType);
return Err(BuilderErr::InvalidType(self.value_type(ptr)?));
}

self.add_value(Store::new_value_data(val, ptr))
Expand All @@ -242,11 +265,11 @@ pub trait LocalValueBuilder: QueryDfgData + AddValue + ConstantBuilder {
let rhs_type = self.value_type(rhs)?;

if op.require_int() && (!lhs_type.is_int() || !rhs_type.is_int()) {
return Err(BuilderErr::InvalidType);
return Err(BuilderErr::InvalidType(lhs_type.clone()));
}

if op.require_float() && (!lhs_type.is_float() || !rhs_type.is_float()) {
return Err(BuilderErr::InvalidType);
return Err(BuilderErr::InvalidType(lhs_type.clone()));
}

if op.require_same_type() && lhs_type != rhs_type {
Expand All @@ -266,11 +289,11 @@ pub trait LocalValueBuilder: QueryDfgData + AddValue + ConstantBuilder {
let val_type = self.value_type(val)?;

if op.require_int() && !val_type.is_int() {
return Err(BuilderErr::InvalidType);
return Err(BuilderErr::InvalidType(val_type.clone()));
}

if op.require_float() && !val_type.is_float() {
return Err(BuilderErr::InvalidType);
return Err(BuilderErr::InvalidType(val_type.clone()));
}

self.add_value(Unary::new_value_data(val_type, op, val))
Expand Down Expand Up @@ -306,7 +329,7 @@ pub trait LocalValueBuilder: QueryDfgData + AddValue + ConstantBuilder {
else_args: Vec<Value>,
) -> Result<Value, BuilderErr> {
if !self.value_type(cond)?.is_int() {
return Err(BuilderErr::InvalidType);
return Err(BuilderErr::InvalidType(self.value_type(cond)?));
}

let then_block_data = self.block_data(then_dst)?;
Expand Down Expand Up @@ -354,7 +377,7 @@ pub trait LocalValueBuilder: QueryDfgData + AddValue + ConstantBuilder {
let callee_type = self.value_type(callee)?;

if !callee_type.is_function() && !callee_type.is_ptr() {
return Err(BuilderErr::InvalidType);
return Err(BuilderErr::InvalidType(callee_type));
}

self.add_value(Call::new_value_data(ret_ty, callee, args))
Expand All @@ -368,7 +391,7 @@ pub trait LocalValueBuilder: QueryDfgData + AddValue + ConstantBuilder {
indices: Vec<Value>,
) -> Result<Value, BuilderErr> {
if !self.value_type(ptr)?.is_ptr() {
return Err(BuilderErr::InvalidType);
return Err(BuilderErr::InvalidType(self.value_type(ptr)?));
}

self.add_value(GetElemPtr::new_value_data(ptr, ty, indices))
Expand Down Expand Up @@ -497,6 +520,12 @@ impl ConstantBuilder for LocalBuilder<'_> {}

impl LocalValueBuilder for LocalBuilder<'_> {}

impl QueryCustomType for LocalBuilder<'_> {
fn custom_type(&self, name: String) -> Result<Type, BuilderErr> {
self.dfg.custom_type(&name).ok_or(BuilderErr::TypeNotFound)
}
}

impl LocalBlockBuilder for LocalBuilder<'_> {}

pub struct GlobalBuilder<'a> {
Expand Down Expand Up @@ -535,6 +564,14 @@ impl AddValue for GlobalBuilder<'_> {
}
}

impl QueryCustomType for GlobalBuilder<'_> {
fn custom_type(&self, name: String) -> Result<Type, BuilderErr> {
self.module
.custom_type(&name)
.ok_or(BuilderErr::TypeNotFound)
}
}

impl ConstantBuilder for GlobalBuilder<'_> {}

impl GlobalValueBuilder for GlobalBuilder<'_> {
Expand Down
58 changes: 29 additions & 29 deletions src/ir/frontend/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::ir::{
BuilderErr, ConstantBuilder, GlobalValueBuilder, LocalBlockBuilder, LocalValueBuilder,
},
module::Module,
types::Type,
types::{Type, TypeKind},
values::{Block, Function, Value},
};

Expand Down Expand Up @@ -161,41 +161,35 @@ impl Ast {
InstKind::Binary(op) => {
let lhs = self.operand_to_value(&ast_inst.operands[0], ctx, function)?;
let rhs = self.operand_to_value(&ast_inst.operands[1], ctx, function)?;

dfg_mut!(ctx.module, function).builder().binary(
op.clone(),
lhs,
rhs,
)?

dfg_mut!(ctx.module, function)
.builder()
.binary(op.clone(), lhs, rhs)?
}
InstKind::Unary(op) => {
let operand =
self.operand_to_value(&ast_inst.operands[0], ctx, function)?;

dfg_mut!(ctx.module, function)
.builder()
.unary(op.clone(), operand)?
}
InstKind::Store => {
let val = self.operand_to_value(&ast_inst.operands[0], ctx, function)?;
let ptr = self.operand_to_value(&ast_inst.operands[1], ctx, function)?;

dfg_mut!(ctx.module, function).builder().store(val, ptr)?
}
InstKind::Load => {
let ptr = self.operand_to_value(&ast_inst.operands[0], ctx, function)?;


dfg_mut!(ctx.module, function)
.builder()
.load(ast_inst.ty.clone().unwrap(), ptr)?
}
InstKind::Alloc => {

dfg_mut!(ctx.module, function)
.builder()
.alloc(ast_inst.ty.clone().unwrap())?
}
InstKind::Alloc => dfg_mut!(ctx.module, function)
.builder()
.alloc(ast_inst.ty.clone().unwrap())?,
InstKind::Jump => {
let (name, args) = match ast_inst.operands[0].as_ref() {
AstNode::Callee(callee) => {
Expand All @@ -210,7 +204,7 @@ impl Ast {
};

let block = ctx.get_block(&name)?;

dfg_mut!(ctx.module, function).builder().jump(block, args)?
}
InstKind::Branch => {
Expand Down Expand Up @@ -239,7 +233,7 @@ impl Ast {
};
let then_block = ctx.get_block(&then_name)?;
let else_block = ctx.get_block(&else_name)?;

dfg_mut!(ctx.module, function)
.builder()
.branch(cond, then_block, else_block, then_args, else_args)?
Expand All @@ -252,7 +246,7 @@ impl Ast {
self.operand_to_value(&ast_inst.operands[0], ctx, function)?;
Some(value)
};

dfg_mut!(ctx.module, function).builder().return_(value)?
}
InstKind::Call => {
Expand All @@ -268,7 +262,7 @@ impl Ast {
_ => unreachable!(),
};
let callee = ctx.get_value(&name)?;

dfg_mut!(ctx.module, function).builder().call(
ast_inst.ty.clone().unwrap(),
callee,
Expand All @@ -282,7 +276,7 @@ impl Ast {
let value = self.operand_to_value(index, ctx, function)?;
indices.push(value);
}

dfg_mut!(ctx.module, function).builder().getelemptr(
ptr,
ast_inst.ty.clone().unwrap(),
Expand Down Expand Up @@ -329,29 +323,35 @@ impl Ast {
) -> Result<Value, BuilderErr> {
let value = match init.as_ref() {
AstNode::Array(array) => {
let (_size, elem_type) = ty.as_array().ok_or(BuilderErr::InvalidType)?;
let (_size, elem_type) =
ty.as_array().ok_or(BuilderErr::InvalidType(ty.clone()))?;
let mut values = Vec::new();
for (_i, elem) in array.elems.iter().enumerate() {
let value = self.global_init_to_value(elem_type.clone(), elem, module)?;
values.push(value);
}

module.builder().array(ty, values)?
}
AstNode::Struct(struct_) => {
let struct_ty = ty.as_struct().ok_or(BuilderErr::InvalidType)?;
let struct_ty = match ty.kind() {
TypeKind::Struct(_) => ty.clone(),
TypeKind::Type(name) => {
module.custom_type(name).ok_or(BuilderErr::TypeNotFound)?
}
_ => return Err(BuilderErr::InvalidType(ty.clone())),
};
let struct_ty = struct_ty
.as_struct()
.ok_or(BuilderErr::InvalidType(struct_ty.clone()))?;
let mut values = Vec::new();
for (i, field) in struct_.fields.iter().enumerate() {
let value = self.global_init_to_value(struct_ty[i].clone(), field, module)?;
values.push(value);
}

module.builder().struct_(ty, values)?
}
AstNode::Bytes(bytes) => {

module.builder().bytes(ty, bytes.clone())?
}
AstNode::Bytes(bytes) => module.builder().bytes(ty, bytes.clone())?,
_ => unreachable!(),
};
Ok(value)
Expand Down
9 changes: 9 additions & 0 deletions src/ir/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,15 @@ impl DataFlowGraph {
pub fn block_data(&self, block: Block) -> Option<&BlockData> {
self.blocks.get(&block)
}

pub fn custom_type(&self, name: &str) -> Option<Type> {
self.custom_types
.upgrade()
.expect("custom type map should be alive.")
.borrow()
.get(name)
.cloned()
}
}

pub type GlobalValueMap = HashMap<Value, ValueData>;
Expand Down
2 changes: 1 addition & 1 deletion src/ir/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ impl fmt::Display for TypeKind {
)
}
TypeKind::Label => write!(f, "label"),
TypeKind::Type(name) => write!(f, "${}", name),
TypeKind::Type(name) => write!(f, "{}", name),
}
}
}
Expand Down
Loading

0 comments on commit 2537c30

Please sign in to comment.