RETURNING WORKSSSSS

This commit is contained in:
SpookyDervish
2025-09-10 18:56:45 +10:00
parent 3103d17026
commit 523ccecbc0
5 changed files with 103 additions and 19 deletions

View File

@@ -1,4 +1,4 @@
from generators.generator import Generator
from generators.generator import Generator, SymbolTable
from ground_ast import *
from error import traceback
from optimizers.x86_64 import X86_64Optimizer
@@ -26,7 +26,7 @@ class X86_64Generator(Generator):
self.stack_size -= 1
def get_variable(self, lines, var_name: str, reg: str, float: bool = False, offset: int = 0, no_stack_pop: bool = True):
var = self.variables.get(var_name, None)
var = self.current_var_scope.lookup(var_name)
var_pos = self.get_var_pos(var_name)
try:
#print(var["type"])
@@ -67,7 +67,7 @@ class X86_64Generator(Generator):
def get_var_pos(self, var_name: str):
try:
return (self.stack_size - self.variables.get(var_name)['stack_loc'] - 1) * 8
return (self.stack_size - self.current_var_scope.lookup(var_name)['stack_loc'] - 1) * 8
except TypeError: # not defined
traceback(self.code, "TypeError", f"\"{var_name}\" is not defined.")
@@ -115,19 +115,19 @@ class X86_64Generator(Generator):
self.stack_size += 1
else:
self.push(starting_value, lines)
self.variables[var_name] = {"stack_loc": stack_location, "type": var_type}
self.current_var_scope.define(var_name, {"stack_loc": stack_location, "type": var_type})
def change_variable(self, lines, var_name: str, new_value):
var_pos = self.get_var_pos(var_name)
if type(new_value) == IntNode: # we're changing a variable to a number
lines.append(f"mov QWORD [rsp + {var_pos}], {new_value.value}\n\t")
self.variables[var_name]["type"] = IntNode
self.current_var_scope.table[var_name]["type"] = IntNode
elif type(new_value) == VarRefNode: # we're changing a variable to the value of another variable
var_type = self.get_variable(lines, new_value.var_name, "rax")
lines.append(f"mov QWORD [rsp + {var_pos}], rax\n\t")
self.variables[var_name]["type"] = var_type
self.current_var_scope.table[var_name]["type"] = var_type
elif type(new_value) == StringNode: # we're changing a variable to a string
lines.append(f"mov QWORD [rsp + {var_pos}], 0\n\t")
@@ -138,21 +138,21 @@ class X86_64Generator(Generator):
#lines.append(f"lea QWORD [rsp + {var_pos}], {string_pointer}\n\t")
##lines.append(f"mov QWORD [rsp + {var_pos + 8}], {string_len[1:-1]}\n\t")
self.variables[var_name]["stack_loc"] = self.stack_size
self.current_var_scope.table[var_name]["stack_loc"] = self.stack_size
lines.append(f"lea rax, {string_pointer}\n\t")
self.push("rax", lines)
lines.append(f"mov rax, {string_len[1:-1]}\n\t")
self.push("rax", lines)
self.variables[var_name]["type"] = StringNode
self.current_var_scope.table[var_name]["type"] = StringNode
elif type(new_value) == BoolNode:
lines.append(f"mov QWORD [rsp + {var_pos}], {'1' if new_value.value else '0'}\n\t")
self.variables[var_name]["type"] = BoolNode
self.current_var_scope.table[var_name]["type"] = BoolNode
elif type(new_value) == str: # we're changing a variable to the value of a register
lines.append(f"mov QWORD [rsp + {var_pos}], {new_value}\n\t")
self.variables[var_name]["type"] = IntNode
self.current_var_scope.table[var_name]["type"] = IntNode
def generate_LabelDecNode(self, node: LabelDecNode, lines):
self.labels.append(node.name)
@@ -164,9 +164,16 @@ class X86_64Generator(Generator):
if node.name == None:
traceback(self.code, "SyntaxError", "Functions require a name.")
self.current_var_scope = SymbolTable(self.current_var_scope)
# function boilerplate
self.function_lines.append(node.name + ":")
self.push("rbp", self.function_lines)
self.function_lines.append("mov rbp, rsp\n\t")
for inst in node.statements:
self.generate_InstructionNode(inst, self.function_lines)
self.add_function(node)
def generate_InstructionNode(self, node: InstructionNode, lines = None):
@@ -200,7 +207,7 @@ class X86_64Generator(Generator):
if type(node.arguments[1]) not in [IntNode, VarRefNode, FloatNode, StringNode, BoolNode]:
traceback(self.code, "TypeError", f"variables can't be of type \"{type(node.arguments[1])}\"")
variable_exists = self.variables.get(node.arguments[0].var_name, None) != None
variable_exists = self.current_var_scope.lookup(node.arguments[0].var_name) != None
if not variable_exists: # create a new variable
self.create_variable(lines, node.arguments[0].var_name, node.arguments[1])
@@ -265,7 +272,7 @@ class X86_64Generator(Generator):
is_integer = number1_type == IntNode and number2_type == IntNode
starting_reg = "rax" if is_integer else "xmm0"
if self.variables.get(node.arguments[2].var_name, None) == None: # we need to create a variable for the destination
if self.current_var_scope.lookup(node.arguments[2].var_name) == None: # we need to create a variable for the destination
self.create_variable(lines, node.arguments[2].var_name, starting_reg, IntNode if is_integer else FloatNode)
else:
self.change_variable(lines, node.arguments[2].var_name, starting_reg)
@@ -304,7 +311,7 @@ class X86_64Generator(Generator):
lines.append(f"divsd xmm0, xmm1\n\t")
if self.variables.get(node.arguments[2].var_name, None) == None: # we need to create a variable for the destination
if self.current_var_scope.lookup(node.arguments[2].var_name) == None: # we need to create a variable for the destination
self.create_variable(lines, node.arguments[2].var_name, "xmm0", FloatNode)
else:
self.change_variable(lines, node.arguments[2].var_name, "xmm0")
@@ -413,7 +420,7 @@ class X86_64Generator(Generator):
var_name = node.arguments[2].var_name
if self.variables.get(var_name, None) == None:
if self.current_var_scope.lookup(var_name) == None:
self.create_variable(lines, var_name, "rax", BoolNode)
else:
self.change_variable(lines, var_name, "rax")
@@ -430,25 +437,75 @@ class X86_64Generator(Generator):
lines.append(f"mov rax, {int(node.arguments[0].value)}")
elif isinstance(node.arguments[0], FloatNode):
lines.append(f"mov xmm0, {node.arguments[0].value}")
#self.get_variable(lines, node.arguments[0].var_name, "rax")
else:
lines.append("mov rax, 0\n\t")
self.pop("rbp", lines)
lines.append("ret\n\t")
old_scope = self.current_var_scope
self.current_var_scope = self.current_var_scope.parent
del old_scope
elif node.instruction == "call":
self.clamp_instruction_args(node, 1, 2)
if not isinstance(node.arguments[0], FunctionCallNode):
traceback(self.code, "TypeError", "Argument 1 of call needs to be a function reference.")
if not isinstance(node.arguments[1], VarPointerNode):
traceback(self.code, "TypeError", "Argument 1 of call needs to be a variable pointer.")
func = self.functions.get(node.arguments[0].func_name, None)
if not func:
traceback(self.code, "TypeError", f"Function \"{node.arguments[0].func_name}\" is not defined.")
if len(self.arg_list) != len(func.args):
traceback(self.code, "TypeError", f"Function \"{node.arguments[0].func_name}\" takes {len(func.args)} arguments, but got {len(self.arg_list)}")
# stack alignment
if self.stack_size % 2 == 0:
lines.append("sub rsp, 8\n\t") # align the stack to 16 bytes
for i, arg in enumerate(self.arg_list):
#self.create_variable(lines, func.args[i].name, arg, func.args[i].arg_type)
value = ""
if isinstance(arg, IntNode):
value = arg.value
elif isinstance(arg, StringNode):
value = self.add_constant(arg.value)
else:
traceback(self.code, "CallError", f"Can't pass {arg} to function.")
if i == 0:
lines.append(f"mov rdi, {value}")
elif i == 1:
lines.append(f"mov rsi, {value}")
elif i == 2:
lines.append(f"mov rdx, {value}")
elif i == 3:
lines.append(f"mov rcx, {value}")
elif i == 4:
lines.append(f"mov r8, {value}")
elif i == 5:
lines.append(f"mov r9, {value}")
else:
traceback(self.code, "CallError", "Functions with more than 6 args aren't supported yet, sorry...")
lines.append(f"call {node.arguments[0].func_name}\n\t")
self.lines.append(f"add rsp, {len(self.arg_list) * 8}")
self.arg_list.clear()
if len(node.arguments) == 2:
if self.variables.get(node.arguments[1].var_name, None):
if not isinstance(node.arguments[1], VarPointerNode):
traceback(self.code, "TypeError", "Argument 1 of call needs to be a variable pointer.")
if self.current_var_scope.lookup(node.arguments[1].var_name):
self.change_variable(lines, node.arguments[1].var_name, "rax")
else:
self.create_variable(lines, node.arguments[1].var_name, "rax", self.ground_type_to_node(self.functions.get(node.arguments[0].func_name).return_type))
elif node.instruction == "pusharg":
self.clamp_instruction_args(node, 1, 1)
#if type(node.arguments[0]) not in [IntNode]:
# traceback(self.code, "TypeError", f"A {node.arguments[0]} can't be passed as an argument.")
self.arg_list.append(node.arguments[0])
else:
raise NotImplementedError(f"A generate method hasn't been made for the \"{node.instruction}\" instruction.")