@@ -10,6 +10,7 @@ import (
10
10
"io/ioutil"
11
11
"os"
12
12
"path/filepath"
13
+ "sort"
13
14
"strconv"
14
15
"strings"
15
16
"testing"
@@ -22,9 +23,9 @@ import (
22
23
// Output is generated by, in effect, turning on -S and comparing the
23
24
// result against a golden file.
24
25
25
- func testEndToEnd (t * testing.T , goarch string ) {
26
+ func testEndToEnd (t * testing.T , goarch , file string ) {
26
27
lex .InitHist ()
27
- input := filepath .Join ("testdata" , goarch + ".s" )
28
+ input := filepath .Join ("testdata" , file + ".s" )
28
29
architecture , ctxt := setArch (goarch )
29
30
lexer := lex .NewLexer (input , ctxt )
30
31
parser := NewParser (ctxt , architecture , lexer )
@@ -33,23 +34,31 @@ func testEndToEnd(t *testing.T, goarch string) {
33
34
testOut = new (bytes.Buffer ) // The assembler writes test output to this buffer.
34
35
ctxt .Bso = obj .Binitw (os .Stdout )
35
36
defer ctxt .Bso .Flush ()
36
- ctxt .Diag = t .Errorf
37
+ failed := false
38
+ ctxt .Diag = func (format string , args ... interface {}) {
39
+ failed = true
40
+ t .Errorf (format , args ... )
41
+ }
37
42
obj .Binitw (ioutil .Discard )
38
43
pList .Firstpc , ok = parser .Parse ()
39
- if ! ok || t .Failed () {
40
- t .Fatalf ("asm: %s assembly failed" , goarch )
44
+ if ! ok || failed {
45
+ t .Errorf ("asm: %s assembly failed" , goarch )
46
+ return
41
47
}
42
48
output := strings .Split (testOut .String (), "\n " )
43
49
44
50
// Reconstruct expected output by independently "parsing" the input.
45
51
data , err := ioutil .ReadFile (input )
46
52
if err != nil {
47
- t .Fatal (err )
53
+ t .Error (err )
54
+ return
48
55
}
49
56
lineno := 0
50
57
seq := 0
58
+ hexByLine := map [string ]string {}
59
+ lines := strings .SplitAfter (string (data ), "\n " )
51
60
Diff:
52
- for _ , line := range strings . SplitAfter ( string ( data ), " \n " ) {
61
+ for _ , line := range lines {
53
62
lineno ++
54
63
55
64
// The general form of a test input line is:
@@ -62,14 +71,31 @@ Diff:
62
71
}
63
72
seq ++
64
73
74
+ var hexes string
65
75
switch len (parts ) {
66
76
default :
67
77
t .Errorf ("%s:%d: unable to understand comments: %s" , input , lineno , line )
68
78
case 1 :
69
79
// no comment
70
80
case 2 :
71
- // one comment, printed form
81
+ // might be printed form or hex
82
+ note := strings .TrimSpace (parts [1 ])
83
+ if isHexes (note ) {
84
+ hexes = note
85
+ } else {
86
+ printed = note
87
+ }
88
+ case 3 :
89
+ // printed form, then hex
72
90
printed = strings .TrimSpace (parts [1 ])
91
+ hexes = strings .TrimSpace (parts [2 ])
92
+ if ! isHexes (hexes ) {
93
+ t .Errorf ("%s:%d: malformed hex instruction encoding: %s" , input , lineno , line )
94
+ }
95
+ }
96
+
97
+ if hexes != "" {
98
+ hexByLine [fmt .Sprintf ("%s:%d" , input , lineno )] = hexes
73
99
}
74
100
75
101
// Canonicalize spacing in printed form.
@@ -142,28 +168,114 @@ Diff:
142
168
t .Errorf ("unexpected output: %q" , output [0 ])
143
169
output = output [1 :]
144
170
}
171
+
172
+ // Checked printing.
173
+ // Now check machine code layout.
174
+
175
+ top := pList .Firstpc
176
+ var text * obj.LSym
177
+ ok = true
178
+ ctxt .Diag = func (format string , args ... interface {}) {
179
+ t .Errorf (format , args ... )
180
+ ok = false
181
+ }
182
+ obj .Flushplist (ctxt )
183
+
184
+ for p := top ; p != nil ; p = p .Link {
185
+ if p .As == obj .ATEXT {
186
+ text = p .From .Sym
187
+ }
188
+ hexes := hexByLine [p .Line ()]
189
+ if hexes == "" {
190
+ continue
191
+ }
192
+ delete (hexByLine , p .Line ())
193
+ if text == nil {
194
+ t .Errorf ("%s: instruction outside TEXT" , p )
195
+ }
196
+ size := int64 (len (text .P )) - p .Pc
197
+ if p .Link != nil {
198
+ size = p .Link .Pc - p .Pc
199
+ } else if p .Isize != 0 {
200
+ size = int64 (p .Isize )
201
+ }
202
+ var code []byte
203
+ if p .Pc < int64 (len (text .P )) {
204
+ code = text .P [p .Pc :]
205
+ if size < int64 (len (code )) {
206
+ code = code [:size ]
207
+ }
208
+ }
209
+ codeHex := fmt .Sprintf ("%x" , code )
210
+ if codeHex == "" {
211
+ codeHex = "empty"
212
+ }
213
+ ok := false
214
+ for _ , hex := range strings .Split (hexes , " or " ) {
215
+ if codeHex == hex {
216
+ ok = true
217
+ break
218
+ }
219
+ }
220
+ if ! ok {
221
+ t .Errorf ("%s: have encoding %s, want %s" , p , codeHex , hexes )
222
+ }
223
+ }
224
+
225
+ if len (hexByLine ) > 0 {
226
+ var missing []string
227
+ for key := range hexByLine {
228
+ missing = append (missing , key )
229
+ }
230
+ sort .Strings (missing )
231
+ for _ , line := range missing {
232
+ t .Errorf ("%s: did not find instruction encoding" , line )
233
+ }
234
+ }
235
+
145
236
}
146
237
147
- func TestPPC64EndToEnd (t * testing.T ) {
148
- testEndToEnd (t , "ppc64" )
238
+ func isHexes (s string ) bool {
239
+ if s == "" {
240
+ return false
241
+ }
242
+ if s == "empty" {
243
+ return true
244
+ }
245
+ for _ , f := range strings .Split (s , " or " ) {
246
+ if f == "" || len (f )% 2 != 0 || strings .TrimLeft (f , "0123456789abcdef" ) != "" {
247
+ return false
248
+ }
249
+ }
250
+ return true
251
+ }
252
+
253
+ func Test386EndToEnd (t * testing.T ) {
254
+ testEndToEnd (t , "386" , "386" )
149
255
}
150
256
151
257
func TestARMEndToEnd (t * testing.T ) {
152
- testEndToEnd (t , "arm" )
258
+ defer os .Setenv ("GOARM" , os .Getenv ("GOARM" ))
259
+
260
+ for _ , goarm := range []string {"5" , "6" , "7" } {
261
+ os .Setenv ("GOARM" , goarm )
262
+ t .Logf ("GOARM=%v" , os .Getenv ("GOARM" ))
263
+ testEndToEnd (t , "arm" , "arm" )
264
+ }
153
265
}
154
266
155
267
func TestARM64EndToEnd (t * testing.T ) {
156
- testEndToEnd (t , "arm64" )
268
+ testEndToEnd (t , "arm64" , "arm64" )
157
269
}
158
270
159
271
func TestAMD64EndToEnd (t * testing.T ) {
160
- testEndToEnd (t , "amd64" )
272
+ testEndToEnd (t , "amd64" , "amd64" )
161
273
}
162
274
163
- func Test386EndToEnd (t * testing.T ) {
164
- testEndToEnd (t , "386 " )
275
+ func TestMIPS64EndToEnd (t * testing.T ) {
276
+ testEndToEnd (t , "mips64" , "mips64 " )
165
277
}
166
278
167
- func TestMIPS64EndToEnd (t * testing.T ) {
168
- testEndToEnd (t , "mips64 " )
279
+ func TestPPC64EndToEnd (t * testing.T ) {
280
+ testEndToEnd (t , "ppc64" , "ppc64 " )
169
281
}
0 commit comments