Files
gasm-sdk/docs/DECISIONS.md
T
petrbalvin 56ad158772
Test / vet (push) Successful in 48s
Test / test (push) Successful in 2m35s
Test / build (push) Successful in 40s
fix: restore iota blocks, asm --format flag and prose after the syntax pass
2026-08-29 17:12:53 +02:00

3.2 KiB

Deferred decisions

Design decisions deliberately postponed, with enough context to pick them up again without re-deriving the analysis. Each entry records what is deferred, why, the options on the table, and the trigger that should reopen it.


GOOBJ external (cross-package) symbol references

Status: resolved (v0.29.0+, 2026-08-07).

Approach taken. Instead of parsing the compiler's iexport data (which would have required either golang.org/x/tools or an in-house parser), the resolver reads the GOOBJ data directly from the target package's .a archive. The .a file contains a _go_.o member whose GOOBJ s is the same one gasm writes — the parser reuses the same layout (blkSymdef, blkNonpkgdef, the string table), so no new dependency was needed.

How it works.

  1. go list -json -export <pkg> finds the target package's .a file.
  2. extractGOOBJ reads the ar archive, finds the _go_.o member, skips the "go object …\n!\n" preamble and parses the GOOBJ header.
  3. goobjFile.symbols() walks blkSymdef and blkNonpkgdef in definition order — the same order the linker uses — to build the symbol → index mapping.
  4. resolveExternalSymbols wires the resolved {PkgIdx, SymIdx} into the GOOBJ emission.

The resolver is invoked automatically when img.Externals is non-empty; it runs go list as a subprocess (consistent with toolchainObjectPreamble which already calls go tool asm). All symbol data is cached per package for the lifetime of the GOOBJ emission.

2026-08-29 tooling round

  • lint abi0-register-args: flags kernels whose // func parameters are never read from the FP frame. Motivated by a real latent bug: kernels reading arguments from registers pass every test while the autogenerated F.abi0 wrapper happens to leave the caller's register values intact, and break on a toolchain upgrade.
  • lint nonportable-register-name: the RAX/EAX register spellings are a gasm extension; go tool asm rejects them, so files using them only link through the gasm goobj path.
  • lint unencodable-instruction: a mnemonic in the architecture table that asm.Encodable rejects is flagged at edit time instead of failing at assembly time.
  • audit-instructions: black-box diff of the encoder against go tool asm. As of this round the tables fully overlap on names; the audit exists to catch drift in both directions (future supersets and future gaps).
  • scaffold differential: generates the direct-call differential skeleton (two independent seed sets, output and in-place buffer comparison) that a pipeline-level fuzz can never replace.
  • verify --args: scalar arguments for -call, closing the repro gap where only buffers could be supplied.
  • debug --script/--timeout/--cover: headless debugging with a watchdog armed before the ptrace attach (untracing sandboxes hang the attach), and label-level block coverage for the "did my test ever enter that branch" question.
  • Superset policy remains: gasm may accept spellings and encodings go tool asm lacks, but such kernels ship only via gasm asm --format goobj; the audit reports the superset surface. The register-alias superset is warned about by lint because the default go build path cannot consume it.