pragcgobuf string
err chan syntax.Error
scope ScopeID
+
+ // scopeVars is a stack tracking the number of variables declared in the
+ // current function at the moment each open scope was opened.
+ scopeVars []int
+
+ lastCloseScopePos syntax.Pos
}
func (p *noder) funchdr(n *Node) ScopeID {
if trackScopes {
Curfn.Func.Parents = append(Curfn.Func.Parents, p.scope)
+ p.scopeVars = append(p.scopeVars, len(Curfn.Func.Dcl))
p.scope = ScopeID(len(Curfn.Func.Parents))
p.markScope(pos)
}
func (p *noder) closeScope(pos syntax.Pos) {
+ p.lastCloseScopePos = pos
types.Popdcl()
if trackScopes {
+ scopeVars := p.scopeVars[len(p.scopeVars)-1]
+ p.scopeVars = p.scopeVars[:len(p.scopeVars)-1]
+ if scopeVars == len(Curfn.Func.Dcl) {
+ // no variables were declared in this scope, so we can retract it.
+
+ if int(p.scope) != len(Curfn.Func.Parents) {
+ Fatalf("scope tracking inconsistency, no variables declared but scopes were not retracted")
+ }
+
+ p.scope = Curfn.Func.Parents[p.scope-1]
+ Curfn.Func.Parents = Curfn.Func.Parents[:len(Curfn.Func.Parents)-1]
+
+ nmarks := len(Curfn.Func.Marks)
+ Curfn.Func.Marks[nmarks-1].Scope = p.scope
+ prevScope := ScopeID(0)
+ if nmarks >= 2 {
+ prevScope = Curfn.Func.Marks[nmarks-2].Scope
+ }
+ if Curfn.Func.Marks[nmarks-1].Scope == prevScope {
+ Curfn.Func.Marks = Curfn.Func.Marks[:nmarks-1]
+ }
+ return
+ }
+
p.scope = Curfn.Func.Parents[p.scope-1]
p.markScope(pos)
// "if" statements, as their implicit blocks always end at the same
// position as an explicit block.
func (p *noder) closeAnotherScope() {
- types.Popdcl()
-
- if trackScopes {
- p.scope = Curfn.Func.Parents[p.scope-1]
- Curfn.Func.Marks[len(Curfn.Func.Marks)-1].Scope = p.scope
- }
+ p.closeScope(p.lastCloseScopePos)
}
// linkname records a //go:linkname directive.
pcs = append(pcs, scopedPCs{start: p0.Pc, end: fnsym.Size, pos: p0.Pos})
}
- // Sort PCs by source position, and walk in parallel with
- // scope marks to assign a lexical scope to each PC interval.
- sort.Sort(pcsByPos(pcs))
- var marki int
- var scope ScopeID
+ // Assign scopes to each chunk of instructions.
for i := range pcs {
- for marki < len(marks) && !xposBefore(pcs[i].pos, marks[marki].Pos) {
- scope = marks[marki].Scope
- marki++
- }
- pcs[i].scope = scope
+ pcs[i].scope = findScope(marks, pcs[i].pos)
}
- // Re-sort to create sorted PC ranges for each DWARF scope.
- sort.Sort(pcsByPC(pcs))
+ // Create sorted PC ranges for each DWARF scope.
for _, pc := range pcs {
r := &dwarfScopes[pc.scope].Ranges
if i := len(*r); i > 0 && (*r)[i-1].End == pc.start {
}
func compactScopes(dwarfScopes []dwarf.Scope) []dwarf.Scope {
- // Forward pass to collapse empty scopes into parents.
- remap := make([]int32, len(dwarfScopes))
- j := int32(1)
- for i := 1; i < len(dwarfScopes); i++ {
- s := &dwarfScopes[i]
- s.Parent = remap[s.Parent]
- if len(s.Vars) == 0 {
- dwarfScopes[s.Parent].UnifyRanges(s)
- remap[i] = s.Parent
- continue
- }
- remap[i] = j
- dwarfScopes[j] = *s
- j++
- }
- dwarfScopes = dwarfScopes[:j]
-
// Reverse pass to propagate PC ranges to parent scopes.
for i := len(dwarfScopes) - 1; i > 0; i-- {
s := &dwarfScopes[i]
return s[i].start < s[j].start
}
-type pcsByPos []scopedPCs
-
-func (s pcsByPos) Len() int { return len(s) }
-func (s pcsByPos) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
-func (s pcsByPos) Less(i, j int) bool {
- return xposBefore(s[i].pos, s[j].pos)
-}
-
type varsByScopeAndOffset struct {
vars []*dwarf.Var
scopes []ScopeID
return curscope
}
+ if len(scopes[curscope].Vars) == 0 {
+ curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
+ continue
+ }
+
if len(scope.Ranges) == 1 {
Uleb128put(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE)
putattr(ctxt, s.Info, DW_ABRV_LEXICAL_BLOCK_SIMPLE, DW_FORM_addr, DW_CLS_ADDRESS, scope.Ranges[0].Start, s.StartPC)
}
curscope = putscope(ctxt, s, scopes, curscope, fnabbrev, encbuf)
+
Uleb128put(ctxt, s.Info, 0)
}
return curscope