llgo/ssa: abiMethodOf; AfterInit bugfix

This commit is contained in:
xushiwei
2024-05-27 14:32:23 +08:00
parent c0a156f347
commit 8e89dc8aa9
10 changed files with 567 additions and 266 deletions

View File

@@ -26,7 +26,7 @@ import (
)
func TestFromTestgo(t *testing.T) {
cltest.FromDir(t, "", "../cl/_testgo", false)
cltest.FromDir(t, "errors", "../cl/_testgo", false)
}
func TestFromTestpy(t *testing.T) {

View File

@@ -93,6 +93,21 @@ func (b Builder) abiImethodOf(m *types.Func) Expr {
return b.aggregateValue(prog.rtType("Imethod"), name.impl, typ.impl)
}
// Method{name string, typ *FuncType, ifn, tfn abi.Text}
func (b Builder) abiMethodOf(m *types.Func) Expr {
prog := b.Prog
mName := m.Name()
mSig := m.Type().(*types.Signature)
fullName := FuncName(m.Pkg(), mName, mSig.Recv())
name := b.Str(mName)
fn := b.Pkg.NewFunc(fullName, mSig, InGo)
sig := fn.raw.Type.(*types.Signature)
sig = types.NewSignatureType(nil, nil, nil, sig.Params(), sig.Results(), sig.Variadic())
typ := b.abiType(sig)
// TODO(xsw): ifn, tfn
return b.aggregateValue(prog.rtType("Method"), name.impl, typ.impl, fn.impl, fn.impl)
}
// func Interface(pkgPath string, methods []abi.Imethod)
func (b Builder) abiInterfaceOf(t *types.Interface) Expr {
prog := b.Prog
@@ -112,21 +127,32 @@ func (b Builder) abiInterfaceOf(t *types.Interface) Expr {
// func Named(pkgPath, name string, underlying *Type, methods []abi.Method)
func (b Builder) abiNamedOf(t *types.Named) Expr {
under := b.abiTypeOf(t.Underlying())
tunder := t.Underlying()
under := b.abiType(tunder)
path := abi.PathOf(t.Obj().Pkg())
name := NameOf(t)
prog := b.Prog
pkg := b.Pkg
fn := pkg.rtFunc("Named")
tSlice := lastParamType(prog, fn)
// TODO(xsw): methods
methods := prog.Zero(tSlice)
var fn = pkg.rtFunc("Named")
var tSlice = lastParamType(prog, fn)
var methods Expr
if _, ok := tunder.(*types.Interface); ok {
methods = prog.Zero(tSlice)
} else {
n := t.NumMethods()
mths := make([]Expr, n)
for i := 0; i < n; i++ {
m := t.Method(i)
mths[i] = b.abiMethodOf(m)
}
methods = b.SliceLit(tSlice, mths...)
}
return b.Call(fn, b.Str(path), b.Str(name), under, methods)
}
func (b Builder) abiPointerOf(t *types.Pointer) Expr {
elem := b.abiTypeOf(t.Elem())
elem := b.abiType(t.Elem())
return b.Call(b.Pkg.rtFunc("PointerTo"), elem)
}
@@ -226,8 +252,7 @@ func (b Builder) unsafeInterface(rawIntf *types.Interface, t Expr, data llvm.Val
return b.unsafeIface(itab.impl, data)
}
func iMethodOf(rawIntf *types.Interface, method *types.Func) int {
name := method.Name()
func iMethodOf(rawIntf *types.Interface, name string) int {
n := rawIntf.NumMethods()
for i := 0; i < n; i++ {
m := rawIntf.Method(i)
@@ -243,11 +268,11 @@ func iMethodOf(rawIntf *types.Interface, method *types.Func) int {
func (b Builder) Imethod(intf Expr, method *types.Func) Expr {
prog := b.Prog
rawIntf := intf.raw.Type.Underlying().(*types.Interface)
i := iMethodOf(rawIntf, method)
tclosure := prog.Type(method.Type(), InGo)
i := iMethodOf(rawIntf, method.Name())
impl := intf.impl
itab := Expr{b.faceItab(impl), prog.VoidPtrPtr()}
pfn := b.Advance(itab, prog.IntVal(uint64(i+3), prog.Int()))
tclosure := prog.Type(method.Type(), InGo)
return b.aggregateValue(tclosure, b.Load(pfn).impl, b.faceData(impl))
}

View File

@@ -585,12 +585,24 @@ func (p Package) AfterInit(b Builder, ret BasicBlock) {
b.SetBlockEx(ret, afterInit, false)
if doAbiInit {
sigAbiInit := types.NewSignatureType(nil, nil, nil, nil, nil, false)
fn := p.NewFunc(p.Path()+".init$abi", sigAbiInit, InC)
fnb := fn.MakeBody(1)
for _, abiInit := range p.abiini {
abiInit(unsafe.Pointer(fnb))
baseName := p.Path() + ".init$abi"
name := baseName
idx := 1
fn := p.NewFunc(name, sigAbiInit, InC)
for {
fnb := fn.MakeBody(1)
first := fnb.blk
p.callAbiInit(fnb)
fnb.Return()
if len(p.abiini) == 0 {
break
}
idx++
name = baseName + strconv.Itoa(idx)
fn = p.NewFunc(name, sigAbiInit, InC)
fnb.SetBlockEx(first, AtStart, false)
fnb.Call(fn.Expr)
}
fnb.Return()
b.Call(fn.Expr)
}
if doPyLoadModSyms {
@@ -599,6 +611,14 @@ func (p Package) AfterInit(b Builder, ret BasicBlock) {
}
}
func (p Package) callAbiInit(fnb Builder) {
abiini := p.abiini
p.abiini = nil
for _, abiInit := range abiini {
abiInit(unsafe.Pointer(fnb))
}
}
/*
type CodeGenFileType = llvm.CodeGenFileType

View File

@@ -417,4 +417,24 @@ func PathOf(pkg *types.Package) string {
return abi.PathOf(pkg)
}
// FuncName:
// - func: pkg.name
// - method: (pkg.T).name, (*pkg.T).name
func FuncName(pkg *types.Package, name string, recv *types.Var) string {
if recv != nil {
var tName string
t := recv.Type()
if tp, ok := t.(*types.Pointer); ok {
t, tName = tp.Elem(), "*"
}
tName += NameOf(t.(*types.Named))
return "(" + tName + ")." + name
}
ret := FullName(pkg, name)
if ret == "main.main" {
ret = "main"
}
return ret
}
// -----------------------------------------------------------------------------

View File

@@ -125,7 +125,14 @@ func (p goTypes) cvtNamed(t *types.Named) (raw *types.Named, cvt bool) {
if named, ok := p.named[id]; ok {
return named, false
}
named := types.NewNamed(t.Obj(), types.Typ[types.Int], nil)
n := t.NumMethods()
methods := make([]*types.Func, n)
for i := 0; i < n; i++ {
m := t.Method(i) // don't need to convert method signature
methods[i] = m
}
named := types.NewNamed(t.Obj(), types.Typ[types.Int], methods)
p.named[id] = named
defer delete(p.named, id)
if tund, cvt := p.cvtType(t.Underlying()); cvt {