aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/noder
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/noder')
-rw-r--r--src/cmd/compile/internal/noder/linker.go1
-rw-r--r--src/cmd/compile/internal/noder/noder.go9
-rw-r--r--src/cmd/compile/internal/noder/reader.go7
-rw-r--r--src/cmd/compile/internal/noder/writer.go33
4 files changed, 36 insertions, 14 deletions
diff --git a/src/cmd/compile/internal/noder/linker.go b/src/cmd/compile/internal/noder/linker.go
index 51b03a1897..df1e248398 100644
--- a/src/cmd/compile/internal/noder/linker.go
+++ b/src/cmd/compile/internal/noder/linker.go
@@ -338,6 +338,7 @@ func (l *linker) linkname(w *pkgbits.Encoder, name *ir.Name) {
linkname := name.Sym().Linkname
if !l.lsymIdx(w, linkname, name.Linksym()) {
w.String(linkname)
+ w.Bool(name.Linksym().IsLinknameStd())
}
}
diff --git a/src/cmd/compile/internal/noder/noder.go b/src/cmd/compile/internal/noder/noder.go
index 973d917784..4e48126e82 100644
--- a/src/cmd/compile/internal/noder/noder.go
+++ b/src/cmd/compile/internal/noder/noder.go
@@ -103,9 +103,10 @@ type noder struct {
err chan syntax.Error
}
-// linkname records a //go:linkname directive.
+// linkname records a //go:linkname or //go:linknamestd directive.
type linkname struct {
pos syntax.Pos
+ std bool
local string
remote string
}
@@ -273,10 +274,10 @@ func (p *noder) pragma(pos syntax.Pos, blankLine bool, text string, old syntax.P
}
}
- case strings.HasPrefix(text, "go:linkname "):
+ case strings.HasPrefix(text, "go:linkname "), strings.HasPrefix(text, "go:linknamestd "):
f := strings.Fields(text)
if !(2 <= len(f) && len(f) <= 3) {
- p.error(syntax.Error{Pos: pos, Msg: "usage: //go:linkname localname [linkname]"})
+ p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("usage: //%s localname [linkname]", f[0])})
break
}
// The second argument is optional. If omitted, we use
@@ -294,7 +295,7 @@ func (p *noder) pragma(pos syntax.Pos, blankLine bool, text string, old syntax.P
} else {
panic("missing pkgpath")
}
- p.linknames = append(p.linknames, linkname{pos, f[1], target})
+ p.linknames = append(p.linknames, linkname{pos, f[0] == "go:linknamestd", f[1], target})
case text == "go:embed", strings.HasPrefix(text, "go:embed "):
args, err := parseGoEmbed(text[len("go:embed"):])
diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go
index 00710775d6..ebb5043a05 100644
--- a/src/cmd/compile/internal/noder/reader.go
+++ b/src/cmd/compile/internal/noder/reader.go
@@ -1277,6 +1277,7 @@ func (r *reader) linkname(name *ir.Name) {
lsym.Set(obj.AttrIndexed, true)
} else {
linkname := r.String()
+ std := r.Bool()
sym := name.Sym()
sym.Linkname = linkname
if sym.Pkg == types.LocalPkg && linkname != "" {
@@ -1286,7 +1287,11 @@ func (r *reader) linkname(name *ir.Name) {
// corresponding packages). So we can tell in which package
// the linkname is used (pulled), and the linker can
// make a decision for allowing or disallowing it.
- sym.Linksym().Set(obj.AttrLinkname, true)
+ if std {
+ sym.Linksym().Set(obj.AttrLinknameStd, true)
+ } else {
+ sym.Linksym().Set(obj.AttrLinkname, true)
+ }
}
}
}
diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go
index 9e0f4fc9c8..027d7e0636 100644
--- a/src/cmd/compile/internal/noder/writer.go
+++ b/src/cmd/compile/internal/noder/writer.go
@@ -86,8 +86,11 @@ type pkgWriter struct {
typDecls map[*types2.TypeName]typeDeclGen
// linknames maps package-scope objects to their linker symbol name,
- // if specified by a //go:linkname directive.
- linknames map[types2.Object]string
+ // if specified by a //go:linkname or //go:linknamestd directive.
+ linknames map[types2.Object]struct {
+ remote string
+ std bool
+ }
// cgoPragmas accumulates any //go:cgo_* pragmas that need to be
// passed through to cmd/link.
@@ -114,7 +117,10 @@ func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info, otherInfo ma
funDecls: make(map[*types2.Func]*syntax.FuncDecl),
typDecls: make(map[*types2.TypeName]typeDeclGen),
- linknames: make(map[types2.Object]string),
+ linknames: make(map[types2.Object]struct {
+ remote string
+ std bool
+ }),
}
}
@@ -1175,7 +1181,9 @@ func (w *writer) varExt(obj *types2.Var) {
func (w *writer) linkname(obj types2.Object) {
w.Sync(pkgbits.SyncLinkname)
w.Int64(-1)
- w.String(w.p.linknames[obj])
+ info := w.p.linknames[obj]
+ w.String(info.remote)
+ w.Bool(info.std)
}
func (w *writer) pragmaFlag(p ir.PragmaFlag) {
@@ -2799,26 +2807,33 @@ func (pw *pkgWriter) collectDecls(noders []*noder) {
pw.cgoPragmas = append(pw.cgoPragmas, p.pragcgobuf...)
for _, l := range p.linknames {
+ directive := "go:linkname"
+ if l.std {
+ directive = "go:linknamestd"
+ }
if !file.importedUnsafe {
- pw.errorf(l.pos, "//go:linkname only allowed in Go files that import \"unsafe\"")
+ pw.errorf(l.pos, "//%s only allowed in Go files that import \"unsafe\"", directive)
continue
}
if strings.Contains(l.remote, "[") && strings.Contains(l.remote, "]") {
- pw.errorf(l.pos, "//go:linkname reference of an instantiation is not allowed")
+ pw.errorf(l.pos, "//%s reference of an instantiation is not allowed", directive)
continue
}
switch obj := pw.curpkg.Scope().Lookup(l.local).(type) {
case *types2.Func, *types2.Var:
if _, ok := pw.linknames[obj]; !ok {
- pw.linknames[obj] = l.remote
+ pw.linknames[obj] = struct {
+ remote string
+ std bool
+ }{l.remote, l.std}
} else {
- pw.errorf(l.pos, "duplicate //go:linkname for %s", l.local)
+ pw.errorf(l.pos, "duplicate //%s for %s", directive, l.local)
}
default:
if types.AllowsGoVersion(1, 18) {
- pw.errorf(l.pos, "//go:linkname must refer to declared function or variable")
+ pw.errorf(l.pos, "//%s must refer to declared function or variable", directive)
}
}
}