Implemented function calls

This commit is contained in:
2024-06-18 16:42:56 +02:00
parent 086998a0c3
commit 76db8feee3
11 changed files with 114 additions and 62 deletions

View File

@ -1,12 +1,18 @@
package build
import (
"git.akyoto.dev/cli/q/src/build/arch/x64"
"git.akyoto.dev/cli/q/src/build/asm"
"git.akyoto.dev/cli/q/src/build/os/linux"
)
// Finalize generates the final machine code.
func Finalize(functions map[string]*Function) ([]byte, []byte) {
a := asm.New()
a := entry()
main := functions["main"]
delete(functions, "main")
a.Merge(&main.Assembler)
for _, f := range functions {
a.Merge(&f.Assembler)
@ -15,3 +21,16 @@ func Finalize(functions map[string]*Function) ([]byte, []byte) {
code, data := a.Finalize()
return code, data
}
// entry returns the entry point of the executable.
// The only job of the entry function is to call `main` and exit cleanly.
// The reason we call `main` instead of using `main` itself is to place
// a return address on the stack, which allows return statements in `main`.
func entry() *asm.Assembler {
entry := asm.New()
entry.Call("main")
entry.MoveRegisterNumber(x64.SyscallArgs[0], linux.Exit)
entry.MoveRegisterNumber(x64.SyscallArgs[1], 0)
entry.Syscall()
return entry
}