From dde7c770ef44d45b8a9f98bf0f46556f18df2f6e Mon Sep 17 00:00:00 2001
From: Austin Clements <austin@google.com>
Date: Fri, 31 May 2019 15:45:06 -0400
Subject: [PATCH] cmd/compile: make the second argument to go:linkname optional

The //go:linkname directive can be used to make a symbol accessible to
another package (when it wouldn't normally be). Sometimes you want to
do this without actually changing the symbol's object file symbol
name; for example, in gccgo this makes unexported symbols non-static,
and in gc this provides ABI0 wrappers for Go symbols so they can be
called from assembly in other packages. Currently, this results in
stutter like

   //go:linkname entersyscall runtime.entersyscall

This CL makes the second argument to go:linkname optional for the case
where the intent is simply to expose the symbol rather than to rename
it in the object file.

Updates #31230.

Change-Id: Id06d9c4b2ec3d8e27f9b8a0d65212ab8048d734f
Reviewed-on: https://go-review.googlesource.com/c/go/+/179861
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
---
 src/cmd/compile/doc.go               |  8 +++++--
 src/cmd/compile/internal/gc/noder.go | 32 ++++++++++++++++++++++------
 2 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/src/cmd/compile/doc.go b/src/cmd/compile/doc.go
index 5291a8b0eba..5b437d6804c 100644
--- a/src/cmd/compile/doc.go
+++ b/src/cmd/compile/doc.go
@@ -216,11 +216,15 @@ not include a stack overflow check. This is most commonly used by low-level
 runtime sources invoked at times when it is unsafe for the calling goroutine to be
 preempted.
 
-	//go:linkname localname importpath.name
+	//go:linkname localname [importpath.name]
 
 The //go:linkname directive instructs the compiler to use ``importpath.name'' as the
 object file symbol name for the variable or function declared as ``localname'' in the
-source code. Because this directive can subvert the type system and package
+source code.
+If the ``importpath.name'' argument is omitted, the directive uses the
+symbol's default object file symbol name and only has the effect of making
+the symbol accessible to other packages.
+Because this directive can subvert the type system and package
 modularity, it is only enabled in files that have imported "unsafe".
 */
 package main
diff --git a/src/cmd/compile/internal/gc/noder.go b/src/cmd/compile/internal/gc/noder.go
index e83ae7c5eba..93d355278e1 100644
--- a/src/cmd/compile/internal/gc/noder.go
+++ b/src/cmd/compile/internal/gc/noder.go
@@ -244,10 +244,21 @@ func (p *noder) node() {
 	xtop = append(xtop, p.decls(p.file.DeclList)...)
 
 	for _, n := range p.linknames {
-		if imported_unsafe {
-			lookup(n.local).Linkname = n.remote
-		} else {
+		if !imported_unsafe {
 			p.yyerrorpos(n.pos, "//go:linkname only allowed in Go files that import \"unsafe\"")
+			continue
+		}
+		s := lookup(n.local)
+		if n.remote != "" {
+			s.Linkname = n.remote
+		} else {
+			// Use the default object symbol name if the
+			// user didn't provide one.
+			if myimportpath == "" {
+				p.yyerrorpos(n.pos, "//go:linkname requires linkname argument or -p compiler flag")
+			} else {
+				s.Linkname = objabi.PathToPrefix(myimportpath) + "." + n.local
+			}
 		}
 	}
 
@@ -1476,11 +1487,20 @@ func (p *noder) pragma(pos syntax.Pos, text string) syntax.Pragma {
 
 	case strings.HasPrefix(text, "go:linkname "):
 		f := strings.Fields(text)
-		if len(f) != 3 {
-			p.error(syntax.Error{Pos: pos, Msg: "usage: //go:linkname localname linkname"})
+		if !(2 <= len(f) && len(f) <= 3) {
+			p.error(syntax.Error{Pos: pos, Msg: "usage: //go:linkname localname [linkname]"})
 			break
 		}
-		p.linknames = append(p.linknames, linkname{pos, f[1], f[2]})
+		// The second argument is optional. If omitted, we use
+		// the default object symbol name for this and
+		// linkname only serves to mark this symbol as
+		// something that may be referenced via the object
+		// symbol name from another package.
+		var target string
+		if len(f) == 3 {
+			target = f[2]
+		}
+		p.linknames = append(p.linknames, linkname{pos, f[1], target})
 
 	case strings.HasPrefix(text, "go:cgo_import_dynamic "):
 		// This is permitted for general use because Solaris
-- 
GitLab