builder,loader: fix -ldflags -X not overriding variables with default values

When a string variable already had a source-level default value, the -ldflags
"-X" flag was silently ignored and the variable remained the default value
at runtime.

Fix by stripping the InitOrder entry for each -X variable before
LoadSSA() is called. With no entry in InitOrder, go/ssa emits no init
store, so the global stays zero-valued in the IR. makeGlobalsModule
still injects the actual -X values at final link time.

The -X values remain out of the per-package build cache with only the
variable names appearing in the cache key.

Signed-off-by: deadprogram <ron@hybridgroup.com>
This commit is contained in:
deadprogram
2026-04-24 10:08:45 +02:00
committed by Ron Evans
parent 8793dc37fa
commit 1a1506ef79
6 changed files with 59 additions and 2 deletions
+23
View File
@@ -304,6 +304,29 @@ func (p *Program) Sorted() []*Package {
return p.sorted
}
// StripVarInitializer removes the package-level initializer for the named
// variable from the type info. This prevents go/ssa from emitting an init
// store for it, leaving the global zero-initialized in the IR. An external
// value (e.g. from -ldflags -X via makeGlobalsModule) can then be linked in
// at final link time without any runtime init overwriting it.
//
// Must be called after Parse() (typechecking populates InitOrder) and before
// LoadSSA() (which consumes InitOrder to build the package init function).
//
// Only 1:1 var initializers (var x = expr) are matched. Multi-variable
// initializers (var x, y = f()) are left untouched.
func (p *Package) StripVarInitializer(name string) {
n := 0
for _, init := range p.info.InitOrder {
if len(init.Lhs) == 1 && init.Lhs[0].Name() == name {
continue // drop this initializer
}
p.info.InitOrder[n] = init
n++
}
p.info.InitOrder = p.info.InitOrder[:n]
}
// MainPkg returns the last package in the Sorted() slice. This is the main
// package of the program.
func (p *Program) MainPkg() *Package {