// Package pass implements processing passes on avo Files. package pass import ( "io" "github.com/mmcloughlin/avo/ir" "github.com/mmcloughlin/avo/printer" ) // Compile pass compiles an avo file. Upon successful completion the avo file // may be printed to Go assembly. var Compile = Concat( Verify, FunctionPass(PruneJumpToFollowingLabel), FunctionPass(PruneDanglingLabels), FunctionPass(LabelTarget), FunctionPass(CFG), InstructionPass(ZeroExtend32BitOutputs), FunctionPass(Liveness), FunctionPass(AllocateRegisters), FunctionPass(BindRegisters), FunctionPass(VerifyAllocation), Func(IncludeTextFlagHeader), FunctionPass(PruneSelfMoves), FunctionPass(RequiredISAExtensions), ) // Interface for a processing pass. type Interface interface { Execute(*ir.File) error } // Func adapts a function to the pass Interface. type Func func(*ir.File) error // Execute calls p. func (p Func) Execute(f *ir.File) error { return p(f) } // 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 // 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() { if err := p(fn); err != nil { return err } } return nil } // InstructionPass is a convenience for implementing a full file pass with a // function that operates on each Instruction independently. type InstructionPass func(*ir.Instruction) error // Execute calls p on every instruction in the file. Exits on the first error. func (p InstructionPass) Execute(f *ir.File) error { for _, fn := range f.Functions() { for _, i := range fn.Instructions() { if err := p(i); err != nil { return err } } } return nil } // Concat returns a pass that executes the given passes in order, stopping on the first error. func Concat(passes ...Interface) Interface { return Func(func(f *ir.File) error { for _, p := range passes { if err := p.Execute(f); err != nil { return err } } return nil }) } // Output pass prints a file. type Output struct { Writer io.WriteCloser Printer printer.Printer } // 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() }