Source file src/cmd/internal/obj/x86/pcrelative_test.go

     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  	"fmt"
    10  	"internal/testenv"
    11  	"io/ioutil"
    12  	"os"
    13  	"os/exec"
    14  	"path/filepath"
    15  	"testing"
    16  )
    17  
    18  const asmData = `
    19  GLOBL zeros<>(SB),8,$64
    20  TEXT ·testASM(SB),4,$0
    21  VMOVUPS zeros<>(SB), %s // PC relative relocation is off by 1, for Y8-Y15, Z8-15 and Z24-Z31
    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, mname, source string) []byte {
    36  	tmpdir, err := ioutil.TempDir("", mname)
    37  	if err != nil {
    38  		t.Fatal(err)
    39  	}
    40  	defer os.RemoveAll(tmpdir)
    41  	err = ioutil.WriteFile(filepath.Join(tmpdir, "go.mod"), []byte(fmt.Sprintf("module %s\n", mname)), 0666)
    42  	if err != nil {
    43  		t.Fatal(err)
    44  	}
    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(source)
    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  
    64  	cmd := exec.Command(
    65  		testenv.GoToolPath(t), "build", "-o",
    66  		filepath.Join(tmpdir, "output"))
    67  
    68  	cmd.Env = append(os.Environ(),
    69  		"GOARCH=amd64", "GOOS=linux", "GOPATH="+filepath.Join(tmpdir, "_gopath"))
    70  	cmd.Dir = tmpdir
    71  
    72  	out, err := cmd.CombinedOutput()
    73  	if err != nil {
    74  		t.Fatalf("error %s output %s", err, out)
    75  	}
    76  	cmd2 := exec.Command(
    77  		testenv.GoToolPath(t), "tool", "objdump", "-s", "testASM",
    78  		filepath.Join(tmpdir, "output"))
    79  	cmd2.Env = cmd.Env
    80  	cmd2.Dir = tmpdir
    81  	objout, err := cmd2.CombinedOutput()
    82  	if err != nil {
    83  		t.Fatalf("error %s output %s", err, objout)
    84  	}
    85  
    86  	return objout
    87  }
    88  
    89  func TestVexEvexPCrelative(t *testing.T) {
    90  	testenv.MustHaveGoBuild(t)
    91  LOOP:
    92  	for _, reg := range []string{"Y0", "Y8", "Z0", "Z8", "Z16", "Z24"} {
    93  		asm := fmt.Sprintf(asmData, reg)
    94  		objout := objdumpOutput(t, "pcrelative", asm)
    95  		data := bytes.Split(objout, []byte("\n"))
    96  		for idx := len(data) - 1; idx >= 0; idx-- {
    97  			// check that RET wasn't overwritten.
    98  			if bytes.Index(data[idx], []byte("RET")) != -1 {
    99  				if testing.Short() {
   100  					break LOOP
   101  				}
   102  				continue LOOP
   103  			}
   104  		}
   105  		t.Errorf("VMOVUPS zeros<>(SB), %s overwrote RET", reg)
   106  	}
   107  }
   108  

View as plain text