From 62fb386d57a0080881c756000e42a2c873372eb8 Mon Sep 17 00:00:00 2001 From: Damian Gryski Date: Fri, 28 Apr 2023 23:01:51 -0700 Subject: [PATCH] compiler,reflect: add tagged pointers for **T etc --- compiler/interface.go | 15 +++++++++++++++ src/reflect/type.go | 23 ++++++++++++++++++++++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/compiler/interface.go b/compiler/interface.go index 6a9e638b..7b49a81d 100644 --- a/compiler/interface.go +++ b/compiler/interface.go @@ -127,6 +127,18 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value { if _, ok := typ.Underlying().(*types.Interface); ok { hasMethodSet = false } + + // Short-circuit all the global pointer logic here for pointers to pointers. + if typ, ok := typ.(*types.Pointer); ok { + if _, ok := typ.Elem().(*types.Pointer); ok { + // For a pointer to a pointer, we just increase the pointer by 1 + ptr := c.getTypeCode(typ.Elem()) + return llvm.ConstGEP(c.ctx.Int8Type(), ptr, []llvm.Value{ + llvm.ConstInt(llvm.Int32Type(), 1, false), + }) + } + } + typeCodeName, isLocal := getTypeCodeName(typ) globalName := "reflect/types.type:" + typeCodeName var global llvm.Value @@ -391,6 +403,9 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value { }, typeFields...) } alignment := c.targetData.TypeAllocSize(c.i8ptrType) + if alignment < 4 { + alignment = 4 + } globalValue := c.ctx.ConstStruct(typeFields, false) global.SetInitializer(globalValue) if isLocal { diff --git a/src/reflect/type.go b/src/reflect/type.go index 00b47a7e..22017900 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -477,7 +477,15 @@ func (t *rawType) underlying() *rawType { return t } +func (t *rawType) ptrtag() uintptr { + return uintptr(unsafe.Pointer(t)) & 0b11 +} + func (t *rawType) isNamed() bool { + if tag := t.ptrtag(); tag != 0 { + return false + } + return t.meta&flagNamed != 0 } @@ -502,9 +510,13 @@ func pointerTo(t *rawType) *rawType { switch t.Kind() { case Pointer: + if tag := t.ptrtag(); tag < 3 { + return (*rawType)(unsafe.Add(unsafe.Pointer(t), 1)) + } + // TODO(dgryski): This is blocking https://github.com/tinygo-org/tinygo/issues/3131 // We need to be able to create types that match existing types to prevent typecode equality. - panic("reflect: cannot make **T type") + panic("reflect: cannot make *****T type") case Struct: return (*structType)(unsafe.Pointer(t)).ptrTo default: @@ -581,6 +593,11 @@ func (t *rawType) Kind() Kind { if t == nil { return Invalid } + + if tag := t.ptrtag(); tag != 0 { + return Pointer + } + return Kind(t.meta & kindMask) } @@ -591,6 +608,10 @@ func (t *rawType) Elem() Type { } func (t *rawType) elem() *rawType { + if tag := t.ptrtag(); tag != 0 { + return (*rawType)(unsafe.Add(unsafe.Pointer(t), -1)) + } + underlying := t.underlying() switch underlying.Kind() { case Pointer: