Advice on adding Golang (Plan 9) x86 assembly variant

Hello,

I am interested in experimenting with Golang assembly with LLVM on X86. Golang Assembly is most similar to AT&T/GAS with some differences:

  • A small number of instructions have operand order flipped
  • Some mnemonics are different
  • Different register naming conventions

Iskander Sharipov covers details here: https://quasilyte.github.io/blog/post/go-asm-complementary-reference/

I have started looking into how the X86AsmPrinter and InstPrinter works. It seems like there could be two high-level approaches:

  1. Treat Golang assembly as a completely separate third variant. This would require substantial edits to various X86Instr*.td files, mainly to account for variant number 2 in all the AsmString entries. That is, strings like “mov{l}\t{$src, $dst|$dst, $src}” would need to account for a third possibility. Likely much of this could be automated, but the changes would be substantial. Then hopefully other differences could be handled with MnemonicAlias. Further changes would be required to X86AsmPrinter.cc, parsers, and no doubt many other places I haven’t even seen yet.

  2. I am interested in whether it’s feasible (and easier) to treat Golang as a “sub-variant” of AT&T. That is, no changes made to the *.td files, but the differences between AT&T and Golang assembly are handled later in code (X86AsmPrinter and the like). I have not fully thought this through yet.

I thought I would reach out for some advice from people who might have a better intuition. Are either of these approaches reasonable? Is there a better third way? Is the whole thing going to be prohibitively difficult? Any pointers appreciated.

Cheers,
Mike

I’d start by asking why you want to do this? Is there some more concrete goal you had in mind, that you want this for? It doesn’t really seem worthwhile to me.

If you just want to create Go assembly from LLVM input, I would suggest having LLVM emit a .o file and then run “go tool objdump foo.o” to disassemble it using Go’s disassembler.

Good question.

The initial motivation was looking at ways of automatically converting existing (reviewed) implementations of crypto algorithms into Go assembly. The secondary motivation was learning more about LLVM.

Yes, I considered that approach. Unfortunately the Go disassembler is incomplete (one example https://golang.org/issue/25617).

I think that the LLVM MC library is already pretty poorly structured for handling alternative assembly dialects. I wouldn’t want to put more complexity in it.

I would strongly support efforts to clean it up, fuzz it, and turn assertion failures and crashes into real assembler diagnostics, though.