Skip to content

cmd/compile: encode linkname pulls in LLVM symbol names - #131

Merged
zhouguangyuan0718 merged 1 commit into
go1.27.masterfrom
codex/runtime-llvm-lowering
Aug 14, 2026
Merged

cmd/compile: encode linkname pulls in LLVM symbol names#131
zhouguangyuan0718 merged 1 commit into
go1.27.masterfrom
codex/runtime-llvm-lowering

Conversation

@zhouguangyuan0718

@zhouguangyuan0718 zhouguangyuan0718 commented Aug 13, 2026

Copy link
Copy Markdown

This is 1/5 of the remaining runtime LLVM support stack after the runtime-lowering and builtin foundation merged in #136.

Stack: #136 (merged) -> this PR -> #132 -> #133 -> #134 -> #135.

This layer completes the Go producer side of the name-only GoObj reference contract already consumed by merged LLVM #79:

  • external source linkname pulls use the <linkname> LLVM declaration suffix
  • a one-time name+ABI definition set keeps local function and data pushes on canonical names
  • both ordinary linkname and standard-library linknamestd references are handled
  • builtin lookup takes precedence, so builtin and linkname encodings remain mutually exclusive
  • <ABI0> stays the outer ABI suffix
  • suffixed references do not receive ordinary imported-package symbol metadata
  • local linknamestd data definitions retain the standard-library authorization flag

The Go IR, SSA, AuxCall, and LSym models are unchanged; no linkname metadata table is added. This PR also does not reintroduce eager full-table builtin declarations, provisional any signatures, closure provenance checks, a second cgo parameter-home mechanism, or named-aggregate ABI reshaping.

Validation:

  • go test -tags="llvm23 dynamicllvm" cmd/internal/goobj cmd/compile/internal/ssa
  • raw and O2 LLVM FileCheck for external pulls, local definitions, and ABI0 wrappers
  • IR -> O2 -> llc -> GoObj smoke: the external symbol is a nonpackage_reference with linkname; local ABIInternal and ABI0 definitions remain canonical
  • full stacked joint make.bash and downstream focused tests

Supersedes only the linkname portion of #128 and the previous mixed implementation in this PR.

@zhouguangyuan0718
zhouguangyuan0718 force-pushed the codex/runtime-llvm-lowering branch 3 times, most recently from cd1444a to 315ad83 Compare August 14, 2026 08:23
zhouguangyuan0718 added a commit to goallc/llvm-project that referenced this pull request Aug 14, 2026
Go compiler-generated builtin references and source-level linkname pulls
can target the same canonical Go symbol while requiring different GoObj
reference identities. This change makes the LLVM symbol name the
complete reference contract:

- `<builtin.N>` identifies a GoObj builtin reference and embeds its
authoritative Go builtin index.
- `<linkname>` identifies a source linkname pull.
- `<ABI0>` remains an orthogonal, outer suffix.
- definitions keep their canonical names.
- malformed or conflicting suffix/metadata combinations fail closed.

GoObj strips the reference suffix, writes builtin references as
`PkgIdxBuiltin`, and writes linkname pulls as non-package references
with `SymFlagLinkname`. The standard-library bit is also carried through
`!goobj.config`, which is required for linker authorization of
`//go:linknamestd` pulls from LLVM-built runtime objects.

The latest commit completes the declaration-based contract for
machine-late helpers. X86 and AArch64 stack-growth/write-barrier
expansion locate the suffixed declaration already emitted by the Go
compiler and use that exact symbol. LLVM therefore has no duplicate Go
builtin table. Production Go IR fails closed when a required declaration
is missing; `-linkshared` deliberately falls back to the canonical name,
matching native Go's disabled builtin-index references.

The dependent Go change is goallc/go#131. It joins the existing GoObj
builtin list with the existing typed declarations generated by
`mkbuiltin`; it does not add another builtin definition list.

Validation:

