Files
avo/pass/pass.go

83 lines
1.9 KiB
Go
Raw Normal View History

2019-01-04 20:00:22 -08:00
// Package pass implements processing passes on avo Files.
2018-12-02 12:28:33 -08:00
package pass
import (
"io"
"github.com/mmcloughlin/avo/ir"
"github.com/mmcloughlin/avo/printer"
)
2018-12-02 12:28:33 -08:00
2019-01-04 20:00:22 -08:00
// Compile pass compiles an avo file. Upon successful completion the avo file
// may be printed to Go assembly.
2018-12-08 22:02:02 -08:00
var Compile = Concat(
FunctionPass(PruneJumpToFollowingLabel),
FunctionPass(PruneDanglingLabels),
2018-12-08 22:02:02 -08:00
FunctionPass(LabelTarget),
FunctionPass(CFG),
FunctionPass(Liveness),
FunctionPass(AllocateRegisters),
FunctionPass(BindRegisters),
FunctionPass(VerifyAllocation),
Func(IncludeTextFlagHeader),
FunctionPass(PruneSelfMoves),
FunctionPass(RequiredISAExtensions),
2018-12-08 22:02:02 -08:00
)
2018-12-02 12:28:33 -08:00
2019-01-04 20:00:22 -08:00
// Interface for a processing pass.
2018-12-08 22:02:02 -08:00
type Interface interface {
Execute(*ir.File) error
2018-12-08 22:02:02 -08:00
}
2019-01-04 20:00:22 -08:00
// Func adapts a function to the pass Interface.
type Func func(*ir.File) error
2018-12-08 22:02:02 -08:00
2019-01-04 20:00:22 -08:00
// Execute calls p.
func (p Func) Execute(f *ir.File) error {
2018-12-08 22:02:02 -08:00
return p(f)
}
2019-01-04 20:00:22 -08:00
// FunctionPass is a convenience for implementing a full file pass with a
// function that operates on each avo Function independently.
type FunctionPass func(*ir.Function) error
2018-12-08 22:02:02 -08:00
2019-01-04 20:00:22 -08:00
// Execute calls p on every function in the file. Exits on the first error.
func (p FunctionPass) Execute(f *ir.File) error {
for _, fn := range f.Functions() {
2018-12-08 22:02:02 -08:00
if err := p(fn); err != nil {
return err
}
}
return nil
}
2019-01-04 20:00:22 -08:00
// Concat returns a pass that executes the given passes in order, stopping on the first error.
2018-12-08 22:02:02 -08:00
func Concat(passes ...Interface) Interface {
return Func(func(f *ir.File) error {
2018-12-08 22:02:02 -08:00
for _, p := range passes {
if err := p.Execute(f); err != nil {
2018-12-02 12:28:33 -08:00
return err
}
}
return nil
2018-12-08 22:02:02 -08:00
})
2018-12-02 12:28:33 -08:00
}
2019-01-04 20:00:22 -08:00
// Output pass prints a file.
type Output struct {
Writer io.WriteCloser
Printer printer.Printer
}
2019-01-04 20:00:22 -08:00
// Execute prints f with the configured Printer and writes output to Writer.
func (o *Output) Execute(f *ir.File) error {
b, err := o.Printer.Print(f)
if err != nil {
return err
}
if _, err = o.Writer.Write(b); err != nil {
return err
}
return o.Writer.Close()
}