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
5.7 KiB
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:
avoprograms are Go programs: use control structures for assembly generation- Register allocation: write your kernels with virtual registers and
avoassigns 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
- fnv1a: FNV-1a hash function.
- dot: Vector dot product.
- geohash: Integer geohash encoding.
- sha1: SHA-1 cryptographic hash.
- stadtx:
StadtXhash port from dgryski/go-stadtx.
Contributing
Contributions to avo are welcome:
- Feedback from using
avoin 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.