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  }