]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.regabi] cmd/compile: added limited //go:registerparams pragma for new ABI dev
authorDavid Chase <drchase@google.com>
Mon, 4 Jan 2021 18:32:10 +0000 (13:32 -0500)
committerDavid Chase <drchase@google.com>
Wed, 13 Jan 2021 15:50:04 +0000 (15:50 +0000)
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>
src/cmd/compile/internal/ir/node.go
src/cmd/compile/internal/noder/lex.go
src/cmd/compile/internal/ssagen/ssa.go
src/cmd/compile/internal/typecheck/iexport.go
src/cmd/compile/internal/typecheck/iimport.go
test/abi/regabipragma.dir/main.go [new file with mode: 0644]
test/abi/regabipragma.dir/tmp/foo.go [new file with mode: 0644]
test/abi/regabipragma.go [new file with mode: 0644]
test/abi/regabipragma.out [new file with mode: 0644]
test/run.go

index a2b6e7203b35d210fb022809bda3180b8ce1f895..a1b09b38ccd54d151291577f734bb21fe1f98bd9 100644 (file)
@@ -452,6 +452,9 @@ const (
 
        // Go command pragmas
        GoBuildPragma
+
+       RegisterParams // TODO remove after register abi is working
+
 )
 
 func AsNode(n types.Object) Node {
index 1095f3344a3f95b4d023a881e5428cba954333c9..cdca9e55f336c790ac586cf15eaf05f3894ce4a7 100644 (file)
@@ -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
        }
index 54bde20f1cdc960d0f0d044e5e27997e3df0fae2..3b542cf92a3790ffaea09ed7866fffb27f048585 100644 (file)
@@ -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)
index 4d48b80346675b6394f384c6a935abb9d30f0b76..1ba877113988064d2765e4b54eb08e35bc6e0cd6 100644 (file)
@@ -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() {
index c9effabce003e792550c8018b9ea0c6b70c28a7b..396d09263a4288cc469fa5ee7c9494d9f083f49c 100644 (file)
@@ -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() {
diff --git a/test/abi/regabipragma.dir/main.go b/test/abi/regabipragma.dir/main.go
new file mode 100644 (file)
index 0000000..d663337
--- /dev/null
@@ -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!"))
+}
diff --git a/test/abi/regabipragma.dir/tmp/foo.go b/test/abi/regabipragma.dir/tmp/foo.go
new file mode 100644 (file)
index 0000000..cff989b
--- /dev/null
@@ -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
+}
diff --git a/test/abi/regabipragma.go b/test/abi/regabipragma.go
new file mode 100644 (file)
index 0000000..93cdb6a
--- /dev/null
@@ -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
diff --git a/test/abi/regabipragma.out b/test/abi/regabipragma.out
new file mode 100644 (file)
index 0000000..7803613
--- /dev/null
@@ -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
index 1c516f4946f38975c8bfda1bbcb4c665558395fa..09f9717cc0c0484c7c182d5d4b06e96ae35ad938 100644 (file)
@@ -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