build: doc external symbols (#9)
This commit is contained in:
@@ -11,12 +11,16 @@ import (
|
|||||||
"github.com/mmcloughlin/avo/printer"
|
"github.com/mmcloughlin/avo/printer"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Config contains options for an avo main function.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
ErrOut io.Writer
|
ErrOut io.Writer
|
||||||
CPUProfile io.WriteCloser
|
CPUProfile io.WriteCloser
|
||||||
Passes []pass.Interface
|
Passes []pass.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Main is the standard main function for an avo program. This extracts the
|
||||||
|
// result from the build Context (logging and exiting on error), and performs
|
||||||
|
// configured passes.
|
||||||
func Main(cfg *Config, context *Context) int {
|
func Main(cfg *Config, context *Context) int {
|
||||||
diag := log.New(cfg.ErrOut, "", 0)
|
diag := log.New(cfg.ErrOut, "", 0)
|
||||||
|
|
||||||
@@ -46,12 +50,14 @@ func Main(cfg *Config, context *Context) int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Flags represents CLI flags for an avo program.
|
||||||
type Flags struct {
|
type Flags struct {
|
||||||
errout *outputValue
|
errout *outputValue
|
||||||
cpuprof *outputValue
|
cpuprof *outputValue
|
||||||
printers []*printerValue
|
printers []*printerValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewFlags initializes avo flags for the given FlagSet.
|
||||||
func NewFlags(fs *flag.FlagSet) *Flags {
|
func NewFlags(fs *flag.FlagSet) *Flags {
|
||||||
f := &Flags{}
|
f := &Flags{}
|
||||||
|
|
||||||
@@ -72,6 +78,7 @@ func NewFlags(fs *flag.FlagSet) *Flags {
|
|||||||
return f
|
return f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Config builds a configuration object based on flag values.
|
||||||
func (f *Flags) Config() *Config {
|
func (f *Flags) Config() *Config {
|
||||||
pc := printer.NewGoRunConfig()
|
pc := printer.NewGoRunConfig()
|
||||||
passes := []pass.Interface{pass.Compile}
|
passes := []pass.Interface{pass.Compile}
|
||||||
|
|||||||
@@ -37,13 +37,13 @@ func (c *Context) Package(path string) {
|
|||||||
}
|
}
|
||||||
pkgs, err := packages.Load(cfg, path)
|
pkgs, err := packages.Load(cfg, path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AddError(err)
|
c.adderror(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pkg := pkgs[0]
|
pkg := pkgs[0]
|
||||||
if len(pkg.Errors) > 0 {
|
if len(pkg.Errors) > 0 {
|
||||||
for _, err := range pkg.Errors {
|
for _, err := range pkg.Errors {
|
||||||
c.AddError(err)
|
c.adderror(err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -54,7 +54,7 @@ func (c *Context) Package(path string) {
|
|||||||
func (c *Context) Constraints(t buildtags.ConstraintsConvertable) {
|
func (c *Context) Constraints(t buildtags.ConstraintsConvertable) {
|
||||||
cs := t.ToConstraints()
|
cs := t.ToConstraints()
|
||||||
if err := cs.Validate(); err != nil {
|
if err := cs.Validate(); err != nil {
|
||||||
c.AddError(err)
|
c.adderror(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.file.Constraints = cs
|
c.file.Constraints = cs
|
||||||
@@ -65,14 +65,14 @@ func (c *Context) Constraint(t buildtags.ConstraintConvertable) {
|
|||||||
c.Constraints(append(c.file.Constraints, t.ToConstraint()))
|
c.Constraints(append(c.file.Constraints, t.ToConstraint()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constraint appends a constraint to the file's build constraints. The
|
// ConstraintExpr appends a constraint to the file's build constraints. The
|
||||||
// constraint to add is parsed from the given expression. The expression should
|
// constraint to add is parsed from the given expression. The expression should
|
||||||
// look the same as the content following "// +build " in regular build
|
// look the same as the content following "// +build " in regular build
|
||||||
// constraint comments.
|
// constraint comments.
|
||||||
func (c *Context) ConstraintExpr(expr string) {
|
func (c *Context) ConstraintExpr(expr string) {
|
||||||
constraint, err := buildtags.ParseConstraint(expr)
|
constraint, err := buildtags.ParseConstraint(expr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AddError(err)
|
c.adderror(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.Constraint(constraint)
|
c.Constraint(constraint)
|
||||||
@@ -103,7 +103,7 @@ func (c *Context) Signature(s *gotypes.Signature) {
|
|||||||
func (c *Context) SignatureExpr(expr string) {
|
func (c *Context) SignatureExpr(expr string) {
|
||||||
s, err := gotypes.ParseSignatureInPackage(c.types(), expr)
|
s, err := gotypes.ParseSignatureInPackage(c.types(), expr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AddError(err)
|
c.adderror(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.Signature(s)
|
c.Signature(s)
|
||||||
@@ -134,7 +134,7 @@ func (c *Context) Label(l avo.Label) {
|
|||||||
|
|
||||||
func (c *Context) activefunc() *avo.Function {
|
func (c *Context) activefunc() *avo.Function {
|
||||||
if c.function == nil {
|
if c.function == nil {
|
||||||
c.AddErrorMessage("no active function")
|
c.adderrormessage("no active function")
|
||||||
return avo.NewFunction("")
|
return avo.NewFunction("")
|
||||||
}
|
}
|
||||||
return c.function
|
return c.function
|
||||||
@@ -142,43 +142,48 @@ func (c *Context) activefunc() *avo.Function {
|
|||||||
|
|
||||||
//go:generate avogen -output zinstructions.go build
|
//go:generate avogen -output zinstructions.go build
|
||||||
|
|
||||||
|
// 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 = avo.NewStaticGlobal(name)
|
||||||
c.file.AddSection(c.global)
|
c.file.AddSection(c.global)
|
||||||
return c.global.Base()
|
return c.global.Base()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DataAttributes sets the attributes on the current active global data section.
|
||||||
func (c *Context) DataAttributes(a avo.Attribute) {
|
func (c *Context) DataAttributes(a avo.Attribute) {
|
||||||
c.activeglobal().Attributes = a
|
c.activeglobal().Attributes = a
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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(avo.NewDatum(offset, v)); err != nil {
|
||||||
c.AddError(err)
|
c.adderror(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AppendDatum appends a constant to the current active global data section.
|
||||||
func (c *Context) AppendDatum(v operand.Constant) {
|
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() *avo.Global {
|
||||||
if c.global == nil {
|
if c.global == nil {
|
||||||
c.AddErrorMessage("no active global")
|
c.adderrormessage("no active global")
|
||||||
return avo.NewStaticGlobal("")
|
return avo.NewStaticGlobal("")
|
||||||
}
|
}
|
||||||
return c.global
|
return c.global
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) AddError(err error) {
|
func (c *Context) adderror(err error) {
|
||||||
e := exterr(err)
|
e := exterr(err)
|
||||||
c.errs = append(c.errs, e)
|
c.errs = append(c.errs, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) AddErrorMessage(msg string) {
|
func (c *Context) adderrormessage(msg string) {
|
||||||
c.AddError(errors.New(msg))
|
c.adderror(errors.New(msg))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Result returns the built file and any accumulated errors.
|
||||||
func (c *Context) Result() (*avo.File, []error) {
|
func (c *Context) Result() (*avo.File, []error) {
|
||||||
return c.file, c.errs
|
return c.file, c.errs
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,27 +16,32 @@ import (
|
|||||||
// ctx provides a global build context.
|
// ctx provides a global build context.
|
||||||
var ctx = NewContext()
|
var ctx = NewContext()
|
||||||
|
|
||||||
func Package(path string) { ctx.Package(path) }
|
// TEXT starts building a new function called name and sets its signature (see SignatureExpr).
|
||||||
|
|
||||||
func TEXT(name, signature string) {
|
func TEXT(name, signature string) {
|
||||||
ctx.Function(name)
|
ctx.Function(name)
|
||||||
ctx.SignatureExpr(signature)
|
ctx.SignatureExpr(signature)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LABEL adds a label to the active function.
|
||||||
func LABEL(name string) { ctx.Label(avo.Label(name)) }
|
func LABEL(name string) { ctx.Label(avo.Label(name)) }
|
||||||
|
|
||||||
|
// GLOBL declares a new static global data section with the given attributes.
|
||||||
func GLOBL(name string, a avo.Attribute) operand.Mem {
|
func GLOBL(name string, a avo.Attribute) operand.Mem {
|
||||||
|
// TODO(mbm): should this be static?
|
||||||
g := ctx.StaticGlobal(name)
|
g := ctx.StaticGlobal(name)
|
||||||
ctx.DataAttributes(a)
|
ctx.DataAttributes(a)
|
||||||
return g
|
return g
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DATA adds a data value to the active data section.
|
||||||
func DATA(offset int, v operand.Constant) {
|
func DATA(offset int, v operand.Constant) {
|
||||||
ctx.AddDatum(offset, v)
|
ctx.AddDatum(offset, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
var flags = NewFlags(flag.CommandLine)
|
var flags = NewFlags(flag.CommandLine)
|
||||||
|
|
||||||
|
// Generate builds and compiles the avo file built with the global context. This
|
||||||
|
// should be the final line of any avo program. Configuration is determined from command-line flags.
|
||||||
func Generate() {
|
func Generate() {
|
||||||
if !flag.Parsed() {
|
if !flag.Parsed() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
@@ -53,29 +58,72 @@ func Generate() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Constraints(t buildtags.ConstraintsConvertable) { ctx.Constraints(t) }
|
// Package sets the package the generated file will belong to. Required to be able to reference types in the package.
|
||||||
func Constraint(t buildtags.ConstraintConvertable) { ctx.Constraint(t) }
|
func Package(path string) { ctx.Package(path) }
|
||||||
func ConstraintExpr(expr string) { ctx.ConstraintExpr(expr) }
|
|
||||||
|
|
||||||
func GP8() reg.GPVirtual { return ctx.GP8() }
|
// Constraints sets build constraints for the file.
|
||||||
|
func Constraints(t buildtags.ConstraintsConvertable) { ctx.Constraints(t) }
|
||||||
|
|
||||||
|
// Constraint appends a constraint to the file's build constraints.
|
||||||
|
func Constraint(t buildtags.ConstraintConvertable) { ctx.Constraint(t) }
|
||||||
|
|
||||||
|
// ConstraintExpr appends a constraint to the file's build constraints. The
|
||||||
|
// constraint to add is parsed from the given expression. The expression should
|
||||||
|
// look the same as the content following "// +build " in regular build
|
||||||
|
// constraint comments.
|
||||||
|
func ConstraintExpr(expr string) { ctx.ConstraintExpr(expr) }
|
||||||
|
|
||||||
|
// GP8 allocates and returns a general-purpose 8-bit register.
|
||||||
|
func GP8() reg.GPVirtual { return ctx.GP8() }
|
||||||
|
|
||||||
|
// GP16 allocates and returns a general-purpose 16-bit register.
|
||||||
func GP16() reg.GPVirtual { return ctx.GP16() }
|
func GP16() reg.GPVirtual { return ctx.GP16() }
|
||||||
|
|
||||||
|
// GP32 allocates and returns a general-purpose 32-bit register.
|
||||||
func GP32() reg.GPVirtual { return ctx.GP32() }
|
func GP32() reg.GPVirtual { return ctx.GP32() }
|
||||||
|
|
||||||
|
// GP64 allocates and returns a general-purpose 64-bit register.
|
||||||
func GP64() reg.GPVirtual { return ctx.GP64() }
|
func GP64() reg.GPVirtual { return ctx.GP64() }
|
||||||
|
|
||||||
|
// XMM allocates and returns a 128-bit vector register.
|
||||||
func XMM() reg.VecVirtual { return ctx.XMM() }
|
func XMM() reg.VecVirtual { return ctx.XMM() }
|
||||||
|
|
||||||
|
// YMM allocates and returns a 256-bit vector register.
|
||||||
func YMM() reg.VecVirtual { return ctx.YMM() }
|
func YMM() reg.VecVirtual { return ctx.YMM() }
|
||||||
|
|
||||||
|
// ZMM allocates and returns a 512-bit vector register.
|
||||||
func ZMM() reg.VecVirtual { return ctx.ZMM() }
|
func ZMM() reg.VecVirtual { return ctx.ZMM() }
|
||||||
|
|
||||||
func Param(name string) gotypes.Component { return ctx.Param(name) }
|
// Param returns a the named argument of the active function.
|
||||||
func ParamIndex(i int) gotypes.Component { return ctx.ParamIndex(i) }
|
func Param(name string) gotypes.Component { return ctx.Param(name) }
|
||||||
|
|
||||||
|
// ParamIndex returns the ith argument of the active function.
|
||||||
|
func ParamIndex(i int) gotypes.Component { return ctx.ParamIndex(i) }
|
||||||
|
|
||||||
|
// Return returns a the named return value of the active function.
|
||||||
func Return(name string) gotypes.Component { return ctx.Return(name) }
|
func Return(name string) gotypes.Component { return ctx.Return(name) }
|
||||||
func ReturnIndex(i int) gotypes.Component { return ctx.ReturnIndex(i) }
|
|
||||||
|
|
||||||
|
// ReturnIndex returns the ith argument of the active function.
|
||||||
|
func ReturnIndex(i int) gotypes.Component { return ctx.ReturnIndex(i) }
|
||||||
|
|
||||||
|
// Load the function argument src into register dst. Returns the destination
|
||||||
|
// register. This is syntactic sugar: it will attempt to select the right MOV
|
||||||
|
// instruction based on the types involved.
|
||||||
func Load(src gotypes.Component, dst reg.Register) reg.Register { return ctx.Load(src, dst) }
|
func Load(src gotypes.Component, dst reg.Register) reg.Register { return ctx.Load(src, dst) }
|
||||||
func Store(src reg.Register, dst gotypes.Component) { ctx.Store(src, dst) }
|
|
||||||
|
|
||||||
func Doc(lines ...string) { ctx.Doc(lines...) }
|
// Store register src into return value dst. This is syntactic sugar: it will
|
||||||
|
// attempt to select the right MOV instruction based on the types involved.
|
||||||
|
func Store(src reg.Register, dst gotypes.Component) { ctx.Store(src, dst) }
|
||||||
|
|
||||||
|
// Doc sets documentation comment lines for the currently active function.
|
||||||
|
func Doc(lines ...string) { ctx.Doc(lines...) }
|
||||||
|
|
||||||
|
// Attributes sets function attributes for the currently active function.
|
||||||
func Attributes(a avo.Attribute) { ctx.Attributes(a) }
|
func Attributes(a avo.Attribute) { ctx.Attributes(a) }
|
||||||
|
|
||||||
|
// AllocLocal allocates size bytes in the stack of the currently active function.
|
||||||
|
// Returns a reference to the base pointer for the newly allocated region.
|
||||||
func AllocLocal(size int) operand.Mem { return ctx.AllocLocal(size) }
|
func AllocLocal(size int) operand.Mem { return ctx.AllocLocal(size) }
|
||||||
|
|
||||||
|
// ConstData builds a static data section containing just the given constant.
|
||||||
func ConstData(name string, v operand.Constant) operand.Mem { return ctx.ConstData(name, v) }
|
func ConstData(name string, v operand.Constant) operand.Mem { return ctx.ConstData(name, v) }
|
||||||
|
|||||||
@@ -10,41 +10,51 @@ import (
|
|||||||
|
|
||||||
//go:generate avogen -output zmov.go mov
|
//go:generate avogen -output zmov.go mov
|
||||||
|
|
||||||
|
// Param returns a the named argument of the active function.
|
||||||
func (c *Context) Param(name string) gotypes.Component {
|
func (c *Context) Param(name string) gotypes.Component {
|
||||||
return c.activefunc().Signature.Params().Lookup(name)
|
return c.activefunc().Signature.Params().Lookup(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParamIndex returns the ith argument of the active function.
|
||||||
func (c *Context) ParamIndex(i int) gotypes.Component {
|
func (c *Context) ParamIndex(i int) gotypes.Component {
|
||||||
return c.activefunc().Signature.Params().At(i)
|
return c.activefunc().Signature.Params().At(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return returns a the named return value of the active function.
|
||||||
func (c *Context) Return(name string) gotypes.Component {
|
func (c *Context) Return(name string) gotypes.Component {
|
||||||
return c.activefunc().Signature.Results().Lookup(name)
|
return c.activefunc().Signature.Results().Lookup(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReturnIndex returns the ith argument of the active function.
|
||||||
func (c *Context) ReturnIndex(i int) gotypes.Component {
|
func (c *Context) ReturnIndex(i int) gotypes.Component {
|
||||||
return c.activefunc().Signature.Results().At(i)
|
return c.activefunc().Signature.Results().At(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load the function argument src into register dst. Returns the destination
|
||||||
|
// register. This is syntactic sugar: it will attempt to select the right MOV
|
||||||
|
// instruction based on the types involved.
|
||||||
func (c *Context) Load(src gotypes.Component, dst reg.Register) reg.Register {
|
func (c *Context) Load(src gotypes.Component, dst reg.Register) reg.Register {
|
||||||
b, err := src.Resolve()
|
b, err := src.Resolve()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AddError(err)
|
c.adderror(err)
|
||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
c.mov(b.Addr, dst, int(gotypes.Sizes.Sizeof(b.Type)), int(dst.Bytes()), b.Type)
|
c.mov(b.Addr, dst, int(gotypes.Sizes.Sizeof(b.Type)), int(dst.Bytes()), b.Type)
|
||||||
return dst
|
return dst
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Store register src into return value dst. This is syntactic sugar: it will
|
||||||
|
// attempt to select the right MOV instruction based on the types involved.
|
||||||
func (c *Context) Store(src reg.Register, dst gotypes.Component) {
|
func (c *Context) Store(src reg.Register, dst gotypes.Component) {
|
||||||
b, err := dst.Resolve()
|
b, err := dst.Resolve()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AddError(err)
|
c.adderror(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.mov(src, b.Addr, int(src.Bytes()), int(gotypes.Sizes.Sizeof(b.Type)), b.Type)
|
c.mov(src, b.Addr, int(src.Bytes()), int(gotypes.Sizes.Sizeof(b.Type)), b.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConstData builds a static data section containing just the given constant.
|
||||||
func (c *Context) ConstData(name string, v operand.Constant) operand.Mem {
|
func (c *Context) ConstData(name string, v operand.Constant) operand.Mem {
|
||||||
g := c.StaticGlobal(name)
|
g := c.StaticGlobal(name)
|
||||||
c.DataAttributes(avo.RODATA | avo.NOPTR)
|
c.DataAttributes(avo.RODATA | avo.NOPTR)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -62,6 +62,6 @@ func (c *Context) mov(a, b operand.Op, an, bn int, t *types.Basic) {
|
|||||||
case (t.Info()&types.IsInteger) != 0 && (t.Info()&types.IsUnsigned) != 0 && an == 2 && bn == 8:
|
case (t.Info()&types.IsInteger) != 0 && (t.Info()&types.IsUnsigned) != 0 && an == 2 && bn == 8:
|
||||||
c.MOVWQZX(a, b)
|
c.MOVWQZX(a, b)
|
||||||
default:
|
default:
|
||||||
c.AddErrorMessage("could not deduce mov instruction")
|
c.adderrormessage("could not deduce mov instruction")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ func (b *build) instruction(i inst.Instruction) {
|
|||||||
b.Printf("func (c *Context) %s(%s) {\n", i.Opcode, s.ParameterList())
|
b.Printf("func (c *Context) %s(%s) {\n", i.Opcode, s.ParameterList())
|
||||||
b.Printf("if inst, err := x86.%s(%s); err == nil", i.Opcode, s.Arguments())
|
b.Printf("if inst, err := x86.%s(%s); err == nil", i.Opcode, s.Arguments())
|
||||||
b.Printf(" { c.Instruction(inst) }")
|
b.Printf(" { c.Instruction(inst) }")
|
||||||
b.Printf(" else { c.AddError(err) }\n")
|
b.Printf(" else { c.adderror(err) }\n")
|
||||||
b.Printf("}\n")
|
b.Printf("}\n")
|
||||||
|
|
||||||
// Global version.
|
// Global version.
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ func (m *mov) Generate(is []inst.Instruction) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
m.Printf("default:\n")
|
m.Printf("default:\n")
|
||||||
m.Printf("c.AddErrorMessage(\"could not deduce mov instruction\")\n")
|
m.Printf("c.adderrormessage(\"could not deduce mov instruction\")\n")
|
||||||
m.Printf("}\n")
|
m.Printf("}\n")
|
||||||
m.Printf("}\n")
|
m.Printf("}\n")
|
||||||
return m.Result()
|
return m.Result()
|
||||||
|
|||||||
Reference in New Issue
Block a user