Commit 71c37e1c authored by Alan Donovan's avatar Alan Donovan

exp/ssa: fixed bug (typo) in findPromotedField.

By appending to the wrong (always empty) list, only the last
anonymous field was being considered for promotion.

Also:
- eliminated "function-local NamedTypes" TODO; nothing to do.
- fixed Function.DumpTo: printing of anon receivers was "( T)",
  now "(T)"; extracted writeSignature into own function.
- eliminated blockNames function;
  thanks to BasicBlock.String, "%s" of []*BasicBlock is fine.
- extracted buildReferrers into own function.

exp/ssa can now build its own transitive closure.

R=gri
CC=golang-dev
https://golang.org/cl/7384054
parent 0ba5f755
...@@ -33,8 +33,6 @@ package ssa ...@@ -33,8 +33,6 @@ package ssa
// TODO(adonovan): fix the following: // TODO(adonovan): fix the following:
// - support f(g()) where g has multiple result parameters. // - support f(g()) where g has multiple result parameters.
// - concurrent SSA code generation of multiple packages. // - concurrent SSA code generation of multiple packages.
// - consider function-local NamedTypes.
// They can have nonempty method-sets due to promotion. Test.
import ( import (
"fmt" "fmt"
......
...@@ -265,6 +265,25 @@ func numberRegisters(f *Function) { ...@@ -265,6 +265,25 @@ func numberRegisters(f *Function) {
} }
} }
// buildReferrers populates the def/use information in all non-nil
// Value.Referrers slice.
// Precondition: all such slices are initially empty.
func buildReferrers(f *Function) {
var rands []*Value
for _, b := range f.Blocks {
for _, instr := range b.Instrs {
rands = instr.Operands(rands[:0]) // recycle storage
for _, rand := range rands {
if r := *rand; r != nil {
if ref := r.Referrers(); ref != nil {
*ref = append(*ref, instr)
}
}
}
}
}
}
// finish() finalizes the function after SSA code generation of its body. // finish() finalizes the function after SSA code generation of its body.
func (f *Function) finish() { func (f *Function) finish() {
f.objects = nil f.objects = nil
...@@ -289,20 +308,7 @@ func (f *Function) finish() { ...@@ -289,20 +308,7 @@ func (f *Function) finish() {
optimizeBlocks(f) optimizeBlocks(f)
// Build immediate-use (referrers) graph. buildReferrers(f)
var rands []*Value
for _, b := range f.Blocks {
for _, instr := range b.Instrs {
rands = instr.Operands(rands[:0]) // recycle storage
for _, rand := range rands {
if r := *rand; r != nil {
if ref := r.Referrers(); ref != nil {
*ref = append(*ref, instr)
}
}
}
}
}
if f.Prog.mode&NaiveForm == 0 { if f.Prog.mode&NaiveForm == 0 {
// For debugging pre-state of lifting pass: // For debugging pre-state of lifting pass:
...@@ -460,39 +466,22 @@ func (f *Function) fullName(from *Package) string { ...@@ -460,39 +466,22 @@ func (f *Function) fullName(from *Package) string {
return f.Name_ return f.Name_
} }
// DumpTo prints to w a human readable "disassembly" of the SSA code of // writeSignature writes to w the signature sig in declaration syntax.
// all basic blocks of function f. // Derived from types.Signature.String().
// //
func (f *Function) DumpTo(w io.Writer) { func writeSignature(w io.Writer, name string, sig *types.Signature, params []*Parameter) {
fmt.Fprintf(w, "# Name: %s\n", f.FullName())
fmt.Fprintf(w, "# Declared at %s\n", f.Prog.Files.Position(f.Pos))
if f.Enclosing != nil {
fmt.Fprintf(w, "# Parent: %s\n", f.Enclosing.Name())
}
if f.FreeVars != nil {
io.WriteString(w, "# Free variables:\n")
for i, fv := range f.FreeVars {
fmt.Fprintf(w, "# % 3d:\t%s %s\n", i, fv.Name(), fv.Type())
}
}
if len(f.Locals) > 0 {
io.WriteString(w, "# Locals:\n")
for i, l := range f.Locals {
fmt.Fprintf(w, "# % 3d:\t%s %s\n", i, l.Name(), indirectType(l.Type()))
}
}
// Function Signature in declaration syntax; derived from types.Signature.String().
io.WriteString(w, "func ") io.WriteString(w, "func ")
params := f.Params if sig.Recv != nil {
if f.Signature.Recv != nil { io.WriteString(w, "(")
fmt.Fprintf(w, "(%s %s) ", params[0].Name(), params[0].Type()) if n := params[0].Name(); n != "" {
io.WriteString(w, n)
io.WriteString(w, " ")
}
io.WriteString(w, params[0].Type().String())
io.WriteString(w, ") ")
params = params[1:] params = params[1:]
} }
io.WriteString(w, f.Name()) io.WriteString(w, name)
io.WriteString(w, "(") io.WriteString(w, "(")
for i, v := range params { for i, v := range params {
if i > 0 { if i > 0 {
...@@ -500,13 +489,13 @@ func (f *Function) DumpTo(w io.Writer) { ...@@ -500,13 +489,13 @@ func (f *Function) DumpTo(w io.Writer) {
} }
io.WriteString(w, v.Name()) io.WriteString(w, v.Name())
io.WriteString(w, " ") io.WriteString(w, " ")
if f.Signature.IsVariadic && i == len(params)-1 { if sig.IsVariadic && i == len(params)-1 {
io.WriteString(w, "...") io.WriteString(w, "...")
} }
io.WriteString(w, v.Type().String()) io.WriteString(w, v.Type().String())
} }
io.WriteString(w, ")") io.WriteString(w, ")")
if res := f.Signature.Results; res != nil { if res := sig.Results; res != nil {
io.WriteString(w, " ") io.WriteString(w, " ")
var t types.Type var t types.Type
if len(res) == 1 && res[0].Name == "" { if len(res) == 1 && res[0].Name == "" {
...@@ -516,6 +505,34 @@ func (f *Function) DumpTo(w io.Writer) { ...@@ -516,6 +505,34 @@ func (f *Function) DumpTo(w io.Writer) {
} }
io.WriteString(w, t.String()) io.WriteString(w, t.String())
} }
}
// DumpTo prints to w a human readable "disassembly" of the SSA code of
// all basic blocks of function f.
//
func (f *Function) DumpTo(w io.Writer) {
fmt.Fprintf(w, "# Name: %s\n", f.FullName())
fmt.Fprintf(w, "# Declared at %s\n", f.Prog.Files.Position(f.Pos))
if f.Enclosing != nil {
fmt.Fprintf(w, "# Parent: %s\n", f.Enclosing.Name())
}
if f.FreeVars != nil {
io.WriteString(w, "# Free variables:\n")
for i, fv := range f.FreeVars {
fmt.Fprintf(w, "# % 3d:\t%s %s\n", i, fv.Name(), fv.Type())
}
}
if len(f.Locals) > 0 {
io.WriteString(w, "# Locals:\n")
for i, l := range f.Locals {
fmt.Fprintf(w, "# % 3d:\t%s %s\n", i, l.Name(), indirectType(l.Type()))
}
}
writeSignature(w, f.Name(), f.Signature, f.Params)
io.WriteString(w, ":\n") io.WriteString(w, ":\n")
if f.Blocks == nil { if f.Blocks == nil {
...@@ -530,7 +547,7 @@ func (f *Function) DumpTo(w io.Writer) { ...@@ -530,7 +547,7 @@ func (f *Function) DumpTo(w io.Writer) {
} }
fmt.Fprintf(w, ".%s:\t\t\t\t\t\t\t P:%d S:%d\n", b, len(b.Preds), len(b.Succs)) fmt.Fprintf(w, ".%s:\t\t\t\t\t\t\t P:%d S:%d\n", b, len(b.Preds), len(b.Succs))
if false { // CFG debugging if false { // CFG debugging
fmt.Fprintf(w, "\t# CFG: %s --> %s --> %s\n", blockNames(b.Preds), b, blockNames(b.Succs)) fmt.Fprintf(w, "\t# CFG: %s --> %s --> %s\n", b.Preds, b, b.Succs)
} }
for _, instr := range b.Instrs { for _, instr := range b.Instrs {
io.WriteString(w, "\t") io.WriteString(w, "\t")
......
...@@ -408,7 +408,7 @@ func findPromotedField(st *types.Struct, id Id) (*anonFieldPath, int) { ...@@ -408,7 +408,7 @@ func findPromotedField(st *types.Struct, id Id) (*anonFieldPath, int) {
var list, next []*anonFieldPath var list, next []*anonFieldPath
for i, f := range st.Fields { for i, f := range st.Fields {
if f.IsAnonymous { if f.IsAnonymous {
list = append(next, &anonFieldPath{nil, i, f}) list = append(list, &anonFieldPath{nil, i, f})
} }
} }
......
...@@ -4,7 +4,6 @@ package ssa ...@@ -4,7 +4,6 @@ package ssa
// Currently it checks CFG invariants but little at the instruction level. // Currently it checks CFG invariants but little at the instruction level.
import ( import (
"bytes"
"fmt" "fmt"
"io" "io"
"os" "os"
...@@ -41,20 +40,6 @@ func MustSanityCheck(fn *Function, reporter io.Writer) { ...@@ -41,20 +40,6 @@ func MustSanityCheck(fn *Function, reporter io.Writer) {
} }
} }
// blockNames returns the names of the specified blocks as a
// human-readable string.
//
func blockNames(blocks []*BasicBlock) string {
var buf bytes.Buffer
for i, b := range blocks {
if i > 0 {
io.WriteString(&buf, ", ")
}
io.WriteString(&buf, b.String())
}
return buf.String()
}
func (s *sanity) diagnostic(prefix, format string, args ...interface{}) { func (s *sanity) diagnostic(prefix, format string, args ...interface{}) {
fmt.Fprintf(s.reporter, "%s: function %s", prefix, s.fn.FullName()) fmt.Fprintf(s.reporter, "%s: function %s", prefix, s.fn.FullName())
if s.block != nil { if s.block != nil {
...@@ -236,7 +221,7 @@ func (s *sanity) checkBlock(b *BasicBlock, index int) { ...@@ -236,7 +221,7 @@ func (s *sanity) checkBlock(b *BasicBlock, index int) {
} }
} }
if !found { if !found {
s.errorf("expected successor edge in predecessor %s; found only: %s", a, blockNames(a.Succs)) s.errorf("expected successor edge in predecessor %s; found only: %s", a, a.Succs)
} }
if a.Func != s.fn { if a.Func != s.fn {
s.errorf("predecessor %s belongs to different function %s", a, a.Func.FullName()) s.errorf("predecessor %s belongs to different function %s", a, a.Func.FullName())
...@@ -251,7 +236,7 @@ func (s *sanity) checkBlock(b *BasicBlock, index int) { ...@@ -251,7 +236,7 @@ func (s *sanity) checkBlock(b *BasicBlock, index int) {
} }
} }
if !found { if !found {
s.errorf("expected predecessor edge in successor %s; found only: %s", c, blockNames(c.Preds)) s.errorf("expected predecessor edge in successor %s; found only: %s", c, c.Preds)
} }
if c.Func != s.fn { if c.Func != s.fn {
s.errorf("successor %s belongs to different function %s", c, c.Func.FullName()) s.errorf("successor %s belongs to different function %s", c, c.Func.FullName())
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment