docs: record the deferred GOOBJ external-symbols decision
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
# 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:** deferred (v0.15.0, 2026-08-02). The GOOBJ emitter resolves only
|
||||
symbols defined in the file being assembled; a reference to any other symbol
|
||||
is rejected.
|
||||
|
||||
**Why it is deferred.** GOOBJ symbol references are *positional*: a
|
||||
reference is a `{PkgIdx, SymIdx}` pair, where `SymIdx` is the index of the
|
||||
symbol in the *referenced package's* symbol-definition table. That ordering
|
||||
is not derivable from the reference site — it lives in the referenced
|
||||
package's gc export data (the iexport binary format, which evolves with the
|
||||
toolchain). `cmd/asm` reads it with `cmd/internal` readers gasm cannot
|
||||
import, so emitting external references means either parsing export data
|
||||
ourselves or taking a dependency that does.
|
||||
|
||||
**What works today.** Single-package objects: every symbol the file defines
|
||||
(as `TEXT` or `GLOBL`, static or exported) and every reference to them.
|
||||
This covers the production use case — the go-flac / go-lz4 kernels carry no
|
||||
`FUNCDATA`/`PCDATA`, hence no references into `runtime`, and the Go side
|
||||
references the assembly symbols, never the reverse. Such a package builds
|
||||
with its assembly object replaced by a gasm-emitted one.
|
||||
|
||||
**The options, when we return.**
|
||||
|
||||
1. **`golang.org/x/tools/go/gcexportdata` as a production dependency.**
|
||||
The straightforward path: read each imported package's export file
|
||||
(paths from `-importcfg` or `go list -export`), assign symbol indices in
|
||||
its symbol order, write `PkgIndex`/`Autolib` entries (fingerprints from
|
||||
the export files' build IDs) and positional references. Robust across
|
||||
toolchain versions — `x/tools` tracks the format. **Cost:** the first
|
||||
production dependency beyond the standard library, an explicit deviation
|
||||
from the "production code depends only on the standard library"
|
||||
principle in the README. Requires the user's explicit agreement.
|
||||
2. **A minimal iexport parser of our own.** Preserves self-containment.
|
||||
Substantial effort and inherently fragile: the format is an internal
|
||||
contract that changes with Go releases, so the parser needs a
|
||||
version-gated fallback and regression tests against several toolchains.
|
||||
3. **Shell out to the toolchain for symbol metadata.** Consistent with the
|
||||
existing GOOBJ preamble probe (which already runs `go tool asm`), but no
|
||||
toolchain command exposes a package's symbols *in definition-index
|
||||
order* — `go tool nm` sorts differently — so this does not solve the
|
||||
core problem on its own; it would only feed option 1 or 2.
|
||||
|
||||
**Trigger to reopen.** An assembly file that needs a cross-package
|
||||
reference — in practice `FUNCDATA $…, runtime·…(SB)` (stack maps / GC
|
||||
metadata written in assembly), or any kernel that calls into another
|
||||
package directly. Until then, option 3's limitation is moot and the
|
||||
single-package emitter suffices.
|
||||
Reference in New Issue
Block a user