diff options
author | Damian Gryski <[email protected]> | 2023-04-28 23:01:51 -0700 |
---|---|---|
committer | Ron Evans <[email protected]> | 2023-06-09 17:30:02 +0200 |
commit | 62fb386d57a0080881c756000e42a2c873372eb8 (patch) | |
tree | ef4e399b665c6bed69f83389567a8cf0221be62d | |
parent | a59f92daf8cc279eb5252ca08fc72604b8c956e1 (diff) | |
download | tinygo-62fb386d57a0080881c756000e42a2c873372eb8.tar.gz tinygo-62fb386d57a0080881c756000e42a2c873372eb8.zip |
compiler,reflect: add tagged pointers for **T etc
-rw-r--r-- | compiler/interface.go | 15 | ||||
-rw-r--r-- | src/reflect/type.go | 23 |
2 files changed, 37 insertions, 1 deletions
diff --git a/compiler/interface.go b/compiler/interface.go index 6a9e638b5..7b49a81d4 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 00b47a7e1..220179003 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: |