feat(asm): add LoongArch encoder with ELF and GOOBJ emission

Assisted-by: DeepSeek V4 Pro
This commit is contained in:
2026-08-13 11:24:44 +02:00
parent 2d1176e045
commit 31ee8e7941
24 changed files with 4777 additions and 149 deletions
+24 -6
View File
@@ -201,6 +201,17 @@ R_RISCV_PCREL_HI20/LO12 relocations). The encoder compresses eligible
instructions to 16-bit RVC forms and is validated byte-for-byte against
`GOARCH=riscv64 go tool asm`.
A **LoongArch encoder** (Phase 5, LoongArch64) encodes the integer and
floating-point instruction sets with the dual-form arithmetic mnemonics (3R
vs 2RI12), the 16/21-bit branch families, the MOV pseudo-instruction and its
constant materialisation (the dcon classification driving lu12i.w/ori/lu32i.d/
lu52i.d expansions), the FP/SP frame mapping (autosize = align8(frame+8),
prologue storing the link register before and after the SP decrement) and
SB/global symbol references (pcalau12i pairs with R_LOONG64_ADDR_HI/LO
relocations). Like the RISC-V encoder it is validated byte-for-byte against
`GOARCH=loong64 go tool asm`, and its GOOBJ output is proven end-to-end by
substituting it into a cross-compiled `go build` and linking with `cmd/link`.
On top of the encoder, `Assemble` walks a parsed `TEXT` body, converts each
operand to an encoder operand, and lays the instructions out so local labels
resolve to relative jump offsets: jumps start in the short (rel8) form and
@@ -288,12 +299,19 @@ boundaries, plus flat `pcfile`, `pcline` and `pcinline` tables — so a
gasm-assembled object drops into a `go build` in place of the toolchain's.
The object preamble (the version-and-experiment header the linker compares
verbatim) is captured from the installed `go tool asm`, so the output is
always consistent with the toolchain that links it. RISC-V GOOBJ emission
uses the same format with the RISC-V architecture marker and RISC-V relocation
types. External cross-package
references and the implicit funcdata/DWARF symbols remain future work (the
linker fills the latter's defaults); the rest of Phase 2 is those, the
remaining EVEX forms and the other architectures.
always consistent with the toolchain that links it. LoongArch GOOBJ emission
uses the same shared emitter with the loong64 marker and R_LOONG64_ADDR_HI/LO
relocation types, and the emitted object links into a real `go build` for
`GOARCH=loong64`. Per function, the emitter also writes the two DWARF
symbols the linker's DWARF pass reads verbatim — the subprogram DIE
(`SDWARFFCN`) and the `.debug_line` state-machine program (`SDWARFLINES`),
both built the way `cmd/asm` builds them (the DIE carries the
R_DWTXTADDR_U4 address reference; the line program one row per source-line
change, in the same special-opcode encoding) — and the pc-value deltas are
in the architecture's MinLC units, as the runtime's `pcvalue` expects.
External cross-package references remain future work (the amd64 and RISC-V
paths resolve them; LoongArch does not yet); the rest of Phase 2 is those
and the remaining EVEX forms.
### `verify`