Avo: Better X86 Assembly Generation from Go
github.com
github.com
I understand the rationale—that you can use the assembly syntax as a sort of IR by unifying the syntax of certain basic operations across different ISAs—but that's properly considered a low-level IR, not assembly. (It's also a pretty bad form of IR for doing any interesting optimizations, which is why Go uses a separate SSA form for that.)
Go (Plan 9) syntax is not sufficiently different to make it a powerful intermediate representation, hence SSA as you point out. In fact many of the differences are frustrating subtle changes in instruction mnemonics or operand order. This might be okay if there was a canonical instruction database that made all these differences from Intel and AT&T easy to discover. However these exceptions are really recorded in various parts of the golang.org/x/arch/x86 repo. Producing the instruction database for avo was quite a time-consuming process. See:
https://github.com/mmcloughlin/avo/blob/master/internal/load... https://github.com/mmcloughlin/avo/issues/23
I've gained a lot more familiarity with the assembler and supporting infrastructure, so I'm hoping I may be able to contribute to this area of the core Go project.
https://github.com/mmcloughlin/avo/blob/0e253b3753beb409b3dd...
It gets to the point where the only source of truth is the Go assembler itself. My test suite takes the avo instruction database and generates a massive assembly file with one line per instruction form, then passes this to `go tool asm`.
It's quirks are annoying to start with, but if you use more than one assembly language you begin to see the advantages of a more consistent syntax between them.
I suspect the advantages for the go maintainers of a uniformish assembler syntax are the real reason for it.
LLVM MachineInstr and Cranelift do this much better than Go does, by maintaining a clean separation between the low-level IR and the assembly language.
Any chance of ARM/ARM64 support?
It would be super useful if you could generate the code to memory then execute it directly.
avo currently implements the x86 subset of Go assembler. It's definitely possible to add support for additional architectures, but it may be a fairly significant project.
> Any chance of ARM/ARM64 support?
Yes multi-architecture support is definitely something I've had in mind. However I wanted to limit the scope for the initial version, so I could produce a result in a reasonable time and allow me to gauge interest.
> It would be super useful if you could generate the code to memory then execute it directly.
avo was inspired by PeachPy and asmjit, both of which can produce executable code directly. So implementing an assembler in avo is something I have had in the back of my mind. However it wasn't one of my primary goals.
The use case I initially had in mind is massively unrolled crypto routines, where there's a lot of assembly code required but not much going on conceptually. My AES-CTR mode CL (https://go-review.googlesource.com/c/go/+/136896) and meow hash port (https://github.com/mmcloughlin/meow) got me thinking in this direction.
https://github.com/mmcloughlin/avo#credits
PeachPy actually has Go output already, and Damian Gryski has used this to great effect:
https://github.com/mmcloughlin/avo/issues/40
Unfortunately because PeachPy wasn't initially written with Go in mind there are some rough edges and Go features it simply doesn't support. avo hopes to fill this gap for Go programmers.