compiler: pass interface typecode through defer frames

Previously, the typecode was passed via a direct reference, which results in invalid IR when the defer is not reached in all return paths.
It also results in incorrect behavior if the defer is in a loop, causing all defers to use the typecode of the last iteration.
This commit is contained in:
Jaden Weiss
2020-04-08 18:25:42 -04:00
committed by Ayke
parent e077e35386
commit 5308e8903e
3 changed files with 57 additions and 13 deletions
+36
View File
@@ -61,6 +61,9 @@ func main() {
thingFunctionalArgs1.Print("functional args 1")
thingFunctionalArgs2 := NewThing(WithName("named thing"))
thingFunctionalArgs2.Print("functional args 2")
// regression testing
regression1033()
}
func runFunc(f func(int), arg int) {
@@ -108,3 +111,36 @@ func exportedDefer() {
func testBound(f func() string) {
println("bound method:", f())
}
// regression1033 is a regression test for https://github.com/tinygo-org/tinygo/issues/1033.
// In previous versions of the compiler, a deferred call to an interface would create an instruction that did not dominate its uses.
func regression1033() {
foo(&Bar{})
}
type Bar struct {
empty bool
}
func (b *Bar) Close() error {
return nil
}
type Closer interface {
Close() error
}
func foo(bar *Bar) error {
var a int
if !bar.empty {
a = 10
if a != 5 {
return nil
}
}
var c Closer = bar
defer c.Close()
return nil
}