diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 13:16:40 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 13:16:40 +0000 |
commit | 47ab3d4a42e9ab51c465c4322d2ec233f6324e6b (patch) | |
tree | a61a0ffd83f4a3def4b36e5c8e99630c559aa723 /src/cmd/compile/internal/ssa/print.go | |
parent | Initial commit. (diff) | |
download | golang-1.18-47ab3d4a42e9ab51c465c4322d2ec233f6324e6b.tar.xz golang-1.18-47ab3d4a42e9ab51c465c4322d2ec233f6324e6b.zip |
Adding upstream version 1.18.10.upstream/1.18.10upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/cmd/compile/internal/ssa/print.go')
-rw-r--r-- | src/cmd/compile/internal/ssa/print.go | 191 |
1 files changed, 191 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/ssa/print.go b/src/cmd/compile/internal/ssa/print.go new file mode 100644 index 0000000..96cd2c7 --- /dev/null +++ b/src/cmd/compile/internal/ssa/print.go @@ -0,0 +1,191 @@ +// 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" + "cmd/internal/src" + "crypto/sha256" + "fmt" + "io" +) + +func printFunc(f *Func) { + f.Logf("%s", f) +} + +func hashFunc(f *Func) []byte { + h := sha256.New() + p := stringFuncPrinter{w: h, printDead: true} + fprintFunc(p, f) + return h.Sum(nil) +} + +func (f *Func) String() string { + var buf bytes.Buffer + p := stringFuncPrinter{w: &buf, printDead: true} + fprintFunc(p, f) + return buf.String() +} + +// rewriteHash returns a hash of f suitable for detecting rewrite cycles. +func (f *Func) rewriteHash() string { + h := sha256.New() + p := stringFuncPrinter{w: h, printDead: false} + fprintFunc(p, f) + return fmt.Sprintf("%x", h.Sum(nil)) +} + +type funcPrinter interface { + header(f *Func) + startBlock(b *Block, reachable bool) + endBlock(b *Block, reachable bool) + value(v *Value, live bool) + startDepCycle() + endDepCycle() + named(n LocalSlot, vals []*Value) +} + +type stringFuncPrinter struct { + w io.Writer + printDead bool +} + +func (p stringFuncPrinter) header(f *Func) { + fmt.Fprint(p.w, f.Name) + fmt.Fprint(p.w, " ") + fmt.Fprintln(p.w, f.Type) +} + +func (p stringFuncPrinter) startBlock(b *Block, reachable bool) { + if !p.printDead && !reachable { + return + } + fmt.Fprintf(p.w, " b%d:", b.ID) + if len(b.Preds) > 0 { + io.WriteString(p.w, " <-") + for _, e := range b.Preds { + pred := e.b + fmt.Fprintf(p.w, " b%d", pred.ID) + } + } + if !reachable { + fmt.Fprint(p.w, " DEAD") + } + io.WriteString(p.w, "\n") +} + +func (p stringFuncPrinter) endBlock(b *Block, reachable bool) { + if !p.printDead && !reachable { + return + } + fmt.Fprintln(p.w, " "+b.LongString()) +} + +func StmtString(p src.XPos) string { + linenumber := "(?) " + if p.IsKnown() { + pfx := "" + if p.IsStmt() == src.PosIsStmt { + pfx = "+" + } + if p.IsStmt() == src.PosNotStmt { + pfx = "-" + } + linenumber = fmt.Sprintf("(%s%d) ", pfx, p.Line()) + } + return linenumber +} + +func (p stringFuncPrinter) value(v *Value, live bool) { + if !p.printDead && !live { + return + } + fmt.Fprintf(p.w, " %s", StmtString(v.Pos)) + fmt.Fprint(p.w, v.LongString()) + if !live { + fmt.Fprint(p.w, " DEAD") + } + fmt.Fprintln(p.w) +} + +func (p stringFuncPrinter) startDepCycle() { + fmt.Fprintln(p.w, "dependency cycle!") +} + +func (p stringFuncPrinter) endDepCycle() {} + +func (p stringFuncPrinter) named(n LocalSlot, vals []*Value) { + fmt.Fprintf(p.w, "name %s: %v\n", n, vals) +} + +func fprintFunc(p funcPrinter, f *Func) { + reachable, live := findlive(f) + defer f.retDeadcodeLive(live) + p.header(f) + printed := make([]bool, f.NumValues()) + for _, b := range f.Blocks { + p.startBlock(b, reachable[b.ID]) + + if f.scheduled { + // Order of Values has been decided - print in that order. + for _, v := range b.Values { + p.value(v, live[v.ID]) + printed[v.ID] = true + } + p.endBlock(b, reachable[b.ID]) + continue + } + + // print phis first since all value cycles contain a phi + n := 0 + for _, v := range b.Values { + if v.Op != OpPhi { + continue + } + p.value(v, live[v.ID]) + 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 + } + } + p.value(v, live[v.ID]) + printed[v.ID] = true + n++ + } + if m == n { + p.startDepCycle() + for _, v := range b.Values { + if printed[v.ID] { + continue + } + p.value(v, live[v.ID]) + printed[v.ID] = true + n++ + } + p.endDepCycle() + } + } + + p.endBlock(b, reachable[b.ID]) + } + for _, name := range f.Names { + p.named(*name, f.NamedValues[*name]) + } +} |