github.com/miolini/go@v0.0.0-20160405192216-fca68c8cb408/src/cmd/compile/internal/ssa/print.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 ( 8 "bytes" 9 "fmt" 10 "io" 11 ) 12 13 func printFunc(f *Func) { 14 f.Logf("%s", f) 15 } 16 17 func (f *Func) String() string { 18 var buf bytes.Buffer 19 p := stringFuncPrinter{w: &buf} 20 fprintFunc(p, f) 21 return buf.String() 22 } 23 24 type funcPrinter interface { 25 header(f *Func) 26 startBlock(b *Block, reachable bool) 27 endBlock(b *Block) 28 value(v *Value, live bool) 29 startDepCycle() 30 endDepCycle() 31 named(n LocalSlot, vals []*Value) 32 } 33 34 type stringFuncPrinter struct { 35 w io.Writer 36 } 37 38 func (p stringFuncPrinter) header(f *Func) { 39 fmt.Fprint(p.w, f.Name) 40 fmt.Fprint(p.w, " ") 41 fmt.Fprintln(p.w, f.Type) 42 } 43 44 func (p stringFuncPrinter) startBlock(b *Block, reachable bool) { 45 fmt.Fprintf(p.w, " b%d:", b.ID) 46 if len(b.Preds) > 0 { 47 io.WriteString(p.w, " <-") 48 for _, pred := range b.Preds { 49 fmt.Fprintf(p.w, " b%d", pred.ID) 50 } 51 } 52 if !reachable { 53 fmt.Fprint(p.w, " DEAD") 54 } 55 io.WriteString(p.w, "\n") 56 } 57 58 func (p stringFuncPrinter) endBlock(b *Block) { 59 fmt.Fprintln(p.w, " "+b.LongString()) 60 } 61 62 func (p stringFuncPrinter) value(v *Value, live bool) { 63 fmt.Fprint(p.w, " ") 64 //fmt.Fprint(p.w, v.Block.Func.Config.fe.Line(v.Line)) 65 //fmt.Fprint(p.w, ": ") 66 fmt.Fprint(p.w, v.LongString()) 67 if !live { 68 fmt.Fprint(p.w, " DEAD") 69 } 70 fmt.Fprintln(p.w) 71 } 72 73 func (p stringFuncPrinter) startDepCycle() { 74 fmt.Fprintln(p.w, "dependency cycle!") 75 } 76 77 func (p stringFuncPrinter) endDepCycle() {} 78 79 func (p stringFuncPrinter) named(n LocalSlot, vals []*Value) { 80 fmt.Fprintf(p.w, "name %s: %v\n", n.Name(), vals) 81 } 82 83 func fprintFunc(p funcPrinter, f *Func) { 84 reachable, live := findlive(f) 85 p.header(f) 86 printed := make([]bool, f.NumValues()) 87 for _, b := range f.Blocks { 88 p.startBlock(b, reachable[b.ID]) 89 90 if f.scheduled { 91 // Order of Values has been decided - print in that order. 92 for _, v := range b.Values { 93 p.value(v, live[v.ID]) 94 printed[v.ID] = true 95 } 96 p.endBlock(b) 97 continue 98 } 99 100 // print phis first since all value cycles contain a phi 101 n := 0 102 for _, v := range b.Values { 103 if v.Op != OpPhi { 104 continue 105 } 106 p.value(v, live[v.ID]) 107 printed[v.ID] = true 108 n++ 109 } 110 111 // print rest of values in dependency order 112 for n < len(b.Values) { 113 m := n 114 outer: 115 for _, v := range b.Values { 116 if printed[v.ID] { 117 continue 118 } 119 for _, w := range v.Args { 120 // w == nil shouldn't happen, but if it does, 121 // don't panic; we'll get a better diagnosis later. 122 if w != nil && w.Block == b && !printed[w.ID] { 123 continue outer 124 } 125 } 126 p.value(v, live[v.ID]) 127 printed[v.ID] = true 128 n++ 129 } 130 if m == n { 131 p.startDepCycle() 132 for _, v := range b.Values { 133 if printed[v.ID] { 134 continue 135 } 136 p.value(v, live[v.ID]) 137 printed[v.ID] = true 138 n++ 139 } 140 p.endDepCycle() 141 } 142 } 143 144 p.endBlock(b) 145 } 146 for _, name := range f.Names { 147 p.named(name, f.NamedValues[name]) 148 } 149 }