From 918b36e28f81b2796a67a7d39d7057aba6727895 Mon Sep 17 00:00:00 2001 From: Li Jie Date: Fri, 17 Jan 2025 18:14:28 +0800 Subject: [PATCH] fix(ssa): fix incorrectly generated ABI for uninstantiated generic methods --- compiler/cl/compile.go | 2 ++ compiler/ssa/abitype.go | 15 +++++++++++++-- compiler/ssa/package.go | 15 ++++++++++++++- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/compiler/cl/compile.go b/compiler/cl/compile.go index fe15ab8bc..7bdef0937 100644 --- a/compiler/cl/compile.go +++ b/compiler/cl/compile.go @@ -260,6 +260,8 @@ func (p *context) compileFuncDecl(pkg llssa.Package, f *ssa.Function) (llssa.Fun fn.Inline(llssa.NoInline) } } + // set compiled to check generic function global instantiation + pkg.Prog.SetFuncCompiled(name) isCgo := isCgoExternSymbol(f) if nblk := len(f.Blocks); nblk > 0 { p.cgoCalled = false diff --git a/compiler/ssa/abitype.go b/compiler/ssa/abitype.go index 9f1841323..9f312700f 100644 --- a/compiler/ssa/abitype.go +++ b/compiler/ssa/abitype.go @@ -155,6 +155,11 @@ func (b Builder) abiMethodOf(mPkg *types.Package, mName string, mSig *types.Sign func (b Builder) abiMthd(mPkg *types.Package, mName string, mSig *types.Signature, name, abiTyp, ifn llvm.Value) (ret Expr, tfn llvm.Value) { fullName := FuncName(mPkg, mName, mSig.Recv(), false) + if mSig.TypeParams().Len() > 0 || mSig.RecvTypeParams().Len() > 0 { + if !b.Pkg.Prog.FuncCompiled(fullName) { + return + } + } if b.Pkg.fnlink != nil { fullName = b.Pkg.fnlink(fullName) } @@ -286,14 +291,20 @@ func (b Builder) abiInitNamed(ret Expr, t *types.Named) func() Expr { if !mthd.IsNil() { mthds = append(mthds, mthd) } - ptrMthds = append(ptrMthds, ptrMthd) + if !ptrMthd.IsNil() { + ptrMthds = append(ptrMthds, ptrMthd) + } } if len(mthds) > 0 { methods = b.SliceLit(tSlice, mthds...) } else { methods = prog.Zero(tSlice) } - ptrMethods = b.SliceLit(tSlice, ptrMthds...) + if len(ptrMthds) > 0 { + ptrMethods = b.SliceLit(tSlice, ptrMthds...) + } else { + ptrMethods = prog.Zero(tSlice) + } } return b.Call(initNamed, ret, under, methods, ptrMethods) } diff --git a/compiler/ssa/package.go b/compiler/ssa/package.go index 537b130af..8b4369cb5 100644 --- a/compiler/ssa/package.go +++ b/compiler/ssa/package.go @@ -109,6 +109,8 @@ type aProgram struct { patchType func(types.Type) types.Type + fnsCompiled map[string]bool + rt *types.Package rtget func() *types.Package @@ -218,6 +220,7 @@ func NewProgram(target *Target) Program { } ctx := llvm.NewContext() td := target.targetData() // TODO(xsw): target config + fnsCompiled := make(map[string]bool) /* arch := target.GOARCH if arch == "" { @@ -230,7 +233,7 @@ func NewProgram(target *Target) Program { */ is32Bits := (td.PointerSize() == 4 || target.GOARCH == "x86") // TODO(xsw): remove temp code return &aProgram{ - ctx: ctx, gocvt: newGoTypes(), + ctx: ctx, gocvt: newGoTypes(), fnsCompiled: fnsCompiled, target: target, td: td, is32Bits: is32Bits, ptrSize: td.PointerSize(), named: make(map[string]llvm.Type), fnnamed: make(map[string]int), linkname: make(map[string]string), @@ -280,6 +283,16 @@ func (p Program) runtime() *types.Package { return p.rt } +// check generic function instantiation +func (p Program) FuncCompiled(name string) bool { + _, ok := p.fnsCompiled[name] + return ok +} + +func (p Program) SetFuncCompiled(name string) { + p.fnsCompiled[name] = true +} + func (p Program) rtNamed(name string) *types.Named { if rt := p.runtime(); rt != nil { if rtScope := rt.Scope(); rtScope != nil {