aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-11-10 06:08:34 +0000
committerChris Lattner <sabre@nondot.org>2008-11-10 06:08:34 +0000
commit9c85ba33ac85bbf5915f300a4b228bad7c693ee7 (patch)
tree85cdfa0459102a72ab383e3f59ae0c6c847a2982
parent7d94e269d87fd5ae53d9b1c43578c70c184db2d3 (diff)
reimplement debug info generation in terms of DebugInfo.h instead of
using MachineModuleInfo. This runs at about the same speed as the old code, but fixes a bunch of bugs and is simpler and shorter. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58971 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp1009
-rw-r--r--lib/CodeGen/CGDebugInfo.h109
-rw-r--r--lib/CodeGen/CGDecl.cpp14
3 files changed, 410 insertions, 722 deletions
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index d246c56a9c..4b3ef0ebd0 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -25,622 +25,415 @@
#include "llvm/Module.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Target/TargetMachine.h"
using namespace clang;
using namespace clang::CodeGen;
CGDebugInfo::CGDebugInfo(CodeGenModule *m)
-: M(m)
-, CurLoc()
-, PrevLoc()
-, CompileUnitCache()
-, TypeCache()
-, StopPointFn(NULL)
-, FuncStartFn(NULL)
-, DeclareFn(NULL)
-, RegionStartFn(NULL)
-, RegionEndFn(NULL)
-, CompileUnitAnchor(NULL)
-, SubprogramAnchor(NULL)
-, GlobalVariableAnchor(NULL)
-, RegionStack()
-, VariableDescList()
-, GlobalVarDescList()
-, EnumDescList()
-, SubrangeDescList()
-, Subprogram(NULL)
-{
- SR = new llvm::DISerializer();
- SR->setModule (&M->getModule());
+ : M(m), DebugFactory(M->getModule()) {
}
-CGDebugInfo::~CGDebugInfo()
-{
+CGDebugInfo::~CGDebugInfo() {
assert(RegionStack.empty() && "Region stack mismatch, stack not empty!");
-
- delete SR;
-
- // Free CompileUnitCache.
- for (std::map<const FileEntry*, 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();
-
- // Free region descriptors.
- for (std::vector<llvm::DebugInfoDesc *>::iterator I
- = RegionStack.begin(); I != RegionStack.end(); ++I) {
- delete *I;
- }
-
- // Free local var descriptors.
- for (std::vector<llvm::VariableDesc *>::iterator I
- = VariableDescList.begin(); I != VariableDescList.end(); ++I) {
- delete *I;
- }
-
- // Free global var descriptors.
- for (std::vector<llvm::GlobalVariableDesc *>::iterator I
- = GlobalVarDescList.begin(); I != GlobalVarDescList.end(); ++I) {
- delete *I;
- }
-
- // Free enum constants descriptors.
- for (std::vector<llvm::EnumeratorDesc *>::iterator I
- = EnumDescList.begin(); I != EnumDescList.end(); ++I) {
- delete *I;
- }
-
- // Free subrange descriptors.
- for (std::vector<llvm::SubrangeDesc *>::iterator I
- = SubrangeDescList.begin(); I != SubrangeDescList.end(); ++I) {
- delete *I;
- }
-
- delete CompileUnitAnchor;
- delete SubprogramAnchor;
- delete GlobalVariableAnchor;
-}
-
-void CGDebugInfo::setLocation(SourceLocation loc) {
- if (loc.isValid())
- CurLoc = M->getContext().getSourceManager().getLogicalLoc(loc);
-}
-
-/// getCastValueFor - Return a llvm representation for a given debug information
-/// descriptor cast to an empty struct pointer.
-llvm::Value *CGDebugInfo::getCastValueFor(llvm::DebugInfoDesc *DD) {
- return llvm::ConstantExpr::getBitCast(SR->Serialize(DD),
- SR->getEmptyStructPtrType());
}
-/// getValueFor - Return a llvm representation for a given debug information
-/// descriptor.
-llvm::Value *CGDebugInfo::getValueFor(llvm::DebugInfoDesc *DD) {
- return SR->Serialize(DD);
+void CGDebugInfo::setLocation(SourceLocation Loc) {
+ if (Loc.isValid())
+ CurLoc = M->getContext().getSourceManager().getLogicalLoc(Loc);
}
/// getOrCreateCompileUnit - Get the compile unit from the cache or create a new
/// one if necessary. This returns null for invalid source locations.
-llvm::CompileUnitDesc*
-CGDebugInfo::getOrCreateCompileUnit(const SourceLocation Loc) {
+llvm::DICompileUnit CGDebugInfo::getOrCreateCompileUnit(SourceLocation Loc) {
if (Loc.isInvalid())
- return NULL;
+ return llvm::DICompileUnit();
SourceManager &SM = M->getContext().getSourceManager();
const FileEntry *FE = SM.getFileEntryForLoc(Loc);
-
+ if (FE == 0) return llvm::DICompileUnit();
+
// See if this compile unit has been used before.
- llvm::CompileUnitDesc *&Unit = CompileUnitCache[FE];
- if (Unit) return Unit;
+ llvm::DICompileUnit &Unit = CompileUnitCache[FE];
+ if (!Unit.isNull()) return Unit;
- // Create new compile unit.
- // FIXME: Where to free these?
- // One way is to iterate over the CompileUnitCache in ~CGDebugInfo.
- Unit = new llvm::CompileUnitDesc();
-
- // Make sure we have an anchor.
- if (!CompileUnitAnchor) {
- CompileUnitAnchor = new llvm::AnchorDesc(Unit);
- }
-
// Get source file information.
- const char *FileName, *DirName;
- if (FE) {
- FileName = FE->getName();
- DirName = FE->getDir()->getName();
- } else {
- FileName = SM.getSourceName(Loc);
- DirName = "";
- }
-
- Unit->setAnchor(CompileUnitAnchor);
- Unit->setFileName(FileName);
- Unit->setDirectory(DirName);
-
- // Set up producer name.
+ const char *FileName = FE->getName();
+ const char *DirName = FE->getDir()->getName();
+
+ // Create new compile unit.
+ // FIXME: Handle other language IDs as well.
// FIXME: Do not know how to get clang version yet.
- Unit->setProducer("clang");
-
- // Set up Language number.
- // FIXME: Handle other languages as well.
- Unit->setLanguage(llvm::dwarf::DW_LANG_C89);
-
- return Unit;
+ return Unit = DebugFactory.CreateCompileUnit(llvm::dwarf::DW_LANG_C89,
+ FileName, DirName, "clang");
}
-
-/// getOrCreateCVRType - Get the CVR qualified type from the cache or create
-/// a new one if necessary.
-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;
-}
-
-
/// getOrCreateBuiltinType - Get the Basic type from the cache or create a new
/// one if necessary.
-llvm::TypeDesc *
-CGDebugInfo::getOrCreateBuiltinType(const BuiltinType *type,
- llvm::CompileUnitDesc *Unit) {
+llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT,
+ llvm::DICompileUnit Unit){
unsigned Encoding = 0;
- switch (type->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;
+ switch (BT->getKind()) {
+ default:
+ case BuiltinType::Void:
+ return llvm::DIType();
+ 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;
}
-
- // 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 = type->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 Size = M->getContext().getTypeSize(BT);
+ uint64_t Align = M->getContext().getTypeAlign(BT);
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;
+
+ return DebugFactory.CreateBasicType(Unit, BT->getName(), Unit, 0, Size, Align,
+ Offset, /*flags*/ 0, Encoding);
}
-llvm::TypeDesc *
-CGDebugInfo::getOrCreatePointerType(const PointerType *type,
- llvm::CompileUnitDesc *Unit) {
- // type*
- llvm::DerivedTypeDesc *DTy =
- new llvm::DerivedTypeDesc(llvm::dwarf::DW_TAG_pointer_type);
+/// getOrCreateCVRType - Get the CVR qualified type from the cache or create
+/// a new one if necessary.
+llvm::DIType CGDebugInfo::CreateCVRType(QualType Ty, llvm::DICompileUnit Unit) {
+ // We will create one Derived type for one qualifier and recurse to handle any
+ // additional ones.
+ llvm::DIType FromTy;
+ unsigned Tag;
+ if (Ty.isConstQualified()) {
+ Tag = llvm::dwarf::DW_TAG_const_type;
+ Ty.removeConst();
+ FromTy = getOrCreateType(Ty, Unit);
+ } else if (Ty.isVolatileQualified()) {
+ Tag = llvm::dwarf::DW_TAG_volatile_type;
+ Ty.removeVolatile();
+ FromTy = getOrCreateType(Ty, Unit);
+ } else {
+ assert(Ty.isRestrictQualified() && "Unknown type qualifier for debug info");
+ Tag = llvm::dwarf::DW_TAG_restrict_type;
+ Ty.removeRestrict();
+ FromTy = getOrCreateType(Ty, Unit);
+ }
+
+ // No need to fill in the Name, Line, Size, Alignment, Offset in case of
+ // CVR derived types.
+ return DebugFactory.CreateDerivedType(Tag, Unit, "", llvm::DICompileUnit(),
+ 0, 0, 0, 0, 0, FromTy);
+}
- // Handle the derived type.
- llvm::TypeDesc *FromTy = getOrCreateType(type->getPointeeType(), Unit);
+llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty,
+ llvm::DICompileUnit Unit) {
+ llvm::DIType EltTy = getOrCreateType(Ty->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;
+ uint64_t Size = M->getContext().getTypeSize(Ty);
+ uint64_t Align = M->getContext().getTypeAlign(Ty);
- // 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;
+ return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit,
+ "", llvm::DICompileUnit(),
+ 0, Size, Align, 0, 0, EltTy);
}
-llvm::TypeDesc *
-CGDebugInfo::getOrCreateTypedefType(const TypedefType *TDT,
- llvm::CompileUnitDesc *Unit) {
- // typedefs are derived from some other type.
- llvm::DerivedTypeDesc *DTy =
- new llvm::DerivedTypeDesc(llvm::dwarf::DW_TAG_typedef);
-
- // Handle derived type.
- llvm::TypeDesc *FromTy = getOrCreateType(TDT->LookThroughTypedefs(),
- Unit);
+llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty,
+ llvm::DICompileUnit Unit) {
+ // Typedefs are derived from some other type. If we have a typedef of a
+ // typedef, make sure to emit the whole chain.
+ llvm::DIType Src = getOrCreateType(Ty->getDecl()->getUnderlyingType(), Unit);
+
+ // We don't set size information, but do specify where the typedef was
+ // declared.
+ const char *TyName = Ty->getDecl()->getName();
+ SourceLocation DefLoc = Ty->getDecl()->getLocation();
+ llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(DefLoc);
- // 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);
- }
+ uint64_t Line = SM.getLogicalLineNumber(DefLoc);
- return DTy;
+ return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_typedef, Unit,
+ TyName, DefUnit, Line, 0, 0, 0, 0, Src);
}
-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);
- 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);
- // FIXME: Remove once we support all types.
- if (ArgTy) Elements.push_back(ArgTy);
- }
- }
+llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
+ llvm::DICompileUnit Unit) {
+ llvm::SmallVector<llvm::DIDescriptor, 16> EltTys;
- // FIXME: set other fields file, line here.
- SubrTy->setContext(Unit);
+ // Add the result type at least.
+ EltTys.push_back(getOrCreateType(Ty->getResultType(), Unit));
+
+ // Set up remainder of arguments if there is a prototype.
+ // FIXME: IF NOT, HOW IS THIS REPRESENTED? llvm-gcc doesn't represent '...'!
+ if (const FunctionTypeProto *FTP = dyn_cast<FunctionTypeProto>(Ty)) {
+ for (unsigned i = 0, e = FTP->getNumArgs(); i != e; ++i)
+ EltTys.push_back(getOrCreateType(FTP->getArgType(i), Unit));
+ } else {
+ // FIXME: Handle () case in C. llvm-gcc doesn't do it either.
+ }
- return SubrTy;
+ llvm::DIArray EltTypeArray =
+ DebugFactory.GetOrCreateArray(&EltTys[0], EltTys.size());
+
+ return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type,
+ Unit, "", llvm::DICompileUnit(),
+ 0, 0, 0, 0, 0,
+ llvm::DIType(), EltTypeArray);
}
/// getOrCreateRecordType - get structure or union type.
-void CGDebugInfo::getOrCreateRecordType(const RecordType *type,
- llvm::CompileUnitDesc *Unit,
- llvm::TypeDesc *&Slot)
-{
- // Prevent recursing in type generation by initializing the slot
- // here.
- llvm::CompositeTypeDesc *RecType;
- if (type->isStructureType())
- Slot = RecType =
- new llvm::CompositeTypeDesc(llvm::dwarf::DW_TAG_structure_type);
- else if (type->isUnionType())
- Slot = RecType =
- new llvm::CompositeTypeDesc(llvm::dwarf::DW_TAG_union_type);
- else
- return;
-
- RecordDecl *RecDecl = type->getDecl();
- // We can not get the type for forward declarations.
- // FIXME: What *should* we be doing here?
- if (!RecDecl->getDefinition(M->getContext()))
- return;
- const ASTRecordLayout &RL = M->getContext().getASTRecordLayout(RecDecl);
-
- SourceManager &SM = M->getContext().getSourceManager();
- uint64_t Line = SM.getLogicalLineNumber(RecDecl->getLocation());
-
- std::vector<llvm::DebugInfoDesc *> &Elements = RecType->getElements();
-
- // Add the members.
- int NumMembers = RecDecl->getNumMembers();
- for (int i = 0; i < NumMembers; i++) {
- FieldDecl *Member = RecDecl->getMember(i);
- llvm::TypeDesc *MemberTy = getOrCreateType(Member->getType(), Unit);
- // FIXME: Remove once we support all types.
- if (MemberTy) {
- MemberTy->setOffset(RL.getFieldOffset(i));
- Elements.push_back(MemberTy);
- }
- }
-
- // Fill in the blanks.
- if (RecType) {
- RecType->setContext(Unit);
- RecType->setName(RecDecl->getName());
- RecType->setFile(getOrCreateCompileUnit(RecDecl->getLocation()));
- RecType->setLine(Line);
- RecType->setSize(RL.getSize());
- RecType->setAlign(RL.getAlignment());
- RecType->setOffset(0);
+llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty,
+ llvm::DICompileUnit Unit) {
+ const RecordDecl *Decl = Ty->getDecl();
+
+ if (!Decl->getDefinition(M->getContext()))
+ return llvm::DIType();
+
+ unsigned Tag;
+ if (Decl->isStruct())
+ Tag = llvm::dwarf::DW_TAG_structure_type;
+ else if (Decl->isUnion())
+ Tag = llvm::dwarf::DW_TAG_union_type;
+ else {
+ assert(Decl->isClass() && "Unknown RecordType!");
+ Tag = llvm::dwarf::DW_TAG_class_type;
}
-}
-
-/// getOrCreateEnumType - get Enum type.
-llvm::TypeDesc *
-CGDebugInfo::getOrCreateEnumType(const EnumType *type,
- llvm::CompileUnitDesc *Unit) {
- llvm::CompositeTypeDesc *EnumTy
- = new llvm::CompositeTypeDesc(llvm::dwarf::DW_TAG_enumeration_type);
- EnumDecl *EDecl = type->getDecl();
SourceManager &SM = M->getContext().getSourceManager();
- uint64_t Line = SM.getLogicalLineNumber(EDecl->getLocation());
- // Size, align and offset of the type.
- uint64_t Size = M->getContext().getTypeSize(type);
- uint64_t Align = M->getContext().getTypeAlign(type);
+ // Get overall information about the record type for the debug info.
+ const char *Name = Decl->getName();
+ if (Name == 0) Name = "";
+
+ llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(Decl->getLocation());
+ uint64_t Line = SM.getLogicalLineNumber(Decl->getLocation());
+
- // Create descriptors for enum members.
- std::vector<llvm::DebugInfoDesc *> &Elements = EnumTy->getElements();
- EnumConstantDecl *ElementList = EDecl->getEnumConstantList();
- while (ElementList) {
- llvm::EnumeratorDesc *EnumDesc = new llvm::EnumeratorDesc();
- // push it to the enum desc list so that we can free it later.
- EnumDescList.push_back(EnumDesc);
-
- const char *ElementName = ElementList->getName();
- uint64_t Value = ElementList->getInitVal().getZExtValue();
-
- EnumDesc->setName(ElementName);
- EnumDesc->setValue(Value);
- Elements.push_back(EnumDesc);
- if (ElementList->getNextDeclarator())
- ElementList
- = dyn_cast<EnumConstantDecl>(ElementList->getNextDeclarator());
- else
- break;
+ // Records and classes and unions can all be recursive. To handle them, we
+ // first generate a debug descriptor for the struct as a forward declaration.
+ // Then (if it is a definition) we go through and get debug info for all of
+ // its members. Finally, we create a descriptor for the complete type (which
+ // may refer to the forward decl if the struct is recursive) and replace all
+ // uses of the forward declaration with the final definition.
+ llvm::DIType FwdDecl =
+ DebugFactory.CreateCompositeType(Tag, Unit, Name, DefUnit, Line, 0, 0, 0, 0,
+ llvm::DIType(), llvm::DIArray());
+
+ // If this is just a forward declaration, return it.
+ if (!Decl->getDefinition(M->getContext()))
+ return FwdDecl;
+
+ // Otherwise, insert it into the TypeCache so that recursive uses will find
+ // it.
+ TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl;
+
+ // Convert all the elements.
+ llvm::SmallVector<llvm::DIDescriptor, 16> EltTys;
+
+ const ASTRecordLayout &RL = M->getContext().getASTRecordLayout(Decl);
+
+ unsigned FieldNo = 0;
+ for (RecordDecl::field_const_iterator I = Decl->field_begin(),
+ E = Decl->field_end(); I != E; ++I, ++FieldNo) {
+ FieldDecl *Field = *I;
+ llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
+
+#if 0
+ const char *FieldName = Field->getName();
+ if (FieldName == 0) FieldName = "";
+
+ // Get the location for the field.
+ SourceLocation FieldDefLoc = Field->getLocation();
+ llvm::DICompileUnit FieldDefUnit = getOrCreateCompileUnit(FieldDefLoc);
+ uint64_t FieldLine = SM.getLogicalLineNumber(FieldDefLoc);
+
+ // Bit size, align and offset of the type.
+ uint64_t FieldSize = M->getContext().getTypeSize(Ty);
+ uint64_t FieldAlign = M->getContext().getTypeAlign(Ty);
+ uint64_t FieldOffset = RL.getFieldOffset(FieldNo);
+
+ // Create a DW_TAG_member node to remember the offset of this field in the
+ // struct. FIXME: This is an absolutely insane way to capture this
+ // information. When we gut debug info, this should be fixed.
+ FieldTy = DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_member, Unit,
+ FieldName, FieldDefUnit,
+ FieldLine, FieldSize, FieldAlign,
+ FieldOffset, 0, FieldTy);
+#endif
+ EltTys.push_back(FieldTy);
}
+
+ llvm::DIArray Elements =
+ DebugFactory.GetOrCreateArray(&EltTys[0], EltTys.size());
- // Fill in the blanks.
- if (EnumTy) {
- EnumTy->setContext(Unit);
- EnumTy->setName(EDecl->getName());
- EnumTy->setSize(Size);
- EnumTy->setAlign(Align);
- EnumTy->setOffset(0);
- EnumTy->setFile(getOrCreateCompileUnit(EDecl->getLocation()));
- EnumTy->setLine(Line);
- }
- return EnumTy;
+ // Bit size, align and offset of the type.
+ uint64_t Size = M->getContext().getTypeSize(Ty);
+ uint64_t Align = M->getContext().getTypeAlign(Ty);
+
+ llvm::DIType RealDecl =
+ DebugFactory.CreateCompositeType(Tag, Unit, Name, DefUnit, Line, Size,
+ Align, 0, 0, llvm::DIType(), Elements);
+
+ // Now that we have a real decl for the struct, replace anything using the
+ // old decl with the new one. This will recursively update the debug info.
+ FwdDecl.getGV()->replaceAllUsesWith(RealDecl.getGV());
+ FwdDecl.getGV()->eraseFromParent();
+
+ return RealDecl;
}
-/// getOrCreateArrayType - get or create array types.
-llvm::TypeDesc *
-CGDebugInfo::getOrCreateArrayType(QualType type,
- llvm::CompileUnitDesc *Unit) {
- llvm::CompositeTypeDesc *ArrayTy
- = new llvm::CompositeTypeDesc(llvm::dwarf::DW_TAG_array_type);
+llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty,
+ llvm::DICompileUnit Unit) {
+ EnumDecl *Decl = Ty->getDecl();
- // Size, align and offset of the type.
- uint64_t Size = M->getContext().getTypeSize(type);
- uint64_t Align = M->getContext().getTypeAlign(type);
+ llvm::SmallVector<llvm::DIDescriptor, 32> Enumerators;
- SourceManager &SM = M->getContext().getSourceManager();
- uint64_t Line = SM.getLogicalLineNumber(CurLoc);
+ // Create DIEnumerator elements for each enumerator.
+ for (EnumConstantDecl *Elt = Decl->getEnumConstantList(); Elt;
+ Elt = dyn_cast_or_null<EnumConstantDecl>(Elt->getNextDeclarator())) {
+ Enumerators.push_back(DebugFactory.CreateEnumerator(Elt->getName(),
+ Elt->getInitVal().getZExtValue()));
+ }
+
+ // Return a CompositeType for the enum itself.
+ llvm::DIArray EltArray =
+ DebugFactory.GetOrCreateArray(&Enumerators[0], Enumerators.size());
- // Add the dimensions of the array.
- std::vector<llvm::DebugInfoDesc *> &Elements = ArrayTy->getElements();
- do {
- const ArrayType *AT = M->getContext().getAsArrayType(type);
- llvm::SubrangeDesc *Subrange = new llvm::SubrangeDesc();
+ const char *EnumName = Decl->getName() ? Decl->getName() : "";
+ SourceLocation DefLoc = Decl->getLocation();
+ llvm::DICompileUnit DefUnit = getOrCreateCompileUnit(DefLoc);
+ SourceManager &SM = M->getContext().getSourceManager();
+ uint64_t Line = SM.getLogicalLineNumber(DefLoc);
+
+ // Size and align of the type.
+ uint64_t Size = M->getContext().getTypeSize(Ty);
+ uint64_t Align = M->getContext().getTypeAlign(Ty);
+
+ return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_enumeration_type,
+ Unit, EnumName, DefUnit, Line,
+ Size, Align, 0, 0,
+ llvm::DIType(), EltArray);
+}
- // push it back on the subrange desc list so that we can free it later.
- SubrangeDescList.push_back(Subrange);
+llvm::DIType CGDebugInfo::CreateType(const TagType *Ty,
+ llvm::DICompileUnit Unit) {
+ if (const RecordType *RT = dyn_cast<RecordType>(Ty))
+ return CreateType(RT, Unit);
+ else if (const EnumType *ET = dyn_cast<EnumType>(Ty))
+ return CreateType(ET, Unit);
+
+ return llvm::DIType();
+}
+llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
+ llvm::DICompileUnit Unit) {
+ // Size and align of the whole array, not the element type.
+ uint64_t Size = M->getContext().getTypeSize(Ty);
+ uint64_t Align = M->getContext().getTypeAlign(Ty);
+
+ // Add the dimensions of the array. FIXME: This loses CV qualifiers from
+ // interior arrays, do we care? Why aren't nested arrays represented the
+ // obvious/recursive way?
+ llvm::SmallVector<llvm::DIDescriptor, 8> Subscripts;
+ QualType EltTy(Ty, 0);
+ while ((Ty = dyn_cast<ArrayType>(EltTy))) {
uint64_t Upper = 0;
- if (const ConstantArrayType *ConstArrTy = dyn_cast<ConstantArrayType>(AT)) {
- Upper = ConstArrTy->getSize().getZExtValue() - 1;
- }
- Subrange->setLo(0);
- Subrange->setHi(Upper);
- Elements.push_back(Subrange);
- type = AT->getElementType();
- } while (type->isArrayType());
-
- ArrayTy->setFromType(getOrCreateType(type, Unit));
-
- if (ArrayTy) {
- ArrayTy->setContext(Unit);
- ArrayTy->setSize(Size);
- ArrayTy->setAlign(Align);
- ArrayTy->setOffset(0);
- ArrayTy->setFile(getOrCreateCompileUnit(CurLoc));
- ArrayTy->setLine(Line);
+ if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Ty))
+ Upper = CAT->getSize().getZExtValue() - 1;
+ // FIXME: Verify this is right for VLAs.
+ Subscripts.push_back(DebugFactory.GetOrCreateSubrange(0, Upper));
+ EltTy = Ty->getElementType();
}
- return ArrayTy;
+
+ llvm::DIArray SubscriptArray =
+ DebugFactory.GetOrCreateArray(&Subscripts[0], Subscripts.size());
+
+ return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_array_type,
+ Unit, "", llvm::DICompileUnit(),
+ 0, Size, Align, 0, 0,
+ getOrCreateType(EltTy, Unit),
+ SubscriptArray);
}
-/// getOrCreateTaggedType - get or create structure/union/Enum type.
-void CGDebugInfo::getOrCreateTagType(const TagType *type,
- llvm::CompileUnitDesc *Unit,
- llvm::TypeDesc *&Slot) {
- if (const RecordType *RT = dyn_cast<RecordType>(type))
- getOrCreateRecordType(RT, Unit, Slot);
- else if (const EnumType *ET = dyn_cast<EnumType>(type))
- Slot = getOrCreateEnumType(ET, Unit);
-}
-
/// 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;
-
+llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty,
+ llvm::DICompileUnit Unit) {
+ if (Ty.isNull())
+ return llvm::DIType();
+
// Check to see if the compile unit already has created this type.
- llvm::TypeDesc *&Slot = TypeCache[type.getAsOpaquePtr()];
- if (Slot) return Slot;
+ llvm::DIType &Slot = TypeCache[Ty.getAsOpaquePtr()];
+ if (!Slot.isNull()) return Slot;
- // We need to check for the CVR qualifiers as the first thing.
- if (type.getCVRQualifiers()) {
- Slot = getOrCreateCVRType(type, Unit);
- return Slot;
- }
+ // Handle CVR qualifiers, which recursively handles what they refer to.
+ if (Ty.getCVRQualifiers())
+ return Slot = CreateCVRType(Ty, Unit);
// Work out details of type.
- switch (type->getTypeClass()) {
- case Type::Complex:
- case Type::Reference:
- case Type::Vector:
- case Type::ExtVector:
- case Type::ASQual:
- case Type::ObjCInterface:
- case Type::ObjCQualifiedInterface:
- case Type::ObjCQualifiedId:
- case Type::TypeOfExp:
- case Type::TypeOfTyp:
- default:
- return NULL;
-
- case Type::TypeName:
- Slot = getOrCreateTypedefType(cast<TypedefType>(type), Unit);
- break;
-
- case Type::FunctionProto:
- case Type::FunctionNoProto:
- Slot = getOrCreateFunctionType(type, Unit);
- break;
-
- case Type::Builtin:
- Slot = getOrCreateBuiltinType(cast<BuiltinType>(type), Unit);
- break;
-
- case Type::Pointer:
- Slot = getOrCreatePointerType(cast<PointerType>(type), Unit);
- break;
-
- case Type::Tagged:
- getOrCreateTagType(cast<TagType>(type), Unit, Slot);
- break;
-
- case Type::ConstantArray:
- case Type::VariableArray:
- case Type::IncompleteArray:
- Slot = getOrCreateArrayType(type, Unit);
- break;
+ switch (Ty->getTypeClass()) {
+ case Type::Complex:
+ case Type::Reference:
+ case Type::Vector:
+ case Type::ExtVector:
+ case Type::ASQual:
+ case Type::ObjCInterface:
+ case Type::ObjCQualifiedInterface:
+ case Type::ObjCQualifiedId:
+ case Type::TypeOfExp:
+ case Type::TypeOfTyp:
+ default:
+ return llvm::DIType();
+
+ case Type::Builtin: Slot = CreateType(cast<BuiltinType>(Ty), Unit); break;
+ case Type::Pointer: Slot = CreateType(cast<PointerType>(Ty), Unit); break;
+ case Type::TypeName: Slot = CreateType(cast<TypedefType>(Ty), Unit); break;
+ case Type::Tagged: Slot = CreateType(cast<TagType>(Ty), Unit); break;
+ case Type::FunctionProto:
+ case Type::FunctionNoProto:
+ Slot = CreateType(cast<FunctionType>(Ty), Unit);
+ break;
+
+ case Type::ConstantArray:
+ case Type::VariableArray:
+ case Type::IncompleteArray:
+ Slot = CreateType(cast<ArrayType>(Ty), Unit);
+ break;
}
-
+
return Slot;
}
/// EmitFunctionStart - Constructs the debug code for entering a function -
/// "llvm.dbg.func.start.".
-void CGDebugInfo::EmitFunctionStart(const char *Name,
- QualType ReturnType,
+void CGDebugInfo::EmitFunctionStart(const char *Name, QualType ReturnType,
llvm::Function *Fn,
- CGBuilderTy &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(Name);
- Subprogram->setFullName(Name);
-
- // Gather location information.
- llvm::CompileUnitDesc *Unit = getOrCreateCompileUnit(CurLoc);
+ CGBuilderTy &Builder) {
+ // FIXME: Why is this using CurLoc???
+ llvm::DICompileUnit Unit = getOrCreateCompileUnit(CurLoc);
SourceManager &SM = M->getContext().getSourceManager();
- uint64_t Loc = SM.getLogicalLineNumber(CurLoc);
-
- // Get Function Type.
- llvm::TypeDesc *SPTy = getOrCreateType(ReturnType, 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), "");
-
+ uint64_t LineNo = SM.getLogicalLineNumber(CurLoc);
+
+ llvm::DISubprogram SP =
+ DebugFactory.CreateSubprogram(Unit, Name, Name, "", Unit, LineNo,
+ getOrCreateType(ReturnType, Unit),
+ Fn->hasInternalLinkage(), true/*definition*/);
+
+ DebugFactory.InsertSubprogramStart(SP, Builder.GetInsertBlock());
+
// Push function on region stack.
- RegionStack.push_back(Subprogram);
+ RegionStack.push_back(SP);
}
-void
-CGDebugInfo::EmitStopPoint(llvm::Function *Fn, CGBuilderTy &Builder)
-{
+void CGDebugInfo::EmitStopPoint(llvm::Function *Fn, CGBuilderTy &Builder) {
if (CurLoc.isInvalid() || CurLoc.isMacroID()) return;
// Don't bother if things are the same as last time.
@@ -654,141 +447,81 @@ CGDebugInfo::EmitStopPoint(llvm::Function *Fn, CGBuilderTy &Builder)
PrevLoc = CurLoc;
// Get the appropriate compile unit.
- llvm::CompileUnitDesc *Unit = getOrCreateCompileUnit(CurLoc);
-
- // Lazily construct llvm.dbg.stoppoint function.
- if (!StopPointFn)
- StopPointFn = llvm::Intrinsic::getDeclaration(&M->getModule(),
- llvm::Intrinsic::dbg_stoppoint);
-
- uint64_t CurLineNo = SM.getLogicalLineNumber(CurLoc);
- uint64_t ColumnNo = SM.getLogicalColumnNumber(CurLoc);
-
- // Invoke llvm.dbg.stoppoint
- Builder.CreateCall3(StopPointFn,
- llvm::ConstantInt::get(llvm::Type::Int32Ty, CurLineNo),
- llvm::ConstantInt::get(llvm::Type::Int32Ty, ColumnNo),
- getCastValueFor(Unit), "");
+ llvm::DICompileUnit Unit = getOrCreateCompileUnit(CurLoc);
+ DebugFactory.InsertStopPoint(Unit, SM.getLogicalLineNumber(CurLoc),
+ SM.getLogicalColumnNumber(CurLoc),
+ Builder.GetInsertBlock());
}
/// EmitRegionStart- Constructs the debug code for entering a declarative
/// region - "llvm.dbg.region.start.".
-void CGDebugInfo::EmitRegionStart(llvm::Function *Fn,
- CGBuilderTy &Builder)
-{
- llvm::BlockDesc *Block = new llvm::BlockDesc();
+void CGDebugInfo::EmitRegionStart(llvm::Function *Fn, CGBuilderTy &Builder) {
+ llvm::DIDescriptor D;
if (!RegionStack.empty())
- Block->setContext(RegionStack.back());
- RegionStack.push_back(Block);
-
- // 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), "");
+ D = RegionStack.back();
+ D = DebugFactory.CreateBlock(D);
+ RegionStack.push_back(D);
+ DebugFactory.InsertRegionStart(D, Builder.GetInsertBlock());
}
/// EmitRegionEnd - Constructs the debug code for exiting a declarative
/// region - "llvm.dbg.region.end."
-void CGDebugInfo::EmitRegionEnd(llvm::Function *Fn, CGBuilderTy &Builder)
-{
+void CGDebugInfo::EmitRegionEnd(llvm::Function *Fn, CGBuilderTy &Builder) {
assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
- // Lazily construct llvm.dbg.region.end function.
- if (!RegionEndFn)
- RegionEndFn =llvm::Intrinsic::getDeclaration(&M->getModule(),
- llvm::Intrinsic::dbg_region_end);
-
// Provide an region stop point.
EmitStopPoint(Fn, Builder);
- // Call llvm.dbg.func.end.
- llvm::DebugInfoDesc *DID = RegionStack.back();
- Builder.CreateCall(RegionEndFn, getCastValueFor(DID), "");
+ DebugFactory.InsertRegionEnd(RegionStack.back(), Builder.GetInsertBlock());
RegionStack.pop_back();
- // FIXME: Should be freeing here?
}
/// EmitDeclare - Emit local variable declaration debug info.
-void CGDebugInfo::EmitDeclare(const VarDecl *decl, unsigned Tag,
- llvm::Value *AI,
- CGBuilderTy &Builder)
-{
+void CGDebugInfo::EmitDeclare(const VarDecl *Decl, unsigned Tag,
+ llvm::Value *Storage, CGBuilderTy &Builder) {
assert(!RegionStack.empty() && "Region stack mismatch, stack empty!");
- // FIXME: If it is a compiler generated temporary then return.
-
- // Construct llvm.dbg.declare function.
- if (!DeclareFn)
- DeclareFn = llvm::Intrinsic::getDeclaration(&M->getModule(),
- llvm::Intrinsic::dbg_declare);
-
- // Get type information.
- llvm::CompileUnitDesc *Unit = getOrCreateCompileUnit(CurLoc);
- llvm::TypeDesc *TyDesc = getOrCreateType(decl->getType(), Unit);
-
+ // Get location information.
SourceManager &SM = M->getContext().getSourceManager();
- uint64_t Loc = SM.getLogicalLineNumber(CurLoc);
-
- // Construct variable.
- llvm::VariableDesc *Variable = new llvm::VariableDesc(Tag);
- Variable->setContext(RegionStack.back());
- Variable->setName(decl->getName());
- Variable->setFile(Unit);
- Variable->setLine(Loc);
- Variable->setType(TyDesc);
-
- // Push it onto the list so that we can free it.
- VariableDescList.push_back(Variable);
-
- // Cast the AllocA result to a {}* for the call to llvm.dbg.declare.
- // These bit cast instructions will get freed when the basic block is
- // deleted. So do not need to free them explicity.
- const llvm::PointerType *EmpPtr = SR->getEmptyStructPtrType();
- llvm::Value *AllocACast = new llvm::BitCastInst(AI, EmpPtr, decl->getName(),
- Builder.GetInsertBlock());
-
- // Call llvm.dbg.declare.
- Builder.CreateCall2(DeclareFn, AllocACast, getCastValueFor(Variable), "");
+ uint64_t Line = SM.getLogicalLineNumber(Decl->getLocation());
+ llvm::DICompileUnit Unit = getOrCreateCompileUnit(Decl->getLocation());
+
+ // Create the descriptor for the variable.
+ llvm::DIVariable D =
+ DebugFactory.CreateVariable(Tag, RegionStack.back(), Decl->getName(),
+ Unit, Line,
+ getOrCreateType(Decl->getType(), Unit));
+ // Insert an llvm.dbg.declare into the current block.
+ DebugFactory.InsertDeclare(Storage, D, Builder.GetInsertBlock());
}
-/// EmitGlobalVariable - Emit information about a global variable.
-void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *GV,
- const VarDecl *decl)
-{
- // Create global variable debug descriptor.
- llvm::GlobalVariableDesc *Global = new llvm::GlobalVariableDesc();
+void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *Decl,
+ llvm::Value *Storage,
+ CGBuilderTy &Builder) {
+ EmitDeclare(Decl, llvm::dwarf::DW_TAG_auto_variable, Storage, Builder);
+}
- // Push it onto the list so that we can free it.
- GlobalVarDescList.push_back(Global);
+/// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument
+/// variable declaration.
+void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI,
+ CGBuilderTy &Builder) {
+ EmitDeclare(Decl, llvm::dwarf::DW_TAG_arg_variable, AI, Builder);
+}
- // Make sure we have an anchor.
- if (!GlobalVariableAnchor)
- GlobalVariableAnchor = new llvm::AnchorDesc(Global);
- // Get name information.
- Global->setName(decl->getName());
- Global->setFullName(decl->getName());
- llvm::CompileUnitDesc *Unit = getOrCreateCompileUnit(CurLoc);
+/// EmitGlobalVariable - Emit information about a global variable.
+void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
+ const VarDecl *Decl) {
+ // Create global variable debug descriptor.
+ llvm::DICompileUnit Unit = getOrCreateCompileUnit(Decl->getLocation());
SourceManager &SM = M->getContext().getSourceManager();
- uint64_t Loc = SM.getLogicalLineNumber(CurLoc);
-
- llvm::TypeDesc *TyD = getOrCreateType(decl->getType(), Unit);
-
- // Fill in the Global information.
- Global->setAnchor(GlobalVariableAnchor);
- Global->setContext(Unit);
- Global->setFile(Unit);
- Global->setLine(Loc);
- Global->setType(TyD);
- Global->setIsDefinition(true);
- Global->setIsStatic(GV->hasInternalLinkage());
- Global->setGlobalVariable(GV);
-
- // Make sure global is created if needed.
- getValueFor(Global);
+ uint64_t LineNo = SM.getLogicalLineNumber(Decl->getLocation());
+ const char *Name = Decl->getName();
+
+ DebugFactory.CreateGlobalVariable(Unit, Name, Name, "", Unit, LineNo,
+ getOrCreateType(Decl->getType(), Unit),
+ Var->hasInternalLinkage(),
+ true/*definition*/, Var);
}
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index 17db496c23..88702dd60a 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -16,30 +16,13 @@
#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Analysis/DebugInfo.h"
#include <map>
-#include <vector>
#include "CGBuilder.h"
-namespace llvm {
- class Function;
- class DISerializer;
- class CompileUnitDesc;
- class BasicBlock;
- class AnchorDesc;
- class DebugInfoDesc;
- class Value;
- class TypeDesc;
- class VariableDesc;
- class SubprogramDesc;
- class GlobalVariable;
- class GlobalVariableDesc;
- class EnumeratorDesc;
- class SubrangeDesc;
-}
-
namespace clang {
- class FunctionDecl;
class VarDecl;
namespace CodeGen {
@@ -49,54 +32,30 @@ namespace CodeGen {
/// and is responsible for emitting to llvm globals or pass directly to
/// the backend.
class CGDebugInfo {
-private:
CodeGenModule *M;
- llvm::DISerializer *SR;
- SourceLocation CurLoc;
- SourceLocation PrevLoc;
+ llvm::DIFactory DebugFactory;
+
+ SourceLocation CurLoc, PrevLoc;
/// CompileUnitCache - Cache of previously constructed CompileUnits.
- std::map<const FileEntry*, llvm::CompileUnitDesc *> CompileUnitCache;
+ llvm::DenseMap<const FileEntry*, llvm::DICompileUnit> CompileUnitCache;
/// TypeCache - Cache of previously constructed Types.
- std::map<void *, llvm::TypeDesc *> TypeCache;
+ // FIXME: Eliminate this map. Be careful of iterator invalidation.
+ std::map<void *, llvm::DIType> TypeCache;
- llvm::Function *StopPointFn;
- llvm::Function *FuncStartFn;
- llvm::Function *DeclareFn;
- llvm::Function *RegionStartFn;
- llvm::Function *RegionEndFn;
- llvm::AnchorDesc *CompileUnitAnchor;
- llvm::AnchorDesc *SubprogramAnchor;
- llvm::AnchorDesc *GlobalVariableAnchor;
- std::vector<llvm::DebugInfoDesc *> RegionStack;
- std::vector<llvm::VariableDesc *> VariableDescList;
- std::vector<llvm::GlobalVariableDesc *> GlobalVarDescList;
- std::vector<llvm::EnumeratorDesc *> EnumDescList;
- std::vector<llvm::SubrangeDesc *> SubrangeDescList;
- llvm::SubprogramDesc *Subprogram;
+ std::vector<llvm::DIDescriptor> RegionStack;
/// Helper functions for getOrCreateType.
- llvm::TypeDesc *getOrCreateCVRType(QualType type,
- llvm::CompileUnitDesc *unit);
- llvm::TypeDesc *getOrCreateBuiltinType(const BuiltinType *type,
- llvm::CompileUnitDesc *unit);
- llvm::TypeDesc *getOrCreateTypedefType(const TypedefType *type,
- llvm::CompileUnitDesc *unit);
- llvm::TypeDesc *getOrCreatePointerType(const PointerType *type,
- llvm::CompileUnitDesc *unit);
- llvm::TypeDesc *getOrCreateFunctionType(QualType type,
- llvm::CompileUnitDesc *unit);
- void getOrCreateRecordType(const RecordType *type,
- llvm::CompileUnitDesc *unit,
- llvm::TypeDesc *&Slot);
- llvm::TypeDesc *getOrCreateEnumType(const EnumType *type,
- llvm::CompileUnitDesc *unit);
- void getOrCreateTagType(const TagType *type,
- llvm::CompileUnitDesc *unit,
- llvm::TypeDesc *&Slot);
- llvm::TypeDesc *getOrCreateArrayType(QualType type,
- llvm::CompileUnitDesc *unit);
+ llvm::DIType CreateType(const BuiltinType *Ty, llvm::DICompileUnit U);
+ llvm::DIType CreateCVRType(QualType Ty, llvm::DICompileUnit U);
+ llvm::DIType CreateType(const TypedefType *Ty, llvm::DICompileUnit U);
+ llvm::DIType CreateType(const PointerType *Ty, llvm::DICompileUnit U);
+ llvm::DIType CreateType(const FunctionType *Ty, llvm::DICompileUnit U);
+ llvm::DIType CreateType(const TagType *Ty, llvm::DICompileUnit U);
+ llvm::DIType CreateType(const RecordType *Ty, llvm::DICompileUnit U);
+ llvm::DIType CreateType(const EnumType *Ty, llvm::DICompileUnit U);
+ llvm::DIType CreateType(const ArrayType *Ty, llvm::DICompileUnit U);
public:
CGDebugInfo(CodeGenModule *m);
@@ -104,7 +63,7 @@ public:
/// setLocation - Update the current source location. If \arg loc is
/// invalid it is ignored.
- void setLocation(SourceLocation loc);
+ void setLocation(SourceLocation Loc);
/// EmitStopPoint - Emit a call to llvm.dbg.stoppoint to indicate a change of
/// source line.
@@ -123,31 +82,33 @@ public:
/// block.
void EmitRegionEnd(llvm::Function *Fn, CGBuilderTy &Builder);
- /// EmitDeclare - Emit call to llvm.dbg.declare for a variable declaration.
- void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI,
- CGBuilderTy &Builder);
+ /// EmitDeclareOfAutoVariable - Emit call to llvm.dbg.declare for an automatic
+ /// variable declaration.
+ void EmitDeclareOfAutoVariable(const VarDecl *Decl, llvm::Value *AI,
+ CGBuilderTy &Builder);
+ /// EmitDeclareOfArgVariable - Emit call to llvm.dbg.declare for an argument
+ /// variable declaration.
+ void EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI,
+ CGBuilderTy &Builder);
+
/// EmitGlobalVariable - Emit information about a global variable.
- void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *decl);
+ void EmitGlobalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl);
private:
+ /// EmitDeclare - Emit call to llvm.dbg.declare for a variable declaration.
+ void EmitDeclare(const VarDecl *decl, unsigned Tag, llvm::Value *AI,
+ CGBuilderTy &Builder);
+
/// getOrCreateCompileUnit - Get the compile unit from the cache or create a
/// new one if necessary.
- llvm::CompileUnitDesc *getOrCreateCompileUnit(SourceLocation loc);
+ llvm::DICompileUnit 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);
+ llvm::DIType getOrCreateType(QualType Ty, llvm::DICompileUnit Unit);
};
} // namespace CodeGen
} // namespace clang
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index 788beb4410..e54c4b386d 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -21,7 +21,6 @@
#include "clang/Basic/TargetInfo.h"
#include "llvm/GlobalVariable.h"
#include "llvm/Type.h"
-#include "llvm/Support/Dwarf.h"
using namespace clang;
using namespace CodeGen;
@@ -174,11 +173,9 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) {
DMEntry = DeclPtr;
// Emit debug info for local var declaration.
- CGDebugInfo *DI = CGM.getDebugInfo();
- if(DI) {
+ if (CGDebugInfo *DI = CGM.getDebugInfo()) {
DI->setLocation(D.getLocation());
- DI->EmitDeclare(&D, llvm::dwarf::DW_TAG_auto_variable,
- DeclPtr, Builder);
+ DI->EmitDeclareOfAutoVariable(&D, DeclPtr, Builder);
}
// If this local has an initializer, emit it now.
@@ -231,12 +228,9 @@ void CodeGenFunction::EmitParmDecl(const VarDecl &D, llvm::Value *Arg) {
DMEntry = DeclPtr;
// Emit debug info for param declaration.
- CGDebugInfo *DI = CGM.getDebugInfo();
- if(DI) {
+ if (CGDebugInfo *DI = CGM.getDebugInfo()) {
DI->setLocation(D.getLocation());
- DI->EmitDeclare(&D, llvm::dwarf::DW_TAG_arg_variable,
- DeclPtr, Builder);
+ DI->EmitDeclareOfArgVariable(&D, DeclPtr, Builder);
}
-
}