go/src/cmd/compile/internal/ssa/print.go

94 lines
2 KiB
Go
Raw Normal View History

// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ssa
import (
"bytes"
"fmt"
"io"
"os"
)
func printFunc(f *Func) {
f.Logf("%s", f)
}
func (f *Func) String() string {
var buf bytes.Buffer
fprintFunc(&buf, f)
return buf.String()
}
func fprintFunc(w io.Writer, f *Func) {
fmt.Fprint(w, f.Name)
fmt.Fprint(w, " ")
fmt.Fprintln(w, f.Type)
printed := make([]bool, f.NumValues())
for _, b := range f.Blocks {
fmt.Fprintf(w, " b%d:", b.ID)
if len(b.Preds) > 0 {
io.WriteString(w, " <-")
for _, pred := range b.Preds {
fmt.Fprintf(w, " b%d", pred.ID)
}
}
io.WriteString(w, "\n")
n := 0
// print phis first since all value cycles contain a phi
for _, v := range b.Values {
if v.Op != OpPhi {
continue
}
fmt.Fprint(w, " ")
fmt.Fprintln(w, v.LongString())
printed[v.ID] = true
n++
}
// print rest of values in dependency order
for n < len(b.Values) {
m := n
outer:
for _, v := range b.Values {
if printed[v.ID] {
continue
}
for _, w := range v.Args {
// w == nil shouldn't happen, but if it does,
// don't panic; we'll get a better diagnosis later.
if w != nil && w.Block == b && !printed[w.ID] {
continue outer
}
}
fmt.Fprint(w, " ")
fmt.Fprintln(w, v.LongString())
printed[v.ID] = true
n++
}
if m == n {
fmt.Fprintln(os.Stderr, "dependency cycle in block", b)
for _, v := range b.Values {
if printed[v.ID] {
continue
}
fmt.Fprintf(os.Stderr, " %v\n", v.LongString())
printed[v.ID] = true
n++
}
// Things are going to go very badly from here;
// one of the optimization passes is likely to hang.
// Frustratingly, panics here get swallowed by fmt,
// and just we end up here again if we call Fatalf.
// Use our last resort.
os.Exit(1)
return
}
}
fmt.Fprintln(w, " "+b.LongString())
}
}