compiler: support all kinds of recursive types
Previously we only supported recursive types in structs. But there can be other kinds of recursive types, like slices: type RecursiveSlice []RecursiveSlice This doesn't involve structs, so it led to infinite recursion in the compiler. This fix avoids recursion at the proper level: at the place where the named type is defined.
Этот коммит содержится в:
родитель
c5598630c9
коммит
5b42871baa
3 изменённых файлов: 17 добавлений и 9 удалений
|
@ -569,10 +569,19 @@ func (c *compilerContext) createDIType(typ types.Type) llvm.Metadata {
|
||||||
case *types.Map:
|
case *types.Map:
|
||||||
return c.getDIType(types.NewPointer(c.program.ImportedPackage("runtime").Members["hashmap"].(*ssa.Type).Type()))
|
return c.getDIType(types.NewPointer(c.program.ImportedPackage("runtime").Members["hashmap"].(*ssa.Type).Type()))
|
||||||
case *types.Named:
|
case *types.Named:
|
||||||
return c.dibuilder.CreateTypedef(llvm.DITypedef{
|
// Placeholder metadata node, to be replaced afterwards.
|
||||||
|
temporaryMDNode := c.dibuilder.CreateReplaceableCompositeType(llvm.Metadata{}, llvm.DIReplaceableCompositeType{
|
||||||
|
Tag: dwarf.TagTypedef,
|
||||||
|
SizeInBits: sizeInBytes * 8,
|
||||||
|
AlignInBits: uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,
|
||||||
|
})
|
||||||
|
c.ditypes[typ] = temporaryMDNode
|
||||||
|
md := c.dibuilder.CreateTypedef(llvm.DITypedef{
|
||||||
Type: c.getDIType(typ.Underlying()),
|
Type: c.getDIType(typ.Underlying()),
|
||||||
Name: typ.String(),
|
Name: typ.String(),
|
||||||
})
|
})
|
||||||
|
temporaryMDNode.ReplaceAllUsesWith(md)
|
||||||
|
return md
|
||||||
case *types.Pointer:
|
case *types.Pointer:
|
||||||
return c.dibuilder.CreatePointerType(llvm.DIPointerType{
|
return c.dibuilder.CreatePointerType(llvm.DIPointerType{
|
||||||
Pointee: c.getDIType(typ.Elem()),
|
Pointee: c.getDIType(typ.Elem()),
|
||||||
|
@ -634,13 +643,6 @@ func (c *compilerContext) createDIType(typ types.Type) llvm.Metadata {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
case *types.Struct:
|
case *types.Struct:
|
||||||
// Placeholder metadata node, to be replaced afterwards.
|
|
||||||
temporaryMDNode := c.dibuilder.CreateReplaceableCompositeType(llvm.Metadata{}, llvm.DIReplaceableCompositeType{
|
|
||||||
Tag: dwarf.TagStructType,
|
|
||||||
SizeInBits: sizeInBytes * 8,
|
|
||||||
AlignInBits: uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,
|
|
||||||
})
|
|
||||||
c.ditypes[typ] = temporaryMDNode
|
|
||||||
elements := make([]llvm.Metadata, typ.NumFields())
|
elements := make([]llvm.Metadata, typ.NumFields())
|
||||||
for i := range elements {
|
for i := range elements {
|
||||||
field := typ.Field(i)
|
field := typ.Field(i)
|
||||||
|
@ -659,7 +661,6 @@ func (c *compilerContext) createDIType(typ types.Type) llvm.Metadata {
|
||||||
AlignInBits: uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,
|
AlignInBits: uint32(c.targetData.ABITypeAlignment(llvmType)) * 8,
|
||||||
Elements: elements,
|
Elements: elements,
|
||||||
})
|
})
|
||||||
temporaryMDNode.ReplaceAllUsesWith(md)
|
|
||||||
return md
|
return md
|
||||||
case *types.TypeParam:
|
case *types.TypeParam:
|
||||||
return c.getDIType(typ.Underlying())
|
return c.getDIType(typ.Underlying())
|
||||||
|
|
6
testdata/slice.go
предоставленный
6
testdata/slice.go
предоставленный
|
@ -6,6 +6,8 @@ type MySlice [32]byte
|
||||||
|
|
||||||
type myUint8 uint8
|
type myUint8 uint8
|
||||||
|
|
||||||
|
type RecursiveSlice []RecursiveSlice
|
||||||
|
|
||||||
// Indexing into slice with named type (regression test).
|
// Indexing into slice with named type (regression test).
|
||||||
var array = [4]int{
|
var array = [4]int{
|
||||||
myUint8(2): 3,
|
myUint8(2): 3,
|
||||||
|
@ -160,6 +162,10 @@ func main() {
|
||||||
for _, c := range named {
|
for _, c := range named {
|
||||||
assert(c == 0)
|
assert(c == 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test recursive slices.
|
||||||
|
rs := []RecursiveSlice(nil)
|
||||||
|
println("len:", len(rs))
|
||||||
}
|
}
|
||||||
|
|
||||||
func printslice(name string, s []int) {
|
func printslice(name string, s []int) {
|
||||||
|
|
1
testdata/slice.txt
предоставленный
1
testdata/slice.txt
предоставленный
|
@ -16,3 +16,4 @@ bytes: len=6 cap=6 data: 1 2 3 102 111 111
|
||||||
slice to array pointer: 1 -2 20 4
|
slice to array pointer: 1 -2 20 4
|
||||||
unsafe.Add array: 1 5 8 4
|
unsafe.Add array: 1 5 8 4
|
||||||
unsafe.Slice array: 3 3 9 15 4
|
unsafe.Slice array: 3 3 9 15 4
|
||||||
|
len: 0
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче