1
2
3
4
5 package ssa
6
7 import (
8 "bytes"
9 "cmd/internal/src"
10 "crypto/sha256"
11 "fmt"
12 "io"
13 )
14
15 func printFunc(f *Func) {
16 f.Logf("%s", f)
17 }
18
19 func hashFunc(f *Func) []byte {
20 h := sha256.New()
21 p := stringFuncPrinter{w: h, printDead: true}
22 fprintFunc(p, f)
23 return h.Sum(nil)
24 }
25
26 func (f *Func) String() string {
27 var buf bytes.Buffer
28 p := stringFuncPrinter{w: &buf, printDead: true}
29 fprintFunc(p, f)
30 return buf.String()
31 }
32
33
34 func (f *Func) rewriteHash() string {
35 h := sha256.New()
36 p := stringFuncPrinter{w: h, printDead: false}
37 fprintFunc(p, f)
38 return fmt.Sprintf("%x", h.Sum(nil))
39 }
40
41 type funcPrinter interface {
42 header(f *Func)
43 startBlock(b *Block, reachable bool)
44 endBlock(b *Block, reachable bool)
45 value(v *Value, live bool)
46 startDepCycle()
47 endDepCycle()
48 named(n LocalSlot, vals []*Value)
49 }
50
51 type stringFuncPrinter struct {
52 w io.Writer
53 printDead bool
54 }
55
56 func (p stringFuncPrinter) header(f *Func) {
57 fmt.Fprint(p.w, f.Name)
58 fmt.Fprint(p.w, " ")
59 fmt.Fprintln(p.w, f.Type)
60 }
61
62 func (p stringFuncPrinter) startBlock(b *Block, reachable bool) {
63 if !p.printDead && !reachable {
64 return
65 }
66 fmt.Fprintf(p.w, " b%d:", b.ID)
67 if len(b.Preds) > 0 {
68 io.WriteString(p.w, " <-")
69 for _, e := range b.Preds {
70 pred := e.b
71 fmt.Fprintf(p.w, " b%d", pred.ID)
72 }
73 }
74 if !reachable {
75 fmt.Fprint(p.w, " DEAD")
76 }
77 io.WriteString(p.w, "\n")
78 }
79
80 func (p stringFuncPrinter) endBlock(b *Block, reachable bool) {
81 if !p.printDead && !reachable {
82 return
83 }
84 fmt.Fprintln(p.w, " "+b.LongString())
85 }
86
87 func StmtString(p src.XPos) string {
88 linenumber := "(?) "
89 if p.IsKnown() {
90 pfx := ""
91 if p.IsStmt() == src.PosIsStmt {
92 pfx = "+"
93 }
94 if p.IsStmt() == src.PosNotStmt {
95 pfx = "-"
96 }
97 linenumber = fmt.Sprintf("(%s%d) ", pfx, p.Line())
98 }
99 return linenumber
100 }
101
102 func (p stringFuncPrinter) value(v *Value, live bool) {
103 if !p.printDead && !live {
104 return
105 }
106 fmt.Fprintf(p.w, " %s", StmtString(v.Pos))
107 fmt.Fprint(p.w, v.LongString())
108 if !live {
109 fmt.Fprint(p.w, " DEAD")
110 }
111 fmt.Fprintln(p.w)
112 }
113
114 func (p stringFuncPrinter) startDepCycle() {
115 fmt.Fprintln(p.w, "dependency cycle!")
116 }
117
118 func (p stringFuncPrinter) endDepCycle() {}
119
120 func (p stringFuncPrinter) named(n LocalSlot, vals []*Value) {
121 fmt.Fprintf(p.w, "name %s: %v\n", n, vals)
122 }
123
124 func fprintFunc(p funcPrinter, f *Func) {
125 reachable, live := findlive(f)
126 defer f.retDeadcodeLive(live)
127 p.header(f)
128 printed := make([]bool, f.NumValues())
129 for _, b := range f.Blocks {
130 p.startBlock(b, reachable[b.ID])
131
132 if f.scheduled {
133
134 for _, v := range b.Values {
135 p.value(v, live[v.ID])
136 printed[v.ID] = true
137 }
138 p.endBlock(b, reachable[b.ID])
139 continue
140 }
141
142
143 n := 0
144 for _, v := range b.Values {
145 if v.Op != OpPhi {
146 continue
147 }
148 p.value(v, live[v.ID])
149 printed[v.ID] = true
150 n++
151 }
152
153
154 for n < len(b.Values) {
155 m := n
156 outer:
157 for _, v := range b.Values {
158 if printed[v.ID] {
159 continue
160 }
161 for _, w := range v.Args {
162
163
164 if w != nil && w.Block == b && !printed[w.ID] {
165 continue outer
166 }
167 }
168 p.value(v, live[v.ID])
169 printed[v.ID] = true
170 n++
171 }
172 if m == n {
173 p.startDepCycle()
174 for _, v := range b.Values {
175 if printed[v.ID] {
176 continue
177 }
178 p.value(v, live[v.ID])
179 printed[v.ID] = true
180 n++
181 }
182 p.endDepCycle()
183 }
184 }
185
186 p.endBlock(b, reachable[b.ID])
187 }
188 for _, name := range f.Names {
189 p.named(*name, f.NamedValues[*name])
190 }
191 }
192
View as plain text