Skip to content

Commit

Permalink
assembly now
Browse files Browse the repository at this point in the history
  • Loading branch information
ibx34 committed Dec 19, 2024
1 parent f1c4e03 commit a6d0cc0
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 87 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@
- `m'` and `t'` are "prime forms". open issue for naming ideas or concerns! More on these later:tm:


as -o whatever.o whatever.s && ld -macosx_version_min 13.0.0 -o whatever whatever.o -lSystem -syslibroot `xcrun -sdk macosx --show-sdk-path` -e main -arch arm64
as -o whatever.o whatever.s && ld -macosx_version_min 13.0.0 -o whatever whatever.o -lSystem -syslibroot `xcrun -sdk macosx --show-sdk-path` -e _start -arch arm64
92 changes: 70 additions & 22 deletions asm.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,78 @@
from ast_exprs import Assignment, AstirExpr, Identifier, Lambda, Symbol # type: ignore
from common import Cursor
from ast_exprs import Assignment, AstirExpr, Identifier, Lambda, Literal, Reference, ShuntingYardAlgorithmResults, Symbol, SymbolTable # type: ignore
from common import Cursor, PrimitiveTypes


class ASM(Cursor):
def __init__(self, input: list[AstirExpr]) -> None:
def __init__(
self, input: list[AstirExpr], symbol_tables: dict[int, SymbolTable]
) -> None:
super().__init__(input)
self.lines: list[str] = [".global _start", ".p2align 3"]
self.lines: list[str] = [".global main", ".p2align 3"]
self.symbol_tables: dict[int, SymbolTable] = symbol_tables
# Format (ref_id, register)
self.ref_id_and_register: list[tuple[int, int]] = []
self.current_usable_register = 0

def generate(self) -> None:
c_expr = self.current()
def lookup_symbol(self, symbol_table: int, symbol_id: int) -> Symbol | None:
if symbol_table not in self.symbol_tables:
return None
_symbol_table: SymbolTable | None = self.symbol_tables[symbol_table]
if _symbol_table is None:
return None
symbol = _symbol_table.lookup_by_id(symbol_id)
return symbol

