Commit 63c2f263 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent a4cfd3bb
...@@ -18,7 +18,10 @@ ...@@ -18,7 +18,10 @@
// See https://www.nexedi.com/licensing for rationale and options. // See https://www.nexedi.com/licensing for rationale and options.
/* /*
gotrace gen generates code according to tracing annotations and imports gotrace TODO
gen generates code according to tracing annotations and imports
list lists tracepoints defined in a package
gotrace gen package gotrace gen package
gotrace list package TODO gotrace list package TODO
...@@ -56,8 +59,8 @@ import ( ...@@ -56,8 +59,8 @@ import (
// traceEvent represents 1 trace:event definition // traceEvent represents 1 trace:event definition
type traceEvent struct { type traceEvent struct {
Pos token.Position Pos token.Position
Pkgt *Package // package this trace event is part of Pkgt *Package // package this trace event is part of
// declaration of function to signal the event // declaration of function to signal the event
// the declaration is constructed on the fly via converting e.g. // the declaration is constructed on the fly via converting e.g.
...@@ -75,17 +78,17 @@ type traceEvent struct { ...@@ -75,17 +78,17 @@ type traceEvent struct {
// traceImport represents 1 trace:import directive // traceImport represents 1 trace:import directive
type traceImport struct { type traceImport struct {
Pos token.Position Pos token.Position
PkgName string // "" if import name was not explicitly specified PkgName string // "" if import name was not explicitly specified
PkgPath string PkgPath string
} }
// traceImported represents 1 imported trace:event // traceImported represents 1 imported trace:event
type traceImported struct { type traceImported struct {
*traceEvent // original event *traceEvent // original event
ImportSpec *traceImport // imported via this spec ImportSpec *traceImport // imported via this spec
ImporterPkg *types.Package // from this package ImporterPkg *types.Package // from this package
ImportedAs map[string]string // where some packages are imported as named (pkgpath -> pkgname) ImportedAs map[string]string // where some packages are imported as named (pkgpath -> pkgname)
} }
// Package represents tracing-related information about a package // Package represents tracing-related information about a package
...@@ -106,7 +109,6 @@ type Package struct { ...@@ -106,7 +109,6 @@ type Package struct {
traceTypeInfo *types.Info // typeinfo for ^^^ traceTypeInfo *types.Info // typeinfo for ^^^
} }
// parseTraceEvent parses trace event definition into traceEvent // parseTraceEvent parses trace event definition into traceEvent
// text is text argument after "//trace:event " // text is text argument after "//trace:event "
func (p *Package) parseTraceEvent(srcfile *ast.File, pos token.Position, text string) (*traceEvent, error) { func (p *Package) parseTraceEvent(srcfile *ast.File, pos token.Position, text string) (*traceEvent, error) {
...@@ -237,30 +239,30 @@ func packageTrace(prog *loader.Program, pkgi *loader.PackageInfo) (*Package, err ...@@ -237,30 +239,30 @@ func packageTrace(prog *loader.Program, pkgi *loader.PackageInfo) (*Package, err
// prepare Package with typechecker ready to typecheck trace files // prepare Package with typechecker ready to typecheck trace files
// (to get trace func argument types) // (to get trace func argument types)
tconf := &types.Config{ tconf := &types.Config{
Importer: &progImporter{prog}, Importer: &progImporter{prog},
// to ignore traceXXX() calls from original package code // to ignore traceXXX() calls from original package code
IgnoreFuncBodies: true, IgnoreFuncBodies: true,
// we take imports from original source file verbatim, // we take imports from original source file verbatim,
// but most of them probably won't be used. // but most of them probably won't be used.
DisableUnusedImportCheck: true, DisableUnusedImportCheck: true,
} }
// tfset := token.NewFileSet() // XXX ok to separate or use original package fset? // tfset := token.NewFileSet() // XXX ok to separate or use original package fset?
tpkg := types.NewPackage(pkgi.Pkg.Path(), pkgi.Pkg.Name()) tpkg := types.NewPackage(pkgi.Pkg.Path(), pkgi.Pkg.Name())
tinfo := &types.Info{Types: make(map[ast.Expr]types.TypeAndValue)} tinfo := &types.Info{Types: make(map[ast.Expr]types.TypeAndValue)}
p := &Package{ p := &Package{
Pkgi: pkgi, Pkgi: pkgi,
// traceFset: tfset, // traceFset: tfset,
// traceChecker: types.NewChecker(tconf, tfset, tpkg, tinfo), // traceChecker: types.NewChecker(tconf, tfset, tpkg, tinfo),
// XXX vvv do we need separate field for traceFset if it is = prog.Fset? // XXX vvv do we need separate field for traceFset if it is = prog.Fset?
traceFset: prog.Fset, traceFset: prog.Fset,
traceChecker: types.NewChecker(tconf, prog.Fset, tpkg, tinfo), traceChecker: types.NewChecker(tconf, prog.Fset, tpkg, tinfo),
tracePkg: tpkg, tracePkg: tpkg,
traceTypeInfo: tinfo, traceTypeInfo: tinfo,
} }
// preload original package files into tracing package // preload original package files into tracing package
...@@ -276,8 +278,8 @@ func packageTrace(prog *loader.Program, pkgi *loader.PackageInfo) (*Package, err ...@@ -276,8 +278,8 @@ func packageTrace(prog *loader.Program, pkgi *loader.PackageInfo) (*Package, err
// already preprocessed results with comments stripped, not original source. // already preprocessed results with comments stripped, not original source.
// Maybe in some time it will be possible to have AST of original source: // Maybe in some time it will be possible to have AST of original source:
// https://github.com/golang/go/issues/16623 // https://github.com/golang/go/issues/16623
for _, file := range pkgi.Files { // ast.File for _, file := range pkgi.Files { // ast.File
for _, commgroup := range file.Comments { // ast.CommentGroup for _, commgroup := range file.Comments { // ast.CommentGroup
for _, comment := range commgroup.List { // ast.Comment for _, comment := range commgroup.List { // ast.Comment
pos := prog.Fset.Position(comment.Slash) pos := prog.Fset.Position(comment.Slash)
//fmt.Printf("%v %q\n", pos, comment.Text) //fmt.Printf("%v %q\n", pos, comment.Text)
...@@ -333,17 +335,18 @@ func packageTrace(prog *loader.Program, pkgi *loader.PackageInfo) (*Package, err ...@@ -333,17 +335,18 @@ func packageTrace(prog *loader.Program, pkgi *loader.PackageInfo) (*Package, err
// byEventName provides []*traceEvent ordering by event name // byEventName provides []*traceEvent ordering by event name
type byEventName []*traceEvent type byEventName []*traceEvent
func (v byEventName) Less(i, j int) bool { return v[i].Name.Name < v[j].Name.Name } func (v byEventName) Less(i, j int) bool { return v[i].Name.Name < v[j].Name.Name }
func (v byEventName) Swap(i, j int) { v[i], v[j] = v[j], v[i] } func (v byEventName) Swap(i, j int) { v[i], v[j] = v[j], v[i] }
func (v byEventName) Len() int { return len(v) } func (v byEventName) Len() int { return len(v) }
// byPkgPath provides []*traceImport ordering by package path // byPkgPath provides []*traceImport ordering by package path
type byPkgPath []*traceImport type byPkgPath []*traceImport
func (v byPkgPath) Less(i, j int) bool { return v[i].PkgPath < v[j].PkgPath } func (v byPkgPath) Less(i, j int) bool { return v[i].PkgPath < v[j].PkgPath }
func (v byPkgPath) Swap(i, j int) { v[i], v[j] = v[j], v[i] } func (v byPkgPath) Swap(i, j int) { v[i], v[j] = v[j], v[i] }
func (v byPkgPath) Len() int { return len(v) } func (v byPkgPath) Len() int { return len(v) }
// SplitTests splits package into main and test parts, each covering trace-related things accordingly // SplitTests splits package into main and test parts, each covering trace-related things accordingly
func (p *Package) SplitTests() (testPkg *Package) { func (p *Package) SplitTests() (testPkg *Package) {
__ := *p __ := *p
...@@ -376,8 +379,6 @@ func (p *Package) SplitTests() (testPkg *Package) { ...@@ -376,8 +379,6 @@ func (p *Package) SplitTests() (testPkg *Package) {
return testPkg return testPkg
} }
// ---------------------------------------- // ----------------------------------------
// Argv returns comma-separated argument-list // Argv returns comma-separated argument-list
...@@ -401,7 +402,7 @@ func (te *traceEvent) ArgvTyped() string { ...@@ -401,7 +402,7 @@ func (te *traceEvent) ArgvTyped() string {
// ArgvTypedRelativeTo returns argument list with types qualified relative to specified package // ArgvTypedRelativeTo returns argument list with types qualified relative to specified package
// importedAs specifies under which name a package was imported, if name was explicitly set // importedAs specifies under which name a package was imported, if name was explicitly set
func (te *traceEvent) ArgvTypedRelativeTo(pkg *types.Package, importedAs map[string/*pkgpath*/]string/*pkgname*/) string { func (te *traceEvent) ArgvTypedRelativeTo(pkg *types.Package, importedAs map[string]string /*pkgpath -> pkgname*/) string {
argv := []string{} argv := []string{}
// default qualifier - relative to original package // default qualifier - relative to original package
...@@ -437,10 +438,9 @@ func (te *traceEvent) ArgvTypedRelativeTo(pkg *types.Package, importedAs map[str ...@@ -437,10 +438,9 @@ func (te *traceEvent) ArgvTypedRelativeTo(pkg *types.Package, importedAs map[str
return strings.Join(argv, ", ") return strings.Join(argv, ", ")
} }
// NeedPkgv returns packages that are needed for argument types // NeedPkgv returns packages that are needed for argument types
func (te *traceEvent) NeedPkgv() []string { func (te *traceEvent) NeedPkgv() []string {
pkgset := StrSet{/*pkgpath*/} pkgset := StrSet{ /*pkgpath*/ }
qf := func(pkg *types.Package) string { qf := func(pkg *types.Package) string {
// if we are called - pkg is used // if we are called - pkg is used
pkgset.Add(pkg.Path()) pkgset.Add(pkg.Path())
...@@ -465,7 +465,6 @@ func (ti *traceImport) ImportSpec() string { ...@@ -465,7 +465,6 @@ func (ti *traceImport) ImportSpec() string {
return t return t
} }
// traceEventCodeTmpl is code template generated for one trace event // traceEventCodeTmpl is code template generated for one trace event
var traceEventCodeTmpl = template.Must(template.New("traceevent").Parse(` var traceEventCodeTmpl = template.Must(template.New("traceevent").Parse(`
// traceevent: {{.Name}}({{.ArgvTyped}}) // traceevent: {{.Name}}({{.ArgvTyped}})
...@@ -614,10 +613,10 @@ func NewProgram(ctxt *build.Context, cwd string) *Program { ...@@ -614,10 +613,10 @@ func NewProgram(ctxt *build.Context, cwd string) *Program {
p := &Program{} p := &Program{}
p.loaderConf = &loader.Config{ p.loaderConf = &loader.Config{
ParserMode: parser.ParseComments, ParserMode: parser.ParseComments,
TypeCheckFuncBodies: func(path string) bool { return false }, TypeCheckFuncBodies: func(path string) bool { return false },
Build: &ctxtNoZTrace, Build: &ctxtNoZTrace,
Cwd: cwd, Cwd: cwd,
} }
return p return p
...@@ -671,7 +670,8 @@ func (p *Program) ImportWithTests(pkgpath string) (prog *loader.Program, pkgi *l ...@@ -671,7 +670,8 @@ func (p *Program) ImportWithTests(pkgpath string) (prog *loader.Program, pkgi *l
if len(prog.Created) > 0 { if len(prog.Created) > 0 {
xtestPkgi = prog.Created[0] xtestPkgi = prog.Created[0]
} }
for _, pkgi = range prog.Imported {} for _, pkgi = range prog.Imported {
}
return prog, pkgi, xtestPkgi, nil return prog, pkgi, xtestPkgi, nil
} }
...@@ -721,14 +721,13 @@ func tracegen(pkgpath string, ctxt *build.Context, cwd string) error { ...@@ -721,14 +721,13 @@ func tracegen(pkgpath string, ctxt *build.Context, cwd string) error {
return xerr.Merge(err1, err2, err3) return xerr.Merge(err1, err2, err3)
} }
// tracegen1 generates code according to tracing directives for a (sub)package @pkgpath // tracegen1 generates code according to tracing directives for a (sub)package @pkgpath
// subpackage is either original package, testing code, or external test package // subpackage is either original package, testing code, or external test package
func tracegen1(P *Program, tpkg *Package, pkgdir string, kind string) error { func tracegen1(P *Program, tpkg *Package, pkgdir string, kind string) error {
var err error var err error
// write ztrace.go with code generated for trace events and imports // write ztrace.go with code generated for trace events and imports
ztrace_go := filepath.Join(pkgdir, "ztrace" + kind + ".go") ztrace_go := filepath.Join(pkgdir, "ztrace"+kind+".go")
if len(tpkg.Eventv) == 0 && len(tpkg.Importv) == 0 { if len(tpkg.Eventv) == 0 && len(tpkg.Importv) == 0 {
err = removeFile(ztrace_go) err = removeFile(ztrace_go)
if err != nil { if err != nil {
...@@ -797,11 +796,12 @@ func tracegen1(P *Program, tpkg *Package, pkgdir string, kind string) error { ...@@ -797,11 +796,12 @@ func tracegen1(P *Program, tpkg *Package, pkgdir string, kind string) error {
} }
// verify export hash so link fails if it gets out of sync with imported package // verify export hash so link fails if it gets out of sync with imported package
err = traceEventImportCheckTmpl.Execute(text, struct{ err = traceEventImportCheckTmpl.Execute(text, struct {
ImportSpec *traceImport ImportSpec *traceImport
ExportHash string}{ ExportHash string
timport, }{
traceExportHash(impPkg, ""/*regular package*/)}) timport,
traceExportHash(impPkg, "" /*regular package*/)})
text.emit("") text.emit("")
...@@ -809,10 +809,10 @@ func tracegen1(P *Program, tpkg *Package, pkgdir string, kind string) error { ...@@ -809,10 +809,10 @@ func tracegen1(P *Program, tpkg *Package, pkgdir string, kind string) error {
for _, event := range impPkg.Eventv { for _, event := range impPkg.Eventv {
needPkg.Add(event.NeedPkgv()...) needPkg.Add(event.NeedPkgv()...)
importedEvent := traceImported{ importedEvent := traceImported{
traceEvent: event, traceEvent: event,
ImportSpec: timport, ImportSpec: timport,
ImporterPkg: tpkg.Pkgi.Pkg, ImporterPkg: tpkg.Pkgi.Pkg,
ImportedAs: importedAs, ImportedAs: importedAs,
} }
err = traceEventImportTmpl.Execute(text, importedEvent) err = traceEventImportTmpl.Execute(text, importedEvent)
if err != nil { if err != nil {
...@@ -822,7 +822,7 @@ func tracegen1(P *Program, tpkg *Package, pkgdir string, kind string) error { ...@@ -822,7 +822,7 @@ func tracegen1(P *Program, tpkg *Package, pkgdir string, kind string) error {
} }
// finish prologue with needed imports // finish prologue with needed imports
needPkg.Delete(tpkg.Pkgi.Pkg.Path()) // our pkg - no need to import needPkg.Delete(tpkg.Pkgi.Pkg.Path()) // our pkg - no need to import
needPkgv := needPkg.Itemv() needPkgv := needPkg.Itemv()
if len(needPkgv) > 0 { if len(needPkgv) > 0 {
prologue.emit("") prologue.emit("")
...@@ -846,7 +846,7 @@ func tracegen1(P *Program, tpkg *Package, pkgdir string, kind string) error { ...@@ -846,7 +846,7 @@ func tracegen1(P *Program, tpkg *Package, pkgdir string, kind string) error {
} }
// write empty ztrace.s so go:linkname works, if there are trace imports // write empty ztrace.s so go:linkname works, if there are trace imports
ztrace_s := filepath.Join(pkgdir, "ztrace" + kind + ".s") ztrace_s := filepath.Join(pkgdir, "ztrace"+kind+".s")
if len(tpkg.Importv) == 0 { if len(tpkg.Importv) == 0 {
err = removeFile(ztrace_s) err = removeFile(ztrace_s)
} else { } else {
...@@ -875,10 +875,10 @@ func traceExport(tpkg *Package, kind string) []byte { ...@@ -875,10 +875,10 @@ func traceExport(tpkg *Package, kind string) []byte {
for _, event := range tpkg.Eventv { for _, event := range tpkg.Eventv {
importedEvent := traceImported{ importedEvent := traceImported{
traceEvent: event, traceEvent: event,
ImportSpec: &traceImport{PkgName: pkgname, PkgPath: pkgpath}, ImportSpec: &traceImport{PkgName: pkgname, PkgPath: pkgpath},
ImporterPkg: nil, // from nowhere ImporterPkg: nil, // from nowhere
ImportedAs: nil, // no naming for imports ImportedAs: nil, // no naming for imports
} }
err := traceEventImportTmpl.Execute(exported, importedEvent) err := traceEventImportTmpl.Execute(exported, importedEvent)
if err != nil { if err != nil {
...@@ -896,7 +896,6 @@ func traceExportHash(tpkg *Package, kind string) string { ...@@ -896,7 +896,6 @@ func traceExportHash(tpkg *Package, kind string) string {
return fmt.Sprintf("%x", sha1.Sum(traceExport(tpkg, kind))) return fmt.Sprintf("%x", sha1.Sum(traceExport(tpkg, kind)))
} }
func main() { func main() {
log.SetFlags(0) log.SetFlags(0)
log.SetPrefix("gotrace: ") log.SetPrefix("gotrace: ")
......
...@@ -17,15 +17,18 @@ ...@@ -17,15 +17,18 @@
// See COPYING file for full licensing terms. // See COPYING file for full licensing terms.
// See https://www.nexedi.com/licensing for rationale and options. // See https://www.nexedi.com/licensing for rationale and options.
// Package tracing provides runtime and usage support for Go tracing facilities /*
// TODO describe how to define tracepoints Package tracing provides runtime and usage support for Go tracing facilities
// TODO doc:
// - tracepoints TODO describe how to define tracepoints
// - probes TODO doc:
// - probes can be attached/detached to/from tracepoints - tracepoints
// - probes
// TODO document //trace:event & //trace:import - probes can be attached/detached to/from tracepoints
// TODO document `gotrace gen` + `gotrace list`
TODO document //trace:event & //trace:import
TODO document `gotrace gen` + `gotrace list`
*/
package tracing package tracing
import ( import (
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment