diff --git a/generators/generator.py b/generators/generator.py index 5f2cc18..8c4927f 100644 --- a/generators/generator.py +++ b/generators/generator.py @@ -52,11 +52,11 @@ class Generator: def add_constant(self, value: Any, no_string: bool = False): existing_constant_name = self.constants_reverse.get(value, None) - if existing_constant_name != None: return f"[.{existing_constant_name}]" + if existing_constant_name != None: return f"[{existing_constant_name}]" self.constants["LC" + str(self.constant_counter)] = {"value": value, "no_string": no_string} self.constants_reverse[value] = "LC" + str(self.constant_counter) self.constant_counter += 1 - return "[.LC" + str(self.constant_counter-1) + "]" + return "[LC" + str(self.constant_counter-1) + "]" def add_function(self, node: FunctionNode): self.functions[node.name] = { diff --git a/generators/x86_64.py b/generators/x86_64.py index 6eb7c9a..cf77374 100644 --- a/generators/x86_64.py +++ b/generators/x86_64.py @@ -32,6 +32,14 @@ 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 + waste = { + "rax": "eax", + "rdi": "edi", + "rsi": "esi" + } + if waste[var_pos] == reg: # literally useless + return + if offset == 0: lines.append(f"mov {reg}, {var_pos}\n\t") elif offset == -8: @@ -248,7 +256,9 @@ class X86_64Generator(Generator): for inst in node.statements: #self.function_lines.append(f"; {inst}\n\t") - self.generate_InstructionNode(inst, self.function_lines) + node_type = str(type(inst))[19:-2] + getattr(self, f"generate_{node_type}")(inst, self.function_lines) + #self.generate_InstructionNode(inst, self.function_lines) def generate_InstructionNode(self, node: InstructionNode, lines = None): lines = lines or self.lines @@ -438,6 +448,7 @@ class X86_64Generator(Generator): if node.arguments[0].value != 0: lines.append(f"jmp .{node.arguments[1].name}\n\t") elif isinstance(node.arguments[0], VarRefNode): + self.current_var_scope.table[node.arguments[0].var_name]["used"] = True # putting a variable in an if statement means we're accessing it self.get_variable(lines, node.arguments[0].var_name, "eax") lines.append(f"test eax, eax\n\t") lines.append(f"jnz .{node.arguments[1].name}\n\t") @@ -491,7 +502,7 @@ class X86_64Generator(Generator): "lesser": "setl" } lines.append(f"{instructions[node.instruction]} al\n\t") - lines.append("movzx rax, al\n\t") + lines.append("movzx eax, al\n\t") var_name = node.arguments[2].var_name @@ -513,7 +524,7 @@ class X86_64Generator(Generator): if isinstance(node.arguments[0], IntNode): lines.append(f"mov rax, {node.arguments[0].value}") elif isinstance(node.arguments[0], BoolNode): - lines.append(f"mov rax, {int(node.arguments[0].value)}") + lines.append(f"mov eax, {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") @@ -526,10 +537,11 @@ class X86_64Generator(Generator): #self.push("rax", lines) elif isinstance(node.arguments[0], VarRefNode): 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"]) + elif var["type"] == BoolNode: + self.get_variable(self.function_lines, node.arguments[0].var_name, "eax", scope=func["scope"]) else: self.get_variable(self.function_lines, node.arguments[0].var_name, "rax", scope=func["scope"]) else: @@ -644,7 +656,7 @@ class X86_64Generator(Generator): f.write("section .data\n") for name, const in self.constants.items(): value = const["value"] - f.write("." + name + ": ") + f.write(name + ": ") value_type = type(value) if value_type == str: if not const["no_string"]: diff --git a/ground_ast.py b/ground_ast.py index 7544839..10af41a 100644 --- a/ground_ast.py +++ b/ground_ast.py @@ -128,6 +128,9 @@ def generate_ast(tokens: list[Token], code: str) -> RootNode: elif token.type == TokenType.LABEL_DECLERATION: if current_node: scope.statements.append(current_node) + if current_node_type == "func": + scope = current_node + current_node_type = None current_node = None scope.statements.append(LabelDecNode(token.value)) diff --git a/optimizers/x86_64.py b/optimizers/x86_64.py index 6b2c2e3..afbb251 100644 --- a/optimizers/x86_64.py +++ b/optimizers/x86_64.py @@ -161,5 +161,5 @@ class X86_64Optimizer(Optimizer): PeepholeRule( match=[Instruction("mov", ["x", "x"])], replace=[] - ) + ), ] \ No newline at end of file diff --git a/out b/out index 5957937..4c6a48b 100644 Binary files a/out and b/out differ diff --git a/out.asm b/out.asm index b95c86d..f101d66 100644 --- a/out.asm +++ b/out.asm @@ -1,19 +1,47 @@ ; ~~~ Auto generated by the GroundPY compiler for Linux x86_64 targets. ~~~ section .data +LC0: db "yep!", 10, 0 +LC1: equ $ - LC0 +LC2: db "nope...", 10, 0 +LC3: equ $ - LC2 section .text global _start _start: mov rdi, 1 -mov rsi, 4 -call add -mov rdi, rax +mov rsi, 3 +call greater +test eax, eax +jnz .yes +jmp .no +.yes: +mov rsi, LC0 +mov rdx, LC1 +push rdi +mov rax, 1 +mov rdi, 1 +syscall +pop rdi +mov rdi, 0 mov rax, 60 syscall -add: +.no: +mov rsi, LC2 +mov rdx, LC3 +push rdi +mov rax, 1 +mov rdi, 1 +syscall +pop rdi +mov rdi, 0 +mov rax, 60 +syscall +greater: push rbp mov rbp, rsp mov rax, rdi -add rax, rsi +cmp rax, rsi +setg al +movzx eax, al pop rbp ret diff --git a/test2.grnd b/test2.grnd index 164936e..21ebe6d 100644 --- a/test2.grnd +++ b/test2.grnd @@ -1,9 +1,17 @@ -fun -int !add -int &a -int &b - add $a $b &a - return $a +fun -bool !greater -int &x -int &y + greater $x $y &x + return $x endfun pusharg 1 -pusharg 4 -call !add &result -end $result \ No newline at end of file +pusharg 3 +call !greater &bigger + +if $bigger %yes +jump %no +@yes +stdout "yep!\n" +end 0 +@no +stdout "nope...\n" +end 0 \ No newline at end of file