Go: A Documentary

Thread × release map

● = the thread had substantive commits in that cycle; hover for the stage summary, click to jump to it in the release page.

Go 1.0 – 1.17

Thread1.01.11.21.31.41.51.61.71.81.91.101.111.121.131.141.151.161.17Status at go1.17 (or at the end of its era slice)
Memory management: GC and allocator (Go 1.0–1.17)
Stop-the-world mark-sweep, then the parallel collector●●●●●replaced by the concurrent collector (threads "Concurrent mark" and "Decentralized GC state machine"); the parallel work distribution (parfor, work buffers) lives on as the root-job / gcWork machinery
Concurrent sweep and proportional sweep●●●●●●●●●still the design at go1.17 (background bgsweep plus proportional on-demand sweeping and the page reclaimer; sweepone driven by heap_live) → continues as Sweeper termination and pacing (1.18+)
Concurrent mark: write barriers and the dev.garbage collector●●●still the structure of the collector (concurrent mark with write barriers, 25% utilisation goal, assists); the barrier flavour changed in 1.8 (hybrid barrier) → continues as Sweeper termination and pacing and Mark worker scheduling and GC work queues (1.18+)
Decentralized GC state machine and mark termination simplification●●●●●●●●still the design at go1.17 (gcStart/gcMarkDone/gcMarkTermination run by whichever goroutine notices the transition; checkmarks mode independent of STW code) → continues as Mark worker scheduling and GC work queues (1.18+)
GC pacer: trigger controller, assists and background utilisation●●●●●●●●●●still the design at go1.17 (trigger-ratio feedback controller, scan-work based assists, 25% background utilisation, soft/hard goal) but now isolated in mgcpacer.go as gcControllerState; → continues as GC pacer redesign (1.18+)
Stack scanning: conservative, precise by frames, stack barriers, hybrid barrier, async safe points●●●●●●●●●●●stack roots scanned precisely using stack maps and stack objects, with no rescan, plus conservative scanning at async safe points; → continues as Stack and register root scanning (1.18+)
Hybrid write barrier and buffered write barrier●●●●●still the design at go1.17 (deletion+insertion "hybrid" barrier with a per-P pointer buffer flushed through wbBufFlush) → continues as Stack and register root scanning (1.18+)
Precise heap scanning: type information, the heap bitmap and GC programs●●●●●●●●●●●●still the design at go1.17 (2-bit/1-bit-per-word sparse per-arena heap bitmap written by heapBitsSetType, GC programs for large types, mark bits in separate per-span bitmaps) → continues as Heap bitmap rewrite and allocation headers (1.18+)
Allocating from mark bits: allocBits, freeindex and ctz●●●●still the design at go1.17 (per-span allocBits/gcmarkBits, freeindex, 64-bit allocCache, nextFreeFast) → continues as Allocation publication, zeroing and preemptibility (1.18+)
Size classes, tiny allocator and mcache/mcentral●●●●●●●●●●●●●still the design at go1.17 (_NumSizeClasses = 68 entries at go1.17 including the 24-byte class, spanClass splitting scan/noscan, mcentral built on spanSet, mcache holds one span per span class) → continues as mallocgc decomposition and size-specialized malloc (1.24+)
Span lifecycle in mheap: free lists, treaps, first-fit and the page reclaimer●●●●●●●●●replaced by the bitmap page allocator in 1.14 (see "The bitmap page allocator"); the in-use span bookkeeping (spanSet, page reclaimer, in-use bitmap) is still the design at go1.17
The bitmap page allocator●●●●still the design at go1.17 (radix-tree summaries over per-chunk 4 MiB allocation bitmaps, searchAddr, sparse chunk index, inUse address ranges) → continues as Scavenger redesign and Address-space layout, tagged pointers and the mem.go layer (1.18+)
Scavenger: returning memory to the OS●●●●●●●●●●●a background scavenger paced by its own cost measurements over the page allocator's address-ordered search with a "free"/"scavenged" watermark; → continues as Scavenger redesign (1.18+)
Heap address space: contiguous arena to sparse arenas●●●●●●●●●●●●●still the design at go1.17 (64 MB heapArena units on 64-bit, 4 MB on Windows and iOS, two-level arena map on platforms with large address spaces, arenaBaseOffset, heap-arena hints) → continues as Address-space layout, tagged pointers and the mem.go layer (1.18+)
Finalizers and span specials●●●●●●●●●finalizers as special records on spans, scanned as roots concurrently, run by one goroutine; → continues as Finalizers, runtime.AddCleanup and the cleanup queue (1.19+)
Mark work distribution: parfor, work buffers, gcWork and root jobs●●●●●●●●●still the design at go1.17 (per-P gcWork with two cached work buffers, global full/empty lists, markroot jobs for data/BSS/span/stack roots shared by workers and assists) → continues as Mark worker scheduling and GC work queues (1.19+)
Runtime allocators for runtime metadata and the port to Go●●●●●persistentalloc, fixalloc and manually-managed spans are still the metadata allocators; the allocator and collector are Go code since 1.5
Memory statistics and accounting●●●●●●●●●●●sharded consistentHeapStats and per-mcache stats feed MemStats, GC pacer state lives in gcController
Allocation-site profiling and GC debugging modes●●●●●●●gccheckmark, clobberfree, zombie-slot detection, scavtrace, allocfreetrace, invalidptr and cgocheck are all present
Scheduler and concurrency runtime (Go 1.0–1.17)
The G-M-P scheduler: from global-lock M:N to per-P run queues, spinning Ms and work stealing●●●●●●●●●●●●●●●●●still the design at go1.17 (findrunnable had just been split into helpers for 1.18) → continues as Scheduler core: spinning Ms, work conservation, stealing, STW interaction (1.18+)
Preemption: cooperative stack-check preemption (1.2) to signal-based asynchronous preemption (1.14)●●●●●●●●both mechanisms active (async preemption on by default, GODEBUG=asyncpreemptoff=1 to disable) → continues as Asynchronous preemption: extended register state (1.18+)
Network poller: from the netFD select loop to the runtime-integrated epoll/kqueue/IOCP poller●●●●●●●●●●●●●●still the design at go1.17 → continues as Netpoller (1.18+)
Timers: timerproc goroutine → per-bucket heaps → timers on Ps●●●●●●●●●●●still the design at go1.17 (timers in per-P heaps, driven by findrunnable/checkTimers) → continues as Timer rewrite: per-P timer heap, timer.lock, and GC-able synchronous timer channels (1.18+)
Channels and select●●●●●●●●●●●●●●●●still the design at go1.17 (hchan with a mutex, sudog queues, selectgo with lock-ordered cases) → continues as Scheduler core: spinning Ms, work conservation, stealing, STW interaction (1.18+)
Semaphores, runtime locks and Notes●●●●●●●●●still the design at go1.17 (futex/sema lock, note, semaRoot treap) → continues as Runtime mutex: tri-state futex/sema locks → "spinbit" mutex (1.23+)
sync.Mutex, RWMutex, WaitGroup, Cond, Once●●●●●●●●●●●●●still the design at go1.17 → continues as sync package API evolution (1.18+)
sync.Pool●●●●●●still the design at go1.17 (per-P poolLocal with private slot plus poolChain of lock-free dequeues, victim cache) → continues as sync package API evolution (1.18+)
sync.Map, atomic.Value and sync/atomic●●●●●●●●●●●●●●still the design at go1.17 → continues as sync/atomic and runtime atomics (1.18+)
Runtime lock ranking (static lock order checking)●●●opt-in via GOEXPERIMENT=staticlockranking; hand-maintained partial order → continues as Runtime lock ranking (1.18+)
Runtime from C to Go: scheduler, channels, semaphores, timers, netpoll●●●completed in Go 1.5; no C in the runtime scheduler
Goroutine and M lifecycle: caches, ids, LockOSThread, Goexit, cgo extra Ms, deadlock detection●●●●●●●●●●●●●●●●still the design at go1.17 → continues as Goroutine lifecycle and identity (1.20+)
Stop-the-world, safe points and GC–scheduler interaction●●●●●●●●●●●●●●●still the design at go1.17 → continues as Scheduler core: spinning Ms, work conservation, stealing, STW interaction (1.18+)
Scheduler diagnostics: schedtrace, GODEBUG, execution tracer, block/mutex profiles●●●●●●●●●●still the design at go1.17
Fast random numbers for the scheduler●●●●●still the design at go1.17 (xorshift64+ fastrand) → continues as Fast random numbers for the scheduler (1.18+)
GOMAXPROCS, thread and resource limits●●●●●still the design at go1.17 → continues as GOMAXPROCS container awareness and dynamic updates (1.25+)
Runtime data structures and type metadata (Go 1.0–1.17)
Hash map core: from the first hashmap.c to the 8-entry bucket design●●●●●●●●●●●●●●●●●still the design at go1.17 (array of 8-slot buckets, tophash bytes, chained overflow, incremental growth) → continues as Swiss-table maps (GOEXPERIMENT=swissmap → only implementation) (1.24+) and Classic map maintenance and maps package helpers (pre-swiss) (1.18+)
Map growth, iteration order, overflow buckets and GC interaction●●●●●●●●●●still the design at go1.17 → continues as Classic map maintenance and maps package helpers (pre-swiss) (1.18+)
Map fast paths and compiler/runtime specialization●●●●●●●●still the design at go1.17 → continues as Classic map maintenance and maps package helpers (pre-swiss) (1.18+)
Hash functions and algorithm tables: memhash, AES hash, fallback hash●●●●●●●●●●●●still the design at go1.17 (AES hash where available, wyhash-based fallback; per-map seeds; hash functions generated per key type) → continues as Map hashing and hash functions (memhash, aeshash, fallback hash) (1.23+)
Compiler-generated equality and hash functions●●●●●●●●●●still the design at go1.17 → continues as Compiler-generated equality/hash functions and type descriptor emission (reflectdata) (1.18+)
Runtime type descriptors: layout, shrinking and name encoding●●●●●●●●●●●●●●●still the design at go1.17 (rtype with tflag, nameOff/typeOff/textOff, varint names, uncommon type following the base) → continues as internal/abi type layout unification and type metadata (rtype → abi.Type) (1.21+)
Interface values, itabs and type assertions●●●●●●●●●●●●●●●●still the design at go1.17 (compiler-emitted itabs, runtime itab hash table) → continues as Interface conversion: itabs, type switch and assertion caches (1.19+)
reflect redesign: from string parsing to Type/Value structs●●●●●still the design at go1.17 for the Type/Value API (opaque Value {typ, ptr, flag}); implementation tuned in 1.18+ → continues as reflect implementation: performance, allocation and escape behaviour (1.18+)
reflect dynamic types: ArrayOf, ChanOf, MapOf, SliceOf, FuncOf, StructOf●●●●●●●●still the design at go1.17 (synthesized rtype structures with GC info built in reflect) → continues as reflect implementation: performance, allocation and escape behaviour (1.18+)
reflect.Call, MakeFunc, method values and argument-frame GC precision●●●●●●●●●●●●replaced by the register-ABI implementation in 1.17 (see register ABI thread) → continues as Register ABI completion for reflect, memmove/memclr and bytealg across architectures (1.18+)
Register ABI support in reflect and runtime assembly (Go 1.17)●reflect assumes the register ABI only under GOEXPERIMENT=regabiargs and uses global register counts; not yet default → continues as Register ABI completion for reflect, memmove/memclr and bytealg across architectures (1.18+)
reflect performance, caches and API additions●●●●●●●●●●●●●still the design at go1.17 → continues as reflect implementation: performance, allocation and escape behaviour (1.18+)
memmove, memclr, duff routines and pointer-write atomicity●●●●●●●●●●●●●●●still the design at go1.17 → continues as memmove / memclr / memequal / internal/bytealg assembly optimisation (1.18+)
internal/bytealg and string/byte comparison primitives●●●●●●●●●●●●●still the design at go1.17 → continues as memmove / memclr / memequal / internal/bytealg assembly optimisation (1.18+)
Slices and append: growslice, makeslice and string/slice conversions●●●●●●●●●●●●●still the design at go1.17 (2x below 1024 old cap threshold, 1.25x above) → continues as Slice growth, string building and allocation-free bytes/strings helpers (1.18+)
Strings: concatenation, conversion and printing helpers●●●●●●●●●●●●still the design at go1.17 → continues as Slice growth, string building and allocation-free bytes/strings helpers (1.18+)
Soft-float, 64-bit division and complex arithmetic helpers●●●●●●●●●●●still the design at go1.17 (Go implementations in softfloat64.go, vlop, complex.go) → no continuation noted
C-to-Go conversion of runtime data-structure code●●●completed in Go 1.5; the runtime is Go with assembly stubs → no continuation noted
internal/reflectlite and checkptr●●●●●still the design at go1.17
Diagnostics and knobs (Go 1.0–1.17)
Execution tracer (trace v1): events, per-goroutine sequencing, annotations●●●●●●●●still the v1 design at go1.17 (per-P buffers, text of events decoded by internal/trace, go tool trace UI) → continues as The new execution tracer (trace v2): generations, per-M buffers, new parser (1.18+)
Race detector integration●●●●●●●●●●●●●●●●still the compiler-instrumentation (racewalk) + TSan-runtime design at go1.17; ports on linux/amd64, darwin, freebsd, windows, netbsd, openbsd/amd64, ppc64le, arm64, darwin/arm64 → continues as Race detector, ASan, MSan and Valgrind integration (1.18+)
CPU profiler and runtime/pprof writers (legacy format to compressed protobuf)●●●●●●●●●●●●●●●●●still the design at go1.17: signal-driven SIGPROF samples logged to a profile buffer, aggregated by runtime/pprof goroutines and streamed as gzip protobuf with inline-aware Locations → continues as CPU profiling, goroutine profiling, pprof labels and the protobuf writer (1.18+)
Profile labels●●●●●still the design at go1.17: g.labels pointer, copied by the signal handler into the CPU profile tag buffer → continues as CPU profiling, goroutine profiling, pprof labels and the protobuf writer (1.18+)
Heap profile accounting and MemStats●●●●●●●●●still the design at go1.17 (consistent stats partly sharded; MemStats copied explicitly), with heapGoal in gcControllerState → continues as runtime/metrics and MemStats (1.18+)
runtime/metrics●●still the design at go1.17 → continues as runtime/metrics and MemStats (1.18+)
GODEBUG, runtime/debug, debug log and traceback knobs●●●●●●●●●●●●●●●still the design at go1.17 → continues as Crash output, runtime/debug, BuildInfo and debuglog (1.18+)
MSan and sanitizer integration●●●●●msan (linux/amd64, arm64) in place; ASan not yet present → continues as Race detector, ASan, MSan and Valgrind integration (1.18+)
GOEXPERIMENT handling (objabi, buildcfg, goexperiment)●regabi sub-experiments on by default in the baseline for amd64 (and Android) → continues in internal/buildcfg/internal/goexperiment (1.18+, see the later report's experiment threads)
Traceback correctness and inlining (diagnostic output)●●●●●●●still the design at go1.17 (gentraceback) → continues as Crash output, runtime/debug, BuildInfo and debuglog (1.18+)
GDB runtime support●●●●●●●runtime-gdb.py maintained (Python 2/3, gdb 7.12–9.2) → continues as Crash output, runtime/debug, BuildInfo and debuglog (1.18+)
OS interface, stacks and panics (Go 1.0–1.4)
Segmented stacks to contiguous (copied) stacks●●●●●still the design at go1.17 (stack growth by copying, 2 KB minimum, no segment chain) → continues as Stack growth, stack bounds and the crash stack (1.18+)
Stack-split prologue, nosplit budget and C-on-Go-stack detection●●●●the prologue check and nosplit budget persist (budget size changed); StackPreempt-style guard poisoning persists → continues as Stack growth, stack bounds and the crash stack (1.18+)
Goroutine preemption (stackguard0, 10 ms and GC preemption)●●replaced by asynchronous (signal-based) preemption in a later release; the cooperative stack-check mechanism remains as a fallback → continues as Signals and async-preemption machinery (1.18+)
Panic, defer, recover and Goexit●●●●●replaced by open-coded defers and the new panic loop in later releases (1.14, then 1.22) → continues as Defer, panic and recover re-implementation (1.18+)
Tracebacks, crash output and GOTRACEBACK●●●●●gentraceback is the single stack walker (becomes the unwinder iterator in 1.21) → continues as Unwinder: gentraceback → unwinder iterator, inline unwinder, pcvalue cache (1.18+)
Symbol tables, pclntab and runtime.Caller/FuncForPC●●●●pclntab is still the design (format changed in 1.2 and 1.16/1.18) → continues as Symbol tables, runtime.Caller and CallersFrames (1.18+)
Signals: handling, os/signal, foreign threads●●●●●still the design (handlers installed with sigaction, sigqueue for os/signal) → continues as Signals and async-preemption machinery (1.18+)
Threads, locks and the OS scheduler interface●●●●●still the design (futex/sema based lock_futex.go, lock_sema.go) → continues as Syscall layer: AllThreadsSyscall, internal/runtime/syscall, libc and Windows SyscallN (1.18+)
cgo runtime support and non-Go threads●●●●●still the design in outline (cgocall/asmcgocall, cgocallback, extra M) → continues as C-to-Go callbacks: extra-M reuse, system-stack bounds, init gating (1.18+)
TLS, g/m registers and shared-library linking●●●●●still the design in outline (g in TLS or a reserved register) → continues as Library entry points and runtime initialization (1.18+)
Clocks, vDSO and timers●●●●vDSO clock_gettime still used on Linux → continues as vDSO, vgetrandom and fast clocks (1.18+)
Windows runtime port●●●●●still VEH-based exception handling → continues as Windows runtime port (1.18+)
Platform ports: OS and architecture matrix●●●●●these ports persist except plan9/solaris variants carried through later work; nacl removed later → continues as New, ported and removed platforms (1.18+)
Integrated network poller: OS back-ends●●●●still the design (epoll, kqueue, IOCP, solaris ports) → continues as Syscall layer: AllThreadsSyscall, internal/runtime/syscall, libc and Windows SyscallN (1.18+)
Runtime C-to-Go conversion and the Go calling convention in C (1.4)●●completed; no C left in the runtime → continues as Library entry points and runtime initialization (1.18+)
Startup, auxv, randomness and security-adjacent runtime details●●still present → continues as Security hardening: AT_SECURE, std fds, AT_RANDOM, gated debug features (1.20+)
OS interface, stacks and panics (Go 1.5–1.17)
C-to-Go conversion of the runtime's OS, arch and signal layers ([dev.cc])●done in 1.5; the all-Go layout (os_$GOOS.go, signal_$GOOS_$GOARCH.go, sys_$GOOS_$GOARCH.s, defs_.go, one sigctxt per OS/arch) is still the structure at go1.17.
New and ported OS/arch targets, 1.5–1.17●●●●●●●●●●●linux/{ppc64,ppc64le,arm64,mips,mipsle,mips64,mips64le,s390x,riscv64}, android/{386,arm,arm64,amd64}, js/wasm, aix/ppc64, darwin/arm64 (iOS) and ios, illumos, freebsd/arm64, netbsd/arm64, openbsd/{arm,arm64,mips64}, plan9/arm exist; nacl, darwin/arm, darwin/386, dragonfly/386 removed; windows/arm64 landing → continues as New, ported and removed platforms (1.18+).
Goroutine stack growth, shrinking, GC stack barriers and stack objects●●●●●●●●●●●●still the design at go1.17: contiguous stacks copied by copystack, shrunk during concurrent mark, stack barriers gone, stack objects used for address-taken locals → continues as Stack growth, stack bounds and the crash stack (1.18+).
Tracebacks, symbol tables and runtime.Callers/CallersFrames●●●●●●●●●●●●●gentraceback is still the single stack walker, now inline-aware, TOPFRAME/SPWRITE-driven → continues as Unwinder: gentraceback → unwinder iterator, inline unwinder, pcvalue cache (1.18+) and Symbol tables, runtime.Caller and CallersFrames (1.18+).
Defer, panic, recover and Goexit (runtime side)●●●●●●●●●●●three defer kinds (heap/stack records via deferproc/deferprocStack, open-coded defers via funcdata bits), all processed by gopanic with a _defer chain; GOEXPERIMENT=regabidefer makes deferred calls func() → continues as Defer, panic and recover re-implementation (1.18+).
Signals: masks, forwarding, sigaltstack and the unified Unix signal layer●●●●●●●●●●●●●one signal_unix.go with sighandler, sigtrampgo, adjustSignalStack, sigfwdgo; libc sigaction under cgo; M-targeted signals for preemption → continues as Signals and async-preemption machinery (1.18+).
Asynchronous preemption: signal plumbing, injected calls and per-arch support●●●●still the design at go1.17 → continues as Signals and async-preemption machinery (1.18+).
cgo runtime support: pointer checks, callbacks, extra Ms, C-to-Go call path●●●●●●●●●●●●the simplified C→Go path (crosscall2 → cgocallback → cgocallbackg → _cgoexp_GoF), cgocheck=1 pointer rules, extra-M list with batch creation → continues as C-to-Go callbacks: extra-M reuse, system-stack bounds, init gating (1.18+).
Shared-library and buildmode entry points (c-archive, c-shared, plugin, shared)●●●●●●●●●●per-arch _rt0__lib entry points exist for linux, darwin, windows, android, ios; init runs on a new thread and the loader thread returns → continues as Library entry points and runtime initialization (1.18+).
vDSO, time sources and process-wide randomness●●●●●●●●●●●vDSO used for clock_gettime on linux/{amd64,386,arm,arm64,mips64x,ppc64x}; Darwin/Windows use libc/KUSER_SHARED_DATA; fastrand seeded from OS randomness → continues as vDSO, vgetrandom and fast clocks (1.18+).
Darwin and OpenBSD move to libc; Solaris and AIX libcall; syscall wrapper layer●●●●●●●macOS and iOS, Solaris/illumos and AIX go through libc via libcCall/asmcgocall trampolines, and openbsd/{amd64,386,arm,arm64} link libc and use pthreads; Linux/FreeBSD still use raw syscalls → continues as Syscall layer: AllThreadsSyscall, internal/runtime/syscall, libc and Windows SyscallN (1.18+).
Windows runtime●●●●●●●●●●●●●Windows 10 long-path support, arm and arm64, high-resolution waitable timers, QPC/KUSER time, SuspendThread preemption, stdcall via syscall_syscall, callbacks via compileCallback → continues as Windows runtime port (1.18+).
CPU feature detection (internal/cpu), auxv parsing and GODEBUG=cpu.*●●●●●●●●internal/cpu is the single detection layer (x86, arm, arm64, ppc64x, s390x, mips64x) with GODEBUG=cpu.feature=off/on → continues as CPU feature detection, GOAMD64 checks and cpu GODEBUG options (1.18+).
Assembly-level runtime entry points: memequal/cmp/IndexByte, hashing, atomics and ABI wrappers●●●●●●●●●●●●●hand-written assembly in runtime, internal/bytealg, runtime/internal/atomic; ABI0/ABIInternal wrappers generated for cross-package assembly references; register ABI prerequisites in place → continues as the register-ABI work of 1.18+ (see Library entry points and runtime initialization).
Debugger function calls and conservative preemption frames●●●●still the design at go1.17 (debug calls run on a new goroutine with conservative scanning of the interrupted frame) → continues as Signals and async-preemption machinery (1.18+).
Thread lifecycle, physical page size and scheduler-facing OS hooks●●●●●●●●still the design at go1.17 → continues in Signals and async-preemption machinery (1.18+).
Plan 9 and NaCl ports●●●●●●Plan 9 still supported (notes as signals, env cache); NaCl removed in 1.14 → continues as New, ported and removed platforms (1.18+).
Compiler frontend (Go 1.0: 2008–2012)
Lexer, grammar and statement syntax (semicolons, chan operators, conversions)●the surface syntax is the Go 1 one; the yacc grammar go.y and hand-written lexer lex.c stayed the parser until the compiler was rewritten in Go (not in this range). → continues as The syntax package (parser, scanner, tree) (1.18+)
Package system, visibility and import resolution●capitalisation-based export and -p/-D/-I import resolution as of go1; compiler flags later reworked by the build system. → continues as Package paths, -p, and build-system contract (1.18+)
Export/import data format●textual export data in the object file's __.PKGDEF section was still the format at go1 and in 1.17 had moved through the binary format and then indexed export data → continues as Unified IR: one serialization for noding, stenciling, inlining and export (1.18+)
Constants and multi-precision arithmetic●arbitrary-precision constants as at go1 (mparith); later moved to go/constant and math/big → continues as Language features as seen by the type checker (by release) (1.18+)
Typecheck/walk separation and package-level declaration order●typecheck pass (typecheck.c) as one separate pass over a whole function tree, still the design at go1.17 in Go form → continues as Old typechecker and IR node-model cleanup (1.18+)
Interfaces, type switches, assertions and comparability●interface layout Eface/Iface and comparison rules as at go1 persisted; the runtime later moved to itab caches in Go-era reflect → continues as Type sets, union terms, interfaces and constraint satisfaction (1.18+)
Embedded fields, method sets and receivers●embedding via genembedtramp-style wrapper generation as at go1 → continues as Method receiver checking (1.18+)
Closures●closure conversion by value-or-reference capture classification as at go1; the compiler later rewrote it → continues as Frontend support for new language features and spec changes (1.18+)
Escape analysis and heap allocation●first escape analysis enabled by default in esc.c → continues as the escape analysis in later threads; no 1.18 link.
Inlining●first inliner, evolved massively afterwards.
Builtins and unsafe●builtin set as at go1 → continues as Language features as seen by the type checker (by release) (1.18+)
Channels, select, maps and strings as built-in types●compiler lowering to runtime calls as at go1.
Initialization and static data●sinit.c static init as at go1 → continues as Static initialization and package init (1.18+)
Composite literals●Go 1 rules; type elision for struct/array elements came later.
Variadic functions (...)●...T as a property of func types.
Statement and flow rules●Go 1 rules.
Diagnostics, error recovery and compiler plumbing●C compiler diagnostics; messages later shared with types2.
Compiler frontend (Go 1.1–1.9)
The C-to-Go translation of the compiler (cmd/gc → cmd/internal/gc → cmd/compile/internal/gc)●●●done in 1.5; the Go gc package then became the single frontend, later split into syntax, types, ssa and so on → continues as Old typechecker and IR node-model cleanup (1.18+)
Parser: from yacc to a hand-written recursive-descent parser●●●●●●●the gc-internal parser was removed in 1.8; the syntax package parser is the only parser → continues as The syntax package (parser, scanner, tree) (1.18+)
The syntax package, position representation and parse-time checks●●still the design (syntax tree with Pos and PosBase; branch checking in the parser) → continues as The syntax package (parser, scanner, tree) (1.18+)
Binary export data and the object-file split●●●●●●●●binary export format (v1..v5 "bexport"/"bimport") plus inlined bodies; later replaced by the indexed format and then unified IR → continues as Unified IR: one serialization for noding, stenciling, inlining and export (1.18+)
Inlining●●●●●●the Node-based inliner with budget 80 survives, extended later (mid-stack, then PGO) → continues as Compile-time performance, concurrency and the self-PGO'd compiler (1.18+)
Escape analysis and stack allocation●●●●●●the 2012–2015 flow-graph analysis (esc.go) with param tags remains; rewritten in later releases → continues as Old typechecker and IR node-model cleanup (1.18+)
Closures, method values and variable capture●●●●●●●still the design (capture by value when never reassigned and not address-taken; closure call → function call) → continues as Old typechecker and IR node-model cleanup (1.18+)
Language changes and rules as implemented in the compiler●●●●●●●●●each rule is part of the language; implementation later moved to types2 → continues as Frontend support for new language features and spec changes (1.18+)
Type aliases (the => experiment and type A = B)●●type A = B is the language feature; the first implementation was reverted in 1.8 and redone on [dev.typealias] in 1.9 → continues as Generic type aliases and Alias type nodes (1.18+)
Constant arithmetic, Mpint/Mpflt and floating-point constants●●●●●big.Int/big.Float-based constants (Mpint, Mpflt) → continues as Old typechecker and IR node-model cleanup (1.18+)
Static initialization, composite literals and init●●●●●●●●sinit.go model with static data, dynamic init and oaslit; extended later with staticinit → continues as Static initialization and package init (1.18+)
Walk-level lowering and runtime-call optimisations●●●●●●●●still the walk/order model; the runtime entry points mostly persist → continues as Static initialization and package init (1.18+)
Write barriers, precise stacks and liveness (compiler side)●●●●●●●●write-barrier insertion moved into SSA later; frontend marks (pragmas, OASWB) removed in 1.9 → continues as Old typechecker and IR node-model cleanup (1.18+)
Compiler data structures: Node, Nodes, Type, and the types package●●●●●ir.Node and types.Type as separate packages came in later releases; the 1.9 types package is the start → continues as Types package internals: size, algorithm kind, TFlag, SIMD flags (1.18+)
Compiler performance, formatting and concurrency●●●backend concurrency via -c, with cmd/go setting it; later default → continues as Compile-time performance, concurrency and the self-PGO'd compiler (1.18+)
Pragmas, directives and compiler flags●●●●●●●●//go: pragma set persisted and grew → continues as Compiler debugging infrastructure: bisect/hash debugging, flags, dumps (1.18+)
Race detector and sanitizer instrumentation in the frontend●●●●racewalk pass (later instrument) → continues as Compiler debugging infrastructure: bisect/hash debugging, flags, dumps (1.18+)
Diagnostics and error messages●●●ongoing; types2 later supplies messages → continues as Error reporting: codes, messages, and sub-errors (1.18+)
Compiler frontend (Go 1.10–1.17)
dev.regabi: from *Node struct to the ir.Node interface and concrete node types●●●●●●●●done: ir.Node is an interface with ~60 concrete node types (ir.Name, ir.Func, ir.CallExpr, …) and generated DoChildren/EditChildren/Copy; Left/Right/List accessors are gone; Nodes is a plain slice → continues as Old typechecker and IR node-model cleanup (1.18+)
dev.regabi: breaking up package gc into base, ir, types, typecheck, noder, inline, staticdata, reflectdata, pkginit●done; layout of cmd/compile/internal/ as it remained → continues as Old typechecker and IR node-model cleanup (1.18+)
Indexed export format and the export-data lifecycle●●●●●●●●the indexed (iexport) format is the only compiler export format, now carrying positions with columns, type information on inlined bodies, closures and ABIs → continues as Unified IR: one serialization for noding, stenciling, inlining and export (1.18+)
Generics bring-up in the compiler (dev.typeparams): parser, -G, types2, irgen, first stenciling●generic code is parsed and type-checked only when the undocumented -G flag is given; stenciling of simple generic functions and types exists but is experimental and not enabled by default → continues as Generics via GC-shape stenciling and runtime dictionaries (1.18+) and Bringing up generics in types2 (1.18+)
types2 port of go/types: reviews, error-message parity and language-version support●types2 is used for -G builds only; the legacy typechecker is still the authority for ordinary compilation → continues as Sharing code between go/types and types2 (1.18+), Error reporting: codes, messages, and sub-errors (1.18+) and Bringing up generics in types2 (1.18+)
The syntax package: parser, scanner, source reader, positions and error recovery●●●●●●●stable parser with optional generics (AllowGenerics), a fast reader, and pragma handling delegated to the noder → continues as The syntax package (parser, scanner, tree) (1.18+)
Constants: Go 2 number literals, evconst, untyped conversion and go/constant●●●●●●●the compiler's constants are go/constant.Value; Ctype/Val/Mpint representation gone; untyped types are types.Ideal{int,rune,float,complex}; rational arithmetic enabled → continues as Frontend support for new language features and spec changes (1.18+)
Language version gating (-lang) and language changes implemented in the frontend●●●●●●●-lang enforced by both checkers (old typechecker and types2) with errors naming the required version → continues as Per-file language versions and version gating (1.18+) and Frontend support for new language features and spec changes (1.18+)
Package initialization order, static initialisation and init functions●●●●●●●spec-compliant init order (initorder.go), static maps/slices/structs emitted as data where possible, fninit earlier → continues as Static initialization and package init (1.18+)
Concurrent compilation and frontend performance●●●●●●backend compiles functions concurrently via the compile queue; frontend is serial → continues as Compile-time performance, concurrency and the self-PGO'd compiler (1.18+)
Directives and pragmas in the frontend (//go: handling)●●●●●●pragma handling is an interface between syntax and the noder with misplacement diagnostics → continues as The syntax package (parser, scanner, tree) (1.18+)
Inlining-related frontend work: export of bodies, type switches, closures, devirtualization●●●●●●inliner handles type switches, method values and (re-enabled for the new export format) closures with limits → continues as Old typechecker and IR node-model cleanup (1.18+)
The legacy typechecker: error quality, alias/recursive-type handling and type checking order●●●●●●●●still the authoritative checker outside -G; heavily incrementally improved → continues as Old typechecker and IR node-model cleanup (1.18+)
Lowering in order/walk and the shape of runtime calls emitted by the frontend●●●●●●●●the frontend lowers many constructs to specialised runtime calls; some previously frontend work moved to SSA construction → continues as Method wrappers and promoted-method sharing (1.18+) for wrappers only; otherwise no direct continuation
checkptr instrumentation and compiler debugging flags●●●●●●-d=checkptr implied by -race/-msan; Debug is a struct → continues as Compiler debugging infrastructure: bisect/hash debugging, flags, dumps (1.18+)
Types package internals and type printing●●●●●●types hosts type constructors, size computation and printing → continues as Types package internals: size, algorithm kind, TFlag, SIMD flags (1.18+)
Register-ABI plumbing in the frontend●●ABI wrappers generated per ir.Func, ABIs exported across packages → continues as Method wrappers and promoted-method sharing (1.18+)
Middle end and SSA optimizer (Go 1.0–1.9)
SSA backend arrival (dev.ssa): bring-up, coverage, default-on●●●still the design at go1.17 (the SSA IR, pass pipeline and rulegen scheme introduced here is what the compiler uses); superseded only in detail by later register-ABI and typed-IR work.
Generic rewrite rules and rulegen●●●still the design at go1.17 (rules in ssa/gen/.rules, generated rewrite.go; extended with new rule syntax and later machinery).
Common subexpression elimination (cse) and its scalability●●●still the design at go1.17 (partition refinement by sorted argument classes).
Nil check elimination and the redesign of nil checks●●●still the design at go1.17 (NilCheck as a memory-ordered op, eliminated by a dominator-tree walk, with a separate arch-specific late pass).
Prove pass and bounds-check elimination●●●still the base design (dominator-walk with facts) but later rewritten around a poset/limit table (the 1.19 rework) → continues as Prove pass and bounds-check elimination: from poset relations to a dense limit table, topo-sorted walk, and division-aware proofs (1.19+).
Escape analysis (esc.c → esc.go)●●●●●●●●●●still the flood-based esc.go design at the end of this range (go1.9) → continues as Escape analysis: call modelling, closures, func-variable callees, and solver speed (1.18+).
Inlining (inl.c → inl.go)●●●●●●classic budget-80 inliner, still the design at go1.17 with later additions (mid-stack inlining, closures) → continues as Inliner: budget, closures, and the interleaved inline/devirtualize driver (1.18+).
Order, walk and temporary lifetimes (order.c, walk.c)●●●●●●order and walk stayed the pre-SSA lowering phases through the end of this range → continues as Range-loop and range-over-func lowering in walk (1.18+) for the range part.
Write-barrier insertion: from gc to the SSA writebarrier pass●●●●●SSA writebarrier pass with store ordering, still the design at go1.17 (hybrid barrier elision refinements later).
Switch, type-switch and select lowering●●●●binary search plus later jump tables → continues as Switch lowering: jump tables, type-switch caches, and switch lookup tables (1.19+ for jump tables).
Interface conversions, type assertions and devirtualization●●●●→ continues as Static devirtualization and shape-aware type-assertion pruning (1.18+).
Phi construction and the SSA builder's scalability●●●Sreedhar-Gao phi building for large functions, still the design at go1.17.
Dominators, loops, CFG editing and block-level passes●●●still the design at go1.17 (dominator tree + likelyadjust + looprotate + fuse/shortcircuit/trim).
Compile-time performance and determinism of the SSA package●●●the allocation caches and sparse structures remain.
Preparing the backend for concurrent compilation (Go 1.9)●completed within 1.9; no later thread.
Lowering of copies, strings and slices; intrinsics●●●●●→ continues as Lowering of builtins to memory ops: memmove/memclr/memequal inlining and generated equality (1.18+).
Middle end and SSA optimizer (Go 1.10–1.17)
Prove pass: unsatisfiability, partial-order facts, loop bounds-check elimination●●●●●●●●still the design at go1.17 (facts table + poset, induction variables found inside prove); loop BCE merged into prove in 1.11 → continues as Prove pass and bounds-check elimination: from poset relations to a dense limit table, topo-sorted walk, and division-aware proofs (1.18+)
Escape analysis: the esc.go fixes, the escape.go rewrite, and the move to package escape●●●●●●●●the escape.go (graph/location) design, now in its own package cmd/compile/internal/escape, handling closure conversion/capture analysis → continues as Escape analysis: call modelling, closures, func-variable callees, and solver speed (1.18+)
Inlining: budget, mid-stack inlining, closures, and what became inlinable●●●●●●●●classic AST-based inliner in cmd/compile/internal/inline with budget 80, mid-stack inlining, for loops and closures inlinable (closures-with-captures-in-functions disabled by -d=inlfuncswithclosures=0) → continues as Inliner: budget, closures, and the interleaved inline/devirtualize driver (1.18+)
Early devirtualization and static value tracing●●a small AST pass in a new devirtualize package (Func), invoked after inlining → continues as Static devirtualization and shape-aware type-assertion pruning (1.18+)
Open-coded defers and defer lowering●●●●stack-allocated defer records (1.13), open-coded defers (1.14), and go/defer wrapped into argument-less closures (1.17)
Late call expansion and the SSA side of the register ABI●●●expand_calls pass lowering aggregate args/results to OpArgReg/SelectN; compiler support for GOEXPERIMENT=regabi in place
Statement boundaries (is_stmt) and source positions through the optimizer●●●●●still the design (stmt marks on src.XPos lico, preserved by passes)
DWARF location lists from SSA●●●●the 1.11 design (direct SSA to location list, ssa/debug.go) remained in place
Switch lowering, select, and type switches in walk●●●●the 1.14 walk/switch.go design (binary search over runs of constants, string length-first) → continues as Switch lowering: jump tables, type-switch caches, and switch lookup tables (1.18+)
Range loops, append and map idioms in walk●●●●still the design (lowering to element pointer with late increment; memclr idiom) → continues as Range-loop and range-over-func lowering in walk (1.18+)
Rewrite-rule generator, typed Aux/AuxInt, and rule syntax●●●●●●●ssa/gen/rulegen.go builds an in-memory syntax tree with typed aux fields; untyped rules removed
Write-barrier elision and the writebarrier pass●●●●●●ssa/writebarrier.go inserts barriers and drops them for provably non-heap stores
Memory-op optimizations: memmove, Move/Zero, dead stores, nil checks●●●●●●generic rules plus dse/dead auto elim passes → continues as Memory-op optimization: memcombine, dead stores, store-to-load forwarding, alias analysis, mem2reg (1.18+), Lowering of builtins to memory ops: memmove/memclr/memequal inlining and generated equality
Arithmetic strength reduction, divisibility and intrinsics●●●●●●●●generic.rules and per-arch rules
CFG and control-flow passes: branchelim, fuse, shortcircuit, phiopt●●●●●●●branchelim on amd64/arm64, strengthened shortcircuit/fuse/phiopt → continues as Branch-free lowering: CondSelect-into-math and ARM64 CCMP (1.18+)
Compiler front of walk/order: ordering fixes and the dev.regabi IR refactor (package walk)●●●●●●●●walk, escape, devirtualize, ssagen are separate packages over the new ir node types
Diagnostics for the optimizer: ssa.html, GOSSAFUNC and optimizer logging●●●●●●●still the tooling at go1.17
Backends and assemblers (Go 1.0–1.6)
Per-architecture compilers 6g/8g/5g/9g and the shared gc code generator●●●●●●●the Prog-list code generators were replaced by the SSA backend (1.7 onward, other area); in 1.6 they still existed as Go packages cmd/compile/internal/{amd64,x86,arm,arm64,ppc64,mips64} → continues as Register-based calling convention (ABIInternal) ports beyond amd64 and amd64 code generation and GOAMD64 microarchitecture levels (1.18+)
Register allocation and the peephole optimizer (reg.c, peep.c)●●●●●●●replaced by the SSA register allocator; the old optimizer was gone before go1.17 → continues as Register allocator, scheduler and block-level backend passes (1.18+)
Expression and statement code quality in 6g/8g/5g (division, bounds checks, loops, slices, interfaces)●●●●●●●superseded by SSA rules and lowering → continues as amd64 code generation and GOAMD64 microarchitecture levels (1.18+)
Stack frames, pointer maps and liveness analysis in the compiler●●●●●liveness analysis (plive) and per-call-site stack maps remain; pointer bitmaps are still 1 bit per word → continues as Stack slot merging, liveness and stack maps (1.18+)
Stack frame layout, prologues, stack split and frame pointers●●●●●●●prologue generation per architecture in cmd/internal/obj/; frame pointers kept on amd64 (default) and arm64 → continues as Prologue, frame pointer, stack split and function alignment (cmd/internal/obj) (1.18+)
Zeroing and copying: Duff's device, REP, unaligned moves and AVX2 runtime assembly●●●●●duffzero/duffcopy still used by amd64 at go1.17 → continues as Duff's device replaced by generated loops; Zero/Move lowering (1.20+)
liblink: a shared assembler/linker library●●●converted to Go as cmd/internal/obj in 1.5 (this thread); the C library itself was deleted (3317e7f19a) → continues as Prologue, frame pointer, stack split and function alignment (cmd/internal/obj) (1.18+)
Normalising Prog/Addr in cmd/internal/obj (the portable instruction representation)●●the design (portable Prog, Addr with TYPE_, From3/RegTo2, shared A numbers, Link context) is still in place → continues as Prologue, frame pointer, stack split and function alignment (cmd/internal/obj) (1.18+)
The Plan 9 C compilers (cc, 5c/6c/8c) in the Go toolchain●●●●●●removed in 1.5 (4a42fae2cd on dev.cc); runtime was rewritten in Go and assembly
Assemblers: 5a/6a/8a/9a and the Go cmd/asm●●●●●●●cmd/asm (cmd/asm/internal/{arch,asm,flags,lex} + cmd/internal/obj) is the assembler → continues as arm64 code generation and assembler (and the other per-arch assembler threads) (1.18+)
C→Go translation of the toolchain (liblink, assemblers, compilers; dev.cc)●●●complete; all tools are Go
The ppc64 / ppc64le port (dev.power64, 9g/9a/9l)●●production port with shared-library support → continues as PPC64 / Power10 backend (GOPPC64, prefixed instructions, PC-relative code) (1.18+)
The arm64 (ARMv8) port (7g/7a/7l)●●production port → continues as arm64 code generation and assembler (1.18+)
The mips64 port and the mips/mips64 register space●production port → continues as s390x, MIPS, 386 and 32-bit ARM backends (1.18+)
Native Client (nacl/386, nacl/amd64p32, nacl/arm) and amd64p32 in the toolchain●●●not covered by this range's commits after 1.5
Position-independent code, dynamic linking and TLS in the assemblers●●●●working on amd64, 386, arm, arm64, ppc64le → continues as Prologue, frame pointer, stack split and function alignment (cmd/internal/obj) (1.18+)
Backends and assemblers (Go 1.7–1.11)
SSA backend bring-up on amd64 (dev.ssa merge)●still the design at go1.17 (the same cmd/compile/internal/ssa package: Value/Block/Func, generic ops lowered by gen/.rules, passes list in compile.go) → continues as Register allocator, scheduler and block-level backend passes (1.18+)
Register allocation, flag allocation and stack slots●●●●●still the design at go1.17 (global allocator in regalloc.go, separate flagalloc, stackalloc) → continues as Register allocator, scheduler and block-level backend passes (1.18+)
Scheduling, tighten, block layout and CFG passes●●●●●still the design at go1.17 (schedule, tighten, layout, looprotate, branchelim, fuse) → continues as Register allocator, scheduler and block-level backend passes (1.18+)
Rewrite-rule machinery and compile-time performance of the SSA compiler●●●●●still the design at go1.17 (rulegen.go, | alternation, automatic commutation) → continues as Late-lower pass, memory-op combining and arch-independent rule migration (1.18+)
Multi-architecture SSA ports: ARM, 386, ARM64 (dev.ssa)●●●still the design at go1.17 (each architecture owns ssa/gen/ARCH.rules, ARCHOps.go and cmd/compile/internal/ARCH/ssa.go) → continues as s390x, MIPS, 386 and 32-bit ARM backends (1.18+) and arm64 code generation and assembler (1.18+)
Multi-architecture SSA ports: PPC64, MIPS64, MIPS32, s390x●●●●●still the design at go1.17; ppc64x, mips64x, mipsx and s390x all remain stack-ABI backends → continues as PPC64 / Power10 backend (GOPPC64, prefixed instructions, PC-relative code) (1.18+) and s390x, MIPS, 386 and 32-bit ARM backends (1.18+)
WebAssembly backend●still the design at go1.17 → continues as WebAssembly backend (1.18+)
Removal of the legacy backend and decoupling gc from the code generators●●●done; the per-architecture ssa.go files are the only code generators → continues as Prologue, frame pointer, stack split and function alignment (cmd/internal/obj) (1.18+) (frame handling)
Liveness, stack maps, safepoints and write barriers●●●●●still the design at go1.17 (liveness over SSA, asynchronous-preemption-capable register maps) → continues as Stack slot merging, liveness and stack maps (1.18+)
DWARF variable locations, statement positions and inline info from the backend●●●still the design at go1.17 (location lists generated from SSA LocalSlot tracking; is_stmt boundaries) → continues as Register allocator, scheduler and block-level backend passes (1.18+)
Intrinsics for atomics, math/bits, math and runtime helpers●●●●●still the design at go1.17 (intrinsics table in ssa.go, SSA ops with per-arch lowerings) → continues as Atomics and memory-ordering code generation (1.18+) and Multi-word arithmetic, intrinsics and carry-chain support (1.18+)
Memory-op combining, byte-order idioms and load/store folding●●●●●still the design at go1.17 (rewrite-rule based) → continues as Late-lower pass, memory-op combining and arch-independent rule migration (1.18+)
amd64 and 386 instruction selection●●●●●still the design at go1.17 → continues as amd64 code generation and GOAMD64 microarchitecture levels (1.18+)
ARM and ARM64 instruction selection and fused operations●●●●still the design at go1.17 → continues as arm64 code generation and assembler (1.18+)
Memory clearing and copying: Zero, Move and Duff's device●●●●●still the design at go1.17 (Duff's device for large Zero/Move, inline stores for small) → continues as Duff's device replaced by generated loops; Zero/Move lowering (1.20+)
cmd/internal/obj: Prog/LSym refactoring, concurrent backend and object-writing●●●●●still the design at go1.17 (assemblers take a newprog allocator, per-function FuncInfo) → continues as Prologue, frame pointer, stack split and function alignment (cmd/internal/obj) (1.18+)
x86 assembler: AVX, AVX2, AVX-512 and the instruction table●●●●●still the design at go1.17 (asm6.go + generated VEX/EVEX tables from x86avxgen) → continues as amd64 code generation and GOAMD64 microarchitecture levels (1.18+)
ARM64 assembler●●●●still the design at go1.17 (table-driven optab in asm7.go) → continues as arm64 code generation and assembler (1.18+)
32-bit ARM, MIPS and PPC64 assemblers●●●●still the design at go1.17 → continues as PPC64 / Power10 backend (GOPPC64, prefixed instructions, PC-relative code) (1.18+) and s390x, MIPS, 386 and 32-bit ARM backends (1.18+)
Prologues, frame pointers, NOFRAME and tail calls●●●●still the design at go1.17 → continues as Prologue, frame pointer, stack split and function alignment (cmd/internal/obj) (1.18+)
Backends and assemblers (Go 1.12–1.17)
Register-based ABI (ABIInternal) and ABI wrappers●●●●amd64 passes arguments and results in registers by default, with ABI0↔ABIInternal wrappers generated by the compiler; R14 = g, X15 = zero, R12/R13 = entry scratch; other architectures still stack-based → continues as Register-based calling convention (ABIInternal) ports beyond amd64 (1.18+)
Late call expansion, AuxCall and the expand_calls pass●●default design: calls carry ssa.AuxCall, and expand_calls lowers arguments/results (including registers) after generic optimization → continues as Register-based calling convention (ABIInternal) ports beyond amd64 (1.18+)
dev.regabi package decomposition (ssagen, liveness, objw, types, abi)●done; gc no longer holds SSA generation or liveness → continues in the 1.18+ compiler layout
Rewrite-rule generator (rulegen): ellipses, commutativity loops, typed aux●●●●●all rule files use typed aux/auxint (=>); commutative ops use nested loops; no chunking → continues in the 1.18+ SSA rule infrastructure
amd64 lowering: read-modify-write, load-op, addressing modes pass, intrinsic-friendly rules●●●●●●still the design at go1.17 → continues as amd64 code generation and GOAMD64 microarchitecture levels (1.18+)
arm64 backend and assembler●●●●●●mature backend with constant synthesis by MOVZ/MOVK and ADD pairs, frame pointer on by default, ARMv8.1 atomics; → continues as arm64 code generation and assembler (1.18+)
riscv64 port: assembler and compiler●●●●working linux/riscv64 with PIE and cgo, atomics, Duff's devices, branch pseudo-instructions → continues as riscv64 compiler and assembler (RVA profiles, vector, compressed) (1.18+)
PPC64 / POWER backend and assembler●●●●●●power8 baseline with power9 instructions under GOPPC64=power9 → continues as PPC64 / Power10 backend (GOPPC64, prefixed instructions, PC-relative code) (1.18+)
s390x backend: compare-and-branch, intrinsics, assembler●●●●●●still stack ABI → continues as s390x, MIPS, 386 and 32-bit ARM backends (1.18+)
386, ARM (32-bit), MIPS/MIPS64 and the 387 removal●●●●●●maintenance; 387 dropped, GO386=softfloat for no-SSE → continues as s390x, MIPS, 386 and 32-bit ARM backends (1.18+)
WebAssembly backend●●●●stack-based simulated registers with SP cached in locals, optional sign-extension/saturating ops via GOWASM → continues as WebAssembly backend (1.18+)
math/bits, atomic and runtime intrinsics (cross-architecture)●●●●●●intrinsics for bits/atomic/FMA exist on most ports → continues as Atomics and memory-ordering code generation and Multi-word arithmetic, intrinsics and carry-chain support (1.18+)
SSA infrastructure passes: layout, regalloc, scheduling, flagalloc, block shape●●●●●●depth-first layout with exit-block placement, regalloc using phi/desired info → continues as Register allocator, scheduler and block-level backend passes (1.18+)
Safepoints, unsafe points and stack maps for asynchronous preemption●●●●stack maps only at call sites; register maps removed; unsafe-point info in PCDATA → continues as Stack slot merging, liveness and stack maps (1.18+)
Debug info generated by the backend: statements, location lists, line tables●●●●●●is_stmt marks with minimal-harm heuristics; debug_lines generated by walking Progs in the compiler → continues in 1.18+
New object file format and content-addressable symbols (dev.link, assembler side)●●●●done; the linker consumes indexed objects (goobj2) → continues in the linker threads (1.18+)
Assembler directives and tooling: PCALIGN/ALIGN, FuncInfo flags, prologue handling●●●●●●still the design at go1.17 → continues as Prologue, frame pointer, stack split and function alignment (cmd/internal/obj) (1.18+)
Linker and object files (Go 1.0–1.9)
Early loaders 5l/6l/8l and the shared src/cmd/ld (2008–2011)●replaced by the C-to-Go converted linker in 1.5 and by cmd/link thereafter → continues as Relocation-free pclntab and funcdata (offsets instead of relocations) and Per-platform object formats and internal linking (Mach-O, PE, XCOFF, wasm, ppc64, riscv64, loong64) (1.18+)
Go symbol table, pc/line table and function metadata (gosymtab, pclntab, findfunc)●●●●●●●●●●still the Go 1.2 pclntab design (contiguous per-function tables plus functab) with a findfunctab bucket index (1.5) and offsets-based types (1.7); the pclntab itself is rewritten in 1.18 → continues as Relocation-free pclntab and funcdata (offsets instead of relocations) (1.18+)
Stack splitting and the linker's nosplit overflow check●●●●●●nosplit chain checking is still done by the linker (stkcheck in cmd/link), reworked in 1.19 → continues as Nosplit stack checking and stack constants (1.19+)
Dead code and data elimination●●●●●●●reachability-flood plus method pruning conditioned on reflect.Value.Method/Call use, as designed in 1.7 → continues as Dead code elimination and reflection-aware pruning (1.18+)
DWARF generation in the linker●●●●●●●●●●function DWARF generated in the compiler (1.8) and assembled by the linker; types/globals still in the linker → continues as DWARF quality for debuggers (types, variables, trampolines) (1.18+)
External (host) linking and cgo●●●●●●●●●internal linking only for cgo-free or stdlib-cgo cases; external linking required in many cgo cases → continues as ELF/relro/hardening and external-link policy (1.18+)
Build modes: -shared, c-archive, c-shared, shared, PIE, plugin●●●●●●●all six build modes implemented; internal PIE on linux/amd64 exists but external is the default → continues as ELF/relro/hardening and external-link policy (1.18+)
liblink, the object file format and the move into the compilers●●●●●●cmd/internal/obj + goobj object format with symbol references, contiguous data and per-package indexes; replaced in the 1.15–1.17 era by the new object file format → continues as Relocation-free pclntab and funcdata (offsets instead of relocations) (1.18+)
From C to Go: cmd/link●●●●●●●cmd/link written in Go, still based on the 1.5 c2go output, being re-architected in the 1.15–1.17 era → continues as Linker performance and memory (1.18+)
Linker speed and memory (Go 1.7 focus)●●●●●incremental; the 1.17-era work moved to the new object format and loader → continues as Linker performance and memory (1.18+)
Runtime type data, GC metadata and sections laid out by the linker●●●●●●●●type descriptors with offsets (nameOff, typeOff, textOff) and GC bitmaps in dedicated sections → continues as Type, itab and typelink layout (.go.type section, relro rework) (1.18+)
Container writers: Windows PE, Mach-O and Plan 9●●●●●●●●●PE, Mach-O and ELF writers in cmd/link/internal/ld; Mach-O code-signing friendly and Windows external linking supported → continues as Per-platform object formats and internal linking (Mach-O, PE, XCOFF, wasm, ppc64, riscv64, loong64) (1.18+)
Architecture and OS ports in the linker (arm, power64, arm64, mips, s390x, nacl, BSDs, Solaris) and trampolines●●●●●●●●●●all ports in cmd/link/internal/<arch>; direct-branch trampolines for ARM and ppc64x → continues as Per-platform object formats and internal linking (Mach-O, PE, XCOFF, wasm, ppc64, riscv64, loong64) (1.18+)
Build IDs, ABI hashes, flags and determinism●●●●●●●●●-buildid, -X, -importcfg, -B, -linkmode, -extld all present → continues as Reproducible build IDs, buildinfo and symbol tables (1.18+)
Linker and object files (Go 1.10–1.17)
New object file format and the loader (dev.link)●●●●done; the linker reads only the indexed object format through cmd/link/internal/loader, sym.Symbol is gone, and the format gained a weak-reloc bit and 16-bit reloc types in 1.17 → continues as Relocation-free pclntab and funcdata (offsets instead of relocations) and Type, itab and typelink layout (.go.type section, relro rework) (1.18+)
Wavefront conversion of linker passes to the loader; sym.Symbol removal●●done (all passes run on loader.Sym; cmd/oldlink gone from the story) → continues as Relocation-free pclntab and funcdata (offsets instead of relocations) (1.18+)
Linker performance and memory engineering●●●●●●●●mmapped, parallel, streaming pipeline with generator symbols; ongoing → continues as Linker performance and memory (1.18+)
pclntab, funcdata and pc tables●●●●●●pclntab split into runtime.pcheader, funcnametab, pctab and generator-built tables; still relocation-based → continues as Relocation-free pclntab and funcdata (offsets instead of relocations) (1.18+)
Dead-code elimination and method pruning●●●●●●●index-based deadcode with UsedInIface/R_USEIFACE/R_USEIFACEMETHOD method pruning, weak itab edges and reflect-aware tracking → continues as Dead code elimination and reflection-aware pruning (1.18+)
DWARF generation in the linker●●●●●●●●DWARF 4 with per-compilation-unit DIE and line-table symbols generated in parallel; line tables produced by the compiler → continues as DWARF quality for debuggers (types, variables, trampolines) (1.18+)
DWARF compression and Mach-O dsymutil combining●●●●still the design at go1.17 (zlib ELF/Mach-O/PE compression; dsymutil combine on macOS/amd64 and arm64) → continues as Linker performance and memory (1.18+)
Symbol ABIs: stable ABI0 vs ABIInternal in the linker and object files●●●●wrapper-based ABIs with name-mangled shared linkage and ABI-aware cgo exports; ABI aliases only for code without wrappers → continues as Type, itab and typelink layout (.go.type section, relro rework) (1.18+)
Mach-O and Darwin support●●●●●●●●internal linking, PIE, plugins and c-shared on darwin/arm64 with code signing, __DATA_CONST, LC_BUILD_VERSION → continues as Per-platform object formats and internal linking (Mach-O, PE, XCOFF, wasm, ppc64, riscv64, loong64) (1.18+)
PE / Windows●●●●●●●●internal/external linking, PIE, ASLR, DEP, windows/arm and windows/arm64 → continues as Per-platform object formats and internal linking (Mach-O, PE, XCOFF, wasm, ppc64, riscv64, loong64) (1.18+)
AIX / XCOFF●●●done; aix/ppc64 supports internal and external linking, c-archive and PIE → continues as Per-platform object formats and internal linking (Mach-O, PE, XCOFF, wasm, ppc64, riscv64, loong64) (1.18+)
WebAssembly●●●●●still the design at go1.17 → continues as Per-platform object formats and internal linking (Mach-O, PE, XCOFF, wasm, ppc64, riscv64, loong64) (1.18+)
Build modes: PIE, plugin, c-shared, c-archive, shared libraries●●●●●●●internal-linking PIE on linux/amd64+arm64, windows and darwin; plugins on darwin/arm64 and freebsd/amd64, disabled without cgo → continues as ELF/relro/hardening and external-link policy (1.18+)
Host object loading and external linking●●●●●●●●host objects (ELF, Mach-O, PE, XCOFF) read with loader symbols; external linker flags probed and filtered; cgo directive encoding as JSON → continues as ELF/relro/hardening and external-link policy (1.18+)
Architecture ports and trampoline insertion●●●●●●two-pass trampoline pass for arm/arm64/ppc64; riscv64, mips64, windows/arm64 external linking supported → continues as Per-platform object formats and internal linking (Mach-O, PE, XCOFF, wasm, ppc64, riscv64, loong64) (1.18+)
GOEXPERIMENT plumbing and tool configuration●●●experiments are a struct in internal/goexperiment parsed by objabi/buildcfg → still the design at go1.17
Build identity, buildinfo and reproducibility●●●●still the design → continues as Reproducible build IDs, buildinfo and symbol tables (1.18+)
Linker restructuring (1.10 code health and error reporting)●●●done; later passes build on these package splits

Go 1.18 – 1.28

Thread1.181.191.201.211.221.231.241.251.261.271.28Status at HEAD
Runtime: memory allocator and garbage collector (Go 1.18–1.28)
GC pacer redesign●●●●redesigned pacer is the only pacer since 1.19 (PacerRedesign GOEXPERIMENT added off in 1.18, defaulted on in 1.18, removed in 1.19); the 512 KiB heap minimum it introduced still sits behind the off-by-default HeapMinimum512KiB experiment
Soft memory limit and GC CPU limiter●●●●●GOMEMLIMIT/debug.SetMemoryLimit and the always-on GC CPU limiter shipped in 1.19; the feature flag was removed in 1.21; accounting fixes ran through 1.25
Green Tea: span-based marking with vector scan kernels●●●●GOEXPERIMENT=greenteagc added off in 1.25, default on in 1.26 (loong64 included later in 1.26); flag and the mgcmark_nogreenteagc.go fallback still present; AVX-512 kernels only on amd64
Heap bitmap rewrite and allocation headers●●●●●●allocation headers are the only heap-metadata scheme (experiment added and defaulted in 1.22, removed in 1.23); GC programs removed in 1.24
mallocgc decomposition and size-specialized malloc●●●●●sizespecializedmalloc added and defaulted on in the 1.26 cycle, off for the go1.26.0 release, on again in 1.27, flag removed in 1.28; specialization now covers size classes 1–7 (≤80 B); unconditional except on plan9/race/asan/msan/valgrind
Scavenger redesign●●●●●●controller-paced background scavenger at 1% of total CPU, chunk-index based search, memory-limit and GOGC goals
Transparent huge page management●●explicit heap THP marking removed in 1.22; density-based scavenger deferral and metadata huge-page toggling remain; GODEBUG=disablethp available
Finalizers, runtime.AddCleanup and the cleanup queue●●●●●●●●AddCleanup shipped in 1.24; cleanups run on up to GOMAXPROCS goroutines since 1.25; GODEBUG=checkfinalizer leak detector since 1.25; misuse panics since 1.26
Weak pointers and the unique package●●●●●unique since 1.23, public weak since 1.24; unique uses a bespoke weak canonicalization map since 1.25
Object pinning (runtime.Pinner)●●●●●runtime.Pinner shipped in 1.21; 1.28 cut pin/unpin costs with batching and per-P caches
Memory arenas experiment●●●●GOEXPERIMENT=arenas (package arena, reflect.ArenaNew) present and off by default since 1.20; no further feature work
runtime.freegc: compiler-directed explicit freeing●GOEXPERIMENT=runtimefreegc present, off by default; noscan objects only
Mark worker scheduling and GC work queues●●●●●●idle workers capped and suppressed when dedicated workers exist (1.19); worker selection integrated into start-the-world (1.26)
Allocation publication, zeroing and preemptibility●●●●●●allocate-black plus freeIndexForScan snapshot; largeType as atomic publication point; preemptible large clears still pending
Sweeper termination and pacing●●●●●●●single-atomic sweep termination; bgsweep yields only when no Ps are idle
Stack and register root scanning●●●●●allgs snapshot at mark start; async-preemption register state (scalar, vector, LR frame) scanned conservatively
Address-space layout, tagged pointers and the mem.go layer●●●●●●●●●per-platform heapAddrBits with 9 low tag bits; all OS mapping goes through mem.go state transitions
Linear-memory heaps (Wasm and sbrk platforms)●●●●●Wasm and Plan 9 share the sbrk free-block allocator; Wasm uses 512 KiB arenas
Heap base address randomization●●GOEXPERIMENT=randomizedheapbase64 on by default since 1.26 (off under race/asan/msan)
Runtime: scheduler, timers, channels, locks and synchronization (Go 1.18–1.28)
Timer rewrite: per-P timer heap, timer.lock, and GC-able synchronous timer channels●●●●●●●●●synchronous (unbuffered-semantics) timer channels are the only mode since asynctimerchan GODEBUG was removed in 1.27; micro-optimisation of channel-timer polling continues in 1.28
Runtime mutex: tri-state futex/sema locks → "spinbit" mutex●●●only the spinbit implementation exists (all platforms except wasm); sched.lock is exempt from some behaviours
Contended runtime-lock profiling (mutex profile for runtime-internal locks)●●●●●runtime locks appear in the mutex profile blaming the unlocker; call stacks gated behind runtimecontentionstacks
Scheduler core: spinning Ms, work conservation, stealing, STW interaction●●●●●●●●●ongoing tightening of races in P handoff, STW and safe-point handling
Syscall path: eliminating _Psyscall, _Gdeadextra, and goroutine states●shipped
GOMAXPROCS container awareness and dynamic updates●●●default behaviour, under containermaxprocs/updatemaxprocs GODEBUGs
testing/synctest bubbles●●●●●GOEXPERIMENT removed in 1.26; all bubble violations are fatal; Test-style API
Coroutines (iter.Pull runtime support)●●●stable runtime primitive (newcoro/coroswitch)
Asynchronous preemption: extended register state●●●●●●●AVX2/AVX-512/Neon/LSX/LASX state saved and conservatively scanned
sync package API evolution●●●●●●●●●●●stable; micro-optimisation continues
sync/atomic and runtime atomics●●●●●●typed atomics standard; runtime-internal atomics under internal/runtime/atomic
Runtime lock ranking●●●●●●generated from DAG; includes rwmutex modelling
Netpoller●●●●●●●epoll/kqueue/IOCP/wasip1 pollers with tagged pollDesc pointers
Goroutine lifecycle and identity●●●●goroutine leak profile on by default (experiment removed 1.27)
Fast random numbers for the scheduler●●●●cheaprand, wyrand-based
Runtime: maps, built-in data structures, hashing, randomness and type metadata (Go 1.18–1.28)
Swiss-table maps (GOEXPERIMENT=swissmap → only implementation)●●●●●only map implementation since the experiment was deleted in 1.26 (2ae059ccaf); GOEXPERIMENT=mapsplitgroup (KKKKVVVV layout) still an opt-in experiment; micro-tuning ongoing in 1.27/1.28
Map hashing and hash functions (memhash, aeshash, fallback hash)●●●●hashing code for maps lives in internal/runtime/maps (moved from runtime), hybrid wyhash/AES keyed by MinAeshashSize, interface hash folds the dynamic type
Compiler-generated equality/hash functions and type descriptor emission (reflectdata)●●●●●●●●●●one equality/hash function per "signature"; large types call subroutines; alg and noalg descriptors share one symbol
internal/abi type layout unification and type metadata (rtype → abi.Type)●●●●●●abi.Type is the single type-descriptor definition used by compiler, linker, runtime, reflect and reflectlite; direct/indirect interface flag lives in TFlag
Interface conversion: itabs, type switch and assertion caches●●●per-call-site caches in front of interface type switches/assertions; itabs generated via rttype
reflect implementation: performance, allocation and escape behaviour●●●●●●●●●●●reflect.Value is stack-allocatable, many accessors inlineable, method Values eagerly materialised
Register ABI completion for reflect, memmove/memclr and bytealg across architectures●●●register ABI unconditional on all ports; non-register fallback paths deleted per port
memmove / memclr / memequal / internal/bytealg assembly optimisation●●●●●●●●●●per-architecture hand tuning continuing; arm64 SIMD memmove landed then reverted in 1.28 cycle
Slice growth, string building and allocation-free bytes/strings helpers●●●●●●smoothed growth formula in nextslicecap, bytealg.MakeNoZero used by bytes/strings
Runtime randomness: fastrand, chacha8rand and math/rand/v2●●●●●internal/chacha8rand generator with SIMD block functions on amd64, arm64, loong64, riscv64
Concurrent hash-trie map (internal/sync.HashTrieMap)●●stable internal API used by unique (and later sync.Map)
iter.Pull and range-over-func iterator types●●●stable; documentation churn
Classic map maintenance and maps package helpers (pre-swiss)●●●●old implementation deleted in 1.26
Runtime: tracing, profiling, metrics and diagnostics (Go 1.18–1.28)
The new execution tracer (trace v2): generations, per-M buffers, new parser●●●●●●●●●●●default since 1.22 (experiment exectracer2 removed, v1 deleted in 1.23); trace format versions 1.22 → 1.23 → 1.25 → 1.26; flight recorder shipped in 1.25; ongoing hardening and perf work
Frame-pointer unwinding in tracing and profiling; profile stack depth●●●●●FP unwinding used by tracer, block and mutex profilers; stack depth 128 default (GODEBUG=profstackdepth); tracefpunwindoff documents which profilers it governs
Mutex and block profiles, including runtime-internal lock contention●●●●●●●runtime-internal lock contention reported in the mutex profile with sync.Mutex-like semantics (blame the unlocker); runtimecontentionstacks setting removed
Flight recorder and trace subscribers●●shipped in runtime/trace (1.25); in-band generation-end signal added 1.26
CPU profiling, goroutine profiling, pprof labels and the protobuf writer●●●●●●●●●●●maintenance; labels in tracebacks behind GODEBUG=tracebacklabels=1
Goroutine leak profile (GC-based leak detection)●●goroutineleak profile on by default; GOEXPERIMENT=goroutineleakprofile removed
runtime/metrics and MemStats●●●●●●●●~dozens of metrics; Read guaranteed not to stop the world (test)
Coverage redesign: runtime/coverage, internal/coverage, covdata●●●●●●default since 1.20; coverageredesign experiment removed (41298239cf, Jan 2025)
Race detector, ASan, MSan and Valgrind integration●●●●●●●●●●●race on linux/riscv64, loong64, s390x; asan/msan linux incl. loong64, riscv64, ppc64le; build-tag Valgrind support
Crash output, runtime/debug, BuildInfo and debuglog●●●●●●●debug.SetCrashOutput public; build info includes VCS and settings; debuglog compiled in tests
Runtime: OS and platform layer, stacks, panics and tracebacks (Go 1.18–1.28)
Defer, panic and recover re-implementation●●●●●●●●●●open-coded + linked defers share one state machine (_panic.nextDefer/nextFrame); recovery transfers to the PC of deferreturn; recover validity is decided by unwinding; still being tuned in 1.28 (linked-defer matching)
Unwinder: gentraceback → unwinder iterator, inline unwinder, pcvalue cache●●●●●unwinder (traceback.go) and inlineUnwinder are the only stack-walk implementations; gentraceback deleted in 1.21
Symbol tables, runtime.Caller and CallersFrames●●●●●●●_func entries are module-relative offsets, findfunc has a single-text-section fast path; documented Caller/Frames semantics
Frame pointers: explicit NOFRAME, FP maintenance and FP unwinding●●●●●all amd64 runtime assembly uses explicit NOFRAME; FP is saved/adjusted across stack copies, signals, cgo and injected calls; FP unwinding used by the tracer
Stack growth, stack bounds and the crash stack●●●●●●●"morestack on g0" prints a traceback on a dedicated crash stack on nearly every arch; stack guard tuned per OS/mode
C-to-Go callbacks: extra-M reuse, system-stack bounds, init gating●●●●●●●●●●●the M created for a C thread is cached in a pthread key until thread exit; g0 bounds re-estimated per callback; init check is an atomic bool
Library entry points and runtime initialization●●●●●●●c-shared/c-archive start-up is largely shared Go code; per-arch assembly reduced
Security hardening: AT_SECURE, std fds, AT_RANDOM, gated debug features●●●●●●isSecureMode/tainted-binary protections in place; page tracer behind GOEXPERIMENT; startup randomness overwritten
runtime/secret and data-independent timing (DIT)●●●●secret.Do implemented under GOEXPERIMENT guard; linux/amd64, arm64 and (1.28) loong64; goroutines spawned inside inherit secret state
vDSO, vgetrandom and fast clocks●●●●●●●●Linux getrandom through vDSO on all arches the kernel supports; per-M state pool
Signals and async-preemption machinery●●●●●●●●●●●signal handling uniform across Unix with libc sigaction under cgo on more arches; preemption saves AVX-512/SVE state
Syscall layer: AllThreadsSyscall, internal/runtime/syscall, libc and Windows SyscallN●●●●●●●●Linux raw syscalls live in internal/runtime/syscall/linux; Windows/darwin generic syscalln in the syscall package
Windows runtime port●●●●●●●●●●Windows 10 minimum, windows/arm removed, loader-provided TLS, high-resolution timers, SEH-aware crashing
New, ported and removed platforms●●●●●●●●●●added linux/loong64, freebsd/riscv64, openbsd/riscv64, openbsd/ppc64, wasip1/wasm; removed windows/arm, openbsd/mips64; linux/ppc64 moved to ELFv2
CPU feature detection, GOAMD64 checks and cpu GODEBUG options●●●●●●●●●●internal/cpu detects features for amd64 (AVX-512 family, SHA-NI), arm64 (SHA3/SHA512, LSE, DIT, SVE/SVE2, Neoverse IDs), riscv64 (extensions, VLENB, vector crypto, zbc), loong64 (HWCAP, LAMCAS); auxv exposed
Compiler frontend: the types2 type checker (Go 1.18–1.28)
Bringing up generics in types2 (type-parameter operands, core/structural types, tparam-as-interface)●●●●●●complete; core types no longer used by the checker (removed in 1.25), residual fixes only
Type sets, union terms, interfaces and constraint satisfaction●●●●●●●●stable; comparable satisfaction by non-type-parameter interfaces since 1.20
Instantiation, Named types, Context deduplication and lazy expansion●●●●●●●●●Named has an explicit state machine, fromRHS/underlying lifecycle enforced since 1.26
Type inference and unification●●●●●●●●●●new unifier-centred inference since 1.21; reverse inference, interface inference and untyped-constant defaulting shipped; assignment-context refinements in 1.27
Generic type aliases and Alias type nodes●●●●●Alias nodes always on (GODEBUG gotypesalias removed in 1.27); generic aliases enabled
Type declaration cycles, valid-type detection and the object path●●●●●●●validType uses a type nest; setDefType removed and replaced by "pending" checks in 1.26; finite-size check at value observation
Per-file language versions and version gating●●●●●●Info.FileVersions; version computed per file from //go:build lines
Language features as seen by the type checker (by release)●●●●●●●●●●generic methods (1.27) and string(int) restriction (1.28) are the latest; untyped composite literal inference in progress
Composite-literal type elision via target types (#12854)●●in progress; targets threaded through assignments, calls, struct literals, sends, switch, delete/append/copy and comparisons
Method receiver checking●●●●receiver handled in collectRecv (1.24 rewrite)
Error reporting: codes, messages, and sub-errors●●●●●●●●●●●compiler and go/types share messages and error codes (internal/types/errors)
Sharing code between go/types and types2●●●●●●most go/types files are generated from types2
Checker performance, memory and API ergonomics●●●●●ongoing micro-optimizations driven by gopls and compilebench
Robustness: invariants, incomplete types and importers●●●●invariant checker in tests; new types2 importer in progress
Compiler frontend: syntax, IR, unified IR and the generics implementation (Go 1.18–1.28)
Generics via GC-shape stenciling and runtime dictionaries●●●●●●●●shipped design since 1.18 (first built on the old typechecker/-G=3, reimplemented on unified IR in 1.20); shape sharing is still "underlying type, pointers collapsed", with occasional shape/reshape bug fixes through 1.27
Unified IR: one serialization for noding, stenciling, inlining and export●●●●●●●●●●●the only frontend since 1.21; internal/pkgbits + noder/{writer,reader,unified,linker}.go; UIR at version V4 (V5 method indices added in 1.28 dev), documented with a formal grammar in 1.25
Old typechecker and IR node-model cleanup●●●●●●●●●typecheck is a thin library (constant folding gone, Ntype gone, ir.CurFunc gone); types2 is the only checker; IR remains ir.Node with generated node_gen.go
RType/ITab fields and implicit conversions in IR (RTTI plumbing)●complete; every runtime-type-needing IR node carries its RType/ITab explicitly
Generic methods (type parameters on methods)●●language feature enabled (go1.27 language version); GOEXPERIMENT=genericmethods was added 2026-04-30, default flipped on, flag deleted 2026-06-12; UIR V4 plus V5 method-index fix
Static initialization and package init●●●●●●●●●staticinit with inline-aware static init (enabled in 1.21), outlined map init for deadcode, init splitting redone in 1.28 cycle
Compile-time performance, concurrency and the self-PGO'd compiler●●●●●●●●●●backend concurrency = GOMAXPROCS (normally capped at 4 by go build); compiler built with PGO from cmd/compile/default.pgo, refreshed about annually; startup heap boost 128 MiB
Compiler debugging infrastructure: bisect/hash debugging, flags, dumps●●●●●●●●-d flags with concurrency tagging, internal/bisect-based HashDebug, astdump HTML
Frontend support for new language features and spec changes●●●●●●●●●●●tracks the language; most features need a noder/typecheck/walk piece plus a types2 piece owned by the fe-types area
The syntax package (parser, scanner, tree)●●●●●●●●●stable; mostly error-message and parser-tolerance work
Package paths, -p, and build-system contract●●●-p required; symbols carry real package paths; export-data readiness signal to cmd/go since 1.28 dev
Types package internals: size, algorithm kind, TFlag, SIMD flags●●●●●types.Type computes layout, alg kind, pointer bytes and abi.TFlag once, lazily and side-effect-free
Method wrappers and promoted-method sharing●●●●●●wrappers for promoted methods shared across receiver types (1.28 cycle)
SIMD frontend: the "midway" source-to-source translator●●●prototype in the frontend, -d flag controlled
ir.StaticValue, ReassignOracle and function-variable tracking●●●batch oracle used by inliner/escape; ongoing migration of callers
Compiler: middle end and SSA optimization (Go 1.18–1.28)
Profile-guided optimization (PGO): hot-call inlining, devirtualization, profile preprocessing●●●●●●●on whenever a profile is supplied; drives inlining and both kinds of devirtualization; 1.28 also accepts Linux perf profiles
Inliner: budget, closures, and the interleaved inline/devirtualize driver●●●●●●●●●●●classic budget-80 inliner with closure, parameter-call and hot-path discounts; runs interleaved with devirtualization (inline/interleaved); functions calling recover became inlinable in 1.28
Escape analysis: call modelling, closures, func-variable callees, and solver speed●●●●●●●●●cmd/compile/internal/escape resolves calls through closures and func variables, has a heavily optimized solver, and owns go/defer wrapping; the zerocopy string→[]byte conversion is controlled by a debug flag
Allocation avoidance: stack-allocated slice backing stores and allocation-free literals●●●●●variable-size make and append use a 32-byte stack buffer when the slice does not escape; a move2heap slice pass handles slices that escape only at the end of their lifetime; runtimefreegc is off by default; bug fixing ongoing in 1.28
New inliner heuristics (GOEXPERIMENT=newinliner, inline/inlheur)●●●experiment exists, off by default, never enabled; gated by buildcfg.Experiment.NewInliner; only maintenance fixes since 1.22
Prove pass and bounds-check elimination: from poset relations to a dense limit table, topo-sorted walk, and division-aware proofs●●●●●●●●●●prove (ssa/prove.go, moved to ssacompile/prove in 1.28) keeps a per-value signed/unsigned limit table plus a relation poset; it walks blocks in topological order; divisibility and divmod rewriting run after it
Known-bits pass (bitwise constant folding)●●known bits pass in the default pipeline, run after prove and before late opt; ops are added incrementally
Memory-op optimization: memcombine, dead stores, store-to-load forwarding, alias analysis, mem2reg●●●●●●●●●memcombine, dse, dead auto elim and elim unread autos are in the default pipeline; type-based disjoint is used by CSE and DSE; mem2reg (1.28) handles single-block scalars only
Lowering of builtins to memory ops: memmove/memclr/memequal inlining and generated equality●●●●●●●●●●constant-size memmove/memclrNoHeapPointers become Move/Zero; runtime.memequal is the MemEq SSA op, expanded inline for small constant sizes; equality functions are generated per "signature" (1.27); preemptible memclr was reverted
Stack-slot merging (mergelocals)●●on by default when optimizing (since 1.23); address-use analysis tightened in 1.28
Switch lowering: jump tables, type-switch caches, and switch lookup tables●●●●●●●●●integer and string-length switches use jump tables (off under -N and retpolines); large type switches jump on type-hash bits behind per-site runtime caches; constant-returning switches become lookup tables (1.27)
Static devirtualization and shape-aware type-assertion pruning●●●●devirtualize.StaticCall uses a flow-insensitive concrete-type analysis that follows multiple assignments, assertions and conversions; impossible type assertions in shaped generic code are dropped
Loop variable per-iteration semantics (loopvar)●●●●per-iteration semantics for files at go1.22+; GOEXPERIMENT=loopvar and -d=loopvar remain for testing; cmd/compile/internal/loopvar does the rewrite
testing.B.Loop support in the compiler (bloop)●●●●●a bloop pass wraps assignments and call results inside for b.Loop() bodies in runtime.KeepAlive; inlining is no longer suppressed
Range-loop and range-over-func lowering in walk●●●●●●●slice/array range loops lower to an incremented element pointer guarded against past-the-end values; range-over-int and range-over-func are lowered; range-clear idioms become memclr
Sparse conditional constant propagation (sccp)●●●●sccp pass in the default pipeline; convergence sped up in 1.27
Loop-invariant code motion (licm)●●licm pass exists with an allow-list of liftable ops; a related "merge conditional branches" pass was disabled late in 1.27
Branch-free lowering: CondSelect-into-math and ARM64 CCMP●●●●●branchelim rewrites CondSelect into arithmetic on all arches; arm64 uses CCMP chains for logical AND conditions
Constant-folding loads from type metadata and dictionaries●●●●rewriteFixedLoad folds loads from read-only abi.Type, abi.PtrType, itab and dictionary symbols
SSA values for zero-sized and multi-field direct-interface types●●●●all zero-sized values are SSA-able; structs with one pointer field plus zero-sized fields are stored directly in interfaces
ARM64 load/store pairing (LDP/STP)●●●●SSA pair pass plus a post-genssa spill/reload fusing step
SSA package decomposition and compiler-infrastructure refactor●cmd/compile/internal/ssa split into subpackages (issue #80409), still in progress
Compiler backend: architectures, register allocation, ABI and assemblers (Go 1.18–1.28)
Register-based calling convention (ABIInternal) ports beyond amd64●●●●●●register ABI enabled on amd64, arm64, ppc64x, riscv64, loong64, s390x; 386, arm and mips still stack-based
Register allocator, scheduler and block-level backend passes●●●●●●●●●●ongoing tuning each cycle
amd64 code generation and GOAMD64 microarchitecture levels●●●●●●●●●●●GOAMD64=v1 default; v3 unlocks BMI1/BMI2/LZCNT/MOVBE/FMA codegen; constant churn of peephole rules
arm64 code generation and assembler●●●●●●●●●●●active; assembler gaining a table-driven SVE/ASIMD path; SVE under GOEXPERIMENT=simd
riscv64 compiler and assembler (RVA profiles, vector, compressed)●●●●●●●●●●●GORISCV64 rva20u64/rva22u64/rva23u64 profiles drive Zba/Zbb/Zbs/Zicond codegen; assembler supports V, crypto vector suites and compressed (RVC) emission
loong64 backend and assembler●●●●●●●●●●feature-complete port with LSX/LASX assembler coverage; very active
PPC64 / Power10 backend (GOPPC64, prefixed instructions, PC-relative code)●●●●●●●power8/9/10 levels; PC-relative (NOTOC) code on power10/linux
Duff's device replaced by generated loops; Zero/Move lowering●●●●●done for amd64, arm64, loong64, riscv64; runtime duff code removed for arm64, loong64, riscv64
Bounds-check calls: new "panicBounds" strategy●all architectures converted; old style removed
Late-lower pass, memory-op combining and arch-independent rule migration●●●●●●late lower on amd64, arm64, ppc64, riscv64; memcombine arch-independent
Stack slot merging, liveness and stack maps●●●●merge-locals on by default; analysis tightened in 1.28
Prologue, frame pointer, stack split and function alignment (cmd/internal/obj)●●●●●●per-arch; amd64 uses PUSH/POP BP and LEAVE
Jump tables for switch statements on more architectures●●●amd64, arm64, loong64, riscv64, mips64x, mipsx
Multi-word arithmetic, intrinsics and carry-chain support●●●●●●●Add64/Sub64/Mul64 intrinsics on all 64-bit ports; 32-bit support for Mul64 added in 1.26
Atomics and memory-ordering code generation●●●●●●intrinsics for sync/atomic And/Or across several ports
WebAssembly backend●●●●●●active small-scale improvements; vector ops landing with simd
s390x, MIPS, 386 and 32-bit ARM backends●●●●●●●maintenance; MIPS gets jump tables, s390x gets regabi
Backend hooks for GOEXPERIMENT=simd (amd64 AVX-512, arm64 SVE, wasm)●●●part of the simd area; backend plumbing only here
SSA package split into subpackages (issue #80409)●in progress
SIMD: the simd packages and their compiler support (Go 1.18–1.28)
Compiler SIMD type system, ABI and register-allocation support●●●SIMD types, vec/mask register classes, ABI passing, X15 zeroing, CPU-feature-aware block analysis and VEX encodings exist on master behind GOEXPERIMENT=simd (X15 whole-register zeroing is unconditional); RegMask widened beyond 64 bits for SVE predicates.
simdgen: the instruction-table-driven generator●●●lives in src/simd/archsimd/_gen (separate module) with simdgen, unify, tmplgen, wasmgen, midway, specgen, gentools; one go generate regenerates everything.
AMD64 archsimd API: AVX, AVX2 and AVX-512 operations●●●simd/archsimd provides 128/256/512-bit vectors on amd64 with operations that map to AVX/AVX2/AVX-512 instructions; experimental (GOEXPERIMENT=simd), not under Go 1 compatibility.
Mask representation, masked operations and merge peepholes●●●masks are opaque MaskNxM types in archsimd; amd64 uses K registers where AVX-512 is available and vector registers otherwise; arm64 SVE uses predicate registers; IfElse/Masked replace Merge.
Memory operands, constant-immediate forms and jump tables●●generated load-op and constant-load rules for AVX/AVX-512; broadcast and non-broadcast memory operands decoded from XED.
dev.simd branch, GOEXPERIMENT=simd lifecycle and merges to master●●●GOEXPERIMENT=simd exists in internal/goexperiment/flags.go, off by default in buildcfg; dev.simd reverse-merged to master repeatedly (development continues "only on dev.simd" and merges "when necessary").
Portable simd package and the "midway" source translator●●simd (vector-length-agnostic types Int8s..Float64s, Mask8s..Mask64s) exists behind GOEXPERIMENT=simd, implemented by rewriting user code in the compiler front end; the GODEBUG simd setting selects emulation and vector length.
ARM64 NEON archsimd●●128-bit NEON types and a large op set in ops_arm64.go; some constant shift ops postponed.
ARM64 SVE: scalable vectors and predicate masks●minimum-viable archsimd SVE types and a growing op set (types_sve.go, ops_sve.go); scalable vector length capped at 32 bytes in model, mask loads/stores removed.
WebAssembly SIMD●128-bit vectors on wasm in types_wasm.go/ops_wasm.go, with Wasm SSA ops, simdssa.go and rules.
Spec-driven API generation (internal/spec, specgen, specfill)●in progress; simd/internal/spec is an executable Go specification of all possible SIMD operations, with specgen, specls, refgen, specfill, specstats tools; plan tracked in SPEC-TRANSITION.md.
API shaping and renames before stabilisation●●●API still experimental; renames continue.
Emulation of missing instructions and test infrastructure●●●ops_emulated_.go per arch; generated test helpers.
Linker, object files and debug info (Go 1.18–1.28)
Relocation-free pclntab and funcdata (offsets instead of relocations)●●●●●done; pclntab has no relocations, lives read-only in .gopclntab together with funcdata and findfunctab; moduledata in its own section
Type, itab and typelink layout (.go.type section, relro rework)●●●●●type descriptors, itabs and GC masks have dedicated linker layout; typelinks and itablinks lists removed; alg/noalg descriptors deduplicated in 1.28 cycle
//go:linkname restrictions and the blocklist●●●●-checklinkname on by default; push-only linknames required for std symbols; blocklist extended each release
DWARF 5 migration●●enabled by default since the 1.25 cycle (ca19f987ca, 2024-12-19; experiment dwarf5 added bdb4676043); internal/buildcfg/exp.go keeps it off on macOS (dwarf5Supported)
DWARF quality for debuggers (types, variables, trampolines)●●●●●●●●●●ongoing, driven by Delve/gdb/lldb needs
Darwin split DWARF (dSYM)●default on Darwin
Nosplit stack checking and stack constants●●done
Dead code elimination and reflection-aware pruning●●●●done
Linker performance and memory●●●●●●incremental
Reproducible build IDs, buildinfo and symbol tables●●●●●GNU build ID and LC_UUID generated by default
FIPS 140 support in the linker●done
ELF/relro/hardening and external-link policy●●●●●●●
Per-platform object formats and internal linking (Mach-O, PE, XCOFF, wasm, ppc64, riscv64, loong64)●●●●●●●●●●●active