Home | History | Annotate | Download | only in x86
      1 // Copyright 2017 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package x86_test
      6 
      7 import (
      8 	"bytes"
      9 	"internal/testenv"
     10 	"io/ioutil"
     11 	"os"
     12 	"os/exec"
     13 	"path/filepath"
     14 	"strings"
     15 	"testing"
     16 )
     17 
     18 const asmData = `
     19 GLOBL zeros<>(SB),8,$64
     20 TEXT testASM(SB),4,$0
     21 VMOVDQU zeros<>(SB), Y8 // PC relative relocation is off by 1, for Y8-15
     22 RET
     23 `
     24 
     25 const goData = `
     26 package main
     27 
     28 func testASM()
     29 
     30 func main() {
     31 	testASM()
     32 }
     33 `
     34 
     35 func objdumpOutput(t *testing.T) []byte {
     36 	cwd, err := os.Getwd()
     37 	if err != nil {
     38 		t.Fatal(err)
     39 	}
     40 	tmpdir, err := ioutil.TempDir("", "19518")
     41 	if err != nil {
     42 		t.Fatal(err)
     43 	}
     44 	defer os.RemoveAll(tmpdir)
     45 	tmpfile, err := os.Create(filepath.Join(tmpdir, "input.s"))
     46 	if err != nil {
     47 		t.Fatal(err)
     48 	}
     49 	defer tmpfile.Close()
     50 	_, err = tmpfile.WriteString(asmData)
     51 	if err != nil {
     52 		t.Fatal(err)
     53 	}
     54 	tmpfile2, err := os.Create(filepath.Join(tmpdir, "input.go"))
     55 	if err != nil {
     56 		t.Fatal(err)
     57 	}
     58 	defer tmpfile2.Close()
     59 	_, err = tmpfile2.WriteString(goData)
     60 	if err != nil {
     61 		t.Fatal(err)
     62 	}
     63 	err = os.Chdir(tmpdir)
     64 	if err != nil {
     65 		t.Fatal(err)
     66 	}
     67 	cmd := exec.Command(
     68 		testenv.GoToolPath(t), "build", "-o",
     69 		filepath.Join(tmpdir, "output"))
     70 
     71 	var env []string
     72 	for _, v := range os.Environ() {
     73 		if !strings.HasPrefix(v, "GOARCH=") {
     74 			env = append(env, v)
     75 		}
     76 	}
     77 	cmd.Env = append(env, "GOARCH=amd64")
     78 	out, err := cmd.CombinedOutput()
     79 	if err != nil {
     80 		t.Fatalf("error %s output %s", err, out)
     81 	}
     82 	cmd2 := exec.Command(
     83 		testenv.GoToolPath(t), "tool", "objdump", "-s", "testASM",
     84 		filepath.Join(tmpdir, "output"))
     85 	cmd2.Env = cmd.Env
     86 	objout, err := cmd2.CombinedOutput()
     87 	if err != nil {
     88 		t.Fatalf("error %s output %s", err, objout)
     89 	}
     90 	err = os.Chdir(cwd)
     91 	if err != nil {
     92 		t.Fatal(err)
     93 	}
     94 	return objout
     95 }
     96 
     97 func TestVexPCrelative(t *testing.T) {
     98 	testenv.MustHaveGoBuild(t)
     99 	objout := objdumpOutput(t)
    100 	data := bytes.Split(objout, []byte("\n"))
    101 	for idx := len(data) - 1; idx >= 0; idx-- {
    102 		// OBJDUMP doesn't know about VMOVDQU,
    103 		// so instead of checking that it was assembled correctly,
    104 		// check that RET wasn't overwritten.
    105 		if bytes.Index(data[idx], []byte("RET")) != -1 {
    106 			return
    107 		}
    108 	}
    109 	t.Fatal("RET was overwritten")
    110 }
    111