feat: generate assembly from main

This commit is contained in:
Gleb Koval 2025-02-21 23:30:17 +00:00
parent 1ce36dd8da
commit 7f2870e340
Signed by: cyclane
GPG Key ID: 15E168A8B332382C
2 changed files with 6 additions and 159 deletions

View File

@ -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
}

View File

@ -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.*$",