]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: allow float syscall return values on windows amd64
authorRichard Wilkes <wilkes@me.com>
Mon, 24 Feb 2020 23:46:00 +0000 (23:46 +0000)
committerAlex Brainman <alex.brainman@gmail.com>
Tue, 25 Feb 2020 08:36:15 +0000 (08:36 +0000)
RELNOTE=yes
Fixes #37273

Change-Id: Iedb7eab185dfeccb1b26902ef36411d2c53ea3e0
GitHub-Last-Rev: bbe30ba45d4a1bd53757b5824ad28024d5e2b179
GitHub-Pull-Request: golang/go#37380
Reviewed-on: https://go-review.googlesource.com/c/go/+/220578
Run-TryBot: Alex Brainman <alex.brainman@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
src/runtime/sys_windows_amd64.s
src/runtime/syscall_windows_test.go

index d2552e87facd733a1d2a62e93b7c4897dbe45b1b..6c8eecd4e7d22cc507ad03b3d81b07e169d3b757 100644 (file)
@@ -62,6 +62,10 @@ loadregs:
        // Return result.
        POPQ    CX
        MOVQ    AX, libcall_r1(CX)
+       // Floating point return values are returned in XMM0. Setting r2 to this
+       // value in case this call returned a floating point value. For details,
+       // see https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention
+       MOVQ    X0, libcall_r2(CX)
 
        // GetLastError().
        MOVQ    0x30(GS), DI
index 5335c12f0f7b8a8f4bc163daa2d019a79c620cf7..2e74546e38333639a73157b2c5c1a969eccd0893 100644 (file)
@@ -725,6 +725,82 @@ uintptr_t cfunc(uintptr_t a, double b, float c, double d) {
        }
 }
 
+func TestFloatReturn(t *testing.T) {
+       if _, err := exec.LookPath("gcc"); err != nil {
+               t.Skip("skipping test: gcc is missing")
+       }
+       if runtime.GOARCH != "amd64" {
+               t.Skipf("skipping test: GOARCH=%s", runtime.GOARCH)
+       }
+
+       const src = `
+#include <stdint.h>
+#include <windows.h>
+
+float cfuncFloat(uintptr_t a, double b, float c, double d) {
+       if (a == 1 && b == 2.2 && c == 3.3f && d == 4.4e44) {
+               return 1.5f;
+       }
+       return 0;
+}
+
+double cfuncDouble(uintptr_t a, double b, float c, double d) {
+       if (a == 1 && b == 2.2 && c == 3.3f && d == 4.4e44) {
+               return 2.5;
+       }
+       return 0;
+}
+`
+       tmpdir, err := ioutil.TempDir("", "TestFloatReturn")
+       if err != nil {
+               t.Fatal("TempDir failed: ", err)
+       }
+       defer os.RemoveAll(tmpdir)
+
+       srcname := "mydll.c"
+       err = ioutil.WriteFile(filepath.Join(tmpdir, srcname), []byte(src), 0)
+       if err != nil {
+               t.Fatal(err)
+       }
+       outname := "mydll.dll"
+       cmd := exec.Command("gcc", "-shared", "-s", "-Werror", "-o", outname, srcname)
+       cmd.Dir = tmpdir
+       out, err := cmd.CombinedOutput()
+       if err != nil {
+               t.Fatalf("failed to build dll: %v - %v", err, string(out))
+       }
+       dllpath := filepath.Join(tmpdir, outname)
+
+       dll := syscall.MustLoadDLL(dllpath)
+       defer dll.Release()
+
+       proc := dll.MustFindProc("cfuncFloat")
+
+       _, r, err := proc.Call(
+               1,
+               uintptr(math.Float64bits(2.2)),
+               uintptr(math.Float32bits(3.3)),
+               uintptr(math.Float64bits(4.4e44)),
+       )
+       fr := math.Float32frombits(uint32(r))
+       if fr != 1.5 {
+               t.Errorf("got %f want 1.5 (err=%v)", fr, err)
+       }
+
+       proc = dll.MustFindProc("cfuncDouble")
+
+       _, r, err = proc.Call(
+               1,
+               uintptr(math.Float64bits(2.2)),
+               uintptr(math.Float32bits(3.3)),
+               uintptr(math.Float64bits(4.4e44)),
+       )
+       dr := math.Float64frombits(uint64(r))
+       if dr != 2.5 {
+               t.Errorf("got %f want 2.5 (err=%v)", dr, err)
+       }
+}
+
 func TestTimeBeginPeriod(t *testing.T) {
        const TIMERR_NOERROR = 0
        if *runtime.TimeBeginPeriodRetValue != TIMERR_NOERROR {