1
1
package compiler
2
2
3
3
import (
4
+ "debug/dwarf"
4
5
"errors"
5
6
"fmt"
6
7
"go/ast"
@@ -91,6 +92,7 @@ type Compiler struct {
91
92
dibuilder * llvm.DIBuilder
92
93
cu llvm.Metadata
93
94
difiles map [string ]llvm.Metadata
95
+ ditypes map [types.Type ]llvm.Metadata
94
96
machine llvm.TargetMachine
95
97
targetData llvm.TargetData
96
98
intType llvm.Type
@@ -136,6 +138,7 @@ func NewCompiler(pkgName string, config Config) (*Compiler, error) {
136
138
c := & Compiler {
137
139
Config : config ,
138
140
difiles : make (map [string ]llvm.Metadata ),
141
+ ditypes : make (map [types.Type ]llvm.Metadata ),
139
142
}
140
143
141
144
target , err := llvm .GetTargetFromTriple (config .Triple )
@@ -596,6 +599,17 @@ func isPointer(typ types.Type) bool {
596
599
597
600
// Get the DWARF type for this Go type.
598
601
func (c * Compiler ) getDIType (typ types.Type ) llvm.Metadata {
602
+ if md , ok := c .ditypes [typ ]; ok {
603
+ return md
604
+ }
605
+ md := c .createDIType (typ )
606
+ c .ditypes [typ ] = md
607
+ return md
608
+ }
609
+
610
+ // createDIType creates a new DWARF type. Don't call this function directly,
611
+ // call getDIType instead.
612
+ func (c * Compiler ) createDIType (typ types.Type ) llvm.Metadata {
599
613
llvmType := c .getLLVMType (typ )
600
614
sizeInBytes := c .targetData .TypeAllocSize (llvmType )
601
615
switch typ := typ .(type ) {
@@ -732,14 +746,17 @@ func (c *Compiler) getDIType(typ types.Type) llvm.Metadata {
732
746
},
733
747
})
734
748
case * types.Struct :
749
+ // Placeholder metadata node, to be replaced afterwards.
750
+ temporaryMDNode := c .dibuilder .CreateReplaceableCompositeType (llvm.Metadata {}, llvm.DIReplaceableCompositeType {
751
+ Tag : dwarf .TagStructType ,
752
+ SizeInBits : sizeInBytes * 8 ,
753
+ AlignInBits : uint32 (c .targetData .ABITypeAlignment (llvmType )) * 8 ,
754
+ })
755
+ c .ditypes [typ ] = temporaryMDNode
735
756
elements := make ([]llvm.Metadata , typ .NumFields ())
736
757
for i := range elements {
737
758
field := typ .Field (i )
738
759
fieldType := field .Type ()
739
- if _ , ok := fieldType .Underlying ().(* types.Pointer ); ok {
740
- // XXX hack to avoid recursive types
741
- fieldType = types .Typ [types .UnsafePointer ]
742
- }
743
760
llvmField := c .getLLVMType (fieldType )
744
761
elements [i ] = c .dibuilder .CreateMemberType (llvm.Metadata {}, llvm.DIMemberType {
745
762
Name : field .Name (),
@@ -749,11 +766,13 @@ func (c *Compiler) getDIType(typ types.Type) llvm.Metadata {
749
766
Type : c .getDIType (fieldType ),
750
767
})
751
768
}
752
- return c .dibuilder .CreateStructType (llvm.Metadata {}, llvm.DIStructType {
769
+ md := c .dibuilder .CreateStructType (llvm.Metadata {}, llvm.DIStructType {
753
770
SizeInBits : sizeInBytes * 8 ,
754
771
AlignInBits : uint32 (c .targetData .ABITypeAlignment (llvmType )) * 8 ,
755
772
Elements : elements ,
756
773
})
774
+ temporaryMDNode .ReplaceAllUsesWith (md )
775
+ return md
757
776
default :
758
777
panic ("unknown type while generating DWARF debug type: " + typ .String ())
759
778
}
0 commit comments