Skip to content

SYSTEM Cited by 1 source

ARM64 ISA (AArch64)

ARM64 (also called AArch64) is ARM's 64-bit instruction set architecture. A fixed-length 4-byte ISA: every instruction is exactly 32 bits. This is the property most relevant to the 2025-10 Go arm64 compiler bug (sources/2025-10-08-cloudflare-we-found-a-bug-in-gos-arm64-compiler).

Fixed-length + small immediates → decomposed operations

Because every opcode must fit in 32 bits, immediate operands are necessarily small:

Instruction Immediate bits Range covered
ADD (immediate) 12 0..4095 (plus optional left-shift-by-12 for 24-bit effective)
MOV (wide immediate) 16 0..65535 (plus MOVK for wider values)

When a single opcode can't encode the needed immediate, the compiler / assembler must decompose the operation into multiple opcodes. ADD reserves a "shift-left-by-12" bit so any 24-bit addition can be expressed as:

ADD $low,          dst, dst   ; low 12 bits
ADD $(high << 12), dst, dst   ; high 12 bits, shifted

Other instructions load the immediate into a register first (via MOVD + MOVK pairs) and then use the register form of the target operation.

The decomposition creates a race window

When the target register is shared runtime-observable state — most importantly the stack pointer RSP — the intermediate state after one opcode and before the next is architecturally indistinguishable from an in-progress instruction. For a userspace scheduler like Go's that can preempt a goroutine at any instruction boundary and then walk the stack, this is a reachable bug window. See concepts/split-instruction-race-window.

The preemption-safe fix is to build the wide immediate in a scratch register first, then apply it with a single indivisible register-to-register opcode:

MOVD $low,  R27
MOVK $high, R27
ADD  R27, RSP, RSP   ; indivisible

Preemption may land before or after the ADD but cannot land during it.

amd64 by contrast

x86-64 is a variable-length ISA. ADD imm32, reg encodes a full 32-bit immediate directly in one variable-length instruction. The immediate-encoding limit that forces decomposition on arm64 does not arise. Hence the Cloudflare bug was arm64-only; amd64 builds of the same Go programs were unaffected.

Seen in

Last updated · 200 distilled / 1,178 read