all: complete the implementation of interface asserts
Because a few things were left unimplemented it only happened to kind-of work before in my test cases. This commit should complete interface-to-interface type asserts.
Этот коммит содержится в:
родитель
61e6f7cf5b
коммит
4ad6df3227
2 изменённых файлов: 29 добавлений и 6 удалений
10
compiler.go
10
compiler.go
|
@ -446,12 +446,14 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
|
|||
}
|
||||
|
||||
interfaceTypes := c.ir.AllInterfaces()
|
||||
interfaceIndex := make([]llvm.Value, len(interfaceTypes))
|
||||
interfaceLengths := make([]llvm.Value, len(interfaceTypes))
|
||||
interfaceMethods := make([]llvm.Value, 0)
|
||||
for i, itfType := range interfaceTypes {
|
||||
if itfType.Type.NumMethods() > 0xff {
|
||||
return errors.New("too many methods for interface " + itfType.Type.String())
|
||||
}
|
||||
interfaceIndex[i] = llvm.ConstInt(llvm.Int16Type(), uint64(i), false)
|
||||
interfaceLengths[i] = llvm.ConstInt(llvm.Int8Type(), uint64(itfType.Type.NumMethods()), false)
|
||||
funcs := make([]*types.Func, itfType.Type.NumMethods())
|
||||
for i := range funcs {
|
||||
|
@ -493,6 +495,14 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error {
|
|||
signatureArrayOldGlobal.ReplaceAllUsesWith(llvm.ConstBitCast(signatureArrayNewGlobal, signatureArrayOldGlobal.Type()))
|
||||
signatureArrayOldGlobal.EraseFromParentAsGlobal()
|
||||
signatureArrayNewGlobal.SetName("runtime.methodSetSignatures")
|
||||
interfaceIndexArray := llvm.ConstArray(llvm.Int16Type(), interfaceIndex)
|
||||
interfaceIndexArrayNewGlobal := llvm.AddGlobal(c.mod, interfaceIndexArray.Type(), "runtime.interfaceIndex.tmp")
|
||||
interfaceIndexArrayNewGlobal.SetInitializer(interfaceIndexArray)
|
||||
interfaceIndexArrayNewGlobal.SetLinkage(llvm.InternalLinkage)
|
||||
interfaceIndexArrayOldGlobal := c.mod.NamedGlobal("runtime.interfaceIndex")
|
||||
interfaceIndexArrayOldGlobal.ReplaceAllUsesWith(llvm.ConstBitCast(interfaceIndexArrayNewGlobal, interfaceIndexArrayOldGlobal.Type()))
|
||||
interfaceIndexArrayOldGlobal.EraseFromParentAsGlobal()
|
||||
interfaceIndexArrayNewGlobal.SetName("runtime.interfaceIndex")
|
||||
interfaceLengthsArray := llvm.ConstArray(llvm.Int8Type(), interfaceLengths)
|
||||
interfaceLengthsArrayNewGlobal := llvm.AddGlobal(c.mod, interfaceLengthsArray.Type(), "runtime.interfaceLengths.tmp")
|
||||
interfaceLengthsArrayNewGlobal.SetInitializer(interfaceLengthsArray)
|
||||
|
|
|
@ -37,7 +37,7 @@ type methodSetRange struct {
|
|||
// in.
|
||||
var (
|
||||
firstTypeWithMethods uint16 // the lowest typecode that has at least one method
|
||||
methodSetRanges [0]methodSetRange // indexes into methodSetSignatures and methodSetFunctions
|
||||
methodSetRanges [0]methodSetRange // indices into methodSetSignatures and methodSetFunctions
|
||||
methodSetSignatures [0]uint16 // uniqued method ID
|
||||
methodSetFunctions [0]*uint8 // function pointer of method
|
||||
interfaceIndex [0]uint16 // mapping from interface ID to an index in interfaceMethods
|
||||
|
@ -81,15 +81,28 @@ func interfaceEqual(x, y _interface) bool {
|
|||
// This is a compiler intrinsic.
|
||||
//go:nobounds
|
||||
func interfaceImplements(typecode, interfaceNum uint16) bool {
|
||||
// method set indexes of the concrete type
|
||||
// method set indices of the interface
|
||||
itfIndex := interfaceIndex[interfaceNum]
|
||||
itfIndexEnd := itfIndex + uint16(interfaceLengths[interfaceNum])
|
||||
|
||||
if itfIndex == itfIndexEnd {
|
||||
// This interface has no methods, so it satisfies all types.
|
||||
// TODO: this should be figured out at compile time (as it is known at
|
||||
// compile time), so that this check is unnecessary at runtime.
|
||||
return true
|
||||
}
|
||||
|
||||
if typecode < firstTypeWithMethods {
|
||||
// Type has no methods while the interface has (checked above), so this
|
||||
// type does not satisfy this interface.
|
||||
return false
|
||||
}
|
||||
|
||||
// method set indices of the concrete type
|
||||
methodSet := methodSetRanges[typecode-firstTypeWithMethods]
|
||||
methodIndex := methodSet.index
|
||||
methodIndexEnd := methodSet.index + methodSet.length
|
||||
|
||||
// method set indexes of the interface
|
||||
itfIndex := interfaceIndex[interfaceNum]
|
||||
itfIndexEnd := itfIndex + uint16(interfaceLengths[interfaceNum])
|
||||
|
||||
// Iterate over all methods of the interface:
|
||||
for itfIndex < itfIndexEnd {
|
||||
methodId := interfaceMethods[itfIndex]
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче