LTO+Debug Info: correctly emit inlined_subroutine when the inlined callee is
from a different CU.

We used to print out an error message and fail to generate inlined_subroutine.

If we use ref_addr in the generated DWARF, the DWARF version should be 3 or
above.
rdar://13926659


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182791 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 90ca034..adee01b 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -1504,9 +1504,14 @@
   DIE *VariableDie = new DIE(Tag);
   DbgVariable *AbsVar = DV->getAbstractVariable();
   DIE *AbsDIE = AbsVar ? AbsVar->getDIE() : NULL;
-  if (AbsDIE)
+  if (AbsDIE) {
+    bool InSameCU = AbsDIE->getCompileUnit() == getCUDie();
     addDIEEntry(VariableDie, dwarf::DW_AT_abstract_origin,
-                            dwarf::DW_FORM_ref4, AbsDIE);
+                InSameCU ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr,
+                AbsDIE);
+    if (!InSameCU)
+      DD->setUseRefAddr(true);
+  }
   else {
     addString(VariableDie, dwarf::DW_AT_name, Name);
     addSourceLine(VariableDie, DV->getVariable());
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 2d42af8..e764e36 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -190,6 +190,7 @@
       IsDarwinGDBCompat = false;
   } else
     IsDarwinGDBCompat = DarwinGDBCompat == Enable ? true : false;
+  UseRefAddr = false;
 
   if (DwarfAccelTables == Default) {
     if (IsDarwin)
@@ -369,6 +370,8 @@
     SPCU->addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin,
                       InSameCU ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr,
                       AbsSPDIE);
+    if (!InSameCU)
+      UseRefAddr = true;
     SPCU->addDie(SPDie);
   } else {
     DISubprogram SPDecl = SP.getFunctionDeclaration();
@@ -469,6 +472,17 @@
   return ScopeDIE;
 }
 
+DIE *DwarfDebug::findSPDieInAllCUs(const MDNode *N) {
+  for (DenseMap<const MDNode *, CompileUnit *>::iterator CUI = CUMap.begin(),
+         CUE = CUMap.end(); CUI != CUE; ++CUI) {
+    CompileUnit *TheCU = CUI->second;
+    DIE *SPDie = TheCU->getDIE(N);
+    if (SPDie)
+      return SPDie;
+  }
+  return 0;
+}
+
 // This scope represents inlined body of a function. Construct DIE to
 // represent this concrete inlined copy of the function.
 DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU,
@@ -481,7 +495,7 @@
     return NULL;
   DIScope DS(Scope->getScopeNode());
   DISubprogram InlinedSP = getDISubprogram(DS);
-  DIE *OriginDIE = TheCU->getDIE(InlinedSP);
+  DIE *OriginDIE = findSPDieInAllCUs(InlinedSP);
   if (!OriginDIE) {
     DEBUG(dbgs() << "Unable to find original DIE for an inlined subprogram.");
     return NULL;
@@ -500,8 +514,12 @@
          "Invalid end label for an inlined scope!");
 
   DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine);
+  bool InSameCU = OriginDIE->getCompileUnit() == TheCU->getCUDie();
   TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin,
-                     dwarf::DW_FORM_ref4, OriginDIE);
+                     InSameCU ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr,
+                     OriginDIE);
+  if (!InSameCU)
+    UseRefAddr = true;
 
   if (Ranges.size() > 1) {
     // .debug_range section has not been laid out yet. Emit offset in
@@ -558,9 +576,12 @@
 
   DIScope DS(Scope->getScopeNode());
   // Early return to avoid creating dangling variable|scope DIEs.
-  if (!Scope->getInlinedAt() && DS.isSubprogram() && Scope->isAbstractScope() &&
-      !TheCU->getDIE(DS))
-    return NULL;
+  DIE *AbstractSPDie = 0;
+  if (!Scope->getInlinedAt() && DS.isSubprogram() && Scope->isAbstractScope()) {
+    AbstractSPDie = findSPDieInAllCUs(DS);
+    if (!AbstractSPDie)
+      return NULL;
+  }
 
   SmallVector<DIE *, 8> Children;
   DIE *ObjectPointer = NULL;
@@ -593,7 +614,7 @@
   else if (DS.isSubprogram()) {
     ProcessedSPNodes.insert(DS);
     if (Scope->isAbstractScope()) {
-      ScopeDIE = TheCU->getDIE(DS);
+      ScopeDIE = AbstractSPDie;
       // Note down abstract DIE.
       if (ScopeDIE)
         AbstractSPDies.insert(std::make_pair(DS, ScopeDIE));
@@ -1683,7 +1704,9 @@
       }
     }
     if (ProcessedSPNodes.count(AScope->getScopeNode()) == 0)
-      constructScopeDIE(TheCU, AScope);
+      // Use the compile unit for the abstract scope to create scope DIEs and
+      // variable DIEs.
+      constructScopeDIE(SPMap.lookup(AScope->getScopeNode()), AScope);
   }
 
   DIE *CurFnDIE = constructScopeDIE(TheCU, FnScope);
