Files
avo/ast.go

167 lines
2.9 KiB
Go
Raw Normal View History

2018-11-06 21:10:54 -05:00
package avo
2018-12-02 12:28:33 -08:00
import (
"github.com/mmcloughlin/avo/operand"
2018-12-02 22:29:30 -08:00
"github.com/mmcloughlin/avo/reg"
2018-12-02 12:28:33 -08:00
)
2018-11-20 11:44:44 -06:00
type Asm interface {
Asm() string
}
2018-11-06 21:10:54 -05:00
// GoType represents a Golang type.
type GoType interface{}
// Parameter represents a parameter to an assembly function.
type Parameter struct {
Name string
Type GoType
}
2018-11-20 11:44:44 -06:00
type Operand interface {
Asm
}
2018-11-30 21:37:17 -08:00
type Node interface {
node()
}
type Label string
func (l Label) node() {}
2018-11-06 21:10:54 -05:00
// Instruction is a single instruction in a function.
type Instruction struct {
2018-11-27 22:38:53 -08:00
Opcode string
2018-12-02 12:28:33 -08:00
Operands []operand.Op
Inputs []operand.Op
Outputs []operand.Op
2018-12-02 12:28:33 -08:00
IsTerminal bool
IsBranch bool
IsConditional bool
// CFG.
Pred []*Instruction
Succ []*Instruction
2018-12-02 23:59:29 -08:00
// LiveIn/LiveOut are sets of live register IDs pre/post execution.
2018-12-03 22:39:43 -08:00
LiveIn reg.Set
LiveOut reg.Set
2018-12-02 12:28:33 -08:00
}
2018-12-02 23:59:29 -08:00
func (i *Instruction) node() {}
2018-12-02 22:29:30 -08:00
2018-12-02 12:28:33 -08:00
func (i Instruction) TargetLabel() *Label {
if !i.IsBranch {
return nil
}
2018-12-02 13:50:55 -08:00
if len(i.Operands) == 0 {
return nil
}
2018-12-02 12:28:33 -08:00
if ref, ok := i.Operands[0].(operand.LabelRef); ok {
lbl := Label(ref)
return &lbl
}
return nil
2018-11-20 11:44:44 -06:00
}
func (i Instruction) Registers() []reg.Register {
var rs []reg.Register
for _, op := range i.Operands {
rs = append(rs, operand.Registers(op)...)
}
return rs
}
2018-12-02 22:29:30 -08:00
func (i Instruction) InputRegisters() []reg.Register {
var rs []reg.Register
for _, op := range i.Inputs {
rs = append(rs, operand.Registers(op)...)
}
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
}
2018-11-30 21:37:17 -08:00
2018-11-06 21:10:54 -05:00
// File represents an assembly file.
type File struct {
2018-11-30 20:43:31 -08:00
Functions []*Function
}
func NewFile() *File {
return &File{}
2018-11-06 21:10:54 -05:00
}
// Function represents an assembly function.
type Function struct {
name string
params []Parameter
2018-12-02 12:28:33 -08:00
Nodes []Node
// LabelTarget maps from label name to the following instruction.
LabelTarget map[Label]*Instruction
// Register allocation.
Allocation reg.Allocation
2018-11-06 21:10:54 -05:00
}
func NewFunction(name string) *Function {
return &Function{
name: name,
}
}
2018-12-02 12:28:33 -08:00
func (f *Function) AddInstruction(i *Instruction) {
2018-11-30 21:37:17 -08:00
f.AddNode(i)
}
func (f *Function) AddLabel(l Label) {
f.AddNode(l)
}
func (f *Function) AddNode(n Node) {
2018-12-02 12:28:33 -08:00
f.Nodes = append(f.Nodes, n)
}
// Instructions returns just the list of instruction nodes.
func (f *Function) Instructions() []*Instruction {
var is []*Instruction
for _, n := range f.Nodes {
i, ok := n.(*Instruction)
if ok {
is = append(is, i)
}
}
return is
2018-11-06 21:10:54 -05:00
}
// Name returns the function name.
func (f *Function) Name() string { return f.name }
// FrameBytes returns the size of the stack frame in bytes.
func (f *Function) FrameBytes() int {
// TODO(mbm): implement
return 0
}
// ArgumentBytes returns the size of the arguments in bytes.
func (f *Function) ArgumentBytes() int {
// TODO(mbm): implement
return 0
}