Commit 1e3c57c2 authored by Cherry Zhang's avatar Cherry Zhang

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: 's avatarDavid Chase <drchase@google.com>
parent cd66c386
......@@ -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()
......
// 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")
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment