[dev.regabi] cmd/compile: refactor Linksym creation

Currently there's a lot of logic within package types for creating
Linksyms. This CL pulls it out into base, where it can be more easily
reused by other compiler code that shouldn't need to depend on package
types.

Package base probably isn't the best place for this, but it's
convenient because it's a package that types already depends on. It's
also where the Ctxt object lives, which these functions depend upon.

Passes toolstash -cmp w/ -gcflags=all=-abiwrap.

Change-Id: I50d8b7e4596955205036969eab24d7dab053b363
Reviewed-on: https://go-review.googlesource.com/c/go/+/284231
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Trust: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Matthew Dempsky 2021-01-17 02:38:41 -08:00
parent 4f5c603c0f
commit 4a4212c0e5
10 changed files with 67 additions and 53 deletions

View file

@ -6,12 +6,8 @@ package base
import ( import (
"os" "os"
"cmd/internal/obj"
) )
var Ctxt *obj.Link
var atExitFuncs []func() var atExitFuncs []func()
func AtExit(f func()) { func AtExit(f func()) {

View 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 base
import (
"cmd/internal/obj"
)
var Ctxt *obj.Link
// TODO(mdempsky): These should probably be obj.Link methods.
// PkgLinksym returns the linker symbol for name within the given
// package prefix. For user packages, prefix should be the package
// path encoded with objabi.PathToPrefix.
func PkgLinksym(prefix, name string, abi obj.ABI) *obj.LSym {
if name == "_" {
// TODO(mdempsky): Cleanup callers and Fatalf instead.
return linksym(prefix, "_", abi)
}
return linksym(prefix, prefix+"."+name, abi)
}
// Linkname returns the linker symbol for the given name as it might
// appear within a //go:linkname directive.
func Linkname(name string, abi obj.ABI) *obj.LSym {
return linksym("_", name, abi)
}
// linksym is an internal helper function for implementing the above
// exported APIs.
func linksym(pkg, name string, abi obj.ABI) *obj.LSym {
return Ctxt.LookupABIInit(name, abi, func(r *obj.LSym) { r.Pkg = pkg })
}

View file

@ -28,7 +28,7 @@ func Info(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.Scope,
if fn.Nname != nil { if fn.Nname != nil {
expect := fn.Linksym() expect := fn.Linksym()
if fnsym.ABI() == obj.ABI0 { if fnsym.ABI() == obj.ABI0 {
expect = fn.Sym().LinksymABI0() expect = fn.LinksymABI(obj.ABI0)
} }
if fnsym != expect { if fnsym != expect {
base.Fatalf("unexpected fnsym: %v != %v", fnsym, expect) base.Fatalf("unexpected fnsym: %v != %v", fnsym, expect)

View file

@ -136,6 +136,7 @@ func (n *Func) editChildren(edit func(Node) Node) { editNodes(n.Body, edit) }
func (f *Func) Type() *types.Type { return f.Nname.Type() } func (f *Func) Type() *types.Type { return f.Nname.Type() }
func (f *Func) Sym() *types.Sym { return f.Nname.Sym() } func (f *Func) Sym() *types.Sym { return f.Nname.Sym() }
func (f *Func) Linksym() *obj.LSym { return f.Nname.Linksym() } func (f *Func) Linksym() *obj.LSym { return f.Nname.Linksym() }
func (f *Func) LinksymABI(abi obj.ABI) *obj.LSym { return f.Nname.LinksymABI(abi) }
// An Inline holds fields used for function bodies that can be inlined. // An Inline holds fields used for function bodies that can be inlined.
type Inline struct { type Inline struct {

View file

@ -227,6 +227,7 @@ func (n *Name) SetWalkdef(x uint8) {
} }
func (n *Name) Linksym() *obj.LSym { return n.sym.Linksym() } func (n *Name) Linksym() *obj.LSym { return n.sym.Linksym() }
func (n *Name) LinksymABI(abi obj.ABI) *obj.LSym { return n.sym.LinksymABI(abi) }
func (*Name) CanBeNtype() {} func (*Name) CanBeNtype() {}
func (*Name) CanBeAnSSASym() {} func (*Name) CanBeAnSSASym() {}

View file

@ -161,11 +161,11 @@ func selectLSym(f *ir.Func, hasBody bool) {
var wrapperABI obj.ABI var wrapperABI obj.ABI
needABIWrapper := false needABIWrapper := false
defABI, hasDefABI := symabiDefs[nam.Sym().LinksymName()] defABI, hasDefABI := symabiDefs[nam.Linksym().Name]
if hasDefABI && defABI == obj.ABI0 { if hasDefABI && defABI == obj.ABI0 {
// Symbol is defined as ABI0. Create an // Symbol is defined as ABI0. Create an
// Internal -> ABI0 wrapper. // Internal -> ABI0 wrapper.
f.LSym = nam.Sym().LinksymABI0() f.LSym = nam.LinksymABI(obj.ABI0)
needABIWrapper, wrapperABI = true, obj.ABIInternal needABIWrapper, wrapperABI = true, obj.ABIInternal
} else { } else {
f.LSym = nam.Linksym() f.LSym = nam.Linksym()

View file

@ -7403,9 +7403,9 @@ func callTargetLSym(callee *ir.Name, callerLSym *obj.LSym) *obj.LSym {
} }
} else { } else {
// check for case 2 above // check for case 2 above
defABI, hasDefABI := symabiDefs[callee.Sym().LinksymName()] defABI, hasDefABI := symabiDefs[lsym.Name]
if hasDefABI && defABI == obj.ABI0 { if hasDefABI && defABI == obj.ABI0 {
lsym = callee.Sym().LinksymABI0() lsym = callee.LinksymABI(obj.ABI0)
} }
} }
return lsym return lsym

View file

@ -287,7 +287,7 @@ func NeedFuncSym(s *types.Sym) {
func WriteFuncSyms() { func WriteFuncSyms() {
sort.Slice(funcsyms, func(i, j int) bool { sort.Slice(funcsyms, func(i, j int) bool {
return funcsyms[i].LinksymName() < funcsyms[j].LinksymName() return funcsyms[i].Linksym().Name < funcsyms[j].Linksym().Name
}) })
for _, s := range funcsyms { for _, s := range funcsyms {
sf := s.Pkg.Lookup(ir.FuncSymName(s)).Linksym() sf := s.Pkg.Lookup(ir.FuncSymName(s)).Linksym()

View file

@ -86,14 +86,17 @@ func InitRuntime() {
// LookupRuntimeFunc looks up Go function name in package runtime. This function // LookupRuntimeFunc looks up Go function name in package runtime. This function
// must follow the internal calling convention. // must follow the internal calling convention.
func LookupRuntimeFunc(name string) *obj.LSym { func LookupRuntimeFunc(name string) *obj.LSym {
s := ir.Pkgs.Runtime.Lookup(name) return LookupRuntimeABI(name, obj.ABIInternal)
s.SetFunc(true)
return s.Linksym()
} }
// LookupRuntimeVar looks up a variable (or assembly function) name in package // LookupRuntimeVar looks up a variable (or assembly function) name in package
// runtime. If this is a function, it may have a special calling // runtime. If this is a function, it may have a special calling
// convention. // convention.
func LookupRuntimeVar(name string) *obj.LSym { func LookupRuntimeVar(name string) *obj.LSym {
return ir.Pkgs.Runtime.Lookup(name).Linksym() return LookupRuntimeABI(name, obj.ABI0)
}
// LookupRuntimeABI looks up a name in package runtime using the given ABI.
func LookupRuntimeABI(name string, abi obj.ABI) *obj.LSym {
return base.PkgLinksym("runtime", name, abi)
} }

View file

@ -64,53 +64,30 @@ func (sym *Sym) IsBlank() bool {
return sym != nil && sym.Name == "_" return sym != nil && sym.Name == "_"
} }
func (sym *Sym) LinksymName() string {
if sym.IsBlank() {
return "_"
}
if sym.Linkname != "" {
return sym.Linkname
}
return sym.Pkg.Prefix + "." + sym.Name
}
// Deprecated: This method should not be used directly. Instead, use a // Deprecated: This method should not be used directly. Instead, use a
// higher-level abstraction that directly returns the linker symbol // higher-level abstraction that directly returns the linker symbol
// for a named object. For example, reflectdata.TypeLinksym(t) instead // for a named object. For example, reflectdata.TypeLinksym(t) instead
// of reflectdata.TypeSym(t).Linksym(). // of reflectdata.TypeSym(t).Linksym().
func (sym *Sym) Linksym() *obj.LSym { func (sym *Sym) Linksym() *obj.LSym {
if sym == nil { abi := obj.ABI0
return nil
}
initPkg := func(r *obj.LSym) {
if sym.Linkname != "" {
r.Pkg = "_"
} else {
r.Pkg = sym.Pkg.Prefix
}
}
if sym.Func() { if sym.Func() {
// This is a function symbol. Mark it as "internal ABI". abi = obj.ABIInternal
return base.Ctxt.LookupABIInit(sym.LinksymName(), obj.ABIInternal, initPkg)
} }
return base.Ctxt.LookupInit(sym.LinksymName(), initPkg) return sym.LinksymABI(abi)
} }
// LinksymABI0 looks up or creates an ABI0 linker symbol for "sym", // Deprecated: This method should not be used directly. Instead, use a
// in cases where we want to specifically select the ABI0 version of // higher-level abstraction that directly returns the linker symbol
// a symbol (typically used only for ABI wrappers). // for a named object. For example, (*ir.Name).LinksymABI(abi) instead
func (sym *Sym) LinksymABI0() *obj.LSym { // of (*ir.Name).Sym().LinksymABI(abi).
func (sym *Sym) LinksymABI(abi obj.ABI) *obj.LSym {
if sym == nil { if sym == nil {
return nil base.Fatalf("nil symbol")
} }
initPkg := func(r *obj.LSym) {
if sym.Linkname != "" { if sym.Linkname != "" {
r.Pkg = "_" return base.Linkname(sym.Linkname, abi)
} else {
r.Pkg = sym.Pkg.Prefix
} }
} return base.PkgLinksym(sym.Pkg.Prefix, sym.Name, abi)
return base.Ctxt.LookupABIInit(sym.LinksymName(), obj.ABI0, initPkg)
} }
// Less reports whether symbol a is ordered before symbol b. // Less reports whether symbol a is ordered before symbol b.