Push DwarfDebug::constructScopeDIE down into DwarfCompileUnit
authorDavid Blaikie <dblaikie@gmail.com>
Wed, 8 Oct 2014 22:20:02 +0000 (22:20 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Wed, 8 Oct 2014 22:20:02 +0000 (22:20 +0000)
One of many steps to generalize subprogram emission to both the DWO and
non-DWO sections (to emit -gmlt-like data under fission). Once the
functions are pushed down into DwarfCompileUnit some of the data
structures will be pushed at least into DwarfFile so that they can be
unique per-file, allowing emission to both files independently.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219345 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/ADT/iterator_range.h
lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
lib/CodeGen/AsmPrinter/DwarfDebug.h

index dd17d6c8f7b45ca1a6a8a0d391ebdaafe224eebe..d004ead71f9d8cfd9b99a1d982b8b4cc543c07b3 100644 (file)
@@ -48,6 +48,10 @@ public:
 template <class T> iterator_range<T> make_range(T x, T y) {
   return iterator_range<T>(std::move(x), std::move(y));
 }
+
+template<typename T> iterator_range<T> make_range(std::pair<T, T> p) {
+  return iterator_range<T>(std::move(p.first), std::move(p.second));
+}
 }
 
 #endif
index b48ecfaf27bfca32c0531a9bd2859b26d73eabe7..bd33c265bef6def611052c3415b6fac28842ab44 100644 (file)
@@ -319,4 +319,63 @@ DIE &DwarfCompileUnit::updateSubprogramScopeDIE(DISubprogram SP) {
   return *SPDie;
 }
 
+// Construct a DIE for this scope.
+void DwarfCompileUnit::constructScopeDIE(
+    LexicalScope *Scope, SmallVectorImpl<std::unique_ptr<DIE>> &FinalChildren) {
+  if (!Scope || !Scope->getScopeNode())
+    return;
+
+  DIScope DS(Scope->getScopeNode());
+
+  assert((Scope->getInlinedAt() || !DS.isSubprogram()) &&
+         "Only handle inlined subprograms here, use "
+         "constructSubprogramScopeDIE for non-inlined "
+         "subprograms");
+
+  SmallVector<std::unique_ptr<DIE>, 8> Children;
+
+  // We try to create the scope DIE first, then the children DIEs. This will
+  // avoid creating un-used children then removing them later when we find out
+  // the scope DIE is null.
+  std::unique_ptr<DIE> ScopeDIE;
+  if (Scope->getParent() && DS.isSubprogram()) {
+    ScopeDIE = DD->constructInlinedScopeDIE(*this, Scope);
+    if (!ScopeDIE)
+      return;
+    // We create children when the scope DIE is not null.
+    DD->createScopeChildrenDIE(*this, Scope, Children);
+  } else {
+    // Early exit when we know the scope DIE is going to be null.
+    if (DD->isLexicalScopeDIENull(Scope))
+      return;
+
+    unsigned ChildScopeCount;
+
+    // We create children here when we know the scope DIE is not going to be
+    // null and the children will be added to the scope DIE.
+    DD->createScopeChildrenDIE(*this, Scope, Children, &ChildScopeCount);
+
+    // There is no need to emit empty lexical block DIE.
+    for (const auto &E : DD->findImportedEntitiesForScope(DS))
+      Children.push_back(
+          constructImportedEntityDIE(DIImportedEntity(E.second)));
+    // If there are only other scopes as children, put them directly in the
+    // parent instead, as this scope would serve no purpose.
+    if (Children.size() == ChildScopeCount) {
+      FinalChildren.insert(FinalChildren.end(),
+                           std::make_move_iterator(Children.begin()),
+                           std::make_move_iterator(Children.end()));
+      return;
+    }
+    ScopeDIE = DD->constructLexicalScopeDIE(*this, Scope);
+    assert(ScopeDIE && "Scope DIE should not be null.");
+  }
+
+  // Add children
+  for (auto &I : Children)
+    ScopeDIE->addChild(std::move(I));
+
+  FinalChildren.push_back(std::move(ScopeDIE));
+}
+
 } // end llvm namespace
index a98ab26cc0f7bf3759b722b4faa677f17744dcd0..0c4ad4923f14fe70aaec4f993b1bcb2481e7bf57 100644 (file)
@@ -26,6 +26,7 @@ class DIE;
 class DwarfDebug;
 class DwarfFile;
 class MCSymbol;
