printing: commit some refactors (probably broken)
This commit is contained in:
132
build/cli.go
Normal file
132
build/cli.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package build
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/mmcloughlin/avo/pass"
|
||||
"github.com/mmcloughlin/avo/printer"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
ErrOut io.Writer
|
||||
Passes []pass.Interface
|
||||
}
|
||||
|
||||
func Main(cfg *Config, context *Context) int {
|
||||
diag := log.New(cfg.ErrOut, "", 0)
|
||||
|
||||
f, errs := context.Result()
|
||||
if errs != nil {
|
||||
for _, err := range errs {
|
||||
diag.Println(err)
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
p := pass.Concat(cfg.Passes...)
|
||||
if err := p.Execute(f); err != nil {
|
||||
diag.Println(err)
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
type Flags struct {
|
||||
errout *outputValue
|
||||
printers []*printerValue
|
||||
}
|
||||
|
||||
func NewFlags(fs *flag.FlagSet) *Flags {
|
||||
f := &Flags{}
|
||||
|
||||
f.errout = newOutputValue(os.Stderr)
|
||||
fs.Var(f.errout, "log", "diagnostics output")
|
||||
|
||||
goasm := newPrinterValue(printer.NewGoAsm, os.Stdout)
|
||||
fs.Var(goasm, "out", "assembly output")
|
||||
f.printers = append(f.printers, goasm)
|
||||
|
||||
stubs := newPrinterValue(printer.NewStubs, nil)
|
||||
fs.Var(stubs, "stubs", "go stub file")
|
||||
f.printers = append(f.printers, stubs)
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *Flags) Config() *Config {
|
||||
pc := printer.NewDefaultConfig()
|
||||
passes := []pass.Interface{pass.Compile}
|
||||
for _, pv := range f.printers {
|
||||
p := pv.Build(pc)
|
||||
if p != nil {
|
||||
passes = append(passes, p)
|
||||
}
|
||||
}
|
||||
return &Config{
|
||||
ErrOut: f.errout.w,
|
||||
Passes: passes,
|
||||
}
|
||||
}
|
||||
|
||||
type outputValue struct {
|
||||
w io.WriteCloser
|
||||
filename string
|
||||
}
|
||||
|
||||
func newOutputValue(dflt io.WriteCloser) *outputValue {
|
||||
return &outputValue{w: dflt}
|
||||
}
|
||||
|
||||
func (o *outputValue) String() string {
|
||||
if o == nil {
|
||||
return ""
|
||||
}
|
||||
return o.filename
|
||||
}
|
||||
|
||||
func (o *outputValue) Set(s string) error {
|
||||
o.filename = s
|
||||
if s == "-" {
|
||||
o.w = nopwritecloser{os.Stdout}
|
||||
return nil
|
||||
}
|
||||
f, err := os.Create(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.w = f
|
||||
return nil
|
||||
}
|
||||
|
||||
type printerValue struct {
|
||||
*outputValue
|
||||
Builder printer.Builder
|
||||
}
|
||||
|
||||
func newPrinterValue(b printer.Builder, dflt io.WriteCloser) *printerValue {
|
||||
return &printerValue{
|
||||
outputValue: newOutputValue(dflt),
|
||||
Builder: b,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *printerValue) Build(cfg printer.Config) pass.Interface {
|
||||
if p.outputValue.w == nil {
|
||||
return nil
|
||||
}
|
||||
return &pass.Output{
|
||||
Writer: p.outputValue.w,
|
||||
Printer: p.Builder(cfg),
|
||||
}
|
||||
}
|
||||
|
||||
// nopwritecloser wraps a Writer and provides a null implementation of Close().
|
||||
type nopwritecloser struct {
|
||||
io.Writer
|
||||
}
|
||||
|
||||
func (nopwritecloser) Close() error { return nil }
|
||||
@@ -2,13 +2,9 @@ package build
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
|
||||
"github.com/mmcloughlin/avo/gotypes"
|
||||
"github.com/mmcloughlin/avo/pass"
|
||||
|
||||
"github.com/mmcloughlin/avo"
|
||||
"github.com/mmcloughlin/avo/gotypes"
|
||||
"github.com/mmcloughlin/avo/reg"
|
||||
)
|
||||
|
||||
@@ -73,28 +69,3 @@ func (c *Context) AddErrorMessage(msg string) {
|
||||
func (c *Context) Result() (*avo.File, []error) {
|
||||
return c.file, c.errs
|
||||
}
|
||||
|
||||
func (c *Context) Main(wout, werr io.Writer) int {
|
||||
diag := log.New(werr, "", 0)
|
||||
|
||||
f, errs := c.Result()
|
||||
if errs != nil {
|
||||
for _, err := range errs {
|
||||
diag.Println(err)
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
if err := pass.Compile.Execute(f); err != nil {
|
||||
diag.Println(err)
|
||||
return 1
|
||||
}
|
||||
|
||||
p := avo.NewGoPrinter(wout)
|
||||
if err := p.Print(f); err != nil {
|
||||
diag.Println(err)
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@ package build
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/mmcloughlin/avo/gotypes"
|
||||
@@ -23,26 +21,14 @@ func TEXT(name, signature string) {
|
||||
|
||||
func LABEL(name string) { ctx.Label(avo.Label(name)) }
|
||||
|
||||
var (
|
||||
output = flag.String("output", "", "output filename (default stdout)")
|
||||
)
|
||||
var flags = NewFlags(flag.CommandLine)
|
||||
|
||||
func EOF() {
|
||||
func Generate() {
|
||||
if !flag.Parsed() {
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
var w io.Writer = os.Stdout
|
||||
if *output != "" {
|
||||
if f, err := os.Create(*output); err != nil {
|
||||
log.Fatal(err)
|
||||
} else {
|
||||
defer f.Close()
|
||||
w = f
|
||||
}
|
||||
}
|
||||
|
||||
os.Exit(ctx.Main(w, os.Stderr))
|
||||
cfg := flags.Config()
|
||||
os.Exit(Main(cfg, ctx))
|
||||
}
|
||||
|
||||
func GP8v() reg.Virtual { return ctx.GP8v() }
|
||||
|
||||
10
examples/add/add.s
Normal file
10
examples/add/add.s
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
#include "textflag.h"
|
||||
|
||||
// func Add(x uint64, y uint64) uint64
|
||||
TEXT ·Add(SB),0,$0-24
|
||||
MOVQ x(FP), CX
|
||||
MOVQ y+8(FP), AX
|
||||
ADDQ CX, AX
|
||||
MOVQ CX, ret+16(FP)
|
||||
RET
|
||||
12
examples/add/add_test.go
Normal file
12
examples/add/add_test.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package add
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"testing/quick"
|
||||
)
|
||||
|
||||
//go:generate go run asm.go -out add.s -stubs stub.go
|
||||
|
||||
func TestAdd(t *testing.T) {
|
||||
quick.CheckEqual(Add, func(x, y uint64) uint64 { return x + y }, nil)
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
@@ -5,11 +7,11 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
TEXT("add", "func(x, y uint64) uint64")
|
||||
TEXT("Add", "func(x, y uint64) uint64")
|
||||
x := Load(Param("x"), GP64v())
|
||||
y := Load(Param("y"), GP64v())
|
||||
ADDQ(x, y)
|
||||
Store(x, ReturnIndex(0))
|
||||
RET()
|
||||
EOF()
|
||||
Generate()
|
||||
}
|
||||
|
||||
3
examples/add/stub.go
Normal file
3
examples/add/stub.go
Normal file
@@ -0,0 +1,3 @@
|
||||
package add
|
||||
|
||||
func Add(x uint64, y uint64) uint64
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"github.com/mmcloughlin/avo/internal/gen"
|
||||
"github.com/mmcloughlin/avo/internal/inst"
|
||||
"github.com/mmcloughlin/avo/internal/load"
|
||||
"github.com/mmcloughlin/avo/printer"
|
||||
)
|
||||
|
||||
var generators = map[string]gen.Builder{
|
||||
@@ -45,9 +46,7 @@ func main() {
|
||||
log.Fatalf("unknown generator type '%s'", t)
|
||||
}
|
||||
|
||||
g := builder(gen.Config{
|
||||
Argv: os.Args,
|
||||
})
|
||||
g := builder(printer.NewDefaultConfig())
|
||||
|
||||
// Determine output writer.
|
||||
w := os.Stdout
|
||||
|
||||
@@ -7,17 +7,19 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/mmcloughlin/avo/internal/inst"
|
||||
"github.com/mmcloughlin/avo/internal/prnt"
|
||||
"github.com/mmcloughlin/avo/printer"
|
||||
)
|
||||
|
||||
type asmtest struct {
|
||||
cfg Config
|
||||
cfg printer.Config
|
||||
sym string // reference to the test function symbol
|
||||
rel8 string // label to be used for near jumps
|
||||
rel32 string // label for far jumps
|
||||
generator
|
||||
prnt.Generator
|
||||
}
|
||||
|
||||
func NewAsmTest(cfg Config) Interface {
|
||||
func NewAsmTest(cfg printer.Config) Interface {
|
||||
return &asmtest{cfg: cfg}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
package gen
|
||||
|
||||
import "github.com/mmcloughlin/avo/internal/inst"
|
||||
import (
|
||||
"github.com/mmcloughlin/avo/internal/inst"
|
||||
"github.com/mmcloughlin/avo/internal/prnt"
|
||||
"github.com/mmcloughlin/avo/printer"
|
||||
)
|
||||
|
||||
type build struct {
|
||||
cfg Config
|
||||
generator
|
||||
cfg printer.Config
|
||||
prnt.Generator
|
||||
}
|
||||
|
||||
func NewBuild(cfg Config) Interface {
|
||||
func NewBuild(cfg printer.Config) Interface {
|
||||
return GoFmt(&build{cfg: cfg})
|
||||
}
|
||||
|
||||
|
||||
@@ -6,14 +6,16 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/mmcloughlin/avo/internal/inst"
|
||||
"github.com/mmcloughlin/avo/internal/prnt"
|
||||
"github.com/mmcloughlin/avo/printer"
|
||||
)
|
||||
|
||||
type ctors struct {
|
||||
cfg Config
|
||||
generator
|
||||
cfg printer.Config
|
||||
prnt.Generator
|
||||
}
|
||||
|
||||
func NewCtors(cfg Config) Interface {
|
||||
func NewCtors(cfg printer.Config) Interface {
|
||||
return GoFmt(&ctors{cfg: cfg})
|
||||
}
|
||||
|
||||
|
||||
@@ -3,15 +3,18 @@ package gen
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/mmcloughlin/avo/internal/prnt"
|
||||
"github.com/mmcloughlin/avo/printer"
|
||||
|
||||
"github.com/mmcloughlin/avo/internal/inst"
|
||||
)
|
||||
|
||||
type ctorstest struct {
|
||||
cfg Config
|
||||
generator
|
||||
cfg printer.Config
|
||||
prnt.Generator
|
||||
}
|
||||
|
||||
func NewCtorsTest(cfg Config) Interface {
|
||||
func NewCtorsTest(cfg printer.Config) Interface {
|
||||
return GoFmt(&ctorstest{cfg: cfg})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
package gen
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/format"
|
||||
"strings"
|
||||
|
||||
"github.com/mmcloughlin/avo/internal/inst"
|
||||
"github.com/mmcloughlin/avo/printer"
|
||||
)
|
||||
|
||||
type Interface interface {
|
||||
@@ -19,23 +17,7 @@ func (f Func) Generate(is []inst.Instruction) ([]byte, error) {
|
||||
return f(is)
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Name string
|
||||
Argv []string
|
||||
}
|
||||
|
||||
func (c Config) GeneratedBy() string {
|
||||
if c.Argv == nil {
|
||||
return c.Name
|
||||
}
|
||||
return fmt.Sprintf("command: %s", strings.Join(c.Argv, " "))
|
||||
}
|
||||
|
||||
func (c Config) GeneratedWarning() string {
|
||||
return fmt.Sprintf("Code generated by %s. DO NOT EDIT.", c.GeneratedBy())
|
||||
}
|
||||
|
||||
type Builder func(Config) Interface
|
||||
type Builder func(printer.Config) Interface
|
||||
|
||||
// GoFmt formats Go code produced from the given generator.
|
||||
func GoFmt(i Interface) Interface {
|
||||
@@ -47,27 +29,3 @@ func GoFmt(i Interface) Interface {
|
||||
return format.Source(b)
|
||||
})
|
||||
}
|
||||
|
||||
type generator struct {
|
||||
buf bytes.Buffer
|
||||
err error
|
||||
}
|
||||
|
||||
func (g *generator) Printf(format string, args ...interface{}) {
|
||||
if g.err != nil {
|
||||
return
|
||||
}
|
||||
if _, err := fmt.Fprintf(&g.buf, format, args...); err != nil {
|
||||
g.AddError(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *generator) AddError(err error) {
|
||||
if err != nil && g.err == nil {
|
||||
g.err = err
|
||||
}
|
||||
}
|
||||
|
||||
func (g *generator) Result() ([]byte, error) {
|
||||
return g.buf.Bytes(), g.err
|
||||
}
|
||||
|
||||
@@ -2,14 +2,16 @@ package gen
|
||||
|
||||
import (
|
||||
"github.com/mmcloughlin/avo/internal/inst"
|
||||
"github.com/mmcloughlin/avo/internal/prnt"
|
||||
"github.com/mmcloughlin/avo/printer"
|
||||
)
|
||||
|
||||
type godata struct {
|
||||
cfg Config
|
||||
generator
|
||||
cfg printer.Config
|
||||
prnt.Generator
|
||||
}
|
||||
|
||||
func NewGoData(cfg Config) Interface {
|
||||
func NewGoData(cfg printer.Config) Interface {
|
||||
return GoFmt(&godata{cfg: cfg})
|
||||
}
|
||||
|
||||
@@ -65,11 +67,11 @@ func (g *godata) Generate(is []inst.Instruction) ([]byte, error) {
|
||||
}
|
||||
|
||||
type godatatest struct {
|
||||
cfg Config
|
||||
generator
|
||||
cfg printer.Config
|
||||
prnt.Generator
|
||||
}
|
||||
|
||||
func NewGoDataTest(cfg Config) Interface {
|
||||
func NewGoDataTest(cfg printer.Config) Interface {
|
||||
return GoFmt(&godatatest{cfg: cfg})
|
||||
}
|
||||
|
||||
|
||||
@@ -7,14 +7,16 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/mmcloughlin/avo/internal/inst"
|
||||
"github.com/mmcloughlin/avo/internal/prnt"
|
||||
"github.com/mmcloughlin/avo/printer"
|
||||
)
|
||||
|
||||
type mov struct {
|
||||
cfg Config
|
||||
generator
|
||||
cfg printer.Config
|
||||
prnt.Generator
|
||||
}
|
||||
|
||||
func NewMOV(cfg Config) Interface {
|
||||
func NewMOV(cfg printer.Config) Interface {
|
||||
return GoFmt(&mov{cfg: cfg})
|
||||
}
|
||||
|
||||
|
||||
40
internal/prnt/printer.go
Normal file
40
internal/prnt/printer.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package prnt
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Generator struct {
|
||||
buf bytes.Buffer
|
||||
err error
|
||||
}
|
||||
|
||||
func (g *Generator) Printf(format string, args ...interface{}) {
|
||||
if g.err != nil {
|
||||
return
|
||||
}
|
||||
if _, err := fmt.Fprintf(&g.buf, format, args...); err != nil {
|
||||
g.AddError(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Generator) NL() {
|
||||
g.Printf("\n")
|
||||
}
|
||||
|
||||
func (g *Generator) Comment(lines ...string) {
|
||||
for _, line := range lines {
|
||||
g.Printf("// %s\n", line)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Generator) AddError(err error) {
|
||||
if err != nil && g.err == nil {
|
||||
g.err = err
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Generator) Result() ([]byte, error) {
|
||||
return g.buf.Bytes(), g.err
|
||||
}
|
||||
23
pass/pass.go
23
pass/pass.go
@@ -1,6 +1,11 @@
|
||||
package pass
|
||||
|
||||
import "github.com/mmcloughlin/avo"
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/mmcloughlin/avo"
|
||||
"github.com/mmcloughlin/avo/printer"
|
||||
)
|
||||
|
||||
var Compile = Concat(
|
||||
FunctionPass(LabelTarget),
|
||||
@@ -42,3 +47,19 @@ func Concat(passes ...Interface) Interface {
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
type Output struct {
|
||||
Writer io.WriteCloser
|
||||
Printer printer.Printer
|
||||
}
|
||||
|
||||
func (o *Output) Execute(f *avo.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()
|
||||
}
|
||||
|
||||
102
printer.go
102
printer.go
@@ -1,102 +0,0 @@
|
||||
package avo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/mmcloughlin/avo/operand"
|
||||
)
|
||||
|
||||
// dot is the pesky unicode dot used in Go assembly.
|
||||
const dot = "\u00b7"
|
||||
|
||||
type Printer interface {
|
||||
Print(*File) error
|
||||
}
|
||||
|
||||
type GoPrinter struct {
|
||||
w io.Writer
|
||||
by string // generated by
|
||||
err error
|
||||
}
|
||||
|
||||
func NewGoPrinter(w io.Writer) *GoPrinter {
|
||||
return &GoPrinter{
|
||||
w: w,
|
||||
by: "avo",
|
||||
}
|
||||
}
|
||||
|
||||
func (p *GoPrinter) SetGeneratedBy(by string) {
|
||||
p.by = by
|
||||
}
|
||||
|
||||
func (p *GoPrinter) Print(f *File) error {
|
||||
p.header()
|
||||
|
||||
for _, fn := range f.Functions {
|
||||
p.function(fn)
|
||||
}
|
||||
|
||||
return p.err
|
||||
}
|
||||
|
||||
func (p *GoPrinter) header() {
|
||||
p.generated()
|
||||
p.nl()
|
||||
p.incl("textflag.h")
|
||||
p.nl()
|
||||
}
|
||||
|
||||
func (p *GoPrinter) generated() {
|
||||
p.comment(fmt.Sprintf("Code generated by %s. DO NOT EDIT.", p.by))
|
||||
}
|
||||
|
||||
func (p *GoPrinter) incl(path string) {
|
||||
p.printf("#include \"%s\"\n", path)
|
||||
}
|
||||
|
||||
func (p *GoPrinter) comment(line string) {
|
||||
p.multicomment([]string{line})
|
||||
}
|
||||
|
||||
func (p *GoPrinter) multicomment(lines []string) {
|
||||
for _, line := range lines {
|
||||
p.printf("// %s\n", line)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *GoPrinter) function(f *Function) {
|
||||
p.printf("// %s\n", f.Stub())
|
||||
p.printf("TEXT %s%s(SB),0,$%d-%d\n", dot, f.Name, f.FrameBytes(), f.ArgumentBytes())
|
||||
|
||||
for _, node := range f.Nodes {
|
||||
switch n := node.(type) {
|
||||
case *Instruction:
|
||||
p.printf("\t%s\t%s\n", n.Opcode, joinOperands(n.Operands))
|
||||
case Label:
|
||||
p.printf("%s:\n", n)
|
||||
default:
|
||||
panic("unexpected node type")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (p *GoPrinter) nl() {
|
||||
p.printf("\n")
|
||||
}
|
||||
|
||||
func (p *GoPrinter) printf(format string, args ...interface{}) {
|
||||
if _, err := fmt.Fprintf(p.w, format, args...); err != nil {
|
||||
p.err = err
|
||||
}
|
||||
}
|
||||
|
||||
func joinOperands(operands []operand.Op) string {
|
||||
asm := make([]string, len(operands))
|
||||
for i, op := range operands {
|
||||
asm[i] = op.Asm()
|
||||
}
|
||||
return strings.Join(asm, ", ")
|
||||
}
|
||||
63
printer/goasm.go
Normal file
63
printer/goasm.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package printer
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/mmcloughlin/avo"
|
||||
"github.com/mmcloughlin/avo/internal/prnt"
|
||||
"github.com/mmcloughlin/avo/operand"
|
||||
)
|
||||
|
||||
// dot is the pesky unicode dot used in Go assembly.
|
||||
const dot = "\u00b7"
|
||||
|
||||
type goasm struct {
|
||||
cfg Config
|
||||
prnt.Generator
|
||||
}
|
||||
|
||||
func NewGoAsm(cfg Config) Printer {
|
||||
return &goasm{cfg: cfg}
|
||||
}
|
||||
|
||||
func (p *goasm) Print(f *avo.File) ([]byte, error) {
|
||||
p.header()
|
||||
for _, fn := range f.Functions {
|
||||
p.function(fn)
|
||||
}
|
||||
return p.Result()
|
||||
}
|
||||
|
||||
func (p *goasm) header() {
|
||||
p.NL()
|
||||
p.include("textflag.h")
|
||||
p.NL()
|
||||
}
|
||||
|
||||
func (p *goasm) include(path string) {
|
||||
p.Printf("#include \"%s\"\n", path)
|
||||
}
|
||||
|
||||
func (p *goasm) function(f *avo.Function) {
|
||||
p.Comment(f.Stub())
|
||||
p.Printf("TEXT %s%s(SB),0,$%d-%d\n", dot, f.Name, f.FrameBytes(), f.ArgumentBytes())
|
||||
|
||||
for _, node := range f.Nodes {
|
||||
switch n := node.(type) {
|
||||
case *avo.Instruction:
|
||||
p.Printf("\t%s\t%s\n", n.Opcode, joinOperands(n.Operands))
|
||||
case avo.Label:
|
||||
p.Printf("%s:\n", n)
|
||||
default:
|
||||
panic("unexpected node type")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func joinOperands(operands []operand.Op) string {
|
||||
asm := make([]string, len(operands))
|
||||
for i, op := range operands {
|
||||
asm[i] = op.Asm()
|
||||
}
|
||||
return strings.Join(asm, ", ")
|
||||
}
|
||||
43
printer/printer.go
Normal file
43
printer/printer.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package printer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/mmcloughlin/avo"
|
||||
)
|
||||
|
||||
type Printer interface {
|
||||
Print(*avo.File) ([]byte, error)
|
||||
}
|
||||
|
||||
type Builder func(Config) Printer
|
||||
|
||||
type Config struct {
|
||||
Name string
|
||||
Argv []string
|
||||
Pkg string
|
||||
}
|
||||
|
||||
func NewDefaultConfig() Config {
|
||||
cfg := Config{
|
||||
Argv: os.Args,
|
||||
}
|
||||
if cwd, err := os.Getwd(); err == nil {
|
||||
cfg.Pkg = filepath.Base(cwd)
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
|
||||
func (c Config) GeneratedBy() string {
|
||||
if c.Argv == nil {
|
||||
return c.Name
|
||||
}
|
||||
return fmt.Sprintf("command: %s", strings.Join(c.Argv, " "))
|
||||
}
|
||||
|
||||
func (c Config) GeneratedWarning() string {
|
||||
return fmt.Sprintf("Code generated by %s. DO NOT EDIT.", c.GeneratedBy())
|
||||
}
|
||||
23
printer/stubs.go
Normal file
23
printer/stubs.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package printer
|
||||
|
||||
import (
|
||||
"github.com/mmcloughlin/avo"
|
||||
"github.com/mmcloughlin/avo/internal/prnt"
|
||||
)
|
||||
|
||||
type stubs struct {
|
||||
cfg Config
|
||||
prnt.Generator
|
||||
}
|
||||
|
||||
func NewStubs(cfg Config) Printer {
|
||||
return &stubs{cfg: cfg}
|
||||
}
|
||||
|
||||
func (s *stubs) Print(f *avo.File) ([]byte, error) {
|
||||
s.Printf("package %s\n\n", s.cfg.Pkg)
|
||||
for _, fn := range f.Functions {
|
||||
s.Printf("%s\n", fn.Stub())
|
||||
}
|
||||
return s.Result()
|
||||
}
|
||||
Reference in New Issue
Block a user