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.cpp b/lib/CodeGen/CGDebugInfo.cpp
index abe1699..e703396 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -13,20 +13,20 @@
 
 #include "CGDebugInfo.h"
 #include "CodeGenModule.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Instructions.h"
 #include "llvm/Intrinsics.h"
 #include "llvm/Module.h"
-#include "llvm/Support/Dwarf.h"
-#include "llvm/Support/IRBuilder.h"
-#include "llvm/Target/TargetMachine.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/AST/ASTContext.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/IRBuilder.h"
+#include "llvm/Target/TargetMachine.h"
 using namespace clang;
 using namespace clang::CodeGen;
 
@@ -35,13 +35,16 @@
 , CurLoc()
 , PrevLoc()
 , CompileUnitCache()
+, TypeCache()
 , StopPointFn(NULL)
-, CompileUnitAnchor(NULL)
-, SubProgramAnchor(NULL)
+, FuncStartFn(NULL)
+, DeclareFn(NULL)
 , RegionStartFn(NULL)
 , RegionEndFn(NULL)
-, FuncStartFn(NULL)
-, CurFuncDesc(NULL)
+, CompileUnitAnchor(NULL)
+, SubprogramAnchor(NULL)
+, RegionStack()
+, Subprogram(NULL)
 {
   SR = new llvm::DISerializer();
   SR->setModule (&M->getModule());
@@ -50,19 +53,28 @@
 CGDebugInfo::~CGDebugInfo()
 {
   delete SR;
-  // Clean up allocated debug info; we can't do this until after the
-  // serializer is destroyed because it caches pointers to
-  // the debug info
+
+  // Free CompileUnitCache.
+  for (std::map<unsigned, llvm::CompileUnitDesc *>::iterator I 
+       = CompileUnitCache.begin(); I != CompileUnitCache.end(); ++I) {
+    delete I->second;
+  }
+  CompileUnitCache.clear();
+
+  // Free TypeCache.
+  for (std::map<void *, llvm::TypeDesc *>::iterator I 
+       = TypeCache.begin(); I != TypeCache.end(); ++I) {
+    delete I->second;
+  }
+  TypeCache.clear();
+
+  for (std::vector<llvm::DebugInfoDesc *>::iterator I 
+       = RegionStack.begin(); I != RegionStack.end(); ++I) {
+    delete *I;
+  }
+  
   delete CompileUnitAnchor;
-  delete SubProgramAnchor;
-  // Clean up compile unit descriptions
-  std::map<unsigned, llvm::CompileUnitDesc *>::iterator MI;
-  for (MI = CompileUnitCache.begin(); MI != CompileUnitCache.end(); ++MI)
-    delete MI->second;
-  // Clean up misc allocations
-  std::vector<llvm::DebugInfoDesc*>::iterator VI;
-  for (VI = DebugAllocationList.begin(); VI != DebugAllocationList.end(); ++VI)
-    delete *VI;
+  delete SubprogramAnchor;
 }
 
 
@@ -73,6 +85,12 @@
                                         SR->getEmptyStructPtrType());
 }
 
+/// getValueFor - Return a llvm representation for a given debug information
+/// descriptor.
+llvm::Value *CGDebugInfo::getValueFor(llvm::DebugInfoDesc *DD) {
+  return SR->Serialize(DD);
+}
+
 /// getOrCreateCompileUnit - Get the compile unit from the cache or create a new
 /// one if necessary.
 llvm::CompileUnitDesc 
@@ -123,10 +141,313 @@
 }
 
 
