github.com/euank/go@v0.0.0-20160829210321-495514729181/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 _, 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  }