]> Cypherpunks repositories - gostls13.git/commitdiff
[release-branch.go1.11] cmd/compile: fix type of OffPtr in some optimization rules
authorCherry Zhang <cherryyz@google.com>
Wed, 3 Oct 2018 02:04:45 +0000 (22:04 -0400)
committerBrad Fitzpatrick <bradfitz@golang.org>
Wed, 3 Oct 2018 18:08:44 +0000 (18:08 +0000)
In some optimization rules the type of generated OffPtr was
incorrectly set to the type of the pointee, instead of the
pointer. When the OffPtr value is spilled, this may generate
a spill of the wrong type, e.g. a floating point spill of an
integer (pointer) value. On Wasm, this leads to invalid
bytecode.

Fixes #27961.

Change-Id: I5d464847eb900ed90794105c0013a1a7330756cc
Reviewed-on: https://go-review.googlesource.com/c/139257
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Richard Musiol <neelance@gmail.com>
(cherry picked from commit c96e3bcc97a965b3e2947cc1d8d831b8d39c1d73)
Reviewed-on: https://go-review.googlesource.com/c/139104
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/compile/internal/ssa/gen/generic.rules
src/cmd/compile/internal/ssa/rewritegeneric.go
test/fixedbugs/issue27961.go [new file with mode: 0644]

index 0b68db7f0465df7ff30f3702a49f8711dd0bcd01..0c397c68734ae4a05e73f3fb1b9305bc188b196b 100644 (file)
 // Don't Move from memory if the values are likely to already be
 // in registers.
 (Move {t1} [n] dst p1
-       mem:(Store {t2} op2:(OffPtr [o2] p2) d1
-               (Store {t3} op3:(OffPtr [0] p3) d2 _)))
+       mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
+               (Store {t3} op3:(OffPtr <tt3> [0] p3) d2 _)))
        && isSamePtr(p1, p2) && isSamePtr(p2, p3)
        && alignof(t2) <= alignof(t1)
        && alignof(t3) <= alignof(t1)
        && registerizable(b, t3)
        && o2 == sizeof(t3)
        && n == sizeof(t2) + sizeof(t3)
-       -> (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1
-               (Store {t3} (OffPtr <t3.(*types.Type)> [0] dst) d2 mem))
+       -> (Store {t2} (OffPtr <tt2> [o2] dst) d1
+               (Store {t3} (OffPtr <tt3> [0] dst) d2 mem))
 (Move {t1} [n] dst p1
-       mem:(Store {t2} op2:(OffPtr [o2] p2) d1
-               (Store {t3} op3:(OffPtr [o3] p3) d2
-                       (Store {t4} op4:(OffPtr [0] p4) d3 _))))
+       mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
+               (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2
+                       (Store {t4} op4:(OffPtr <tt4> [0] p4) d3 _))))
        && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4)
        && alignof(t2) <= alignof(t1)
        && alignof(t3) <= alignof(t1)
        && o3 == sizeof(t4)
        && o2-o3 == sizeof(t3)
        && n == sizeof(t2) + sizeof(t3) + sizeof(t4)
-       -> (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1
-               (Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2
-                       (Store {t4} (OffPtr <t4.(*types.Type)> [0] dst) d3 mem)))
+       -> (Store {t2} (OffPtr <tt2> [o2] dst) d1
+               (Store {t3} (OffPtr <tt3> [o3] dst) d2
+                       (Store {t4} (OffPtr <tt4> [0] dst) d3 mem)))
 (Move {t1} [n] dst p1
-       mem:(Store {t2} op2:(OffPtr [o2] p2) d1
-               (Store {t3} op3:(OffPtr [o3] p3) d2
-                       (Store {t4} op4:(OffPtr [o4] p4) d3
-                               (Store {t5} op5:(OffPtr [0] p5) d4 _)))))
+       mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
+               (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2
+                       (Store {t4} op4:(OffPtr <tt4> [o4] p4) d3
+                               (Store {t5} op5:(OffPtr <tt5> [0] p5) d4 _)))))
        && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5)
        && alignof(t2) <= alignof(t1)
        && alignof(t3) <= alignof(t1)
        && o3-o4 == sizeof(t4)
        && o2-o3 == sizeof(t3)
        && n == sizeof(t2) + sizeof(t3) + sizeof(t4) + sizeof(t5)
