• Stars
    star
    2,704
  • Rank 16,880 (Top 0.4 %)
  • Language
    Go
  • License
    BSD 3-Clause "New...
  • Created about 6 years ago
  • Updated about 2 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Generate x86 Assembly with Go

avo
Build Status go.dev Go Report Card

Generate x86 Assembly with Go

avo makes high-performance Go assembly easier to write, review and maintain. The avo package presents a familiar assembly-like interface that simplifies development without sacrificing performance:

  • Use Go control structures for assembly generation; avo programs are Go programs
  • Register allocation: write functions with virtual registers and avo assigns physical registers for you
  • Automatically load arguments and store return values: ensure memory offsets are correct for complex structures
  • Generation of stub files to interface with your Go package

For more about avo:

Note: APIs subject to change while avo is still in an experimental phase. You can use it to build real things but we suggest you pin a version with your package manager of choice.

Quick Start

Install avo with go get:

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

avo assembly generators are pure Go programs. Here's a function that adds two uint64 values:

//go:build ignore

package main

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

func main() {
	TEXT("Add", NOSPLIT, "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()
}

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.

#include "textflag.h"

// func Add(x uint64, y uint64) uint64
TEXT Β·Add(SB), NOSPLIT, $0-24
	MOVQ x+0(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", NOSPLIT, "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())

	Comment("Initialize sum register to zero.")
	s := GP64()
	XORQ(s, s)

	Label("loop")
	Comment("Loop until zero bytes remain.")
	CMPQ(n, Imm(0))
	JE(LabelRef("done"))

	Comment("Load from pointer and add to running sum.")
	ADDQ(Mem{Base: ptr}, s)

	Comment("Advance pointer, decrement byte count.")
	ADDQ(Imm(8), ptr)
	DECQ(n)
	JMP(LabelRef("loop"))

	Label("done")
	Comment("Store sum to return value.")
	Store(s, ReturnIndex(0))
	RET()
	Generate()
}

The result from this code generator is:

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

#include "textflag.h"

// func Sum(xs []uint64) uint64
TEXT Β·Sum(SB), NOSPLIT, $0-32
	MOVQ xs_base+0(FP), AX
	MOVQ xs_len+8(FP), CX

	// Initialize sum register to zero.
	XORQ DX, DX

loop:
	// Loop until zero bytes remain.
	CMPQ CX, $0x00
	JE   done

	// Load from pointer and add to running sum.
	ADDQ (AX), DX

	// Advance pointer, decrement byte count.
	ADDQ $0x08, AX
	DECQ CX
	JMP  loop

done:
	// Store sum to return value.
	MOVQ DX, ret+24(FP)
	RET

Full example at examples/sum.

Features

For demonstrations of avo features:

  • args: Loading function arguments.
  • returns: Building return values.
  • complex: Working with complex{64,128} types.
  • data: Defining DATA sections.
  • ext: Interacting with types from external packages.
  • pragma: Apply compiler directives to generated functions.

Real Examples

Implementations of full algorithms:

Adopters

Popular projects1 using avo:

golang / go ⭐ 114k

The Go programming language

klauspost / compress ⭐ 4.1k

Optimized Go Compression Packages

golang / crypto ⭐ 2.8k

[mirror] Go supplementary cryptography libraries

klauspost / reedsolomon ⭐ 1.7k

Reed-Solomon Erasure Coding in Go

cloudflare / circl ⭐ 1k

CIRCL: Cloudflare Interoperable Reusable Cryptographic Library

segmentio / asm ⭐ 801

Go library providing algorithms optimized to leverage the characteristics of modern CPUs

zeebo / blake3 ⭐ 347

Pure Go implementation of BLAKE3 with AVX2 and SSE4.1 acceleration

zeebo / xxh3 ⭐ 329

XXH3 algorithm in Go

lukechampine / blake3 ⭐ 309

A pure-Go implementation of the BLAKE3 cryptographic hash function

minio / md5-simd ⭐ 151

Accelerate aggregated MD5 hashing performance up to 8x for AVX512 and 4x for AVX2. Useful for server applications that need to compute many MD5 sums in parallel.

See the full list of projects using avo.

Contributing

Contributions to avo are welcome:

Credits

Inspired by the PeachPy and asmjit projects. Thanks to Damian Gryski for advice, and his extensive library of PeachPy Go projects.

License

avo is available under the BSD 3-Clause License.

Footnotes

  1. Projects drawn from the avo third-party test suite. Popularity estimated from Github star count collected on Sep 1, 2023. ↩

More Repositories

1

globe

Globe wireframe visualizations in Golang
Go
1,591
star
2

geohash

Golang geohash library
Go
525
star
3

mathfmt

Document mathematical Go code beautifully
Go
197
star
4

addchain

Cryptographic Addition Chain Generation in Go
Go
184
star
5

meow

Meow hash for Golang
Go
124
star
6

profile

Simple profiling for Go
Go
76
star
7

pearl

Tor relay implementation in Golang
Go
75
star
8

cryptofuzz

Fuzzing Go crypto
Go
73
star
9

finsky

Google Play API for Python
Python
57
star
10

ec3

Elliptic Curve Cryptography Compiler: an incomplete experiment in code-generation for elliptic curves in Go
Go
55
star
11

luhn

Generate and verify Luhn check digits
Python
43
star
12

reprotobuf

Reverse engineer protobuf from javanano
Python
29
star
13

professor

Safer interface to Golang net/http/pprof
Go
23
star
14

spherand

Random points on a sphere in Golang
Go
22
star
15

trunnel

Code generator for binary parsing
Go
19
star
16

hellollvm

Basic LLVM passes
C++
17
star
17

md4

Assembly-optimized MD4 hash algorithm in Go
Go
17
star
18

problems

Programming problems
Go
15
star
19

starbucks

All starbucks locations in the world
Python
15
star
20

torcerts

Tor relay certificate downloader
Python
11
star
21

gophercon

Notes from Gophercon
11
star
22

deconstructedgeohash

Supporting code for Geohash Assembly blog post
C++
10
star
23

geohashbench

Benchmarks to compare golang geohash implementations
Go
10
star
24

cpudb

CPUID database derived from InstLatx64
Go
10
star
25

supercomputing

Notes from Supercomputing Conference
10
star
26

garble

Randomize your data
Python
9
star
27

databundler

Embed CSV data in a Golang package
Go
9
star
28

openflights

OpenFlights data in Golang format
Go
9
star
29

iacago

Intel IACA Markers for Golang Assembly
Makefile
9
star
30

goperf

Continuous Benchmarking for the Go compiler
Go
8
star
31

ghr

GitHub recruitment scraper
Go
8
star
32

podium

Convert Golang present talks to PDF
Go
8
star
33

reveal

Reveal source code line-by-line in LaTeX presentations
Python
8
star
34

keepaneyeon

Monitor URLs for changes
Python
8
star
35

aesnix

Experiments with AES-NI performance in Golang
Assembly
7
star
36

ssarules

SSA rules description language in the Go compiler
Go
6
star
37

cite

Cite snippets in your godoc
Go
5
star
38

cuptisamples

NVIDIA CUPTI samples mirror.
Shell
4
star
39

bib

BibTeX references for your Go source code
Go
3
star
40

talks

Talks I've given
Python
3
star
41

cpuid

Interface to intel's cpuid instruction.
C
3
star
42

x

Experimental.
Go
2
star
43

adorn

Generate function and decorator types for Golang interfaces
Go
2
star
44

rqc

Redis query compiler
Go
2
star
45

godepex

Exclude packages from godep
Go
2
star
46

random

Utilities to complement Golang's math/rand package
Go
2
star
47

toroulette

Run a random version of tor
Makefile
2
star
48

bugsalsa

Investigating a 32-bit overflow bug in SUPERCOP-derived salsa20 implementations
Go
2
star
49

usgsmaps

Fetch topo maps from USGS
Python
2
star
50

doclint

Experimental C++ Documentation Linter based on Clang LibTooling
C++
1
star