feat: ptr repr

This commit is contained in:
Edgar 2024-02-14 11:21:33 +01:00
parent 1d60bb5482
commit caf3a94eee
No known key found for this signature in database
GPG key ID: 70ADAE8F35904387
7 changed files with 117 additions and 22 deletions

View file

@ -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<PathBuf, Box<
let llvm_module = context.create_module(&module.name);
llvm_module.set_source_file_name(&filename);
llvm_module.set_triple(&triple);
llvm_module.set_data_layout(&machine.get_target_data().get_data_layout());
let (di_builder, di_unit) = llvm_module.create_debug_info_builder(
true,
inkwell::debug_info::DWARFSourceLanguage::Rust,
@ -368,7 +370,7 @@ fn compile_fn(ctx: &ModuleCompileCtx, fn_id: DefId) -> 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(),
}
}

View file

@ -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();

View file

@ -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);
}
}
}

View file

@ -97,6 +97,7 @@ pub struct DebugInfo {
pub struct BasicBlock {
pub statements: SmallVec<[Statement; 8]>,
pub terminator: Terminator,
pub terminator_span: Option<Span>,
}
#[derive(Debug, Clone)]
@ -202,6 +203,7 @@ pub enum TypeKind {
Uint(UintTy),
Float(FloatTy),
FnDef(DefId, Vec<TypeInfo>), // The vec are generic types, not arg types
Ptr(Box<TypeInfo>),
}
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),

View file

@ -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<T
ast::ValueExpr::Str { .. } => 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),
}
}

14
programs/factorial.ed Normal file
View file

@ -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);
}
}
}

12
programs/ptr.ed Normal file
View file

@ -0,0 +1,12 @@
mod Main {
pub fn main(argc: i64, argv: ptr<char>) -> i64 {
let mut a: i64 = 0;
if argc > 2 {
a = 1;
}
return a;
}
}