Black Lives Matter. Support the Equal Justice Initiative.

Source file src/cmd/compile/internal/ssa/print.go

Documentation: cmd/compile/internal/ssa

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

View as plain text