Skip to content

Commit ef8ae82

Browse files
committed
cmd/compile: fix bug in dwarf-gen var location generation
This patch fixes a bug in the SSA back end's DWARF generation code that determines variable locations / lifetimes. The code in question was written to handle sequences of initial pseudo-ops (zero width instructions such as OpPhi, OpArg, etc) in a basic block, detecting these ops at the start of a block and then treating the values specially when emitting ranges for the variables in those values. The logic in this code wasn't quite correct, meaning that a flag variable wasn't being set properly to record the presence of a block of zero-width value-bearing ops, leading to incorrect or missing DWARF locations for register params. Also in this patch is a tweak to some sanity-checking code intended to catch scheduling problems with OpArg/OpPhi etc. The checks need to allow for the possibility of an Arg op scheduled after a spill of an incoming register param inserted by the register allocator. Example: b1: v13 = ArgIntReg <int> {p1+16} [2] : CX v14 = ArgIntReg <int> {p2+16} [5] : R8 v38 = ArgIntReg <int> {p3+16} [8] : R11 v35 = ArgIntReg <int> {p1+0} [0] : AX v15 = StoreReg <int> v35 : .autotmp_4[int] v40 = Arg <int> {p4} [16] : p4+16[int] v1 = InitMem <mem> v3 = SB <uintptr> : SB v18 = CMPQ <flags> v14 v13 NE v18 → b3 b2 (unlikely) (18) Here the register allocator has decided to spill v35, meaning that the OpArg v40 is no longer going to be positioned prior to all other non-zero-width ops; this is a valid scenario and needs to be handled properly by the debug code. Fixes #46425. Change-Id: I239b3ad56a9c1b8ebf68af42e1f57308293ed7e6 Reviewed-on: https://go-review.googlesource.com/c/go/+/332269 Trust: Than McIntosh <[email protected]> Reviewed-by: Cherry Mui <[email protected]> Run-TryBot: Than McIntosh <[email protected]> TryBot-Result: Go Bot <[email protected]>
1 parent 770899f commit ef8ae82

File tree

1 file changed

+13
-6
lines changed

1 file changed

+13
-6
lines changed

src/cmd/compile/internal/ssa/debug.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,8 +1115,14 @@ func (state *debugState) buildLocationLists(blockLocs []*BlockDebug) {
11151115
continue
11161116
}
11171117

1118+
mustBeFirst := func(v *Value) bool {
1119+
return v.Op == OpPhi || v.Op.isLoweredGetClosurePtr() ||
1120+
v.Op == OpArgIntReg || v.Op == OpArgFloatReg
1121+
}
1122+
11181123
zeroWidthPending := false
1119-
apcChangedSize := 0 // size of changedVars for leading Args, Phi, ClosurePtr
1124+
blockPrologComplete := false // set to true at first non-zero-width op
1125+
apcChangedSize := 0 // size of changedVars for leading Args, Phi, ClosurePtr
11201126
// expect to see values in pattern (apc)* (zerowidth|real)*
11211127
for _, v := range b.Values {
11221128
slots := state.valueNames[v.ID]
@@ -1125,16 +1131,16 @@ func (state *debugState) buildLocationLists(blockLocs []*BlockDebug) {
11251131

11261132
if opcodeTable[v.Op].zeroWidth {
11271133
if changed {
1128-
if hasAnyArgOp(v) || v.Op == OpPhi || v.Op.isLoweredGetClosurePtr() {
1134+
if mustBeFirst(v) || v.Op == OpArg {
11291135
// These ranges begin at true beginning of block, not after first instruction
1130-
if zeroWidthPending {
1131-
panic(fmt.Errorf("Unexpected op '%s' mixed with OpArg/OpPhi/OpLoweredGetClosurePtr at beginning of block %s in %s\n%s", v.LongString(), b, b.Func.Name, b.Func))
1136+
if blockPrologComplete && mustBeFirst(v) {
1137+
panic(fmt.Errorf("Unexpected placement of op '%s' appearing after non-pseudo-op at beginning of block %s in %s\n%s", v.LongString(), b, b.Func.Name, b.Func))
11321138
}
11331139
apcChangedSize = len(state.changedVars.contents())
1140+
// Other zero-width ops must wait on a "real" op.
1141+
zeroWidthPending = true
11341142
continue
11351143
}
1136-
// Other zero-width ops must wait on a "real" op.
1137-
zeroWidthPending = true
11381144
}
11391145
continue
11401146
}
@@ -1145,6 +1151,7 @@ func (state *debugState) buildLocationLists(blockLocs []*BlockDebug) {
11451151
// Not zero-width; i.e., a "real" instruction.
11461152

11471153
zeroWidthPending = false
1154+
blockPrologComplete = true
11481155
for i, varID := range state.changedVars.contents() {
11491156
if i < apcChangedSize { // buffered true start-of-block changes
11501157
state.updateVar(VarID(varID), v.Block, BlockStart)

0 commit comments

Comments
 (0)