Commit c17b6b48 authored by Todd Neal's avatar Todd Neal

[dev.ssa] cmd/compile: truncate auxint when constructing Prog

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/19740Reviewed-by: default avatarKeith Randall <khr@golang.org>
parent 9dc1334c
......@@ -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
......
......@@ -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")
......
......@@ -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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment