1
0
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:
David Lazar 2017-02-17 16:55:40 -05:00
parent 301149b9e4
commit 0824ae6dc1
4 changed files with 26 additions and 19 deletions

View File

@ -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)

View File

@ -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)
}
}

View File

@ -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

View File

@ -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)