Add compile-expr/
This commit is contained in:
		
							parent
							
								
									a77da74da5
								
							
						
					
					
						commit
						689034a522
					
				
							
								
								
									
										3
									
								
								compile-expr/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								compile-expr/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,3 @@
 | 
			
		||||
expr
 | 
			
		||||
expr.o
 | 
			
		||||
expr.s
 | 
			
		||||
							
								
								
									
										8
									
								
								compile-expr/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								compile-expr/Makefile
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
			
		||||
expr: expr.o
 | 
			
		||||
	ld expr.o -o expr -l System -syslibroot `xcrun -sdk macosx --show-sdk-path` -e main -arch arm64
 | 
			
		||||
 | 
			
		||||
expr.o: expr.s
 | 
			
		||||
	as expr.s -o expr.o
 | 
			
		||||
 | 
			
		||||
expr.s: expr.ppp
 | 
			
		||||
	./expr.py expr.ppp > expr.s
 | 
			
		||||
							
								
								
									
										1
									
								
								compile-expr/expr.ppp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								compile-expr/expr.ppp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
(((a*b)+(c*d))*((e*f)+(g*h)))+(((i*j)+(k*l))*((m*n)+(o*p)))
 | 
			
		||||
							
								
								
									
										61
									
								
								compile-expr/expr.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										61
									
								
								compile-expr/expr.py
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,61 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
Generates the ARM64 Assembly for an executable that performs the given 
 | 
			
		||||
calculation and exits with that number as the exit code. It currently
 | 
			
		||||
only allows for multiplication and addition. You can check the output
 | 
			
		||||
modulo 256 using `echo $?`. The only defined variables are the letters
 | 
			
		||||
a-z, where they represent their 1-based index into the alphabet.
 | 
			
		||||
"""
 | 
			
		||||
 | 
			
		||||
import string
 | 
			
		||||
import sys, os; sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) # just becuase this is in a subdirectory
 | 
			
		||||
from ppp_lexer import *
 | 
			
		||||
from ppp_parser import *
 | 
			
		||||
 | 
			
		||||
_program, file_path = sys.argv
 | 
			
		||||
 | 
			
		||||
lexer = Lexer.from_file(file_path)
 | 
			
		||||
expr = parse_expression(lexer)
 | 
			
		||||
lexer.assert_token(EofToken())
 | 
			
		||||
 | 
			
		||||
def get_index(char: str) -> int:
 | 
			
		||||
	"""
 | 
			
		||||
	Assuming char is [a-z]
 | 
			
		||||
	"""
 | 
			
		||||
	return ord(char)-96
 | 
			
		||||
 | 
			
		||||
def get_stack_address(index: int) -> int:
 | 
			
		||||
	return 112-index*4
 | 
			
		||||
 | 
			
		||||
def to_asm(expr: Expression, *, taken: int=0):
 | 
			
		||||
	"""
 | 
			
		||||
	Generates the assembly using registers w0, w1, w2, ... as a stack.
 | 
			
		||||
 | 
			
		||||
	`taken` is how many registers are already taken by previous elements 'on the stack'
 | 
			
		||||
	"""
 | 
			
		||||
	if isinstance(expr, Variable):
 | 
			
		||||
		assert expr.name in string.ascii_lowercase
 | 
			
		||||
		address = get_stack_address(get_index(expr.name))
 | 
			
		||||
		print(f"\tldr w{taken}, [sp, {address}] // {expr.name}")
 | 
			
		||||
	else:
 | 
			
		||||
		match expr:
 | 
			
		||||
			case Addition():       word = 'add'
 | 
			
		||||
			case Multiplication(): word = 'mul'
 | 
			
		||||
			case _: assert False, f"Unimplemented: {expr}"
 | 
			
		||||
		to_asm(expr.lhs, taken=taken)
 | 
			
		||||
		to_asm(expr.rhs, taken=taken+1)
 | 
			
		||||
 | 
			
		||||
		print(f"\t{word} w{taken}, w{taken}, w{taken+1} // {expr.represent()}")
 | 
			
		||||
 | 
			
		||||
print(".global main")
 | 
			
		||||
print(".align 2")
 | 
			
		||||
print()
 | 
			
		||||
print("main:")
 | 
			
		||||
print("\tsub sp, sp, #112") # to fit 26*4=104 bytes. It seems that the sp should only be offset by 16 bytes at a time.
 | 
			
		||||
for i in range(1,27):
 | 
			
		||||
	print(f"\tmov w0, {i}")
 | 
			
		||||
	print(f"\tstr w0, [sp, {get_stack_address(i)}]")
 | 
			
		||||
to_asm(expr)
 | 
			
		||||
print("\tadd sp, sp, 112")
 | 
			
		||||
print("\tret")
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user