github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/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 // The kind of block this is. 16 Kind BlockKind 17 18 // Subsequent blocks, if any. The number and order depend on the block kind. 19 // All successors must be distinct (to make phi values in successors unambiguous). 20 Succs []*Block 21 22 // Inverse of successors. 23 // The order is significant to Phi nodes in the block. 24 Preds []*Block 25 // TODO: predecessors is a pain to maintain. Can we somehow order phi 26 // arguments by block id and have this field computed explicitly when needed? 27 28 // A value that determines how the block is exited. Its value depends on the kind 29 // of the block. For instance, a BlockIf has a boolean control value and BlockExit 30 // has a memory control value. 31 Control *Value 32 33 // Auxiliary info for the block. Its value depends on the Kind. 34 Aux interface{} 35 36 // The unordered set of Values that define the operation of this block. 37 // The list must include the control value, if any. (TODO: need this last condition?) 38 // After the scheduling pass, this list is ordered. 39 Values []*Value 40 41 // The containing function 42 Func *Func 43 44 // Line number for block's control operation 45 Line int32 46 47 // Likely direction for branches. 48 // If BranchLikely, Succs[0] is the most likely branch taken. 49 // If BranchUnlikely, Succs[1] is the most likely branch taken. 50 // Ignored if len(Succs) < 2. 51 // Fatal if not BranchUnknown and len(Succs) > 2. 52 Likely BranchPrediction 53 54 // After flagalloc, records whether flags are live at the end of the block. 55 FlagsLiveAtEnd bool 56 57 // Storage for Succs, Preds, and Values 58 succstorage [2]*Block 59 predstorage [4]*Block 60 valstorage [8]*Value 61 } 62 63 // kind control successors 64 // ------------------------------------------ 65 // Exit return mem [] 66 // Plain nil [next] 67 // If a boolean Value [then, else] 68 // Call mem [nopanic, panic] (control opcode should be OpCall or OpStaticCall) 69 type BlockKind int32 70 71 // short form print 72 func (b *Block) String() string { 73 return fmt.Sprintf("b%d", b.ID) 74 } 75 76 // long form print 77 func (b *Block) LongString() string { 78 s := b.Kind.String() 79 if b.Aux != nil { 80 s += fmt.Sprintf(" %s", b.Aux) 81 } 82 if b.Control != nil { 83 s += fmt.Sprintf(" %s", b.Control) 84 } 85 if len(b.Succs) > 0 { 86 s += " ->" 87 for _, c := range b.Succs { 88 s += " " + c.String() 89 } 90 } 91 switch b.Likely { 92 case BranchUnlikely: 93 s += " (unlikely)" 94 case BranchLikely: 95 s += " (likely)" 96 } 97 return s 98 } 99 100 func (b *Block) SetControl(v *Value) { 101 if w := b.Control; w != nil { 102 w.Uses-- 103 } 104 b.Control = v 105 if v != nil { 106 v.Uses++ 107 } 108 } 109 110 // AddEdgeTo adds an edge from block b to block c. Used during building of the 111 // SSA graph; do not use on an already-completed SSA graph. 112 func (b *Block) AddEdgeTo(c *Block) { 113 b.Succs = append(b.Succs, c) 114 c.Preds = append(c.Preds, b) 115 } 116 117 func (b *Block) Logf(msg string, args ...interface{}) { b.Func.Logf(msg, args...) } 118 func (b *Block) Log() bool { return b.Func.Log() } 119 func (b *Block) Fatalf(msg string, args ...interface{}) { b.Func.Fatalf(msg, args...) } 120 func (b *Block) Unimplementedf(msg string, args ...interface{}) { b.Func.Unimplementedf(msg, args...) } 121 122 type BranchPrediction int8 123 124 const ( 125 BranchUnlikely = BranchPrediction(-1) 126 BranchUnknown = BranchPrediction(0) 127 BranchLikely = BranchPrediction(+1) 128 )