diff options
| author | Russ Cox <rsc@golang.org> | 2020-12-23 00:58:27 -0500 |
|---|---|---|
| committer | Russ Cox <rsc@golang.org> | 2020-12-23 06:39:36 +0000 |
| commit | 01fd2d05c8b7bfc083977ca73123a5541b289737 (patch) | |
| tree | c769857e30a859d3c511dd64db1af0b3016633d3 /src/cmd/compile/internal/dwarfgen/scope.go | |
| parent | 6c34d2f42077bd7757c942c8d1b466366190b45a (diff) | |
| download | go-git-01fd2d05c8b7bfc083977ca73123a5541b289737.tar.gz | |
[dev.regabi] cmd/compile: split out package dwarfgen [generated]
[git-generate]
cd src/cmd/compile/internal/gc
rf '
# Inline and remove ngotype.
ex {
import "cmd/compile/internal/ir"
import "cmd/compile/internal/reflectdata"
var n ir.Node
ngotype(n) -> reflectdata.TypeSym(n.Type())
}
rm ngotype
mv recordFlags RecordFlags
mv recordPackageName RecordPackageName
mv RecordFlags RecordPackageName dwarf.go
mv debuginfo Info
mv genAbstractFunc AbstractFunc
mv scope.go scope_test.go dwarf.go dwinl.go cmd/compile/internal/dwarfgen
'
Change-Id: I31fa982900dbba2066ca4c7a706af922e5481c70
Reviewed-on: https://go-review.googlesource.com/c/go/+/279477
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Diffstat (limited to 'src/cmd/compile/internal/dwarfgen/scope.go')
| -rw-r--r-- | src/cmd/compile/internal/dwarfgen/scope.go | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/dwarfgen/scope.go b/src/cmd/compile/internal/dwarfgen/scope.go new file mode 100644 index 0000000000..1c040edc28 --- /dev/null +++ b/src/cmd/compile/internal/dwarfgen/scope.go @@ -0,0 +1,112 @@ +// 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 dwarfgen + +import ( + "sort" + + "cmd/compile/internal/base" + "cmd/compile/internal/ir" + "cmd/internal/dwarf" + "cmd/internal/obj" + "cmd/internal/src" +) + +// See golang.org/issue/20390. +func xposBefore(p, q src.XPos) bool { + return base.Ctxt.PosTable.Pos(p).Before(base.Ctxt.PosTable.Pos(q)) +} + +func findScope(marks []ir.Mark, pos src.XPos) ir.ScopeID { + i := sort.Search(len(marks), func(i int) bool { + return xposBefore(pos, marks[i].Pos) + }) + if i == 0 { + return 0 + } + return marks[i-1].Scope +} + +func assembleScopes(fnsym *obj.LSym, fn *ir.Func, dwarfVars []*dwarf.Var, varScopes []ir.ScopeID) []dwarf.Scope { + // Initialize the DWARF scope tree based on lexical scopes. + dwarfScopes := make([]dwarf.Scope, 1+len(fn.Parents)) + for i, parent := range fn.Parents { + dwarfScopes[i+1].Parent = int32(parent) + } + + scopeVariables(dwarfVars, varScopes, dwarfScopes) + scopePCs(fnsym, fn.Marks, dwarfScopes) + return compactScopes(dwarfScopes) +} + +// scopeVariables assigns DWARF variable records to their scopes. +func scopeVariables(dwarfVars []*dwarf.Var, varScopes []ir.ScopeID, dwarfScopes []dwarf.Scope) { + sort.Stable(varsByScopeAndOffset{dwarfVars, varScopes}) + + i0 := 0 + for i := range dwarfVars { + if varScopes[i] == varScopes[i0] { + continue + } + dwarfScopes[varScopes[i0]].Vars = dwarfVars[i0:i] + i0 = i + } + if i0 < len(dwarfVars) { + dwarfScopes[varScopes[i0]].Vars = dwarfVars[i0:] + } +} + +// scopePCs assigns PC ranges to their scopes. +func scopePCs(fnsym *obj.LSym, marks []ir.Mark, dwarfScopes []dwarf.Scope) { + // If there aren't any child scopes (in particular, when scope + // tracking is disabled), we can skip a whole lot of work. + if len(marks) == 0 { + return + } + p0 := fnsym.Func().Text + scope := findScope(marks, p0.Pos) + for p := p0; p != nil; p = p.Link { + if p.Pos == p0.Pos { + continue + } + dwarfScopes[scope].AppendRange(dwarf.Range{Start: p0.Pc, End: p.Pc}) + p0 = p + scope = findScope(marks, p0.Pos) + } + if p0.Pc < fnsym.Size { + dwarfScopes[scope].AppendRange(dwarf.Range{Start: p0.Pc, End: fnsym.Size}) + } +} + +func compactScopes(dwarfScopes []dwarf.Scope) []dwarf.Scope { + // Reverse pass to propagate PC ranges to parent scopes. + for i := len(dwarfScopes) - 1; i > 0; i-- { + s := &dwarfScopes[i] + dwarfScopes[s.Parent].UnifyRanges(s) + } + + return dwarfScopes +} + +type varsByScopeAndOffset struct { + vars []*dwarf.Var + scopes []ir.ScopeID +} + +func (v varsByScopeAndOffset) Len() int { + return len(v.vars) +} + +func (v varsByScopeAndOffset) Less(i, j int) bool { + if v.scopes[i] != v.scopes[j] { + return v.scopes[i] < v.scopes[j] + } + return v.vars[i].StackOffset < v.vars[j].StackOffset +} + +func (v varsByScopeAndOffset) Swap(i, j int) { + v.vars[i], v.vars[j] = v.vars[j], v.vars[i] + v.scopes[i], v.scopes[j] = v.scopes[j], v.scopes[i] +} |
