]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: revise block/func end sentinels in debug analysis
authorThan McIntosh <thanm@google.com>
Wed, 28 Apr 2021 22:26:54 +0000 (18:26 -0400)
committerThan McIntosh <thanm@google.com>
Fri, 30 Apr 2021 18:46:51 +0000 (18:46 +0000)
The SSA code for debug variable location analysis (for DWARF) has two
special 'sentinel' values that it uses to handshake with the
debugInfo.GetPC callback when capturing the PC values of debug
variable ranges after prog generatoin: "BlockStart" and "BlockEnd".

"BlockStart" has the expected semantics: it means "the PC value of the
first instruction of block B", but "BlockEnd" does not mean "PC value
of the last instruction of block B", but rather it is implemented as
"the PC value of the last instruction of the function". This causes
confusion when reading the code, and seems to to result in implementation
flaws in the past, leading to incorrect ranges in some cases.

To help with this, add a new sentinel "FuncEnd" (which has the "last
inst in the function" semantics) and change the implementation of
"BlockEnd" to actually mean what its name implies (last inst in
block).

Updates #45720.

Change-Id: Ic3497fb60413e898d2bfe27805c3db56483d12a2
Reviewed-on: https://go-review.googlesource.com/c/go/+/314930
Trust: Than McIntosh <thanm@google.com>
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: David Chase <drchase@google.com>
src/cmd/compile/internal/ssa/debug.go
src/cmd/compile/internal/ssagen/ssa.go

index d725fc526eaa9ab761e74611846c12e21333ab70..46743f54eb5f1c67f3b10039403602dd63fec1c9 100644 (file)
@@ -152,6 +152,12 @@ var BlockEnd = &Value{
        Aux: StringToAux("BlockEnd"),
 }
 
+var FuncEnd = &Value{
+       ID:  -30000,
+       Op:  OpInvalid,
+       Aux: StringToAux("FuncEnd"),
+}
+
 // RegisterSet is a bitmap of registers, indexed by Register.num.
 type RegisterSet uint64
 
@@ -948,7 +954,7 @@ func (state *debugState) buildLocationLists(blockLocs []*BlockDebug) {
 
        // Flush any leftover entries live at the end of the last block.
        for varID := range state.lists {
-               state.writePendingEntry(VarID(varID), state.f.Blocks[len(state.f.Blocks)-1].ID, BlockEnd.ID)
+               state.writePendingEntry(VarID(varID), state.f.Blocks[len(state.f.Blocks)-1].ID, FuncEnd.ID)
                list := state.lists[varID]
                if state.loggingEnabled {
                        if len(list) == 0 {
index c49350005e4fd53c653bde468bd1a24f11d2bdef..fb35d8044e42927361fd3f286299b714fc19607c 100644 (file)
@@ -6964,6 +6964,10 @@ func genssa(f *ssa.Func, pp *objw.Progs) {
                debugInfo := ssa.BuildFuncDebug(base.Ctxt, f, base.Debug.LocationLists > 1, StackOffset)
                e.curfn.DebugInfo = debugInfo
                bstart := s.bstart
+               idToIdx := make([]int, f.NumBlocks())
+               for i, b := range f.Blocks {
+                       idToIdx[b.ID] = i
+               }
                // Note that at this moment, Prog.Pc is a sequence number; it's
                // not a real PC until after assembly, so this mapping has to
                // be done later.
@@ -6976,6 +6980,10 @@ func genssa(f *ssa.Func, pp *objw.Progs) {
                                }
                                return bstart[b].Pc
                        case ssa.BlockEnd.ID:
+                               blk := f.Blocks[idToIdx[b]]
+                               nv := len(blk.Values)
+                               return valueToProgAfter[blk.Values[nv-1].ID].Pc
+                       case ssa.FuncEnd.ID:
                                return e.curfn.LSym.Size
                        default:
                                return valueToProgAfter[v].Pc