mirror of
https://github.com/golang/go
synced 2024-11-11 20:20:23 -07:00
[dev.regabi] cmd/compile: added limited //go:registerparams pragma for new ABI dev
This only works for functions; if you try it with a method, it will fail. It does work for both local package and imports. For now, it tells you when it thinks it sees either a declaration or a call of such a function (this will normally be silent since no existing code uses this pragma). Note: it appears to be really darn hard to figure out if this pragma was set for a method, and the method's call site. Better ir.Node wranglers than I might be able to make headway, but it seemed unnecessary for this experiment. Change-Id: I601c2ddd124457bf6d62f714d7ac871705743c0a Reviewed-on: https://go-review.googlesource.com/c/go/+/279521 Trust: David Chase <drchase@google.com> Run-TryBot: David Chase <drchase@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Jeremy Faller <jeremy@golang.org>
This commit is contained in:
parent
c1370e918f
commit
861707a8c8
@ -452,6 +452,9 @@ const (
|
|||||||
|
|
||||||
// Go command pragmas
|
// Go command pragmas
|
||||||
GoBuildPragma
|
GoBuildPragma
|
||||||
|
|
||||||
|
RegisterParams // TODO remove after register abi is working
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func AsNode(n types.Object) Node {
|
func AsNode(n types.Object) Node {
|
||||||
|
@ -28,6 +28,7 @@ const (
|
|||||||
ir.Nosplit |
|
ir.Nosplit |
|
||||||
ir.Noinline |
|
ir.Noinline |
|
||||||
ir.NoCheckPtr |
|
ir.NoCheckPtr |
|
||||||
|
ir.RegisterParams | // TODO remove after register abi is working
|
||||||
ir.CgoUnsafeArgs |
|
ir.CgoUnsafeArgs |
|
||||||
ir.UintptrEscapes |
|
ir.UintptrEscapes |
|
||||||
ir.Systemstack |
|
ir.Systemstack |
|
||||||
@ -79,6 +80,8 @@ func pragmaFlag(verb string) ir.PragmaFlag {
|
|||||||
// in the argument list.
|
// in the argument list.
|
||||||
// Used in syscall/dll_windows.go.
|
// Used in syscall/dll_windows.go.
|
||||||
return ir.UintptrEscapes
|
return ir.UintptrEscapes
|
||||||
|
case "go:registerparams": // TODO remove after register abi is working
|
||||||
|
return ir.RegisterParams
|
||||||
case "go:notinheap":
|
case "go:notinheap":
|
||||||
return ir.NotInHeap
|
return ir.NotInHeap
|
||||||
}
|
}
|
||||||
|
@ -356,6 +356,13 @@ func buildssa(fn *ir.Func, worker int) *ssa.Func {
|
|||||||
if fn.Pragma&ir.Nosplit != 0 {
|
if fn.Pragma&ir.Nosplit != 0 {
|
||||||
s.f.NoSplit = true
|
s.f.NoSplit = true
|
||||||
}
|
}
|
||||||
|
if fn.Pragma&ir.RegisterParams != 0 { // TODO remove after register abi is working
|
||||||
|
if strings.Contains(name, ".") {
|
||||||
|
base.ErrorfAt(fn.Pos(), "Calls to //go:registerparams method %s won't work, remove the pragma from the declaration.", name)
|
||||||
|
}
|
||||||
|
s.f.Warnl(fn.Pos(), "Declared function %s has register params", name)
|
||||||
|
}
|
||||||
|
|
||||||
s.panics = map[funcLine]*ssa.Block{}
|
s.panics = map[funcLine]*ssa.Block{}
|
||||||
s.softFloat = s.config.SoftFloat
|
s.softFloat = s.config.SoftFloat
|
||||||
|
|
||||||
@ -4685,6 +4692,7 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
|
|||||||
}
|
}
|
||||||
|
|
||||||
testLateExpansion := false
|
testLateExpansion := false
|
||||||
|
inRegisters := false
|
||||||
|
|
||||||
switch n.Op() {
|
switch n.Op() {
|
||||||
case ir.OCALLFUNC:
|
case ir.OCALLFUNC:
|
||||||
@ -4692,6 +4700,13 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
|
|||||||
if k == callNormal && fn.Op() == ir.ONAME && fn.(*ir.Name).Class == ir.PFUNC {
|
if k == callNormal && fn.Op() == ir.ONAME && fn.(*ir.Name).Class == ir.PFUNC {
|
||||||
fn := fn.(*ir.Name)
|
fn := fn.(*ir.Name)
|
||||||
sym = fn.Sym()
|
sym = fn.Sym()
|
||||||
|
// TODO remove after register abi is working
|
||||||
|
inRegistersImported := fn.Pragma()&ir.RegisterParams != 0
|
||||||
|
inRegistersSamePackage := fn.Func != nil && fn.Func.Pragma&ir.RegisterParams != 0
|
||||||
|
inRegisters = inRegistersImported || inRegistersSamePackage
|
||||||
|
if inRegisters {
|
||||||
|
s.f.Warnl(n.Pos(), "Called function %s has register params", sym.Linksym().Name)
|
||||||
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
closure = s.expr(fn)
|
closure = s.expr(fn)
|
||||||
|
@ -976,6 +976,9 @@ func (w *exportWriter) funcExt(n *ir.Name) {
|
|||||||
w.linkname(n.Sym())
|
w.linkname(n.Sym())
|
||||||
w.symIdx(n.Sym())
|
w.symIdx(n.Sym())
|
||||||
|
|
||||||
|
// TODO remove after register abi is working.
|
||||||
|
w.uint64(uint64(n.Func.Pragma))
|
||||||
|
|
||||||
// Escape analysis.
|
// Escape analysis.
|
||||||
for _, fs := range &types.RecvsParams {
|
for _, fs := range &types.RecvsParams {
|
||||||
for _, f := range fs(n.Type()).FieldSlice() {
|
for _, f := range fs(n.Type()).FieldSlice() {
|
||||||
|
@ -647,6 +647,9 @@ func (r *importReader) funcExt(n *ir.Name) {
|
|||||||
r.linkname(n.Sym())
|
r.linkname(n.Sym())
|
||||||
r.symIdx(n.Sym())
|
r.symIdx(n.Sym())
|
||||||
|
|
||||||
|
// TODO remove after register abi is working
|
||||||
|
n.SetPragma(ir.PragmaFlag(r.uint64()))
|
||||||
|
|
||||||
// Escape analysis.
|
// Escape analysis.
|
||||||
for _, fs := range &types.RecvsParams {
|
for _, fs := range &types.RecvsParams {
|
||||||
for _, f := range fs(n.Type()).FieldSlice() {
|
for _, f := range fs(n.Type()).FieldSlice() {
|
||||||
|
36
test/abi/regabipragma.dir/main.go
Normal file
36
test/abi/regabipragma.dir/main.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// Copyright 2021 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.
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"regabipragma.dir/tmp"
|
||||||
|
)
|
||||||
|
|
||||||
|
type S string
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func (s S) ff(t string) string {
|
||||||
|
return string(s) + " " + t
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
//go:registerparams
|
||||||
|
func f(s,t string) string { // ERROR "Declared function f has register params"
|
||||||
|
return s + " " + t
|
||||||
|
}
|
||||||
|
|
||||||
|
func check(s string) {
|
||||||
|
if s != "Hello world!" {
|
||||||
|
fmt.Printf("FAIL, wanted 'Hello world!' but got '%s'\n", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
check(f("Hello", "world!")) // ERROR "Called function ...f has register params"
|
||||||
|
check(tmp.F("Hello", "world!")) // ERROR "Called function regabipragma.dir/tmp.F has register params"
|
||||||
|
check(S("Hello").ff("world!"))
|
||||||
|
check(tmp.S("Hello").FF("world!"))
|
||||||
|
}
|
19
test/abi/regabipragma.dir/tmp/foo.go
Normal file
19
test/abi/regabipragma.dir/tmp/foo.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// Copyright 2021 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.
|
||||||
|
|
||||||
|
package tmp
|
||||||
|
|
||||||
|
|
||||||
|
type S string
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func (s S) FF(t string) string {
|
||||||
|
return string(s) + " " + t
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
//go:registerparams
|
||||||
|
func F(s,t string) string {
|
||||||
|
return s + " " + t
|
||||||
|
}
|
9
test/abi/regabipragma.go
Normal file
9
test/abi/regabipragma.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// runindir
|
||||||
|
|
||||||
|
// Copyright 2021 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.
|
||||||
|
|
||||||
|
// TODO May delete or adapt this test once regabi is the default
|
||||||
|
|
||||||
|
package ignore
|
6
test/abi/regabipragma.out
Normal file
6
test/abi/regabipragma.out
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# regabipragma.dir/tmp
|
||||||
|
tmp/foo.go:17:6: Declared function F has register params
|
||||||
|
# regabipragma.dir
|
||||||
|
./main.go:21:6: Declared function f has register params
|
||||||
|
./main.go:32:9: Called function "".f has register params
|
||||||
|
./main.go:33:13: Called function regabipragma.dir/tmp.F has register params
|
@ -59,7 +59,7 @@ var (
|
|||||||
|
|
||||||
// dirs are the directories to look for *.go files in.
|
// dirs are the directories to look for *.go files in.
|
||||||
// TODO(bradfitz): just use all directories?
|
// TODO(bradfitz): just use all directories?
|
||||||
dirs = []string{".", "ken", "chan", "interface", "syntax", "dwarf", "fixedbugs", "codegen", "runtime"}
|
dirs = []string{".", "ken", "chan", "interface", "syntax", "dwarf", "fixedbugs", "codegen", "runtime", "abi"}
|
||||||
|
|
||||||
// ratec controls the max number of tests running at a time.
|
// ratec controls the max number of tests running at a time.
|
||||||
ratec chan bool
|
ratec chan bool
|
||||||
|
Loading…
Reference in New Issue
Block a user