func cgenFnDecl(node *Node, imports ImportList, ops *x64.OpcodeList) { // Get function & set RVA fn, ok := node.sym.(*Function) if !ok { panic(fmt.Sprintf("Unknown symbol: %v, node: %v", node.sym, node.token)) } fn.rva = uint32(ops.Rva()) ops.PUSH(x64.Rbp) ops.MOV(x64.Rbp, x64.Rsp) // Generate calls for all functions for _, n := range node.stats { cgenFnCall(n, ops) } // Check if we are main - we need to exit! if node.token.Val == "main" { ops.MOVI(x64.Rcx, 0) ops.CALLPTR(imports.funcRva("ExitProcess")) } else { // TODO: When local variables added must update this! ops.MOV(x64.Rsp, x64.Rbp) ops.POP(x64.Rbp) ops.RET() } }
func cgenPrintlnDecl(node *Node, imports ImportList, ops *x64.OpcodeList) { // Get function & set RVA fn, ok := node.sym.(*Function) if !ok { panic(fmt.Sprintf("Unknown symbol: %v", node.sym)) } fn.rva = uint32(ops.Rva()) ops.PUSH(x64.Rbp) ops.MOV(x64.Rbp, x64.Rsp) // Get the output handle ops.MOVI(x64.Rcx, STD_OUTPUT_HANDLE) ops.CALLPTR(imports.funcRva("GetStdHandle")) // Write to console // See [https://msdn.microsoft.com/en-us/library/ms235286.aspx] for more information ops.MOV(x64.Rcx, x64.Rax) // Copy output handle result from AX into register ops.MOVM(x64.Rdx, x64.Rbp, 24) // Move string literal RVA into register ops.MOVM(x64.R8, x64.Rbp, 16) // Move string length into register ops.MOVI(x64.R9, 0) // TODO: This should be a local variable on the stack! ops.PUSHI(0) ops.CALLPTR(imports.funcRva("WriteConsoleA")) // Clean stack ops.MOV(x64.Rsp, x64.Rbp) ops.POP(x64.Rbp) ops.RET() }