compiler: add interface IR test

This is important as golden test output and to verify that the output is
correct. Later improvements and bug fixes are clearly visible in the IR,
and unintentional changes will also be immediately spotted.
Этот коммит содержится в:
Ayke van Laethem 2021-03-24 00:34:29 +01:00 коммит произвёл Ron Evans
родитель e9f9a4b750
коммит 5d334922d7
3 изменённых файлов: 153 добавлений и 0 удалений

Просмотреть файл

@ -61,6 +61,7 @@ func TestCompiler(t *testing.T) {
"slice.go",
"string.go",
"float.go",
"interface.go",
}
for _, testCase := range tests {

54
compiler/testdata/interface.go предоставленный Обычный файл
Просмотреть файл

@ -0,0 +1,54 @@
// This file tests interface types and interface builtins.
package main
// Test interface construction.
func simpleType() interface{} {
return 0
}
func pointerType() interface{} {
// Pointers have an element type, in this case int.
var v *int
return v
}
func interfaceType() interface{} {
// Interfaces can exist in interfaces, but only indirectly (through
// pointers).
var v *error
return v
}
func anonymousInterfaceType() interface{} {
var v *interface {
String() string
}
return v
}
// Test interface builtins.
func isInt(itf interface{}) bool {
_, ok := itf.(int)
return ok
}
func isError(itf interface{}) bool {
// Interface assert on (builtin) named interface type.
_, ok := itf.(error)
return ok
}
func isStringer(itf interface{}) bool {
// Interface assert on anonymous interface type.
_, ok := itf.(interface {
String() string
})
return ok
}
func callErrorMethod(itf error) string {
return itf.Error()
}

98
compiler/testdata/interface.ll предоставленный Обычный файл
Просмотреть файл

@ -0,0 +1,98 @@
; ModuleID = 'interface.go'
source_filename = "interface.go"
target datalayout = "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-f64:32:64-f80:32-n8:16:32-S128"
target triple = "i686--linux"
%runtime.typecodeID = type { %runtime.typecodeID*, i32, %runtime.interfaceMethodInfo* }
%runtime.interfaceMethodInfo = type { i8*, i32 }
%runtime._interface = type { i32, i8* }
%runtime._string = type { i8*, i32 }
@"reflect/types.type:basic:int" = linkonce_odr constant %runtime.typecodeID zeroinitializer
@"reflect/types.type:pointer:basic:int" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:basic:int", i32 0, %runtime.interfaceMethodInfo* null }
@"reflect/types.type:pointer:named:error" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:named:error", i32 0, %runtime.interfaceMethodInfo* null }
@"reflect/types.type:named:error" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:interface:{func:{}{basic:string}}", i32 0, %runtime.interfaceMethodInfo* null }
@"reflect/types.type:interface:{func:{}{basic:string}}" = external constant %runtime.typecodeID
@"reflect/types.type:pointer:interface:{func:{}{basic:string}}" = linkonce_odr constant %runtime.typecodeID { %runtime.typecodeID* @"reflect/types.type:interface:{func:{}{basic:string}}", i32 0, %runtime.interfaceMethodInfo* null }
@"reflect/types.type:basic:int$id" = external constant i8
@"func Error() string" = external constant i8
@"error$interface" = linkonce_odr constant [1 x i8*] [i8* @"func Error() string"]
@"func String() string" = external constant i8
@"reflect/types.interface:interface{String() string}$interface" = linkonce_odr constant [1 x i8*] [i8* @"func String() string"]
declare noalias nonnull i8* @runtime.alloc(i32, i8*, i8*)
define hidden void @main.init(i8* %context, i8* %parentHandle) unnamed_addr {
entry:
ret void
}
define hidden %runtime._interface @main.simpleType(i8* %context, i8* %parentHandle) unnamed_addr {
entry:
ret %runtime._interface { i32 ptrtoint (%runtime.typecodeID* @"reflect/types.type:basic:int" to i32), i8* null }
}
define hidden %runtime._interface @main.pointerType(i8* %context, i8* %parentHandle) unnamed_addr {
entry:
ret %runtime._interface { i32 ptrtoint (%runtime.typecodeID* @"reflect/types.type:pointer:basic:int" to i32), i8* null }
}
define hidden %runtime._interface @main.interfaceType(i8* %context, i8* %parentHandle) unnamed_addr {
entry:
ret %runtime._interface { i32 ptrtoint (%runtime.typecodeID* @"reflect/types.type:pointer:named:error" to i32), i8* null }
}
define hidden %runtime._interface @main.anonymousInterfaceType(i8* %context, i8* %parentHandle) unnamed_addr {
entry:
ret %runtime._interface { i32 ptrtoint (%runtime.typecodeID* @"reflect/types.type:pointer:interface:{func:{}{basic:string}}" to i32), i8* null }
}
define hidden i1 @main.isInt(i32 %itf.typecode, i8* %itf.value, i8* %context, i8* %parentHandle) unnamed_addr {
entry:
%typecode = call i1 @runtime.typeAssert(i32 %itf.typecode, i8* nonnull @"reflect/types.type:basic:int$id", i8* undef, i8* null)
br i1 %typecode, label %typeassert.ok, label %typeassert.next
typeassert.ok: ; preds = %entry
br label %typeassert.next
typeassert.next: ; preds = %typeassert.ok, %entry
ret i1 %typecode
}
declare i1 @runtime.typeAssert(i32, i8* dereferenceable_or_null(1), i8*, i8*)
define hidden i1 @main.isError(i32 %itf.typecode, i8* %itf.value, i8* %context, i8* %parentHandle) unnamed_addr {
entry:
%0 = call i1 @runtime.interfaceImplements(i32 %itf.typecode, i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @"error$interface", i32 0, i32 0), i8* undef, i8* null)
br i1 %0, label %typeassert.ok, label %typeassert.next
typeassert.ok: ; preds = %entry
br label %typeassert.next
typeassert.next: ; preds = %typeassert.ok, %entry
ret i1 %0
}
declare i1 @runtime.interfaceImplements(i32, i8** dereferenceable_or_null(4), i8*, i8*)
define hidden i1 @main.isStringer(i32 %itf.typecode, i8* %itf.value, i8* %context, i8* %parentHandle) unnamed_addr {
entry:
%0 = call i1 @runtime.interfaceImplements(i32 %itf.typecode, i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @"reflect/types.interface:interface{String() string}$interface", i32 0, i32 0), i8* undef, i8* null)
br i1 %0, label %typeassert.ok, label %typeassert.next
typeassert.ok: ; preds = %entry
br label %typeassert.next
typeassert.next: ; preds = %typeassert.ok, %entry
ret i1 %0
}
define hidden %runtime._string @main.callErrorMethod(i32 %itf.typecode, i8* %itf.value, i8* %context, i8* %parentHandle) unnamed_addr {
entry:
%invoke.func = call i32 @runtime.interfaceMethod(i32 %itf.typecode, i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @"error$interface", i32 0, i32 0), i8* nonnull @"func Error() string", i8* undef, i8* null)
%invoke.func.cast = inttoptr i32 %invoke.func to %runtime._string (i8*, i8*, i8*)*
%0 = call %runtime._string %invoke.func.cast(i8* %itf.value, i8* undef, i8* undef)
ret %runtime._string %0
}
declare i32 @runtime.interfaceMethod(i32, i8** dereferenceable_or_null(4), i8* dereferenceable_or_null(1), i8*, i8*)