mirror of
https://github.com/golang/go.git
synced 2025-05-30 19:52:53 +00:00
cmd/internal/obj/arm64: fix branch too far for CBZ (and like)
The assembler backend fixes too-far conditional branches, but only for BEQ and like. Add a case for CBZ and like. Fixes #17925. Change-Id: Ie516e6c5ca165b582367283a0110f7081e00c214 Reviewed-on: https://go-review.googlesource.com/33304 Run-TryBot: Cherry Zhang <cherryyz@google.com> Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
parent
cd66c38619
commit
1e3c57c2cc
@ -601,7 +601,7 @@ func span7(ctxt *obj.Link, cursym *obj.LSym) {
|
||||
o = oplook(ctxt, p)
|
||||
|
||||
/* very large branches */
|
||||
if o.type_ == 7 && p.Pcond != nil {
|
||||
if (o.type_ == 7 || o.type_ == 39) && p.Pcond != nil { // 7: BEQ and like, 39: CBZ and like
|
||||
otxt := p.Pcond.Pc - c
|
||||
if otxt <= -(1<<18)+10 || otxt >= (1<<18)-10 {
|
||||
q := ctxt.NewProg()
|
||||
|
62
src/cmd/internal/obj/arm64/asm_test.go
Normal file
62
src/cmd/internal/obj/arm64/asm_test.go
Normal file
@ -0,0 +1,62 @@
|
||||
// Copyright 2016 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 arm64
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"internal/testenv"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// TestLarge generates a very large file to verify that large
|
||||
// program builds successfully, in particular, too-far
|
||||
// conditional branches are fixed.
|
||||
func TestLarge(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("Skip in short mode")
|
||||
}
|
||||
testenv.MustHaveGoBuild(t)
|
||||
|
||||
dir, err := ioutil.TempDir("", "testlarge")
|
||||
if err != nil {
|
||||
t.Fatalf("could not create directory: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
// generate a very large function
|
||||
buf := bytes.NewBuffer(make([]byte, 0, 7000000))
|
||||
gen(buf)
|
||||
|
||||
tmpfile := filepath.Join(dir, "x.s")
|
||||
err = ioutil.WriteFile(tmpfile, buf.Bytes(), 0644)
|
||||
if err != nil {
|
||||
t.Fatalf("can't write output: %v\n", err)
|
||||
}
|
||||
|
||||
// build generated file
|
||||
cmd := exec.Command(testenv.GoToolPath(t), "tool", "asm", "-o", filepath.Join(dir, "x.o"), tmpfile)
|
||||
cmd.Env = []string{"GOARCH=arm64", "GOOS=linux"}
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Errorf("Build failed: %v, output: %s", err, out)
|
||||
}
|
||||
}
|
||||
|
||||
// gen generates a very large program, with a very far conditional branch.
|
||||
func gen(buf *bytes.Buffer) {
|
||||
fmt.Fprintln(buf, "TEXT f(SB),0,$0-0")
|
||||
fmt.Fprintln(buf, "CBZ R0, label")
|
||||
fmt.Fprintln(buf, "BEQ label")
|
||||
for i := 0; i < 1<<19; i++ {
|
||||
fmt.Fprintln(buf, "MOVD R0, R1")
|
||||
}
|
||||
fmt.Fprintln(buf, "label:")
|
||||
fmt.Fprintln(buf, "RET")
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user