Skip to content

Commit

Permalink
using ADRP+ADD instruction pair for loading global variables
Browse files Browse the repository at this point in the history
  • Loading branch information
rigel-star committed Feb 6, 2024
1 parent 9fafa80 commit fe912b6
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 60 deletions.
29 changes: 20 additions & 9 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<tokenizer::Token> = tokener.start_scan();
let reg_manager: Rc<RefCell<register::RegisterManager>> = Rc::new(RefCell::new(register::RegisterManager::new()));
let sym_table: Rc<RefCell<symtable::Symtable>> = Rc::new(RefCell::new(symtable::Symtable::new()));
Expand Down
77 changes: 28 additions & 49 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,29 +47,37 @@ 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<ASTNode> = 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");
}
}
}

fn parse_single_stmt(&mut self) -> Option<ASTNode> {
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(),
Expand All @@ -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<ASTNode> {
_ = self.token_match(TokenKind::T_LBRACE);
Expand Down Expand Up @@ -186,43 +179,33 @@ impl<'a> Parser<'a> {

fn parse_assignment_stmt(&mut self) -> Option<ASTNode> {
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<ASTNode> = 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))
}

fn parse_global_variable_decl_stmt(&mut self) {
_ = self.token_match(TokenKind::KW_GLOBAL);
// let mut sym: MaybeUninit<Symbol> = MaybeUninit::<Symbol>::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();
let id_token: Token = self.token_match(TokenKind::T_IDENTIFIER).clone();
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<ASTNode> {
Expand Down Expand Up @@ -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))
Expand Down
9 changes: 8 additions & 1 deletion src/symtable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ SOFTWARE.

use crate::enums::*;
use crate::types::*;
use std::slice::Iter;

#[derive(Clone)]
pub struct Symbol {
Expand All @@ -40,10 +41,16 @@ impl Symbol {

#[derive(Clone)]
pub struct Symtable {
syms: Vec<Symbol>, // tracks all the global symbols
syms: Vec<Symbol>, //
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;

Expand Down

0 comments on commit fe912b6

Please sign in to comment.