mirror of
https://github.com/golang/go
synced 2024-11-18 14:34:39 -07:00
cmd/compile: add flag for debugging PC-value tables
For example, `-d pctab=pctoinline` prints the PC-inline table and inlining tree for every function. Change-Id: Ia6b9ce4d83eed0b494318d40ffe06481ec5d58ab Reviewed-on: https://go-review.googlesource.com/37235 Run-TryBot: David Lazar <lazard@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>
This commit is contained in:
parent
301149b9e4
commit
0824ae6dc1
@ -37,6 +37,7 @@ var (
|
|||||||
Debug_panic int
|
Debug_panic int
|
||||||
Debug_slice int
|
Debug_slice int
|
||||||
Debug_wb int
|
Debug_wb int
|
||||||
|
Debug_pctab string
|
||||||
)
|
)
|
||||||
|
|
||||||
// Debug arguments.
|
// Debug arguments.
|
||||||
@ -59,6 +60,7 @@ var debugtab = []struct {
|
|||||||
{"typeassert", &Debug_typeassert}, // print information about type assertion inlining
|
{"typeassert", &Debug_typeassert}, // print information about type assertion inlining
|
||||||
{"wb", &Debug_wb}, // print information about write barriers
|
{"wb", &Debug_wb}, // print information about write barriers
|
||||||
{"export", &Debug_export}, // print export data
|
{"export", &Debug_export}, // print export data
|
||||||
|
{"pctab", &Debug_pctab}, // print named pc-value table
|
||||||
}
|
}
|
||||||
|
|
||||||
func usage() {
|
func usage() {
|
||||||
@ -319,6 +321,9 @@ func Main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set via a -d flag
|
||||||
|
Ctxt.Debugpcln = Debug_pctab
|
||||||
|
|
||||||
// enable inlining. for now:
|
// enable inlining. for now:
|
||||||
// default: inlining on. (debug['l'] == 1)
|
// default: inlining on. (debug['l'] == 1)
|
||||||
// -l: inlining off (debug['l'] == 0)
|
// -l: inlining off (debug['l'] == 0)
|
||||||
|
@ -76,3 +76,10 @@ func (ctxt *Link) OutermostPos(xpos src.XPos) src.Pos {
|
|||||||
}
|
}
|
||||||
return ctxt.PosTable.Pos(outerxpos)
|
return ctxt.PosTable.Pos(outerxpos)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dumpInlTree(ctxt *Link, tree InlTree) {
|
||||||
|
for i, call := range tree.nodes {
|
||||||
|
pos := ctxt.PosTable.Pos(call.Pos)
|
||||||
|
ctxt.Logf("%0d | %0d | %s (%s)\n", i, call.Parent, call.Func, pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -716,7 +716,7 @@ type Link struct {
|
|||||||
Debugasm int32
|
Debugasm int32
|
||||||
Debugvlog int32
|
Debugvlog int32
|
||||||
Debugdivmod int32
|
Debugdivmod int32
|
||||||
Debugpcln int32
|
Debugpcln string
|
||||||
Flag_shared bool
|
Flag_shared bool
|
||||||
Flag_dynlink bool
|
Flag_dynlink bool
|
||||||
Flag_optimize bool
|
Flag_optimize bool
|
||||||
|
@ -24,31 +24,23 @@ func addvarint(d *Pcdata, v uint32) {
|
|||||||
// where func is the function, val is the current value, p is the instruction being
|
// where func is the function, val is the current value, p is the instruction being
|
||||||
// considered, and arg can be used to further parameterize valfunc.
|
// considered, and arg can be used to further parameterize valfunc.
|
||||||
func funcpctab(ctxt *Link, dst *Pcdata, func_ *LSym, desc string, valfunc func(*Link, *LSym, int32, *Prog, int32, interface{}) int32, arg interface{}) {
|
func funcpctab(ctxt *Link, dst *Pcdata, func_ *LSym, desc string, valfunc func(*Link, *LSym, int32, *Prog, int32, interface{}) int32, arg interface{}) {
|
||||||
// To debug a specific function, uncomment lines and change name.
|
dbg := desc == ctxt.Debugpcln
|
||||||
dbg := 0
|
|
||||||
|
|
||||||
//if func_.Name == "main.main" || desc == "pctospadj" {
|
|
||||||
// dbg = 1
|
|
||||||
//}
|
|
||||||
|
|
||||||
ctxt.Debugpcln += int32(dbg)
|
|
||||||
|
|
||||||
dst.P = dst.P[:0]
|
dst.P = dst.P[:0]
|
||||||
|
|
||||||
if ctxt.Debugpcln != 0 {
|
if dbg {
|
||||||
ctxt.Logf("funcpctab %s [valfunc=%s]\n", func_.Name, desc)
|
ctxt.Logf("funcpctab %s [valfunc=%s]\n", func_.Name, desc)
|
||||||
}
|
}
|
||||||
|
|
||||||
val := int32(-1)
|
val := int32(-1)
|
||||||
oldval := val
|
oldval := val
|
||||||
if func_.Text == nil {
|
if func_.Text == nil {
|
||||||
ctxt.Debugpcln -= int32(dbg)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
pc := func_.Text.Pc
|
pc := func_.Text.Pc
|
||||||
|
|
||||||
if ctxt.Debugpcln != 0 {
|
if dbg {
|
||||||
ctxt.Logf("%6x %6d %v\n", uint64(pc), val, func_.Text)
|
ctxt.Logf("%6x %6d %v\n", uint64(pc), val, func_.Text)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +52,7 @@ func funcpctab(ctxt *Link, dst *Pcdata, func_ *LSym, desc string, valfunc func(*
|
|||||||
|
|
||||||
if val == oldval && started != 0 {
|
if val == oldval && started != 0 {
|
||||||
val = valfunc(ctxt, func_, val, p, 1, arg)
|
val = valfunc(ctxt, func_, val, p, 1, arg)
|
||||||
if ctxt.Debugpcln != 0 {
|
if dbg {
|
||||||
ctxt.Logf("%6x %6s %v\n", uint64(p.Pc), "", p)
|
ctxt.Logf("%6x %6s %v\n", uint64(p.Pc), "", p)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
@ -72,7 +64,7 @@ func funcpctab(ctxt *Link, dst *Pcdata, func_ *LSym, desc string, valfunc func(*
|
|||||||
// for a true instruction boundary in the program.
|
// for a true instruction boundary in the program.
|
||||||
if p.Link != nil && p.Link.Pc == p.Pc {
|
if p.Link != nil && p.Link.Pc == p.Pc {
|
||||||
val = valfunc(ctxt, func_, val, p, 1, arg)
|
val = valfunc(ctxt, func_, val, p, 1, arg)
|
||||||
if ctxt.Debugpcln != 0 {
|
if dbg {
|
||||||
ctxt.Logf("%6x %6s %v\n", uint64(p.Pc), "", p)
|
ctxt.Logf("%6x %6s %v\n", uint64(p.Pc), "", p)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
@ -92,7 +84,7 @@ func funcpctab(ctxt *Link, dst *Pcdata, func_ *LSym, desc string, valfunc func(*
|
|||||||
// as variable-length little-endian base-128 integers,
|
// as variable-length little-endian base-128 integers,
|
||||||
// where the 0x80 bit indicates that the integer continues.
|
// where the 0x80 bit indicates that the integer continues.
|
||||||
|
|
||||||
if ctxt.Debugpcln != 0 {
|
if dbg {
|
||||||
ctxt.Logf("%6x %6d %v\n", uint64(p.Pc), val, p)
|
ctxt.Logf("%6x %6d %v\n", uint64(p.Pc), val, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,22 +106,20 @@ func funcpctab(ctxt *Link, dst *Pcdata, func_ *LSym, desc string, valfunc func(*
|
|||||||
}
|
}
|
||||||
|
|
||||||
if started != 0 {
|
if started != 0 {
|
||||||
if ctxt.Debugpcln != 0 {
|
if dbg {
|
||||||
ctxt.Logf("%6x done\n", uint64(func_.Text.Pc+func_.Size))
|
ctxt.Logf("%6x done\n", uint64(func_.Text.Pc+func_.Size))
|
||||||
}
|
}
|
||||||
addvarint(dst, uint32((func_.Size-pc)/int64(ctxt.Arch.MinLC)))
|
addvarint(dst, uint32((func_.Size-pc)/int64(ctxt.Arch.MinLC)))
|
||||||
addvarint(dst, 0) // terminator
|
addvarint(dst, 0) // terminator
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctxt.Debugpcln != 0 {
|
if dbg {
|
||||||
ctxt.Logf("wrote %d bytes to %p\n", len(dst.P), dst)
|
ctxt.Logf("wrote %d bytes to %p\n", len(dst.P), dst)
|
||||||
for i := 0; i < len(dst.P); i++ {
|
for i := 0; i < len(dst.P); i++ {
|
||||||
ctxt.Logf(" %02x", dst.P[i])
|
ctxt.Logf(" %02x", dst.P[i])
|
||||||
}
|
}
|
||||||
ctxt.Logf("\n")
|
ctxt.Logf("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxt.Debugpcln -= int32(dbg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// pctofileline computes either the file number (arg == 0)
|
// pctofileline computes either the file number (arg == 0)
|
||||||
@ -297,6 +287,11 @@ func linkpcln(ctxt *Link, cursym *LSym) {
|
|||||||
pcinlineState := new(pcinlineState)
|
pcinlineState := new(pcinlineState)
|
||||||
funcpctab(ctxt, &pcln.Pcinline, cursym, "pctoinline", pcinlineState.pctoinline, nil)
|
funcpctab(ctxt, &pcln.Pcinline, cursym, "pctoinline", pcinlineState.pctoinline, nil)
|
||||||
pcln.InlTree = pcinlineState.localTree
|
pcln.InlTree = pcinlineState.localTree
|
||||||
|
if ctxt.Debugpcln == "pctoinline" && len(pcln.InlTree.nodes) > 0 {
|
||||||
|
ctxt.Logf("-- inlining tree for %s:\n", cursym)
|
||||||
|
dumpInlTree(ctxt, pcln.InlTree)
|
||||||
|
ctxt.Logf("--\n")
|
||||||
|
}
|
||||||
|
|
||||||
// tabulate which pc and func data we have.
|
// tabulate which pc and func data we have.
|
||||||
havepc := make([]uint32, (npcdata+31)/32)
|
havepc := make([]uint32, (npcdata+31)/32)
|
||||||
|
Loading…
Reference in New Issue
Block a user