]> Cypherpunks repositories - gostls13.git/commitdiff
windows/386: clean stack after syscall (it is necessary after call cdecl functions...
authorJaroslavas Počepko <jp@webmaster.ms>
Tue, 30 Aug 2011 04:43:54 +0000 (14:43 +1000)
committerAlex Brainman <alex.brainman@gmail.com>
Tue, 30 Aug 2011 04:43:54 +0000 (14:43 +1000)
Result of discussion here: http://groups.google.com/group/golang-nuts/browse_thread/thread/357c806cbb57ca62

R=golang-dev, bradfitz, alex.brainman, hectorchu, rsc
CC=golang-dev
https://golang.org/cl/4961045

src/pkg/runtime/syscall_windows_test.go [new file with mode: 0644]
src/pkg/runtime/windows/386/sys.s

diff --git a/src/pkg/runtime/syscall_windows_test.go b/src/pkg/runtime/syscall_windows_test.go
new file mode 100644 (file)
index 0000000..aec85ec
--- /dev/null
@@ -0,0 +1,61 @@
+// Copyright 2010 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runtime_test
+
+import (
+       "syscall"
+       "unsafe"
+       "testing"
+)
+
+func TestStdCall(t *testing.T) {
+       type Rect struct {
+               left, top, right, bottom int32
+       }
+
+       h, e := syscall.LoadLibrary("user32.dll")
+       if e != 0 {
+               t.Fatal("LoadLibrary(USER32)")
+       }
+       p, e := syscall.GetProcAddress(h, "UnionRect")
+       if e != 0 {
+               t.Fatal("GetProcAddress(USER32.UnionRect)")
+       }
+
+       res := Rect{}
+       expected := Rect{1, 1, 40, 60}
+       a, _, _ := syscall.Syscall(uintptr(p),
+               3,
+               uintptr(unsafe.Pointer(&res)),
+               uintptr(unsafe.Pointer(&Rect{10, 1, 14, 60})),
+               uintptr(unsafe.Pointer(&Rect{1, 2, 40, 50})))
+       if a != 1 || res.left != expected.left ||
+               res.top != expected.top ||
+               res.right != expected.right ||
+               res.bottom != expected.bottom {
+               t.Error("stdcall USER32.UnionRect returns", a, "res=", res)
+       }
+}
+
+func TestCDecl(t *testing.T) {
+       h, e := syscall.LoadLibrary("user32.dll")
+       if e != 0 {
+               t.Fatal("LoadLibrary(USER32)")
+       }
+       p, e := syscall.GetProcAddress(h, "wsprintfA")
+       if e != 0 {
+               t.Fatal("GetProcAddress(USER32.wsprintfA)")
+       }
+
+       var buf [50]byte
+       a, _, _ := syscall.Syscall6(uintptr(p),
+               5,
+               uintptr(unsafe.Pointer(&buf[0])),
+               uintptr(unsafe.Pointer(syscall.StringBytePtr("%d %d %d"))),
+               1000, 2000, 3000, 0)
+       if string(buf[:a]) != "1000 2000 3000" {
+               t.Error("cdecl USER32.wsprintfA returns", a, "buf=", buf[:a])
+       }
+}
index 111e3d94c3591be534fbbdcf2a81129a05706927..94aed83f06d337114291ac8ffbdda6a71cafb1a0 100644 (file)
@@ -12,6 +12,7 @@ TEXT runtime·asmstdcall(SB),7,$0
        MOVL    $0, 0x34(FS)
 
        // Copy args to the stack.
+       MOVL    SP, BP
        MOVL    wincall_n(DX), CX       // words
        MOVL    CX, BX
        SALL    $2, BX
@@ -21,9 +22,11 @@ TEXT runtime·asmstdcall(SB),7,$0
        CLD
        REP; MOVSL
 
-       // Call stdcall function.
+       // Call stdcall or cdecl function.
+       // DI SI BP BX are preserved, SP is not
        MOVL    wincall_fn(DX), AX
        CALL    AX
+       MOVL    BP, SP
 
        // Return result.
        MOVL    c+0(FP), DX