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

View File

@@ -22,6 +22,7 @@ import (
"github.com/goplus/llgo/ssa/abi"
"github.com/goplus/llvm"
"golang.org/x/tools/go/types/typeutil"
)
// -----------------------------------------------------------------------------
@@ -54,9 +55,13 @@ func (b Builder) abiTypeOf(t types.Type) func() Expr {
case *types.Struct:
return b.abiStructOf(t)
case *types.Named:
if iface, ok := t.Underlying().(*types.Interface); ok {
obj := t.Obj()
return b.abiInterfaceOf(abi.PathOf(obj.Pkg()), abi.TypeName(obj), iface)
}
return b.abiNamedOf(t)
case *types.Interface:
return b.abiInterfaceOf("", t)
return b.abiInterfaceOf("", "", t)
case *types.Signature:
return b.abiFuncOf(t)
case *types.Slice:
@@ -100,15 +105,14 @@ func (b Builder) abiImethodOf(mName string, typ Expr) Expr {
return b.aggregateValue(prog.rtType("Imethod"), name.impl, typ.impl)
}
func (b Builder) abiMethods(t *types.Named) (ret int) {
n := t.NumMethods()
for i := 0; i < n; i++ {
m := t.Method(i)
mSig := m.Type().(*types.Signature)
recvType := mSig.Recv().Type()
if _, ok := recvType.(*types.Pointer); !ok {
ret++
func (b Builder) abiMethods(t *types.Named) (ret, pret int) {
methods := typeutil.IntuitiveMethodSet(t, nil)
pret = len(methods)
for _, m := range methods {
if _, ok := m.Recv().(*types.Pointer); ok {
continue
}
ret++
}
return
}
@@ -120,6 +124,9 @@ func (b Builder) abiMethodOf(m *types.Func /*, bg Background = InGo */) (mthd, p
mSig := m.Type().(*types.Signature)
name := b.Str(mName).impl
if !token.IsExported(mName) {
name = b.Str(abi.FullName(mPkg, m.Name())).impl
}
abiSigGo := types.NewSignatureType(nil, nil, nil, mSig.Params(), mSig.Results(), mSig.Variadic())
abiSig := prog.FuncDecl(abiSigGo, InGo).raw.Type
abiTyp := b.abiType(abiSig)
@@ -149,7 +156,7 @@ func (b Builder) abiMthd(mPkg *types.Package, mName string, mSig *types.Signatur
}
// func Interface(pkgPath, name string, methods []abi.Imethod)
func (b Builder) abiInterfaceOf(name string, t *types.Interface) func() Expr {
func (b Builder) abiInterfaceOf(pkgPath string, name string, t *types.Interface) func() Expr {
n := t.NumMethods()
typs := make([]Expr, n)
for i := 0; i < n; i++ {
@@ -161,11 +168,17 @@ func (b Builder) abiInterfaceOf(name string, t *types.Interface) func() Expr {
methods := make([]Expr, n)
for i := 0; i < n; i++ {
m := t.Method(i)
methods[i] = b.abiImethodOf(m.Name(), typs[i])
mName := m.Name()
if !token.IsExported(mName) {
mName = abi.FullName(m.Pkg(), mName)
}
methods[i] = b.abiImethodOf(mName, typs[i])
}
pkg := b.Pkg
fn := pkg.rtFunc("Interface")
pkgPath := pkg.Path()
if pkgPath == "" {
pkgPath = pkg.Path()
}
tSlice := lastParamType(prog, fn)
methodSlice := b.SliceLit(tSlice, methods...)
return b.Call(fn, b.Str(pkgPath), b.Str(name), methodSlice)
@@ -178,8 +191,7 @@ func (b Builder) abiNamedOf(t *types.Named) func() Expr {
pkg := b.Pkg
tunder := t.Underlying()
kind := int(abi.UnderlyingKind(tunder))
numMethods := b.abiMethods(t)
numPtrMethods := t.NumMethods()
numMethods, numPtrMethods := b.abiMethods(t)
newNamed := pkg.rtFunc("NewNamed")
return b.Call(newNamed, b.Prog.Val(kind), b.Prog.Val(numMethods), b.Prog.Val(numPtrMethods))
}
@@ -193,10 +205,10 @@ func (b Builder) abiInitNamed(ret Expr, t *types.Named) func() Expr {
prog := b.Prog
path := abi.PathOf(t.Obj().Pkg())
name := NameOf(t)
var initNamed = pkg.rtFunc("InitNamed")
var tSlice = lastParamType(prog, initNamed)
var n = t.NumMethods()
mset := typeutil.IntuitiveMethodSet(t, nil)
n := len(mset)
var methods, ptrMethods Expr
if n == 0 {
methods = prog.Zero(tSlice)
@@ -205,7 +217,7 @@ func (b Builder) abiInitNamed(ret Expr, t *types.Named) func() Expr {
var mthds []Expr
var ptrMthds = make([]Expr, 0, n)
for i := 0; i < n; i++ {
m := t.Method(i)
m := mset[i].Obj().(*types.Func)
mthd, ptrMthd := b.abiMethodOf(m)
if !mthd.IsNil() {
mthds = append(mthds, mthd)
@@ -304,6 +316,10 @@ func (p Package) abiTypeInit(g Global, t types.Type, pub bool) {
b.blk.last = blks[1].last
}
if t, ok := t.(*types.Named); ok {
// skip interface
if _, ok := t.Underlying().(*types.Interface); ok {
return
}
tabi = b.abiInitNamed(vexpr, t)
if pub {
blks = b.Func.MakeBlocks(2)

View File

@@ -113,7 +113,6 @@ func (p Program) Zero(t Type) Expr {
ret = llvm.ConstStruct(flds, false)
case *types.Slice:
ret = p.Zero(p.rtType("Slice")).impl
/* TODO(xsw):
case *types.Interface:
var name string
if u.Empty() {
@@ -122,7 +121,6 @@ func (p Program) Zero(t Type) Expr {
name = "Iface"
}
ret = p.Zero(p.rtType(name)).impl
*/
default:
log.Panicln("todo:", u)
}

View File

@@ -234,7 +234,21 @@ func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) Expr {
}
tx := b.faceAbiType(x)
tabi := b.abiType(assertedTyp.raw.Type)
eq := b.BinOp(token.EQL, tx, tabi)
var eq Expr
var val func() Expr
if rawIntf, ok := assertedTyp.raw.Type.Underlying().(*types.Interface); ok {
if rawIntf.Empty() {
eq = b.Prog.BoolVal(true)
} else {
eq = b.InlineCall(b.Pkg.rtFunc("Implements"), tabi, tx)
}
val = func() Expr { return Expr{b.unsafeInterface(rawIntf, tx, b.faceData(x.impl)), assertedTyp} }
} else {
eq = b.BinOp(token.EQL, tx, tabi)
val = func() Expr { return b.valFromData(assertedTyp, b.faceData(x.impl)) }
}
if commaOk {
prog := b.Prog
t := prog.Struct(assertedTyp, prog.Bool())
@@ -246,8 +260,7 @@ func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) Expr {
phi.AddIncoming(b, blks[:2], func(i int, blk BasicBlock) Expr {
b.SetBlockEx(blk, AtEnd, false)
if i == 0 {
val := b.valFromData(assertedTyp, b.faceData(x.impl))
valTrue := aggregateValue(b.impl, t.ll, val.impl, prog.BoolVal(true).impl)
valTrue := aggregateValue(b.impl, t.ll, val().impl, prog.BoolVal(true).impl)
b.Jump(blks[2])
return Expr{valTrue, t}
}
@@ -263,10 +276,10 @@ func (b Builder) TypeAssert(x Expr, assertedTyp Type, commaOk bool) Expr {
blks := b.Func.MakeBlocks(2)
b.If(eq, blks[0], blks[1])
b.SetBlockEx(blks[1], AtEnd, false)
b.Panic(b.Str("type assertion failed"))
b.Panic(b.MakeInterface(b.Prog.Any(), b.Str("type assertion failed")))
b.SetBlockEx(blks[0], AtEnd, false)
b.blk.last = blks[0].last
return b.valFromData(assertedTyp, b.faceData(x.impl))
return val()
}
// ChangeInterface constructs a value of one interface type from a