Skip to content

Commit efef0ce

Browse files
committed
Started working on lowering and declaration merging for C function bodies
1 parent f45dc0d commit efef0ce

File tree

9 files changed

+56
-15
lines changed

9 files changed

+56
-15
lines changed

Diff for: src/asg/func.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub struct Func {
99
pub return_type: Type,
1010
pub stmts: Vec<Stmt>,
1111
pub is_foreign: bool,
12+
pub is_exposed: bool,
1213
pub is_generic: bool,
1314
pub vars: VariableStorage,
1415
pub source: Source,

Diff for: src/ast/func/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub struct FuncHead {
1818
pub params: Params,
1919
pub return_type: Type,
2020
pub is_foreign: bool,
21+
pub is_exposed: bool,
2122
pub source: Source,
2223
pub abide_abi: bool,
2324
pub tag: Option<Tag>,

Diff for: src/c/translation/function.rs

+7
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ pub fn declare_function(
7474

7575
match func_info.specifiers.storage_class {
7676
Some(StorageClassSpecifier::Typedef) => {
77+
if body.is_some() {
78+
return Err(
79+
ParseErrorKind::Misc("Cannot typedef function with body").at(declarator.source)
80+
);
81+
}
82+
7783
let ast_type = ast::TypeKind::FuncPtr(ast::FuncPtr {
7884
parameters: required,
7985
return_type: Box::new(func_info.ast_type),
@@ -102,6 +108,7 @@ pub fn declare_function(
102108
},
103109
return_type: func_info.ast_type,
104110
is_foreign: true,
111+
is_exposed: body.is_some(),
105112
source,
106113
abide_abi: true,
107114
tag: None,

Diff for: src/interpreter_env/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ fn thin_void_func(name: impl Into<String>, syscall_kind: InterpreterSyscallKind)
2929
return_type: void.clone(),
3030
abide_abi: false,
3131
is_foreign: false,
32+
is_exposed: false,
3233
source,
3334
tag: None,
3435
privacy: Privacy::Public,
@@ -66,6 +67,7 @@ fn thin_cstring_func(
6667
return_type: void.clone(),
6768
abide_abi: false,
6869
is_foreign: false,
70+
is_exposed: false,
6971
source,
7072
tag: None,
7173
privacy: Privacy::Public,
@@ -111,6 +113,7 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) {
111113
params: Params::default(),
112114
return_type: void.clone(),
113115
is_foreign: false,
116+
is_exposed: false,
114117
source,
115118
abide_abi: false,
116119
tag: Some(Tag::InterpreterEntryPoint),
@@ -230,6 +233,7 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) {
230233
return_type: void.clone(),
231234
abide_abi: false,
232235
is_foreign: false,
236+
is_exposed: false,
233237
source,
234238
tag: None,
235239
privacy: Privacy::Public,
@@ -274,6 +278,7 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) {
274278
return_type: void.clone(),
275279
abide_abi: false,
276280
is_foreign: false,
281+
is_exposed: false,
277282
source,
278283
tag: None,
279284
privacy: Privacy::Public,
@@ -312,6 +317,7 @@ pub fn setup_build_system_interpreter_symbols(file: &mut AstFile) {
312317
return_type: TypeKind::Named(Name::plain("Dependency"), vec![]).at(source),
313318
abide_abi: false,
314319
is_foreign: false,
320+
is_exposed: false,
315321
source,
316322
tag: None,
317323
privacy: Privacy::Public,

Diff for: src/llvm_backend/functions/head.rs

+34-13
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@ use crate::{
1313
};
1414
use cstr::cstr;
1515
use llvm_sys::{
16-
core::{LLVMAddFunction, LLVMFunctionType, LLVMSetFunctionCallConv, LLVMSetLinkage},
16+
core::{
17+
LLVMAddFunction, LLVMFunctionType, LLVMGetNamedFunction, LLVMSetFunctionCallConv,
18+
LLVMSetLinkage,
19+
},
1720
LLVMCallConv, LLVMLinkage,
1821
};
19-
use std::ffi::CString;
22+
use std::{ffi::CString, ptr::null_mut};
2023

2124
pub unsafe fn create_func_heads(ctx: &mut BackendCtx) -> Result<(), BackendError> {
2225
for (func_ref, func) in ctx.ir_module.funcs.iter() {
@@ -62,19 +65,37 @@ pub unsafe fn create_func_heads(ctx: &mut BackendCtx) -> Result<(), BackendError
6265
};
6366

6467
let name = CString::new(func.mangled_name.as_bytes()).unwrap();
65-
let skeleton = LLVMAddFunction(
66-
ctx.backend_module.get(),
67-
name.as_ptr(),
68-
function_type.pointer,
69-
);
70-
LLVMSetFunctionCallConv(skeleton, LLVMCallConv::LLVMCCallConv as u32);
7168

72-
let nounwind = create_enum_attribute(cstr!("nounwind"), 0);
73-
add_func_attribute(skeleton, nounwind);
69+
let existing = if func.is_foreign || func.is_exposed {
70+
LLVMGetNamedFunction(ctx.backend_module.get(), name.as_ptr())
71+
} else {
72+
null_mut()
73+
};
74+
75+
let skeleton = if existing.is_null() {
76+
let skeleton = LLVMAddFunction(
77+
ctx.backend_module.get(),
78+
name.as_ptr(),
79+
function_type.pointer,
80+
);
81+
82+
LLVMSetFunctionCallConv(skeleton, LLVMCallConv::LLVMCCallConv as u32);
7483

75-
if !func.is_foreign && !func.is_exposed {
76-
LLVMSetLinkage(skeleton, LLVMLinkage::LLVMPrivateLinkage);
77-
}
84+
let nounwind = create_enum_attribute(cstr!("nounwind"), 0);
85+
add_func_attribute(skeleton, nounwind);
86+
87+
if !func.is_foreign && !func.is_exposed {
88+
LLVMSetLinkage(skeleton, LLVMLinkage::LLVMPrivateLinkage);
89+
}
90+
91+
skeleton
92+
} else {
93+
if func.is_foreign || func.is_exposed {
94+
LLVMSetLinkage(existing, LLVMLinkage::LLVMExternalLinkage);
95+
}
96+
97+
existing
98+
};
7899

79100
ctx.func_skeletons.insert(
80101
func_ref,

Diff for: src/lower/function.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ pub fn lower_func_head(
115115
};
116116

117117
let is_main = mangled_name == "main";
118-
let is_exposed = is_main;
118+
let is_exposed = func.is_exposed || is_main;
119119

120120
Ok(ir_module.funcs.insert(
121121
func_ref,

Diff for: src/parser/parse_func.rs

+3
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,15 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
2525
let source = self.input.advance().source;
2626

2727
let mut is_foreign = false;
28+
let mut is_exposed = false;
2829
let mut abide_abi = false;
2930
let mut privacy = Privacy::Protected;
3031
let mut givens = vec![];
3132

3233
for annotation in annotations {
3334
match annotation.kind {
3435
AnnotationKind::Foreign => is_foreign = true,
36+
AnnotationKind::Exposed => is_exposed = true,
3537
AnnotationKind::AbideAbi => abide_abi = true,
3638
AnnotationKind::Public => privacy = Privacy::Public,
3739
AnnotationKind::Private => privacy = Privacy::Private,
@@ -81,6 +83,7 @@ impl<'a, I: Inflow<Token>> Parser<'a, I> {
8183
params,
8284
return_type,
8385
is_foreign,
86+
is_exposed,
8487
source,
8588
abide_abi,
8689
tag: None,

Diff for: src/pragma_section/parse.rs

+1
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ impl PragmaSection {
111111
params: Params::default(),
112112
return_type: TypeKind::Void.at(source),
113113
is_foreign: false,
114+
is_exposed: false,
114115
source,
115116
abide_abi: false,
116117
tag: None,

Diff for: src/resolve/func_head.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ pub fn create_func_head<'a>(
117117
params,
118118
return_type,
119119
stmts: vec![],
120-
is_foreign: head.is_foreign,
120+
is_foreign: head.is_foreign && !head.is_exposed,
121+
is_exposed: head.is_exposed,
121122
vars: VariableStorage::new(),
122123
source: head.source,
123124
abide_abi: head.abide_abi,

0 commit comments

Comments
 (0)