aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGDebugInfo.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2013-04-08 18:45:10 +0000
committerDimitry Andric <dim@FreeBSD.org>2013-04-08 18:45:10 +0000
commit809500fc2c13c8173a16b052304d983864e4a1e1 (patch)
tree4fc2f184c499d106f29a386c452b49e5197bf63d /lib/CodeGen/CGDebugInfo.cpp
parentbe7c9ec198dcdb5bf73a35bfbb00b3333cb87909 (diff)
downloadsrc-809500fc2c13c8173a16b052304d983864e4a1e1.tar.gz
src-809500fc2c13c8173a16b052304d983864e4a1e1.zip
Vendor import of clang trunk r178860:vendor/clang/clang-trunk-r178860
Notes
Notes: svn path=/vendor/clang/dist/; revision=249261 svn path=/vendor/clang/clang-trunk-r178860/; revision=249262; tag=vendor/clang/clang-trunk-r178860
Diffstat (limited to 'lib/CodeGen/CGDebugInfo.cpp')
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp905
1 files changed, 544 insertions, 361 deletions
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 80fa09be7473..711d6861507c 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -12,30 +12,30 @@
//===----------------------------------------------------------------------===//
#include "CGDebugInfo.h"
-#include "CodeGenFunction.h"
-#include "CodeGenModule.h"
#include "CGBlocks.h"
#include "CGObjCRuntime.h"
+#include "CodeGenFunction.h"
+#include "CodeGenModule.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclFriend.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/AST/RecordLayout.h"
-#include "clang/Basic/SourceManager.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Version.h"
#include "clang/Frontend/CodeGenOptions.h"
-#include "llvm/Constants.h"
-#include "llvm/DerivedTypes.h"
-#include "llvm/Instructions.h"
-#include "llvm/Intrinsics.h"
-#include "llvm/Module.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/Module.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/DataLayout.h"
using namespace clang;
using namespace clang::CodeGen;
@@ -79,7 +79,7 @@ void CGDebugInfo::setLocation(SourceLocation Loc) {
llvm::MDNode *N = D;
LexicalBlockStack.pop_back();
LexicalBlockStack.push_back(N);
- } else if (Scope.isLexicalBlock()) {
+ } else if (Scope.isLexicalBlock() || Scope.isSubprogram()) {
llvm::DIDescriptor D
= DBuilder.createLexicalBlockFile(Scope, getOrCreateFile(CurLoc));
llvm::MDNode *N = D;
@@ -126,7 +126,9 @@ StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
return FII->getName();
// Otherwise construct human readable name for debug info.
- std::string NS = FD->getNameAsString();
+ SmallString<128> NS;
+ llvm::raw_svector_ostream OS(NS);
+ FD->printName(OS);
// Add any template specialization args.
if (Info) {
@@ -134,15 +136,15 @@ StringRef CGDebugInfo::getFunctionName(const FunctionDecl *FD) {
const TemplateArgument *Args = TArgs->data();
unsigned NumArgs = TArgs->size();
PrintingPolicy Policy(CGM.getLangOpts());
- NS += TemplateSpecializationType::PrintTemplateArgumentList(Args,
- NumArgs,
- Policy);
+ TemplateSpecializationType::PrintTemplateArgumentList(OS, Args, NumArgs,
+ Policy);
}
// Copy this name on the side and use its reference.
- char *StrPtr = DebugInfoNames.Allocate<char>(NS.length());
- memcpy(StrPtr, NS.data(), NS.length());
- return StringRef(StrPtr, NS.length());
+ OS.flush();
+ char *StrPtr = DebugInfoNames.Allocate<char>(NS.size());
+ memcpy(StrPtr, NS.data(), NS.size());
+ return StringRef(StrPtr, NS.size());
}
StringRef CGDebugInfo::getObjCMethodName(const ObjCMethodDecl *OMD) {
@@ -199,8 +201,12 @@ CGDebugInfo::getClassName(const RecordDecl *RD) {
}
StringRef Name = RD->getIdentifier()->getName();
PrintingPolicy Policy(CGM.getLangOpts());
- std::string TemplateArgList =
- TemplateSpecializationType::PrintTemplateArgumentList(Args, NumArgs, Policy);
+ SmallString<128> TemplateArgList;
+ {
+ llvm::raw_svector_ostream OS(TemplateArgList);
+ TemplateSpecializationType::PrintTemplateArgumentList(OS, Args, NumArgs,
+ Policy);
+ }
// Copy this name on the side and use its reference.
size_t Length = Name.size() + TemplateArgList.size();
@@ -256,9 +262,9 @@ unsigned CGDebugInfo::getLineNumber(SourceLocation Loc) {
}
/// getColumnNumber - Get column number for the location.
-unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc) {
+unsigned CGDebugInfo::getColumnNumber(SourceLocation Loc, bool Force) {
// We may not want column information at all.
- if (!CGM.getCodeGenOpts().DebugColumnInfo)
+ if (!Force && !CGM.getCodeGenOpts().DebugColumnInfo)
return 0;
// If the location is invalid then use the current column.
@@ -306,6 +312,12 @@ void CGDebugInfo::CreateCompileUnit() {
char *FilenamePtr = DebugInfoNames.Allocate<char>(MainFileName.length());
memcpy(FilenamePtr, MainFileName.c_str(), MainFileName.length());
StringRef Filename(FilenamePtr, MainFileName.length());
+
+ // 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());
unsigned LangTag;
const LangOptions &LO = CGM.getLangOpts();
@@ -330,10 +342,10 @@ 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);
+ DBuilder.createCompileUnit(LangTag, Filename, getCurrentDirname(),
+ Producer, LO.Optimize,
+ CGM.getCodeGenOpts().DwarfDebugFlags,
+ RuntimeVers, SplitDwarfFilename);
// FIXME - Eliminate TheCU.
TheCU = llvm::DICompileUnit(DBuilder.getCU());
}
@@ -380,22 +392,12 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
llvm::DIType ISATy = DBuilder.createPointerType(ClassTy, Size);
- llvm::DIType FwdTy = DBuilder.createStructType(TheCU, "objc_object",
- getOrCreateMainFile(),
- 0, 0, 0, 0,
- llvm::DIArray());
-
- llvm::TrackingVH<llvm::MDNode> ObjNode(FwdTy);
- SmallVector<llvm::Value *, 1> EltTys;
- llvm::DIType FieldTy =
- DBuilder.createMemberType(llvm::DIDescriptor(ObjNode), "isa",
- getOrCreateMainFile(), 0, Size,
- 0, 0, 0, ISATy);
- EltTys.push_back(FieldTy);
- llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
+ ObjTy =
+ DBuilder.createStructType(TheCU, "objc_object", getOrCreateMainFile(),
+ 0, 0, 0, 0, llvm::DIType(), llvm::DIArray());
- ObjNode->replaceOperandWith(10, Elements);
- ObjTy = llvm::DIType(ObjNode);
+ ObjTy.setTypeArray(DBuilder.getOrCreateArray(&*DBuilder.createMemberType(
+ ObjTy, "isa", getOrCreateMainFile(), 0, Size, 0, 0, 0, ISATy)));
return ObjTy;
}
case BuiltinType::ObjCSel: {
@@ -407,6 +409,34 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT) {
0);
return SelTy;
}
+
+ case BuiltinType::OCLImage1d:
+ return getOrCreateStructPtrType("opencl_image1d_t",
+ OCLImage1dDITy);
+ case BuiltinType::OCLImage1dArray:
+ return getOrCreateStructPtrType("opencl_image1d_array_t",
+ OCLImage1dArrayDITy);
+ case BuiltinType::OCLImage1dBuffer:
+ return getOrCreateStructPtrType("opencl_image1d_buffer_t",
+ OCLImage1dBufferDITy);
+ case BuiltinType::OCLImage2d:
+ return getOrCreateStructPtrType("opencl_image2d_t",
+ OCLImage2dDITy);
+ case BuiltinType::OCLImage2dArray:
+ return getOrCreateStructPtrType("opencl_image2d_array_t",
+ OCLImage2dArrayDITy);
+ case BuiltinType::OCLImage3d:
+ return getOrCreateStructPtrType("opencl_image3d_t",
+ OCLImage3dDITy);
+ case BuiltinType::OCLSampler:
+ return DBuilder.createBasicType("opencl_sampler_t",
+ CGM.getContext().getTypeSize(BT),
+ CGM.getContext().getTypeAlign(BT),
+ llvm::dwarf::DW_ATE_unsigned);
+ case BuiltinType::OCLEvent:
+ return getOrCreateStructPtrType("opencl_event_t",
+ OCLEventDITy);
+
case BuiltinType::UChar:
case BuiltinType::Char_U: Encoding = llvm::dwarf::DW_ATE_unsigned_char; break;
case BuiltinType::Char_S:
@@ -502,6 +532,13 @@ llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) {
llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,
llvm::DIFile Unit) {
+
+ // The frontend treats 'id' as a typedef to an ObjCObjectType,
+ // whereas 'id<protocol>' is treated as an ObjCPointerType. For the
+ // debug info, we want to emit 'id' in both cases.
+ if (Ty->isObjCQualifiedIdType())
+ return getOrCreateType(CGM.getContext().getObjCIdType(), Unit);
+
llvm::DIType DbgTy =
CreatePointerLikeType(llvm::dwarf::DW_TAG_pointer_type, Ty,
Ty->getPointeeType(), Unit);
@@ -556,7 +593,7 @@ llvm::DIDescriptor CGDebugInfo::createContextChain(const Decl *Context) {
if (const RecordDecl *RD = dyn_cast<RecordDecl>(Context)) {
if (!RD->isDependentType()) {
llvm::DIType Ty = getOrCreateLimitedType(CGM.getContext().getTypeDeclType(RD),
- getOrCreateMainFile());
+ getOrCreateMainFile());
return llvm::DIDescriptor(Ty);
}
}
@@ -590,7 +627,6 @@ llvm::DIType CGDebugInfo::CreatePointeeType(QualType PointeeTy,
return RetTy;
}
return getOrCreateType(PointeeTy, Unit);
-
}
llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
@@ -601,7 +637,7 @@ llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
Tag == llvm::dwarf::DW_TAG_rvalue_reference_type)
return DBuilder.createReferenceType(Tag,
CreatePointeeType(PointeeTy, Unit));
-
+
// Bit size, align and offset of the type.
// Size is always the size of a pointer. We can't use getTypeSize here
// because that does not return the correct value for references.
@@ -613,6 +649,18 @@ llvm::DIType CGDebugInfo::CreatePointerLikeType(unsigned Tag,
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);
+ return Cache;
+}
+
llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
llvm::DIFile Unit) {
if (BlockLiteralGenericSet)
@@ -639,7 +687,7 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
EltTy = DBuilder.createStructType(Unit, "__block_descriptor",
Unit, LineNo, FieldOffset, 0,
- Flags, Elements);
+ Flags, llvm::DIType(), Elements);
// Bit size, align and offset of the type.
uint64_t Size = CGM.getContext().getTypeSize(Ty);
@@ -669,7 +717,7 @@ llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty,
EltTy = DBuilder.createStructType(Unit, "__block_literal_generic",
Unit, LineNo, FieldOffset, 0,
- Flags, Elements);
+ Flags, llvm::DIType(), Elements);
BlockLiteralGenericSet = true;
BlockLiteralGeneric = DBuilder.createPointerType(EltTy, Size);
@@ -715,33 +763,6 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,
}
-void CGDebugInfo::
-CollectRecordStaticVars(const RecordDecl *RD, llvm::DIType FwdDecl) {
-
- for (RecordDecl::decl_iterator I = RD->decls_begin(), E = RD->decls_end();
- I != E; ++I)
- if (const VarDecl *V = dyn_cast<VarDecl>(*I)) {
- if (V->getInit()) {
- const APValue *Value = V->evaluateValue();
- if (Value && Value->isInt()) {
- llvm::ConstantInt *CI
- = llvm::ConstantInt::get(CGM.getLLVMContext(), Value->getInt());
-
- // Create the descriptor for static variable.
- llvm::DIFile VUnit = getOrCreateFile(V->getLocation());
- StringRef VName = V->getName();
- llvm::DIType VTy = getOrCreateType(V->getType(), VUnit);
- // Do not use DIGlobalVariable for enums.
- if (VTy.getTag() != llvm::dwarf::DW_TAG_enumeration_type) {
- DBuilder.createStaticVariable(FwdDecl, VName, VName, VUnit,
- getLineNumber(V->getLocation()),
- VTy, true, CI);
- }
- }
- }
- }
-}
-
llvm::DIType CGDebugInfo::createFieldType(StringRef name,
QualType type,
uint64_t sizeInBitsOverride,
@@ -775,94 +796,159 @@ llvm::DIType CGDebugInfo::createFieldType(StringRef name,
alignInBits, offsetInBits, flags, debugType);
}
+/// CollectRecordLambdaFields - Helper for CollectRecordFields.
+void CGDebugInfo::
+CollectRecordLambdaFields(const CXXRecordDecl *CXXDecl,
+ SmallVectorImpl<llvm::Value *> &elements,
+ llvm::DIType RecordTy) {
+ // For C++11 Lambdas a Field will be the same as a Capture, but the Capture
+ // has the name and the location of the variable so we should iterate over
+ // both concurrently.
+ const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(CXXDecl);
+ RecordDecl::field_iterator Field = CXXDecl->field_begin();
+ unsigned fieldno = 0;
+ for (CXXRecordDecl::capture_const_iterator I = CXXDecl->captures_begin(),
+ E = CXXDecl->captures_end(); I != E; ++I, ++Field, ++fieldno) {
+ const LambdaExpr::Capture C = *I;
+ if (C.capturesVariable()) {
+ VarDecl *V = C.getCapturedVar();
+ llvm::DIFile VUnit = getOrCreateFile(C.getLocation());
+ StringRef VName = V->getName();
+ uint64_t SizeInBitsOverride = 0;
+ if (Field->isBitField()) {
+ SizeInBitsOverride = Field->getBitWidthValue(CGM.getContext());
+ assert(SizeInBitsOverride && "found named 0-width bitfield");
+ }
+ llvm::DIType fieldType
+ = createFieldType(VName, Field->getType(), SizeInBitsOverride,
+ C.getLocation(), Field->getAccess(),
+ layout.getFieldOffset(fieldno), VUnit, RecordTy);
+ elements.push_back(fieldType);
+ } else {
+ // TODO: Need to handle 'this' in some way by probably renaming the
+ // this of the lambda class and having a field member of 'this' or
+ // by using AT_object_pointer for the function and having that be
+ // used as 'this' for semantic references.
+ assert(C.capturesThis() && "Field that isn't captured and isn't this?");
+ FieldDecl *f = *Field;
+ llvm::DIFile VUnit = getOrCreateFile(f->getLocation());
+ QualType type = f->getType();
+ llvm::DIType fieldType
+ = createFieldType("this", type, 0, f->getLocation(), f->getAccess(),
+ layout.getFieldOffset(fieldno), VUnit, RecordTy);
+
+ elements.push_back(fieldType);
+ }
+ }
+}
+
+/// CollectRecordStaticField - Helper for CollectRecordFields.
+void CGDebugInfo::
+CollectRecordStaticField(const VarDecl *Var,
+ SmallVectorImpl<llvm::Value *> &elements,
+ 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;
+ if (Var->getInit()) {
+ const APValue *Value = Var->evaluateValue();
+ if (Value) {
+ if (Value->isInt())
+ C = llvm::ConstantInt::get(CGM.getLLVMContext(), Value->getInt());
+ if (Value->isFloat())
+ C = llvm::ConstantFP::get(CGM.getLLVMContext(), Value->getFloat());
+ }
+ }
+
+ unsigned Flags = 0;
+ AccessSpecifier Access = Var->getAccess();
+ if (Access == clang::AS_private)
+ Flags |= llvm::DIDescriptor::FlagPrivate;
+ 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);
+ StaticDataMemberCache[Var->getCanonicalDecl()] = llvm::WeakVH(GV);
+}
+
+/// CollectRecordNormalField - Helper for CollectRecordFields.
+void CGDebugInfo::
+CollectRecordNormalField(const FieldDecl *field, uint64_t OffsetInBits,
+ llvm::DIFile tunit,
+ SmallVectorImpl<llvm::Value *> &elements,
+ llvm::DIType RecordTy) {
+ StringRef name = field->getName();
+ QualType type = field->getType();
+
+ // Ignore unnamed fields unless they're anonymous structs/unions.
+ if (name.empty() && !type->isRecordType())
+ return;
+
+ uint64_t SizeInBitsOverride = 0;
+ if (field->isBitField()) {
+ SizeInBitsOverride = field->getBitWidthValue(CGM.getContext());
+ assert(SizeInBitsOverride && "found named 0-width bitfield");
+ }
+
+ llvm::DIType fieldType
+ = createFieldType(name, type, SizeInBitsOverride,
+ field->getLocation(), field->getAccess(),
+ OffsetInBits, tunit, RecordTy);
+
+ elements.push_back(fieldType);
+}
+
/// 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) {
- unsigned fieldNo = 0;
- const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record);
const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(record);
- // For C++11 Lambdas a Field will be the same as a Capture, but the Capture
- // has the name and the location of the variable so we should iterate over
- // both concurrently.
- if (CXXDecl && CXXDecl->isLambda()) {
- RecordDecl::field_iterator Field = CXXDecl->field_begin();
- unsigned fieldno = 0;
- for (CXXRecordDecl::capture_const_iterator I = CXXDecl->captures_begin(),
- E = CXXDecl->captures_end(); I != E; ++I, ++Field, ++fieldno) {
- const LambdaExpr::Capture C = *I;
- if (C.capturesVariable()) {
- VarDecl *V = C.getCapturedVar();
- llvm::DIFile VUnit = getOrCreateFile(C.getLocation());
- StringRef VName = V->getName();
- uint64_t SizeInBitsOverride = 0;
- if (Field->isBitField()) {
- SizeInBitsOverride = Field->getBitWidthValue(CGM.getContext());
- assert(SizeInBitsOverride && "found named 0-width bitfield");
- }
- llvm::DIType fieldType
- = createFieldType(VName, Field->getType(), SizeInBitsOverride, C.getLocation(),
- Field->getAccess(), layout.getFieldOffset(fieldno),
- VUnit, RecordTy);
- elements.push_back(fieldType);
- } else {
- // TODO: Need to handle 'this' in some way by probably renaming the
- // this of the lambda class and having a field member of 'this' or
- // by using AT_object_pointer for the function and having that be
- // used as 'this' for semantic references.
- assert(C.capturesThis() && "Field that isn't captured and isn't this?");
- FieldDecl *f = *Field;
- llvm::DIFile VUnit = getOrCreateFile(f->getLocation());
- QualType type = f->getType();
- llvm::DIType fieldType
- = createFieldType("this", type, 0, f->getLocation(), f->getAccess(),
- layout.getFieldOffset(fieldNo), VUnit, RecordTy);
-
- elements.push_back(fieldType);
- }
- }
- } else {
+ if (CXXDecl && CXXDecl->isLambda())
+ CollectRecordLambdaFields(CXXDecl, elements, RecordTy);
+ else {
+ const ASTRecordLayout &layout = CGM.getContext().getASTRecordLayout(record);
+
+ // 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;
- for (RecordDecl::field_iterator I = record->field_begin(),
- E = record->field_end();
- I != E; ++I, ++fieldNo) {
- FieldDecl *field = *I;
-
- if (IsMsStruct) {
- // Zero-length bitfields following non-bitfield members are ignored
- if (CGM.getContext().ZeroBitfieldFollowsNonBitfield((field), LastFD)) {
- --fieldNo;
- continue;
- }
- LastFD = field;
- }
-
- StringRef name = field->getName();
- QualType type = field->getType();
- // Ignore unnamed fields unless they're anonymous structs/unions.
- if (name.empty() && !type->isRecordType()) {
- LastFD = field;
- continue;
- }
+ // 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;
+ }
+ CollectRecordNormalField(field, layout.getFieldOffset(fieldNo),
+ tunit, elements, RecordTy);
- uint64_t SizeInBitsOverride = 0;
- if (field->isBitField()) {
- SizeInBitsOverride = field->getBitWidthValue(CGM.getContext());
- assert(SizeInBitsOverride && "found named 0-width bitfield");
+ // Bump field number for next field.
+ ++fieldNo;
}
-
- llvm::DIType fieldType
- = createFieldType(name, type, SizeInBitsOverride,
- field->getLocation(), field->getAccess(),
- layout.getFieldOffset(fieldNo), tunit, RecordTy);
-
- elements.push_back(fieldType);
- }
}
}
@@ -872,13 +958,18 @@ CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit,
llvm::DIType
CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
llvm::DIFile Unit) {
- llvm::DIType FnTy
- = getOrCreateType(QualType(Method->getType()->getAs<FunctionProtoType>(),
- 0),
- Unit);
+ const FunctionProtoType *Func = Method->getType()->getAs<FunctionProtoType>();
+ if (Method->isStatic())
+ return getOrCreateType(QualType(Func, 0), Unit);
+ return getOrCreateInstanceMethodType(Method->getThisType(CGM.getContext()),
+ Func, Unit);
+}
+llvm::DIType CGDebugInfo::getOrCreateInstanceMethodType(
+ QualType ThisPtr, const FunctionProtoType *Func, llvm::DIFile Unit) {
// Add "this" pointer.
- llvm::DIArray Args = llvm::DICompositeType(FnTy).getTypeArray();
+ llvm::DIArray Args = llvm::DICompositeType(
+ getOrCreateType(QualType(Func, 0), Unit)).getTypeArray();
assert (Args.getNumElements() && "Invalid number of arguments!");
SmallVector<llvm::Value *, 16> Elts;
@@ -886,32 +977,28 @@ CGDebugInfo::getOrCreateMethodType(const CXXMethodDecl *Method,
// First element is always return type. For 'void' functions it is NULL.
Elts.push_back(Args.getElement(0));
- if (!Method->isStatic()) {
- // "this" pointer is always first argument.
- QualType ThisPtr = Method->getThisType(CGM.getContext());
-
- const CXXRecordDecl *RD = Method->getParent();
- if (isa<ClassTemplateSpecializationDecl>(RD)) {
- // Create pointer type directly in this case.
- const PointerType *ThisPtrTy = cast<PointerType>(ThisPtr);
- QualType PointeeTy = ThisPtrTy->getPointeeType();
- unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy);
- uint64_t Size = CGM.getContext().getTargetInfo().getPointerWidth(AS);
- uint64_t Align = CGM.getContext().getTypeAlign(ThisPtrTy);
- llvm::DIType PointeeType = getOrCreateType(PointeeTy, Unit);
- 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
- // metadata doesn't represent that.
- ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType);
- Elts.push_back(ThisPtrType);
- } else {
- llvm::DIType ThisPtrType = getOrCreateType(ThisPtr, Unit);
- TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType;
- ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType);
- Elts.push_back(ThisPtrType);
- }
+ // "this" pointer is always first argument.
+ const CXXRecordDecl *RD = ThisPtr->getPointeeCXXRecordDecl();
+ if (isa<ClassTemplateSpecializationDecl>(RD)) {
+ // Create pointer type directly in this case.
+ const PointerType *ThisPtrTy = cast<PointerType>(ThisPtr);
+ QualType PointeeTy = ThisPtrTy->getPointeeType();
+ unsigned AS = CGM.getContext().getTargetAddressSpace(PointeeTy);
+ uint64_t Size = CGM.getContext().getTargetInfo().getPointerWidth(AS);
+ uint64_t Align = CGM.getContext().getTypeAlign(ThisPtrTy);
+ llvm::DIType PointeeType = getOrCreateType(PointeeTy, Unit);
+ 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
+ // metadata doesn't represent that.
+ ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType);
+ Elts.push_back(ThisPtrType);
+ } else {
+ llvm::DIType ThisPtrType = getOrCreateType(ThisPtr, Unit);
+ TypeCache[ThisPtr.getAsOpaquePtr()] = ThisPtrType;
+ ThisPtrType = DBuilder.createObjectPointerType(ThisPtrType);
+ Elts.push_back(ThisPtrType);
}
// Copy rest of the arguments.
@@ -1199,7 +1286,7 @@ 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, 0,
+ 0, Size, 0, 0, llvm::DIDescriptor::FlagArtificial,
getOrCreateVTablePtrType(Unit));
EltTys.push_back(VPTR);
}
@@ -1215,10 +1302,10 @@ llvm::DIType CGDebugInfo::getOrCreateRecordType(QualType RTy,
/// getOrCreateInterfaceType - Emit an objective c interface type standalone
/// debug info.
llvm::DIType CGDebugInfo::getOrCreateInterfaceType(QualType D,
- SourceLocation Loc) {
+ SourceLocation Loc) {
assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
llvm::DIType T = getOrCreateType(D, getOrCreateFile(Loc));
- DBuilder.retainType(T);
+ RetainedTypes.push_back(D.getAsOpaquePtr());
return T;
}
@@ -1236,18 +1323,19 @@ 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::DIType FwdDecl = getOrCreateLimitedType(QualType(Ty, 0), DefUnit);
+ llvm::DICompositeType FwdDecl(
+ getOrCreateLimitedType(QualType(Ty, 0), DefUnit));
+ assert(FwdDecl.Verify() &&
+ "The debug type of a RecordType should be a DICompositeType");
if (FwdDecl.isForwardDecl())
return FwdDecl;
- llvm::TrackingVH<llvm::MDNode> FwdDeclNode(FwdDecl);
-
// Push the struct on region stack.
- LexicalBlockStack.push_back(FwdDeclNode);
+ LexicalBlockStack.push_back(&*FwdDecl);
RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl);
- // Add this to the completed types cache since we're completing it.
+ // Add this to the completed-type cache while we're completing it recursively.
CompletedTypeCache[QualType(Ty, 0).getAsOpaquePtr()] = FwdDecl;
// Convert all the elements.
@@ -1263,8 +1351,7 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
CollectVTableInfo(CXXDecl, DefUnit, EltTys);
}
- // Collect static variables with initializers and other fields.
- CollectRecordStaticVars(RD, FwdDecl);
+ // Collect data fields (including static variables and any initializers).
CollectRecordFields(RD, DefUnit, EltTys, FwdDecl);
llvm::DIArray TParamsArray;
if (CXXDecl) {
@@ -1279,19 +1366,10 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty) {
RegionMap.erase(Ty->getDecl());
llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
- // FIXME: Magic numbers ahoy! These should be changed when we
- // get some enums in llvm/Analysis/DebugInfo.h to refer to
- // them.
- if (RD->isUnion())
- FwdDeclNode->replaceOperandWith(10, Elements);
- else if (CXXDecl) {
- FwdDeclNode->replaceOperandWith(10, Elements);
- FwdDeclNode->replaceOperandWith(13, TParamsArray);
- } else
- FwdDeclNode->replaceOperandWith(10, Elements);
+ FwdDecl.setTypeArray(Elements, TParamsArray);
- RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDeclNode);
- return llvm::DIType(FwdDeclNode);
+ RegionMap[Ty->getDecl()] = llvm::WeakVH(FwdDecl);
+ return FwdDecl;
}
/// CreateType - get objective-c object type.
@@ -1319,8 +1397,8 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
if (!Def) {
llvm::DIType FwdDecl =
DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type,
- ID->getName(), TheCU, DefUnit, Line,
- RuntimeLang);
+ ID->getName(), TheCU, DefUnit, Line,
+ RuntimeLang);
return FwdDecl;
}
@@ -1334,18 +1412,18 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
if (ID->getImplementation())
Flags |= llvm::DIDescriptor::FlagObjcClassComplete;
- llvm::DIType RealDecl =
+ llvm::DICompositeType RealDecl =
DBuilder.createStructType(Unit, ID->getName(), DefUnit,
Line, Size, Align, Flags,
- llvm::DIArray(), RuntimeLang);
+ llvm::DIType(), llvm::DIArray(), RuntimeLang);
// Otherwise, insert it into the CompletedTypeCache so that recursive uses
// will find it and we're emitting the complete type.
- CompletedTypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RealDecl;
+ QualType QualTy = QualType(Ty, 0);
+ CompletedTypeCache[QualTy.getAsOpaquePtr()] = RealDecl;
// Push the struct on region stack.
- llvm::TrackingVH<llvm::MDNode> FwdDeclNode(RealDecl);
- LexicalBlockStack.push_back(FwdDeclNode);
+ LexicalBlockStack.push_back(static_cast<llvm::MDNode*>(RealDecl));
RegionMap[Ty->getDecl()] = llvm::WeakVH(RealDecl);
// Convert all the elements.
@@ -1373,13 +1451,13 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
ObjCMethodDecl *Setter = PD->getSetterMethodDecl();
llvm::MDNode *PropertyNode =
DBuilder.createObjCProperty(PD->getName(),
- PUnit, PLine,
+ PUnit, PLine,
(Getter && Getter->isImplicit()) ? "" :
getSelectorName(PD->getGetterName()),
(Setter && Setter->isImplicit()) ? "" :
getSelectorName(PD->getSetterName()),
PD->getPropertyAttributes(),
- getOrCreateType(PD->getType(), PUnit));
+ getOrCreateType(PD->getType(), PUnit));
EltTys.push_back(PropertyNode);
}
@@ -1440,9 +1518,9 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
if (ObjCPropertyImplDecl *PImpD =
ImpD->FindPropertyImplIvarDecl(Field->getIdentifier())) {
if (ObjCPropertyDecl *PD = PImpD->getPropertyDecl()) {
- SourceLocation Loc = PD->getLocation();
- llvm::DIFile PUnit = getOrCreateFile(Loc);
- unsigned PLine = getLineNumber(Loc);
+ SourceLocation Loc = PD->getLocation();
+ llvm::DIFile PUnit = getOrCreateFile(Loc);
+ unsigned PLine = getLineNumber(Loc);
ObjCMethodDecl *Getter = PD->getGetterMethodDecl();
ObjCMethodDecl *Setter = PD->getSetterMethodDecl();
PropertyNode =
@@ -1465,31 +1543,33 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
}
llvm::DIArray Elements = DBuilder.getOrCreateArray(EltTys);
- FwdDeclNode->replaceOperandWith(10, Elements);
+ RealDecl.setTypeArray(Elements);
+
+ // If the implementation is not yet set, we do not want to mark it
+ // as complete. An implementation may declare additional
+ // private ivars that we would miss otherwise.
+ if (ID->getImplementation() == 0)
+ CompletedTypeCache.erase(QualTy.getAsOpaquePtr());
LexicalBlockStack.pop_back();
- return llvm::DIType(FwdDeclNode);
+ return RealDecl;
}
llvm::DIType CGDebugInfo::CreateType(const VectorType *Ty, llvm::DIFile Unit) {
llvm::DIType ElementTy = getOrCreateType(Ty->getElementType(), Unit);
- int64_t NumElems = Ty->getNumElements();
- int64_t LowerBound = 0;
- if (NumElems == 0)
+ int64_t Count = Ty->getNumElements();
+ if (Count == 0)
// If number of elements are not known then this is an unbounded array.
- // Use Low = 1, Hi = 0 to express such arrays.
- LowerBound = 1;
- else
- --NumElems;
+ // Use Count == -1 to express such arrays.
+ Count = -1;
- llvm::Value *Subscript = DBuilder.getOrCreateSubrange(LowerBound, NumElems);
+ llvm::Value *Subscript = DBuilder.getOrCreateSubrange(0, Count);
llvm::DIArray SubscriptArray = DBuilder.getOrCreateArray(Subscript);
uint64_t Size = CGM.getContext().getTypeSize(Ty);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
- return
- DBuilder.createVectorType(Size, Align, ElementTy, SubscriptArray);
+ return DBuilder.createVectorType(Size, Align, ElementTy, SubscriptArray);
}
llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
@@ -1523,19 +1603,19 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,
SmallVector<llvm::Value *, 8> Subscripts;
QualType EltTy(Ty, 0);
while ((Ty = dyn_cast<ArrayType>(EltTy))) {
- int64_t UpperBound = 0;
- int64_t LowerBound = 0;
- if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Ty)) {
- if (CAT->getSize().getZExtValue())
- UpperBound = CAT->getSize().getZExtValue() - 1;
- } else
- // This is an unbounded array. Use Low = 1, Hi = 0 to express such
- // arrays.
- LowerBound = 1;
+ // If the number of elements is known, then count is that number. Otherwise,
+ // it's -1. This allows us to represent a subrange with an array of 0
+ // elements, like this:
+ //
+ // struct foo {
+ // int x[0];
+ // };
+ 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(LowerBound,
- UpperBound));
+ Subscripts.push_back(DBuilder.getOrCreateSubrange(0, Count));
EltTy = Ty->getElementType();
}
@@ -1561,38 +1641,15 @@ llvm::DIType CGDebugInfo::CreateType(const RValueReferenceType *Ty,
llvm::DIType CGDebugInfo::CreateType(const MemberPointerType *Ty,
llvm::DIFile U) {
- QualType PointerDiffTy = CGM.getContext().getPointerDiffType();
- llvm::DIType PointerDiffDITy = getOrCreateType(PointerDiffTy, U);
-
- if (!Ty->getPointeeType()->isFunctionType()) {
- // We have a data member pointer type.
- return PointerDiffDITy;
- }
-
- // We have a member function pointer type. Treat it as a struct with two
- // ptrdiff_t members.
- std::pair<uint64_t, unsigned> Info = CGM.getContext().getTypeInfo(Ty);
-
- uint64_t FieldOffset = 0;
- llvm::Value *ElementTypes[2];
-
- // FIXME: This should be a DW_TAG_pointer_to_member type.
- ElementTypes[0] =
- DBuilder.createMemberType(U, "ptr", U, 0,
- Info.first, Info.second, FieldOffset, 0,
- PointerDiffDITy);
- FieldOffset += Info.first;
-
- ElementTypes[1] =
- DBuilder.createMemberType(U, "ptr", U, 0,
- Info.first, Info.second, FieldOffset, 0,
- PointerDiffDITy);
-
- llvm::DIArray Elements = DBuilder.getOrCreateArray(ElementTypes);
-
- return DBuilder.createStructType(U, StringRef("test"),
- U, 0, FieldOffset,
- 0, 0, Elements);
+ llvm::DIType ClassType = getOrCreateType(QualType(Ty->getClass(), 0), U);
+ if (!Ty->getPointeeType()->isFunctionType())
+ return DBuilder.createMemberPointerType(
+ CreatePointeeType(Ty->getPointeeType(), U), ClassType);
+ return DBuilder.createMemberPointerType(getOrCreateInstanceMethodType(
+ CGM.getContext().getPointerType(
+ QualType(Ty->getClass(), Ty->getPointeeType().getCVRQualifiers())),
+ Ty->getPointeeType()->getAs<FunctionProtoType>(), U),
+ ClassType);
}
llvm::DIType CGDebugInfo::CreateType(const AtomicType *Ty,
@@ -1651,12 +1708,14 @@ llvm::DIType CGDebugInfo::CreateEnumType(const EnumDecl *ED) {
return DbgTy;
}
-static QualType UnwrapTypeForDebugInfo(QualType T) {
+static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
+ Qualifiers Quals;
do {
+ Quals += T.getLocalQualifiers();
QualType LastT = T;
switch (T->getTypeClass()) {
default:
- return T;
+ return C.getQualifiedType(T.getTypePtr(), Quals);
case Type::TemplateSpecialization:
T = cast<TemplateSpecializationType>(T)->desugar();
break;
@@ -1681,13 +1740,8 @@ static QualType UnwrapTypeForDebugInfo(QualType T) {
case Type::Paren:
T = cast<ParenType>(T)->getInnerType();
break;
- case Type::SubstTemplateTypeParm: {
- // We need to keep the qualifiers handy since getReplacementType()
- // will strip them away.
- unsigned Quals = T.getLocalFastQualifiers();
+ case Type::SubstTemplateTypeParm:
T = cast<SubstTemplateTypeParmType>(T)->getReplacementType();
- T.addFastQualifiers(Quals);
- }
break;
case Type::Auto:
T = cast<AutoType>(T)->getDeducedType();
@@ -1695,8 +1749,7 @@ static QualType UnwrapTypeForDebugInfo(QualType T) {
}
assert(T != LastT && "Type unwrapping failed to unwrap!");
- if (T == LastT)
- return T;
+ (void)LastT;
} while (true);
}
@@ -1704,9 +1757,16 @@ static QualType UnwrapTypeForDebugInfo(QualType T) {
llvm::DIType CGDebugInfo::getTypeOrNull(QualType Ty) {
// Unwrap the type as needed for debug information.
- Ty = UnwrapTypeForDebugInfo(Ty);
+ Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
// Check for existing entry.
+ if (Ty->getTypeClass() == Type::ObjCInterface) {
+ llvm::Value *V = getCachedInterfaceTypeOrNull(Ty);
+ if (V)
+ return llvm::DIType(cast<llvm::MDNode>(V));
+ else return llvm::DIType();
+ }
+
llvm::DenseMap<void *, llvm::WeakVH>::iterator it =
TypeCache.find(Ty.getAsOpaquePtr());
if (it != TypeCache.end()) {
@@ -1723,20 +1783,40 @@ llvm::DIType CGDebugInfo::getTypeOrNull(QualType Ty) {
llvm::DIType CGDebugInfo::getCompletedTypeOrNull(QualType Ty) {
// Unwrap the type as needed for debug information.
- Ty = UnwrapTypeForDebugInfo(Ty);
+ Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
// Check for existing entry.
+ llvm::Value *V = 0;
llvm::DenseMap<void *, llvm::WeakVH>::iterator it =
CompletedTypeCache.find(Ty.getAsOpaquePtr());
- if (it != CompletedTypeCache.end()) {
- // Verify that the debug info still exists.
- if (llvm::Value *V = it->second)
- return llvm::DIType(cast<llvm::MDNode>(V));
+ if (it != CompletedTypeCache.end())
+ V = it->second;
+ else {
+ V = getCachedInterfaceTypeOrNull(Ty);
}
+ // Verify that any cached debug info still exists.
+ if (V != 0)
+ return llvm::DIType(cast<llvm::MDNode>(V));
+
return llvm::DIType();
}
+/// getCachedInterfaceTypeOrNull - Get the type from the interface
+/// cache, unless it needs to regenerated. Otherwise return null.
+llvm::Value *CGDebugInfo::getCachedInterfaceTypeOrNull(QualType Ty) {
+ // Is there a cached interface that hasn't changed?
+ llvm::DenseMap<void *, std::pair<llvm::WeakVH, unsigned > >
+ ::iterator it1 = ObjCInterfaceCache.find(Ty.getAsOpaquePtr());
+
+ if (it1 != ObjCInterfaceCache.end())
+ if (ObjCInterfaceDecl* Decl = getObjCInterfaceDecl(Ty))
+ if (Checksum(Decl) == it1->second.second)
+ // Return cached forward declaration.
+ return it1->second.first;
+
+ return 0;
+}
/// getOrCreateType - Get the type from the cache or create a new
/// one if necessary.
@@ -1745,7 +1825,7 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) {
return llvm::DIType();
// Unwrap the type as needed for debug information.
- Ty = UnwrapTypeForDebugInfo(Ty);
+ Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
llvm::DIType T = getCompletedTypeOrNull(Ty);
@@ -1754,21 +1834,63 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile Unit) {
// Otherwise create the type.
llvm::DIType Res = CreateTypeNode(Ty, Unit);
+ void* TyPtr = Ty.getAsOpaquePtr();
+
+ // And update the type cache.
+ TypeCache[TyPtr] = Res;
llvm::DIType TC = getTypeOrNull(Ty);
if (TC.Verify() && TC.isForwardDecl())
- ReplaceMap.push_back(std::make_pair(Ty.getAsOpaquePtr(),
- static_cast<llvm::Value*>(TC)));
-
- // And update the type cache.
- TypeCache[Ty.getAsOpaquePtr()] = Res;
+ 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
+ // 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());
+ // Store the forward declaration in the cache.
+ ObjCInterfaceCache[TyPtr] = std::make_pair(TC, Checksum(Decl));
+
+ // Register the type for replacement in finalize().
+ ReplaceMap.push_back(std::make_pair(TyPtr, static_cast<llvm::Value*>(TC)));
+ return TC;
+ }
if (!Res.isForwardDecl())
- CompletedTypeCache[Ty.getAsOpaquePtr()] = Res;
+ CompletedTypeCache[TyPtr] = Res;
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;
+}
+
+ObjCInterfaceDecl *CGDebugInfo::getObjCInterfaceDecl(QualType Ty) {
+ switch (Ty->getTypeClass()) {
+ case Type::ObjCObjectPointer:
+ return getObjCInterfaceDecl(cast<ObjCObjectPointerType>(Ty)->getPointeeType());
+ case Type::ObjCInterface:
+ return cast<ObjCInterfaceType>(Ty)->getDecl();
+ default:
+ return 0;
+ }
+}
+
/// CreateTypeNode - Create a new debug type node.
llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile Unit) {
// Handle qualifiers, which recursively handles what they refer to.
@@ -1852,12 +1974,12 @@ 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::DIFile Unit) {
+ llvm::DIFile Unit) {
if (Ty.isNull())
return llvm::DIType();
// Unwrap the type as needed for debug information.
- Ty = UnwrapTypeForDebugInfo(Ty);
+ Ty = UnwrapTypeForDebugInfo(Ty, CGM.getContext());
llvm::DIType T = getTypeOrNull(Ty);
@@ -1901,46 +2023,45 @@ llvm::DIType CGDebugInfo::CreateLimitedType(const RecordType *Ty) {
uint64_t Size = CGM.getContext().getTypeSize(Ty);
uint64_t Align = CGM.getContext().getTypeAlign(Ty);
const CXXRecordDecl *CXXDecl = dyn_cast<CXXRecordDecl>(RD);
- llvm::TrackingVH<llvm::MDNode> RealDecl;
+ llvm::DICompositeType RealDecl;
if (RD->isUnion())
RealDecl = DBuilder.createUnionType(RDContext, RDName, DefUnit, Line,
- Size, Align, 0, llvm::DIArray());
+ Size, Align, 0, llvm::DIArray());
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());
+ Size, Align, 0, 0, llvm::DIType(),
+ llvm::DIArray(), llvm::DIType(),
+ llvm::DIArray());
} else
RealDecl = DBuilder.createStructType(RDContext, RDName, DefUnit, Line,
- Size, Align, 0, llvm::DIArray());
+ Size, Align, 0, llvm::DIType(), llvm::DIArray());
RegionMap[Ty->getDecl()] = llvm::WeakVH(RealDecl);
- TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = llvm::DIType(RealDecl);
+ TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = RealDecl;
if (CXXDecl) {
// A class's primary base or the class itself contains the vtable.
- llvm::MDNode *ContainingType = NULL;
+ 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;
+ const ASTRecordLayout &BRL = CGM.getContext().getASTRecordLayout(PBase);
+ const CXXRecordDecl *PBT = BRL.getPrimaryBase();
+ if (PBT && !BRL.isPrimaryBaseVirtual())
+ PBase = PBT;
+ else
+ break;
}
- ContainingType =
- getOrCreateType(QualType(PBase->getTypeForDecl(), 0), DefUnit);
- }
- else if (CXXDecl->isDynamicClass())
+ ContainingType = llvm::DICompositeType(
+ getOrCreateType(QualType(PBase->getTypeForDecl(), 0), DefUnit));
+ } else if (CXXDecl->isDynamicClass())
ContainingType = RealDecl;
- RealDecl->replaceOperandWith(12, ContainingType);
+ RealDecl.setContainingType(ContainingType);
}
return llvm::DIType(RealDecl);
}
@@ -2027,8 +2148,9 @@ llvm::DIType CGDebugInfo::getOrCreateFunctionType(const Decl *D,
// First element is always return type. For 'void' functions it is NULL.
Elts.push_back(getOrCreateType(OMethod->getResultType(), F));
// "self" pointer is always first argument.
- llvm::DIType SelfTy = getOrCreateType(OMethod->getSelfDecl()->getType(), F);
- Elts.push_back(DBuilder.createObjectPointerType(SelfTy));
+ QualType SelfDeclTy = OMethod->getSelfDecl()->getType();
+ llvm::DIType SelfTy = getOrCreateType(SelfDeclTy, F);
+ Elts.push_back(CreateSelfType(SelfDeclTy, SelfTy));
// "_cmd" pointer is always second argument.
llvm::DIType CmdTy = getOrCreateType(OMethod->getCmdDecl()->getType(), F);
Elts.push_back(DBuilder.createArtificialType(CmdTy));
@@ -2084,13 +2206,18 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
}
}
Name = getFunctionName(FD);
- // Use mangled name as linkage name for c/c++ functions.
+ // Use mangled name as linkage name for C/C++ functions.
if (FD->hasPrototype()) {
LinkageName = CGM.getMangledName(GD);
Flags |= llvm::DIDescriptor::FlagPrototyped;
}
+ // No need to replicate the linkage name if it isn't different from the
+ // subprogram name, no need to have it at all unless coverage is enabled or
+ // debug is set to more than just line tables.
if (LinkageName == Name ||
- CGM.getCodeGenOpts().getDebugInfo() <= CodeGenOptions::DebugLineTablesOnly)
+ (!CGM.getCodeGenOpts().EmitGcovArcs &&
+ !CGM.getCodeGenOpts().EmitGcovNotes &&
+ CGM.getCodeGenOpts().getDebugInfo() <= CodeGenOptions::DebugLineTablesOnly))
LinkageName = StringRef();
if (CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo) {
@@ -2151,7 +2278,8 @@ void CGDebugInfo::EmitFunctionStart(GlobalDecl GD, QualType FnType,
/// EmitLocation - Emit metadata to indicate a change in line/column
/// information in the source file.
-void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) {
+void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc,
+ bool ForceColumnInfo) {
// Update our current location
setLocation(Loc);
@@ -2163,16 +2291,19 @@ void CGDebugInfo::EmitLocation(CGBuilderTy &Builder, SourceLocation Loc) {
if (CurLoc == PrevLoc ||
SM.getExpansionLoc(CurLoc) == SM.getExpansionLoc(PrevLoc))
// New Builder may not be in sync with CGDebugInfo.
- if (!Builder.getCurrentDebugLocation().isUnknown())
+ if (!Builder.getCurrentDebugLocation().isUnknown() &&
+ Builder.getCurrentDebugLocation().getScope(CGM.getLLVMContext()) ==
+ LexicalBlockStack.back())
return;
// Update last state.
PrevLoc = CurLoc;
llvm::MDNode *Scope = LexicalBlockStack.back();
- Builder.SetCurrentDebugLocation(llvm::DebugLoc::get(getLineNumber(CurLoc),
- getColumnNumber(CurLoc),
- Scope));
+ Builder.SetCurrentDebugLocation(llvm::DebugLoc::get
+ (getLineNumber(CurLoc),
+ getColumnNumber(CurLoc, ForceColumnInfo),
+ Scope));
}
/// CreateLexicalBlock - Creates a new lexical block node and pushes it on
@@ -2229,7 +2360,7 @@ void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) {
// EmitTypeForVarWithBlocksAttr - Build up structure info for the byref.
// See BuildByRefType.
-llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD,
+llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,
uint64_t *XOffset) {
SmallVector<llvm::Value *, 5> EltTys;
@@ -2248,7 +2379,7 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD,
EltTys.push_back(CreateMemberType(Unit, FType, "__flags", &FieldOffset));
EltTys.push_back(CreateMemberType(Unit, FType, "__size", &FieldOffset));
- bool HasCopyAndDispose = CGM.getContext().BlockRequiresCopying(Type);
+ bool HasCopyAndDispose = CGM.getContext().BlockRequiresCopying(Type, VD);
if (HasCopyAndDispose) {
FType = CGM.getContext().getPointerType(CGM.getContext().VoidTy);
EltTys.push_back(CreateMemberType(Unit, FType, "__copy_helper",
@@ -2256,6 +2387,14 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD,
EltTys.push_back(CreateMemberType(Unit, FType, "__destroy_helper",
&FieldOffset));
}
+ bool HasByrefExtendedLayout;
+ Qualifiers::ObjCLifetime Lifetime;
+ if (CGM.getContext().getByrefLifetime(Type,
+ Lifetime, HasByrefExtendedLayout)
+ && HasByrefExtendedLayout)
+ EltTys.push_back(CreateMemberType(Unit, FType,
+ "__byref_variable_layout",
+ &FieldOffset));
CharUnits Align = CGM.getContext().getDeclAlign(VD);
if (Align > CGM.getContext().toCharUnitsFromBits(
@@ -2292,7 +2431,7 @@ llvm::DIType CGDebugInfo::EmitTypeForVarWithBlocksAttr(const ValueDecl *VD,
unsigned Flags = llvm::DIDescriptor::FlagBlockByrefStruct;
return DBuilder.createStructType(Unit, "", Unit, 0, FieldOffset, 0, Flags,
- Elements);
+ llvm::DIType(), Elements);
}
/// EmitDeclare - Emit local variable declaration debug info.
@@ -2324,7 +2463,7 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
// 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->hasTrivialCopyConstructor() ||
+ if (Record->hasNonTrivialCopyConstructor() ||
!Record->hasTrivialDestructor())
Ty = DBuilder.createReferenceType(llvm::dwarf::DW_TAG_reference_type, Ty);
}
@@ -2392,25 +2531,11 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
return;
}
-
- // Create the descriptor for the variable.
- llvm::DIVariable D =
- DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope),
- Name, Unit, Line, Ty,
- CGM.getLangOpts().Optimize, Flags, 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;
- }
-
- // If VD is an anonymous union then Storage represents value for
- // all union fields.
- if (const RecordType *RT = dyn_cast<RecordType>(VD->getType())) {
+ } else if (const RecordType *RT = dyn_cast<RecordType>(VD->getType())) {
+ // If VD is an anonymous union then Storage represents value for
+ // all union fields.
const RecordDecl *RD = cast<RecordDecl>(RT->getDecl());
- if (RD->isUnion()) {
+ if (RD->isUnion() && RD->isAnonymousStructOrUnion()) {
for (RecordDecl::field_iterator I = RD->field_begin(),
E = RD->field_end();
I != E; ++I) {
@@ -2434,8 +2559,20 @@ void CGDebugInfo::EmitDeclare(const VarDecl *VD, unsigned Tag,
DBuilder.insertDeclare(Storage, D, Builder.GetInsertBlock());
Call->setDebugLoc(llvm::DebugLoc::get(Line, Column, Scope));
}
+ return;
}
}
+
+ // Create the descriptor for the variable.
+ llvm::DIVariable D =
+ DBuilder.createLocalVariable(Tag, llvm::DIDescriptor(Scope),
+ Name, Unit, Line, Ty,
+ CGM.getLangOpts().Optimize, Flags, 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));
}
void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
@@ -2445,6 +2582,19 @@ void CGDebugInfo::EmitDeclareOfAutoVariable(const VarDecl *VD,
EmitDeclare(VD, llvm::dwarf::DW_TAG_auto_variable, Storage, 0, Builder);
}
+/// Look up the completed type for a self pointer in the TypeCache and
+/// create a copy of it with the ObjectPointer and Artificial flags
+/// set. If the type is not cached, a new one is created. This should
+/// 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 CachedTy = getTypeOrNull(QualTy);
+ if (CachedTy.Verify()) Ty = CachedTy;
+ else DEBUG(llvm::dbgs() << "No cached type for self.");
+ return DBuilder.createObjectPointerType(Ty);
+}
+
void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(const VarDecl *VD,
llvm::Value *Storage,
CGBuilderTy &Builder,
@@ -2468,7 +2618,7 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(const VarDecl *VD,
// Self is passed along as an implicit non-arg variable in a
// block. Mark it as the object pointer.
if (isa<ImplicitParamDecl>(VD) && VD->getName() == "self")
- Ty = DBuilder.createObjectPointerType(Ty);
+ Ty = CreateSelfType(VD->getType(), Ty);
// Get location information.
unsigned Line = getLineNumber(VD->getLocation());
@@ -2482,6 +2632,8 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(const VarDecl *VD,
SmallVector<llvm::Value *, 9> addr;
llvm::Type *Int64Ty = CGM.Int64Ty;
+ if (isa<llvm::AllocaInst>(Storage))
+ addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpDeref));
addr.push_back(llvm::ConstantInt::get(Int64Ty, llvm::DIBuilder::OpPlus));
addr.push_back(llvm::ConstantInt::get(Int64Ty, offset.getQuantity()));
if (isByRef) {
@@ -2503,6 +2655,7 @@ void CGDebugInfo::EmitDeclareOfBlockDeclRefVariable(const VarDecl *VD,
DBuilder.createComplexVariable(llvm::dwarf::DW_TAG_auto_variable,
llvm::DIDescriptor(LexicalBlockStack.back()),
VD->getName(), Unit, Line, Ty, addr);
+
// Insert an llvm.dbg.declare into the current block.
llvm::Instruction *Call =
DBuilder.insertDeclare(Storage, D, Builder.GetInsertPoint());
@@ -2530,7 +2683,8 @@ namespace {
}
void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
- llvm::Value *addr,
+ llvm::Value *Arg,
+ llvm::Value *LocalAddr,
CGBuilderTy &Builder) {
assert(CGM.getCodeGenOpts().getDebugInfo() >= CodeGenOptions::LimitedDebugInfo);
ASTContext &C = CGM.getContext();
@@ -2651,27 +2805,48 @@ void CGDebugInfo::EmitDeclareOfBlockLiteralArgVariable(const CGBlockInfo &block,
DBuilder.createStructType(tunit, typeName.str(), tunit, line,
CGM.getContext().toBits(block.BlockSize),
CGM.getContext().toBits(block.BlockAlign),
- 0, fieldsArray);
+ 0, llvm::DIType(), fieldsArray);
type = DBuilder.createPointerType(type, CGM.PointerWidthInBits);
// Get overall information about the block.
unsigned flags = llvm::DIDescriptor::FlagArtificial;
llvm::MDNode *scope = LexicalBlockStack.back();
- StringRef name = ".block_descriptor";
// Create the descriptor for the parameter.
llvm::DIVariable debugVar =
DBuilder.createLocalVariable(llvm::dwarf::DW_TAG_arg_variable,
llvm::DIDescriptor(scope),
- name, tunit, line, type,
+ Arg->getName(), tunit, line, type,
CGM.getLangOpts().Optimize, flags,
- cast<llvm::Argument>(addr)->getArgNo() + 1);
-
- // Insert an llvm.dbg.value into the current block.
- llvm::Instruction *declare =
- DBuilder.insertDbgValueIntrinsic(addr, 0, debugVar,
- Builder.GetInsertBlock());
- declare->setDebugLoc(llvm::DebugLoc::get(line, column, scope));
+ cast<llvm::Argument>(Arg)->getArgNo() + 1);
+
+ if (LocalAddr) {
+ // Insert an llvm.dbg.value into the current block.
+ llvm::Instruction *DbgVal =
+ DBuilder.insertDbgValueIntrinsic(LocalAddr, 0, debugVar,
+ Builder.GetInsertBlock());
+ DbgVal->setDebugLoc(llvm::DebugLoc::get(line, column, scope));
+ }
+
+ // Insert an llvm.dbg.declare into the current block.
+ llvm::Instruction *DbgDecl =
+ DBuilder.insertDeclare(Arg, debugVar, Builder.GetInsertBlock());
+ 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();
}
/// EmitGlobalVariable - Emit information about a global variable.
@@ -2705,7 +2880,8 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,
getContextDescriptor(dyn_cast<Decl>(D->getDeclContext()));
DBuilder.createStaticVariable(DContext, DeclName, LinkageName,
Unit, LineNo, getOrCreateType(T, Unit),
- Var->hasInternalLinkage(), Var);
+ Var->hasInternalLinkage(), Var,
+ getStaticDataMemberDeclaration(D));
}
/// EmitGlobalVariable - Emit information about an objective-c interface.
@@ -2752,7 +2928,8 @@ void CGDebugInfo::EmitGlobalVariable(const ValueDecl *VD,
return;
DBuilder.createStaticVariable(Unit, Name, Name, Unit,
getLineNumber(VD->getLocation()),
- Ty, true, Init);
+ Ty, true, Init,
+ getStaticDataMemberDeclaration(VD));
}
/// getOrCreateNamesSpace - Return namespace descriptor for the given
@@ -2774,7 +2951,7 @@ CGDebugInfo::getOrCreateNameSpace(const NamespaceDecl *NSDecl) {
return NS;
}
-void CGDebugInfo::finalize(void) {
+void CGDebugInfo::finalize() {
for (std::vector<std::pair<void *, llvm::WeakVH> >::const_iterator VI
= ReplaceMap.begin(), VE = ReplaceMap.end(); VI != VE; ++VI) {
llvm::DIType Ty, RepTy;
@@ -2789,10 +2966,16 @@ void CGDebugInfo::finalize(void) {
if (llvm::Value *V = it->second)
RepTy = llvm::DIType(cast<llvm::MDNode>(V));
}
-
- if (Ty.Verify() && Ty.isForwardDecl() && RepTy.Verify()) {
+
+ if (Ty.Verify() && Ty.isForwardDecl() && RepTy.Verify())
Ty.replaceAllUsesWith(RepTy);
- }
}
+
+ // We keep our own list of retained types, because we need to look
+ // up the final type in the type cache.
+ for (std::vector<void *>::const_iterator RI = RetainedTypes.begin(),
+ RE = RetainedTypes.end(); RI != RE; ++RI)
+ DBuilder.retainType(llvm::DIType(cast<llvm::MDNode>(TypeCache[*RI])));
+
DBuilder.finalize();
}