Files
avo/README.md
Michael McLoughlin 602bb5197c build: unify Label function signatures
The Context.Label method and LABEL global function did not agree. Also
breaks the convention I'd like to set that capitalized functions must
agree with existing Go assembly syntax.

To help avoid a conflict with `avo.Label`, attributes were moved to
their own package.

Fixes #35
2019-01-05 18:18:49 -08:00

5.7 KiB

avo
Build Status GoDoc

High-level Golang x86 Assembly Generator

avo aims to make high-performance Go assembly easier to write, review and maintain. It's a Go package that presents a familiar assembly-like interface, together with features to simplify development without sacrificing performance:

  • avo programs are Go programs: use control structures for assembly generation
  • Register allocation: write your kernels with virtual registers and avo assigns physical registers for you
  • Automatic parameter load/stores: ensure memory offsets are always correct even for complex data structures
  • Generation of stub files to interface with your Go package

Inspired by the PeachPy and asmjit projects.

Note: avo is still in an experimental phase. APIs subject to change.

Install

Install avo with go get:

$ go get -u github.com/mmcloughlin/avo

Quick Start

avo assembly generators are pure Go programs. Let's get started with a function that adds two uint64 values.

// +build ignore

package main

import (
	. "github.com/mmcloughlin/avo/build"
)

func main() {
	TEXT("Add", "func(x, y uint64) uint64")
	Doc("Add adds x and y.")
	x := Load(Param("x"), GP64())
	y := Load(Param("y"), GP64())
	ADDQ(x, y)
	Store(y, ReturnIndex(0))
	RET()
	Generate()
}

You can go run this code to see the assembly output. To integrate this into the rest of your Go package we recommend a go:generate line to produce the assembly and the corresponding Go stub file.

//go:generate go run asm.go -out add.s -stubs stub.go

After running go generate the add.s file will contain the Go assembly.

// Code generated by command: go run asm.go -out add.s -stubs stub.go. DO NOT EDIT.

// func Add(x uint64, y uint64) uint64
TEXT ·Add(SB), $0-24
	MOVQ	x(FP), AX
	MOVQ	y+8(FP), CX
	ADDQ	AX, CX
	MOVQ	CX, ret+16(FP)
	RET

The same call will produce the stub file stub.go which will enable the function to be called from your Go code.

// Code generated by command: go run asm.go -out add.s -stubs stub.go. DO NOT EDIT.

package add

// Add adds x and y.
func Add(x uint64, y uint64) uint64

See the examples/add directory for the complete working example.

Examples

See examples for the full suite of examples.

Slice Sum

Sum a slice of uint64s:

func main() {
	TEXT("Sum", "func(xs []uint64) uint64")
	Doc("Sum returns the sum of the elements in xs.")
	ptr := Load(Param("xs").Base(), GP64())
	n := Load(Param("xs").Len(), GP64())
	s := GP64()
	XORQ(s, s)
	Label("loop")
	CMPQ(n, Imm(0))
	JE(LabelRef("done"))
	ADDQ(Mem{Base: ptr}, s)
	ADDQ(Imm(8), ptr)
	DECQ(n)
	JMP(LabelRef("loop"))
	Label("done")
	Store(s, ReturnIndex(0))
	RET()
	Generate()
}

Parameter Load/Store

avo provides deconstruction of complex data datatypes into components. For example, load the length of a string argument with:

	TEXT("StringLen", "func(s string) int")
	strlen := Load(Param("s").Len(), GP64())

Index an array:

	TEXT("ArrayThree", "func(a [7]uint64) uint64")
	a3 := Load(Param("a").Index(3), GP64())

Access a struct field (provided you have loaded your package with the Package function):

	TEXT("FieldFloat64", "func(s Struct) float64")
	f64 := Load(Param("s").Field("Float64"), XMM())

Component accesses can be arbitrarily nested:

	TEXT("FieldArrayTwoBTwo", "func(s Struct) byte")
	b2 := Load(Param("s").Field("Array").Index(2).Field("B").Index(2), GP8())

Very similar techniques apply to writing return values. See examples/args and examples/returns for more.

Real Examples

Contributing

Contributions to avo are welcome:

  • Feedback from using avo in a real project is incredibly valuable.
  • Submit bug reports to the issues page.
  • Pull requests accepted. Take a look at outstanding issues for ideas (especially the "good first issue" label).

License

avo is available under the BSD 3-Clause License.