]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix magic multiply smashing AX
authorRuss Cox <rsc@golang.org>
Mon, 14 Dec 2015 20:55:44 +0000 (15:55 -0500)
committerRuss Cox <rsc@golang.org>
Wed, 16 Dec 2015 20:58:17 +0000 (20:58 +0000)
Fixes #12411.

Change-Id: I2202a754c7750e3b2119e3744362c98ca0d2433e
Reviewed-on: https://go-review.googlesource.com/17818
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/cmd/compile/internal/amd64/ggen.go
src/cmd/compile/internal/x86/ggen.go
test/fixedbugs/issue12411.go [new file with mode: 0644]

index 0cd3473e2907fa907e10ed9220d8c5c8b7413244..84c3d5d7d49a640067bf905717efe3001ec66f1c 100644 (file)
@@ -365,24 +365,25 @@ func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
        gc.Cgenr(nl, &n1, res)
        var n2 gc.Node
        gc.Cgenr(nr, &n2, nil)
-       var ax gc.Node
-       gc.Nodreg(&ax, t, x86.REG_AX)
+       var ax, oldax, dx, olddx gc.Node
+       savex(x86.REG_AX, &ax, &oldax, res, gc.Types[gc.TUINT64])
+       savex(x86.REG_DX, &dx, &olddx, res, gc.Types[gc.TUINT64])
        gmove(&n1, &ax)
        gins(a, &n2, nil)
        gc.Regfree(&n2)
        gc.Regfree(&n1)
 
-       var dx gc.Node
        if t.Width == 1 {
                // byte multiply behaves differently.
-               gc.Nodreg(&ax, t, x86.REG_AH)
-
-               gc.Nodreg(&dx, t, x86.REG_DX)
-               gmove(&ax, &dx)
+               var byteAH, byteDX gc.Node
+               gc.Nodreg(&byteAH, t, x86.REG_AH)
+               gc.Nodreg(&byteDX, t, x86.REG_DX)
+               gmove(&byteAH, &byteDX)
        }
-
-       gc.Nodreg(&dx, t, x86.REG_DX)
        gmove(&dx, res)
+
+       restx(&ax, &oldax)
+       restx(&dx, &olddx)
 }
 
 /*
index 4e72dcb1e99088c609fa0a2db9d96b271b611cc3..e559a9f5da9dcbb76edc44295135071e76f6e4f9 100644 (file)
@@ -531,24 +531,21 @@ func cgen_bmul(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) bool {
 func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
        var n1 gc.Node
        var n2 gc.Node
-       var ax gc.Node
-       var dx gc.Node
 
        t := nl.Type
        a := optoas(gc.OHMUL, t)
 
        // gen nl in n1.
        gc.Tempname(&n1, t)
-
        gc.Cgen(nl, &n1)
 
        // gen nr in n2.
        gc.Regalloc(&n2, t, res)
-
        gc.Cgen(nr, &n2)
 
-       // multiply.
-       gc.Nodreg(&ax, t, x86.REG_AX)
+       var ax, oldax, dx, olddx gc.Node
+       savex(x86.REG_AX, &ax, &oldax, res, gc.Types[gc.TUINT32])
+       savex(x86.REG_DX, &dx, &olddx, res, gc.Types[gc.TUINT32])
 
        gmove(&n2, &ax)
        gins(a, &n1, nil)
@@ -556,14 +553,16 @@ func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
 
        if t.Width == 1 {
                // byte multiply behaves differently.
-               gc.Nodreg(&ax, t, x86.REG_AH)
-
-               gc.Nodreg(&dx, t, x86.REG_DX)
-               gmove(&ax, &dx)
+               var byteAH, byteDX gc.Node
+               gc.Nodreg(&byteAH, t, x86.REG_AH)
+               gc.Nodreg(&byteDX, t, x86.REG_DX)
+               gmove(&byteAH, &byteDX)
        }
 
-       gc.Nodreg(&dx, t, x86.REG_DX)
        gmove(&dx, res)
+
+       restx(&ax, &oldax)
+       restx(&dx, &olddx)
 }
 
 /*
diff --git a/test/fixedbugs/issue12411.go b/test/fixedbugs/issue12411.go
new file mode 100644 (file)
index 0000000..0a8b7c3
--- /dev/null
@@ -0,0 +1,24 @@
+// +build !386
+// run
+
+// Copyright 2015 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.
+
+// Issue 12411. Loss of AX during %.
+
+package main
+
+func main() {
+       x := f(4)
+       if x != 0 {
+               println("BUG: x=", x)
+       }
+}
+
+//go:noinline
+func f(x int) int {
+       // AX was live on entry to one of the % code generations,
+       // and the % code generation smashed it.
+       return ((2 * x) % 3) % (2 % ((x << 2) ^ (x % 3)))
+}