def generate(self, expr: AstirExpr | None = None) -> list[str]:
c_expr = self.current() if expr is None else expr
to_add: list[str] = []
if isinstance(c_expr, Assignment):
if isinstance(c_expr.right, Lambda) and isinstance(c_expr.left, Identifier):
lambda_def = c_expr.right.definition
parameters_to_registers: dict[str, str] = {}
last_reg = 0
for k in lambda_def.parameters.symbols.keys():
parameter = lambda_def.parameters.symbols.get(k)
if parameter is None or not isinstance(parameter, Symbol):
break
elif parameter.name == "ret":
continue
parameters_to_registers[parameter.name] = f"X{last_reg}"
last_reg += 1
# -1 to get rid of the return type. the length in the name may be temporary :)
self.lines.append(
f"{c_expr.left.value}_{len(lambda_def.parameters.symbols.keys())-1}:"
to_add.append(f"{c_expr.left.value}:")
print(f"Being added: {to_add}")
generated_body = self.generate(c_expr.right.body)
print(f"Generated body -> {generated_body}")
to_add.extend(generated_body)
to_add.append("ret")
self.lines.extend(to_add)
elif isinstance(c_expr, Reference):
symbol = self.lookup_symbol(c_expr.belongs_to, c_expr.symbol_id)
if symbol is None:
raise Exception("failed to lookup symbol")
if isinstance(symbol.val, Reference):
symbol2 = self.lookup_symbol(
symbol.val.belongs_to, symbol.val.symbol_id
)
pass
return None
register = self.current_usable_register
self.ref_id_and_register.append((symbol.val.symbol_id, register))
to_add.append(f"x{register}") # Temp
self.current_usable_register += 1
elif isinstance(c_expr, ShuntingYardAlgorithmResults):
if len(c_expr.oeprators) > 0:
raise Exception("Invalid shunting yard algorithm")
stack: list[str] = []
c_expr.results.reverse()
while len(c_expr.results) > 0 and (term := c_expr.results.pop()):
# TODO: make some like class method or something
# to make this cleaner??
if isinstance(term, Reference):
stack.extend(self.generate(term))
elif isinstance(term, Literal):
if term.ty != PrimitiveTypes.INT:
raise Exception("Unexpected type.")
stack.append(str(term.val))
elif isinstance(term, str):
if term == "+":
stack.reverse()
(item1, item2) = (stack.pop(), stack.pop())
if not item1.startswith("x"):
register = self.current_usable_register
to_add.append(f"mov x{register}, {item1}")
item1 = f"x{register}"
self.current_usable_register += 1
print(
f"Adding last two items on stack: {item1}, {item2} = {item1 + item2}"
)
to_add.append(f"add x0, {item1}, {item2}")

print(f"{c_expr}")
return to_add
6 changes: 3 additions & 3 deletions ast_1.py
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ def parse(self) -> AstirExpr | None:
# for parsing arithmetic
self.op_stack.append(possible_op[0])
self.already_parsing_sya = True
res: list[AstirExpr] = [result]
res: list[AstirExpr | str] = [result]
while True:
c = self.current()
possible_op = get_op(c)
Expand All @@ -504,8 +504,8 @@ def parse(self) -> AstirExpr | None:
self.at -= 1
break
res.append(parsed)

sya_res = ShuntingYardAlgorithmResults(self.op_stack, res)
res.extend(self.op_stack)
self.op_stack = []
sya_res = ShuntingYardAlgorithmResults(self.op_stack, res)
self.already_parsing_sya = False
return sya_res # type: ignore
2 changes: 1 addition & 1 deletion ast_exprs.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def __repr__(self) -> str:


class ShuntingYardAlgorithmResults(AstirExpr):
def __init__(self, operators: list[str], results: list[AstirExpr]) -> None:
def __init__(self, operators: list[str], results: list[AstirExpr | str]) -> None:
super().__init__(PrimitiveTypes.UNIT)
self.oeprators = operators
self.results = results
Expand Down
2 changes: 1 addition & 1 deletion boot.dal
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
take_int_and_add_2\ x int :: int → x + 2

main\ :: int → take_int_and_add_2 2
_start\ :: int → take_int_and_add_2 2
9 changes: 6 additions & 3 deletions boot.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from asm import ASM
from ast_1 import Parser, Lexer # type: ignore
from ast_1 import Parser, Lexer # type: ignore

#from asm import ASM # type: ignore
# from asm import ASM # type: ignore


def run():
Expand All @@ -12,9 +12,12 @@ def run():
parser = Parser(lexer.results)
parser.parse_all()
print(f"{parser.results}\n\n")
code_generator = ASM(parser.results)
code_generator = ASM(parser.results, parser.symbol_tables)
code_generator.generate()
code_generator.advance()
code_generator.generate()
print(f"{code_generator.lines}")
open("boot.s", "w+").write("\n".join(code_generator.lines))


if __name__ == "__main__":
Expand Down
68 changes: 12 additions & 56 deletions whatever.s
Original file line number Diff line number Diff line change
@@ -1,70 +1,26 @@
// Assembler program to print "Hello World!"
// to stdout.
//
// X0-X2 - parameters to linux function services
// X16 - linux function number
//
.global _start // Provide program starting address to linker
.global _start
.p2align 3

_return_int:
add X1, X0, 2
mov X0, X1
add X0, X0, 2

ret

_start:
mov X0, 2
bl _return_int // This take the 2 from X0 and adds 2 to it
cmp X0, 4 // We want to check if the rseult from _return_in
// is eq to 4
bl _return_int
cmp X0, 4
b.eq print_hello_world

mov X0, #0 // Use 0 return code
mov X16, #1 // Service command code 1 terminates this program
svc 0 // Call MacOS to terminate the program
mov X0, #0
mov X16, #1
svc 0

// Setup the parameters to print hello world
// and then call Linux to do it.
print_hello_world: mov X0, #1 // 1 = StdOut
adr X1, helloworld // string to print
mov X2, #13 // length of our string
mov X16, #4 // MacOS write system call
svc 0 // Call linux to output the string
print_hello_world: mov X0, #1
adr X1, helloworld
mov X2, #13
mov X16, #4
svc 0
ret

; print_goodbye: mov X0, #1 // 1 = StdOut
; adr X1, goodbyeworld // string to print
; mov X2, #13 // length of our string
; mov X16, #4 // MacOS write system call
; svc 0 // Call linux to output the string
; ret

; _start: MOV X10, 1
; MOV X11, 4
; MOV X12, helloworld
; MOV X13, goodbyeworld
; ADD X9, X10, X11
; CMP X9, 3
; csel X12, X14, X13, EQ

; ; B.EQ print_hello_world
; ; B.NE print_goodbye

; mov X0, #1 // 1 = StdOut
; adr X1, X14 // string to print`
; mov X2, #13 // length of our string
; mov X16, #4 // MacOS write system call
; svc 0 // Call linux to output the string
/*
mov X0, #1 // 1 = StdOut
adr X1, 123 // string to print
mov X2, #3 // length of our string
mov X16, #4 // MacOS write system call
svc 0 // Call linux to output the string
*/
// Setup the parameters to exit the program
// and then call Linux to do it.

helloworld: .ascii "Hello World!\n" // 13

0 comments on commit a6d0cc0

Please sign in to comment.