github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/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 _, 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.fe.Pos(v.Pos)) 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, vals) 82 } 83 84 func fprintFunc(p funcPrinter, f *Func) { 85 reachable, live := findlive(f) 86 defer f.retDeadcodeLive(live) 87 p.header(f) 88 printed := make([]bool, f.NumValues()) 89 for _, b := range f.Blocks { 90 p.startBlock(b, reachable[b.ID]) 91 92 if f.scheduled { 93 // Order of Values has been decided - print in that order. 94 for _, v := range b.Values { 95 p.value(v, live[v.ID]) 96 printed[v.ID] = true 97 } 98 p.endBlock(b) 99 continue 100 } 101 102 // print phis first since all value cycles contain a phi 103 n := 0 104 for _, v := range b.Values { 105 if v.Op != OpPhi { 106 continue 107 } 108 p.value(v, live[v.ID]) 109 printed[v.ID] = true 110 n++ 111 } 112 113 // print rest of values in dependency order 114 for n < len(b.Values) { 115 m := n 116 outer: 117 for _, v := range b.Values { 118 if printed[v.ID] { 119 continue 120 } 121 for _, w := range v.Args { 122 // w == nil shouldn't happen, but if it does, 123 // don't panic; we'll get a better diagnosis later. 124 if w != nil && w.Block == b && !printed[w.ID] { 125 continue outer 126 } 127 } 128 p.value(v, live[v.ID]) 129 printed[v.ID] = true 130 n++ 131 } 132 if m == n { 133 p.startDepCycle() 134 for _, v := range b.Values { 135 if printed[v.ID] { 136 continue 137 } 138 p.value(v, live[v.ID]) 139 printed[v.ID] = true 140 n++ 141 } 142 p.endDepCycle() 143 } 144 } 145 146 p.endBlock(b) 147 } 148 for _, name := range f.Names { 149 p.named(name, f.NamedValues[name]) 150 } 151 }