Motivation:
Previously, we assumed that the set of types for which a
complete method set (containing all synthesized wrapper
functions) is required at runtime was the set of types
used as operands to some *ssa.MakeInterface instruction.
In fact, this is an underapproximation because types can
be derived from other ones via reflection, and some of
these may need methods. The reflect.Type API allows *T to
be derived from T, and these may have different method
sets. Reflection also allows almost any subcomponent of a
type to be accessed (with one exception: given T, defined
'type T struct{S}', you can reach S but not struct{S}).
As a result, the pointer analysis was unable to generate
all necessary constraints before running the solver,
causing a crash when reflection derives types whose
methods are unavailable. (A similar problem would afflict
an ahead-of-time compiler based on ssa. The ssa/interp
interpreter was immune only because it does not require
all wrapper methods to be created before execution
begins.)
Description:
This change causes the SSA builder to record, for each
package, the set of all types with non-empty method sets that
are referenced within that package. This set is accessed via
Packages.TypesWithMethodSets(). Program.TypesWithMethodSets()
returns its union across all packages.
The set of references that matter are:
- types of operands to some MakeInterface instruction (as before)
- types of all exported package members
- all subcomponents of the above, recursively.
This is a conservative approximation to the set of types
whose methods may be called dynamically.
We define the owning package of a type as follows:
- the owner of a named type is the package in which it is defined;
- the owner of a pointer-to-named type is the owner of that named type;
- the owner of all other types is nil.
A package must include the method sets for all types that it
owns, and all subcomponents of that type that are not owned by
another package, recursively. Types with an owner appear in
exactly one package; types with no owner (such as struct{T})
may appear within multiple packages.
(A typical Go compiler would emit multiple copies of these
methods as weak symbols; a typical linker would eliminate
duplicates.)
Also:
- go/types/typemap: implement hash function for *Tuple.
- pointer: generate nodes/constraints for all of
ssa.Program.TypesWithMethodSets().
Add rtti.go regression test.
- Add API test of Package.TypesWithMethodSets().
- Set Function.Pkg to nil (again) for wrapper functions,
since these may be shared by many packages.
- Remove a redundant logging statement.
- Document that ssa CREATE phase is in fact sequential.
Fixesgolang/go#6605
R=gri
CC=golang-dev
https://golang.org/cl/14920056
The new method is functionally identical to typeCheck, and
obviates the LoadMainPackage method.
Updated all clients.
Fixes bug 6561.
R=gri
CC=golang-dev
https://golang.org/cl/14494051
Motivation: pointer analysis tools (like the oracle) want the
user to specify a set of initial packages, like 'go test'.
This change enables the user to specify a set of packages on
the command line using importer.LoadInitialPackages(args).
Each argument is interpreted as either:
- a comma-separated list of *.go source files together
comprising one non-importable ad-hoc package.
e.g. "src/pkg/net/http/triv.go" gives us [main].
- an import path, denoting both the imported package
and its non-importable external test package, if any.
e.g. "fmt" gives us [fmt, fmt_test].
Current type-checker limitations mean that only the first
import path may contribute tests: multiple packages augmented
by *_test.go files could create import cycles, which 'go test'
avoids by building a separate executable for each one.
That approach is less attractive for static analysis.
Details: (many files touched, but importer.go is the crux)
importer:
- PackageInfo.Importable boolean indicates whether
package is importable.
- un-expose Importer.Packages; expose AllPackages() instead.
- CreatePackageFromArgs has become LoadInitialPackages.
- imports() moved to util.go, renamed importsOf().
- InitialPackagesUsage usage message exported to clients.
- the package name for ad-hoc packages now comes from the
'package' decl, not "main".
ssa.Program:
- added CreatePackages() method
- PackagesByPath un-exposed, renamed 'imported'.
- expose AllPackages and ImportedPackage accessors.
oracle:
- describe: explain and workaround a go/types bug.
Misc:
- Removed various unnecessary error.Error() calls in Printf args.
R=crawshaw
CC=golang-dev
https://golang.org/cl/13579043
1. ParseFiles (in util.go) parses each file in its own goroutine.
2. (*Importer).LoadPackage asynchronously prefetches the
import graph by scanning the imports of each loaded package
and calling LoadPackage on each one.
LoadPackage is now thread-safe and idempotent: it uses a
condition variable per package; the first goroutine to
request a package becomes responsible for loading it and
broadcasts to the others (waiting) when it becomes ready.
ssadump runs 34% faster when loading the oracle.
Also, refactorings:
- delete SourceLoader mechanism; just expose go/build.Context directly.
- CreateSourcePackage now also returns an error directly,
rather than via PackageInfo.Err, since every client wants that.
R=crawshaw
CC=golang-dev
https://golang.org/cl/13509045
CanonicalPos was inadequate since many pairs of instruction share the same pos (e.g. Allocs and Phis). Instead, we generalize the DebugRef instruction to associate not just Idents but Exprs with ssa.Values.
We no longer store any DebugRefs for constant expressions, to save space. (The type and value of such expressions can be obtained by other means, at a cost in complexity.)
Function.ValueForExpr queries the DebugRef info to return the ssa.Value of a given Expr.
Added tests.
Also:
- the DebugInfo flag is now per package, not global.
It must be set between Create and Build phases if desired.
- {Value,Instruction}.Pos() documentation updated: we still maintain
this information in the instruction stream even in non-debug mode,
but we make fewer claims about its invariants.
- Go and Defer instructions can now use their respective go/defer
token positions (not the call's lparen), so they do.
- SelectState:
Posn token.Pos indicates the <- position
DebugNode ast.Expr is the send stmt or receive expr.
- In building SelectStmt, we introduce extra temporaries in debug
mode to hold the result of the receive in 'case <-ch' even though
this value isn't ordinarily needed.
- Use *SelectState (indirectly) since the struct is getting bigger.
- Document some missing instructions in doc.go.
R=gri
CC=golang-dev
https://golang.org/cl/12147043
stdlib_test runs the builder (in sanity-checking mode) over
the Go standard library. It also prints some stats about
the time and memory usage.
Also:
- importer.LoadPackage too (not just doImport) must consult
the cache to avoid creating duplicate Package instances for
the same import path when called serially from a test.
- importer: skip empty directories without an error.
- importer: print all errors, not just the first.
- visit.go: added AllFunctions utility for enumerating all
Functions in a Program.
- ssa.MethodSet is not safe to expose from the package since
it must be accessed under an (inaccessible) lock. (!!!)
This CL makes it unexported and restricts its use to the
single function Program.LookupMethod().
- Program.MethodSet() has gone.
Clients should instead iterate over the types.MethodSet
and call LookupMethod.
- Package.DumpTo(): improved efficiency of methodset printing
(by not creating wrappers) and accuracy (by showing * on
receiver type only when necessary).
- Program.CreatePackage: documented precondition and added
assertion.
R=gri
CC=golang-dev
https://golang.org/cl/12058048
We now use LookupFieldOrMethod for all SelectorExprs, and
simplify the logic to discriminate the various cases.
We inline static calls to promoted/indirected functions,
dramatically reducing the number of functions created.
More tests are needed, but I'd like to submit this as-is.
In this CL, we:
- rely less on Id strings. Internally we now use
*types.Method (and its components) almost everywhere.
- stop thinking of types.Methods as objects. They don't
have stable identities. (Hopefully they will become
plain-old structs soon.)
- eliminate receiver indirection wrappers:
indirection and promotion are handled together by makeWrapper.
- Handle the interactions of promotion, indirection and
abstract methods much more cleanly.
- support receiver-bound interface method closures.
- break up builder.selectField so we can re-use parts
(emitFieldSelection).
- add importer.PackageInfo.classifySelector utility.
- delete interfaceMethodIndex()
- delete namedTypeMethodIndex()
- delete isSuperInterface() (replaced by types.IsAssignable)
- call memberFromObject on each declared concrete method's
*types.Func, not on every Method frem each method set, in the
CREATE phase for packages loaded by gcimporter.
go/types:
- document Func, Signature.Recv() better.
- use fmt in {Package,Label}.String
- reimplement Func.String to be prettier and to include method
receivers.
API changes:
- Function.method now holds the types.Method (soon to be
not-an-object) for synthetic wrappers.
- CallCommon.Method now contains an abstract (interface)
method object; was an abstract method index.
- CallCommon.MethodId() gone.
- Program.LookupMethod now takes a *Method not an Id string.
R=gri
CC=golang-dev
https://golang.org/cl/11674043
ssa:
- Prog.CreatePackages inlined into all callers.
- Prog.CreatePackage is now exposed; idempotent; and checks for errors.
- '*address' not 'address' now implements lvalue (since it's 6 words).
- removed types.Method case from createMemberFromObject.
importer:
- added importer.PackageInfo.String method.
- simplifed importer.PackageInfo by putting types.Info in it.
- removed obsolete precondition from IsType.
R=gri
CC=golang-dev
https://golang.org/cl/11408045
This exposed a bug: we weren't creating Functions for methods
of imported named types.
Also:
- simplification: 'candidate' no longer contains 'concrete *Function'.
We look this up on demand.
NB: this CL contains a copy of CL 10935047 (use of typemap);
will submit/sync/resolve soon.
R=gri
CC=golang-dev
https://golang.org/cl/11051043