functions basically work now, but they're extremely inneficient

This commit is contained in:
SpookyDervish
2025-09-13 06:26:15 +10:00
parent 865a31827a
commit 170272353c
6 changed files with 74 additions and 66 deletions

View File

@@ -1,6 +1,6 @@
from generators.generator import Generator, SymbolTable
from ground_ast import *
from error import traceback
from error import traceback, warning
from optimizers.x86_64 import X86_64Optimizer
class X86_64Generator(Generator):
@@ -74,6 +74,8 @@ class X86_64Generator(Generator):
except TypeError as e: # variable doesnt exist
traceback(self.code, "NameError", f"\"{var_name}\" is not defined.")
scope.table[var_name]["used"] = True
return var["type"]
def get_var_pos(self, var_name: str, scope: SymbolTable = None):
@@ -131,12 +133,14 @@ class X86_64Generator(Generator):
self.stack_size += 1
else:
self.push(starting_value, lines)
scope.define(var_name, {"stack_loc": stack_location, "type": var_type})
scope.define(var_name, {"stack_loc": stack_location, "type": var_type, "used": False})
def change_variable(self, lines, var_name: str, new_value, scope: SymbolTable = None):
scope = scope or self.current_var_scope
var_pos = self.get_var_pos(var_name, scope)
old_var_type = scope.table[var_name]["type"]
if isinstance(var_pos, str):
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")
@@ -213,6 +217,8 @@ class X86_64Generator(Generator):
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")
scope.table[var_name]["type"] = IntNode
if scope.table[var_name]["type"] != old_var_type:
warning(self.code, f"Changing the type of \"{var_name}\" at runtime is considered bad practice.")
def generate_LabelDecNode(self, node: LabelDecNode, lines):
self.labels.append(node.name)
@@ -238,10 +244,10 @@ class X86_64Generator(Generator):
except IndexError:
traceback(self.code, "CallError", "Functions with more than 6 args aren't supported yet, sorry...")
self.current_var_scope.define(arg.name, {"stack_loc": stack_loc, "type": self.ground_type_to_node(arg.arg_type)})
self.current_var_scope.define(arg.name, {"stack_loc": stack_loc, "type": self.ground_type_to_node(arg.arg_type), "used": False})
for inst in node.statements:
self.function_lines.append(f"; {inst}\n\t")
#self.function_lines.append(f"; {inst}\n\t")
self.generate_InstructionNode(inst, self.function_lines)
def generate_InstructionNode(self, node: InstructionNode, lines = None):
@@ -253,7 +259,6 @@ class X86_64Generator(Generator):
if not type(node.arguments[0]) in [IntNode, VarRefNode]: # example: "end true"
traceback(self.code, "TypeError", f"end expects an integer, not {node.arguments[0]}")
lines.append("mov rax, 60\n\t")
if type(node.arguments[0]) in [IntNode,BoolNode]:
lines.append("mov rdi, " + str(node.arguments[0].value) + "\n\t")
elif isinstance(node.arguments[0], VarRefNode):
@@ -263,7 +268,8 @@ class X86_64Generator(Generator):
else:
if var_type not in [IntNode,BoolNode]:
traceback(self.code, "TypeError", f"end expects an integer, not \"{var_type}\"")
#lines.append("mov rdi, " + str(self.get_variable(lines, node.arguments[0].var_name)) + "\n\t")
lines.append("mov rax, 60\n\t")
lines.append("syscall\n\t")
### VARIABLE INSTRUCTIONS ###
@@ -516,7 +522,7 @@ class X86_64Generator(Generator):
length = self.add_constant(f"equ $ - {string_pointer[1:-1]}", no_string=True)
lines.append(f"lea rax, [rel {string_pointer[1:-1]}]\n\t")
lines.append(f"lea rdx, {length}\n\t")
lines.append(f"mov rdx, {length[1:-1]}\n\t")
#self.push("rax", lines)
elif isinstance(node.arguments[0], VarRefNode):
var = func_scope.lookup(node.arguments[0].var_name)
@@ -529,9 +535,26 @@ class X86_64Generator(Generator):
else:
lines.append("mov rax, 0\n\t")
for _ in range(self.stack_size): # TODO: THIS IS THE WORST FUCKING BULLSHIT EVER, KILL IT NOW!!!!
self.pop("rbp", lines)
size = 0
for name, var in self.current_var_scope.table.items():
if type(var["stack_loc"]) == str:
continue # its in a register, we dont need to free up the stack
if var["type"] == StringNode:
size += 2
else:
size += 1
lines.append(f"add rsp, {8 * (size)}\n\t")
self.stack_size -= size - 1
lines.append("pop rbp")
lines.append("ret\n\t")
# warn about unused variables
for name, var in self.current_var_scope.table.items():
if not var["used"]:
warning(self.code, f"\"{name}\" was defined but never used.")
old_scope = self.current_var_scope
self.current_var_scope = self.current_var_scope.parent
del old_scope
@@ -549,7 +572,7 @@ class X86_64Generator(Generator):
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:
if self.stack_size % 2 != 0:
lines.append("sub rsp, 8\n\t") # align the stack to 16 bytes
self.stack_size -= 1
@@ -587,8 +610,8 @@ class X86_64Generator(Generator):
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")
if len(self.arg_list) > 0:
self.lines.append(f"add rsp, {len(self.arg_list) * 8}")
#if len(self.arg_list) > 0:
# lines.append(f"add rsp, {len(self.arg_list) * 8}")
self.stack_size += len(self.arg_list)
self.arg_list.clear()
@@ -599,7 +622,7 @@ class X86_64Generator(Generator):
if self.current_var_scope.lookup(node.arguments[1].var_name):
self.change_variable(lines, node.arguments[1].var_name, "rax")
else:
self.current_var_scope.define(node.arguments[1].var_name, {"stack_loc": "rax", "type": self.ground_type_to_node(func.return_type)})
self.current_var_scope.define(node.arguments[1].var_name, {"stack_loc": "rax", "type": self.ground_type_to_node(func.return_type), "used": False})
#self.create_variable(lines, node.arguments[1].var_name, "rax", self.ground_type_to_node(self.functions.get(node.arguments[0].func_name)["func"].return_type))
elif node.instruction == "pusharg":
self.clamp_instruction_args(node, 1, 1)