diff options
Diffstat (limited to 'src/cmd/compile/internal/noder')
| -rw-r--r-- | src/cmd/compile/internal/noder/linker.go | 1 | ||||
| -rw-r--r-- | src/cmd/compile/internal/noder/noder.go | 9 | ||||
| -rw-r--r-- | src/cmd/compile/internal/noder/reader.go | 7 | ||||
| -rw-r--r-- | src/cmd/compile/internal/noder/writer.go | 33 |
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) } } } |
