]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: pass windows float syscall args via XMM
authorDavid Crawshaw <crawshaw@golang.org>
Wed, 26 Oct 2016 17:29:39 +0000 (13:29 -0400)
committerDavid Crawshaw <crawshaw@golang.org>
Fri, 28 Oct 2016 13:13:08 +0000 (13:13 +0000)
Based on the calling convention documented in:

https://msdn.microsoft.com/en-us/library/zthk2dkh.aspx

and long-used in golang.org/x/mobile/gl via some fixup asm:

https://go.googlesource.com/mobile/+/master/gl/work_windows_amd64.s

Fixes #6510

Change-Id: I97e81baaa2872bcd732b1308915eb66f1ba2168f
Reviewed-on: https://go-review.googlesource.com/32173
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Reviewed-by: Minux Ma <minux@golang.org>
src/runtime/sys_windows_amd64.s
src/runtime/syscall_windows_test.go

index 9c197379fb8f421e11523ef7e49bc3cbcee7c6bf..9679099c4e7729c5d9bc74997d389fd5b29c4bba 100644 (file)
@@ -45,6 +45,14 @@ loadregs:
        MOVQ    8(SI), DX
        MOVQ    16(SI), R8
        MOVQ    24(SI), R9
+       // Floating point arguments are passed in the XMM
+       // registers. Set them here in case any of the arguments
+       // are floating point values. For details see
+       //      https://msdn.microsoft.com/en-us/library/zthk2dkh.aspx
+       MOVQ    CX, X0
+       MOVQ    DX, X1
+       MOVQ    R8, X2
+       MOVQ    R9, X3
 
        // Call stdcall function.
        CALL    AX
index c19cd71662ff4bec5fedefab3dd5aff56531720d..11e67df100d9f1c67033fa917891e3e5703e7567 100644 (file)
@@ -10,6 +10,7 @@ import (
        "internal/syscall/windows/sysdll"
        "internal/testenv"
        "io/ioutil"
+       "math"
        "os"
        "os/exec"
        "path/filepath"
@@ -622,6 +623,61 @@ uintptr_t cfunc(callback f, uintptr_t n) {
        }
 }
 
+func TestFloatArgs(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>
+
+uintptr_t cfunc(uintptr_t a, double b, float c, double d) {
+       if (a == 1 && b == 2.2 && c == 3.3f && d == 4.4e44) {
+               return 1;
+       }
+       return 0;
+}
+`
+       tmpdir, err := ioutil.TempDir("", "TestFloatArgs")
+       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("cfunc")
+
+       r, _, err := proc.Call(
+               1,
+               uintptr(math.Float64bits(2.2)),
+               uintptr(math.Float32bits(3.3)),
+               uintptr(math.Float64bits(4.4e44)),
+       )
+       if r != 1 {
+               t.Errorf("got %d want 1 (err=%v)", r, err)
+       }
+}
+
 func TestTimeBeginPeriod(t *testing.T) {
        const TIMERR_NOERROR = 0
        if *runtime.TimeBeginPeriodRetValue != TIMERR_NOERROR {