1
2
3
4
5 package ssa
6
7 import (
8 "cmd/internal/src"
9 "fmt"
10 )
11
12
13 type Block struct {
14
15
16 ID ID
17
18
19 Pos src.XPos
20
21
22 Kind BlockKind
23
24
25
26
27
28
29 Likely BranchPrediction
30
31
32 FlagsLiveAtEnd bool
33
34
35 Succs []Edge
36
37
38
39
40
41 Preds []Edge
42
43
44
45
46
47
48
49
50
51
52 Controls [2]*Value
53
54
55 Aux Aux
56 AuxInt int64
57
58
59
60 Values []*Value
61
62
63 Func *Func
64
65
66 succstorage [2]Edge
67 predstorage [4]Edge
68 valstorage [9]*Value
69 }
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 type Edge struct {
89
90 b *Block
91
92
93
94
95 i int
96 }
97
98 func (e Edge) Block() *Block {
99 return e.b
100 }
101 func (e Edge) Index() int {
102 return e.i
103 }
104 func (e Edge) String() string {
105 return fmt.Sprintf("{%v,%d}", e.b, e.i)
106 }
107
108
109
110
111
112
113
114 type BlockKind int8
115
116
117 func (b *Block) String() string {
118 return fmt.Sprintf("b%d", b.ID)
119 }
120
121
122 func (b *Block) LongString() string {
123 s := b.Kind.String()
124 if b.Aux != nil {
125 s += fmt.Sprintf(" {%s}", b.Aux)
126 }
127 if t := b.AuxIntString(); t != "" {
128 s += fmt.Sprintf(" [%s]", t)
129 }
130 for _, c := range b.ControlValues() {
131 s += fmt.Sprintf(" %s", c)
132 }
133 if len(b.Succs) > 0 {
134 s += " ->"
135 for _, c := range b.Succs {
136 s += " " + c.b.String()
137 }
138 }
139 switch b.Likely {
140 case BranchUnlikely:
141 s += " (unlikely)"
142 case BranchLikely:
143 s += " (likely)"
144 }
145 return s
146 }
147
148
149
150 func (b *Block) NumControls() int {
151 if b.Controls[0] == nil {
152 return 0
153 }
154 if b.Controls[1] == nil {
155 return 1
156 }
157 return 2
158 }
159
160
161
162
163
164 func (b *Block) ControlValues() []*Value {
165 if b.Controls[0] == nil {
166 return b.Controls[:0]
167 }
168 if b.Controls[1] == nil {
169 return b.Controls[:1]
170 }
171 return b.Controls[:2]
172 }
173
174
175
176
177 func (b *Block) SetControl(v *Value) {
178 b.ResetControls()
179 b.Controls[0] = v
180 v.Uses++
181 }
182
183
184 func (b *Block) ResetControls() {
185 if b.Controls[0] != nil {
186 b.Controls[0].Uses--
187 }
188 if b.Controls[1] != nil {
189 b.Controls[1].Uses--
190 }
191 b.Controls = [2]*Value{}
192 }
193
194
195 func (b *Block) AddControl(v *Value) {
196 i := b.NumControls()
197 b.Controls[i] = v
198 v.Uses++
199 }
200
201
202
203 func (b *Block) ReplaceControl(i int, v *Value) {
204 b.Controls[i].Uses--
205 b.Controls[i] = v
206 v.Uses++
207 }
208
209
210
211 func (b *Block) CopyControls(from *Block) {
212 if b == from {
213 return
214 }
215 b.ResetControls()
216 for _, c := range from.ControlValues() {
217 b.AddControl(c)
218 }
219 }
220
221
222
223
224 func (b *Block) Reset(kind BlockKind) {
225 b.Kind = kind
226 b.ResetControls()
227 b.Aux = nil
228 b.AuxInt = 0
229 }
230
231
232
233
234
235 func (b *Block) resetWithControl(kind BlockKind, v *Value) {
236 b.Kind = kind
237 b.ResetControls()
238 b.Aux = nil
239 b.AuxInt = 0
240 b.Controls[0] = v
241 v.Uses++
242 }
243
244
245
246
247
248 func (b *Block) resetWithControl2(kind BlockKind, v, w *Value) {
249 b.Kind = kind
250 b.ResetControls()
251 b.Aux = nil
252 b.AuxInt = 0
253 b.Controls[0] = v
254 b.Controls[1] = w
255 v.Uses++
256 w.Uses++
257 }
258
259
260
261
262 func (b *Block) truncateValues(i int) {
263 tail := b.Values[i:]
264 for j := range tail {
265 tail[j] = nil
266 }
267 b.Values = b.Values[:i]
268 }
269
270
271
272 func (b *Block) AddEdgeTo(c *Block) {
273 i := len(b.Succs)
274 j := len(c.Preds)
275 b.Succs = append(b.Succs, Edge{c, j})
276 c.Preds = append(c.Preds, Edge{b, i})
277 b.Func.invalidateCFG()
278 }
279
280
281
282
283
284 func (b *Block) removePred(i int) {
285 n := len(b.Preds) - 1
286 if i != n {
287 e := b.Preds[n]
288 b.Preds[i] = e
289
290 e.b.Succs[e.i].i = i
291 }
292 b.Preds[n] = Edge{}
293 b.Preds = b.Preds[:n]
294 b.Func.invalidateCFG()
295 }
296
297
298
299
300 func (b *Block) removeSucc(i int) {
301 n := len(b.Succs) - 1
302 if i != n {
303 e := b.Succs[n]
304 b.Succs[i] = e
305
306 e.b.Preds[e.i].i = i
307 }
308 b.Succs[n] = Edge{}
309 b.Succs = b.Succs[:n]
310 b.Func.invalidateCFG()
311 }
312
313 func (b *Block) swapSuccessors() {
314 if len(b.Succs) != 2 {
315 b.Fatalf("swapSuccessors with len(Succs)=%d", len(b.Succs))
316 }
317 e0 := b.Succs[0]
318 e1 := b.Succs[1]
319 b.Succs[0] = e1
320 b.Succs[1] = e0
321 e0.b.Preds[e0.i].i = 1
322 e1.b.Preds[e1.i].i = 0
323 b.Likely *= -1
324 }
325
326
327
328
329
330
331
332
333
334
335
336
337 func (b *Block) removePhiArg(phi *Value, i int) {
338 n := len(b.Preds)
339 if numPhiArgs := len(phi.Args); numPhiArgs-1 != n {
340 b.Fatalf("inconsistent state, num predecessors: %d, num phi args: %d", n, numPhiArgs)
341 }
342 phi.Args[i].Uses--
343 phi.Args[i] = phi.Args[n]
344 phi.Args[n] = nil
345 phi.Args = phi.Args[:n]
346 }
347
348
349
350
351
352 func (b *Block) LackingPos() bool {
353
354
355
356 if b.Kind != BlockPlain {
357 return false
358 }
359 if b.Pos != src.NoXPos {
360 return false
361 }
362 for _, v := range b.Values {
363 if v.LackingPos() {
364 continue
365 }
366 return false
367 }
368 return true
369 }
370
371 func (b *Block) AuxIntString() string {
372 switch b.Kind.AuxIntType() {
373 case "int8":
374 return fmt.Sprintf("%v", int8(b.AuxInt))
375 case "uint8":
376 return fmt.Sprintf("%v", uint8(b.AuxInt))
377 default:
378 return fmt.Sprintf("%v", b.AuxInt)
379 case "":
380 return ""
381 }
382 }
383
384
385 func (b *Block) likelyBranch() bool {
386 if len(b.Preds) == 0 {
387 return false
388 }
389 for _, e := range b.Preds {
390 p := e.b
391 if len(p.Succs) == 1 || len(p.Succs) == 2 && (p.Likely == BranchLikely && p.Succs[0].b == b ||
392 p.Likely == BranchUnlikely && p.Succs[1].b == b) {
393 continue
394 }
395 return false
396 }
397 return true
398 }
399
400 func (b *Block) Logf(msg string, args ...interface{}) { b.Func.Logf(msg, args...) }
401 func (b *Block) Log() bool { return b.Func.Log() }
402 func (b *Block) Fatalf(msg string, args ...interface{}) { b.Func.Fatalf(msg, args...) }
403
404 type BranchPrediction int8
405
406 const (
407 BranchUnlikely = BranchPrediction(-1)
408 BranchUnknown = BranchPrediction(0)
409 BranchLikely = BranchPrediction(+1)
410 )
411
View as plain text