Skip to content

Commit

Permalink
analyzing function declaration and function calls
Browse files Browse the repository at this point in the history
  • Loading branch information
rigel-star committed Nov 2, 2024
1 parent a18e1a9 commit fd8f5f2
Show file tree
Hide file tree
Showing 15 changed files with 424 additions and 333 deletions.
10 changes: 9 additions & 1 deletion src/ast/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,13 @@ pub struct WidenExpr {

#[derive(Clone, Debug)]
pub struct IdentExpr {
#[deprecated]
pub symtbl_pos: usize, // position in the symbol table

/// Name of the symbol
pub sym_name: String,

/// Result type of the symbol
pub result_type: LitTypeVariant
}

Expand All @@ -42,7 +48,9 @@ pub struct SubscriptExpr {

#[derive(Clone, Debug)]
pub struct FuncCallExpr {
pub symtbl_pos: usize, // position of the function being called in the symbol table,
/// Name of the called function
pub symbol_name: String,

pub result_type: LitTypeVariant, // function return type
// args
pub args: Vec<Expr>
Expand Down
21 changes: 20 additions & 1 deletion src/ast/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,40 @@ pub struct ReturnStmt {
#[derive(Clone, Debug)]
pub struct VarDeclStmt {
pub symtbl_pos: usize, // position of this symbol in the symbol table

/// Name of the symbol
pub sym_name: String,

pub class: StorageClass
}

#[derive(Clone, Debug)]
pub struct ArrVarDeclStmt {
pub symtbl_pos: usize,

/// Name of the symbol
pub sym_name: String,

pub class: StorageClass,
pub vals: Vec<Expr>
}

#[derive(Clone, Debug)]
pub struct AssignStmt {
pub symtbl_pos: usize
#[deprecated]
pub symtbl_pos: usize,

/// Name of the symbol
pub sym_name: String
}

#[derive(Clone, Debug)]
pub struct FuncCallStmt {
#[deprecated]
pub symtbl_pos: usize,

pub symbol_name: String,

pub args: Vec<Expr>
}

Expand All @@ -50,5 +66,8 @@ pub enum Stmt {
Assignment(AssignStmt),
VarDecl(VarDeclStmt),
LValue(usize), // usize for symbol table position of this left value
LValue2 {
name: String
},
FuncCall(FuncCallStmt),
}
41 changes: 5 additions & 36 deletions src/code_gen/aarch64/aarch64_codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ impl<'aarch64> CodeGen for Aarch64CodeGen<'aarch64> {
};

let func_name: String = if let Some(ctx_rc) = &mut self.ctx {
let ctx_borrow: std::cell::Ref<CompilerCtx<'aarch64>> = ctx_rc.borrow();
let ctx_borrow = ctx_rc.borrow();
let func_name: String = ctx_borrow.sym_table.get_symbol(index).unwrap().name.clone();
if let Some(finfo) = ctx_borrow.func_table.get(&func_name) {
self.current_function = Some(finfo.clone());
Expand All @@ -219,6 +219,7 @@ impl<'aarch64> CodeGen for Aarch64CodeGen<'aarch64> {
};

let func_info: FunctionInfo = self.current_function.as_ref().cloned().unwrap();
self.ctx.as_ref().unwrap().borrow_mut().switch_to_func_scope(func_info.func_id);

// If the function is declared as extern, print its external linkage
// declaration and return a placeholder value indicating an unresolved
Expand Down Expand Up @@ -250,14 +251,15 @@ impl<'aarch64> CodeGen for Aarch64CodeGen<'aarch64> {
}

if let Some(ref body) = ast.left {
_ = self.gen_code_from_ast(body, 0xFFFFFFFF, ast.operation)?;
self.gen_code_from_ast(body, 0xFFFFFFFF, ast.operation)?;
if self.early_return_label_id != NO_REG {
println!("_L{}:", self.early_return_label_id);
self.early_return_label_id = NO_REG; // reset early return label after function code generation
}
}

self.current_function = None;
self.ctx.as_ref().unwrap().borrow_mut().switch_to_global_scope();

// ldp -> Load Pair of Registers
// Restore the saved frame pointer (x29) and link register (x30) from the stack.
Expand Down Expand Up @@ -490,38 +492,6 @@ impl<'aarch64> CodeGen for Aarch64CodeGen<'aarch64> {
self.reg_manager.borrow_mut()
}

fn gen_func_call_stmt(&mut self, func_call_stmt: &FuncCallStmt) -> CodeGenResult {
let func_info: FunctionInfo = if let Some(ctx_rc) = &self.ctx {
let ctx_borrow = ctx_rc.borrow();
if let Some(symbol) = ctx_borrow.sym_table.get_symbol(func_call_stmt.symtbl_pos) {
if let Some(func_info) = ctx_borrow.func_table.get(&symbol.name) {
func_info.clone()
} else {
panic!("function info not found");
}
} else {
panic!("undefined symbol");
}
} else {
return Err(CodeGenErr::NoContext);
};
// Assign the function id whenever generating code for function
self.function_id = func_info.func_id;
let args: &Vec<crate::ast::Expr> = &func_call_stmt.args;
let mut used_regs: Vec<AllocedReg> = Vec::<AllocedReg>::new();
for expr in args {
let used_reg: AllocedReg = self.gen_expr(expr, ASTOperation::AST_FUNC_CALL, 0xFFFFFFFF, ASTOperation::AST_NONE)?;
used_regs.push(used_reg);
}
let mut _reg_mgr = self.reg_manager.borrow_mut();
for ar in used_regs {
_reg_mgr.deallocate(ar.idx, &ar.lit_type());
}
println!("bl _{}", func_info.name);
self.function_id = 0xFFFFFFFF;
Ok(AllocedReg::no_reg())
}

fn gen_local_var_decl_stmt(&mut self, var_decl_stmt: &crate::ast::VarDeclStmt, expr_ast: &Expr) -> CodeGenResult {
if self.current_function.is_none() {
panic!("Parsing a local variable but function is not defined... Weird.");
Expand Down Expand Up @@ -572,7 +542,7 @@ impl<'aarch64> CodeGen for Aarch64CodeGen<'aarch64> {
fn gen_func_call_expr(&mut self, func_call_expr: &crate::ast::FuncCallExpr) -> CodeGenResult {
let func_info_res: Option<FunctionInfo> = if let Some(ctx_rc) = &self.ctx {
let ctx_borrow = ctx_rc.borrow_mut();
if let Some(symbol) = ctx_borrow.sym_table.get_symbol(func_call_expr.symtbl_pos) {
if let Ok(symbol) = ctx_borrow.find_sym(&func_call_expr.symbol_name) {
ctx_borrow.func_table.get(&symbol.name).cloned()
} else {
None
Expand Down Expand Up @@ -765,7 +735,6 @@ impl<'aarch64> Aarch64CodeGen<'aarch64> {
}

fn __allocate_reg(&mut self, val_type: &LitTypeVariant) -> AllocedReg {
println!("{:?}", val_type);
let alloced_reg: RegAllocResult = self.reg_manager.borrow_mut().allocate(val_type);
if alloced_reg.is_err() {
panic!("Couldn't allocate register");
Expand Down
1 change: 1 addition & 0 deletions src/code_gen/cg_error.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#[derive(Debug)]
pub enum CodeGenErr {
NoContext,
UndefinedSymbol
Expand Down
25 changes: 6 additions & 19 deletions src/code_gen/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ use crate::ast::AssignStmt;
use crate::ast::BinExpr;
use crate::ast::Expr;
use crate::ast::FuncCallExpr;
use crate::ast::FuncCallStmt;
use crate::ast::LitValExpr;
use crate::ast::Stmt;
use crate::ast::VarDeclStmt;
Expand Down Expand Up @@ -135,28 +134,15 @@ pub trait CodeGen {
}
else if ast_node.operation == ASTOperation::AST_GLUE {
if let Some(left) = ast_node.left.as_ref() {
_ = self.gen_code_from_ast(left, reg, parent_ast_kind);
self.gen_code_from_ast(left, reg, parent_ast_kind)?;
self.reg_manager().deallocate_all();
}
if let Some(right) = ast_node.right.as_ref() {
_ = self.gen_code_from_ast(right, reg, parent_ast_kind);
self.gen_code_from_ast(right, reg, parent_ast_kind)?;
self.reg_manager().deallocate_all();
}
Ok(AllocedReg::no_reg())
}
else if ast_node.operation == ASTOperation::AST_FUNC_CALL {
if ast_node.result_type == LitTypeVariant::Void {
if let ASTKind::StmtAST(func_call_stmt) = &ast_node.kind {
match func_call_stmt {
Stmt::FuncCall(func_call) => {
return self.gen_func_call_stmt(func_call);
},
_ => return Ok(AllocedReg::no_reg())
}
}
}
Ok(AllocedReg::no_reg())
}
else if ast_node.operation == ASTOperation::AST_RETURN {
let early_return = parent_ast_kind != ASTOperation::AST_FUNCTION;
let possible_ret_stmt: Stmt = ast_node.kind.clone().unwrap_stmt();
Expand Down Expand Up @@ -259,7 +245,10 @@ pub trait CodeGen {
crate::ast::ASTKind::Empty => Ok(AllocedReg::no_reg())
}
},
Expr::FuncCall(func_call) => self.gen_func_call_expr(func_call),
Expr::FuncCall(func_call) => {
println!("{:?}", expr);
self.gen_func_call_expr(func_call)
},
_ => Ok(AllocedReg::no_reg())
}
}
Expand Down Expand Up @@ -372,8 +361,6 @@ pub trait CodeGen {

fn gen_return_stmt(&mut self, early_return: bool) -> CodeGenResult;

fn gen_func_call_stmt(&mut self, func_call_stmt: &FuncCallStmt) -> CodeGenResult;

fn gen_func_call_expr(&mut self, func_call_expr: &FuncCallExpr) -> CodeGenResult;

fn gen_local_var_decl_stmt(&mut self, var_decl_stmt: &VarDeclStmt, expr_ast: &Expr) -> CodeGenResult;
Expand Down
1 change: 1 addition & 0 deletions src/code_gen/reg/register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub type RegIdx = usize;

pub const INVALID_REG_IDX: usize = 0xFFFFFFFF;

#[derive(Debug)]
pub struct AllocedReg {
pub size: RegSize,
pub idx: RegIdx
Expand Down
98 changes: 96 additions & 2 deletions src/context/compiler_ctx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,22 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

use crate::{ast::SourceFile, FunctionInfoTable, Symbol, Symtable};
use crate::{
ast::SourceFile,
FunctionInfo,
FunctionInfoTable,
Symbol,
Symtable,
INVALID_FUNC_ID
};

use super::CtxError;

#[derive(Debug, Eq, PartialEq)]
pub enum CompilerScope {
GLOBAL,
FUNCTION
}

#[derive(Debug)]
pub struct CompilerCtx<'ctx> {
Expand All @@ -38,6 +53,10 @@ pub struct CompilerCtx<'ctx> {

/// Source file that is currently being processed.
pub current_file: Option<&'ctx SourceFile>,

pub current_function: usize,

pub scope: CompilerScope
}

impl<'ctx> CompilerCtx<'ctx> {
Expand All @@ -47,10 +66,85 @@ impl<'ctx> CompilerCtx<'ctx> {
func_table,
label_id: 0,
current_file: None,
current_function: INVALID_FUNC_ID,
scope: CompilerScope::GLOBAL
}
}

pub fn incr_label_count(&mut self) {
self.label_id += 1;
}
}

pub fn get_curr_func(&self) -> Option<&FunctionInfo> {
if let Some(symbol) = self.sym_table.get_symbol(self.current_function) {
if let Some(func_info) = self.func_table.get(&symbol.name) {
return Some(func_info);
}
}
None
}

pub fn get_curr_func_mut(&mut self) -> Option<&mut FunctionInfo> {
if let Some(symbol) = self.sym_table.get_symbol(self.current_function) {
if let Some(func_info) = self.func_table.get_mut(&symbol.name) {
return Some(func_info);
}
}
None
}

pub fn switch_to_func_scope(&mut self, func_id: usize) {
self.current_function = func_id;
self.scope = CompilerScope::FUNCTION;
}

pub fn switch_to_global_scope(&mut self) {
self.current_function = INVALID_FUNC_ID;
self.scope = CompilerScope::GLOBAL;
}

pub fn find_sym(&self, name: &str) -> Result<&Symbol, CtxError> {
if let Some(func_info) = self.get_curr_func() {
if let Some(sym_pos) = func_info.local_syms.find_symbol(name) {
if let Some(sym) = func_info.local_syms.get_symbol(sym_pos) {
return Ok(sym);
}
}
}
return self.find_sym_in_table(name, self.sym_table);
}

fn find_sym_in_table<'a>(&'a self, name: &str, table: &'a Symtable<Symbol>) -> Result<&Symbol, CtxError> {
if let Some(sym_pos) = table.find_symbol(name) {
return if let Some(sym) = table.get_symbol(sym_pos) {
Ok(sym)
} else {
Err(CtxError::UndefinedSymbol)
};
}
Err(CtxError::UndefinedSymbol)
}

pub fn find_sym_mut(&mut self, name: &str) -> Result<&mut Symbol, CtxError> {
if let Some(local_sym_pos) = {
if let Some(func_info) = self.get_curr_func_mut() {
func_info.local_syms.find_symbol(name)
} else {
None
}
} {
if let Some(func_mut) = self.get_curr_func_mut() {
if let Some(mut_sym) = func_mut.local_syms.get_symbol_mut(local_sym_pos) {
return Ok(mut_sym);
}
}
} else if let Some(sym_pos) = self.sym_table.find_symbol(name) {
if let Some(sym) = self.sym_table.get_symbol_mut(sym_pos) {
return Ok(sym);
} else {
return Err(CtxError::UndefinedSymbol);
}
}
Err(CtxError::UndefinedSymbol)
}
}
3 changes: 3 additions & 0 deletions src/context/ctx_error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub enum CtxError {
UndefinedSymbol
}
4 changes: 3 additions & 1 deletion src/context/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod compiler_ctx;
mod ctx_error;

pub use compiler_ctx::*;
pub use compiler_ctx::*;
pub use ctx_error::*;
6 changes: 3 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ fn main() {
let ctx: Rc<RefCell<CompilerCtx>> = Rc::new(RefCell::new(CompilerCtx::new(&mut symt, &mut funct)));

// semantic analyzer
let s_analyzer: SemanticAnalyzer = SemanticAnalyzer::new(Rc::clone(&ctx));
let mut s_analyzer: SemanticAnalyzer = SemanticAnalyzer::new(Rc::clone(&ctx));

// register manager
let rm: RefCell<Aarch64RegManager> = RefCell::new(Aarch64RegManager::new());
Expand All @@ -88,9 +88,9 @@ fn main() {
for sf in &mut source_files {
let tokens: Vec<tokenizer::Token> = sf.tokens.clone().unwrap();
ctx.borrow_mut().current_file = Some(sf);
let parse_result: Vec<ast::AST> = parser_borrow.parse_with_ctx(Rc::clone(&ctx), tokens);
let mut parse_result: Vec<ast::AST> = parser_borrow.parse_with_ctx(Rc::clone(&ctx), tokens);

s_analyzer.start_analysis(&parse_result);
s_analyzer.start_analysis(&mut parse_result);

if !parser_borrow.has_parsing_errors() {
cg.gen_with_ctx(Rc::clone(&ctx), &parse_result);
Expand Down
Loading

0 comments on commit fd8f5f2

Please sign in to comment.