Commit 634049db authored by Rob Pike's avatar Rob Pike

[dev.cc] cmd/asm: add end-to-end test

Add trivial golden test that verifies output matches expectation.
The input is based on the old grammar and is intended to cover
the space of the input language.

PPC64 and ARM only for now; others to follow.

Change-Id: Ib5957822bcafd5b9d4c1dea1c03cc6ee1238f7ef
Reviewed-on: https://go-review.googlesource.com/5421Reviewed-by: 's avatarRuss Cox <rsc@golang.org>
parent 5d111b89
......@@ -5,6 +5,7 @@
package asm
import (
"bytes"
"fmt"
"text/scanner"
......@@ -18,6 +19,8 @@ import (
// TODO: configure the architecture
var testOut *bytes.Buffer // Gathers output when testing.
// append adds the Prog to the end of the program-thus-far.
// If doLabel is set, it also defines the labels collect for this Prog.
func (p *Parser) append(prog *obj.Prog, cond string, doLabel bool) {
......@@ -46,6 +49,9 @@ func (p *Parser) append(prog *obj.Prog, cond string, doLabel bool) {
if *flags.Debug {
fmt.Println(p.histLineNum, prog)
}
if testOut != nil {
fmt.Fprintln(testOut, p.histLineNum, prog)
}
}
// validateSymbol checks that addr represents a valid name for a pseudo-op.
......
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package asm
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"testing"
"cmd/asm/internal/lex"
"cmd/internal/obj"
)
// An end-to-end test for the assembler: Do we print what we parse?
// Output is generated by, in effect, turning on -S and comparing the
// result against a golden file.
func testEndToEnd(t *testing.T, goarch string) {
lex.InitHist()
input := filepath.Join("testdata", goarch+".s")
output := filepath.Join("testdata", goarch+".out")
architecture, ctxt := setArch(goarch)
lexer := lex.NewLexer(input, ctxt)
parser := NewParser(ctxt, architecture, lexer)
pList := obj.Linknewplist(ctxt)
var ok bool
testOut = new(bytes.Buffer) // The assembler writes -S output to this buffer.
ctxt.Bso = obj.Binitw(os.Stdout)
defer obj.Bflush(ctxt.Bso)
ctxt.Diag = log.Fatalf
obj.Binitw(ioutil.Discard)
pList.Firstpc, ok = parser.Parse()
if !ok {
t.Fatalf("asm: ppc64 assembly failed")
}
result := string(testOut.Bytes())
expect, err := ioutil.ReadFile(output)
if err != nil {
t.Fatal(err)
}
if result != string(expect) {
if false { // Enable to capture output.
fmt.Printf("%s", result)
os.Exit(1)
}
t.Errorf("%s failed: output differs", goarch)
r := strings.Split(result, "\n")
e := strings.Split(string(expect), "\n")
if len(r) != len(e) {
t.Errorf("%s: expected %d lines, got %d", len(e), len(r))
}
n := len(e)
if n > len(r) {
n = len(r)
}
for i := 0; i < n; i++ {
if r[i] != e[i] {
t.Errorf("%s:%d:\nexpected\n\t%s\ngot\n\t%s", output, i, e[i], r[i])
}
}
}
}
func TestPPC64EndToEnd(t *testing.T) {
testEndToEnd(t, "ppc64")
}
func TestARMEndToEnd(t *testing.T) {
testEndToEnd(t, "arm")
}
......@@ -15,10 +15,17 @@ import (
// A simple in-out test: Do we print what we parse?
func newParser(goarch string) *Parser {
func setArch(goarch string) (*arch.Arch, *obj.Link) {
os.Setenv("GOOS", "linux") // obj can handle this OS for all architectures.
architecture := arch.Set(goarch)
ctxt := obj.Linknew(architecture.LinkArch)
if architecture == nil {
panic("asm: unrecognized architecture " + goarch)
}
return architecture, obj.Linknew(architecture.LinkArch)
}
func newParser(goarch string) *Parser {
architecture, ctxt := setArch(goarch)
return NewParser(ctxt, architecture, nil)
}
......
1 00001 (testdata/arm.s:1) TEXT foo+0(SB),0,$0
10 00002 (testdata/arm.s:10) ADD $1,R2,R3
11 00003 (testdata/arm.s:11) ADD R1<<R2,R3,R4
12 00004 (testdata/arm.s:12) ADD R1>>R2,R3,R4
13 00005 (testdata/arm.s:13) ADD R1@>R2,R3,R4
14 00006 (testdata/arm.s:14) ADD R1->R2,R3,R4
15 00007 (testdata/arm.s:15) ADD R1,R2,R3
16 00008 (testdata/arm.s:16) ADD R1<<R2,R3,R4
26 00009 (testdata/arm.s:26) ADD $1,R2
27 00010 (testdata/arm.s:27) ADD R1<<R2,R3
28 00011 (testdata/arm.s:28) ADD R1>>R2,R3
29 00012 (testdata/arm.s:29) ADD R1@>R2,R3
30 00013 (testdata/arm.s:30) ADD R1->R2,R3
31 00014 (testdata/arm.s:31) ADD R1,R2
40 00015 (testdata/arm.s:40) CLZ.S R1,R2
49 00016 (testdata/arm.s:49) MOVW.S R1,R2
50 00017 (testdata/arm.s:50) MOVW.S $1,R2
51 00018 (testdata/arm.s:51) MOVW.S R1<<R2,R3
60 00019 (testdata/arm.s:60) JMP.S ,20(PC)
66 00020 (testdata/arm.s:66) JMP.S ,0(R2)
67 00021 (testdata/arm.s:67) JMP.S ,foo+0(SB)
68 00022 (testdata/arm.s:68) JMP.S ,bar<>+0(SB)
77 00023 (testdata/arm.s:77) BX 0(R2),
86 00024 (testdata/arm.s:86) BEQ ,25(PC)
95 00025 (testdata/arm.s:95) SWI.S ,R1
96 00026 (testdata/arm.s:96) SWI.S ,0(R1)
97 00027 (testdata/arm.s:97) SWI.S ,foo+0(SB)
106 00028 (testdata/arm.s:106) CMP.S $1,R2,
107 00029 (testdata/arm.s:107) CMP.S R1<<R2,R3,
108 00030 (testdata/arm.s:108) CMP.S R1,R2,
122 00031 (testdata/arm.s:122) MOVM 0(R1),[R2,R5,R8,R10]
123 00032 (testdata/arm.s:123) MOVM 0(R1),[R2,R3,R4,R5]
124 00033 (testdata/arm.s:124) MOVM.S 0(R1),[R2]
135 00034 (testdata/arm.s:135) MOVM [R2,R5,R8,R10],0(R1)
136 00035 (testdata/arm.s:136) MOVM [R2,R3,R4,R5],0(R1)
137 00036 (testdata/arm.s:137) MOVM.S [R2],0(R1)
146 00037 (testdata/arm.s:146) STREX.S 0(R2),R1,R3
152 00038 (testdata/arm.s:152) STREX.S 0(R2),R1,R1
158 00039 (testdata/arm.s:158) STREX.S 0(R2),R3,R3
166 00040 (testdata/arm.s:166) CASE.S R1,
175 00041 (testdata/arm.s:175) WORD ,$1234
184 00042 (testdata/arm.s:184) ABSF.S F1,F2
190 00043 (testdata/arm.s:190) ADDD.S F1,F2
191 00044 (testdata/arm.s:191) ADDD.S $0.5,F2
197 00045 (testdata/arm.s:197) ADDD.S F1,F2,F3
198 00046 (testdata/arm.s:198) ADDD.S $0.5,F2,F3
204 00047 (testdata/arm.s:204) CMPD.S F1,F2
228 00048 (testdata/arm.s:228) MRC ,$8301712627
237 00049 (testdata/arm.s:237) MULL R1,R2,(R3, R4)
249 00050 (testdata/arm.s:249) MULAWT R1,R2,R3, R4
257 00051 (testdata/arm.s:257) PLD 0(R1),
258 00052 (testdata/arm.s:258) PLD 4(R1),
267 00053 (testdata/arm.s:267) RET ,
276 00054 (testdata/arm.s:276) END ,
TEXT foo(SB), 0, $0
// ADD
//
// LTYPE1 cond imsr ',' spreg ',' reg
// {
// outcode($1, $2, &$3, $5, &$7);
// }
// Cover some operand space here too.
ADD $1, R2, R3
ADD R1<<R2, R3, R4
ADD R1>>R2, R3, R4
ADD R1@>R2, R3, R4
ADD R1->R2, R3, R4
ADD R1, R2, R3
ADD R(1)<<R(2), R(3), R(4)
// LTYPE1 cond imsr ',' spreg ',' // asm doesn't support trailing comma.
// {
// outcode($1, $2, &$3, $5, &nullgen);
// }
// LTYPE1 cond imsr ',' reg
// {
// outcode($1, $2, &$3, 0, &$5);
// }
ADD $1, R2
ADD R1<<R2, R3
ADD R1>>R2, R3
ADD R1@>R2, R3
ADD R1->R2, R3
ADD R1, R2
//
// MVN
//
// LTYPE2 cond imsr ',' reg
// {
// outcode($1, $2, &$3, 0, &$5);
// }
CLZ.S R1, R2
//
// MOVW
//
// LTYPE3 cond gen ',' gen
// {
// outcode($1, $2, &$3, 0, &$5);
// }
MOVW.S R1, R2
MOVW.S $1, R2
MOVW.S R1<<R2, R3
//
// B/BL
//
// LTYPE4 cond comma rel
// {
// outcode($1, $2, &nullgen, 0, &$4);
// }
B.S 1(PC)
// LTYPE4 cond comma nireg
// {
// outcode($1, $2, &nullgen, 0, &$4);
// }
B.S (R2)
B.S foo(SB)
B.S bar<>(SB)
//
// BX
//
// LTYPEBX comma ireg
// {
// outcode($1, Always, &nullgen, 0, &$3);
// }
BX (R2)
//
// BEQ
//
// LTYPE5 comma rel
// {
// outcode($1, Always, &nullgen, 0, &$3);
// }
BEQ 1(PC)
//
// SWI
//
// LTYPE6 cond comma gen
// {
// outcode($1, $2, &nullgen, 0, &$4);
// }
SWI.S R1
SWI.S (R1)
SWI.S foo(SB)
//
// CMP
//
// LTYPE7 cond imsr ',' spreg
// {
// outcode($1, $2, &$3, $5, &nullgen);
// }
CMP.S $1, R2
CMP.S R1<<R2, R3
CMP.S R1, R2
//
// MOVM
//
// LTYPE8 cond ioreg ',' '[' reglist ']'
// {
// var g obj.Addr
//
// g = nullgen;
// g.Type = obj.TYPE_CONST;
// g.Offset = int64($6);
// outcode($1, $2, &$3, 0, &g);
// }
MOVM 0(R1), [R2,R5,R8,g]
MOVM 0(R1), [R2-R5]
MOVM.S (R1), [R2]
// LTYPE8 cond '[' reglist ']' ',' ioreg
// {
// var g obj.Addr
//
// g = nullgen;
// g.Type = obj.TYPE_CONST;
// g.Offset = int64($4);
// outcode($1, $2, &g, 0, &$7);
// }
MOVM [R2,R5,R8,g], 0(R1)
MOVM [R2-R5], 0(R1)
MOVM.S [R2], (R1)
//
// SWAP
//
// LTYPE9 cond reg ',' ireg ',' reg
// {
// outcode($1, $2, &$5, int32($3.Reg), &$7);
// }
STREX.S R1, (R2), R3
// LTYPE9 cond reg ',' ireg
// {
// outcode($1, $2, &$5, int32($3.Reg), &$3);
// }
STREX.S R1, (R2)
// LTYPE9 cond comma ireg ',' reg
// {
// outcode($1, $2, &$4, int32($6.Reg), &$6);
// }
STREX.S (R2), R3
// CASE
//
// LTYPED cond reg
// {
// outcode($1, $2, &$3, 0, &nullgen);
// }
CASE.S R1
//
// word
//
// LTYPEH comma ximm
// {
// outcode($1, Always, &nullgen, 0, &$3);
// }
WORD $1234
//
// floating-point coprocessor
//
// LTYPEI cond freg ',' freg
// {
// outcode($1, $2, &$3, 0, &$5);
// }
ABSF.S F1, F2
// LTYPEK cond frcon ',' freg
// {
// outcode($1, $2, &$3, 0, &$5);
// }
ADDD.S F1, F2
ADDD.S $0.5, F2
// LTYPEK cond frcon ',' LFREG ',' freg
// {
// outcode($1, $2, &$3, $5, &$7);
// }
ADDD.S F1, F2, F3
ADDD.S $0.5, F2, F3
// LTYPEL cond freg ',' freg
// {
// outcode($1, $2, &$3, int32($5.Reg), &nullgen);
// }
CMPD.S F1, F2
//
// MCR MRC
//
// LTYPEJ cond con ',' expr ',' spreg ',' creg ',' creg oexpr
// {
// var g obj.Addr
//
// g = nullgen;
// g.Type = obj.TYPE_CONST;
// g.Offset = int64(
// (0xe << 24) | /* opcode */
// ($1 << 20) | /* MCR/MRC */
// (($2^C_SCOND_XOR) << 28) | /* scond */
// (($3 & 15) << 8) | /* coprocessor number */
// (($5 & 7) << 21) | /* coprocessor operation */
// (($7 & 15) << 12) | /* arm register */
// (($9 & 15) << 16) | /* Crn */
// (($11 & 15) << 0) | /* Crm */
// (($12 & 7) << 5) | /* coprocessor information */
// (1<<4)); /* must be set */
// outcode(AMRC, Always, &nullgen, 0, &g);
// }
MRC.S 4, 6, R1, C2, C3, 7
//
// MULL r1,r2,(hi,lo)
//
// LTYPEM cond reg ',' reg ',' regreg
// {
// outcode($1, $2, &$3, int32($5.Reg), &$7);
// }
MULL R1, R2, (R3,R4)
//
// MULA r1,r2,r3,r4: (r1*r2+r3) & 0xffffffff . r4
// MULAW{T,B} r1,r2,r3,r4
//
// LTYPEN cond reg ',' reg ',' reg ',' spreg
// {
// $7.Type = obj.TYPE_REGREG2;
// $7.Offset = int64($9);
// outcode($1, $2, &$3, int32($5.Reg), &$7);
// }
MULAWT R1, R2, R3, R4
//
// PLD
//
// LTYPEPLD oreg
// {
// outcode($1, Always, &$2, 0, &nullgen);
// }
PLD (R1)
PLD 4(R1)
//
// RET
//
// LTYPEA cond
// {
// outcode($1, $2, &nullgen, 0, &nullgen);
// }
RET
//
// END
//
// LTYPEE
// {
// outcode($1, Always, &nullgen, 0, &nullgen);
// }
END
5 00001 (testdata/ppc64.s:5) TEXT foo(SB),$0
15 00002 (testdata/ppc64.s:15) MOVW R1,R2
21 00003 (testdata/ppc64.s:21) MOVW foo<>+3(SB),R2
22 00004 (testdata/ppc64.s:22) MOVW 16(R1),R2
28 00005 (testdata/ppc64.s:28) MOVW 0(R1),R2
29 00006 (testdata/ppc64.s:29) MOVW 0(R1+R2),R3
35 00007 (testdata/ppc64.s:35) MOVW R1,R2
41 00008 (testdata/ppc64.s:41) MOVB foo<>+3(SB),R2
42 00009 (testdata/ppc64.s:42) MOVB 16(R1),R2
48 00010 (testdata/ppc64.s:48) MOVB 0(R1),R2
49 00011 (testdata/ppc64.s:49) MOVB 0(R1+R2),R3
58 00012 (testdata/ppc64.s:58) FMOVD foo<>+3(SB),F2
59 00013 (testdata/ppc64.s:59) FMOVD 16(R1),F2
65 00014 (testdata/ppc64.s:65) FMOVD 0(R1),F2
71 00015 (testdata/ppc64.s:71) FMOVD $0.10000000000000001,F2
77 00016 (testdata/ppc64.s:77) FMOVD F1,F2
83 00017 (testdata/ppc64.s:83) FMOVD F2,foo<>+3(SB)
84 00018 (testdata/ppc64.s:84) FMOVD F2,16(R1)
90 00019 (testdata/ppc64.s:90) FMOVD F2,0(R1)
99 00020 (testdata/ppc64.s:99) MOVW R1,foo<>+3(SB)
100 00021 (testdata/ppc64.s:100) MOVW R1,16(R2)
106 00022 (testdata/ppc64.s:106) MOVW R1,0(R1)
107 00023 (testdata/ppc64.s:107) MOVW R1,0(R2+R3)
113 00024 (testdata/ppc64.s:113) MOVB R1,foo<>+3(SB)
114 00025 (testdata/ppc64.s:114) MOVB R1,16(R2)
120 00026 (testdata/ppc64.s:120) MOVB R1,0(R1)
121 00027 (testdata/ppc64.s:121) MOVB R1,0(R2+R3)
129 00028 (testdata/ppc64.s:129) FMOVD F1,foo<>+3(SB)
130 00029 (testdata/ppc64.s:130) FMOVD F1,16(R2)
136 00030 (testdata/ppc64.s:136) FMOVD F1,0(R1)
145 00031 (testdata/ppc64.s:145) MOVFL FPSCR,F1
151 00032 (testdata/ppc64.s:151) MOVFL F1,FPSCR
157 00033 (testdata/ppc64.s:157) MOVFL F1,$4,FPSCR
163 00034 (testdata/ppc64.s:163) MOVFL FPSCR,C0
184 00035 (testdata/ppc64.s:184) MOVW R1,C1
190 00036 (testdata/ppc64.s:190) MOVW R1,CR
202 00037 (testdata/ppc64.s:202) ADD R1,R2,R3
208 00038 (testdata/ppc64.s:208) ADD $1,R2,R3
220 00039 (testdata/ppc64.s:220) ADD R1,R2
226 00040 (testdata/ppc64.s:226) ADD $4,R1
232 00041 (testdata/ppc64.s:232) ADDE R1,R2,R3
238 00042 (testdata/ppc64.s:238) ADDE R1,R2
244 00043 (testdata/ppc64.s:244) SLW R1,R2,R3
250 00044 (testdata/ppc64.s:250) SLW R1,R2
256 00045 (testdata/ppc64.s:256) SLW $4,R1,R2
262 00046 (testdata/ppc64.s:262) SLW $4,R1
268 00047 (testdata/ppc64.s:268) SLW $4,R1
274 00048 (testdata/ppc64.s:274) SUBME R1,R1
292 00049 (testdata/ppc64.s:292) MOVW $1,R1
298 00050 (testdata/ppc64.s:298) MOVW $1,R1
299 00051 (testdata/ppc64.s:299) MOVW $foo(SB),R1
323 00052 (testdata/ppc64.s:323) MOVFL C0,C1
335 00053 (testdata/ppc64.s:335) MOVW CR,R1
341 00054 (testdata/ppc64.s:341) MOVW SPR(0),R1
342 00055 (testdata/ppc64.s:342) MOVW SPR(7),R1
348 00056 (testdata/ppc64.s:348) MOVW LR,R1
349 00057 (testdata/ppc64.s:349) MOVW CTR,R1
355 00058 (testdata/ppc64.s:355) MOVW R1,LR
356 00059 (testdata/ppc64.s:356) MOVW R1,CTR
368 00060 (testdata/ppc64.s:368) MOVW R1,SPR(7)
380 00061 (testdata/ppc64.s:380) JMP ,62(APC)
381 00062 (testdata/ppc64.s:381) JMP ,61
387 00063 (testdata/ppc64.s:387) JMP ,4(R1)
388 00064 (testdata/ppc64.s:388) JMP ,foo(SB)
394 00065 (testdata/ppc64.s:394) JMP ,CTR
413 00066 (testdata/ppc64.s:413) BEQ C1,67(APC)
414 00067 (testdata/ppc64.s:414) BEQ C1,66
440 00068 (testdata/ppc64.s:440) BC 4,CTR
450 00069 (testdata/ppc64.s:450) BC $3,R4,66
470 00070 (testdata/ppc64.s:470) BC $3,R3,LR
500 00071 (testdata/ppc64.s:500) FABS F1,F2
506 00072 (testdata/ppc64.s:506) FADD F1,F2
512 00073 (testdata/ppc64.s:512) FADD F1,F2,F3
518 00074 (testdata/ppc64.s:518) FMADD F1,F2,F3,F4
524 00075 (testdata/ppc64.s:524) FCMPU F1,F2
530 00076 (testdata/ppc64.s:530) FCMPU F1,F2,C0
539 00077 (testdata/ppc64.s:539) CMP R1,R2
545 00078 (testdata/ppc64.s:545) CMP R1,$4
551 00079 (testdata/ppc64.s:551) CMP R1,C0,R2
557 00080 (testdata/ppc64.s:557) CMP R1,C0,$4
566 00081 (testdata/ppc64.s:566) RLDC $4,R1,$5,R2
572 00082 (testdata/ppc64.s:572) RLDC $26,R1,$201326592,R2
578 00083 (testdata/ppc64.s:578) RLDC R1,R2,$4,R3
584 00084 (testdata/ppc64.s:584) RLWMI R1,R2,$201326592,R3
593 00085 (testdata/ppc64.s:593) MOVMW foo(SB),R2
594 00086 (testdata/ppc64.s:594) MOVMW 4(R1),R2
600 00087 (testdata/ppc64.s:600) MOVMW R1,foo(SB)
601 00088 (testdata/ppc64.s:601) MOVMW R1,4(R2)
611 00089 (testdata/ppc64.s:611) LSW 0(R1),R2
612 00090 (testdata/ppc64.s:612) LSW 0(R1+R2),R3
618 00091 (testdata/ppc64.s:618) LSW 0(R1+NONE),R2
619 00092 (testdata/ppc64.s:619) LSW 0(R1+NONE),R3
625 00093 (testdata/ppc64.s:625) STSW R1,0(R2)
626 00094 (testdata/ppc64.s:626) STSW R1,0(R2+R3)
632 00095 (testdata/ppc64.s:632) STSW R1,0(R2+NONE)
633 00096 (testdata/ppc64.s:633) STSW R1,0(R2+NONE)
639 00097 (testdata/ppc64.s:639) MOVHBR 0(R1),R2
640 00098 (testdata/ppc64.s:640) MOVHBR 0(R1+R2),R3
646 00099 (testdata/ppc64.s:646) MOVHBR R1,0(R2)
647 00100 (testdata/ppc64.s:647) MOVHBR R1,0(R2+R3)
653 00101 (testdata/ppc64.s:653) DCBF 0(R1),
654 00102 (testdata/ppc64.s:654) DCBF 0(R1),
663 00103 (testdata/ppc64.s:663) NOP ,
669 00104 (testdata/ppc64.s:669) NOP R2,
675 00105 (testdata/ppc64.s:675) NOP F2,
681 00106 (testdata/ppc64.s:681) NOP R2,
687 00107 (testdata/ppc64.s:687) NOP F2,
693 00108 (testdata/ppc64.s:693) NOP $4,
701 00109 (testdata/ppc64.s:701) RET ,
709 00110 (testdata/ppc64.s:709) END ,
This diff is collapsed.
......@@ -83,6 +83,11 @@ func NewLexer(name string, ctxt *obj.Link) TokenReader {
return input
}
// InitHist sets the line count to 1, for reproducible testing.
func InitHist() {
histLine = 1
}
// The other files in this directory each contain an implementation of TokenReader.
// A TokenReader is like a reader, but returns lex tokens of type Token. It also can tell you what
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment