Commit 114c0596 authored by Cherry Zhang's avatar Cherry Zhang

[dev.ssa] cmd/compile: fix possible invalid pointer spill in large Zero/Move on ARM

Instead of comparing the address of the end of the memory to zero/copy,
comparing the address of the last element, which is a valid pointer.
Also unify large and unaligned Zero/Move, by passing alignment as AuxInt.

Fixes #16515 for ARM.

Change-Id: I19a62b31c5acf5c55c16a89bea1039c926dc91e5
Reviewed-on: https://go-review.googlesource.com/25300
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarDavid Chase <drchase@google.com>
parent 83208504
...@@ -797,7 +797,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -797,7 +797,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
} }
return return
} }
case ssa.OpARMDUFFZERO, ssa.OpARMLoweredZero, ssa.OpARMLoweredZeroU: case ssa.OpARMDUFFZERO, ssa.OpARMLoweredZero:
// arg0 is ptr // arg0 is ptr
if w.Args[0] == v.Args[0] { if w.Args[0] == v.Args[0] {
if gc.Debug_checknil != 0 && int(v.Line) > 1 { if gc.Debug_checknil != 0 && int(v.Line) > 1 {
...@@ -805,7 +805,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -805,7 +805,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
} }
return return
} }
case ssa.OpARMDUFFCOPY, ssa.OpARMLoweredMove, ssa.OpARMLoweredMoveU: case ssa.OpARMDUFFCOPY, ssa.OpARMLoweredMove:
// arg0 is dst ptr, arg1 is src ptr // arg0 is dst ptr, arg1 is src ptr
if w.Args[0] == v.Args[0] || w.Args[1] == v.Args[0] { if w.Args[0] == v.Args[0] || w.Args[1] == v.Args[0] {
if gc.Debug_checknil != 0 && int(v.Line) > 1 { if gc.Debug_checknil != 0 && int(v.Line) > 1 {
...@@ -835,15 +835,23 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -835,15 +835,23 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
if gc.Debug_checknil != 0 && v.Line > 1 { // v.Line==1 in generated wrappers if gc.Debug_checknil != 0 && v.Line > 1 { // v.Line==1 in generated wrappers
gc.Warnl(v.Line, "generated nil check") gc.Warnl(v.Line, "generated nil check")
} }
case ssa.OpARMLoweredZero, ssa.OpARMLoweredZeroU: case ssa.OpARMLoweredZero:
// MOVW.P Rarg2, 4(R1) // MOVW.P Rarg2, 4(R1)
// CMP Rarg1, R1 // CMP Rarg1, R1
// BLT -2(PC) // BLE -2(PC)
// arg1 is the end of memory to zero // arg1 is the address of the last element to zero
// arg2 is known to be zero // arg2 is known to be zero
var sz int64 = 4 // auxint is alignment
mov := arm.AMOVW var sz int64
if v.Op == ssa.OpARMLoweredZeroU { // unaligned var mov obj.As
switch {
case v.AuxInt%4 == 0:
sz = 4
mov = arm.AMOVW
case v.AuxInt%2 == 0:
sz = 2
mov = arm.AMOVH
default:
sz = 1 sz = 1
mov = arm.AMOVB mov = arm.AMOVB
} }
...@@ -858,18 +866,26 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -858,18 +866,26 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p2.From.Type = obj.TYPE_REG p2.From.Type = obj.TYPE_REG
p2.From.Reg = gc.SSARegNum(v.Args[1]) p2.From.Reg = gc.SSARegNum(v.Args[1])
p2.Reg = arm.REG_R1 p2.Reg = arm.REG_R1
p3 := gc.Prog(arm.ABLT) p3 := gc.Prog(arm.ABLE)
p3.To.Type = obj.TYPE_BRANCH p3.To.Type = obj.TYPE_BRANCH
gc.Patch(p3, p) gc.Patch(p3, p)
case ssa.OpARMLoweredMove, ssa.OpARMLoweredMoveU: case ssa.OpARMLoweredMove:
// MOVW.P 4(R1), Rtmp // MOVW.P 4(R1), Rtmp
// MOVW.P Rtmp, 4(R2) // MOVW.P Rtmp, 4(R2)
// CMP Rarg2, R1 // CMP Rarg2, R1
// BLT -3(PC) // BLE -3(PC)
// arg2 is the end of src // arg2 is the address of the last element of src
var sz int64 = 4 // auxint is alignment
mov := arm.AMOVW var sz int64
if v.Op == ssa.OpARMLoweredMoveU { // unaligned var mov obj.As
switch {
case v.AuxInt%4 == 0:
sz = 4
mov = arm.AMOVW
case v.AuxInt%2 == 0:
sz = 2
mov = arm.AMOVH
default:
sz = 1 sz = 1
mov = arm.AMOVB mov = arm.AMOVB
} }
...@@ -891,7 +907,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) { ...@@ -891,7 +907,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
p3.From.Type = obj.TYPE_REG p3.From.Type = obj.TYPE_REG
p3.From.Reg = gc.SSARegNum(v.Args[2]) p3.From.Reg = gc.SSARegNum(v.Args[2])
p3.Reg = arm.REG_R1 p3.Reg = arm.REG_R1
p4 := gc.Prog(arm.ABLT) p4 := gc.Prog(arm.ABLE)
p4.To.Type = obj.TYPE_BRANCH p4.To.Type = obj.TYPE_BRANCH
gc.Patch(p4, p) gc.Patch(p4, p)
case ssa.OpVarDef: case ssa.OpVarDef:
......
...@@ -302,13 +302,12 @@ ...@@ -302,13 +302,12 @@
// Large zeroing uses a loop // Large zeroing uses a loop
(Zero [s] ptr mem) (Zero [s] ptr mem)
&& SizeAndAlign(s).Size()%4 == 0 && (SizeAndAlign(s).Size() > 512 || config.noDuffDevice) && (SizeAndAlign(s).Size() > 512 || config.noDuffDevice) || SizeAndAlign(s).Align()%4 != 0 ->
&& SizeAndAlign(s).Align()%4 == 0 -> (LoweredZero [SizeAndAlign(s).Align()]
(LoweredZero ptr (ADDconst <ptr.Type> ptr [SizeAndAlign(s).Size()]) (MOVWconst [0]) mem) ptr
(ADDconst <ptr.Type> ptr [SizeAndAlign(s).Size()-moveSize(SizeAndAlign(s).Align(), config)])
// Unaligned zeroing uses a loop (MOVWconst [0])
(Zero [s] ptr mem) && SizeAndAlign(s).Size() > 4 && SizeAndAlign(s).Align()%4 != 0 -> mem)
(LoweredZeroU ptr (ADDconst <ptr.Type> ptr [SizeAndAlign(s).Size()]) (MOVWconst [0]) mem)
// moves // moves
(Move [s] _ _ mem) && SizeAndAlign(s).Size() == 0 -> mem (Move [s] _ _ mem) && SizeAndAlign(s).Size() == 0 -> mem
...@@ -343,13 +342,12 @@ ...@@ -343,13 +342,12 @@
// Large move uses a loop // Large move uses a loop
(Move [s] dst src mem) (Move [s] dst src mem)
&& SizeAndAlign(s).Size()%4 == 0 && (SizeAndAlign(s).Size() > 512 || config.noDuffDevice) && (SizeAndAlign(s).Size() > 512 || config.noDuffDevice) || SizeAndAlign(s).Align()%4 != 0 ->
&& SizeAndAlign(s).Align()%4 == 0 -> (LoweredMove [SizeAndAlign(s).Align()]
(LoweredMove dst src (ADDconst <src.Type> src [SizeAndAlign(s).Size()]) mem) dst
src
// Unaligned move uses a loop (ADDconst <src.Type> src [SizeAndAlign(s).Size()-moveSize(SizeAndAlign(s).Align(), config)])
(Move [s] dst src mem) && SizeAndAlign(s).Size() > 4 && SizeAndAlign(s).Align()%4 != 0 -> mem)
(LoweredMoveU dst src (ADDconst <src.Type> src [SizeAndAlign(s).Size()]) mem)
// calls // calls
(StaticCall [argwid] {target} mem) -> (CALLstatic [argwid] {target} mem) (StaticCall [argwid] {target} mem) -> (CALLstatic [argwid] {target} mem)
......
...@@ -415,17 +415,18 @@ func init() { ...@@ -415,17 +415,18 @@ func init() {
}, },
}, },
// large zeroing (must be 4-byte aligned) // large or unaligned zeroing
// arg0 = address of memory to zero (in R1, changed as side effect) // arg0 = address of memory to zero (in R1, changed as side effect)
// arg1 = address of the end of the memory to zero // arg1 = address of the last element to zero
// arg2 = value to store (always zero) // arg2 = value to store (always zero)
// arg3 = mem // arg3 = mem
// returns mem // returns mem
// MOVW.P Rarg2, 4(R1) // MOVW.P Rarg2, 4(R1)
// CMP R1, Rarg1 // CMP R1, Rarg1
// BLT -2(PC) // BLE -2(PC)
{ {
name: "LoweredZero", name: "LoweredZero",
aux: "Int64",
argLength: 4, argLength: 4,
reg: regInfo{ reg: regInfo{
inputs: []regMask{buildReg("R1"), gp, gp}, inputs: []regMask{buildReg("R1"), gp, gp},
...@@ -433,55 +434,19 @@ func init() { ...@@ -433,55 +434,19 @@ func init() {
}, },
}, },
// large move (must be 4-byte aligned) // large or unaligned move
// arg0 = address of dst memory (in R2, changed as side effect) // arg0 = address of dst memory (in R2, changed as side effect)
// arg1 = address of src memory (in R1, changed as side effect) // arg1 = address of src memory (in R1, changed as side effect)
// arg2 = address of the end of src memory // arg2 = address of the last element of src
// arg3 = mem // arg3 = mem
// returns mem // returns mem
// MOVW.P 4(R1), Rtmp // MOVW.P 4(R1), Rtmp
// MOVW.P Rtmp, 4(R2) // MOVW.P Rtmp, 4(R2)
// CMP R1, Rarg2 // CMP R1, Rarg2
// BLT -3(PC) // BLE -3(PC)
{ {
name: "LoweredMove", name: "LoweredMove",
argLength: 4, aux: "Int64",
reg: regInfo{
inputs: []regMask{buildReg("R2"), buildReg("R1"), gp},
clobbers: buildReg("R1 R2 FLAGS"),
},
},
// unaligned zeroing
// arg0 = address of memory to zero (in R1, changed as side effect)
// arg1 = address of the end of the memory to zero
// arg2 = value to store (always zero)
// arg3 = mem
// returns mem
// MOVB.P Rarg2, 1(R1)
// CMP R1, Rarg1
// BLT -2(PC)
{
name: "LoweredZeroU",
argLength: 4,
reg: regInfo{
inputs: []regMask{buildReg("R1"), gp, gp},
clobbers: buildReg("R1 FLAGS"),
},
},
// unaligned move
// arg0 = address of dst memory (in R2, changed as side effect)
// arg1 = address of src memory (in R1, changed as side effect)
// arg2 = address of the end of src memory
// arg3 = mem
// returns mem
// MOVB.P 1(R1), Rtmp
// MOVB.P Rtmp, 1(R2)
// CMP R1, Rarg2
// BLT -3(PC)
{
name: "LoweredMoveU",
argLength: 4, argLength: 4,
reg: regInfo{ reg: regInfo{
inputs: []regMask{buildReg("R2"), buildReg("R1"), gp}, inputs: []regMask{buildReg("R2"), buildReg("R1"), gp},
......
...@@ -786,8 +786,6 @@ const ( ...@@ -786,8 +786,6 @@ const (
OpARMDUFFCOPY OpARMDUFFCOPY
OpARMLoweredZero OpARMLoweredZero
OpARMLoweredMove OpARMLoweredMove
OpARMLoweredZeroU
OpARMLoweredMoveU
OpARMLoweredGetClosurePtr OpARMLoweredGetClosurePtr
OpARMMOVWconvert OpARMMOVWconvert
OpARMFlagEQ OpARMFlagEQ
...@@ -9880,6 +9878,7 @@ var opcodeTable = [...]opInfo{ ...@@ -9880,6 +9878,7 @@ var opcodeTable = [...]opInfo{
}, },
{ {
name: "LoweredZero", name: "LoweredZero",
auxType: auxInt64,
argLen: 4, argLen: 4,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
...@@ -9892,30 +9891,7 @@ var opcodeTable = [...]opInfo{ ...@@ -9892,30 +9891,7 @@ var opcodeTable = [...]opInfo{
}, },
{ {
name: "LoweredMove", name: "LoweredMove",
argLen: 4, auxType: auxInt64,
reg: regInfo{
inputs: []inputInfo{
{0, 4}, // R2
{1, 2}, // R1
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
clobbers: 4294967302, // R1 R2 FLAGS
},
},
{
name: "LoweredZeroU",
argLen: 4,
reg: regInfo{
inputs: []inputInfo{
{0, 2}, // R1
{1, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
{2, 5119}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12
},
clobbers: 4294967298, // R1 FLAGS
},
},
{
name: "LoweredMoveU",
argLen: 4, argLen: 4,
reg: regInfo{ reg: regInfo{
inputs: []inputInfo{ inputs: []inputInfo{
......
...@@ -10696,43 +10696,23 @@ func rewriteValueARM_OpMove(v *Value, config *Config) bool { ...@@ -10696,43 +10696,23 @@ func rewriteValueARM_OpMove(v *Value, config *Config) bool {
return true return true
} }
// match: (Move [s] dst src mem) // match: (Move [s] dst src mem)
// cond: SizeAndAlign(s).Size()%4 == 0 && (SizeAndAlign(s).Size() > 512 || config.noDuffDevice) && SizeAndAlign(s).Align()%4 == 0 // cond: (SizeAndAlign(s).Size() > 512 || config.noDuffDevice) || SizeAndAlign(s).Align()%4 != 0
// result: (LoweredMove dst src (ADDconst <src.Type> src [SizeAndAlign(s).Size()]) mem) // result: (LoweredMove [SizeAndAlign(s).Align()] dst src (ADDconst <src.Type> src [SizeAndAlign(s).Size()-moveSize(SizeAndAlign(s).Align(), config)]) mem)
for { for {
s := v.AuxInt s := v.AuxInt
dst := v.Args[0] dst := v.Args[0]
src := v.Args[1] src := v.Args[1]
mem := v.Args[2] mem := v.Args[2]
if !(SizeAndAlign(s).Size()%4 == 0 && (SizeAndAlign(s).Size() > 512 || config.noDuffDevice) && SizeAndAlign(s).Align()%4 == 0) { if !((SizeAndAlign(s).Size() > 512 || config.noDuffDevice) || SizeAndAlign(s).Align()%4 != 0) {
break break
} }
v.reset(OpARMLoweredMove) v.reset(OpARMLoweredMove)
v.AuxInt = SizeAndAlign(s).Align()
v.AddArg(dst) v.AddArg(dst)
v.AddArg(src) v.AddArg(src)
v0 := b.NewValue0(v.Line, OpARMADDconst, src.Type) v0 := b.NewValue0(v.Line, OpARMADDconst, src.Type)
v0.AddArg(src) v0.AddArg(src)
v0.AuxInt = SizeAndAlign(s).Size() v0.AuxInt = SizeAndAlign(s).Size() - moveSize(SizeAndAlign(s).Align(), config)
v.AddArg(v0)
v.AddArg(mem)
return true
}
// match: (Move [s] dst src mem)
// cond: SizeAndAlign(s).Size() > 4 && SizeAndAlign(s).Align()%4 != 0
// result: (LoweredMoveU dst src (ADDconst <src.Type> src [SizeAndAlign(s).Size()]) mem)
for {
s := v.AuxInt
dst := v.Args[0]
src := v.Args[1]
mem := v.Args[2]
if !(SizeAndAlign(s).Size() > 4 && SizeAndAlign(s).Align()%4 != 0) {
break
}
v.reset(OpARMLoweredMoveU)
v.AddArg(dst)
v.AddArg(src)
v0 := b.NewValue0(v.Line, OpARMADDconst, src.Type)
v0.AddArg(src)
v0.AuxInt = SizeAndAlign(s).Size()
v.AddArg(v0) v.AddArg(v0)
v.AddArg(mem) v.AddArg(mem)
return true return true
...@@ -16763,42 +16743,21 @@ func rewriteValueARM_OpZero(v *Value, config *Config) bool { ...@@ -16763,42 +16743,21 @@ func rewriteValueARM_OpZero(v *Value, config *Config) bool {
return true return true
} }
// match: (Zero [s] ptr mem) // match: (Zero [s] ptr mem)
// cond: SizeAndAlign(s).Size()%4 == 0 && (SizeAndAlign(s).Size() > 512 || config.noDuffDevice) && SizeAndAlign(s).Align()%4 == 0 // cond: (SizeAndAlign(s).Size() > 512 || config.noDuffDevice) || SizeAndAlign(s).Align()%4 != 0
// result: (LoweredZero ptr (ADDconst <ptr.Type> ptr [SizeAndAlign(s).Size()]) (MOVWconst [0]) mem) // result: (LoweredZero [SizeAndAlign(s).Align()] ptr (ADDconst <ptr.Type> ptr [SizeAndAlign(s).Size()-moveSize(SizeAndAlign(s).Align(), config)]) (MOVWconst [0]) mem)
for { for {
s := v.AuxInt s := v.AuxInt
ptr := v.Args[0] ptr := v.Args[0]
mem := v.Args[1] mem := v.Args[1]
if !(SizeAndAlign(s).Size()%4 == 0 && (SizeAndAlign(s).Size() > 512 || config.noDuffDevice) && SizeAndAlign(s).Align()%4 == 0) { if !((SizeAndAlign(s).Size() > 512 || config.noDuffDevice) || SizeAndAlign(s).Align()%4 != 0) {
break break
} }
v.reset(OpARMLoweredZero) v.reset(OpARMLoweredZero)
v.AuxInt = SizeAndAlign(s).Align()
v.AddArg(ptr) v.AddArg(ptr)
v0 := b.NewValue0(v.Line, OpARMADDconst, ptr.Type) v0 := b.NewValue0(v.Line, OpARMADDconst, ptr.Type)
v0.AddArg(ptr) v0.AddArg(ptr)
v0.AuxInt = SizeAndAlign(s).Size() v0.AuxInt = SizeAndAlign(s).Size() - moveSize(SizeAndAlign(s).Align(), config)
v.AddArg(v0)
v1 := b.NewValue0(v.Line, OpARMMOVWconst, config.fe.TypeUInt32())
v1.AuxInt = 0
v.AddArg(v1)
v.AddArg(mem)
return true
}
// match: (Zero [s] ptr mem)
// cond: SizeAndAlign(s).Size() > 4 && SizeAndAlign(s).Align()%4 != 0
// result: (LoweredZeroU ptr (ADDconst <ptr.Type> ptr [SizeAndAlign(s).Size()]) (MOVWconst [0]) mem)
for {
s := v.AuxInt
ptr := v.Args[0]
mem := v.Args[1]
if !(SizeAndAlign(s).Size() > 4 && SizeAndAlign(s).Align()%4 != 0) {
break
}
v.reset(OpARMLoweredZeroU)
v.AddArg(ptr)
v0 := b.NewValue0(v.Line, OpARMADDconst, ptr.Type)
v0.AddArg(ptr)
v0.AuxInt = SizeAndAlign(s).Size()
v.AddArg(v0) v.AddArg(v0)
v1 := b.NewValue0(v.Line, OpARMMOVWconst, config.fe.TypeUInt32()) v1 := b.NewValue0(v.Line, OpARMMOVWconst, config.fe.TypeUInt32())
v1.AuxInt = 0 v1.AuxInt = 0
......
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