From caf3a94eeea2fb093f6e3222a698771a8862a8b5 Mon Sep 17 00:00:00 2001 From: Edgar Luque Date: Wed, 14 Feb 2024 11:21:33 +0100 Subject: [PATCH] feat: ptr repr --- lib/edlang_codegen_llvm/src/codegen.rs | 56 ++++++++++++++----- lib/edlang_driver/tests/programs.rs | 1 + lib/edlang_driver/tests/programs/factorial.ed | 14 +++++ lib/edlang_ir/src/lib.rs | 5 ++ lib/edlang_lowering/src/lib.rs | 37 +++++++++--- programs/factorial.ed | 14 +++++ programs/ptr.ed | 12 ++++ 7 files changed, 117 insertions(+), 22 deletions(-) create mode 100644 lib/edlang_driver/tests/programs/factorial.ed create mode 100644 programs/factorial.ed create mode 100644 programs/ptr.ed diff --git a/lib/edlang_codegen_llvm/src/codegen.rs b/lib/edlang_codegen_llvm/src/codegen.rs index 670b61792..978bc018b 100644 --- a/lib/edlang_codegen_llvm/src/codegen.rs +++ b/lib/edlang_codegen_llvm/src/codegen.rs @@ -14,6 +14,7 @@ use inkwell::{ targets::{InitializationConfig, Target, TargetData, TargetMachine}, types::{AnyType, BasicMetadataTypeEnum, BasicType}, values::{BasicValue, BasicValueEnum, PointerValue}, + AddressSpace, }; use ir::{LocalKind, ModuleBody, ProgramBody, TypeInfo, ValueTree}; use llvm_sys::debuginfo::LLVMDIFlagPublic; @@ -102,6 +103,7 @@ pub fn compile(session: &Session, program: &ProgramBody) -> Result Result<(), BuilderError> debug_loc = ctx.set_debug_loc(debug_loc.get_scope(), span); } - trace!("compiling stmt {}: {:?}", idx, stmt.kind); + trace!("compiling stmt {}: {:?}", idx, stmt); match &stmt.kind { ir::StatementKind::Assign(place, rvalue) => { let local = &body.locals[place.local]; @@ -428,6 +430,9 @@ fn compile_fn(ctx: &ModuleCompileCtx, fn_id: DefId) -> Result<(), BuilderError> } trace!("compiling terminator: {:?}", block.terminator); + if let Some(span) = block.terminator_span { + debug_loc = ctx.set_debug_loc(debug_loc.get_scope(), span); + } match &block.terminator { ir::Terminator::Target(id) => { ctx.builder.build_unconditional_branch(blocks[*id])?; @@ -954,6 +959,10 @@ fn compile_value<'ctx>( .const_float((*x) as f64) .as_basic_value_enum(), ir::ConstValue::F64(x) => ty.into_float_type().const_float(*x).as_basic_value_enum(), + ir::ConstValue::Char(x) => ty + .into_int_type() + .const_int((*x) as u64, false) + .as_basic_value_enum(), }, ValueTree::Branch(_) => todo!(), }) @@ -1022,6 +1031,12 @@ fn compile_basic_type<'ctx>( ir::TypeKind::FnDef(_def_id, _generic_args) => { panic!() } + ir::TypeKind::Ptr(_pointee) => ctx + .ctx + .context + .ptr_sized_int_type(&ctx.target_data, None) + .ptr_type(AddressSpace::default()) + .as_basic_type_enum(), } } @@ -1031,79 +1046,80 @@ fn compile_debug_type<'ctx>(ctx: &ModuleCompileCtx<'ctx, '_>, ty: &ir::TypeInfo) // 4 = float // 5 = signed // 11 = numeric string + // https://dwarfstd.org/doc/DWARF5.pdf#section.7.8 match &ty.kind { ir::TypeKind::Unit => todo!(), ir::TypeKind::Bool => ctx .di_builder - .create_basic_type("bool", 1, 2, LLVMDIFlagPublic) + .create_basic_type("bool", 1, 0x2, LLVMDIFlagPublic) .unwrap() .as_type(), ir::TypeKind::Char => ctx .di_builder - .create_basic_type("char", 1, 6, LLVMDIFlagPublic) + .create_basic_type("char", 8, 0x6, LLVMDIFlagPublic) .unwrap() .as_type(), ir::TypeKind::Int(ty) => match ty { ir::IntTy::I128 => ctx .di_builder - .create_basic_type("i128", 128, 5, LLVMDIFlagPublic) + .create_basic_type("i128", 128, 0x5, LLVMDIFlagPublic) .unwrap() .as_type(), ir::IntTy::I64 => ctx .di_builder - .create_basic_type("i64", 64, 5, LLVMDIFlagPublic) + .create_basic_type("i64", 64, 0x5, LLVMDIFlagPublic) .unwrap() .as_type(), ir::IntTy::I32 => ctx .di_builder - .create_basic_type("i32", 32, 5, LLVMDIFlagPublic) + .create_basic_type("i32", 32, 0x5, LLVMDIFlagPublic) .unwrap() .as_type(), ir::IntTy::I16 => ctx .di_builder - .create_basic_type("i16", 16, 5, LLVMDIFlagPublic) + .create_basic_type("i16", 16, 0x5, LLVMDIFlagPublic) .unwrap() .as_type(), ir::IntTy::I8 => ctx .di_builder - .create_basic_type("i8", 8, 5, LLVMDIFlagPublic) + .create_basic_type("i8", 8, 0x5, LLVMDIFlagPublic) .unwrap() .as_type(), ir::IntTy::Isize => ctx .di_builder - .create_basic_type("isize", 64, 5, LLVMDIFlagPublic) + .create_basic_type("isize", 64, 0x5, LLVMDIFlagPublic) .unwrap() .as_type(), }, ir::TypeKind::Uint(ty) => match ty { ir::UintTy::U128 => ctx .di_builder - .create_basic_type("u128", 128, 7, LLVMDIFlagPublic) + .create_basic_type("u128", 128, 0x7, LLVMDIFlagPublic) .unwrap() .as_type(), ir::UintTy::U64 => ctx .di_builder - .create_basic_type("u64", 64, 7, LLVMDIFlagPublic) + .create_basic_type("u64", 64, 0x7, LLVMDIFlagPublic) .unwrap() .as_type(), ir::UintTy::U32 => ctx .di_builder - .create_basic_type("u32", 32, 7, LLVMDIFlagPublic) + .create_basic_type("u32", 32, 0x7, LLVMDIFlagPublic) .unwrap() .as_type(), ir::UintTy::U16 => ctx .di_builder - .create_basic_type("u16", 16, 7, LLVMDIFlagPublic) + .create_basic_type("u16", 16, 0x7, LLVMDIFlagPublic) .unwrap() .as_type(), ir::UintTy::U8 => ctx .di_builder - .create_basic_type("u8", 8, 7, LLVMDIFlagPublic) + .create_basic_type("u8", 8, 0x7, LLVMDIFlagPublic) .unwrap() .as_type(), ir::UintTy::Usize => ctx .di_builder - .create_basic_type("usize", 64, 7, LLVMDIFlagPublic) + .create_basic_type("usize", 64, 0x7, LLVMDIFlagPublic) .unwrap() .as_type(), }, @@ -1122,5 +1138,15 @@ fn compile_debug_type<'ctx>(ctx: &ModuleCompileCtx<'ctx, '_>, ty: &ir::TypeInfo) ir::TypeKind::FnDef(_def_id, _generic_args) => { panic!() } + ir::TypeKind::Ptr(pointee) => ctx + .di_builder + .create_pointer_type( + &format!("ptr<{:?}>", pointee.kind), + compile_debug_type(ctx, pointee), + (ctx.target_data.get_pointer_byte_size(None) * 8).into(), + ctx.target_data.get_pointer_byte_size(None), + AddressSpace::default(), + ) + .as_type(), } } diff --git a/lib/edlang_driver/tests/programs.rs b/lib/edlang_driver/tests/programs.rs index 371731caf..9c88ce2fc 100644 --- a/lib/edlang_driver/tests/programs.rs +++ b/lib/edlang_driver/tests/programs.rs @@ -7,6 +7,7 @@ mod common; #[test_case(include_str!("programs/simple.ed"), "simple", false, 1, &["a", "b"] ; "simple.ed 3")] #[test_case(include_str!("programs/basic_ifs.ed"), "basic_ifs", false, 9, &[] ; "basic_ifs")] #[test_case(include_str!("programs/while.ed"), "while", false, 10, &[] ; "r#while")] +#[test_case(include_str!("programs/factorial.ed"), "factorial", false, 6, &[] ; "factorial")] fn example_tests(source: &str, name: &str, is_library: bool, status_code: i32, args: &[&str]) { let program = compile_program(source, name, is_library).unwrap(); diff --git a/lib/edlang_driver/tests/programs/factorial.ed b/lib/edlang_driver/tests/programs/factorial.ed new file mode 100644 index 000000000..60f6d6fad --- /dev/null +++ b/lib/edlang_driver/tests/programs/factorial.ed @@ -0,0 +1,14 @@ +mod Main { + pub fn main() -> i32 { + let b: i32 = factorial(3); + return b; + } + + fn factorial(n: i32) -> i32 { + if n == 1 { + return n; + } else { + return n * factorial(n - 1); + } + } +} diff --git a/lib/edlang_ir/src/lib.rs b/lib/edlang_ir/src/lib.rs index a1b617815..91fe5af2d 100644 --- a/lib/edlang_ir/src/lib.rs +++ b/lib/edlang_ir/src/lib.rs @@ -97,6 +97,7 @@ pub struct DebugInfo { pub struct BasicBlock { pub statements: SmallVec<[Statement; 8]>, pub terminator: Terminator, + pub terminator_span: Option, } #[derive(Debug, Clone)] @@ -202,6 +203,7 @@ pub enum TypeKind { Uint(UintTy), Float(FloatTy), FnDef(DefId, Vec), // The vec are generic types, not arg types + Ptr(Box), } impl TypeKind { @@ -232,6 +234,7 @@ impl TypeKind { Self::Float(_) => todo!(), TypeKind::Unit => unreachable!(), TypeKind::FnDef(_, _) => unreachable!(), + TypeKind::Ptr(_pointee) => todo!(), } } } @@ -298,6 +301,7 @@ impl ValueTree { ConstValue::U128(_) => TypeKind::Uint(UintTy::U8), ConstValue::F32(_) => TypeKind::Float(FloatTy::F32), ConstValue::F64(_) => TypeKind::Float(FloatTy::F64), + ConstValue::Char(_) => TypeKind::Char, }, ValueTree::Branch(_) => todo!(), } @@ -428,6 +432,7 @@ pub enum UnOp { #[derive(Debug, Clone, Copy)] pub enum ConstValue { Bool(bool), + Char(char), I8(i8), I16(i16), I32(i32), diff --git a/lib/edlang_lowering/src/lib.rs b/lib/edlang_lowering/src/lib.rs index dc569f1bd..426d0195a 100644 --- a/lib/edlang_lowering/src/lib.rs +++ b/lib/edlang_lowering/src/lib.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use ast::{BinaryOp, ModuleStatement, WhileStmt}; +use ast::{BinaryOp, ModuleStatement, Span, WhileStmt}; use common::{BodyBuilder, BuildCtx}; use edlang_ast as ast; use edlang_ir as ir; @@ -184,6 +184,7 @@ fn lower_while(builder: &mut BodyBuilder, info: &WhileStmt, ret_type: &TypeKind) builder.body.blocks.push(BasicBlock { statements: statements.into(), terminator: Terminator::Target(builder.body.blocks.len() + 1), + terminator_span: Some(info.block.span), }); let (discriminator, discriminator_type) = lower_expr(builder, &info.condition, None); @@ -195,7 +196,7 @@ fn lower_while(builder: &mut BodyBuilder, info: &WhileStmt, ret_type: &TypeKind) }; builder.statements.push(Statement { - span: None, + span: Some(info.span), kind: StatementKind::Assign(place.clone(), discriminator), }); @@ -206,6 +207,7 @@ fn lower_while(builder: &mut BodyBuilder, info: &WhileStmt, ret_type: &TypeKind) builder.body.blocks.push(BasicBlock { statements: statements.into(), terminator: Terminator::Unreachable, + terminator_span: Some(info.block.span), }); // keep idx for switch targets @@ -226,6 +228,7 @@ fn lower_while(builder: &mut BodyBuilder, info: &WhileStmt, ret_type: &TypeKind) builder.body.blocks.push(BasicBlock { statements: statements.into(), terminator: Terminator::Unreachable, + terminator_span: Some(Span::new(info.block.span.hi, info.block.span.hi)), }); Some(idx) } else { @@ -261,7 +264,7 @@ fn lower_if_stmt(builder: &mut BodyBuilder, info: &ast::IfStmt, ret_type: &TypeK }; builder.statements.push(Statement { - span: None, + span: Some(info.span), kind: StatementKind::Assign(place.clone(), condition), }); @@ -272,6 +275,7 @@ fn lower_if_stmt(builder: &mut BodyBuilder, info: &ast::IfStmt, ret_type: &TypeK builder.body.blocks.push(BasicBlock { statements: statements.into(), terminator: Terminator::Unreachable, + terminator_span: Some(info.span), }); // keep idx for switch targets @@ -291,6 +295,7 @@ fn lower_if_stmt(builder: &mut BodyBuilder, info: &ast::IfStmt, ret_type: &TypeK builder.body.blocks.push(BasicBlock { statements: statements.into(), terminator: Terminator::Unreachable, + terminator_span: Some(Span::new(info.then_block.span.hi, info.then_block.span.hi)), }); Some(idx) } else { @@ -314,6 +319,10 @@ fn lower_if_stmt(builder: &mut BodyBuilder, info: &ast::IfStmt, ret_type: &TypeK builder.body.blocks.push(BasicBlock { statements: statements.into(), terminator: Terminator::Unreachable, + terminator_span: info + .else_block + .as_ref() + .map(|x| Span::new(x.span.hi, x.span.hi)), }); Some(idx) } else { @@ -383,7 +392,6 @@ fn find_expr_type(builder: &mut BodyBuilder, info: &ast::Expression) -> Option todo!(), ast::ValueExpr::Path(path) => { // todo: handle full path - dbg!("found local"); builder.get_local(&path.first.name)?.ty.kind.clone() } }, @@ -607,6 +615,7 @@ fn lower_fn_call(builder: &mut BodyBuilder, info: &ast::FnCallExpr) -> (Operand, builder.body.blocks.push(BasicBlock { statements: statements.into(), terminator: kind, + terminator_span: Some(info.span), }); (Operand::Move(dest_place), ret_ty.kind.clone()) @@ -755,7 +764,7 @@ fn lower_return(builder: &mut BodyBuilder, info: &ast::ReturnStmt, return_type: if let Some(value_expr) = &info.value { let (value, _ty) = lower_expr(builder, value_expr, Some(return_type)); builder.statements.push(Statement { - span: None, + span: Some(info.span), kind: StatementKind::Assign( Place { local: builder.ret_local, @@ -770,6 +779,7 @@ fn lower_return(builder: &mut BodyBuilder, info: &ast::ReturnStmt, return_type: builder.body.blocks.push(BasicBlock { statements: statements.into(), terminator: Terminator::Return, + terminator_span: Some(info.span), }); } @@ -789,7 +799,8 @@ fn lower_path(builder: &mut BodyBuilder, info: &ast::PathExpr) -> (ir::Place, Ty ) } -pub fn lower_type(_ctx: &BuildCtx, t: &ast::Type) -> ir::TypeInfo { +#[allow(clippy::only_used_in_recursion)] +pub fn lower_type(ctx: &BuildCtx, t: &ast::Type) -> ir::TypeInfo { match t.name.name.as_str() { "()" => ir::TypeInfo { span: Some(t.span), @@ -835,6 +846,18 @@ pub fn lower_type(_ctx: &BuildCtx, t: &ast::Type) -> ir::TypeInfo { span: Some(t.span), kind: ir::TypeKind::Int(ir::IntTy::I128), }, - _ => todo!(), + "char" => ir::TypeInfo { + span: Some(t.span), + kind: ir::TypeKind::Char, + }, + "bool" => ir::TypeInfo { + span: Some(t.span), + kind: ir::TypeKind::Bool, + }, + "ptr" => ir::TypeInfo { + span: Some(t.span), + kind: ir::TypeKind::Ptr(Box::new(lower_type(ctx, t.generics.first().unwrap()))), + }, + x => todo!("{:?}", x), } } diff --git a/programs/factorial.ed b/programs/factorial.ed new file mode 100644 index 000000000..c7d717845 --- /dev/null +++ b/programs/factorial.ed @@ -0,0 +1,14 @@ +mod Main { + pub fn main() -> i32 { + let b: i32 = factorial(2); + return b; + } + + fn factorial(n: i32) -> i32 { + if n == 1 { + return n; + } else { + return n * factorial(n - 1); + } + } +} diff --git a/programs/ptr.ed b/programs/ptr.ed new file mode 100644 index 000000000..e98648f2f --- /dev/null +++ b/programs/ptr.ed @@ -0,0 +1,12 @@ +mod Main { + + pub fn main(argc: i64, argv: ptr) -> i64 { + let mut a: i64 = 0; + + if argc > 2 { + a = 1; + } + + return a; + } +}