aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/compile/internal/dwarfgen/dwarf.go3
-rw-r--r--src/cmd/compile/internal/ir/name.go1
-rw-r--r--src/cmd/compile/internal/noder/stencil.go18
-rw-r--r--src/cmd/internal/dwarf/dwarf.go67
-rw-r--r--src/cmd/link/internal/ld/dwarf_test.go84
5 files changed, 168 insertions, 5 deletions
diff --git a/src/cmd/compile/internal/dwarfgen/dwarf.go b/src/cmd/compile/internal/dwarfgen/dwarf.go
index 30472a9ebd..3007262db9 100644
--- a/src/cmd/compile/internal/dwarfgen/dwarf.go
+++ b/src/cmd/compile/internal/dwarfgen/dwarf.go
@@ -217,6 +217,7 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []*ir
DeclCol: declpos.RelCol(),
InlIndex: int32(inlIndex),
ChildIndex: -1,
+ DictIndex: n.DictIndex,
})
// Record go type of to insure that it gets emitted by the linker.
fnsym.Func().RecordAutoType(reflectdata.TypeLinksym(n.Type()))
@@ -374,6 +375,7 @@ func createSimpleVar(fnsym *obj.LSym, n *ir.Name) *dwarf.Var {
DeclCol: declpos.RelCol(),
InlIndex: int32(inlIndex),
ChildIndex: -1,
+ DictIndex: n.DictIndex,
}
}
@@ -478,6 +480,7 @@ func createComplexVar(fnsym *obj.LSym, fn *ir.Func, varID ssa.VarID) *dwarf.Var
DeclCol: declpos.RelCol(),
InlIndex: int32(inlIndex),
ChildIndex: -1,
+ DictIndex: n.DictIndex,
}
list := debug.LocationLists[varID]
if len(list) != 0 {
diff --git a/src/cmd/compile/internal/ir/name.go b/src/cmd/compile/internal/ir/name.go
index 9fb22378cd..dcfff7deba 100644
--- a/src/cmd/compile/internal/ir/name.go
+++ b/src/cmd/compile/internal/ir/name.go
@@ -40,6 +40,7 @@ type Name struct {
Class Class // uint8
pragma PragmaFlag // int16
flags bitset16
+ DictIndex uint16 // index of the dictionary entry describing the type of this variable declaration plus 1
sym *types.Sym
Func *Func // TODO(austin): nil for I.M, eqFor, hashfor, and hashmem
Offset_ int64
diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go
index 5069db9fe1..6c990c1828 100644
--- a/src/cmd/compile/internal/noder/stencil.go
+++ b/src/cmd/compile/internal/noder/stencil.go
@@ -779,6 +779,7 @@ func (subst *subster) localvar(name *ir.Name) *ir.Name {
m.Func = name.Func
subst.ts.Vars[name] = m
m.SetTypecheck(1)
+ m.DictIndex = name.DictIndex
if name.Defn != nil {
if name.Defn.Op() == ir.ONAME {
// This is a closure variable, so its Defn is the outer
@@ -1268,14 +1269,18 @@ func (subst *subster) node(n ir.Node) ir.Node {
// function info.gfInfo. This will indicate the dictionary entry with the
// correct concrete type for the associated instantiated function.
func findDictType(info *instInfo, t *types.Type) int {
- for i, dt := range info.gfInfo.tparams {
+ return info.gfInfo.findDictType(t)
+}
+
+func (gfInfo *gfInfo) findDictType(t *types.Type) int {
+ for i, dt := range gfInfo.tparams {
if dt == t {
return i
}
}
- for i, dt := range info.gfInfo.derivedTypes {
+ for i, dt := range gfInfo.derivedTypes {
if types.Identical(dt, t) {
- return i + len(info.gfInfo.tparams)
+ return i + len(gfInfo.tparams)
}
}
return -1
@@ -1736,6 +1741,7 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo {
for _, n := range gf.Dcl {
addType(&info, n, n.Type())
+ n.DictIndex = uint16(info.findDictType(n.Type()) + 1)
}
if infoPrintMode {
@@ -1805,9 +1811,13 @@ func (g *irgen) getGfInfo(gn *ir.Name) *gfInfo {
// Visit the closure body and add all relevant entries to the
// dictionary of the outer function (closure will just use
// the dictionary of the outer function).
- for _, n1 := range n.(*ir.ClosureExpr).Func.Body {
+ cfunc := n.(*ir.ClosureExpr).Func
+ for _, n1 := range cfunc.Body {
ir.Visit(n1, visitFunc)
}
+ for _, n := range cfunc.Dcl {
+ n.DictIndex = uint16(info.findDictType(n.Type()) + 1)
+ }
}
if n.Op() == ir.OSWITCH && n.(*ir.SwitchStmt).Tag != nil && n.(*ir.SwitchStmt).Tag.Op() == ir.OTYPESW && !n.(*ir.SwitchStmt).Tag.(*ir.TypeSwitchGuard).X.Type().IsEmptyInterface() {
for _, cc := range n.(*ir.SwitchStmt).Cases {
diff --git a/src/cmd/internal/dwarf/dwarf.go b/src/cmd/internal/dwarf/dwarf.go
index 69aafaf986..be37641706 100644
--- a/src/cmd/internal/dwarf/dwarf.go
+++ b/src/cmd/internal/dwarf/dwarf.go
@@ -50,6 +50,7 @@ type Var struct {
Abbrev int // Either DW_ABRV_AUTO[_LOCLIST] or DW_ABRV_PARAM[_LOCLIST]
IsReturnValue bool
IsInlFormal bool
+ DictIndex uint16 // index of the dictionary entry describing the type of this variable
StackOffset int32
// This package can't use the ssa package, so it can't mention ssa.FuncDebug,
// so indirect through a closure.
@@ -97,6 +98,8 @@ type FnState struct {
Scopes []Scope
InlCalls InlCalls
UseBASEntries bool
+
+ dictIndexToOffset []int64
}
func EnableLogging(doit bool) {
@@ -315,6 +318,7 @@ const (
DW_AT_go_runtime_type = 0x2904
DW_AT_go_package_name = 0x2905 // Attribute for DW_TAG_compile_unit
+ DW_AT_go_dict_index = 0x2906 // Attribute for DW_TAG_typedef_type, index of the dictionary entry describing the real type of this type shape
DW_AT_internal_location = 253 // params and locals; not emitted
)
@@ -362,6 +366,7 @@ const (
DW_ABRV_STRINGTYPE
DW_ABRV_STRUCTTYPE
DW_ABRV_TYPEDECL
+ DW_ABRV_DICT_INDEX
DW_NABRV
)
@@ -882,6 +887,17 @@ var abbrevs = [DW_NABRV]dwAbbrev{
{DW_AT_type, DW_FORM_ref_addr},
},
},
+
+ /* DICT_INDEX */
+ {
+ DW_TAG_typedef,
+ DW_CHILDREN_no,
+ []dwAttrForm{
+ {DW_AT_name, DW_FORM_string},
+ {DW_AT_type, DW_FORM_ref_addr},
+ {DW_AT_go_dict_index, DW_FORM_udata},
+ },
+ },
}
// GetAbbrev returns the contents of the .debug_abbrev section.
@@ -1196,6 +1212,9 @@ func putPrunedScopes(ctxt Context, s *FnState, fnabbrev int) error {
sort.Sort(byChildIndex(pruned.Vars))
scopes[k] = pruned
}
+
+ s.dictIndexToOffset = putparamtypes(ctxt, s, scopes, fnabbrev)
+
var encbuf [20]byte
if putscope(ctxt, s, scopes, 0, fnabbrev, encbuf[:0]) < int32(len(scopes)) {
return errors.New("multiple toplevel scopes")
@@ -1451,6 +1470,47 @@ func PutDefaultFunc(ctxt Context, s *FnState, isWrapper bool) error {
return nil
}
+// putparamtypes writes typedef DIEs for any parametric types that are used by this function.
+func putparamtypes(ctxt Context, s *FnState, scopes []Scope, fnabbrev int) []int64 {
+ if fnabbrev == DW_ABRV_FUNCTION_CONCRETE {
+ return nil
+ }
+
+ maxDictIndex := uint16(0)
+
+ for i := range scopes {
+ for _, v := range scopes[i].Vars {
+ if v.DictIndex > maxDictIndex {
+ maxDictIndex = v.DictIndex
+ }
+ }
+ }
+
+ if maxDictIndex == 0 {
+ return nil
+ }
+
+ dictIndexToOffset := make([]int64, maxDictIndex)
+
+ for i := range scopes {
+ for _, v := range scopes[i].Vars {
+ if v.DictIndex == 0 || dictIndexToOffset[v.DictIndex-1] != 0 {
+ continue
+ }
+
+ dictIndexToOffset[v.DictIndex-1] = ctxt.CurrentOffset(s.Info)
+
+ Uleb128put(ctxt, s.Info, int64(DW_ABRV_DICT_INDEX))
+ n := fmt.Sprintf(".param%d", v.DictIndex-1)
+ putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n)
+ putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
+ putattr(ctxt, s.Info, DW_ABRV_DICT_INDEX, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DictIndex-1), nil)
+ }
+ }
+
+ return dictIndexToOffset
+}
+
func putscope(ctxt Context, s *FnState, scopes []Scope, curscope int32, fnabbrev int, encbuf []byte) int32 {
if logDwarf {
@@ -1624,7 +1684,12 @@ func putvar(ctxt Context, s *FnState, v *Var, absfn Sym, fnabbrev, inlIndex int,
putattr(ctxt, s.Info, abbrev, DW_FORM_flag, DW_CLS_FLAG, isReturn, nil)
}
putattr(ctxt, s.Info, abbrev, DW_FORM_udata, DW_CLS_CONSTANT, int64(v.DeclLine), nil)
- putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
+ if v.DictIndex > 0 && s.dictIndexToOffset != nil && s.dictIndexToOffset[v.DictIndex-1] != 0 {
+ // If the type of this variable is parametric use the entry emitted by putparamtypes
+ putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, s.dictIndexToOffset[v.DictIndex-1], s.Info)
+ } else {
+ putattr(ctxt, s.Info, abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type)
+ }
}
if abbrevUsesLoclist(abbrev) {
diff --git a/src/cmd/link/internal/ld/dwarf_test.go b/src/cmd/link/internal/ld/dwarf_test.go
index 0aeaa7565c..3d112d97a4 100644
--- a/src/cmd/link/internal/ld/dwarf_test.go
+++ b/src/cmd/link/internal/ld/dwarf_test.go
@@ -11,6 +11,7 @@ import (
"debug/pe"
"errors"
"fmt"
+ "internal/buildcfg"
"internal/testenv"
"io"
"io/ioutil"
@@ -1746,3 +1747,86 @@ func main() {
expected, found)
}
}
+
+func TestDictIndex(t *testing.T) {
+ // Check that variables with a parametric type have a dictionary index attribute
+ testenv.MustHaveGoBuild(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 = `
+package main
+
+import "fmt"
+
+func testfn[T any](arg T) {
+ var mapvar = make(map[int]T)
+ mapvar[0] = arg
+ fmt.Println(arg, mapvar)
+}
+
+func main() {
+ testfn("test")
+}
+`
+
+ dir := t.TempDir()
+ f := gobuild(t, dir, prog, NoOpt)
+ defer f.Close()
+
+ d, err := f.DWARF()
+ if err != nil {
+ t.Fatalf("error reading DWARF: %v", err)
+ }
+
+ rdr := d.Reader()
+ found := false
+ for entry, err := rdr.Next(); entry != nil; entry, err = rdr.Next() {
+ if err != nil {
+ t.Fatalf("error reading DWARF: %v", err)
+ }
+ name, _ := entry.Val(dwarf.AttrName).(string)
+ if strings.HasPrefix(name, "main.testfn") {
+ found = true
+ break
+ }
+ }
+
+ if !found {
+ t.Fatalf("could not find main.testfn")
+ }
+
+ offs := []dwarf.Offset{}
+ for entry, err := rdr.Next(); entry != nil; entry, err = rdr.Next() {
+ if err != nil {
+ t.Fatalf("error reading DWARF: %v", err)
+ }
+ if entry.Tag == 0 {
+ break
+ }
+ name, _ := entry.Val(dwarf.AttrName).(string)
+ switch name {
+ case "arg", "mapvar":
+ offs = append(offs, entry.Val(dwarf.AttrType).(dwarf.Offset))
+ }
+ }
+ if len(offs) != 2 {
+ t.Errorf("wrong number of variables found in main.testfn %d", len(offs))
+ }
+ for _, off := range offs {
+ rdr.Seek(off)
+ entry, err := rdr.Next()
+ if err != nil {
+ t.Fatalf("error reading DWARF: %v", err)
+ }
+ if _, ok := entry.Val(intdwarf.DW_AT_go_dict_index).(int64); !ok {
+ t.Errorf("could not find DW_AT_go_dict_index attribute offset %#x (%T)", off, entry.Val(intdwarf.DW_AT_go_dict_index))
+ }
+ }
+}