From bf75299f0a09cf0672a1c59786f8057ead6a37a4 Mon Sep 17 00:00:00 2001
From: Bill Wendling <isanbard@gmail.com>
Date: Fri, 26 Sep 2008 00:28:12 +0000
Subject: [PATCH] If we have a function with an unreachable statement such that
 the ending debug information is in an unreachable block, then it's possible
 that the high/low pc values won't be set for the dwarf information. E.g.,
 this function:

void abort(void) __attribute__((__noreturn__));
void dead_beef(void) __attribute__ ((noreturn));

int *b;

void dead_beef(void) {
  *b=0xdeadbeef;
  abort();
}

has a call to "@llvm.dbg.region.end" only in the unreachable block:

define void @dead_beef() noreturn nounwind  {
entry:
	call void @llvm.dbg.func.start(...)
	call void @llvm.dbg.stoppoint(...)
...
	call void @abort( ) noreturn nounwind
	unreachable

return:		; No predecessors!
	call void @llvm.dbg.stoppoint(...)
	call void @llvm.dbg.region.end(...)
	ret void
}

The dwarf information emitted is something like:

0x00000084:     TAG_subprogram [5]
                 AT_name( "dead_beef" )
                 AT_external( 0x01 )
                 AT_prototyped( 0x01 )
                 AT_decl_file( 0x01 )
                 AT_decl_line( 0x08 )

Note that this is *not* the best fix for this problem, but a band-aid for an
gaping wound. This code needs to be changed when we revamp our debugging
information.

llvm-svn: 56628
---
 include/llvm/CodeGen/DwarfWriter.h            |  2 +-
 lib/CodeGen/AsmPrinter/DwarfWriter.cpp        | 56 +++++++++++++++++--
 lib/Target/CellSPU/SPUAsmPrinter.cpp          |  2 +-
 .../PowerPC/AsmPrinter/PPCAsmPrinter.cpp      |  4 +-
 .../X86/AsmPrinter/X86ATTAsmPrinter.cpp       |  2 +-
 5 files changed, 55 insertions(+), 11 deletions(-)

diff --git a/include/llvm/CodeGen/DwarfWriter.h b/include/llvm/CodeGen/DwarfWriter.h
index 981513baee0..f5f5cd30d35 100644
--- a/include/llvm/CodeGen/DwarfWriter.h
+++ b/include/llvm/CodeGen/DwarfWriter.h
@@ -74,7 +74,7 @@ public:
   
   /// EndFunction - Gather and emit post-function debug information.
   ///
-  void EndFunction();
+  void EndFunction(MachineFunction *MF);
 };
 
 
diff --git a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp
index d45ab13e863..06282211d17 100644
--- a/lib/CodeGen/AsmPrinter/DwarfWriter.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfWriter.cpp
@@ -2031,6 +2031,39 @@ private:
     ConstructScope(RootScope, 0, 0, SPDie, Unit);
   }
 
+  /// ConstructDefaultScope - Construct a default scope for the subprogram.
+  ///
+  void ConstructDefaultScope(MachineFunction *MF) {
+    // Find the correct subprogram descriptor.
+    std::vector<SubprogramDesc *> Subprograms;
+    MMI->getAnchoredDescriptors<SubprogramDesc>(*M, Subprograms);
+
+    for (unsigned i = 0, N = Subprograms.size(); i < N; ++i) {
+      SubprogramDesc *SPD = Subprograms[i];
+
+      if (SPD->getName() == MF->getFunction()->getName()) {
+        // Get the compile unit context.
+        CompileUnit *Unit = GetBaseCompileUnit();
+
+        // Get the subprogram die.
+        DIE *SPDie = Unit->getDieMapSlotFor(SPD);
+        assert(SPDie && "Missing subprogram descriptor");
+
+        // Add the function bounds.
+        AddLabel(SPDie, DW_AT_low_pc, DW_FORM_addr,
+                 DWLabel("func_begin", SubprogramCount));
+        AddLabel(SPDie, DW_AT_high_pc, DW_FORM_addr,
+                 DWLabel("func_end", SubprogramCount));
+
+        MachineLocation Location(RI->getFrameRegister(*MF));
+        AddAddress(SPDie, DW_AT_frame_base, Location);
+        return;
+      }
+    }
+
+    assert(0 && "Couldn't find DIE for machine function!");
+  }
+
   /// EmitInitial - Emit initial Dwarf declarations.  This is necessary for cc
   /// tools to recognize the object file contains Dwarf information.
   void EmitInitial() {
@@ -2588,7 +2621,7 @@ private:
     Asm->SwitchToDataSection(TAI->getDwarfARangesSection());
 
     // FIXME - Mock up
-  #if 0
+#if 0
     CompileUnit *Unit = GetBaseCompileUnit();
 
     // Don't include size of length
@@ -2612,7 +2645,7 @@ private:
 
     Asm->EmitInt32(0); Asm->EOL("EOM (1)");
     Asm->EmitInt32(0); Asm->EOL("EOM (2)");
-  #endif
+#endif
 
     Asm->EOL();
   }
