mirror of
https://github.com/golang/go
synced 2024-11-26 05:17:58 -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
|
||||
GoBuildPragma
|
||||
|
||||
RegisterParams // TODO remove after register abi is working
|
||||
|
||||
)
|
||||
|
||||
func AsNode(n types.Object) Node {
|
||||
|
@ -28,6 +28,7 @@ const (
|
||||
ir.Nosplit |
|
||||
ir.Noinline |
|
||||
ir.NoCheckPtr |
|
||||
ir.RegisterParams | // TODO remove after register abi is working
|
||||
ir.CgoUnsafeArgs |
|
||||
ir.UintptrEscapes |
|
||||
ir.Systemstack |
|
||||
@ -79,6 +80,8 @@ func pragmaFlag(verb string) ir.PragmaFlag {
|
||||
// in the argument list.
|
||||
// Used in syscall/dll_windows.go.
|
||||
return ir.UintptrEscapes
|
||||
case "go:registerparams": // TODO remove after register abi is working
|
||||
return ir.RegisterParams
|
||||
case "go:notinheap":
|
||||
return ir.NotInHeap
|
||||
}
|
||||
|
@ -356,6 +356,13 @@ func buildssa(fn *ir.Func, worker int) *ssa.Func {
|
||||
if fn.Pragma&ir.Nosplit != 0 {
|
||||
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.softFloat = s.config.SoftFloat
|
||||
|
||||
@ -4685,6 +4692,7 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool) *ssa.Val
|
||||
}
|
||||
|
||||
testLateExpansion := false
|
||||
inRegisters := false
|
||||
|
||||
switch n.Op() {
|
||||
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 {
|
||||
fn := fn.(*ir.Name)
|
||||
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
|
||||
}
|
||||
closure = s.expr(fn)
|
||||
|
@ -976,6 +976,9 @@ func (w *exportWriter) funcExt(n *ir.Name) {
|
||||
w.linkname(n.Sym())
|
||||
w.symIdx(n.Sym())
|
||||
|
||||
// TODO remove after register abi is working.
|
||||
w.uint64(uint64(n.Func.Pragma))
|
||||
|
||||
// Escape analysis.
|
||||
for _, fs := range &types.RecvsParams {
|
||||
for _, f := range fs(n.Type()).FieldSlice() {
|
||||
|
@ -647,6 +647,9 @@ func (r *importReader) funcExt(n *ir.Name) {
|
||||
r.linkname(n.Sym())
|
||||
r.symIdx(n.Sym())
|
||||
|
||||
// TODO remove after register abi is working
|
||||
n.SetPragma(ir.PragmaFlag(r.uint64()))
|
||||
|
||||
// Escape analysis.
|
||||
for _, fs := range &types.RecvsParams {
|
||||
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.
|
||||
// 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 chan bool
|
||||
|
Loading…
Reference in New Issue
Block a user