github.com/xgo-dev/plan9asm
Plan 9 assembly parser and LLVM IR translator, extracted as an independent module.
github.com/xgo-dev/plan9asm: parser + lowering library.cmd/plan9asm: package/file oriented helper (list,transpile), moved fromllgo-stdlib-opt/chore/plan9asm.cmd/plan9asmll: stdlib-oriented converter/test tool (.s -> .ll, optionalllccompile).
- Library parser/lowering targets:
386,amd64,arm,arm64,wasm. - Tool targets (
cmd/plan9asmll -all-targets):darwin/amd64,darwin/arm64linux/386,linux/amd64,linux/arm,linux/arm64windows/386,windows/amd64,windows/arm64js/wasm,wasip1/wasm
- The package-oriented
cmd/plan9asmand coverage-orientedcmd/plan9asmscansupport the same five Plan 9 assembly architectures. 386currently reuses the x86 lowering path fromamd64backend logic.arm64does not includearm(32-bit). They are separate architectures.- Instruction coverage is tracked for all five LLGo Plan 9 assembly GOARCH targets by architecture, level, family, opcode, and operand form against Go's official opcode/encoder sources, positive GOROOT assembly, and executable real-world regressions. See Plan 9 assembly instruction coverage.
- LLVM 22 is the only supported object-code toolchain; LLVM 23 and older releases are intentionally rejected instead of used as fallbacks.
TranslateModulebuilds an in-memoryllvm.Module(github.com/xgo-dev/llvm).Translatekeeps compatibility and returns textual IR from that module.- Root module dependency stays small (
goplus/llvm). golang.org/x/tools/go/packagesis used only incmd/plan9asmllsubmodule.cmd/plan9asmdoes not depend onllgo/internal/buildorllgo/internal/packages.
go test ./...Some tests require local LLVM 22 tools (llc, clang) and skip when unavailable.
The executable cases under testdata/conformance use the native Go
assembler as an oracle, then compile and run the same assembly through
plan9asm/LLVM. Run them with:
go test . -run 'Test.*Conformance'The separate cross-version instruction coverage gate compares Go's assembler corpus and encoder forms against the checked-in baseline:
scripts/check-go-asm-coverage.shOn a Linux/amd64 host with the Debian cross GCC toolchains and QEMU user-mode emulators installed, run the cross-architecture link and execution smoke test:
PLAN9ASM_CROSS_EXEC=1 go test . -run '^TestCrossLinuxRuntimeMatrix$' -count=1 -vShow flags:
go run -C cmd/plan9asmll . -hList selected asm files only:
go run -C cmd/plan9asmll . -patterns=std -goos=linux -goarch=386 -list-onlyConvert one target (.s -> .ll):
go run -C cmd/plan9asmll . \
-patterns=std \
-goos=linux -goarch=amd64 \
-out _out/plan9asmll/linux-amd64 \
-report /tmp/plan9asmll-linux-amd64.jsonConvert and compile (.ll -> .o) via llc:
go run -C cmd/plan9asmll . \
-all-targets \
-patterns=std \
-compile \
-out _out/plan9asmll/all-targets \
-report /tmp/plan9asmll-all-targets.jsonRun only x86 (386) targets:
go run -C cmd/plan9asmll . \
-patterns=std \
-targets=linux/386,windows/386 \
-compile \
-out _out/plan9asmll/x86 \
-report /tmp/plan9asmll-x86.json- Every asm file is printed with explicit status (
OKorFAIL). - On failure, tool prints:
- the primary reason line,
- unsupported opcode set (if detected),
- per-hit location as file line number + source line.
-keep-going=true(default) continues through all files and summarizes at the end.
- The stdlib asm corpus depends on your local Go toolchain version (
go tool dist list,GOROOTcontent). - If
-compileis enabled, LLVM 22'sllc-22(or a version-verifiedllc) must be discoverable inPATHor set via-llc. - Design notes and migration details are in
doc/llvm-module-migration.md.
List packages/files containing .s:
go run -C cmd/plan9asm . list -goos=linux -goarch=amd64 stdtranspile package mode uses positional patterns (go build/test style) and supports multiple patterns.
Transpile package selected .s files:
go run -C cmd/plan9asm . transpile \
-dir _out/plan9asm/runtime-linux-amd64 \
-goos=linux -goarch=amd64 \
runtimeTranspile one .s file:
go run -C cmd/plan9asm . transpile \
-i /path/to/file.s \
-o /tmp/file.ll \
-goos=linux -goarch=amd64Raw C callbacks and tail-call trampolines sometimes have no Go function
signature. Passing them through typed LLVM lowering cannot preserve an unknown
set of incoming or outgoing registers. ForeignARM64Functions recognizes the
restricted file-local, NOSPLIT, zero-Go-frame form (non-leaf callbacks must
explicitly use NOFRAME).
A compiler driver can assemble such a file with go tool asm -p <package> and
pass the Darwin/ARM64 Go object to TranslateNativeARM64Object. The returned
Mach-O assembly preserves the encoded instructions and maps R_ADDR and
R_CALLARM64 relocations to selected local definitions or explicitly supplied
dynamic imports. The accompanying DATA list lets the driver bind Go globals to
their assembly definitions. The driver remains responsible for selecting the
target, running tools, and supplying library link arguments.
This path does not translate Go ABI functions. Unsupported object formats, relocations, and undeclared foreign calls return errors instead of inventing function signatures. The object reader accepts the go120ld format used since Go 1.20; the runtime tests execute native callbacks only on Darwin/ARM64.