aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGDebugInfo.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2013-12-22 00:07:40 +0000
committerDimitry Andric <dim@FreeBSD.org>2013-12-22 00:07:40 +0000
commitbfef399519ca9b8a4b4c6b563253bad7e0eeffe0 (patch)
treedf8df0b0067b381eab470a3b8f28d14a552a6340 /lib/CodeGen/CGDebugInfo.cpp
parent6a0372513edbc473b538d2f724efac50405d6fef (diff)
downloadsrc-bfef399519ca9b8a4b4c6b563253bad7e0eeffe0.tar.gz
src-bfef399519ca9b8a4b4c6b563253bad7e0eeffe0.zip
Vendor import of clang release_34 branch r197841 (effectively, 3.4 RC3):vendor/clang/clang-release_34-r197841
Notes
Notes: svn path=/vendor/clang/dist/; revision=259701 svn path=/vendor/clang/clang-release_34-r197841/; revision=259703; tag=vendor/clang/clang-release_34-r197841
Diffstat (limited to 'lib/CodeGen/CGDebugInfo.cpp')
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp1355
1 files changed, 822 insertions, 533 deletions
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index ddcb931e46c5..fcb26f0da615 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -13,6 +13,7 @@
#include "CGDebugInfo.h"
#include "CGBlocks.h"
+#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
@@ -36,12 +37,13 @@
#include "llvm/IR/Module.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
using namespace clang;
using namespace clang::CodeGen;
CGDebugInfo::CGDebugInfo(CodeGenModule &CGM)
- : CGM(CGM), DBuilder(CGM.getModule()),
- BlockLiteralGenericSet(false) {
+ : CGM(CGM), DebugKind(CGM.getCodeGenOpts().getDebugInfo()),
+ DBuilder(CGM.getModule()) {
CreateCompileUnit();
}
@@ -50,9 +52,54 @@ CGDebugInfo::~CGDebugInfo() {
"Region stack mismatch, stack not empty!");
}
+
+NoLocation::NoLocation(CodeGenFunction &CGF, CGBuilderTy &B)
+ : DI(CGF.getDebugInfo()), Builder(B) {
+ if (DI) {
+ SavedLoc = DI->getLocation();
+ DI->CurLoc = SourceLocation();
+ Builder.SetCurrentDebugLocation(llvm::DebugLoc());
+ }
+}
+
+NoLocation::~NoLocation() {
+ if (DI) {
+ assert(Builder.getCurrentDebugLocation().isUnknown());
+ DI->CurLoc = SavedLoc;
+ }
+}
+
+ArtificialLocation::ArtificialLocation(CodeGenFunction &CGF, CGBuilderTy &B)
+ : DI(CGF.getDebugInfo()), Builder(B) {
+ if (DI) {
+ SavedLoc = DI->getLocation();
+ DI->CurLoc = SourceLocation();
+ Builder.SetCurrentDebugLocation(llvm::DebugLoc());
+ }
+}
+
+void ArtificialLocation::Emit() {
+ if (DI) {
+ // Sync the Builder.
+ DI->EmitLocation(Builder, SavedLoc);
+ DI->CurLoc = SourceLocation();
+ // Construct a location that has a valid scope, but no line info.
+ assert(!DI->LexicalBlockStack.empty());
+ llvm::DIDescriptor Scope(DI->LexicalBlockStack.back());
+ Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(0, 0, Scope));
+ }
+}
+
+ArtificialLocation::~ArtificialLocation() {
+ if (DI) {
+ assert(Builder.getCurrentDebugLocation().getLine() == 0);
+ DI->CurLoc = SavedLoc;
+ }
+}
+
void CGDebugInfo::setLocation(SourceLocation Loc) {
// If the new location isn't valid return.
- if (!Loc.isValid()) return;
+ if (Loc.isInvalid()) return;
CurLoc = CGM.getContext().getSourceManager().getExpansionLoc(Loc);
@@ -112,7 +159,7 @@ llvm::DIScope CGDebugInfo::getContextDescriptor(const Decl *Context) {
}
/// getFunctionName - Get function name for the given FunctionDecl. If the
-/// name is constructred on demand (e.g. C++ destructor) then the name
+/// name is constructed on demand (e.g. C++ destructor) then the name
/// is stored on the side.
StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
assert (FD && "Invalid FunctionDecl!");
@@ -138,10 +185,7 @@ StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
}
// Copy this name on the side and use its reference.
- OS.flush();
- char *StrPtr = DebugInfoNames.Allocate<char>(NS.size());
- memcpy(StrPtr, NS.data(), NS.size());
- return StringRef(StrPtr, NS.size());
+ return internString(OS.str());
}
StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) {
@@ -149,35 +193,37 @@ StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) {
llvm::raw_svector_ostream OS(MethodName);
OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';
const DeclContext *DC = OMD->getDeclContext();
- if (const ObjCImplementationDecl *OID =
+ if (const ObjCImplementationDecl *OID =
dyn_cast<const ObjCImplementationDecl>(DC)) {
OS << OID->getName();
- } else if (const ObjCInterfaceDecl *OID =
+ } else if (const ObjCInterfaceDecl *OID =
dyn_cast<const ObjCInterfaceDecl>(DC)) {
OS << OID->getName();
- } else if (const ObjCCategoryImplDecl *OCD =
+ } else if (const ObjCCategoryImplDecl *OCD =
dyn_cast<const ObjCCategoryImplDecl>(DC)){
OS << ((const NamedDecl *)OCD)->getIdentifier()->getNameStart() << '(' <<
OCD->getIdentifier()->getNameStart() << ')';
+ } else if (isa<ObjCProtocolDecl>(DC)) {
+ // We can extract the type of the class from the self pointer.
+ if (ImplicitParamDecl* SelfDecl = OMD->getSelfDecl()) {
+ QualType ClassTy =
+ cast<ObjCObjectPointerType>(SelfDecl->getType())->getPointeeType();
+ ClassTy.print(OS, PrintingPolicy(LangOptions()));
+ }
}
OS << ' ' << OMD->getSelector().getAsString() << ']';
- char *StrPtr = DebugInfoNames.Allocate<char>(OS.tell());
- memcpy(StrPtr, MethodName.begin(), OS.tell());
- return StringRef(StrPtr, OS.tell());
+ return internString(OS.str());
}
/// getSelectorName - Return selector name. This is used for debugging
/// info.
StringRef CGDebugInfo::getSelectorName(Selector S) {
- const std::string &SName = S.getAsString();
- char *StrPtr = DebugInfoNames.Allocate<char>(SName.size());
- memcpy(StrPtr, SName.data(), SName.size());
- return StringRef(StrPtr, SName.size());
+ return internString(S.getAsString());
}
/// getClassName - Get class name including template argument list.
-StringRef
+StringRef
CGDebugInfo::getClassName(const RecordDecl *RD) {
const ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(RD);
@@ -206,11 +252,7 @@ CGDebugInfo::getClassName(const RecordDecl *RD) {
}
// Copy this name on the side and use its reference.
- size_t Length = Name.size() + TemplateArgList.size();
- char *StrPtr = DebugInfoNames.Allocate<char>(Length);
- memcpy(StrPtr, Name.data(), Name.size());
- memcpy(StrPtr + Name.size(), TemplateArgList.data(), TemplateArgList.size());
- return StringRef(StrPtr, Length);
+ return internString(Name, TemplateArgList);
}
/// getOrCreateFile - Get the file debug info descriptor for the input location.
@@ -280,9 +322,7 @@ StringRef CGDebugInfo::getCurrentDirname() {
return CWDName;
SmallString<256> CWD;
llvm::sys::fs::current_path(CWD);
- char *CompDirnamePtr = DebugInfoNames.Allocate<char>(CWD.size());
- memcpy(CompDirnamePtr, CWD.data(), CWD.size());
- return CWDName = StringRef(CompDirnamePtr, CWD.size());
+ return CWDName = internString(CWD);
}
/// CreateCompileUnit - Create new compile unit.
@@ -301,21 +341,20 @@ void CGDebugInfo::CreateCompileUnit() {
std::string MainFileDir;
if (const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID())) {
MainFileDir = MainFile->getDir()->getName();
- if (MainFileDir != ".")
- MainFileName = MainFileDir + "/" + MainFileName;
+ if (MainFileDir != ".") {
+ llvm::SmallString<1024> MainFileDirSS(MainFileDir);
+ llvm::sys::path::append(MainFileDirSS, MainFileName);
+ MainFileName = MainFileDirSS.str();
+ }
}
// Save filename string.
- char *FilenamePtr = DebugInfoNames.Allocate<char>(MainFileName.length());
- memcpy(FilenamePtr, MainFileName.c_str(), MainFileName.length());
- StringRef Filename(FilenamePtr, MainFileName.length());
+ StringRef Filename = internString(MainFileName);
// Save split dwarf file string.
std::string SplitDwarfFile = CGM.getCodeGenOpts().SplitDwarfFile;
- char *SplitDwarfPtr = DebugInfoNames.Allocate<char>(SplitDwarfFile.length());
- memcpy(SplitDwarfPtr, SplitDwarfFile.c_str(), SplitDwarfFile.length());
- StringRef SplitDwarfFilename(SplitDwarfPtr, SplitDwarfFile.length());
-
+ StringRef SplitDwarfFilename = internString(SplitDwarfFile);
+
unsigned LangTag;
const LangOptions &LO = CGM.getLangOpts();
if (LO.CPlusPlus) {
@@ -339,12 +378,11 @@ void CGDebugInfo::CreateCompileUnit() {
RuntimeVers = LO.ObjCRuntime.isNonFragile() ? 2 : 1;
// Create new compile unit.
- DBuilder.createCompileUnit(LangTag, Filename, getCurrentDirname(),
- Producer, LO.Optimize,
- CGM.getCodeGenOpts().DwarfDebugFlags,
- RuntimeVers, SplitDwarfFilename);
// FIXME - Eliminate TheCU.
- TheCU = llvm::DICompileUnit(DBuilder.getCU());
+ TheCU = DBuilder.createCompileUnit(LangTag, Filename, getCurrentDirname(),
+ Producer, LO.Optimize,
+ CGM.getCodeGenOpts().DwarfDebugFlags,
+ RuntimeVers, SplitDwarfFilename);
}
/// CreateType - Get the Basic type from the cache or create a new
@@ -360,12 +398,11 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
case BuiltinType::Dependent:
llvm_unreachable("Unexpected builtin type");
case BuiltinType::NullPtr:
- return DBuilder.
- createNullPtrType(BT->getName(CGM.getLangOpts()));
+ return DBuilder.createNullPtrType();
case BuiltinType::Void:
return llvm::DIType();
case BuiltinType::ObjCClass:
- if (ClassTy.Verify())
+ if (ClassTy)
return ClassTy;
ClassTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
"objc_class", TheCU,
@@ -377,16 +414,16 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
// Class isa;
// } *id;
- if (ObjTy.Verify())
+ if (ObjTy)
return ObjTy;
- if (!ClassTy.Verify())
+ if (!ClassTy)
ClassTy = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
"objc_class", TheCU,
getOrCreateMainFile(), 0);
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
-
+
llvm::DIType ISATy = DBuilder.createPointerType(ClassTy, Size);
ObjTy =
@@ -398,7 +435,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
return ObjTy;
}
case BuiltinType::ObjCSel: {
- if (SelTy.Verify())
+ if (SelTy)
return SelTy;
SelTy =
DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
@@ -411,7 +448,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
return getOrCreateStructPtrType("opencl_image1d_t",
OCLImage1dDITy);
case BuiltinType::OCLImage1dArray:
- return getOrCreateStructPtrType("opencl_image1d_array_t",
+ return getOrCreateStructPtrType("opencl_image1d_array_t",
OCLImage1dArrayDITy);
case BuiltinType::OCLImage1dBuffer:
return getOrCreateStructPtrType("opencl_image1d_buffer_t",
@@ -471,7 +508,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
// Bit size, align and offset of the type.
uint64_t Size = CGM.getContext().getTypeSize(BT);
uint64_t Align = CGM.getContext().getTypeAlign(BT);
- llvm::DIType DbgTy =
+ llvm::DIType DbgTy =
DBuilder.createBasicType(BTName, Size, Align, Encoding);
return DbgTy;
}
@@ -484,7 +521,7 @@ llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty) {
uint64_t Size = CGM.getContext().getTypeSize(Ty);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
- llvm::DIType DbgTy =
+ llvm::DIType DbgTy =
DBuilder.createBasicType("complex", Size, Align, Encoding);
return DbgTy;
@@ -523,7 +560,7 @@ llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) {
// No need to fill in the Name, Line, Size, Alignment, Offset in case of
// CVR derived types.
llvm::DIType DbgTy = DBuilder.createQualifiedType(Tag, FromTy);
-
+
return DbgTy;
}
@@ -537,20 +574,48 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,
return getOrCreateType(CGM.getContext().getObjCIdType(), Unit);
llvm::DIType DbgTy =
- CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
+ CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
Ty->getPointeeType(), Unit);
return DbgTy;
}
llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty,
llvm::DIFile Unit) {
- return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
+ return CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
Ty->getPointeeType(), Unit);
}
+/// In C++ mode, types have linkage, so we can rely on the ODR and
+/// on their mangled names, if they're external.
+static SmallString<256>
+getUniqueTagTypeName(const TagType *Ty, CodeGenModule &CGM,
+ llvm::DICompileUnit TheCU) {
+ SmallString<256> FullName;
+ // FIXME: ODR should apply to ObjC++ exactly the same wasy it does to C++.
+ // For now, only apply ODR with C++.
+ const TagDecl *TD = Ty->getDecl();
+ if (TheCU.getLanguage() != llvm::dwarf::DW_LANG_C_plus_plus ||
+ !TD->isExternallyVisible())
+ return FullName;
+ // Microsoft Mangler does not have support for mangleCXXRTTIName yet.
+ if (CGM.getTarget().getCXXABI().isMicrosoft())
+ return FullName;
+
+ // TODO: This is using the RTTI name. Is there a better way to get
+ // a unique string for a type?
+ llvm::raw_svector_ostream Out(FullName);
+ CGM.getCXXABI().getMangleContext().mangleCXXRTTIName(QualType(Ty, 0), Out);
+ Out.flush();
+ return FullName;
+}
+
// Creates a forward declaration for a RecordDecl in the given context.
-llvm::DIType CGDebugInfo::createRecordFwdDecl(const RecordDecl *RD,
- llvm::DIDescriptor Ctx) {
+llvm::DICompositeType
+CGDebugInfo::getOrCreateRecordFwdDecl(const RecordType *Ty,
+ llvm::DIDescriptor Ctx) {
+ const RecordDecl *RD = Ty->getDecl();
+ if (llvm::DIType T = getTypeOrNull(CGM.getContext().getRecordType(RD)))
+ return llvm::DICompositeType(T);
llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
unsigned Line = getLineNumber(RD->getLocation());
StringRef RDName = getClassName(RD);
@@ -566,74 +631,18 @@ llvm::DIType CGDebugInfo::createRecordFwdDecl(const RecordDecl *RD,
}
// Create the type.
- return DBuilder.createForwardDecl(Tag, RDName, Ctx, DefUnit, Line);
-}
-
-// Walk up the context chain and create forward decls for record decls,
-// and normal descriptors for namespaces.
-llvm::DIDescriptor CGDebugInfo::createContextChain(const Decl *Context) {
- if (!Context)
- return TheCU;
-
- // See if we already have the parent.
- llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator
- I = RegionMap.find(Context);
- if (I != RegionMap.end()) {
- llvm::Value *V = I->second;
- return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(V));
- }
-
- // Check namespace.
- if (const NamespaceDecl *NSDecl = dyn_cast<NamespaceDecl>(Context))
- return llvm::DIDescriptor(getOrCreateNameSpace(NSDecl));
-
- if (const RecordDecl *RD = dyn_cast<RecordDecl>(Context)) {
- if (!RD->isDependentType()) {
- llvm::DIType Ty = getOrCreateLimitedType(CGM.getContext().getTypeDeclType(RD),
- getOrCreateMainFile());
- return llvm::DIDescriptor(Ty);
- }
- }
- return TheCU;
-}
-
-/// CreatePointeeType - Create Pointee type. If Pointee is a record
-/// then emit record's fwd if debug info size reduction is enabled.
-llvm::DIType CGDebugInfo::CreatePointeeType(QualType PointeeTy,
- llvm::DIFile Unit) {
- if (CGM.getCodeGenOpts().getDebugInfo() != CodeGenOptions::LimitedDebugInfo)
- return getOrCreateType(PointeeTy, Unit);
-
- // Limit debug info for the pointee type.
-
- // If we have an existing type, use that, it's still smaller than creating
- // a new type.
- llvm::DIType Ty = getTypeOrNull(PointeeTy);
- if (Ty.Verify()) return Ty;
-
- // Handle qualifiers.
- if (PointeeTy.hasLocalQualifiers())
- return CreateQualifiedType(PointeeTy, Unit);
-
- if (const RecordType *RTy = dyn_cast<RecordType>(PointeeTy)) {
- RecordDecl *RD = RTy->getDecl();
- llvm::DIDescriptor FDContext =
- getContextDescriptor(cast<Decl>(RD->getDeclContext()));
- llvm::DIType RetTy = createRecordFwdDecl(RD, FDContext);
- TypeCache[QualType(RTy, 0).getAsOpaquePtr()] = RetTy;
- return RetTy;
- }
- return getOrCreateType(PointeeTy, Unit);
+ SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
+ return DBuilder.createForwardDecl(Tag, RDName, Ctx, DefUnit, Line, 0, 0, 0,
+ FullName);
}
llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
- const Type *Ty,
+ const Type *Ty,
QualType PointeeTy,
llvm::DIFile Unit) {
if (Tag == llvm::dwarf::DW_TAG_reference_type ||
Tag == llvm::dwarf::DW_TAG_rvalue_reference_type)
- return DBuilder.createReferenceType(Tag,
- CreatePointeeType(PointeeTy, Unit));
+ return DBuilder.createReferenceType(Tag, getOrCreateType(PointeeTy, Unit));
// Bit size, align and offset of the type.
// Size is always the size of a pointer. We can't use getTypeSize here
@@ -642,25 +651,24 @@ llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
uint64_t Size = CGM.getTarget().getPointerWidth(AS);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
- return DBuilder.createPointerType(CreatePointeeType(PointeeTy, Unit),
- Size, Align);
+ return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit), Size,
+ Align);
}
-llvm::DIType CGDebugInfo::getOrCreateStructPtrType(StringRef Name, llvm::DIType &Cache) {
- if (Cache.Verify())
- return Cache;
- Cache =
- DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
- Name, TheCU, getOrCreateMainFile(),
- 0);
- unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
- Cache = DBuilder.createPointerType(Cache, Size);
+llvm::DIType CGDebugInfo::getOrCreateStructPtrType(StringRef Name,
+ llvm::DIType &Cache) {
+ if (Cache)
return Cache;
+ Cache = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, Name,
+ TheCU, getOrCreateMainFile(), 0);
+ unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
+ Cache = DBuilder.createPointerType(Cache, Size);
+ return Cache;
}
llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
llvm::DIFile Unit) {
- if (BlockLiteralGenericSet)
+ if (BlockLiteralGeneric)
return BlockLiteralGeneric;
SmallVector<llvm::Value *, 8> EltTys;
@@ -716,7 +724,6 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
Unit, LineNo, FieldOffset, 0,
Flags, llvm::DIType(), Elements);
- BlockLiteralGenericSet = true;
BlockLiteralGeneric = DBuilder.createPointerType(EltTy, Size);
return BlockLiteralGeneric;
}
@@ -725,16 +732,16 @@ llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty, llvm::DIFile 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);
- if (!Src.Verify())
+ if (!Src)
return llvm::DIType();
// We don't set size information, but do specify where the typedef was
// declared.
unsigned Line = getLineNumber(Ty->getDecl()->getLocation());
const TypedefNameDecl *TyDecl = Ty->getDecl();
-
+
llvm::DIDescriptor TypedefContext =
getContextDescriptor(cast<Decl>(Ty->getDecl()->getDeclContext()));
-
+
return
DBuilder.createTypedef(Src, TyDecl->getName(), Unit, Line, TypedefContext);
}
@@ -767,7 +774,7 @@ llvm::DIType CGDebugInfo::createFieldType(StringRef name,
AccessSpecifier AS,
uint64_t offsetInBits,
llvm::DIFile tunit,
- llvm::DIDescriptor scope) {
+ llvm::DIScope scope) {
llvm::DIType debugType = getOrCreateType(type, tunit);
// Get the location for the field.
@@ -839,20 +846,15 @@ CollectRecordLambdaFields(const CXXRecordDecl *CXXDecl,
}
}
-/// CollectRecordStaticField - Helper for CollectRecordFields.
-void CGDebugInfo::
-CollectRecordStaticField(const VarDecl *Var,
- SmallVectorImpl<llvm::Value *> &elements,
- llvm::DIType RecordTy) {
+/// Helper for CollectRecordFields.
+llvm::DIDerivedType
+CGDebugInfo::CreateRecordStaticField(const VarDecl *Var,
+ llvm::DIType RecordTy) {
// Create the descriptor for the static variable, with or without
// constant initializers.
llvm::DIFile VUnit = getOrCreateFile(Var->getLocation());
llvm::DIType VTy = getOrCreateType(Var->getType(), VUnit);
- // Do not describe enums as static members.
- if (VTy.getTag() == llvm::dwarf::DW_TAG_enumeration_type)
- return;
-
unsigned LineNumber = getLineNumber(Var->getLocation());
StringRef VName = Var->getName();
llvm::Constant *C = NULL;
@@ -873,10 +875,10 @@ CollectRecordStaticField(const VarDecl *Var,
else if (Access == clang::AS_protected)
Flags |= llvm::DIDescriptor::FlagProtected;
- llvm::DIType GV = DBuilder.createStaticMemberType(RecordTy, VName, VUnit,
- LineNumber, VTy, Flags, C);
- elements.push_back(GV);
+ llvm::DIDerivedType GV = DBuilder.createStaticMemberType(
+ RecordTy, VName, VUnit, LineNumber, VTy, Flags, C);
StaticDataMemberCache[Var->getCanonicalDecl()] = llvm::WeakVH(GV);
+ return GV;
}
/// CollectRecordNormalField - Helper for CollectRecordFields.
@@ -908,10 +910,10 @@ CollectRecordNormalField(const FieldDecl *field, uint64_t OffsetInBits,
/// CollectRecordFields - A helper function to collect debug info for
/// record fields. This is used while creating debug info entry for a Record.
-void CGDebugInfo::
-CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit,
- SmallVectorImpl<llvm::Value *> &elements,
- llvm::DIType RecordTy) {
+void CGDebugInfo::CollectRecordFields(const RecordDecl *record,
+ llvm::DIFile tunit,
+ SmallVectorImpl<llvm::Value *> &elements,
+ llvm::DICompositeType RecordTy) {
const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(record);
if (CXXDecl && CXXDecl->isLambda())
@@ -922,24 +924,22 @@ CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit,
// Field number for non-static fields.
unsigned fieldNo = 0;
- // Bookkeeping for an ms struct, which ignores certain fields.
- bool IsMsStruct = record->isMsStruct(CGM.getContext());
- const FieldDecl *LastFD = 0;
-
// Static and non-static members should appear in the same order as
// the corresponding declarations in the source program.
for (RecordDecl::decl_iterator I = record->decls_begin(),
E = record->decls_end(); I != E; ++I)
- if (const VarDecl *V = dyn_cast<VarDecl>(*I))
- CollectRecordStaticField(V, elements, RecordTy);
- else if (FieldDecl *field = dyn_cast<FieldDecl>(*I)) {
- if (IsMsStruct) {
- // Zero-length bitfields following non-bitfield members are
- // completely ignored; we don't even count them.
- if (CGM.getContext().ZeroBitfieldFollowsNonBitfield((field), LastFD))
- continue;
- LastFD = field;
- }
+ if (const VarDecl *V = dyn_cast<VarDecl>(*I)) {
+ // Reuse the existing static member declaration if one exists
+ llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator MI =
+ StaticDataMemberCache.find(V->getCanonicalDecl());
+ if (MI != StaticDataMemberCache.end()) {
+ assert(MI->second &&
+ "Static data member declaration should still exist");
+ elements.push_back(
+ llvm::DIDerivedType(cast<llvm::MDNode>(MI->second)));
+ } else
+ elements.push_back(CreateRecordStaticField(V, RecordTy));
+ } else if (FieldDecl *field = dyn_cast<FieldDecl>(*I)) {
CollectRecordNormalField(field, layout.getFieldOffset(fieldNo),
tunit, elements, RecordTy);
@@ -952,17 +952,17 @@ CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit,
/// getOrCreateMethodType - CXXMethodDecl's type is a FunctionType. This
/// function type is not updated to include implicit "this" pointer. Use this
/// routine to get a method type which includes "this" pointer.
-llvm::DIType
+llvm::DICompositeType
CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
llvm::DIFile Unit) {
const FunctionProtoType *Func = Method->getType()->getAs<FunctionProtoType>();
if (Method->isStatic())
- return getOrCreateType(QualType(Func, 0), Unit);
+ return llvm::DICompositeType(getOrCreateType(QualType(Func, 0), Unit));
return getOrCreateInstanceMethodType(Method->getThisType(CGM.getContext()),
Func, Unit);
}
-llvm::DIType CGDebugInfo::getOrCreateInstanceMethodType(
+llvm::DICompositeType CGDebugInfo::getOrCreateInstanceMethodType(
QualType ThisPtr, const FunctionProtoType *Func, llvm::DIFile Unit) {
// Add "this" pointer.
llvm::DIArray Args = llvm::DICompositeType(
@@ -984,7 +984,8 @@ llvm::DIType CGDebugInfo::getOrCreateInstanceMethodType(
uint64_t Size = CGM.getTarget().getPointerWidth(AS);
uint64_t Align = CGM.getContext().getTypeAlign(ThisPtrTy);
llvm::DIType PointeeType = getOrCreateType(PointeeTy, Unit);
- llvm::DIType ThisPtrType = DBuilder.createPointerType(PointeeType, Size, Align);
+ llvm::DIType ThisPtrType =
+ DBuilder.createPointerType(PointeeType, Size, Align);
TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType;
// TODO: This and the artificial type below are misleading, the
// types aren't artificial the argument is, but the current
@@ -1007,7 +1008,7 @@ llvm::DIType CGDebugInfo::getOrCreateInstanceMethodType(
return DBuilder.createSubroutineType(Unit, EltTypeArray);
}
-/// isFunctionLocalClass - Return true if CXXRecordDecl is defined
+/// isFunctionLocalClass - Return true if CXXRecordDecl is defined
/// inside a function.
static bool isFunctionLocalClass(const CXXRecordDecl *RD) {
if (const CXXRecordDecl *NRD = dyn_cast<CXXRecordDecl>(RD->getDeclContext()))
@@ -1023,11 +1024,11 @@ llvm::DISubprogram
CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
llvm::DIFile Unit,
llvm::DIType RecordTy) {
- bool IsCtorOrDtor =
+ bool IsCtorOrDtor =
isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method);
-
+
StringRef MethodName = getFunctionName(Method);
- llvm::DIType MethodTy = getOrCreateMethodType(Method, Unit);
+ llvm::DICompositeType MethodTy = getOrCreateMethodType(Method, Unit);
// Since a single ctor/dtor corresponds to multiple functions, it doesn't
// make sense to give a single ctor/dtor a linkage name.
@@ -1036,24 +1037,32 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
MethodLinkageName = CGM.getMangledName(Method);
// Get the location for the method.
- llvm::DIFile MethodDefUnit = getOrCreateFile(Method->getLocation());
- unsigned MethodLine = getLineNumber(Method->getLocation());
+ llvm::DIFile MethodDefUnit;
+ unsigned MethodLine = 0;
+ if (!Method->isImplicit()) {
+ MethodDefUnit = getOrCreateFile(Method->getLocation());
+ MethodLine = getLineNumber(Method->getLocation());
+ }
// Collect virtual method info.
llvm::DIType ContainingType;
- unsigned Virtuality = 0;
+ unsigned Virtuality = 0;
unsigned VIndex = 0;
-
+
if (Method->isVirtual()) {
if (Method->isPure())
Virtuality = llvm::dwarf::DW_VIRTUALITY_pure_virtual;
else
Virtuality = llvm::dwarf::DW_VIRTUALITY_virtual;
-
+
// It doesn't make sense to give a virtual destructor a vtable index,
// since a single destructor has two entries in the vtable.
- if (!isa<CXXDestructorDecl>(Method))
- VIndex = CGM.getVTableContext().getMethodVTableIndex(Method);
+ // FIXME: Add proper support for debug info for virtual calls in
+ // the Microsoft ABI, where we may use multiple vptrs to make a vftable
+ // lookup if we have multiple or virtual inheritance.
+ if (!isa<CXXDestructorDecl>(Method) &&
+ !CGM.getTarget().getCXXABI().isMicrosoft())
+ VIndex = CGM.getItaniumVTableContext().getMethodVTableIndex(Method);
ContainingType = RecordTy;
}
@@ -1068,7 +1077,7 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
if (const CXXConstructorDecl *CXXC = dyn_cast<CXXConstructorDecl>(Method)) {
if (CXXC->isExplicit())
Flags |= llvm::DIDescriptor::FlagExplicit;
- } else if (const CXXConversionDecl *CXXC =
+ } else if (const CXXConversionDecl *CXXC =
dyn_cast<CXXConversionDecl>(Method)) {
if (CXXC->isExplicit())
Flags |= llvm::DIDescriptor::FlagExplicit;
@@ -1078,21 +1087,21 @@ CGDebugInfo::CreateCXXMemberFunction(const CXXMethodDecl *Method,
llvm::DIArray TParamsArray = CollectFunctionTemplateParams(Method, Unit);
llvm::DISubprogram SP =
- DBuilder.createMethod(RecordTy, MethodName, MethodLinkageName,
+ DBuilder.createMethod(RecordTy, MethodName, MethodLinkageName,
MethodDefUnit, MethodLine,
- MethodTy, /*isLocalToUnit=*/false,
+ MethodTy, /*isLocalToUnit=*/false,
/* isDefinition=*/ false,
Virtuality, VIndex, ContainingType,
Flags, CGM.getLangOpts().Optimize, NULL,
TParamsArray);
-
+
SPCache[Method->getCanonicalDecl()] = llvm::WeakVH(SP);
return SP;
}
/// CollectCXXMemberFunctions - A helper function to collect debug info for
-/// C++ member functions. This is used while creating debug info entry for
+/// C++ member functions. This is used while creating debug info entry for
/// a Record.
void CGDebugInfo::
CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit,
@@ -1104,40 +1113,42 @@ CollectCXXMemberFunctions(const CXXRecordDecl *RD, llvm::DIFile Unit,
// the functions.
for(DeclContext::decl_iterator I = RD->decls_begin(),
E = RD->decls_end(); I != E; ++I) {
- Decl *D = *I;
- if (D->isImplicit() && !D->isUsed())
- continue;
-
- if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
- EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy));
- else if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D))
+ if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*I)) {
+ // Reuse the existing member function declaration if it exists.
+ // It may be associated with the declaration of the type & should be
+ // reused as we're building the definition.
+ //
+ // This situation can arise in the vtable-based debug info reduction where
+ // implicit members are emitted in a non-vtable TU.
+ llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator MI =
+ SPCache.find(Method->getCanonicalDecl());
+ if (MI == SPCache.end()) {
+ // If the member is implicit, lazily create it when we see the
+ // definition, not before. (an ODR-used implicit default ctor that's
+ // never actually code generated should not produce debug info)
+ if (!Method->isImplicit())
+ EltTys.push_back(CreateCXXMemberFunction(Method, Unit, RecordTy));
+ } else
+ EltTys.push_back(MI->second);
+ } else if (const FunctionTemplateDecl *FTD =
+ dyn_cast<FunctionTemplateDecl>(*I)) {
+ // Add any template specializations that have already been seen. Like
+ // implicit member functions, these may have been added to a declaration
+ // in the case of vtable-based debug info reduction.
for (FunctionTemplateDecl::spec_iterator SI = FTD->spec_begin(),
- SE = FTD->spec_end(); SI != SE; ++SI)
- EltTys.push_back(CreateCXXMemberFunction(cast<CXXMethodDecl>(*SI), Unit,
- RecordTy));
- }
-}
-
-/// CollectCXXFriends - A helper function to collect debug info for
-/// C++ base classes. This is used while creating debug info entry for
-/// a Record.
-void CGDebugInfo::
-CollectCXXFriends(const CXXRecordDecl *RD, llvm::DIFile Unit,
- SmallVectorImpl<llvm::Value *> &EltTys,
- llvm::DIType RecordTy) {
- for (CXXRecordDecl::friend_iterator BI = RD->friend_begin(),
- BE = RD->friend_end(); BI != BE; ++BI) {
- if ((*BI)->isUnsupportedFriend())
- continue;
- if (TypeSourceInfo *TInfo = (*BI)->getFriendType())
- EltTys.push_back(DBuilder.createFriend(RecordTy,
- getOrCreateType(TInfo->getType(),
- Unit)));
+ SE = FTD->spec_end();
+ SI != SE; ++SI) {
+ llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator MI =
+ SPCache.find(cast<CXXMethodDecl>(*SI)->getCanonicalDecl());
+ if (MI != SPCache.end())
+ EltTys.push_back(MI->second);
+ }
+ }
}
}
/// CollectCXXBases - A helper function to collect debug info for
-/// C++ base classes. This is used while creating debug info entry for
+/// C++ base classes. This is used while creating debug info entry for
/// a Record.
void CGDebugInfo::
CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit,
@@ -1149,30 +1160,30 @@ CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit,
BE = RD->bases_end(); BI != BE; ++BI) {
unsigned BFlags = 0;
uint64_t BaseOffset;
-
+
const CXXRecordDecl *Base =
cast<CXXRecordDecl>(BI->getType()->getAs<RecordType>()->getDecl());
-
+
if (BI->isVirtual()) {
// virtual base offset offset is -ve. The code generator emits dwarf
// expression where it expects +ve number.
- BaseOffset =
- 0 - CGM.getVTableContext()
+ BaseOffset =
+ 0 - CGM.getItaniumVTableContext()
.getVirtualBaseOffsetOffset(RD, Base).getQuantity();
BFlags = llvm::DIDescriptor::FlagVirtual;
} else
BaseOffset = CGM.getContext().toBits(RL.getBaseClassOffset(Base));
// FIXME: Inconsistent units for BaseOffset. It is in bytes when
// BI->isVirtual() and bits when not.
-
+
AccessSpecifier Access = BI->getAccessSpecifier();
if (Access == clang::AS_private)
BFlags |= llvm::DIDescriptor::FlagPrivate;
else if (Access == clang::AS_protected)
BFlags |= llvm::DIDescriptor::FlagProtected;
-
- llvm::DIType DTy =
- DBuilder.createInheritance(RecordTy,
+
+ llvm::DIType DTy =
+ DBuilder.createInheritance(RecordTy,
getOrCreateType(BI->getType(), Unit),
BaseOffset, BFlags);
EltTys.push_back(DTy);
@@ -1182,23 +1193,119 @@ CollectCXXBases(const CXXRecordDecl *RD, llvm::DIFile Unit,
/// CollectTemplateParams - A helper function to collect template parameters.
llvm::DIArray CGDebugInfo::
CollectTemplateParams(const TemplateParameterList *TPList,
- const TemplateArgumentList &TAList,
+ ArrayRef<TemplateArgument> TAList,
llvm::DIFile Unit) {
- SmallVector<llvm::Value *, 16> TemplateParams;
+ SmallVector<llvm::Value *, 16> TemplateParams;
for (unsigned i = 0, e = TAList.size(); i != e; ++i) {
const TemplateArgument &TA = TAList[i];
- const NamedDecl *ND = TPList->getParam(i);
- if (TA.getKind() == TemplateArgument::Type) {
+ StringRef Name;
+ if (TPList)
+ Name = TPList->getParam(i)->getName();
+ switch (TA.getKind()) {
+ case TemplateArgument::Type: {
llvm::DIType TTy = getOrCreateType(TA.getAsType(), Unit);
llvm::DITemplateTypeParameter TTP =
- DBuilder.createTemplateTypeParameter(TheCU, ND->getName(), TTy);
+ DBuilder.createTemplateTypeParameter(TheCU, Name, TTy);
TemplateParams.push_back(TTP);
- } else if (TA.getKind() == TemplateArgument::Integral) {
+ } break;
+ case TemplateArgument::Integral: {
llvm::DIType TTy = getOrCreateType(TA.getIntegralType(), Unit);
llvm::DITemplateValueParameter TVP =
- DBuilder.createTemplateValueParameter(TheCU, ND->getName(), TTy,
- TA.getAsIntegral().getZExtValue());
- TemplateParams.push_back(TVP);
+ DBuilder.createTemplateValueParameter(
+ TheCU, Name, TTy,
+ llvm::ConstantInt::get(CGM.getLLVMContext(), TA.getAsIntegral()));
+ TemplateParams.push_back(TVP);
+ } break;
+ case TemplateArgument::Declaration: {
+ const ValueDecl *D = TA.getAsDecl();
+ bool InstanceMember = D->isCXXInstanceMember();
+ QualType T = InstanceMember
+ ? CGM.getContext().getMemberPointerType(
+ D->getType(), cast<RecordDecl>(D->getDeclContext())
+ ->getTypeForDecl())
+ : CGM.getContext().getPointerType(D->getType());
+ llvm::DIType TTy = getOrCreateType(T, Unit);
+ llvm::Value *V = 0;
+ // Variable pointer template parameters have a value that is the address
+ // of the variable.
+ if (const VarDecl *VD = dyn_cast<VarDecl>(D))
+ V = CGM.GetAddrOfGlobalVar(VD);
+ // Member function pointers have special support for building them, though
+ // this is currently unsupported in LLVM CodeGen.
+ if (InstanceMember) {
+ if (const CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(D))
+ V = CGM.getCXXABI().EmitMemberPointer(method);
+ } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ V = CGM.GetAddrOfFunction(FD);
+ // Member data pointers have special handling too to compute the fixed
+ // offset within the object.
+ if (isa<FieldDecl>(D)) {
+ // These five lines (& possibly the above member function pointer
+ // handling) might be able to be refactored to use similar code in
+ // CodeGenModule::getMemberPointerConstant
+ uint64_t fieldOffset = CGM.getContext().getFieldOffset(D);
+ CharUnits chars =
+ CGM.getContext().toCharUnitsFromBits((int64_t) fieldOffset);
+ V = CGM.getCXXABI().EmitMemberDataPointer(
+ cast<MemberPointerType>(T.getTypePtr()), chars);
+ }
+ llvm::DITemplateValueParameter TVP =
+ DBuilder.createTemplateValueParameter(TheCU, Name, TTy,
+ V->stripPointerCasts());
+ TemplateParams.push_back(TVP);
+ } break;
+ case TemplateArgument::NullPtr: {
+ QualType T = TA.getNullPtrType();
+ llvm::DIType TTy = getOrCreateType(T, Unit);
+ llvm::Value *V = 0;
+ // Special case member data pointer null values since they're actually -1
+ // instead of zero.
+ if (const MemberPointerType *MPT =
+ dyn_cast<MemberPointerType>(T.getTypePtr()))
+ // But treat member function pointers as simple zero integers because
+ // it's easier than having a special case in LLVM's CodeGen. If LLVM
+ // CodeGen grows handling for values of non-null member function
+ // pointers then perhaps we could remove this special case and rely on
+ // EmitNullMemberPointer for member function pointers.
+ if (MPT->isMemberDataPointer())
+ V = CGM.getCXXABI().EmitNullMemberPointer(MPT);
+ if (!V)
+ V = llvm::ConstantInt::get(CGM.Int8Ty, 0);
+ llvm::DITemplateValueParameter TVP =
+ DBuilder.createTemplateValueParameter(TheCU, Name, TTy, V);
+ TemplateParams.push_back(TVP);
+ } break;
+ case TemplateArgument::Template: {
+ llvm::DITemplateValueParameter TVP =
+ DBuilder.createTemplateTemplateParameter(
+ TheCU, Name, llvm::DIType(),
+ TA.getAsTemplate().getAsTemplateDecl()
+ ->getQualifiedNameAsString());
+ TemplateParams.push_back(TVP);
+ } break;
+ case TemplateArgument::Pack: {
+ llvm::DITemplateValueParameter TVP =
+ DBuilder.createTemplateParameterPack(
+ TheCU, Name, llvm::DIType(),
+ CollectTemplateParams(NULL, TA.getPackAsArray(), Unit));
+ TemplateParams.push_back(TVP);
+ } break;
+ case TemplateArgument::Expression: {
+ const Expr *E = TA.getAsExpr();
+ QualType T = E->getType();
+ llvm::Value *V = CGM.EmitConstantExpr(E, T);
+ assert(V && "Expression in template argument isn't constant");
+ llvm::DIType TTy = getOrCreateType(T, Unit);
+ llvm::DITemplateValueParameter TVP =
+ DBuilder.createTemplateValueParameter(TheCU, Name, TTy,
+ V->stripPointerCasts());
+ TemplateParams.push_back(TVP);
+ } break;
+ // And the following should never occur:
+ case TemplateArgument::TemplateExpansion:
+ case TemplateArgument::Null:
+ llvm_unreachable(
+ "These argument types shouldn't exist in concrete types");
}
}
return DBuilder.getOrCreateArray(TemplateParams);
@@ -1213,8 +1320,8 @@ CollectFunctionTemplateParams(const FunctionDecl *FD, llvm::DIFile Unit) {
const TemplateParameterList *TList =
FD->getTemplateSpecializationInfo()->getTemplate()
->getTemplateParameters();
- return
- CollectTemplateParams(TList, *FD->getTemplateSpecializationArgs(), Unit);
+ return CollectTemplateParams(
+ TList, FD->getTemplateSpecializationArgs()->asArray(), Unit);
}
return llvm::DIArray();
}
@@ -1227,12 +1334,12 @@ CollectCXXTemplateParams(const ClassTemplateSpecializationDecl *TSpecial,
llvm::PointerUnion<ClassTemplateDecl *,
ClassTemplatePartialSpecializationDecl *>
PU = TSpecial->getSpecializedTemplateOrPartial();
-
+
TemplateParameterList *TPList = PU.is<ClassTemplateDecl *>() ?
PU.get<ClassTemplateDecl *>()->getTemplateParameters() :
PU.get<ClassTemplatePartialSpecializationDecl *>()->getTemplateParameters();
const TemplateArgumentList &TAList = TSpecial->getTemplateInstantiationArgs();
- return CollectTemplateParams(TPList, TAList, Unit);
+ return CollectTemplateParams(TPList, TAList.asArray(), Unit);
}
/// getOrCreateVTablePtrType - Return debug info descriptor for vtable.
@@ -1255,13 +1362,8 @@ llvm::DIType CGDebugInfo::getOrCreateVTablePtrType(llvm::DIFile Unit) {
/// getVTableName - Get vtable name for the given Class.
StringRef CGDebugInfo::getVTableName(const CXXRecordDecl *RD) {
- // Construct gdb compatible name name.
- std::string Name = "_vptr$" + RD->getNameAsString();
-
- // Copy this name on the side and use its reference.
- char *StrPtr = DebugInfoNames.Allocate<char>(Name.length());
- memcpy(StrPtr, Name.data(), Name.length());
- return StringRef(StrPtr, Name.length());
+ // Copy the gdb compatible name on the side and use its reference.
+ return internString("_vptr$", RD->getNameAsString());
}
@@ -1283,15 +1385,16 @@ CollectVTableInfo(const CXXRecordDecl *RD, llvm::DIFile Unit,
unsigned Size = CGM.getContext().getTypeSize(CGM.getContext().VoidPtrTy);
llvm::DIType VPTR
= DBuilder.createMemberType(Unit, getVTableName(RD), Unit,
- 0, Size, 0, 0, llvm::DIDescriptor::FlagArtificial,
+ 0, Size, 0, 0,
+ llvm::DIDescriptor::FlagArtificial,
getOrCreateVTablePtrType(Unit));
EltTys.push_back(VPTR);
}
-/// getOrCreateRecordType - Emit record type's standalone debug info.
-llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy,
+/// getOrCreateRecordType - Emit record type's standalone debug info.
+llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy,
SourceLocation Loc) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
llvm::DIType T = getOrCreateType(RTy, getOrCreateFile(Loc));
return T;
}
@@ -1300,15 +1403,76 @@ llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy,
/// debug info.
llvm::DIType CGDebugInfo::getOrCreateInterfaceType(QualType D,
SourceLocation Loc) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
llvm::DIType T = getOrCreateType(D, getOrCreateFile(Loc));
RetainedTypes.push_back(D.getAsOpaquePtr());
return T;
}
+void CGDebugInfo::completeType(const RecordDecl *RD) {
+ if (DebugKind > CodeGenOptions::LimitedDebugInfo ||
+ !CGM.getLangOpts().CPlusPlus)
+ completeRequiredType(RD);
+}
+
+void CGDebugInfo::completeRequiredType(const RecordDecl *RD) {
+ if (const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD))
+ if (CXXDecl->isDynamicClass())
+ return;
+
+ QualType Ty = CGM.getContext().getRecordType(RD);
+ llvm::DIType T = getTypeOrNull(Ty);
+ if (T && T.isForwardDecl())
+ completeClassData(RD);
+}
+
+void CGDebugInfo::completeClassData(const RecordDecl *RD) {
+ if (DebugKind <= CodeGenOptions::DebugLineTablesOnly)
+ return;
+ QualType Ty = CGM.getContext().getRecordType(RD);
+ void* TyPtr = Ty.getAsOpaquePtr();
+ if (CompletedTypeCache.count(TyPtr))
+ return;
+ llvm::DIType Res = CreateTypeDefinition(Ty->castAs<RecordType>());
+ assert(!Res.isForwardDecl());
+ CompletedTypeCache[TyPtr] = Res;
+ TypeCache[TyPtr] = Res;
+}
+
/// CreateType - get structure or union type.
llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
RecordDecl *RD = Ty->getDecl();
+ const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
+ // Always emit declarations for types that aren't required to be complete when
+ // in limit-debug-info mode. If the type is later found to be required to be
+ // complete this declaration will be upgraded to a definition by
+ // `completeRequiredType`.
+ // If the type is dynamic, only emit the definition in TUs that require class
+ // data. This is handled by `completeClassData`.
+ llvm::DICompositeType T(getTypeOrNull(QualType(Ty, 0)));
+ // If we've already emitted the type, just use that, even if it's only a
+ // declaration. The completeType, completeRequiredType, and completeClassData
+ // callbacks will handle promoting the declaration to a definition.
+ if (T ||
+ (DebugKind <= CodeGenOptions::LimitedDebugInfo &&
+ // Under -flimit-debug-info, emit only a declaration unless the type is
+ // required to be complete.
+ !RD->isCompleteDefinitionRequired() && CGM.getLangOpts().CPlusPlus) ||
+ // If the class is dynamic, only emit a declaration. A definition will be
+ // emitted whenever the vtable is emitted.
+ (CXXDecl && CXXDecl->hasDefinition() && CXXDecl->isDynamicClass()) || T) {
+ llvm::DIDescriptor FDContext =
+ getContextDescriptor(cast<Decl>(RD->getDeclContext()));
+ if (!T)
+ T = getOrCreateRecordFwdDecl(Ty, FDContext);
+ return T;
+ }
+
+ return CreateTypeDefinition(Ty);
+}
+
+llvm::DIType CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) {
+ RecordDecl *RD = Ty->getDecl();
// Get overall information about the record type for the debug info.
llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
@@ -1320,14 +1484,16 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
// may refer to the forward decl if the struct is recursive) and replace all
// uses of the forward declaration with the final definition.
- llvm::DICompositeType FwdDecl(
- getOrCreateLimitedType(QualType(Ty, 0), DefUnit));
- assert(FwdDecl.Verify() &&
- "The debug type of a RecordType should be a DICompositeType");
+ llvm::DICompositeType FwdDecl(getOrCreateLimitedType(Ty, DefUnit));
+ assert(FwdDecl.isCompositeType() &&
+ "The debug type of a RecordType should be a llvm::DICompositeType");
if (FwdDecl.isForwardDecl())
return FwdDecl;
+ if (const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD))
+ CollectContainingType(CXXDecl, FwdDecl);
+
// Push the struct on region stack.
LexicalBlockStack.push_back(&*FwdDecl);
RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl);
@@ -1337,6 +1503,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
// Convert all the elements.
SmallVector<llvm::Value *, 16> EltTys;
+ // what about nested types?
// Note: The split of CXXDecl information here is intentional, the
// gdb tests will depend on a certain ordering at printout. The debug
@@ -1350,20 +1517,14 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
// Collect data fields (including static variables and any initializers).
CollectRecordFields(RD, DefUnit, EltTys, FwdDecl);
- llvm::DIArray TParamsArray;
- if (CXXDecl) {
+ if (CXXDecl)
CollectCXXMemberFunctions(CXXDecl, DefUnit, EltTys, FwdDecl);
- CollectCXXFriends(CXXDecl, DefUnit, EltTys, FwdDecl);
- if (const ClassTemplateSpecializationDecl *TSpecial
- = dyn_cast<ClassTemplateSpecializationDecl>(RD))
- TParamsArray = CollectCXXTemplateParams(TSpecial, DefUnit);
- }
LexicalBlockStack.pop_back();
RegionMap.erase(Ty->getDecl());
llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
- FwdDecl.setTypeArray(Elements, TParamsArray);
+ FwdDecl.setTypeArray(Elements);
RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl);
return FwdDecl;
@@ -1376,6 +1537,31 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCObjectType *Ty,
return getOrCreateType(Ty->getBaseType(), Unit);
}
+
+/// \return true if Getter has the default name for the property PD.
+static bool hasDefaultGetterName(const ObjCPropertyDecl *PD,
+ const ObjCMethodDecl *Getter) {
+ assert(PD);
+ if (!Getter)
+ return true;
+
+ assert(Getter->getDeclName().isObjCZeroArgSelector());
+ return PD->getName() ==
+ Getter->getDeclName().getObjCSelector().getNameForSlot(0);
+}
+
+/// \return true if Setter has the default name for the property PD.
+static bool hasDefaultSetterName(const ObjCPropertyDecl *PD,
+ const ObjCMethodDecl *Setter) {
+ assert(PD);
+ if (!Setter)
+ return true;
+
+ assert(Setter->getDeclName().isObjCOneArgSelector());
+ return SelectorTable::constructSetterName(PD->getName()) ==
+ Setter->getDeclName().getObjCSelector().getNameForSlot(0);
+}
+
/// CreateType - get objective-c interface type.
llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
llvm::DIFile Unit) {
@@ -1418,8 +1604,8 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
// will find it and we're emitting the complete type.
QualType QualTy = QualType(Ty, 0);
CompletedTypeCache[QualTy.getAsOpaquePtr()] = RealDecl;
- // Push the struct on region stack.
+ // Push the struct on region stack.
LexicalBlockStack.push_back(static_cast<llvm::MDNode*>(RealDecl));
RegionMap[Ty->getDecl()] = llvm::WeakVH(RealDecl);
@@ -1432,12 +1618,13 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
getOrCreateType(CGM.getContext().getObjCInterfaceType(SClass), Unit);
if (!SClassTy.isValid())
return llvm::DIType();
-
+
llvm::DIType InhTag =
DBuilder.createInheritance(RealDecl, SClassTy, 0, 0);
EltTys.push_back(InhTag);
}
+ // Create entries for all of the properties.
for (ObjCContainerDecl::prop_iterator I = ID->prop_begin(),
E = ID->prop_end(); I != E; ++I) {
const ObjCPropertyDecl *PD = *I;
@@ -1449,9 +1636,9 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
llvm::MDNode *PropertyNode =
DBuilder.createObjCProperty(PD->getName(),
PUnit, PLine,
- (Getter && Getter->isImplicit()) ? "" :
+ hasDefaultGetterName(PD, Getter) ? "" :
getSelectorName(PD->getGetterName()),
- (Setter && Setter->isImplicit()) ? "" :
+ hasDefaultSetterName(PD, Setter) ? "" :
getSelectorName(PD->getSetterName()),
PD->getPropertyAttributes(),
getOrCreateType(PD->getType(), PUnit));
@@ -1465,7 +1652,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
if (!FieldTy.isValid())
return llvm::DIType();
-
+
StringRef FieldName = Field->getName();
// Ignore unnamed fields.
@@ -1483,8 +1670,8 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
// Bit size, align and offset of the type.
FieldSize = Field->isBitField()
- ? Field->getBitWidthValue(CGM.getContext())
- : CGM.getContext().getTypeSize(FType);
+ ? Field->getBitWidthValue(CGM.getContext())
+ : CGM.getContext().getTypeSize(FType);
FieldAlign = CGM.getContext().getTypeAlign(FType);
}
@@ -1512,7 +1699,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
llvm::MDNode *PropertyNode = NULL;
if (ObjCImplementationDecl *ImpD = ID->getImplementation()) {
- if (ObjCPropertyImplDecl *PImpD =
+ if (ObjCPropertyImplDecl *PImpD =
ImpD->FindPropertyImplIvarDecl(Field->getIdentifier())) {
if (ObjCPropertyDecl *PD = PImpD->getPropertyDecl()) {
SourceLocation Loc = PD->getLocation();
@@ -1523,9 +1710,9 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
PropertyNode =
DBuilder.createObjCProperty(PD->getName(),
PUnit, PLine,
- (Getter && Getter->isImplicit()) ? "" :
+ hasDefaultGetterName(PD, Getter) ? "" :
getSelectorName(PD->getGetterName()),
- (Setter && Setter->isImplicit()) ? "" :
+ hasDefaultSetterName(PD, Setter) ? "" :
getSelectorName(PD->getSetterName()),
PD->getPropertyAttributes(),
getOrCreateType(PD->getType(), PUnit));
@@ -1547,7 +1734,7 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
// private ivars that we would miss otherwise.
if (ID->getImplementation() == 0)
CompletedTypeCache.erase(QualTy.getAsOpaquePtr());
-
+
LexicalBlockStack.pop_back();
return RealDecl;
}
@@ -1585,7 +1772,7 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
Align = 0;
else
Align = CGM.getContext().getTypeAlign(Ty->getElementType());
- } else if (Ty->isDependentSizedArrayType() || Ty->isIncompleteType()) {
+ } else if (Ty->isIncompleteType()) {
Size = 0;
Align = 0;
} else {
@@ -1610,7 +1797,7 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
int64_t Count = -1; // Count == -1 is an unbounded array.
if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Ty))
Count = CAT->getSize().getZExtValue();
-
+
// FIXME: Verify this is right for VLAs.
Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Count));
EltTy = Ty->getElementType();
@@ -1618,30 +1805,30 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(Subscripts);
- llvm::DIType DbgTy =
+ llvm::DIType DbgTy =
DBuilder.createArrayType(Size, Align, getOrCreateType(EltTy, Unit),
SubscriptArray);
return DbgTy;
}
-llvm::DIType CGDebugInfo::CreateType(const LValueReferenceType *Ty,
+llvm::DIType CGDebugInfo::CreateType(const LValueReferenceType *Ty,
llvm::DIFile Unit) {
- return CreatePointerLikeType(llvm::dwarf::DW_TAG_reference_type,
+ return CreatePointerLikeType(llvm::dwarf::DW_TAG_reference_type,
Ty, Ty->getPointeeType(), Unit);
}
-llvm::DIType CGDebugInfo::CreateType(const RValueReferenceType *Ty,
+llvm::DIType CGDebugInfo::CreateType(const RValueReferenceType *Ty,
llvm::DIFile Unit) {
- return CreatePointerLikeType(llvm::dwarf::DW_TAG_rvalue_reference_type,
+ return CreatePointerLikeType(llvm::dwarf::DW_TAG_rvalue_reference_type,
Ty, Ty->getPointeeType(), Unit);
}
-llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty,
+llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty,
llvm::DIFile U) {
llvm::DIType ClassType = getOrCreateType(QualType(Ty->getClass(), 0), U);
if (!Ty->getPointeeType()->isFunctionType())
return DBuilder.createMemberPointerType(
- CreatePointeeType(Ty->getPointeeType(), U), ClassType);
+ getOrCreateType(Ty->getPointeeType(), U), ClassType);
return DBuilder.createMemberPointerType(getOrCreateInstanceMethodType(
CGM.getContext().getPointerType(
QualType(Ty->getClass(), Ty->getPointeeType().getCVRQualifiers())),
@@ -1649,7 +1836,7 @@ llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty,
ClassType);
}
-llvm::DIType CGDebugInfo::CreateType(const AtomicType *Ty,
+llvm::DIType CGDebugInfo::CreateType(const AtomicType *Ty,
llvm::DIFile U) {
// Ignore the atomic wrapping
// FIXME: What is the correct representation?
@@ -1657,7 +1844,8 @@ llvm::DIType CGDebugInfo::CreateType(const AtomicType *Ty,
}
/// CreateEnumType - get enumeration type.
-llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
+llvm::DIType CGDebugInfo::CreateEnumType(const EnumType *Ty) {
+ const EnumDecl *ED = Ty->getDecl();
uint64_t Size = 0;
uint64_t Align = 0;
if (!ED->getTypeForDecl()->isIncompleteType()) {
@@ -1665,6 +1853,8 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
Align = CGM.getContext().getTypeAlign(ED->getTypeForDecl());
}
+ SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
+
// If this is just a forward declaration, construct an appropriately
// marked node and just return it.
if (!ED->getDefinition()) {
@@ -1675,7 +1865,7 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
StringRef EDName = ED->getName();
return DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_enumeration_type,
EDName, EDContext, DefUnit, Line, 0,
- Size, Align);
+ Size, Align, FullName);
}
// Create DIEnumerator elements for each enumerator.
@@ -1686,7 +1876,7 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
Enum != EnumEnd; ++Enum) {
Enumerators.push_back(
DBuilder.createEnumerator(Enum->getName(),
- Enum->getInitVal().getZExtValue()));
+ Enum->getInitVal().getSExtValue()));
}
// Return a CompositeType for the enum itself.
@@ -1694,21 +1884,25 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
llvm::DIFile DefUnit = getOrCreateFile(ED->getLocation());
unsigned Line = getLineNumber(ED->getLocation());
- llvm::DIDescriptor EnumContext =
+ llvm::DIDescriptor EnumContext =
getContextDescriptor(cast<Decl>(ED->getDeclContext()));
llvm::DIType ClassTy = ED->isFixed() ?
getOrCreateType(ED->getIntegerType(), DefUnit) : llvm::DIType();
- llvm::DIType DbgTy =
+ llvm::DIType DbgTy =
DBuilder.createEnumerationType(EnumContext, ED->getName(), DefUnit, Line,
Size, Align, EltArray,
- ClassTy);
+ ClassTy, FullName);
return DbgTy;
}
static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
Qualifiers Quals;
do {
- Quals += T.getLocalQualifiers();
+ Qualifiers InnerQuals = T.getLocalQualifiers();
+ // Qualifiers::operator+() doesn't like it if you add a Qualifier
+ // that is already there.
+ Quals += Qualifiers::removeCommonQualifiers(Quals, InnerQuals);
+ Quals += InnerQuals;
QualType LastT = T;
switch (T->getTypeClass()) {
default:
@@ -1741,21 +1935,25 @@ static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
T = cast<SubstTemplateTypeParmType>(T)->getReplacementType();
break;
case Type::Auto:
- T = cast<AutoType>(T)->getDeducedType();
+ QualType DT = cast<AutoType>(T)->getDeducedType();
+ if (DT.isNull())
+ return T;
+ T = DT;
break;
}
-
+
assert(T != LastT && "Type unwrapping failed to unwrap!");
(void)LastT;
} while (true);
}
-/// getType - Get the type from the cache or return null type if it doesn't exist.
+/// getType - Get the type from the cache or return null type if it doesn't
+/// exist.
llvm::DIType CGDebugInfo::getTypeOrNull(QualType Ty) {
// Unwrap the type as needed for debug information.
Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
-
+
// Check for existing entry.
if (Ty->getTypeClass() == Type::ObjCInterface) {
llvm::Value *V = getCachedInterfaceTypeOrNull(Ty);
@@ -1793,10 +1991,7 @@ llvm::DIType CGDebugInfo::getCompletedTypeOrNull(QualType Ty) {
}
// Verify that any cached debug info still exists.
- if (V != 0)
- return llvm::DIType(cast<llvm::MDNode>(V));
-
- return llvm::DIType();
+ return llvm::DIType(cast_or_null<llvm::MDNode>(V));
}
/// getCachedInterfaceTypeOrNull - Get the type from the interface
@@ -1824,9 +2019,7 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) {
// Unwrap the type as needed for debug information.
Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
- llvm::DIType T = getCompletedTypeOrNull(Ty);
-
- if (T.Verify())
+ if (llvm::DIType T = getCompletedTypeOrNull(Ty))
return T;
// Otherwise create the type.
@@ -1836,29 +2029,33 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) {
// And update the type cache.
TypeCache[TyPtr] = Res;
+ // FIXME: this getTypeOrNull call seems silly when we just inserted the type
+ // into the cache - but getTypeOrNull has a special case for cached interface
+ // types. We should probably just pull that out as a special case for the
+ // "else" block below & skip the otherwise needless lookup.
llvm::DIType TC = getTypeOrNull(Ty);
- if (TC.Verify() && TC.isForwardDecl())
+ if (TC && TC.isForwardDecl())
ReplaceMap.push_back(std::make_pair(TyPtr, static_cast<llvm::Value*>(TC)));
else if (ObjCInterfaceDecl* Decl = getObjCInterfaceDecl(Ty)) {
// Interface types may have elements added to them by a
// subsequent implementation or extension, so we keep them in
// the ObjCInterfaceCache together with a checksum. Instead of
- // the (possibly) incomplete interace type, we return a forward
+ // the (possibly) incomplete interface type, we return a forward
// declaration that gets RAUW'd in CGDebugInfo::finalize().
- llvm::DenseMap<void *, std::pair<llvm::WeakVH, unsigned > >
- ::iterator it = ObjCInterfaceCache.find(TyPtr);
- if (it != ObjCInterfaceCache.end())
- TC = llvm::DIType(cast<llvm::MDNode>(it->second.first));
- else
- TC = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
- Decl->getName(), TheCU, Unit,
- getLineNumber(Decl->getLocation()),
- TheCU.getLanguage());
+ std::pair<llvm::WeakVH, unsigned> &V = ObjCInterfaceCache[TyPtr];
+ if (V.first)
+ return llvm::DIType(cast<llvm::MDNode>(V.first));
+ TC = DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
+ Decl->getName(), TheCU, Unit,
+ getLineNumber(Decl->getLocation()),
+ TheCU.getLanguage());
// Store the forward declaration in the cache.
- ObjCInterfaceCache[TyPtr] = std::make_pair(TC, Checksum(Decl));
+ V.first = TC;
+ V.second = Checksum(Decl);
// Register the type for replacement in finalize().
ReplaceMap.push_back(std::make_pair(TyPtr, static_cast<llvm::Value*>(TC)));
+
return TC;
}
@@ -1868,19 +2065,25 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) {
return Res;
}
-/// Currently the checksum merely consists of the number of ivars.
-unsigned CGDebugInfo::Checksum(const ObjCInterfaceDecl
- *InterfaceDecl) {
- unsigned IvarNo = 0;
- for (const ObjCIvarDecl *Ivar = InterfaceDecl->all_declared_ivar_begin();
- Ivar != 0; Ivar = Ivar->getNextIvar()) ++IvarNo;
- return IvarNo;
+/// Currently the checksum of an interface includes the number of
+/// ivars and property accessors.
+unsigned CGDebugInfo::Checksum(const ObjCInterfaceDecl *ID) {
+ // The assumption is that the number of ivars can only increase
+ // monotonically, so it is safe to just use their current number as
+ // a checksum.
+ unsigned Sum = 0;
+ for (const ObjCIvarDecl *Ivar = ID->all_declared_ivar_begin();
+ Ivar != 0; Ivar = Ivar->getNextIvar())
+ ++Sum;
+
+ return Sum;
}
ObjCInterfaceDecl *CGDebugInfo::getObjCInterfaceDecl(QualType Ty) {
switch (Ty->getTypeClass()) {
case Type::ObjCObjectPointer:
- return getObjCInterfaceDecl(cast<ObjCObjectPointerType>(Ty)->getPointeeType());
+ return getObjCInterfaceDecl(cast<ObjCObjectPointerType>(Ty)
+ ->getPointeeType());
case Type::ObjCInterface:
return cast<ObjCInterfaceType>(Ty)->getDecl();
default:
@@ -1895,7 +2098,7 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) {
return CreateQualifiedType(Ty, Unit);
const char *Diag = 0;
-
+
// Work out details of type.
switch (Ty->getTypeClass()) {
#define TYPE(Class, Base)
@@ -1920,6 +2123,10 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) {
return CreateType(cast<ComplexType>(Ty));
case Type::Pointer:
return CreateType(cast<PointerType>(Ty), Unit);
+ case Type::Decayed:
+ // Decayed types are just pointers in LLVM and DWARF.
+ return CreateType(
+ cast<PointerType>(cast<DecayedType>(Ty)->getDecayedType()), Unit);
case Type::BlockPointer:
return CreateType(cast<BlockPointerType>(Ty), Unit);
case Type::Typedef:
@@ -1927,7 +2134,7 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) {
case Type::Record:
return CreateType(cast<RecordType>(Ty));
case Type::Enum:
- return CreateEnumType(cast<EnumType>(Ty)->getDecl());
+ return CreateEnumType(cast<EnumType>(Ty));
case Type::FunctionProto:
case Type::FunctionNoProto:
return CreateType(cast<FunctionType>(Ty), Unit);
@@ -1956,10 +2163,13 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) {
case Type::TypeOf:
case Type::Decltype:
case Type::UnaryTransform:
- case Type::Auto:
+ case Type::PackExpansion:
llvm_unreachable("type should have been unwrapped!");
+ case Type::Auto:
+ Diag = "auto";
+ break;
}
-
+
assert(Diag && "Fall through without a diagnostic?");
unsigned DiagID = CGM.getDiags().getCustomDiagID(DiagnosticsEngine::Error,
"debug information for %0 is not yet supported");
@@ -1970,117 +2180,119 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) {
/// getOrCreateLimitedType - Get the type from the cache or create a new
/// limited type if necessary.
-llvm::DIType CGDebugInfo::getOrCreateLimitedType(QualType Ty,
+llvm::DIType CGDebugInfo::getOrCreateLimitedType(const RecordType *Ty,
llvm::DIFile Unit) {
- if (Ty.isNull())
- return llvm::DIType();
+ QualType QTy(Ty, 0);
- // Unwrap the type as needed for debug information.
- Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
-
- llvm::DIType T = getTypeOrNull(Ty);
+ llvm::DICompositeType T(getTypeOrNull(QTy));
// We may have cached a forward decl when we could have created
// a non-forward decl. Go ahead and create a non-forward decl
// now.
- if (T.Verify() && !T.isForwardDecl()) return T;
+ if (T && !T.isForwardDecl()) return T;
// Otherwise create the type.
- llvm::DIType Res = CreateLimitedTypeNode(Ty, Unit);
+ llvm::DICompositeType Res = CreateLimitedType(Ty);
- if (T.Verify() && T.isForwardDecl())
- ReplaceMap.push_back(std::make_pair(Ty.getAsOpaquePtr(),
- static_cast<llvm::Value*>(T)));
+ // Propagate members from the declaration to the definition
+ // CreateType(const RecordType*) will overwrite this with the members in the
+ // correct order if the full type is needed.
+ Res.setTypeArray(T.getTypeArray());
+
+ if (T && T.isForwardDecl())
+ ReplaceMap.push_back(
+ std::make_pair(QTy.getAsOpaquePtr(), static_cast<llvm::Value *>(T)));
// And update the type cache.
- TypeCache[Ty.getAsOpaquePtr()] = Res;
+ TypeCache[QTy.getAsOpaquePtr()] = Res;
return Res;
}
// TODO: Currently used for context chains when limiting debug info.
-llvm::DIType CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
+llvm::DICompositeType CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
RecordDecl *RD = Ty->getDecl();
-
+
// Get overall information about the record type for the debug info.
llvm::DIFile DefUnit = getOrCreateFile(RD->getLocation());
unsigned Line = getLineNumber(RD->getLocation());
StringRef RDName = getClassName(RD);
- llvm::DIDescriptor RDContext;
- if (CGM.getCodeGenOpts().getDebugInfo() == CodeGenOptions::LimitedDebugInfo)
- RDContext = createContextChain(cast<Decl>(RD->getDeclContext()));
- else
- RDContext = getContextDescriptor(cast<Decl>(RD->getDeclContext()));
+ llvm::DIDescriptor RDContext =
+ getContextDescriptor(cast<Decl>(RD->getDeclContext()));
+
+ // If we ended up creating the type during the context chain construction,
+ // just return that.
+ // FIXME: this could be dealt with better if the type was recorded as
+ // completed before we started this (see the CompletedTypeCache usage in
+ // CGDebugInfo::CreateTypeDefinition(const RecordType*) - that would need to
+ // be pushed to before context creation, but after it was known to be
+ // destined for completion (might still have an issue if this caller only
+ // required a declaration but the context construction ended up creating a
+ // definition)
+ llvm::DICompositeType T(getTypeOrNull(CGM.getContext().getRecordType(RD)));
+ if (T && (!T.isForwardDecl() || !RD->getDefinition()))
+ return T;
// If this is just a forward declaration, construct an appropriately
// marked node and just return it.
if (!RD->getDefinition())
- return createRecordFwdDecl(RD, RDContext);
+ return getOrCreateRecordFwdDecl(Ty, RDContext);
uint64_t Size = CGM.getContext().getTypeSize(Ty);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
- const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
llvm::DICompositeType RealDecl;
-
+
+ SmallString<256> FullName = getUniqueTagTypeName(Ty, CGM, TheCU);
+
if (RD->isUnion())
RealDecl = DBuilder.createUnionType(RDContext, RDName, DefUnit, Line,
- Size, Align, 0, llvm::DIArray());
+ Size, Align, 0, llvm::DIArray(), 0,
+ FullName);
else if (RD->isClass()) {
// FIXME: This could be a struct type giving a default visibility different
// than C++ class type, but needs llvm metadata changes first.
RealDecl = DBuilder.createClassType(RDContext, RDName, DefUnit, Line,
Size, Align, 0, 0, llvm::DIType(),
llvm::DIArray(), llvm::DIType(),
- llvm::DIArray());
+ llvm::DIArray(), FullName);
} else
RealDecl = DBuilder.createStructType(RDContext, RDName, DefUnit, Line,
- Size, Align, 0, llvm::DIType(), llvm::DIArray());
+ Size, Align, 0, llvm::DIType(),
+ llvm::DIArray(), 0, llvm::DIType(),
+ FullName);
RegionMap[Ty->getDecl()] = llvm::WeakVH(RealDecl);
TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RealDecl;
- if (CXXDecl) {
- // A class's primary base or the class itself contains the vtable.
- llvm::DICompositeType ContainingType;
- const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
- if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) {
- // Seek non virtual primary base root.
- while (1) {
- const ASTRecordLayout &BRL = CGM.getContext().getASTRecordLayout(PBase);
- const CXXRecordDecl *PBT = BRL.getPrimaryBase();
- if (PBT && !BRL.isPrimaryBaseVirtual())
- PBase = PBT;
- else
- break;
- }
- ContainingType = llvm::DICompositeType(
- getOrCreateType(QualType(PBase->getTypeForDecl(), 0), DefUnit));
- } else if (CXXDecl->isDynamicClass())
- ContainingType = RealDecl;
-
- RealDecl.setContainingType(ContainingType);
- }
- return llvm::DIType(RealDecl);
+ if (const ClassTemplateSpecializationDecl *TSpecial =
+ dyn_cast<ClassTemplateSpecializationDecl>(RD))
+ RealDecl.setTypeArray(llvm::DIArray(),
+ CollectCXXTemplateParams(TSpecial, DefUnit));
+ return RealDecl;
}
-/// CreateLimitedTypeNode - Create a new debug type node, but only forward
-/// declare composite types that haven't been processed yet.
-llvm::DIType CGDebugInfo::CreateLimitedTypeNode(QualType Ty,llvm::DIFile Unit) {
-
- // Work out details of type.
- switch (Ty->getTypeClass()) {
-#define TYPE(Class, Base)
-#define ABSTRACT_TYPE(Class, Base)
-#define NON_CANONICAL_TYPE(Class, Base)
-#define DEPENDENT_TYPE(Class, Base) case Type::Class:
- #include "clang/AST/TypeNodes.def"
- llvm_unreachable("Dependent types cannot show up in debug information");
+void CGDebugInfo::CollectContainingType(const CXXRecordDecl *RD,
+ llvm::DICompositeType RealDecl) {
+ // A class's primary base or the class itself contains the vtable.
+ llvm::DICompositeType ContainingType;
+ const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
+ if (const CXXRecordDecl *PBase = RL.getPrimaryBase()) {
+ // Seek non virtual primary base root.
+ while (1) {
+ const ASTRecordLayout &BRL = CGM.getContext().getASTRecordLayout(PBase);
+ const CXXRecordDecl *PBT = BRL.getPrimaryBase();
+ if (PBT && !BRL.isPrimaryBaseVirtual())
+ PBase = PBT;
+ else
+ break;
+ }
+ ContainingType = llvm::DICompositeType(
+ getOrCreateType(QualType(PBase->getTypeForDecl(), 0),
+ getOrCreateFile(RD->getLocation())));
+ } else if (RD->isDynamicClass())
+ ContainingType = RealDecl;
- case Type::Record:
- return CreateLimitedType(cast<RecordType>(Ty));
- default:
- return CreateTypeNode(Ty, Unit);
- }
+ RealDecl.setContainingType(ContainingType);
}
/// CreateMemberType - Create new member and increase Offset by FType's size.
@@ -2097,21 +2309,57 @@ llvm::DIType CGDebugInfo::CreateMemberType(llvm::DIFile Unit, QualType FType,
return Ty;
}
+llvm::DIDescriptor CGDebugInfo::getDeclarationOrDefinition(const Decl *D) {
+ // We only need a declaration (not a definition) of the type - so use whatever
+ // we would otherwise do to get a type for a pointee. (forward declarations in
+ // limited debug info, full definitions (if the type definition is available)
+ // in unlimited debug info)
+ if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
+ return getOrCreateType(CGM.getContext().getTypeDeclType(TD),
+ getOrCreateFile(TD->getLocation()));
+ // Otherwise fall back to a fairly rudimentary cache of existing declarations.
+ // This doesn't handle providing declarations (for functions or variables) for
+ // entities without definitions in this TU, nor when the definition proceeds
+ // the call to this function.
+ // FIXME: This should be split out into more specific maps with support for
+ // emitting forward declarations and merging definitions with declarations,
+ // the same way as we do for types.
+ llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator I =
+ DeclCache.find(D->getCanonicalDecl());
+ if (I == DeclCache.end())
+ return llvm::DIDescriptor();
+ llvm::Value *V = I->second;
+ return llvm::DIDescriptor(dyn_cast_or_null<llvm::MDNode>(V));
+}
+
/// getFunctionDeclaration - Return debug info descriptor to describe method
/// declaration for the given method definition.
llvm::DISubprogram CGDebugInfo::getFunctionDeclaration(const Decl *D) {
+ if (!D || DebugKind == CodeGenOptions::DebugLineTablesOnly)
+ return llvm::DISubprogram();
+
const FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
if (!FD) return llvm::DISubprogram();
// Setup context.
- getContextDescriptor(cast<Decl>(D->getDeclContext()));
+ llvm::DIScope S = getContextDescriptor(cast<Decl>(D->getDeclContext()));
llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
MI = SPCache.find(FD->getCanonicalDecl());
+ if (MI == SPCache.end()) {
+ if (const CXXMethodDecl *MD =
+ dyn_cast<CXXMethodDecl>(FD->getCanonicalDecl())) {
+ llvm::DICompositeType T(S);
+ llvm::DISubprogram SP =
+ CreateCXXMemberFunction(MD, getOrCreateFile(MD->getLocation()), T);
+ T.addMember(SP);
+ return SP;
+ }
+ }
if (MI != SPCache.end()) {
llvm::Value *V = MI->second;
llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(V));
- if (SP.isSubprogram() && !llvm::DISubprogram(SP).isDefinition())
+ if (SP.isSubprogram() && !SP.isDefinition())
return SP;
}
@@ -2123,7 +2371,7 @@ llvm::DISubprogram CGDebugInfo::getFunctionDeclaration(const Decl *D) {
if (MI != SPCache.end()) {
llvm::Value *V = MI->second;
llvm::DISubprogram SP(dyn_cast_or_null<llvm::MDNode>(V));
- if (SP.isSubprogram() && !llvm::DISubprogram(SP).isDefinition())
+ if (SP.isSubprogram() && !SP.isDefinition())
return SP;
}
}
@@ -2132,9 +2380,15 @@ llvm::DISubprogram CGDebugInfo::getFunctionDeclaration(const Decl *D) {
// getOrCreateFunctionType - Construct DIType. If it is a c++ method, include
// implicit parameter "this".
-llvm::DIType CGDebugInfo::getOrCreateFunctionType(const Decl *D,
- QualType FnType,
- llvm::DIFile F) {
+llvm::DICompositeType CGDebugInfo::getOrCreateFunctionType(const Decl *D,
+ QualType FnType,
+ llvm::DIFile F) {
+ if (!D || DebugKind == CodeGenOptions::DebugLineTablesOnly)
+ // Create fake but valid subroutine type. Otherwise
+ // llvm::DISubprogram::Verify() would return false, and
+ // subprogram DIE will miss DW_AT_decl_file and
+ // DW_AT_decl_line fields.
+ return DBuilder.createSubroutineType(F, DBuilder.getOrCreateArray(None));
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
return getOrCreateMethodType(Method, F);
@@ -2143,7 +2397,14 @@ llvm::DIType CGDebugInfo::getOrCreateFunctionType(const Decl *D,
SmallVector<llvm::Value *, 16> Elts;
// First element is always return type. For 'void' functions it is NULL.
- Elts.push_back(getOrCreateType(OMethod->getResultType(), F));
+ QualType ResultTy = OMethod->getResultType();
+
+ // Replace the instancetype keyword with the actual type.
+ if (ResultTy == CGM.getContext().getObjCInstanceType())
+ ResultTy = CGM.getContext().getPointerType(
+ QualType(OMethod->getClassInterface()->getTypeForDecl(), 0));
+
+ Elts.push_back(getOrCreateType(ResultTy, F));
// "self" pointer is always first argument.
QualType SelfDeclTy = OMethod->getSelfDecl()->getType();
llvm::DIType SelfTy = getOrCreateType(SelfDeclTy, F);
@@ -2152,14 +2413,14 @@ llvm::DIType CGDebugInfo::getOrCreateFunctionType(const Decl *D,
llvm::DIType CmdTy = getOrCreateType(OMethod->getCmdDecl()->getType(), F);
Elts.push_back(DBuilder.createArtificialType(CmdTy));
// Get rest of the arguments.
- for (ObjCMethodDecl::param_const_iterator PI = OMethod->param_begin(),
+ for (ObjCMethodDecl::param_const_iterator PI = OMethod->param_begin(),
PE = OMethod->param_end(); PI != PE; ++PI)
Elts.push_back(getOrCreateType((*PI)->getType(), F));
llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts);
return DBuilder.createSubroutineType(F, EltTypeArray);
}
- return getOrCreateType(FnType, F);
+ return llvm::DICompositeType(getOrCreateType(FnType, F));
}
/// EmitFunctionStart - Constructs the debug code for entering a function.
@@ -2187,7 +2448,7 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
llvm::DIArray TParamsArray;
if (!HasDecl) {
// Use llvm function name.
- Name = Fn->getName();
+ LinkageName = Fn->getName();
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
// If there is a DISubprogram for this function available then use it.
llvm::DenseMap<const FunctionDecl *, llvm::WeakVH>::iterator
@@ -2214,16 +2475,16 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
if (LinkageName == Name ||
(!CGM.getCodeGenOpts().EmitGcovArcs &&
!CGM.getCodeGenOpts().EmitGcovNotes &&
- CGM.getCodeGenOpts().getDebugInfo() <= CodeGenOptions::DebugLineTablesOnly))
+ DebugKind <= CodeGenOptions::DebugLineTablesOnly))
LinkageName = StringRef();
- if (CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo) {
+ if (DebugKind >= CodeGenOptions::LimitedDebugInfo) {
if (const NamespaceDecl *NSDecl =
- dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext()))
+ dyn_cast_or_null<NamespaceDecl>(FD->getDeclContext()))
FDContext = getOrCreateNameSpace(NSDecl);
else if (const RecordDecl *RDecl =
- dyn_cast_or_null<RecordDecl>(FD->getDeclContext()))
- FDContext = getContextDescriptor(cast<Decl>(RDecl->getDeclContext()));
+ dyn_cast_or_null<RecordDecl>(FD->getDeclContext()))
+ FDContext = getContextDescriptor(cast<Decl>(RDecl));
// Collect template parameters.
TParamsArray = CollectFunctionTemplateParams(FD, Unit);
@@ -2243,28 +2504,15 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
if (!HasDecl || D->isImplicit())
Flags |= llvm::DIDescriptor::FlagArtificial;
- llvm::DIType DIFnType;
- llvm::DISubprogram SPDecl;
- if (HasDecl &&
- CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo) {
- DIFnType = getOrCreateFunctionType(D, FnType, Unit);
- SPDecl = getFunctionDeclaration(D);
- } else {
- // Create fake but valid subroutine type. Otherwise
- // llvm::DISubprogram::Verify() would return false, and
- // subprogram DIE will miss DW_AT_decl_file and
- // DW_AT_decl_line fields.
- SmallVector<llvm::Value*, 16> Elts;
- llvm::DIArray EltTypeArray = DBuilder.getOrCreateArray(Elts);
- DIFnType = DBuilder.createSubroutineType(Unit, EltTypeArray);
- }
- llvm::DISubprogram SP;
- SP = DBuilder.createFunction(FDContext, Name, LinkageName, Unit,
- LineNo, DIFnType,
- Fn->hasInternalLinkage(), true/*definition*/,
- getLineNumber(CurLoc), Flags,
- CGM.getLangOpts().Optimize,
- Fn, TParamsArray, SPDecl);
+ llvm::DISubprogram SP =
+ DBuilder.createFunction(FDContext, Name, LinkageName, Unit, LineNo,
+ getOrCreateFunctionType(D, FnType, Unit),
+ Fn->hasInternalLinkage(), true /*definition*/,
+ getLineNumber(CurLoc), Flags,
+ CGM.getLangOpts().Optimize, Fn, TParamsArray,
+ getFunctionDeclaration(D));
+ if (HasDecl)
+ DeclCache.insert(std::make_pair(D->getCanonicalDecl(), llvm::WeakVH(SP)));
// Push function on region stack.
llvm::MDNode *SPN = SP;
@@ -2274,10 +2522,10 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
}
/// EmitLocation - Emit metadata to indicate a change in line/column
-/// information in the source file.
+/// information in the source file. If the location is invalid, the
+/// previous location will be reused.
void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc,
bool ForceColumnInfo) {
-
// Update our current location
setLocation(Loc);
@@ -2292,7 +2540,7 @@ void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc,
Builder.getCurrentDebugLocation().getScope(CGM.getLLVMContext()) ==
LexicalBlockStack.back())
return;
-
+
// Update last state.
PrevLoc = CurLoc;
@@ -2319,7 +2567,8 @@ void CGDebugInfo::CreateLexicalBlock(SourceLocation Loc) {
/// EmitLexicalBlockStart - Constructs the debug code for entering a declarative
/// region - beginning of a DW_TAG_lexical_block.
-void CGDebugInfo::EmitLexicalBlockStart(CGBuilderTy &Builder, SourceLocation Loc) {
+void CGDebugInfo::EmitLexicalBlockStart(CGBuilderTy &Builder,
+ SourceLocation Loc) {
// Set our current location.
setLocation(Loc);
@@ -2334,7 +2583,8 @@ void CGDebugInfo::EmitLexicalBlockStart(CGBuilderTy &Builder, SourceLocation Loc
/// EmitLexicalBlockEnd - Constructs the debug code for exiting a declarative
/// region - end of a DW_TAG_lexical_block.
-void CGDebugInfo::EmitLexicalBlockEnd(CGBuilderTy &Builder, SourceLocation Loc) {
+void CGDebugInfo::EmitLexicalBlockEnd(CGBuilderTy &Builder,
+ SourceLocation Loc) {
assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
// Provide an entry in the line table for the end of the block.
@@ -2355,7 +2605,7 @@ void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) {
FnBeginRegionCount.pop_back();
}
-// EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
+// EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
// See BuildByRefType.
llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
uint64_t *XOffset) {
@@ -2364,9 +2614,9 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
QualType FType;
uint64_t FieldSize, FieldOffset;
unsigned FieldAlign;
-
+
llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
- QualType Type = VD->getType();
+ QualType Type = VD->getType();
FieldOffset = 0;
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
@@ -2388,21 +2638,23 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
Qualifiers::ObjCLifetime Lifetime;
if (CGM.getContext().getByrefLifetime(Type,
Lifetime, HasByrefExtendedLayout)
- && HasByrefExtendedLayout)
+ && HasByrefExtendedLayout) {
+ FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
EltTys.push_back(CreateMemberType(Unit, FType,
"__byref_variable_layout",
&FieldOffset));
-
+ }
+
CharUnits Align = CGM.getContext().getDeclAlign(VD);
if (Align > CGM.getContext().toCharUnitsFromBits(
CGM.getTarget().getPointerAlign(0))) {
- CharUnits FieldOffsetInBytes
+ CharUnits FieldOffsetInBytes
= CGM.getContext().toCharUnitsFromBits(FieldOffset);
CharUnits AlignedOffsetInBytes
= FieldOffsetInBytes.RoundUpToAlignment(Align);
CharUnits NumPaddingBytes
= AlignedOffsetInBytes - FieldOffsetInBytes;
-
+
if (NumPaddingBytes.isPositive()) {
llvm::APInt pad(32, NumPaddingBytes.getQuantity());
FType = CGM.getContext().getConstantArrayType(CGM.getContext().CharTy,
@@ -2410,40 +2662,45 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
EltTys.push_back(CreateMemberType(Unit, FType, "", &FieldOffset));
}
}
-
+
FType = Type;
llvm::DIType FieldTy = CGDebugInfo::getOrCreateType(FType, Unit);
FieldSize = CGM.getContext().getTypeSize(FType);
FieldAlign = CGM.getContext().toBits(Align);
- *XOffset = FieldOffset;
+ *XOffset = FieldOffset;
FieldTy = DBuilder.createMemberType(Unit, VD->getName(), Unit,
0, FieldSize, FieldAlign,
FieldOffset, 0, FieldTy);
EltTys.push_back(FieldTy);
FieldOffset += FieldSize;
-
+
llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
-
+
unsigned Flags = llvm::DIDescriptor::FlagBlockByrefStruct;
-
+
return DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags,
llvm::DIType(), Elements);
}
/// EmitDeclare - Emit local variable declaration debug info.
void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
- llvm::Value *Storage,
+ llvm::Value *Storage,
unsigned ArgNo, CGBuilderTy &Builder) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
- llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
+ bool Unwritten =
+ VD->isImplicit() || (isa<Decl>(VD->getDeclContext()) &&
+ cast<Decl>(VD->getDeclContext())->isImplicit());
+ llvm::DIFile Unit;
+ if (!Unwritten)
+ Unit = getOrCreateFile(VD->getLocation());
llvm::DIType Ty;
uint64_t XOffset = 0;
if (VD->hasAttr<BlocksAttr>())
Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset);
- else
+ else
Ty = getOrCreateType(VD->getType(), Unit);
// If there is no debug info for this type then do not emit debug info
@@ -2451,24 +2708,13 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
if (!Ty)
return;
- if (llvm::Argument *Arg = dyn_cast<llvm::Argument>(Storage)) {
- // If Storage is an aggregate returned as 'sret' then let debugger know
- // about this.
- if (Arg->hasStructRetAttr())
- Ty = DBuilder.createReferenceType(llvm::dwarf::DW_TAG_reference_type, Ty);
- else if (CXXRecordDecl *Record = VD->getType()->getAsCXXRecordDecl()) {
- // If an aggregate variable has non trivial destructor or non trivial copy
- // constructor than it is pass indirectly. Let debug info know about this
- // by using reference of the aggregate type as a argument type.
- if (Record->hasNonTrivialCopyConstructor() ||
- !Record->hasTrivialDestructor())
- Ty = DBuilder.createReferenceType(llvm::dwarf::DW_TAG_reference_type, Ty);
- }
- }
-
// Get location information.
- unsigned Line = getLineNumber(VD->getLocation());
- unsigned Column = getColumnNumber(VD->getLocation());
+ unsigned Line = 0;
+ unsigned Column = 0;
+ if (!Unwritten) {
+ Line = getLineNumber(VD->getLocation());
+ Column = getColumnNumber(VD->getLocation());
+ }
unsigned Flags = 0;
if (VD->isImplicit())
Flags |= llvm::DIDescriptor::FlagArtificial;
@@ -2479,6 +2725,10 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
// otherwise it is 'self' or 'this'.
if (isa<ImplicitParamDecl>(VD) && ArgNo == 1)
Flags |= llvm::DIDescriptor::FlagObjectPointer;
+ if (llvm::Argument *Arg = dyn_cast<llvm::Argument>(Storage))
+ if (Arg->getType()->isPointerTy() && !Arg->hasByValAttr() &&
+ !VD->getType()->isPointerType())
+ Flags |= llvm::DIDescriptor::FlagIndirectVariable;
llvm::MDNode *Scope = LexicalBlockStack.back();
@@ -2501,33 +2751,18 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
// Create the descriptor for the variable.
llvm::DIVariable D =
- DBuilder.createComplexVariable(Tag,
+ DBuilder.createComplexVariable(Tag,
llvm::DIDescriptor(Scope),
VD->getName(), Unit, Line, Ty,
addr, ArgNo);
-
- // Insert an llvm.dbg.declare into the current block.
- llvm::Instruction *Call =
- DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
- Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
- return;
- } else if (isa<VariableArrayType>(VD->getType())) {
- // These are "complex" variables in that they need an op_deref.
- // Create the descriptor for the variable.
- llvm::Value *Addr = llvm::ConstantInt::get(CGM.Int64Ty,
- llvm::DIBuilder::OpDeref);
- llvm::DIVariable D =
- DBuilder.createComplexVariable(Tag,
- llvm::DIDescriptor(Scope),
- Name, Unit, Line, Ty,
- Addr, ArgNo);
// Insert an llvm.dbg.declare into the current block.
llvm::Instruction *Call =
DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
return;
- }
+ } else if (isa<VariableArrayType>(VD->getType()))
+ Flags |= llvm::DIDescriptor::FlagIndirectVariable;
} else if (const RecordType *RT = dyn_cast<RecordType>(VD->getType())) {
// If VD is an anonymous union then Storage represents value for
// all union fields.
@@ -2539,18 +2774,18 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
FieldDecl *Field = *I;
llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit);
StringRef FieldName = Field->getName();
-
+
// Ignore unnamed fields. Do not ignore unnamed records.
if (FieldName.empty() && !isa<RecordType>(Field->getType()))
continue;
-
+
// Use VarDecl's Tag, Scope and Line number.
llvm::DIVariable D =
DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope),
- FieldName, Unit, Line, FieldTy,
+ FieldName, Unit, Line, FieldTy,
CGM.getLangOpts().Optimize, Flags,
ArgNo);
-
+
// Insert an llvm.dbg.declare into the current block.
llvm::Instruction *Call =
DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
@@ -2575,7 +2810,7 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
llvm::Value *Storage,
CGBuilderTy &Builder) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
EmitDeclare(VD, llvm::dwarf::DW_TAG_auto_variable, Storage, 0, Builder);
}
@@ -2585,9 +2820,10 @@ void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
/// never happen though, since creating a type for the implicit self
/// argument implies that we already parsed the interface definition
/// and the ivar declarations in the implementation.
-llvm::DIType CGDebugInfo::CreateSelfType(const QualType &QualTy, llvm::DIType Ty) {
+llvm::DIType CGDebugInfo::CreateSelfType(const QualType &QualTy,
+ llvm::DIType Ty) {
llvm::DIType CachedTy = getTypeOrNull(QualTy);
- if (CachedTy.Verify()) Ty = CachedTy;
+ if (CachedTy) Ty = CachedTy;
else DEBUG(llvm::dbgs() << "No cached type for self.");
return DBuilder.createObjectPointerType(Ty);
}
@@ -2596,20 +2832,20 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(const VarDecl *VD,
llvm::Value *Storage,
CGBuilderTy &Builder,
const CGBlockInfo &blockInfo) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
-
+
if (Builder.GetInsertBlock() == 0)
return;
-
+
bool isByRef = VD->hasAttr<BlocksAttr>();
-
+
uint64_t XOffset = 0;
llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
llvm::DIType Ty;
if (isByRef)
Ty = EmitTypeForVarWithBlocksAttr(VD, &XOffset);
- else
+ else
Ty = getOrCreateType(VD->getType(), Unit);
// Self is passed along as an implicit non-arg variable in a
@@ -2649,7 +2885,7 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(const VarDecl *VD,
// Create the descriptor for the variable.
llvm::DIVariable D =
- DBuilder.createComplexVariable(llvm::dwarf::DW_TAG_auto_variable,
+ DBuilder.createComplexVariable(llvm::dwarf::DW_TAG_auto_variable,
llvm::DIDescriptor(LexicalBlockStack.back()),
VD->getName(), Unit, Line, Ty, addr);
@@ -2665,7 +2901,7 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(const VarDecl *VD,
void CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI,
unsigned ArgNo,
CGBuilderTy &Builder) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
EmitDeclare(VD, llvm::dwarf::DW_TAG_arg_variable, AI, ArgNo, Builder);
}
@@ -2683,7 +2919,7 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
llvm::Value *Arg,
llvm::Value *LocalAddr,
CGBuilderTy &Builder) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
ASTContext &C = CGM.getContext();
const BlockDecl *blockDecl = block.getBlockDecl();
@@ -2692,7 +2928,7 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
llvm::DIFile tunit = getOrCreateFile(loc);
unsigned line = getLineNumber(loc);
unsigned column = getColumnNumber(loc);
-
+
// Build the debug-info type for the block literal.
getContextDescriptor(cast<Decl>(blockDecl->getDeclContext()));
@@ -2812,7 +3048,7 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
// Create the descriptor for the parameter.
llvm::DIVariable debugVar =
DBuilder.createLocalVariable(llvm::dwarf::DW_TAG_arg_variable,
- llvm::DIDescriptor(scope),
+ llvm::DIDescriptor(scope),
Arg->getName(), tunit, line, type,
CGM.getLangOpts().Optimize, flags,
cast<llvm::Argument>(Arg)->getArgNo() + 1);
@@ -2831,25 +3067,32 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
DbgDecl->setDebugLoc(llvm::DebugLoc::get(line, column, scope));
}
-/// getStaticDataMemberDeclaration - If D is an out-of-class definition of
-/// a static data member of a class, find its corresponding in-class
-/// declaration.
-llvm::DIDerivedType CGDebugInfo::getStaticDataMemberDeclaration(const Decl *D) {
- if (cast<VarDecl>(D)->isStaticDataMember()) {
- llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator
- MI = StaticDataMemberCache.find(D->getCanonicalDecl());
- if (MI != StaticDataMemberCache.end())
- // Verify the info still exists.
- if (llvm::Value *V = MI->second)
- return llvm::DIDerivedType(cast<llvm::MDNode>(V));
- }
- return llvm::DIDerivedType();
+/// If D is an out-of-class definition of a static data member of a class, find
+/// its corresponding in-class declaration.
+llvm::DIDerivedType
+CGDebugInfo::getOrCreateStaticDataMemberDeclarationOrNull(const VarDecl *D) {
+ if (!D->isStaticDataMember())
+ return llvm::DIDerivedType();
+ llvm::DenseMap<const Decl *, llvm::WeakVH>::iterator MI =
+ StaticDataMemberCache.find(D->getCanonicalDecl());
+ if (MI != StaticDataMemberCache.end()) {
+ assert(MI->second && "Static data member declaration should still exist");
+ return llvm::DIDerivedType(cast<llvm::MDNode>(MI->second));
+ }
+
+ // If the member wasn't found in the cache, lazily construct and add it to the
+ // type (used when a limited form of the type is emitted).
+ llvm::DICompositeType Ctxt(
+ getContextDescriptor(cast<Decl>(D->getDeclContext())));
+ llvm::DIDerivedType T = CreateRecordStaticField(D, Ctxt);
+ Ctxt.addMember(T);
+ return T;
}
/// EmitGlobalVariable - Emit information about a global variable.
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
const VarDecl *D) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
// Create global variable debug descriptor.
llvm::DIFile Unit = getOrCreateFile(D->getLocation());
unsigned LineNo = getLineNumber(D->getLocation());
@@ -2873,18 +3116,19 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
LinkageName = Var->getName();
if (LinkageName == DeclName)
LinkageName = StringRef();
- llvm::DIDescriptor DContext =
+ llvm::DIDescriptor DContext =
getContextDescriptor(dyn_cast<Decl>(D->getDeclContext()));
- DBuilder.createStaticVariable(DContext, DeclName, LinkageName,
- Unit, LineNo, getOrCreateType(T, Unit),
- Var->hasInternalLinkage(), Var,
- getStaticDataMemberDeclaration(D));
+ llvm::DIGlobalVariable GV = DBuilder.createStaticVariable(
+ DContext, DeclName, LinkageName, Unit, LineNo, getOrCreateType(T, Unit),
+ Var->hasInternalLinkage(), Var,
+ getOrCreateStaticDataMemberDeclarationOrNull(D));
+ DeclCache.insert(std::make_pair(D->getCanonicalDecl(), llvm::WeakVH(GV)));
}
/// EmitGlobalVariable - Emit information about an objective-c interface.
void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
ObjCInterfaceDecl *ID) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
// Create global variable debug descriptor.
llvm::DIFile Unit = getOrCreateFile(ID->getLocation());
unsigned LineNo = getLineNumber(ID->getLocation());
@@ -2908,9 +3152,9 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
}
/// EmitGlobalVariable - Emit global variable's debug info.
-void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
+void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
llvm::Constant *Init) {
- assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
+ assert(DebugKind >= CodeGenOptions::LimitedDebugInfo);
// Create the descriptor for the variable.
llvm::DIFile Unit = getOrCreateFile(VD->getLocation());
StringRef Name = VD->getName();
@@ -2923,34 +3167,79 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
// Do not use DIGlobalVariable for enums.
if (Ty.getTag() == llvm::dwarf::DW_TAG_enumeration_type)
return;
- DBuilder.createStaticVariable(Unit, Name, Name, Unit,
- getLineNumber(VD->getLocation()),
- Ty, true, Init,
- getStaticDataMemberDeclaration(VD));
+ llvm::DIGlobalVariable GV = DBuilder.createStaticVariable(
+ Unit, Name, Name, Unit, getLineNumber(VD->getLocation()), Ty, true, Init,
+ getOrCreateStaticDataMemberDeclarationOrNull(cast<VarDecl>(VD)));
+ DeclCache.insert(std::make_pair(VD->getCanonicalDecl(), llvm::WeakVH(GV)));
+}
+
+llvm::DIScope CGDebugInfo::getCurrentContextDescriptor(const Decl *D) {
+ if (!LexicalBlockStack.empty())
+ return llvm::DIScope(LexicalBlockStack.back());
+ return getContextDescriptor(D);
}
void CGDebugInfo::EmitUsingDirective(const UsingDirectiveDecl &UD) {
- llvm::DIScope Scope =
- LexicalBlockStack.empty()
- ? getContextDescriptor(cast<Decl>(UD.getDeclContext()))
- : llvm::DIScope(LexicalBlockStack.back());
+ if (CGM.getCodeGenOpts().getDebugInfo() < CodeGenOptions::LimitedDebugInfo)
+ return;
DBuilder.createImportedModule(
- Scope, getOrCreateNameSpace(UD.getNominatedNamespace()),
+ getCurrentContextDescriptor(cast<Decl>(UD.getDeclContext())),
+ getOrCreateNameSpace(UD.getNominatedNamespace()),
getLineNumber(UD.getLocation()));
}
+void CGDebugInfo::EmitUsingDecl(const UsingDecl &UD) {
+ if (CGM.getCodeGenOpts().getDebugInfo() < CodeGenOptions::LimitedDebugInfo)
+ return;
+ assert(UD.shadow_size() &&
+ "We shouldn't be codegening an invalid UsingDecl containing no decls");
+ // Emitting one decl is sufficient - debuggers can detect that this is an
+ // overloaded name & provide lookup for all the overloads.
+ const UsingShadowDecl &USD = **UD.shadow_begin();
+ if (llvm::DIDescriptor Target =
+ getDeclarationOrDefinition(USD.getUnderlyingDecl()))
+ DBuilder.createImportedDeclaration(
+ getCurrentContextDescriptor(cast<Decl>(USD.getDeclContext())), Target,
+ getLineNumber(USD.getLocation()));
+}
+
+llvm::DIImportedEntity
+CGDebugInfo::EmitNamespaceAlias(const NamespaceAliasDecl &NA) {
+ if (CGM.getCodeGenOpts().getDebugInfo() < CodeGenOptions::LimitedDebugInfo)
+ return llvm::DIImportedEntity(0);
+ llvm::WeakVH &VH = NamespaceAliasCache[&NA];
+ if (VH)
+ return llvm::DIImportedEntity(cast<llvm::MDNode>(VH));
+ llvm::DIImportedEntity R(0);
+ if (const NamespaceAliasDecl *Underlying =
+ dyn_cast<NamespaceAliasDecl>(NA.getAliasedNamespace()))
+ // This could cache & dedup here rather than relying on metadata deduping.
+ R = DBuilder.createImportedModule(
+ getCurrentContextDescriptor(cast<Decl>(NA.getDeclContext())),
+ EmitNamespaceAlias(*Underlying), getLineNumber(NA.getLocation()),
+ NA.getName());
+ else
+ R = DBuilder.createImportedModule(
+ getCurrentContextDescriptor(cast<Decl>(NA.getDeclContext())),
+ getOrCreateNameSpace(cast<NamespaceDecl>(NA.getAliasedNamespace())),
+ getLineNumber(NA.getLocation()), NA.getName());
+ VH = R;
+ return R;
+}
+
/// getOrCreateNamesSpace - Return namespace descriptor for the given
/// namespace decl.
-llvm::DINameSpace
+llvm::DINameSpace
CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) {
- llvm::DenseMap<const NamespaceDecl *, llvm::WeakVH>::iterator I =
+ NSDecl = NSDecl->getCanonicalDecl();
+ llvm::DenseMap<const NamespaceDecl *, llvm::WeakVH>::iterator I =
NameSpaceCache.find(NSDecl);
if (I != NameSpaceCache.end())
return llvm::DINameSpace(cast<llvm::MDNode>(I->second));
-
+
unsigned LineNo = getLineNumber(NSDecl->getLocation());
llvm::DIFile FileD = getOrCreateFile(NSDecl->getLocation());
- llvm::DIDescriptor Context =
+ llvm::DIDescriptor Context =
getContextDescriptor(dyn_cast<Decl>(NSDecl->getDeclContext()));
llvm::DINameSpace NS =
DBuilder.createNameSpace(Context, NSDecl->getName(), FileD, LineNo);
@@ -2965,7 +3254,7 @@ void CGDebugInfo::finalize() {
// Verify that the debug info still exists.
if (llvm::Value *V = VI->second)
Ty = llvm::DIType(cast<llvm::MDNode>(V));
-
+
llvm::DenseMap<void *, llvm::WeakVH>::iterator it =
TypeCache.find(VI->first);
if (it != TypeCache.end()) {
@@ -2974,7 +3263,7 @@ void CGDebugInfo::finalize() {
RepTy = llvm::DIType(cast<llvm::MDNode>(V));
}
- if (Ty.Verify() && Ty.isForwardDecl() && RepTy.Verify())
+ if (Ty && Ty.isForwardDecl() && RepTy)
Ty.replaceAllUsesWith(RepTy);
}