- focused X86/AArch64 stack-growth and write-barrier lit tests: 5/5
passed, including `-linkshared` fallback
- broader Generic/X86/AArch64 Go and GoObj lit coverage: 60 passed, 1
unsupported; the only excluded failure is the pre-existing stale REP
expectation in `go-memset-inline.ll`
- Go compiler focused tests and 15 LLVM codegen fixtures passed with the
dependent Go change
- a full Go/LLVM joint `make.bash` completed on darwin/arm64
- runtime and its dependency closure compiled through LLVM, produced
GoObj/archive output, and reached final link; the remaining failure is
the independent `callRet` nosplit chain exceeding the 792-byte limit by
8 bytes
zhouguangyuan0718 added a commit that referenced this pull request Aug 14, 2026
## Summary

- carry the runtime-specific LLVM lowering needed to compile the runtime
package
- encode ordinary GoObj builtin references as `<builtin.N>` LLVM
declaration names, created lazily from each exact SSA/AuxCall signature
- generate the late-machine-helper classification from `mkbuiltin.go`
and eagerly retain only `gcWriteBarrier1..8` plus the three `morestack`
ABI0 declarations
- keep runtime implementations on their canonical names; ABI0 remains
the outer `<ABI0>` suffix
- remove the old `!goobj.builtin` reference metadata path and pin the
merged LLVM #79 release

This replaces the runtime-lowering and builtin portions of #131. The
remaining linkname naming contract stays in #131; eager declarations for
the full builtin table, provisional `any` signatures, and
named-aggregate call-boundary reshaping are deliberately outside this
PR.

Depends on goallc/llvm-project#79 and release
`goallc-llvm23.1.0-20260814T092516Z`
(`3710742685729c697378ab13a456484e5693aba9`).

## Validation

- `go test cmd/internal/goobj cmd/dist cmd/llvmtoolexec`
- `go test -tags="llvm23 dynamicllvm" cmd/compile/internal/ssa`
- all 130 LLVM codegen cases on darwin/arm64
- IR -> LLVM O2 -> GoObj -> link -> execute smoke test
- LLVM O2/GoObj archive generation for runtime and its exact 28-package
dependency closure
- generated `builtinlist.go` matches `mkbuiltin.go -stdout`

## Known independent follow-ups

- linking the fully LLVM-built runtime closure reaches the existing
`callRet: nosplit stack over 792 byte limit` by 8 bytes
- `runtime.test` additionally reaches the separate named-aggregate
`pageCache` / `PageCache` caller-boundary issue
@zhouguangyuan0718
zhouguangyuan0718 force-pushed the codex/runtime-llvm-lowering branch from 78de653 to 8ee583d Compare August 14, 2026 18:29
@zhouguangyuan0718 zhouguangyuan0718 changed the title cmd/compile: support runtime-specific LLVM lowering cmd/compile: encode linkname pulls in LLVM symbol names Aug 14, 2026
@zhouguangyuan0718
zhouguangyuan0718 merged commit e7c0f66 into go1.27.master Aug 14, 2026
4 of 6 checks passed
zhouguangyuan0718 added a commit that referenced this pull request Aug 15, 2026
This is 2/5 of the remaining runtime LLVM support stack. It depends on
the pure linkname contract in #131; the runtime-lowering and builtin
foundation is merged in #136.

Stack: #136 (merged) -> #131 -> this PR -> #133 -> #134 -> #135.

Keep named aggregate types in ABIInternal declarations and definitions.
When a caller and callee describe the same physical Go ABI carrier with
different nominal types, the caller rebuilds the value at the call
boundary. This includes compiler-generated runtime calls, promoted
method receivers, results, and open-defer result carriers.

The callee signature is recovered from the current-package definition;
the caller AuxCall remains authoritative for physical ABI assignment.
The differential ABI tests run the normal O2 pipeline before checking
fixed stack homes.

Focused unit and codegen tests cover named runtime aggregates,
caller-side carrier reshaping, promoted receivers, current-package
callee signatures, defined aggregate conversions, and named open-defer
results.

Rebased validation:

- joint `make.bash` with the LLVM #79 payload
- `cmd/compile/internal/ssa` unit tests
- LLVM ABI differential and `llvm_opendefer.go` codegen tests

Supersedes the named-ABI and promoted-receiver portions of #128.
zhouguangyuan0718 added a commit that referenced this pull request Aug 15, 2026
This is the traceback/inline layer of the remaining runtime LLVM
support. PR #132 is merged.

Stack: #136 (merged) -> #131 (merged) -> #132 (merged) -> this PR ->
#134 -> #135.

