aboutsummaryrefslogtreecommitdiffhomepage
path: root/compiler/interface.go
diff options
context:
space:
mode:
authorDamian Gryski <[email protected]>2023-03-24 09:35:16 -0700
committerRon Evans <[email protected]>2023-03-30 21:10:54 +0200
commit3fbd3c4d935f7c1b7c1db21319b8b2b5386e6075 (patch)
tree8fdb4acc756f2e0ecc0fa524004aa999788dde51 /compiler/interface.go
parent1213a451975de12f9ff71f20deebdf54dcbc9264 (diff)
downloadtinygo-3fbd3c4d935f7c1b7c1db21319b8b2b5386e6075.tar.gz
tinygo-3fbd3c4d935f7c1b7c1db21319b8b2b5386e6075.zip
compiler,reflect: support channel directions
Diffstat (limited to 'compiler/interface.go')
-rw-r--r--compiler/interface.go44
1 files changed, 39 insertions, 5 deletions
diff --git a/compiler/interface.go b/compiler/interface.go
index edd10138b..dd181c546 100644
--- a/compiler/interface.go
+++ b/compiler/interface.go
@@ -60,6 +60,14 @@ const (
structFieldFlagIsEmbedded
)
+type reflectChanDir int
+
+const (
+ refRecvDir reflectChanDir = 1 << iota // <-chan
+ refSendDir // chan<-
+ refBothDir = refRecvDir | refSendDir // chan
+)
+
// createMakeInterface emits the LLVM IR for the *ssa.MakeInterface instruction.
// It tries to put the type in the interface value, but if that's not possible,
// it will do an allocation of the right size and put that in the interface
@@ -161,7 +169,13 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
types.NewVar(token.NoPos, nil, "pkgpath", types.Typ[types.UnsafePointer]),
types.NewVar(token.NoPos, nil, "name", types.NewArray(types.Typ[types.Int8], int64(len(pkgname)+1+len(name)+1))),
)
- case *types.Chan, *types.Slice:
+ case *types.Chan:
+ typeFieldTypes = append(typeFieldTypes,
+ types.NewVar(token.NoPos, nil, "numMethods", types.Typ[types.Uint16]), // reuse for select chan direction
+ types.NewVar(token.NoPos, nil, "ptrTo", types.Typ[types.UnsafePointer]),
+ types.NewVar(token.NoPos, nil, "elementType", types.Typ[types.UnsafePointer]),
+ )
+ case *types.Slice:
typeFieldTypes = append(typeFieldTypes,
types.NewVar(token.NoPos, nil, "numMethods", types.Typ[types.Uint16]),
types.NewVar(token.NoPos, nil, "ptrTo", types.Typ[types.UnsafePointer]),
@@ -243,10 +257,20 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
}
metabyte |= 1 << 5 // "named" flag
case *types.Chan:
+ var dir reflectChanDir
+ switch typ.Dir() {
+ case types.SendRecv:
+ dir = refBothDir
+ case types.RecvOnly:
+ dir = refRecvDir
+ case types.SendOnly:
+ dir = refSendDir
+ }
+
typeFields = []llvm.Value{
- llvm.ConstInt(c.ctx.Int16Type(), 0, false), // numMethods
- c.getTypeCode(types.NewPointer(typ)), // ptrTo
- c.getTypeCode(typ.Elem()), // elementType
+ llvm.ConstInt(c.ctx.Int16Type(), uint64(dir), false), // actually channel direction
+ c.getTypeCode(types.NewPointer(typ)), // ptrTo
+ c.getTypeCode(typ.Elem()), // elementType
}
case *types.Slice:
typeFields = []llvm.Value{
@@ -448,7 +472,17 @@ func getTypeCodeName(t types.Type) (string, bool) {
return "basic:" + basicTypeNames[t.Kind()], false
case *types.Chan:
s, isLocal := getTypeCodeName(t.Elem())
- return "chan:" + s, isLocal
+ var dir string
+ switch t.Dir() {
+ case types.SendOnly:
+ dir = "s:"
+ case types.RecvOnly:
+ dir = "r:"
+ case types.SendRecv:
+ dir = "sr:"
+ }
+
+ return "chan:" + dir + s, isLocal
case *types.Interface:
isLocal := false
methods := make([]string, t.NumMethods())