mirror of
https://github.com/edg-l/edlang.git
synced 2024-11-22 16:08:24 +00:00
fn call
This commit is contained in:
parent
37e083e2a7
commit
e5ea36a25c
|
@ -3,7 +3,7 @@ use std::{error::Error, path::PathBuf, time::Instant};
|
||||||
use ariadne::Source;
|
use ariadne::Source;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use edlang_codegen_mlir::linker::{link_binary, link_shared_lib};
|
use edlang_codegen_mlir::linker::{link_binary, link_shared_lib};
|
||||||
use edlang_lowering::{lower_module, IdGenerator};
|
use edlang_lowering::lower_modules;
|
||||||
use edlang_session::{DebugInfo, OptLevel, Session};
|
use edlang_session::{DebugInfo, OptLevel, Session};
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
|
@ -85,11 +85,10 @@ pub fn main() -> Result<(), Box<dyn Error>> {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut gen = IdGenerator::new(0);
|
let module_irs = lower_modules(&[module.clone()]);
|
||||||
let ir = lower_module(&mut gen, &module);
|
|
||||||
|
|
||||||
if args.ir {
|
if args.ir {
|
||||||
println!("{:#?}", ir);
|
println!("{:#?}", module_irs);
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,6 @@ pub enum Terminator {
|
||||||
args: Vec<Operand>,
|
args: Vec<Operand>,
|
||||||
dest: Place,
|
dest: Place,
|
||||||
target: Option<usize>, // block
|
target: Option<usize>, // block
|
||||||
fn_span: Span,
|
|
||||||
},
|
},
|
||||||
Unreachable,
|
Unreachable,
|
||||||
}
|
}
|
||||||
|
@ -97,12 +96,13 @@ pub struct TypeInfo {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum TypeKind {
|
pub enum TypeKind {
|
||||||
|
Unit,
|
||||||
Bool,
|
Bool,
|
||||||
Char,
|
Char,
|
||||||
Int(IntTy),
|
Int(IntTy),
|
||||||
Uint(UintTy),
|
Uint(UintTy),
|
||||||
Float(FloatTy),
|
Float(FloatTy),
|
||||||
FuncDef { name: String, args: Vec<Self> },
|
FnDef(DefId, Vec<TypeInfo>), // The vec are generic types, not arg types
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -141,6 +141,7 @@ pub struct ConstData {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ConstKind {
|
pub enum ConstKind {
|
||||||
Value(ValueTree),
|
Value(ValueTree),
|
||||||
|
ZeroSized,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
89
lib/edlang_lowering/src/common.rs
Normal file
89
lib/edlang_lowering/src/common.rs
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use edlang_ir::{Body, DefId, Local, Statement, TypeInfo};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default)]
|
||||||
|
pub struct IdGenerator {
|
||||||
|
pub current_id: usize,
|
||||||
|
pub module_id: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IdGenerator {
|
||||||
|
pub const fn new(module_id: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
current_id: 0,
|
||||||
|
module_id: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next_id(&mut self) -> usize {
|
||||||
|
self.current_id += 1;
|
||||||
|
self.current_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next_defid(&mut self) -> DefId {
|
||||||
|
let id = self.next_id();
|
||||||
|
|
||||||
|
DefId {
|
||||||
|
module_id: self.module_id,
|
||||||
|
id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default)]
|
||||||
|
pub struct BuildCtx {
|
||||||
|
pub module_name_to_id: HashMap<String, usize>,
|
||||||
|
pub modules: HashMap<usize, ModuleCtx>,
|
||||||
|
pub functions: HashMap<DefId, Body>,
|
||||||
|
pub module_id_counter: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Default)]
|
||||||
|
pub struct ModuleCtx {
|
||||||
|
pub id: usize,
|
||||||
|
pub func_name_to_id: HashMap<String, DefId>,
|
||||||
|
pub functions: HashMap<DefId, (Vec<TypeInfo>, TypeInfo)>,
|
||||||
|
pub gen: IdGenerator,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct BodyBuilder {
|
||||||
|
pub local_module: usize,
|
||||||
|
pub body: Body,
|
||||||
|
pub statements: Vec<Statement>,
|
||||||
|
pub locals: HashMap<String, usize>,
|
||||||
|
pub ret_local: Option<usize>,
|
||||||
|
pub ctx: BuildCtx,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BodyBuilder {
|
||||||
|
pub fn add_local(&mut self, local: Local) -> usize {
|
||||||
|
let id = self.body.locals.len();
|
||||||
|
self.body.locals.push(local);
|
||||||
|
id
|
||||||
|
}
|
||||||
|
pub fn get_local(&self, name: &str) -> Option<&Local> {
|
||||||
|
self.body.locals.get(*(self.locals.get(name)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_current_module(&self) -> &ModuleCtx {
|
||||||
|
self.ctx
|
||||||
|
.modules
|
||||||
|
.get(&self.local_module)
|
||||||
|
.expect("current module should exist")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_current_module_mut(&mut self) -> &mut ModuleCtx {
|
||||||
|
self.ctx
|
||||||
|
.modules
|
||||||
|
.get_mut(&self.local_module)
|
||||||
|
.expect("current module should exist")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_fn_by_name(&self, name: &str) -> Option<&(Vec<TypeInfo>, TypeInfo)> {
|
||||||
|
let id = self.get_current_module().func_name_to_id.get(name)?;
|
||||||
|
let f = self.get_current_module().functions.get(&id)?;
|
||||||
|
Some(f)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,71 +1,90 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use ast::Function;
|
use common::{BodyBuilder, BuildCtx, IdGenerator, ModuleCtx};
|
||||||
use edlang_ast as ast;
|
use edlang_ast as ast;
|
||||||
use edlang_ir as ir;
|
use edlang_ir as ir;
|
||||||
use ir::{DefId, Local, Operand, Place, Statement, TypeInfo};
|
use ir::{ConstData, ConstKind, Local, Operand, Place, Statement, Terminator, TypeInfo};
|
||||||
|
|
||||||
pub struct IdGenerator {
|
mod common;
|
||||||
pub current_id: usize,
|
|
||||||
pub module_id: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IdGenerator {
|
pub fn lower_modules(modules: &[ast::Module]) -> Vec<ir::ModuleBody> {
|
||||||
pub const fn new(module_id: usize) -> Self {
|
let mut ctx = BuildCtx::default();
|
||||||
Self {
|
|
||||||
current_id: 0,
|
for m in modules {
|
||||||
module_id: 0,
|
ctx.module_name_to_id
|
||||||
}
|
.insert(m.name.name.clone(), ctx.module_id_counter);
|
||||||
|
ctx.module_id_counter += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_id(&mut self) -> usize {
|
let mut lowered_modules = Vec::with_capacity(modules.len());
|
||||||
self.current_id += 1;
|
|
||||||
self.current_id
|
// todo: maybe should do a prepass here populating all symbols
|
||||||
|
|
||||||
|
for module in modules {
|
||||||
|
let ir;
|
||||||
|
(ctx, ir) = lower_module(ctx, module);
|
||||||
|
lowered_modules.push(ir);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_defid(&mut self) -> DefId {
|
lowered_modules
|
||||||
let id = self.next_id();
|
|
||||||
|
|
||||||
DefId {
|
|
||||||
module_id: self.module_id,
|
|
||||||
id,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BuildCtx {
|
fn lower_module(mut ctx: BuildCtx, module: &ast::Module) -> (BuildCtx, ir::ModuleBody) {
|
||||||
pub func_ids: HashMap<String, DefId>,
|
|
||||||
pub functions: HashMap<DefId, Function>,
|
|
||||||
pub gen: IdGenerator,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn lower_module(gen: &mut IdGenerator, module: &ast::Module) -> ir::ModuleBody {
|
|
||||||
let mut body = ir::ModuleBody {
|
let mut body = ir::ModuleBody {
|
||||||
module_id: gen.next_id(),
|
module_id: ctx.module_id_counter,
|
||||||
functions: Default::default(),
|
functions: Default::default(),
|
||||||
modules: Default::default(),
|
modules: Default::default(),
|
||||||
span: module.span,
|
span: module.span,
|
||||||
};
|
};
|
||||||
|
ctx.module_id_counter += 1;
|
||||||
|
|
||||||
let mut ctx = BuildCtx {
|
let mut module_ctx = ModuleCtx {
|
||||||
func_ids: Default::default(),
|
id: body.module_id,
|
||||||
functions: Default::default(),
|
|
||||||
gen: IdGenerator::new(body.module_id),
|
gen: IdGenerator::new(body.module_id),
|
||||||
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
for stmt in &module.contents {
|
for stmt in &module.contents {
|
||||||
match stmt {
|
match stmt {
|
||||||
ast::ModuleStatement::Function(func) => {
|
ast::ModuleStatement::Function(func) => {
|
||||||
ctx.func_ids.insert(func.name.name.clone(), ctx.gen.next_defid());
|
let next_id = module_ctx.gen.next_defid();
|
||||||
|
module_ctx
|
||||||
|
.func_name_to_id
|
||||||
|
.insert(func.name.name.clone(), next_id);
|
||||||
|
|
||||||
|
let mut args = Vec::new();
|
||||||
|
let ret_type;
|
||||||
|
|
||||||
|
if let Some(ret) = func.return_type.as_ref() {
|
||||||
|
ret_type = lower_type(&mut ctx, ret);
|
||||||
|
} else {
|
||||||
|
ret_type = TypeInfo {
|
||||||
|
span: None,
|
||||||
|
kind: ir::TypeKind::Unit,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
for arg in &func.params {
|
||||||
|
let ty = lower_type(&mut ctx, &arg.arg_type);
|
||||||
|
args.push(ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_ctx.functions.insert(next_id, (args, ret_type));
|
||||||
}
|
}
|
||||||
_ => {}
|
ast::ModuleStatement::Constant(_) => todo!(),
|
||||||
|
ast::ModuleStatement::Struct(_) => todo!(),
|
||||||
|
ast::ModuleStatement::Module(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.module_name_to_id
|
||||||
|
.insert(module.name.name.clone(), body.module_id);
|
||||||
|
ctx.modules.insert(body.module_id, module_ctx);
|
||||||
|
|
||||||
for stmt in &module.contents {
|
for stmt in &module.contents {
|
||||||
match stmt {
|
match stmt {
|
||||||
ast::ModuleStatement::Function(func) => {
|
ast::ModuleStatement::Function(func) => {
|
||||||
let (res, new_ctx) = lower_function(ctx, func);
|
let (res, new_ctx) = lower_function(ctx, func, body.module_id);
|
||||||
body.functions.insert(res.def_id, res);
|
body.functions.insert(res.def_id, res);
|
||||||
ctx = new_ctx;
|
ctx = new_ctx;
|
||||||
}
|
}
|
||||||
|
@ -75,20 +94,24 @@ pub fn lower_module(gen: &mut IdGenerator, module: &ast::Module) -> ir::ModuleBo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
body
|
(ctx, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BodyBuilder {
|
fn lower_function(
|
||||||
pub body: ir::Body,
|
mut ctx: BuildCtx,
|
||||||
pub statements: Vec<ir::Statement>,
|
func: &ast::Function,
|
||||||
pub locals: HashMap<String, usize>,
|
module_id: usize,
|
||||||
pub ret_local: Option<usize>,
|
) -> (ir::Body, BuildCtx) {
|
||||||
pub ctx: BuildCtx,
|
let def_id = *ctx
|
||||||
}
|
.modules
|
||||||
|
.get(&module_id)
|
||||||
|
.unwrap()
|
||||||
|
.func_name_to_id
|
||||||
|
.get(&func.name.name)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
fn lower_function(mut ctx: BuildCtx, func: &ast::Function) -> (ir::Body, BuildCtx) {
|
|
||||||
let body = ir::Body {
|
let body = ir::Body {
|
||||||
def_id: *ctx.func_ids.get(&func.name.name).unwrap(),
|
def_id,
|
||||||
ret_type: func.return_type.as_ref().map(|x| lower_type(&mut ctx, x)),
|
ret_type: func.return_type.as_ref().map(|x| lower_type(&mut ctx, x)),
|
||||||
locals: Default::default(),
|
locals: Default::default(),
|
||||||
blocks: Default::default(),
|
blocks: Default::default(),
|
||||||
|
@ -102,7 +125,8 @@ fn lower_function(mut ctx: BuildCtx, func: &ast::Function) -> (ir::Body, BuildCt
|
||||||
statements: Vec::new(),
|
statements: Vec::new(),
|
||||||
locals: HashMap::new(),
|
locals: HashMap::new(),
|
||||||
ret_local: None,
|
ret_local: None,
|
||||||
ctx
|
ctx,
|
||||||
|
local_module: module_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
// store args ret
|
// store args ret
|
||||||
|
@ -189,7 +213,7 @@ fn lower_assign(builder: &mut BodyBuilder, info: &ast::AssignStmt) {
|
||||||
|
|
||||||
builder.statements.push(Statement {
|
builder.statements.push(Statement {
|
||||||
span: Some(info.span),
|
span: Some(info.span),
|
||||||
kind: ir::StatementKind::Assign(place, rvalue)
|
kind: ir::StatementKind::Assign(place, rvalue),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,12 +224,95 @@ fn lower_expr(
|
||||||
) -> ir::RValue {
|
) -> ir::RValue {
|
||||||
match info {
|
match info {
|
||||||
ast::Expression::Value(info) => ir::RValue::Use(lower_value(builder, info, type_hint)),
|
ast::Expression::Value(info) => ir::RValue::Use(lower_value(builder, info, type_hint)),
|
||||||
ast::Expression::FnCall(_) => todo!(),
|
ast::Expression::FnCall(info) => ir::RValue::Use(lower_fn_call(builder, info)),
|
||||||
ast::Expression::Unary(_, _) => todo!(),
|
ast::Expression::Unary(_, _) => todo!(),
|
||||||
ast::Expression::Binary(_, _, _) => todo!(),
|
ast::Expression::Binary(_, _, _) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lower_fn_call(builder: &mut BodyBuilder, info: &ast::FnCallExpr) -> ir::Operand {
|
||||||
|
let (arg_types, ret_type) = builder.get_fn_by_name(&info.name.name).unwrap().clone();
|
||||||
|
|
||||||
|
let mut args = Vec::new();
|
||||||
|
|
||||||
|
let target_local = builder.add_local(Local {
|
||||||
|
mutable: false,
|
||||||
|
span: None,
|
||||||
|
ty: ret_type,
|
||||||
|
kind: ir::LocalKind::Temp,
|
||||||
|
});
|
||||||
|
|
||||||
|
let dest_place = Place {
|
||||||
|
local: target_local,
|
||||||
|
projection: Default::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (expr, ty) in info.params.iter().zip(arg_types) {
|
||||||
|
let rvalue = lower_expr(builder, expr, Some(&ty));
|
||||||
|
|
||||||
|
let local = builder.add_local(Local {
|
||||||
|
mutable: false,
|
||||||
|
span: None,
|
||||||
|
ty,
|
||||||
|
kind: ir::LocalKind::Temp,
|
||||||
|
});
|
||||||
|
|
||||||
|
let place = Place {
|
||||||
|
local,
|
||||||
|
projection: Default::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
builder.statements.push(Statement {
|
||||||
|
span: None,
|
||||||
|
kind: ir::StatementKind::StorageLive(local),
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.statements.push(Statement {
|
||||||
|
span: None,
|
||||||
|
kind: ir::StatementKind::Assign(place.clone(), rvalue),
|
||||||
|
});
|
||||||
|
|
||||||
|
args.push(Operand::Move(place))
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.statements.push(Statement {
|
||||||
|
span: None,
|
||||||
|
kind: ir::StatementKind::StorageLive(target_local),
|
||||||
|
});
|
||||||
|
|
||||||
|
let fn_id = *builder
|
||||||
|
.get_current_module()
|
||||||
|
.func_name_to_id
|
||||||
|
.get(&info.name.name)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let next_block = builder.body.blocks.len() + 1;
|
||||||
|
|
||||||
|
let terminator = Terminator::Call {
|
||||||
|
func: Operand::Constant(ConstData {
|
||||||
|
span: Some(info.span),
|
||||||
|
type_info: TypeInfo {
|
||||||
|
span: None,
|
||||||
|
kind: ir::TypeKind::FnDef(fn_id, vec![]),
|
||||||
|
},
|
||||||
|
kind: ConstKind::ZeroSized,
|
||||||
|
}),
|
||||||
|
args,
|
||||||
|
dest: dest_place.clone(),
|
||||||
|
target: Some(next_block),
|
||||||
|
};
|
||||||
|
|
||||||
|
let statements = std::mem::take(&mut builder.statements);
|
||||||
|
|
||||||
|
builder.body.blocks.push(ir::BasicBlock {
|
||||||
|
id: builder.body.blocks.len(),
|
||||||
|
statements: statements.into(),
|
||||||
|
terminator,
|
||||||
|
});
|
||||||
|
|
||||||
|
Operand::Move(dest_place)
|
||||||
|
}
|
||||||
|
|
||||||
fn lower_value(
|
fn lower_value(
|
||||||
builder: &mut BodyBuilder,
|
builder: &mut BodyBuilder,
|
||||||
info: &ast::ValueExpr,
|
info: &ast::ValueExpr,
|
||||||
|
@ -339,8 +446,12 @@ fn lower_path(builder: &mut BodyBuilder, info: &ast::PathExpr) -> ir::Place {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lower_type(gen: &mut BuildCtx, t: &ast::Type) -> ir::TypeInfo {
|
pub fn lower_type(ctx: &mut BuildCtx, t: &ast::Type) -> ir::TypeInfo {
|
||||||
match t.name.name.as_str() {
|
match t.name.name.as_str() {
|
||||||
|
"()" => ir::TypeInfo {
|
||||||
|
span: Some(t.span),
|
||||||
|
kind: ir::TypeKind::Unit,
|
||||||
|
},
|
||||||
"u8" => ir::TypeInfo {
|
"u8" => ir::TypeInfo {
|
||||||
span: Some(t.span),
|
span: Some(t.span),
|
||||||
kind: ir::TypeKind::Uint(ir::UintTy::U8),
|
kind: ir::TypeKind::Uint(ir::UintTy::U8),
|
||||||
|
|
|
@ -3,6 +3,11 @@ mod Main {
|
||||||
fn main(argc: i32) -> i32 {
|
fn main(argc: i32) -> i32 {
|
||||||
let mut x: i32 = 2;
|
let mut x: i32 = 2;
|
||||||
x = 4;
|
x = 4;
|
||||||
|
let y: i32 = other(2);
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn other(a: i32) -> i32 {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue