Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(571)

Delta Between Two Patch Sets: src/pkg/exp/ssa/sanity.go

Issue 7199052: code review 7199052: exp/ssa: (#2 of 5): core utilities (Closed)
Left Patch Set: diff -r 987e3a448a7b https://code.google.com/p/go/ Created 12 years, 2 months ago
Right Patch Set: diff -r ca5e5de48173 https://code.google.com/p/go/ Created 12 years, 2 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/exp/ssa/print.go ('k') | src/pkg/exp/ssa/ssa.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 package ssa 1 package ssa
2 2
3 // An optional pass for sanity checking invariants of the SSA representation. 3 // An optional pass for sanity checking invariants of the SSA representation.
4 // Currently it checks CFG invariants but little at the instruction level. 4 // Currently it checks CFG invariants but little at the instruction level.
5 5
6 import ( 6 import (
7 "bytes" 7 "bytes"
8 "fmt" 8 "fmt"
9 "io" 9 "io"
10 "os" 10 "os"
11 "reflect"
12 ) 11 )
13 12
14 type sanity struct { 13 type sanity struct {
15 reporter io.Writer 14 reporter io.Writer
16 fn *Function 15 fn *Function
17 block *BasicBlock 16 block *BasicBlock
18 insane bool 17 insane bool
19 } 18 }
20 19
21 // SanityCheck performs integrity checking of the SSA representation 20 // SanityCheck performs integrity checking of the SSA representation
22 // of the function fn and returns true if it was valid. Diagnostics 21 // of the function fn and returns true if it was valid. Diagnostics
23 // are written to reporter if non-nil, os.Stderr otherwise . Some 22 // are written to reporter if non-nil, os.Stderr otherwise. Some
iant 2013/01/25 05:33:02 s/otherwise ./otherwise./
adonovan 2013/01/25 15:37:51 Done.
24 // diagnostics are only warnings and do not imply a negative result. 23 // diagnostics are only warnings and do not imply a negative result.
25 // 24 //
26 // Sanity checking is intended to facilitate the debugging of code 25 // Sanity checking is intended to facilitate the debugging of code
27 // transformation passes. 26 // transformation passes.
28 // 27 //
29 func SanityCheck(fn *Function, reporter io.Writer) bool { 28 func SanityCheck(fn *Function, reporter io.Writer) bool {
30 if reporter == nil { 29 if reporter == nil {
31 reporter = os.Stderr 30 reporter = os.Stderr
32 } 31 }
33 return (&sanity{reporter: reporter}).checkFunction(fn) 32 return (&sanity{reporter: reporter}).checkFunction(fn)
(...skipping 16 matching lines...) Expand all
50 for i, b := range blocks { 49 for i, b := range blocks {
51 if i > 0 { 50 if i > 0 {
52 io.WriteString(&buf, ", ") 51 io.WriteString(&buf, ", ")
53 } 52 }
54 io.WriteString(&buf, b.Name) 53 io.WriteString(&buf, b.Name)
55 } 54 }
56 return buf.String() 55 return buf.String()
57 } 56 }
58 57
59 func (s *sanity) diagnostic(prefix, format string, args ...interface{}) { 58 func (s *sanity) diagnostic(prefix, format string, args ...interface{}) {
60 » var buf bytes.Buffer 59 » fmt.Fprintf(s.reporter, "%s: function %s", prefix, s.fn.FullName())
iant 2013/01/25 05:33:02 Why do you use the bytes.Buffer here? Why not alw
adonovan 2013/01/25 15:37:51 It's a legacy of when reporter was a callback. Ch
iant 2013/01/25 16:40:49 A bit of both, I suppose. (In C stderr is unbuffe
61 » fmt.Fprintf(&buf, "%s: function %s", prefix, s.fn.FullName())
62 if s.block != nil { 60 if s.block != nil {
63 » » fmt.Fprintf(&buf, ", block %s", s.block.Name) 61 » » fmt.Fprintf(s.reporter, ", block %s", s.block.Name)
64 » } 62 » }
65 » io.WriteString(&buf, ": ") 63 » io.WriteString(s.reporter, ": ")
66 » fmt.Fprintf(&buf, format, args...) 64 » fmt.Fprintf(s.reporter, format, args...)
67
68 » io.WriteString(s.reporter, buf.String())
69 io.WriteString(s.reporter, "\n") 65 io.WriteString(s.reporter, "\n")
70 } 66 }
71 67
72 func (s *sanity) errorf(format string, args ...interface{}) { 68 func (s *sanity) errorf(format string, args ...interface{}) {
73 s.insane = true 69 s.insane = true
74 s.diagnostic("Error", format, args...) 70 s.diagnostic("Error", format, args...)
75 } 71 }
76 72
77 func (s *sanity) warnf(format string, args ...interface{}) { 73 func (s *sanity) warnf(format string, args ...interface{}) {
78 s.diagnostic("Warning", format, args...) 74 s.diagnostic("Warning", format, args...)
(...skipping 25 matching lines...) Expand all
104 s.errorf("control flow instruction not at end of block") 100 s.errorf("control flow instruction not at end of block")
105 case *Phi: 101 case *Phi:
106 if idx == 0 { 102 if idx == 0 {
107 // It suffices to apply this check to just the first phi node. 103 // It suffices to apply this check to just the first phi node.
108 if dup := findDuplicate(s.block.Preds); dup != nil { 104 if dup := findDuplicate(s.block.Preds); dup != nil {
109 s.errorf("phi node in block with duplicate prede cessor %s", dup.Name) 105 s.errorf("phi node in block with duplicate prede cessor %s", dup.Name)
110 } 106 }
111 } else { 107 } else {
112 prev := s.block.Instrs[idx-1] 108 prev := s.block.Instrs[idx-1]
113 if _, ok := prev.(*Phi); !ok { 109 if _, ok := prev.(*Phi); !ok {
114 » » » » s.errorf("Phi instruction follows a non-Phi: %s" , reflect.TypeOf(prev)) 110 » » » » s.errorf("Phi instruction follows a non-Phi: %T" , prev)
115 } 111 }
116 } 112 }
117 if ne, np := len(instr.Edges), len(s.block.Preds); ne != np { 113 if ne, np := len(instr.Edges), len(s.block.Preds); ne != np {
118 s.errorf("phi node has %d edges but %d predecessors", ne , np) 114 s.errorf("phi node has %d edges but %d predecessors", ne , np)
119 } 115 }
120 116
121 case *Alloc: 117 case *Alloc:
122 case *Call: 118 case *Call:
123 case *BinOp: 119 case *BinOp:
124 case *UnOp: 120 case *UnOp:
(...skipping 15 matching lines...) Expand all
140 case *Send: 136 case *Send:
141 case *Store: 137 case *Store:
142 case *MapUpdate: 138 case *MapUpdate:
143 case *Next: 139 case *Next:
144 case *Lookup: 140 case *Lookup:
145 case *Conv: 141 case *Conv:
146 case *ChangeInterface: 142 case *ChangeInterface:
147 case *MakeInterface: 143 case *MakeInterface:
148 // TODO(adonovan): implement checks. 144 // TODO(adonovan): implement checks.
149 default: 145 default:
150 » » panic("Unknown instruction type: " + reflect.TypeOf(instr).Strin g()) 146 » » panic(fmt.Sprintf("Unknown instruction type: %T", instr))
151 } 147 }
152 } 148 }
153 149
154 func (s *sanity) checkFinalInstr(idx int, instr Instruction) { 150 func (s *sanity) checkFinalInstr(idx int, instr Instruction) {
155 switch instr.(type) { 151 switch instr.(type) {
156 case *If: 152 case *If:
157 if nsuccs := len(s.block.Succs); nsuccs != 2 { 153 if nsuccs := len(s.block.Succs); nsuccs != 2 {
158 s.errorf("If-terminated block has %d successors; expecte d 2", nsuccs) 154 s.errorf("If-terminated block has %d successors; expecte d 2", nsuccs)
159 return 155 return
160 } 156 }
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 if b == nil { 254 if b == nil {
259 s.warnf("nil *BasicBlock at f.Blocks[%d]", i) 255 s.warnf("nil *BasicBlock at f.Blocks[%d]", i)
260 continue 256 continue
261 } 257 }
262 s.checkBlock(b, i == 0) 258 s.checkBlock(b, i == 0)
263 } 259 }
264 s.block = nil 260 s.block = nil
265 s.fn = nil 261 s.fn = nil
266 return !s.insane 262 return !s.insane
267 } 263 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b