* remember to update the version in moon.mod when you edit this file


2026.8.24: v0.1.0
    finish x86-64 backend

2026.8.24: v0.2.0
    fix some bug and add some tests

2026.8.28: v0.3.0
    finish wasm backend

2026.9.5: v0.4.0
    finish risc-v64 backend
    
2026.9.5: v0.5.0
    finish wasm stack machine polish and docs

2026.9.13: v0.6.0
    finish loongarch64 (la64, LP64D) backend with data/float-pool emission
    add SSA interpreter (interp package) with builtin runtime and CLI --run
    fix rv64 port: isel write-back, comparison lowering, call cty return
    register encoding, conditional-branch fall-through semantics

2026.9.13: v0.7.0
    finish arm64 (AArch64, AAPCS64 ELF) backend: target constants, ABI
    lowering, instruction selection and GAS emission (emit_arm64)
    byte-exact vs vendor/qbe -t arm64: IR 5684/5684, asm 406/406
    add CLI -t arm64, compile_arm64/compile_arm64_debug API, snapshots and
    docs; make live/spill/rega target-aware (rglob, nrsave, retregs/argregs)


2026.9.19: v0.8.0
    refactor documents
    refactor repo package
    refactor float in backends

2026.9.19: v0.9.0
    rv64: emit data segments and floating-point constant pool byte-identical
    to vendor/qbe -t rv64; thread -G gas settings; unique cross-function labels
    compare.py: diff stderr for debug dumps (the old stdout compare was a no-op)
    debug dumps: drop the export keyword, canonical stage headers, fix phiins
    temp naming (Tmp.bid + single-definition early-out)
    parser errors: qbe:<file>:<line>: format, reference token names and messages
    add tools/check_rv64_asm.py independent RISC-V encodability gate

2026.9.20: v0.10.0
    align with the frozen vendor/qbe reference (ripe-lang master 661ceb2)
    debug dumps: port parse.c typecheck() (operand/jump/undefined-block checks,
    clsmerge); front-end flags now 406/406 on all three targets, differential
    matrix 99.7%
    port simpl.c blit expansion; add blit0/blit1 pseudo-ops, reqz/rnez; rv64
    vararg lowering, aggregate Cptr blobs, compare operand classes
    assembly: .text/.balign/endbr64+hint#34/.p2align/.type/.size/GNU-stack,
    leaf-function %rsp framing, reference fp-constant rodata layout, quoted
    local symbols; amd64 263/336, arm64 252/336, rv64 224/336 byte-identical

2026.9.24: v0.11.0
    complete byte-for-byte alignment with vendor/qbe (661ceb2) on amd64/arm64/rv64
    debug dumps: 12096/12096 (12 flags x 3 targets); emitted assembly:
    1008/1008 (336 compilable tests x 3 targets) byte-identical
    rega: live-out registers mapped before allocation; section-3 bshas guard
    amd64: xsel "mov" suffix, non-leaf frame parity, leaf epilogue addq,
    shift-argument fixarg; arm64: ctoa negated table, Cptr call cty bit;
    rv64: argsclass ngp check, fpstruct field classes, struct-return blobs,
    extension constant class, alloc slots grouped by alignment class
    loadopt: stable phi ordering; CI now gates every debug flag and assembly

2026.9.24: v0.12.0
    compare.py: reference and port now get their own flagsets; -G m maps to the
    matching Mach-O reference target (amd64_apple/arm64_apple) and is skipped
    for targets without one (the blanket amd64_apple mapping was wrong)
    amd64 Mach-O (-G m): byte-identical to vendor/qbe -t amd64_apple (336/336);
    no .type/.size/.note.GNU-stack, __TEXT literal sections, "_" data refs;
    CI gates it
    arm64 Mach-O: labels, sym@page/@pageoff, .balign 4, "_" prefixes and
    literal sections implemented; the Apple ABI (4-byte non-wide stack slots,
    apple_selvastart/apple_selvaarg/apple_extsb) is still pending, so arm64
    -G m is reported but not gated
    docs (en+zh): retract the previously unverified "406/406 (-G e and -G m)"
    
