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()
|
interfaceTypes := c.ir.AllInterfaces()
|
||||||
|
interfaceIndex := make([]llvm.Value, len(interfaceTypes))
|
||||||
interfaceLengths := make([]llvm.Value, len(interfaceTypes))
|
interfaceLengths := make([]llvm.Value, len(interfaceTypes))
|
||||||
interfaceMethods := make([]llvm.Value, 0)
|
interfaceMethods := make([]llvm.Value, 0)
|
||||||
for i, itfType := range interfaceTypes {
|
for i, itfType := range interfaceTypes {
|
||||||
if itfType.Type.NumMethods() > 0xff {
|
if itfType.Type.NumMethods() > 0xff {
|
||||||
return errors.New("too many methods for interface " + itfType.Type.String())
|
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)
|
interfaceLengths[i] = llvm.ConstInt(llvm.Int8Type(), uint64(itfType.Type.NumMethods()), false)
|
||||||
funcs := make([]*types.Func, itfType.Type.NumMethods())
|
funcs := make([]*types.Func, itfType.Type.NumMethods())
|
||||||
for i := range funcs {
|
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.ReplaceAllUsesWith(llvm.ConstBitCast(signatureArrayNewGlobal, signatureArrayOldGlobal.Type()))
|
||||||
signatureArrayOldGlobal.EraseFromParentAsGlobal()
|
signatureArrayOldGlobal.EraseFromParentAsGlobal()
|
||||||
signatureArrayNewGlobal.SetName("runtime.methodSetSignatures")
|
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)
|
interfaceLengthsArray := llvm.ConstArray(llvm.Int8Type(), interfaceLengths)
|
||||||
interfaceLengthsArrayNewGlobal := llvm.AddGlobal(c.mod, interfaceLengthsArray.Type(), "runtime.interfaceLengths.tmp")
|
interfaceLengthsArrayNewGlobal := llvm.AddGlobal(c.mod, interfaceLengthsArray.Type(), "runtime.interfaceLengths.tmp")
|
||||||
interfaceLengthsArrayNewGlobal.SetInitializer(interfaceLengthsArray)
|
interfaceLengthsArrayNewGlobal.SetInitializer(interfaceLengthsArray)
|
||||||
|
|
|
@ -37,7 +37,7 @@ type methodSetRange struct {
|
||||||
// in.
|
// in.
|
||||||
var (
|
var (
|
||||||
firstTypeWithMethods uint16 // the lowest typecode that has at least one method
|
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
|
methodSetSignatures [0]uint16 // uniqued method ID
|
||||||
methodSetFunctions [0]*uint8 // function pointer of method
|
methodSetFunctions [0]*uint8 // function pointer of method
|
||||||
interfaceIndex [0]uint16 // mapping from interface ID to an index in interfaceMethods
|
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.
|
// This is a compiler intrinsic.
|
||||||
//go:nobounds
|
//go:nobounds
|
||||||
func interfaceImplements(typecode, interfaceNum uint16) bool {
|
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]
|
methodSet := methodSetRanges[typecode-firstTypeWithMethods]
|
||||||
methodIndex := methodSet.index
|
methodIndex := methodSet.index
|
||||||
methodIndexEnd := methodSet.index + methodSet.length
|
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:
|
// Iterate over all methods of the interface:
|
||||||
for itfIndex < itfIndexEnd {
|
for itfIndex < itfIndexEnd {
|
||||||
methodId := interfaceMethods[itfIndex]
|
methodId := interfaceMethods[itfIndex]
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче