aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/ssa/debug.go
diff options
context:
space:
mode:
authorHeschi Kreinick <heschi@google.com>2018-02-05 16:55:54 -0500
committerHeschi Kreinick <heschi@google.com>2018-02-21 18:01:31 +0000
commitac81c5c402ac1023296d4c418287d26aa48061d7 (patch)
tree469732f8bcdf8f51aa4011e15df324641a40385e /src/cmd/compile/internal/ssa/debug.go
parente181852dd487b97c0ed3662573793ca77f3299b0 (diff)
downloadgo-ac81c5c402ac1023296d4c418287d26aa48061d7.tar.gz
go-ac81c5c402ac1023296d4c418287d26aa48061d7.zip
cmd/compile/internal/ssa: refactor buildLocationLists
Change the closures to methods on debugState, mostly just for aesthetic reasons. Change-Id: I5242807f7300efafc7efb4eb3bd305ac3ec8e826 Reviewed-on: https://go-review.googlesource.com/92403 Reviewed-by: David Chase <drchase@google.com>
Diffstat (limited to 'src/cmd/compile/internal/ssa/debug.go')
-rw-r--r--src/cmd/compile/internal/ssa/debug.go245
1 files changed, 125 insertions, 120 deletions
diff --git a/src/cmd/compile/internal/ssa/debug.go b/src/cmd/compile/internal/ssa/debug.go
index 95f7e09231..358edc04d9 100644
--- a/src/cmd/compile/internal/ssa/debug.go
+++ b/src/cmd/compile/internal/ssa/debug.go
@@ -167,6 +167,7 @@ type debugState struct {
slots []*LocalSlot
vars []GCNode
varSlots [][]SlotID
+ lists [][]byte
// The user variable that each slot rolls up to, indexed by SlotID.
slotVars []VarID
@@ -176,6 +177,7 @@ type debugState struct {
cache *Cache
registers []Register
stackOffset func(LocalSlot) int32
+ ctxt *obj.Link
// The names (slots) associated with each value, indexed by Value ID.
valueNames [][]SlotID
@@ -184,6 +186,9 @@ type debugState struct {
currentState stateAtPC
liveCount []int
changedVars *sparseSet
+
+ // The pending location list entry for each user variable, indexed by VarID.
+ pendingEntries []pendingEntry
}
func (state *debugState) initializeCache() {
@@ -251,6 +256,7 @@ func (state *debugState) initializeCache() {
}
freePieceIdx += len(slots)
}
+ state.pendingEntries = pe
}
func (state *debugState) allocBlock(b *Block) *BlockDebug {
@@ -303,6 +309,7 @@ func BuildFuncDebug(ctxt *obj.Link, f *Func, loggingEnabled bool, stackOffset fu
cache: f.Cache,
registers: f.Config.registers,
stackOffset: stackOffset,
+ ctxt: ctxt,
}
// Recompose any decomposed variables, and record the names associated with each value.
@@ -327,6 +334,8 @@ func BuildFuncDebug(ctxt *obj.Link, f *Func, loggingEnabled bool, stackOffset fu
// Fill in the var<->slot mappings.
state.varSlots = make([][]SlotID, len(state.vars))
state.slotVars = make([]VarID, len(state.slots))
+ state.lists = make([][]byte, len(state.vars))
+
for varID, n := range state.vars {
parts := varParts[n]
state.varSlots[varID] = parts
@@ -347,13 +356,13 @@ func BuildFuncDebug(ctxt *obj.Link, f *Func, loggingEnabled bool, stackOffset fu
}
blockLocs := state.liveness()
- lists := state.buildLocationLists(ctxt, blockLocs)
+ state.buildLocationLists(blockLocs)
return &FuncDebug{
Slots: state.slots,
VarSlots: state.varSlots,
Vars: state.vars,
- LocationLists: lists,
+ LocationLists: state.lists,
}
}
@@ -717,118 +726,7 @@ func firstReg(set RegisterSet) uint8 {
// The returned location lists are not fully complete. They are in terms of
// SSA values rather than PCs, and have no base address/end entries. They will
// be finished by PutLocationList.
-func (state *debugState) buildLocationLists(Ctxt *obj.Link, blockLocs []*BlockDebug) [][]byte {
- lists := make([][]byte, len(state.vars))
- pendingEntries := state.cache.pendingEntries
-
- // writePendingEntry writes out the pending entry for varID, if any,
- // terminated at endBlock/Value.
- writePendingEntry := func(varID VarID, endBlock, endValue ID) {
- list := lists[varID]
- pending := pendingEntries[varID]
- if !pending.present {
- return
- }
-
- // Pack the start/end coordinates into the start/end addresses
- // of the entry, for decoding by PutLocationList.
- start, startOK := encodeValue(Ctxt, pending.startBlock, pending.startValue)
- end, endOK := encodeValue(Ctxt, endBlock, endValue)
- if !startOK || !endOK {
- // If someone writes a function that uses >65K values,
- // they get incomplete debug info on 32-bit platforms.
- return
- }
- list = appendPtr(Ctxt, list, start)
- list = appendPtr(Ctxt, list, end)
- // Where to write the length of the location description once
- // we know how big it is.
- sizeIdx := len(list)
- list = list[:len(list)+2]
-
- if state.loggingEnabled {
- var partStrs []string
- for i, slot := range state.varSlots[varID] {
- partStrs = append(partStrs, fmt.Sprintf("%v@%v", state.slots[slot], state.LocString(pending.pieces[i])))
- }
- state.logf("Add entry for %v: \tb%vv%v-b%vv%v = \t%v\n", state.vars[varID], pending.startBlock, pending.startValue, endBlock, endValue, strings.Join(partStrs, " "))
- }
-
- for i, slotID := range state.varSlots[varID] {
- loc := pending.pieces[i]
- slot := state.slots[slotID]
-
- if !loc.absent() {
- if loc.onStack() {
- if loc.stackOffsetValue() == 0 {
- list = append(list, dwarf.DW_OP_call_frame_cfa)
- } else {
- list = append(list, dwarf.DW_OP_fbreg)
- list = dwarf.AppendSleb128(list, int64(loc.stackOffsetValue()))
- }
- } else {
- regnum := Ctxt.Arch.DWARFRegisters[state.registers[firstReg(loc.Registers)].ObjNum()]
- if regnum < 32 {
- list = append(list, dwarf.DW_OP_reg0+byte(regnum))
- } else {
- list = append(list, dwarf.DW_OP_regx)
- list = dwarf.AppendUleb128(list, uint64(regnum))
- }
- }
- }
-
- if len(state.varSlots[varID]) > 1 {
- list = append(list, dwarf.DW_OP_piece)
- list = dwarf.AppendUleb128(list, uint64(slot.Type.Size()))
- }
- }
- Ctxt.Arch.ByteOrder.PutUint16(list[sizeIdx:], uint16(len(list)-sizeIdx-2))
- lists[varID] = list
- }
-
- // updateVar updates the pending location list entry for varID to
- // reflect the new locations in curLoc, caused by v.
- updateVar := func(varID VarID, v *Value, curLoc []VarLoc) {
- // Assemble the location list entry with whatever's live.
- empty := true
- for _, slotID := range state.varSlots[varID] {
- if !curLoc[slotID].absent() {
- empty = false
- break
- }
- }
- pending := &pendingEntries[varID]
- if empty {
- writePendingEntry(varID, v.Block.ID, v.ID)
- pending.clear()
- return
- }
-
- // Extend the previous entry if possible.
- if pending.present {
- merge := true
- for i, slotID := range state.varSlots[varID] {
- if !canMerge(pending.pieces[i], curLoc[slotID]) {
- merge = false
- break
- }
- }
- if merge {
- return
- }
- }
-
- writePendingEntry(varID, v.Block.ID, v.ID)
- pending.present = true
- pending.startBlock = v.Block.ID
- pending.startValue = v.ID
- for i, slot := range state.varSlots[varID] {
- pending.pieces[i] = curLoc[slot]
- }
- return
-
- }
-
+func (state *debugState) buildLocationLists(blockLocs []*BlockDebug) {
// Run through the function in program text order, building up location
// lists as we go. The heavy lifting has mostly already been done.
for _, b := range state.f.Blocks {
@@ -853,7 +751,7 @@ func (state *debugState) buildLocationLists(Ctxt *obj.Link, blockLocs []*BlockDe
phisPending = false
for _, varID := range state.changedVars.contents() {
- updateVar(VarID(varID), v, state.currentState.slots)
+ state.updateVar(VarID(varID), v, state.currentState.slots)
}
state.changedVars.clear()
}
@@ -865,18 +763,125 @@ func (state *debugState) buildLocationLists(Ctxt *obj.Link, blockLocs []*BlockDe
}
// Flush any leftover entries live at the end of the last block.
- for varID := range lists {
- writePendingEntry(VarID(varID), state.f.Blocks[len(state.f.Blocks)-1].ID, BlockEnd.ID)
- list := lists[varID]
+ for varID := range state.lists {
+ state.writePendingEntry(VarID(varID), state.f.Blocks[len(state.f.Blocks)-1].ID, BlockEnd.ID)
+ list := state.lists[varID]
if len(list) == 0 {
continue
}
if state.loggingEnabled {
- state.logf("\t%v : %q\n", state.vars[varID], hex.EncodeToString(lists[varID]))
+ state.logf("\t%v : %q\n", state.vars[varID], hex.EncodeToString(state.lists[varID]))
+ }
+ }
+}
+
+// updateVar updates the pending location list entry for varID to
+// reflect the new locations in curLoc, caused by v.
+func (state *debugState) updateVar(varID VarID, v *Value, curLoc []VarLoc) {
+ // Assemble the location list entry with whatever's live.
+ empty := true
+ for _, slotID := range state.varSlots[varID] {
+ if !curLoc[slotID].absent() {
+ empty = false
+ break
+ }
+ }
+ pending := &state.pendingEntries[varID]
+ if empty {
+ state.writePendingEntry(varID, v.Block.ID, v.ID)
+ pending.clear()
+ return
+ }
+
+ // Extend the previous entry if possible.
+ if pending.present {
+ merge := true
+ for i, slotID := range state.varSlots[varID] {
+ if !canMerge(pending.pieces[i], curLoc[slotID]) {
+ merge = false
+ break
+ }
+ }
+ if merge {
+ return
+ }
+ }
+
+ state.writePendingEntry(varID, v.Block.ID, v.ID)
+ pending.present = true
+ pending.startBlock = v.Block.ID
+ pending.startValue = v.ID
+ for i, slot := range state.varSlots[varID] {
+ pending.pieces[i] = curLoc[slot]
+ }
+ return
+
+}
+
+// writePendingEntry writes out the pending entry for varID, if any,
+// terminated at endBlock/Value.
+func (state *debugState) writePendingEntry(varID VarID, endBlock, endValue ID) {
+ pending := state.pendingEntries[varID]
+ if !pending.present {
+ return
+ }
+
+ // Pack the start/end coordinates into the start/end addresses
+ // of the entry, for decoding by PutLocationList.
+ start, startOK := encodeValue(state.ctxt, pending.startBlock, pending.startValue)
+ end, endOK := encodeValue(state.ctxt, endBlock, endValue)
+ if !startOK || !endOK {
+ // If someone writes a function that uses >65K values,
+ // they get incomplete debug info on 32-bit platforms.
+ return
+ }
+ list := state.lists[varID]
+ list = appendPtr(state.ctxt, list, start)
+ list = appendPtr(state.ctxt, list, end)
+ // Where to write the length of the location description once
+ // we know how big it is.
+ sizeIdx := len(list)
+ list = list[:len(list)+2]
+
+ if state.loggingEnabled {
+ var partStrs []string
+ for i, slot := range state.varSlots[varID] {
+ partStrs = append(partStrs, fmt.Sprintf("%v@%v", state.slots[slot], state.LocString(pending.pieces[i])))
+ }
+ state.logf("Add entry for %v: \tb%vv%v-b%vv%v = \t%v\n", state.vars[varID], pending.startBlock, pending.startValue, endBlock, endValue, strings.Join(partStrs, " "))
+ }
+
+ for i, slotID := range state.varSlots[varID] {
+ loc := pending.pieces[i]
+ slot := state.slots[slotID]
+
+ if !loc.absent() {
+ if loc.onStack() {
+ if loc.stackOffsetValue() == 0 {
+ list = append(list, dwarf.DW_OP_call_frame_cfa)
+ } else {
+ list = append(list, dwarf.DW_OP_fbreg)
+ list = dwarf.AppendSleb128(list, int64(loc.stackOffsetValue()))
+ }
+ } else {
+ regnum := state.ctxt.Arch.DWARFRegisters[state.registers[firstReg(loc.Registers)].ObjNum()]
+ if regnum < 32 {
+ list = append(list, dwarf.DW_OP_reg0+byte(regnum))
+ } else {
+ list = append(list, dwarf.DW_OP_regx)
+ list = dwarf.AppendUleb128(list, uint64(regnum))
+ }
+ }
+ }
+
+ if len(state.varSlots[varID]) > 1 {
+ list = append(list, dwarf.DW_OP_piece)
+ list = dwarf.AppendUleb128(list, uint64(slot.Type.Size()))
}
}
- return lists
+ state.ctxt.Arch.ByteOrder.PutUint16(list[sizeIdx:], uint16(len(list)-sizeIdx-2))
+ state.lists[varID] = list
}
// PutLocationList adds list (a location list in its intermediate representation) to listSym.