+class LexicalScope;
 
 class DwarfCompileUnit : public DwarfUnit {
   /// The attribute index of DW_AT_stmt_list in the compile unit DIE, avoiding
@@ -68,6 +69,9 @@ public:
   /// variables in this scope then create and insert DIEs for these
   /// variables.
   DIE &updateSubprogramScopeDIE(DISubprogram SP);
+
+  void constructScopeDIE(LexicalScope *Scope,
+                         SmallVectorImpl<std::unique_ptr<DIE>> &FinalChildren);
 };
 
 } // end llvm namespace
index 52cd9e7e42234c30301f7ec22317b08b780db29e..9deaa94ca0688bd2ad7e4335e445efacebac3e9b 100644 (file)
@@ -349,25 +349,11 @@ class DwarfDebug : public AsmPrinterHandler {
   void ensureAbstractVariableIsCreatedIfScoped(const DIVariable &Var,
                                                const MDNode *Scope);
 
-  /// \brief A helper function to check whether the DIE for a given Scope is
-  /// going to be null.
-  bool isLexicalScopeDIENull(LexicalScope *Scope);
-
   /// \brief A helper function to construct a RangeSpanList for a given
   /// lexical scope.
   void addScopeRangeList(DwarfCompileUnit &TheCU, DIE &ScopeDIE,
                          const SmallVectorImpl<InsnRange> &Range);
 
-  /// \brief Construct new DW_TAG_lexical_block for this scope and
-  /// attach DW_AT_low_pc/DW_AT_high_pc labels.
-  std::unique_ptr<DIE> constructLexicalScopeDIE(DwarfCompileUnit &TheCU,
-                                                LexicalScope *Scope);
-
-  /// \brief This scope represents inlined body of a function. Construct
-  /// DIE to represent this concrete inlined copy of the function.
-  std::unique_ptr<DIE> constructInlinedScopeDIE(DwarfCompileUnit &TheCU,
-                                                LexicalScope *Scope);
-
   /// \brief Construct a DIE for this scope.
   void constructScopeDIE(DwarfCompileUnit &TheCU, LexicalScope *Scope,
                          SmallVectorImpl<std::unique_ptr<DIE>> &FinalChildren);
@@ -379,10 +365,6 @@ class DwarfDebug : public AsmPrinterHandler {
   /// \brief Construct a DIE for this subprogram scope.
   void constructSubprogramScopeDIE(DwarfCompileUnit &TheCU,
                                    LexicalScope *Scope);
-  /// A helper function to create children of a Scope DIE.
-  DIE *createScopeChildrenDIE(DwarfCompileUnit &TheCU, LexicalScope *Scope,
-                              SmallVectorImpl<std::unique_ptr<DIE>> &Children,
-                              unsigned *ChildScopeCount = nullptr);
 
   /// \brief Emit initial Dwarf sections with a label at the start of each one.
   void emitSectionLabels();
@@ -680,6 +662,33 @@ public:
   const MachineFunction *getCurrentFunction() const { return CurFn; }
   const MCSymbol *getFunctionBeginSym() const { return FunctionBeginSym; }
   const MCSymbol *getFunctionEndSym() const { return FunctionEndSym; }
+
+  iterator_range<ImportedEntityMap::const_iterator> findImportedEntitiesForScope(const MDNode *Scope) const {
+    return make_range(std::equal_range(
+        ScopesWithImportedEntities.begin(), ScopesWithImportedEntities.end(),
+        std::pair<const MDNode *, const MDNode *>(Scope, nullptr), less_first()));
+  }
+
+  /// \brief A helper function to check whether the DIE for a given Scope is
+  /// going to be null.
+  bool isLexicalScopeDIENull(LexicalScope *Scope);
+
+  // FIXME: Sink these functions down into DwarfFile/Dwarf*Unit.
+
+  /// \brief Construct new DW_TAG_lexical_block for this scope and
+  /// attach DW_AT_low_pc/DW_AT_high_pc labels.
+  std::unique_ptr<DIE> constructLexicalScopeDIE(DwarfCompileUnit &TheCU,
+                                                LexicalScope *Scope);
+
+  /// \brief This scope represents inlined body of a function. Construct
+  /// DIE to represent this concrete inlined copy of the function.
+  std::unique_ptr<DIE> constructInlinedScopeDIE(DwarfCompileUnit &TheCU,
+                                                LexicalScope *Scope);
+
+  /// A helper function to create children of a Scope DIE.
+  DIE *createScopeChildrenDIE(DwarfCompileUnit &TheCU, LexicalScope *Scope,
+                              SmallVectorImpl<std::unique_ptr<DIE>> &Children,
+                              unsigned *ChildScopeCount = nullptr);
 };
 } // End of namespace llvm