ast: move "ast" types from root to ir sub-package

Closes #32
This commit is contained in:
Michael McLoughlin
2019-01-06 14:21:10 -08:00
parent 4a920c22b5
commit 0f63e0906d
15 changed files with 3925 additions and 3925 deletions

View File

@@ -4,10 +4,10 @@ import (
"errors" "errors"
"go/types" "go/types"
"github.com/mmcloughlin/avo"
"github.com/mmcloughlin/avo/attr" "github.com/mmcloughlin/avo/attr"
"github.com/mmcloughlin/avo/buildtags" "github.com/mmcloughlin/avo/buildtags"
"github.com/mmcloughlin/avo/gotypes" "github.com/mmcloughlin/avo/gotypes"
"github.com/mmcloughlin/avo/ir"
"github.com/mmcloughlin/avo/operand" "github.com/mmcloughlin/avo/operand"
"github.com/mmcloughlin/avo/reg" "github.com/mmcloughlin/avo/reg"
"golang.org/x/tools/go/packages" "golang.org/x/tools/go/packages"
@@ -16,9 +16,9 @@ import (
// Context maintains state for incrementally building an avo File. // Context maintains state for incrementally building an avo File.
type Context struct { type Context struct {
pkg *packages.Package pkg *packages.Package
file *avo.File file *ir.File
function *avo.Function function *ir.Function
global *avo.Global global *ir.Global
errs ErrorList errs ErrorList
reg.Collection reg.Collection
} }
@@ -26,7 +26,7 @@ type Context struct {
// NewContext initializes an empty build Context. // NewContext initializes an empty build Context.
func NewContext() *Context { func NewContext() *Context {
return &Context{ return &Context{
file: avo.NewFile(), file: ir.NewFile(),
Collection: *reg.NewCollection(), Collection: *reg.NewCollection(),
} }
} }
@@ -81,7 +81,7 @@ func (c *Context) ConstraintExpr(expr string) {
// Function starts building a new function with the given name. // Function starts building a new function with the given name.
func (c *Context) Function(name string) { func (c *Context) Function(name string) {
c.function = avo.NewFunction(name) c.function = ir.NewFunction(name)
c.file.AddSection(c.function) c.file.AddSection(c.function)
} }
@@ -124,19 +124,19 @@ func (c *Context) AllocLocal(size int) operand.Mem {
} }
// Instruction adds an instruction to the active function. // Instruction adds an instruction to the active function.
func (c *Context) Instruction(i *avo.Instruction) { func (c *Context) Instruction(i *ir.Instruction) {
c.activefunc().AddInstruction(i) c.activefunc().AddInstruction(i)
} }
// Label adds a label to the active function. // Label adds a label to the active function.
func (c *Context) Label(name string) { func (c *Context) Label(name string) {
c.activefunc().AddLabel(avo.Label(name)) c.activefunc().AddLabel(ir.Label(name))
} }
func (c *Context) activefunc() *avo.Function { func (c *Context) activefunc() *ir.Function {
if c.function == nil { if c.function == nil {
c.adderrormessage("no active function") c.adderrormessage("no active function")
return avo.NewFunction("") return ir.NewFunction("")
} }
return c.function return c.function
} }
@@ -145,7 +145,7 @@ func (c *Context) activefunc() *avo.Function {
// StaticGlobal adds a new static data section to the file and returns a pointer to it. // StaticGlobal adds a new static data section to the file and returns a pointer to it.
func (c *Context) StaticGlobal(name string) operand.Mem { func (c *Context) StaticGlobal(name string) operand.Mem {
c.global = avo.NewStaticGlobal(name) c.global = ir.NewStaticGlobal(name)
c.file.AddSection(c.global) c.file.AddSection(c.global)
return c.global.Base() return c.global.Base()
} }
@@ -157,7 +157,7 @@ func (c *Context) DataAttributes(a attr.Attribute) {
// AddDatum adds constant v at offset to the current active global data section. // AddDatum adds constant v at offset to the current active global data section.
func (c *Context) AddDatum(offset int, v operand.Constant) { func (c *Context) AddDatum(offset int, v operand.Constant) {
if err := c.activeglobal().AddDatum(avo.NewDatum(offset, v)); err != nil { if err := c.activeglobal().AddDatum(ir.NewDatum(offset, v)); err != nil {
c.adderror(err) c.adderror(err)
} }
} }
@@ -167,10 +167,10 @@ func (c *Context) AppendDatum(v operand.Constant) {
c.activeglobal().Append(v) c.activeglobal().Append(v)
} }
func (c *Context) activeglobal() *avo.Global { func (c *Context) activeglobal() *ir.Global {
if c.global == nil { if c.global == nil {
c.adderrormessage("no active global") c.adderrormessage("no active global")
return avo.NewStaticGlobal("") return ir.NewStaticGlobal("")
} }
return c.global return c.global
} }
@@ -184,6 +184,6 @@ func (c *Context) adderrormessage(msg string) {
} }
// Result returns the built file and any accumulated errors. // Result returns the built file and any accumulated errors.
func (c *Context) Result() (*avo.File, error) { func (c *Context) Result() (*ir.File, error) {
return c.file, c.errs.Err() return c.file, c.errs.Err()
} }

View File

@@ -7,7 +7,6 @@ import (
const ( const (
pkg = "github.com/mmcloughlin/avo" pkg = "github.com/mmcloughlin/avo"
instType = "avo.Instruction"
operandType = "operand.Op" operandType = "operand.Op"
) )

View File

@@ -27,7 +27,7 @@ func (c *ctors) Generate(is []inst.Instruction) ([]byte, error) {
c.Printf("package x86\n\n") c.Printf("package x86\n\n")
c.Printf("import (\n") c.Printf("import (\n")
c.Printf("\t\"errors\"\n") c.Printf("\t\"errors\"\n")
c.Printf("\t\"%s\"\n", pkg) c.Printf("\tintrep \"%s/ir\"\n", pkg)
c.Printf("\t\"%s/reg\"\n", pkg) c.Printf("\t\"%s/reg\"\n", pkg)
c.Printf("\t\"%s/operand\"\n", pkg) c.Printf("\t\"%s/operand\"\n", pkg)
c.Printf(")\n\n") c.Printf(")\n\n")
@@ -46,7 +46,7 @@ func (c *ctors) instruction(i inst.Instruction) {
s := params(i) s := params(i)
c.Printf("func %s(%s) (*%s, error) {\n", i.Opcode, s.ParameterList(), instType) c.Printf("func %s(%s) (*intrep.Instruction, error) {\n", i.Opcode, s.ParameterList())
c.forms(i, s) c.forms(i, s)
c.Printf("}\n\n") c.Printf("}\n\n")
} }
@@ -85,7 +85,7 @@ func (c *ctors) forms(i inst.Instruction, s signature) {
func construct(i inst.Instruction, f inst.Form, s signature) string { func construct(i inst.Instruction, f inst.Form, s signature) string {
buf := bytes.NewBuffer(nil) buf := bytes.NewBuffer(nil)
fmt.Fprintf(buf, "%s{\n", instType) fmt.Fprintf(buf, "intrep.Instruction{\n")
fmt.Fprintf(buf, "\tOpcode: %#v,\n", i.Opcode) fmt.Fprintf(buf, "\tOpcode: %#v,\n", i.Opcode)
fmt.Fprintf(buf, "\tOperands: %s,\n", s.ParameterSlice()) fmt.Fprintf(buf, "\tOperands: %s,\n", s.ParameterSlice())

2
ir/doc.go Normal file
View File

@@ -0,0 +1,2 @@
// Package ir provides the intermediate representation of avo programs.
package ir

View File

@@ -1,4 +1,4 @@
package avo package ir
import ( import (
"errors" "errors"

View File

@@ -4,16 +4,16 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/mmcloughlin/avo" "github.com/mmcloughlin/avo/ir"
) )
// LabelTarget populates the LabelTarget of the given function. This maps from // LabelTarget populates the LabelTarget of the given function. This maps from
// label name to the following instruction. // label name to the following instruction.
func LabelTarget(fn *avo.Function) error { func LabelTarget(fn *ir.Function) error {
target := map[avo.Label]*avo.Instruction{} target := map[ir.Label]*ir.Instruction{}
for idx := 0; idx < len(fn.Nodes); idx++ { for idx := 0; idx < len(fn.Nodes); idx++ {
// Is this a label? // Is this a label?
lbl, ok := fn.Nodes[idx].(avo.Label) lbl, ok := fn.Nodes[idx].(ir.Label)
if !ok { if !ok {
continue continue
} }
@@ -27,7 +27,7 @@ func LabelTarget(fn *avo.Function) error {
} }
idx++ idx++
// Should be an instruction. // Should be an instruction.
i, ok := fn.Nodes[idx].(*avo.Instruction) i, ok := fn.Nodes[idx].(*ir.Instruction)
if !ok { if !ok {
return errors.New("instruction should follow a label") return errors.New("instruction should follow a label")
} }
@@ -38,14 +38,14 @@ func LabelTarget(fn *avo.Function) error {
} }
// CFG constructs the call-flow-graph for the function. // CFG constructs the call-flow-graph for the function.
func CFG(fn *avo.Function) error { func CFG(fn *ir.Function) error {
is := fn.Instructions() is := fn.Instructions()
n := len(is) n := len(is)
// Populate successors. // Populate successors.
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
cur := is[i] cur := is[i]
var nxt *avo.Instruction var nxt *ir.Instruction
if i+1 < n { if i+1 < n {
nxt = is[i+1] nxt = is[i+1]
} }

View File

@@ -5,22 +5,21 @@ import (
"sort" "sort"
"testing" "testing"
"github.com/mmcloughlin/avo/ir"
"github.com/mmcloughlin/avo/operand" "github.com/mmcloughlin/avo/operand"
"github.com/mmcloughlin/avo"
) )
func TestLabelTarget(t *testing.T) { func TestLabelTarget(t *testing.T) {
expect := map[avo.Label]*avo.Instruction{ expect := map[ir.Label]*ir.Instruction{
"lblA": {Opcode: "A"}, "lblA": {Opcode: "A"},
"lblB": {Opcode: "B"}, "lblB": {Opcode: "B"},
} }
f := avo.NewFunction("happypath") f := ir.NewFunction("happypath")
for lbl, i := range expect { for lbl, i := range expect {
f.AddLabel(lbl) f.AddLabel(lbl)
f.AddInstruction(i) f.AddInstruction(i)
f.AddInstruction(&avo.Instruction{Opcode: "IDK"}) f.AddInstruction(&ir.Instruction{Opcode: "IDK"})
} }
if err := LabelTarget(f); err != nil { if err := LabelTarget(f); err != nil {
@@ -33,11 +32,11 @@ func TestLabelTarget(t *testing.T) {
} }
func TestLabelTargetDuplicate(t *testing.T) { func TestLabelTargetDuplicate(t *testing.T) {
f := avo.NewFunction("dupelabel") f := ir.NewFunction("dupelabel")
f.AddLabel(avo.Label("lblA")) f.AddLabel(ir.Label("lblA"))
f.AddInstruction(&avo.Instruction{Opcode: "A"}) f.AddInstruction(&ir.Instruction{Opcode: "A"})
f.AddLabel(avo.Label("lblA")) f.AddLabel(ir.Label("lblA"))
f.AddInstruction(&avo.Instruction{Opcode: "A"}) f.AddInstruction(&ir.Instruction{Opcode: "A"})
err := LabelTarget(f) err := LabelTarget(f)
@@ -47,9 +46,9 @@ func TestLabelTargetDuplicate(t *testing.T) {
} }
func TestLabelTargetEndsWithLabel(t *testing.T) { func TestLabelTargetEndsWithLabel(t *testing.T) {
f := avo.NewFunction("endswithlabel") f := ir.NewFunction("endswithlabel")
f.AddInstruction(&avo.Instruction{Opcode: "A"}) f.AddInstruction(&ir.Instruction{Opcode: "A"})
f.AddLabel(avo.Label("theend")) f.AddLabel(ir.Label("theend"))
err := LabelTarget(f) err := LabelTarget(f)
@@ -59,10 +58,10 @@ func TestLabelTargetEndsWithLabel(t *testing.T) {
} }
func TestLabelTargetInstructionFollowLabel(t *testing.T) { func TestLabelTargetInstructionFollowLabel(t *testing.T) {
f := avo.NewFunction("expectinstafterlabel") f := ir.NewFunction("expectinstafterlabel")
f.AddLabel(avo.Label("lblA")) f.AddLabel(ir.Label("lblA"))
f.AddLabel(avo.Label("lblB")) f.AddLabel(ir.Label("lblB"))
f.AddInstruction(&avo.Instruction{Opcode: "A"}) f.AddInstruction(&ir.Instruction{Opcode: "A"})
err := LabelTarget(f) err := LabelTarget(f)
@@ -72,9 +71,9 @@ func TestLabelTargetInstructionFollowLabel(t *testing.T) {
} }
func TestCFGSingleBasicBlock(t *testing.T) { func TestCFGSingleBasicBlock(t *testing.T) {
f := avo.NewFunction("simple") f := ir.NewFunction("simple")
f.AddInstruction(&avo.Instruction{Opcode: "A"}) f.AddInstruction(&ir.Instruction{Opcode: "A"})
f.AddInstruction(&avo.Instruction{Opcode: "B"}) f.AddInstruction(&ir.Instruction{Opcode: "B"})
f.AddInstruction(Terminal("RET")) f.AddInstruction(Terminal("RET"))
if err := ComputeCFG(t, f); err != nil { if err := ComputeCFG(t, f); err != nil {
@@ -95,11 +94,11 @@ func TestCFGSingleBasicBlock(t *testing.T) {
} }
func TestCFGCondBranch(t *testing.T) { func TestCFGCondBranch(t *testing.T) {
f := avo.NewFunction("condbranch") f := ir.NewFunction("condbranch")
f.AddInstruction(&avo.Instruction{Opcode: "A"}) f.AddInstruction(&ir.Instruction{Opcode: "A"})
f.AddLabel(avo.Label("lblB")) f.AddLabel(ir.Label("lblB"))
f.AddInstruction(&avo.Instruction{Opcode: "B"}) f.AddInstruction(&ir.Instruction{Opcode: "B"})
f.AddInstruction(&avo.Instruction{Opcode: "C"}) f.AddInstruction(&ir.Instruction{Opcode: "C"})
f.AddInstruction(CondBranch("J", "lblB")) f.AddInstruction(CondBranch("J", "lblB"))
f.AddInstruction(Terminal("RET")) f.AddInstruction(Terminal("RET"))
@@ -117,10 +116,10 @@ func TestCFGCondBranch(t *testing.T) {
} }
func TestCFGUncondBranch(t *testing.T) { func TestCFGUncondBranch(t *testing.T) {
f := avo.NewFunction("uncondbranch") f := ir.NewFunction("uncondbranch")
f.AddInstruction(&avo.Instruction{Opcode: "A"}) f.AddInstruction(&ir.Instruction{Opcode: "A"})
f.AddLabel(avo.Label("lblB")) f.AddLabel(ir.Label("lblB"))
f.AddInstruction(&avo.Instruction{Opcode: "B"}) f.AddInstruction(&ir.Instruction{Opcode: "B"})
f.AddInstruction(UncondBranch("JMP", "lblB")) f.AddInstruction(UncondBranch("JMP", "lblB"))
if err := ComputeCFG(t, f); err != nil { if err := ComputeCFG(t, f); err != nil {
@@ -135,11 +134,11 @@ func TestCFGUncondBranch(t *testing.T) {
} }
func TestCFGJumpForward(t *testing.T) { func TestCFGJumpForward(t *testing.T) {
f := avo.NewFunction("forward") f := ir.NewFunction("forward")
f.AddInstruction(&avo.Instruction{Opcode: "A"}) f.AddInstruction(&ir.Instruction{Opcode: "A"})
f.AddInstruction(CondBranch("J", "done")) f.AddInstruction(CondBranch("J", "done"))
f.AddInstruction(&avo.Instruction{Opcode: "B"}) f.AddInstruction(&ir.Instruction{Opcode: "B"})
f.AddLabel(avo.Label("done")) f.AddLabel(ir.Label("done"))
f.AddInstruction(Terminal("RET")) f.AddInstruction(Terminal("RET"))
if err := ComputeCFG(t, f); err != nil { if err := ComputeCFG(t, f); err != nil {
@@ -155,13 +154,13 @@ func TestCFGJumpForward(t *testing.T) {
} }
func TestCFGMultiReturn(t *testing.T) { func TestCFGMultiReturn(t *testing.T) {
f := avo.NewFunction("multireturn") f := ir.NewFunction("multireturn")
f.AddInstruction(&avo.Instruction{Opcode: "A"}) f.AddInstruction(&ir.Instruction{Opcode: "A"})
f.AddInstruction(CondBranch("J", "fork")) f.AddInstruction(CondBranch("J", "fork"))
f.AddInstruction(&avo.Instruction{Opcode: "B"}) f.AddInstruction(&ir.Instruction{Opcode: "B"})
f.AddInstruction(Terminal("RET1")) f.AddInstruction(Terminal("RET1"))
f.AddLabel(avo.Label("fork")) f.AddLabel(ir.Label("fork"))
f.AddInstruction(&avo.Instruction{Opcode: "C"}) f.AddInstruction(&ir.Instruction{Opcode: "C"})
f.AddInstruction(Terminal("RET2")) f.AddInstruction(Terminal("RET2"))
if err := ComputeCFG(t, f); err != nil { if err := ComputeCFG(t, f); err != nil {
@@ -179,8 +178,8 @@ func TestCFGMultiReturn(t *testing.T) {
} }
func TestCFGShortLoop(t *testing.T) { func TestCFGShortLoop(t *testing.T) {
f := avo.NewFunction("shortloop") f := ir.NewFunction("shortloop")
f.AddLabel(avo.Label("cycle")) f.AddLabel(ir.Label("cycle"))
f.AddInstruction(UncondBranch("JMP", "cycle")) f.AddInstruction(UncondBranch("JMP", "cycle"))
if err := ComputeCFG(t, f); err != nil { if err := ComputeCFG(t, f); err != nil {
@@ -193,8 +192,8 @@ func TestCFGShortLoop(t *testing.T) {
} }
func TestCFGUndefinedLabel(t *testing.T) { func TestCFGUndefinedLabel(t *testing.T) {
f := avo.NewFunction("undeflabel") f := ir.NewFunction("undeflabel")
f.AddInstruction(&avo.Instruction{Opcode: "A"}) f.AddInstruction(&ir.Instruction{Opcode: "A"})
f.AddInstruction(CondBranch("J", "undef")) f.AddInstruction(CondBranch("J", "undef"))
err := ComputeCFG(t, f) err := ComputeCFG(t, f)
@@ -205,9 +204,9 @@ func TestCFGUndefinedLabel(t *testing.T) {
} }
func TestCFGMissingLabel(t *testing.T) { func TestCFGMissingLabel(t *testing.T) {
f := avo.NewFunction("missinglabel") f := ir.NewFunction("missinglabel")
f.AddInstruction(&avo.Instruction{Opcode: "A"}) f.AddInstruction(&ir.Instruction{Opcode: "A"})
f.AddInstruction(&avo.Instruction{Opcode: "J", IsBranch: true}) // no label operand f.AddInstruction(&ir.Instruction{Opcode: "J", IsBranch: true}) // no label operand
err := ComputeCFG(t, f) err := ComputeCFG(t, f)
if err == nil { if err == nil {
t.Fatal("expect error on missing label") t.Fatal("expect error on missing label")
@@ -215,13 +214,13 @@ func TestCFGMissingLabel(t *testing.T) {
} }
// Terminal builds a terminal instruction. // Terminal builds a terminal instruction.
func Terminal(opcode string) *avo.Instruction { func Terminal(opcode string) *ir.Instruction {
return &avo.Instruction{Opcode: opcode, IsTerminal: true} return &ir.Instruction{Opcode: opcode, IsTerminal: true}
} }
// CondBranch builds a conditional branch instruction to the given label. // CondBranch builds a conditional branch instruction to the given label.
func CondBranch(opcode, lbl string) *avo.Instruction { func CondBranch(opcode, lbl string) *ir.Instruction {
return &avo.Instruction{ return &ir.Instruction{
Opcode: opcode, Opcode: opcode,
Operands: []operand.Op{operand.LabelRef(lbl)}, Operands: []operand.Op{operand.LabelRef(lbl)},
IsBranch: true, IsBranch: true,
@@ -230,8 +229,8 @@ func CondBranch(opcode, lbl string) *avo.Instruction {
} }
// UncondBranch builds an unconditional branch instruction to the given label. // UncondBranch builds an unconditional branch instruction to the given label.
func UncondBranch(opcode, lbl string) *avo.Instruction { func UncondBranch(opcode, lbl string) *ir.Instruction {
return &avo.Instruction{ return &ir.Instruction{
Opcode: opcode, Opcode: opcode,
Operands: []operand.Op{operand.LabelRef(lbl)}, Operands: []operand.Op{operand.LabelRef(lbl)},
IsBranch: true, IsBranch: true,
@@ -239,7 +238,7 @@ func UncondBranch(opcode, lbl string) *avo.Instruction {
} }
} }
func ComputeCFG(t *testing.T, f *avo.Function) error { func ComputeCFG(t *testing.T, f *ir.Function) error {
t.Helper() t.Helper()
if err := LabelTarget(f); err != nil { if err := LabelTarget(f); err != nil {
t.Fatal(err) t.Fatal(err)
@@ -247,11 +246,11 @@ func ComputeCFG(t *testing.T, f *avo.Function) error {
return CFG(f) return CFG(f)
} }
func AssertSuccessors(t *testing.T, f *avo.Function, expect map[string][]string) { func AssertSuccessors(t *testing.T, f *ir.Function, expect map[string][]string) {
AssertEqual(t, "successors", OpcodeSuccessorGraph(f), expect) AssertEqual(t, "successors", OpcodeSuccessorGraph(f), expect)
} }
func AssertPredecessors(t *testing.T, f *avo.Function, expect map[string][]string) { func AssertPredecessors(t *testing.T, f *ir.Function, expect map[string][]string) {
AssertEqual(t, "predecessors", OpcodePredecessorGraph(f), expect) AssertEqual(t, "predecessors", OpcodePredecessorGraph(f), expect)
} }
@@ -264,17 +263,17 @@ func AssertEqual(t *testing.T, what string, got, expect interface{}) {
} }
// OpcodeSuccessorGraph builds a map from opcode name to successor opcode names. // OpcodeSuccessorGraph builds a map from opcode name to successor opcode names.
func OpcodeSuccessorGraph(f *avo.Function) map[string][]string { func OpcodeSuccessorGraph(f *ir.Function) map[string][]string {
return OpcodeGraph(f, func(i *avo.Instruction) []*avo.Instruction { return i.Succ }) return OpcodeGraph(f, func(i *ir.Instruction) []*ir.Instruction { return i.Succ })
} }
// OpcodePredecessorGraph builds a map from opcode name to predecessor opcode names. // OpcodePredecessorGraph builds a map from opcode name to predecessor opcode names.
func OpcodePredecessorGraph(f *avo.Function) map[string][]string { func OpcodePredecessorGraph(f *ir.Function) map[string][]string {
return OpcodeGraph(f, func(i *avo.Instruction) []*avo.Instruction { return i.Pred }) return OpcodeGraph(f, func(i *ir.Instruction) []*ir.Instruction { return i.Pred })
} }
// OpcodeGraph builds a map from opcode name to neighboring opcode names. Each list of neighbors is sorted. // OpcodeGraph builds a map from opcode name to neighboring opcode names. Each list of neighbors is sorted.
func OpcodeGraph(f *avo.Function, neighbors func(*avo.Instruction) []*avo.Instruction) map[string][]string { func OpcodeGraph(f *ir.Function, neighbors func(*ir.Instruction) []*ir.Instruction) map[string][]string {
g := map[string][]string{} g := map[string][]string{}
for _, i := range f.Instructions() { for _, i := range f.Instructions() {
opcodes := []string{} opcodes := []string{}

View File

@@ -4,7 +4,7 @@ package pass
import ( import (
"io" "io"
"github.com/mmcloughlin/avo" "github.com/mmcloughlin/avo/ir"
"github.com/mmcloughlin/avo/printer" "github.com/mmcloughlin/avo/printer"
) )
@@ -22,23 +22,23 @@ var Compile = Concat(
// Interface for a processing pass. // Interface for a processing pass.
type Interface interface { type Interface interface {
Execute(*avo.File) error Execute(*ir.File) error
} }
// Func adapts a function to the pass Interface. // Func adapts a function to the pass Interface.
type Func func(*avo.File) error type Func func(*ir.File) error
// Execute calls p. // Execute calls p.
func (p Func) Execute(f *avo.File) error { func (p Func) Execute(f *ir.File) error {
return p(f) return p(f)
} }
// FunctionPass is a convenience for implementing a full file pass with a // FunctionPass is a convenience for implementing a full file pass with a
// function that operates on each avo Function independently. // function that operates on each avo Function independently.
type FunctionPass func(*avo.Function) error type FunctionPass func(*ir.Function) error
// Execute calls p on every function in the file. Exits on the first error. // Execute calls p on every function in the file. Exits on the first error.
func (p FunctionPass) Execute(f *avo.File) error { func (p FunctionPass) Execute(f *ir.File) error {
for _, fn := range f.Functions() { for _, fn := range f.Functions() {
if err := p(fn); err != nil { if err := p(fn); err != nil {
return err return err
@@ -49,7 +49,7 @@ func (p FunctionPass) Execute(f *avo.File) error {
// Concat returns a pass that executes the given passes in order, stopping on the first error. // Concat returns a pass that executes the given passes in order, stopping on the first error.
func Concat(passes ...Interface) Interface { func Concat(passes ...Interface) Interface {
return Func(func(f *avo.File) error { return Func(func(f *ir.File) error {
for _, p := range passes { for _, p := range passes {
if err := p.Execute(f); err != nil { if err := p.Execute(f); err != nil {
return err return err
@@ -66,7 +66,7 @@ type Output struct {
} }
// Execute prints f with the configured Printer and writes output to Writer. // Execute prints f with the configured Printer and writes output to Writer.
func (o *Output) Execute(f *avo.File) error { func (o *Output) Execute(f *ir.File) error {
b, err := o.Printer.Print(f) b, err := o.Printer.Print(f)
if err != nil { if err != nil {
return err return err

View File

@@ -3,13 +3,13 @@ package pass
import ( import (
"errors" "errors"
"github.com/mmcloughlin/avo" "github.com/mmcloughlin/avo/ir"
"github.com/mmcloughlin/avo/operand" "github.com/mmcloughlin/avo/operand"
"github.com/mmcloughlin/avo/reg" "github.com/mmcloughlin/avo/reg"
) )
// Liveness computes register liveness. // Liveness computes register liveness.
func Liveness(fn *avo.Function) error { func Liveness(fn *ir.Function) error {
// Note this implementation is initially naive so as to be "obviously correct". // Note this implementation is initially naive so as to be "obviously correct".
// There are a well-known optimizations we can apply if necessary. // There are a well-known optimizations we can apply if necessary.
@@ -67,7 +67,7 @@ func Liveness(fn *avo.Function) error {
} }
// AllocateRegisters performs register allocation. // AllocateRegisters performs register allocation.
func AllocateRegisters(fn *avo.Function) error { func AllocateRegisters(fn *ir.Function) error {
// Populate allocators (one per kind). // Populate allocators (one per kind).
as := map[reg.Kind]*Allocator{} as := map[reg.Kind]*Allocator{}
for _, i := range fn.Instructions() { for _, i := range fn.Instructions() {
@@ -110,7 +110,7 @@ func AllocateRegisters(fn *avo.Function) error {
} }
// BindRegisters applies the result of register allocation, replacing all virtual registers with their assigned physical registers. // BindRegisters applies the result of register allocation, replacing all virtual registers with their assigned physical registers.
func BindRegisters(fn *avo.Function) error { func BindRegisters(fn *ir.Function) error {
for _, i := range fn.Instructions() { for _, i := range fn.Instructions() {
for idx := range i.Operands { for idx := range i.Operands {
i.Operands[idx] = operand.ApplyAllocation(i.Operands[idx], fn.Allocation) i.Operands[idx] = operand.ApplyAllocation(i.Operands[idx], fn.Allocation)
@@ -120,7 +120,7 @@ func BindRegisters(fn *avo.Function) error {
} }
// VerifyAllocation performs sanity checks following register allocation. // VerifyAllocation performs sanity checks following register allocation.
func VerifyAllocation(fn *avo.Function) error { func VerifyAllocation(fn *ir.Function) error {
// All registers should be physical. // All registers should be physical.
for _, i := range fn.Instructions() { for _, i := range fn.Instructions() {
for _, r := range i.Registers() { for _, r := range i.Registers() {

View File

@@ -4,11 +4,11 @@ import (
"testing" "testing"
"github.com/mmcloughlin/avo/internal/test" "github.com/mmcloughlin/avo/internal/test"
"github.com/mmcloughlin/avo/ir"
"github.com/mmcloughlin/avo/reg" "github.com/mmcloughlin/avo/reg"
"github.com/mmcloughlin/avo/pass" "github.com/mmcloughlin/avo/pass"
"github.com/mmcloughlin/avo"
"github.com/mmcloughlin/avo/build" "github.com/mmcloughlin/avo/build"
"github.com/mmcloughlin/avo/operand" "github.com/mmcloughlin/avo/operand"
) )
@@ -57,7 +57,7 @@ func AssertRegistersMatchSet(t *testing.T, rs []reg.Register, s reg.Set) {
} }
} }
func ConstructLiveness(t *testing.T, ctx *build.Context) *avo.Function { func ConstructLiveness(t *testing.T, ctx *build.Context) *ir.Function {
f, err := ctx.Result() f, err := ctx.Result()
if err != nil { if err != nil {
build.LogError(test.Logger(t), err, 0) build.LogError(test.Logger(t), err, 0)
@@ -70,7 +70,7 @@ func ConstructLiveness(t *testing.T, ctx *build.Context) *avo.Function {
} }
fn := fns[0] fn := fns[0]
passes := []func(*avo.Function) error{ passes := []func(*ir.Function) error{
pass.LabelTarget, pass.LabelTarget,
pass.CFG, pass.CFG,
pass.Liveness, pass.Liveness,

View File

@@ -1,12 +1,12 @@
package pass package pass
import ( import (
"github.com/mmcloughlin/avo"
"github.com/mmcloughlin/avo/attr" "github.com/mmcloughlin/avo/attr"
"github.com/mmcloughlin/avo/ir"
) )
// IncludeTextFlagHeader includes textflag.h if necessary. // IncludeTextFlagHeader includes textflag.h if necessary.
func IncludeTextFlagHeader(f *avo.File) error { func IncludeTextFlagHeader(f *ir.File) error {
const textflagheader = "textflag.h" const textflagheader = "textflag.h"
// Check if we already have it. // Check if we already have it.
@@ -25,13 +25,13 @@ func IncludeTextFlagHeader(f *avo.File) error {
} }
// requirestextflags returns whether the file uses flags in the textflags.h header. // requirestextflags returns whether the file uses flags in the textflags.h header.
func requirestextflags(f *avo.File) bool { func requirestextflags(f *ir.File) bool {
for _, s := range f.Sections { for _, s := range f.Sections {
var a attr.Attribute var a attr.Attribute
switch s := s.(type) { switch s := s.(type) {
case *avo.Function: case *ir.Function:
a = s.Attributes a = s.Attributes
case *avo.Global: case *ir.Global:
a = s.Attributes a = s.Attributes
} }
if a.ContainsTextFlags() { if a.ContainsTextFlags() {

View File

@@ -4,8 +4,8 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/mmcloughlin/avo"
"github.com/mmcloughlin/avo/internal/prnt" "github.com/mmcloughlin/avo/internal/prnt"
"github.com/mmcloughlin/avo/ir"
"github.com/mmcloughlin/avo/operand" "github.com/mmcloughlin/avo/operand"
) )
@@ -22,13 +22,13 @@ func NewGoAsm(cfg Config) Printer {
return &goasm{cfg: cfg} return &goasm{cfg: cfg}
} }
func (p *goasm) Print(f *avo.File) ([]byte, error) { func (p *goasm) Print(f *ir.File) ([]byte, error) {
p.header(f) p.header(f)
for _, s := range f.Sections { for _, s := range f.Sections {
switch s := s.(type) { switch s := s.(type) {
case *avo.Function: case *ir.Function:
p.function(s) p.function(s)
case *avo.Global: case *ir.Global:
p.global(s) p.global(s)
default: default:
panic("unknown section type") panic("unknown section type")
@@ -37,7 +37,7 @@ func (p *goasm) Print(f *avo.File) ([]byte, error) {
return p.Result() return p.Result()
} }
func (p *goasm) header(f *avo.File) { func (p *goasm) header(f *ir.File) {
p.Comment(p.cfg.GeneratedWarning()) p.Comment(p.cfg.GeneratedWarning())
if len(f.Constraints) > 0 { if len(f.Constraints) > 0 {
@@ -57,7 +57,7 @@ func (p *goasm) includes(paths []string) {
} }
} }
func (p *goasm) function(f *avo.Function) { func (p *goasm) function(f *ir.Function) {
p.NL() p.NL()
p.Comment(f.Stub()) p.Comment(f.Stub())
@@ -83,13 +83,13 @@ func (p *goasm) function(f *avo.Function) {
for _, node := range f.Nodes { for _, node := range f.Nodes {
switch n := node.(type) { switch n := node.(type) {
case *avo.Instruction: case *ir.Instruction:
if len(n.Operands) > 0 { if len(n.Operands) > 0 {
p.Printf("\t%s\t%s\n", n.Opcode, joinOperands(n.Operands)) p.Printf("\t%s\t%s\n", n.Opcode, joinOperands(n.Operands))
} else { } else {
p.Printf("\t%s\n", n.Opcode) p.Printf("\t%s\n", n.Opcode)
} }
case avo.Label: case ir.Label:
p.Printf("%s:\n", n) p.Printf("%s:\n", n)
default: default:
panic("unexpected node type") panic("unexpected node type")
@@ -97,7 +97,7 @@ func (p *goasm) function(f *avo.Function) {
} }
} }
func (p *goasm) global(g *avo.Global) { func (p *goasm) global(g *ir.Global) {
p.NL() p.NL()
for _, d := range g.Data { for _, d := range g.Data {
a := operand.NewDataAddr(g.Symbol, d.Offset) a := operand.NewDataAddr(g.Symbol, d.Offset)
@@ -106,7 +106,7 @@ func (p *goasm) global(g *avo.Global) {
p.Printf("GLOBL %s(SB), %s, $%d\n", g.Symbol, g.Attributes.Asm(), g.Size) p.Printf("GLOBL %s(SB), %s, $%d\n", g.Symbol, g.Attributes.Asm(), g.Size)
} }
func textsize(f *avo.Function) string { func textsize(f *ir.Function) string {
// Reference: https://github.com/golang/go/blob/b115207baf6c2decc3820ada4574ef4e5ad940ec/src/cmd/internal/obj/util.go#L260-L265 // Reference: https://github.com/golang/go/blob/b115207baf6c2decc3820ada4574ef4e5ad940ec/src/cmd/internal/obj/util.go#L260-L265
// //
// case TYPE_TEXTSIZE: // case TYPE_TEXTSIZE:

View File

@@ -7,13 +7,13 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/mmcloughlin/avo"
"github.com/mmcloughlin/avo/internal/stack" "github.com/mmcloughlin/avo/internal/stack"
"github.com/mmcloughlin/avo/ir"
) )
// Printer can produce output for an avo File. // Printer can produce output for an avo File.
type Printer interface { type Printer interface {
Print(*avo.File) ([]byte, error) Print(*ir.File) ([]byte, error)
} }
// Builder can construct a printer. // Builder can construct a printer.

View File

@@ -1,8 +1,8 @@
package printer package printer
import ( import (
"github.com/mmcloughlin/avo"
"github.com/mmcloughlin/avo/internal/prnt" "github.com/mmcloughlin/avo/internal/prnt"
"github.com/mmcloughlin/avo/ir"
) )
type stubs struct { type stubs struct {
@@ -15,7 +15,7 @@ func NewStubs(cfg Config) Printer {
return &stubs{cfg: cfg} return &stubs{cfg: cfg}
} }
func (s *stubs) Print(f *avo.File) ([]byte, error) { func (s *stubs) Print(f *ir.File) ([]byte, error) {
s.Comment(s.cfg.GeneratedWarning()) s.Comment(s.cfg.GeneratedWarning())
if len(f.Constraints) > 0 { if len(f.Constraints) > 0 {

File diff suppressed because it is too large Load Diff