go/ssa: gofmt
Gofmt to update doc comments to the new formatting.
(There are so many files in x/tools I am breaking up the
gofmt'ing into multiple CLs.)
For golang/go#51082.
Change-Id: I58a534f3e518dad2d3a867f81b08a551a76bd423
Reviewed-on: https://go-review.googlesource.com/c/tools/+/399362
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Russ Cox <rsc@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
diff --git a/go/ssa/block.go b/go/ssa/block.go
index 35f3173..28170c7 100644
--- a/go/ssa/block.go
+++ b/go/ssa/block.go
@@ -19,14 +19,12 @@
// String returns a human-readable label of this block.
// It is not guaranteed unique within the function.
-//
func (b *BasicBlock) String() string {
return fmt.Sprintf("%d", b.Index)
}
// emit appends an instruction to the current basic block.
// If the instruction defines a Value, it is returned.
-//
func (b *BasicBlock) emit(i Instruction) Value {
i.setBlock(b)
b.Instrs = append(b.Instrs, i)
@@ -63,7 +61,6 @@
// replacePred replaces all occurrences of p in b's predecessor list with q.
// Ordinarily there should be at most one.
-//
func (b *BasicBlock) replacePred(p, q *BasicBlock) {
for i, pred := range b.Preds {
if pred == p {
@@ -74,7 +71,6 @@
// replaceSucc replaces all occurrences of p in b's successor list with q.
// Ordinarily there should be at most one.
-//
func (b *BasicBlock) replaceSucc(p, q *BasicBlock) {
for i, succ := range b.Succs {
if succ == p {
@@ -86,7 +82,6 @@
// removePred removes all occurrences of p in b's
// predecessor list and φ-nodes.
// Ordinarily there should be at most one.
-//
func (b *BasicBlock) removePred(p *BasicBlock) {
phis := b.phis()
diff --git a/go/ssa/blockopt.go b/go/ssa/blockopt.go
index e79260a..7dabce8 100644
--- a/go/ssa/blockopt.go
+++ b/go/ssa/blockopt.go
@@ -31,7 +31,6 @@
// deleteUnreachableBlocks marks all reachable blocks of f and
// eliminates (nils) all others, including possibly cyclic subgraphs.
-//
func deleteUnreachableBlocks(f *Function) {
const white, black = 0, -1
// We borrow b.Index temporarily as the mark bit.
@@ -61,7 +60,6 @@
// jumpThreading attempts to apply simple jump-threading to block b,
// in which a->b->c become a->c if b is just a Jump.
// The result is true if the optimization was applied.
-//
func jumpThreading(f *Function, b *BasicBlock) bool {
if b.Index == 0 {
return false // don't apply to entry block
@@ -108,7 +106,6 @@
// fuseBlocks attempts to apply the block fusion optimization to block
// a, in which a->b becomes ab if len(a.Succs)==len(b.Preds)==1.
// The result is true if the optimization was applied.
-//
func fuseBlocks(f *Function, a *BasicBlock) bool {
if len(a.Succs) != 1 {
return false
@@ -150,7 +147,6 @@
// optimizeBlocks() performs some simple block optimizations on a
// completed function: dead block elimination, block fusion, jump
// threading.
-//
func optimizeBlocks(f *Function) {
deleteUnreachableBlocks(f)
diff --git a/go/ssa/builder.go b/go/ssa/builder.go
index 9a691e9..45a8376 100644
--- a/go/ssa/builder.go
+++ b/go/ssa/builder.go
@@ -96,7 +96,6 @@
// to t or f depending on its value, performing various simplifications.
//
// Postcondition: fn.currentBlock is nil.
-//
func (b *builder) cond(fn *Function, e ast.Expr, t, f *BasicBlock) {
switch e := e.(type) {
case *ast.ParenExpr:
@@ -139,7 +138,6 @@
// logicalBinop emits code to fn to evaluate e, a &&- or
// ||-expression whose reified boolean value is wanted.
// The value is returned.
-//
func (b *builder) logicalBinop(fn *Function, e *ast.BinaryExpr) Value {
rhs := fn.newBasicBlock("binop.rhs")
done := fn.newBasicBlock("binop.done")
@@ -200,7 +198,6 @@
// assignment or return statement, and "value,ok" uses of
// TypeAssertExpr, IndexExpr (when X is a map), and UnaryExpr (when Op
// is token.ARROW).
-//
func (b *builder) exprN(fn *Function, e ast.Expr) Value {
typ := fn.typeOf(e).(*types.Tuple)
switch e := e.(type) {
@@ -250,7 +247,6 @@
// The result is nil if no special handling was required; in this case
// the caller should treat this like an ordinary library function
// call.
-//
func (b *builder) builtin(fn *Function, obj *types.Builtin, args []ast.Expr, typ types.Type, pos token.Pos) Value {
switch obj.Name() {
case "make":
@@ -341,10 +337,10 @@
// addressable expression e as being a potentially escaping pointer
// value. For example, in this code:
//
-// a := A{
-// b: [1]B{B{c: 1}}
-// }
-// return &a.b[0].c
+// a := A{
+// b: [1]B{B{c: 1}}
+// }
+// return &a.b[0].c
//
// the application of & causes a.b[0].c to have its address taken,
// which means that ultimately the local variable a must be
@@ -355,7 +351,6 @@
// - &x, including when implicit in method call or composite literals.
// - a[:] iff a is an array (not *array)
// - references to variables in lexically enclosing functions.
-//
func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
switch e := e.(type) {
case *ast.Ident:
@@ -478,7 +473,6 @@
// storebuf sb so that they can be executed later. This allows correct
// in-place update of existing variables when the RHS is a composite
// literal that may reference parts of the LHS.
-//
func (b *builder) assign(fn *Function, loc lvalue, e ast.Expr, isZero bool, sb *storebuf) {
// Can we initialize it in place?
if e, ok := unparen(e).(*ast.CompositeLit); ok {
@@ -537,7 +531,6 @@
// expr lowers a single-result expression e to SSA form, emitting code
// to fn and returning the Value defined by the expression.
-//
func (b *builder) expr(fn *Function, e ast.Expr) Value {
e = unparen(e)
@@ -862,7 +855,6 @@
// must thus be addressable.
//
// escaping is defined as per builder.addr().
-//
func (b *builder) receiver(fn *Function, e ast.Expr, wantAddr, escaping bool, sel *types.Selection) Value {
var v Value
if wantAddr && !sel.Indirect() && !isPointer(fn.typeOf(e)) {
@@ -883,7 +875,6 @@
// setCallFunc populates the function parts of a CallCommon structure
// (Func, Method, Recv, Args[0]) based on the kind of invocation
// occurring in e.
-//
func (b *builder) setCallFunc(fn *Function, e *ast.CallExpr, c *CallCommon) {
c.pos = e.Lparen
@@ -950,7 +941,6 @@
// emitCallArgs emits to f code for the actual parameters of call e to
// a (possibly built-in) function of effective type sig.
// The argument values are appended to args, which is then returned.
-//
func (b *builder) emitCallArgs(fn *Function, sig *types.Signature, e *ast.CallExpr, args []Value) []Value {
// f(x, y, z...): pass slice z straight through.
if e.Ellipsis != 0 {
@@ -1022,7 +1012,6 @@
// setCall emits to fn code to evaluate all the parameters of a function
// call e, and populates *c with those values.
-//
func (b *builder) setCall(fn *Function, e *ast.CallExpr, c *CallCommon) {
// First deal with the f(...) part and optional receiver.
b.setCallFunc(fn, e, c)
@@ -1043,7 +1032,6 @@
// localValueSpec emits to fn code to define all of the vars in the
// function-local ValueSpec, spec.
-//
func (b *builder) localValueSpec(fn *Function, spec *ast.ValueSpec) {
switch {
case len(spec.Values) == len(spec.Names):
@@ -1086,7 +1074,6 @@
// isDef is true if this is a short variable declaration (:=).
//
// Note the similarity with localValueSpec.
-//
func (b *builder) assignStmt(fn *Function, lhss, rhss []ast.Expr, isDef bool) {
// Side effects of all LHSs and RHSs must occur in left-to-right order.
lvals := make([]lvalue, len(lhss))
@@ -1152,8 +1139,10 @@
//
// Because the elements of a composite literal may refer to the
// variables being updated, as in the second line below,
+//
// x := T{a: 1}
// x = T{a: x.a}
+//
// all the reads must occur before all the writes. Thus all stores to
// loc are emitted to the storebuf sb for later execution.
//
@@ -1161,7 +1150,6 @@
// case when the type name is implicit. e.g. in []*T{{}}, the inner
// literal has type *T behaves like &T{}.
// In that case, addr must hold a T, not a *T.
-//
func (b *builder) compLit(fn *Function, addr Value, e *ast.CompositeLit, isZero bool, sb *storebuf) {
typ := deref(fn.typeOf(e))
switch t := typ.Underlying().(type) {
@@ -1300,7 +1288,6 @@
// switchStmt emits to fn code for the switch statement s, optionally
// labelled by label.
-//
func (b *builder) switchStmt(fn *Function, s *ast.SwitchStmt, label *lblock) {
// We treat SwitchStmt like a sequential if-else chain.
// Multiway dispatch can be recovered later by ssautil.Switches()
@@ -1386,7 +1373,6 @@
// typeSwitchStmt emits to fn code for the type switch statement s, optionally
// labelled by label.
-//
func (b *builder) typeSwitchStmt(fn *Function, s *ast.TypeSwitchStmt, label *lblock) {
// We treat TypeSwitchStmt like a sequential if-else chain.
// Multiway dispatch can be recovered later by ssautil.Switches().
@@ -1509,7 +1495,6 @@
// selectStmt emits to fn code for the select statement s, optionally
// labelled by label.
-//
func (b *builder) selectStmt(fn *Function, s *ast.SelectStmt, label *lblock) {
// A blocking select of a single case degenerates to a
// simple send or receive.
@@ -1691,7 +1676,6 @@
// forStmt emits to fn code for the for statement s, optionally
// labelled by label.
-//
func (b *builder) forStmt(fn *Function, s *ast.ForStmt, label *lblock) {
// ...init...
// jump loop
@@ -1748,7 +1732,6 @@
// over array, *array or slice value x.
// The v result is defined only if tv is non-nil.
// forPos is the position of the "for" token.
-//
func (b *builder) rangeIndexed(fn *Function, x Value, tv types.Type, pos token.Pos) (k, v Value, loop, done *BasicBlock) {
//
// length = len(x)
@@ -1843,7 +1826,6 @@
// Range/Next/Extract to iterate over map or string value x.
// tk and tv are the types of the key/value results k and v, or nil
// if the respective component is not wanted.
-//
func (b *builder) rangeIter(fn *Function, x Value, tk, tv types.Type, pos token.Pos) (k, v Value, loop, done *BasicBlock) {
//
// it = range x
@@ -1907,7 +1889,6 @@
// tk is the channel's element type, or nil if the k result is
// not wanted
// pos is the position of the '=' or ':=' token.
-//
func (b *builder) rangeChan(fn *Function, x Value, tk types.Type, pos token.Pos) (k Value, loop, done *BasicBlock) {
//
// loop: (target of continue)
@@ -1946,7 +1927,6 @@
// rangeStmt emits to fn code for the range statement s, optionally
// labelled by label.
-//
func (b *builder) rangeStmt(fn *Function, s *ast.RangeStmt, label *lblock) {
var tk, tv types.Type
if s.Key != nil && !isBlankIdent(s.Key) {
@@ -2291,7 +2271,6 @@
// Functions are built using buildFunction.
//
// May add types that require runtime type information to builder.
-//
func (b *builder) buildCreated() {
for ; b.finished < b.created.Len(); b.finished++ {
fn := b.created.At(b.finished)
@@ -2304,7 +2283,6 @@
// May add newly CREATEd functions that may need to be built or runtime type information.
//
// EXCLUSIVE_LOCKS_ACQUIRED(prog.methodsMu)
-//
func (b *builder) needsRuntimeTypes() {
if b.created.Len() == 0 {
return
@@ -2337,7 +2315,6 @@
// need only build a single package.
//
// Build is idempotent and thread-safe.
-//
func (prog *Program) Build() {
var wg sync.WaitGroup
for _, p := range prog.packages {
@@ -2361,7 +2338,6 @@
// error-free).
//
// Build is idempotent and thread-safe.
-//
func (p *Package) Build() { p.buildOnce.Do(p.build) }
func (p *Package) build() {
diff --git a/go/ssa/const.go b/go/ssa/const.go
index f43792e..dc182d9 100644
--- a/go/ssa/const.go
+++ b/go/ssa/const.go
@@ -16,7 +16,6 @@
// NewConst returns a new constant of the specified value and type.
// val must be valid according to the specification of Const.Value.
-//
func NewConst(val constant.Value, typ types.Type) *Const {
return &Const{typ, val}
}
@@ -29,7 +28,6 @@
// nilConst returns a nil constant of the specified type, which may
// be any reference type, including interfaces.
-//
func nilConst(typ types.Type) *Const {
return NewConst(nil, typ)
}
@@ -42,7 +40,6 @@
// zeroConst returns a new "zero" constant of the specified type,
// which must not be an array or struct type: the zero values of
// aggregates are well-defined but cannot be represented by Const.
-//
func zeroConst(t types.Type) *Const {
switch t := t.(type) {
case *types.Basic:
@@ -119,7 +116,6 @@
// Int64 returns the numeric value of this constant truncated to fit
// a signed 64-bit integer.
-//
func (c *Const) Int64() int64 {
switch x := constant.ToInt(c.Value); x.Kind() {
case constant.Int:
@@ -136,7 +132,6 @@
// Uint64 returns the numeric value of this constant truncated to fit
// an unsigned 64-bit integer.
-//
func (c *Const) Uint64() uint64 {
switch x := constant.ToInt(c.Value); x.Kind() {
case constant.Int:
@@ -153,7 +148,6 @@
// Float64 returns the numeric value of this constant truncated to fit
// a float64.
-//
func (c *Const) Float64() float64 {
f, _ := constant.Float64Val(c.Value)
return f
@@ -161,7 +155,6 @@
// Complex128 returns the complex value of this constant truncated to
// fit a complex128.
-//
func (c *Const) Complex128() complex128 {
re, _ := constant.Float64Val(constant.Real(c.Value))
im, _ := constant.Float64Val(constant.Imag(c.Value))
diff --git a/go/ssa/create.go b/go/ssa/create.go
index 97da645..0ab2fe1 100644
--- a/go/ssa/create.go
+++ b/go/ssa/create.go
@@ -22,7 +22,6 @@
// NewProgram returns a new SSA Program.
//
// mode controls diagnostics and checking during SSA construction.
-//
func NewProgram(fset *token.FileSet, mode BuilderMode) *Program {
prog := &Program{
Fset: fset,
@@ -48,7 +47,6 @@
// For objects from Go source code, syntax is the associated syntax
// tree (for funcs and vars only); it will be used during the build
// phase.
-//
func memberFromObject(pkg *Package, obj types.Object, syntax ast.Node) {
name := obj.Name()
switch obj := obj.(type) {
@@ -136,7 +134,6 @@
// membersFromDecl populates package pkg with members for each
// typechecker object (var, func, const or type) associated with the
// specified decl.
-//
func membersFromDecl(pkg *Package, decl ast.Decl) {
switch decl := decl.(type) {
case *ast.GenDecl: // import, const, type or var
@@ -198,7 +195,6 @@
//
// The real work of building SSA form for each function is not done
// until a subsequent call to Package.Build().
-//
func (prog *Program) CreatePackage(pkg *types.Package, files []*ast.File, info *types.Info, importable bool) *Package {
p := &Package{
Prog: prog,
@@ -281,7 +277,6 @@
// AllPackages returns a new slice containing all packages in the
// program prog in unspecified order.
-//
func (prog *Program) AllPackages() []*Package {
pkgs := make([]*Package, 0, len(prog.packages))
for _, pkg := range prog.packages {
@@ -303,7 +298,6 @@
// false---yet this function remains very convenient.
// Clients should use (*Program).Package instead where possible.
// SSA doesn't really need a string-keyed map of packages.
-//
func (prog *Program) ImportedPackage(path string) *Package {
return prog.imported[path]
}
diff --git a/go/ssa/doc.go b/go/ssa/doc.go
index 6885bed..13d0241 100644
--- a/go/ssa/doc.go
+++ b/go/ssa/doc.go
@@ -41,60 +41,60 @@
//
// The primary interfaces of this package are:
//
-// - Member: a named member of a Go package.
-// - Value: an expression that yields a value.
-// - Instruction: a statement that consumes values and performs computation.
-// - Node: a Value or Instruction (emphasizing its membership in the SSA value graph)
+// - Member: a named member of a Go package.
+// - Value: an expression that yields a value.
+// - Instruction: a statement that consumes values and performs computation.
+// - Node: a Value or Instruction (emphasizing its membership in the SSA value graph)
//
// A computation that yields a result implements both the Value and
// Instruction interfaces. The following table shows for each
// concrete type which of these interfaces it implements.
//
-// Value? Instruction? Member?
-// *Alloc ✔ ✔
-// *BinOp ✔ ✔
-// *Builtin ✔
-// *Call ✔ ✔
-// *ChangeInterface ✔ ✔
-// *ChangeType ✔ ✔
-// *Const ✔
-// *Convert ✔ ✔
-// *DebugRef ✔
-// *Defer ✔
-// *Extract ✔ ✔
-// *Field ✔ ✔
-// *FieldAddr ✔ ✔
-// *FreeVar ✔
-// *Function ✔ ✔ (func)
-// *Global ✔ ✔ (var)
-// *Go ✔
-// *If ✔
-// *Index ✔ ✔
-// *IndexAddr ✔ ✔
-// *Jump ✔
-// *Lookup ✔ ✔
-// *MakeChan ✔ ✔
-// *MakeClosure ✔ ✔
-// *MakeInterface ✔ ✔
-// *MakeMap ✔ ✔
-// *MakeSlice ✔ ✔
-// *MapUpdate ✔
-// *NamedConst ✔ (const)
-// *Next ✔ ✔
-// *Panic ✔
-// *Parameter ✔
-// *Phi ✔ ✔
-// *Range ✔ ✔
-// *Return ✔
-// *RunDefers ✔
-// *Select ✔ ✔
-// *Send ✔
-// *Slice ✔ ✔
-// *SliceToArrayPointer ✔ ✔
-// *Store ✔
-// *Type ✔ (type)
-// *TypeAssert ✔ ✔
-// *UnOp ✔ ✔
+// Value? Instruction? Member?
+// *Alloc ✔ ✔
+// *BinOp ✔ ✔
+// *Builtin ✔
+// *Call ✔ ✔
+// *ChangeInterface ✔ ✔
+// *ChangeType ✔ ✔
+// *Const ✔
+// *Convert ✔ ✔
+// *DebugRef ✔
+// *Defer ✔
+// *Extract ✔ ✔
+// *Field ✔ ✔
+// *FieldAddr ✔ ✔
+// *FreeVar ✔
+// *Function ✔ ✔ (func)
+// *Global ✔ ✔ (var)
+// *Go ✔
+// *If ✔
+// *Index ✔ ✔
+// *IndexAddr ✔ ✔
+// *Jump ✔
+// *Lookup ✔ ✔
+// *MakeChan ✔ ✔
+// *MakeClosure ✔ ✔
+// *MakeInterface ✔ ✔
+// *MakeMap ✔ ✔
+// *MakeSlice ✔ ✔
+// *MapUpdate ✔
+// *NamedConst ✔ (const)
+// *Next ✔ ✔
+// *Panic ✔
+// *Parameter ✔
+// *Phi ✔ ✔
+// *Range ✔ ✔
+// *Return ✔
+// *RunDefers ✔
+// *Select ✔ ✔
+// *Send ✔
+// *Slice ✔ ✔
+// *SliceToArrayPointer ✔ ✔
+// *Store ✔
+// *Type ✔ (type)
+// *TypeAssert ✔ ✔
+// *UnOp ✔ ✔
//
// Other key types in this package include: Program, Package, Function
// and BasicBlock.
@@ -122,5 +122,4 @@
// of trying to determine corresponding elements across the four
// domains of source locations, ast.Nodes, types.Objects,
// ssa.Values/Instructions.
-//
package ssa // import "golang.org/x/tools/go/ssa"
diff --git a/go/ssa/dom.go b/go/ssa/dom.go
index 822fe97..ce2473c 100644
--- a/go/ssa/dom.go
+++ b/go/ssa/dom.go
@@ -29,12 +29,10 @@
// its parent in the dominator tree, if any.
// Neither the entry node (b.Index==0) nor recover node
// (b==b.Parent().Recover()) have a parent.
-//
func (b *BasicBlock) Idom() *BasicBlock { return b.dom.idom }
// Dominees returns the list of blocks that b immediately dominates:
// its children in the dominator tree.
-//
func (b *BasicBlock) Dominees() []*BasicBlock { return b.dom.children }
// Dominates reports whether b dominates c.
@@ -50,7 +48,6 @@
// DomPreorder returns a new slice containing the blocks of f in
// dominator tree preorder.
-//
func (f *Function) DomPreorder() []*BasicBlock {
n := len(f.Blocks)
order := make(byDomPreorder, n)
@@ -110,7 +107,6 @@
// buildDomTree computes the dominator tree of f using the LT algorithm.
// Precondition: all blocks are reachable (e.g. optimizeBlocks has been run).
-//
func buildDomTree(f *Function) {
// The step numbers refer to the original LT paper; the
// reordering is due to Georgiadis.
@@ -210,7 +206,6 @@
// numberDomTree sets the pre- and post-order numbers of a depth-first
// traversal of the dominator tree rooted at v. These are used to
// answer dominance queries in constant time.
-//
func numberDomTree(v *BasicBlock, pre, post int32) (int32, int32) {
v.dom.pre = pre
pre++
@@ -228,7 +223,6 @@
// computed by the LT algorithm by comparing against the dominance
// relation computed by a naive Kildall-style forward dataflow
// analysis (Algorithm 10.16 from the "Dragon" book).
-//
func sanityCheckDomTree(f *Function) {
n := len(f.Blocks)
diff --git a/go/ssa/emit.go b/go/ssa/emit.go
index 8b48020..fb11c35 100644
--- a/go/ssa/emit.go
+++ b/go/ssa/emit.go
@@ -15,7 +15,6 @@
// emitNew emits to f a new (heap Alloc) instruction allocating an
// object of type typ. pos is the optional source location.
-//
func emitNew(f *Function, typ types.Type, pos token.Pos) *Alloc {
v := &Alloc{Heap: true}
v.setType(types.NewPointer(typ))
@@ -26,7 +25,6 @@
// emitLoad emits to f an instruction to load the address addr into a
// new temporary, and returns the value so defined.
-//
func emitLoad(f *Function, addr Value) *UnOp {
v := &UnOp{Op: token.MUL, X: addr}
v.setType(deref(addr.Type()))
@@ -36,7 +34,6 @@
// emitDebugRef emits to f a DebugRef pseudo-instruction associating
// expression e with value v.
-//
func emitDebugRef(f *Function, e ast.Expr, v Value, isAddr bool) {
if !f.debugInfo() {
return // debugging not enabled
@@ -68,7 +65,6 @@
// where op is an eager shift, logical or arithmetic operation.
// (Use emitCompare() for comparisons and Builder.logicalBinop() for
// non-eager operations.)
-//
func emitArith(f *Function, op token.Token, x, y Value, t types.Type, pos token.Pos) Value {
switch op {
case token.SHL, token.SHR:
@@ -106,7 +102,6 @@
// emitCompare emits to f code compute the boolean result of
// comparison comparison 'x op y'.
-//
func emitCompare(f *Function, op token.Token, x, y Value, pos token.Pos) Value {
xt := x.Type().Underlying()
yt := y.Type().Underlying()
@@ -151,7 +146,6 @@
// isValuePreserving returns true if a conversion from ut_src to
// ut_dst is value-preserving, i.e. just a change of type.
// Precondition: neither argument is a named type.
-//
func isValuePreserving(ut_src, ut_dst types.Type) bool {
// Identical underlying types?
if structTypesIdentical(ut_dst, ut_src) {
@@ -176,7 +170,6 @@
// and returns the converted value. Implicit conversions are required
// by language assignability rules in assignments, parameter passing,
// etc.
-//
func emitConv(f *Function, val Value, typ types.Type) Value {
t_src := val.Type()
@@ -260,7 +253,6 @@
// emitStore emits to f an instruction to store value val at location
// addr, applying implicit conversions as required by assignability rules.
-//
func emitStore(f *Function, addr, val Value, pos token.Pos) *Store {
s := &Store{
Addr: addr,
@@ -273,7 +265,6 @@
// emitJump emits to f a jump to target, and updates the control-flow graph.
// Postcondition: f.currentBlock is nil.
-//
func emitJump(f *Function, target *BasicBlock) {
b := f.currentBlock
b.emit(new(Jump))
@@ -284,7 +275,6 @@
// emitIf emits to f a conditional jump to tblock or fblock based on
// cond, and updates the control-flow graph.
// Postcondition: f.currentBlock is nil.
-//
func emitIf(f *Function, cond Value, tblock, fblock *BasicBlock) {
b := f.currentBlock
b.emit(&If{Cond: cond})
@@ -295,7 +285,6 @@
// emitExtract emits to f an instruction to extract the index'th
// component of tuple. It returns the extracted value.
-//
func emitExtract(f *Function, tuple Value, index int) Value {
e := &Extract{Tuple: tuple, Index: index}
e.setType(tuple.Type().(*types.Tuple).At(index).Type())
@@ -304,7 +293,6 @@
// emitTypeAssert emits to f a type assertion value := x.(t) and
// returns the value. x.Type() must be an interface.
-//
func emitTypeAssert(f *Function, x Value, t types.Type, pos token.Pos) Value {
a := &TypeAssert{X: x, AssertedType: t}
a.setPos(pos)
@@ -314,7 +302,6 @@
// emitTypeTest emits to f a type test value,ok := x.(t) and returns
// a (value, ok) tuple. x.Type() must be an interface.
-//
func emitTypeTest(f *Function, x Value, t types.Type, pos token.Pos) Value {
a := &TypeAssert{
X: x,
@@ -334,7 +321,6 @@
// Intended for wrapper methods.
// Precondition: f does/will not use deferred procedure calls.
// Postcondition: f.currentBlock is nil.
-//
func emitTailCall(f *Function, call *Call) {
tresults := f.Signature.Results()
nr := tresults.Len()
@@ -371,7 +357,6 @@
// If v is the address of a struct, the result will be the address of
// a field; if it is the value of a struct, the result will be the
// value of a field.
-//
func emitImplicitSelections(f *Function, v Value, indices []int, pos token.Pos) Value {
for _, index := range indices {
fld := deref(v.Type()).Underlying().(*types.Struct).Field(index)
@@ -407,7 +392,6 @@
// will be the field's address; otherwise the result will be the
// field's value.
// Ident id is used for position and debug info.
-//
func emitFieldSelection(f *Function, v Value, index int, wantAddr bool, id *ast.Ident) Value {
fld := deref(v.Type()).Underlying().(*types.Struct).Field(index)
if isPointer(v.Type()) {
@@ -437,7 +421,6 @@
// zeroValue emits to f code to produce a zero value of type t,
// and returns it.
-//
func zeroValue(f *Function, t types.Type) Value {
switch t.Underlying().(type) {
case *types.Struct, *types.Array:
@@ -455,7 +438,6 @@
// type.
//
// Idempotent.
-//
func createRecoverBlock(f *Function) {
if f.Recover != nil {
return // already created
diff --git a/go/ssa/example_test.go b/go/ssa/example_test.go
index 2ab9e99..1557831 100644
--- a/go/ssa/example_test.go
+++ b/go/ssa/example_test.go
@@ -48,7 +48,6 @@
// Build and run the ssadump.go program if you want a standalone tool
// with similar functionality. It is located at
// golang.org/x/tools/cmd/ssadump.
-//
func Example_buildPackage() {
// Replace interface{} with any for this test.
ssa.SetNormalizeAnyForTesting(true)
diff --git a/go/ssa/func.go b/go/ssa/func.go
index 75884a5..48ed570 100644
--- a/go/ssa/func.go
+++ b/go/ssa/func.go
@@ -55,7 +55,6 @@
// Destinations associated with unlabelled for/switch/select stmts.
// We push/pop one of these as we enter/leave each construct and for
// each BranchStmt we scan for the innermost target of the right type.
-//
type targets struct {
tail *targets // rest of stack
_break *BasicBlock
@@ -66,7 +65,6 @@
// Destinations associated with a labelled block.
// We populate these as labels are encountered in forward gotos or
// labelled statements.
-//
type lblock struct {
_goto *BasicBlock
_break *BasicBlock
@@ -75,7 +73,6 @@
// labelledBlock returns the branch target associated with the
// specified label, creating it if needed.
-//
func (f *Function) labelledBlock(label *ast.Ident) *lblock {
lb := f.lblocks[label.Obj]
if lb == nil {
@@ -90,7 +87,6 @@
// addParam adds a (non-escaping) parameter to f.Params of the
// specified name, type and source position.
-//
func (f *Function) addParam(name string, typ types.Type, pos token.Pos) *Parameter {
v := &Parameter{
name: name,
@@ -115,7 +111,6 @@
// addSpilledParam declares a parameter that is pre-spilled to the
// stack; the function body will load/store the spilled location.
// Subsequent lifting will eliminate spills where possible.
-//
func (f *Function) addSpilledParam(obj types.Object) {
param := f.addParamObj(obj)
spill := &Alloc{Comment: obj.Name()}
@@ -129,7 +124,6 @@
// startBody initializes the function prior to generating SSA code for its body.
// Precondition: f.Type() already set.
-//
func (f *Function) startBody() {
f.currentBlock = f.newBasicBlock("entry")
f.objects = make(map[types.Object]Value) // needed for some synthetics, e.g. init
@@ -143,7 +137,6 @@
// f.startBody() was called. f.info != nil.
// Postcondition:
// len(f.Params) == len(f.Signature.Params) + (f.Signature.Recv() ? 1 : 0)
-//
func (f *Function) createSyntacticParams(recv *ast.FieldList, functype *ast.FuncType) {
// Receiver (at most one inner iteration).
if recv != nil {
@@ -190,7 +183,6 @@
// numberRegisters assigns numbers to all SSA registers
// (value-defining Instructions) in f, to aid debugging.
// (Non-Instruction Values are named at construction.)
-//
func numberRegisters(f *Function) {
v := 0
for _, b := range f.Blocks {
@@ -311,7 +303,6 @@
// removeNilBlocks eliminates nils from f.Blocks and updates each
// BasicBlock.Index. Use this after any pass that may delete blocks.
-//
func (f *Function) removeNilBlocks() {
j := 0
for _, b := range f.Blocks {
@@ -332,7 +323,6 @@
// functions will include full debug info. This greatly increases the
// size of the instruction stream, and causes Functions to depend upon
// the ASTs, potentially keeping them live in memory for longer.
-//
func (pkg *Package) SetDebugMode(debug bool) {
// TODO(adonovan): do we want ast.File granularity?
pkg.debug = debug
@@ -346,7 +336,6 @@
// addNamedLocal creates a local variable, adds it to function f and
// returns it. Its name and type are taken from obj. Subsequent
// calls to f.lookup(obj) will return the same local.
-//
func (f *Function) addNamedLocal(obj types.Object) *Alloc {
l := f.addLocal(obj.Type(), obj.Pos())
l.Comment = obj.Name()
@@ -360,7 +349,6 @@
// addLocal creates an anonymous local variable of type typ, adds it
// to function f and returns it. pos is the optional source location.
-//
func (f *Function) addLocal(typ types.Type, pos token.Pos) *Alloc {
v := &Alloc{}
v.setType(types.NewPointer(typ))
@@ -374,7 +362,6 @@
// that is local to function f or one of its enclosing functions.
// If escaping, the reference comes from a potentially escaping pointer
// expression and the referent must be heap-allocated.
-//
func (f *Function) lookup(obj types.Object, escaping bool) Value {
if v, ok := f.objects[obj]; ok {
if alloc, ok := v.(*Alloc); ok && escaping {
@@ -412,13 +399,14 @@
// The specific formatting rules are not guaranteed and may change.
//
// Examples:
-// "math.IsNaN" // a package-level function
-// "(*bytes.Buffer).Bytes" // a declared method or a wrapper
-// "(*bytes.Buffer).Bytes$thunk" // thunk (func wrapping method; receiver is param 0)
-// "(*bytes.Buffer).Bytes$bound" // bound (func wrapping method; receiver supplied by closure)
-// "main.main$1" // an anonymous function in main
-// "main.init#1" // a declared init function
-// "main.init" // the synthesized package initializer
+//
+// "math.IsNaN" // a package-level function
+// "(*bytes.Buffer).Bytes" // a declared method or a wrapper
+// "(*bytes.Buffer).Bytes$thunk" // thunk (func wrapping method; receiver is param 0)
+// "(*bytes.Buffer).Bytes$bound" // bound (func wrapping method; receiver supplied by closure)
+// "main.main$1" // an anonymous function in main
+// "main.init#1" // a declared init function
+// "main.init" // the synthesized package initializer
//
// When these functions are referred to from within the same package
// (i.e. from == f.Pkg.Object), they are rendered without the package path.
@@ -428,7 +416,6 @@
// (But two methods may have the same name "(T).f" if one is a synthetic
// wrapper promoting a non-exported method "f" from another package; in
// that case, the strings are equal but the identifiers "f" are distinct.)
-//
func (f *Function) RelString(from *types.Package) string {
// Anonymous?
if f.parent != nil {
@@ -619,7 +606,6 @@
// newBasicBlock adds to f a new basic block and returns it. It does
// not automatically become the current block for subsequent calls to emit.
// comment is an optional string for more readable debugging output.
-//
func (f *Function) newBasicBlock(comment string) *BasicBlock {
b := &BasicBlock{
Index: len(f.Blocks),
@@ -645,7 +631,6 @@
// "reflect" package, etc.
//
// TODO(adonovan): think harder about the API here.
-//
func (prog *Program) NewFunction(name string, sig *types.Signature, provenance string) *Function {
return &Function{Prog: prog, name: name, Signature: sig, Synthetic: provenance}
}
@@ -663,5 +648,4 @@
// the result is the *ast.FuncDecl or *ast.FuncLit that declared the
// function. Otherwise, it is an opaque Node providing only position
// information; this avoids pinning the AST in memory.
-//
func (f *Function) Syntax() ast.Node { return f.syntax }
diff --git a/go/ssa/instantiate.go b/go/ssa/instantiate.go
index 871d708..9934839 100644
--- a/go/ssa/instantiate.go
+++ b/go/ssa/instantiate.go
@@ -55,7 +55,6 @@
// Precondition: fn is a package level declaration (function or method).
//
// EXCLUSIVE_LOCKS_ACQUIRED(prog.methodMu)
-//
func (prog *Program) createInstanceSet(fn *Function) {
assert(len(fn._TypeParams) > 0 && len(fn._TypeArgs) == 0, "Can only create instance sets for generic functions")
@@ -88,7 +87,6 @@
// lookupOrCreate returns the instantiation of insts.fn using targs.
// If the instantiation is reported, this is added to cr.
-//
func (insts *instanceSet) lookupOrCreate(targs []types.Type, cr *creator) *Function {
if insts.instances == nil {
insts.instances = make(map[*typeList]*Function)
@@ -116,7 +114,6 @@
// createInstance returns an CREATEd instantiation of fn using targs.
//
// Function is added to cr.
-//
func createInstance(fn *Function, targs []types.Type, info *types.Info, syntax ast.Node, cr *creator) *Function {
prog := fn.Prog
var sig *types.Signature
diff --git a/go/ssa/interp/interp.go b/go/ssa/interp/interp.go
index a982660..aa5918f 100644
--- a/go/ssa/interp/interp.go
+++ b/go/ssa/interp/interp.go
@@ -131,7 +131,6 @@
// runDefer runs a deferred call d.
// It always returns normally, but may set or clear fr.panic.
-//
func (fr *frame) runDefer(d *deferred) {
if fr.i.mode&EnableTracing != 0 {
fmt.Fprintf(os.Stderr, "%s: invoking deferred function call\n",
@@ -160,7 +159,6 @@
//
// If there was no initial state of panic, or it was recovered from,
// runDefers returns normally.
-//
func (fr *frame) runDefers() {
for d := fr.defers; d != nil; d = d.tail {
fr.runDefer(d)
@@ -429,7 +427,6 @@
// prepareCall determines the function value and argument values for a
// function call in a Call, Go or Defer instruction, performing
// interface method lookup if needed.
-//
func prepareCall(fr *frame, call *ssa.CallCommon) (fn value, args []value) {
v := fr.get(call.Value)
if call.Method == nil {
@@ -458,7 +455,6 @@
// call interprets a call to a function (function, builtin or closure)
// fn with arguments args, returning its result.
// callpos is the position of the callsite.
-//
func call(i *interpreter, caller *frame, callpos token.Pos, fn value, args []value) value {
switch fn := fn.(type) {
case *ssa.Function:
@@ -484,7 +480,6 @@
// callSSA interprets a call to function fn with arguments args,
// and lexical environment env, returning its result.
// callpos is the position of the callsite.
-//
func callSSA(i *interpreter, caller *frame, callpos token.Pos, fn *ssa.Function, args []value, env []value) value {
if i.mode&EnableTracing != 0 {
fset := fn.Prog.Fset
@@ -551,7 +546,6 @@
// After a recovered panic in a function with NRPs, fr.result is
// undefined and fr.block contains the block at which to resume
// control.
-//
func runFrame(fr *frame) {
defer func() {
if fr.block == nil {
@@ -643,7 +637,6 @@
// gc does), or the argument to os.Exit for normal termination.
//
// The SSA program must include the "runtime" package.
-//
func Interpret(mainpkg *ssa.Package, mode Mode, sizes types.Sizes, filename string, args []string) (exitCode int) {
i := &interpreter{
prog: mainpkg.Prog,
diff --git a/go/ssa/interp/ops.go b/go/ssa/interp/ops.go
index 7fd0b88..8f03138 100644
--- a/go/ssa/interp/ops.go
+++ b/go/ssa/interp/ops.go
@@ -336,7 +336,6 @@
// binop implements all arithmetic and logical binary operators for
// numeric datatypes and strings. Both operands must have identical
// dynamic type.
-//
func binop(op token.Token, t types.Type, x, y value) value {
switch op {
case token.ADD:
@@ -810,7 +809,6 @@
// appropriate for type t.
// If t is a reference type, at most one of x or y may be a nil value
// of that type.
-//
func eqnil(t types.Type, x, y value) bool {
switch t.Underlying().(type) {
case *types.Map, *types.Signature, *types.Slice:
@@ -919,7 +917,6 @@
// typeAssert checks whether dynamic type of itf is instr.AssertedType.
// It returns the extracted value on success, and panics on failure,
// unless instr.CommaOk, in which case it always returns a "value,ok" tuple.
-//
func typeAssert(i *interpreter, instr *ssa.TypeAssert, itf iface) value {
var v value
err := ""
@@ -956,7 +953,6 @@
// failure if "BUG" appears in the combined stdout/stderr output, even
// if it exits zero. This is a global variable shared by all
// interpreters in the same process.)
-//
var CapturedOutput *bytes.Buffer
var capturedOutputMu sync.Mutex
@@ -1129,10 +1125,11 @@
// widen widens a basic typed value x to the widest type of its
// category, one of:
-// bool, int64, uint64, float64, complex128, string.
+//
+// bool, int64, uint64, float64, complex128, string.
+//
// This is inefficient but reduces the size of the cross-product of
// cases we have to consider.
-//
func widen(x value) value {
switch y := x.(type) {
case bool, int64, uint64, float64, complex128, string, unsafe.Pointer:
@@ -1166,7 +1163,6 @@
// conv converts the value x of type t_src to type t_dst and returns
// the result.
// Possible cases are described with the ssa.Convert operator.
-//
func conv(t_dst, t_src types.Type, x value) value {
ut_src := t_src.Underlying()
ut_dst := t_dst.Underlying()
@@ -1425,7 +1421,6 @@
// checkInterface checks that the method set of x implements the
// interface itype.
// On success it returns "", on failure, an error message.
-//
func checkInterface(i *interpreter, itype *types.Interface, x iface) string {
if meth, _ := types.MissingMethod(x.t, itype, true); meth != nil {
return fmt.Sprintf("interface conversion: %v is not %v: missing method %s",
diff --git a/go/ssa/lift.go b/go/ssa/lift.go
index 048e9b0..c350481 100644
--- a/go/ssa/lift.go
+++ b/go/ssa/lift.go
@@ -61,7 +61,6 @@
//
// domFrontier's methods mutate the slice's elements but not its
// length, so their receivers needn't be pointers.
-//
type domFrontier [][]*BasicBlock
func (df domFrontier) add(u, v *BasicBlock) {
@@ -127,7 +126,6 @@
// - fn has no dead blocks (blockopt has run).
// - Def/use info (Operands and Referrers) is up-to-date.
// - The dominator tree is up-to-date.
-//
func lift(fn *Function) {
// TODO(adonovan): opt: lots of little optimizations may be
// worthwhile here, especially if they cause us to avoid
@@ -382,7 +380,6 @@
// and returns true.
//
// fresh is a source of fresh ids for phi nodes.
-//
func liftAlloc(df domFrontier, alloc *Alloc, newPhis newPhiMap, fresh *int) bool {
// Don't lift aggregates into registers, because we don't have
// a way to express their zero-constants.
@@ -491,7 +488,6 @@
// replaceAll replaces all intraprocedural uses of x with y,
// updating x.Referrers and y.Referrers.
// Precondition: x.Referrers() != nil, i.e. x must be local to some function.
-//
func replaceAll(x, y Value) {
var rands []*Value
pxrefs := x.Referrers()
@@ -514,7 +510,6 @@
// renamed returns the value to which alloc is being renamed,
// constructing it lazily if it's the implicit zero initialization.
-//
func renamed(renaming []Value, alloc *Alloc) Value {
v := renaming[alloc.index]
if v == nil {
@@ -533,7 +528,6 @@
// renaming is a map from *Alloc (keyed by index number) to its
// dominating stored value; newPhis[x] is the set of new φ-nodes to be
// prepended to block x.
-//
func rename(u *BasicBlock, renaming []Value, newPhis newPhiMap) {
// Each φ-node becomes the new name for its associated Alloc.
for _, np := range newPhis[u] {
diff --git a/go/ssa/lvalue.go b/go/ssa/lvalue.go
index 4d85be3..64262de 100644
--- a/go/ssa/lvalue.go
+++ b/go/ssa/lvalue.go
@@ -16,7 +16,6 @@
// An lvalue represents an assignable location that may appear on the
// left-hand side of an assignment. This is a generalization of a
// pointer to permit updates to elements of maps.
-//
type lvalue interface {
store(fn *Function, v Value) // stores v into the location
load(fn *Function) Value // loads the contents of the location
@@ -60,7 +59,6 @@
// element of a map or string. These locations are not addressable
// since pointers cannot be formed from them, but they do support
// load(), and in the case of maps, store().
-//
type element struct {
m, k Value // map or string
t types.Type // map element type or string byte type
@@ -97,7 +95,6 @@
// A blank is a dummy variable whose name is "_".
// It is not reified: loads are illegal and stores are ignored.
-//
type blank struct{}
func (bl blank) load(fn *Function) Value {
diff --git a/go/ssa/methods.go b/go/ssa/methods.go
index 0bfce60..7955ed3 100644
--- a/go/ssa/methods.go
+++ b/go/ssa/methods.go
@@ -20,7 +20,6 @@
// Thread-safe.
//
// EXCLUSIVE_LOCKS_ACQUIRED(prog.methodsMu)
-//
func (prog *Program) MethodValue(sel *types.Selection) *Function {
if sel.Kind() != types.MethodVal {
panic(fmt.Sprintf("MethodValue(%s) kind != MethodVal", sel))
@@ -48,7 +47,6 @@
// LookupMethod returns the implementation of the method of type T
// identified by (pkg, name). It returns nil if the method exists but
// is abstract, and panics if T has no such method.
-//
func (prog *Program) LookupMethod(T types.Type, pkg *types.Package, name string) *Function {
sel := prog.MethodSets.MethodSet(T).Lookup(pkg, name)
if sel == nil {
@@ -111,7 +109,6 @@
// Thread-safe.
//
// EXCLUSIVE_LOCKS_ACQUIRED(prog.methodsMu)
-//
func (prog *Program) RuntimeTypes() []types.Type {
prog.methodsMu.Lock()
defer prog.methodsMu.Unlock()
@@ -127,7 +124,6 @@
// declaredFunc returns the concrete function/method denoted by obj.
// Panic ensues if there is none.
-//
func (prog *Program) declaredFunc(obj *types.Func) *Function {
if v := prog.packageLevelMember(obj); v != nil {
return v.(*Function)
@@ -153,7 +149,6 @@
// TODO(adonovan): make this faster. It accounts for 20% of SSA build time.
//
// EXCLUSIVE_LOCKS_ACQUIRED(prog.methodsMu)
-//
func (prog *Program) needMethodsOf(T types.Type, cr *creator) {
prog.methodsMu.Lock()
prog.needMethods(T, false, cr)
@@ -164,7 +159,6 @@
// Recursive case: skip => don't create methods for T.
//
// EXCLUSIVE_LOCKS_REQUIRED(prog.methodsMu)
-//
func (prog *Program) needMethods(T types.Type, skip bool, cr *creator) {
// Each package maintains its own set of types it has visited.
if prevSkip, ok := prog.runtimeTypes.At(T).(bool); ok {
diff --git a/go/ssa/mode.go b/go/ssa/mode.go
index 298f24b..b17d565 100644
--- a/go/ssa/mode.go
+++ b/go/ssa/mode.go
@@ -15,9 +15,8 @@
//
// *BuilderMode satisfies the flag.Value interface. Example:
//
-// var mode = ssa.BuilderMode(0)
-// func init() { flag.Var(&mode, "build", ssa.BuilderModeDoc) }
-//
+// var mode = ssa.BuilderMode(0)
+// func init() { flag.Var(&mode, "build", ssa.BuilderModeDoc) }
type BuilderMode uint
const (
diff --git a/go/ssa/print.go b/go/ssa/print.go
index d0f3bbf..b8e5392 100644
--- a/go/ssa/print.go
+++ b/go/ssa/print.go
@@ -24,7 +24,6 @@
// Functions (including methods) and Globals use RelString and
// all types are displayed with relType, so that only cross-package
// references are package-qualified.
-//
func relName(v Value, i Instruction) string {
var from *types.Package
if i != nil {
diff --git a/go/ssa/sanity.go b/go/ssa/sanity.go
index 0cda704..ba08c41 100644
--- a/go/ssa/sanity.go
+++ b/go/ssa/sanity.go
@@ -30,7 +30,6 @@
//
// Sanity-checking is intended to facilitate the debugging of code
// transformation passes.
-//
func sanityCheck(fn *Function, reporter io.Writer) bool {
if reporter == nil {
reporter = os.Stderr
@@ -40,7 +39,6 @@
// mustSanityCheck is like sanityCheck but panics instead of returning
// a negative result.
-//
func mustSanityCheck(fn *Function, reporter io.Writer) {
if !sanityCheck(fn, reporter) {
fn.WriteTo(os.Stderr)
diff --git a/go/ssa/source.go b/go/ssa/source.go
index 2100ba2..b9a0836 100644
--- a/go/ssa/source.go
+++ b/go/ssa/source.go
@@ -25,11 +25,10 @@
// enclosed by the package's init() function.
//
// Returns nil if not found; reasons might include:
-// - the node is not enclosed by any function.
-// - the node is within an anonymous function (FuncLit) and
-// its SSA function has not been created yet
-// (pkg.Build() has not yet been called).
-//
+// - the node is not enclosed by any function.
+// - the node is within an anonymous function (FuncLit) and
+// its SSA function has not been created yet
+// (pkg.Build() has not yet been called).
func EnclosingFunction(pkg *Package, path []ast.Node) *Function {
// Start with package-level function...
fn := findEnclosingPackageLevelFunction(pkg, path)
@@ -67,14 +66,12 @@
// depend on whether SSA code for pkg has been built, so it can be
// used to quickly reject check inputs that will cause
// EnclosingFunction to fail, prior to SSA building.
-//
func HasEnclosingFunction(pkg *Package, path []ast.Node) bool {
return findEnclosingPackageLevelFunction(pkg, path) != nil
}
// findEnclosingPackageLevelFunction returns the Function
// corresponding to the package-level function enclosing path.
-//
func findEnclosingPackageLevelFunction(pkg *Package, path []ast.Node) *Function {
if n := len(path); n >= 2 { // [... {Gen,Func}Decl File]
switch decl := path[n-2].(type) {
@@ -109,7 +106,6 @@
// findNamedFunc returns the named function whose FuncDecl.Ident is at
// position pos.
-//
func findNamedFunc(pkg *Package, pos token.Pos) *Function {
// Look at all package members and method sets of named types.
// Not very efficient.
@@ -137,13 +133,13 @@
// expression e.
//
// It returns nil if no value was found, e.g.
-// - the expression is not lexically contained within f;
-// - f was not built with debug information; or
-// - e is a constant expression. (For efficiency, no debug
-// information is stored for constants. Use
-// go/types.Info.Types[e].Value instead.)
-// - e is a reference to nil or a built-in function.
-// - the value was optimised away.
+// - the expression is not lexically contained within f;
+// - f was not built with debug information; or
+// - e is a constant expression. (For efficiency, no debug
+// information is stored for constants. Use
+// go/types.Info.Types[e].Value instead.)
+// - e is a reference to nil or a built-in function.
+// - the value was optimised away.
//
// If e is an addressable expression used in an lvalue context,
// value is the address denoted by e, and isAddr is true.
@@ -155,7 +151,6 @@
// astutil.PathEnclosingInterval to locate the ast.Node, then
// EnclosingFunction to locate the Function, then ValueForExpr to find
// the ssa.Value.)
-//
func (f *Function) ValueForExpr(e ast.Expr) (value Value, isAddr bool) {
if f.debugInfo() { // (opt)
e = unparen(e)
@@ -177,7 +172,6 @@
// Package returns the SSA Package corresponding to the specified
// type-checker package object.
// It returns nil if no such SSA package has been created.
-//
func (prog *Program) Package(obj *types.Package) *Package {
return prog.packages[obj]
}
@@ -186,7 +180,6 @@
// the specified named object, which may be a package-level const
// (*NamedConst), var (*Global) or func (*Function) of some package in
// prog. It returns nil if the object is not found.
-//
func (prog *Program) packageLevelMember(obj types.Object) Member {
if pkg, ok := prog.packages[obj.Pkg()]; ok {
return pkg.objects[obj]
@@ -205,7 +198,6 @@
//
// TODO(adonovan): check the invariant that obj.Type() matches the
// result's Signature, both in the params/results and in the receiver.
-//
func (prog *Program) FuncValue(obj *types.Func) *Function {
fn, _ := prog.packageLevelMember(obj).(*Function)
return fn
@@ -213,7 +205,6 @@
// ConstValue returns the SSA Value denoted by the source-level named
// constant obj.
-//
func (prog *Program) ConstValue(obj *types.Const) *Const {
// TODO(adonovan): opt: share (don't reallocate)
// Consts for const objects and constant ast.Exprs.
@@ -245,8 +236,9 @@
// If the identifier is a field selector and its base expression is
// non-addressable, then VarValue returns the value of that field.
// For example:
-// func f() struct {x int}
-// f().x // VarValue(x) returns a *Field instruction of type int
+//
+// func f() struct {x int}
+// f().x // VarValue(x) returns a *Field instruction of type int
//
// All other identifiers denote addressable locations (variables).
// For them, VarValue may return either the variable's address or its
@@ -255,14 +247,14 @@
//
// If !isAddr, the returned value is the one associated with the
// specific identifier. For example,
-// var x int // VarValue(x) returns Const 0 here
-// x = 1 // VarValue(x) returns Const 1 here
+//
+// var x int // VarValue(x) returns Const 0 here
+// x = 1 // VarValue(x) returns Const 1 here
//
// It is not specified whether the value or the address is returned in
// any particular case, as it may depend upon optimizations performed
// during SSA code generation, such as registerization, constant
// folding, avoidance of materialization of subexpressions, etc.
-//
func (prog *Program) VarValue(obj *types.Var, pkg *Package, ref []ast.Node) (value Value, isAddr bool) {
// All references to a var are local to some function, possibly init.
fn := EnclosingFunction(pkg, ref)
diff --git a/go/ssa/source_test.go b/go/ssa/source_test.go
index 24cf57e..81bda88 100644
--- a/go/ssa/source_test.go
+++ b/go/ssa/source_test.go
@@ -325,7 +325,6 @@
// findInterval parses input and returns the [start, end) positions of
// the first occurrence of substr in input. f==nil indicates failure;
// an error has already been reported in that case.
-//
func findInterval(t *testing.T, fset *token.FileSet, input, substr string) (f *ast.File, start, end token.Pos) {
f, err := parser.ParseFile(fset, "<input>", input, 0)
if err != nil {
diff --git a/go/ssa/ssa.go b/go/ssa/ssa.go
index f991c0c..97c745b 100644
--- a/go/ssa/ssa.go
+++ b/go/ssa/ssa.go
@@ -46,7 +46,6 @@
// Members also contains entries for "init" (the synthetic package
// initializer) and "init#%d", the nth declared init function,
// and unspecified other things too.
-//
type Package struct {
Prog *Program // the owning program
Pkg *types.Package // the corresponding go/types.Package
@@ -67,7 +66,6 @@
// A Member is a member of a Go package, implemented by *NamedConst,
// *Global, *Function, or *Type; they are created by package-level
// const, var, func and type declarations respectively.
-//
type Member interface {
Name() string // declared name of the package member
String() string // package-qualified name of the package member
@@ -93,7 +91,6 @@
//
// NB: a NamedConst is not a Value; it contains a constant Value, which
// it augments with the name and position of its 'const' declaration.
-//
type NamedConst struct {
object *types.Const
Value *Const
@@ -169,7 +166,6 @@
// An Instruction that defines a value (e.g. BinOp) also implements
// the Value interface; an Instruction that only has an effect (e.g. Store)
// does not.
-//
type Instruction interface {
// String returns the disassembled form of this value.
//
@@ -246,7 +242,6 @@
// Node is provided to simplify SSA graph algorithms. Clients should
// use the more specific and informative Value or Instruction
// interfaces where appropriate.
-//
type Node interface {
// Common methods:
String() string
@@ -297,7 +292,6 @@
// Syntax.Pos() always returns the position of the declaring "func" token.
//
// Type() returns the function's Signature.
-//
type Function struct {
name string
object types.Object // a declared *types.Func or one of its wrappers
@@ -353,7 +347,6 @@
//
// The order of Preds and Succs is significant (to Phi and If
// instructions, respectively).
-//
type BasicBlock struct {
Index int // index of this block within Parent().Blocks
Comment string // optional label; no semantic significance
@@ -383,7 +376,6 @@
//
// Pos() returns the position of the value that was captured, which
// belongs to an enclosing function.
-//
type FreeVar struct {
name string
typ types.Type
@@ -396,7 +388,6 @@
}
// A Parameter represents an input parameter of a function.
-//
type Parameter struct {
name string
object types.Object // a *types.Var; nil for non-source locals
@@ -422,10 +413,10 @@
// Pos() returns token.NoPos.
//
// Example printed form:
-// 42:int
+//
+// 42:int
// "hello":untyped string
// 3+4i:MyComplex
-//
type Const struct {
typ types.Type
Value constant.Value
@@ -436,7 +427,6 @@
//
// Pos() returns the position of the ast.ValueSpec.Names[*]
// identifier.
-//
type Global struct {
name string
object types.Object // a *types.Var; may be nil for synthetics e.g. init$guard
@@ -455,16 +445,15 @@
// Go spec (excluding "make" and "new") or one of these ssa-defined
// intrinsics:
//
-// // wrapnilchk returns ptr if non-nil, panics otherwise.
-// // (For use in indirection wrappers.)
-// func ssa:wrapnilchk(ptr *T, recvType, methodName string) *T
+// // wrapnilchk returns ptr if non-nil, panics otherwise.
+// // (For use in indirection wrappers.)
+// func ssa:wrapnilchk(ptr *T, recvType, methodName string) *T
//
// Object() returns a *types.Builtin for built-ins defined by the spec,
// nil for others.
//
// Type() returns a *types.Signature representing the effective
// signature of the built-in for this call.
-//
type Builtin struct {
name string
sig *types.Signature
@@ -499,9 +488,9 @@
// allocates a varargs slice.
//
// Example printed form:
-// t0 = local int
-// t1 = new int
//
+// t0 = local int
+// t1 = new int
type Alloc struct {
register
Comment string
@@ -519,8 +508,8 @@
// during SSA renaming.
//
// Example printed form:
-// t2 = phi [0: t0, 1: t1]
//
+// t2 = phi [0: t0, 1: t1]
type Phi struct {
register
Comment string // a hint as to its purpose
@@ -538,10 +527,10 @@
// Pos() returns the ast.CallExpr.Lparen, if explicit in the source.
//
// Example printed form:
-// t2 = println(t0, t1)
-// t4 = t3()
-// t7 = invoke t5.Println(...t6)
//
+// t2 = println(t0, t1)
+// t4 = t3()
+// t7 = invoke t5.Println(...t6)
type Call struct {
register
Call CallCommon
@@ -552,8 +541,8 @@
// Pos() returns the ast.BinaryExpr.OpPos, if explicit in the source.
//
// Example printed form:
-// t1 = t0 + 1:int
//
+// t1 = t0 + 1:int
type BinOp struct {
register
// One of:
@@ -583,9 +572,9 @@
// specified.
//
// Example printed form:
-// t0 = *x
-// t2 = <-t1,ok
//
+// t0 = *x
+// t2 = <-t1,ok
type UnOp struct {
register
Op token.Token // One of: NOT SUB ARROW MUL XOR ! - <- * ^
@@ -597,11 +586,11 @@
// change to Type().
//
// Type changes are permitted:
-// - between a named type and its underlying type.
-// - between two named types of the same underlying type.
-// - between (possibly named) pointers to identical base types.
-// - from a bidirectional channel to a read- or write-channel,
-// optionally adding/removing a name.
+// - between a named type and its underlying type.
+// - between two named types of the same underlying type.
+// - between (possibly named) pointers to identical base types.
+// - from a bidirectional channel to a read- or write-channel,
+// optionally adding/removing a name.
//
// This operation cannot fail dynamically.
//
@@ -609,8 +598,8 @@
// from an explicit conversion in the source.
//
// Example printed form:
-// t1 = changetype *int <- IntPtr (t0)
//
+// t1 = changetype *int <- IntPtr (t0)
type ChangeType struct {
register
X Value
@@ -621,12 +610,13 @@
//
// A conversion may change the value and representation of its operand.
// Conversions are permitted:
-// - between real numeric types.
-// - between complex numeric types.
-// - between string and []byte or []rune.
-// - between pointers and unsafe.Pointer.
-// - between unsafe.Pointer and uintptr.
-// - from (Unicode) integer to (UTF-8) string.
+// - between real numeric types.
+// - between complex numeric types.
+// - between string and []byte or []rune.
+// - between pointers and unsafe.Pointer.
+// - between unsafe.Pointer and uintptr.
+// - from (Unicode) integer to (UTF-8) string.
+//
// A conversion may imply a type name change also.
//
// This operation cannot fail dynamically.
@@ -638,8 +628,8 @@
// from an explicit conversion in the source.
//
// Example printed form:
-// t1 = convert []byte <- string (t0)
//
+// t1 = convert []byte <- string (t0)
type Convert struct {
register
X Value
@@ -655,8 +645,8 @@
// otherwise.
//
// Example printed form:
-// t1 = change interface interface{} <- I (t0)
//
+// t1 = change interface interface{} <- I (t0)
type ChangeInterface struct {
register
X Value
@@ -669,8 +659,8 @@
// from an explicit conversion in the source.
//
// Example printed form:
-// t1 = slice to array pointer *[4]byte <- []byte (t0)
//
+// t1 = slice to array pointer *[4]byte <- []byte (t0)
type SliceToArrayPointer struct {
register
X Value
@@ -683,15 +673,16 @@
// of X, and Program.MethodValue(m) to find the implementation of a method.
//
// To construct the zero value of an interface type T, use:
-// NewConst(constant.MakeNil(), T, pos)
+//
+// NewConst(constant.MakeNil(), T, pos)
//
// Pos() returns the ast.CallExpr.Lparen, if the instruction arose
// from an explicit conversion in the source.
//
// Example printed form:
-// t1 = make interface{} <- int (42:int)
-// t2 = make Stringer <- t0
//
+// t1 = make interface{} <- int (42:int)
+// t2 = make Stringer <- t0
type MakeInterface struct {
register
X Value
@@ -706,9 +697,9 @@
// closure or the ast.SelectorExpr.Sel for a bound method closure.
//
// Example printed form:
-// t0 = make closure anon@1.2 [x y z]
-// t1 = make closure bound$(main.I).add [i]
//
+// t0 = make closure anon@1.2 [x y z]
+// t1 = make closure bound$(main.I).add [i]
type MakeClosure struct {
register
Fn Value // always a *Function
@@ -724,9 +715,9 @@
// the ast.CompositeLit.Lbrack if created by a literal.
//
// Example printed form:
-// t1 = make map[string]int t0
-// t1 = make StringIntMap t0
//
+// t1 = make map[string]int t0
+// t1 = make StringIntMap t0
type MakeMap struct {
register
Reserve Value // initial space reservation; nil => default
@@ -741,9 +732,9 @@
// created it.
//
// Example printed form:
-// t0 = make chan int 0
-// t0 = make IntChan 0
//
+// t0 = make chan int 0
+// t0 = make IntChan 0
type MakeChan struct {
register
Size Value // int; size of buffer; zero => synchronous.
@@ -763,9 +754,9 @@
// created it.
//
// Example printed form:
-// t1 = make []string 1:int t0
-// t1 = make StringSlice 1:int t0
//
+// t1 = make []string 1:int t0
+// t1 = make StringSlice 1:int t0
type MakeSlice struct {
register
Len Value
@@ -786,8 +777,8 @@
// NoPos if not explicit in the source (e.g. a variadic argument slice).
//
// Example printed form:
-// t1 = slice t0[1:]
//
+// t1 = slice t0[1:]
type Slice struct {
register
X Value // slice, string, or *array
@@ -809,8 +800,8 @@
// the position of the inducing explicit selection.
//
// Example printed form:
-// t1 = &t0.name [#1]
//
+// t1 = &t0.name [#1]
type FieldAddr struct {
register
X Value // *struct
@@ -827,10 +818,9 @@
// field, if explicit in the source. For implicit selections, returns
// the position of the inducing explicit selection.
-//
// Example printed form:
-// t1 = t0.name [#1]
//
+// t1 = t0.name [#1]
type Field struct {
register
X Value // struct
@@ -852,8 +842,8 @@
// explicit in the source.
//
// Example printed form:
-// t2 = &t0[t1]
//
+// t2 = &t0[t1]
type IndexAddr struct {
register
X Value // slice or *array,
@@ -866,8 +856,8 @@
// explicit in the source.
//
// Example printed form:
-// t2 = t0[t1]
//
+// t2 = t0[t1]
type Index struct {
register
X Value // array
@@ -885,9 +875,9 @@
// Pos() returns the ast.IndexExpr.Lbrack, if explicit in the source.
//
// Example printed form:
-// t2 = t0[t1]
-// t5 = t3[t4],ok
//
+// t2 = t0[t1]
+// t5 = t3[t4],ok
type Lookup struct {
register
X Value // string or map
@@ -897,7 +887,6 @@
// SelectState is a helper for Select.
// It represents one goal state and its corresponding communication.
-//
type SelectState struct {
Dir types.ChanDir // direction of case (SendOnly or RecvOnly)
Chan Value // channel to use (for send or receive)
@@ -912,7 +901,9 @@
// Let n be the number of States for which Dir==RECV and T_i (0<=i<n)
// be the element type of each such state's Chan.
// Select returns an n+2-tuple
-// (index int, recvOk bool, r_0 T_0, ... r_n-1 T_n-1)
+//
+// (index int, recvOk bool, r_0 T_0, ... r_n-1 T_n-1)
+//
// The tuple's components, described below, must be accessed via the
// Extract instruction.
//
@@ -938,9 +929,9 @@
// Pos() returns the ast.SelectStmt.Select.
//
// Example printed form:
-// t3 = select nonblocking [<-t0, t1<-t2]
-// t4 = select blocking []
//
+// t3 = select nonblocking [<-t0, t1<-t2]
+// t4 = select blocking []
type Select struct {
register
States []*SelectState
@@ -957,8 +948,8 @@
// Pos() returns the ast.RangeStmt.For.
//
// Example printed form:
-// t0 = range "hello":string
//
+// t0 = range "hello":string
type Range struct {
register
X Value // string or map
@@ -980,8 +971,8 @@
// The types of k and/or v may be types.Invalid.
//
// Example printed form:
-// t1 = next t0
//
+// t1 = next t0
type Next struct {
register
Iter Value
@@ -1020,9 +1011,9 @@
// type-switch statement.
//
// Example printed form:
-// t1 = typeassert t0.(int)
-// t3 = typeassert,ok t2.(T)
//
+// t1 = typeassert t0.(int)
+// t3 = typeassert,ok t2.(T)
type TypeAssert struct {
register
X Value
@@ -1037,8 +1028,8 @@
// IndexExpr(Map).
//
// Example printed form:
-// t1 = extract t0 #1
//
+// t1 = extract t0 #1
type Extract struct {
register
Tuple Value
@@ -1055,8 +1046,8 @@
// Pos() returns NoPos.
//
// Example printed form:
-// jump done
//
+// jump done
type Jump struct {
anInstruction
}
@@ -1071,8 +1062,8 @@
// Pos() returns NoPos.
//
// Example printed form:
-// if t0 goto done else body
//
+// if t0 goto done else body
type If struct {
anInstruction
Cond Value
@@ -1097,9 +1088,9 @@
// Pos() returns the ast.ReturnStmt.Return, if explicit in the source.
//
// Example printed form:
-// return
-// return nil:I, 2:int
//
+// return
+// return nil:I, 2:int
type Return struct {
anInstruction
Results []Value
@@ -1116,8 +1107,8 @@
// Pos() returns NoPos.
//
// Example printed form:
-// rundefers
//
+// rundefers
type RunDefers struct {
anInstruction
}
@@ -1134,8 +1125,8 @@
// in the source.
//
// Example printed form:
-// panic t0
//
+// panic t0
type Panic struct {
anInstruction
X Value // an interface{}
@@ -1150,10 +1141,10 @@
// Pos() returns the ast.GoStmt.Go.
//
// Example printed form:
-// go println(t0, t1)
-// go t3()
-// go invoke t5.Println(...t6)
//
+// go println(t0, t1)
+// go t3()
+// go invoke t5.Println(...t6)
type Go struct {
anInstruction
Call CallCommon
@@ -1168,10 +1159,10 @@
// Pos() returns the ast.DeferStmt.Defer.
//
// Example printed form:
-// defer println(t0, t1)
-// defer t3()
-// defer invoke t5.Println(...t6)
//
+// defer println(t0, t1)
+// defer t3()
+// defer invoke t5.Println(...t6)
type Defer struct {
anInstruction
Call CallCommon
@@ -1183,8 +1174,8 @@
// Pos() returns the ast.SendStmt.Arrow, if explicit in the source.
//
// Example printed form:
-// send t0 <- t1
//
+// send t0 <- t1
type Send struct {
anInstruction
Chan, X Value
@@ -1200,8 +1191,8 @@
// implementation choices, the details are not specified.
//
// Example printed form:
-// *x = y
//
+// *x = y
type Store struct {
anInstruction
Addr Value
@@ -1216,8 +1207,8 @@
// if explicit in the source.
//
// Example printed form:
-// t0[t1] = t2
//
+// t0[t1] = t2
type MapUpdate struct {
anInstruction
Map Value
@@ -1255,10 +1246,10 @@
// ordinary SSA renaming machinery.)
//
// Example printed form:
-// ; *ast.CallExpr @ 102:9 is t5
-// ; var x float64 @ 109:72 is x
-// ; address of *ast.CompositeLit @ 216:10 is t0
//
+// ; *ast.CallExpr @ 102:9 is t5
+// ; var x float64 @ 109:72 is x
+// ; address of *ast.CompositeLit @ 216:10 is t0
type DebugRef struct {
anInstruction
Expr ast.Expr // the referring expression (never *ast.ParenExpr)
@@ -1281,7 +1272,6 @@
// from it) is unique within a function. As always in this API,
// semantics are determined only by identity; names exist only to
// facilitate debugging.
-//
type register struct {
anInstruction
num int // "name" of virtual register, e.g. "t0". Not guaranteed unique.
@@ -1308,15 +1298,17 @@
// 'func'.
//
// Value may be one of:
-// (a) a *Function, indicating a statically dispatched call
-// to a package-level function, an anonymous function, or
-// a method of a named type.
-// (b) a *MakeClosure, indicating an immediately applied
-// function literal with free variables.
-// (c) a *Builtin, indicating a statically dispatched call
-// to a built-in function.
-// (d) any other value, indicating a dynamically dispatched
-// function call.
+//
+// (a) a *Function, indicating a statically dispatched call
+// to a package-level function, an anonymous function, or
+// a method of a named type.
+// (b) a *MakeClosure, indicating an immediately applied
+// function literal with free variables.
+// (c) a *Builtin, indicating a statically dispatched call
+// to a built-in function.
+// (d) any other value, indicating a dynamically dispatched
+// function call.
+//
// StaticCallee returns the identity of the callee in cases
// (a) and (b), nil otherwise.
//
@@ -1324,8 +1316,9 @@
// Args[0] contains the receiver parameter.
//
// Example printed form:
-// t2 = println(t0, t1)
-// go t3()
+//
+// t2 = println(t0, t1)
+// go t3()
// defer t5(...t6)
//
// 2. "invoke" mode: when Method is non-nil (IsInvoke), a CallCommon
@@ -1340,13 +1333,13 @@
// receiver but the first true argument.
//
// Example printed form:
-// t1 = invoke t0.String()
-// go invoke t3.Run(t2)
-// defer invoke t4.Handle(...t5)
+//
+// t1 = invoke t0.String()
+// go invoke t3.Run(t2)
+// defer invoke t4.Handle(...t5)
//
// For all calls to variadic functions (Signature().Variadic()),
// the last element of Args is a slice.
-//
type CallCommon struct {
Value Value // receiver (invoke mode) or func value (call mode)
Method *types.Func // abstract method (invoke mode)
@@ -1368,7 +1361,6 @@
//
// In either "call" or "invoke" mode, if the callee is a method, its
// receiver is represented by sig.Recv, not sig.Params().At(0).
-//
func (c *CallCommon) Signature() *types.Signature {
if c.Method != nil {
return c.Method.Type().(*types.Signature)
@@ -1411,7 +1403,6 @@
// The CallInstruction interface, implemented by *Go, *Defer and *Call,
// exposes the common parts of function-calling instructions,
// yet provides a way back to the Value defined by *Call alone.
-//
type CallInstruction interface {
Instruction
Common() *CallCommon // returns the common parts of the call
@@ -1511,7 +1502,6 @@
// Func returns the package-level function of the specified name,
// or nil if not found.
-//
func (p *Package) Func(name string) (f *Function) {
f, _ = p.Members[name].(*Function)
return
@@ -1519,7 +1509,6 @@
// Var returns the package-level variable of the specified name,
// or nil if not found.
-//
func (p *Package) Var(name string) (g *Global) {
g, _ = p.Members[name].(*Global)
return
@@ -1527,7 +1516,6 @@
// Const returns the package-level constant of the specified name,
// or nil if not found.
-//
func (p *Package) Const(name string) (c *NamedConst) {
c, _ = p.Members[name].(*NamedConst)
return
@@ -1535,7 +1523,6 @@
// Type returns the package-level type of the specified name,
// or nil if not found.
-//
func (p *Package) Type(name string) (t *Type) {
t, _ = p.Members[name].(*Type)
return
diff --git a/go/ssa/ssautil/load.go b/go/ssa/ssautil/load.go
index 88d7c8f..58d185f 100644
--- a/go/ssa/ssautil/load.go
+++ b/go/ssa/ssautil/load.go
@@ -34,7 +34,6 @@
// packages with well-typed syntax trees.
//
// The mode parameter controls diagnostics and checking during SSA construction.
-//
func Packages(initial []*packages.Package, mode ssa.BuilderMode) (*ssa.Program, []*ssa.Package) {
return doPackages(initial, mode, false)
}
@@ -56,7 +55,6 @@
// well-typed syntax trees.
//
// The mode parameter controls diagnostics and checking during SSA construction.
-//
func AllPackages(initial []*packages.Package, mode ssa.BuilderMode) (*ssa.Program, []*ssa.Package) {
return doPackages(initial, mode, true)
}
@@ -104,7 +102,6 @@
//
// Deprecated: Use golang.org/x/tools/go/packages and the Packages
// function instead; see ssa.Example_loadPackages.
-//
func CreateProgram(lprog *loader.Program, mode ssa.BuilderMode) *ssa.Program {
prog := ssa.NewProgram(lprog.Fset, mode)
@@ -131,7 +128,6 @@
// The operation fails if there were any type-checking or import errors.
//
// See ../example_test.go for an example.
-//
func BuildPackage(tc *types.Config, fset *token.FileSet, pkg *types.Package, files []*ast.File, mode ssa.BuilderMode) (*ssa.Package, *types.Info, error) {
if fset == nil {
panic("no token.FileSet")
diff --git a/go/ssa/ssautil/switch.go b/go/ssa/ssautil/switch.go
index db03bf5..dd4b04e 100644
--- a/go/ssa/ssautil/switch.go
+++ b/go/ssa/ssautil/switch.go
@@ -55,7 +55,6 @@
// A type switch may contain duplicate types, or types assignable
// to an interface type also in the list.
// TODO(adonovan): eliminate such duplicates.
-//
type Switch struct {
Start *ssa.BasicBlock // block containing start of if/else chain
X ssa.Value // the switch operand
@@ -103,7 +102,6 @@
// Switches may even be inferred from if/else- or goto-based control flow.
// (In general, the control flow constructs of the source program
// cannot be faithfully reproduced from the SSA representation.)
-//
func Switches(fn *ssa.Function) []Switch {
// Traverse the CFG in dominance order, so we don't
// enter an if/else-chain in the middle.
@@ -197,7 +195,6 @@
// isComparisonBlock returns the operands (v, k) if a block ends with
// a comparison v==k, where k is a compile-time constant.
-//
func isComparisonBlock(b *ssa.BasicBlock) (v ssa.Value, k *ssa.Const) {
if n := len(b.Instrs); n >= 2 {
if i, ok := b.Instrs[n-1].(*ssa.If); ok {
@@ -216,7 +213,6 @@
// isTypeAssertBlock returns the operands (y, x, T) if a block ends with
// a type assertion "if y, ok := x.(T); ok {".
-//
func isTypeAssertBlock(b *ssa.BasicBlock) (y, x ssa.Value, T types.Type) {
if n := len(b.Instrs); n >= 4 {
if i, ok := b.Instrs[n-1].(*ssa.If); ok {
diff --git a/go/ssa/ssautil/visit.go b/go/ssa/ssautil/visit.go
index 3424e8a..5f27050 100644
--- a/go/ssa/ssautil/visit.go
+++ b/go/ssa/ssautil/visit.go
@@ -18,7 +18,6 @@
// synthetic wrappers.
//
// Precondition: all packages are built.
-//
func AllFunctions(prog *ssa.Program) map[*ssa.Function]bool {
visit := visitor{
prog: prog,
diff --git a/go/ssa/util.go b/go/ssa/util.go
index 87a8a24..8c711cb 100644
--- a/go/ssa/util.go
+++ b/go/ssa/util.go
@@ -36,7 +36,6 @@
// isBlankIdent returns true iff e is an Ident with name "_".
// They have no associated types.Object, and thus no type.
-//
func isBlankIdent(e ast.Expr) bool {
id, ok := e.(*ast.Ident)
return ok && id.Name == "_"
@@ -75,7 +74,6 @@
// returns a closure that prints the corresponding "end" message.
// Call using 'defer logStack(...)()' to show builder stack on panic.
// Don't forget trailing parens!
-//
func logStack(format string, args ...interface{}) func() {
msg := fmt.Sprintf(format, args...)
io.WriteString(os.Stderr, msg)
diff --git a/go/ssa/wrappers.go b/go/ssa/wrappers.go
index 69bc833..799ba14 100644
--- a/go/ssa/wrappers.go
+++ b/go/ssa/wrappers.go
@@ -42,7 +42,6 @@
// - the result may be a thunk or a wrapper.
//
// EXCLUSIVE_LOCKS_REQUIRED(prog.methodsMu)
-//
func makeWrapper(prog *Program, sel *types.Selection, cr *creator) *Function {
obj := sel.Obj().(*types.Func) // the declared function
sig := sel.Type().(*types.Signature) // type of this wrapper
@@ -147,7 +146,6 @@
// createParams creates parameters for wrapper method fn based on its
// Signature.Params, which do not include the receiver.
// start is the index of the first regular parameter to use.
-//
func createParams(fn *Function, start int) {
tparams := fn.Signature.Params()
for i, n := start, tparams.Len(); i < n; i++ {
@@ -166,22 +164,21 @@
// Use MakeClosure with such a wrapper to construct a bound method
// closure. e.g.:
//
-// type T int or: type T interface { meth() }
-// func (t T) meth()
-// var t T
-// f := t.meth
-// f() // calls t.meth()
+// type T int or: type T interface { meth() }
+// func (t T) meth()
+// var t T
+// f := t.meth
+// f() // calls t.meth()
//
// f is a closure of a synthetic wrapper defined as if by:
//
-// f := func() { return t.meth() }
+// f := func() { return t.meth() }
//
// Unlike makeWrapper, makeBound need perform no indirection or field
// selections because that can be done before the closure is
// constructed.
//
// EXCLUSIVE_LOCKS_ACQUIRED(meth.Prog.methodsMu)
-//
func makeBound(prog *Program, obj *types.Func, cr *creator) *Function {
targs := receiverTypeArgs(obj)
key := boundsKey{obj, prog.canon.List(targs)}
@@ -243,22 +240,21 @@
//
// Precondition: sel.Kind() == types.MethodExpr.
//
-// type T int or: type T interface { meth() }
-// func (t T) meth()
-// f := T.meth
-// var t T
-// f(t) // calls t.meth()
+// type T int or: type T interface { meth() }
+// func (t T) meth()
+// f := T.meth
+// var t T
+// f(t) // calls t.meth()
//
// f is a synthetic wrapper defined as if by:
//
-// f := func(t T) { return t.meth() }
+// f := func(t T) { return t.meth() }
//
// TODO(adonovan): opt: currently the stub is created even when used
// directly in a function call: C.f(i, 0). This is less efficient
// than inlining the stub.
//
// EXCLUSIVE_LOCKS_ACQUIRED(meth.Prog.methodsMu)
-//
func makeThunk(prog *Program, sel *types.Selection, cr *creator) *Function {
if sel.Kind() != types.MethodExpr {
panic(sel)