diff --git a/bichara b/bichara index 5ed2498..ba16b2a 100755 --- a/bichara +++ b/bichara @@ -15,10 +15,10 @@ elif [ "$1" = "build" ]; then fi OUTPUT_FILE="$2" if ! [ -e "./$OUTPUT_DIR/ir" ]; then mkdir -p "./$OUTPUT_DIR/ir"; fi - cargo run 1> "./$OUTPUT_DIR/ir/$OUTPUT_FILE" + cargo run 1> "./$OUTPUT_DIR/ir/$OUTPUT_FILE.S" if ! [ $? -eq 0 ]; then echo "*** COMPILATION FAILED ***"; exit 2; fi - gcc -o "./$OUTPUT_DIR/output" "./$OUTPUT_DIR/ir/$OUTPUT_FILE" + gcc -o "./$OUTPUT_DIR/ir/$OUTPUT_FILE" "./$OUTPUT_DIR/ir/$OUTPUT_FILE.S" "./$OUTPUT_DIR/ir/"*.c -lm fi \ No newline at end of file diff --git a/examples/input1.bic b/examples/input1.bic index 87a4476..f6604bb 100644 --- a/examples/input1.bic +++ b/examples/input1.bic @@ -1,7 +1,5 @@ -def print_me() -> void { - let a = 222; -} +def extern calculate_sin_5() -> void; def main() -> void { - print_me(); + calculate_sin_5(); } \ No newline at end of file diff --git a/src/code_gen/aarch64/aarch64_codegen.rs b/src/code_gen/aarch64/aarch64_codegen.rs index c660fe6..7d0c02a 100644 --- a/src/code_gen/aarch64/aarch64_codegen.rs +++ b/src/code_gen/aarch64/aarch64_codegen.rs @@ -157,6 +157,10 @@ impl<'aarch64> CodeGen for Aarch64CodeGen<'aarch64> { panic!("Please provide a context to work on!"); }; // function preamble + if func_info.storage_class == StorageClass::EXTERN { + println!(".extern _{}", func_name); + return 0xFFFFFFFF; + } println!(".global _{}\n_{}:", func_name, func_name); println!("sub sp, sp, {}", func_info.stack_size); if let Some(ref body) = ast.left { @@ -381,7 +385,7 @@ impl<'aarch64> CodeGen for Aarch64CodeGen<'aarch64> { if let Some(ctx_rc) = &self.ctx { let ctx_borrow = ctx_rc.borrow_mut(); if let Some(symbol) = ctx_borrow.sym_table.get_symbol(symbol_id) { - println!("call {}", symbol.name); + println!("bl _{}", symbol.name); } } } diff --git a/src/parser/parser_impl.rs b/src/parser/parser_impl.rs index 78c1570..e572928 100644 --- a/src/parser/parser_impl.rs +++ b/src/parser/parser_impl.rs @@ -245,6 +245,18 @@ impl<'parser> Parser<'parser> { self.local_offset = 0; // match and ignore function declaration keyword 'def' _ = self.token_match(TokenKind::KW_DEF); + + // Storage class of the function that is being parsed. + // By default, it is set to 'GLOBAL'. + let mut func_storage_class: StorageClass = StorageClass::GLOBAL; + + // 'def' keyword could be followed by the 'extern' keyword, + // symbolizing the external definition of the function's body. + if self.current_token.kind == TokenKind::KW_EXTERN { + _ = self.token_match(TokenKind::KW_EXTERN); + func_storage_class = StorageClass::EXTERN; + } + let id_token: Token = self.token_match(TokenKind::T_IDENTIFIER).clone(); _ = self.token_match(TokenKind::T_LPAREN); _ = self.token_match(TokenKind::T_RPAREN); @@ -264,7 +276,7 @@ impl<'parser> Parser<'parser> { id_token.lexeme.clone(), func_return_type, SymbolType::Function, - StorageClass::GLOBAL, + func_storage_class, )); // in case the function symbol addition process fails if function_id.is_none() { @@ -274,12 +286,18 @@ impl<'parser> Parser<'parser> { ))); } self.current_function_id = function_id.unwrap(); + let mut function_body: Option = None; // create function body - let function_body_res: ParseResult2 = self.parse_compound_stmt(); - let function_body: AST = match function_body_res { - Ok(ast) => ast, - Err(err) => return Err(err) - }; + if func_storage_class != StorageClass::EXTERN { + let function_body_res: ParseResult2 = self.parse_compound_stmt(); + let __body: AST = match function_body_res { + Ok(ast) => ast, + Err(err) => return Err(err) + }; + function_body = Some(__body); + } else { + _ = self.token_match(TokenKind::T_SEMICOLON); + } let temp_func_id: usize = self.current_function_id; self.current_function_id = INVALID_FUNC_ID; // function parsing done; exiting out of function body // function information collection @@ -289,6 +307,7 @@ impl<'parser> Parser<'parser> { function_id.unwrap(), stack_offset, func_return_type, + func_storage_class ); // create a new FunctionInfo if let Some(ctx_rc) = &mut self.ctx { @@ -304,7 +323,7 @@ impl<'parser> Parser<'parser> { func_id: temp_func_id, })), ASTOperation::AST_FUNCTION, - Some(function_body), + function_body, None, func_return_type, )) diff --git a/src/symbol/function.rs b/src/symbol/function.rs index b5bf70c..472df15 100644 --- a/src/symbol/function.rs +++ b/src/symbol/function.rs @@ -27,6 +27,8 @@ SOFTWARE. use std::collections::HashMap; use crate::types::LitTypeVariant; +use super::StorageClass; + /// Limit of local variables in a function. pub const LOCAL_LIMIT: usize = 1024; @@ -87,17 +89,25 @@ pub struct FunctionInfo { pub stack_size: i32, pub return_type: LitTypeVariant, /// Contains information about the variables defined locally in 'this' function - pub local_syms: LocalSymtable + pub local_syms: LocalSymtable, + pub storage_class: StorageClass } impl FunctionInfo { - pub fn new(name: String, func_id: usize, stack_size: i32, return_type: LitTypeVariant) -> Self { + pub fn new( + name: String, + func_id: usize, + stack_size: i32, + return_type: LitTypeVariant, + storage_class: StorageClass + ) -> Self { Self { name, func_id, stack_size, return_type, - local_syms: LocalSymtable::new() + local_syms: LocalSymtable::new(), + storage_class } } } diff --git a/src/symbol/sym.rs b/src/symbol/sym.rs index ee4abfc..e85c9cc 100644 --- a/src/symbol/sym.rs +++ b/src/symbol/sym.rs @@ -35,9 +35,17 @@ pub enum SymbolType { #[derive(Copy, Clone, PartialEq, Debug)] pub enum StorageClass { - GLOBAL, // globally visible symbol - LOCAL, // locally visible symbol - PARAM, // locally visible function parameter + /// Globally visible symbol. + GLOBAL, + + /// Locally visible symbol. + LOCAL, + + /// Locally visible function parameter. + PARAM, + + /// Externally defined symbol. + EXTERN } #[derive(Clone, PartialEq, Debug)]