mirror of
https://github.com/edg-l/edlang.git
synced 2024-11-23 00:18:24 +00:00
ok
This commit is contained in:
parent
19c52009ab
commit
bfad93ac5a
|
@ -41,6 +41,20 @@ pub struct PathExpr {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PathExpr {
|
||||||
|
pub fn get_full_path(&self) -> String {
|
||||||
|
let mut result = self.first.name.clone();
|
||||||
|
for path in &self.extra {
|
||||||
|
result.push('.');
|
||||||
|
match path {
|
||||||
|
PathSegment::Field(name) => result.push_str(&name.name),
|
||||||
|
PathSegment::Index { .. } => result.push_str("[]"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub enum PathSegment {
|
pub enum PathSegment {
|
||||||
Field(Ident),
|
Field(Ident),
|
||||||
|
|
|
@ -2,20 +2,25 @@ use std::{collections::HashMap, error::Error};
|
||||||
|
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use edlang_ast::{
|
use edlang_ast::{
|
||||||
ArithOp, AssignStmt, BinaryOp, Constant, Expression, Function, LetStmt, Module,
|
ArithOp, AssignStmt, BinaryOp, CmpOp, Constant, Expression, FnCallExpr, Function, IfStmt,
|
||||||
ModuleStatement, ReturnStmt, Statement, Struct, ValueExpr,
|
LetStmt, LogicOp, Module, ModuleStatement, ReturnStmt, Statement, Struct, ValueExpr,
|
||||||
};
|
};
|
||||||
use edlang_session::Session;
|
use edlang_session::Session;
|
||||||
use melior::{
|
use melior::{
|
||||||
dialect::{arith, func, memref},
|
dialect::{
|
||||||
|
arith::{self, CmpiPredicate},
|
||||||
|
cf, func, memref,
|
||||||
|
},
|
||||||
ir::{
|
ir::{
|
||||||
attribute::{FlatSymbolRefAttribute, IntegerAttribute, StringAttribute, TypeAttribute},
|
attribute::{FlatSymbolRefAttribute, IntegerAttribute, StringAttribute, TypeAttribute},
|
||||||
r#type::{FunctionType, IntegerType, MemRefType},
|
r#type::{FunctionType, IntegerType, MemRefType},
|
||||||
Attribute, Block, BlockRef, Location, Module as MeliorModule, Region, Type, Value,
|
Attribute, Block, BlockRef, Location, Module as MeliorModule, Region, Type, TypeLike,
|
||||||
ValueLike,
|
Value, ValueLike,
|
||||||
},
|
},
|
||||||
Context as MeliorContext,
|
Context as MeliorContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::util::call_site;
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct LocalVar<'ctx, 'parent: 'ctx> {
|
pub struct LocalVar<'ctx, 'parent: 'ctx> {
|
||||||
pub ast_type: edlang_ast::Type,
|
pub ast_type: edlang_ast::Type,
|
||||||
|
@ -48,7 +53,19 @@ struct ScopeContext<'ctx, 'parent: 'ctx> {
|
||||||
pub functions: HashMap<String, &'parent Function>,
|
pub functions: HashMap<String, &'parent Function>,
|
||||||
pub structs: HashMap<String, &'parent Struct>,
|
pub structs: HashMap<String, &'parent Struct>,
|
||||||
pub constants: HashMap<String, &'parent Constant>,
|
pub constants: HashMap<String, &'parent Constant>,
|
||||||
pub ret_type: Option<&'parent edlang_ast::Type>,
|
pub function: Option<&'parent edlang_ast::Function>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ctx, 'parent: 'ctx> ScopeContext<'ctx, 'parent> {
|
||||||
|
fn is_type_signed(&self, type_info: &edlang_ast::Type) -> bool {
|
||||||
|
let signed = ["i8", "i16", "i32", "i64", "i128"];
|
||||||
|
signed.contains(&type_info.name.name.as_str())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_float(&self, type_info: &edlang_ast::Type) -> bool {
|
||||||
|
let signed = ["f32", "f64"];
|
||||||
|
signed.contains(&type_info.name.name.as_str())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BlockHelper<'ctx, 'this: 'ctx> {
|
struct BlockHelper<'ctx, 'this: 'ctx> {
|
||||||
|
@ -155,6 +172,7 @@ fn compile_function_def<'ctx, 'parent>(
|
||||||
let region = Region::new();
|
let region = Region::new();
|
||||||
|
|
||||||
let location = get_location(context, session, info.name.span.lo);
|
let location = get_location(context, session, info.name.span.lo);
|
||||||
|
let location = Location::name(context, &info.name.name, location);
|
||||||
|
|
||||||
let mut args = Vec::with_capacity(info.params.len());
|
let mut args = Vec::with_capacity(info.params.len());
|
||||||
let mut fn_args_types = Vec::with_capacity(info.params.len());
|
let mut fn_args_types = Vec::with_capacity(info.params.len());
|
||||||
|
@ -162,6 +180,7 @@ fn compile_function_def<'ctx, 'parent>(
|
||||||
for param in &info.params {
|
for param in &info.params {
|
||||||
let param_type = scope_ctx.resolve_type(context, ¶m.arg_type)?;
|
let param_type = scope_ctx.resolve_type(context, ¶m.arg_type)?;
|
||||||
let loc = get_location(context, session, param.name.span.lo);
|
let loc = get_location(context, session, param.name.span.lo);
|
||||||
|
let loc = Location::name(context, ¶m.name.name, loc);
|
||||||
args.push((param_type, loc));
|
args.push((param_type, loc));
|
||||||
fn_args_types.push(param_type);
|
fn_args_types.push(param_type);
|
||||||
}
|
}
|
||||||
|
@ -183,7 +202,7 @@ fn compile_function_def<'ctx, 'parent>(
|
||||||
};
|
};
|
||||||
let fn_block = helper.append_block(Block::new(&args));
|
let fn_block = helper.append_block(Block::new(&args));
|
||||||
let mut scope_ctx = scope_ctx.clone();
|
let mut scope_ctx = scope_ctx.clone();
|
||||||
scope_ctx.ret_type = info.return_type.as_ref();
|
scope_ctx.function = Some(info);
|
||||||
|
|
||||||
// Push arguments into locals
|
// Push arguments into locals
|
||||||
for (i, param) in info.params.iter().enumerate() {
|
for (i, param) in info.params.iter().enumerate() {
|
||||||
|
@ -205,7 +224,11 @@ fn compile_function_def<'ctx, 'parent>(
|
||||||
if final_block.terminator().is_none() {
|
if final_block.terminator().is_none() {
|
||||||
final_block.append_operation(func::r#return(
|
final_block.append_operation(func::r#return(
|
||||||
&[],
|
&[],
|
||||||
|
Location::name(
|
||||||
|
context,
|
||||||
|
"return",
|
||||||
get_location(context, session, info.span.hi),
|
get_location(context, session, info.span.hi),
|
||||||
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -231,7 +254,7 @@ fn compile_block<'ctx, 'parent: 'ctx>(
|
||||||
scope_ctx: &mut ScopeContext<'ctx, 'parent>,
|
scope_ctx: &mut ScopeContext<'ctx, 'parent>,
|
||||||
helper: &BlockHelper<'ctx, 'parent>,
|
helper: &BlockHelper<'ctx, 'parent>,
|
||||||
mut block: &'parent BlockRef<'ctx, 'parent>,
|
mut block: &'parent BlockRef<'ctx, 'parent>,
|
||||||
info: &edlang_ast::Block,
|
info: &'parent edlang_ast::Block,
|
||||||
) -> Result<&'parent BlockRef<'ctx, 'parent>, Box<dyn std::error::Error>> {
|
) -> Result<&'parent BlockRef<'ctx, 'parent>, Box<dyn std::error::Error>> {
|
||||||
tracing::debug!("compiling block");
|
tracing::debug!("compiling block");
|
||||||
for stmt in &info.body {
|
for stmt in &info.body {
|
||||||
|
@ -244,11 +267,15 @@ fn compile_block<'ctx, 'parent: 'ctx>(
|
||||||
}
|
}
|
||||||
Statement::For(_) => todo!(),
|
Statement::For(_) => todo!(),
|
||||||
Statement::While(_) => todo!(),
|
Statement::While(_) => todo!(),
|
||||||
Statement::If(_) => todo!(),
|
Statement::If(info) => {
|
||||||
|
block = compile_if_stmt(session, context, scope_ctx, helper, block, info)?;
|
||||||
|
}
|
||||||
Statement::Return(info) => {
|
Statement::Return(info) => {
|
||||||
compile_return(session, context, scope_ctx, helper, block, info)?;
|
compile_return(session, context, scope_ctx, helper, block, info)?;
|
||||||
}
|
}
|
||||||
Statement::FnCall(_) => todo!(),
|
Statement::FnCall(info) => {
|
||||||
|
compile_fn_call(session, context, scope_ctx, helper, block, info)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,7 +288,7 @@ fn compile_let<'ctx, 'parent: 'ctx>(
|
||||||
scope_ctx: &mut ScopeContext<'ctx, 'parent>,
|
scope_ctx: &mut ScopeContext<'ctx, 'parent>,
|
||||||
helper: &BlockHelper<'ctx, 'parent>,
|
helper: &BlockHelper<'ctx, 'parent>,
|
||||||
block: &'parent BlockRef<'ctx, 'parent>,
|
block: &'parent BlockRef<'ctx, 'parent>,
|
||||||
info: &LetStmt,
|
info: &'parent LetStmt,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
tracing::debug!("compiling let");
|
tracing::debug!("compiling let");
|
||||||
let value = compile_expression(
|
let value = compile_expression(
|
||||||
|
@ -271,7 +298,7 @@ fn compile_let<'ctx, 'parent: 'ctx>(
|
||||||
helper,
|
helper,
|
||||||
block,
|
block,
|
||||||
&info.value,
|
&info.value,
|
||||||
Some(scope_ctx.resolve_type(context, &info.r#type)?),
|
Some(&info.r#type),
|
||||||
)?;
|
)?;
|
||||||
let location = get_location(context, session, info.name.span.lo);
|
let location = get_location(context, session, info.name.span.lo);
|
||||||
|
|
||||||
|
@ -332,7 +359,7 @@ fn compile_assign<'ctx, 'parent: 'ctx>(
|
||||||
helper,
|
helper,
|
||||||
block,
|
block,
|
||||||
&info.value,
|
&info.value,
|
||||||
Some(scope_ctx.resolve_type(context, &local.ast_type)?),
|
Some(&local.ast_type),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let k0 = block
|
let k0 = block
|
||||||
|
@ -357,6 +384,10 @@ fn compile_return<'ctx, 'parent: 'ctx>(
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
tracing::debug!("compiling return");
|
tracing::debug!("compiling return");
|
||||||
let location = get_location(context, session, info.span.lo);
|
let location = get_location(context, session, info.span.lo);
|
||||||
|
let location = Location::name(context, "return", location);
|
||||||
|
|
||||||
|
let ret_type = scope_ctx.function.and_then(|x| x.return_type.clone());
|
||||||
|
|
||||||
if let Some(value) = &info.value {
|
if let Some(value) = &info.value {
|
||||||
let value = compile_expression(
|
let value = compile_expression(
|
||||||
session,
|
session,
|
||||||
|
@ -365,9 +396,7 @@ fn compile_return<'ctx, 'parent: 'ctx>(
|
||||||
helper,
|
helper,
|
||||||
block,
|
block,
|
||||||
value,
|
value,
|
||||||
scope_ctx
|
ret_type.as_ref(),
|
||||||
.ret_type
|
|
||||||
.map(|x| scope_ctx.resolve_type(context, x).unwrap()),
|
|
||||||
)?;
|
)?;
|
||||||
block.append_operation(func::r#return(&[value], location));
|
block.append_operation(func::r#return(&[value], location));
|
||||||
} else {
|
} else {
|
||||||
|
@ -384,7 +413,7 @@ fn compile_expression<'ctx, 'parent: 'ctx>(
|
||||||
helper: &BlockHelper<'ctx, 'parent>,
|
helper: &BlockHelper<'ctx, 'parent>,
|
||||||
block: &'parent BlockRef<'ctx, 'parent>,
|
block: &'parent BlockRef<'ctx, 'parent>,
|
||||||
info: &Expression,
|
info: &Expression,
|
||||||
type_hint: Option<Type<'ctx>>,
|
type_hint: Option<&'parent edlang_ast::Type>,
|
||||||
) -> Result<Value<'ctx, 'parent>, Box<dyn std::error::Error>> {
|
) -> Result<Value<'ctx, 'parent>, Box<dyn std::error::Error>> {
|
||||||
tracing::debug!("compiling expression");
|
tracing::debug!("compiling expression");
|
||||||
Ok(match info {
|
Ok(match info {
|
||||||
|
@ -408,10 +437,10 @@ fn compile_expression<'ctx, 'parent: 'ctx>(
|
||||||
.result(0)?
|
.result(0)?
|
||||||
.into(),
|
.into(),
|
||||||
ValueExpr::Int { value, span } => {
|
ValueExpr::Int { value, span } => {
|
||||||
let type_it = match type_hint {
|
let type_it = match type_hint.map(|x| scope_ctx.resolve_type(context, x)) {
|
||||||
Some(info) => info,
|
Some(info) => info,
|
||||||
None => IntegerType::new(context, 32).into(),
|
None => Ok(IntegerType::new(context, 32).into()),
|
||||||
};
|
}?;
|
||||||
block
|
block
|
||||||
.append_operation(arith::constant(
|
.append_operation(arith::constant(
|
||||||
context,
|
context,
|
||||||
|
@ -422,10 +451,10 @@ fn compile_expression<'ctx, 'parent: 'ctx>(
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
ValueExpr::Float { value, span } => {
|
ValueExpr::Float { value, span } => {
|
||||||
let type_it = match type_hint {
|
let type_it = match type_hint.map(|x| scope_ctx.resolve_type(context, x)) {
|
||||||
Some(info) => info,
|
Some(info) => info,
|
||||||
None => Type::float32(context),
|
None => Ok(Type::float32(context)),
|
||||||
};
|
}?;
|
||||||
block
|
block
|
||||||
.append_operation(arith::constant(
|
.append_operation(arith::constant(
|
||||||
context,
|
context,
|
||||||
|
@ -443,6 +472,7 @@ fn compile_expression<'ctx, 'parent: 'ctx>(
|
||||||
.expect("local not found");
|
.expect("local not found");
|
||||||
|
|
||||||
let location = get_location(context, session, path.first.span.lo);
|
let location = get_location(context, session, path.first.span.lo);
|
||||||
|
let location = Location::name(context, &path.first.name, location);
|
||||||
|
|
||||||
if local.is_alloca {
|
if local.is_alloca {
|
||||||
let k0 = block
|
let k0 = block
|
||||||
|
@ -464,8 +494,158 @@ fn compile_expression<'ctx, 'parent: 'ctx>(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Expression::FnCall(info) => {
|
Expression::FnCall(info) => {
|
||||||
|
compile_fn_call(session, context, scope_ctx, helper, block, info)?
|
||||||
|
}
|
||||||
|
Expression::Unary(_, _) => todo!(),
|
||||||
|
Expression::Binary(lhs, op, rhs) => {
|
||||||
|
let lhs =
|
||||||
|
compile_expression(session, context, scope_ctx, helper, block, lhs, type_hint)?;
|
||||||
|
let rhs =
|
||||||
|
compile_expression(session, context, scope_ctx, helper, block, rhs, type_hint)?;
|
||||||
|
|
||||||
|
match op {
|
||||||
|
BinaryOp::Arith(arith_op, span) => {
|
||||||
|
let location = get_location(context, session, span.lo);
|
||||||
|
let ast_type_hint = type_hint.expect("type info missing");
|
||||||
|
|
||||||
|
block.append_operation(if scope_ctx.is_float(ast_type_hint) {
|
||||||
|
match arith_op {
|
||||||
|
ArithOp::Add => arith::addf(lhs, rhs, location),
|
||||||
|
ArithOp::Sub => arith::subf(lhs, rhs, location),
|
||||||
|
ArithOp::Mul => arith::mulf(lhs, rhs, location),
|
||||||
|
ArithOp::Div => arith::divf(lhs, rhs, location),
|
||||||
|
ArithOp::Mod => arith::remf(lhs, rhs, location),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match arith_op {
|
||||||
|
ArithOp::Add => arith::addi(lhs, rhs, location),
|
||||||
|
ArithOp::Sub => arith::subi(lhs, rhs, location),
|
||||||
|
ArithOp::Mul => arith::muli(lhs, rhs, location),
|
||||||
|
ArithOp::Div => {
|
||||||
|
if scope_ctx.is_type_signed(ast_type_hint) {
|
||||||
|
arith::divsi(lhs, rhs, location)
|
||||||
|
} else {
|
||||||
|
arith::divui(lhs, rhs, location)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ArithOp::Mod => {
|
||||||
|
if scope_ctx.is_type_signed(ast_type_hint) {
|
||||||
|
arith::remsi(lhs, rhs, location)
|
||||||
|
} else {
|
||||||
|
arith::remui(lhs, rhs, location)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
BinaryOp::Logic(logic_op, span) => {
|
||||||
|
let location = get_location(context, session, span.lo);
|
||||||
|
|
||||||
|
block.append_operation(match logic_op {
|
||||||
|
LogicOp::And => {
|
||||||
|
dbg!(lhs.r#type());
|
||||||
|
dbg!(rhs.r#type());
|
||||||
|
let const_true = block
|
||||||
|
.append_operation(arith::constant(
|
||||||
|
context,
|
||||||
|
IntegerAttribute::new(1, IntegerType::new(context, 1).into())
|
||||||
|
.into(),
|
||||||
|
location,
|
||||||
|
))
|
||||||
|
.result(0)?
|
||||||
|
.into();
|
||||||
|
let lhs_bool = block
|
||||||
|
.append_operation(arith::cmpi(
|
||||||
|
context,
|
||||||
|
CmpiPredicate::Eq,
|
||||||
|
lhs,
|
||||||
|
const_true,
|
||||||
|
location,
|
||||||
|
))
|
||||||
|
.result(0)?
|
||||||
|
.into();
|
||||||
|
let rhs_bool = block
|
||||||
|
.append_operation(arith::cmpi(
|
||||||
|
context,
|
||||||
|
CmpiPredicate::Eq,
|
||||||
|
rhs,
|
||||||
|
const_true,
|
||||||
|
location,
|
||||||
|
))
|
||||||
|
.result(0)?
|
||||||
|
.into();
|
||||||
|
arith::andi(lhs_bool, rhs_bool, location)
|
||||||
|
}
|
||||||
|
LogicOp::Or => {
|
||||||
|
let const_true = block
|
||||||
|
.append_operation(arith::constant(
|
||||||
|
context,
|
||||||
|
IntegerAttribute::new(1, IntegerType::new(context, 1).into())
|
||||||
|
.into(),
|
||||||
|
location,
|
||||||
|
))
|
||||||
|
.result(0)?
|
||||||
|
.into();
|
||||||
|
let lhs_bool = block
|
||||||
|
.append_operation(arith::cmpi(
|
||||||
|
context,
|
||||||
|
CmpiPredicate::Eq,
|
||||||
|
lhs,
|
||||||
|
const_true,
|
||||||
|
location,
|
||||||
|
))
|
||||||
|
.result(0)?
|
||||||
|
.into();
|
||||||
|
let rhs_bool = block
|
||||||
|
.append_operation(arith::cmpi(
|
||||||
|
context,
|
||||||
|
CmpiPredicate::Eq,
|
||||||
|
rhs,
|
||||||
|
const_true,
|
||||||
|
location,
|
||||||
|
))
|
||||||
|
.result(0)?
|
||||||
|
.into();
|
||||||
|
arith::ori(lhs_bool, rhs_bool, location)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
BinaryOp::Compare(cmp_op, span) => {
|
||||||
|
let location = get_location(context, session, span.lo);
|
||||||
|
block.append_operation(match cmp_op {
|
||||||
|
CmpOp::Eq => arith::cmpi(context, CmpiPredicate::Eq, lhs, rhs, location),
|
||||||
|
CmpOp::NotEq => arith::cmpi(context, CmpiPredicate::Ne, lhs, rhs, location),
|
||||||
|
CmpOp::Lt => arith::cmpi(context, CmpiPredicate::Slt, lhs, rhs, location),
|
||||||
|
CmpOp::LtEq => arith::cmpi(context, CmpiPredicate::Sle, lhs, rhs, location),
|
||||||
|
CmpOp::Gt => arith::cmpi(context, CmpiPredicate::Sgt, lhs, rhs, location),
|
||||||
|
CmpOp::GtEq => arith::cmpi(context, CmpiPredicate::Sge, lhs, rhs, location),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
BinaryOp::Bitwise(_, _) => todo!(),
|
||||||
|
}
|
||||||
|
.result(0)?
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compile_fn_call<'ctx, 'parent: 'ctx>(
|
||||||
|
session: &Session,
|
||||||
|
context: &'ctx MeliorContext,
|
||||||
|
scope_ctx: &ScopeContext<'ctx, 'parent>,
|
||||||
|
_helper: &BlockHelper<'ctx, 'parent>,
|
||||||
|
block: &'parent BlockRef<'ctx, 'parent>,
|
||||||
|
info: &FnCallExpr,
|
||||||
|
) -> Result<Value<'ctx, 'parent>, Box<dyn Error>> {
|
||||||
let mut args = Vec::with_capacity(info.params.len());
|
let mut args = Vec::with_capacity(info.params.len());
|
||||||
let location = get_location(context, session, info.name.span.lo);
|
let location = get_location(context, session, info.name.span.lo);
|
||||||
|
let location_callee = Location::name(context, &info.name.name, location);
|
||||||
|
let location_caller = Location::name(
|
||||||
|
context,
|
||||||
|
&info.name.name,
|
||||||
|
get_location(context, session, scope_ctx.function.unwrap().span.lo),
|
||||||
|
);
|
||||||
|
let location = call_site(location_callee, location_caller);
|
||||||
|
|
||||||
let target_fn = scope_ctx
|
let target_fn = scope_ctx
|
||||||
.functions
|
.functions
|
||||||
|
@ -483,21 +663,21 @@ fn compile_expression<'ctx, 'parent: 'ctx>(
|
||||||
session,
|
session,
|
||||||
context,
|
context,
|
||||||
scope_ctx,
|
scope_ctx,
|
||||||
helper,
|
_helper,
|
||||||
block,
|
block,
|
||||||
arg,
|
arg,
|
||||||
Some(scope_ctx.resolve_type(context, &arg_info.arg_type)?),
|
Some(&arg_info.arg_type),
|
||||||
)?;
|
)?;
|
||||||
args.push(value);
|
args.push(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
let return_type = if let Some(return_type) = &target_fn.return_type {
|
let return_type = if let Some(ret_type) = &target_fn.return_type {
|
||||||
vec![scope_ctx.resolve_type(context, return_type)?]
|
vec![scope_ctx.resolve_type(context, ret_type)?]
|
||||||
} else {
|
} else {
|
||||||
vec![]
|
vec![]
|
||||||
};
|
};
|
||||||
|
|
||||||
block
|
Ok(block
|
||||||
.append_operation(func::call(
|
.append_operation(func::call(
|
||||||
context,
|
context,
|
||||||
FlatSymbolRefAttribute::new(context, &info.name.name),
|
FlatSymbolRefAttribute::new(context, &info.name.name),
|
||||||
|
@ -506,52 +686,91 @@ fn compile_expression<'ctx, 'parent: 'ctx>(
|
||||||
location,
|
location,
|
||||||
))
|
))
|
||||||
.result(0)?
|
.result(0)?
|
||||||
.into()
|
.into())
|
||||||
}
|
}
|
||||||
Expression::Unary(_, _) => todo!(),
|
|
||||||
Expression::Binary(lhs, op, rhs) => {
|
|
||||||
let lhs =
|
|
||||||
compile_expression(session, context, scope_ctx, helper, block, lhs, type_hint)?;
|
|
||||||
let rhs =
|
|
||||||
compile_expression(session, context, scope_ctx, helper, block, rhs, type_hint)?;
|
|
||||||
|
|
||||||
match op {
|
fn compile_if_stmt<'c, 'this: 'c>(
|
||||||
BinaryOp::Arith(op, span) => {
|
session: &Session,
|
||||||
match op {
|
context: &'c MeliorContext,
|
||||||
// todo check if its a float or unsigned
|
scope_ctx: &mut ScopeContext<'c, 'this>,
|
||||||
ArithOp::Add => block.append_operation(arith::addi(
|
helper: &BlockHelper<'c, 'this>,
|
||||||
lhs,
|
block: &'this BlockRef<'c, 'this>,
|
||||||
rhs,
|
info: &'this IfStmt,
|
||||||
get_location(context, session, span.lo),
|
) -> Result<&'this BlockRef<'c, 'this>, Box<dyn Error>> {
|
||||||
)),
|
let condition = compile_expression(
|
||||||
ArithOp::Sub => block.append_operation(arith::subi(
|
session,
|
||||||
lhs,
|
context,
|
||||||
rhs,
|
scope_ctx,
|
||||||
get_location(context, session, span.lo),
|
helper,
|
||||||
)),
|
block,
|
||||||
ArithOp::Mul => block.append_operation(arith::muli(
|
&info.condition,
|
||||||
lhs,
|
None,
|
||||||
rhs,
|
)?;
|
||||||
get_location(context, session, span.lo),
|
|
||||||
)),
|
let then_successor = helper.append_block(Block::new(&[]));
|
||||||
ArithOp::Div => block.append_operation(arith::divsi(
|
let else_successor = helper.append_block(Block::new(&[]));
|
||||||
lhs,
|
|
||||||
rhs,
|
let location = get_location(context, session, info.span.lo);
|
||||||
get_location(context, session, span.lo),
|
|
||||||
)),
|
block.append_operation(cf::cond_br(
|
||||||
ArithOp::Mod => block.append_operation(arith::remsi(
|
context,
|
||||||
lhs,
|
condition,
|
||||||
rhs,
|
then_successor,
|
||||||
get_location(context, session, span.lo),
|
else_successor,
|
||||||
)),
|
&[],
|
||||||
|
&[],
|
||||||
|
Location::name(context, "if", location),
|
||||||
|
));
|
||||||
|
|
||||||
|
let mut then_successor = then_successor;
|
||||||
|
let mut else_successor = else_successor;
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut then_scope_ctx = scope_ctx.clone();
|
||||||
|
then_successor = compile_block(
|
||||||
|
session,
|
||||||
|
context,
|
||||||
|
&mut then_scope_ctx,
|
||||||
|
helper,
|
||||||
|
then_successor,
|
||||||
|
&info.then_block,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(else_block) = info.else_block.as_ref() {
|
||||||
|
let mut else_scope_ctx = scope_ctx.clone();
|
||||||
|
else_successor = compile_block(
|
||||||
|
session,
|
||||||
|
context,
|
||||||
|
&mut else_scope_ctx,
|
||||||
|
helper,
|
||||||
|
else_successor,
|
||||||
|
else_block,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
BinaryOp::Logic(_, _) => todo!(),
|
|
||||||
BinaryOp::Compare(_, _) => todo!(),
|
// both return
|
||||||
BinaryOp::Bitwise(_, _) => todo!(),
|
if then_successor.terminator().is_some() && else_successor.terminator().is_some() {
|
||||||
|
return Ok(then_successor);
|
||||||
}
|
}
|
||||||
.result(0)?
|
|
||||||
.into()
|
let final_block = helper.append_block(Block::new(&[]));
|
||||||
|
|
||||||
|
if then_successor.terminator().is_none() {
|
||||||
|
then_successor.append_operation(cf::br(
|
||||||
|
final_block,
|
||||||
|
&[],
|
||||||
|
get_location(context, session, info.span.hi),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
if else_successor.terminator().is_none() {
|
||||||
|
else_successor.append_operation(cf::br(
|
||||||
|
final_block,
|
||||||
|
&[],
|
||||||
|
get_location(context, session, info.span.hi),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(final_block)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use edlang_ast::Module;
|
||||||
use edlang_session::Session;
|
use edlang_session::Session;
|
||||||
use melior::{
|
use melior::{
|
||||||
dialect::DialectRegistry,
|
dialect::DialectRegistry,
|
||||||
ir::{Location, Module as MeliorModule},
|
ir::{operation::OperationPrintingFlags, Location, Module as MeliorModule},
|
||||||
pass::{self, PassManager},
|
pass::{self, PassManager},
|
||||||
utility::{register_all_dialects, register_all_llvm_translations, register_all_passes},
|
utility::{register_all_dialects, register_all_llvm_translations, register_all_passes},
|
||||||
Context as MeliorContext,
|
Context as MeliorContext,
|
||||||
|
@ -42,16 +42,20 @@ impl Context {
|
||||||
assert!(melior_module.as_operation().verify());
|
assert!(melior_module.as_operation().verify());
|
||||||
|
|
||||||
tracing::debug!(
|
tracing::debug!(
|
||||||
"MLIR Code before passes:\n{:#?}",
|
"MLIR Code before passes:\n{}",
|
||||||
melior_module.as_operation()
|
melior_module.as_operation().to_string_with_flags(
|
||||||
|
OperationPrintingFlags::new().enable_debug_info(true, true)
|
||||||
|
)?
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: Add proper error handling.
|
// TODO: Add proper error handling.
|
||||||
self.run_pass_manager(&mut melior_module)?;
|
self.run_pass_manager(&mut melior_module)?;
|
||||||
|
|
||||||
tracing::debug!(
|
tracing::debug!(
|
||||||
"MLIR Code after passes:\n{:#?}",
|
"MLIR Code after passes:\n{}",
|
||||||
melior_module.as_operation()
|
melior_module.as_operation().to_string_with_flags(
|
||||||
|
OperationPrintingFlags::new().enable_debug_info(true, true)
|
||||||
|
)?
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(melior_module)
|
Ok(melior_module)
|
||||||
|
|
|
@ -32,6 +32,7 @@ pub mod codegen;
|
||||||
mod context;
|
mod context;
|
||||||
mod ffi;
|
mod ffi;
|
||||||
pub mod linker;
|
pub mod linker;
|
||||||
|
mod util;
|
||||||
|
|
||||||
pub fn compile(session: &Session, program: &Module) -> Result<PathBuf, Box<dyn std::error::Error>> {
|
pub fn compile(session: &Session, program: &Module) -> Result<PathBuf, Box<dyn std::error::Error>> {
|
||||||
let context = Context::new();
|
let context = Context::new();
|
||||||
|
|
|
@ -2,8 +2,6 @@ use std::path::Path;
|
||||||
|
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
// TODO: Implement a proper linker driver, passing only the arguments needed dynamically based on the requirements.
|
|
||||||
|
|
||||||
#[instrument(level = "debug")]
|
#[instrument(level = "debug")]
|
||||||
pub fn link_shared_lib(input_path: &Path, output_filename: &Path) -> Result<(), std::io::Error> {
|
pub fn link_shared_lib(input_path: &Path, output_filename: &Path) -> Result<(), std::io::Error> {
|
||||||
let args: &[&str] = {
|
let args: &[&str] = {
|
||||||
|
@ -24,15 +22,41 @@ pub fn link_shared_lib(input_path: &Path, output_filename: &Path) -> Result<(),
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
{
|
{
|
||||||
|
let (scrt1, crti, crtn) = {
|
||||||
|
if file_exists("/usr/lib64/Scrt1.o") {
|
||||||
|
(
|
||||||
|
"/usr/lib64/Scrt1.o",
|
||||||
|
"/usr/lib64/crti.o",
|
||||||
|
"/usr/lib64/crtn.o",
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
"/lib/x86_64-linux-gnu/Scrt1.o",
|
||||||
|
"/lib/x86_64-linux-gnu/crti.o",
|
||||||
|
"/lib/x86_64-linux-gnu/crtn.o",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
&[
|
&[
|
||||||
|
"-pie",
|
||||||
"--hash-style=gnu",
|
"--hash-style=gnu",
|
||||||
"--eh-frame-hdr",
|
"--eh-frame-hdr",
|
||||||
"-shared",
|
"--dynamic-linker",
|
||||||
|
"/lib64/ld-linux-x86-64.so.2",
|
||||||
|
"-m",
|
||||||
|
"elf_x86_64",
|
||||||
|
scrt1,
|
||||||
|
crti,
|
||||||
"-o",
|
"-o",
|
||||||
&output_filename.display().to_string(),
|
&output_filename.display().to_string(),
|
||||||
"-L/lib/../lib64",
|
"-L/lib64",
|
||||||
"-L/usr/lib/../lib64",
|
"-L/usr/lib64",
|
||||||
|
"-L/lib/x86_64-linux-gnu",
|
||||||
|
"-zrelro",
|
||||||
|
"--no-as-needed",
|
||||||
"-lc",
|
"-lc",
|
||||||
|
crtn,
|
||||||
&input_path.display().to_string(),
|
&input_path.display().to_string(),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -96,3 +120,7 @@ pub fn link_binary(input_path: &Path, output_filename: &Path) -> Result<(), std:
|
||||||
proc.wait_with_output()?;
|
proc.wait_with_output()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn file_exists(path: &str) -> bool {
|
||||||
|
Path::new(path).exists()
|
||||||
|
}
|
||||||
|
|
6
lib/edlang_codegen_mlir/src/util.rs
Normal file
6
lib/edlang_codegen_mlir/src/util.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
use melior::{ir::Location, Context};
|
||||||
|
use mlir_sys::mlirLocationCallSiteGet;
|
||||||
|
|
||||||
|
pub fn call_site<'c>(callee: Location<'c>, caller: Location<'c>) -> Location<'c> {
|
||||||
|
unsafe { Location::from_raw(mlirLocationCallSiteGet(callee.to_raw(), caller.to_raw())) }
|
||||||
|
}
|
|
@ -244,7 +244,7 @@ pub(crate) ForStmt: ast::ForStmt = {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) IfStmt: ast::IfStmt = {
|
pub(crate) IfStmt: ast::IfStmt = {
|
||||||
<lo:@L> "if" <condition:Expression> <then_block:Block> <else_block:Block?> <hi:@R> => {
|
<lo:@L> "if" <condition:Expression> <then_block:Block> <else_block:("else" <Block>)?> <hi:@R> => {
|
||||||
ast::IfStmt {
|
ast::IfStmt {
|
||||||
condition,
|
condition,
|
||||||
then_block,
|
then_block,
|
||||||
|
|
|
@ -3,6 +3,14 @@ mod Main {
|
||||||
return a + b;
|
return a + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check(a: i32) -> i32 {
|
||||||
|
if a == 2 {
|
||||||
|
return a;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> i32 {
|
fn main() -> i32 {
|
||||||
let x: i32 = 2 + 3;
|
let x: i32 = 2 + 3;
|
||||||
let y: i32 = add(x, 4);
|
let y: i32 = add(x, 4);
|
||||||
|
|
Loading…
Reference in a new issue