Example #1
0
func (v *CompileVisitor) FunctionPostlogue() {
	// First we roll back the stack from where we started...
	for v.Stack.Name == "_" {
		// We need to pop off any extra layers of stack we've added...
		if v.Stack.Size > 0 {
			v.Append(x86.Commented(x86.AddL(x86.Imm32(v.Stack.Size), x86.ESP),
				"We stored this much on the stack so far."))
		}
		v.Stack = v.Stack.Parent // We've popped off the arguments...
	}
	// Now jump to the "real" postlogue.  This is a little stupid, but I
	// expect it'll come in handy when I implement defer (not to mention
	// panic/recover).
	v.Append(x86.Jmp(x86.Symbol("return_" + v.Stack.Name)))
}
Example #2
0
func (v *CompileVisitor) PopType(t ast.Type) {
	switch t.Form {
	case ast.Tuple:
		for _, o := range t.Params.Objects {
			v.PopType(*o.Type)
		}
	case ast.Basic:
		switch t.N {
		case ast.String:
			v.Append(x86.AddL(x86.Imm32(8), x86.ESP))
		default:
			panic(fmt.Sprintf("I don't know how to pop basic type %s", t))
		}
	default:
		panic(fmt.Sprintf("I don't know how to pop type %s", t.Form))
	}
}
Example #3
0
func (v *CompileVisitor) Visit(n0 ast.Node) (w ast.Visitor) {
	// The following only handles functions (not methods)
	if n, ok := n0.(*ast.FuncDecl); ok && n.Recv == nil {
		v.FunctionPrologue(n)
		for _, statement := range n.Body.List {
			v.CompileStatement(statement)
		}
		v.FunctionPostlogue()
		v.Append(x86.GlobalSymbol("return_" + n.Name.Name))
		v.Append(x86.Commented(x86.PopL(x86.EAX), "Pop the return address"))
		// Pop off function arguments...
		fmt.Println("Function", v.Stack.Name, "has stack size", v.Stack.Size)
		fmt.Println("Function", v.Stack.Name, "has return values size", v.Stack.ReturnSize)
		v.Append(x86.Commented(x86.AddL(x86.Imm32(v.Stack.Size-4-v.Stack.ReturnSize), x86.ESP),
			"Popping "+v.Stack.Name+" arguments."))
		// Then we return!
		v.Append(x86.RawAssembly("\tjmp *%eax"))
		v.Stack = v.Stack.Parent
		return nil // No need to peek inside the func declaration!
	}
	return v
}