← board

AArch64 text-assembler (EmitAsmA64) for cleaner ARM64 codegen

Motivation

ir_codegen_aarch64.inc is 2140 lines of raw word emission. Same readability / maintenance argument as the x86 and xtensa emitters: write blocks as assembly text, encode once, get correct branch-offset resolution for free.

New vs the x86/xtensa precedent

No typed encoder layer exists for AArch64 — unlike x64 (x64enc.inc), rv32 (rv32enc.inc), xtensa (xtensaenc.inc), the aarch64 backend emits 32-bit words inline. So this ticket grows the encoders too: either a thin new compiler/a64enc.inc (the xtensa shape — typed EncodeA64* over the byte sink) that EmitAsmA64 sits on top of, or encode functions inside the text assembler. Prefer the thin typed layer — it doubles as the seed for future inline asm.

Upside: AArch64 is fixed-width 32-bit, no ModRM/SIB/REX, flat register file. The operand model is simpler than x86 once the encoders exist.

Operand model

mnem dst, src, … comma-separated. Registers x0..x30/sp/xzr (64-bit), w0..w30/wzr (32-bit). Loads/stores take base + scaled immediate, not bracketed-flat memory like x86: ldr x3, [x2, #8]. Markers: % value hole (imm/offset/branch, range-checked per instruction), .name: label, @data/ @glob reloc.

Scope (incremental — mix freely)

  1. Cover what converted blocks use first: mov movz movk add sub and orr eor, ldr str ldrb strb ldrh strh (base+imm), ret nop, branches b b.cond cbz cbnz + the comparison/cset set. Grow on demand.
  2. Labels + branch offset resolution back+forward, honouring ranges (b ±128 MB, b.cond/cbz ±1 MB) and word-scaled (>>2) imm fields.
  3. Convert ≥1 real branch/label-bearing block (e.g. a EmitSetccA64-style comparison or a loop). Leave heavily-dynamic blocks on inline word emission.

Landmines

Acceptance

Deferred

Log