1
2
3
4
5 package test
6
7 import (
8 "cmd/compile/internal/ir"
9 "cmd/compile/internal/liveness"
10 "cmd/compile/internal/typecheck"
11 "cmd/compile/internal/types"
12 "cmd/internal/src"
13 "internal/testenv"
14 "path/filepath"
15 "sort"
16 "strings"
17 "testing"
18 )
19
20 func mkiv(name string) *ir.Name {
21 i32 := types.Types[types.TINT32]
22 s := typecheck.Lookup(name)
23 v := ir.NewNameAt(src.NoXPos, s, i32)
24 return v
25 }
26
27 func TestMergeLocalState(t *testing.T) {
28 v1 := mkiv("v1")
29 v2 := mkiv("v2")
30 v3 := mkiv("v3")
31
32 testcases := []struct {
33 vars []*ir.Name
34 partition map[*ir.Name][]int
35 experr bool
36 }{
37 {
38 vars: []*ir.Name{v1, v2, v3},
39 partition: map[*ir.Name][]int{
40 v1: []int{0, 1, 2},
41 v2: []int{0, 1, 2},
42 v3: []int{0, 1, 2},
43 },
44 experr: false,
45 },
46 {
47
48 vars: []*ir.Name{v1, v2, v3},
49 partition: map[*ir.Name][]int{
50 v1: []int{-1, 0},
51 v2: []int{0, 1, 2},
52 v3: []int{0, 1, 2},
53 },
54 experr: true,
55 },
56 {
57
58 vars: []*ir.Name{v1, v2, v2},
59 partition: map[*ir.Name][]int{
60 v1: []int{0, 1, 2},
61 v2: []int{0, 1, 2},
62 v3: []int{0, 1, 2},
63 },
64 experr: true,
65 },
66 {
67
68 vars: []*ir.Name{v1, v2, v3},
69 partition: map[*ir.Name][]int{
70 v1: []int{0},
71 v2: []int{0, 1, 2},
72 v3: []int{0, 1, 2},
73 },
74 experr: true,
75 },
76 {
77
78 vars: []*ir.Name{v1, v2, v3},
79 partition: map[*ir.Name][]int{
80 v1: []int{0, 1},
81 v2: []int{0, 1},
82 v3: []int{0, 1},
83 },
84 experr: true,
85 },
86 {
87
88 vars: []*ir.Name{v1, v2, v3},
89 partition: map[*ir.Name][]int{
90 v1: []int{0, 1, 2},
91 v2: []int{1, 0, 2},
92 v3: []int{0, 1, 2},
93 },
94 experr: true,
95 },
96 }
97
98 for k, testcase := range testcases {
99 mls, err := liveness.MakeMergeLocalsState(testcase.partition, testcase.vars)
100 t.Logf("tc %d err is %v\n", k, err)
101 if testcase.experr && err == nil {
102 t.Fatalf("tc:%d missing error mls %v", k, mls)
103 } else if !testcase.experr && err != nil {
104 t.Fatalf("tc:%d unexpected error mls %v", k, err)
105 }
106 if mls != nil {
107 t.Logf("tc %d: mls: %v\n", k, mls.String())
108 }
109 }
110 }
111
112 func TestMergeLocalsIntegration(t *testing.T) {
113 testenv.MustHaveGoBuild(t)
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141 tmpdir := t.TempDir()
142 src := filepath.Join("testdata", "mergelocals", "integration.go")
143 obj := filepath.Join(tmpdir, "p.a")
144 out, err := testenv.Command(t, testenv.GoToolPath(t), "tool", "compile",
145 "-p=p", "-c", "1", "-o", obj, "-d=mergelocalstrace=2,mergelocals=1",
146 src).CombinedOutput()
147 if err != nil {
148 t.Fatalf("failed to compile: %v\n%s", err, out)
149 }
150 vars := make(map[string]string)
151 lines := strings.Split(string(out), "\n")
152 prolog := true
153 varsAtFrameOffset := make(map[string]int)
154 for _, line := range lines {
155 if line == "=-= stack layout for ABC:" {
156 prolog = false
157 continue
158 } else if prolog || line == "" {
159 continue
160 }
161 fields := strings.Fields(line)
162 wantFields := 9
163 if len(fields) != wantFields {
164 t.Log(string(out))
165 t.Fatalf("bad trace output line, wanted %d fields got %d: %s",
166 wantFields, len(fields), line)
167 }
168 vname := fields[1]
169 frameoff := fields[3]
170 varsAtFrameOffset[frameoff] = varsAtFrameOffset[frameoff] + 1
171 vars[vname] = frameoff
172 }
173 wantvnum := 8
174 gotvnum := len(vars)
175 if wantvnum != gotvnum {
176 t.Log(string(out))
177 t.Fatalf("expected trace output on %d vars got %d\n", wantvnum, gotvnum)
178 }
179
180
181 n3 := 0
182 got := []int{}
183 for _, v := range varsAtFrameOffset {
184 if v > 2 {
185 n3++
186 }
187 got = append(got, v)
188 }
189 sort.Ints(got)
190 if n3 == 0 {
191 t.Logf("%s\n", string(out))
192 t.Fatalf("expected at least one clump of 3, got: %+v", got)
193 }
194 }
195
View as plain text