aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/asm
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2016-01-21 20:48:21 -0500
committerRuss Cox <rsc@golang.org>2016-01-24 05:50:41 +0000
commit2eb8d94dbd822fab695f2781c8b6d14345be1d07 (patch)
tree90f4be71f1698e68a68a577fce6de67276e4b269 /src/cmd/asm
parentd3ff40fb1f4daae5b7ef4c54909a35d57e1ca753 (diff)
downloadgo-2eb8d94dbd822fab695f2781c8b6d14345be1d07.tar.xz
cmd/asm: add test for verification of instruction encodings
Not much testing yet, but the test now exists. Another step toward #13822. Change-Id: Idb2b06bf53a6113c83008150b4c0b631bb195279 Reviewed-on: https://go-review.googlesource.com/18844 Reviewed-by: Rob Pike <r@golang.org> Run-TryBot: Russ Cox <rsc@golang.org>
Diffstat (limited to 'src/cmd/asm')
-rw-r--r--src/cmd/asm/internal/asm/endtoend_test.go146
-rw-r--r--src/cmd/asm/internal/asm/testdata/amd64.s2
-rw-r--r--src/cmd/asm/internal/asm/testdata/arm.s2
3 files changed, 131 insertions, 19 deletions
diff --git a/src/cmd/asm/internal/asm/endtoend_test.go b/src/cmd/asm/internal/asm/endtoend_test.go
index bba82b5fca..620bb97417 100644
--- a/src/cmd/asm/internal/asm/endtoend_test.go
+++ b/src/cmd/asm/internal/asm/endtoend_test.go
@@ -10,6 +10,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
+ "sort"
"strconv"
"strings"
"testing"
@@ -22,9 +23,9 @@ import (
// Output is generated by, in effect, turning on -S and comparing the
// result against a golden file.
-func testEndToEnd(t *testing.T, goarch string) {
+func testEndToEnd(t *testing.T, goarch, file string) {
lex.InitHist()
- input := filepath.Join("testdata", goarch+".s")
+ input := filepath.Join("testdata", file+".s")
architecture, ctxt := setArch(goarch)
lexer := lex.NewLexer(input, ctxt)
parser := NewParser(ctxt, architecture, lexer)
@@ -33,23 +34,31 @@ func testEndToEnd(t *testing.T, goarch string) {
testOut = new(bytes.Buffer) // The assembler writes test output to this buffer.
ctxt.Bso = obj.Binitw(os.Stdout)
defer ctxt.Bso.Flush()
- ctxt.Diag = t.Errorf
+ failed := false
+ ctxt.Diag = func(format string, args ...interface{}) {
+ failed = true
+ t.Errorf(format, args...)
+ }
obj.Binitw(ioutil.Discard)
pList.Firstpc, ok = parser.Parse()
- if !ok || t.Failed() {
- t.Fatalf("asm: %s assembly failed", goarch)
+ if !ok || failed {
+ t.Errorf("asm: %s assembly failed", goarch)
+ return
}
output := strings.Split(testOut.String(), "\n")
// Reconstruct expected output by independently "parsing" the input.
data, err := ioutil.ReadFile(input)
if err != nil {
- t.Fatal(err)
+ t.Error(err)
+ return
}
lineno := 0
seq := 0
+ hexByLine := map[string]string{}
+ lines := strings.SplitAfter(string(data), "\n")
Diff:
- for _, line := range strings.SplitAfter(string(data), "\n") {
+ for _, line := range lines {
lineno++
// The general form of a test input line is:
@@ -62,14 +71,31 @@ Diff:
}
seq++
+ var hexes string
switch len(parts) {
default:
t.Errorf("%s:%d: unable to understand comments: %s", input, lineno, line)
case 1:
// no comment
case 2:
- // one comment, printed form
+ // might be printed form or hex
+ note := strings.TrimSpace(parts[1])
+ if isHexes(note) {
+ hexes = note
+ } else {
+ printed = note
+ }
+ case 3:
+ // printed form, then hex
printed = strings.TrimSpace(parts[1])
+ hexes = strings.TrimSpace(parts[2])
+ if !isHexes(hexes) {
+ t.Errorf("%s:%d: malformed hex instruction encoding: %s", input, lineno, line)
+ }
+ }
+
+ if hexes != "" {
+ hexByLine[fmt.Sprintf("%s:%d", input, lineno)] = hexes
}
// Canonicalize spacing in printed form.
@@ -142,28 +168,114 @@ Diff:
t.Errorf("unexpected output: %q", output[0])
output = output[1:]
}
+
+ // Checked printing.
+ // Now check machine code layout.
+
+ top := pList.Firstpc
+ var text *obj.LSym
+ ok = true
+ ctxt.Diag = func(format string, args ...interface{}) {
+ t.Errorf(format, args...)
+ ok = false
+ }
+ obj.Flushplist(ctxt)
+
+ for p := top; p != nil; p = p.Link {
+ if p.As == obj.ATEXT {
+ text = p.From.Sym
+ }
+ hexes := hexByLine[p.Line()]
+ if hexes == "" {
+ continue
+ }
+ delete(hexByLine, p.Line())
+ if text == nil {
+ t.Errorf("%s: instruction outside TEXT", p)
+ }
+ size := int64(len(text.P)) - p.Pc
+ if p.Link != nil {
+ size = p.Link.Pc - p.Pc
+ } else if p.Isize != 0 {
+ size = int64(p.Isize)
+ }
+ var code []byte
+ if p.Pc < int64(len(text.P)) {
+ code = text.P[p.Pc:]
+ if size < int64(len(code)) {
+ code = code[:size]
+ }
+ }
+ codeHex := fmt.Sprintf("%x", code)
+ if codeHex == "" {
+ codeHex = "empty"
+ }
+ ok := false
+ for _, hex := range strings.Split(hexes, " or ") {
+ if codeHex == hex {
+ ok = true
+ break
+ }
+ }
+ if !ok {
+ t.Errorf("%s: have encoding %s, want %s", p, codeHex, hexes)
+ }
+ }
+
+ if len(hexByLine) > 0 {
+ var missing []string
+ for key := range hexByLine {
+ missing = append(missing, key)
+ }
+ sort.Strings(missing)
+ for _, line := range missing {
+ t.Errorf("%s: did not find instruction encoding", line)
+ }
+ }
+
}
-func TestPPC64EndToEnd(t *testing.T) {
- testEndToEnd(t, "ppc64")
+func isHexes(s string) bool {
+ if s == "" {
+ return false
+ }
+ if s == "empty" {
+ return true
+ }
+ for _, f := range strings.Split(s, " or ") {
+ if f == "" || len(f)%2 != 0 || strings.TrimLeft(f, "0123456789abcdef") != "" {
+ return false
+ }
+ }
+ return true
+}
+
+func Test386EndToEnd(t *testing.T) {
+ testEndToEnd(t, "386", "386")
}
func TestARMEndToEnd(t *testing.T) {
- testEndToEnd(t, "arm")
+ defer os.Setenv("GOARM", os.Getenv("GOARM"))
+
+ for _, goarm := range []string{"5", "6", "7"} {
+ os.Setenv("GOARM", goarm)
+ t.Logf("GOARM=%v", os.Getenv("GOARM"))
+ testEndToEnd(t, "arm", "arm")
+ }
}
func TestARM64EndToEnd(t *testing.T) {
- testEndToEnd(t, "arm64")
+ testEndToEnd(t, "arm64", "arm64")
}
func TestAMD64EndToEnd(t *testing.T) {
- testEndToEnd(t, "amd64")
+ testEndToEnd(t, "amd64", "amd64")
}
-func Test386EndToEnd(t *testing.T) {
- testEndToEnd(t, "386")
+func TestMIPS64EndToEnd(t *testing.T) {
+ testEndToEnd(t, "mips64", "mips64")
}
-func TestMIPS64EndToEnd(t *testing.T) {
- testEndToEnd(t, "mips64")
+func TestPPC64EndToEnd(t *testing.T) {
+ testEndToEnd(t, "ppc64", "ppc64")
}
diff --git a/src/cmd/asm/internal/asm/testdata/amd64.s b/src/cmd/asm/internal/asm/testdata/amd64.s
index 35af32a5cd..5512df0034 100644
--- a/src/cmd/asm/internal/asm/testdata/amd64.s
+++ b/src/cmd/asm/internal/asm/testdata/amd64.s
@@ -122,4 +122,4 @@ loop:
LOOP loop // LOOP
// LTYPE0 nonnon { outcode($1, &$2); }
- RET
+ RET // c3
diff --git a/src/cmd/asm/internal/asm/testdata/arm.s b/src/cmd/asm/internal/asm/testdata/arm.s
index 0102cd8414..8062750250 100644
--- a/src/cmd/asm/internal/asm/testdata/arm.s
+++ b/src/cmd/asm/internal/asm/testdata/arm.s
@@ -189,7 +189,7 @@ TEXT foo(SB), 7, $0
// outcode($1, $2, &$3, 0, &$5);
// }
ADDD.S F1, F2
- MOVF.S $0.5, F2 // MOVF.S $(0.5), F2
+ MOVF $0.5, F2 // MOVF $(0.5), F2
// LTYPEK cond frcon ',' LFREG ',' freg
// {