-       -> (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1
-               (Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2
-                       (Store {t4} (OffPtr <t4.(*types.Type)> [o4] dst) d3
-                               (Store {t5} (OffPtr <t5.(*types.Type)> [0] dst) d4 mem))))
+       -> (Store {t2} (OffPtr <tt2> [o2] dst) d1
+               (Store {t3} (OffPtr <tt3> [o3] dst) d2
+                       (Store {t4} (OffPtr <tt4> [o4] dst) d3
+                               (Store {t5} (OffPtr <tt5> [0] dst) d4 mem))))
 
 // Same thing but with VarDef in the middle.
 (Move {t1} [n] dst p1
        mem:(VarDef
-               (Store {t2} op2:(OffPtr [o2] p2) d1
-                       (Store {t3} op3:(OffPtr [0] p3) d2 _))))
+               (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
+                       (Store {t3} op3:(OffPtr <tt3> [0] p3) d2 _))))
        && isSamePtr(p1, p2) && isSamePtr(p2, p3)
        && alignof(t2) <= alignof(t1)
        && alignof(t3) <= alignof(t1)
        && registerizable(b, t3)
        && o2 == sizeof(t3)
        && n == sizeof(t2) + sizeof(t3)
-       -> (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1
-               (Store {t3} (OffPtr <t3.(*types.Type)> [0] dst) d2 mem))
+       -> (Store {t2} (OffPtr <tt2> [o2] dst) d1
+               (Store {t3} (OffPtr <tt3> [0] dst) d2 mem))
 (Move {t1} [n] dst p1
        mem:(VarDef
-               (Store {t2} op2:(OffPtr [o2] p2) d1
-                       (Store {t3} op3:(OffPtr [o3] p3) d2
-                               (Store {t4} op4:(OffPtr [0] p4) d3 _)))))
+               (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
+                       (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2
+                               (Store {t4} op4:(OffPtr <tt4> [0] p4) d3 _)))))
        && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4)
        && alignof(t2) <= alignof(t1)
        && alignof(t3) <= alignof(t1)
        && o3 == sizeof(t4)
        && o2-o3 == sizeof(t3)
        && n == sizeof(t2) + sizeof(t3) + sizeof(t4)
-       -> (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1
-               (Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2
-                       (Store {t4} (OffPtr <t4.(*types.Type)> [0] dst) d3 mem)))
+       -> (Store {t2} (OffPtr <tt2> [o2] dst) d1
+               (Store {t3} (OffPtr <tt3> [o3] dst) d2
+                       (Store {t4} (OffPtr <tt4> [0] dst) d3 mem)))
 (Move {t1} [n] dst p1
        mem:(VarDef
-               (Store {t2} op2:(OffPtr [o2] p2) d1
-                       (Store {t3} op3:(OffPtr [o3] p3) d2
-                               (Store {t4} op4:(OffPtr [o4] p4) d3
-                                       (Store {t5} op5:(OffPtr [0] p5) d4 _))))))
+               (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1
+                       (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2
+                               (Store {t4} op4:(OffPtr <tt4> [o4] p4) d3
+                                       (Store {t5} op5:(OffPtr <tt5> [0] p5) d4 _))))))
        && isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5)
        && alignof(t2) <= alignof(t1)
        && alignof(t3) <= alignof(t1)
        && o3-o4 == sizeof(t4)
        && o2-o3 == sizeof(t3)
        && n == sizeof(t2) + sizeof(t3) + sizeof(t4) + sizeof(t5)
-       -> (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1
-               (Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2
-                       (Store {t4} (OffPtr <t4.(*types.Type)> [o4] dst) d3
-                               (Store {t5} (OffPtr <t5.(*types.Type)> [0] dst) d4 mem))))
+       -> (Store {t2} (OffPtr <tt2> [o2] dst) d1
+               (Store {t3} (OffPtr <tt3> [o3] dst) d2
+                       (Store {t4} (OffPtr <tt4> [o4] dst) d3
+                               (Store {t5} (OffPtr <tt5> [0] dst) d4 mem))))
 
 // Prefer to Zero and Store than to Move.
 (Move {t1} [n] dst p1
index a1c83ea37834ef7aa6fee21d3549e5019093144b..7936bdf12997cbd37f15bca9b79aa11e987b827c 100644 (file)
@@ -16223,9 +16223,9 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
                v.AddArg(v0)
                return true
        }
