Debug Info: remove duplication of DIEs when a DIE is part of the type system
and it is shared across CUs.
We add a few maps in DwarfDebug to map MDNodes for the type system to the
corresponding DIEs: MDTypeNodeToDieMap, MDSPNodeToDieMap, and
MDStaticMemberNodeToDieMap. These DIEs can be shared across CUs, that is why we
keep the maps in DwarfDebug instead of CompileUnit.
Sometimes, when we try to add an attribute to a DIE, the DIE is not yet added
to its owner yet, so we don't know whether we should use ref_addr or ref4.
We create a worklist that will be processed during finalization to add
attributes with the correct form (ref_addr or ref4).
We add addDIEEntry to DwarfDebug to be a wrapper around DIE->addValue. It checks
whether we know the correct form, if not, we update the worklist
(DIEEntryWorklist).
A testing case is added to show that we only create a single DIE for a type
MDNode and we use ref_addr to refer to the type DIE.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@191792 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h
index 144635e..7e0ae22 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -326,6 +326,30 @@
// Maps subprogram MDNode with its corresponding CompileUnit.
DenseMap <const MDNode *, CompileUnit *> SPMap;
+ /// Maps type MDNode with its corresponding DIE. These DIEs can be
+ /// shared across CUs, that is why we keep the map here instead
+ /// of in CompileUnit.
+ DenseMap<const MDNode *, DIE *> MDTypeNodeToDieMap;
+ /// Maps subprogram MDNode with its corresponding DIE.
+ DenseMap<const MDNode *, DIE *> MDSPNodeToDieMap;
+ /// Maps static member MDNode with its corresponding DIE.
+ DenseMap<const MDNode *, DIE *> MDStaticMemberNodeToDieMap;
+
+ /// Specifies a worklist item. Sometimes, when we try to add an attribute to
+ /// a DIE, the DIE is not yet added to its owner yet, so we don't know whether
+ /// we should use ref_addr or ref4. We create a worklist that will be
+ /// processed during finalization to add attributes with the correct form
+ /// (ref_addr or ref4).
+ struct DIEEntryWorkItem {
+ DIE *Die;
+ uint16_t Attribute;
+ DIEEntry *Entry;
+ DIEEntryWorkItem(DIE *D, uint16_t A, DIEEntry *E) :
+ Die(D), Attribute(A), Entry(E) {
+ }
+ };
+ SmallVector<DIEEntryWorkItem, 64> DIEEntryWorklist;
+
// Used to uniquely define abbreviations.
FoldingSet<DIEAbbrev> AbbreviationsSet;
@@ -660,6 +684,28 @@
DwarfDebug(AsmPrinter *A, Module *M);
~DwarfDebug();
+ void insertTypeDIE(const MDNode *TypeMD, DIE *Die) {
+ MDTypeNodeToDieMap.insert(std::make_pair(TypeMD, Die));
+ }
+ DIE *getTypeDIE(const MDNode *TypeMD) {
+ return MDTypeNodeToDieMap.lookup(TypeMD);
+ }
+ void insertSPDIE(const MDNode *SPMD, DIE *Die) {
+ MDSPNodeToDieMap.insert(std::make_pair(SPMD, Die));
+ }
+ DIE *getSPDIE(const MDNode *SPMD) {
+ return MDSPNodeToDieMap.lookup(SPMD);
+ }
+ void insertStaticMemberDIE(const MDNode *StaticMD, DIE *Die) {
+ MDStaticMemberNodeToDieMap.insert(std::make_pair(StaticMD, Die));
+ }
+ DIE *getStaticMemberDIE(const MDNode *StaticMD) {
+ return MDStaticMemberNodeToDieMap.lookup(StaticMD);
+ }
+ void insertDIEEntryWorklist(DIE *Die, uint16_t Attribute, DIEEntry *Entry) {
+ DIEEntryWorklist.push_back(DIEEntryWorkItem(Die, Attribute, Entry));
+ }
+
/// \brief Emit all Dwarf sections that should come prior to the
/// content.
void beginModule();
@@ -722,6 +768,11 @@
return Ref.resolve(TypeIdentifierMap);
}
+ /// When we don't know whether the correct form is ref4 or ref_addr, we create
+ /// a worklist item and insert it to DIEEntryWorklist.
+ void addDIEEntry(DIE *Die, uint16_t Attribute, uint16_t Form,
+ DIEEntry *Entry);
+
/// isSubprogramContext - Return true if Context is either a subprogram
/// or another context nested inside a subprogram.
bool isSubprogramContext(const MDNode *Context);