Skip to content

Commit 652aebf

Browse files
cherrymuidmitshur
authored andcommitted
[release-branch.go1.14] cmd/compile, runtime: mark R12 clobbered for write barrier call on PPC64
When external linking, for large binaries, the external linker may insert a trampoline for the write barrier call, which looks 0000000005a98cc8 <__long_branch_runtime.gcWriteBarrier>: 5a98cc8: 86 01 82 3d addis r12,r2,390 5a98ccc: d8 bd 8c e9 ld r12,-16936(r12) 5a98cd0: a6 03 89 7d mtctr r12 5a98cd4: 20 04 80 4e bctr It clobbers R12 (and CTR, which is never live across a call). As at compile time we don't know whether the binary is big and what link mode will be used, I think we need to mark R12 as clobbered for write barrier call. For extra safety (future-proof) we mark caller-saved register that cannot be used for function arguments, which includes R11, as potentially clobbered as well. Updates #40851. Fixes #40938. Change-Id: Iedd901c5072f1127cc59b0a48cfeb4aaec81b519 Reviewed-on: https://go-review.googlesource.com/c/go/+/248917 Run-TryBot: Cherry Zhang <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Austin Clements <[email protected]> (cherry picked from commit b58d297) Reviewed-on: https://go-review.googlesource.com/c/go/+/249697
1 parent dd953de commit 652aebf

File tree

3 files changed

+24
-23
lines changed

3 files changed

+24
-23
lines changed

src/cmd/compile/internal/ssa/gen/PPC64Ops.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -561,9 +561,9 @@ func init() {
561561
{name: "LoweredAtomicOr8", argLength: 3, reg: gpstore, asm: "OR", faultOnNilArg0: true, hasSideEffects: true},
562562

563563
// LoweredWB invokes runtime.gcWriteBarrier. arg0=destptr, arg1=srcptr, arg2=mem, aux=runtime.gcWriteBarrier
564-
// It preserves R0 through R15, g, and its arguments R20 and R21,
564+
// It preserves R0 through R17 (except special registers R1, R2, R11, R12, R13), g, and its arguments R20 and R21,
565565
// but may clobber anything else, including R31 (REGTMP).
566-
{name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("R20"), buildReg("R21")}, clobbers: (callerSave &^ buildReg("R0 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R14 R15 R20 R21 g")) | buildReg("R31")}, clobberFlags: true, aux: "Sym", symEffect: "None"},
566+
{name: "LoweredWB", argLength: 3, reg: regInfo{inputs: []regMask{buildReg("R20"), buildReg("R21")}, clobbers: (callerSave &^ buildReg("R0 R3 R4 R5 R6 R7 R8 R9 R10 R14 R15 R16 R17 R20 R21 g")) | buildReg("R31")}, clobberFlags: true, aux: "Sym", symEffect: "None"},
567567

568568
// There are three of these functions so that they can have three different register inputs.
569569
// When we check 0 <= c <= cap (A), then 0 <= b <= c (B), then 0 <= a <= b (C), we want the

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

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/runtime/asm_ppc64x.s

+21-20
Original file line numberDiff line numberDiff line change
@@ -916,23 +916,23 @@ TEXT ·checkASM(SB),NOSPLIT,$0-1
916916
// - R20 is the destination of the write
917917
// - R21 is the value being written at R20.
918918
// It clobbers condition codes.
919-
// It does not clobber R0 through R15,
919+
// It does not clobber R0 through R17 (except special registers),
920920
// but may clobber any other register, *including* R31.
921921
TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$112
922922
// The standard prologue clobbers R31.
923-
// We use R16 and R17 as scratch registers.
924-
MOVD g_m(g), R16
925-
MOVD m_p(R16), R16
926-
MOVD (p_wbBuf+wbBuf_next)(R16), R17
923+
// We use R18 and R19 as scratch registers.
924+
MOVD g_m(g), R18
925+
MOVD m_p(R18), R18
926+
MOVD (p_wbBuf+wbBuf_next)(R18), R19
927927
// Increment wbBuf.next position.
928-
ADD $16, R17
929-
MOVD R17, (p_wbBuf+wbBuf_next)(R16)
930-
MOVD (p_wbBuf+wbBuf_end)(R16), R16
931-
CMP R16, R17
928+
ADD $16, R19
929+
MOVD R19, (p_wbBuf+wbBuf_next)(R18)
930+
MOVD (p_wbBuf+wbBuf_end)(R18), R18
931+
CMP R18, R19
932932
// Record the write.
933-
MOVD R21, -16(R17) // Record value
934-
MOVD (R20), R16 // TODO: This turns bad writes into bad reads.
935-
MOVD R16, -8(R17) // Record *slot
933+
MOVD R21, -16(R19) // Record value
934+
MOVD (R20), R18 // TODO: This turns bad writes into bad reads.
935+
MOVD R18, -8(R19) // Record *slot
936936
// Is the buffer full? (flags set in CMP above)
937937
BEQ flush
938938
ret:
@@ -956,11 +956,12 @@ flush:
956956
MOVD R8, (FIXED_FRAME+56)(R1)
957957
MOVD R9, (FIXED_FRAME+64)(R1)
958958
MOVD R10, (FIXED_FRAME+72)(R1)
959-
MOVD R11, (FIXED_FRAME+80)(R1)
960-
MOVD R12, (FIXED_FRAME+88)(R1)
959+
// R11, R12 may be clobbered by external-linker-inserted trampoline
961960
// R13 is REGTLS
962-
MOVD R14, (FIXED_FRAME+96)(R1)
963-
MOVD R15, (FIXED_FRAME+104)(R1)
961+
MOVD R14, (FIXED_FRAME+80)(R1)
962+
MOVD R15, (FIXED_FRAME+88)(R1)
963+
MOVD R16, (FIXED_FRAME+96)(R1)
964+
MOVD R17, (FIXED_FRAME+104)(R1)
964965

965966
// This takes arguments R20 and R21.
966967
CALL runtime·wbBufFlush(SB)
@@ -975,10 +976,10 @@ flush:
975976
MOVD (FIXED_FRAME+56)(R1), R8
976977
MOVD (FIXED_FRAME+64)(R1), R9
977978
MOVD (FIXED_FRAME+72)(R1), R10
978-
MOVD (FIXED_FRAME+80)(R1), R11
979-
MOVD (FIXED_FRAME+88)(R1), R12
980-
MOVD (FIXED_FRAME+96)(R1), R14
981-
MOVD (FIXED_FRAME+104)(R1), R15
979+
MOVD (FIXED_FRAME+80)(R1), R14
980+
MOVD (FIXED_FRAME+88)(R1), R15
981+
MOVD (FIXED_FRAME+96)(R1), R16
982+
MOVD (FIXED_FRAME+104)(R1), R17
982983
JMP ret
983984

984985
// Note: these functions use a special calling convention to save generated code space.

0 commit comments

Comments
 (0)