Skip to content

Commit

Permalink
cmd/compile: make sure address of offset(SP) is rematerializeable
Browse files Browse the repository at this point in the history
An address of offset(SP) may point to the callee args area, and
may be used to move things into/out of the args/results. If an
address like that is spilled and picked up by the GC, it may hold
an arg/result live in the callee, which may not actually be live
(e.g. a result not initialized at function entry). Make sure
they are rematerializeable, so they are always short-lived and
never picked up by the GC.

This CL changes 386, PPC64, and Wasm. On AMD64 we already have
the rule (line 2159). On other architectures, we already have
similar rules like
(OffPtr [off] ptr:(SP)) => (MOVDaddr [int32(off)] ptr)
to avoid this problem. (Probably me in the past had run into
this...)

Fixes #42944.

Change-Id: Id2ec73ac08f8df1829a9a7ceb8f749d67fe86d1e
Reviewed-on: https://go-review.googlesource.com/c/go/+/275174
Trust: Cherry Zhang <[email protected]>
Run-TryBot: Cherry Zhang <[email protected]>
TryBot-Result: Go Bot <[email protected]>
Reviewed-by: Keith Randall <[email protected]>
  • Loading branch information
cherrymui committed Dec 3, 2020
1 parent b78b427 commit 37a32a1
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/cmd/compile/internal/ssa/gen/386.rules
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,7 @@
// fold ADDL into LEAL
(ADDLconst [c] (LEAL [d] {s} x)) && is32Bit(int64(c)+int64(d)) => (LEAL [c+d] {s} x)
(LEAL [c] {s} (ADDLconst [d] x)) && is32Bit(int64(c)+int64(d)) => (LEAL [c+d] {s} x)
(ADDLconst [c] x:(SP)) => (LEAL [c] x) // so it is rematerializeable
(LEAL [c] {s} (ADDL x y)) && x.Op != OpSB && y.Op != OpSB => (LEAL1 [c] {s} x y)
(ADDL x (LEAL [c] {s} y)) && x.Op != OpSB && y.Op != OpSB => (LEAL1 [c] {s} x y)

Expand Down
1 change: 1 addition & 0 deletions src/cmd/compile/internal/ssa/gen/PPC64.rules
Original file line number Diff line number Diff line change
Expand Up @@ -845,6 +845,7 @@
(SUB x (MOVDconst [c])) && is32Bit(-c) => (ADDconst [-c] x)

(ADDconst [c] (MOVDaddr [d] {sym} x)) && is32Bit(c+int64(d)) => (MOVDaddr [int32(c+int64(d))] {sym} x)
(ADDconst [c] x:(SP)) && is32Bit(c) => (MOVDaddr [int32(c)] x) // so it is rematerializeable

(MULL(W|D) x (MOVDconst [c])) && is16Bit(c) => (MULL(W|D)const [int32(c)] x)

Expand Down
1 change: 1 addition & 0 deletions src/cmd/compile/internal/ssa/gen/Wasm.rules
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@
// folding offset into address
(I64AddConst [off] (LoweredAddr {sym} [off2] base)) && isU32Bit(off+int64(off2)) =>
(LoweredAddr {sym} [int32(off)+off2] base)
(I64AddConst [off] x:(SP)) && isU32Bit(off) => (LoweredAddr [int32(off)] x) // so it is rematerializeable

// transforming readonly globals into constants
(I64Load [off] (LoweredAddr {sym} [off2] (SB)) _) && symIsRO(sym) && isU32Bit(off+int64(off2)) => (I64Const [int64(read64(sym, off+int64(off2), config.ctxt.Arch.ByteOrder))])
Expand Down
13 changes: 13 additions & 0 deletions src/cmd/compile/internal/ssa/rewrite386.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions src/cmd/compile/internal/ssa/rewritePPC64.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions src/cmd/compile/internal/ssa/rewriteWasm.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions src/cmd/compile/internal/wasm/ssa.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,12 @@ func ssaGenValueOnStack(s *gc.SSAGenState, v *ssa.Value, extend bool) {
}

case ssa.OpWasmLoweredAddr:
if v.Aux == nil { // address of off(SP), no symbol
getValue64(s, v.Args[0])
i64Const(s, v.AuxInt)
s.Prog(wasm.AI64Add)
break
}
p := s.Prog(wasm.AGet)
p.From.Type = obj.TYPE_ADDR
switch v.Aux.(type) {
Expand Down
24 changes: 24 additions & 0 deletions test/fixedbugs/issue42944.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// errorcheck -0 -live

// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Issue 42944: address of callee args area should only be short-lived
// and never across a call.

package p

type T [10]int // trigger DUFFCOPY when passing by value, so it uses the address

func F() {
var x T
var i int
for {
x = G(i) // no autotmp live at this and next calls
H(i, x)
}
}

func G(int) T
func H(int, T)

0 comments on commit 37a32a1

Please sign in to comment.