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, err := os.MkdirTemp("", mname)
    35  	if err != nil {
    36  		t.Fatal(err)
    37  	}
    38  	defer os.RemoveAll(tmpdir)
    39  	err = os.WriteFile(filepath.Join(tmpdir, "go.mod"), []byte(fmt.Sprintf("module %s\n", mname)), 0666)
    40  	if err != nil {
    41  		t.Fatal(err)
    42  	}
    43  	tmpfile, err := os.Create(filepath.Join(tmpdir, "input.s"))
    44  	if err != nil {
    45  		t.Fatal(err)
    46  	}
    47  	defer tmpfile.Close()
    48  	_, err = tmpfile.WriteString(source)
    49  	if err != nil {
    50  		t.Fatal(err)
    51  	}
    52  	tmpfile2, err := os.Create(filepath.Join(tmpdir, "input.go"))
    53  	if err != nil {
    54  		t.Fatal(err)
    55  	}
    56  	defer tmpfile2.Close()
    57  	_, err = tmpfile2.WriteString(goData)
    58  	if err != nil {
    59  		t.Fatal(err)
    60  	}
    61  
    62  	cmd := testenv.Command(t,
    63  		testenv.GoToolPath(t), "build", "-o",
    64  		filepath.Join(tmpdir, "output"))
    65  
    66  	cmd.Env = append(os.Environ(),
    67  		"GOARCH=amd64", "GOOS=linux", "GOPATH="+filepath.Join(tmpdir, "_gopath"))
    68  	cmd.Dir = tmpdir
    69  
    70  	out, err := cmd.CombinedOutput()
    71  	if err != nil {
    72  		t.Fatalf("error %s output %s", err, out)
    73  	}
    74  	cmd2 := testenv.Command(t,
    75  		testenv.GoToolPath(t), "tool", "objdump", "-s", "testASM",
    76  		filepath.Join(tmpdir, "output"))
    77  	cmd2.Env = cmd.Env
    78  	cmd2.Dir = tmpdir
    79  	objout, err := cmd2.CombinedOutput()
    80  	if err != nil {
    81  		t.Fatalf("error %s output %s", err, objout)
    82  	}
    83  
    84  	return objout
    85  }
    86  
    87  func TestVexEvexPCrelative(t *testing.T) {
    88  	testenv.MustHaveGoBuild(t)
    89  LOOP:
    90  	for _, reg := range []string{"Y0", "Y8", "Z0", "Z8", "Z16", "Z24"} {
    91  		asm := fmt.Sprintf(asmData, reg)
    92  		objout := objdumpOutput(t, "pcrelative", asm)
    93  		data := bytes.Split(objout, []byte("\n"))
    94  		for idx := len(data) - 1; idx >= 0; idx-- {
    95  			// check that RET wasn't overwritten.
    96  			if bytes.Contains(data[idx], []byte("RET")) {
    97  				if testing.Short() {
    98  					break LOOP
    99  				}
   100  				continue LOOP
   101  			}
   102  		}
   103  		t.Errorf("VMOVUPS zeros<>(SB), %s overwrote RET", reg)
   104  	}
   105  }
   106  

View as plain text