golang/go

cmd/compile: internal compiler error: panic during lower

ALTree opened this issue · 2 comments

$ gotip version
go version devel +944a9c7a4f Thu Dec 13 06:33:18 2018 +0000 windows/amd64

The following program

package p

func f() {
        var s string
        var p, q bool
        s = "a"
        for p {
                p = false == (true != q)
                s = ""
        }
        _ = s == "bbb"
}

crashes the tip compiler with:

$ gotip build crash.go
# command-line-arguments
.\crash.go:11:8: internal compiler error: 'f': panic during lower while compiling f:

runtime error: index out of range

goroutine 21 [running]:
cmd/compile/internal/ssa.Compile.func1(0xc0003ef108, 0xc0000be6e0)
        go/src/cmd/compile/internal/ssa/compile.go:45 +0xac
panic(0xd7d140, 0x15551c0)
        go/src/runtime/panic.go:513 +0x1c5
cmd/compile/internal/ssa.read8(...)
        go/src/cmd/compile/internal/ssa/rewrite.go:1140
cmd/compile/internal/ssa.rewriteValueAMD64_OpAMD64MOVBload_0(0xc000395378, 0xc000395a01)
        go/src/cmd/compile/internal/ssa/rewriteAMD64.go:12599 +0x95b
cmd/compile/internal/ssa.rewriteValueAMD64(0xc000395378, 0x0)
        go/src/cmd/compile/internal/ssa/rewriteAMD64.go:255 +0x2b41
cmd/compile/internal/ssa.applyRewrite(0xc0000be6e0, 0xe10e00, 0xe10e68)
        go/src/cmd/compile/internal/ssa/rewrite.go:80 +0x34d
cmd/compile/internal/ssa.lower(0xc0000be6e0)
        go/src/cmd/compile/internal/ssa/lower.go:10 +0x4d
cmd/compile/internal/ssa.Compile(0xc0000be6e0)
        go/src/cmd/compile/internal/ssa/compile.go:90 +0x473
cmd/compile/internal/gc.buildssa(0xc0000be2c0, 0x1, 0x0)
        go/src/cmd/compile/internal/gc/ssa.go:233 +0xbdc
cmd/compile/internal/gc.compileSSA(0xc0000be2c0, 0x1)
        go/src/cmd/compile/internal/gc/pgen.go:280 +0x54
cmd/compile/internal/gc.compileFunctions.func2(0xc000341e60, 0xc000052ad0, 0x1)
        go/src/cmd/compile/internal/gc/pgen.go:345 +0x50
created by cmd/compile/internal/gc.compileFunctions
        go/src/cmd/compile/internal/gc/pgen.go:343 +0x12f

goroutine 21 [running]:
runtime/debug.Stack(0xf81b00, 0xc00007a008, 0x0)
        go/src/runtime/debug/stack.go:24 +0xa4
cmd/compile/internal/gc.Fatalf(0xc000064600, 0x32, 0xc000092640, 0x5, 0x5)
        go/src/cmd/compile/internal/gc/subr.go:190 +0x292
cmd/compile/internal/gc.(*ssafn).Fatalf(0xc000067fb0, 0xb08000000002, 0xe05637, 0x2c, 0xc0003113c0, 0x4, 0x4)
        go/src/cmd/compile/internal/gc/ssa.go:5830 +0x1b7
cmd/compile/internal/ssa.(*Func).Fatalf(...)
        go/src/cmd/compile/internal/ssa/func.go:577
cmd/compile/internal/ssa.Compile.func1(0xc0003ef108, 0xc0000be6e0)
        go/src/cmd/compile/internal/ssa/compile.go:47 +0x225
panic(0xd7d140, 0x15551c0)
        go/src/runtime/panic.go:513 +0x1c5
cmd/compile/internal/ssa.read8(...)
        go/src/cmd/compile/internal/ssa/rewrite.go:1140
cmd/compile/internal/ssa.rewriteValueAMD64_OpAMD64MOVBload_0(0xc000395378, 0xc000395a01)
        go/src/cmd/compile/internal/ssa/rewriteAMD64.go:12599 +0x95b
cmd/compile/internal/ssa.rewriteValueAMD64(0xc000395378, 0x0)
        go/src/cmd/compile/internal/ssa/rewriteAMD64.go:255 +0x2b41
cmd/compile/internal/ssa.applyRewrite(0xc0000be6e0, 0xe10e00, 0xe10e68)
        go/src/cmd/compile/internal/ssa/rewrite.go:80 +0x34d
cmd/compile/internal/ssa.lower(0xc0000be6e0)
        go/src/cmd/compile/internal/ssa/lower.go:10 +0x4d
cmd/compile/internal/ssa.Compile(0xc0000be6e0)
        go/src/cmd/compile/internal/ssa/compile.go:90 +0x473
cmd/compile/internal/gc.buildssa(0xc0000be2c0, 0x1, 0x0)
        go/src/cmd/compile/internal/gc/ssa.go:233 +0xbdc
cmd/compile/internal/gc.compileSSA(0xc0000be2c0, 0x1)
        go/src/cmd/compile/internal/gc/pgen.go:280 +0x54
cmd/compile/internal/gc.compileFunctions.func2(0xc000341e60, 0xc000052ad0, 0x1)
        go/src/cmd/compile/internal/gc/pgen.go:345 +0x50
created by cmd/compile/internal/gc.compileFunctions
        go/src/cmd/compile/internal/gc/pgen.go:343 +0x12f

It compiles fine on go1.11.

This is a weird dead code situation. Basically we have

   s := "a"
   if len(s) == 3 {
      load s[0], s[1], and s[2]
   }

The compiler realizes that the branch is never taken. And it constant folds "a" into all occurrences of s. But the dead code load "a"[1] is still floating around in the SSA form - it hasn't been removed yet. When the rewrite engine tries to evaluate "a"[1] at compile time, it barfs.

The easy fix is to just check for and ignore out-of-bounds errors in the rewrite rule. That bounds check was a nice sanity check, but dead code is insane.

A bigger fix is another deadcode pass before lowering. I don't want to go there for this issue.

Change https://golang.org/cl/154057 mentions this issue: cmd/compile: ignore out-of-bounds reads from readonly constants