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
Also:
- Implement Program.FuncValue for interface methods (+ test).
- go/types.Object.String(): don't package-qualify names unless
they are package level objects---otherwise you see "main.x" for
locals, struct fields, etc.
- go/types.Func.String(): don't assume Type() is *Signature;
it could be *Builtin.
R=gri
CC=golang-dev
https://golang.org/cl/12058045
buildDecl was visiting all decls in source order, but the spec
calls for visiting all vars and init() funcs in order, then
all remaining functions. These two passes are now called
buildInit(), buildFuncDecl().
+ Test.
Also:
- Added workaround to gcimporter for Func with pkg==nil.
- Prog.concreteMethods has been merged into Pkg.values.
- Prog.concreteMethod() renamed declaredFunc().
- s/mfunc/obj/ (name cleanup from recent gri CL)
R=gri
CC=golang-dev
https://golang.org/cl/12030044
A Method corresponds to a MethodVal Selection;
so the explicit Method object is not needed anymore.
- moved Selection code into separate file
- implemented Selection.String()
- improved and more consistent documentation
R=adonovan
CC=golang-dev
https://golang.org/cl/11950043
methprom.go covers method promotion.
Found bug: receiver() requires a following load under some
circumstances.
ifaceconv.go covers interface conversion.
Found bug: confusion about infallible and fallible conversions
led to use of TypeAssert in emitConv, which should never fail.
Changed semantics of ChangeInterface to make it infallible
and made some simplifications.
Also in this CL:
- SelectState.Pos now records the position of the
the '<-' operator for sends/receives done by a Select.
R=gri
CC=golang-dev
https://golang.org/cl/11931044
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
Now, in a "switch y := x.(type)", there is no object for the
outer y, only implicit objects, one per case (including
default).
Also: don't set obj=nil for blank idents (workaround suggested by gri).
R=gri
CC=golang-dev
https://golang.org/cl/11564046
- implemented objset for tracking duplicates of fields and methods
which permitted a simpler and faster scope implementation in turn
- related cleanups and internal renames
- fixed a couple of identifier reporting bugs
Speed of type-checking itself increased by almost 10%
(from ~71Kloc/s to ~78Kloc/s on one machine, measured
via go test -run=Self).
R=adonovan
CC=golang-dev
https://golang.org/cl/11750043
Reduces by 94% the number of wrappers created during the tests.
(No appreciable difference in running time, sadly.)
R=gri
CC=golang-dev
https://golang.org/cl/11619043
Details:
- emitImplicitSelections now emits common code for implicit
field selections in both method and field lookups.
The last iteration over the LookupFieldOrMethod indices---the explicit,
final index---is handled by the caller.
- anonFieldPath, candidate and the BFS algo in buildMethodSet are all gone.
R=gri
CC=golang-dev
https://golang.org/cl/11576045
Temporarily remove Field objects in favor of Vars for struct fields.
In forthcoming CL, Fields will play the symmetric role to Methods, and
serve as lookup results including index information.
R=adonovan
CC=golang-dev
https://golang.org/cl/11594043
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
- fixed method set computation
- lazily compute it for a type on demand
- lazy allocation of various temporary maps
Also:
- removed Interface.IsEmpty, Scope.IsEmpty
(these convenience functions didn't carry their weight)
- cosmetic changes
Next:
- consolidate various lookup APIs
- use lazily computed method sets for various checks
instead of individual lookups
R=adonovan
CC=golang-dev
https://golang.org/cl/11385044
(Motivation: "Literal" is a syntactic property, not a semantic one.)
Also: delete a "TODO: opt" that the lifting pass already does for us.
R=gri
CC=golang-dev
https://golang.org/cl/11351043
- removed a number of obsolete TODO(gri) comments.
- bring ssa.DefaultType back into sync with types.defaultType.
- re-enable types.Package.Path()!="" assertion.
- use Path() (not reflect pointer) in sort routine.
- make interp.checkInterface use types.MissingMethod.
- un-export ssa.MakeId function.
- inline pointer() into all callers, and delete.
- enable two more interp_tests: $GOROOT/test/{method3,cmp}.go
- add links to bugs to other interp_tests.
- add runtime.NumCPU to ssa/interp/externals.go
R=gri
CC=golang-dev
https://golang.org/cl/11353043
This CL adds three new functions to determine the SSA Value
for a given syntactic var, func or const object:
Program.{Const,Func,Var}Value.
Since constants and functions are immutable, the first
two only need a types.Object; but each distinct
reference to a var may return a distinct Value, so the third
requires an ast.Ident parameter too.
Debug information for local vars is encoded in the
instruction stream in the form of DebugRef instructions,
which are a no-op but relate their operand to a particular
ident in the AST. The beauty of this approach is that it
naturally stays consistent during optimisation passes
(e.g. lifting) without additional bookkeeping.
DebugRef instructions are only generated if the DebugMode
builder flag is set; I plan to make the policy more fine-
grained (per function).
DebugRef instructions are inserted for:
- expr(Ident) for rvalue idents
- address.store() for idents that update an lvalue
- address.address() for idents that take address of lvalue
(this new method replaces all uses of lval.(address).addr)
- expr() for all constant expressions
- local ValueSpecs with implicit zero initialization (no RHS)
(this case doesn't call store() or address())
To ensure we don't forget to emit debug info for uses of Idents,
we must use the lvalue mechanism consistently. (Previously,
many simple cases had effectively inlined these functions.)
Similarly setCallFunc no longer inlines expr(Ident).
Also:
- Program.Value() has been inlined & specialized.
- Program.Package() has moved nearer the new lookup functions.
- refactoring: funcSyntax has lost paramFields, resultFields;
gained funcType, which provides access to both.
- add package-level constants to Package.values map.
- opt: don't call localValueSpec for constants.
(The resulting code is always optimised away.)
There are a number of comments asking whether Literals
should have positions. Will address in a follow-up.
Added tests of all interesting cases.
R=gri
CC=golang-dev
https://golang.org/cl/11259044
Objects:
- provide IsExported, SameName, uniqueName methods
- clean up a lot of dependent code
Scopes:
- don't add children to Universe scope (!)
- document Node, WriteTo
Types:
- remove Deref in favor of internal function deref
ssa, ssa/interp:
- introduced local deref, adjusted code
- fixed some "Underlying" bugs (pun intended)
R=adonovan
CC=golang-dev
https://golang.org/cl/11232043
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
Yields a ~20% improvement in SSA construction time.
Also: better names for promotion wrapper functions.
R=gri
CC=golang-dev
https://golang.org/cl/11050043
Details:
- reintroduce interp.asUint64: it's not sound to use only the
low 32 bits of y, which is what asInt gives us, when GOARCH=386.
- instead, emit a uint64 conversion when y is not unsigned
(i.e. a signed var, or an untyped constant).
Tested on 386 & x86-64.
R=gri
CC=golang-dev
https://golang.org/cl/11023043
Various bug fixes:
- don't allow := to redeclare non-variables
- don't permit a comma-ok expression as a two-value function return
Lots of dead code removed.
Fixesgolang/go#5500.
R=adonovan
CC=golang-dev
https://golang.org/cl/10792044
We use the new field to determine whether or not a function is
synthetic, not Pos() == 0, so synthetic functions can have
positions too.
R=gri
CC=golang-dev
https://golang.org/cl/10916044
Before, all values received on some channel by Select would
flow to an empty interface, creating a spurious confluence for
flow analyses. Now, the tuple returned by Select has one
component for each 'receive' case.
Also, fixes:
- Removed workarounds for now-fixed typechecker bug in FuncLit+TypeAssert.
- sanity check that all Value Instructions have non-nil Type().
- Convert: document and sanity-check that at least one of the types is basic.
Also, other things to help clients:
- Define CallInstruction interface: common parts of Call, Go, Defer.
- Add CallCommon.Signature() method.
- Literal.Pos() is now populated.
R=gri
CC=golang-dev
https://golang.org/cl/10505043
methodIndex() utility was split and specialized to its two
cases, *Interface vs *Named, which are logically quite
different.
We can't memoize promotion wrappers yet; we need typemap.
Terminology:
- "thunks" are now "wrappers"
- "bridge methods" are now "promotion wrappers"
Where the diff is messy it's just because of indentation.
R=gri
CC=golang-dev
https://golang.org/cl/10282043
Method sets:
- Simplify CallCommon.
Avoid the implicit copy when calling a T method on a *T
receiver. This simplifies clients. Instead we generate
"indirection wrapper" functions that do this (like gc does).
New invariant:
m's receiver type is exactly T for all m in MethodSet(T)
- MakeInterface no longer holds the concrete type's MethodSet.
We can defer its computation this way.
- ssa.Type now just wraps a types.TypeName object.
MethodSets are computed as needed, not eagerly.
Position info:
- new CanonicalPos utility maps ast.Expr to canonical
token.Pos, as returned by {Instruction,Value}.Pos() methods.
- Don't set posn for implicit operations (e.g. varargs array alloc)
- Set position info for ChangeInterface and Slice instructions.
Cosmetic:
- add Member.Token() method
- simplify isPointer
- Omit words "interface", "slice" when printing MakeInterface,
MakeSlice; the type is enough.
- Comments on PathEnclosingInterval.
- Remove Function.FullName() where implicit String() suffices.
Also:
- Exposed NewLiteral to clients.
- Added ssa.Instruction.Parent() *Function
Added ssa.BasicBlock.Parent() *Function.
Added Sanity checks for above.
R=golang-dev, gri
CC=golang-dev
https://golang.org/cl/10166045