Preserve deleted function's local variables' debug info.
authorDevang Patel <dpatel@apple.com>
Mon, 28 Jun 2010 18:25:03 +0000 (18:25 +0000)
committerDevang Patel <dpatel@apple.com>
Mon, 28 Jun 2010 18:25:03 +0000 (18:25 +0000)
Radar 8122864.

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

lib/CodeGen/AsmPrinter/DwarfDebug.cpp
lib/CodeGen/AsmPrinter/DwarfDebug.h
test/FrontendC/2010-06-28-DbgLocalVar.c [new file with mode: 0644]

index 92b4fef9e7886067db108b700799a939e66a7886..265296ade94dd0ef47acfa16a2516ea88fcac62a 100644 (file)
@@ -1386,6 +1386,7 @@ static bool isSubprogramContext(const MDNode *Context) {
 /// If there are global variables in this scope then create and insert
 /// DIEs for these variables.
 DIE *DwarfDebug::updateSubprogramScopeDIE(const MDNode *SPNode) {
+  ProcessedSPNodes.insert(SPNode);
   CompileUnit *SPCU = getCompileUnit(SPNode);
   DIE *SPDie = SPCU->getDIE(SPNode);
   assert(SPDie && "Unable to find subprogram DIE!");
@@ -2005,6 +2006,40 @@ void DwarfDebug::beginModule(Module *M) {
 ///
 void DwarfDebug::endModule() {
   if (!FirstCU) return;
+  const Module *M = MMI->getModule();
+  if (NamedMDNode *AllSPs = M->getNamedMetadata("llvm.dbg.sp")) {
+    for (unsigned SI = 0, SE = AllSPs->getNumOperands(); SI != SE; ++SI) {
+      if (ProcessedSPNodes.count(AllSPs->getOperand(SI)) != 0) continue;
+      DISubprogram SP(AllSPs->getOperand(SI));
+      if (!SP.Verify()) continue;
+
+      // Collect info for variables that were optimized out.
+      StringRef FName = SP.getLinkageName();
+      if (FName.empty())
+        FName = SP.getName();
+      NamedMDNode *NMD = 
+        M->getNamedMetadata(Twine("llvm.dbg.lv.", getRealLinkageName(FName)));
+      if (!NMD) continue;
+      unsigned E = NMD->getNumOperands();
+      if (!E) continue;
+      DbgScope *Scope = new DbgScope(NULL, DIDescriptor(SP), NULL);
+      for (unsigned I = 0; I != E; ++I) {
+        DIVariable DV(NMD->getOperand(I));
+        if (!DV.Verify()) continue;
+        Scope->addVariable(new DbgVariable(DV));
+      }
+      
+      // Construct subprogram DIE and add variables DIEs.
+      constructSubprogramDIE(SP);
+      DIE *ScopeDIE = getCompileUnit(SP)->getDIE(SP);
+      const SmallVector<DbgVariable *, 8> &Variables = Scope->getVariables();
+      for (unsigned i = 0, N = Variables.size(); i < N; ++i) {
+        DIE *VariableDIE = constructVariableDIE(Variables[i], Scope);
+        if (VariableDIE)
+          ScopeDIE->addChild(VariableDIE);
+      }
+    }
+  }
 
   // Attach DW_AT_inline attribute with inlined subprogram DIEs.
   for (SmallPtrSet<DIE *, 4>::iterator AI = InlinedSubprogramDIEs.begin(),
index 43f9d17c0a41f447b3f72bbd9bdad8fd576ca3b0..9b3427dcaf376066292d85d87020f851ad7e1a6f 100644 (file)
@@ -219,6 +219,10 @@ class DwarfDebug {
   DenseMap<const MDNode *, SmallVector<InlineInfoLabels, 4> > InlineInfo;
   SmallVector<const MDNode *, 4> InlinedSPNodes;
 
+  // ProcessedSPNodes - This is a collection of subprogram MDNodes that
+  // are processed to create DIEs.
+  SmallPtrSet<const MDNode *, 16> ProcessedSPNodes;
+
   /// LabelsBeforeInsn - Maps instruction with label emitted before 
   /// instruction.
   DenseMap<const MachineInstr *, MCSymbol *> LabelsBeforeInsn;
diff --git a/test/FrontendC/2010-06-28-DbgLocalVar.c b/test/FrontendC/2010-06-28-DbgLocalVar.c
new file mode 100644 (file)
index 0000000..e5df885
--- /dev/null
@@ -0,0 +1,14 @@
+// RUN: %llvmgcc -S -O2 -g %s -o - | llc -O2 -o %t.s 
+// RUN: grep DW_TAG_structure_type %t.s | count 2
+// Radar 8122864
+
+// Code is not generated for function foo, but preserve type information of
+// local variable xyz.
+static foo() {
+  struct X { int a; int b; } xyz;
+}
+
+int bar() {
+  foo();
+  return 1;
+}