diff options
| author | Josh Bleecher Snyder <josharian@gmail.com> | 2017-04-07 19:50:31 +0000 |
|---|---|---|
| committer | Josh Bleecher Snyder <josharian@gmail.com> | 2017-04-07 19:52:26 +0000 |
| commit | 3cf1ce40bde952c0ca0ac2af7737bfae5841f0c4 (patch) | |
| tree | eb4a5983beb577cf49316e84ab9245c7aa8fc7e3 /src/cmd/internal | |
| parent | c8b889cc4824f4dbd64a51a3f7b5b6dce4b87ed2 (diff) | |
| download | go-3cf1ce40bde952c0ca0ac2af7737bfae5841f0c4.tar.xz | |
Revert "cmd/compile: output DWARF lexical blocks for local variables"
This reverts commit c8b889cc4824f4dbd64a51a3f7b5b6dce4b87ed2.
Reason for revert: broke noopt build, compiler performance regression, new Curfn uses
Let's fix those and then try this again.
Change-Id: Icc3cad1365d04cac8fd09da9dbb0bbf55c13ef44
Reviewed-on: https://go-review.googlesource.com/39991
Reviewed-by: Robert Griesemer <gri@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Diffstat (limited to 'src/cmd/internal')
| -rw-r--r-- | src/cmd/internal/dwarf/dwarf.go | 177 | ||||
| -rw-r--r-- | src/cmd/internal/obj/data.go | 2 | ||||
| -rw-r--r-- | src/cmd/internal/obj/link.go | 3 | ||||
| -rw-r--r-- | src/cmd/internal/obj/objfile.go | 31 | ||||
| -rw-r--r-- | src/cmd/internal/src/scope.go | 36 |
5 files changed, 34 insertions, 215 deletions
diff --git a/src/cmd/internal/dwarf/dwarf.go b/src/cmd/internal/dwarf/dwarf.go index da419d8574..7625149914 100644 --- a/src/cmd/internal/dwarf/dwarf.go +++ b/src/cmd/internal/dwarf/dwarf.go @@ -8,20 +8,14 @@ package dwarf import ( - "cmd/internal/src" - "errors" "fmt" ) // InfoPrefix is the prefix for all the symbols containing DWARF info entries. const InfoPrefix = "go.info." -// RangePrefix is the prefix for all the symbols containing DWARF range lists. -const RangePrefix = "go.range." - // Sym represents a symbol. type Sym interface { - Len() int64 } // A Var represents a local variable or a function parameter. @@ -32,63 +26,6 @@ type Var struct { Type Sym } -// A Scope represents a lexical scope, all variables contained in a scope -// will only be visible to instructions covered by the scope. -// Lexical scopes are contiguous in source files but can end up being -// compiled to discontiguous blocks of instructions in the executable, the -// Ranges field lists all the blocks of instructions that belong in this -// scope. -type Scope struct { - src.Scope - Ranges []Range - Vars []*Var -} - -// A Range represents a half-open interval [Start, End). -type Range struct { - Start, End int64 -} - -// UnifyRanges merges the list of ranges of c into the list of ranges of s -func (s *Scope) UnifyRanges(c *Scope) { - out := make([]Range, 0, len(s.Ranges)+len(c.Ranges)) - - i, j := 0, 0 - for { - var cur Range - if i < len(s.Ranges) && j < len(c.Ranges) { - if s.Ranges[i].Start < c.Ranges[j].Start { - cur = s.Ranges[i] - i++ - } else { - cur = c.Ranges[j] - j++ - } - } else if i < len(s.Ranges) { - cur = s.Ranges[i] - i++ - } else if j < len(c.Ranges) { - cur = c.Ranges[j] - j++ - } else { - break - } - - if len(out) == 0 { - out = append(out, cur) - } else { - last := &out[len(out)-1] - if cur.Start > last.End { - out = append(out, cur) - } else if cur.End > last.End { - last.End = cur.End - } - } - } - - s.Ranges = out -} - // A Context specifies how to add data to a Sym. type Context interface { PtrSize() int @@ -216,8 +153,6 @@ const ( DW_ABRV_VARIABLE DW_ABRV_AUTO DW_ABRV_PARAM - DW_ABRV_LEXICAL_BLOCK_RANGES - DW_ABRV_LEXICAL_BLOCK_SIMPLE DW_ABRV_STRUCTFIELD DW_ABRV_FUNCTYPEPARAM DW_ABRV_DOTDOTDOT @@ -308,25 +243,6 @@ var abbrevs = [DW_NABRV]dwAbbrev{ }, }, - /* LEXICAL_BLOCK_RANGES */ - { - DW_TAG_lexical_block, - DW_CHILDREN_yes, - []dwAttrForm{ - {DW_AT_ranges, DW_FORM_data4}, // replace with DW_FORM_sec_offset in DWARFv4. - }, - }, - - /* LEXICAL_BLOCK_SIMPLE */ - { - DW_TAG_lexical_block, - DW_CHILDREN_yes, - []dwAttrForm{ - {DW_AT_low_pc, DW_FORM_addr}, - {DW_AT_high_pc, DW_FORM_addr}, - }, - }, - /* STRUCTFIELD */ { DW_TAG_member, @@ -604,8 +520,8 @@ func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, da ctxt.AddInt(s, 2, value) case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr - if cls == DW_CLS_PTR { // DW_AT_stmt_list and DW_AT_ranges - ctxt.AddSectionOffset(s, 4, data, value) + if cls == DW_CLS_PTR { // DW_AT_stmt_list + ctxt.AddSectionOffset(s, 4, data, 0) break } ctxt.AddInt(s, 4, value) @@ -634,13 +550,15 @@ func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, da ctxt.AddInt(s, 1, 0) } - // In DWARF 3 the ref_addr is always 32 bits, unless emitting a large + // In DWARF 2 (which is what we claim to generate), + // the ref_addr is the same size as a normal address. + // In DWARF 3 it is always 32 bits, unless emitting a large // (> 4 GB of debug info aka "64-bit") unit, which we don't implement. case DW_FORM_ref_addr: // reference to a DIE in the .info section if data == nil { return fmt.Errorf("dwarf: null reference in %d", abbrev) } else { - ctxt.AddSectionOffset(s, 4, data, 0) + ctxt.AddSectionOffset(s, ctxt.PtrSize(), data, 0) } case DW_FORM_ref1, // reference within the compilation unit @@ -683,7 +601,7 @@ func HasChildren(die *DWDie) bool { // PutFunc writes a DIE for a function to s. // It also writes child DIEs for each variable in vars. -func PutFunc(ctxt Context, s, ranges Sym, name string, external bool, startPC Sym, size int64, scopes []Scope) error { +func PutFunc(ctxt Context, s Sym, name string, external bool, startPC Sym, size int64, vars []*Var) { Uleb128put(ctxt, s, DW_ABRV_FUNCTION) putattr(ctxt, s, DW_ABRV_FUNCTION, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name) putattr(ctxt, s, DW_ABRV_FUNCTION, DW_FORM_addr, DW_CLS_ADDRESS, 0, startPC) @@ -693,72 +611,29 @@ func PutFunc(ctxt Context, s, ranges Sym, name string, external bool, startPC Sy ev = 1 } putattr(ctxt, s, DW_ABRV_FUNCTION, DW_FORM_flag, DW_CLS_FLAG, ev, 0) - if len(scopes) > 0 { - var encbuf [20]byte - if putscope(ctxt, s, ranges, startPC, 0, scopes, encbuf[:0]) < int32(len(scopes)) { - return errors.New("multiple toplevel scopes") - } - } - - Uleb128put(ctxt, s, 0) - return nil -} - -func putvar(ctxt Context, s Sym, v *Var, encbuf []byte) { - n := v.Name - - Uleb128put(ctxt, s, int64(v.Abbrev)) - putattr(ctxt, s, v.Abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n) - loc := append(encbuf[:0], DW_OP_call_frame_cfa) - if v.Offset != 0 { - loc = append(loc, DW_OP_consts) - loc = AppendSleb128(loc, int64(v.Offset)) - loc = append(loc, DW_OP_plus) - } - putattr(ctxt, s, v.Abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc) - putattr(ctxt, s, v.Abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) -} - -func putscope(ctxt Context, s, ranges Sym, startPC Sym, curscope int32, scopes []Scope, encbuf []byte) int32 { - for _, v := range scopes[curscope].Vars { - putvar(ctxt, s, v, encbuf) - } - this := curscope - curscope++ - for curscope < int32(len(scopes)) { - scope := scopes[curscope] - if scope.Parent != this { - return curscope - } - - emptyscope := len(scope.Vars) == 0 || len(scope.Ranges) == 0 - - if !emptyscope { - if len(scope.Ranges) == 1 { - Uleb128put(ctxt, s, DW_ABRV_LEXICAL_BLOCK_SIMPLE) - putattr(ctxt, s, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].Start, startPC) - putattr(ctxt, s, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].End, startPC) - } else { - Uleb128put(ctxt, s, DW_ABRV_LEXICAL_BLOCK_RANGES) - putattr(ctxt, s, DW_ABRV_LEXICAL_BLOCK_RANGES, DW_FORM_data4, DW_CLS_PTR, ranges.Len(), ranges) - ctxt.AddAddress(ranges, nil, -1) - ctxt.AddAddress(ranges, startPC, 0) - for _, pcrange := range scope.Ranges { - ctxt.AddAddress(ranges, nil, pcrange.Start) - ctxt.AddAddress(ranges, nil, pcrange.End) - } - ctxt.AddAddress(ranges, nil, 0) - ctxt.AddAddress(ranges, nil, 0) - } + names := make(map[string]bool) + var encbuf [20]byte + for _, v := range vars { + var n string + if names[v.Name] { + n = fmt.Sprintf("%s#%d", v.Name, len(names)) + } else { + n = v.Name } + names[n] = true - curscope = putscope(ctxt, s, ranges, startPC, curscope, scopes, encbuf) - - if !emptyscope { - Uleb128put(ctxt, s, 0) + Uleb128put(ctxt, s, int64(v.Abbrev)) + putattr(ctxt, s, v.Abbrev, DW_FORM_string, DW_CLS_STRING, int64(len(n)), n) + loc := append(encbuf[:0], DW_OP_call_frame_cfa) + if v.Offset != 0 { + loc = append(loc, DW_OP_consts) + loc = AppendSleb128(loc, int64(v.Offset)) + loc = append(loc, DW_OP_plus) } + putattr(ctxt, s, v.Abbrev, DW_FORM_block1, DW_CLS_BLOCK, int64(len(loc)), loc) + putattr(ctxt, s, v.Abbrev, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, v.Type) } - return curscope + Uleb128put(ctxt, s, 0) } // VarsByOffset attaches the methods of sort.Interface to []*Var, diff --git a/src/cmd/internal/obj/data.go b/src/cmd/internal/obj/data.go index 7a19e3a38c..114841dedb 100644 --- a/src/cmd/internal/obj/data.go +++ b/src/cmd/internal/obj/data.go @@ -114,7 +114,7 @@ func (s *LSym) WriteInt(ctxt *Link, off int64, siz int, i int64) { // WriteAddr writes an address of size siz into s at offset off. // rsym and roff specify the relocation for the address. func (s *LSym) WriteAddr(ctxt *Link, off int64, siz int, rsym *LSym, roff int64) { - if siz != ctxt.Arch.PtrSize && siz != 4 { + if siz != ctxt.Arch.PtrSize { ctxt.Diag("WriteAddr: bad address size %d in %s", siz, s.Name) } s.prepwrite(ctxt, off, siz) diff --git a/src/cmd/internal/obj/link.go b/src/cmd/internal/obj/link.go index e08d7a0340..fd07851f3b 100644 --- a/src/cmd/internal/obj/link.go +++ b/src/cmd/internal/obj/link.go @@ -483,7 +483,6 @@ const ( SHOSTOBJ SDWARFSECT SDWARFINFO - SDWARFRANGE SSUB = SymKind(1 << 8) SMASK = SymKind(SSUB - 1) SHIDDEN = SymKind(1 << 9) @@ -740,7 +739,7 @@ type Link struct { Armsize int32 Pc int64 DiagFunc func(string, ...interface{}) - DebugInfo func(fn *LSym, curfn interface{}) []dwarf.Scope // if non-nil, curfn is a *gc.Node + DebugInfo func(fn *LSym, curfn interface{}) []*dwarf.Var // if non-nil, curfn is a *gc.Node Cursym *LSym Version int Errors int diff --git a/src/cmd/internal/obj/objfile.go b/src/cmd/internal/obj/objfile.go index 314c7a9de6..6858143674 100644 --- a/src/cmd/internal/obj/objfile.go +++ b/src/cmd/internal/obj/objfile.go @@ -542,14 +542,10 @@ func (c dwCtxt) SymValue(s dwarf.Sym) int64 { return 0 } func (c dwCtxt) AddAddress(s dwarf.Sym, data interface{}, value int64) { + rsym := data.(*LSym) ls := s.(*LSym) size := c.PtrSize() - if data != nil { - rsym := data.(*LSym) - ls.WriteAddr(c.Link, ls.Size, size, rsym, value) - } else { - ls.WriteInt(c.Link, ls.Size, size, value) - } + ls.WriteAddr(c.Link, ls.Size, size, rsym, value) } func (c dwCtxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) { ls := s.(*LSym) @@ -559,10 +555,6 @@ func (c dwCtxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64 r.Type = R_DWARFREF } -func (s *LSym) Len() int64 { - return s.Size -} - // makeFuncDebugEntry makes a DWARF Debugging Information Entry // for TEXT symbol s. func makeFuncDebugEntry(ctxt *Link, curfn interface{}, s *LSym) { @@ -572,21 +564,10 @@ func makeFuncDebugEntry(ctxt *Link, curfn interface{}, s *LSym) { } dsym.Type = SDWARFINFO dsym.Set(AttrDuplicateOK, s.DuplicateOK()) - - drsym := ctxt.Lookup(dwarf.RangePrefix+s.Name, int(s.Version)) - if drsym.Size != 0 { - return - } - drsym.Type = SDWARFRANGE - drsym.Set(AttrDuplicateOK, s.DuplicateOK()) - - var scopes []dwarf.Scope + var vars []*dwarf.Var if ctxt.DebugInfo != nil { - scopes = ctxt.DebugInfo(s, curfn) - } - err := dwarf.PutFunc(dwCtxt{ctxt}, dsym, drsym, s.Name, s.Version == 0, s, s.Size, scopes) - if err != nil { - ctxt.Diag("emitting DWARF for %s failed: %v", s.Name, err) + vars = ctxt.DebugInfo(s, curfn) } - ctxt.Data = append(ctxt.Data, dsym, drsym) + dwarf.PutFunc(dwCtxt{ctxt}, dsym, s.Name, s.Version == 0, s, s.Size, vars) + ctxt.Data = append(ctxt.Data, dsym) } diff --git a/src/cmd/internal/src/scope.go b/src/cmd/internal/src/scope.go deleted file mode 100644 index d9ca1f5bfa..0000000000 --- a/src/cmd/internal/src/scope.go +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2017 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package src - -// Scope represents a lexical scope. -type Scope struct { - Start, End XPos - Parent int32 -} - -// Scopes represents a tree of lexical scopes -type Scopes struct { - Scopes []Scope // lexical scopes - curscope int32 // current scope index (during noding) -} - -// Open starts a new scope, scopes.Curscope is the parent. -func (scopes *Scopes) Open(posTable *PosTable, pos Pos) { - scope := Scope{Parent: scopes.curscope, Start: NoXPos, End: NoXPos} - if pos.IsKnown() { - scope.Start = posTable.XPos(pos) - } - scopes.Scopes = append(scopes.Scopes, scope) - scopes.curscope = int32(len(scopes.Scopes) - 1) -} - -// Close ends the current scope. -func (scopes *Scopes) Close(posTable *PosTable, pos Pos) { - scope := &scopes.Scopes[scopes.curscope] - if pos.IsKnown() { - scope.End = posTable.XPos(pos) - } - scopes.curscope = scope.Parent -} |
