Skip to content

Commit

Permalink
cmd/internal/obj/ppc64: fix PCALIGN on ppc64le
Browse files Browse the repository at this point in the history
This fixes a potential issue with the previous implementation
of PCALIGN on ppc64. Previously PCALIGN was processed inside of
asmout and indicated the padding size by setting the value in
the optab, changing it back after the alignment instructions
were added. Now PCALIGN is processed outside of asmout, and optab
is not changed.

Change-Id: I8b0093a0e2b7e06176af27e05150d04ae2c55d60
Reviewed-on: https://go-review.googlesource.com/c/go/+/225198
Run-TryBot: Lynn Boger <[email protected]>
Reviewed-by: Cherry Zhang <[email protected]>
Reviewed-by: Carlos Eduardo Seo <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
  • Loading branch information
laboger committed Mar 24, 2020
1 parent 191118a commit 60a964e
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 22 deletions.
34 changes: 12 additions & 22 deletions src/cmd/internal/obj/ppc64/asm9.go
Original file line number Diff line number Diff line change
Expand Up @@ -627,8 +627,6 @@ func addpad(pc, a int64, ctxt *obj.Link) int {
}
case 16:
switch pc % 16 {
// When currently aligned to 4, avoid 3 NOPs and set to
// 8 byte alignment which should still help.
case 4, 12:
return 4
case 8:
Expand Down Expand Up @@ -758,15 +756,20 @@ func span9(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
if int(o.size) > 4*len(out) {
log.Fatalf("out array in span9 is too small, need at least %d for %v", o.size/4, p)
}
origsize := o.size
c.asmout(p, o, out[:])
if origsize == 0 && o.size > 0 {
for i = 0; i < int32(o.size/4); i++ {
c.ctxt.Arch.ByteOrder.PutUint32(bp, out[0])
bp = bp[4:]
// asmout is not set up to add large amounts of padding
if o.type_ == 0 && p.As == obj.APCALIGN {
pad := LOP_RRR(OP_OR, REGZERO, REGZERO, REGZERO)
aln := c.vregoff(&p.From)
v := addpad(p.Pc, aln, c.ctxt)
if v > 0 {
// Same padding instruction for all
for i = 0; i < int32(v/4); i++ {
c.ctxt.Arch.ByteOrder.PutUint32(bp, pad)
bp = bp[4:]
}
}
o.size = origsize
} else {
c.asmout(p, o, out[:])
for i = 0; i < int32(o.size/4); i++ {
c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
bp = bp[4:]
Expand Down Expand Up @@ -2387,19 +2390,6 @@ func (c *ctxt9) asmout(p *obj.Prog, o *Optab, out []uint32) {
prasm(p)

case 0: /* pseudo ops */
if p.As == obj.APCALIGN {
aln := c.vregoff(&p.From)
v := addpad(p.Pc, aln, c.ctxt)
if v > 0 {
for i := 0; i < 6; i++ {
out[i] = uint32(0)
}
o.size = int8(v)
out[0] = LOP_RRR(OP_OR, REGZERO, REGZERO, REGZERO)
return
}
o.size = 0
}
break

case 1: /* mov r1,r2 ==> OR Rs,Rs,Ra */
Expand Down
81 changes: 81 additions & 0 deletions src/cmd/internal/obj/ppc64/asm_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package ppc64

import (
"internal/testenv"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
)

var invalidPCAlignSrc = `
TEXT test(SB),0,$0-0
ADD $2, R3
PCALIGN $32
RET
`
var validPCAlignSrc = `
TEXT test(SB),0,$0-0
ADD $2, R3
PCALIGN $16
MOVD $8, R4
ADD $8, R4
PCALIGN $16
ADD $8, R4
PCALIGN $8
ADD $4, R6
PCALIGN $16
ADD R2, R3, R4
RET
`

// TestPCalign generates two asm files containing the
// PCALIGN directive, to verify correct values are and
// accepted, and incorrect values are flagged in error.
func TestPCalign(t *testing.T) {
testenv.MustHaveGoBuild(t)

dir, err := ioutil.TempDir("", "testpcalign")
if err != nil {
t.Fatalf("could not create directory: %v", err)
}
defer os.RemoveAll(dir)

// generate a test with valid uses of PCALIGN

tmpfile := filepath.Join(dir, "x.s")
err = ioutil.WriteFile(tmpfile, []byte(validPCAlignSrc), 0644)
if err != nil {
t.Fatalf("can't write output: %v\n", err)
}

// build generated file without errors and assemble it
cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), "-S", tmpfile)
cmd.Env = append(os.Environ(), "GOARCH=ppc64le", "GOOS=linux")
out, err := cmd.CombinedOutput()
if err != nil {
t.Errorf("Build failed: %v, output: %s", err, out)
}

// generate a test with invalid use of PCALIGN

tmpfile = filepath.Join(dir, "xi.s")
err = ioutil.WriteFile(tmpfile, []byte(invalidPCAlignSrc), 0644)
if err != nil {
t.Fatalf("can't write output: %v\n", err)
}

// build test with errors and check for messages
cmd = exec.Command(testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "xi.o"), "-S", tmpfile)
cmd.Env = append(os.Environ(), "GOARCH=ppc64le", "GOOS=linux")
out, err = cmd.CombinedOutput()
if !strings.Contains(string(out), "Unexpected alignment") {
t.Errorf("Invalid alignment not detected for PCALIGN\n")
}
}

0 comments on commit 60a964e

Please sign in to comment.