mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-07-26 06:38:42 +00:00
compiler: key deferInvokeFuncs on distinct name
This commit is contained in:
+4
-4
@@ -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).
|
||||
|
||||
@@ -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
|
||||
|
||||
Vendored
+41
@@ -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 = ®ression5541RuntimeImpl{}
|
||||
defer runtime.Close()
|
||||
|
||||
var module regression5541Closer = ®ression5541Module{}
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user