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