Commit efe2831c authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 8c5eab16
...@@ -734,7 +734,7 @@ func (c *Conn) err(op string, e error) error { ...@@ -734,7 +734,7 @@ func (c *Conn) err(op string, e error) error {
// ---- exchange of messages ---- // ---- exchange of messages ----
//trace:event traceConnRecv(c *Conn, msg Msg) //trace:event traceConnRecv(c *Conn /*aaa*/, msg Msg)
//trace:event traceConnSend(c *Conn, msg Msg) // XXX -> traceConnSendPre ? //trace:event traceConnSend(c *Conn, msg Msg) // XXX -> traceConnSendPre ?
// Recv receives message // Recv receives message
......
...@@ -28,6 +28,7 @@ package main ...@@ -28,6 +28,7 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"go/ast"
"go/parser" "go/parser"
"go/token" "go/token"
"log" "log"
...@@ -41,27 +42,53 @@ import ( ...@@ -41,27 +42,53 @@ import (
// traceEvent represents 1 trace:event definition // traceEvent represents 1 trace:event definition
type traceEvent struct { type traceEvent struct {
Pkg loader.PackageInfo // XXX or loader.PackageInfo.Pkg (*types.Package) ? //Pkg loader.PackageInfo // XXX or loader.PackageInfo.Pkg (*types.Package) ?
Pos token.Position //Pos token.Position
Text string //Text string
Name string //Name string
Argv string //Argv string
*ast.FuncDecl
}
// TypedArgv returns argument list with types
func (te *traceEvent) TypedArgv() string {
//format.Node(&buf, fset, te.FuncDecl.Params)
for _, field := range te.FuncDecl.Params.List {
namev := []string{}
for _, name := range field.Names {
namev = append(namev, name)
}
}
}
// Argv returns comma-separated argument-list
func (te *traceEvent) Argv() string {
argv := []string{}
for _, field := range te.FuncDecl.Params.List {
for _, name := range field.Names {
argv = append(argv, name)
}
}
return strings.Join(argv, ", ")
} }
// 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].Text < v[j].Text } //func (v byEventName) Less(i, j int) bool { return v[i].Text < v[j].Text }
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) }
// traceEventCode is code template for one trace event // traceEventCode is code template for one trace event
const traceEventCode = ` const traceEventCode = `
// traceevent: {{.Text}} XXX .Text -> .Name.Signature // traceevent: {{.Name}}({{.Type.Params}}) XXX or better raw .Text (e.g. comments)
XXX .Signature -> .Argvdef
type _t_{{.Name}} struct { type _t_{{.Name}} struct {
tracing.Probe tracing.Probe
probefunc func{{.Argv}} probefunc func{{.Type.Params}}
} }
var _{{.Name}} *_t_{{.Name}} var _{{.Name}} *_t_{{.Name}}
...@@ -69,20 +96,20 @@ var _{{.Name}} *_t_{{.Name}} ...@@ -69,20 +96,20 @@ var _{{.Name}} *_t_{{.Name}}
{{/* after https://github.com/golang/go/issues/19348 is done this separate {{/* after https://github.com/golang/go/issues/19348 is done this separate
* checking function will be inlined and tracepoint won't cost a function * checking function will be inlined and tracepoint won't cost a function
* call when it is disabled */}} * call when it is disabled */}}
func {{.Name}}{{.Argv}} { func {{.Name}}{{.Type.Params}} {
if _{{.Name}} != nil { if _{{.Name}} != nil {
_{{.Name}}_run(...) // XXX argv without types here _{{.Name}}_run({{.Type.Params}}) // XXX argv without types here
} }
} }
func _{{.Name}}{{.Argv}}_run({{.Argv}}) { func _{{.Name}}{{.Argv}}_run({{.Argv}}) {
for p := _{{.Name}}; p != nil; p = (*_t_{{.Name}})(unsafe.Pointer(p.Next())) { for p := _{{.Name}}; p != nil; p = (*_t_{{.Name}})(unsafe.Pointer(p.Next())) {
p.probefunc(...) // XXX argv without types here p.probefunc({{.Type.Params}}) // XXX argv without types here
} }
} }
// XXX ... is only types from argv // XXX ... is only types from argv
func {{.Name}}_Attach(pg *tracing.ProbeGroup, probe func(...)) *tracing.Probe { func {{.Name}}_Attach(pg *tracing.ProbeGroup, probe func({{.Type.Params}})) *tracing.Probe {
p := _t_{{.Name}}{probefunc: probe} p := _t_{{.Name}}{probefunc: probe}
tracing.AttachProbe(pg, (**tracing.Probe)(unsafe.Pointer(&_{{.Name}}), &p.Probe) tracing.AttachProbe(pg, (**tracing.Probe)(unsafe.Pointer(&_{{.Name}}), &p.Probe)
return &p.Probe return &p.Probe
...@@ -91,6 +118,37 @@ func {{.Name}}_Attach(pg *tracing.ProbeGroup, probe func(...)) *tracing.Probe { ...@@ -91,6 +118,37 @@ func {{.Name}}_Attach(pg *tracing.ProbeGroup, probe func(...)) *tracing.Probe {
var traceEventCodeTmpl = template.Must(template.New("traceevent").Parse(traceEventCode)) var traceEventCodeTmpl = template.Must(template.New("traceevent").Parse(traceEventCode))
// parseTraceEvent parses trace event definition into XXX
// text is text argument after "//trace:event "
func parseTraceEvent(text string) (*traceEvent, error) {
if !strings.HasPrefix(text, "trace") {
return nil, fmt.Errorf("trace event must start with \"trace\"") // XXXpos
}
// trace trace event definition as func declaration
text = "package xxx\nfunc " + text // XXX
fset := token.NewFileSet() // XXX
filename := "tracefunc.go" // XXX
f, err := parser.ParseFile(fset, filename, text, 0)
if err != nil {
return nil, err
}
if len(f.Decls) != 1 {
return nil, fmt.Errorf("trace event must be func-like")
}
declf, ok := f.Decls[0].(*ast.FuncDecl)
if !ok {
return nil, fmt.Errorf("trace event must be func-like, not %v", f.Decls[0])
}
if declf.Type.Results != nil {
return nil, fmt.Errorf("trace event must not return results")
}
return &traceEvent{declf}, nil
}
// tracegen generates code according to tracing directives in a package @ pkgpath // tracegen generates code according to tracing directives in a package @ pkgpath
func tracegen(pkgpath string) error { func tracegen(pkgpath string) error {
// XXX typechecking is much slower than parsing + we don't need to // XXX typechecking is much slower than parsing + we don't need to
...@@ -111,7 +169,7 @@ func tracegen(pkgpath string) error { ...@@ -111,7 +169,7 @@ func tracegen(pkgpath string) error {
pkg := lprog.InitialPackages()[0] pkg := lprog.InitialPackages()[0]
//fmt.Println(pkg) //fmt.Println(pkg)
eventv := []traceEvent{} // events this package defines eventv := []*traceEvent{} // events this package defines
importv := map[/*pkgpath*/string][]traceEvent{} // events this package imports importv := map[/*pkgpath*/string][]traceEvent{} // events this package imports
// go through files of the package and process //trace: directives // go through files of the package and process //trace: directives
...@@ -138,10 +196,11 @@ func tracegen(pkgpath string) error { ...@@ -138,10 +196,11 @@ func tracegen(pkgpath string) error {
directive, arg := textv[0], textv[1] directive, arg := textv[0], textv[1]
switch directive { switch directive {
case "//trace:event": case "//trace:event":
if !strings.HasPrefix(arg, "trace") { event, err := parseTraceEvent(arg)
log.Fatalf("%v: trace event must start with \"trace\"", pos) if err != nil {
log.Fatalf("%v: %v", pos, err)
} }
event := traceEvent{Pos: pos, Text: arg, Name: "name", Argv: "argv"} // XXX
eventv = append(eventv, event) eventv = append(eventv, event)
case "//trace:import": case "//trace: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