Preserve runtime traceback and defer semantics across LLVM optimization:

- record required frontend inline edges independently of surviving
instructions
- materialize machine-level inline anchors only when optimization
removed an edge
- attach the native function-end source position to the synthetic
deferreturn recovery call
- keep runtime.gorecover itself as a physical frame, while allowing its
direct callers to be represented by Go inline frames
- conservatively keep nosplit functions out of LLVM inlining so the
runtime callRet chain stays within the linker-enforced final GoObj stack
limit

The nosplit fence is intentionally temporary: native Go permits nosplit
inlining, and the linker checks the final PCSP tables and call
relocations. The source now carries a TODO to replace the blanket fence
with a targeted policy after the callRet frame growth is understood.

The debug fixture uses the final machine layout after LLVM #78,
including small-leaf stack-check elision.

Validation after rebasing onto b79bf4b:

- joint make.bash
- full cmd/compile/internal/ssa tests with LLVM enabled
- focused gorecover identity test
- 90/90 plugin CTest, including X86 and AArch64 debug-inline GoObj
checks
- open-defer codegen through LLVM O2, checking the recover caller
attribute group has no noinline
- recover1.go passed three consecutive LLVM O2 runs
- optimized IR confirms LLVM actually inlined direct recover callers and
retained their inlinedAt locations; direct, nested, recursive, and no-op
recover semantics still pass
- runtime and its 28 dependencies through LLVM O2 with test dependencies
native: runtime.test links successfully and the previous callRet nosplit
overflow is gone

Executing that runtime.test reaches a separate LLVM late stack-check
issue before test enumeration: runtime.tlsinit.abi0 receives a
stack-growth prologue although the native Go ABI0 wrapper does not. This
is after successful linking and is not a symbol-resolution or
inline-budget failure in this PR.

Supersedes the traceback/defer portion of #128.
zhouguangyuan0718 added a commit that referenced this pull request Aug 15, 2026
This is the entry-argument-map and stack-growth layer of the remaining
runtime LLVM support. PR #133 is merged.


Stack: #136 (merged) -> #131 (merged) -> #132 (merged) -> #133 (merged)
-> this PR -> #135.

Implement the final entry-map and stack-growth contract agreed with LLVM
#78:

- every GoObj Go function keeps entry ArgsPointerMaps map 0
- entry and entry-depth PCDATA_StackMapIndex ranges use the native -1
sentinel
- runtime stack-map lookup interprets that sentinel as entry map 0
- nosplit and systemstack are explicit function policies; the obsolete
stack-growth statepoint attribute is removed
- morestack remains a raw call, while LLVM decides from final frame size
and leafness whether a split prologue is needed
- GoObj derives entry map ranges from CFG state rather than a dedicated
morestack marker

The Machine StackMaps bridge remains Go-owned: `GoALLCStackMapPrinter`
distinguishes the function-entry `STACKMAP` from ordinary statepoint
records and passes their raw locations through `MCContext`; LLVM only
provides generic metadata-printer dispatch and final GoObj
serialization. Object-level `objview` checks cover entry PCDATA=-1,
entry ArgsPointerMaps map 0, ordinary statepoint map 1, returning to
entry depth, and the morestack map-0 path.

The pinned payload is `goallc-llvm23.1.0-20260815T055258Z`, revision
`ce1ede9c622755eeeb0ea695d5bffad3bac32dcc`, released after LLVM #81
merged.

Validation after rebasing onto #133 merge `24581b9a69`:

- coordinated Release+assertions X86/AArch64 LLVM build
- 42 focused LLVM GoObj CodeGen tests
- 91/91 plugin CTest with structured objview checks
- prior joint `make.bash` and linux amd64/arm64 CI on the fallback
payload
- full `cmd/compile/internal/ssa` tests with LLVM enabled
- ABI differential source and machine ArgsPointerMaps tests
- caller-state and nosplit GoObj tests
- statepoint codegen through LLVM O2

The stale LLVM `nowritebarrierrec` propagation test from the old stack
was removed: finalized-IR enforcement remains the existing explicit TODO
and is outside this entry-map PR.

Supersedes the entry-argmap and stack-growth portion of #128.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant