From 865a31827aa896709e7f84535fd02cb25b6bfd01 Mon Sep 17 00:00:00 2001 From: SpookyDervish <78246495+SpookyDervish@users.noreply.github.com> Date: Fri, 12 Sep 2025 06:28:45 +1000 Subject: [PATCH] ok damn it nearly works --- generators/generator.py | 2 +- generators/x86_64.py | 41 +++++++++++++++++++++++++------- optimizers/x86_64.py | 21 +++++++++++++++++ out | Bin 4712 -> 0 bytes out.asm | 51 +++++++++++++++++++++++++++++++--------- test2.grnd | 19 +++++++++------ 6 files changed, 107 insertions(+), 27 deletions(-) delete mode 100644 out diff --git a/generators/generator.py b/generators/generator.py index 4f19f51..dd7e830 100644 --- a/generators/generator.py +++ b/generators/generator.py @@ -74,7 +74,7 @@ class Generator: pass def generate_node(self, node): - #self.lines.append(f"; {node}\n\t") + self.lines.append(f"; {node}\n\t") node_type = str(type(node))[19:-2] if not hasattr(self, f"generate_{node_type}"): raise NotImplementedError(f"Generator has no generate method for {node_type}.") diff --git a/generators/x86_64.py b/generators/x86_64.py index 8d2d069..4f886d0 100644 --- a/generators/x86_64.py +++ b/generators/x86_64.py @@ -32,7 +32,12 @@ class X86_64Generator(Generator): var_pos = self.get_var_pos(var_name, scope) if isinstance(var_pos, str): # in a reg, not on the stack - lines.append(f"mov {reg}, {var_pos}\n\t") + if offset == 0: + lines.append(f"mov {reg}, {var_pos}\n\t") + elif offset == -8: + if var_pos == "rax": # according to the SysV ABI, the second return value of a function is stored in RDX + var_pos = "rdx" + lines.append(f"mov {reg}, {var_pos}\n\t") else: try: #print(var["type"]) @@ -223,7 +228,7 @@ class X86_64Generator(Generator): self.current_var_scope = func["scope"] # function boilerplate - self.function_lines.append(node.name + ":") + self.function_lines.append(node.name + ":\n\t") self.push("rbp", self.function_lines) self.function_lines.append("mov rbp, rsp\n\t") @@ -236,6 +241,7 @@ class X86_64Generator(Generator): self.current_var_scope.define(arg.name, {"stack_loc": stack_loc, "type": self.ground_type_to_node(arg.arg_type)}) for inst in node.statements: + self.function_lines.append(f"; {inst}\n\t") self.generate_InstructionNode(inst, self.function_lines) def generate_InstructionNode(self, node: InstructionNode, lines = None): @@ -495,6 +501,8 @@ class X86_64Generator(Generator): func = self.functions.get(node.parent.name) # the return statement will be a parent of a function node, so we can get the current scope using that + func_scope: SymbolTable = func["scope"] + if len(node.arguments) == 1: if isinstance(node.arguments[0], IntNode): lines.append(f"mov rax, {node.arguments[0].value}") @@ -503,13 +511,26 @@ class X86_64Generator(Generator): 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") + elif isinstance(node.arguments[0], StringNode): + string_pointer = self.add_constant(node.arguments[0].value) + 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") + #self.push("rax", lines) elif isinstance(node.arguments[0], VarRefNode): - self.get_variable(self.function_lines, node.arguments[0].var_name, "rax", scope=func["scope"]) + var = func_scope.lookup(node.arguments[0].var_name) + + if var["type"] == StringNode: + self.get_variable(self.function_lines, node.arguments[0].var_name, "rax", offset=0, scope=func["scope"]) + self.get_variable(self.function_lines, node.arguments[0].var_name, "rdx", offset=-8, scope=func["scope"]) + else: + self.get_variable(self.function_lines, node.arguments[0].var_name, "rax", scope=func["scope"]) else: lines.append("mov rax, 0\n\t") - - self.pop("rbp", lines) + for _ in range(self.stack_size): # TODO: THIS IS THE WORST FUCKING BULLSHIT EVER, KILL IT NOW!!!! + self.pop("rbp", lines) lines.append("ret\n\t") old_scope = self.current_var_scope self.current_var_scope = self.current_var_scope.parent @@ -517,7 +538,7 @@ class X86_64Generator(Generator): 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.") + traceback(self.code, "TypeError", "Argument 2 of call needs to be a function reference.") func = self.functions.get(node.arguments[0].func_name, None) if not func: @@ -530,6 +551,7 @@ class X86_64Generator(Generator): # stack alignment if self.stack_size % 2 == 0: lines.append("sub rsp, 8\n\t") # align the stack to 16 bytes + self.stack_size -= 1 for i, arg in enumerate(self.arg_list): #self.create_variable(lines, func.args[i].name, arg, func.args[i].arg_type) @@ -565,7 +587,9 @@ 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") - self.lines.append(f"add rsp, {len(self.arg_list) * 8}") + if len(self.arg_list) > 0: + self.lines.append(f"add rsp, {len(self.arg_list) * 8}") + self.stack_size += len(self.arg_list) self.arg_list.clear() if len(node.arguments) == 2: @@ -575,7 +599,8 @@ 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.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)) + self.current_var_scope.define(node.arguments[1].var_name, {"stack_loc": "rax", "type": self.ground_type_to_node(func.return_type)}) + #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) #if type(node.arguments[0]) not in [IntNode]: diff --git a/optimizers/x86_64.py b/optimizers/x86_64.py index a1c0aa0..6b2c2e3 100644 --- a/optimizers/x86_64.py +++ b/optimizers/x86_64.py @@ -140,5 +140,26 @@ class X86_64Optimizer(Optimizer): Instruction("mov", ["y", "x"]) ], replace=[] + ), + + PeepholeRule( + match=[ + Instruction("mov", ["x", "y"]), + Instruction("add", ["z", "x"]) + ], + replace=[ + Instruction("add", ["z", "y"]) + ] + ), + PeepholeRule( + match=[ + Instruction("add", ["x", "0"]) + ], + replace=[] + ), + + PeepholeRule( + match=[Instruction("mov", ["x", "x"])], + replace=[] ) ] \ No newline at end of file diff --git a/out b/out deleted file mode 100644 index 7e88acafc7885d808ab36ba76002fb3a6346b1ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4712 zcmeHLu}Z{15S_$C&O(eT06BCZ zc54brtxdj5F5?c5*HmMK%oBJ> diff --git a/out.asm b/out.asm index bc1b03f..49492d4 100644 --- a/out.asm +++ b/out.asm @@ -1,23 +1,52 @@ ; ~~~ Auto generated by the GroundPY compiler for Linux x86_64 targets. ~~~ section .data +.LC0: db "test of returning strings INSIDE a variable!", 10, 0 +.LC1: equ $ - .LC0 section .text global _start _start: +; FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, String]), InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=RootNode(statements=[..., InstructionNode(instruction='endfun', parent=..., arguments=[]), FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=..., return_type='int', name='function2'), InstructionNode(instruction='endfun', parent=..., arguments=[]), InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), InstructionNode(instruction='stdout', parent=..., arguments=[VariableReference]), InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), InstructionNode(instruction='end', parent=..., arguments=[VariableReference])]), return_type='string', name='idk') +; InstructionNode(instruction='endfun', parent=RootNode(statements=[FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, String]), InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=..., return_type='string', name='idk'), ..., FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=..., return_type='int', name='function2'), InstructionNode(instruction='endfun', parent=..., arguments=[]), InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), InstructionNode(instruction='stdout', parent=..., arguments=[VariableReference]), InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), InstructionNode(instruction='end', parent=..., arguments=[VariableReference])]), arguments=[]) +; FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=RootNode(statements=[FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, String]), InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=..., return_type='string', name='idk'), InstructionNode(instruction='endfun', parent=..., arguments=[]), ..., InstructionNode(instruction='endfun', parent=..., arguments=[]), InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), InstructionNode(instruction='stdout', parent=..., arguments=[VariableReference]), InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), InstructionNode(instruction='end', parent=..., arguments=[VariableReference])]), return_type='int', name='function2') +; InstructionNode(instruction='endfun', parent=RootNode(statements=[FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, String]), InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=..., return_type='string', name='idk'), InstructionNode(instruction='endfun', parent=..., arguments=[]), FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=..., return_type='int', name='function2'), ..., InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), InstructionNode(instruction='stdout', parent=..., arguments=[VariableReference]), InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), InstructionNode(instruction='end', parent=..., arguments=[VariableReference])]), arguments=[]) +; InstructionNode(instruction='call', parent=RootNode(statements=[FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, String]), InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=..., return_type='string', name='idk'), InstructionNode(instruction='endfun', parent=..., arguments=[]), FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=..., return_type='int', name='function2'), InstructionNode(instruction='endfun', parent=..., arguments=[]), ..., InstructionNode(instruction='stdout', parent=..., arguments=[VariableReference]), InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), InstructionNode(instruction='end', parent=..., arguments=[VariableReference])]), arguments=[FunctionCall, VariablePointer]) sub rsp, 8 -mov rdi, 2 -mov rsi, 3 -call add -add rsp, 16 -push rax -mov rax, 60 -mov rdi, [rsp + 0] +call idk +; InstructionNode(instruction='stdout', parent=RootNode(statements=[FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, String]), InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=..., return_type='string', name='idk'), InstructionNode(instruction='endfun', parent=..., arguments=[]), FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=..., return_type='int', name='function2'), InstructionNode(instruction='endfun', parent=..., arguments=[]), InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), ..., InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), InstructionNode(instruction='end', parent=..., arguments=[VariableReference])]), arguments=[VariableReference]) +mov rsi, rax +push rdi +mov rax, 1 +mov rdi, 1 syscall -add: +pop rdi +; InstructionNode(instruction='call', parent=RootNode(statements=[FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, String]), InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=..., return_type='string', name='idk'), InstructionNode(instruction='endfun', parent=..., arguments=[]), FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=..., return_type='int', name='function2'), InstructionNode(instruction='endfun', parent=..., arguments=[]), InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), InstructionNode(instruction='stdout', parent=..., arguments=[VariableReference]), ..., InstructionNode(instruction='end', parent=..., arguments=[VariableReference])]), arguments=[FunctionCall, VariablePointer]) +call function2 +; InstructionNode(instruction='end', parent=RootNode(statements=[FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, String]), InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=..., return_type='string', name='idk'), InstructionNode(instruction='endfun', parent=..., arguments=[]), FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=..., return_type='int', name='function2'), InstructionNode(instruction='endfun', parent=..., arguments=[]), InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), InstructionNode(instruction='stdout', parent=..., arguments=[VariableReference]), InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), ...]), arguments=[VariableReference]) +mov rax, 60 +mov rdi, rax +syscall +idk: push rbp mov rbp, rsp -mov rax, rdi -mov rbx, rsi -add rax, rbx +; InstructionNode(instruction='set', parent=FunctionNode(args=[], statements=[..., InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=RootNode(statements=[..., InstructionNode(instruction='endfun', parent=..., arguments=[]), FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=..., return_type='int', name='function2'), InstructionNode(instruction='endfun', parent=..., arguments=[]), InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), InstructionNode(instruction='stdout', parent=..., arguments=[VariableReference]), InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), InstructionNode(instruction='end', parent=..., arguments=[VariableReference])]), return_type='string', name='idk'), arguments=[VariablePointer, String]) +lea rax, [.LC0] +push rax +push .LC1 +; InstructionNode(instruction='return', parent=FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, String]), ...], parent=RootNode(statements=[..., InstructionNode(instruction='endfun', parent=..., arguments=[]), FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=..., return_type='int', name='function2'), InstructionNode(instruction='endfun', parent=..., arguments=[]), InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), InstructionNode(instruction='stdout', parent=..., arguments=[VariableReference]), InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), InstructionNode(instruction='end', parent=..., arguments=[VariableReference])]), return_type='string', name='idk'), arguments=[VariableReference]) +mov rax, [rsp + 8] +mov rdx, [rsp + 0] +pop rbp +pop rbp +pop rbp +ret +function2: +push rbp +mov rbp, rsp +; InstructionNode(instruction='set', parent=FunctionNode(args=[], statements=[..., InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=RootNode(statements=[FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, String]), InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=..., return_type='string', name='idk'), InstructionNode(instruction='endfun', parent=..., arguments=[]), ..., InstructionNode(instruction='endfun', parent=..., arguments=[]), InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), InstructionNode(instruction='stdout', parent=..., arguments=[VariableReference]), InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), InstructionNode(instruction='end', parent=..., arguments=[VariableReference])]), return_type='int', name='function2'), arguments=[VariablePointer, Int]) +push 123 +; InstructionNode(instruction='return', parent=FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), ...], parent=RootNode(statements=[FunctionNode(args=[], statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, String]), InstructionNode(instruction='return', parent=..., arguments=[VariableReference])], parent=..., return_type='string', name='idk'), InstructionNode(instruction='endfun', parent=..., arguments=[]), ..., InstructionNode(instruction='endfun', parent=..., arguments=[]), InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), InstructionNode(instruction='stdout', parent=..., arguments=[VariableReference]), InstructionNode(instruction='call', parent=..., arguments=[FunctionCall, VariablePointer]), InstructionNode(instruction='end', parent=..., arguments=[VariableReference])]), return_type='int', name='function2'), arguments=[VariableReference]) +mov rax, [rsp + 0] +pop rbp pop rbp ret diff --git a/test2.grnd b/test2.grnd index 093e48d..6c21404 100644 --- a/test2.grnd +++ b/test2.grnd @@ -1,9 +1,14 @@ -fun -int !add -int &x -int &y - add $x $y &x - return $x +fun -string !idk + set &var "test of returning strings INSIDE a variable!\n" + return $var endfun -pusharg 2 -pusharg 3 -call !add &var -end $var \ No newline at end of file +fun -int !function2 + set &intvar 123 + return $intvar +endfun + +call !idk &var +stdout $var +call !function2 &lol +end $lol \ No newline at end of file