2026.9.24: v0.13.0
    arm64 Mach-O (-G m) now byte-identical to vendor/qbe -t arm64_apple
    (336/336; compare.py 406/406): ported the Apple ABI path -- 4-byte stack
    slots for non-wide scalars (T.apple && !KWIDE), arguments after the
    ellipsis forced to 8-byte stack slots, apple_selvastart/apple_selvaarg,
    no vararg register-save area/slot bias, and a true 16-byte stack align
    (the old stk + (stk & 15) only worked for 8-byte-aligned stacks);
    apple_extsb is a no-op here (no narrow parsb..paruh/argsb..arguh forms)
    CI now gates the Mach-O flavor on both amd64 and arm64

2026.9.25: v0.14.0
    programmatic QBE IL builder (ir_builder) + C ABI (ir_builder_capi,
    include/qbe_builder.h): build IL, print it back, emit arm64 asm / Mach-O
    object / JIT image; C demo (demo/12_builder_capi.c)
    Rust glue layer (rust/, crate qbe-builder) over the C ABI, with a
    Cranelift/inkwell-style API, including an in-memory JIT
    (qbe_jit_load/symbol/global/free; Module::jit / JitModule::get_fn)

2026.9.25: v0.15.0
    in-memory JIT resolves external symbols (libc printf/putchar/malloc/sqrt)
    with dlsym(RTLD_DEFAULT); far calls go through in-image veneers
    (adrp x16; add x16; br x16) and external data addresses are patched in
    place; --run-asm and the C-ABI/Rust JIT all use it
    binary/object/JIT string data now decodes assembler escapes (\n, \t, ...),
    so route B matches route A and demo 11 runs under the JIT

2026.9.25: v0.16.0
    arm64 JIT: external calls use 64-bit veneers (movz/movk x16 + br), removing
    the +/-4GB limit; host callbacks (qbe_jit_symbol_define / Rust
    jit_with_symbols) let JIT code call back into the host; external data
    adrp range is checked
    --run-asm dispatches on the function signature (0..8 integer or 0..8 float
    arguments, result printed by type)

2026.9.25: v0.17.0
    CLI split: --jit is the in-memory JIT (route B, no toolchain, resolves libc
    and host callbacks); --run-asm now assembles/links with clang and runs
    (route A); --clang only selects the clang backend for --emit obj

2026.9.25: v0.18.0
    split the arm64 runtime into three packages: native/ (OS primitives + C
    shim: mmap/mprotect, symbol lookup, temp files, process spawn, dynamic
    linking), jit/ (ExecBlock/JitModule), and run_asm/ (clang route A + wasm
    runner); no behaviour change, tests moved to the matching package

2026.9.25: v0.18.1
    condense the README into a features/status/roadmap list and drop the stale
    differential counters; fix the literal '{entry}' placeholder in the --jit
    argument-count error message

2026.9.25: v0.18.2
    docs: replace the stale 5684/5684 debug-dump counter (measured with 14
    flags) with flag-independent wording in doc/README, doc/guide, doc/abi_arm64
    and their zh versions; test/README: --asm covers 406/406, not 336/336

2026.9.25: v0.19.0
    debug info (line tables): implement the upstream `dbgfile "path"` and
    `dbgloc LINE[,COL]` IL statements; emit `.file <n> "path"` (dedup +
    numbering) and `.loc` in the amd64/arm64/rv64/la64 GAS backends. Output is
    byte-identical to vendor/qbe on every debug flag; `dbgloc` is a no-op for
    --jit/--run-asm/--emit obj/the interpreter. New test/dbg corpus, parser and
    util unit tests, doc/debug_info.md (+zh)

2026.9.25: v0.20.0
    debug info (CFI): new -g/--debug-info flag emits DWARF call-frame
    information for amd64 (push rbp/sub rsp/callee pushes, leave/add rsp) and
    arm64 (stp x29,x30 frame, mov x29,sp, x19..x28/d8..d15 saves), so the
    assembler produces .eh_frame/.debug_frame; off by default, so the plain
    output stays byte-identical to the reference; arm64/amd64 emitter tests
    and doc/debug_info.md (+zh) updated

2026.9.25: v0.21.0
    debug info (compilation unit): -g also emits a minimal DWARF5 CU
    (.debug_abbrev/.debug_info/.debug_addr) covering the module text; the CU's
    low/high PC use DW_FORM_addrx so .debug_info has no Mach-O relocations and
    the linker debug map relocates .debug_addr (same as clang). macOS lldb now
    sets source breakpoints and unwinds from assembly-only objects; ELF/arm64
    verified with llvm-dwarfdump --verify; off by default; docs (+zh) updated

2026.9.25: v0.21.1
    add scripts/run_dbg_demo.sh: emit -g arm64 assembly, link it, and assert
    that lldb sets a source breakpoint and unwinds; wired into the macOS CI job

2026.9.25: v0.21.2
    debug info: emit DWARF4 instead of DWARF5 for the compilation unit; Apple's
    lldb rejects version 5 (the macOS CI smoke test caught it). low/high PC are
    plain DW_FORM_addr values relocated by the linker debug map; .debug_addr is
    gone; verified with llvm-dwarfdump --verify on ELF and Mach-O

2026.9.25: v0.22.0
    debug info (variables and types): the programmatic builder can name a compile
    unit (set_dbg_compile_unit), attach source locations (dbg_loc) and declare
    variables with a language type (dbg_var, Cranelift-style value labels). -g
    then emits DW_TAG_subprogram/DW_TAG_variable and base/pointer/aggregate type
    DIEs plus a .debug_loc entry per variable (DW_OP_regx for a register,
    DW_OP_fbreg for a stack slot, resolved after regalloc). Exposed through the
    C ABI (qbe_dbg_enable/qbe_dbg_compile_unit/qbe_dbg_var/qbe_dbg_loc,
    qbe_emit_asm_gas) and the Rust crate (DebugType, declare_var,
    set_source_loc, emit_asm_with_gas). macOS lldb prints frame variables end to
    end; scripts/run_dbg_vars_demo.sh gates it in CI

2026.9.25: v0.22.1
    bootstrap.sh is now an interactive rustup-style installer: a colored
    numbered menu picks the MoonBit compiler (PATH / install / custom path),
    then it builds the native qbe binary and offers to install it to
    `/.local/bin and update the shell rc. Non-interactive flags: --moon,
    --bin-dir, --no-path, --yes; vendor/qbe is now behind --with-reference

2026.9.25: v0.22.2
    add scripts/bootstrap.ps1, the Windows PowerShell counterpart of
    bootstrap.sh: same rustup-style menu (-Moon/-InstallMoon/-SkipInstall),
    -Target native|wasm, and -BinDir/-NoPath PATH handling via the user
    environment; falls back to the default target when the POSIX-only native
    build is unavailable on Windows

2026.9.25: v0.22.3
    installer: use the current MoonBit installers. Unix/macOS now runs
    `curl -fsSL https://cli.moonbitlang.cn/install/unix.sh | bash` (the old
    https://moonbitlang.com/install.sh 404s, and the brew route is gone);
    Windows sets `Set-ExecutionPolicy RemoteSigned -Scope CurrentUser` and runs
    `irm https://cli.moonbitlang.cn/install/powershell.ps1 | iex`

2026.9.25: v0.23.0
    release audit: fixed broken relative links in
    doc/isel.md and the zh docs; the installers try the .cn mirror first and
    fall back to .com (GitHub runners cannot always reach .cn, so CI keeps
    .com); Windows uses Set-ExecutionPolicy RemoteSigned + the .cn
    powershell.ps1; filled in moon.mod repository/description/keywords; stopped
    tracking .idea/

2026.9.25: v0.23.1
    la64: emit GNU-as LoongArch that can actually be assembled. Fix the class
    suffix (add.d not add.l), module-global block labels (no duplicate .L1 /
    lost labels), aggregate ABI (size/dark guard, argument register assignment,
    Cfpint casts, Cptr blobs, return registers), fcmp.gt/ge via swapped
    lt/le, FPR-based ffint/ftintrz, constant materialization and reserved
    scratch registers; 338/338 reference-compilable tests now assemble
    wasm: emit validator-clean WAT. Unify the i64/i32 pointer model, add the
    missing extensions (extsw/extuw/extub/extuh), width-correct conversions
    and Cast reinterprets, aggregate-pointer arguments and returns, per-op
    store widths, external-function imports and fixed-arity call fixups;
    338/338 reference-compilable tests now validate
    add tools/check_la64_asm.py, tools/check_wasm.py and the unified
    tools/check_all_backends.py; CI now gates all five backends (previously
    la64 and wasm had no gate); refresh la64 snapshots and the docs


