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 _, e := range b.Preds { 49 pred := e.b 50 fmt.Fprintf(p.w, " b%d", pred.ID) 51 } 52 } 53 if !reachable { 54 fmt.Fprint(p.w, " DEAD") 55 } 56 io.WriteString(p.w, "\n") 57 } 58 59 func (p stringFuncPrinter) endBlock(b *Block) { 60 fmt.Fprintln(p.w, " "+b.LongString()) 61 } 62 63 func (p stringFuncPrinter) value(v *Value, live bool) { 64 fmt.Fprint(p.w, " ") 65 //fmt.Fprint(p.w, v.Block.Func.Config.fe.Line(v.Line)) 66 //fmt.Fprint(p.w, ": ") 67 fmt.Fprint(p.w, v.LongString()) 68 if !live { 69 fmt.Fprint(p.w, " DEAD") 70 } 71 fmt.Fprintln(p.w) 72 } 73 74 func (p stringFuncPrinter) startDepCycle() { 75 fmt.Fprintln(p.w, "dependency cycle!") 76 } 77 78 func (p stringFuncPrinter) endDepCycle() {} 79 80 func (p stringFuncPrinter) named(n LocalSlot, vals []*Value) { 81 fmt.Fprintf(p.w, "name %s: %v\n", n.Name(), vals) 82 } 83 84 func fprintFunc(p funcPrinter, f *Func) { 85 reachable, live := findlive(f) 86 p.header(f) 87 printed := make([]bool, f.NumValues()) 88 for _, b := range f.Blocks { 89 p.startBlock(b, reachable[b.ID]) 90 91 if f.scheduled { 92 // Order of Values has been decided - print in that order. 93 for _, v := range b.Values { 94 p.value(v, live[v.ID]) 95 printed[v.ID] = true 96 } 97 p.endBlock(b) 98 continue 99 } 100 101 // print phis first since all value cycles contain a phi 102 n := 0 103 for _, v := range b.Values { 104 if v.Op != OpPhi { 105 continue 106 } 107 p.value(v, live[v.ID]) 108 printed[v.ID] = true 109 n++ 110 } 111 112 // print rest of values in dependency order 113 for n < len(b.Values) { 114 m := n 115 outer: 116 for _, v := range b.Values { 117 if printed[v.ID] { 118 continue 119 } 120 for _, w := range v.Args { 121 // w == nil shouldn't happen, but if it does, 122 // don't panic; we'll get a better diagnosis later. 123 if w != nil && w.Block == b && !printed[w.ID] { 124 continue outer 125 } 126 } 127 p.value(v, live[v.ID]) 128 printed[v.ID] = true 129 n++ 130 } 131 if m == n { 132 p.startDepCycle() 133 for _, v := range b.Values { 134 if printed[v.ID] { 135 continue 136 } 137 p.value(v, live[v.ID]) 138 printed[v.ID] = true 139 n++ 140 } 141 p.endDepCycle() 142 } 143 } 144 145 p.endBlock(b) 146 } 147 for _, name := range f.Names { 148 p.named(name, f.NamedValues[name]) 149 } 150 } 151