From 7f2870e340c633a36f965309b102c437041686c4 Mon Sep 17 00:00:00 2001 From: Gleb Koval Date: Fri, 21 Feb 2025 23:30:17 +0000 Subject: [PATCH] feat: generate assembly from main --- src/main/wacc/Main.scala | 162 +---------------------------------- src/test/wacc/examples.scala | 3 +- 2 files changed, 6 insertions(+), 159 deletions(-) diff --git a/src/main/wacc/Main.scala b/src/main/wacc/Main.scala index e8e7b7b..89cfd98 100644 --- a/src/main/wacc/Main.scala +++ b/src/main/wacc/Main.scala @@ -64,157 +64,8 @@ def frontend( } val s = "enter an integer to echo" -def backend(typedProg: microWacc.Program): List[asm.AsmLine] | String = - typedProg match { - case microWacc.Program( - Nil, - microWacc.Call(microWacc.Builtin.Exit, microWacc.IntLiter(v) :: Nil) :: Nil - ) => - s""".intel_syntax noprefix -.globl main -main: - mov edi, ${v} - call exit@plt -""" - case microWacc.Program( - Nil, - microWacc.Assign(microWacc.Ident("x", _), microWacc.IntLiter(1)) :: - microWacc.Call(microWacc.Builtin.Println, _) :: - microWacc.Assign( - microWacc.Ident("x", _), - microWacc.Call(microWacc.Builtin.ReadInt, Nil) - ) :: - microWacc.Call(microWacc.Builtin.Println, microWacc.Ident("x", _) :: Nil) :: Nil - ) => - """.intel_syntax noprefix -.globl main -.section .rodata -# length of .L.str0 - .int 24 -.L.str0: - .asciz "enter an integer to echo" -.text -main: - push rbp - # push {rbx, r12} - sub rsp, 16 - mov qword ptr [rsp], rbx - mov qword ptr [rsp + 8], r12 - mov rbp, rsp - mov r12d, 1 - lea rdi, [rip + .L.str0] - # statement primitives do not return results (but will clobber r0/rax) - call _prints - call _println - # load the current value in the destination of the read so it supports defaults - mov edi, r12d - call _readi - mov r12d, eax - mov edi, eax - # statement primitives do not return results (but will clobber r0/rax) - call _printi - call _println - mov rax, 0 - # pop/peek {rbx, r12} - mov rbx, qword ptr [rsp] - mov r12, qword ptr [rsp + 8] - add rsp, 16 - pop rbp - ret - -.section .rodata -# length of .L._printi_str0 - .int 2 -.L._printi_str0: - .asciz "%d" -.text -_printi: - push rbp - mov rbp, rsp - # external calls must be stack-aligned to 16 bytes, accomplished by masking with fffffffffffffff0 - and rsp, -16 - mov esi, edi - lea rdi, [rip + .L._printi_str0] - # on x86, al represents the number of SIMD registers used as variadic arguments - mov al, 0 - call printf@plt - mov rdi, 0 - call fflush@plt - mov rsp, rbp - pop rbp - ret - -.section .rodata -# length of .L._prints_str0 - .int 4 -.L._prints_str0: - .asciz "%.*s" -.text -_prints: - push rbp - mov rbp, rsp - # external calls must be stack-aligned to 16 bytes, accomplished by masking with fffffffffffffff0 - and rsp, -16 - mov rdx, rdi - mov esi, dword ptr [rdi - 4] - lea rdi, [rip + .L._prints_str0] - # on x86, al represents the number of SIMD registers used as variadic arguments - mov al, 0 - call printf@plt - mov rdi, 0 - call fflush@plt - mov rsp, rbp - pop rbp - ret - -.section .rodata -# length of .L._println_str0 - .int 0 -.L._println_str0: - .asciz "" -.text -_println: - push rbp - mov rbp, rsp - # external calls must be stack-aligned to 16 bytes, accomplished by masking with fffffffffffffff0 - and rsp, -16 - lea rdi, [rip + .L._println_str0] - call puts@plt - mov rdi, 0 - call fflush@plt - mov rsp, rbp - pop rbp - ret - -.section .rodata -# length of .L._readi_str0 - .int 2 -.L._readi_str0: - .asciz "%d" -.text -_readi: - push rbp - mov rbp, rsp - # external calls must be stack-aligned to 16 bytes, accomplished by masking with fffffffffffffff0 - and rsp, -16 - # RDI contains the "original" value of the destination of the read - # allocate space on the stack to store the read: preserve alignment! - # the passed default argument should be stored in case of EOF - sub rsp, 16 - mov dword ptr [rsp], edi - lea rsi, qword ptr [rsp] - lea rdi, [rip + .L._readi_str0] - # on x86, al represents the number of SIMD registers used as variadic arguments - mov al, 0 - call scanf@plt - mov eax, dword ptr [rsp] - add rsp, 16 - mov rsp, rbp - pop rbp - ret - """ - case _ => List() - } +def backend(typedProg: microWacc.Program): List[asm.AsmLine] = + asmGenerator.generateAsm(typedProg) def compile(filename: String, outFile: Option[File] = None)(using stdout: PrintStream = Console.out @@ -222,13 +73,8 @@ def compile(filename: String, outFile: Option[File] = None)(using frontend(os.read(os.Path(filename))) match { case Left(typedProg) => val asmFile = outFile.getOrElse(File(filename.stripSuffix(".wacc") + ".s")) - backend(typedProg) match { - case s: String => - os.write.over(os.Path(asmFile.getAbsolutePath), s) - case ops: List[asm.AsmLine] => { - writer.writeTo(ops, PrintStream(asmFile)) - } - } + val asm = backend(typedProg) + writer.writeTo(asm, PrintStream(asmFile)) 0 case Right(exitCode) => exitCode } diff --git a/src/test/wacc/examples.scala b/src/test/wacc/examples.scala index abff693..970bcb6 100644 --- a/src/test/wacc/examples.scala +++ b/src/test/wacc/examples.scala @@ -81,13 +81,14 @@ class ParallelExamplesSpec extends AnyFlatSpec with BeforeAndAfterAll with Paral // disable formatting to avoid binPack "^.*wacc-examples/valid/advanced.*$", "^.*wacc-examples/valid/array.*$", + "^.*wacc-examples/valid/basic/exit.*$", "^.*wacc-examples/valid/basic/skip.*$", "^.*wacc-examples/valid/expressions.*$", "^.*wacc-examples/valid/function/nested_functions.*$", "^.*wacc-examples/valid/function/simple_functions.*$", "^.*wacc-examples/valid/if.*$", "^.*wacc-examples/valid/IO/print.*$", - "^.*wacc-examples/valid/IO/read(?!echoInt\\.wacc).*$", + "^.*wacc-examples/valid/IO/read.*$", "^.*wacc-examples/valid/IO/IOLoop.wacc.*$", "^.*wacc-examples/valid/IO/IOSequence.wacc.*$", "^.*wacc-examples/valid/pairs.*$",