-       // match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr [o2] p2) d1 (Store {t3} op3:(OffPtr [0] p3) d2 _)))
+       // match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [0] p3) d2 _)))
        // cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && alignof(t2) <= alignof(t1) && alignof(t3) <= alignof(t1) && registerizable(b, t2) && registerizable(b, t3) && o2 == sizeof(t3) && n == sizeof(t2) + sizeof(t3)
-       // result: (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1 (Store {t3} (OffPtr <t3.(*types.Type)> [0] dst) d2 mem))
+       // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [0] dst) d2 mem))
        for {
                n := v.AuxInt
                t1 := v.Aux
@@ -16242,6 +16242,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
                if op2.Op != OpOffPtr {
                        break
                }
+               tt2 := op2.Type
                o2 := op2.AuxInt
                p2 := op2.Args[0]
                d1 := mem.Args[1]
@@ -16255,6 +16256,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
                if op3.Op != OpOffPtr {
                        break
                }
+               tt3 := op3.Type
                if op3.AuxInt != 0 {
                        break
                }
@@ -16265,14 +16267,14 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
                }
                v.reset(OpStore)
                v.Aux = t2
-               v0 := b.NewValue0(v.Pos, OpOffPtr, t2.(*types.Type))
+               v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
                v0.AuxInt = o2
                v0.AddArg(dst)
                v.AddArg(v0)
                v.AddArg(d1)
                v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
                v1.Aux = t3
-               v2 := b.NewValue0(v.Pos, OpOffPtr, t3.(*types.Type))
+               v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
                v2.AuxInt = 0
                v2.AddArg(dst)
                v1.AddArg(v2)
@@ -16281,9 +16283,9 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
                v.AddArg(v1)
                return true
        }
-       // match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr [o2] p2) d1 (Store {t3} op3:(OffPtr [o3] p3) d2 (Store {t4} op4:(OffPtr [0] p4) d3 _))))
+       // match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2 (Store {t4} op4:(OffPtr <tt4> [0] p4) d3 _))))
        // cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && alignof(t2) <= alignof(t1) && alignof(t3) <= alignof(t1) && alignof(t4) <= alignof(t1) && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && o3 == sizeof(t4) && o2-o3 == sizeof(t3) && n == sizeof(t2) + sizeof(t3) + sizeof(t4)
-       // result: (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1 (Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2 (Store {t4} (OffPtr <t4.(*types.Type)> [0] dst) d3 mem)))
+       // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [0] dst) d3 mem)))
        for {
                n := v.AuxInt
                t1 := v.Aux
@@ -16300,6 +16302,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
                if op2.Op != OpOffPtr {
                        break
                }
+               tt2 := op2.Type
                o2 := op2.AuxInt
                p2 := op2.Args[0]
                d1 := mem.Args[1]
@@ -16313,6 +16316,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
                if op3.Op != OpOffPtr {
                        break
                }
+               tt3 := op3.Type
                o3 := op3.AuxInt
                p3 := op3.Args[0]
                d2 := mem_2.Args[1]
@@ -16326,6 +16330,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
                if op4.Op != OpOffPtr {
                        break
                }
+               tt4 := op4.Type
                if op4.AuxInt != 0 {
                        break
                }
@@ -16336,21 +16341,21 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
                }
                v.reset(OpStore)
                v.Aux = t2
-               v0 := b.NewValue0(v.Pos, OpOffPtr, t2.(*types.Type))
+               v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
                v0.AuxInt = o2
                v0.AddArg(dst)
                v.AddArg(v0)
                v.AddArg(d1)
                v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
                v1.Aux = t3
-               v2 := b.NewValue0(v.Pos, OpOffPtr, t3.(*types.Type))
+               v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
                v2.AuxInt = o3
                v2.AddArg(dst)
                v1.AddArg(v2)
                v1.AddArg(d2)
                v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
                v3.Aux = t4
-               v4 := b.NewValue0(v.Pos, OpOffPtr, t4.(*types.Type))
+               v4 := b.NewValue0(v.Pos, OpOffPtr, tt4)
                v4.AuxInt = 0
                v4.AddArg(dst)
                v3.AddArg(v4)
@@ -16360,9 +16365,9 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
                v.AddArg(v1)
                return true
        }
