Skip to content

Commit af7eafd

Browse files
committed
cmd/compile: convert 386 port to use addressing modes pass (take 2)
Retrying CL 222782, with a fix that will hopefully stop the random crashing. The issue with the previous CL is that it does pointer arithmetic in a way that may briefly generate an out-of-bounds pointer. If an interrupt happens to occur in that state, the referenced object may be collected incorrectly. Suppose there was code that did s[x+c]. The previous CL had a rule to the effect of ptr + (x + c) -> c + (ptr + x). But ptr+x is not guaranteed to point to the same object as ptr. In contrast, ptr+(x+c) is guaranteed to point to the same object as ptr, because we would have already checked that x+c is in bounds. For example, strconv.trim used to have this code: MOVZX -0x1(BX)(DX*1), BP CMPL $0x30, AL After CL 222782, it had this code: LEAL 0(BX)(DX*1), BP CMPB $0x30, -0x1(BP) An interrupt between those last two instructions could see BP pointing outside the backing store of the slice involved. It's really hard to actually demonstrate a bug. First, you need to have an interrupt occur at exactly the right time. Then, there must be no other pointers to the object in question. Since the interrupted frame will be scanned conservatively, there can't even be a dead pointer in another register or on the stack. (In the example above, a bug can't happen because BX still holds the original pointer.) Then, the object in question needs to be collected (or at least scanned?) before the interrupted code continues. This CL needs to handle load combining somewhat differently than CL 222782 because of the new restriction on arithmetic. That's the only real difference (other than removing the bad rules) from that old CL. This bug is also present in the amd64 rewrite rules, and we haven't seen any crashing as a result. I will fix up that code similarly to this one in a separate CL. Update #37881 Change-Id: I5f0d584d9bef4696bfe89a61ef0a27c8d507329f Reviewed-on: https://go-review.googlesource.com/c/go/+/225798 Run-TryBot: Keith Randall <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Cherry Zhang <[email protected]>
1 parent 4a8b9bd commit af7eafd

File tree

9 files changed

+1270
-5325
lines changed

9 files changed

+1270
-5325
lines changed

src/cmd/compile/internal/ssa/addressingmodes.go

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ func addressingModes(f *Func) {
1111
default:
1212
// Most architectures can't do this.
1313
return
14-
case "amd64":
15-
// TODO: 386, s390x?
14+
case "amd64", "386":
15+
// TODO: s390x?
1616
}
1717

1818
var tmp []*Value
@@ -21,7 +21,17 @@ func addressingModes(f *Func) {
2121
if !combineFirst[v.Op] {
2222
continue
2323
}
24-
p := v.Args[0]
24+
// All matched operations have the pointer in arg[0].
25+
// All results have the pointer in arg[0] and the index in arg[1].
26+
// *Except* for operations which update a register,
27+
// which are marked with resultInArg0. Those have
28+
// the pointer in arg[1], and the corresponding result op
29+
// has the pointer in arg[1] and the index in arg[2].
30+
ptrIndex := 0
31+
if opcodeTable[v.Op].resultInArg0 {
32+
ptrIndex = 1
33+
}
34+
p := v.Args[ptrIndex]
2535
c, ok := combine[[2]Op{v.Op, p.Op}]
2636
if !ok {
2737
continue
@@ -71,10 +81,11 @@ func addressingModes(f *Func) {
7181
f.Fatalf("unknown aux combining for %s and %s\n", v.Op, p.Op)
7282
}
7383
// Combine the operations.
74-
tmp = append(tmp[:0], v.Args[1:]...)
84+
tmp = append(tmp[:0], v.Args[:ptrIndex]...)
85+
tmp = append(tmp, p.Args...)
86+
tmp = append(tmp, v.Args[ptrIndex+1:]...)
7587
v.resetArgs()
7688
v.Op = c
77-
v.AddArgs(p.Args...)
7889
v.AddArgs(tmp...)
7990
}
8091
}
@@ -97,6 +108,7 @@ func init() {
97108
// x.Args[0].Args + x.Args[1:]
98109
// Additionally, the Aux/AuxInt from x.Args[0] is merged into x.
99110
var combine = map[[2]Op]Op{
111+
// amd64
100112
[2]Op{OpAMD64MOVBload, OpAMD64ADDQ}: OpAMD64MOVBloadidx1,
101113
[2]Op{OpAMD64MOVWload, OpAMD64ADDQ}: OpAMD64MOVWloadidx1,
102114
[2]Op{OpAMD64MOVLload, OpAMD64ADDQ}: OpAMD64MOVLloadidx1,
@@ -150,5 +162,64 @@ var combine = map[[2]Op]Op{
150162
[2]Op{OpAMD64MOVQstoreconst, OpAMD64LEAQ1}: OpAMD64MOVQstoreconstidx1,
151163
[2]Op{OpAMD64MOVQstoreconst, OpAMD64LEAQ8}: OpAMD64MOVQstoreconstidx8,
152164

153-
// TODO: 386
165+
// 386
166+
[2]Op{Op386MOVBload, Op386ADDL}: Op386MOVBloadidx1,
167+
[2]Op{Op386MOVWload, Op386ADDL}: Op386MOVWloadidx1,
168+
[2]Op{Op386MOVLload, Op386ADDL}: Op386MOVLloadidx1,
169+
[2]Op{Op386MOVSSload, Op386ADDL}: Op386MOVSSloadidx1,
170+
[2]Op{Op386MOVSDload, Op386ADDL}: Op386MOVSDloadidx1,
171+
172+
[2]Op{Op386MOVBstore, Op386ADDL}: Op386MOVBstoreidx1,
173+
[2]Op{Op386MOVWstore, Op386ADDL}: Op386MOVWstoreidx1,
174+
[2]Op{Op386MOVLstore, Op386ADDL}: Op386MOVLstoreidx1,
175+
[2]Op{Op386MOVSSstore, Op386ADDL}: Op386MOVSSstoreidx1,
176+
[2]Op{Op386MOVSDstore, Op386ADDL}: Op386MOVSDstoreidx1,
177+
178+
[2]Op{Op386MOVBstoreconst, Op386ADDL}: Op386MOVBstoreconstidx1,
179+
[2]Op{Op386MOVWstoreconst, Op386ADDL}: Op386MOVWstoreconstidx1,
180+
[2]Op{Op386MOVLstoreconst, Op386ADDL}: Op386MOVLstoreconstidx1,
181+
182+
[2]Op{Op386MOVBload, Op386LEAL1}: Op386MOVBloadidx1,
183+
[2]Op{Op386MOVWload, Op386LEAL1}: Op386MOVWloadidx1,
184+
[2]Op{Op386MOVWload, Op386LEAL2}: Op386MOVWloadidx2,
185+
[2]Op{Op386MOVLload, Op386LEAL1}: Op386MOVLloadidx1,
186+
[2]Op{Op386MOVLload, Op386LEAL4}: Op386MOVLloadidx4,
187+
[2]Op{Op386MOVSSload, Op386LEAL1}: Op386MOVSSloadidx1,
188+
[2]Op{Op386MOVSSload, Op386LEAL4}: Op386MOVSSloadidx4,
189+
[2]Op{Op386MOVSDload, Op386LEAL1}: Op386MOVSDloadidx1,
190+
[2]Op{Op386MOVSDload, Op386LEAL8}: Op386MOVSDloadidx8,
191+
192+
[2]Op{Op386MOVBstore, Op386LEAL1}: Op386MOVBstoreidx1,
193+
[2]Op{Op386MOVWstore, Op386LEAL1}: Op386MOVWstoreidx1,
194+
[2]Op{Op386MOVWstore, Op386LEAL2}: Op386MOVWstoreidx2,
195+
[2]Op{Op386MOVLstore, Op386LEAL1}: Op386MOVLstoreidx1,
196+
[2]Op{Op386MOVLstore, Op386LEAL4}: Op386MOVLstoreidx4,
197+
[2]Op{Op386MOVSSstore, Op386LEAL1}: Op386MOVSSstoreidx1,
198+
[2]Op{Op386MOVSSstore, Op386LEAL4}: Op386MOVSSstoreidx4,
199+
[2]Op{Op386MOVSDstore, Op386LEAL1}: Op386MOVSDstoreidx1,
200+
[2]Op{Op386MOVSDstore, Op386LEAL8}: Op386MOVSDstoreidx8,
201+
202+
[2]Op{Op386MOVBstoreconst, Op386LEAL1}: Op386MOVBstoreconstidx1,
203+
[2]Op{Op386MOVWstoreconst, Op386LEAL1}: Op386MOVWstoreconstidx1,
204+
[2]Op{Op386MOVWstoreconst, Op386LEAL2}: Op386MOVWstoreconstidx2,
205+
[2]Op{Op386MOVLstoreconst, Op386LEAL1}: Op386MOVLstoreconstidx1,
206+
[2]Op{Op386MOVLstoreconst, Op386LEAL4}: Op386MOVLstoreconstidx4,
207+
208+
[2]Op{Op386ADDLload, Op386LEAL4}: Op386ADDLloadidx4,
209+
[2]Op{Op386SUBLload, Op386LEAL4}: Op386SUBLloadidx4,
210+
[2]Op{Op386MULLload, Op386LEAL4}: Op386MULLloadidx4,
211+
[2]Op{Op386ANDLload, Op386LEAL4}: Op386ANDLloadidx4,
212+
[2]Op{Op386ORLload, Op386LEAL4}: Op386ORLloadidx4,
213+
[2]Op{Op386XORLload, Op386LEAL4}: Op386XORLloadidx4,
214+
215+
[2]Op{Op386ADDLmodify, Op386LEAL4}: Op386ADDLmodifyidx4,
216+
[2]Op{Op386SUBLmodify, Op386LEAL4}: Op386SUBLmodifyidx4,
217+
[2]Op{Op386ANDLmodify, Op386LEAL4}: Op386ANDLmodifyidx4,
218+
[2]Op{Op386ORLmodify, Op386LEAL4}: Op386ORLmodifyidx4,
219+
[2]Op{Op386XORLmodify, Op386LEAL4}: Op386XORLmodifyidx4,
220+
221+
[2]Op{Op386ADDLconstmodify, Op386LEAL4}: Op386ADDLconstmodifyidx4,
222+
[2]Op{Op386ANDLconstmodify, Op386LEAL4}: Op386ANDLconstmodifyidx4,
223+
[2]Op{Op386ORLconstmodify, Op386LEAL4}: Op386ORLconstmodifyidx4,
224+
[2]Op{Op386XORLconstmodify, Op386LEAL4}: Op386XORLconstmodifyidx4,
154225
}

0 commit comments

Comments
 (0)