func (f *Function) AllocLocal(size int) operand.Mem {
	ptr := operand.NewStackAddr(f.LocalSize)
	f.LocalSize += size
	return ptr
}
AllocLocal allocates size bytes in this function's stack.
Returns a reference to the base pointer for the newly allocated region.
package ir
import (
	"errors"
	"github.com/mmcloughlin/avo/attr"
	"github.com/mmcloughlin/avo/buildtags"
	"github.com/mmcloughlin/avo/gotypes"
	"github.com/mmcloughlin/avo/operand"
	"github.com/mmcloughlin/avo/reg"
)
type Node interface {
	node()
}
type Label string
func (l Label) node() {}
type Comment struct {
	Lines []string
}
func (c *Comment) node() {}
func NewComment(lines ...string) *Comment {
	return &Comment{
		Lines: lines,
	}
}
type Instruction struct {
	Opcode   string
	Operands []operand.Op
	Inputs  []operand.Op
	Outputs []operand.Op
	IsTerminal       bool
	IsBranch         bool
	IsConditional    bool
	CancellingInputs bool
	ISA []string
	Pred []*Instruction
	Succ []*Instruction
	LiveIn  reg.MaskSet
	LiveOut reg.MaskSet
}
func (i *Instruction) node() {}
func (i Instruction) IsUnconditionalBranch() bool {
	return i.IsBranch && !i.IsConditional
}
func (i Instruction) TargetLabel() *Label {
	if !i.IsBranch {
		return nil
	}
	if len(i.Operands) == 0 {
		return nil
	}
	if ref, ok := i.Operands[0].(operand.LabelRef); ok {
		lbl := Label(ref)
		return &lbl
	}
	return nil
}
func (i Instruction) Registers() []reg.Register {
	var rs []reg.Register
	for _, op := range i.Operands {
		rs = append(rs, operand.Registers(op)...)
	}
	return rs
}
func (i Instruction) InputRegisters() []reg.Register {
	var rs []reg.Register
	for _, op := range i.Inputs {
		rs = append(rs, operand.Registers(op)...)
	}
	if i.CancellingInputs && rs[0] == rs[1] {
		rs = []reg.Register{}
	}
	for _, op := range i.Outputs {
		if operand.IsMem(op) {
			rs = append(rs, operand.Registers(op)...)
		}
	}
	return rs
}
func (i Instruction) OutputRegisters() []reg.Register {
	var rs []reg.Register
	for _, op := range i.Outputs {
		if r, ok := op.(reg.Register); ok {
			rs = append(rs, r)
		}
	}
	return rs
}
type Section interface {
	section()
}
type File struct {
	Constraints buildtags.Constraints
	Includes    []string
	Sections    []Section
}
func NewFile() *File {
	return &File{}
}
func (f *File) AddSection(s Section) {
	f.Sections = append(f.Sections, s)
}
func (f *File) Functions() []*Function {
	var fns []*Function
	for _, s := range f.Sections {
		if fn, ok := s.(*Function); ok {
			fns = append(fns, fn)
		}
	}
	return fns
}
type Pragma struct {
	Directive string
	Arguments []string
}
type Function struct {
	Name       string
	Attributes attr.Attribute
	Pragmas    []Pragma
	Doc        []string
	Signature  *gotypes.Signature
	LocalSize  int
	Nodes []Node
	LabelTarget map[Label]*Instruction
	Allocation reg.Allocation
	ISA []string
}
func (f *Function) section() {}
func NewFunction(name string) *Function {
	return &Function{
		Name:      name,
		Signature: gotypes.NewSignatureVoid(),
	}
}
func (f *Function) AddPragma(directive string, args ...string) {
	f.Pragmas = append(f.Pragmas, Pragma{
		Directive: directive,
		Arguments: args,
	})
}
func (f *Function) SetSignature(s *gotypes.Signature) {
	f.Signature = s
}