Skip to content

Commit 06c884c

Browse files
committed
Add a panic, pull out constant to keep in sync
1 parent 60e1f18 commit 06c884c

File tree

2 files changed

+28
-7
lines changed

2 files changed

+28
-7
lines changed

compiler/interface.go

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ import (
1818
"tinygo.org/x/go-llvm"
1919
)
2020

21+
// numMethodHasMethodSet is a flag in bit 15 of the numMethod field (uint16) in
22+
// Named, Pointer, and Struct type descriptors. When set, an inline method set
23+
// is present in the type descriptor. Must match the constant in
24+
// src/internal/reflectlite/type.go.
25+
const numMethodHasMethodSet = 0x8000
26+
2127
// Type kinds for basic types.
2228
// They must match the constants for the Kind type in src/reflect/type.go.
2329
var basicTypes = [...]uint8{
@@ -321,8 +327,11 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
321327
}
322328
pkgPathPtr := c.pkgPathPtr(pkgpath)
323329
namedNumMethods := uint64(numMethods)
330+
if namedNumMethods&numMethodHasMethodSet != 0 {
331+
panic("numMethods overflow: too many exported methods on named type " + name)
332+
}
324333
if len(methods) > 0 {
325-
namedNumMethods |= 0x8000 // numMethodHasMethodSet flag
334+
namedNumMethods |= numMethodHasMethodSet
326335
}
327336
typeFields = []llvm.Value{
328337
llvm.ConstInt(c.ctx.Int16Type(), namedNumMethods, false), // numMethods
@@ -359,8 +368,11 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
359368
}
360369
case *types.Pointer:
361370
ptrNumMethods := uint64(numMethods)
371+
if ptrNumMethods&numMethodHasMethodSet != 0 {
372+
panic("numMethods overflow: too many exported methods on pointer type")
373+
}
362374
if len(methods) > 0 {
363-
ptrNumMethods |= 0x8000 // numMethodHasMethodSet flag
375+
ptrNumMethods |= numMethodHasMethodSet
364376
}
365377
typeFields = []llvm.Value{
366378
llvm.ConstInt(c.ctx.Int16Type(), ptrNumMethods, false), // numMethods
@@ -396,8 +408,11 @@ func (c *compilerContext) getTypeCode(typ types.Type) llvm.Value {
396408
llvmStructType := c.getLLVMType(typ)
397409
size := c.targetData.TypeStoreSize(llvmStructType)
398410
structNumMethods := uint64(numMethods)
411+
if structNumMethods&numMethodHasMethodSet != 0 {
412+
panic("numMethods overflow: too many exported methods on struct type")
413+
}
399414
if len(methods) > 0 {
400-
structNumMethods |= 0x8000 // numMethodHasMethodSet flag
415+
structNumMethods |= numMethodHasMethodSet
401416
}
402417
typeFields = []llvm.Value{
403418
llvm.ConstInt(c.ctx.Int16Type(), structNumMethods, false), // numMethods

transform/interface-lowering.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ import (
3636
"tinygo.org/x/go-llvm"
3737
)
3838

39+
// numMethodHasMethodSet is a flag in bit 15 of the numMethod field (uint16) in
40+
// Named, Pointer, and Struct type descriptors. When set, an inline method set
41+
// is present in the type descriptor. Must match the constant in
42+
// src/internal/reflectlite/type.go.
43+
const numMethodHasMethodSet = 0x8000
44+
3945
// signatureInfo is a Go signature of an interface method. It does not represent
4046
// any method in particular.
4147
type signatureInfo struct {
@@ -379,8 +385,8 @@ func (p *lowerInterfacesPass) run() error {
379385

380386
// Read numMethods from the original type descriptor (index 2:
381387
// after prefix pointer at 0 and kind byte at 1). For Named,
382-
// Pointer, and Struct types, bit 15 (0x8000) indicates that an
383-
// inline method set is present.
388+
// Pointer, and Struct types, the numMethodHasMethodSet flag
389+
// indicates that an inline method set is present.
384390
var numMethodsConst uint64
385391
var numMethodsIsI16 bool
386392
if numFields > 2 {
@@ -399,10 +405,10 @@ func (p *lowerInterfacesPass) run() error {
399405
// Struct types. When the method set is pruned to empty, we
400406
// remove it and clear the numMethodHasMethodSet flag (bit 15
401407
// of numMethod) so the runtime skips reading it.
402-
if numMethodsIsI16 && numMethodsConst&0x8000 != 0 && p.isMethodSetType(field.Type()) {
408+
if numMethodsIsI16 && numMethodsConst&numMethodHasMethodSet != 0 && p.isMethodSetType(field.Type()) {
403409
elems := field.Type().StructElementTypes()
404410
if elems[1].ArrayLength() == 0 {
405-
clearedNumMethods := numMethodsConst & ^uint64(0x8000)
411+
clearedNumMethods := numMethodsConst & ^uint64(numMethodHasMethodSet)
406412
newInitializerFields[1] = llvm.ConstInt(p.ctx.Int16Type(), clearedNumMethods, false)
407413
continue
408414
}

0 commit comments

Comments
 (0)