diff --git a/src/ast.rs b/src/ast.rs index b0786e3..c79e7ff 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -147,7 +147,9 @@ impl ASTTraverser { _ => panic!("Not a valid symbol table indexing method") }; println!("{}:", self.sym_table.borrow().get_symbol(index).name); - self.gen_ast((*ast.left).as_ref().unwrap(), 0xFFFFFFFF, ast.operation); + if let Some(body) = &*ast.left { + self.gen_ast(body, 0xFFFFFFFF, ast.operation); + } println!("mov x0, 0"); 0xFFFFFFFF } @@ -204,13 +206,13 @@ impl ASTTraverser { } fn gen_add(&mut self, r1: usize, r2: usize) -> usize { - println!("add {}, {}, {}\n", self.reg_manager.borrow().name(r1), self.reg_manager.borrow().name(r1), self.reg_manager.borrow().name(r2)); + println!("add {}, {}, {}", self.reg_manager.borrow().name(r1), self.reg_manager.borrow().name(r1), self.reg_manager.borrow().name(r2)); self.reg_manager.borrow_mut().deallocate(r2); r1 } fn gen_sub(&mut self, r1: usize, r2: usize) -> usize { - println!("sub {}, {}, {}\n", self.reg_manager.borrow().name(r1), self.reg_manager.borrow().name(r1), self.reg_manager.borrow().name(r2)); + println!("sub {}, {}, {}", self.reg_manager.borrow().name(r1), self.reg_manager.borrow().name(r1), self.reg_manager.borrow().name(r2)); self.reg_manager.borrow_mut().deallocate(r2); r1 } @@ -246,15 +248,24 @@ impl ASTTraverser { fn gen_load_reg_into_gid(&mut self, reg: usize, id: &LitType) -> usize { let reg_name: String = self.reg_manager.borrow().name(reg); - let sym: String = match id { - LitType::I32(int_id) => self.sym_table.borrow().get_symbol(*int_id as usize).name.clone(), - LitType::String(_id) => _id.clone(), - _ => String::from(""), + let mut offset: usize = 0; + match id { + LitType::I32(index) => { + for (idx, symbol) in self.sym_table.borrow().iter().enumerate() { + if idx == *index as usize { break; } + if symbol.sym_type == SymbolType::Variable { + offset += 4; + } + } + }, + _ => panic!("Not supported indexing type!") }; let addr_reg: usize = self.reg_manager.borrow_mut().allocate(); let addr_reg_name: String = self.reg_manager.borrow().name(addr_reg); - println!("ldr {}, ={}\nstr {}, [{}]", addr_reg_name, sym, reg_name, addr_reg_name); - 0 + println!("adrp {}, .L2+{}@PAGE", addr_reg_name, offset); + println!("add {}, {}, .L2+{}@PAGEOFF", &addr_reg_name, addr_reg_name, offset); + println!("str {}, [{}]", reg_name, addr_reg_name); + addr_reg } fn get_next_label(&mut self) -> usize { diff --git a/src/main.rs b/src/main.rs index 2b59836..cf265a5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,7 +35,7 @@ pub mod register; pub mod types; fn main() { - let mut tokener: tokenizer::Tokenizer = tokenizer::Tokenizer::new("global int main; global int a; a = abc();"); + let mut tokener: tokenizer::Tokenizer = tokenizer::Tokenizer::new("global int a; a = 4 + 5; global int b; b = 4;"); let tokens: Vec = tokener.start_scan(); let reg_manager: Rc> = Rc::new(RefCell::new(register::RegisterManager::new())); let sym_table: Rc> = Rc::new(RefCell::new(symtable::Symtable::new())); diff --git a/src/parser.rs b/src/parser.rs index a2b4b09..0124283 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -47,14 +47,27 @@ impl<'a> Parser<'a> { } pub fn start(&mut self, traverser: &mut ASTTraverser) { - // first, parse the globals - self.parse_globals(); - // main code starts from here - println!(".text"); + let mut nodes: Vec = vec![]; loop { if self.current_token.kind == TokenKind::T_EOF { break; } - if let Some(stmt) = &self.parse_single_stmt() { - traverser.traverse(stmt); + if let Some(stmt) = self.parse_single_stmt() { + nodes.push(stmt); + } + } + self.dump_globals(); + // .text section starts from here + println!("\n.text"); + for node in &nodes { + traverser.traverse(node); + } + println!("mov x0, 0\nmov x16, 1\nsvc 0x80"); + } + + fn dump_globals(&self) { + println!(".data\n\t.align 2\n.L2:"); + for symbol in self.sym_table.borrow().iter() { + if symbol.sym_type == SymbolType::Variable { + println!("\t.word 0"); } } } @@ -62,14 +75,9 @@ impl<'a> Parser<'a> { fn parse_single_stmt(&mut self) -> Option { match self.current_token.kind { TokenKind::KW_GLOBAL => { - // ignore globals as they are already parsed - self.jump_past(TokenKind::T_SEMICOLON); + self.parse_global_variable_decl_stmt(); None }, - TokenKind::KW_LOCAL => { - self.parse_local_variable_decl_stmt(); - Some(ASTNode::make_leaf(ASTNodeKind::AST_INTLIT, LitType::I32(12), LitType::I32(0))) - }, TokenKind::T_IDENTIFIER => self.parse_assignment_stmt(), TokenKind::KW_IF => self.parse_if_stmt(), TokenKind::KW_WHILE => self.parse_while_stmt(), @@ -81,21 +89,6 @@ impl<'a> Parser<'a> { } } - // This function parses tokens starting from 'KW_GLOBAL' to the next 'T_SEMICOLON'. - fn parse_globals(&mut self) { - println!(".data"); - loop { - match self.current_token.kind { - TokenKind::KW_GLOBAL => self.parse_global_variable_decl_stmt(), - TokenKind::T_EOF => break, - _ => self.skip_to_next_token() - } - } - // reinit the parser to its starting state - self.current_token = &self.tokens[0]; - self.current = 0; - } - // parse compound statement(statement starting with '{' and ending with '}') fn parse_compound_stmt(&mut self) -> Option { _ = self.token_match(TokenKind::T_LBRACE); @@ -186,14 +179,15 @@ impl<'a> Parser<'a> { fn parse_assignment_stmt(&mut self) -> Option { let id_token: Token = self.token_match(TokenKind::T_IDENTIFIER).clone(); - if self.sym_table.borrow().find_symbol(&id_token.lexeme) == 0xFFFFFFFF { // if the symbol has not been defined + let _id_index_symt: usize = self.sym_table.borrow().find_symbol(&id_token.lexeme); + if _id_index_symt == 0xFFFFFFFF { // if the symbol has not been defined panic!("Assigning to an undefined symbol '{}'", id_token.lexeme); } _ = self.token_match(TokenKind::T_EQUAL); let bin_expr_node: Option = self.parse_equality(); let _result_type: LitType = bin_expr_node.as_ref().unwrap().result_type.clone(); _ = self.token_match(TokenKind::T_SEMICOLON); - let lvalueid: ASTNode = ASTNode::make_leaf(ASTNodeKind::AST_LVIDENT, LitType::String(id_token.lexeme), LitType::String(String::from(""))); + let lvalueid: ASTNode = ASTNode::make_leaf(ASTNodeKind::AST_LVIDENT, LitType::I32(_id_index_symt as i32), LitType::String(String::from(""))); Some(ASTNode::new(ASTNodeKind::AST_ASSIGN, bin_expr_node, Some(lvalueid), None, _result_type)) } @@ -201,13 +195,10 @@ impl<'a> Parser<'a> { _ = self.token_match(TokenKind::KW_GLOBAL); // let mut sym: MaybeUninit = MaybeUninit::::uninit(); let mut sym: Symbol = Symbol::new(String::from(""), LitType::I32(0), SymbolType::Variable); - let mut data_size: i32 = 4; match self.current_token.kind { TokenKind::KW_INT => (), - | TokenKind::KW_CHAR => { - data_size = 2; - sym.lit_type = LitType::U8(0); - }, + | TokenKind::KW_CHAR => sym.lit_type = LitType::U8(0), + TokenKind::T_LONG_NUM => sym.lit_type = LitType::I64(0), _ => panic!("Can't create variable of type {:?}", self.current_token.kind) } self.skip_to_next_token(); @@ -215,14 +206,6 @@ impl<'a> Parser<'a> { sym.name = id_token.lexeme.clone(); _ = self.token_match(TokenKind::T_SEMICOLON); self.sym_table.borrow_mut().add_symbol(sym); // track the symbol that has been defined - println!("{}: .space {} // int {};", id_token.lexeme, data_size, id_token.lexeme); - } - - fn parse_local_variable_decl_stmt(&mut self) { - _ = self.token_match(TokenKind::KW_LOCAL); - _ = self.token_match(TokenKind::KW_INT); - let _id_token: Token = self.token_match(TokenKind::T_IDENTIFIER).clone(); - _ = self.token_match(TokenKind::T_SEMICOLON); } fn parse_equality(&mut self) -> Option { @@ -253,15 +236,11 @@ impl<'a> Parser<'a> { let id_type: LitType = possible_id_node.clone().unwrap().value.unwrap(); match id_type { LitType::I32(id_idx) => { - if id_idx as usize == 0xFFFFFFFF { - panic!("Undefined symbol!"); - } let symbol: Symbol = self.sym_table.borrow().get_symbol(id_idx as usize).clone(); - (id_idx, symbol.lit_type.clone()) + (id_idx as usize, symbol.lit_type.clone()) }, - _ => panic!("{:?}", id_type) - }; - (0, LitType::None) + _ => panic!("parse_func_call_expr: {:?}", id_type) + } }; self.token_match(TokenKind::T_RPAREN); // match and ignore ')' Some(ASTNode::make_leaf(ASTNodeKind::AST_FUNC_CALL, LitType::I32(symbol_index as i32), result_type)) diff --git a/src/symtable.rs b/src/symtable.rs index a7bc2d6..b3f3f63 100644 --- a/src/symtable.rs +++ b/src/symtable.rs @@ -24,6 +24,7 @@ SOFTWARE. use crate::enums::*; use crate::types::*; +use std::slice::Iter; #[derive(Clone)] pub struct Symbol { @@ -40,10 +41,16 @@ impl Symbol { #[derive(Clone)] pub struct Symtable { - syms: Vec, // tracks all the global symbols + syms: Vec, // counter: usize, // next free slot in the table } +impl Symtable { + pub fn iter(&self) -> Iter<'_, Symbol> { + self.syms.iter() + } +} + // Maximum number of symbols in program pub const NSYMBOLS: usize = 1024;