updated compiler with support for more operators.
(only the unary operators from this are implemented for now)
This commit is contained in:
@@ -510,7 +510,7 @@ impl CodeGenerator {
|
||||
code.push("\tpop zero".to_string());
|
||||
}
|
||||
// Comparison operators - return 1 (true) or 0 (false)
|
||||
BinaryOperator::Eq => {
|
||||
BinaryOperator::Equal => {
|
||||
code.push(format!("\tcmp {}, {}", left_reg, right_reg));
|
||||
code.push(format!("\tlli 1, {}", result_reg));
|
||||
let end_label = format!("_cmp_end_{}", self.get_unique_label());
|
||||
@@ -518,7 +518,7 @@ impl CodeGenerator {
|
||||
code.push(format!("\tlli 0, {}", result_reg));
|
||||
code.push(format!("{}:", end_label));
|
||||
}
|
||||
BinaryOperator::Ne => {
|
||||
BinaryOperator::NotEqual => {
|
||||
code.push(format!("\tcmp {}, {}", left_reg, right_reg));
|
||||
code.push(format!("\tlli 1, {}", result_reg));
|
||||
let end_label = format!("_cmp_end_{}", self.get_unique_label());
|
||||
@@ -526,7 +526,7 @@ impl CodeGenerator {
|
||||
code.push(format!("\tlli 0, {}", result_reg));
|
||||
code.push(format!("{}:", end_label));
|
||||
}
|
||||
BinaryOperator::Lt => {
|
||||
BinaryOperator::LessThan => {
|
||||
code.push(format!("\tcmp {}, {}", left_reg, right_reg));
|
||||
code.push(format!("\tlli 1, {}", result_reg));
|
||||
let end_label = format!("_cmp_end_{}", self.get_unique_label());
|
||||
@@ -534,7 +534,7 @@ impl CodeGenerator {
|
||||
code.push(format!("\tlli 0, {}", result_reg));
|
||||
code.push(format!("{}:", end_label));
|
||||
}
|
||||
BinaryOperator::Le => {
|
||||
BinaryOperator::LessOrEqual => {
|
||||
code.push(format!("\tcmp {}, {}", left_reg, right_reg));
|
||||
code.push(format!("\tlli 1, {}", result_reg));
|
||||
let end_label = format!("_cmp_end_{}", self.get_unique_label());
|
||||
@@ -542,7 +542,7 @@ impl CodeGenerator {
|
||||
code.push(format!("\tlli 0, {}", result_reg));
|
||||
code.push(format!("{}:", end_label));
|
||||
}
|
||||
BinaryOperator::Gt => {
|
||||
BinaryOperator::GreaterThan => {
|
||||
code.push(format!("\tcmp {}, {}", left_reg, right_reg));
|
||||
code.push(format!("\tlli 1, {}", result_reg));
|
||||
let end_label = format!("_cmp_end_{}", self.get_unique_label());
|
||||
@@ -550,7 +550,7 @@ impl CodeGenerator {
|
||||
code.push(format!("\tlli 0, {}", result_reg));
|
||||
code.push(format!("{}:", end_label));
|
||||
}
|
||||
BinaryOperator::Ge => {
|
||||
BinaryOperator::GreaterOrEqual => {
|
||||
code.push(format!("\tcmp {}, {}", left_reg, right_reg));
|
||||
code.push(format!("\tlli 1, {}", result_reg));
|
||||
let end_label = format!("_cmp_end_{}", self.get_unique_label());
|
||||
@@ -581,13 +581,6 @@ impl CodeGenerator {
|
||||
arg_regs.push(arg_reg);
|
||||
}
|
||||
|
||||
// Save caller-saved registers and track which ones we saved
|
||||
// old method, inefficient.
|
||||
// let saved_regs = self.allocator.get_caller_saved_registers();
|
||||
// for reg in &saved_regs {
|
||||
// code.push(format!("\tpush {}", reg));
|
||||
// }
|
||||
|
||||
// Save caller-saved registers and track which ones we saved
|
||||
let saved_regs = self.allocator.get_caller_saved_registers();
|
||||
for reg in &saved_regs {
|
||||
@@ -604,9 +597,6 @@ impl CodeGenerator {
|
||||
));
|
||||
}
|
||||
|
||||
// if GLOBAL_METHODS.contains_key(name.name.as_str()) {
|
||||
// code.push(format!("\tcall {}",
|
||||
// GLOBAL_METHODS[name.name.as_str()])); } else
|
||||
if self.symbols.contains(&name.name) {
|
||||
// Call local function
|
||||
code.push(format!("\tcall {}", name));
|
||||
@@ -644,11 +634,6 @@ impl CodeGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
// Restore caller-saved registers in reverse order (LIFO)
|
||||
// for reg in saved_regs.iter().rev() {
|
||||
// code.push(format!("\tpop {}", reg));
|
||||
// }
|
||||
|
||||
// Free argument registers
|
||||
for reg in arg_regs {
|
||||
self.allocator.free_temp(reg);
|
||||
@@ -677,7 +662,9 @@ impl CodeGenerator {
|
||||
UnaryOperator::Dereference => {
|
||||
code.push(format!("\tldw {}, {}", operand_reg, result_reg));
|
||||
}
|
||||
UnaryOperator::Reference => {
|
||||
UnaryOperator::AddressOf => {
|
||||
// ensure the referenced variable is on the stack and return its
|
||||
// address.
|
||||
let (offset, alloc_code) =
|
||||
self.allocator.free_register(&operand_reg)?;
|
||||
code.extend(alloc_code);
|
||||
@@ -687,6 +674,28 @@ impl CodeGenerator {
|
||||
result_reg
|
||||
));
|
||||
}
|
||||
UnaryOperator::SizeOf => {
|
||||
if let Ok(id) = operand.type_id() {
|
||||
let size = id.size();
|
||||
code.push(format!("\tmov {}, {}", size, result_reg));
|
||||
}
|
||||
}
|
||||
UnaryOperator::CastAs => {} /* this should be removed once the */
|
||||
// semantic analyser can handle it!
|
||||
UnaryOperator::Increment => {
|
||||
// prefix increment
|
||||
code.push(format!("\tmov {}, {}", operand_reg, result_reg));
|
||||
code.push(format!("\taddi {}, {}, 1", operand_reg, operand_reg));
|
||||
}
|
||||
UnaryOperator::Decrement => {
|
||||
// prefix decrement
|
||||
code.push(format!("\tmov {}, {}", operand_reg, result_reg));
|
||||
code.push(format!("\tsubi {}, {}, 1", operand_reg, operand_reg));
|
||||
}
|
||||
UnaryOperator::BitwiseNot => {
|
||||
code.push(format!("\tnot {}, {}", operand_reg, result_reg));
|
||||
}
|
||||
UnaryOperator::LogicalNot => unimplemented!(),
|
||||
}
|
||||
|
||||
self.allocator.free_temp(operand_reg);
|
||||
@@ -694,6 +703,8 @@ impl CodeGenerator {
|
||||
}
|
||||
|
||||
Expression::Empty => Ok((Register::Null, code)),
|
||||
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ impl RegisterAllocator {
|
||||
}
|
||||
|
||||
// This is a true temporary - safe to free
|
||||
if reg != Register::Zero {
|
||||
if !matches!(reg, Register::Zero | Register::Null) {
|
||||
self.in_use.insert(reg, false);
|
||||
}
|
||||
}
|
||||
@@ -141,7 +141,7 @@ impl RegisterAllocator {
|
||||
// Check if this variable is in a register
|
||||
if let Some(location) = self.variable_locations.get(var).cloned() {
|
||||
if let Some(reg) = location.register
|
||||
&& reg != Register::Zero
|
||||
&& !matches!(reg, Register::Zero | Register::Null)
|
||||
{
|
||||
self.register_contents.remove(®);
|
||||
self.in_use.insert(reg, false);
|
||||
|
||||
Reference in New Issue
Block a user