Generate subprogram debug info with -g.
Also take care of freeing memory at the right places.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@51553 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index ca93302..9ac77a4 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -14,6 +14,7 @@
 #ifndef CLANG_CODEGEN_CGDEBUGINFO_H
 #define CLANG_CODEGEN_CGDEBUGINFO_H
 
+#include "clang/AST/Type.h"
 #include "clang/Basic/SourceLocation.h"
 #include <map>
 #include <vector>
@@ -28,14 +29,18 @@
   class AnchorDesc;
   class DebugInfoDesc;
   class Value;
+  class TypeDesc;
+  class SubprogramDesc;
 }
 
 namespace clang {
+  class FunctionDecl;
 namespace CodeGen {
   class CodeGenModule;
 
-/// DebugInfo - This class gathers all debug information during compilation and
-/// is responsible for emitting to llvm globals or pass directly to the backend.
+/// CGDebugInfo - This class gathers all debug information during compilation 
+/// and is responsible for emitting to llvm globals or pass directly to 
+/// the backend.
 class CGDebugInfo {
 private:
   CodeGenModule *M;
@@ -45,41 +50,70 @@
 
   /// CompileUnitCache - Cache of previously constructed CompileUnits.
   std::map<unsigned, llvm::CompileUnitDesc *> CompileUnitCache;
-  std::vector<llvm::DebugInfoDesc*> DebugAllocationList;
+
+  /// TypeCache - Cache of previously constructed Types.
+  std::map<void *, llvm::TypeDesc *> TypeCache;
   
   llvm::Function *StopPointFn;
-  llvm::AnchorDesc *CompileUnitAnchor;
-  llvm::AnchorDesc *SubProgramAnchor;
+  llvm::Function *FuncStartFn;
+  llvm::Function *DeclareFn;
   llvm::Function *RegionStartFn;
   llvm::Function *RegionEndFn;
-  llvm::Function *FuncStartFn;
-  llvm::Value *CurFuncDesc;  
+  llvm::AnchorDesc *CompileUnitAnchor;
+  llvm::AnchorDesc *SubprogramAnchor;
+  std::vector<llvm::DebugInfoDesc *> RegionStack;  
+  llvm::SubprogramDesc *Subprogram;
 
-  /// getOrCreateCompileUnit - Get the compile unit from the cache or create a
-  /// new one if necessary.
-  llvm::CompileUnitDesc *getOrCreateCompileUnit(SourceLocation loc);
-
-  /// getCastValueFor - Return a llvm representation for a given debug
-  /// information descriptor cast to an empty struct pointer.
-  llvm::Value *getCastValueFor(llvm::DebugInfoDesc *DD);
+  /// Helper functions for getOrCreateType.
+  llvm::TypeDesc *getOrCreateCVRType(QualType type, 
+                                     llvm::CompileUnitDesc *unit);
+  llvm::TypeDesc *getOrCreateBuiltinType(QualType type, 
+                                     llvm::CompileUnitDesc *unit);
+  llvm::TypeDesc *getOrCreateTypedefType(QualType type, 
+                                     llvm::CompileUnitDesc *unit);
+  llvm::TypeDesc *getOrCreatePointerType(QualType type, 
+                                     llvm::CompileUnitDesc *unit);
+  llvm::TypeDesc *getOrCreateFunctionType(QualType type, 
+                                     llvm::CompileUnitDesc *unit);
 
 public:
   CGDebugInfo(CodeGenModule *m);
   ~CGDebugInfo();
 
-  void setLocation(SourceLocation loc) { CurLoc = loc; };
+  void setLocation(SourceLocation loc) { CurLoc = loc; }
 
   /// EmitStopPoint - Emit a call to llvm.dbg.stoppoint to indicate a change of
   /// source line.
   void EmitStopPoint(llvm::Function *Fn, llvm::IRBuilder &Builder);
+
+  /// EmitFunctionStart - Emit a call to llvm.dbg.function.start to indicate
+  /// start of a new function
+  void EmitFunctionStart(const FunctionDecl *FnDecl, llvm::Function *Fn,
+                         llvm::IRBuilder &Builder);
   
-  /// EmitFunctionStart - Emit a call to llvm.dbg.func.start to indicate start
+  /// EmitRegionStart - Emit a call to llvm.dbg.region.start to indicate start
   /// of a new block.  
-  void EmitFunctionStart(llvm::Function *Fn, llvm::IRBuilder &Builder);
+  void EmitRegionStart(llvm::Function *Fn, llvm::IRBuilder &Builder);
   
-  /// EmitFunctionEnd - Emit call to llvm.dbg.region.end to indicate end of a 
+  /// EmitRegionEnd - Emit call to llvm.dbg.region.end to indicate end of a 
   /// block.
-  void EmitFunctionEnd(llvm::Function *Fn, llvm::IRBuilder &Builder);
+  void EmitRegionEnd(llvm::Function *Fn, llvm::IRBuilder &Builder);
+ 
+  /// getOrCreateCompileUnit - Get the compile unit from the cache or create a
+  /// new one if necessary.
+  llvm::CompileUnitDesc *getOrCreateCompileUnit(SourceLocation loc);
+
+  /// getOrCreateType - Get the type from the cache or create a new type if
+  /// necessary.
+  llvm::TypeDesc *getOrCreateType(QualType type, llvm::CompileUnitDesc *unit);
+
+  /// getCastValueFor - Return a llvm representation for a given debug
+  /// information descriptor cast to an empty struct pointer.
+  llvm::Value *getCastValueFor(llvm::DebugInfoDesc *DD);
+
+  /// getValueFor - Return a llvm representation for a given debug information
+  /// descriptor.
+  llvm::Value *getValueFor(llvm::DebugInfoDesc *DD);
 };
 } // namespace CodeGen
 } // namespace clang