functions basically work now, but they're extremely inneficient
This commit is contained in:
@@ -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)
|
||||
|
Reference in New Issue
Block a user