Go: cmd/compile: invalid instruction: MOVL $11553462026240, AX

Created on 30 Sep 2020  ·  14Comments  ·  Source: golang/go

Filed on behalf of Jan Mercl (from a golang-dev thread).

What version of Go are you using (go version)?

$ go version
go version go1.15.2 linux/amd64

Does this issue reproduce with the latest release?

Yes.

What operating system and processor architecture are you using (go env)?

$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/jnml/.cache/go-build"
GOENV="/home/jnml/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/jnml/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/jnml"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/jnml/src/go.googlesource.com/go/goroot"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/jnml/src/go.googlesource.com/go/goroot/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build571607678=/tmp/go-build -gno-record-gcc-switches"

What did you do?

jnml@e5-1650:~/tmp/csmith$ cat main.go
package foo

import "modernc.org/libc"

func safe_div_func_int16_t_s_s(tls *libc.TLS, si1 int16, si2 int16) int16 {
        if (int32(si2) == 0) || ((int32(si1) == (-32767 - 1)) && (int32(si2) == (-1))) {
                return si1
        }
        return (int16(int32(si1) / int32(si2)))
}

func safe_lshift_func_int16_t_s_u(tls *libc.TLS, left int16, right uint32) int16 {
        if ((int32(left) < 0) || ((right) >= uint32(32))) || (int32(left) > (int32((32767)) >> (right))) {
                return left
        }
        return (int16(int32(left) << (right)))
}

func safe_sub_func_int32_t_s_s(tls *libc.TLS, si1 int32, si2 int32) int32 {
        if ((si1 ^ si2) & (((si1 ^ ((si1 ^ si2) & (^int32(libc.Int32FromInt32(2147483647))))) - si2) ^ si2)) < 0 {
                return si1
        }
        return (si1 - si2)
}

func safe_unary_minus_func_int64_t_s(tls *libc.TLS, si int64) int64 {
        if si == (-9223372036854775807 - int64(1)) {
                return si
        }
        return -si
}

func safe_sub_func_uint16_t_u_u(tls *libc.TLS, ui1 uint16, ui2 uint16) uint16 {
        return (uint16(int32(ui1) - int32(ui2)))
}

func func_44(tls *libc.TLS) uint16 {
        return safe_sub_func_uint16_t_u_u(tls, (uint16((int32(safe_div_func_int16_t_s_s(tls, 0, int16(safe_sub_func_int32_t_s_s(tls, 1, int32(safe_lshift_func_int16_t_s_u(tls, int16(0x1504), uint32(safe_unary_minus_func_int64_t_s(tls, int64(libc.Bool32(true))))))))))))), 0)
}
jnml@e5-1650:~/tmp/csmith$ go build main.go

What did you expect to see?

Nothing but a command prompt.

What did you see instead?

# command-line-arguments
./main.go:38:2: invalid instruction: 00105 (/home/jnml/tmp/csmith/main.go:38)   MOVL    $11553462026240, AX
jnml@e5-1650:~/tmp/csmith$
NeedsFix release-blocker

All 14 comments

cc @randall77

I'm trying to reproduce, this has the look and feel of a bug I thought I could create on MIPS, that I (also) encountered with late call expansion. Basically, if you can smuggle a funny constant past the early phases and have it appear "late" (e.g., within late call expansion, which is not in this compiler yet, or in prove, which is), surprising things can happen. I solved it for MIPS by adding some code generation rules, but I don't see the same missing rules on AMD64 so it is not an exact duplicate.

No, it's weirder than that. Compare compilation of the two MOVLconst <int32> [0] : AX in the code:

b28: ← b16-
v24 (9) = MOVLconst <int32> [0] : AX
v102 (+9) = DIVL <int32,int32> [false] v24 v85 : <AX,DX>
v106 (+9) = Select0 <int32> v102 : AX
Plain → b30 (+38)
b10: ← b8-
v43 (13) = MOVLconst <int32> [32767] : CX
v42 (13) = SARLconst <int32> [31] v43 : CX
v20 (13) = CMPLconst <flags> [5380] v42
LT v20 → b13 b12 (13)
b12: ← b10-
v105 (16) = MOVLconst <int32> [0] : AX
Plain → b16 (+38)


v42   00030 (+9) XORL AX, AX
v102  00031 (9) CMPL CX, $-1
v102  00032 (9) JEQ 36
v102  00033 (9) CDQ
v102  00034 (9) IDIVL CX
v102  00035 (9) JMP 38
v102  00036 (9) NEGL AX
v102  00037 (9) XORL DX, DX
b28   00038 (+38) JMP 28
v43   00039 (13) MOVL $32767, CX
v42   00040 (13) SARL $31, CX
v20   00041 (13) CMPL CX, $5380
b10   00042 (13) JLT 8
v105  00043 (16) MOVL $11553462026240, AX
b12   00044 (+38) JMP 9

I've got other things to work on, just wanted to be sure that wasn't a variant of the bug I fixed just the other day for MIPS.

FWIW, a slightly more contained repro - no imports and simplied where possible:
https://play.golang.org/p/rB2HvJwS5j3

v105 (16) = MOVLconst <int32> [0] : AX
v105  00043 (16) MOVL $11553462026240, AX

This looks to me like a rule isn't sign extending an int32 constant to 64 bits. The pretty printer will just ignore the high bits but the MOVL will get a copy of the raw int64 value. I bet the new typed rules in master will fix it.

I got curious and took a quick look at the AMD64 rules in Go 1.15. This looks like the sort of rule that could cause an issue like this:

https://github.com/golang/go/blob/fa01c8a14eeb760c58c5cd09afec327fdd392b2c/src/cmd/compile/internal/ssa/gen/AMD64.rules#L1457

(The sign extension to 64-bits happens before the shift and not after, so the resulting value could be out-of-range for an int32. This particular rule probably doesn't trigger very often because the generic rules do most constant folding.)

A MOVLconst that doesn't have its high bits sign-extended correctly should fail if the check pass is enabled. Does it?

Yep (based on https://github.com/golang/go/issues/41711#issuecomment-701610857).

$ ./go1.15/bin/go tool compile -d=ssa/check/on example.go 
example.go:37:35: internal compiler error: 'func_44': bad int32 AuxInt value for v43

Please file a bug report including a short program that triggers the error.
https://golang.org/issue/new

@gopherbot please open a backport issue for 1.15.

Seems to be ok for 1.14 and earlier.

Backport issue(s) opened: #41720 (for 1.15).

Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://golang.org/wiki/MinorReleases.

Also ok at tip. Just 1.15 needs fixing.

Change https://golang.org/cl/258817 mentions this issue: [release-branch.go1.15] cmd/compile: fix left shift constant folding rule

@randall77 , is it okay to close this issue now that the 1.15 CL is in?

Yes.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rsc picture rsc  ·  3Comments

longzhizhi picture longzhizhi  ·  3Comments

gopherbot picture gopherbot  ·  3Comments

natefinch picture natefinch  ·  3Comments

bradfitz picture bradfitz  ·  3Comments