-       // match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr [o2] p2) d1 (Store {t3} op3:(OffPtr [o3] p3) d2 (Store {t4} op4:(OffPtr [o4] p4) d3 (Store {t5} op5:(OffPtr [0] p5) d4 _)))))
+       // match: (Move {t1} [n] dst p1 mem:(Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2 (Store {t4} op4:(OffPtr <tt4> [o4] p4) d3 (Store {t5} op5:(OffPtr <tt5> [0] p5) d4 _)))))
        // cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && alignof(t2) <= alignof(t1) && alignof(t3) <= alignof(t1) && alignof(t4) <= alignof(t1) && alignof(t5) <= alignof(t1) && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && registerizable(b, t5) && o4 == sizeof(t5) && o3-o4 == sizeof(t4) && o2-o3 == sizeof(t3) && n == sizeof(t2) + sizeof(t3) + sizeof(t4) + sizeof(t5)
-       // result: (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1 (Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2 (Store {t4} (OffPtr <t4.(*types.Type)> [o4] dst) d3 (Store {t5} (OffPtr <t5.(*types.Type)> [0] dst) d4 mem))))
+       // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [o4] dst) d3 (Store {t5} (OffPtr <tt5> [0] dst) d4 mem))))
        for {
                n := v.AuxInt
                t1 := v.Aux
@@ -16379,6 +16384,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
                if op2.Op != OpOffPtr {
                        break
                }
+               tt2 := op2.Type
                o2 := op2.AuxInt
                p2 := op2.Args[0]
                d1 := mem.Args[1]
@@ -16392,6 +16398,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
                if op3.Op != OpOffPtr {
                        break
                }
+               tt3 := op3.Type
                o3 := op3.AuxInt
                p3 := op3.Args[0]
                d2 := mem_2.Args[1]
@@ -16405,6 +16412,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
                if op4.Op != OpOffPtr {
                        break
                }
+               tt4 := op4.Type
                o4 := op4.AuxInt
                p4 := op4.Args[0]
                d3 := mem_2_2.Args[1]
@@ -16418,6 +16426,7 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
                if op5.Op != OpOffPtr {
                        break
                }
+               tt5 := op5.Type
                if op5.AuxInt != 0 {
                        break
                }
@@ -16428,28 +16437,28 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
                }
                v.reset(OpStore)
                v.Aux = t2
-               v0 := b.NewValue0(v.Pos, OpOffPtr, t2.(*types.Type))
+               v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
                v0.AuxInt = o2
                v0.AddArg(dst)
                v.AddArg(v0)
                v.AddArg(d1)
                v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
                v1.Aux = t3
-               v2 := b.NewValue0(v.Pos, OpOffPtr, t3.(*types.Type))
+               v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
                v2.AuxInt = o3
                v2.AddArg(dst)
                v1.AddArg(v2)
                v1.AddArg(d2)
                v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
                v3.Aux = t4
-               v4 := b.NewValue0(v.Pos, OpOffPtr, t4.(*types.Type))
+               v4 := b.NewValue0(v.Pos, OpOffPtr, tt4)
                v4.AuxInt = o4
                v4.AddArg(dst)
                v3.AddArg(v4)
                v3.AddArg(d3)
                v5 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
                v5.Aux = t5
-               v6 := b.NewValue0(v.Pos, OpOffPtr, t5.(*types.Type))
+               v6 := b.NewValue0(v.Pos, OpOffPtr, tt5)
                v6.AuxInt = 0
                v6.AddArg(dst)
                v5.AddArg(v6)
