mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: adjust is-statement on Pos's to improve debugging
Stores to auto tmp variables can be hoisted to places where the line numbers make debugging look "jumpy". Turning those instructions into ones with is_stmt = 0 in the DWARF (accomplished by marking ssa nodes with NotStmt) makes debugging look better while still attributing the instructions with the correct line number. The same is true for certain register allocator spills and reloads. Change-Id: I97a394eb522d4911cc40b4bf5bf76d3d7221f6c0 Reviewed-on: https://go-review.googlesource.com/98415 Run-TryBot: David Chase <drchase@google.com> Reviewed-by: Cherry Zhang <cherryyz@google.com> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
dead03b794
commit
b9a365681f
4 changed files with 34 additions and 38 deletions
|
|
@ -419,6 +419,16 @@ func (s *state) newValue1A(op ssa.Op, t *types.Type, aux interface{}, arg *ssa.V
|
||||||
return s.curBlock.NewValue1A(s.peekPos(), op, t, aux, arg)
|
return s.curBlock.NewValue1A(s.peekPos(), op, t, aux, arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newValue1Apos adds a new value with one argument and an aux value to the current block.
|
||||||
|
// isStmt determines whether the created values may be a statement or not
|
||||||
|
// (i.e., false means never, yes means maybe).
|
||||||
|
func (s *state) newValue1Apos(op ssa.Op, t *types.Type, aux interface{}, arg *ssa.Value, isStmt bool) *ssa.Value {
|
||||||
|
if isStmt {
|
||||||
|
return s.curBlock.NewValue1A(s.peekPos(), op, t, aux, arg)
|
||||||
|
}
|
||||||
|
return s.curBlock.NewValue1A(s.peekPos().WithNotStmt(), op, t, aux, arg)
|
||||||
|
}
|
||||||
|
|
||||||
// newValue1I adds a new value with one argument and an auxint value to the current block.
|
// newValue1I adds a new value with one argument and an auxint value to the current block.
|
||||||
func (s *state) newValue1I(op ssa.Op, t *types.Type, aux int64, arg *ssa.Value) *ssa.Value {
|
func (s *state) newValue1I(op ssa.Op, t *types.Type, aux int64, arg *ssa.Value) *ssa.Value {
|
||||||
return s.curBlock.NewValue1I(s.peekPos(), op, t, aux, arg)
|
return s.curBlock.NewValue1I(s.peekPos(), op, t, aux, arg)
|
||||||
|
|
@ -449,6 +459,16 @@ func (s *state) newValue3A(op ssa.Op, t *types.Type, aux interface{}, arg0, arg1
|
||||||
return s.curBlock.NewValue3A(s.peekPos(), op, t, aux, arg0, arg1, arg2)
|
return s.curBlock.NewValue3A(s.peekPos(), op, t, aux, arg0, arg1, arg2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// newValue3Apos adds a new value with three arguments and an aux value to the current block.
|
||||||
|
// isStmt determines whether the created values may be a statement or not
|
||||||
|
// (i.e., false means never, yes means maybe).
|
||||||
|
func (s *state) newValue3Apos(op ssa.Op, t *types.Type, aux interface{}, arg0, arg1, arg2 *ssa.Value, isStmt bool) *ssa.Value {
|
||||||
|
if isStmt {
|
||||||
|
return s.curBlock.NewValue3A(s.peekPos(), op, t, aux, arg0, arg1, arg2)
|
||||||
|
}
|
||||||
|
return s.curBlock.NewValue3A(s.peekPos().WithNotStmt(), op, t, aux, arg0, arg1, arg2)
|
||||||
|
}
|
||||||
|
|
||||||
// newValue4 adds a new value with four arguments to the current block.
|
// newValue4 adds a new value with four arguments to the current block.
|
||||||
func (s *state) newValue4(op ssa.Op, t *types.Type, arg0, arg1, arg2, arg3 *ssa.Value) *ssa.Value {
|
func (s *state) newValue4(op ssa.Op, t *types.Type, arg0, arg1, arg2, arg3 *ssa.Value) *ssa.Value {
|
||||||
return s.curBlock.NewValue4(s.peekPos(), op, t, arg0, arg1, arg2, arg3)
|
return s.curBlock.NewValue4(s.peekPos(), op, t, arg0, arg1, arg2, arg3)
|
||||||
|
|
@ -997,7 +1017,7 @@ func (s *state) stmt(n *Node) {
|
||||||
// varkill in the store chain is enough to keep it correctly ordered
|
// varkill in the store chain is enough to keep it correctly ordered
|
||||||
// with respect to call ops.
|
// with respect to call ops.
|
||||||
if !s.canSSA(n.Left) {
|
if !s.canSSA(n.Left) {
|
||||||
s.vars[&memVar] = s.newValue1A(ssa.OpVarKill, types.TypeMem, n.Left, s.mem())
|
s.vars[&memVar] = s.newValue1Apos(ssa.OpVarKill, types.TypeMem, n.Left, s.mem(), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
case OVARLIVE:
|
case OVARLIVE:
|
||||||
|
|
@ -2338,7 +2358,7 @@ func (s *state) append(n *Node, inplace bool) *ssa.Value {
|
||||||
for i, arg := range args {
|
for i, arg := range args {
|
||||||
addr := s.newValue2(ssa.OpPtrIndex, pt, p2, s.constInt(types.Types[TINT], int64(i)))
|
addr := s.newValue2(ssa.OpPtrIndex, pt, p2, s.constInt(types.Types[TINT], int64(i)))
|
||||||
if arg.store {
|
if arg.store {
|
||||||
s.storeType(et, addr, arg.v, 0)
|
s.storeType(et, addr, arg.v, 0, true)
|
||||||
} else {
|
} else {
|
||||||
s.move(et, addr, arg.v)
|
s.move(et, addr, arg.v)
|
||||||
}
|
}
|
||||||
|
|
@ -2488,7 +2508,7 @@ func (s *state) assign(left *Node, right *ssa.Value, deref bool, skip skipMask)
|
||||||
// Left is not ssa-able. Compute its address.
|
// Left is not ssa-able. Compute its address.
|
||||||
addr := s.addr(left, false)
|
addr := s.addr(left, false)
|
||||||
if left.Op == ONAME && left.Class() != PEXTERN && skip == 0 {
|
if left.Op == ONAME && left.Class() != PEXTERN && skip == 0 {
|
||||||
s.vars[&memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, left, s.mem())
|
s.vars[&memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, left, s.mem(), !left.IsAutoTmp())
|
||||||
}
|
}
|
||||||
if isReflectHeaderDataField(left) {
|
if isReflectHeaderDataField(left) {
|
||||||
// Package unsafe's documentation says storing pointers into
|
// Package unsafe's documentation says storing pointers into
|
||||||
|
|
@ -2508,7 +2528,7 @@ func (s *state) assign(left *Node, right *ssa.Value, deref bool, skip skipMask)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Treat as a store.
|
// Treat as a store.
|
||||||
s.storeType(t, addr, right, skip)
|
s.storeType(t, addr, right, skip, !left.IsAutoTmp())
|
||||||
}
|
}
|
||||||
|
|
||||||
// zeroVal returns the zero value for type t.
|
// zeroVal returns the zero value for type t.
|
||||||
|
|
@ -3491,7 +3511,7 @@ func (s *state) addr(n *Node, bounded bool) *ssa.Value {
|
||||||
s.Fatalf("addr of undeclared ONAME %v. declared: %v", n, s.decladdrs)
|
s.Fatalf("addr of undeclared ONAME %v. declared: %v", n, s.decladdrs)
|
||||||
return nil
|
return nil
|
||||||
case PAUTO:
|
case PAUTO:
|
||||||
return s.newValue1A(ssa.OpAddr, t, n, s.sp)
|
return s.newValue1Apos(ssa.OpAddr, t, n, s.sp, !n.IsAutoTmp())
|
||||||
case PPARAMOUT: // Same as PAUTO -- cannot generate LEA early.
|
case PPARAMOUT: // Same as PAUTO -- cannot generate LEA early.
|
||||||
// ensure that we reuse symbols for out parameters so
|
// ensure that we reuse symbols for out parameters so
|
||||||
// that cse works on their addresses
|
// that cse works on their addresses
|
||||||
|
|
@ -3776,11 +3796,11 @@ func (s *state) rtcall(fn *obj.LSym, returns bool, results []*types.Type, args .
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// do *left = right for type t.
|
/// do *left = right for type t.
|
||||||
func (s *state) storeType(t *types.Type, left, right *ssa.Value, skip skipMask) {
|
func (s *state) storeType(t *types.Type, left, right *ssa.Value, skip skipMask, leftIsStmt bool) {
|
||||||
if skip == 0 && (!types.Haspointers(t) || ssa.IsStackAddr(left)) {
|
if skip == 0 && (!types.Haspointers(t) || ssa.IsStackAddr(left)) {
|
||||||
// Known to not have write barrier. Store the whole type.
|
// Known to not have write barrier. Store the whole type.
|
||||||
s.store(t, left, right)
|
s.vars[&memVar] = s.newValue3Apos(ssa.OpStore, types.TypeMem, t, left, right, s.mem(), leftIsStmt)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -444,7 +444,7 @@ func (s *regAllocState) makeSpill(v *Value, b *Block) *Value {
|
||||||
// *Value which is either v or a copy of v allocated to the chosen register.
|
// *Value which is either v or a copy of v allocated to the chosen register.
|
||||||
func (s *regAllocState) allocValToReg(v *Value, mask regMask, nospill bool, pos src.XPos) *Value {
|
func (s *regAllocState) allocValToReg(v *Value, mask regMask, nospill bool, pos src.XPos) *Value {
|
||||||
vi := &s.values[v.ID]
|
vi := &s.values[v.ID]
|
||||||
|
pos = pos.WithNotStmt()
|
||||||
// Check if v is already in a requested register.
|
// Check if v is already in a requested register.
|
||||||
if mask&vi.regs != 0 {
|
if mask&vi.regs != 0 {
|
||||||
r := pickReg(mask & vi.regs)
|
r := pickReg(mask & vi.regs)
|
||||||
|
|
@ -1893,18 +1893,20 @@ func (e *edgeState) process() {
|
||||||
fmt.Printf("breaking cycle with v%d in %s:%s\n", vid, loc, c)
|
fmt.Printf("breaking cycle with v%d in %s:%s\n", vid, loc, c)
|
||||||
}
|
}
|
||||||
e.erase(r)
|
e.erase(r)
|
||||||
|
pos := d.pos.WithNotStmt()
|
||||||
if _, isReg := loc.(*Register); isReg {
|
if _, isReg := loc.(*Register); isReg {
|
||||||
c = e.p.NewValue1(d.pos, OpCopy, c.Type, c)
|
c = e.p.NewValue1(pos, OpCopy, c.Type, c)
|
||||||
} else {
|
} else {
|
||||||
c = e.p.NewValue1(d.pos, OpLoadReg, c.Type, c)
|
c = e.p.NewValue1(pos, OpLoadReg, c.Type, c)
|
||||||
}
|
}
|
||||||
e.set(r, vid, c, false, d.pos)
|
e.set(r, vid, c, false, pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// processDest generates code to put value vid into location loc. Returns true
|
// processDest generates code to put value vid into location loc. Returns true
|
||||||
// if progress was made.
|
// if progress was made.
|
||||||
func (e *edgeState) processDest(loc Location, vid ID, splice **Value, pos src.XPos) bool {
|
func (e *edgeState) processDest(loc Location, vid ID, splice **Value, pos src.XPos) bool {
|
||||||
|
pos = pos.WithNotStmt()
|
||||||
occupant := e.contents[loc]
|
occupant := e.contents[loc]
|
||||||
if occupant.vid == vid {
|
if occupant.vid == vid {
|
||||||
// Value is already in the correct place.
|
// Value is already in the correct place.
|
||||||
|
|
|
||||||
|
|
@ -116,54 +116,30 @@ scanner = (struct bufio.Scanner *) <A>
|
||||||
a = 0
|
a = 0
|
||||||
n = 0
|
n = 0
|
||||||
t = 0
|
t = 0
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
|
||||||
91: n += a
|
91: n += a
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
|
||||||
90: t += i * a
|
90: t += i * a
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
||||||
90: t += i * a
|
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
|
||||||
86: for i, a := range hist {
|
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
|
||||||
87: if a == 0 { //gdb-opt=(a,n,t)
|
87: if a == 0 { //gdb-opt=(a,n,t)
|
||||||
a = 3
|
a = 3
|
||||||
n = 3
|
n = 3
|
||||||
t = 3
|
t = 3
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
|
||||||
91: n += a
|
91: n += a
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
|
||||||
90: t += i * a
|
90: t += i * a
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
||||||
90: t += i * a
|
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
|
||||||
86: for i, a := range hist {
|
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
|
||||||
87: if a == 0 { //gdb-opt=(a,n,t)
|
87: if a == 0 { //gdb-opt=(a,n,t)
|
||||||
a = 0
|
a = 0
|
||||||
n = 6
|
n = 6
|
||||||
t = 9
|
t = 9
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
|
||||||
91: n += a
|
91: n += a
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
|
||||||
90: t += i * a
|
90: t += i * a
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
||||||
90: t += i * a
|
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
|
||||||
86: for i, a := range hist {
|
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
|
||||||
87: if a == 0 { //gdb-opt=(a,n,t)
|
87: if a == 0 { //gdb-opt=(a,n,t)
|
||||||
a = 1
|
a = 1
|
||||||
n = 8
|
n = 8
|
||||||
t = 17
|
t = 17
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
|
||||||
91: n += a
|
91: n += a
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
|
||||||
90: t += i * a
|
90: t += i * a
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
||||||
90: t += i * a
|
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
|
||||||
86: for i, a := range hist {
|
|
||||||
92: fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
|
|
||||||
87: if a == 0 { //gdb-opt=(a,n,t)
|
87: if a == 0 { //gdb-opt=(a,n,t)
|
||||||
a = 0
|
a = 0
|
||||||
n = 9
|
n = 9
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
20: y := id(0)
|
20: y := id(0)
|
||||||
21: fmt.Println(x)
|
21: fmt.Println(x)
|
||||||
0:
|
0:
|
||||||
22: for i := x; i < 3; i++ {
|
|
||||||
23: x := i * i
|
23: x := i * i
|
||||||
24: y += id(x) //gdb-dbg=(x,y)//gdb-opt=(x,y)
|
24: y += id(x) //gdb-dbg=(x,y)//gdb-opt=(x,y)
|
||||||
x = 0
|
x = 0
|
||||||
|
|
@ -32,7 +31,6 @@ y = 1
|
||||||
x = <optimized out>
|
x = <optimized out>
|
||||||
y = 1
|
y = 1
|
||||||
22: for i := x; i < 3; i++ {
|
22: for i := x; i < 3; i++ {
|
||||||
27: fmt.Println(x, y)
|
|
||||||
26: y = x + y //gdb-dbg=(x,y)//gdb-opt=(x,y)
|
26: y = x + y //gdb-dbg=(x,y)//gdb-opt=(x,y)
|
||||||
x = 0
|
x = 0
|
||||||
y = 1
|
y = 1
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue