Example #1
0
// PopTo returns code to save data from the stack into the variable.
// It also changes the stack size accordingly.
func (s *Stack) PopTo(name string) x86.X86 {
	v := s.Lookup(name)
	off := SizeOnStack(v.Type())
	if TypeToSize(v.Type()) != off {
		panic("I can't yet handle types with sizes that aren't a multiple of 4")
	}
	comment := "Popping to variable " + v.Name()
	if v.Name() == "_" {
		comment = fmt.Sprint("Popping to ", name, " of type ", PrettyType(v.Type()), " at ", v.InMemory())
	}
	code := []x86.X86{x86.Comment(s.PrettyComments())}
	switch off {
	case 4:
		s.Size -= off
		vnew := s.Lookup(name) // Its location relative to stack may have changed!
		return x86.RawAssembly(x86.Assembly([]x86.X86{
			x86.PopL(x86.EAX),
			x86.Commented(x86.MovL(x86.EAX, vnew.InMemory()), comment),
		}))
	case 8:
		s.Size -= 4
		vnew := s.Lookup(name) // Its location relative to stack may have changed!
		code = append(code,
			x86.PopL(x86.EAX),
			x86.Commented(x86.MovL(x86.EAX, vnew.InMemory()), comment))
		s.Size -= 4
		vnew = s.Lookup(name) // Its location relative to stack may have changed again!
		code = append(code,
			x86.PopL(x86.EAX),
			x86.Commented(x86.MovL(x86.EAX, vnew.InMemory().Add(4)), comment))
		return x86.RawAssembly(x86.Assembly(code))
	default:
		panic(fmt.Sprintf("I don't pop variables with length %s", SizeOnStack(v.Type())))
	}
	panic("This can't happen")
}
Example #2
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
}