feat: allow extern fns

This commit is contained in:
Edgar 2024-02-28 09:53:58 +01:00
parent dd7b949a44
commit 3872c0128b
No known key found for this signature in database
GPG key ID: 70ADAE8F35904387
7 changed files with 111 additions and 52 deletions

33
Cargo.lock generated
View file

@ -355,6 +355,7 @@ name = "edlang_ir"
version = "0.0.1-alpha.10"
dependencies = [
"edlang_span",
"educe",
"smallvec",
]
@ -392,6 +393,18 @@ dependencies = [
name = "edlang_span"
version = "0.0.1-alpha.10"
[[package]]
name = "educe"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4bd92664bf78c4d3dba9b7cdafce6fa15b13ed3ed16175218196942e99168a8"
dependencies = [
"enum-ordinalize",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "either"
version = "1.10.0"
@ -407,6 +420,26 @@ dependencies = [
"log",
]
[[package]]
name = "enum-ordinalize"
version = "4.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5"
dependencies = [
"enum-ordinalize-derive",
]
[[package]]
name = "enum-ordinalize-derive"
version = "4.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "equivalent"
version = "1.0.1"

View file

@ -140,7 +140,7 @@ pub struct Function {
pub is_public: bool,
pub params: Vec<FnParam>,
pub return_type: Option<Type>,
pub body: Block,
pub body: Option<Block>,
pub span: Span,
}

View file

@ -223,9 +223,7 @@ fn compile_fn_signature(ctx: &ModuleCompileCtx<'_, '_>, fn_id: DefId) {
let fn_value = ctx.module.add_function(
&body.get_mangled_name(),
fn_type,
Some(if body.is_extern {
inkwell::module::Linkage::AvailableExternally
} else if body.is_pub {
Some(if body.is_pub || body.is_extern {
inkwell::module::Linkage::External
} else {
inkwell::module::Linkage::Private
@ -261,7 +259,7 @@ fn compile_fn_signature(ctx: &ModuleCompileCtx<'_, '_>, fn_id: DefId) {
line as u32 + 1,
di_type,
body.is_pub,
true,
!body.is_extern,
line as u32 + 1,
0,
false,
@ -271,6 +269,11 @@ fn compile_fn_signature(ctx: &ModuleCompileCtx<'_, '_>, fn_id: DefId) {
fn compile_fn(ctx: &ModuleCompileCtx, fn_id: DefId) -> Result<(), BuilderError> {
let body = ctx.ctx.program.functions.get(&fn_id).unwrap();
if body.is_extern {
return Ok(());
}
trace!("compiling fn body: {}", body.name);
let fn_value = ctx.module.get_function(&body.get_mangled_name()).unwrap();

View file

@ -15,3 +15,4 @@ repository = "https://github.com/edg-l/edlang"
[dependencies]
edlang_span = { version = "0.0.1-alpha.10", path = "../edlang_span" }
smallvec = "1.13.1"
educe = "0.5.11"

View file

@ -6,6 +6,7 @@ use std::{
};
use edlang_span::Span;
use educe::Educe;
use smallvec::SmallVec;
pub mod scalar_int;
@ -91,6 +92,10 @@ impl Body {
}
pub fn get_mangled_name(&self) -> String {
if self.is_extern {
return self.name.clone();
}
if self.name == "main" {
"main".to_string()
} else {
@ -221,8 +226,10 @@ pub struct SwitchTarget {
pub targets: Vec<usize>,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Debug, Clone, Educe, Eq, PartialOrd, Ord)]
#[educe(PartialEq)]
pub struct TypeInfo {
#[educe(PartialEq(ignore))]
pub span: Option<Span>,
pub kind: TypeKind,
}

View file

@ -170,60 +170,61 @@ fn lower_function(
.unwrap()
.clone();
// store args ret
if func.body.is_some() && !func.is_extern {
// store args ret
builder.ret_local = builder.body.locals.len();
builder.body.locals.push(Local::new(
None,
LocalKind::ReturnPointer,
ret_ty.clone(),
None,
false,
));
for (arg, ty) in func.params.iter().zip(args_ty) {
builder
.name_to_local
.insert(arg.name.name.clone(), builder.body.locals.len());
builder.ret_local = builder.body.locals.len();
builder.body.locals.push(Local::new(
Some(arg.name.span),
LocalKind::Arg,
ty,
Some(arg.name.name.clone()),
None,
LocalKind::ReturnPointer,
ret_ty.clone(),
None,
false,
));
}
// Get all user defined locals
for stmt in &func.body.body {
if let ast::Statement::Let(info) = stmt {
let ty = lower_type(&builder.ctx, &info.r#type, builder.local_module)?;
for (arg, ty) in func.params.iter().zip(args_ty) {
builder
.name_to_local
.insert(info.name.name.clone(), builder.body.locals.len());
.insert(arg.name.name.clone(), builder.body.locals.len());
builder.body.locals.push(Local::new(
Some(info.name.span),
LocalKind::Temp,
Some(arg.name.span),
LocalKind::Arg,
ty,
Some(info.name.name.clone()),
info.is_mut,
Some(arg.name.name.clone()),
false,
));
}
}
for stmt in &func.body.body {
lower_statement(&mut builder, stmt, &ret_ty)?;
}
// Get all user defined locals
for stmt in &func.body.as_ref().unwrap().body {
if let ast::Statement::Let(info) = stmt {
let ty = lower_type(&builder.ctx, &info.r#type, builder.local_module)?;
builder
.name_to_local
.insert(info.name.name.clone(), builder.body.locals.len());
builder.body.locals.push(Local::new(
Some(info.name.span),
LocalKind::Temp,
ty,
Some(info.name.name.clone()),
info.is_mut,
));
}
}
if !builder.statements.is_empty() {
let statements = std::mem::take(&mut builder.statements);
builder.body.blocks.push(BasicBlock {
statements: statements.into(),
terminator: Terminator::Return,
terminator_span: None,
});
}
for stmt in &func.body.as_ref().unwrap().body {
lower_statement(&mut builder, stmt, &ret_ty)?;
}
if !builder.statements.is_empty() {
let statements = std::mem::take(&mut builder.statements);
builder.body.blocks.push(BasicBlock {
statements: statements.into(),
terminator: Terminator::Return,
terminator_span: None,
});
}
}
let (mut ctx, body) = (builder.ctx, builder.body);
ctx.unresolved_function_signatures.remove(&body.def_id);
ctx.body.functions.insert(body.def_id, body);
@ -478,6 +479,8 @@ fn lower_assign(builder: &mut BodyBuilder, info: &ast::AssignStmt) -> Result<(),
kind: ty,
};
dbg!("here1");
for _ in 0..info.deref_times {
match &ty.kind {
TypeKind::Ptr(is_mut, inner) => {
@ -497,8 +500,12 @@ fn lower_assign(builder: &mut BodyBuilder, info: &ast::AssignStmt) -> Result<(),
place.projection.push(PlaceElem::Deref);
}
dbg!("here2");
let (rvalue, _ty, _span) = lower_expr(builder, &info.value, Some(&ty))?;
dbg!("here3");
builder.statements.push(Statement {
span: Some(info.name.first.span),
kind: StatementKind::Assign(place, rvalue),
@ -1062,8 +1069,6 @@ fn lower_return(
let (value, ty, span) = lower_expr(builder, value_expr, Some(return_type))?;
if return_type.kind != ty {
dbg!("here");
dbg!(value);
return Err(LoweringError::UnexpectedType {
span,
found: ty,

View file

@ -420,14 +420,24 @@ pub(crate) FnParam: ast::FnParam = {
}
pub(crate) Function: ast::Function = {
<lo:@L> <is_public:"pub"?> <is_extern:"extern"?> "fn" <name:Ident> "(" <params:Comma<FnParam>> ")"
<return_type:("->" <Type>)?> <body:Block> <hi:@R> => ast::Function {
<lo:@L> <is_public:"pub"?> "extern" "fn" <name:Ident> "(" <params:Comma<FnParam>> ")"
<return_type:("->" <Type>)?> ";" <hi:@R> => ast::Function {
is_public: is_public.is_some(),
is_extern: is_extern.is_some(),
is_extern: true,
name,
params,
return_type,
body,
body: None,
span: ast::Span::new(lo, hi),
},
<lo:@L> <is_public:"pub"?> "fn" <name:Ident> "(" <params:Comma<FnParam>> ")"
<return_type:("->" <Type>)?> <body:Block> <hi:@R> => ast::Function {
is_public: is_public.is_some(),
is_extern: false,
name,
params,
return_type,
body: Some(body),
span: ast::Span::new(lo, hi),
}
}