Skip to content

Commit

Permalink
bug finally fixed
Browse files Browse the repository at this point in the history
  • Loading branch information
Ianyourgod committed Jul 7, 2024
1 parent c7021ee commit dfa3dc3
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 68 deletions.
32 changes: 17 additions & 15 deletions src/code_gen/convert_pass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ impl Pass {
instructions.push(nodes::Instruction::Mov(nodes::BinOp {
src: nodes::Operand::Register(reg),
dest: nodes::Operand::Pseudo(nodes::Identifier { name: arg.0.clone() }),
suffix: nodes::Suffix::L,
suffix: self.type_to_suffix(&arg.1),
}));
} else {
instructions.push(nodes::Instruction::Mov(nodes::BinOp {
Expand Down Expand Up @@ -208,8 +208,8 @@ impl Pass {
tacky::nodes::BinaryOperator::Or => panic!(),
tacky::nodes::BinaryOperator::GreaterThan => {
instructions.push(nodes::Instruction::Cmp(nodes::BinOp {
src: src1,
dest: src2.clone(),
src: src2.clone(),
dest: src1,
suffix: src_type_suf,
}));
instructions.push(nodes::Instruction::Mov(nodes::BinOp {
Expand All @@ -221,8 +221,8 @@ impl Pass {
},
tacky::nodes::BinaryOperator::GreaterThanEqual => {
instructions.push(nodes::Instruction::Cmp(nodes::BinOp {
src: src1,
dest: src2.clone(),
src: src2.clone(),
dest: src1,
suffix: src_type_suf,
}));
instructions.push(nodes::Instruction::Mov(nodes::BinOp {
Expand All @@ -234,8 +234,8 @@ impl Pass {
},
tacky::nodes::BinaryOperator::LessThan => {
instructions.push(nodes::Instruction::Cmp(nodes::BinOp {
src: src1,
dest: src2.clone(),
src: src2.clone(),
dest: src1,
suffix: src_type_suf,
}));
instructions.push(nodes::Instruction::Mov(nodes::BinOp {
Expand All @@ -247,8 +247,8 @@ impl Pass {
},
tacky::nodes::BinaryOperator::LessThanEqual => {
instructions.push(nodes::Instruction::Cmp(nodes::BinOp {
src: src1,
dest: src2.clone(),
src: src2.clone(),
dest: src1,
suffix: src_type_suf,
}));
instructions.push(nodes::Instruction::Mov(nodes::BinOp {
Expand All @@ -260,8 +260,8 @@ impl Pass {
},
tacky::nodes::BinaryOperator::Equal => {
instructions.push(nodes::Instruction::Cmp(nodes::BinOp {
src: src1,
dest: src2.clone(),
src: src2.clone(),
dest: src1,
suffix: src_type_suf,
}));
instructions.push(nodes::Instruction::Mov(nodes::BinOp {
Expand All @@ -273,8 +273,8 @@ impl Pass {
},
tacky::nodes::BinaryOperator::NotEqual => {
instructions.push(nodes::Instruction::Cmp(nodes::BinOp {
src: src1,
dest: src2.clone(),
src: src2.clone(),
dest: src1,
suffix: src_type_suf,
}));
instructions.push(nodes::Instruction::Mov(nodes::BinOp {
Expand Down Expand Up @@ -347,11 +347,13 @@ impl Pass {
}

for (i, arg) in register_args.iter().enumerate() {
instructions.push(nodes::Instruction::Mov(nodes::BinOp {
let mov = nodes::Instruction::Mov(nodes::BinOp {
src: self.emit_value(arg),
dest: nodes::Operand::Register(arg_registers[i]),
suffix: self.type_to_suffix(&self.get_type(arg))
}));
});

instructions.push(mov);
}

// go over stack args in reverse order
Expand Down
2 changes: 0 additions & 2 deletions src/code_gen/inst_fixn2_pass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ impl Pass {

for function in self.program.statements.clone() {
let mut instructions: Vec<nodes::Instruction> = Vec::new();

instructions.push(nodes::Instruction::AllocateStack((function.context.stack_offset + 15) & !15)); // Align stack to 16 bytes

for statement in function.instructions {
self.emit_instruction(&statement, &mut instructions);
Expand Down
1 change: 0 additions & 1 deletion src/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ impl Emitter {
output.push_str(" push %rbp\n");
output.push_str(" mov %rsp, %rbp\n");
for instruction in &function.instructions {

match instruction {
code_gen::nodes::Instruction::Mov(mov) => {
output.push_str(&format!(" mov{} {}, {}\n", mov.suffix, self.displ_op(&mov.src, &mov.suffix), self.displ_op(&mov.dest, &mov.suffix)));
Expand Down
2 changes: 1 addition & 1 deletion src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ mod tests {
Token { kind: TokenType::Keyword, literal: String::from("let"), line: 0, pos: 0, length: 3 },
Token { kind: TokenType::Identifier, literal: String::from("x"), line: 0, pos: 4, length: 1 },
Token { kind: TokenType::Colon, literal: String::from(""), line: 0, pos: 5, length: 1 },
Token { kind: TokenType::Identifier, literal: String::from("int"), line: 0, pos: 7, length: 3 },
Token { kind: TokenType::Keyword, literal: String::from("int"), line: 0, pos: 7, length: 3 },
Token { kind: TokenType::Assign, literal: String::from(""), line: 0, pos: 11, length: 1 },
Token { kind: TokenType::Int, literal: String::from("5"), line: 0, pos: 13, length: 1 },
Token { kind: TokenType::SemiColon, literal: String::from(""), line: 0, pos: 14, length: 1 },
Expand Down
23 changes: 23 additions & 0 deletions src/parser/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,29 @@ pub enum Literal {
I64(i64),
}

impl Literal {
pub fn get_type(&self) -> Type {
match self {
Literal::I32(_) => Type::I32,
Literal::I64(_) => Type::I64,
}
}

pub fn as_i32(&self) -> i32 {
match self {
Literal::I32(val) => *val,
Literal::I64(val) => *val as i32,
}
}

pub fn as_i64(&self) -> i64 {
match self {
Literal::I32(val) => *val as i64,
Literal::I64(val) => *val,
}
}
}

#[derive(Debug, Clone, PartialEq)]
pub struct Identifier {
pub value: String,
Expand Down
13 changes: 8 additions & 5 deletions src/semantic_analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,20 @@ impl Analysis {
}

pub fn run(&mut self) -> (parser::nodes::Program, symbol_table::SymbolTable) {
let first_pass = identifier_resolution_pass::Pass::new(&self.ast);
let mut program: parser::nodes::Program;

let program = first_pass.run();
let mut first_pass = identifier_resolution_pass::Pass::new(&self.ast);

let second_pass = loop_labeling_pass::Pass::new(&program);
program = first_pass.run();

let program = second_pass.run();
let mut second_pass = loop_labeling_pass::Pass::new(&program);

program = second_pass.run();

let third_pass = type_checking_pass::Pass::new(&program);

let (program, sym_tbl) = third_pass.run();
let sym_tbl: symbol_table::SymbolTable;
(program, sym_tbl) = third_pass.run();

(program, sym_tbl)
}
Expand Down
41 changes: 23 additions & 18 deletions src/semantic_analysis/identifier_resolution_pass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::parser::nodes;

pub struct Pass {
pub program: nodes::Program,
pub global_identifier_number: i32,
}

#[derive(Clone)]
Expand All @@ -11,7 +12,12 @@ pub struct Context {

pub struct VarMap {
pub map: std::collections::HashMap<String, (String, bool)>,
pub tmp_n: i32,
}

impl VarMap {
pub fn new() -> VarMap {
VarMap { map: std::collections::HashMap::new() }
}
}

impl Clone for VarMap {
Expand All @@ -23,23 +29,22 @@ impl Clone for VarMap {

VarMap {
map: new_map,
tmp_n: self.tmp_n,
}
}
}

impl Context {
fn new() -> Context {
Context { identifier_map: VarMap { map: std::collections::HashMap::new(), tmp_n: -1 } }
Context { identifier_map: VarMap::new() }
}
}

impl Pass {
pub fn new(program: &nodes::Program) -> Pass {
Pass { program: program.clone() }
Pass { program: program.clone(), global_identifier_number: -1 }
}

pub fn run(&self) -> nodes::Program {
pub fn run(&mut self) -> nodes::Program {
let mut program = nodes::Program {
function_definitions: Vec::new(),
};
Expand All @@ -55,19 +60,19 @@ impl Pass {
program
}

fn make_temporary(&self, context: &mut Context) -> String {
context.identifier_map.tmp_n += 1;
format!(".localvar{}", context.identifier_map.tmp_n)
fn make_local_var(&mut self, context: &mut Context) -> String {
self.global_identifier_number += 1;
format!(".localvar{}", self.global_identifier_number)
}

fn resolve_statement(&self, statement: Box<nodes::Statement>, context: &mut Context) -> Box<nodes::Statement> {
fn resolve_statement(&mut self, statement: Box<nodes::Statement>, context: &mut Context) -> Box<nodes::Statement> {
match *statement {
nodes::Statement::VariableDeclaration(decl) => {
if context.identifier_map.map.contains_key(&decl.ident.value) && context.identifier_map.map.get(&decl.ident.value).unwrap().1 {
panic!("Variable {} already declared in scope", decl.ident.value);
}

let new_ident = self.make_temporary(context);
let new_ident = self.make_local_var(context);

context.identifier_map.map.insert(decl.ident.value.clone(), (new_ident.clone(), true));

Expand Down Expand Up @@ -125,7 +130,7 @@ impl Pass {
}
}

fn resolve_function_declaration(&self, func: nodes::FunctionDeclaration, context: &mut Context) -> nodes::FunctionDeclaration {
fn resolve_function_declaration(&mut self, func: nodes::FunctionDeclaration, context: &mut Context) -> nodes::FunctionDeclaration {
if context.identifier_map.map.contains_key(&func.function_name) && context.identifier_map.map.get(&func.function_name).unwrap().1 {
panic!("Function {} already declared in scope", func.function_name);
}
Expand All @@ -137,14 +142,14 @@ impl Pass {
let mut new_params: Vec<nodes::FunctionArg> = Vec::new();

for param in func.params {
let var_name = self.make_temporary(&mut new_context);
let var_name = self.make_local_var(&mut new_context);

new_params.push(nodes::FunctionArg {
kind: param.kind.clone(),
ident: nodes::Identifier { value: var_name.clone() },
});

new_context.identifier_map.map.insert(param.ident.value, (var_name, true));
new_context.identifier_map.map.insert(param.ident.value.clone(), (var_name.clone(), true));
}

let new_body = self.resolve_statement(func.body, &mut new_context);
Expand All @@ -157,7 +162,7 @@ impl Pass {
}
}

fn resolve_expression(&self, expr: Box<nodes::Expression>, context: &mut Context) -> Box<nodes::Expression> {
fn resolve_expression(&mut self, expr: Box<nodes::Expression>, context: &mut Context) -> Box<nodes::Expression> {
match *expr {
nodes::Expression::Var(ref ident, _) => {
if context.identifier_map.map.contains_key(&ident.value) {
Expand Down Expand Up @@ -233,7 +238,7 @@ mod tests {
],
};

let pass = Pass::new(&program);
let mut pass = Pass::new(&program);
let new_program = pass.run();

assert_eq!(new_program.function_definitions[0].body, Box::new(nodes::Statement::Compound(nodes::CompoundStatement {
Expand Down Expand Up @@ -277,7 +282,7 @@ mod tests {
],
};

let pass = Pass::new(&program);
let mut pass = Pass::new(&program);
pass.run();
}

Expand Down Expand Up @@ -305,7 +310,7 @@ mod tests {
],
};

let pass = Pass::new(&program);
let mut pass = Pass::new(&program);
let new_program = pass.run();

assert_eq!(new_program.function_definitions[0].body, Box::new(nodes::Statement::Compound(nodes::CompoundStatement {
Expand Down Expand Up @@ -342,7 +347,7 @@ mod tests {
],
};

let pass = Pass::new(&program);
let mut pass = Pass::new(&program);
pass.run();
}
}
13 changes: 6 additions & 7 deletions src/semantic_analysis/loop_labeling_pass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@ use crate::parser::nodes;

pub struct Pass {
pub program: nodes::Program,
pub global_label_count: u32,
}

pub struct Context {
pub label: Option<String>,
pub label_count: i32, // This is a hack to generate unique "labels". a label is just so tacky knows what loop a break or continue statement is referring to
}

impl Pass {
pub fn new(program: &nodes::Program) -> Pass {
Pass { program: program.clone() }
Pass { program: program.clone(), global_label_count: 0, }
}

pub fn run(&self) -> nodes::Program {
pub fn run(&mut self) -> nodes::Program {
let mut program = nodes::Program {
function_definitions: Vec::new(),
};
Expand All @@ -30,7 +30,6 @@ impl Pass {

let mut context = Context {
label: None,
label_count: 0,
};

for statement in body_statements {
Expand All @@ -50,7 +49,7 @@ impl Pass {
program
}

fn label_statement(&self, statement: &nodes::Statement, statements: &mut Vec<Box<nodes::Statement>>, context: &mut Context) {
fn label_statement(&mut self, statement: &nodes::Statement, statements: &mut Vec<Box<nodes::Statement>>, context: &mut Context) {
match statement {
nodes::Statement::WhileStatement(ref while_statement) => {
let body_statements = match *while_statement.body {
Expand All @@ -60,9 +59,9 @@ impl Pass {


let old_label = context.label.clone();
let new_label = context.label_count.to_string();
let new_label = self.global_label_count.to_string();
context.label = Some(new_label.clone());
context.label_count += 1;
self.global_label_count += 1;

let mut new_body_statements: Vec<Box<nodes::Statement>> = Vec::new();

Expand Down
Loading

0 comments on commit dfa3dc3

Please sign in to comment.