Exemple #1
0
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()
	}
}
Exemple #2
0
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()
}