From fc15b3ff194dfa04753d629990ae82f697ffdc34 Mon Sep 17 00:00:00 2001 From: Vishruth-Thimmaiah Date: Fri, 29 Nov 2024 22:54:49 +0530 Subject: [PATCH] feat: builtin functions imported by default --- examples/ex6.slpe | 4 +-- src/llvm/func.rs | 57 ++++++++++++++++++++++++++++++++---- src/llvm/stdlib_defs.rs | 11 +++++-- stdlib/src/builtin/arrays.rs | 8 ++--- 4 files changed, 66 insertions(+), 14 deletions(-) diff --git a/examples/ex6.slpe b/examples/ex6.slpe index 7d243ea..262e9f9 100644 --- a/examples/ex6.slpe +++ b/examples/ex6.slpe @@ -1,7 +1,7 @@ import std:builtin func main() u32 { - let u32[] a = [1, 2, 3] - let u32 b = builtin:len(a) + let u32[] a = [1, 2, 3, 2] + let u32 b = len(a) return b } diff --git a/src/llvm/func.rs b/src/llvm/func.rs index fff4023..4b1dc79 100644 --- a/src/llvm/func.rs +++ b/src/llvm/func.rs @@ -10,7 +10,10 @@ use crate::{ parser::nodes::{ExpressionParserNode, FunctionCallParserNode, FunctionParserNode, ReturnNode}, }; -use super::codegen::{CodeGen, FunctionStore}; +use super::{ + codegen::{CodeGen, FunctionStore}, + stdlib_defs::get_builtin_function, +}; impl<'ctx> CodeGen<'ctx> { pub fn add_function(&self, node: &FunctionParserNode) { @@ -72,10 +75,7 @@ impl<'ctx> CodeGen<'ctx> { if let Some(func) = get_stdlib_function(&internal_func_name) { func } else { - errors::compiler_error(&format!( - "Function '{}' not found in stdlib", - func_name - )); + errors::compiler_error(&format!("Function '{}' not found in stdlib", func_name)); } } else { todo!("user defined functions are not supported yet"); @@ -108,6 +108,47 @@ impl<'ctx> CodeGen<'ctx> { func } + pub fn def_builtin(&self, func_name: &str) -> Option> { + if let Some(func) = self.module.get_function(func_name) { + if func.get_linkage() == inkwell::module::Linkage::External { + return Some(func); + } + } + let internal_func_name = format!("__builtin__{}", func_name); + + let func_def = if let Some(func_def) = get_builtin_function(&internal_func_name) { + func_def + } else { + return None; + }; + let params = self.def_func_args( + &func_def + .args + .to_vec() + .iter() + .map(|p| (p.0.to_string(), p.1.clone())) + .collect::>(), + ); + + let fn_type = if let Some(expr) = self.def_expr(&func_def.return_type) { + expr.fn_type(¶ms, false) + } else { + self.context.void_type().fn_type(¶ms, false) + }; + + let func = self.module.add_function( + &internal_func_name, + fn_type, + Some(inkwell::module::Linkage::External), + ); + + if let Some(exec_engine) = self.execution_engine.as_ref() { + exec_engine.add_global_mapping(&func, func_def.ptr); + } + + Some(func) + } + pub fn add_func_call( &self, func_node: &FunctionCallParserNode, @@ -115,8 +156,12 @@ impl<'ctx> CodeGen<'ctx> { ) -> BasicValueEnum<'ctx> { let function = if let Some(imported) = &func_node.imported { self.def_extern(&func_node.func_name, imported) + } else if let Some(func) = self.module.get_function(&func_node.func_name) { + func + } else if let Some(func) = self.def_builtin(&func_node.func_name) { + func } else { - self.module.get_function(&func_node.func_name).unwrap() + panic!("Function {} not found", func_node.func_name) }; let mut args = Vec::new(); let params = function.get_params(); diff --git a/src/llvm/stdlib_defs.rs b/src/llvm/stdlib_defs.rs index 56c99c3..352267f 100644 --- a/src/llvm/stdlib_defs.rs +++ b/src/llvm/stdlib_defs.rs @@ -30,9 +30,16 @@ pub fn get_stdlib_function(name: &str) -> Option { return_type: &DATATYPE::NONE, ptr: stdlib::io::__std__io__printflt as usize, }, - "__std__builtin__len" => StdLibFunc { + _ => return None, + }; + Some(func) +} + +pub fn get_builtin_function(name: &str) -> Option { + let func = match name { + "__builtin__len" => StdLibFunc { args: &[("arr", &DATATYPE::U32)], - ptr: stdlib::builtin::arrays::__std__builtin__len as usize, + ptr: stdlib::builtin::arrays::__builtin__len as usize, return_type: &DATATYPE::U64, }, _ => return None, diff --git a/stdlib/src/builtin/arrays.rs b/stdlib/src/builtin/arrays.rs index 0457b52..55858c4 100644 --- a/stdlib/src/builtin/arrays.rs +++ b/stdlib/src/builtin/arrays.rs @@ -1,11 +1,11 @@ #[repr(C)] pub struct Array { pub len: u64, - pub data: *const u32, + pub data: *const u32, } #[no_mangle] -pub extern "C" fn __std__builtin__len(arr: Array) -> u64 { - let len = unsafe { &*(arr.len as *const u64) }; - return *len; +pub extern "C" fn __builtin__len(arr: *const Array) -> u64 { + let deref_arr = unsafe { &*(arr) }; + return deref_arr.len; }