ssa: set method.name to pkg.name if private

This commit is contained in:
visualfc
2024-06-05 22:24:51 +08:00
parent 226fd29af8
commit 2fce2318ed
14 changed files with 1056 additions and 32 deletions

Binary file not shown.

View File

@@ -246,7 +246,19 @@ type Method struct {
// Exported reports whether the method is exported.
func (p *Method) Exported() bool {
return IsExported(p.Name_)
return lastDot(p.Name_) == -1
}
// Name returns the tag string for method.
func (p *Method) Name() string {
_, name := splitName(p.Name_)
return name
}
// PkgPath returns the pkgpath string for method, or empty if there is none.
func (p *Method) PkgPath() string {
pkg, _ := splitName(p.Name_)
return pkg
}
// UncommonType is present only for defined types or types with methods
@@ -280,6 +292,23 @@ type Imethod struct {
Typ_ *FuncType // .(*FuncType) underneath
}
// Exported reports whether the imethod is exported.
func (p *Imethod) Exported() bool {
return lastDot(p.Name_) == -1
}
// Name returns the tag string for imethod.
func (p *Imethod) Name() string {
_, name := splitName(p.Name_)
return name
}
// PkgPath returns the pkgpath string for imethod, or empty if there is none.
func (p *Imethod) PkgPath() string {
pkg, _ := splitName(p.Name_)
return pkg
}
func (t *Type) Kind() Kind { return Kind(t.Kind_ & KindMask) }
// Size returns the size of data with type t.
@@ -450,4 +479,20 @@ func addChecked(p unsafe.Pointer, x uintptr, whySafe string) unsafe.Pointer {
return unsafe.Pointer(uintptr(p) + x)
}
func splitName(s string) (pkg string, name string) {
i := lastDot(s)
if i == -1 {
return s, ""
}
return s[:i], s[i+1:]
}
func lastDot(s string) int {
i := len(s) - 1
for i >= 0 && s[i] != '.' {
i--
}
return i
}
// -----------------------------------------------------------------------------

Binary file not shown.

View File

@@ -266,4 +266,60 @@ func IfacePtrData(i iface) unsafe.Pointer {
return i.data
}
// Implements reports whether the type V implements the interface type T.
func Implements(T, V *abi.Type) bool {
if T.Kind() != abi.Interface {
return false
}
t := (*abi.InterfaceType)(unsafe.Pointer(T))
if len(t.Methods) == 0 {
return true
}
// The same algorithm applies in both cases, but the
// method tables for an interface type and a concrete type
// are different, so the code is duplicated.
// In both cases the algorithm is a linear scan over the two
// lists - T's methods and V's methods - simultaneously.
// Since method tables are stored in a unique sorted order
// (alphabetical, with no duplicate method names), the scan
// through V's methods must hit a match for each of T's
// methods along the way, or else V does not implement T.
// This lets us run the scan in overall linear time instead of
// the quadratic time a naive search would require.
// See also ../runtime/iface.go.
if V.Kind() == abi.Interface {
v := (*abi.InterfaceType)(unsafe.Pointer(V))
i := 0
for j := 0; j < len(v.Methods); j++ {
tm := &t.Methods[i]
vm := &v.Methods[j]
if vm.Name_ == tm.Name_ && vm.Typ_ == tm.Typ_ {
if i++; i >= len(t.Methods) {
return true
}
}
}
return false
}
v := V.Uncommon()
if v == nil {
return false
}
i := 0
vmethods := v.Methods()
for j := 0; j < int(v.Mcount); j++ {
tm := &t.Methods[i]
vm := vmethods[j]
if vm.Name_ == tm.Name_ && vm.Mtyp_ == tm.Typ_ {
if i++; i >= len(t.Methods) {
return true
}
}
}
return false
}
// -----------------------------------------------------------------------------