tinygo/testdata/interface.go
Ayke van Laethem 6c6a43310a
compiler: fix invalid incoming block in complex typeassert flow
A single *ssa.BasicBlock may be split in multiple LLVM basic blocks due
to typeassert instructions. This means the incoming block and outgoing
block are different. PHI nodes need to get the result from the outgoing
block, which was fixed before, but incoming branches need to branch to
the incoming block, not the outgoing block.

Branching to the outgoing block led to a LLVM verification error when
compiling the fmt package.

Originally found in (*fmt.pp).handleMethods.
2018-10-23 15:00:37 +02:00

129 строки
2,1 КиБ
Go

package main
func main() {
thing := &Thing{"foo"}
println("thing:", thing.String())
thing.Print()
printItf(5)
printItf(byte('x'))
printItf("foo")
printItf(Foo(18))
printItf(*thing)
printItf(thing)
printItf(Stringer(thing))
printItf(Number(3))
array := Array([4]uint32{1, 7, 11, 13})
printItf(array)
printItf(ArrayStruct{3, array})
printItf(SmallPair{3, 5})
s := Stringer(thing)
println("Stringer.String():", s.String())
var itf interface{} = s
println("Stringer.(*Thing).String():", itf.(Stringer).String())
println("nested switch:", nestedSwitch('v', 3))
}
func printItf(val interface{}) {
switch val := val.(type) {
case Doubler:
println("is Doubler:", val.Double())
case Tuple:
println("is Tuple:", val.Nth(0), val.Nth(1), val.Nth(2), val.Nth(3))
val.Print()
case int:
println("is int:", val)
case byte:
println("is byte:", val)
case string:
println("is string:", val)
case Thing:
println("is Thing:", val.String())
case *Thing:
println("is *Thing:", val.String())
case Foo:
println("is Foo:", val)
default:
println("is ?")
}
}
func nestedSwitch(verb rune, arg interface{}) bool {
switch verb {
case 'v', 's':
switch arg.(type) {
case int:
return true
}
}
return false
}
type Thing struct {
name string
}
func (t Thing) String() string {
return t.name
}
func (t Thing) Print() {
println("Thing.Print:", t.name)
}
type Stringer interface {
String() string
}
type Foo int
type Number int
func (n Number) Double() int {
return int(n) * 2
}
type Doubler interface {
Double() int
}
type Tuple interface {
Nth(int) uint32
Print()
}
type Array [4]uint32
func (a Array) Nth(n int) uint32 {
return a[n]
}
func (a Array) Print() {
println("Array len:", len(a))
}
type ArrayStruct struct {
n int
a Array
}
func (a ArrayStruct) Nth(n int) uint32 {
return a.a[n]
}
func (a ArrayStruct) Print() {
println("ArrayStruct.Print:", len(a.a), a.n)
}
type SmallPair struct {
a byte
b byte
}
func (p SmallPair) Nth(n int) uint32 {
return uint32(int(p.a)*n + int(p.b)*n)
}
func (p SmallPair) Print() {
println("SmallPair.Print:", p.a, p.b)
}