Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/compile: invalid conversion from a negative float to uint64 on arm64 #43047

Closed
gballet opened this issue Dec 7, 2020 · 5 comments
Closed

cmd/compile: invalid conversion from a negative float to uint64 on arm64 #43047

gballet opened this issue Dec 7, 2020 · 5 comments

Comments

@gballet
Copy link

@gballet gballet commented Dec 7, 2020

On aarch64, the conversion of a negative float to uint64 yields 0.

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

go version go1.15 linux/arm64

Does this issue reproduce with the latest release?

Yes, and it has been present since at least 1.13

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

GO111MODULE=""
GOARCH="arm64"
GOBIN=""
GOCACHE="/home/ubuntu/.cache/go-build"
GOENV="/home/ubuntu/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="arm64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/ubuntu/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/ubuntu/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_arm64"
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 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build178011601=/tmp/go-build -gno-record-gcc-switches"

What did you do?

The following program reproduces the error:

package main

import (
	"fmt"
)

func main() {
	x := -64.0
	fmt.Println(x, uint64(x), uint64(int64(x)))
}

x86_64 output:

-64 18446744073709551552 18446744073709551552

aarch64 output:

-64 0 18446744073709551552

What did you expect to see?

Expecting the outputs for x86_64 and aarch64 to be exactly the same might not be reasonable, due to differences in hardware implementations. At the very least, I would expect the output of uint64(<float>) and uint64(int64(<float>)) to be the same.

What did you see instead?

uint64(-64.0) == 0 and uint64(int64(-64.0)) == 18446744073709551552

@mengzhuo
Copy link
Contributor

@mengzhuo mengzhuo commented Dec 7, 2020

I can confirm that go1.13 is affected.
The compiler compile FCVTZUD F0, R0 => fcvtzu x0, d0 which is corrected on arm64.
However the spec says it should be like uint64(int64(x)).

Conversions between numeric types
For the conversion of non-constant numeric values, the following rules apply:

When converting between integer types, if the value is a signed integer, it is sign extended to implicit infinite precision; otherwise it is zero extended. It is then truncated to fit in the result type's size. For example, if v := uint16(0x10F0), then uint32(int8(v)) == 0xFFFFFFF0. The conversion always yields a valid value; there is no indication of overflow.
When converting a floating-point number to an integer, the fraction is discarded (truncation towards zero).

Loading

@gopherbot
Copy link

@gopherbot gopherbot commented Dec 7, 2020

Change https://golang.org/cl/275832 mentions this issue: cmd/compile: fix float convert uint on arm64

Loading

@cherrymui
Copy link
Contributor

@cherrymui cherrymui commented Dec 7, 2020

The Go spec reads

In all non-constant conversions involving floating-point or complex values, if the result type cannot represent the value the conversion succeeds but the result value is implementation-dependent.

So it is totally okay for x := -64.0; uint64(x) be 0 and be different on different platforms.

Loading

@odeke-em odeke-em changed the title arm64: invalid conversion from a negative float to uint64 cmd/compile: invalid conversion from a negative float to uint64 on arm64 Dec 7, 2020
@mengzhuo
Copy link
Contributor

@mengzhuo mengzhuo commented Dec 8, 2020

The Go spec reads

In all non-constant conversions involving floating-point or complex values, if the result type cannot represent the value the conversion succeeds but the result value is implementation-dependent.

So it is totally okay for x := -64.0; uint64(x) be 0 and be different on different platforms.

@cherrymui I agreed with you that it's an undefined behavior in spec.
@odeke-em Maybe we can close this issue?

Loading

@odeke-em
Copy link
Member

@odeke-em odeke-em commented Dec 8, 2020

Sounds good, thank you for chiming in @mengzhuo and @cherrymui! Marking as won't fix due to undefined behavior.

Loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
5 participants