Skip to content

Commit 71ea8f1

Browse files
committed
go/ssa: lift structs, arrays and typeparams
Lift locals with underlying types of struct, array and typeparam. Changes to vta tests are due to the tests being sensitive to register names. Change-Id: I558c0e6897b62f93ae1e700307e6e1e4dea008d0 Reviewed-on: https://go-review.googlesource.com/c/tools/+/451996 Run-TryBot: Tim King <[email protected]> Commit-Queue: Tim King <[email protected]> gopls-CI: kokoro <[email protected]> Reviewed-by: Alan Donovan <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Zvonimir Pavlinovic <[email protected]>
1 parent d59a28f commit 71ea8f1

21 files changed

+188
-311
lines changed

go/callgraph/vta/graph_test.go

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -152,21 +152,21 @@ func vtaGraphStr(g vtaGraph) []string {
152152
return vgs
153153
}
154154

155-
// subGraph checks if a graph `g1` is a subgraph of graph `g2`.
156-
// Assumes that each element in `g1` and `g2` is an edge set
157-
// for a particular node in a fixed yet arbitrary format.
158-
func subGraph(g1, g2 []string) bool {
159-
m := make(map[string]bool)
160-
for _, s := range g2 {
161-
m[s] = true
155+
// setdiff returns the set difference of `X-Y` or {s | s ∈ X, s ∉ Y }.
156+
func setdiff(X, Y []string) []string {
157+
y := make(map[string]bool)
158+
var delta []string
159+
for _, s := range Y {
160+
y[s] = true
162161
}
163162

164-
for _, s := range g1 {
165-
if _, ok := m[s]; !ok {
166-
return false
163+
for _, s := range X {
164+
if _, ok := y[s]; !ok {
165+
delta = append(delta, s)
167166
}
168167
}
169-
return true
168+
sort.Strings(delta)
169+
return delta
170170
}
171171

172172
func TestVTAGraphConstruction(t *testing.T) {
@@ -201,8 +201,9 @@ func TestVTAGraphConstruction(t *testing.T) {
201201
}
202202

203203
g, _ := typePropGraph(ssautil.AllFunctions(prog), cha.CallGraph(prog))
204-
if gs := vtaGraphStr(g); !subGraph(want, gs) {
205-
t.Errorf("`%s`: want superset of %v;\n got %v", file, want, gs)
204+
got := vtaGraphStr(g)
205+
if diff := setdiff(want, got); len(diff) > 0 {
206+
t.Errorf("`%s`: want superset of %v;\n got %v\ndiff: %v", file, want, got, diff)
206207
}
207208
})
208209
}

go/callgraph/vta/testdata/src/callgraph_collections.go

Lines changed: 1 addition & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -37,31 +37,5 @@ func Baz(a A, b B) {
3737
x[len(x)-1].Foo()
3838
}
3939

40-
// Relevant SSA:
41-
// func Baz(a A, b B):
42-
// ...
43-
// t4 = Do(t2, t3)
44-
// t5 = range t4
45-
// jump 1
46-
// 1:
47-
// t6 = phi [0: nil:[]I, 2: t16] #x
48-
// t7 = next t5
49-
// t8 = extract t7 #0
50-
// if t8 goto 2 else 3
51-
// 2:
52-
// t9 = extract t7 #1
53-
// t10 = extract t7 #2
54-
// t11 = invoke t9.Foo()
55-
// t12 = invoke t10.Foo()
56-
// ...
57-
// jump 1
58-
// 3:
59-
// t17 = len(t6)
60-
// t18 = t17 - 1:int
61-
// t19 = &t6[t18]
62-
// t20 = *t19
63-
// t21 = invoke t20.Foo()
64-
// return
65-
6640
// WANT:
67-
// Baz: Do(t2, t3) -> Do; invoke t10.Foo() -> B.Foo; invoke t20.Foo() -> A.Foo, B.Foo; invoke t9.Foo() -> A.Foo, B.Foo
41+
// Baz: Do(a, b) -> Do; invoke t16.Foo() -> A.Foo, B.Foo; invoke t5.Foo() -> A.Foo, B.Foo; invoke t6.Foo() -> B.Foo

go/callgraph/vta/testdata/src/callgraph_fields.go

Lines changed: 1 addition & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -31,61 +31,6 @@ func Baz(b B) {
3131
a.Do()
3232
}
3333

34-
// Relevant SSA:
35-
// func Baz(b B):
36-
// t0 = local B (b)
37-
// *t0 = b
38-
// t1 = *t0
39-
// t2 = NewA(t1)
40-
// t3 = (*A).Do(t2)
41-
// return
42-
//
43-
// func (a *A) Do():
44-
// t0 = &a.I [#0]
45-
// t1 = *t0
46-
// t2 = invoke t1.Foo()
47-
// return
48-
//
49-
// Name: (testdata.A).Foo
50-
// Synthetic: wrapper for func (testdata.I).Foo()
51-
// Location: testdata/callgraph_fields.go:10:2
52-
// func (arg0 testdata.A) Foo():
53-
// t0 = local testdata.A ()
54-
// *t0 = arg0
55-
// t1 = &t0.I [#0]
56-
// t2 = *t1
57-
// t3 = invoke t2.Foo()
58-
// return
59-
//
60-
// Name: (*testdata.A).Foo
61-
// Synthetic: wrapper for func (testdata.I).Foo()
62-
// Location: testdata/callgraph_fields.go:10:2
63-
// func (arg0 *testdata.A) Foo():
64-
// t0 = &arg0.I [#0]
65-
// t1 = *t0
66-
// t2 = invoke t1.Foo()
67-
// return
68-
//
69-
// func (b B) Foo():
70-
// t0 = local B (b)
71-
// *t0 = b
72-
// return
73-
//
74-
// func (b *testdata.B) Foo():
75-
// t0 = ssa:wrapnilchk(b, "testdata.B":string, "Foo":string)
76-
// t1 = *t0
77-
// t2 = (testdata.B).Foo(t1)
78-
// return
79-
//
80-
// func NewA(b B) *A:
81-
// t0 = new B (b)
82-
// *t0 = b
83-
// t1 = new A (complit)
84-
// t2 = &t1.I [#0]
85-
// t3 = make I <- *B (t0)
86-
// *t2 = t3
87-
// return t1
88-
8934
// WANT:
90-
// Baz: (*A).Do(t2) -> A.Do; NewA(t1) -> NewA
35+
// Baz: (*A).Do(t0) -> A.Do; NewA(b) -> NewA
9136
// A.Do: invoke t1.Foo() -> B.Foo

go/callgraph/vta/testdata/src/callgraph_generics.go

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -39,33 +39,24 @@ func Foo(a A, b B) {
3939

4040
// Relevant SSA:
4141
//func Foo(a A, b B):
42-
// t0 = local A (a)
43-
// *t0 = a
44-
// t1 = local B (b)
45-
// *t1 = b
46-
// t2 = new bool (x)
47-
// *t2 = true:bool
48-
// t3 = instantiated[bool](t2)
49-
// t4 = new int (y)
50-
// *t4 = 1:int
51-
// t5 = instantiated[int](t4)
52-
// t6 = *t0
53-
// t7 = interfaceInstantiated[testdata.A](t6)
54-
// t8 = *t1
55-
// t9 = interfaceInstantiated[testdata.B](t8)
42+
// t0 = new bool (x)
43+
// *t0 = true:bool
44+
// t1 = instantiated[bool](t2)
45+
// t1 = new int (y)
46+
// *t2 = 1:int
47+
// t3 = instantiated[[int]](t4)
48+
// t4 = interfaceInstantiated[testdata.A](a)
49+
// t5 = interfaceInstantiated[testdata.B](b)
5650
// return
5751
//
58-
//func interfaceInstantiated[testdata.B](x B):
59-
// t0 = local B (x)
60-
// *t0 = x
61-
// t1 = *t0
62-
// t2 = (B).Bar(t1)
52+
//func interfaceInstantiated[[testdata.B]](x B):
53+
// t0 = (B).Bar(b)
6354
// return
6455
//
6556
//func interfaceInstantiated[X I](x X):
6657
// (external)
6758

6859
// WANT:
69-
// Foo: instantiated[bool](t2) -> instantiated[bool]; instantiated[int](t4) -> instantiated[int]; interfaceInstantiated[testdata.A](t6) -> interfaceInstantiated[testdata.A]; interfaceInstantiated[testdata.B](t8) -> interfaceInstantiated[testdata.B]
70-
// interfaceInstantiated[testdata.B]: (B).Bar(t1) -> B.Bar
71-
// interfaceInstantiated[testdata.A]: (A).Bar(t1) -> A.Bar
60+
// Foo: instantiated[bool](t0) -> instantiated[bool]; instantiated[int](t2) -> instantiated[int]; interfaceInstantiated[testdata.A](a) -> interfaceInstantiated[testdata.A]; interfaceInstantiated[testdata.B](b) -> interfaceInstantiated[testdata.B]
61+
// interfaceInstantiated[testdata.B]: (B).Bar(x) -> B.Bar
62+
// interfaceInstantiated[testdata.A]: (A).Bar(x) -> A.Bar

go/callgraph/vta/testdata/src/callgraph_interfaces.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,11 @@ func Baz(b bool) {
4949

5050
// func Do(b bool) I:
5151
// ...
52-
// t3 = local C (c)
53-
// t4 = *t3
54-
// t5 = (C).Foo(t4)
55-
// t6 = NewB()
56-
// t7 = make I <- B (t6)
57-
// return t7
52+
// t1 = (C).Foo(struct{}{}:C)
53+
// t2 = NewB()
54+
// t3 = make I <- B (t2)
55+
// return t3
5856

5957
// WANT:
6058
// Baz: Do(b) -> Do; invoke t0.Foo() -> A.Foo, B.Foo
61-
// Do: (C).Foo(t4) -> C.Foo; NewB() -> NewB
59+
// Do: (C).Foo(struct{}{}:C) -> C.Foo; NewB() -> NewB

go/callgraph/vta/testdata/src/callgraph_pointers.go

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -35,37 +35,9 @@ func Baz(a A, b B, c bool) {
3535
(*x).Foo()
3636
}
3737

38-
// Relevant SSA:
39-
// func Baz(a A, b B, c bool):
40-
// t0 = local A (a)
41-
// ...
42-
// t5 = Do(t2, t4, c)
43-
// t6 = *t5
44-
// t7 = invoke t6.Foo()
45-
// return
46-
47-
// func Do(a A, i I, c bool) *I:
48-
// t0 = local A (a)
49-
// *t0 = a
50-
// ...
51-
// if c goto 1 else 3
52-
// 1:
53-
// t2 = &t0.f [#0]
54-
// ...
55-
// jump 2
56-
// 2:
57-
// t6 = &t0.f [#0]
58-
// ...
59-
// t9 = invoke t8.Foo()
60-
// return t1
61-
// 3:
62-
// t10 = &t0.f [#0] alias between A.f and t10
63-
// *t10 = t1 alias between t10 and t1
64-
// jump 2
65-
6638
// The command a.f = &i introduces aliasing that results in
6739
// A and B reaching both *A.f and return value of Do(a, b, c).
6840

6941
// WANT:
70-
// Baz: Do(t2, t4, c) -> Do; invoke t6.Foo() -> A.Foo, B.Foo
42+
// Baz: Do(a, t0, c) -> Do; invoke t2.Foo() -> A.Foo, B.Foo
7143
// Do: invoke t8.Foo() -> A.Foo, B.Foo

go/callgraph/vta/testdata/src/callgraph_static.go

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,9 @@ func Baz(a A) {
2020

2121
// Relevant SSA:
2222
// func Baz(a A):
23-
// ...
24-
// t2 = (A).foo(t1)
25-
// t3 = Bar()
26-
// ...
27-
// t6 = Baz(t5)
23+
// t0 = (A).foo(a)
24+
// t1 = Bar()
25+
// t2 = Baz(struct{}{}:A)
2826

2927
// WANT:
30-
// Baz: (A).foo(t1) -> A.foo; Bar() -> Bar; Baz(t5) -> Baz
28+
// Baz: (A).foo(a) -> A.foo; Bar() -> Bar; Baz(struct{}{}:A) -> Baz

go/callgraph/vta/testdata/src/dynamic_calls.go

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,23 +27,22 @@ func Baz(x B, h func() I, i I) I {
2727
return h()
2828
}
2929

30+
var g *B = &B{} // ensure *B.foo is created.
31+
3032
// Relevant SSA:
3133
// func Baz(x B, h func() I, i I) I:
32-
// t0 = local B (x)
33-
// *t0 = x
34-
// t1 = *t0
35-
// t2 = make I <- B (t1)
36-
// t3 = invoke i.foo(t2)
37-
// t4 = h()
38-
// return t4
39-
40-
// Local(t2) has seemingly duplicates of successors. This
34+
// t0 = make I <- B (x)
35+
// t1 = invoke i.foo(t0)
36+
// t2 = h()
37+
// return t2
38+
39+
// Local(t0) has seemingly duplicates of successors. This
4140
// happens in stringification of type propagation graph.
4241
// Due to CHA, we analyze A.foo and *A.foo as well as B.foo
4342
// and *B.foo, which have similar bodies and hence similar
4443
// type flow that gets merged together during stringification.
4544

4645
// WANT:
47-
// Local(t2) -> Local(ai), Local(ai), Local(bi), Local(bi)
48-
// Constant(testdata.I) -> Local(t4)
49-
// Local(t1) -> Local(t2)
46+
// Local(t0) -> Local(ai), Local(ai), Local(bi), Local(bi)
47+
// Constant(testdata.I) -> Local(t2)
48+
// Local(x) -> Local(t0)

go/callgraph/vta/testdata/src/maps.go

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,23 +30,16 @@ func Baz(m map[I]I, b1, b2 B, n map[string]*J) *J {
3030

3131
// Relevant SSA:
3232
// func Baz(m map[I]I, b1 B, b2 B, n map[string]*J) *J:
33-
// t0 = local B (b1)
34-
// *t0 = b1
35-
// t1 = local B (b2)
36-
// *t1 = b2
37-
// t2 = *t0
38-
// t3 = make I <- B (t2)
39-
// t4 = *t1
40-
// t5 = make I <- B (t4)
41-
// m[t3] = t5
42-
// t6 = *t0
43-
// t7 = (B).Foo(t6)
44-
// t8 = n[t7]
45-
// return t8
33+
// t0 = make I <- B (b1)
34+
// t1 = make I <- B (b2)
35+
// m[t0] = t1
36+
// t2 = (B).Foo(b1)
37+
// t3 = n[t2]
38+
// return t3
4639

4740
// WANT:
48-
// Local(t4) -> Local(t5)
49-
// Local(t5) -> MapValue(testdata.I)
50-
// Local(t3) -> MapKey(testdata.I)
51-
// Local(t8) -> MapValue(*testdata.J)
52-
// MapValue(*testdata.J) -> Local(t8)
41+
// Local(b2) -> Local(t1)
42+
// Local(t1) -> MapValue(testdata.I)
43+
// Local(t0) -> MapKey(testdata.I)
44+
// Local(t3) -> MapValue(*testdata.J)
45+
// MapValue(*testdata.J) -> Local(t3)

go/callgraph/vta/testdata/src/panic.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,14 @@ func Baz(a A) {
5050
// return
5151
//
5252
// func Baz(i I):
53-
// t0 = local A (a)
54-
// *t0 = a
5553
// defer recover1()
56-
// defer recover()
57-
// t1 = *t0
58-
// t2 = make interface{} <- A (t1)
54+
// t0 = make interface{} <- A (a)
5955
// panic t2
6056

61-
// t2 argument to panic in Baz gets ultimately connected to recover
57+
// t0 argument to panic in Baz gets ultimately connected to recover
6258
// registers t1 in recover1() and t0 in recover2().
6359

6460
// WANT:
6561
// Panic -> Recover
66-
// Local(t2) -> Panic
62+
// Local(t0) -> Panic
6763
// Recover -> Local(t0), Local(t1)

0 commit comments

Comments
 (0)