]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: emit DIEs for zero sized variables
authorAlessandro Arzilli <alessandro.arzilli@gmail.com>
Fri, 23 Sep 2022 15:31:19 +0000 (17:31 +0200)
committerThan McIntosh <thanm@google.com>
Fri, 28 Oct 2022 17:49:22 +0000 (17:49 +0000)
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>
src/cmd/compile/internal/dwarfgen/dwarf.go
src/cmd/compile/internal/ssa/debug.go
src/cmd/compile/internal/ssagen/pgen.go
src/cmd/link/internal/ld/dwarf_test.go

index 179152f5bfa96bc1760c817256a8d19f9778007d..90c331f0b6ed087709a69de54366c6d74f02a616 100644 (file)
@@ -151,6 +151,21 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []*ir
        } else {
                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
        if fnsym.WasInlined() {
index 3eaba3a2385abd87481457a5d8cf4861144c4b62..584aaef3bf1df6519de48bc1af7e5303c2730fc0 100644 (file)
@@ -38,6 +38,8 @@ type FuncDebug struct {
        // Register-resident output parameters for the function. This is filled in at
        // SSA generation time.
        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.
        GetPC func(ID, ID) int64
index 7e7c13adc97eb00de9f9548e1029ea7ff22ad2a5..6b29e8369722a5d8549dc625ac2baa883daff69e 100644 (file)
@@ -140,6 +140,7 @@ func (s *ssafn) AllocFrame(f *ssa.Func) {
                        continue
                }
                if !n.Used() {
+                       fn.DebugInfo.(*ssa.FuncDebug).OptDcl = fn.Dcl[i:]
                        fn.Dcl = fn.Dcl[:i]
                        break
                }
index 65f82d9d78c37a8a4bd246aafbdf45fe008a6ef8..3132e1233cd751ec636a86a6ebeeea6032b9703a 100644 (file)
@@ -1917,3 +1917,56 @@ func main() {
                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")
+               }
+       }
+}