diff --git a/a.out b/a.out index 193e800..43fbe8b 100644 Binary files a/a.out and b/a.out differ diff --git a/generators/x86_64.py b/generators/x86_64.py index 1316760..db3d5e9 100644 --- a/generators/x86_64.py +++ b/generators/x86_64.py @@ -23,7 +23,7 @@ class X86_64Generator(Generator): self.lines.append("pop " + reg + "\n\t") self.stack_size -= 1 - def get_variable(self, var_name: str, reg: str, float: bool = False, offset: int = 0, no_stack_pop: bool = False): + def get_variable(self, var_name: str, reg: str, float: bool = False, offset: int = 0, no_stack_pop: bool = True): var = self.variables.get(var_name, None) var_pos = self.get_var_pos(var_name) try: @@ -47,6 +47,14 @@ class X86_64Generator(Generator): f"QWORD [rsp + {var_pos + offset}]" ) self.pop(reg) + elif var["type"] == BoolNode: + if no_stack_pop: + self.lines.append(f"mov {reg}, [rsp + {var_pos + offset}]\n\t") + else: + self.push( + f"QWORD [rsp + {var_pos + offset}]" + ) + self.pop(reg) except TypeError: # variable doesnt exist traceback(self.code, "NameError", f"\"{var_name}\" is not defined.") @@ -93,6 +101,9 @@ class X86_64Generator(Generator): self.lines.append(f"mov rax, {string_len[1:-1]}\n\t") self.push("rax") + elif type(starting_value) == BoolNode: + self.push("1" if starting_value.value else "0") + elif type(starting_value) == str: if starting_value.startswith("xmm"): # floating point stuff self.lines.append("sub rsp, 8\n\t") # make space @@ -131,6 +142,10 @@ class X86_64Generator(Generator): self.variables[var_name]["type"] = StringNode + elif type(new_value) == BoolNode: + self.lines.append(f"mov QWORD [rsp + {var_pos}], {"1" if new_value.value else "0"}\n\t") + self.variables[var_name]["type"] = BoolNode + elif type(new_value) == str: # we're changing a variable to the value of a register self.lines.append(f"mov QWORD [rsp + {var_pos}], {new_value}\n\t") self.variables[var_name]["type"] = IntNode @@ -150,14 +165,14 @@ class X86_64Generator(Generator): traceback(self.code, "TypeError", f"end expects an integer, not {node.arguments[0]}") self.lines.append("mov rax, 60\n\t") - if isinstance(node.arguments[0], IntNode): + if type(node.arguments[0]) in [IntNode,BoolNode]: self.lines.append("mov rdi, " + str(node.arguments[0].value) + "\n\t") elif isinstance(node.arguments[0], VarRefNode): var_type = self.get_variable(node.arguments[0].var_name, "rdi", no_stack_pop=True) if var_type == FloatNode: self.lines.append("cvttsd2si rdi, xmm0\n\t") else: - if var_type != IntNode: + if var_type not in [IntNode,BoolNode]: traceback(self.code, "TypeError", f"end expects an integer, not \"{var_type}\"") #self.lines.append("mov rdi, " + str(self.get_variable(node.arguments[0].var_name)) + "\n\t") self.lines.append("syscall\n\t") @@ -170,7 +185,7 @@ class X86_64Generator(Generator): traceback(self.code, "TypeError", "set expects only 2 arguments.") if not isinstance(node.arguments[0], VarPointerNode): traceback(self.code, "TypeError", f"the first argument of set should be a variable pointer, not \"{node.arguments[0]}\"") - if type(node.arguments[1]) not in [IntNode, VarRefNode, FloatNode, StringNode]: + 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 @@ -420,10 +435,138 @@ class X86_64Generator(Generator): traceback(self.code, "TypeError", f"jump expects a label reference as the first argument, not \"{node.arguments[0]}\"") self.lines.append(f"jmp .{node.arguments[0].name}\n\t") + + elif node.instruction == "if": + if len(node.arguments) != 2: # example: "jump" or "jump $bool" + traceback(self.code, "TypeError", "if expects exactly 2 arguments.") + elif not type(node.arguments[0]) in [VarRefNode,BoolNode,StringNode,FloatNode,IntNode]: + traceback(self.code, "TypeError", f"if expects a value or variable refernce as the first argument, not \"{node.arguments[0]}\"") + elif not isinstance(node.arguments[1], LabelRefNode): + traceback(self.code, "TypeError", f"if expects a label reference as the second argument, not \"{node.arguments[1]}\"") + + + if isinstance(node.arguments[0], BoolNode): + if node.arguments[0].value: + self.lines.append(f"jmp .{node.arguments[1].name}\n\t") + #self.lines.append("mov eax, 1") + #self.lines.append(f"cmp eax, {1 if node.arguments[0].value else 0}") + elif type(node.arguments[0]) in [IntNode,FloatNode]: + if node.arguments[0].value != 0: + self.lines.append(f"jmp .{node.arguments[1].name}\n\t") + elif isinstance(node.arguments[0], VarRefNode): + self.get_variable(node.arguments[0].var_name, "eax") + self.lines.append(f"test eax, eax\n\t") + self.lines.append(f"jnz .{node.arguments[1].name}\n\t") + + elif node.instruction == "equal": + if len(node.arguments) != 3: # example: "equal" or "equal $bool" + traceback(self.code, "TypeError", "equal expects exactly 3 arguments.") + elif not type(node.arguments[0]) in [VarRefNode,BoolNode,FloatNode,IntNode]: + traceback(self.code, "TypeError", f"equal expects a value or variable refernce as the first argument, not \"{node.arguments[0].__repr__()}\"") + elif not type(node.arguments[1]) in [VarRefNode,BoolNode,FloatNode,IntNode]: + traceback(self.code, "TypeError", f"equal expects a value or variable refernce as the second argument, not \"{node.arguments[1].__repr__()}\"") + elif not isinstance(node.arguments[2], VarPointerNode): + traceback(self.code, "TypeError", f"the third argument of equal should be a variable pointer, not \"{node.arguments[2].__repr__()}\"") + + arg1 = None + arg2 = None + + if isinstance(node.arguments[0], BoolNode): + self.lines.append(f"mov rax, {int(node.arguments[0].value)}\n\t") + arg1 = "rax" + elif isinstance(node.arguments[0], IntNode): + self.lines.append(f"mov rax, {node.arguments[0].value}\n\t") + arg1 = "rax" + elif isinstance(node.arguments[0], FloatNode): + const_name = self.add_constant(node.arguments[0].value) + self.lines.append(f"movsd xmm0, {const_name}\n\t") + arg1 = "xmm0" + elif isinstance(node.arguments[0], VarRefNode): + self.get_variable(node.arguments[0].var_name, "rax") + arg1 = "rax" + + if isinstance(node.arguments[1], BoolNode): + self.lines.append(f"mov rbx, {int(node.arguments[1].value)}\n\t") + arg2 = "rbx" + elif isinstance(node.arguments[1], IntNode): + self.lines.append(f"mov rbx, {node.arguments[1].value}\n\t") + arg2 = "rbx" + elif isinstance(node.arguments[1], FloatNode): + const_name = self.add_constant(node.arguments[1].value) + self.lines.append(f"movsd xmm1, {const_name}\n\t") + arg2 = "xmm1" + elif isinstance(node.arguments[1], VarRefNode): + self.get_variable(node.arguments[1].var_name, "rbx") + arg2 = "rbx" + + self.lines.append(f"cmp {arg1}, {arg2}\n\t") + self.lines.append("sete al\n\t") + self.lines.append("movzx rax, al\n\t") + + var_name = node.arguments[2].var_name + if self.variables.get(var_name, None) == None: + self.create_variable(var_name, "rax", BoolNode) + else: + self.change_variable(var_name, "rax") + + elif node.instruction == "inequal": + if len(node.arguments) != 3: # example: "inequal" or "inequal $bool" + traceback(self.code, "TypeError", "inequal expects exactly 3 arguments.") + elif not type(node.arguments[0]) in [VarRefNode,BoolNode,FloatNode,IntNode]: + traceback(self.code, "TypeError", f"inequal expects a value or variable refernce as the first argument, not \"{node.arguments[0].__repr__()}\"") + elif not type(node.arguments[1]) in [VarRefNode,BoolNode,FloatNode,IntNode]: + traceback(self.code, "TypeError", f"inequal expects a value or variable refernce as the second argument, not \"{node.arguments[1].__repr__()}\"") + elif not isinstance(node.arguments[2], VarPointerNode): + traceback(self.code, "TypeError", f"the third argument of inequal should be a variable pointer, not \"{node.arguments[2].__repr__()}\"") + + arg1 = None + arg2 = None + + if isinstance(node.arguments[0], BoolNode): + self.lines.append(f"mov rax, {int(node.arguments[0].value)}\n\t") + arg1 = "rax" + elif isinstance(node.arguments[0], IntNode): + self.lines.append(f"mov rax, {node.arguments[0].value}\n\t") + arg1 = "rax" + elif isinstance(node.arguments[0], FloatNode): + const_name = self.add_constant(node.arguments[0].value) + self.lines.append(f"movsd xmm0, {const_name}\n\t") + arg1 = "xmm0" + elif isinstance(node.arguments[0], VarRefNode): + self.get_variable(node.arguments[0].var_name, "rax") + arg1 = "rax" + + if isinstance(node.arguments[1], BoolNode): + self.lines.append(f"mov rbx, {int(node.arguments[1].value)}\n\t") + arg2 = "rbx" + elif isinstance(node.arguments[1], IntNode): + self.lines.append(f"mov rbx, {node.arguments[1].value}\n\t") + arg2 = "rbx" + elif isinstance(node.arguments[1], FloatNode): + const_name = self.add_constant(node.arguments[1].value) + self.lines.append(f"movsd xmm1, {const_name}\n\t") + arg2 = "xmm1" + elif isinstance(node.arguments[1], VarRefNode): + self.get_variable(node.arguments[1].var_name, "rbx") + arg2 = "rbx" + + self.lines.append(f"cmp {arg1}, {arg2}\n\t") + self.lines.append("setne al\n\t") + self.lines.append("movzx rax, al\n\t") + + var_name = node.arguments[2].var_name + if self.variables.get(var_name, None) == None: + self.create_variable(var_name, "rax", BoolNode) + else: + self.change_variable(var_name, "rax") + else: self.lines.append("; FUCK\n\t") #raise NotImplementedError(f"A generate method hasn't been made for the \"{node.instruction}\" instruction.") + + + def write(self): with open(self.output_path + ".asm", "w") as f: diff --git a/main.py b/main.py index 40e198c..d3dd979 100644 --- a/main.py +++ b/main.py @@ -27,14 +27,15 @@ def main(): traceback(code, "fatal error", f"unkown architecture \"{arch}\"") generator.init() - compile_time = time()-start - print(f"Compiled in {round(compile_time, 3)} seconds.") system(f"nasm -felf64 {out_path}.asm") system(f"ld -m elf_{arch} -o {out_path} {out_path}.o") remove(out_path + ".o") #remove(out_path + ".asm") + compile_time = time()-start + print(f"Compiled in {round(compile_time, 3)} seconds.") + if __name__ == "__main__": main() diff --git a/out b/out index e04ac58..b48ed60 100644 Binary files a/out and b/out differ diff --git a/out.asm b/out.asm index ddd38ec..e4e68af 100644 --- a/out.asm +++ b/out.asm @@ -4,8 +4,39 @@ section .data section .text global _start _start: + ; InstructionNode(instruction='set', parent=RootNode(statements=[..., InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Boolean]), LabelDecleration, InstructionNode(instruction='add', parent=..., arguments=[Int, VariableReference, VariablePointer]), InstructionNode(instruction='add', parent=..., arguments=[Int, VariableReference, VariablePointer]), InstructionNode(instruction='inequal', parent=..., arguments=[Int, VariableReference, VariablePointer]), InstructionNode(instruction='if', parent=..., arguments=[VariableReference, LabelReference]), InstructionNode(instruction='end', parent=..., arguments=[VariableReference])]), arguments=[VariablePointer, Int]) + mov rax, 0 + push rax + ; InstructionNode(instruction='set', parent=RootNode(statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), ..., InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Boolean]), LabelDecleration, InstructionNode(instruction='add', parent=..., arguments=[Int, VariableReference, VariablePointer]), InstructionNode(instruction='add', parent=..., arguments=[Int, VariableReference, VariablePointer]), InstructionNode(instruction='inequal', parent=..., arguments=[Int, VariableReference, VariablePointer]), InstructionNode(instruction='if', parent=..., arguments=[VariableReference, LabelReference]), InstructionNode(instruction='end', parent=..., arguments=[VariableReference])]), arguments=[VariablePointer, Int]) + mov rax, 0 + push rax + ; InstructionNode(instruction='set', parent=RootNode(statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), ..., LabelDecleration, InstructionNode(instruction='add', parent=..., arguments=[Int, VariableReference, VariablePointer]), InstructionNode(instruction='add', parent=..., arguments=[Int, VariableReference, VariablePointer]), InstructionNode(instruction='inequal', parent=..., arguments=[Int, VariableReference, VariablePointer]), InstructionNode(instruction='if', parent=..., arguments=[VariableReference, LabelReference]), InstructionNode(instruction='end', parent=..., arguments=[VariableReference])]), arguments=[VariablePointer, Boolean]) + push 1 ; LabelDecleration - .myLabel: - ; InstructionNode(instruction='jump', parent=RootNode(statements=[LabelDecleration, ...]), arguments=[LabelReference]) - jmp .myLabel + .loop: + ; InstructionNode(instruction='add', parent=RootNode(statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Boolean]), LabelDecleration, ..., InstructionNode(instruction='add', parent=..., arguments=[Int, VariableReference, VariablePointer]), InstructionNode(instruction='inequal', parent=..., arguments=[Int, VariableReference, VariablePointer]), InstructionNode(instruction='if', parent=..., arguments=[VariableReference, LabelReference]), InstructionNode(instruction='end', parent=..., arguments=[VariableReference])]), arguments=[Int, VariableReference, VariablePointer]) + mov rax, 1 + mov rbx, [rsp + 16] + add rax, rbx + mov QWORD [rsp + 16], rax + ; InstructionNode(instruction='add', parent=RootNode(statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Boolean]), LabelDecleration, InstructionNode(instruction='add', parent=..., arguments=[Int, VariableReference, VariablePointer]), ..., InstructionNode(instruction='inequal', parent=..., arguments=[Int, VariableReference, VariablePointer]), InstructionNode(instruction='if', parent=..., arguments=[VariableReference, LabelReference]), InstructionNode(instruction='end', parent=..., arguments=[VariableReference])]), arguments=[Int, VariableReference, VariablePointer]) + mov rax, 1 + mov rbx, [rsp + 8] + add rax, rbx + mov QWORD [rsp + 8], rax + ; InstructionNode(instruction='inequal', parent=RootNode(statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Boolean]), LabelDecleration, InstructionNode(instruction='add', parent=..., arguments=[Int, VariableReference, VariablePointer]), InstructionNode(instruction='add', parent=..., arguments=[Int, VariableReference, VariablePointer]), ..., InstructionNode(instruction='if', parent=..., arguments=[VariableReference, LabelReference]), InstructionNode(instruction='end', parent=..., arguments=[VariableReference])]), arguments=[Int, VariableReference, VariablePointer]) + mov rax, 100000 + mov rbx, [rsp + 16] + cmp rax, rbx + setne al + movzx rax, al + mov QWORD [rsp + 0], rax + ; InstructionNode(instruction='if', parent=RootNode(statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Boolean]), LabelDecleration, InstructionNode(instruction='add', parent=..., arguments=[Int, VariableReference, VariablePointer]), InstructionNode(instruction='add', parent=..., arguments=[Int, VariableReference, VariablePointer]), InstructionNode(instruction='inequal', parent=..., arguments=[Int, VariableReference, VariablePointer]), ..., InstructionNode(instruction='end', parent=..., arguments=[VariableReference])]), arguments=[VariableReference, LabelReference]) + mov eax, [rsp + 0] + test eax, eax + jnz .loop + ; InstructionNode(instruction='end', parent=RootNode(statements=[InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Int]), InstructionNode(instruction='set', parent=..., arguments=[VariablePointer, Boolean]), LabelDecleration, InstructionNode(instruction='add', parent=..., arguments=[Int, VariableReference, VariablePointer]), InstructionNode(instruction='add', parent=..., arguments=[Int, VariableReference, VariablePointer]), InstructionNode(instruction='inequal', parent=..., arguments=[Int, VariableReference, VariablePointer]), InstructionNode(instruction='if', parent=..., arguments=[VariableReference, LabelReference]), ...]), arguments=[VariableReference]) + mov rax, 60 + mov rdi, [rsp + 8] + syscall \ No newline at end of file diff --git a/test b/test deleted file mode 100644 index 3cd4628..0000000 Binary files a/test and /dev/null differ diff --git a/test.c b/test.c index 23704de..43e6f6a 100644 --- a/test.c +++ b/test.c @@ -1,5 +1,7 @@ -#include int main() { - printf("Hello, World!\n"); - return 0; + int lol = 0; + for (int i = 0; i != 100000000; i++) { + lol++; + } + return lol; } \ No newline at end of file diff --git a/test.o b/test.o deleted file mode 100644 index 19dab46..0000000 Binary files a/test.o and /dev/null differ diff --git a/test.s b/test.s deleted file mode 100644 index 079e309..0000000 --- a/test.s +++ /dev/null @@ -1,45 +0,0 @@ - .file "test.c" - .text - .section .rodata -.LC0: - .string "Hello, World!" - .text - .globl main - .type main, @function -main: -.LFB0: - .cfi_startproc - endbr64 - pushq %rbp - .cfi_def_cfa_offset 16 - .cfi_offset 6, -16 - movq %rsp, %rbp - .cfi_def_cfa_register 6 - leaq .LC0(%rip), %rax - movq %rax, %rdi - call puts@PLT - movl $0, %eax - popq %rbp - .cfi_def_cfa 7, 8 - ret - .cfi_endproc -.LFE0: - .size main, .-main - .ident "GCC: (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0" - .section .note.GNU-stack,"",@progbits - .section .note.gnu.property,"a" - .align 8 - .long 1f - 0f - .long 4f - 1f - .long 5 -0: - .string "GNU" -1: - .align 8 - .long 0xc0000002 - .long 3f - 2f -2: - .long 0x3 -3: - .align 8 -4: diff --git a/test2.grnd b/test2.grnd index 9f706fb..6d6022f 100644 --- a/test2.grnd +++ b/test2.grnd @@ -1,2 +1,9 @@ -@myLabel -jump %myLabel \ No newline at end of file +set &var 0 +set &lol 0 +set &cond true +@loop +add 1 $var &var +add 1 $lol &lol +inequal 100000000 $var &cond +if $cond %loop +end $lol \ No newline at end of file