From 07cf24bdfe55dd3493e580c67b5437a114df7658 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Thu, 18 Aug 2022 03:53:58 -0700 Subject: [PATCH] cmd/compile/internal/noder: set ir.Name.DictIndex for unified IR For local variables of derived type, Delve relies on ir.Name.DictIndex being set to the type's rtype index within the function's dictionary. This CL implements that functionality within unified IR. Manually double checked that Delve behaves correctly, at least as far as I can tell from casual use. Specifically, I confirmed that running the test program from TestDictIndex, stepping into testfn, and then running `print mapvar` prints `map[int]main.CustomInt []`, which matches the behavior under GOEXPERIMENT=nounified. (Also compare that when ir.Name.DictIndex is *not* set by unified IR, `print mapvar` instead prints `map[int]go.shape.int []`.) Fixes #54514. Change-Id: I90d443945895abfba04dc018f15e00217930091c Reviewed-on: https://go-review.googlesource.com/c/go/+/424735 Reviewed-by: Cuong Manh Le Reviewed-by: Keith Randall Run-TryBot: Matthew Dempsky Reviewed-by: Keith Randall TryBot-Result: Gopher Robot --- src/cmd/compile/internal/noder/reader.go | 17 ++++++++++++---- src/cmd/compile/internal/noder/writer.go | 26 ++++++++++++++++-------- src/cmd/link/internal/ld/dwarf_test.go | 4 ---- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 9280232fc9..1acc8c7fb6 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -1490,7 +1490,7 @@ func (r *reader) addLocal(name *ir.Name, ctxt ir.Class) { if name.Sym().Name == dictParamName { r.dictParam = name } else { - if ctxt == ir.PAUTO { + if r.synthetic == nil { r.Sync(pkgbits.SyncAddLocal) if r.p.SyncMarkers() { want := r.Int() @@ -1498,12 +1498,10 @@ func (r *reader) addLocal(name *ir.Name, ctxt ir.Class) { base.FatalfAt(name.Pos(), "locals table has desynced") } } + r.varDictIndex(name) } r.locals = append(r.locals, name) - - // TODO(go.dev/issue/54514): Set name.DictIndex for variables of - // derived type and enable cmd/link/internal/ld.TestDictIndex. } name.SetUsed(true) @@ -3062,6 +3060,17 @@ func (r *reader) rtype0(pos src.XPos) (typ *types.Type, rtype ir.Node) { return } +// varDictIndex populates name.DictIndex if name is a derived type. +func (r *reader) varDictIndex(name *ir.Name) { + if r.Bool() { + idx := 1 + r.dict.rtypesOffset() + r.Len() + if int(uint16(idx)) != idx { + base.FatalfAt(name.Pos(), "DictIndex overflow for %v: %v", name, idx) + } + name.DictIndex = uint16(idx) + } +} + func (r *reader) itab(pos src.XPos) (typ *types.Type, typRType ir.Node, iface *types.Type, ifaceRType ir.Node, itab ir.Node) { if r.Bool() { // derived types idx := r.Len() diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index a90aec9fc8..6c2ef033f6 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -1090,20 +1090,19 @@ func (w *writer) funcargs(sig *types2.Signature) { func (w *writer) funcarg(param *types2.Var, result bool) { if param.Name() != "" || result { - w.addLocal(param, true) + w.addLocal(param) } } // addLocal records the declaration of a new local variable. -func (w *writer) addLocal(obj *types2.Var, isParam bool) { +func (w *writer) addLocal(obj *types2.Var) { idx := len(w.localsIdx) - if !isParam { - w.Sync(pkgbits.SyncAddLocal) - if w.p.SyncMarkers() { - w.Int(idx) - } + w.Sync(pkgbits.SyncAddLocal) + if w.p.SyncMarkers() { + w.Int(idx) } + w.varDictIndex(obj) if w.localsIdx == nil { w.localsIdx = make(map[*types2.Var]int) @@ -1295,7 +1294,7 @@ func (w *writer) assign(expr syntax.Expr) { // TODO(mdempsky): Minimize locals index size by deferring // this until the variables actually come into scope. - w.addLocal(obj, false) + w.addLocal(obj) return } } @@ -1558,7 +1557,7 @@ func (w *writer) switchStmt(stmt *syntax.SwitchStmt) { obj := obj.(*types2.Var) w.typ(obj.Type()) - w.addLocal(obj, false) + w.addLocal(obj) } w.stmts(clause.Body) @@ -2177,6 +2176,15 @@ func (w *writer) rtype(typ types2.Type) { } } +// varDictIndex writes out information for populating DictIndex for +// the ir.Name that will represent obj. +func (w *writer) varDictIndex(obj *types2.Var) { + info := w.p.typIdx(obj.Type(), w.dict) + if w.Bool(info.derived) { + w.Len(w.dict.rtypeIdx(info)) + } +} + func isUntyped(typ types2.Type) bool { basic, ok := typ.(*types2.Basic) return ok && basic.Info()&types2.IsUntyped != 0 diff --git a/src/cmd/link/internal/ld/dwarf_test.go b/src/cmd/link/internal/ld/dwarf_test.go index 4ac3dbdcfd..4b50371161 100644 --- a/src/cmd/link/internal/ld/dwarf_test.go +++ b/src/cmd/link/internal/ld/dwarf_test.go @@ -11,7 +11,6 @@ import ( "debug/dwarf" "debug/pe" "fmt" - "internal/buildcfg" "internal/testenv" "io" "io/ioutil" @@ -1597,9 +1596,6 @@ func TestDictIndex(t *testing.T) { if runtime.GOOS == "plan9" { t.Skip("skipping on plan9; no DWARF symbol table in executables") } - if buildcfg.Experiment.Unified { - t.Skip("GOEXPERIMENT=unified does not emit dictionaries yet") - } t.Parallel() const prog = `