Beispiel #1
0
// genRootCalls generates the synthetic root of the callgraph and the
// initial calls from it to the analysis scope, such as main, a test
// or a library.
//
func (a *analysis) genRootCalls() *cgnode {
	r := ssa.NewFunction("<root>", new(types.Signature), "root of callgraph")
	r.Prog = a.prog // hack.
	r.Enclosing = r // hack, so Function.String() doesn't crash
	r.String()      // (asserts that it doesn't crash)
	root := a.makeCGNode(r, 0, nil)

	// TODO(adonovan): make an ssa utility to construct an actual
	// root function so we don't need to special-case site-less
	// call edges.

	// For each main package, call main.init(), main.main().
	for _, mainPkg := range a.config.Mains {
		main := mainPkg.Func("main")
		if main == nil {
			panic(fmt.Sprintf("%s has no main function", mainPkg))
		}

		targets := a.addOneNode(main.Signature, "root.targets", nil)
		site := &callsite{targets: targets}
		root.sites = append(root.sites, site)
		for _, fn := range [2]*ssa.Function{mainPkg.Func("init"), main} {
			if a.log != nil {
				fmt.Fprintf(a.log, "\troot call to %s:\n", fn)
			}
			a.copy(targets, a.valueNode(fn), 1)
		}
	}

	return root
}
Beispiel #2
0
// newMethod creates a new method of the specified name, package and receiver type.
func newMethod(pkg *ssa.Package, recvType types.Type, name string) *ssa.Function {
	// TODO(adonovan): fix: hack: currently the only part of Signature
	// that is needed is the "pointerness" of Recv.Type, and for
	// now, we'll set it to always be false since we're only
	// concerned with rtype.  Encapsulate this better.
	sig := types.NewSignature(nil, types.NewVar(token.NoPos, nil, "recv", recvType), nil, nil, false)
	fn := ssa.NewFunction(name, sig, "fake reflect method")
	fn.Pkg = pkg
	fn.Prog = pkg.Prog
	return fn
}