compiler: key deferInvokeFuncs on distinct name

This commit is contained in:
Jake Bailey
2026-07-21 14:32:01 -07:00
committed by Ron Evans
parent b536dd6f79
commit 3071e339cd
3 changed files with 51 additions and 6 deletions
+4 -4
View File
@@ -372,12 +372,12 @@ func (b *builder) createDefer(instr *ssa.Defer) {
// Method call on an interface.
// Get callback type number.
methodName := instr.Call.Method.FullName()
if _, ok := b.deferInvokeFuncs[methodName]; !ok {
b.deferInvokeFuncs[methodName] = len(b.allDeferFuncs)
key := b.getInvokeFunctionName(&instr.Call)
if _, ok := b.deferInvokeFuncs[key]; !ok {
b.deferInvokeFuncs[key] = len(b.allDeferFuncs)
b.allDeferFuncs = append(b.allDeferFuncs, &instr.Call)
}
callback := llvm.ConstInt(b.uintptrType, uint64(b.deferInvokeFuncs[methodName]), false)
callback := llvm.ConstInt(b.uintptrType, uint64(b.deferInvokeFuncs[key]), false)
// Collect all values to be put in the struct (starting with
// runtime._defer fields, followed by the call parameters).
+6 -2
View File
@@ -1193,8 +1193,7 @@ func (c *compilerContext) getMethodSetValue(methods []*types.Func) llvm.Value {
// thunk is declared, not defined: it will be defined by the interface lowering
// pass.
func (c *compilerContext) getInvokeFunction(instr *ssa.CallCommon) llvm.Value {
s, _ := c.getTypeCodeName(instr.Value.Type().Underlying())
fnName := s + "." + instr.Method.Name() + "$invoke"
fnName := c.getInvokeFunctionName(instr)
llvmFn := c.mod.NamedFunction(fnName)
if llvmFn.IsNil() {
sig := instr.Method.Type().(*types.Signature)
@@ -1213,6 +1212,11 @@ func (c *compilerContext) getInvokeFunction(instr *ssa.CallCommon) llvm.Value {
return llvmFn
}
func (c *compilerContext) getInvokeFunctionName(instr *ssa.CallCommon) string {
s, _ := c.getTypeCodeName(instr.Value.Type().Underlying())
return s + "." + instr.Method.Name() + "$invoke"
}
// createInterfaceTypeAssert creates a call to a declared-but-not-defined
// $typeassert function for the given interface. This function will be defined
// by the interface lowering pass as a type-ID comparison chain, avoiding the
+41
View File
@@ -70,6 +70,7 @@ func main() {
// regression testing
regression1033()
regression5541()
//Test deferred builtins
testDeferBuiltinClose()
@@ -224,6 +225,46 @@ func foo(bar *Bar) error {
return nil
}
var regression5541RuntimeClosed, regression5541ModuleClosed int
type regression5541Closer interface {
Close()
}
type regression5541Runtime interface {
Foo()
regression5541Closer
}
type regression5541RuntimeImpl struct{}
func (*regression5541RuntimeImpl) Foo() {
}
func (*regression5541RuntimeImpl) Close() {
regression5541RuntimeClosed++
}
type regression5541Module struct{}
func (*regression5541Module) Close() {
regression5541ModuleClosed++
}
func regression5541() {
func() {
var runtime regression5541Runtime = &regression5541RuntimeImpl{}
defer runtime.Close()
var module regression5541Closer = &regression5541Module{}
defer module.Close()
}()
if regression5541RuntimeClosed != 1 || regression5541ModuleClosed != 1 {
println("deferred interface methods were not both called")
}
}
type issue1304 struct {
a [0]int // zero-length field
b int // field 'b' covers entire struct