cmd/compile: panic: branch too far on arm64
ALTree opened this issue · 6 comments
$ go version
go version devel +549cb18a91 Sat Feb 17 04:38:14 2018 +0000 linux/amd64
The program at the end of this report crashes the tip compiler when built for arm64 with optimizations disabled, as GOARCH=arm64 go build -gcflags -N crash.go
, with the following error:
# command-line-arguments
panic: branch too far
goroutine 8 [running]:
cmd/internal/obj/arm64.(*ctxt7).brdist(0xc00098ddc0, 0xc00014bae8, 0x0, 0xe, 0x2, 0xc0f94017e0)
go/src/cmd/internal/obj/arm64/asm7.go:4672 +0x32a
cmd/internal/obj/arm64.(*ctxt7).asmout(0xc00098ddc0, 0xc00014bae8, 0xf9ec7e, 0xc00098dd50, 0x6, 0x6)
go/src/cmd/internal/obj/arm64/asm7.go:2884 +0x5ab2
cmd/internal/obj/arm64.span7(0xc00000e240, 0xc0005a4070, 0xc00004e480)
go/src/cmd/internal/obj/arm64/asm7.go:787 +0x951
cmd/internal/obj.Flushplist(0xc00000e240, 0xc00098df08, 0xc00004e480, 0x7ffdb24382fe, 0x16)
go/src/cmd/internal/obj/plist.go:107 +0x6ca
cmd/compile/internal/gc.(*Progs).Flush(0xc000081f40)
go/src/cmd/compile/internal/gc/gsubr.go:87 +0xc1
cmd/compile/internal/gc.compileSSA(0xc000001200, 0x1)
go/src/cmd/compile/internal/gc/pgen.go:247 +0x188
cmd/compile/internal/gc.compileFunctions.func2(0xc00059ac60, 0xc0005284a0, 0x1)
go/src/cmd/compile/internal/gc/pgen.go:288 +0x49
created by cmd/compile/internal/gc.compileFunctions
go/src/cmd/compile/internal/gc/pgen.go:286 +0x11c
go tool compile
says:
crash.go:62:3: branch too far 0x2000 vs 0x2000 [0x0]
00228 (crash.go:10) TBZ $63, R0, 32996
32996 (crash.go:10) JMP 26972
The issue is not present in 1.10, and it was introduced in commit cdd9616 (cmd/compile: generate tbz/tbnz when comparing against zero on arm64).
Apologies for the reproducer length. The program was generated by a fuzzer and deleting any line makes the crash go away.
package p
func fun0() {
var B0, B1, B2, B3, B4 bool
var S0, S1 string
var I0, I1, I2, I3, I4 int
for true {
var B5, B6 bool
for !(S0 >= "ccc" || !true || I4 == I3) {
var I5, I6 int
var B7, B8 bool
switch S0[8:10] + (S0) + (S0[1:12]) + (S1[2:15] + S0[5:24]) + (S0 + "ffffff") {
case "bb" + S0[0:20] + S1 + (S1 + S1[8:23] + (S1[2:17])) + (S1[1:15] + S0[7:21] + (S0[6:11] + S1 + ("dddd" + S1[6:10]))):
B3 = S0[8:23]+S0[0:23]+("dddd"+S1[7:21]+(S0[0:21]+S0[3:12]))+(S1+S1+(S1[0:16]+S1)) != "ffffff"+S1[1:18] || I2 < I6
I2 = 50 + 70 + len([]int{len("eeeee")})
S1 = S1[2:15] + S1 + (S1 + S1) + ("a" + "a")
S1 = S0 + S0[0:10] + S0 + S0 + "dddd"
B1 = I5+I6 > len([]string{S0[4:15] + S1, S0[1:8] + "dddd" + (S0[0:14] + S1), S0 + "ccc" + (S1 + "bb")})
S0 = "eeeee" + S1[7:15] + ("bb" + S0 + (S0[7:22] + "a" + ("ccc" + S0[7:16] + (S0 + S0)) + (S1[2:8] + S1))) + (S1[8:14] + S1[7:19])
}
for len([]string{S1[3:11] + S1[0:15] + ("bb" + S0) + ("a" + S0), S1[2:18] + S1 + (S1[7:15] + S1) + (S1 + "eeeee") + (S0 + S1[8:21])}) >= len([]string{S0[0:14] + "eeeee"})+(I0+35+len(S0[2:24])) {
var S2 string
I0 = len(S1)
B3 = false && B2
B8 = S1 > S1
B8 = "dddd" < S1[7:17]
S1 = S0 + S1 + ("dddd" + S2[6:12] + (S2 + "ccc") + ("a" + S1[0:13] + (S1[8:15] + S2[0:14] + (S2[6:22] + S2)))) + (S2[6:10] + "eeeee" + (S2[3:22] + S0[2:22] + (S0[7:13] + S2[2:20])) + (S1 + S0[1:8] + (S0 + S1[6:13])) + (S0[0:12] + S0[2:14]) + (S0 + S0))
}
switch len([]bool{I4 > 25}) <= I1+len([]bool{}) || (B8 && B2) != B0 {
case true && I6 < I0:
S0 = S1[7:19] + S1[4:20] + (S0 + S1) + (S0[0:24] + S1) + ("eeeee" + S0 + ("a" + "ffffff" + (S1 + S0) + (S0[0:13] + S0[6:19] + (S1[7:11] + "ccc")) + (S1 + S1[1:15] + (S0[3:9] + "dddd") + (S1 + S1[6:22])) + (S0 + "ccc")) + (S0 + S0 + ("eeeee" + S1)))
B1 = S1[7:8]+S1+(S1+S1[7:10]) == "eeeee"+S0
I0 = len([]string{S0[6:9] + S0[8:14] + ("a" + "a"), S1 + S0 + (S0 + S0) + (S0 + S0 + (S0 + "bb" + ("bb" + S1)) + ("bb" + S1 + (S0[7:19] + S0[5:11])) + (S0 + S0[3:19] + (S0[6:21] + "bb" + (S1 + "a")) + (S1[0:15] + S0 + (S0[7:24] + S0 + ("bb" + "ffffff") + (S0 + "bb"))) + (S1[4:24] + S1[6:15] + ("bb" + S1[7:17])))), "eeeee" + S1 + (S0 + S1)})
I4 = len(S1)
S0 = "ffffff" + S1[8:23] + (S0[7:17] + "eeeee" + (S1 + S0[2:9]) + (S1[1:20] + S1) + (S0[6:17] + "bb")) + (S0[7:20] + S1[1:19] + (S1[8:9] + S0) + ("a" + S1[0:14])) + (S0[5:21] + S0 + (S1[8:17] + S0[5:9])) + ("ffffff" + S0 + (S0 + S0[4:16])) + (S0 + "eeeee")
B3 = B1 && B0
I5 = len([]bool{})
}
switch S0[0:9] + S0 + (S0[8:13] + "bb" + ("dddd" + S1 + (S0[6:23] + "eeeee") + (S0[7:9] + "ffffff")) + ("bb" + S0[3:23])) + (S1[0:21] + "dddd" + (S0 + S1 + (S1 + S0[3:15]))) {
case S1[6:8] + S1:
S1 = "ffffff" + S0 + ("ccc" + S1[2:12] + (S0 + S1)) + (S0 + "a") + (S0 + S0 + (S0 + "eeeee")) + (S1 + S1[2:10] + (S0 + S0 + (S1[6:18] + "eeeee") + (S0[5:16] + S1 + (S1[0:24] + "a")))) + ("a" + S0 + (S1[7:19] + "a" + (S0[2:20] + S1[4:22] + (S1 + S1[2:14])) + (S0 + S1[6:20] + (S0[7:13] + S0 + (S1 + "ccc" + ("ccc" + S1 + (S0 + S0))))) + (S1 + "ccc")))
S0 = S0[6:14] + S1 + (S0[5:18] + S0) + (S0 + S1[7:23] + (S1 + "a" + (S0[2:19] + S1) + (S1[5:11] + "eeeee" + ("ccc" + "bb")))) + ("bb" + S0[5:23] + (S0 + S0))
B8 = I6 != I3
S0 = S0 + S1 + ("ffffff" + S1 + (S0 + S0[2:22]))
I6 = I3 + I3 - len([]int{I0 - 57, -19, len([]int{+89 + (len(S1[6:10]) - (I6 - I1)), len("a")})})
I6 = len("ccc") - (I0 - I3 + (2 + I1 + len(S1[8:21]) - (len([]int{len([]int{len([]bool{B3 != B6, false || true}), I3 - 0, len(S0[5:13]), len([]bool{S1 != S0, I5 < I5, 81 > I1})}), -I0}) - len([]int{len([]string{S0 + S0}), len([]bool{I1 >= I5 || !B7, B4 && B5}), len(S0[0:12])}))))
B8 = !(-(+18 + (88 - I1)) <= 16-I6) && (!(26 <= I4) || S1+S0+("a"+S1+("ccc"+S0)) > S0+"ffffff"+("eeeee"+S1)+(S1[5:24]+S1[7:19]+(S0+S0[2:22]+(S0+"eeeee"+(S0+S0)+(S1[5:9]+S0[2:13]))+(S1+S0))))
}
I4 = len([]int{len([]string{S1 + S1, "bb" + S1 + (S0[2:20] + S0[0:15]) + (S0 + "dddd" + (S0[1:12] + S0) + (S0 + S0[2:14]) + (S0 + "eeeee"))}) + len([]int{}), len("ccc")}) + len("eeeee")
B0 = !(((B5 || B7) && "dddd" <= "dddd" || S1[7:8]+S1[1:24]+(S0+S1+("ffffff"+"dddd")+("ccc"+S1))+(S1[2:19]+"ffffff")+(S1[8:21]+S1[8:21]+("a"+S1[5:9]+("ccc"+"ffffff"))) <= S1+"dddd") && S0[7:23]+S1[8:9]+("dddd"+"ffffff") == S0[3:18]+S1) != (S0[5:15]+S1 > S1[4:23]+S1[5:9]+(S0[3:12]+S0[0:16]) && (!(I0 >= 30) && "eeeee"+"eeeee" == "bb"+S1))
}
var S2, S3 string
switch len([]string{}) {
case len(S0[8:24]):
S1 = "ffffff" + S1[0:14] + (S1[2:23] + "eeeee") + (S3 + S1 + ("ccc" + S0) + ("bb" + S0[5:17]) + (S0 + S2)) + (S1 + S1 + (S2[8:13] + S3 + ("ffffff" + S3) + (S3 + S2 + (S0 + S3[6:8] + (S2[4:24] + S3) + (S3[2:19] + S1[5:15])))))
S2 = S2[7:18] + S1[4:21]
S2 = S2 + "bb" + (S3[1:10] + "eeeee" + (S3[1:23] + S1 + (S0[1:23] + S1) + (S2[5:20] + S1[2:18] + (S2[3:22] + "dddd") + (S0 + S2[4:14] + (S1 + S0[8:20]))) + (S3 + S0)))
S1 = S1 + S2[6:24] + ("eeeee" + S3 + (S3 + S1 + (S0 + S3[4:8]) + (S3 + S2[8:14])) + (S1[4:8] + S3 + (S1 + S3[1:23] + (S2 + S3)) + ("a" + S0[7:21])))
}
for I4+len([]string{"bb" + S0}) != -((I1+I4)+len([]bool{!B2, !B5, "bb"+S1 >= S1[4:16]+"ffffff"})) || 95 > I1 {
S0 = S0[1:24] + S3[1:10] + ("ccc" + S2[3:9] + ("ffffff" + S0)) + ("a" + S0[2:8]) + (S2[4:14] + "a" + (S2 + S0[6:12]))
}
}
}
Oh, I found another, much bigger reproducer that causes the crash even without -N
.
prog5139950150760489618.go:3568:37: branch too far 0x21aa vs 0x2000 [0x0]
04048 (prog5139950150760489618.go:732) TBZ $63, R0, 38520
38520 (prog5139950150760489618.go:735) MOVD $""..autotmp_4462-25600(SP), R17
So this has nothing to do with optimizations, it just happen to be easier to trigger when optimizations are disabled.
Change https://golang.org/cl/94902 mentions this issue: cmd/internal/obj/arm64: fix branch-too-far with TBZ like instructions
btw. I see this issue while compiling influxdb master using 1.10 on aarch64 and the patch above fixes the problem. So it might be a candidate for backport to 1.10 release.
| # github.com/influxdata/influxdb/tests
| panic: branch too far
|
| goroutine 70 [running]:
| cmd/internal/obj/arm64.(*ctxt7).brdist(0xc421e63dc0, 0xc4202fafa0, 0x0, 0xe, 0x2, 0xf943afe0)
| /mnt/a/zonit/build/tmp/work/x86_64-linux/go-cross-aarch64/1.10-r0/recipe-sysroot-native/usr/lib/aarch64-bec-linux/go/s
rc/cmd/internal/obj/arm64/asm7.go:4616 +0x32a
| cmd/internal/obj/arm64.(*ctxt7).asmout(0xc421e63dc0, 0xc4202fafa0, 0xfa1922, 0xc421e63d50, 0x6, 0x6)
| /mnt/a/zonit/build/tmp/work/x86_64-linux/go-cross-aarch64/1.10-r0/recipe-sysroot-native/usr/lib/aarch64-bec-linux/go/s
rc/cmd/internal/obj/arm64/asm7.go:2855 +0xcf0
| cmd/internal/obj/arm64.span7(0xc42039e000, 0xc4217db650, 0xc421770250)
| /mnt/a/zonit/build/tmp/work/x86_64-linux/go-cross-aarch64/1.10-r0/recipe-sysroot-native/usr/lib/aarch64-bec-linux/go/s
rc/cmd/internal/obj/arm64/asm7.go:760 +0x951
| cmd/internal/obj.Flushplist(0xc42039e000, 0xc421e63f08, 0xc421770250, 0x7ffe8e8b440c, 0x24)
| /mnt/a/zonit/build/tmp/work/x86_64-linux/go-cross-aarch64/1.10-r0/recipe-sysroot-native/usr/lib/aarch64-bec-linux/go/s
rc/cmd/internal/obj/plist.go:107 +0x6ca
| cmd/compile/internal/gc.(*Progs).Flush(0xc421dd4e10)
| /mnt/a/zonit/build/tmp/work/x86_64-linux/go-cross-aarch64/1.10-r0/recipe-sysroot-native/usr/lib/aarch64-bec-linux/go/s
rc/cmd/compile/internal/gc/gsubr.go:87 +0xc1
| cmd/compile/internal/gc.compileSSA(0xc4200e3c80, 0x3)
| /mnt/a/zonit/build/tmp/work/x86_64-linux/go-cross-aarch64/1.10-r0/recipe-sysroot-native/usr/lib/aarch64-bec-linux/go/s
rc/cmd/compile/internal/gc/pgen.go:248 +0x188
| cmd/compile/internal/gc.compileFunctions.func2(0xc4217fd9e0, 0xc4217d2b90, 0x3)
| /mnt/a/zonit/build/tmp/work/x86_64-linux/go-cross-aarch64/1.10-r0/recipe-sysroot-native/usr/lib/aarch64-bec-linux/go/s
rc/cmd/compile/internal/gc/pgen.go:289 +0x49
| created by cmd/compile/internal/gc.compileFunctions
| /mnt/a/zonit/build/tmp/work/x86_64-linux/go-cross-aarch64/1.10-r0/recipe-sysroot-native/usr/lib/aarch64-bec-linux/go/s
rc/cmd/compile/internal/gc/pgen.go:287 +0x11c
@gopherbot please consider this for backport to 1.10. I just come cross this bug in my ios project with go version go1.10.3 darwin/amd64.
Follow golang version do not have this bug in my ios project:
go version go1.9.2 darwin/amd64
go version go1.9.7 darwin/amd64
Backport issue(s) opened: #25794 (for 1.10).
Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://golang.org/wiki/MinorReleases.
Change https://golang.org/cl/147057 mentions this issue: [release-branch.go1.10] cmd/internal/obj/arm64: fix branch-too-far with TBZ like instructions