github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/compile/internal/gc/scope.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package gc 6 7 import ( 8 "github.com/gagliardetto/golang-go/cmd/internal/dwarf" 9 "github.com/gagliardetto/golang-go/cmd/internal/obj" 10 "github.com/gagliardetto/golang-go/cmd/internal/src" 11 "sort" 12 ) 13 14 // See golang.org/issue/20390. 15 func xposBefore(p, q src.XPos) bool { 16 return Ctxt.PosTable.Pos(p).Before(Ctxt.PosTable.Pos(q)) 17 } 18 19 func findScope(marks []Mark, pos src.XPos) ScopeID { 20 i := sort.Search(len(marks), func(i int) bool { 21 return xposBefore(pos, marks[i].Pos) 22 }) 23 if i == 0 { 24 return 0 25 } 26 return marks[i-1].Scope 27 } 28 29 func assembleScopes(fnsym *obj.LSym, fn *Node, dwarfVars []*dwarf.Var, varScopes []ScopeID) []dwarf.Scope { 30 // Initialize the DWARF scope tree based on lexical scopes. 31 dwarfScopes := make([]dwarf.Scope, 1+len(fn.Func.Parents)) 32 for i, parent := range fn.Func.Parents { 33 dwarfScopes[i+1].Parent = int32(parent) 34 } 35 36 scopeVariables(dwarfVars, varScopes, dwarfScopes) 37 scopePCs(fnsym, fn.Func.Marks, dwarfScopes) 38 return compactScopes(dwarfScopes) 39 } 40 41 // scopeVariables assigns DWARF variable records to their scopes. 42 func scopeVariables(dwarfVars []*dwarf.Var, varScopes []ScopeID, dwarfScopes []dwarf.Scope) { 43 sort.Stable(varsByScopeAndOffset{dwarfVars, varScopes}) 44 45 i0 := 0 46 for i := range dwarfVars { 47 if varScopes[i] == varScopes[i0] { 48 continue 49 } 50 dwarfScopes[varScopes[i0]].Vars = dwarfVars[i0:i] 51 i0 = i 52 } 53 if i0 < len(dwarfVars) { 54 dwarfScopes[varScopes[i0]].Vars = dwarfVars[i0:] 55 } 56 } 57 58 // scopePCs assigns PC ranges to their scopes. 59 func scopePCs(fnsym *obj.LSym, marks []Mark, dwarfScopes []dwarf.Scope) { 60 // If there aren't any child scopes (in particular, when scope 61 // tracking is disabled), we can skip a whole lot of work. 62 if len(marks) == 0 { 63 return 64 } 65 p0 := fnsym.Func.Text 66 scope := findScope(marks, p0.Pos) 67 for p := fnsym.Func.Text; p != nil; p = p.Link { 68 if p.Pos == p0.Pos { 69 continue 70 } 71 dwarfScopes[scope].AppendRange(dwarf.Range{Start: p0.Pc, End: p.Pc}) 72 p0 = p 73 scope = findScope(marks, p0.Pos) 74 } 75 if p0.Pc < fnsym.Size { 76 dwarfScopes[scope].AppendRange(dwarf.Range{Start: p0.Pc, End: fnsym.Size}) 77 } 78 } 79 80 func compactScopes(dwarfScopes []dwarf.Scope) []dwarf.Scope { 81 // Reverse pass to propagate PC ranges to parent scopes. 82 for i := len(dwarfScopes) - 1; i > 0; i-- { 83 s := &dwarfScopes[i] 84 dwarfScopes[s.Parent].UnifyRanges(s) 85 } 86 87 return dwarfScopes 88 } 89 90 type varsByScopeAndOffset struct { 91 vars []*dwarf.Var 92 scopes []ScopeID 93 } 94 95 func (v varsByScopeAndOffset) Len() int { 96 return len(v.vars) 97 } 98 99 func (v varsByScopeAndOffset) Less(i, j int) bool { 100 if v.scopes[i] != v.scopes[j] { 101 return v.scopes[i] < v.scopes[j] 102 } 103 return v.vars[i].StackOffset < v.vars[j].StackOffset 104 } 105 106 func (v varsByScopeAndOffset) Swap(i, j int) { 107 v.vars[i], v.vars[j] = v.vars[j], v.vars[i] 108 v.scopes[i], v.scopes[j] = v.scopes[j], v.scopes[i] 109 }