@@ -2822,7 +2855,7 @@ public:
 
   /// EndFunction - Gather and emit post-function debug information.
   ///
-  void EndFunction() {
+  void EndFunction(MachineFunction *MF) {
     if (!ShouldEmitDwarf()) return;
 
     // Define end label for subprogram.
@@ -2842,7 +2875,18 @@ public:
     }
 
     // Construct scopes for subprogram.
-    ConstructRootScope(MMI->getRootScope());
+    if (MMI->getRootScope())
+      ConstructRootScope(MMI->getRootScope());
+    else
+      // FIXME: This is wrong. We are essentially getting past a problem with
+      // debug information not being able to handle unreachable blocks that have
+      // debug information in them. In particular, those unreachable blocks that
+      // have "region end" info in them. That situation results in the "root
+      // scope" not being created. If that's the case, then emit a "default"
+      // scope, i.e., one that encompasses the whole function. This isn't
+      // desirable. And a better way of handling this (and all of the debugging
+      // information) needs to be explored.
+      ConstructDefaultScope(MF);
 
     DebugFrames.push_back(FunctionDebugFrameInfo(SubprogramCount,
                                                  MMI->getFrameMoves()));
@@ -3922,8 +3966,8 @@ void DwarfWriter::BeginFunction(MachineFunction *MF) {
 
 /// EndFunction - Gather and emit post-function debug information.
 ///
-void DwarfWriter::EndFunction() {
-  DD->EndFunction();
+void DwarfWriter::EndFunction(MachineFunction *MF) {
+  DD->EndFunction(MF);
   DE->EndFunction();
 
   if (MachineModuleInfo *MMI = DD->getMMI() ? DD->getMMI() : DE->getMMI())
diff --git a/lib/Target/CellSPU/SPUAsmPrinter.cpp b/lib/Target/CellSPU/SPUAsmPrinter.cpp
index 5b0bacfc89f..8d9e8911162 100644
--- a/lib/Target/CellSPU/SPUAsmPrinter.cpp
+++ b/lib/Target/CellSPU/SPUAsmPrinter.cpp
@@ -461,7 +461,7 @@ LinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF)
   EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
   
   // Emit post-function debug information.
-  DW.EndFunction();
+  DW.EndFunction(&MF);
   
   // We didn't modify anything.
   return false;
diff --git a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp
index f21cb4e710f..557c3af86f0 100644
--- a/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp
+++ b/lib/Target/PowerPC/AsmPrinter/PPCAsmPrinter.cpp
@@ -617,7 +617,7 @@ bool PPCLinuxAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
   EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
 
   // Emit post-function debug information.
-  DW.EndFunction();
+  DW.EndFunction(&MF);
 
   // We didn't modify anything.
   return false;
@@ -809,7 +809,7 @@ bool PPCDarwinAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
   EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
 
   // Emit post-function debug information.
-  DW.EndFunction();
+  DW.EndFunction(&MF);
 
   // We didn't modify anything.
   return false;
diff --git a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp
index 57db93387f0..eb66a4fc611 100644
--- a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp
+++ b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp
@@ -260,7 +260,7 @@ bool X86ATTAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
 
   // Emit post-function debug information.
   if (TAI->doesSupportDebugInformation())
-    DW.EndFunction();
+    DW.EndFunction(&MF);
 
   // Print out jump tables referenced by the function.
   EmitJumpTableInfo(MF.getJumpTableInfo(), MF);