-void 
-CGDebugInfo::EmitStopPoint(llvm::Function *Fn, llvm::IRBuilder &Builder) {
-  if (CurLoc.isInvalid() || CurLoc.isMacroID()) return;
+llvm::TypeDesc *
+CGDebugInfo::getOrCreateCVRType(QualType type, llvm::CompileUnitDesc *Unit)
+{
+  // We will create a Derived type.
+  llvm::DerivedTypeDesc *DTy = NULL;
+  llvm::TypeDesc *FromTy = NULL;
 
+  if (type.isConstQualified()) {
+    DTy = new llvm::DerivedTypeDesc(llvm::dwarf::DW_TAG_const_type);
+    type.removeConst(); 
+    FromTy = getOrCreateType(type, Unit);
+  } else if (type.isVolatileQualified()) {
+    DTy = new llvm::DerivedTypeDesc(llvm::dwarf::DW_TAG_volatile_type);
+    type.removeVolatile(); 
+    FromTy = getOrCreateType(type, Unit);
+  } else if (type.isRestrictQualified()) {
+    DTy = new llvm::DerivedTypeDesc(llvm::dwarf::DW_TAG_restrict_type);
+    type.removeRestrict(); 
+    FromTy = getOrCreateType(type, Unit);
+  }
+
+  // No need to fill in the Name, Line, Size, Alignment, Offset in case of        // CVR derived types.
+  DTy->setContext(Unit);
+  DTy->setFromType(FromTy);
+
+  return DTy;
+}
+
+   
+/// getOrCreateType - Get the Basic type from the cache or create a new
+/// one if necessary.
+llvm::TypeDesc *
+CGDebugInfo::getOrCreateBuiltinType(QualType type, llvm::CompileUnitDesc *Unit)
+{
+  assert (type->getTypeClass() == Type::Builtin);
+
+  const BuiltinType *BT = type->getAsBuiltinType(); 
+
+  unsigned Encoding = 0;
+  switch (BT->getKind())
+  {
+    case BuiltinType::Void:
+      return NULL;
+    case BuiltinType::UChar:
+    case BuiltinType::Char_U:
+      Encoding = llvm::dwarf::DW_ATE_unsigned_char;
+      break;
+    case BuiltinType::Char_S:
+    case BuiltinType::SChar:
+      Encoding = llvm::dwarf::DW_ATE_signed_char;
+      break;
+    case BuiltinType::UShort:
+    case BuiltinType::UInt:
+    case BuiltinType::ULong:
+    case BuiltinType::ULongLong:
+      Encoding = llvm::dwarf::DW_ATE_unsigned;
+      break;
+    case BuiltinType::Short:
+    case BuiltinType::Int:
+    case BuiltinType::Long:
+    case BuiltinType::LongLong:
+      Encoding = llvm::dwarf::DW_ATE_signed;
+      break;
+    case BuiltinType::Bool:
+      Encoding = llvm::dwarf::DW_ATE_boolean;
+      break;
+    case BuiltinType::Float:
+    case BuiltinType::Double:
+      Encoding = llvm::dwarf::DW_ATE_float;
+      break;
+    default:
+      Encoding = llvm::dwarf::DW_ATE_signed;
+      break;
+  } 
+
+  // Ty will have contain the resulting type.
+  llvm::BasicTypeDesc *BTy = new llvm::BasicTypeDesc();
+
+  // Get the name and location early to assist debugging.
+  const char *TyName = BT->getName();
+
+  // Bit size, align and offset of the type.
+  uint64_t Size = M->getContext().getTypeSize(type);
+  uint64_t Align = M->getContext().getTypeAlign(type);
+  uint64_t Offset = 0;
+                                                  
+  // If the type is defined, fill in the details.
+  if (BTy) {
+    BTy->setContext(Unit);
+    BTy->setName(TyName);
+    BTy->setSize(Size);
+    BTy->setAlign(Align);
+    BTy->setOffset(Offset);
+    BTy->setEncoding(Encoding);
+  }
+                                                                                
+  return BTy;
+}
+
+llvm::TypeDesc *
+CGDebugInfo::getOrCreatePointerType(QualType type, llvm::CompileUnitDesc *Unit)
+{
+  // type*
+  llvm::DerivedTypeDesc *DTy =
+    new llvm::DerivedTypeDesc(llvm::dwarf::DW_TAG_pointer_type);
+
+  // Handle the derived type.
+  const PointerType *PTRT = type->getAsPointerType();
+  llvm::TypeDesc *FromTy = getOrCreateType(PTRT->getPointeeType(), Unit);
+ 
+  // Get the name and location early to assist debugging.
+  SourceManager &SM = M->getContext().getSourceManager();
+  uint64_t Line = SM.getLogicalLineNumber(CurLoc);
+                                                                               
+  // Bit size, align and offset of the type.
+  uint64_t Size = M->getContext().getTypeSize(type);
+  uint64_t Align = M->getContext().getTypeAlign(type);
+  uint64_t Offset = 0;
+                                                                               
+  // If the type is defined, fill in the details.
+  if (DTy) {
+    DTy->setContext(Unit);
+    DTy->setLine(Line);
+    DTy->setSize(Size);
+    DTy->setAlign(Align);
+    DTy->setOffset(Offset);
+    DTy->setFromType(FromTy);
+  }
+
+  return DTy;
+}
+
+llvm::TypeDesc *
+CGDebugInfo::getOrCreateTypedefType(QualType type, llvm::CompileUnitDesc *Unit)
+{
+  // typedefs are derived from some other type.
+  llvm::DerivedTypeDesc *DTy =
+    new llvm::DerivedTypeDesc(llvm::dwarf::DW_TAG_typedef);
+
+  // Handle derived type.
+  const TypedefType *TDT = type->getAsTypedefType();
+  llvm::TypeDesc *FromTy = getOrCreateType(TDT->LookThroughTypedefs(),
+                                               Unit);
+
+  // Get the name and location early to assist debugging.
+  const char *TyName = TDT->getDecl()->getName();
+  SourceManager &SM = M->getContext().getSourceManager();
+  uint64_t Line = SM.getLogicalLineNumber(TDT->getDecl()->getLocation());
+                                                                                
+  // If the type is defined, fill in the details.
+  if (DTy) {
+    DTy->setContext(Unit);
+    DTy->setFile(getOrCreateCompileUnit(TDT->getDecl()->getLocation()));
+    DTy->setLine(Line);
+    DTy->setName(TyName);
+    DTy->setFromType(FromTy);
+  }
+
+  return DTy;
+}
+
+llvm::TypeDesc *
+CGDebugInfo::getOrCreateFunctionType(QualType type, llvm::CompileUnitDesc *Unit)
+{
+  llvm::CompositeTypeDesc *SubrTy =
+    new llvm::CompositeTypeDesc(llvm::dwarf::DW_TAG_subroutine_type);
+
+  // Prepare to add the arguments for the subroutine.
+  std::vector<llvm::DebugInfoDesc *> &Elements = SubrTy->getElements();
+
+  // Get result type.
+  const FunctionType *FT = type->getAsFunctionType();
+  llvm::TypeDesc *ArgTy = getOrCreateType(FT->getResultType(), Unit);
+  if (ArgTy) Elements.push_back(ArgTy);
+
+  // Set up remainder of arguments.
+  if (type->getTypeClass() == Type::FunctionProto) {
+    const FunctionTypeProto *FTPro = dyn_cast<FunctionTypeProto>(type);
+    for (unsigned int i =0; i < FTPro->getNumArgs(); i++) {
+      QualType ParamType = FTPro->getArgType(i);
+      ArgTy = getOrCreateType(ParamType, Unit);
+      if (ArgTy) Elements.push_back(ArgTy);
+    }
+  }
+
+  // FIXME: set other fields file, line here.	
+  SubrTy->setContext(Unit);
+
+  return SubrTy;
+}
+
+
+  
+/// getOrCreateType - Get the type from the cache or create a new
+/// one if necessary.
+llvm::TypeDesc *
+CGDebugInfo::getOrCreateType(QualType type, llvm::CompileUnitDesc *Unit)
+{
+  if (type.isNull())
+    return NULL;
+
+  // Check to see if the compile unit already has created this type.
+  llvm::TypeDesc *&Slot = TypeCache[type.getAsOpaquePtr()];
+  if (Slot) return Slot;
+
+  // We need to check for the CVR qualifiers as the first thing.
+  if (type.getCVRQualifiers()) {
+    Slot = getOrCreateCVRType (type, Unit);
+    return Slot;
+  }
+
+  // Work out details of type.
+  switch(type->getTypeClass()) {
+    case Type::Complex:
+    case Type::Reference:
+    case Type::ConstantArray:
+    case Type::VariableArray:
+    case Type::IncompleteArray:
+    case Type::Vector:
+    case Type::ExtVector:
+    case Type::Tagged:
+    case Type::ASQual:
+    case Type::ObjCInterface:
+    case Type::ObjCQualifiedInterface:
+    case Type::ObjCQualifiedId:
+    case Type::TypeOfExp:
+    case Type::TypeOfTyp:
+    default:
+    {
+      assert (0 && "Unsupported type");
+      return NULL;
+    }
+
+    case Type::TypeName:
+      Slot = getOrCreateTypedefType(type, Unit);
+      break;
+
+    case Type::FunctionProto:
+    case Type::FunctionNoProto:
+      Slot = getOrCreateFunctionType(type, Unit);
+      break;
+
+    case Type::Builtin:
+      Slot = getOrCreateBuiltinType(type, Unit);
+      break;
+
+    case Type::Pointer:
+      Slot = getOrCreatePointerType(type, Unit);
+      break;
+  }
+
+  return Slot;
+}
+
+/// EmitFunctionStart - Constructs the debug code for entering a function -
+/// "llvm.dbg.func.start.".
+void CGDebugInfo::EmitFunctionStart(const FunctionDecl *FnDecl,
+                                    llvm::Function *Fn,
+                                    llvm::IRBuilder &Builder)
+{
+  // Create subprogram descriptor.
+  Subprogram = new llvm::SubprogramDesc();
+
+  // Make sure we have an anchor.
+  if (!SubprogramAnchor) {
+    SubprogramAnchor = new llvm::AnchorDesc(Subprogram);
+  }
+
+  // Get name information.
+  Subprogram->setName(FnDecl->getName());
+  Subprogram->setFullName(FnDecl->getName());
+
+  // Gather location information.
+  llvm::CompileUnitDesc *Unit = getOrCreateCompileUnit(CurLoc);
+  SourceManager &SM = M->getContext().getSourceManager();
+  uint64_t Loc = SM.getLogicalLineNumber(CurLoc);
+
+  // Get Function Type.
+  QualType type = FnDecl->getResultType();
+  llvm::TypeDesc *SPTy = getOrCreateType(type, Unit);
+
+  Subprogram->setAnchor(SubprogramAnchor);
+  Subprogram->setContext(Unit);
+  Subprogram->setFile(Unit);
+  Subprogram->setLine(Loc);
+  Subprogram->setType(SPTy);
+  Subprogram->setIsStatic(Fn->hasInternalLinkage());
+  Subprogram->setIsDefinition(true);
+
+  // Lazily construct llvm.dbg.func.start.
+  if (!FuncStartFn)
+    FuncStartFn = llvm::Intrinsic::getDeclaration(&M->getModule(),
+                    llvm::Intrinsic::dbg_func_start);
+
+  // Call llvm.dbg.func.start which also implicitly calls llvm.dbg.stoppoint.
+  Builder.CreateCall(FuncStartFn, getCastValueFor(Subprogram), "");
+
+  // Push function on region stack.
+  RegionStack.push_back(Subprogram);
+}
+
+
+void 
+CGDebugInfo::EmitStopPoint(llvm::Function *Fn, llvm::IRBuilder &Builder) 
+{
+  if (CurLoc.isInvalid() || CurLoc.isMacroID()) return;
+  
   // Don't bother if things are the same as last time.
   SourceManager &SM = M->getContext().getSourceManager();
   if (CurLoc == PrevLoc 
@@ -157,35 +478,25 @@
 
 /// EmitRegionStart- Constructs the debug code for entering a declarative
 /// region - "llvm.dbg.region.start.".
-void CGDebugInfo::EmitFunctionStart(llvm::Function *Fn, llvm::IRBuilder &Builder) 
+void CGDebugInfo::EmitRegionStart(llvm::Function *Fn, llvm::IRBuilder &Builder) 
 {
-  // Get the appropriate compile unit.
-  llvm::CompileUnitDesc *Unit = getOrCreateCompileUnit(CurLoc);
+  llvm::BlockDesc *Block = new llvm::BlockDesc();
+  if (RegionStack.size() > 0)
+    Block->setContext(RegionStack.back());
+  RegionStack.push_back(Block);
 
-  llvm::SubprogramDesc* Block = new llvm::SubprogramDesc;
-  DebugAllocationList.push_back(Block);
-  Block->setFile(Unit);
-  Block->setContext(Unit);
-  if (!SubProgramAnchor) {
-    SubProgramAnchor = new llvm::AnchorDesc(Block);
-    SR->Serialize(SubProgramAnchor);
-  }
-  Block->setAnchor(SubProgramAnchor);
-  Block->setName(Fn->getName());
-  Block->setFullName(Fn->getName());
-  Block->setIsDefinition(true);
-  SourceManager &SM = M->getContext().getSourceManager();
-  Block->setLine(SM.getLogicalLineNumber(CurLoc));
-  CurFuncDesc = getCastValueFor(Block);
-  if (!FuncStartFn)
-    FuncStartFn = llvm::Intrinsic::getDeclaration(&M->getModule(),
-                                llvm::Intrinsic::dbg_func_start);
-  Builder.CreateCall(FuncStartFn, CurFuncDesc);
+  // Lazily construct llvm.dbg.region.start function.
+  if (!RegionStartFn)
+    RegionStartFn = llvm::Intrinsic::getDeclaration(&M->getModule(), 
+                                llvm::Intrinsic::dbg_region_start);
+
+  // Call llvm.dbg.func.start.
+  Builder.CreateCall(RegionStartFn, getCastValueFor(Block), "");
 }
 
 /// EmitRegionEnd - Constructs the debug code for exiting a declarative
 /// region - "llvm.dbg.region.end."
-void CGDebugInfo::EmitFunctionEnd(llvm::Function *Fn, llvm::IRBuilder &Builder) 
+void CGDebugInfo::EmitRegionEnd(llvm::Function *Fn, llvm::IRBuilder &Builder) 
 {
   // Lazily construct llvm.dbg.region.end function.
   if (!RegionEndFn)
@@ -196,6 +507,8 @@
   EmitStopPoint(Fn, Builder);
   
   // Call llvm.dbg.func.end.
-  Builder.CreateCall(RegionEndFn, CurFuncDesc, "");
+  llvm::DebugInfoDesc *DID = RegionStack.back();
+  Builder.CreateCall(RegionEndFn, getCastValueFor(DID), "");
+  RegionStack.pop_back();
 }