Example #1
0
File: cgen.go Project: g-dx/clarac
func cgenFnCall(node *Node, ops *x64.OpcodeList) {

	// Check function
	fn, ok := node.sym.(*Function)
	if !ok {
		panic(fmt.Sprintf("Unknown symbol: %v, node: %v", node.sym, node))
	}

	switch fn.fnName {
	default:
		ops.CALL(fn.Rva())
	case printlnFuncName:
		cgenPrintCall(node, ops)
	}
}
Example #2
0
File: cgen.go Project: g-dx/clarac
func cgenPrintCall(node *Node, ops *x64.OpcodeList) {

	// Get symbol
	fn, ok := node.sym.(*Function)
	if !ok {
		panic(fmt.Sprintf("Unknown symbol: %v", node.sym))
	}

	// Push the base/frame pointer register value onto stack and overwrite base/frame pointer register to point to
	// the top of stack. This stack pointer can now be modified by us and restored at the end of the function to its
	// previous state

	// TODO: commented out as we must inline this call
	//	ops.PUSH(x64.Rbp)
	//	ops.MOV(x64.Rbp, x64.Rsp)

	// Push values onto stack (string RVA & length)

	str, ok := node.stats[0].sym.(*StringLiteralSymbol)
	if !ok {
		panic(fmt.Sprintf("print function parameter not string literal! - %v", str))
	}
	ops.PUSHI(str.Rva())
	ops.PUSHI(uint32(len(str.Val())))

	// Call print

	ops.CALL(fn.Rva())

	// Clean up stack by overwriting the stack pointer register with the base/frame pointer register. This discards
	// the two values we pushed onto the stack. Then pop the old base/frame pointer value off the stack & back into
	// the base/frame pointer register. This restores the caller's stack.
	// TODO: on x64 we should use 'leave' instruction

	//	ops.MOV(x64.Rsp, x64.Rbp)
	//	ops.POP(x64.Rbp)
	//	ops.RET()
}