fixing quite a few bugs

This commit is contained in:
SpookyDervish
2025-09-13 07:08:11 +10:00
parent 170272353c
commit 86d59a8177
7 changed files with 70 additions and 19 deletions

View File

@@ -52,11 +52,11 @@ class Generator:
def add_constant(self, value: Any, no_string: bool = False): def add_constant(self, value: Any, no_string: bool = False):
existing_constant_name = self.constants_reverse.get(value, None) 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["LC" + str(self.constant_counter)] = {"value": value, "no_string": no_string}
self.constants_reverse[value] = "LC" + str(self.constant_counter) self.constants_reverse[value] = "LC" + str(self.constant_counter)
self.constant_counter += 1 self.constant_counter += 1
return "[.LC" + str(self.constant_counter-1) + "]" return "[LC" + str(self.constant_counter-1) + "]"
def add_function(self, node: FunctionNode): def add_function(self, node: FunctionNode):
self.functions[node.name] = { self.functions[node.name] = {

View File

@@ -32,6 +32,14 @@ class X86_64Generator(Generator):
var_pos = self.get_var_pos(var_name, scope) var_pos = self.get_var_pos(var_name, scope)
if isinstance(var_pos, str): # in a reg, not on the stack 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: if offset == 0:
lines.append(f"mov {reg}, {var_pos}\n\t") lines.append(f"mov {reg}, {var_pos}\n\t")
elif offset == -8: elif offset == -8:
@@ -248,7 +256,9 @@ class X86_64Generator(Generator):
for inst in node.statements: 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) 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): def generate_InstructionNode(self, node: InstructionNode, lines = None):
lines = lines or self.lines lines = lines or self.lines
@@ -438,6 +448,7 @@ class X86_64Generator(Generator):
if node.arguments[0].value != 0: if node.arguments[0].value != 0:
lines.append(f"jmp .{node.arguments[1].name}\n\t") lines.append(f"jmp .{node.arguments[1].name}\n\t")
elif isinstance(node.arguments[0], VarRefNode): 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") self.get_variable(lines, node.arguments[0].var_name, "eax")
lines.append(f"test eax, eax\n\t") lines.append(f"test eax, eax\n\t")
lines.append(f"jnz .{node.arguments[1].name}\n\t") lines.append(f"jnz .{node.arguments[1].name}\n\t")
@@ -491,7 +502,7 @@ class X86_64Generator(Generator):
"lesser": "setl" "lesser": "setl"
} }
lines.append(f"{instructions[node.instruction]} al\n\t") 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 var_name = node.arguments[2].var_name
@@ -513,7 +524,7 @@ class X86_64Generator(Generator):
if isinstance(node.arguments[0], IntNode): if isinstance(node.arguments[0], IntNode):
lines.append(f"mov rax, {node.arguments[0].value}") lines.append(f"mov rax, {node.arguments[0].value}")
elif isinstance(node.arguments[0], BoolNode): 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): elif isinstance(node.arguments[0], FloatNode):
lines.append(f"mov xmm0, {node.arguments[0].value}") lines.append(f"mov xmm0, {node.arguments[0].value}")
#self.get_variable(lines, node.arguments[0].var_name, "rax") #self.get_variable(lines, node.arguments[0].var_name, "rax")
@@ -526,10 +537,11 @@ class X86_64Generator(Generator):
#self.push("rax", lines) #self.push("rax", lines)
elif isinstance(node.arguments[0], VarRefNode): elif isinstance(node.arguments[0], VarRefNode):
var = func_scope.lookup(node.arguments[0].var_name) var = func_scope.lookup(node.arguments[0].var_name)
if var["type"] == StringNode: 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, "rax", offset=0, scope=func["scope"])
self.get_variable(self.function_lines, node.arguments[0].var_name, "rdx", offset=-8, 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: else:
self.get_variable(self.function_lines, node.arguments[0].var_name, "rax", scope=func["scope"]) self.get_variable(self.function_lines, node.arguments[0].var_name, "rax", scope=func["scope"])
else: else:
@@ -644,7 +656,7 @@ class X86_64Generator(Generator):
f.write("section .data\n") f.write("section .data\n")
for name, const in self.constants.items(): for name, const in self.constants.items():
value = const["value"] value = const["value"]
f.write("." + name + ": ") f.write(name + ": ")
value_type = type(value) value_type = type(value)
if value_type == str: if value_type == str:
if not const["no_string"]: if not const["no_string"]:

View File

@@ -128,6 +128,9 @@ def generate_ast(tokens: list[Token], code: str) -> RootNode:
elif token.type == TokenType.LABEL_DECLERATION: elif token.type == TokenType.LABEL_DECLERATION:
if current_node: if current_node:
scope.statements.append(current_node) scope.statements.append(current_node)
if current_node_type == "func":
scope = current_node
current_node_type = None
current_node = None current_node = None
scope.statements.append(LabelDecNode(token.value)) scope.statements.append(LabelDecNode(token.value))

View File

@@ -161,5 +161,5 @@ class X86_64Optimizer(Optimizer):
PeepholeRule( PeepholeRule(
match=[Instruction("mov", ["x", "x"])], match=[Instruction("mov", ["x", "x"])],
replace=[] replace=[]
) ),
] ]

BIN
out

Binary file not shown.

38
out.asm
View File

@@ -1,19 +1,47 @@
; ~~~ Auto generated by the GroundPY compiler for Linux x86_64 targets. ~~~ ; ~~~ Auto generated by the GroundPY compiler for Linux x86_64 targets. ~~~
section .data section .data
LC0: db "yep!", 10, 0
LC1: equ $ - LC0
LC2: db "nope...", 10, 0
LC3: equ $ - LC2
section .text section .text
global _start global _start
_start: _start:
mov rdi, 1 mov rdi, 1
mov rsi, 4 mov rsi, 3
call add call greater
mov rdi, rax 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 mov rax, 60
syscall 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 push rbp
mov rbp, rsp mov rbp, rsp
mov rax, rdi mov rax, rdi
add rax, rsi cmp rax, rsi
setg al
movzx eax, al
pop rbp pop rbp
ret ret

View File

@@ -1,9 +1,17 @@
fun -int !add -int &a -int &b fun -bool !greater -int &x -int &y
add $a $b &a greater $x $y &x
return $a return $x
endfun endfun
pusharg 1 pusharg 1
pusharg 4 pusharg 3
call !add &result call !greater &bigger
end $result
if $bigger %yes
jump %no
@yes
stdout "yep!\n"
end 0
@no
stdout "nope...\n"
end 0