Browse Source

compiler, reflect: add Type.PkgPath

pull/3533/head
Damian Gryski 2 years ago
committed by Damian Gryski
parent
commit
2de64d3f4e
  1. 29
      compiler/interface.go
  2. 3
      compiler/testdata/interface.ll
  3. 16
      src/reflect/type.go
  4. 4
      src/reflect/value_test.go

29
compiler/interface.go

@ -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, "pkglen", types.Typ[types.Uintptr]),
types.NewVar(token.NoPos, nil, "pkgpath", 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())))),
)
@ -172,9 +174,32 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
typeFields = []llvm.Value{c.getTypeCode(types.NewPointer(typ))}
case *types.Named:
name := typ.Obj().Name()
pkg := typ.Obj().Pkg()
var pkgpath string
pkgpathName := "reflect/types.type.pkgpath.empty"
if pkg != nil {
pkgpath = pkg.Path()
pkgpathName = "reflect/types.type.pkgpath:" + pkgpath
}
pkgpathInitializer := c.ctx.ConstString(pkgpath, false)
pkgpathGlobal := llvm.AddGlobal(c.mod, pkgpathInitializer.Type(), pkgpathName)
pkgpathGlobal.SetInitializer(pkgpathInitializer)
pkgpathGlobal.SetAlignment(1)
pkgpathGlobal.SetUnnamedAddr(true)
pkgpathGlobal.SetLinkage(llvm.LinkOnceODRLinkage)
pkgpathGlobal.SetGlobalConstant(true)
pkgpathPtr := llvm.ConstGEP(pkgpathGlobal.GlobalValueType(), pkgpathGlobal, []llvm.Value{
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
llvm.ConstInt(c.ctx.Int32Type(), 0, false),
})
typeFields = []llvm.Value{
c.getTypeCode(types.NewPointer(typ)), // ptrTo
c.getTypeCode(typ.Underlying()), // underlying
c.getTypeCode(types.NewPointer(typ)), // ptrTo
c.getTypeCode(typ.Underlying()), // underlying
llvm.ConstInt(c.uintptrType, uint64(len(pkgpath)), false), // pkgpath length
pkgpathPtr, // pkgpath pointer
llvm.ConstInt(c.uintptrType, uint64(len(name)), false), // length
c.ctx.ConstString(name, false), // name
}

3
compiler/testdata/interface.ll

@ -9,7 +9,8 @@ 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, 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:named:error" = linkonce_odr constant { i8, ptr, ptr, i32, ptr, i32, [5 x i8] } { i8 52, ptr @"reflect/types.type:pointer:named:error", ptr @"reflect/types.type:interface:{Error:func:{}{basic:string}}", i32 0, ptr @"reflect/types.type.pkgpath.empty", i32 5, [5 x i8] c"error" }, align 4
@"reflect/types.type.pkgpath.empty" = linkonce_odr unnamed_addr constant [0 x i8] zeroinitializer, align 1
@"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

16
src/reflect/type.go

@ -50,6 +50,8 @@
// meta uint8
// ptrTo *typeStruct
// elem *typeStruct // underlying type
// plen uintptr // length of pkgpath
// pkg *byte // pkgpath
// nlem uintptr // length of name
// name [1]byte // actual name; length nlem
//
@ -428,6 +430,8 @@ type namedType struct {
rawType
ptrTo *rawType
elem *rawType
plen uintptr
pkg *byte
nlen uintptr
name [1]byte
}
@ -489,8 +493,7 @@ func pointerTo(t *rawType) *rawType {
func (t *rawType) String() string {
if t.isNamed() {
// TODO(dgryski): `main` until pkgPath support lands
return "<unknown>" + "." + t.Name()
return t.PkgPath() + "." + t.Name()
}
switch t.Kind() {
@ -918,8 +921,13 @@ func (t rawType) MethodByName(name string) (Method, bool) {
panic("unimplemented: (reflect.Type).MethodByName()")
}
func (t rawType) PkgPath() string {
panic("unimplemented: (reflect.Type).PkgPath()")
func (t *rawType) PkgPath() string {
if t.isNamed() {
ntype := (*namedType)(unsafe.Pointer(t))
return unsafe.String(ntype.pkg, ntype.plen)
}
return ""
}
func (t rawType) FieldByName(name string) (StructField, bool) {

4
src/reflect/value_test.go

@ -221,6 +221,10 @@ func TestNamedTypes(t *testing.T) {
t.Errorf("TypeOf.Name()=%v, want %v", got, want)
}
if got, want := TypeOf(named).String(), "reflect_test.namedString"; got != want {
t.Errorf("TypeOf.String()=%v, want %v", got, want)
}
m := make(map[[4]uint16]string)
if got, want := TypeOf(m).String(), "map[[4]uint16]string"; got != want {

Loading…
Cancel
Save