2026.9.25: v0.24.0
    variadic arguments across the whole tool: declare `...`, emit va_start /
    va_arg and call variadic functions from the MoonBit builder, the C ABI and
    Rust (Signature::variadic, call_vararg)
    parser: accept arguments after the ellipsis in a call (C parserefl)
    la64: port selvastart/selvaarg and the Params layout; lowering matches rv64
    rv64: pass arguments after `...` as if the float file were exhausted (Oargv)
    interpreter: materialise varargs in an 8-byte-slot buffer, execute
    va_start/va_arg
    wasm32: self-contained convention (caller-built buffer passed as a hidden
    trailing i64 parameter); external imports are keyed by call signature
    add tools/check_vararg_runtime.py (interp + wasm + la64 under qemu-user)
    and test/emit/016_vararg_after.ssa
    publish the Rust bindings to crates.io as `qopple` 0.24.0, with a companion
    `qopple-cli` subprocess wrapper; `qopple` ships prebuilt native archives for
    aarch64 macOS and x86_64/aarch64 Linux, so downstream builds need neither
    the MoonBit toolchain nor the repository; add .github/workflows/crates.yml

2026.9.30: v0.25.0
    Qopple C Compiler (qpcc) M0-M5: a C front end built on the programmatic
    QBE builder. preprocessor, globals, structs, char literals, the C11
    numeric type core (unsigned/short/long long/_Bool/float/double, casts),
    control flow (if/for/while/switch/goto/labels), enum and union, typedef
    and local aggregate initializers, _Alignof, _Static_assert/_Generic,
    indirect calls and function pointers, variadic calls; a clang oracle
    drives the tests

2026.9.30: v0.26.0
    qpcc front end: a full C11 (+ GNU extensions) lexer, AST and parser, C23
    syntax and -std=c11|c23 switching; a typed-AST semantic analyser (scopes,
    declarators, expression and statement checking, typeof, bitfield layout);
    source positions and statement locations

2026.10.1: v0.27.0
    qpcc codegen on the checked AST becomes the only compiler, and QPCC parses
    and compiles the original QBE C sources. aggregate/struct ABI: by-value
    struct parameters and sret returns; unique basic-block names; object
    relocations carry their addend

2026.10.1: v0.28.0
    qpcc A-series: variadic definitions, bitfield access, global aggregate and
    string initializers, computed goto and label addresses, sequentially
    consistent atomics, _Alignas, _Complex; parameter decay, linkage and GOT
    relocations; links the original QBE compiler

2026.10.2: v0.29.0
    self-host correctness: the optimizer and arm64 defects the QPCC-built qbe
    exposed -- gvn word-constant widening and phi dominance, store value class,
    arm64 imm12 lsl #12, large symbol offsets through a scratch, loadopt
    insertion order, salloc constant folding, spill merge() and register cost,
    arm64 copies to/from stack slots, printcon address offsets, dominators by
    RPO index; add examples/qpcc-selfhost/semantic-check.sh

2026.10.3: v0.30.0
    self-host complete: the QPCC-built qbe passes all 58 semantic-check
    fixtures. implicit function declarations use the standard register ABI;
    the mem/ssa UNDEF sentinel is distinct from the zero constant; the object
    emitter no longer maps the IP1 scratch twice; the QPCC CI job runs on
    macos-26; TODO.md records the remaining known issues

2026.10.3: v0.31.0
    QPCC gains C2y support, opt-in with -std=c2y: _Maxof/_Minof (N3628),
    _Countof (N3369), named loops (N3355: break/continue with a label, label
    chains naming one statement) and _Defer statements (TS 25755/N3590,
    cleanup semantics on every block exit); hand-written stddefer.h and
    stdcountof.h; the oracle grows to 144 fixtures
2026.10.3: v0.32.0
    QPCC gains _Tagged_union (a QPCC extension behind -f_tagged_union): the
    tag is optional (so typedef + anonymous works), a synthetic int sits at
    offset 0 with the members overlapping after it, _Tag_of/_Get_tag and
    designated initializers work, and a member cannot be assigned directly
    (change the value as a whole). Also fixes a comparison result-class bug
    that miscompiled float comparisons inside &&/|| (plain structs too), a
    put_int off-by-one that dropped the first byte of a static initializer,
    a cast fold that read a float constant bits as an integer, `auto` not
    being inferred in C2y, and _Defer bodies not walked for locals/labels.
    The oracle grows to 151 fixtures
