Summary
LLGo's existing DWARF generator recursively expands named pointer/typedef cycles until the host Go process overflows its stack. This becomes a broad native-build blocker whenever DWARF is enabled by default.
This was found while validating #2112 and must be fixed in a dedicated DWARF PR rather than in the pclntab packaging implementation.
Reproduction
Host: Darwin/arm64, Go 1.24.11, LLVM 19.
go test ./test/go -run '^TestRecursivePointerTypeBuilds$' -count=1 -v
The standalone probe contains recursive named pointer types such as:
type Link *Link
type Peano *Peano
The same failure class appeared in the default-DWARF CI run https://github.com/xgo-dev/llgo/actions/runs/29549966202 while compiling the standard recursive named-type case:
type recursiveNamedT18 *[10]recursiveNamedT19
type recursiveNamedT19 recursiveNamedT18
The host compiler repeatedly enters the aDIBuilder type-construction path and ends in a Go stack overflow. Both programs build and run when DWARF is omitted (-ldflags=-w).
Analysis
ssa/di.go currently checks b.types[t], calls createType, and only stores the returned DI node after createType finishes. A cycle such as named typedef → pointer/array → named typedef therefore re-enters diTypeEx before the first node is cached. This is a pclntab-independent DI construction bug; runtime line lookup is never reached.
The fix needs an in-progress placeholder/replaceable composite node inserted into the cache before descending. It should then complete or replace that node after members, pointees, and typedef underlyings are resolved. Merely adding the type to a visited set would avoid the stack overflow but leave references without valid DI metadata.
Expected behavior
DI type construction should memoize a placeholder before descending through recursive members/pointees, then complete the node after its dependencies are visited. Recursive legal Go types must never crash the compiler.
The eventual fix should add direct tests for:
- named pointer cycles (
Link, Peano);
- the
T18/T19 named pointer-array/typedef cycle;
- mutually recursive aggregate types;
- repeated references to an in-progress DI node.
Summary
LLGo's existing DWARF generator recursively expands named pointer/typedef cycles until the host Go process overflows its stack. This becomes a broad native-build blocker whenever DWARF is enabled by default.
This was found while validating #2112 and must be fixed in a dedicated DWARF PR rather than in the pclntab packaging implementation.
Reproduction
Host: Darwin/arm64, Go 1.24.11, LLVM 19.
The standalone probe contains recursive named pointer types such as:
The same failure class appeared in the default-DWARF CI run https://github.com/xgo-dev/llgo/actions/runs/29549966202 while compiling the standard recursive named-type case:
The host compiler repeatedly enters the
aDIBuildertype-construction path and ends in a Go stack overflow. Both programs build and run when DWARF is omitted (-ldflags=-w).Analysis
ssa/di.gocurrently checksb.types[t], callscreateType, and only stores the returned DI node aftercreateTypefinishes. A cycle such as named typedef → pointer/array → named typedef therefore re-entersdiTypeExbefore the first node is cached. This is a pclntab-independent DI construction bug; runtime line lookup is never reached.The fix needs an in-progress placeholder/replaceable composite node inserted into the cache before descending. It should then complete or replace that node after members, pointees, and typedef underlyings are resolved. Merely adding the type to a visited set would avoid the stack overflow but leave references without valid DI metadata.
Expected behavior
DI type construction should memoize a placeholder before descending through recursive members/pointees, then complete the node after its dependencies are visited. Recursive legal Go types must never crash the compiler.
The eventual fix should add direct tests for:
Link,Peano);T18/T19named pointer-array/typedef cycle;