From 572f1aee09dfc984e11b16d4ac0e14a90edbd0db Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Sun, 4 Feb 2024 17:27:06 +0100 Subject: [PATCH] prog --- lib/edlang_codegen_mlir/src/codegen.rs | 61 ++++++++++++++++++---- lib/edlang_ir/src/lib.rs | 6 ++- lib/edlang_lowering/src/lib.rs | 70 +++++++++++++++++++++++++- programs/simple.ed | 1 + 4 files changed, 126 insertions(+), 12 deletions(-) diff --git a/lib/edlang_codegen_mlir/src/codegen.rs b/lib/edlang_codegen_mlir/src/codegen.rs index 97abaa924..e0f0d7ee8 100644 --- a/lib/edlang_codegen_mlir/src/codegen.rs +++ b/lib/edlang_codegen_mlir/src/codegen.rs @@ -4,6 +4,7 @@ use edlang_ir as ir; use edlang_ir::DefId; use edlang_session::Session; use inkwell::{ + attributes::Attribute, builder::{Builder, BuilderError}, context::Context, debug_info::{DICompileUnit, DebugInfoBuilder}, @@ -12,7 +13,7 @@ use inkwell::{ types::{AnyType, BasicMetadataTypeEnum, BasicType}, values::{AnyValue, AnyValueEnum, BasicValue, BasicValueEnum, PointerValue}, }; -use ir::{TypeInfo, ValueTree}; +use ir::{ConstData, Operand, TypeInfo, ValueTree}; use tracing::info; #[derive(Debug, Clone, Copy)] @@ -153,7 +154,7 @@ fn compile_fn_signature(ctx: &ModuleCompileCtx, body: &ir::Body) { compile_basic_type(ctx, &ret_type).fn_type(&args, false) }; - ctx.module.add_function( + let fn_value = ctx.module.add_function( name, fn_type, Some(if body.is_extern { @@ -164,6 +165,12 @@ fn compile_fn_signature(ctx: &ModuleCompileCtx, body: &ir::Body) { inkwell::module::Linkage::Private }), ); + + // nonlazybind + fn_value.add_attribute( + inkwell::attributes::AttributeLoc::Function, + ctx.ctx.context.create_enum_attribute(37, 0), + ); } fn compile_fn(ctx: &ModuleCompileCtx, body: &ir::Body) -> Result<(), BuilderError> { @@ -273,8 +280,47 @@ fn compile_fn(ctx: &ModuleCompileCtx, body: &ir::Body) -> Result<(), BuilderErro args, dest, target, - } => todo!(), - ir::Terminator::Unreachable => todo!(), + } => { + if let Operand::Constant(c) = func { + if let ir::TypeKind::FnDef(fn_id, generics) = &c.type_info.kind { + let fn_symbol = ctx.ctx.symbols.get(fn_id).unwrap(); + let fn_value = ctx.module.get_function(fn_symbol).unwrap(); + let args: Vec<_> = args + .iter() + .map(|x| { + compile_load_operand(ctx, body, &locals, x) + .unwrap() + .0 + .into() + }) + .collect(); + let result = ctx.builder.build_call(fn_value, &args, "")?; + + if let Some(dest) = dest { + let is_void = + matches!(body.locals[dest.local].ty.kind, ir::TypeKind::Unit); + + if !is_void { + ctx.builder.build_store( + *locals.get(&dest.local).unwrap(), + result.try_as_basic_value().expect_left("value was right"), + )?; + } + } + + if let Some(target) = target { + ctx.builder.build_unconditional_branch(blocks[*target])?; + } + } else { + todo!() + } + } else { + todo!() + } + } + ir::Terminator::Unreachable => { + ctx.builder.build_unreachable()?; + } } } @@ -645,10 +691,7 @@ fn compile_value<'ctx>( .into_int_type() .const_int((*x) as u64, true) .as_basic_value_enum(), - ir::ConstValue::U64(x) => ty - .into_int_type() - .const_int((*x) as u64, true) - .as_basic_value_enum(), + ir::ConstValue::U64(x) => ty.into_int_type().const_int(*x, true).as_basic_value_enum(), ir::ConstValue::U128(x) => ty .into_int_type() .const_int((*x) as u64, true) @@ -702,7 +745,7 @@ fn compile_basic_type<'ctx>( ) -> inkwell::types::BasicTypeEnum<'ctx> { // ctx.di_builder.create_basic_type(name, size_in_bits, encoding, flags) match &ty.kind { - ir::TypeKind::Unit => panic!(), + ir::TypeKind::Unit => todo!(), ir::TypeKind::Bool => ctx.ctx.context.bool_type().as_basic_type_enum(), ir::TypeKind::Char => ctx.ctx.context.i32_type().as_basic_type_enum(), ir::TypeKind::Int(ty) => match ty { diff --git a/lib/edlang_ir/src/lib.rs b/lib/edlang_ir/src/lib.rs index 97067ec81..31d86acb1 100644 --- a/lib/edlang_ir/src/lib.rs +++ b/lib/edlang_ir/src/lib.rs @@ -109,7 +109,7 @@ pub enum Terminator { Call { func: Operand, args: Vec, - dest: Place, + dest: Option, target: Option, // block }, Unreachable, @@ -133,6 +133,10 @@ pub enum TypeKind { } impl TypeKind { + pub fn is_unit(&self) -> bool { + matches!(self, Self::Unit) + } + pub fn get_falsy_value(&self) -> ValueTree { match self { Self::Bool => ValueTree::Leaf(ConstValue::Bool(false)), diff --git a/lib/edlang_lowering/src/lib.rs b/lib/edlang_lowering/src/lib.rs index 6a787cf26..7d9f73187 100644 --- a/lib/edlang_lowering/src/lib.rs +++ b/lib/edlang_lowering/src/lib.rs @@ -184,7 +184,9 @@ fn lower_function( ast::Statement::While(_) => todo!(), ast::Statement::If(_) => todo!(), ast::Statement::Return(info) => lower_return(&mut builder, info), - ast::Statement::FnCall(_) => todo!(), + ast::Statement::FnCall(info) => { + lower_fn_call_no_ret(&mut builder, info); + } } } @@ -370,6 +372,70 @@ fn lower_binary_expr( } } +fn lower_fn_call_no_ret(builder: &mut BodyBuilder, info: &ast::FnCallExpr) { + let (arg_types, _ret_type) = builder.get_fn_by_name(&info.name.name).unwrap().clone(); + + let mut args = Vec::new(); + + 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)) + } + + 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: None, + 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, + }); +} + 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(); @@ -438,7 +504,7 @@ fn lower_fn_call(builder: &mut BodyBuilder, info: &ast::FnCallExpr) -> ir::Opera kind: ConstKind::ZeroSized, }), args, - dest: dest_place.clone(), + dest: Some(dest_place.clone()), target: Some(next_block), }; diff --git a/programs/simple.ed b/programs/simple.ed index bd874366f..dd88b6c42 100644 --- a/programs/simple.ed +++ b/programs/simple.ed @@ -3,6 +3,7 @@ mod Main { pub fn main(argc: i32) -> i32 { let mut x: i32 = 2; x = 4; + a(); return x + 2; }