compiler, reflect: add support for named types
Этот коммит содержится в:
родитель
45f119de34
коммит
7654d86d2c
4 изменённых файлов: 43 добавлений и 5 удалений
|
@ -112,6 +112,8 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||
typeFieldTypes = append(typeFieldTypes,
|
||||
types.NewVar(token.NoPos, nil, "ptrTo", types.Typ[types.UnsafePointer]),
|
||||
types.NewVar(token.NoPos, nil, "underlying", types.Typ[types.UnsafePointer]),
|
||||
types.NewVar(token.NoPos, nil, "len", types.Typ[types.Uintptr]),
|
||||
types.NewVar(token.NoPos, nil, "name", types.NewArray(types.Typ[types.Int8], int64(len(typ.Obj().Name())))),
|
||||
)
|
||||
case *types.Chan, *types.Slice:
|
||||
typeFieldTypes = append(typeFieldTypes,
|
||||
|
@ -169,9 +171,12 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
|
|||
case *types.Basic:
|
||||
typeFields = []llvm.Value{c.getTypeCode(types.NewPointer(typ))}
|
||||
case *types.Named:
|
||||
name := typ.Obj().Name()
|
||||
typeFields = []llvm.Value{
|
||||
c.getTypeCode(types.NewPointer(typ)), // ptrTo
|
||||
c.getTypeCode(typ.Underlying()), // underlying
|
||||
llvm.ConstInt(c.uintptrType, uint64(len(name)), false), // length
|
||||
c.ctx.ConstString(name, false), // name
|
||||
}
|
||||
metabyte |= 1 << 5 // "named" flag
|
||||
case *types.Chan:
|
||||
|
|
2
compiler/testdata/interface.ll
предоставленный
2
compiler/testdata/interface.ll
предоставленный
|
@ -9,7 +9,7 @@ target triple = "wasm32-unknown-wasi"
|
|||
@"reflect/types.type:basic:int" = linkonce_odr constant { i8, ptr } { i8 2, ptr @"reflect/types.type:pointer:basic:int" }, align 4
|
||||
@"reflect/types.type:pointer:basic:int" = linkonce_odr constant { i8, ptr } { i8 21, ptr @"reflect/types.type:basic:int" }, align 4
|
||||
@"reflect/types.type:pointer:named:error" = linkonce_odr constant { i8, ptr } { i8 21, ptr @"reflect/types.type:named:error" }, align 4
|
||||
@"reflect/types.type:named:error" = linkonce_odr constant { i8, ptr, ptr } { i8 52, ptr @"reflect/types.type:pointer:named:error", ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}" }, align 4
|
||||
@"reflect/types.type:named:error" = linkonce_odr constant { i8, ptr, ptr, i32, [5 x i8] } { i8 52, ptr @"reflect/types.type:pointer:named:error", ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}", i32 5, [5 x i8] c"error" }, align 4
|
||||
@"reflect/types.type:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant { i8, ptr } { i8 20, ptr @"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" }, align 4
|
||||
@"reflect/types.type:pointer:interface:{Error:func:{}{basic:string}}" = linkonce_odr constant { i8, ptr } { i8 21, ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}" }, align 4
|
||||
@"reflect/types.type:pointer:interface:{String:func:{}{basic:string}}" = linkonce_odr constant { i8, ptr } { i8 21, ptr @"reflect/types.type:interface:{String:func:{}{basic:string}}" }, align 4
|
||||
|
|
|
@ -46,6 +46,12 @@
|
|||
// - signature types (this is missing input and output parameters):
|
||||
// meta uint8
|
||||
// ptrTo *typeStruct
|
||||
// - named types
|
||||
// meta uint8
|
||||
// ptrTo *typeStruct
|
||||
// elem *typeStruct // underlying type
|
||||
// nlem uintptr // length of name
|
||||
// name [1]byte // actual name; length nlem
|
||||
//
|
||||
// The type struct is essentially a union of all the above types. Which it is,
|
||||
// can be determined by looking at the meta byte.
|
||||
|
@ -417,6 +423,14 @@ type mapType struct {
|
|||
key *rawType
|
||||
}
|
||||
|
||||
type namedType struct {
|
||||
rawType
|
||||
ptrTo *rawType
|
||||
elem *rawType
|
||||
nlen uintptr
|
||||
name [1]byte
|
||||
}
|
||||
|
||||
// Type for struct types. The numField value is intentionally put before ptrTo
|
||||
// for better struct packing on 32-bit and 64-bit architectures. On these
|
||||
// architectures, the ptrTo field still has the same offset as in all the other
|
||||
|
@ -439,12 +453,16 @@ type structField struct {
|
|||
// Equivalent to (go/types.Type).Underlying(): if this is a named type return
|
||||
// the underlying type, else just return the type itself.
|
||||
func (t *rawType) underlying() *rawType {
|
||||
if t.meta&flagNamed != 0 {
|
||||
if t.isNamed() {
|
||||
return (*elemType)(unsafe.Pointer(t)).elem
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
func (t *rawType) isNamed() bool {
|
||||
return t.meta&flagNamed != 0
|
||||
}
|
||||
|
||||
func TypeOf(i interface{}) Type {
|
||||
return ValueOf(i).typecode
|
||||
}
|
||||
|
@ -842,7 +860,12 @@ func (t *rawType) NumMethod() int {
|
|||
}
|
||||
|
||||
func (t *rawType) Name() string {
|
||||
panic("unimplemented: (reflect.Type).Name()")
|
||||
if t.isNamed() {
|
||||
ntype := (*namedType)(unsafe.Pointer(t))
|
||||
return unsafe.String(&ntype.name[0], ntype.nlen)
|
||||
}
|
||||
|
||||
return t.Kind().String()
|
||||
}
|
||||
|
||||
func (t *rawType) Key() Type {
|
||||
|
|
|
@ -213,6 +213,16 @@ func TestBytes(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestNamedTypes(t *testing.T) {
|
||||
type namedString string
|
||||
|
||||
named := namedString("foo")
|
||||
if got, want := TypeOf(named).Name(), "namedString"; got != want {
|
||||
t.Errorf("TypeOf.Name()=%v, want %v", got, want)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func equal[T comparable](a, b []T) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче