Skip to content

Commit

Permalink
introducing local variables
Browse files Browse the repository at this point in the history
  • Loading branch information
rigel-star committed Mar 6, 2024
1 parent d5d2762 commit cde7efa
Show file tree
Hide file tree
Showing 6 changed files with 327 additions and 116 deletions.
97 changes: 44 additions & 53 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,7 @@ extern crate lazy_static;
use std::{cell::RefCell, rc::Rc};

use crate::{
enums::*,
register::{self, RegisterManager},
symtable,
types::*,
enums::*, function::{self, FunctionInfo}, register::{self, RegisterManager}, symtable::{self, StorageClass, Symbol}, types::*
};

lazy_static::lazy_static! {
Expand Down Expand Up @@ -92,41 +89,12 @@ impl ASTNode {
result_type,
}
}

/// Modify the given node's type into the 'to' type.
pub fn modify(&mut self, to: LitTypeVariant, op: ASTNodeKind) -> Option<ASTNode> {
let ltype: LitTypeVariant = self.result_type;
let lsize: usize = self.result_type.size();
let rsize: usize = to.size();
if !ltype.is_ptr_type() && !to.is_ptr_type() {
if ltype == to {
return Some(self.clone());
}
// tree's size is too big
if lsize > rsize {
return None;
}
if rsize > lsize {
return Some(ASTNode::new(
ASTNodeKind::AST_WIDEN,
Some(self.clone()),
None,
None,
to,
));
}
}
if ltype.is_ptr_type() && ltype == to && (op == ASTNodeKind::AST_NONE) {
return Some(self.clone());
}
// if we reach here, then types are incompatible
None
}
}

pub struct ASTTraverser {
reg_manager: Rc<RefCell<register::RegisterManager>>,
sym_table: Rc<RefCell<symtable::Symtable>>,
func_info_table: Rc<RefCell<function::FunctionInfoTable>>,
_label_id: &'static mut usize,
}