@@ -16465,9 +16474,9 @@ func rewriteValuegeneric_OpMove_0(v *Value) bool {
 func rewriteValuegeneric_OpMove_10(v *Value) bool {
        b := v.Block
        _ = b
-       // match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr [o2] p2) d1 (Store {t3} op3:(OffPtr [0] p3) d2 _))))
+       // match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [0] p3) d2 _))))
        // cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && alignof(t2) <= alignof(t1) && alignof(t3) <= alignof(t1) && registerizable(b, t2) && registerizable(b, t3) && o2 == sizeof(t3) && n == sizeof(t2) + sizeof(t3)
-       // result: (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1 (Store {t3} (OffPtr <t3.(*types.Type)> [0] dst) d2 mem))
+       // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [0] dst) d2 mem))
        for {
                n := v.AuxInt
                t1 := v.Aux
@@ -16488,6 +16497,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
                if op2.Op != OpOffPtr {
                        break
                }
+               tt2 := op2.Type
                o2 := op2.AuxInt
                p2 := op2.Args[0]
                d1 := mem_0.Args[1]
@@ -16501,6 +16511,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
                if op3.Op != OpOffPtr {
                        break
                }
+               tt3 := op3.Type
                if op3.AuxInt != 0 {
                        break
                }
@@ -16511,14 +16522,14 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
                }
                v.reset(OpStore)
                v.Aux = t2
-               v0 := b.NewValue0(v.Pos, OpOffPtr, t2.(*types.Type))
+               v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
                v0.AuxInt = o2
                v0.AddArg(dst)
                v.AddArg(v0)
                v.AddArg(d1)
                v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
                v1.Aux = t3
-               v2 := b.NewValue0(v.Pos, OpOffPtr, t3.(*types.Type))
+               v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
                v2.AuxInt = 0
                v2.AddArg(dst)
                v1.AddArg(v2)
@@ -16527,9 +16538,9 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
                v.AddArg(v1)
                return true
        }
-       // match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr [o2] p2) d1 (Store {t3} op3:(OffPtr [o3] p3) d2 (Store {t4} op4:(OffPtr [0] p4) d3 _)))))
+       // match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2 (Store {t4} op4:(OffPtr <tt4> [0] p4) d3 _)))))
        // cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && alignof(t2) <= alignof(t1) && alignof(t3) <= alignof(t1) && alignof(t4) <= alignof(t1) && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && o3 == sizeof(t4) && o2-o3 == sizeof(t3) && n == sizeof(t2) + sizeof(t3) + sizeof(t4)
-       // result: (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1 (Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2 (Store {t4} (OffPtr <t4.(*types.Type)> [0] dst) d3 mem)))
+       // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [0] dst) d3 mem)))
        for {
                n := v.AuxInt
                t1 := v.Aux
@@ -16550,6 +16561,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
                if op2.Op != OpOffPtr {
                        break
                }
+               tt2 := op2.Type
                o2 := op2.AuxInt
                p2 := op2.Args[0]
                d1 := mem_0.Args[1]
@@ -16563,6 +16575,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
                if op3.Op != OpOffPtr {
                        break
                }
+               tt3 := op3.Type
                o3 := op3.AuxInt
                p3 := op3.Args[0]
                d2 := mem_0_2.Args[1]
@@ -16576,6 +16589,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
                if op4.Op != OpOffPtr {
                        break
                }
+               tt4 := op4.Type
                if op4.AuxInt != 0 {
                        break
                }
@@ -16586,21 +16600,21 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
                }
                v.reset(OpStore)
                v.Aux = t2
-               v0 := b.NewValue0(v.Pos, OpOffPtr, t2.(*types.Type))
+               v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
                v0.AuxInt = o2
                v0.AddArg(dst)
                v.AddArg(v0)
                v.AddArg(d1)
                v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
                v1.Aux = t3
-               v2 := b.NewValue0(v.Pos, OpOffPtr, t3.(*types.Type))
+               v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
                v2.AuxInt = o3
                v2.AddArg(dst)
                v1.AddArg(v2)
                v1.AddArg(d2)
                v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
                v3.Aux = t4
-               v4 := b.NewValue0(v.Pos, OpOffPtr, t4.(*types.Type))
+               v4 := b.NewValue0(v.Pos, OpOffPtr, tt4)
                v4.AuxInt = 0
                v4.AddArg(dst)
                v3.AddArg(v4)
@@ -16610,9 +16624,9 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
                v.AddArg(v1)
                return true
        }
-       // match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr [o2] p2) d1 (Store {t3} op3:(OffPtr [o3] p3) d2 (Store {t4} op4:(OffPtr [o4] p4) d3 (Store {t5} op5:(OffPtr [0] p5) d4 _))))))
+       // match: (Move {t1} [n] dst p1 mem:(VarDef (Store {t2} op2:(OffPtr <tt2> [o2] p2) d1 (Store {t3} op3:(OffPtr <tt3> [o3] p3) d2 (Store {t4} op4:(OffPtr <tt4> [o4] p4) d3 (Store {t5} op5:(OffPtr <tt5> [0] p5) d4 _))))))
        // cond: isSamePtr(p1, p2) && isSamePtr(p2, p3) && isSamePtr(p3, p4) && isSamePtr(p4, p5) && alignof(t2) <= alignof(t1) && alignof(t3) <= alignof(t1) && alignof(t4) <= alignof(t1) && alignof(t5) <= alignof(t1) && registerizable(b, t2) && registerizable(b, t3) && registerizable(b, t4) && registerizable(b, t5) && o4 == sizeof(t5) && o3-o4 == sizeof(t4) && o2-o3 == sizeof(t3) && n == sizeof(t2) + sizeof(t3) + sizeof(t4) + sizeof(t5)
