1
0
mirror of https://github.com/golang/go synced 2024-11-26 19:51:17 -07:00

cmd/compile: emit DIEs for zero sized variables

Fixes the compiler to emit DIEs for zero sized variables.

Fixes #54615

Change-Id: I1e0c86a97f1abcc7edae516b6a7fe35bcb65ed0f
Reviewed-on: https://go-review.googlesource.com/c/go/+/433479
Reviewed-by: Damien Neil <dneil@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Alessandro Arzilli <alessandro.arzilli@gmail.com>
Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
Alessandro Arzilli 2022-09-23 17:31:19 +02:00 committed by Than McIntosh
parent 77296e3645
commit e59d873ff9
4 changed files with 71 additions and 0 deletions

View File

@ -151,6 +151,21 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []*ir
} else { } else {
decls, vars, selected = createSimpleVars(fnsym, apDecls) decls, vars, selected = createSimpleVars(fnsym, apDecls)
} }
if fn.DebugInfo != nil {
// Recover zero sized variables eliminated by the stackframe pass
for _, n := range fn.DebugInfo.(*ssa.FuncDebug).OptDcl {
if n.Class != ir.PAUTO {
continue
}
types.CalcSize(n.Type())
if n.Type().Size() == 0 {
decls = append(decls, n)
vars = append(vars, createSimpleVar(fnsym, n))
vars[len(vars)-1].StackOffset = 0
fnsym.Func().RecordAutoType(reflectdata.TypeLinksym(n.Type()))
}
}
}
dcl := apDecls dcl := apDecls
if fnsym.WasInlined() { if fnsym.WasInlined() {

View File

@ -38,6 +38,8 @@ type FuncDebug struct {
// Register-resident output parameters for the function. This is filled in at // Register-resident output parameters for the function. This is filled in at
// SSA generation time. // SSA generation time.
RegOutputParams []*ir.Name RegOutputParams []*ir.Name
// Variable declarations that were removed during optimization
OptDcl []*ir.Name
// Filled in by the user. Translates Block and Value ID to PC. // Filled in by the user. Translates Block and Value ID to PC.
GetPC func(ID, ID) int64 GetPC func(ID, ID) int64

View File

@ -140,6 +140,7 @@ func (s *ssafn) AllocFrame(f *ssa.Func) {
continue continue
} }
if !n.Used() { if !n.Used() {
fn.DebugInfo.(*ssa.FuncDebug).OptDcl = fn.Dcl[i:]
fn.Dcl = fn.Dcl[:i] fn.Dcl = fn.Dcl[:i]
break break
} }

View File

@ -1917,3 +1917,56 @@ func main() {
t.Errorf("no LPT entries for test.go") t.Errorf("no LPT entries for test.go")
} }
} }
func TestZeroSizedVariable(t *testing.T) {
testenv.MustHaveGoBuild(t)
if runtime.GOOS == "plan9" {
t.Skip("skipping on plan9; no DWARF symbol table in executables")
}
t.Parallel()
// This test verifies that the compiler emits DIEs for zero sized variables
// (for example variables of type 'struct {}').
// See go.dev/issues/54615.
const prog = `
package main
import (
"fmt"
)
func main() {
zeroSizedVariable := struct{}{}
fmt.Println(zeroSizedVariable)
}
`
for _, opt := range []string{NoOpt, DefaultOpt} {
dir := t.TempDir()
f := gobuild(t, dir, prog, opt)
defer f.Close()
defer os.RemoveAll(dir)
d, err := f.DWARF()
if err != nil {
t.Fatalf("error reading DWARF: %v", err)
}
rdr := d.Reader()
ex := dwtest.Examiner{}
if err := ex.Populate(rdr); err != nil {
t.Fatalf("error reading DWARF: %v", err)
}
// Locate the main.zeroSizedVariable DIE
abcs := ex.Named("zeroSizedVariable")
if len(abcs) == 0 {
t.Fatalf("unable to locate DIE for zeroSizedVariable")
}
if len(abcs) != 1 {
t.Fatalf("more than one zeroSizedVariable DIE")
}
}
}