Skip to content

Commit

Permalink
go/ir: consider fake exits when building (post-)dominator frontier
Browse files Browse the repository at this point in the history
We correctly considered fake exits when building the (post-)dominator
tree, but forgot to do so when calculating the frontier. This would
lead to missing phi and sigma nodes, ultimately resulting in returning
wrong values.

Closes gh-949

(cherry picked from commit 390eb5b)
  • Loading branch information
dominikh committed May 1, 2021
1 parent 5a1275a commit 0a83c9b
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 5 deletions.
2 changes: 1 addition & 1 deletion go/ir/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ func h(error)
}
}
}
if expected := 1; phis != expected {
if expected := 3; phis != expected {
g.WriteTo(os.Stderr)
t.Errorf("expected %d Phi nodes (for the range index), got %d", expected, phis)
}
Expand Down
8 changes: 8 additions & 0 deletions go/ir/dom.go
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,10 @@ func printDomTreeDot(buf io.Writer, f *Function) {
for _, pred := range b.Preds {
fmt.Fprintf(buf, "\tn%d -> n%d [style=\"dotted\",weight=0];\n", pred.dom.pre, v.pre)
}

if f.fakeExits.Has(b) {
fmt.Fprintf(buf, "\tn%d -> n%d [style=\"dotted\",weight=0,color=red];\n", b.dom.pre, f.Exit.dom.pre)
}
}
fmt.Fprintln(buf, "}")
}
Expand Down Expand Up @@ -456,6 +460,10 @@ func printPostDomTreeDot(buf io.Writer, f *Function) {
for _, pred := range b.Preds {
fmt.Fprintf(buf, "\tn%d -> n%d [style=\"dotted\",weight=0];\n", pred.pdom.pre, v.pre)
}

if f.fakeExits.Has(b) {
fmt.Fprintf(buf, "\tn%d -> n%d [style=\"dotted\",weight=0,color=red];\n", b.dom.pre, f.Exit.dom.pre)
}
}
fmt.Fprintln(buf, "}")
}
20 changes: 16 additions & 4 deletions go/ir/lift.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,16 @@ func (df domFrontier) add(u, v *BasicBlock) {
// the DF -> IDF step.
func (df domFrontier) build(fn *Function) {
for _, b := range fn.Blocks {
if len(b.Preds) >= 2 {
for _, p := range b.Preds {
preds := b.Preds[0:len(b.Preds):len(b.Preds)]
if b == fn.Exit {
for i, v := range fn.fakeExits.values {
if v {
preds = append(preds, fn.Blocks[i])
}
}
}
if len(preds) >= 2 {
for _, p := range preds {
runner := p
for runner != b.dom.idom {
df.add(runner, b)
Expand All @@ -105,8 +113,12 @@ func (rdf postDomFrontier) add(u, v *BasicBlock) {

func (rdf postDomFrontier) build(fn *Function) {
for _, b := range fn.Blocks {
if len(b.Succs) >= 2 {
for _, s := range b.Succs {
succs := b.Succs[0:len(b.Succs):len(b.Succs)]
if fn.fakeExits.Has(b) {
succs = append(succs, fn.Exit)
}
if len(succs) >= 2 {
for _, s := range succs {
runner := s
for runner != b.pdom.idom {
rdf.add(runner, b)
Expand Down
10 changes: 10 additions & 0 deletions staticcheck/testdata/src/CheckPureFunctions/CheckPureFunctions.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package pkg

import (
"context"
"fmt"
"net/http"
"strings"
)
Expand Down Expand Up @@ -36,3 +37,12 @@ func fn3() {
stubPointer()
stubInt()
}

func fn4() error {
// Test for https://github.com/dominikh/go-tools/issues/949
if true {
return fmt.Errorf("")
}
for {
}
}

0 comments on commit 0a83c9b

Please sign in to comment.