Expand All @@ -135,11 +103,13 @@ impl ASTTraverser {
pub fn new(
reg_manager: Rc<RefCell<RegisterManager>>,
sym_table: Rc<RefCell<symtable::Symtable>>,
func_info_table: Rc<RefCell<function::FunctionInfoTable>>,
label_id: &'static mut usize
) -> Self {
Self {
reg_manager,
sym_table,
func_info_table,
_label_id: label_id,
}
}
Expand Down Expand Up @@ -179,10 +149,8 @@ impl ASTTraverser {
ASTNodeKind::AST_ADD => self.gen_add(leftreg, rightreg),
ASTNodeKind::AST_SUBTRACT => self.gen_sub(leftreg, rightreg),
ASTNodeKind::AST_INTLIT => self.gen_load_intlit_into_reg(ast.value.as_ref().unwrap()),
ASTNodeKind::AST_IDENT => self.gen_load_gid_into_reg(ast.value.as_ref().unwrap()),
ASTNodeKind::AST_LVIDENT => {
self.gen_load_reg_into_gid(_reg, ast.value.as_ref().unwrap())
}
ASTNodeKind::AST_IDENT => self.gen_load_id_into_reg(ast.value.as_ref().unwrap()),
ASTNodeKind::AST_LVIDENT => self.gen_load_reg_into_id(_reg, ast.value.as_ref().unwrap()),
ASTNodeKind::AST_ASSIGN => rightreg,
ASTNodeKind::AST_GTHAN
| ASTNodeKind::AST_LTHAN
Expand Down Expand Up @@ -218,10 +186,13 @@ impl ASTTraverser {
_ => panic!("Not a valid symbol table indexing method"),
};
let func_name: String = self.sym_table.borrow().get_symbol(index).unwrap().name.clone();
println!("{}:", func_name);
let func_info: FunctionInfo = self.func_info_table.borrow().get(&func_name).unwrap().clone();
println!(".global _{}\n_{}:", func_name, func_name);
println!("sub sp, sp, {}", func_info.stack_size);
if let Some(body) = &*ast.left {
self.gen_ast(body, 0xFFFFFFFF, ast.operation);
}
println!("add sp, sp, {}", func_info.stack_size);
0xFFFFFFFF
}

Expand Down Expand Up @@ -365,24 +336,35 @@ impl ASTTraverser {

// Load value from a variable into a register.
// Return the number of the register
fn gen_load_gid_into_reg(&mut self, id: &LitType) -> usize {
let reg: usize = self.reg_manager.borrow_mut().allocate();
let reg_name: String = self.reg_manager.borrow().name(reg);
fn gen_load_id_into_reg(&mut self, id: &LitType) -> usize {
let value_containing_reg: usize = self.reg_manager.borrow_mut().allocate();
let value_reg_name: String = self.reg_manager.borrow().name(value_containing_reg);
self.dump_gid_address_load_code_from_name(&reg_name, id);
println!("ldr {}, [{}]", value_reg_name, reg_name);
let symbol: Symbol = self.get_symbol_from_index(id);
if symbol.class == StorageClass::GLOBAL {
let reg: usize = self.reg_manager.borrow_mut().allocate();
let reg_name: String = self.reg_manager.borrow().name(reg);
self.dump_gid_address_load_code_from_name(&reg_name, id);
println!("ldr {}, [{}]", value_reg_name, reg_name);
} else {
println!("ldr {}, [sp, {}]", value_reg_name, symbol.local_offset);
}
value_containing_reg
}

// Refer to this page for explanation on '@PAGE' and '@PAGEOFF': https://stackoverflow.com/questions/65351533/apple-clang12-llvm-unknown-aarch64-fixup-kind
fn gen_load_reg_into_gid(&mut self, reg: usize, id: &LitType) -> usize {
fn gen_load_reg_into_id(&mut self, reg: usize, id: &LitType) -> usize {
let reg_name: String = self.reg_manager.borrow().name(reg);
let addr_reg: usize = self.reg_manager.borrow_mut().allocate();
let addr_reg_name: String = self.reg_manager.borrow().name(addr_reg);
self.dump_gid_address_load_code_from_name(&addr_reg_name, id);
println!("str {}, [{}]", reg_name, addr_reg_name);
addr_reg
let symbol: Symbol = self.get_symbol_from_index(id);
if symbol.class == StorageClass::GLOBAL {
let addr_reg: usize = self.reg_manager.borrow_mut().allocate();
let addr_reg_name: String = self.reg_manager.borrow().name(addr_reg);
self.dump_gid_address_load_code_from_name(&addr_reg_name, id);
println!("str {}, [{}]", reg_name, addr_reg_name);
addr_reg
} else {
println!("mov {}, [sp, {}]", reg_name, symbol.local_offset);
0xFFFFFFFF
}
}

// Generally speaking, loading one variable's address into another variable
Expand Down Expand Up @@ -425,9 +407,11 @@ impl ASTTraverser {
LitType::I32(_idx) => self.sym_table.borrow().get_symbol(*_idx as usize).unwrap().clone(),
_ => panic!("Can't index symtable with this type: {:?}", id),
};
let sym_name: &str = &symbol.name;
println!("adrp {}, {}@PAGE", reg_name, sym_name);
println!("add {}, {}, {}@PAGEOFF", reg_name, reg_name, sym_name);
if symbol.class == StorageClass::GLOBAL {
let sym_name: &str = &symbol.name;
println!("adrp {}, {}@PAGE", reg_name, sym_name);
println!("add {}, {}, {}@PAGEOFF", reg_name, reg_name, sym_name);
}
}

fn _calc_id_offset(&self, id: &LitType) -> usize {
Expand All @@ -448,6 +432,13 @@ impl ASTTraverser {
offset
}

fn get_symbol_from_index(&self, id: &LitType) -> Symbol {
match id {
LitType::I32(_idx) => self.sym_table.borrow().get_symbol(*_idx as usize).unwrap().clone(),
_ => panic!("Can't index symtable with this type: {:?}", id),
}
}

fn get_next_label(&mut self) -> usize {
let label: usize = *self._label_id;
(*self._label_id) += 1;
Expand Down
63 changes: 63 additions & 0 deletions src/function.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
MIT License
Copyright (c) 2023 Kagati Foundation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

use std::collections::HashMap;

use crate::types::LitTypeVariant;

#[derive(Clone)]
pub struct FunctionInfo {
pub name: String,
pub stack_size: i32,
pub return_type: LitTypeVariant
}

impl FunctionInfo {
pub fn new(name: String, stack_size: i32, return_type: LitTypeVariant) -> Self {
Self {
name, stack_size, return_type
}
}
}

pub struct FunctionInfoTable {
functions: HashMap<String, FunctionInfo>,
}

impl FunctionInfoTable {
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
Self {
functions: HashMap::new()
}
}

pub fn add(&mut self, func_info: FunctionInfo) {
self.functions.insert(func_info.name.clone(), func_info);
}

pub fn get(&self, name: &str) -> Option<&FunctionInfo> {
self.functions.get(name)
}
}
9 changes: 5 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub mod symtable;
pub mod tokenizer;
pub mod types;
pub mod utils;
pub mod function;

/*
global char n;
Expand All @@ -45,15 +46,15 @@ def main() -> char {
fn main() {
static mut LABEL_ID: usize = 0;
let mut tokener: tokenizer::Tokenizer = tokenizer::Tokenizer::new(
"global char *name = \"ramesh\"; global integer value = 12; value = value + value;",
"def main() -> void { local integer a = 45; local integer b = 12; a = b; }",
);
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()));
let mut p: parser::Parser = parser::Parser::new(tokens, Rc::clone(&sym_table), unsafe { &mut LABEL_ID });
let func_table: Rc<RefCell<function::FunctionInfoTable>> = Rc::new(RefCell::new(function::FunctionInfoTable::new()));
let mut p: parser::Parser = parser::Parser::new(tokener.start_scan(), Rc::clone(&sym_table), Rc::clone(&func_table), unsafe { &mut LABEL_ID });
let mut traverser: ast::ASTTraverser =
ast::ASTTraverser::new(Rc::clone(&reg_manager), Rc::clone(&sym_table), unsafe { &mut LABEL_ID });
ast::ASTTraverser::new(Rc::clone(&reg_manager), Rc::clone(&sym_table), Rc::clone(&func_table), unsafe { &mut LABEL_ID });
p.start(&mut traverser);
}
Loading

0 comments on commit cde7efa

Please sign in to comment.