diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml index 10e5cc4..01d9cf4 100644 --- a/.gitea/workflows/test.yml +++ b/.gitea/workflows/test.yml @@ -79,9 +79,16 @@ jobs: # hanging test reports its own goroutine dump rather than a silent job kill. # The pattern is `packages` in the project's justfile: the logic packages, since a # thin cmd/ would drag the total under the floor. release.yml runs the same - # command, so the floor is the same number everywhere. + # command, so the floor is the same number everywhere. ./verify/... carries the + # live oracle-parity comparison against `go tool asm` (the TestGroundTruth + # suites); the runner's Go setup provides both the tool and GOROOT. run: go test -count=1 -timeout 10m -coverprofile=coverage.out ./arch/... ./asm/... ./ast/... ./disasm/... ./format/... ./lexer/... ./lint/... ./lsp/... ./parser/... ./token/... ./verify/... + - name: Oracle parity + # Re-run the live go-tool-asm comparison as its own step so that a parity + # regression names the gate that failed instead of hiding inside the suite. + run: go test -count=1 -timeout 10m -run 'TestGroundTruth' ./verify/... + - name: Coverage floor run: | perl -e ' diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f1872c..83fe3bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,40 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [development] +### Added + +- **Indirect JMP and CALL on all four architectures.** `JMP AX`, + `CALL AX`, `JMP (BX)` and the memory forms encode at byte parity with + the toolchain (FF /2 and FF /4 on amd64); arm64 lowers `JMP (R0)` to + BR and accepts the raw BR/BLR spellings; riscv64 lowers `JMP (X5)` to + JALR; loong64 accepts the raw `JIRL rd, rj, off` spelling the Go + assembler cannot express. A frameless amd64 function containing a + CALL now receives the toolchain's forced base-pointer frame. The + verify trampolines join the ground-truth lists, and a lint check for + control flow through registers and memory extends to the new forms. +- **`gasm asm -GOARCH` and `gasm diff -GOARCH`.** The target + architecture can be named explicitly instead of inferred from the + file-name suffix, which is how the suffix-less majority of GOROOT's + `.s` files (cpu_x86.s, stub.s, ...) become assemblable. +- **`gasm audit-instructions --corpus [dir]`.** Assembles every `.s` + file under a directory (default GOROOT/src) with the gasm encoder + only: suffixed files for their architecture, suffix-less files for + all four, as a GOARCH build would. Reports the headline number (108 + of 627 GOROOT files, 17.2 %, assemble for every target architecture + today; the pre-0.34 baseline was 23), the per-architecture pass rates + and the most common failure reasons with a representative file each, + which drive the encodability backlog by frequency. +- **Fuzz targets for the parser and the formatter.** FuzzParse (no + panic, always a usable file) and FuzzFormatIdempotency (formatting + twice equals formatting once; clean input stays clean) seed + themselves from the repository's kernels, so the plain test suite + replays every seed in CI and `just fuzz` runs the mutation engine on + demand. The first sessions found and fixed eight formatter and + lexer defects. +- **Oracle parity as its own CI step.** The push pipeline already ran + the live go-tool-asm comparison inside the suite; a dedicated step + now names that gate when it fails. + ### Changed - **Canonical just recipes.** `just gates` is the definition of done @@ -58,6 +92,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 `docs/ARCHITECTURE.md` said otherwise. - **The CLI reference listed 17 of the 18 lint rules.** The missing `reserved-register-write` is documented with the rest. +- **riscv64 JALR silently jumped to the wrong register.** The trampoline + form `JALR X0, 0(X5)` read the memory operand's base as the destination, + encoding a jump to X0 with no diagnostic; the destination is the first + operand. The leaf detection shared the confusion, so affected functions + also grew a bogus prologue. `JALR X0, 0(X1)` as written in the verify + trampoline was mis-encoded since its introduction. +- **DATA lines demanded their GLOBL first.** collectData processed the + declarations in file order, but the Plan 9 convention puts every DATA + line before its symbol's GLOBL; correctly ordered files (most of + GOROOT's) failed with "no matching GLOBL". Two passes: symbols are + registered before initialisers are applied. +- **The formatter lost idempotency on degenerate lines.** Found by the + new fuzz target: illegal tokens survived into the output, a label + sharing its line with a non-instruction split into a line the parser + rejects, stray-operand lines entered the alignment width computation, + and rendered `/ *`, `> >` sequences re-lexed as comments and shifts. + The label, width and spacing rules now agree between passes. ## [0.33.0] - 2026-09-14 diff --git a/README.md b/README.md index f1f7b0e..a35eff8 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,11 @@ every mnemonic the real assembler accepts is recognised; what the encoder can emit today is narrower, and a recognised but unencodable instruction is reported as an explicit error, never as a wrong byte. +The same measurement runs over GOROOT's whole assembly corpus: +`gasm audit-instructions --corpus` reports 108 of 627 files (17.2 %) +assembling for every target architecture today, with the top failure +reasons per architecture; the number moves with every release. + ## Direction The plan, in the order it is being worked: