]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.ssa] cmd/compile: truncate auxint when constructing Prog
authorTodd Neal <todd@tneal.org>
Fri, 19 Feb 2016 22:58:21 +0000 (16:58 -0600)
committerTodd Neal <todd@tneal.org>
Tue, 23 Feb 2016 03:52:08 +0000 (03:52 +0000)
The upper bits of 8/16/32 bit constants are undefined.  We need to
truncate in order to prevent x86.oclass misidentifying the size of the
constant.

Fixes #14389

Change-Id: I3e5ff79cd904376572a93f489ba7e152a5cb6e60
Reviewed-on: https://go-review.googlesource.com/19740
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/gc/testdata/arith_ssa.go
src/cmd/compile/internal/ssa/value.go

index 3f8fdce83bb7616be9aabae35f980a711f13a1a7..19fda373bfdc0c7166063e2a544ef02fef8912ae 100644 (file)
@@ -3990,7 +3990,7 @@ func (s *genState) genValue(v *ssa.Value) {
                r := regnum(v)
                a := regnum(v.Args[0])
                if r == a {
-                       if v.AuxInt == 1 {
+                       if v.AuxInt2Int64() == 1 {
                                var asm int
                                switch v.Op {
                                // Software optimization manual recommends add $1,reg.
@@ -4009,7 +4009,7 @@ func (s *genState) genValue(v *ssa.Value) {
                                p.To.Type = obj.TYPE_REG
                                p.To.Reg = r
                                return
-                       } else if v.AuxInt == -1 {
+                       } else if v.AuxInt2Int64() == -1 {
                                var asm int
                                switch v.Op {
                                case ssa.OpAMD64ADDQconst:
@@ -4026,7 +4026,7 @@ func (s *genState) genValue(v *ssa.Value) {
                        } else {
                                p := Prog(v.Op.Asm())
                                p.From.Type = obj.TYPE_CONST
-                               p.From.Offset = v.AuxInt
+                               p.From.Offset = v.AuxInt2Int64()
                                p.To.Type = obj.TYPE_REG
                                p.To.Reg = r
                                return
@@ -4044,7 +4044,7 @@ func (s *genState) genValue(v *ssa.Value) {
                p := Prog(asm)
                p.From.Type = obj.TYPE_MEM
                p.From.Reg = a
-               p.From.Offset = v.AuxInt
+               p.From.Offset = v.AuxInt2Int64()
                p.To.Type = obj.TYPE_REG
                p.To.Reg = r
        case ssa.OpAMD64MULQconst, ssa.OpAMD64MULLconst, ssa.OpAMD64MULWconst, ssa.OpAMD64MULBconst:
@@ -4059,7 +4059,7 @@ func (s *genState) genValue(v *ssa.Value) {
                }
                p := Prog(v.Op.Asm())
                p.From.Type = obj.TYPE_CONST
-               p.From.Offset = v.AuxInt
+               p.From.Offset = v.AuxInt2Int64()
                p.To.Type = obj.TYPE_REG
                p.To.Reg = r
                // TODO: Teach doasm to compile the three-address multiply imul $c, r1, r2
@@ -4074,7 +4074,7 @@ func (s *genState) genValue(v *ssa.Value) {
                // a = b + (- const), saves us 1 instruction. We can't fit
                // - (-1 << 31) into  4 bytes offset in lea.
                // We handle 2-address just fine below.
-               if v.AuxInt == -1<<31 || x == r {
+               if v.AuxInt2Int64() == -1<<31 || x == r {
                        if x != r {
                                // This code compensates for the fact that the register allocator
                                // doesn't understand 2-address instructions yet.  TODO: fix that.
@@ -4086,10 +4086,10 @@ func (s *genState) genValue(v *ssa.Value) {
                        }
                        p := Prog(v.Op.Asm())
                        p.From.Type = obj.TYPE_CONST
-                       p.From.Offset = v.AuxInt
+                       p.From.Offset = v.AuxInt2Int64()
                        p.To.Type = obj.TYPE_REG
                        p.To.Reg = r
-               } else if x == r && v.AuxInt == -1 {
+               } else if x == r && v.AuxInt2Int64() == -1 {
                        var asm int
                        // x = x - (-1) is the same as x++
                        // See OpAMD64ADDQconst comments about inc vs add $1,reg
@@ -4104,7 +4104,7 @@ func (s *genState) genValue(v *ssa.Value) {
                        p := Prog(asm)
                        p.To.Type = obj.TYPE_REG
                        p.To.Reg = r
-               } else if x == r && v.AuxInt == 1 {
+               } else if x == r && v.AuxInt2Int64() == 1 {
                        var asm int
                        switch v.Op {
                        case ssa.OpAMD64SUBQconst:
@@ -4130,7 +4130,7 @@ func (s *genState) genValue(v *ssa.Value) {
                        p := Prog(asm)
                        p.From.Type = obj.TYPE_MEM
                        p.From.Reg = x
-                       p.From.Offset = -v.AuxInt
+                       p.From.Offset = -v.AuxInt2Int64()
                        p.To.Type = obj.TYPE_REG
                        p.To.Reg = r
                }
@@ -4157,7 +4157,7 @@ func (s *genState) genValue(v *ssa.Value) {
                }
                p := Prog(v.Op.Asm())
                p.From.Type = obj.TYPE_CONST
-               p.From.Offset = v.AuxInt
+               p.From.Offset = v.AuxInt2Int64()
                p.To.Type = obj.TYPE_REG
                p.To.Reg = r
        case ssa.OpAMD64SBBQcarrymask, ssa.OpAMD64SBBLcarrymask:
@@ -4204,29 +4204,18 @@ func (s *genState) genValue(v *ssa.Value) {
                p.From.Type = obj.TYPE_REG
                p.From.Reg = regnum(v.Args[0])
                p.To.Type = obj.TYPE_CONST
-               p.To.Offset = v.AuxInt
+               p.To.Offset = v.AuxInt2Int64()
        case ssa.OpAMD64TESTQconst, ssa.OpAMD64TESTLconst, ssa.OpAMD64TESTWconst, ssa.OpAMD64TESTBconst:
                p := Prog(v.Op.Asm())
                p.From.Type = obj.TYPE_CONST
-               p.From.Offset = v.AuxInt
+               p.From.Offset = v.AuxInt2Int64()
                p.To.Type = obj.TYPE_REG
                p.To.Reg = regnum(v.Args[0])
        case ssa.OpAMD64MOVBconst, ssa.OpAMD64MOVWconst, ssa.OpAMD64MOVLconst, ssa.OpAMD64MOVQconst:
                x := regnum(v)
                p := Prog(v.Op.Asm())
                p.From.Type = obj.TYPE_CONST
-               var i int64
-               switch v.Op {
-               case ssa.OpAMD64MOVBconst:
-                       i = int64(v.AuxInt8())
-               case ssa.OpAMD64MOVWconst:
-                       i = int64(v.AuxInt16())
-               case ssa.OpAMD64MOVLconst:
-                       i = int64(v.AuxInt32())
-               case ssa.OpAMD64MOVQconst:
-                       i = v.AuxInt
-               }
-               p.From.Offset = i
+               p.From.Offset = v.AuxInt2Int64()
                p.To.Type = obj.TYPE_REG
                p.To.Reg = x
                // If flags are live at this instruction, suppress the
index 821c0dd12dee397f08990c82d48e9ded021afa75..f4bea0ed11383372b4f81dca235f9133d442ca00 100644 (file)
@@ -10,6 +10,42 @@ package main
 
 import "fmt"
 
+const (
+       y = 0x0fffFFFF
+)
+
+//go:noinline
+func invalidAdd_ssa(x uint32) uint32 {
+       return x + y + y + y + y + y + y + y + y + y + y + y + y + y + y + y + y + y
+}
+
+//go:noinline
+func invalidSub_ssa(x uint32) uint32 {
+       return x - y - y - y - y - y - y - y - y - y - y - y - y - y - y - y - y - y
+}
+
+//go:noinline
+func invalidMul_ssa(x uint32) uint32 {
+       return x * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y
+}
+
+// testLargeConst tests a situation where larger than 32 bit consts were passed to ADDL
+// causing an invalid instruction error.
+func testLargeConst() {
+       if want, got := uint32(268435440), invalidAdd_ssa(1); want != got {
+               println("testLargeConst add failed, wanted", want, "got", got)
+               failed = true
+       }
+       if want, got := uint32(4026531858), invalidSub_ssa(1); want != got {
+               println("testLargeConst sub failed, wanted", want, "got", got)
+               failed = true
+       }
+       if want, got := uint32(268435455), invalidMul_ssa(1); want != got {
+               println("testLargeConst mul failed, wanted", want, "got", got)
+               failed = true
+       }
+}
+
 // testArithRshConst ensures that "const >> const" right shifts correctly perform
 // sign extension on the lhs constant
 func testArithRshConst() {
@@ -394,6 +430,7 @@ func main() {
        testOverflowConstShift()
        testArithConstShift()
        testArithRshConst()
+       testLargeConst()
 
        if failed {
                panic("failed")
index c2ea6ee202028764620e37235d8d1a0c7a8f9e15..cc8c9fe87179a0e7ac4155f62cba431665cb77be 100644 (file)
@@ -77,6 +77,25 @@ func (v *Value) AuxInt32() int32 {
        }
        return int32(v.AuxInt)
 }
+
+// AuxInt2Int64 is used to sign extend the lower bits of AuxInt according to
+// the size of AuxInt specified in the opcode table.
+func (v *Value) AuxInt2Int64() int64 {
+       switch opcodeTable[v.Op].auxType {
+       case auxInt64:
+               return v.AuxInt
+       case auxInt32:
+               return int64(int32(v.AuxInt))
+       case auxInt16:
+               return int64(int16(v.AuxInt))
+       case auxInt8:
+               return int64(int8(v.AuxInt))
+       default:
+               v.Fatalf("op %s doesn't have an aux int field", v.Op)
+               return -1
+       }
+}
+
 func (v *Value) AuxFloat() float64 {
        if opcodeTable[v.Op].auxType != auxFloat {
                v.Fatalf("op %s doesn't have a float aux field", v.Op)