@@ -1973,7 +1996,8 @@
     Asm->OutStreamer.AddComment("Length of Compilation Unit Info");
     Asm->EmitInt32(ContentSize);
     Asm->OutStreamer.AddComment("DWARF version number");
-    Asm->EmitInt16(dwarf::DWARF_VERSION);
+    Asm->EmitInt16((DD->getUseRefAddr() && dwarf::DWARF_VERSION < 3) ?
+                   3 : dwarf::DWARF_VERSION);
     Asm->OutStreamer.AddComment("Offset Into Abbrev. Section");
     Asm->EmitSectionOffset(Asm->GetTempSymbol(ASection->getLabelBeginName()),
                            ASectionSym);
@@ -2214,7 +2238,8 @@
     Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_begin", ID));
 
     Asm->OutStreamer.AddComment("DWARF Version");
-    Asm->EmitInt16(dwarf::DWARF_VERSION);
+    Asm->EmitInt16((UseRefAddr && dwarf::DWARF_VERSION < 3) ?
+                   3 : dwarf::DWARF_VERSION);
 
     Asm->OutStreamer.AddComment("Offset of Compilation Unit Info");
     Asm->EmitSectionOffset(Asm->GetTempSymbol(ISec->getLabelBeginName(), ID),
@@ -2261,7 +2286,8 @@
                                                   TheCU->getUniqueID()));
 
     if (Asm->isVerbose()) Asm->OutStreamer.AddComment("DWARF Version");
-    Asm->EmitInt16(dwarf::DWARF_VERSION);
+    Asm->EmitInt16((UseRefAddr && dwarf::DWARF_VERSION < 3) ?
+                   3 : dwarf::DWARF_VERSION);
 
     Asm->OutStreamer.AddComment("Offset of Compilation Unit Info");
     const MCSection *ISec = Asm->getObjFileLowering().getDwarfInfoSection();
@@ -2544,7 +2570,8 @@
   Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_inlined_begin", 1));
 
   Asm->OutStreamer.AddComment("Dwarf Version");
-  Asm->EmitInt16(dwarf::DWARF_VERSION);
+  Asm->EmitInt16((UseRefAddr && dwarf::DWARF_VERSION < 3) ?
+                 3 : dwarf::DWARF_VERSION);
   Asm->OutStreamer.AddComment("Address Size (in bytes)");
   Asm->EmitInt8(Asm->getDataLayout().getPointerSize());
 
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h
index 6cc792b..65e4fa9 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -402,6 +402,9 @@
   // Whether or not we're emitting info for older versions of gdb on darwin.
   bool IsDarwinGDBCompat;
 
+  // Whether or not we use ref_addr in the generated DWARF.
+  unsigned UseRefAddr;
+
   // DWARF5 Experimental Options
   bool HasDwarfAccelTables;
   bool HasSplitDwarf;
@@ -601,6 +604,9 @@
   /// \brief Return Label immediately following the instruction.
   MCSymbol *getLabelAfterInsn(const MachineInstr *MI);
 
+  /// \brief Search all compile units to find the SP DIE for the given MDNode.
+  DIE *findSPDieInAllCUs(const MDNode *N);
+
 public:
   //===--------------------------------------------------------------------===//
   // Main entry points.
@@ -640,6 +646,9 @@
   /// output to the limitations of darwin gdb.
   bool useDarwinGDBCompat() { return IsDarwinGDBCompat; }
 
+  bool getUseRefAddr() { return UseRefAddr; }
+  void setUseRefAddr(bool RefAddr) { UseRefAddr = RefAddr; }
+
   // Experimental DWARF5 features.
 
   /// \brief Returns whether or not to emit tables that dwarf consumers can