github.com/gocuntian/go@v0.0.0-20160610041250-fee02d270bf8/src/cmd/compile/internal/ssa/block.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ssa 6 7 import "fmt" 8 9 // Block represents a basic block in the control flow graph of a function. 10 type Block struct { 11 // A unique identifier for the block. The system will attempt to allocate 12 // these IDs densely, but no guarantees. 13 ID ID 14 15 // Line number for block's control operation 16 Line int32 17 18 // The kind of block this is. 19 Kind BlockKind 20 21 // Likely direction for branches. 22 // If BranchLikely, Succs[0] is the most likely branch taken. 23 // If BranchUnlikely, Succs[1] is the most likely branch taken. 24 // Ignored if len(Succs) < 2. 25 // Fatal if not BranchUnknown and len(Succs) > 2. 26 Likely BranchPrediction 27 28 // After flagalloc, records whether flags are live at the end of the block. 29 FlagsLiveAtEnd bool 30 31 // Subsequent blocks, if any. The number and order depend on the block kind. 32 Succs []Edge 33 34 // Inverse of successors. 35 // The order is significant to Phi nodes in the block. 36 // TODO: predecessors is a pain to maintain. Can we somehow order phi 37 // arguments by block id and have this field computed explicitly when needed? 38 Preds []Edge 39 40 // A value that determines how the block is exited. Its value depends on the kind 41 // of the block. For instance, a BlockIf has a boolean control value and BlockExit 42 // has a memory control value. 43 Control *Value 44 45 // Auxiliary info for the block. Its value depends on the Kind. 46 Aux interface{} 47 48 // The unordered set of Values that define the operation of this block. 49 // The list must include the control value, if any. (TODO: need this last condition?) 50 // After the scheduling pass, this list is ordered. 51 Values []*Value 52 53 // The containing function 54 Func *Func 55 56 // Storage for Succs, Preds, and Values 57 succstorage [2]Edge 58 predstorage [4]Edge 59 valstorage [9]*Value 60 } 61 62 // Edge represents a CFG edge. 63 // Example edges for b branching to either c or d. 64 // (c and d have other predecessors.) 65 // b.Succs = [{c,3}, {d,1}] 66 // c.Preds = [?, ?, ?, {b,0}] 67 // d.Preds = [?, {b,1}, ?] 68 // These indexes allow us to edit the CFG in constant time. 69 // In addition, it informs phi ops in degenerate cases like: 70 // b: 71 // if k then c else c 72 // c: 73 // v = Phi(x, y) 74 // Then the indexes tell you whether x is chosen from 75 // the if or else branch from b. 76 // b.Succs = [{c,0},{c,1}] 77 // c.Preds = [{b,0},{b,1}] 78 // means x is chosen if k is true. 79 type Edge struct { 80 // block edge goes to (in a Succs list) or from (in a Preds list) 81 b *Block 82 // index of reverse edge. Invariant: 83 // e := x.Succs[idx] 84 // e.b.Preds[e.i] = Edge{x,idx} 85 // and similarly for predecessors. 86 i int 87 } 88 89 func (e Edge) Block() *Block { 90 return e.b 91 } 92 93 // kind control successors 94 // ------------------------------------------ 95 // Exit return mem [] 96 // Plain nil [next] 97 // If a boolean Value [then, else] 98 // Call mem [nopanic, panic] (control opcode should be OpCall or OpStaticCall) 99 type BlockKind int8 100 101 // short form print 102 func (b *Block) String() string { 103 return fmt.Sprintf("b%d", b.ID) 104 } 105 106 // long form print 107 func (b *Block) LongString() string { 108 s := b.Kind.String() 109 if b.Aux != nil { 110 s += fmt.Sprintf(" %s", b.Aux) 111 } 112 if b.Control != nil { 113 s += fmt.Sprintf(" %s", b.Control) 114 } 115 if len(b.Succs) > 0 { 116 s += " ->" 117 for _, c := range b.Succs { 118 s += " " + c.b.String() 119 } 120 } 121 switch b.Likely { 122 case BranchUnlikely: 123 s += " (unlikely)" 124 case BranchLikely: 125 s += " (likely)" 126 } 127 return s 128 } 129 130 func (b *Block) SetControl(v *Value) { 131 if w := b.Control; w != nil { 132 w.Uses-- 133 } 134 b.Control = v 135 if v != nil { 136 v.Uses++ 137 } 138 } 139 140 // AddEdgeTo adds an edge from block b to block c. Used during building of the 141 // SSA graph; do not use on an already-completed SSA graph. 142 func (b *Block) AddEdgeTo(c *Block) { 143 i := len(b.Succs) 144 j := len(c.Preds) 145 b.Succs = append(b.Succs, Edge{c, j}) 146 c.Preds = append(c.Preds, Edge{b, i}) 147 } 148 149 // removePred removes the ith input edge from b. 150 // It is the responsibility of the caller to remove 151 // the corresponding successor edge. 152 func (b *Block) removePred(i int) { 153 n := len(b.Preds) - 1 154 if i != n { 155 e := b.Preds[n] 156 b.Preds[i] = e 157 // Update the other end of the edge we moved. 158 e.b.Succs[e.i].i = i 159 } 160 b.Preds[n] = Edge{} 161 b.Preds = b.Preds[:n] 162 } 163 164 // removeSucc removes the ith output edge from b. 165 // It is the responsibility of the caller to remove 166 // the corresponding predecessor edge. 167 func (b *Block) removeSucc(i int) { 168 n := len(b.Succs) - 1 169 if i != n { 170 e := b.Succs[n] 171 b.Succs[i] = e 172 // Update the other end of the edge we moved. 173 e.b.Preds[e.i].i = i 174 } 175 b.Succs[n] = Edge{} 176 b.Succs = b.Succs[:n] 177 } 178 179 func (b *Block) swapSuccessors() { 180 if len(b.Succs) != 2 { 181 b.Fatalf("swapSuccessors with len(Succs)=%d", len(b.Succs)) 182 } 183 e0 := b.Succs[0] 184 e1 := b.Succs[1] 185 b.Succs[0] = e1 186 b.Succs[1] = e0 187 e0.b.Preds[e0.i].i = 1 188 e1.b.Preds[e1.i].i = 0 189 b.Likely *= -1 190 } 191 192 func (b *Block) Logf(msg string, args ...interface{}) { b.Func.Logf(msg, args...) } 193 func (b *Block) Log() bool { return b.Func.Log() } 194 func (b *Block) Fatalf(msg string, args ...interface{}) { b.Func.Fatalf(msg, args...) } 195 func (b *Block) Unimplementedf(msg string, args ...interface{}) { b.Func.Unimplementedf(msg, args...) } 196 197 type BranchPrediction int8 198 199 const ( 200 BranchUnlikely = BranchPrediction(-1) 201 BranchUnknown = BranchPrediction(0) 202 BranchLikely = BranchPrediction(+1) 203 )