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  	"os"
    12  	"path/filepath"
    13  	"testing"
    14  )
    15  
    16  const asmData = `
    17  GLOBL zeros<>(SB),8,$64
    18  TEXT ·testASM(SB),4,$0
    19  VMOVUPS zeros<>(SB), %s // PC relative relocation is off by 1, for Y8-Y15, Z8-15 and Z24-Z31
    20  RET
    21  `
    22  
    23  const goData = `
    24  package main
    25  
    26  func testASM()
    27  
    28  func main() {
    29  	testASM()
    30  }
    31  `
    32  
    33  func objdumpOutput(t *testing.T, mname, source string) []byte {
    34  	tmpdir := t.TempDir()
    35  	err := os.WriteFile(filepath.Join(tmpdir, "go.mod"), []byte(fmt.Sprintf("module %s\n", mname)), 0666)
    36  	if err != nil {
    37  		t.Fatal(err)
    38  	}
    39  	tmpfile, err := os.Create(filepath.Join(tmpdir, "input.s"))
    40  	if err != nil {
    41  		t.Fatal(err)
    42  	}
    43  	defer tmpfile.Close()
    44  	_, err = tmpfile.WriteString(source)
    45  	if err != nil {
    46  		t.Fatal(err)
    47  	}
    48  	tmpfile2, err := os.Create(filepath.Join(tmpdir, "input.go"))
    49  	if err != nil {
    50  		t.Fatal(err)
    51  	}
    52  	defer tmpfile2.Close()
    53  	_, err = tmpfile2.WriteString(goData)
    54  	if err != nil {
    55  		t.Fatal(err)
    56  	}
    57  
    58  	cmd := testenv.Command(t,
    59  		testenv.GoToolPath(t), "build", "-o",
    60  		filepath.Join(tmpdir, "output"))
    61  
    62  	cmd.Env = append(os.Environ(),
    63  		"GOARCH=amd64", "GOOS=linux", "GOPATH="+filepath.Join(tmpdir, "_gopath"))
    64  	cmd.Dir = tmpdir
    65  
    66  	out, err := cmd.CombinedOutput()
    67  	if err != nil {
    68  		t.Fatalf("error %s output %s", err, out)
    69  	}
    70  	cmd2 := testenv.Command(t,
    71  		testenv.GoToolPath(t), "tool", "objdump", "-s", "testASM",
    72  		filepath.Join(tmpdir, "output"))
    73  	cmd2.Env = cmd.Env
    74  	cmd2.Dir = tmpdir
    75  	objout, err := cmd2.CombinedOutput()
    76  	if err != nil {
    77  		t.Fatalf("error %s output %s", err, objout)
    78  	}
    79  
    80  	return objout
    81  }
    82  
    83  func TestVexEvexPCrelative(t *testing.T) {
    84  	testenv.MustHaveGoBuild(t)
    85  LOOP:
    86  	for _, reg := range []string{"Y0", "Y8", "Z0", "Z8", "Z16", "Z24"} {
    87  		asm := fmt.Sprintf(asmData, reg)
    88  		objout := objdumpOutput(t, "pcrelative", asm)
    89  		data := bytes.Split(objout, []byte("\n"))
    90  		for idx := len(data) - 1; idx >= 0; idx-- {
    91  			// check that RET wasn't overwritten.
    92  			if bytes.Contains(data[idx], []byte("RET")) {
    93  				if testing.Short() {
    94  					break LOOP
    95  				}
    96  				continue LOOP
    97  			}
    98  		}
    99  		t.Errorf("VMOVUPS zeros<>(SB), %s overwrote RET", reg)
   100  	}
   101  }
   102  

View as plain text