-       // result: (Store {t2} (OffPtr <t2.(*types.Type)> [o2] dst) d1 (Store {t3} (OffPtr <t3.(*types.Type)> [o3] dst) d2 (Store {t4} (OffPtr <t4.(*types.Type)> [o4] dst) d3 (Store {t5} (OffPtr <t5.(*types.Type)> [0] dst) d4 mem))))
+       // result: (Store {t2} (OffPtr <tt2> [o2] dst) d1 (Store {t3} (OffPtr <tt3> [o3] dst) d2 (Store {t4} (OffPtr <tt4> [o4] dst) d3 (Store {t5} (OffPtr <tt5> [0] dst) d4 mem))))
        for {
                n := v.AuxInt
                t1 := v.Aux
@@ -16633,6 +16647,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
                if op2.Op != OpOffPtr {
                        break
                }
+               tt2 := op2.Type
                o2 := op2.AuxInt
                p2 := op2.Args[0]
                d1 := mem_0.Args[1]
@@ -16646,6 +16661,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
                if op3.Op != OpOffPtr {
                        break
                }
+               tt3 := op3.Type
                o3 := op3.AuxInt
                p3 := op3.Args[0]
                d2 := mem_0_2.Args[1]
@@ -16659,6 +16675,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
                if op4.Op != OpOffPtr {
                        break
                }
+               tt4 := op4.Type
                o4 := op4.AuxInt
                p4 := op4.Args[0]
                d3 := mem_0_2_2.Args[1]
@@ -16672,6 +16689,7 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
                if op5.Op != OpOffPtr {
                        break
                }
+               tt5 := op5.Type
                if op5.AuxInt != 0 {
                        break
                }
@@ -16682,28 +16700,28 @@ func rewriteValuegeneric_OpMove_10(v *Value) bool {
                }
                v.reset(OpStore)
                v.Aux = t2
-               v0 := b.NewValue0(v.Pos, OpOffPtr, t2.(*types.Type))
+               v0 := b.NewValue0(v.Pos, OpOffPtr, tt2)
                v0.AuxInt = o2
                v0.AddArg(dst)
                v.AddArg(v0)
                v.AddArg(d1)
                v1 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
                v1.Aux = t3
-               v2 := b.NewValue0(v.Pos, OpOffPtr, t3.(*types.Type))
+               v2 := b.NewValue0(v.Pos, OpOffPtr, tt3)
                v2.AuxInt = o3
                v2.AddArg(dst)
                v1.AddArg(v2)
                v1.AddArg(d2)
                v3 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
                v3.Aux = t4
-               v4 := b.NewValue0(v.Pos, OpOffPtr, t4.(*types.Type))
+               v4 := b.NewValue0(v.Pos, OpOffPtr, tt4)
                v4.AuxInt = o4
                v4.AddArg(dst)
                v3.AddArg(v4)
                v3.AddArg(d3)
                v5 := b.NewValue0(v.Pos, OpStore, types.TypeMem)
                v5.Aux = t5
-               v6 := b.NewValue0(v.Pos, OpOffPtr, t5.(*types.Type))
+               v6 := b.NewValue0(v.Pos, OpOffPtr, tt5)
                v6.AuxInt = 0
                v6.AddArg(dst)
                v5.AddArg(v6)
diff --git a/test/fixedbugs/issue27961.go b/test/fixedbugs/issue27961.go
new file mode 100644 (file)
index 0000000..f8b4f66
--- /dev/null
@@ -0,0 +1,35 @@
+// run
+
+// Copyright 2018 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 27961: some optimizations generate OffPtr with wrong
+// types, which causes invalid bytecode on Wasm.
+
+package main
+
+import "math"
+
+type Vec2 [2]float64
+
+func main() {
+       var a Vec2
+       a.A().B().C().D()
+}
+
+func (v Vec2) A() Vec2 {
+       return Vec2{v[0], v[0]}
+}
+
+func (v Vec2) B() Vec2 {
+       return Vec2{1.0 / v.D(), 0}
+}
+
+func (v Vec2) C() Vec2 {
+       return Vec2{v[0], v[0]}
+}
+
+func (v Vec2) D() float64 {
+       return math.Sqrt(v[0])
+}